diff options
Diffstat (limited to 'src/shared/rm-rf.c')
-rw-r--r-- | src/shared/rm-rf.c | 31 |
1 files changed, 22 insertions, 9 deletions
diff --git a/src/shared/rm-rf.c b/src/shared/rm-rf.c index 50112e3b5e..a89e8afc2a 100644 --- a/src/shared/rm-rf.c +++ b/src/shared/rm-rf.c @@ -21,6 +21,7 @@ #include "util.h" #include "path-util.h" +#include "btrfs-util.h" #include "rm-rf.h" int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) { @@ -116,22 +117,22 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) { } if ((flags & REMOVE_SUBVOLUME) && st.st_ino == 256) { - struct btrfs_ioctl_vol_args args = {}; /* This could be a subvolume, try to remove it */ - strncpy(args.name, de->d_name, sizeof(args.name)-1); - if (ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &args) < 0) { - - if (errno != ENOTTY && errno != EINVAL) { + r = btrfs_subvol_remove_fd(fd, de->d_name, true); + if (r < 0) { + if (r != -ENOTTY && r != -EINVAL) { if (ret == 0) - ret = -errno; + ret = r; safe_close(subdir_fd); continue; } - /* ENOTTY, then it wasn't a btrfs subvolume */ + /* ENOTTY, then it wasn't a + * btrfs subvolume, continue + * below. */ } else { /* It was a subvolume, continue. */ safe_close(subdir_fd); @@ -175,6 +176,18 @@ int rm_rf(const char *path, RemoveFlags flags) { return -EPERM; } + if ((flags & (REMOVE_SUBVOLUME|REMOVE_ROOT|REMOVE_PHYSICAL)) == (REMOVE_SUBVOLUME|REMOVE_ROOT|REMOVE_PHYSICAL)) { + /* Try to remove as subvolume first */ + r = btrfs_subvol_remove(path, true); + if (r >= 0) + return r; + + if (r != -ENOTTY && r != -EINVAL) + return r; + + /* Not btrfs or not a subvolume */ + } + fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); if (fd < 0) { @@ -201,8 +214,8 @@ int rm_rf(const char *path, RemoveFlags flags) { r = rm_rf_children(fd, flags, NULL); if (flags & REMOVE_ROOT) { - if (rmdir(path) < 0 && errno != ENOENT) { - if (r == 0) + if (rmdir(path) < 0) { + if (r == 0 && errno != ENOENT) r = -errno; } } |