88#include " snowflake/platform.h"
99#include " snowflake/SnowflakeTransferException.hpp"
1010#include < cerrno>
11+ #include " boost/filesystem.hpp"
1112
1213#define COMPRESSION_AUTO " AUTO"
1314#define COMPRESSION_AUTO_DETECT " AUTO_DETECT"
2021#include < fnmatch.h>
2122#endif
2223
23-
24+ using namespace boost ::filesystem ;
2425
2526Snowflake::Client::FileMetadataInitializer::FileMetadataInitializer (
2627 std::vector<FileMetadata> &smallFileMetadata,
@@ -34,16 +35,16 @@ Snowflake::Client::FileMetadataInitializer::FileMetadataInitializer(
3435}
3536
3637void
37- Snowflake::Client::FileMetadataInitializer::initUploadFileMetadata (const std::string &fileDir, const char *fileName,
38+ Snowflake::Client::FileMetadataInitializer::initUploadFileMetadata (const std::string &fileNameFull,
39+ const std::string &destPath,
40+ const std::string &fileName,
3841 size_t fileSize, size_t threshold)
3942{
40- std::string fileNameFull = fileDir;
41- fileNameFull += fileName;
42-
4343 FileMetadata fileMetadata;
4444 fileMetadata.srcFileName = m_stmtPutGet->platformStringToUTF8 (fileNameFull);
4545 fileMetadata.srcFileSize = fileSize;
46- fileMetadata.destFileName = m_stmtPutGet->platformStringToUTF8 (std::string (fileName));
46+ fileMetadata.destPath = m_stmtPutGet->platformStringToUTF8 (destPath);
47+ fileMetadata.destFileName = m_stmtPutGet->platformStringToUTF8 (fileName);
4748 // process compression type
4849 initCompressionMetadata (fileMetadata);
4950
@@ -56,9 +57,52 @@ Snowflake::Client::FileMetadataInitializer::initUploadFileMetadata(const std::st
5657
5758void Snowflake::Client::FileMetadataInitializer::populateSrcLocUploadMetadata (std::string &sourceLocation,
5859 size_t putThreshold)
60+ {
61+ // looking for files on disk.
62+ std::string srcLocationPlatform = m_stmtPutGet->UTF8ToPlatformString (sourceLocation);
63+ size_t dirSep = srcLocationPlatform.find_last_of (PATH_SEP);
64+ std::string basePath = srcLocationPlatform.substr (0 , dirSep + 1 );
65+
66+ std::vector<std::string> fileList;
67+ if (!listFilesRecursive (srcLocationPlatform, fileList))
68+ {
69+ CXX_LOG_ERROR (" Failed on finding files for uploading." );
70+ return ;
71+ }
72+
73+ for (auto file = fileList.begin (); file != fileList.end (); file++)
74+ {
75+ path p (*file);
76+ size_t fileSize = file_size (p);
77+ std::string fileNameFull = p.string ();
78+ std::string fileName = p.filename ().string ();
79+ // make the path on stage by removing base path and file name from full path
80+ std::string destPath = fileNameFull.substr (basePath.length (),
81+ fileNameFull.length () - basePath.length () - fileName.length ());
82+ initUploadFileMetadata (fileNameFull, destPath, fileName, fileSize, putThreshold);
83+ }
84+ }
85+
86+ void Snowflake::Client::FileMetadataInitializer::includeSubfolderFilesRecursive (const std::string &folderPath,
87+ std::vector<std::string> & fileList)
88+ {
89+ for (auto const & entry : recursive_directory_iterator (folderPath))
90+ {
91+ if (is_regular_file (entry))
92+ {
93+ fileList.push_back (entry.path ().string ());
94+ }
95+ }
96+ }
97+
98+ bool Snowflake::Client::FileMetadataInitializer::listFilesRecursive (const std::string &sourceLocation,
99+ std::vector<std::string> & fileList)
59100{
60101// looking for files on disk.
61102 std::string srcLocationPlatform = m_stmtPutGet->UTF8ToPlatformString (sourceLocation);
103+ size_t dirSep = srcLocationPlatform.find_last_of (PATH_SEP);
104+ std::string dirPath = srcLocationPlatform.substr (0 , dirSep + 1 );
105+ std::string filePattern = srcLocationPlatform.substr (dirSep + 1 );
62106
63107#ifdef _WIN32
64108 WIN32_FIND_DATA fdd;
@@ -71,8 +115,7 @@ void Snowflake::Client::FileMetadataInitializer::populateSrcLocUploadMetadata(st
71115 {
72116 CXX_LOG_ERROR (" No file matching pattern %s has been found. Error: %d" ,
73117 sourceLocation.c_str (), dwError);
74- FindClose (hFind);
75- return ;
118+ return false ;
76119 }
77120 else if (dwError != ERROR_SUCCESS)
78121 {
@@ -85,37 +128,24 @@ void Snowflake::Client::FileMetadataInitializer::populateSrcLocUploadMetadata(st
85128 do {
86129 if (!(fdd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
87130 {
88- std::string fileFullPath = std::string (fdd.cFileName );
89- size_t dirSep = srcLocationPlatform.find_last_of (PATH_SEP);
90- if (dirSep == std::string::npos)
91- {
92- dirSep = sourceLocation.find_last_of (ALTER_PATH_SEP);
93- }
94- if (dirSep != std::string::npos)
95- {
96- std::string dirPath = srcLocationPlatform.substr (0 , dirSep + 1 );
97- LARGE_INTEGER fileSize;
98- fileSize.LowPart = fdd.nFileSizeLow ;
99- fileSize.HighPart = fdd.nFileSizeHigh ;
100- initUploadFileMetadata (dirPath, (char *)fdd.cFileName , (size_t )fileSize.QuadPart , putThreshold);
101- }
131+ fileList.push_back (dirPath + fdd.cFileName );
132+ }
133+ else
134+ {
135+ includeSubfolderFilesRecursive (dirPath + fdd.cFileName , fileList);
102136 }
103137 } while (FindNextFile (hFind, &fdd) != 0 );
104138
105139 DWORD dwError = GetLastError ();
140+ FindClose (hFind);
106141 if (dwError != ERROR_NO_MORE_FILES)
107142 {
108143 CXX_LOG_ERROR (" Failed on FindNextFile. Error: %d" , dwError);
109144 throw SnowflakeTransferException (TransferError::DIR_OPEN_ERROR,
110145 srcLocationPlatform.c_str (), dwError);
111146 }
112- FindClose (hFind);
113147
114148#else
115- unsigned long dirSep = srcLocationPlatform.find_last_of (PATH_SEP);
116- std::string dirPath = srcLocationPlatform.substr (0 , dirSep + 1 );
117- std::string filePattern = srcLocationPlatform.substr (dirSep + 1 );
118-
119149 DIR * dir = nullptr ;
120150 struct dirent * dir_entry;
121151 if ((dir = opendir (dirPath.c_str ())) != NULL )
@@ -130,8 +160,11 @@ void Snowflake::Client::FileMetadataInitializer::populateSrcLocUploadMetadata(st
130160 if (!ret)
131161 {
132162 if (S_ISREG (fileStatus.st_mode )) {
133- initUploadFileMetadata (dirPath, dir_entry->d_name ,
134- (size_t ) fileStatus.st_size , putThreshold);
163+ fileList.pushback (dirPath + dir_entry->d_name );
164+ }
165+ else if (S_ISDIR (fileStatus.st_mode ))
166+ {
167+ includeSubfolderFilesRecursive (dirPath + dir_entry->d_name , fileList);
135168 }
136169 }
137170 else
@@ -169,7 +202,7 @@ void Snowflake::Client::FileMetadataInitializer::initCompressionMetadata(
169202 // guess
170203 CXX_LOG_INFO (" Auto detect on compression type" );
171204 fileMetadata.sourceCompression = FileCompressionType::guessCompressionType (
172- fileMetadata.srcFileName );
205+ m_stmtPutGet-> UTF8ToPlatformString ( fileMetadata.srcFileName ) );
173206 }
174207 else if (!sf_strncasecmp (m_sourceCompression, COMPRESSION_NONE,
175208 sizeof (COMPRESSION_NONE)))
@@ -253,8 +286,9 @@ populateSrcLocDownloadMetadata(std::string &sourceLocation,
253286 size_t getThreshold)
254287{
255288 std::string fullPath = *remoteLocation + sourceLocation;
256- size_t dirSep = fullPath.find_last_of (' /' );
257- std::string dstFileName = fullPath.substr (dirSep + 1 );
289+ size_t dirSep = sourceLocation.find_last_of (' /' );
290+ std::string dstFileName = sourceLocation.substr (dirSep + 1 );
291+ std::string dstPath = sourceLocation.substr (0 , dirSep + 1 );
258292
259293 FileMetadata fileMetadata;
260294 fileMetadata.presignedUrl = presignedUrl;
@@ -271,6 +305,7 @@ populateSrcLocDownloadMetadata(std::string &sourceLocation,
271305 metaListToPush.push_back (fileMetadata);
272306 metaListToPush.back ().srcFileName = fullPath;
273307 metaListToPush.back ().destFileName = dstFileName;
308+ metaListToPush.back ().destPath = dstPath;
274309 if (encMat)
275310 {
276311 EncryptionProvider::decryptFileKey (&(metaListToPush.back ()), encMat, getRandomDev ());
0 commit comments