#include "snapper/AppUtil.h"
#include "snapper/BtrfsUtils.h"
+#ifdef HAVE_LIBBTRFSUTIL
+#include <btrfsutil.h>
+#endif
namespace snapper
{
bool
is_subvolume_read_only(int fd)
{
+#ifdef HAVE_LIBBTRFSUTIL
+ enum btrfs_util_error err;
+ bool readonly;
+
+ err = btrfs_util_get_subvolume_read_only_fd(fd, &readonly);
+ if (err)
+ throw runtime_error_with_errno("btrfs_util_get_subvolume_read_only_fd() failed", errno);
+
+ return readonly;
+#else
__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;
+#endif
}
void
create_subvolume(int fddst, const string& name)
{
+#ifdef HAVE_LIBBTRFSUTIL
+ enum btrfs_util_error err;
+
+ err = btrfs_util_create_subvolume_fd(fddst, name.c_str(), 0, NULL, NULL);
+ if (err)
+ throw runtime_error_with_errno("btrfs_util_create_subvolume_fd() failed", errno);
+#else
struct btrfs_ioctl_vol_args args;
memset(&args, 0, sizeof(args));
if (ioctl(fddst, BTRFS_IOC_SUBVOL_CREATE, &args) < 0)
throw runtime_error_with_errno("ioctl(BTRFS_IOC_SUBVOL_CREATE) failed", errno);
+#endif
}
void
create_snapshot(int fd, int fddst, const string& name, bool read_only, qgroup_t qgroup)
{
+#ifdef HAVE_LIBBTRFSUTIL
+ enum btrfs_util_error err;
+ struct btrfs_util_qgroup_inherit *util_inherit = NULL;
+ int flags = 0;
+
+ if (read_only)
+ flags |= BTRFS_UTIL_CREATE_SNAPSHOT_READ_ONLY;
+
+#ifdef ENABLE_BTRFS_QUOTA
+ size_t size = sizeof(btrfs_qgroup_inherit) + sizeof(((btrfs_qgroup_inherit*) 0)->qgroups[0]);
+ vector<char> buffer(size, 0);
+
+ if (qgroup != no_qgroup)
+ {
+ struct btrfs_qgroup_inherit *inherit;
+
+ inherit = (btrfs_qgroup_inherit*) &buffer[0];
+ inherit->num_qgroups = 1;
+ inherit->num_ref_copies = 0;
+ inherit->num_excl_copies = 0;
+ inherit->qgroups[0] = qgroup;
+ util_inherit = (struct btrfs_util_qgroup_inherit *)inherit;
+ }
+#endif
+ err = btrfs_util_create_snapshot_fd2(fd, fddst, name.c_str(), flags, NULL, util_inherit);
+ if (err && errno != ENOTTY && errno != EINVAL)
+ throw runtime_error_with_errno("btrfs_util_create_snapshot_fd2() failed", errno);
+
+ /* No BTRFS_IOC_SNAP_CREATE fallback */
+#else
struct btrfs_ioctl_vol_args_v2 args_v2;
memset(&args_v2, 0, sizeof(args_v2));
if (ioctl(fddst, BTRFS_IOC_SNAP_CREATE, &args) < 0)
throw runtime_error_with_errno("ioctl(BTRFS_IOC_SNAP_CREATE) failed", errno);
+#endif
}
void
delete_subvolume(int fd, const string& name)
{
+#ifdef HAVE_LIBBTRFSUTIL
+ enum btrfs_util_error err;
+
+ err = btrfs_util_delete_subvolume_fd(fd, name.c_str(), 0);
+ if (err)
+ throw runtime_error_with_errno("btrfs_util_delete_subvolume_fd() failed", errno);
+#else
struct btrfs_ioctl_vol_args args;
memset(&args, 0, sizeof(args));
if (ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &args) < 0)
throw runtime_error_with_errno("ioctl(BTRFS_IOC_SNAP_DESTROY) failed", errno);
+#endif
}
void
set_default_id(int fd, subvolid_t id)
{
+#ifdef HAVE_LIBBTRFSUTIL
+ enum btrfs_util_error err;
+
+ err = btrfs_util_set_default_subvolume_fd(fd, id);
+ if (err)
+ throw runtime_error_with_errno("btrfs_util_set_default_subvolume_fd() failed", errno);
+#else
if (ioctl(fd, BTRFS_IOC_DEFAULT_SUBVOL, &id) < 0)
throw runtime_error_with_errno("ioctl(BTRFS_IOC_DEFAULT_SUBVOL) failed", errno);
+#endif
}
subvolid_t
get_default_id(int fd)
{
+#ifdef HAVE_LIBBTRFSUTIL
+ enum btrfs_util_error err;
+ uint64_t id;
+
+ err = btrfs_util_get_default_subvolume_fd(fd, &id);
+ if (err)
+ throw runtime_error_with_errno("btrfs_util_get_default_subvolume_fd() failed", errno);
+
+ return id;
+#else
struct btrfs_ioctl_search_args args;
memset(&args, 0, sizeof(args));
throw std::runtime_error("name != default");
return btrfs_disk_key_objectid(&di->location);
+#endif
}
bool
does_subvolume_exist(int fd, subvolid_t subvolid)
{
+#ifdef HAVE_LIBBTRFSUTIL
+ enum btrfs_util_error err;
+ struct btrfs_util_subvolume_info subvol_info;
+
+ err = btrfs_util_subvolume_info_fd(fd, subvolid, &subvol_info);
+ if (err == BTRFS_UTIL_ERROR_SUBVOLUME_NOT_FOUND)
+ return false;
+ else if (err)
+ throw runtime_error_with_errno("btrfs_util_subvolume_info_fd() failed", errno);
+
+ return true;
+#else
struct btrfs_ioctl_search_args args;
struct btrfs_ioctl_search_key* sk = &args.key;
throw runtime_error_with_errno("ioctl(BTRFS_IOC_TREE_SEARCH) failed", errno);
return sk->nr_items == 0;
+#endif
}
#endif
void
sync(int fd)
{
+#ifdef HAVE_LIBBTRFSUTIL
+ enum btrfs_util_error err;
+
+ err = btrfs_util_sync_fd(fd);
+ if (err)
+ throw runtime_error_with_errno("(btrfs_util_sync_fd() failed", errno);
+#else
if (ioctl(fd, BTRFS_IOC_SYNC) < 0)
throw runtime_error_with_errno("ioctl(BTRFS_IOC_SYNC) failed", errno);
+#endif
}