From: Arvin Schnell Date: Fri, 20 May 2011 10:31:42 +0000 (+0200) Subject: - silently create missing parent directories X-Git-Tag: v0.1.3~378 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1a7da70454ef1bb970bd0e17bd4d6000dca86e5d;p=thirdparty%2Fsnapper.git - silently create missing parent directories --- diff --git a/snapper/File.cc b/snapper/File.cc index a292f53d..65866b52 100644 --- a/snapper/File.cc +++ b/snapper/File.cc @@ -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; + } } } } diff --git a/snapper/File.h b/snapper/File.h index c9436fc1..96bb4e08 100644 --- a/snapper/File.h +++ b/snapper/File.h @@ -106,6 +106,8 @@ namespace snapper const Snapper* getSnapper() const; + bool createParentDirectories(const string& path) const; + const Comparison* comparison; string name; diff --git a/testsuite-real/.gitignore b/testsuite-real/.gitignore index 93c45433..c0e93592 100644 --- a/testsuite-real/.gitignore +++ b/testsuite-real/.gitignore @@ -4,6 +4,8 @@ permissions1 permissions2 owner1 owner2 +missing-directory1 error1 error2 error3 +error4 diff --git a/testsuite-real/Makefile.am b/testsuite-real/Makefile.am index 9a4bbfea..2acf42fd 100644 --- a/testsuite-real/Makefile.am +++ b/testsuite-real/Makefile.am @@ -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 index 00000000..349818e8 --- /dev/null +++ b/testsuite-real/error4.cc @@ -0,0 +1,34 @@ + +#include +#include + +#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 index 00000000..d5b0369d --- /dev/null +++ b/testsuite-real/missing-directory1.cc @@ -0,0 +1,37 @@ + +#include +#include + +#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); +} diff --git a/testsuite-real/run-all b/testsuite-real/run-all index 43b689e7..5514c5cb 100755 --- a/testsuite-real/run-all +++ b/testsuite-real/run-all @@ -26,7 +26,10 @@ run permissions2 run owner1 run owner2 +run missing-directory1 + run error1 run error2 run error3 +run error4