]> granicus.if.org Git - icinga2/commitdiff
Make sort order for Utility::{Glob,GlobRecursive} deterministic.
authorGunnar Beutner <gunnar.beutner@netways.de>
Thu, 22 May 2014 11:11:59 +0000 (13:11 +0200)
committerGunnar Beutner <gunnar.beutner@netways.de>
Thu, 22 May 2014 11:12:58 +0000 (13:12 +0200)
Fixes #5854

lib/base/utility.cpp

index 98b79dcfb19b8adf0a22dd036e52d332727ffc8b..c11a43e09165432990d5b46095e36cf418ad2f55 100644 (file)
@@ -450,6 +450,8 @@ String Utility::NewUniqueID(void)
  */
 bool Utility::Glob(const String& pathSpec, const boost::function<void (const String&)>& callback, int type)
 {
+       std::vector<String> files, dirs;
+
 #ifdef _WIN32
        HANDLE handle;
        WIN32_FIND_DATA wfd;
@@ -472,13 +474,12 @@ bool Utility::Glob(const String& pathSpec, const boost::function<void (const Str
                if (strcmp(wfd.cFileName, ".") == 0 || strcmp(wfd.cFileName, "..") == 0)
                        continue;
 
-               if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && !(type & GlobDirectory))
-                       continue;
-
-               if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && !(type & GlobFile))
-                       continue;
+               String path = DirName(pathSpec) + "/" + wfd.cFileName;
 
-               callback(DirName(pathSpec) + "/" + wfd.cFileName);
+               if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (type & GlobDirectory))
+                       dirs.push_back(path)
+               else if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (type & GlobFile)
+                       files.push_back(path);
        } while (FindNextFile(handle, &wfd));
 
        if (!FindClose(handle)) {
@@ -486,8 +487,6 @@ bool Utility::Glob(const String& pathSpec, const boost::function<void (const Str
                    << boost::errinfo_api_function("FindClose")
                    << errinfo_win32_error(GetLastError()));
        }
-
-       return true;
 #else /* _WIN32 */
        glob_t gr;
 
@@ -519,19 +518,26 @@ bool Utility::Glob(const String& pathSpec, const boost::function<void (const Str
                if (!S_ISDIR(statbuf.st_mode) && !S_ISREG(statbuf.st_mode))
                        continue;
 
-               if (S_ISDIR(statbuf.st_mode) && !(type & GlobDirectory))
-                       continue;
+               if (S_ISDIR(statbuf.st_mode) && (type & GlobDirectory))
+                       dirs.push_back(*gp);
+               else if (!S_ISDIR(statbuf.st_mode) && (type & GlobFile))
+                       files.push_back(*gp);
+       }
 
-               if (!S_ISDIR(statbuf.st_mode) && !(type & GlobFile))
-                       continue;
+       globfree(&gr);
+#endif /* _WIN32 */
 
-               callback(*gp);
+       std::sort(files.begin(), files.end());
+       BOOST_FOREACH(const String& cpath, files) {
+               callback(cpath);
        }
 
-       globfree(&gr);
+       std::sort(dirs.begin(), dirs.end());
+       BOOST_FOREACH(const String& cpath, dirs) {
+               callback(cpath);
+       }
 
        return true;
-#endif /* _WIN32 */
 }
 
 /**
@@ -546,6 +552,8 @@ bool Utility::Glob(const String& pathSpec, const boost::function<void (const Str
  */
 bool Utility::GlobRecursive(const String& path, const String& pattern, const boost::function<void (const String&)>& callback, int type)
 {
+       std::vector<String> files, dirs, alldirs;
+
 #ifdef _WIN32
        HANDLE handle;
        WIN32_FIND_DATA wfd;
@@ -573,18 +581,16 @@ bool Utility::GlobRecursive(const String& path, const String& pattern, const boo
                String cpath = path + "/" + wfd.cFileName;
 
                if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-                       GlobRecursive(cpath, pattern, callback, type);
-
-               if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && !(type & GlobDirectory))
-                       continue;
-
-               if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && !(type & GlobFile))
-                       continue;
+                       alldirs.push_back(cpath);
 
                if (!Utility::Match(pattern, wfd.cFileName))
                        continue;
 
-               callback(cpath);
+               if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (type & GlobFile))
+                       files.push_back(cpath);
+
+               if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (type & GlobDirectory))
+                       dirs.push_back(cpath);
        } while (FindNextFile(handle, &wfd));
 
        if (!FindClose(handle)) {
@@ -625,44 +631,40 @@ bool Utility::GlobRecursive(const String& path, const String& pattern, const boo
 
                struct stat statbuf;
 
-               if (lstat(cpath.CStr(), &statbuf) < 0) {
-                       closedir(dirp);
-
-                       BOOST_THROW_EXCEPTION(posix_error()
-                           << boost::errinfo_api_function("lstat")
-                           << boost::errinfo_errno(errno)
-                           << boost::errinfo_file_name(cpath));
-               }
+               if (lstat(cpath.CStr(), &statbuf) < 0)
+                       continue;
 
                if (S_ISDIR(statbuf.st_mode))
-                       GlobRecursive(cpath, pattern, callback, type);
+                       alldirs.push_back(cpath);
 
-               if (stat(cpath.CStr(), &statbuf) < 0) {
-                       closedir(dirp);
+               if (!Utility::Match(pattern, ent.d_name))
+                       continue;
 
-                       BOOST_THROW_EXCEPTION(posix_error()
-                           << boost::errinfo_api_function("stat")
-                           << boost::errinfo_errno(errno)
-                           << boost::errinfo_file_name(cpath));
-               }
+               if (S_ISDIR(statbuf.st_mode) && (type & GlobDirectory))
+                       dirs.push_back(cpath);
 
-               if (!S_ISDIR(statbuf.st_mode) && !S_ISREG(statbuf.st_mode))
-                       continue;
+               if (!S_ISDIR(statbuf.st_mode) && (type & GlobFile))
+                       files.push_back(cpath);
+       }
 
-               if (S_ISDIR(statbuf.st_mode) && !(type & GlobDirectory))
-                       continue;
+       closedir(dirp);
 
-               if (!S_ISDIR(statbuf.st_mode) && !(type & GlobFile))
-                       continue;
+#endif /* _WIN32 */
 
-               if (!Utility::Match(pattern, ent.d_name))
-                       continue;
+       std::sort(files.begin(), files.end());
+       BOOST_FOREACH(const String& cpath, files) {
+               callback(cpath);
+       }
 
+       std::sort(dirs.begin(), dirs.end());
+       BOOST_FOREACH(const String& cpath, dirs) {
                callback(cpath);
        }
 
-       closedir(dirp);
-#endif /* _WIN32 */
+       std::sort(alldirs.begin(), alldirs.end());
+       BOOST_FOREACH(const String& cpath, alldirs) {
+               GlobRecursive(cpath, pattern, callback, type);
+       }
 
        return true;
 }