diff options
Diffstat (limited to 'src/basic')
-rw-r--r-- | src/basic/btrfs-util.c | 43 | ||||
-rw-r--r-- | src/basic/btrfs-util.h | 1 | ||||
-rw-r--r-- | src/basic/copy.c | 2 | ||||
-rw-r--r-- | src/basic/signal-util.c | 6 | ||||
-rw-r--r-- | src/basic/signal-util.h | 2 | ||||
-rw-r--r-- | src/basic/util.c | 41 | ||||
-rw-r--r-- | src/basic/util.h | 6 |
7 files changed, 68 insertions, 33 deletions
diff --git a/src/basic/btrfs-util.c b/src/basic/btrfs-util.c index 49528dbf01..074deeccda 100644 --- a/src/basic/btrfs-util.c +++ b/src/basic/btrfs-util.c @@ -352,6 +352,19 @@ int btrfs_subvol_get_id_fd(int fd, uint64_t *ret) { return 0; } +int btrfs_subvol_get_id(int fd, const char *subvol, uint64_t *ret) { + _cleanup_close_ int subvol_fd = -1; + + assert(fd >= 0); + assert(ret); + + subvol_fd = openat(fd, subvol, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); + if (subvol_fd < 0) + return -errno; + + return btrfs_subvol_get_id_fd(subvol_fd, ret); +} + static bool btrfs_ioctl_search_args_inc(struct btrfs_ioctl_search_args *args) { assert(args); @@ -937,7 +950,7 @@ int btrfs_subvol_remove_fd(int fd, const char *subvolume, bool recursive) { return subvol_remove_children(fd, subvolume, 0, recursive); } -static int subvol_snapshot_children(int old_fd, int new_fd, const char *subvolume, uint64_t subvol_id, BtrfsSnapshotFlags flags) { +static int subvol_snapshot_children(int old_fd, int new_fd, const char *subvolume, uint64_t old_subvol_id, BtrfsSnapshotFlags flags) { struct btrfs_ioctl_search_args args = { .key.tree_id = BTRFS_ROOT_TREE_OBJECTID, @@ -956,8 +969,9 @@ static int subvol_snapshot_children(int old_fd, int new_fd, const char *subvolum .flags = flags & BTRFS_SNAPSHOT_READ_ONLY ? BTRFS_SUBVOL_RDONLY : 0, .fd = old_fd, }; - int r; _cleanup_close_ int subvolume_fd = -1; + uint64_t new_subvol_id; + int r; assert(old_fd >= 0); assert(new_fd >= 0); @@ -972,13 +986,17 @@ static int subvol_snapshot_children(int old_fd, int new_fd, const char *subvolum if (!(flags & BTRFS_SNAPSHOT_RECURSIVE)) return 0; - if (subvol_id == 0) { - r = btrfs_subvol_get_id_fd(old_fd, &subvol_id); + if (old_subvol_id == 0) { + r = btrfs_subvol_get_id_fd(old_fd, &old_subvol_id); if (r < 0) return r; } - args.key.min_offset = args.key.max_offset = subvol_id; + r = btrfs_subvol_get_id(new_fd, vol_args.name, &new_subvol_id); + if (r < 0) + return r; + + args.key.min_offset = args.key.max_offset = old_subvol_id; while (btrfs_ioctl_search_args_compare(&args) <= 0) { const struct btrfs_ioctl_search_header *sh; @@ -1001,17 +1019,24 @@ static int subvol_snapshot_children(int old_fd, int new_fd, const char *subvolum if (sh->type != BTRFS_ROOT_BACKREF_KEY) continue; - if (sh->offset != subvol_id) + + /* Avoid finding the source subvolume a second + * time */ + if (sh->offset != old_subvol_id) continue; - ref = BTRFS_IOCTL_SEARCH_HEADER_BODY(sh); + /* Avoid running into loops if the new + * subvolume is below the old one. */ + if (sh->objectid == new_subvol_id) + continue; + ref = BTRFS_IOCTL_SEARCH_HEADER_BODY(sh); p = strndup((char*) ref + sizeof(struct btrfs_root_ref), le64toh(ref->name_len)); if (!p) return -ENOMEM; zero(ino_args); - ino_args.treeid = subvol_id; + ino_args.treeid = old_subvol_id; ino_args.objectid = htole64(ref->dirid); if (ioctl(old_fd, BTRFS_IOC_INO_LOOKUP, &ino_args) < 0) @@ -1056,7 +1081,7 @@ static int subvol_snapshot_children(int old_fd, int new_fd, const char *subvolum } /* When btrfs clones the subvolumes, child - * subvolumes appear as directories. Remove + * subvolumes appear as empty directories. Remove * them, so that we can create a new snapshot * in their place */ if (unlinkat(new_child_fd, p, AT_REMOVEDIR) < 0) { diff --git a/src/basic/btrfs-util.h b/src/basic/btrfs-util.h index a7eb895c93..8632c3638c 100644 --- a/src/basic/btrfs-util.h +++ b/src/basic/btrfs-util.h @@ -61,6 +61,7 @@ int btrfs_subvol_snapshot(const char *old_path, const char *new_path, BtrfsSnaps int btrfs_subvol_set_read_only_fd(int fd, bool b); int btrfs_subvol_set_read_only(const char *path, bool b); int btrfs_subvol_get_read_only_fd(int fd); +int btrfs_subvol_get_id(int fd, const char *subvolume, uint64_t *ret); int btrfs_subvol_get_id_fd(int fd, uint64_t *ret); int btrfs_subvol_get_info_fd(int fd, BtrfsSubvolInfo *info); int btrfs_subvol_get_quota_fd(int fd, BtrfsQuotaInfo *quota); diff --git a/src/basic/copy.c b/src/basic/copy.c index 1282cb88be..230e7e4d3f 100644 --- a/src/basic/copy.c +++ b/src/basic/copy.c @@ -396,7 +396,7 @@ int copy_file_atomic(const char *from, const char *to, mode_t mode, bool replace assert(from); assert(to); - r = tempfn_random(to, &t); + r = tempfn_random(to, NULL, &t); if (r < 0) return r; diff --git a/src/basic/signal-util.c b/src/basic/signal-util.c index 84cf42b285..90abe8af81 100644 --- a/src/basic/signal-util.c +++ b/src/basic/signal-util.c @@ -159,7 +159,7 @@ int sigset_add_many(sigset_t *ss, ...) { return r; } -int sigprocmask_many(int how, ...) { +int sigprocmask_many(int how, sigset_t *old, ...) { va_list ap; sigset_t ss; int r; @@ -167,14 +167,14 @@ int sigprocmask_many(int how, ...) { if (sigemptyset(&ss) < 0) return -errno; - va_start(ap, how); + va_start(ap, old); r = sigset_add_many_ap(&ss, ap); va_end(ap); if (r < 0) return r; - if (sigprocmask(how, &ss, NULL) < 0) + if (sigprocmask(how, &ss, old) < 0) return -errno; return 0; diff --git a/src/basic/signal-util.h b/src/basic/signal-util.h index 9dc8a28726..5e6eb50b07 100644 --- a/src/basic/signal-util.h +++ b/src/basic/signal-util.h @@ -33,7 +33,7 @@ int default_signals(int sig, ...); int sigaction_many(const struct sigaction *sa, ...); int sigset_add_many(sigset_t *ss, ...); -int sigprocmask_many(int how, ...); +int sigprocmask_many(int how, sigset_t *old, ...); const char *signal_to_string(int i) _const_; int signal_from_string(const char *s) _pure_; diff --git a/src/basic/util.c b/src/basic/util.c index 6f6906f877..b7c70af541 100644 --- a/src/basic/util.c +++ b/src/basic/util.c @@ -2521,7 +2521,7 @@ int fopen_temporary(const char *path, FILE **_f, char **_temp_path) { assert(_f); assert(_temp_path); - r = tempfn_xxxxxx(path, &t); + r = tempfn_xxxxxx(path, NULL, &t); if (r < 0) return r; @@ -2551,7 +2551,7 @@ int symlink_atomic(const char *from, const char *to) { assert(from); assert(to); - r = tempfn_random(to, &t); + r = tempfn_random(to, NULL, &t); if (r < 0) return r; @@ -2594,7 +2594,7 @@ int mknod_atomic(const char *path, mode_t mode, dev_t dev) { assert(path); - r = tempfn_random(path, &t); + r = tempfn_random(path, NULL, &t); if (r < 0) return r; @@ -2615,7 +2615,7 @@ int mkfifo_atomic(const char *path, mode_t mode) { assert(path); - r = tempfn_random(path, &t); + r = tempfn_random(path, NULL, &t); if (r < 0) return r; @@ -4969,7 +4969,7 @@ int fflush_and_check(FILE *f) { return 0; } -int tempfn_xxxxxx(const char *p, char **ret) { +int tempfn_xxxxxx(const char *p, const char *extra, char **ret) { const char *fn; char *t; @@ -4981,24 +4981,27 @@ int tempfn_xxxxxx(const char *p, char **ret) { * /foo/bar/waldo * * Into this: - * /foo/bar/.#waldoXXXXXX + * /foo/bar/.#<extra>waldoXXXXXX */ fn = basename(p); if (!filename_is_valid(fn)) return -EINVAL; - t = new(char, strlen(p) + 2 + 6 + 1); + if (extra == NULL) + extra = ""; + + t = new(char, strlen(p) + 2 + strlen(extra) + 6 + 1); if (!t) return -ENOMEM; - strcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), fn), "XXXXXX"); + strcpy(stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn), "XXXXXX"); *ret = path_kill_slashes(t); return 0; } -int tempfn_random(const char *p, char **ret) { +int tempfn_random(const char *p, const char *extra, char **ret) { const char *fn; char *t, *x; uint64_t u; @@ -5012,18 +5015,21 @@ int tempfn_random(const char *p, char **ret) { * /foo/bar/waldo * * Into this: - * /foo/bar/.#waldobaa2a261115984a9 + * /foo/bar/.#<extra>waldobaa2a261115984a9 */ fn = basename(p); if (!filename_is_valid(fn)) return -EINVAL; - t = new(char, strlen(p) + 2 + 16 + 1); + if (!extra) + extra = ""; + + t = new(char, strlen(p) + 2 + strlen(extra) + 16 + 1); if (!t) return -ENOMEM; - x = stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), fn); + x = stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn); u = random_u64(); for (i = 0; i < 16; i++) { @@ -5037,7 +5043,7 @@ int tempfn_random(const char *p, char **ret) { return 0; } -int tempfn_random_child(const char *p, char **ret) { +int tempfn_random_child(const char *p, const char *extra, char **ret) { char *t, *x; uint64_t u; unsigned i; @@ -5048,14 +5054,17 @@ int tempfn_random_child(const char *p, char **ret) { /* Turns this: * /foo/bar/waldo * Into this: - * /foo/bar/waldo/.#3c2b6219aa75d7d0 + * /foo/bar/waldo/.#<extra>3c2b6219aa75d7d0 */ - t = new(char, strlen(p) + 3 + 16 + 1); + if (!extra) + extra = ""; + + t = new(char, strlen(p) + 3 + strlen(extra) + 16 + 1); if (!t) return -ENOMEM; - x = stpcpy(stpcpy(t, p), "/.#"); + x = stpcpy(stpcpy(stpcpy(t, p), "/.#"), extra); u = random_u64(); for (i = 0; i < 16; i++) { diff --git a/src/basic/util.h b/src/basic/util.h index 467ae234a0..7aca46d777 100644 --- a/src/basic/util.h +++ b/src/basic/util.h @@ -828,9 +828,9 @@ int bind_remount_recursive(const char *prefix, bool ro); int fflush_and_check(FILE *f); -int tempfn_xxxxxx(const char *p, char **ret); -int tempfn_random(const char *p, char **ret); -int tempfn_random_child(const char *p, char **ret); +int tempfn_xxxxxx(const char *p, const char *extra, char **ret); +int tempfn_random(const char *p, const char *extra, char **ret); +int tempfn_random_child(const char *p, const char *extra, char **ret); int take_password_lock(const char *root); |