]> git.ipfire.org Git - thirdparty/snapper.git/commitdiff
- added some functions for rollback (fate #317062)
authorArvin Schnell <aschnell@suse.de>
Wed, 2 Apr 2014 09:59:35 +0000 (11:59 +0200)
committerArvin Schnell <aschnell@suse.de>
Wed, 2 Apr 2014 09:59:35 +0000 (11:59 +0200)
snapper/Btrfs.cc
snapper/Btrfs.h
snapper/BtrfsUtils.cc
snapper/BtrfsUtils.h
snapper/Filesystem.cc
snapper/Filesystem.h

index 8bfc8752b7ccbce2399912f2bc83429067b4cf05..695bd662fd7e32bfda3406449a648b6c10af5ba8 100644 (file)
@@ -51,6 +51,7 @@
 #include "snapper/SnapperTmpl.h"
 #include "snapper/SnapperDefines.h"
 #include "snapper/Acls.h"
+#include "snapper/Regex.h"
 
 
 namespace snapper
@@ -1225,6 +1226,79 @@ namespace snapper
 #endif
 
 
+#ifdef ENABLE_ROLLBACK
+
+    unsigned int
+    Btrfs::getDefault() const
+    {
+       try
+       {
+           SDir subvolume_dir = openSubvolumeDir();
+           unsigned long long id = get_default_id(subvolume_dir.fd());
+           string name = get_subvolume(subvolume_dir.fd(), id);
+
+           if (name.empty())
+               return 0;
+
+           Regex rx("^.snapshots/([0-9]*)/snapshot");
+           if (!rx.match(name))
+               throw IOErrorException();
+
+           int num = 0;
+           rx.cap(1) >> num;
+           return num;
+       }
+       catch (const runtime_error& e)
+       {
+           throw IOErrorException();
+       }
+    }
+
+
+    void
+    Btrfs::setDefault(unsigned int num) const
+    {
+       try
+       {
+           if (num == 0)
+           {
+               SDir subvolume_dir = openSubvolumeDir();
+               unsigned long long id = get_id(subvolume_dir.fd());
+               set_default_id(subvolume_dir.fd(), id);
+           }
+           else
+           {
+               SDir snapshot_dir = openSnapshotDir(num);
+               unsigned long long id = get_id(snapshot_dir.fd());
+
+               SDir subvolume_dir = openSubvolumeDir();
+               set_default_id(subvolume_dir.fd(), id);
+           }
+       }
+       catch (const runtime_error& e)
+       {
+           throw IOErrorException();
+       }
+    }
+
+#else
+
+    unsigned int
+    Btrfs::getDefault() const
+    {
+       throw std::logic_error("not implemented");
+    }
+
+
+    void
+    Btrfs::setDefault(unsigned int num) const
+    {
+       throw std::logic_error("not implemented");
+    }
+
+#endif
+
+
 #ifdef ENABLE_ROLLBACK
 
     void
index fe77910700c778a6894949f80819d390e25d1b08..bcfe153a0f0939f1c515878f51eda49fb70e3c61 100644 (file)
@@ -60,6 +60,9 @@ namespace snapper
 
        virtual void cmpDirs(const SDir& dir1, const SDir& dir2, cmpdirs_cb_t cb) const;
 
+       virtual unsigned int getDefault() const;
+       virtual void setDefault(unsigned int num) const;
+
     private:
 
        void addToFstab() const;
index c0b9e99ff3f259c361b76fe09c4d9b9f353f09f9..fb44cb6df46fef7e0454adead72b16925dc9bdda 100644 (file)
@@ -69,10 +69,15 @@ struct btrfs_ioctl_vol_args_v2
 
 #endif
 
+#ifndef BTRFS_IOC_SUBVOL_GETFLAGS
+#define BTRFS_IOC_SUBVOL_GETFLAGS _IOR(BTRFS_IOCTL_MAGIC, 25, __u64)
+#endif
+
 
 namespace snapper
 {
 
+
     // See btrfsprogs source code for references.
 
 
@@ -84,6 +89,17 @@ namespace snapper
 
 
     bool
+    is_subvolume_read_only(int fd, bool& read_only)
+    {
+       __u64 flags;
+       if (ioctl(fd, BTRFS_IOC_SUBVOL_GETFLAGS, &flags) != 0)
+           throw runtime_error_with_errno("ioctl(BTRFS_IOC_SUBVOL_GETFLAGS) failed", errno);
+
+       return flags & BTRFS_SUBVOL_RDONLY;
+    }
+
+
+    void
     create_subvolume(int fddst, const string& name)
     {
        struct btrfs_ioctl_vol_args args;
@@ -137,6 +153,50 @@ namespace snapper
 
 #ifdef ENABLE_ROLLBACK
 
+    void
+    set_default_id(int fd, unsigned long long id)
+    {
+       if (ioctl(fd, BTRFS_IOC_DEFAULT_SUBVOL, &id) != 0)
+           throw runtime_error_with_errno("ioctl(BTRFS_IOC_DEFAULT_SUBVOL) failed", errno);
+    }
+
+
+    unsigned long long
+    get_default_id(int fd)
+    {
+       struct btrfs_ioctl_search_args args;
+       memset(&args, 0, sizeof(args));
+
+       struct btrfs_ioctl_search_key* sk = &args.key;
+       sk->tree_id = BTRFS_ROOT_TREE_OBJECTID;
+       sk->nr_items = 1;
+       sk->max_objectid = BTRFS_ROOT_TREE_DIR_OBJECTID;
+       sk->min_objectid = BTRFS_ROOT_TREE_DIR_OBJECTID;
+       sk->max_type = BTRFS_DIR_ITEM_KEY;
+       sk->min_type = BTRFS_DIR_ITEM_KEY;
+       sk->max_offset = (__u64) -1;
+       sk->max_transid = (__u64) -1;
+
+       if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) != 0)
+           throw runtime_error_with_errno("ioctl(BTRFS_IOC_TREE_SEARCH) failed", errno);
+
+       if (sk->nr_items == 0)
+           throw std::runtime_error("sk->nr_items == 0");
+
+       struct btrfs_ioctl_search_header* sh = (struct btrfs_ioctl_search_header*) args.buf;
+       if (sh->type != BTRFS_DIR_ITEM_KEY)
+           throw std::runtime_error("sh->type != BTRFS_DIR_ITEM_KEY");
+
+       struct btrfs_dir_item* di = (struct btrfs_dir_item*)(sh + 1);
+       int name_len = btrfs_stack_dir_name_len(di);
+       const char* name = (const char*)(di + 1);
+       if (strncmp("default", name, name_len) != 0)
+           throw std::runtime_error("name != default");
+
+       return btrfs_disk_key_objectid(&di->location);
+    }
+
+
     string
     get_subvolume(int fd, unsigned long long id)
     {
index f12ad1133079f0f30b1e3c1c1f37a4b6a0699db7..cb49702f1db20bbb3ce1d559c029e3f30cdfcc4d 100644 (file)
@@ -34,10 +34,15 @@ namespace snapper
 
     bool is_subvolume(const struct stat& stat);
 
+    bool is_subvolume_read_only(int fd);
+
     void create_subvolume(int fddst, const string& name);
     void create_snapshot(int fd, int fddst, const string& name, bool read_only);
     void delete_subvolume(int fd, const string& name);
 
+    void set_default_id(int fd, unsigned long long id);
+    unsigned long long get_default_id(int fd);
+
     string get_subvolume(int fd, unsigned long long id);
     unsigned long long get_id(int fd);
 
index 8e6bfa39e0279aff579db7a76d9242bf38fec8f8..a56c5015d147e90cebf8fd51bf2877d45caea338 100644 (file)
@@ -144,4 +144,18 @@ namespace snapper
        snapper::cmpDirs(dir1, dir2, cb);
     }
 
+
+    unsigned int
+    Filesystem::getDefault() const
+    {
+       throw std::logic_error("not implemented");
+    }
+
+
+    void
+    Filesystem::setDefault(unsigned int num) const
+    {
+       throw std::logic_error("not implemented");
+    }
+
 }
index 3958f55131558b4e6e54fc82e182bc39f7c5c229..6521abc7236aef4333d5fdd877bab9686142a583 100644 (file)
@@ -72,6 +72,9 @@ namespace snapper
 
        virtual void cmpDirs(const SDir& dir1, const SDir& dir2, cmpdirs_cb_t cb) const;
 
+       virtual unsigned int getDefault() const;
+       virtual void setDefault(unsigned int num) const;
+
     protected:
 
        const string subvolume;