]> git.ipfire.org Git - thirdparty/snapper.git/commitdiff
- silently create missing parent directories
authorArvin Schnell <aschnell@suse.de>
Fri, 20 May 2011 10:31:42 +0000 (12:31 +0200)
committerArvin Schnell <aschnell@suse.de>
Fri, 20 May 2011 10:31:42 +0000 (12:31 +0200)
snapper/File.cc
snapper/File.h
testsuite-real/.gitignore
testsuite-real/Makefile.am
testsuite-real/error4.cc [new file with mode: 0644]
testsuite-real/missing-directory1.cc [new file with mode: 0644]
testsuite-real/run-all

index a292f53d017a1b1144909d3d9526310676c0ac67..65866b527a9189e7b7cc8714bc698f4e170086c8 100644 (file)
@@ -373,6 +373,26 @@ namespace snapper
     }
 
 
+    bool
+    File::createParentDirectories(const string& path) const
+    {
+       string::size_type pos = path.rfind('/');
+       if (pos == string::npos)
+           return true;
+
+       const string& leading_path = path.substr(0, pos);
+
+       struct stat fs;
+       if (stat(leading_path.c_str(), &fs) == 0)
+           return S_ISDIR(fs.st_mode);
+
+       if (!createParentDirectories(leading_path))
+           return false;
+
+       return mkdir(leading_path.c_str(), 0777) == 0;
+    }
+
+
     bool
     File::doRollback()
     {
@@ -440,36 +460,44 @@ namespace snapper
            }
            else
            {
-               switch (fs.st_mode & S_IFMT)
+               if (!createParentDirectories(getAbsolutePath(LOC_SYSTEM)))
                {
-                   case S_IFDIR: {
-                       if (mkdir(getAbsolutePath(LOC_SYSTEM).c_str(), 0) != 0)
-                       {
-                           y2err("mkdir failed path:" << getAbsolutePath(LOC_SYSTEM) <<
-                                 " errno:" << errno);
-                           error = true;
-                       }
-                       chmod(getAbsolutePath(LOC_SYSTEM).c_str(), fs.st_mode);
-                       chown(getAbsolutePath(LOC_SYSTEM).c_str(), fs.st_uid, fs.st_gid);
-                   } break;
+                   y2err("createParentDirectories failed path:" << getAbsolutePath(LOC_SYSTEM));
+                   error = true;
+               }
+               else
+               {
+                   switch (fs.st_mode & S_IFMT)
+                   {
+                       case S_IFDIR: {
+                           if (mkdir(getAbsolutePath(LOC_SYSTEM).c_str(), 0) != 0)
+                           {
+                               y2err("mkdir failed path:" << getAbsolutePath(LOC_SYSTEM) <<
+                                     " errno:" << errno);
+                               error = true;
+                           }
+                           chmod(getAbsolutePath(LOC_SYSTEM).c_str(), fs.st_mode);
+                           chown(getAbsolutePath(LOC_SYSTEM).c_str(), fs.st_uid, fs.st_gid);
+                       } break;
 
-                   case S_IFREG: {
-                       // TODO: use clonefile
-                       SystemCmd cmd(CPBIN " --preserve=mode,ownership " +
-                                     getAbsolutePath(LOC_PRE) + " " + getAbsolutePath(LOC_SYSTEM));
-                   } break;
+                       case S_IFREG: {
+                           // TODO: use clonefile
+                           SystemCmd cmd(CPBIN " --preserve=mode,ownership " +
+                                         getAbsolutePath(LOC_PRE) + " " + getAbsolutePath(LOC_SYSTEM));
+                       } break;
 
-                   case S_IFLNK: {
-                       string tmp;
-                       readlink(getAbsolutePath(LOC_PRE), tmp);
-                       if (symlink(tmp, getAbsolutePath(LOC_SYSTEM)) != 0)
-                       {
-                           y2err("symlink failed path:" << getAbsolutePath(LOC_SYSTEM) <<
-                                 " errno:" << errno);
-                           error = true;
-                       }
-                       lchown(getAbsolutePath(LOC_SYSTEM).c_str(), fs.st_uid, fs.st_gid);
-                   } break;
+                       case S_IFLNK: {
+                           string tmp;
+                           readlink(getAbsolutePath(LOC_PRE), tmp);
+                           if (symlink(tmp, getAbsolutePath(LOC_SYSTEM)) != 0)
+                           {
+                               y2err("symlink failed path:" << getAbsolutePath(LOC_SYSTEM) <<
+                                     " errno:" << errno);
+                               error = true;
+                           }
+                           lchown(getAbsolutePath(LOC_SYSTEM).c_str(), fs.st_uid, fs.st_gid);
+                       } break;
+                   }
                }
            }
        }
@@ -484,42 +512,50 @@ namespace snapper
            }
            else
            {
-               if (getPreToPostStatus() & CONTENT)
+               if (!createParentDirectories(getAbsolutePath(LOC_SYSTEM)))
                {
-                   switch (fs.st_mode & S_IFMT)
+                   y2err("createParentDirectories failed path:" << getAbsolutePath(LOC_SYSTEM));
+                   error = true;
+               }
+               else
+               {
+                   if (getPreToPostStatus() & CONTENT)
                    {
-                       case S_IFREG: {
-                           // TODO: use clonefile
-                           SystemCmd cmd(CPBIN " --preserve=mode,ownership " +
-                                         getAbsolutePath(LOC_PRE) + " " + getAbsolutePath(LOC_SYSTEM));
-                       } break;
-
-                       case S_IFLNK: {
-                           unlink(getAbsolutePath(LOC_SYSTEM).c_str());
-                           string tmp;
-                           readlink(getAbsolutePath(LOC_PRE), tmp);
-                           symlink(tmp, getAbsolutePath(LOC_SYSTEM));
-                       } break;
+                       switch (fs.st_mode & S_IFMT)
+                       {
+                           case S_IFREG: {
+                               // TODO: use clonefile
+                               SystemCmd cmd(CPBIN " --preserve=mode,ownership " +
+                                             getAbsolutePath(LOC_PRE) + " " + getAbsolutePath(LOC_SYSTEM));
+                           } break;
+
+                           case S_IFLNK: {
+                               unlink(getAbsolutePath(LOC_SYSTEM).c_str());
+                               string tmp;
+                               readlink(getAbsolutePath(LOC_PRE), tmp);
+                               symlink(tmp, getAbsolutePath(LOC_SYSTEM));
+                           } break;
+                       }
                    }
-               }
 
-               if (getPreToPostStatus() & PERMISSIONS)
-               {
-                   if (chmod(getAbsolutePath(LOC_SYSTEM).c_str(), fs.st_mode) != 0)
+                   if (getPreToPostStatus() & PERMISSIONS)
                    {
-                       y2err("chmod failed path:" << getAbsolutePath(LOC_SYSTEM) <<
-                             " errno:" << errno);
-                       error = true;
+                       if (chmod(getAbsolutePath(LOC_SYSTEM).c_str(), fs.st_mode) != 0)
+                       {
+                           y2err("chmod failed path:" << getAbsolutePath(LOC_SYSTEM) <<
+                                 " errno:" << errno);
+                           error = true;
+                       }
                    }
-               }
 
-               if (getPreToPostStatus() & (USER | GROUP))
-               {
-                   if (lchown(getAbsolutePath(LOC_SYSTEM).c_str(), fs.st_uid, fs.st_gid) != 0)
+                   if (getPreToPostStatus() & (USER | GROUP))
                    {
-                       y2err("lchown failed path:" << getAbsolutePath(LOC_SYSTEM) <<
-                             " errno:" << errno);
-                       error = true;
+                       if (lchown(getAbsolutePath(LOC_SYSTEM).c_str(), fs.st_uid, fs.st_gid) != 0)
+                       {
+                           y2err("lchown failed path:" << getAbsolutePath(LOC_SYSTEM) <<
+                                 " errno:" << errno);
+                           error = true;
+                       }
                    }
                }
            }
index c9436fc1a42db837485131cc242743f39e30c479..96bb4e081f626dc839e29204a3647dc27056eccd 100644 (file)
@@ -106,6 +106,8 @@ namespace snapper
 
        const Snapper* getSnapper() const;
 
+       bool createParentDirectories(const string& path) const;
+
        const Comparison* comparison;
 
        string name;
index 93c4543304e963b2849a184b0d6763c1580582f6..c0e935922b1a76630fc0ea848014d0da72a57381 100644 (file)
@@ -4,6 +4,8 @@ permissions1
 permissions2
 owner1
 owner2
+missing-directory1
 error1
 error2
 error3
+error4
index 9a4bbfea06c7999cc66d99b94c0346f9c11b0226..2acf42fd464f5d472c46b437777350b21a6d99a2 100644 (file)
@@ -10,8 +10,8 @@ LDADD = ../snapper/libsnapper.la
 
 noinst_SCRIPTS = run-all
 
-noinst_PROGRAMS = simple1 permissions1 permissions2 owner1 owner2 error1 error2        \
-       error3
+noinst_PROGRAMS = simple1 permissions1 permissions2 owner1 owner2      \
+       missing-directory1 error1 error2 error3 error4
 
 simple1_SOURCES = simple1.cc common.h common.cc
 
@@ -21,9 +21,12 @@ permissions2_SOURCES = permissions2.cc common.h common.cc
 owner1_SOURCES = owner1.cc common.h common.cc
 owner2_SOURCES = owner2.cc common.h common.cc
 
+missing_directory1_SOURCES = missing-directory1.cc common.h common.cc
+
 error1_SOURCES = error1.cc common.h common.cc
 error2_SOURCES = error2.cc common.h common.cc
 error3_SOURCES = error3.cc common.h common.cc
+error4_SOURCES = error4.cc common.h common.cc
 
 EXTRA_DIST = $(noinst_SCRIPTS)
 
diff --git a/testsuite-real/error4.cc b/testsuite-real/error4.cc
new file mode 100644 (file)
index 0000000..349818e
--- /dev/null
@@ -0,0 +1,34 @@
+
+#include <stdlib.h>
+#include <iostream>
+
+#include "common.h"
+
+using namespace std;
+
+
+int
+main()
+{
+    setup();
+
+    run_command("mkdir wrong-type");
+    run_command("touch wrong-type/file");
+
+    first_snapshot();
+
+    run_command("rm wrong-type/file");
+
+    second_snapshot();
+
+    run_command("rmdir wrong-type");
+    run_command("touch wrong-type");
+
+    check_rollback_statistics(1, 0, 0);
+
+    rollback();
+
+    check_rollback_errors(1, 0, 0);
+
+    exit(EXIT_SUCCESS);
+}
diff --git a/testsuite-real/missing-directory1.cc b/testsuite-real/missing-directory1.cc
new file mode 100644 (file)
index 0000000..d5b0369
--- /dev/null
@@ -0,0 +1,37 @@
+
+#include <stdlib.h>
+#include <iostream>
+
+#include "common.h"
+
+using namespace std;
+
+
+int
+main()
+{
+    setup();
+
+    run_command("mkdir not-here");
+    run_command("touch not-here/file");
+    run_command("mkdir not-here/directory");
+
+    first_snapshot();
+
+    run_command("rm not-here/file");
+    run_command("rmdir not-here/directory");
+
+    second_snapshot();
+
+    run_command("rmdir not-here");
+
+    check_rollback_statistics(2, 0, 0);
+
+    rollback();
+
+    check_rollback_errors(0, 0, 0);
+
+    check_first();
+
+    exit(EXIT_SUCCESS);
+}
index 43b689e71c79c2c27a3913be4a3852ee3233986d..5514c5cb640edd670eef788886c4b6a7521641e7 100755 (executable)
@@ -26,7 +26,10 @@ run permissions2
 run owner1
 run owner2
 
+run missing-directory1
+
 run error1
 run error2
 run error3
+run error4