Hello community, here is the log from the commit of package snapper for openSUSE:Factory checked in at Sun Aug 7 19:04:23 CEST 2011. -------- --- snapper/snapper.changes 2011-08-01 14:50:48.000000000 +0200 +++ /mounts/work_src_done/STABLE/snapper/snapper.changes 2011-08-05 14:41:08.000000000 +0200 @@ -1,0 +2,5 @@ +Thu Aug 04 20:51:59 CEST 2011 - aschnell@suse.de + +- added experimental ext4 support + +------------------------------------------------------------------- calling whatdependson for head-i586 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ snapper.spec ++++++ --- /var/tmp/diff_new_pack.4IOYUk/_old 2011-08-07 19:03:27.000000000 +0200 +++ /var/tmp/diff_new_pack.4IOYUk/_new 2011-08-07 19:03:27.000000000 +0200 @@ -20,7 +20,7 @@ Name: snapper Version: 0.0.7 -Release: 1 +Release: 3 License: GPL Group: System/Packages BuildRoot: %{_tmppath}/%{name}-%{version}-build @@ -77,8 +77,9 @@ Summary: Library for filesystem snapshot management Group: System/Libraries -Requires: btrfsprogs diffutils util-linux +Requires: diffutils util-linux PreReq: %fillup_prereq +Supplements: btrfsprogs %description -n libsnapper1 This package contains libsnapper, a library for filesystem snapshot management. ++++++ snapper-0.0.7.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.0.7/LIBVERSION new/snapper-0.0.7/LIBVERSION --- old/snapper-0.0.7/LIBVERSION 2011-07-29 16:34:02.000000000 +0200 +++ new/snapper-0.0.7/LIBVERSION 2011-08-03 14:25:59.000000000 +0200 @@ -1 +1 @@ -1.1.0 +1.2.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.0.7/doc/snapper.8 new/snapper-0.0.7/doc/snapper.8 --- old/snapper-0.0.7/doc/snapper.8 2011-08-01 14:49:29.000000000 +0200 +++ new/snapper-0.0.7/doc/snapper.8 2011-08-05 14:40:21.000000000 +0200 @@ -1,7 +1,7 @@ .TH "snapper" "8" 0.0.7 "snapper" "System Tools" .SH "NAME" .LP -snapper - Command\-line program for btrfs snapshot management +snapper - Command\-line program for filesystem snapshot management .SH "SYNTAX" .LP @@ -12,16 +12,17 @@ .SH "DESCRIPTION" .LP -Snapper is a command\-line program for btrfs snapshot management. It can -create, delete and compare snapshots and rollback changes between snapshots. +Snapper is a command\-line program for filesystem snapshot management. It can +create, delete and compare snapshots and rollback changes between +snapshots. Supported filesystems are btrfs and ext4. .SH CONCEPTS .SS Configurations .LP -For each btrfs subvolume that should be snapshotted by snapper a configuration -file is required. The complete setup can be done with the create-config -command. +For each filesystem or subvolume that should be snapshotted by snapper a +configuration file is required. The complete setup can be done with the +create-config command. .SS Snapshots .LP @@ -36,7 +37,7 @@ \fBsingle\fR - These snapshots have no special relationship to other snapshots. .LP -Note that btrfs\-wise all three types are the same. +Note that filesystem\-wise all three types are the same. .SS Automatic Snapshot Creation Next to manual snapshot creation snapshots are also created automatically. @@ -70,7 +71,7 @@ Increase verbosity. .TP .I \-t, \-\-table\-style -Specifies table style to use. Table style is identified by an integer number. +Specifies table style. Table style is identified by an integer number. .TP .I \-c, \-\-config <name> Use specified configuration instead of the default. @@ -100,7 +101,11 @@ .TP .B create-config [options] <subvolume> -Create a new configuration for a btrfs subvolume. +Create a new configuration for a filesystem or subvolume. +.TP +\fI\-f, \-\-fstype\fR <fstype> +Manually set filesystem type. Supported values are btrfs and ext4. Without +this option snapper detect the filesystem. .TP \fI\-t, \-\-template\fR <name> Name of template for the new configuration file. @@ -143,6 +148,14 @@ Delete a snapshot. .TP +.B mount <number> +Mount a snapshot. Not required for all filesystem types. + +.TP +.B umount <number> +Unmount a snapshot. Not required for all filesystem types. + +.TP .B diff [options] <number1> <number2> Compare two snapshots. This will show a list of files and directories that have been created, modified or deleted in the time between the two @@ -179,6 +192,9 @@ .TP .B /etc/snapper/filters Directory containing filter files. +.TP +.B /var/log/snapper.log +Logfile. Please include this file in bug reports. .SH "HOMEPAGE" .LP diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.0.7/doc/snapper.8.in new/snapper-0.0.7/doc/snapper.8.in --- old/snapper-0.0.7/doc/snapper.8.in 2011-06-15 11:49:47.000000000 +0200 +++ new/snapper-0.0.7/doc/snapper.8.in 2011-08-05 10:26:24.000000000 +0200 @@ -1,7 +1,7 @@ .TH "snapper" "8" @VERSION@ "snapper" "System Tools" .SH "NAME" .LP -snapper - Command\-line program for btrfs snapshot management +snapper - Command\-line program for filesystem snapshot management .SH "SYNTAX" .LP @@ -12,16 +12,17 @@ .SH "DESCRIPTION" .LP -Snapper is a command\-line program for btrfs snapshot management. It can -create, delete and compare snapshots and rollback changes between snapshots. +Snapper is a command\-line program for filesystem snapshot management. It can +create, delete and compare snapshots and rollback changes between +snapshots. Supported filesystems are btrfs and ext4. .SH CONCEPTS .SS Configurations .LP -For each btrfs subvolume that should be snapshotted by snapper a configuration -file is required. The complete setup can be done with the create-config -command. +For each filesystem or subvolume that should be snapshotted by snapper a +configuration file is required. The complete setup can be done with the +create-config command. .SS Snapshots .LP @@ -36,7 +37,7 @@ \fBsingle\fR - These snapshots have no special relationship to other snapshots. .LP -Note that btrfs\-wise all three types are the same. +Note that filesystem\-wise all three types are the same. .SS Automatic Snapshot Creation Next to manual snapshot creation snapshots are also created automatically. @@ -70,7 +71,7 @@ Increase verbosity. .TP .I \-t, \-\-table\-style -Specifies table style to use. Table style is identified by an integer number. +Specifies table style. Table style is identified by an integer number. .TP .I \-c, \-\-config <name> Use specified configuration instead of the default. @@ -100,7 +101,11 @@ .TP .B create-config [options] <subvolume> -Create a new configuration for a btrfs subvolume. +Create a new configuration for a filesystem or subvolume. +.TP +\fI\-f, \-\-fstype\fR <fstype> +Manually set filesystem type. Supported values are btrfs and ext4. Without +this option snapper detect the filesystem. .TP \fI\-t, \-\-template\fR <name> Name of template for the new configuration file. @@ -143,6 +148,14 @@ Delete a snapshot. .TP +.B mount <number> +Mount a snapshot. Not required for all filesystem types. + +.TP +.B umount <number> +Unmount a snapshot. Not required for all filesystem types. + +.TP .B diff [options] <number1> <number2> Compare two snapshots. This will show a list of files and directories that have been created, modified or deleted in the time between the two @@ -179,6 +192,9 @@ .TP .B /etc/snapper/filters Directory containing filter files. +.TP +.B /var/log/snapper.log +Logfile. Please include this file in bug reports. .SH "HOMEPAGE" .LP diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.0.7/snapper/AppUtil.cc new/snapper-0.0.7/snapper/AppUtil.cc --- old/snapper-0.0.7/snapper/AppUtil.cc 2011-05-18 14:36:24.000000000 +0200 +++ new/snapper-0.0.7/snapper/AppUtil.cc 2011-08-04 17:59:55.000000000 +0200 @@ -331,6 +331,18 @@ string + realpath(const string& path) + { + char* buf = ::realpath(path.c_str(), NULL); + if (!buf) + return string(); + string s(buf); + free(buf); + return s; + } + + + string sformat(const string& format, ...) { char* result; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.0.7/snapper/AppUtil.h new/snapper-0.0.7/snapper/AppUtil.h --- old/snapper-0.0.7/snapper/AppUtil.h 2011-05-18 14:36:24.000000000 +0200 +++ new/snapper-0.0.7/snapper/AppUtil.h 2011-08-04 17:59:55.000000000 +0200 @@ -53,6 +53,8 @@ int readlink(const string& path, string& buf); int symlink(const string& oldpath, const string& newpath); + string realpath(const string& path); + template<class StreamType> void classic(StreamType& stream) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.0.7/snapper/File.cc new/snapper-0.0.7/snapper/File.cc --- old/snapper-0.0.7/snapper/File.cc 2011-07-29 16:34:02.000000000 +0200 +++ new/snapper-0.0.7/snapper/File.cc 2011-08-03 14:55:29.000000000 +0200 @@ -26,6 +26,7 @@ #include <unistd.h> #include <fnmatch.h> #include <errno.h> +#include <boost/algorithm/string.hpp> #include "snapper/File.h" #include "snapper/Snapper.h" @@ -311,6 +312,36 @@ } + Files::iterator + Files::findAbsolutePath(const string& filename) + { + string subvolume = getSnapper()->subvolumeDir(); + + if (!boost::starts_with(filename, subvolume)) + return end(); + + if (subvolume == "/") + return find(filename); + else + return find(string(filename, subvolume.size())); + } + + + Files::const_iterator + Files::findAbsolutePath(const string& filename) const + { + string subvolume = getSnapper()->subvolumeDir(); + + if (!boost::starts_with(filename, subvolume)) + return end(); + + if (subvolume == "/") + return find(filename); + else + return find(string(filename, subvolume.size())); + } + + unsigned int File::getPreToSystemStatus() { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.0.7/snapper/File.h new/snapper-0.0.7/snapper/File.h --- old/snapper-0.0.7/snapper/File.h 2011-05-26 15:38:04.000000000 +0200 +++ new/snapper-0.0.7/snapper/File.h 2011-08-03 14:25:59.000000000 +0200 @@ -163,6 +163,9 @@ iterator find(const string& name); const_iterator find(const string& name) const; + iterator findAbsolutePath(const string& name); + const_iterator findAbsolutePath(const string& name) const; + private: void initialize(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.0.7/snapper/Filesystem.cc new/snapper-0.0.7/snapper/Filesystem.cc --- old/snapper-0.0.7/snapper/Filesystem.cc 2011-07-31 22:32:24.000000000 +0200 +++ new/snapper-0.0.7/snapper/Filesystem.cc 2011-08-04 11:12:57.000000000 +0200 @@ -20,9 +20,11 @@ */ +#include <string.h> #include <sys/stat.h> #include <sys/types.h> #include <errno.h> +#include <mntent.h> #include "snapper/Filesystem.h" #include "snapper/Snapper.h" @@ -52,28 +54,27 @@ { SystemCmd cmd2(BTRFSBIN " subvolume create " + quote(subvolume + "/.snapshots")); if (cmd2.retcode() != 0) - { throw AddConfigFailedException("creating btrfs snapshot failed"); - } } string Btrfs::infosDir() const { - return subvolume + "/.snapshots"; + return (subvolume == "/" ? "" : subvolume) + "/.snapshots"; } string Btrfs::snapshotDir(unsigned int num) const { - return subvolume + "/.snapshots/" + decString(num) + "/snapshot"; + return (subvolume == "/" ? "" : subvolume) + "/.snapshots/" + + decString(num) + "/snapshot"; } void - Btrfs::createFilesystemSnapshot(unsigned int num) const + Btrfs::createSnapshot(unsigned int num) const { SystemCmd cmd(BTRFSBIN " subvolume snapshot " + quote(subvolume) + " " + quote(snapshotDir(num))); @@ -83,7 +84,7 @@ void - Btrfs::deleteFilesystemSnapshot(unsigned int num) const + Btrfs::deleteSnapshot(unsigned int num) const { SystemCmd cmd(BTRFSBIN " subvolume delete " + quote(snapshotDir(num))); if (cmd.retcode() != 0) @@ -91,20 +92,27 @@ } + bool + Btrfs::isSnapshotMounted(unsigned int num) const + { + return true; + } + + void - Btrfs::mountFilesystemSnapshot(unsigned int num) const + Btrfs::mountSnapshot(unsigned int num) const { } void - Btrfs::umountFilesystemSnapshot(unsigned int num) const + Btrfs::umountSnapshot(unsigned int num) const { } bool - Btrfs::checkFilesystemSnapshot(unsigned int num) const + Btrfs::checkSnapshot(unsigned int num) const { return checkDir(snapshotDir(num)); } @@ -122,6 +130,7 @@ } else if (errno != EEXIST) { + y2err("mkdir failed errno:" << errno << " (" << strerror(errno) << ")"); throw AddConfigFailedException("mkdir failed"); } @@ -134,6 +143,7 @@ } else if (errno != EEXIST) { + y2err("mkdir failed errno:" << errno << " (" << strerror(errno) << ")"); throw AddConfigFailedException("mkdir failed"); } } @@ -142,7 +152,7 @@ string Ext4::infosDir() const { - return subvolume + "/.snapshots/.info"; + return (subvolume == "/" ? "" : subvolume) + "/.snapshots/.info"; } @@ -156,12 +166,12 @@ string Ext4::snapshotFile(unsigned int num) const { - return subvolume + "/.snapshots/" + decString(num); + return (subvolume == "/" ? "" : subvolume) + "/.snapshots/" + decString(num); } void - Ext4::createFilesystemSnapshot(unsigned int num) const + Ext4::createSnapshot(unsigned int num) const { SystemCmd cmd1(TOUCHBIN " " + quote(snapshotFile(num))); if (cmd1.retcode() != 0) @@ -174,26 +184,61 @@ void - Ext4::deleteFilesystemSnapshot(unsigned int num) const + Ext4::deleteSnapshot(unsigned int num) const { SystemCmd cmd(CHSNAPBIN " -S " + quote(snapshotFile(num))); if (cmd.retcode() != 0) throw DeleteSnapshotFailedException(); + } + - // TODO + bool + Ext4::isSnapshotMounted(unsigned int num) const + { + FILE* f = setmntent("/etc/mtab", "r"); + if (!f) + { + y2err("setmntent failed"); + throw IsSnapshotMountedFailedException(); + } + + bool mounted = false; + + struct mntent* m; + while ((m = getmntent(f))) + { + if (strcmp(m->mnt_type, "rootfs") == 0) + continue; + + if (m->mnt_dir == snapshotDir(num)) + { + mounted = true; + break; + } + } + + endmntent(f); + + return mounted; } void - Ext4::mountFilesystemSnapshot(unsigned int num) const + Ext4::mountSnapshot(unsigned int num) const { + if (isSnapshotMounted(num)) + return; + SystemCmd cmd1(CHSNAPBIN " +n " + quote(snapshotFile(num))); if (cmd1.retcode() != 0) throw MountSnapshotFailedException(); int r1 = mkdir(snapshotDir(num).c_str(), 0755); if (r1 != 0 && errno != EEXIST) + { + y2err("mkdir failed errno:" << errno << " (" << strerror(errno) << ")"); throw MountSnapshotFailedException(); + } SystemCmd cmd2(MOUNTBIN " -t ext4 -r -o loop,noload " + quote(snapshotFile(num)) + " " + quote(snapshotDir(num))); @@ -203,8 +248,11 @@ void - Ext4::umountFilesystemSnapshot(unsigned int num) const + Ext4::umountSnapshot(unsigned int num) const { + if (!isSnapshotMounted(num)) + return; + SystemCmd cmd1(UMOUNTBIN " " + quote(snapshotDir(num))); if (cmd1.retcode() != 0) throw UmountSnapshotFailedException(); @@ -212,11 +260,13 @@ SystemCmd cmd2(CHSNAPBIN " -n " + quote(snapshotFile(num))); if (cmd2.retcode() != 0) throw UmountSnapshotFailedException(); + + rmdir(snapshotDir(num).c_str()); } bool - Ext4::checkFilesystemSnapshot(unsigned int num) const + Ext4::checkSnapshot(unsigned int num) const { return checkNormalFile(snapshotFile(num)); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.0.7/snapper/Filesystem.h new/snapper-0.0.7/snapper/Filesystem.h --- old/snapper-0.0.7/snapper/Filesystem.h 2011-07-31 22:32:24.000000000 +0200 +++ new/snapper-0.0.7/snapper/Filesystem.h 2011-08-04 10:47:10.000000000 +0200 @@ -51,13 +51,14 @@ virtual string infosDir() const = 0; virtual string snapshotDir(unsigned int num) const = 0; - virtual void createFilesystemSnapshot(unsigned int num) const = 0; - virtual void deleteFilesystemSnapshot(unsigned int num) const = 0; + virtual void createSnapshot(unsigned int num) const = 0; + virtual void deleteSnapshot(unsigned int num) const = 0; - virtual void mountFilesystemSnapshot(unsigned int num) const = 0; - virtual void umountFilesystemSnapshot(unsigned int num) const = 0; + virtual bool isSnapshotMounted(unsigned int num) const = 0; + virtual void mountSnapshot(unsigned int num) const = 0; + virtual void umountSnapshot(unsigned int num) const = 0; - virtual bool checkFilesystemSnapshot(unsigned int num) const = 0; + virtual bool checkSnapshot(unsigned int num) const = 0; protected: @@ -79,13 +80,14 @@ virtual string infosDir() const; virtual string snapshotDir(unsigned int num) const; - virtual void createFilesystemSnapshot(unsigned int num) const; - virtual void deleteFilesystemSnapshot(unsigned int num) const; + virtual void createSnapshot(unsigned int num) const; + virtual void deleteSnapshot(unsigned int num) const; - virtual void mountFilesystemSnapshot(unsigned int num) const; - virtual void umountFilesystemSnapshot(unsigned int num) const; + virtual bool isSnapshotMounted(unsigned int num) const; + virtual void mountSnapshot(unsigned int num) const; + virtual void umountSnapshot(unsigned int num) const; - virtual bool checkFilesystemSnapshot(unsigned int num) const; + virtual bool checkSnapshot(unsigned int num) const; }; @@ -104,13 +106,14 @@ virtual string snapshotDir(unsigned int num) const; virtual string snapshotFile(unsigned int num) const; - virtual void createFilesystemSnapshot(unsigned int num) const; - virtual void deleteFilesystemSnapshot(unsigned int num) const; + virtual void createSnapshot(unsigned int num) const; + virtual void deleteSnapshot(unsigned int num) const; - virtual void mountFilesystemSnapshot(unsigned int num) const; - virtual void umountFilesystemSnapshot(unsigned int num) const; + virtual bool isSnapshotMounted(unsigned int num) const; + virtual void mountSnapshot(unsigned int num) const; + virtual void umountSnapshot(unsigned int num) const; - virtual bool checkFilesystemSnapshot(unsigned int num) const; + virtual bool checkSnapshot(unsigned int num) const; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.0.7/snapper/Snapper.cc new/snapper-0.0.7/snapper/Snapper.cc --- old/snapper-0.0.7/snapper/Snapper.cc 2011-07-31 22:32:24.000000000 +0200 +++ new/snapper-0.0.7/snapper/Snapper.cc 2011-08-05 11:21:57.000000000 +0200 @@ -24,6 +24,7 @@ #include <sys/types.h> #include <glob.h> #include <string.h> +#include <mntent.h> #include <boost/algorithm/string.hpp> #include "config.h" @@ -542,12 +543,12 @@ void Snapper::addConfig(const string& config_name, const string& subvolume, - const string& template_name) + const string& fstype, const string& template_name) { y2mil("Snapper add-config"); y2mil("libsnapper version " VERSION); y2mil("config_name:" << config_name << " subvolume:" << subvolume << - " template_name:" << template_name); + " fstype:" << fstype << " template_name:" << template_name); if (config_name.empty() || config_name.find_first_of(" \t") != string::npos) { @@ -564,6 +565,16 @@ throw AddConfigFailedException("cannot access template config"); } + auto_ptr<Filesystem> filesystem; + try + { + filesystem.reset(Filesystem::create(fstype, subvolume)); + } + catch (const InvalidConfigException& e) + { + throw AddConfigFailedException("invalid filesystem type"); + } + try { SysconfigFile sysconfig(SYSCONFIGFILE); @@ -593,14 +604,72 @@ { SysconfigFile config(CONFIGSDIR "/" + config_name); config.setValue("SUBVOLUME", subvolume); + config.setValue("FSTYPE", fstype); } catch (const FileNotFoundException& e) { throw AddConfigFailedException("modifying config failed"); } - auto_ptr<Filesystem> filesystem(new Btrfs(subvolume)); filesystem->addConfig(); } + + static bool + is_subpath(const string& a, const string& b) + { + if (b == "/") + return true; + + size_t len = b.length(); + + if (len > a.length()) + return false; + + return (len == a.length() || a[len] == '/') && a.compare(0, len, b) == 0; + } + + + bool + Snapper::detectFstype(const string& subvolume, string& fstype) + { + y2mil("subvolume:" << subvolume); + + if (!boost::starts_with(subvolume, "/") || !checkDir(subvolume)) + return false; + + FILE* f = setmntent("/etc/mtab", "r"); + if (!f) + { + y2err("setmntent failed"); + return false; + } + + fstype.clear(); + + string best_match; + + struct mntent* m; + while ((m = getmntent(f))) + { + if (strcmp(m->mnt_type, "rootfs") == 0) + continue; + + if (strlen(m->mnt_dir) >= best_match.length() && is_subpath(subvolume, m->mnt_dir)) + { + best_match = m->mnt_dir; + fstype = m->mnt_type; + } + } + + endmntent(f); + + if (fstype == "ext4dev") + fstype = "ext4"; + + y2mil("fstype:" << fstype); + + return !best_match.empty(); + } + } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.0.7/snapper/Snapper.h new/snapper-0.0.7/snapper/Snapper.h --- old/snapper-0.0.7/snapper/Snapper.h 2011-07-29 16:34:02.000000000 +0200 +++ new/snapper-0.0.7/snapper/Snapper.h 2011-08-02 12:19:16.000000000 +0200 @@ -140,7 +140,9 @@ static list<ConfigInfo> getConfigs(); static void addConfig(const string& config_name, const string& subvolume, - const string& template_name); + const string& fstype, const string& template_name); + + static bool detectFstype(const string& subvolume, string& fstype); const Filesystem* getFilesystem() const { return filesystem; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.0.7/snapper/Snapshot.cc new/snapper-0.0.7/snapper/Snapshot.cc --- old/snapper-0.0.7/snapper/Snapshot.cc 2011-08-01 12:30:45.000000000 +0200 +++ new/snapper-0.0.7/snapper/Snapshot.cc 2011-08-04 10:47:10.000000000 +0200 @@ -149,7 +149,7 @@ getChildValue(node, "cleanup", snapshot.cleanup); - if (!snapper->getFilesystem()->checkFilesystemSnapshot(num)) + if (!snapper->getFilesystem()->checkSnapshot(num)) { y2err("snapshot check failed. not adding snapshot " << num); continue; @@ -274,15 +274,21 @@ unsigned int Snapshots::nextNumber() { - unsigned int num = entries.empty() ? 1 : entries.rbegin()->num + 1; + unsigned int num = entries.empty() ? 0 : entries.rbegin()->num; - int r; - while ((r = mkdir((snapper->infosDir() + "/" + decString(num)).c_str(), 0777)) == -1 && - errno == EEXIST) + while (true) + { ++num; - if (r != 0) - { + if (snapper->getFilesystem()->checkSnapshot(num)) + continue; + + if (mkdir((snapper->infosDir() + "/" + decString(num)).c_str(), 0777) == 0) + break; + + if (errno == EEXIST) + continue; + y2err("mkdir failed errno:" << errno << " (" << strerror(errno) << ")"); throw IOErrorException(); } @@ -322,28 +328,41 @@ void Snapshot::mountFilesystemSnapshot() const { - snapper->getFilesystem()->mountFilesystemSnapshot(num); + if (isCurrent()) + return; + + snapper->getFilesystem()->mountSnapshot(num); } void Snapshot::umountFilesystemSnapshot() const { - snapper->getFilesystem()->umountFilesystemSnapshot(num); + if (isCurrent()) + return; + + snapper->getFilesystem()->umountSnapshot(num); } void Snapshot::createFilesystemSnapshot() const { - snapper->getFilesystem()->createFilesystemSnapshot(num); + if (isCurrent()) + throw IllegalSnapshotException(); + + snapper->getFilesystem()->createSnapshot(num); } void Snapshot::deleteFilesystemSnapshot() const { - snapper->getFilesystem()->deleteFilesystemSnapshot(num); + if (isCurrent()) + throw IllegalSnapshotException(); + + snapper->getFilesystem()->umountSnapshot(num); + snapper->getFilesystem()->deleteSnapshot(num); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.0.7/snapper/Snapshot.h new/snapper-0.0.7/snapper/Snapshot.h --- old/snapper-0.0.7/snapper/Snapshot.h 2011-07-29 19:50:42.000000000 +0200 +++ new/snapper-0.0.7/snapper/Snapshot.h 2011-08-04 10:47:10.000000000 +0200 @@ -54,6 +54,12 @@ }; + struct IsSnapshotMountedFailedException : public std::exception + { + explicit IsSnapshotMountedFailedException() throw() {} + virtual const char* what() const throw() { return "is snapshot mounted failed"; } + }; + struct MountSnapshotFailedException : public std::exception { explicit MountSnapshotFailedException() throw() {} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.0.7/snapper.spec.in new/snapper-0.0.7/snapper.spec.in --- old/snapper-0.0.7/snapper.spec.in 2011-07-04 16:20:45.000000000 +0200 +++ new/snapper-0.0.7/snapper.spec.in 2011-08-05 12:36:14.000000000 +0200 @@ -61,8 +61,9 @@ %package -n libsnapper@LIBVERSION_MAJOR@ Summary: Library for filesystem snapshot management Group: System/Libraries -Requires: btrfsprogs diffutils util-linux +Requires: diffutils util-linux PreReq: %fillup_prereq +Supplements: btrfsprogs %description -n libsnapper@LIBVERSION_MAJOR@ This package contains libsnapper, a library for filesystem snapshot management. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.0.7/tools/snapper.cc new/snapper-0.0.7/tools/snapper.cc --- old/snapper-0.0.7/tools/snapper.cc 2011-08-01 12:33:33.000000000 +0200 +++ new/snapper-0.0.7/tools/snapper.cc 2011-08-04 21:12:47.000000000 +0200 @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2011 Novell, Inc. + * + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, you may + * find current contact information at www.novell.com. + */ + #include <stdlib.h> #include <string.h> @@ -89,6 +110,7 @@ << _("\tsnapper create-config <subvolume>") << endl << endl << _(" Options for 'create-config' command:") << endl + << _("\t--fstype, -f <fstype>\t\tManually set filesystem type.") << endl << _("\t--template, -t <name>\t\tName of config template to use.") << endl << endl; } @@ -98,6 +120,7 @@ command_create_config() { const struct option options[] = { + { "fstype", required_argument, 0, 'f' }, { "template", required_argument, 0, 't' }, { 0, 0, 0, 0 } }; @@ -109,18 +132,33 @@ exit(EXIT_FAILURE); } - string subvolume = getopts.popArg(); + string subvolume = realpath(getopts.popArg()); + if (subvolume.empty()) + { + cerr << _("Invalid subvolume.") << endl; + exit(EXIT_FAILURE); + } + string fstype = ""; string template_name = "default"; GetOpts::parsed_opts::const_iterator opt; + if ((opt = opts.find("fstype")) != opts.end()) + fstype = opt->second; + if ((opt = opts.find("template")) != opts.end()) template_name = opt->second; + if (fstype.empty() && !Snapper::detectFstype(subvolume, fstype)) + { + cerr << _("Detecting filesystem type failed.") << endl; + exit(EXIT_FAILURE); + } + try { - Snapper::addConfig(config_name, subvolume, template_name); + Snapper::addConfig(config_name, subvolume, fstype, template_name); } catch (const AddConfigFailedException& e) { @@ -441,6 +479,60 @@ void +help_mount() +{ + cout << _(" Mount snapshot:") << endl + << _("\tsnapper mount <number>") << endl + << endl; +} + + +void +command_mount() +{ + getopts.parse("mount", GetOpts::no_options); + if (!getopts.hasArgs()) + { + cerr << _("Command 'mount' needs at least one argument.") << endl; + exit(EXIT_FAILURE); + } + + while (getopts.hasArgs()) + { + Snapshots::iterator snapshot = readNum(getopts.popArg()); + snapshot->mountFilesystemSnapshot(); + } +} + + +void +help_umount() +{ + cout << _(" Umount snapshot:") << endl + << _("\tsnapper umount <number>") << endl + << endl; +} + + +void +command_umount() +{ + getopts.parse("mount", GetOpts::no_options); + if (!getopts.hasArgs()) + { + cerr << _("Command 'mount' needs at least one argument.") << endl; + exit(EXIT_FAILURE); + } + + while (getopts.hasArgs()) + { + Snapshots::iterator snapshot = readNum(getopts.popArg()); + snapshot->umountFilesystemSnapshot(); + } +} + + +void help_diff() { cout << _(" Comparing snapshots:") << endl @@ -482,7 +574,7 @@ if ((opt = opts.find("file")) != opts.end()) { - tmp = files.find(opt->second); + tmp = files.findAbsolutePath(opt->second); if (tmp == files.end()) { cerr << sformat(_("File '%s' not included in diff."), opt->second.c_str()) << endl; @@ -505,7 +597,8 @@ if (tmp == files.end()) { for (Files::const_iterator it = files.begin(); it != files.end(); ++it) - fprintf(file, "%s %s\n", statusToString(it->getPreToPostStatus()).c_str(), it->getName().c_str()); + fprintf(file, "%s %s\n", statusToString(it->getPreToPostStatus()).c_str(), + it->getAbsolutePath(LOC_SYSTEM).c_str()); } else { @@ -589,7 +682,7 @@ name.erase(0, pos + 1); } - Files::iterator it = files.find(name); + Files::iterator it = files.findAbsolutePath(name); if (it == files.end()) { cerr << sformat(_("File '%s' not found in diff."), name.c_str()) << endl; @@ -693,6 +786,8 @@ help_create(); help_modify(); help_delete(); + help_mount(); + help_umount(); help_diff(); help_rollback(); help_cleanup(); @@ -744,6 +839,8 @@ cmds["create"] = command_create; cmds["modify"] = command_modify; cmds["delete"] = command_delete; + cmds["mount"] = command_mount; + cmds["umount"] = command_umount; cmds["diff"] = command_diff; cmds["rollback"] = command_rollback; cmds["cleanup"] = command_cleanup; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Remember to have fun... -- To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-commit+help@opensuse.org