2727#include < cstring>
2828// fix NAME_MAX not found on macOS GCC8.1
2929#include < climits>
30+ #include < memory>
3031
3132#ifdef _WIN32
3233
4142// When compiling Unicode targets WinAPI automatically uses *W Unicode versions
4243// of called functions. Thus, we explicitly call *A versions of the functions.
4344
44- static BOOL myIsDirectory (const std::string& path)
45- {
46- // See http://msdn.microsoft.com/en-us/library/bb773621(VS.85).aspx
47- return PathIsDirectoryA (path.c_str ());
48- }
49-
50- static HANDLE myFindFirstFile (const std::string& path, LPWIN32_FIND_DATAA findData)
51- {
52- HANDLE hFind = FindFirstFileA (path.c_str (), findData);
53- return hFind;
54- }
55-
56- static BOOL myFileExists (const std::string& path)
57- {
58- return PathFileExistsA (path.c_str ()) && !PathIsDirectoryA (path.c_str ());
59- }
60-
6145std::string FileLister::recursiveAddFiles (std::map<std::string, std::size_t > &files, const std::string &path, const std::set<std::string> &extra, const PathMatch& ignored)
6246{
6347 return addFiles (files, path, extra, true , ignored);
6448}
6549
6650std::string FileLister::addFiles (std::map<std::string, std::size_t > &files, const std::string &path, const std::set<std::string> &extra, bool recursive, const PathMatch& ignored)
6751{
52+ if (path.empty ())
53+ return " no path specified" ;
54+
6855 const std::string cleanedPath = Path::toNativeSeparators (path);
6956
7057 // basedir is the base directory which is used to form pathnames.
@@ -75,7 +62,7 @@ std::string FileLister::addFiles(std::map<std::string, std::size_t> &files, cons
7562 std::string searchPattern = cleanedPath;
7663
7764 // The user wants to check all files in a dir
78- const bool checkAllFilesInDir = ( myIsDirectory ( cleanedPath) != FALSE );
65+ const bool checkAllFilesInDir = Path::isDirectory ( cleanedPath);
7966
8067 if (checkAllFilesInDir) {
8168 const char c = cleanedPath.back ();
@@ -100,60 +87,63 @@ std::string FileLister::addFiles(std::map<std::string, std::size_t> &files, cons
10087 }
10188
10289 WIN32_FIND_DATAA ffd;
103- HANDLE hFind = myFindFirstFile (searchPattern, &ffd);
104- if (INVALID_HANDLE_VALUE == hFind)
105- return " " ;
90+ HANDLE hFind = FindFirstFileA (searchPattern.c_str (), &ffd);
91+ if (INVALID_HANDLE_VALUE == hFind) {
92+ const DWORD err = GetLastError ();
93+ if (err == ERROR_FILE_NOT_FOUND) {
94+ // no files matched
95+ return " " ;
96+ }
97+ return " finding files failed (error: " + std::to_string (err) + " )" ;
98+ }
99+ std::unique_ptr<void , decltype (&FindClose)> hFind_deleter (hFind, FindClose);
106100
107101 do {
108- if (ffd.cFileName [0 ] == ' .' || ffd.cFileName [0 ] == ' \0 ' )
109- continue ;
110-
111- const char * ansiFfd = ffd.cFileName ;
112- if (std::strchr (ansiFfd,' ?' )) {
113- ansiFfd = ffd.cAlternateFileName ;
114- }
102+ if (ffd.cFileName [0 ] != ' .' && ffd.cFileName [0 ] != ' \0 ' )
103+ {
104+ const char * ansiFfd = ffd.cFileName ;
105+ if (std::strchr (ansiFfd,' ?' )) {
106+ ansiFfd = ffd.cAlternateFileName ;
107+ }
115108
116- const std::string fname (basedir + ansiFfd);
109+ const std::string fname (basedir + ansiFfd);
117110
118- if ((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0 ) {
119- // File
120- if ((!checkAllFilesInDir || Path::acceptFile (fname, extra)) && !ignored.match (fname)) {
121- const std::string nativename = Path::fromNativeSeparators (fname);
111+ if ((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0 ) {
112+ // File
113+ if ((!checkAllFilesInDir || Path::acceptFile (fname, extra)) && !ignored.match (fname)) {
114+ const std::string nativename = Path::fromNativeSeparators (fname);
122115
123- // Limitation: file sizes are assumed to fit in a 'size_t'
116+ // Limitation: file sizes are assumed to fit in a 'size_t'
124117#ifdef _WIN64
125- files[nativename] = (static_cast <std::size_t >(ffd.nFileSizeHigh ) << 32 ) | ffd.nFileSizeLow ;
118+ files[nativename] = (static_cast <std::size_t >(ffd.nFileSizeHigh ) << 32 ) | ffd.nFileSizeLow ;
126119#else
127- files[nativename] = ffd.nFileSizeLow ;
120+ files[nativename] = ffd.nFileSizeLow ;
128121#endif
129- }
130- } else {
131- // Directory
132- if (recursive) {
133- if (!ignored.match (fname)) {
134- std::string err = FileLister::recursiveAddFiles (files, fname, extra, ignored);
135- if (!err.empty ())
136- return err;
122+ }
123+ } else {
124+ // Directory
125+ if (recursive) {
126+ if (!ignored.match (fname)) {
127+ std::string err = FileLister::recursiveAddFiles (files, fname, extra, ignored);
128+ if (!err.empty ())
129+ return err;
130+ }
137131 }
138132 }
139133 }
140- } while (FindNextFileA (hFind, &ffd) != FALSE );
141134
142- FindClose ( hFind);
143- return " " ;
144- }
145-
146- bool FileLister::isDirectory ( const std::string &path)
147- {
148- return ( myIsDirectory (path) != FALSE );
149- }
135+ if (! FindNextFileA ( hFind, &ffd)) {
136+ const DWORD err = GetLastError () ;
137+ // no more files matched
138+ if (err != ERROR_NO_MORE_FILES)
139+ return " failed to get next file (error: " + std::to_string (err) + " ) " ;
140+ break ;
141+ }
142+ } while ( true );
150143
151- bool FileLister::fileExists (const std::string &path)
152- {
153- return (myFileExists (path) != FALSE );
144+ return " " ;
154145}
155146
156-
157147#else
158148
159149// /////////////////////////////////////////////////////////////////////////////
@@ -189,8 +179,11 @@ static std::string addFiles2(std::map<std::string, std::size_t> &files,
189179 if (stat (path.c_str (), &file_stat) != -1 ) {
190180 if ((file_stat.st_mode & S_IFMT) == S_IFDIR) {
191181 DIR * dir = opendir (path.c_str ());
192- if (!dir)
193- return " " ;
182+ if (!dir) {
183+ const int err = errno;
184+ return " could not open directory '" + path + " ' (errno: " + std::to_string (err) + " )" ;
185+ }
186+ std::unique_ptr<DIR, decltype (&closedir)> dir_deleter (dir, closedir);
194187
195188 std::string new_path = path;
196189 new_path += ' /' ;
@@ -204,15 +197,14 @@ static std::string addFiles2(std::map<std::string, std::size_t> &files,
204197 new_path += dir_result->d_name ;
205198
206199#if defined(_DIRENT_HAVE_D_TYPE) || defined(_BSD_SOURCE)
207- const bool path_is_directory = (dir_result->d_type == DT_DIR || (dir_result->d_type == DT_UNKNOWN && FileLister ::isDirectory (new_path)));
200+ const bool path_is_directory = (dir_result->d_type == DT_DIR || (dir_result->d_type == DT_UNKNOWN && Path ::isDirectory (new_path)));
208201#else
209- const bool path_is_directory = FileLister ::isDirectory (new_path);
202+ const bool path_is_directory = Path ::isDirectory (new_path);
210203#endif
211204 if (path_is_directory) {
212205 if (recursive && !ignored.match (new_path)) {
213206 std::string err = addFiles2 (files, new_path, extra, recursive, ignored);
214207 if (!err.empty ()) {
215- closedir (dir);
216208 return err;
217209 }
218210 }
@@ -221,13 +213,12 @@ static std::string addFiles2(std::map<std::string, std::size_t> &files,
221213 if (stat (new_path.c_str (), &file_stat) != -1 )
222214 files[new_path] = file_stat.st_size ;
223215 else {
224- closedir (dir) ;
225- return " Can't stat " + new_path + " errno: " + std::to_string (errno) ;
216+ const int err = errno ;
217+ return " could not stat file ' " + new_path + " ' ( errno: " + std::to_string (err) + " ) " ;
226218 }
227219 }
228220 }
229221 }
230- closedir (dir);
231222 } else
232223 files[path] = file_stat.st_size ;
233224 }
@@ -241,27 +232,14 @@ std::string FileLister::recursiveAddFiles(std::map<std::string, std::size_t> &fi
241232
242233std::string FileLister::addFiles (std::map<std::string, std::size_t > &files, const std::string &path, const std::set<std::string> &extra, bool recursive, const PathMatch& ignored)
243234{
244- if (!path.empty ()) {
245- std::string corrected_path = path;
246- if (endsWith (corrected_path, ' /' ))
247- corrected_path.erase (corrected_path.end () - 1 );
235+ if (path.empty ())
236+ return " no path specified" ;
248237
249- return addFiles2 (files, corrected_path, extra, recursive, ignored);
250- }
251-
252- return " " ;
253- }
254-
255- bool FileLister::isDirectory (const std::string &path)
256- {
257- struct stat file_stat;
258- return (stat (path.c_str (), &file_stat) != -1 && (file_stat.st_mode & S_IFMT) == S_IFDIR);
259- }
238+ std::string corrected_path = path;
239+ if (endsWith (corrected_path, ' /' ))
240+ corrected_path.erase (corrected_path.end () - 1 );
260241
261- bool FileLister::fileExists (const std::string &path)
262- {
263- struct stat file_stat;
264- return (stat (path.c_str (), &file_stat) != -1 && (file_stat.st_mode & S_IFMT) == S_IFREG);
242+ return addFiles2 (files, corrected_path, extra, recursive, ignored);
265243}
266244
267245#endif
0 commit comments