]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Add util::create_dir, replacing create_parent_dirs and create_dir
authorJoel Rosdahl <joel@rosdahl.net>
Sun, 25 Aug 2019 08:49:00 +0000 (10:49 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Thu, 5 Sep 2019 20:04:43 +0000 (22:04 +0200)
src/ccache.cpp
src/ccache.hpp
src/lockfile.cpp
src/util.cpp
src/util.hpp
unittest/framework.cpp
unittest/test_util.cpp

index 96163a0a1f1990d092fb68a0aa1178e93e1ad81c..9142d355a915b6a6098bbb588bc6bfa0c250afe1 100644 (file)
@@ -3432,7 +3432,7 @@ out:
 static void
 create_initial_config_file(const char* path)
 {
-  if (create_parent_dirs(path) != 0) {
+  if (!util::create_dir(util::dir_name(path))) {
     return;
   }
 
index b34374e9a05918a36c3be44c3fdd46f6b876b789..9e2d0f6ce962ea361245df8efa2b48325b70f8af 100644 (file)
@@ -163,8 +163,6 @@ bool copy_fd(int fd_in, int fd_out);
 bool clone_file(const char* src, const char* dest, bool via_tmp_file);
 bool copy_file(const char* src, const char* dest, bool via_tmp_file);
 bool move_file(const char* src, const char* dest);
-int create_dir(const char* dir);
-int create_parent_dirs(const char* path);
 const char* get_hostname(void);
 const char* tmp_string(void);
 char* format(const char* format, ...) ATTR_FORMAT(printf, 1, 2);
index c717d09152c271c3ca2b914b78d97bf4151cd95f..bc9d1745352154cdb5bf8ec811ae69ee911924ee 100644 (file)
@@ -17,6 +17,7 @@
 // Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
 #include "ccache.hpp"
+#include "util.hpp"
 
 // This function acquires a lockfile for the given path. Returns true if the
 // lock was acquired, otherwise false. If the lock has been considered stale
@@ -49,7 +50,7 @@ lockfile_acquire(const char* path, unsigned staleness_limit)
       cc_log("lockfile_acquire: open WRONLY %s: %s", lockfile, strerror(errno));
       if (saved_errno == ENOENT) {
         // Directory doesn't exist?
-        if (create_parent_dirs(lockfile) == 0) {
+        if (util::create_dir(util::dir_name(lockfile))) {
           // OK. Retry.
           continue;
         }
@@ -104,7 +105,7 @@ lockfile_acquire(const char* path, unsigned staleness_limit)
     cc_log("lockfile_acquire: symlink %s: %s", lockfile, strerror(saved_errno));
     if (saved_errno == ENOENT) {
       // Directory doesn't exist?
-      if (create_parent_dirs(lockfile) == 0) {
+      if (util::create_dir(util::dir_name(lockfile))) {
         // OK. Retry.
         continue;
       }
index cb3815eb26fe4ff28f283db46b164b53b20ddab1..a826dc0945f7337158be476f810b2b9e8a94fe0e 100644 (file)
@@ -508,61 +508,6 @@ move_file(const char* src, const char* dest)
   return ok;
 }
 
-// Make sure a directory exists.
-int
-create_dir(const char* dir)
-{
-  struct stat st;
-  if (stat(dir, &st) == 0) {
-    if (S_ISDIR(st.st_mode)) {
-      return 0;
-    }
-    errno = ENOTDIR;
-    return 1;
-  }
-  if (mkdir(dir, 0777) != 0 && errno != EEXIST) {
-    return 1;
-  }
-  return 0;
-}
-
-// Create directories leading to path. Returns 0 on success, otherwise -1.
-int
-create_parent_dirs(const char* path)
-{
-  int res;
-  char* parent = x_dirname(path);
-  struct stat st;
-  if (stat(parent, &st) == 0) {
-    if (S_ISDIR(st.st_mode)) {
-      res = 0;
-    } else {
-      res = -1;
-      errno = ENOTDIR;
-    }
-  } else {
-    res = create_parent_dirs(parent);
-    if (res == 0) {
-      res = mkdir(parent, 0777);
-      // Have to handle the condition of the directory already existing because
-      // the file system could have changed in between calling stat and
-      // actually creating the directory. This can happen when there are
-      // multiple instances of ccache running and trying to create the same
-      // directory chain, which usually is the case when the cache root does
-      // not initially exist. As long as one of the processes creates the
-      // directories then our condition is satisfied and we avoid a race
-      // condition.
-      if (res != 0 && errno == EEXIST) {
-        res = 0;
-      }
-    } else {
-      res = -1;
-    }
-  }
-  free(parent);
-  return res;
-}
-
 // Return a static string with the current hostname.
 const char*
 get_hostname(void)
@@ -1226,7 +1171,7 @@ create_tmp_fd(char** fname)
   char* tmpl = format("%s.%s", *fname, tmp_string());
   int fd = mkstemp(tmpl);
   if (fd == -1 && errno == ENOENT) {
-    if (create_parent_dirs(*fname) != 0) {
+    if (!util::create_dir(util::dir_name(*fname))) {
       fatal("Failed to create directory %s: %s",
             x_dirname(*fname),
             strerror(errno));
@@ -1776,6 +1721,33 @@ base_name(const std::string& path)
   return n == std::string::npos ? path : path.substr(n + 1);
 }
 
+bool
+create_dir(const std::string& dir)
+{
+  struct stat st;
+  if (stat(dir.c_str(), &st) == 0) {
+    if (S_ISDIR(st.st_mode)) {
+      return true;
+    } else {
+      errno = ENOTDIR;
+      return false;
+    }
+  } else {
+    if (!create_dir(util::dir_name(dir))) {
+      return false;
+    }
+    int result = mkdir(dir.c_str(), 0777);
+    // Treat an already existing directory as OK since the file system could
+    // have changed in between calling stat and actually creating the
+    // directory. This can happen when there are multiple instances of ccache
+    // running and trying to create the same directory chain, which usually is
+    // the case when the cache root does not initially exist. As long as one of
+    // the processes creates the directories then our condition is satisfied
+    // and we avoid a race condition.
+    return result == 0 || errno == EEXIST;
+  }
+}
+
 std::string
 dir_name(const std::string& path)
 {
index c3d58417a7abef2b7ecf71e9f2c393e4536fb976..7be3b5b131665d5b4bfcf7ec8550eb687ab4969f 100644 (file)
@@ -27,6 +27,11 @@ namespace util {
 // Get base name of path.
 std::string base_name(const std::string& path);
 
+// Create a directory if needed, including its parents if needed.
+//
+// Returns true if the directory exists or could be created, otherwise false.
+bool create_dir(const std::string& dir);
+
 // Get directory name of path.
 std::string dir_name(const std::string& path);
 
index 5a219c707db60ed8adeef25a1aaa4c4af8cadd50..648079e2d0c6d4b6a7b9a4cf6ec8b46c0cc42906 100644 (file)
@@ -18,6 +18,7 @@
 
 #include "framework.hpp"
 
+#include "../src/util.hpp"
 #include "util.hpp"
 
 #include <float.h>
@@ -109,7 +110,7 @@ cct_suite_begin(const char* name)
     printf("=== SUITE: %s ===\n", name);
   }
   dir_before_suite = gnu_getcwd();
-  create_dir(name);
+  util::create_dir(name);
   cct_chdir(name);
   current_suite = name;
 }
@@ -130,7 +131,7 @@ cct_test_begin(const char* name)
     printf("--- TEST: %s ---\n", name);
   }
   dir_before_test = gnu_getcwd();
-  create_dir(name);
+  util::create_dir(name);
   cct_chdir(name);
   current_test = name;
 
index 0ba3ffc5188177f6148f0b47ef3be1637dc40518..9520834464eefa3e11af79cb814ebba697b98f6d 100644 (file)
@@ -30,6 +30,19 @@ TEST_CASE("util::base_name")
   CHECK(util::base_name("/foo/bar/f.txt") == "f.txt");
 }
 
+TEST_CASE("util::create_dir")
+{
+  CHECK(util::create_dir("/"));
+
+  CHECK(util::create_dir("create/dir"));
+  struct stat st;
+  CHECK(stat("create/dir", &st) == 0);
+  CHECK(S_ISDIR(st.st_mode));
+
+  util::write_file("create/dir/file", "");
+  CHECK(!util::create_dir("create/dir/file"));
+}
+
 TEST_CASE("util::dir_name")
 {
   CHECK(util::dir_name("") == ".");