summaryrefslogtreecommitdiff
path: root/src/basic
diff options
context:
space:
mode:
Diffstat (limited to 'src/basic')
-rw-r--r--src/basic/btrfs-util.c43
-rw-r--r--src/basic/btrfs-util.h1
-rw-r--r--src/basic/copy.c2
-rw-r--r--src/basic/fdset.c3
-rw-r--r--src/basic/hashmap.c14
-rw-r--r--src/basic/hashmap.h27
-rw-r--r--src/basic/macro.h11
-rw-r--r--src/basic/ordered-set.h6
-rw-r--r--src/basic/rm-rf.c2
-rw-r--r--src/basic/set.h4
-rw-r--r--src/basic/signal-util.c6
-rw-r--r--src/basic/signal-util.h2
-rw-r--r--src/basic/util.c45
-rw-r--r--src/basic/util.h6
14 files changed, 102 insertions, 70 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/fdset.c b/src/basic/fdset.c
index 6101b628ec..a4823e6659 100644
--- a/src/basic/fdset.c
+++ b/src/basic/fdset.c
@@ -267,8 +267,7 @@ bool fdset_isempty(FDSet *fds) {
int fdset_iterate(FDSet *s, Iterator *i) {
void *p;
- p = set_iterate(MAKE_SET(s), i);
- if (!p)
+ if (!set_iterate(MAKE_SET(s), i, &p))
return -ENOENT;
return PTR_TO_FD(p);
diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c
index 20d599d04b..0ee2f3bd31 100644
--- a/src/basic/hashmap.c
+++ b/src/basic/hashmap.c
@@ -733,29 +733,33 @@ static unsigned hashmap_iterate_entry(HashmapBase *h, Iterator *i) {
: hashmap_iterate_in_internal_order(h, i);
}
-void *internal_hashmap_iterate(HashmapBase *h, Iterator *i, const void **key) {
+bool internal_hashmap_iterate(HashmapBase *h, Iterator *i, void **value, const void **key) {
struct hashmap_base_entry *e;
void *data;
unsigned idx;
idx = hashmap_iterate_entry(h, i);
if (idx == IDX_NIL) {
+ if (value)
+ *value = NULL;
if (key)
*key = NULL;
- return NULL;
+ return false;
}
e = bucket_at(h, idx);
data = entry_value(h, e);
+ if (value)
+ *value = data;
if (key)
*key = e->key;
- return data;
+ return true;
}
-void *set_iterate(Set *s, Iterator *i) {
- return internal_hashmap_iterate(HASHMAP_BASE(s), i, NULL);
+bool set_iterate(Set *s, Iterator *i, void **value) {
+ return internal_hashmap_iterate(HASHMAP_BASE(s), i, value, NULL);
}
#define HASHMAP_FOREACH_IDX(idx, h, i) \
diff --git a/src/basic/hashmap.h b/src/basic/hashmap.h
index a03ee5812a..5723f09ca9 100644
--- a/src/basic/hashmap.h
+++ b/src/basic/hashmap.h
@@ -65,6 +65,7 @@ typedef struct {
} Iterator;
#define _IDX_ITERATOR_FIRST (UINT_MAX - 1)
+#define _IDX_ITERATOR_NIL (UINT_MAX)
#define ITERATOR_FIRST ((Iterator) { .idx = _IDX_ITERATOR_FIRST, .next_key = NULL })
typedef unsigned long (*hash_func_t)(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]);
@@ -296,12 +297,12 @@ static inline unsigned ordered_hashmap_buckets(OrderedHashmap *h) {
return internal_hashmap_buckets(HASHMAP_BASE(h));
}
-void *internal_hashmap_iterate(HashmapBase *h, Iterator *i, const void **key);
-static inline void *hashmap_iterate(Hashmap *h, Iterator *i, const void **key) {
- return internal_hashmap_iterate(HASHMAP_BASE(h), i, key);
+bool internal_hashmap_iterate(HashmapBase *h, Iterator *i, void **value, const void **key);
+static inline bool hashmap_iterate(Hashmap *h, Iterator *i, void **value, const void **key) {
+ return internal_hashmap_iterate(HASHMAP_BASE(h), i, value, key);
}
-static inline void *ordered_hashmap_iterate(OrderedHashmap *h, Iterator *i, const void **key) {
- return internal_hashmap_iterate(HASHMAP_BASE(h), i, key);
+static inline bool ordered_hashmap_iterate(OrderedHashmap *h, Iterator *i, void **value, const void **key) {
+ return internal_hashmap_iterate(HASHMAP_BASE(h), i, value, key);
}
void internal_hashmap_clear(HashmapBase *h);
@@ -386,24 +387,16 @@ static inline char **ordered_hashmap_get_strv(OrderedHashmap *h) {
* It is safe to remove the current entry.
*/
#define HASHMAP_FOREACH(e, h, i) \
- for ((i) = ITERATOR_FIRST, (e) = hashmap_iterate((h), &(i), NULL); \
- (e); \
- (e) = hashmap_iterate((h), &(i), NULL))
+ for ((i) = ITERATOR_FIRST; hashmap_iterate((h), &(i), (void**)&(e), NULL); )
#define ORDERED_HASHMAP_FOREACH(e, h, i) \
- for ((i) = ITERATOR_FIRST, (e) = ordered_hashmap_iterate((h), &(i), NULL); \
- (e); \
- (e) = ordered_hashmap_iterate((h), &(i), NULL))
+ for ((i) = ITERATOR_FIRST; ordered_hashmap_iterate((h), &(i), (void**)&(e), NULL); )
#define HASHMAP_FOREACH_KEY(e, k, h, i) \
- for ((i) = ITERATOR_FIRST, (e) = hashmap_iterate((h), &(i), (const void**) &(k)); \
- (e); \
- (e) = hashmap_iterate((h), &(i), (const void**) &(k)))
+ for ((i) = ITERATOR_FIRST; hashmap_iterate((h), &(i), (void**)&(e), (const void**) &(k)); )
#define ORDERED_HASHMAP_FOREACH_KEY(e, k, h, i) \
- for ((i) = ITERATOR_FIRST, (e) = ordered_hashmap_iterate((h), &(i), (const void**) &(k)); \
- (e); \
- (e) = ordered_hashmap_iterate((h), &(i), (const void**) &(k)))
+ for ((i) = ITERATOR_FIRST; ordered_hashmap_iterate((h), &(i), (void**)&(e), (const void**) &(k)); )
DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free);
DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free);
diff --git a/src/basic/macro.h b/src/basic/macro.h
index cc1c9e73c0..5fa17ed208 100644
--- a/src/basic/macro.h
+++ b/src/basic/macro.h
@@ -248,18 +248,19 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
REENABLE_WARNING
#endif
+#define assert_log(expr) ((_likely_(expr)) \
+ ? (true) \
+ : (log_assert_failed_return(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__), false))
+
#define assert_return(expr, r) \
do { \
- if (_unlikely_(!(expr))) { \
- log_assert_failed_return(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
+ if (!assert_log(expr)) \
return (r); \
- } \
} while (false)
#define assert_return_errno(expr, r, err) \
do { \
- if (_unlikely_(!(expr))) { \
- log_assert_failed_return(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
+ if (!assert_log(expr)) { \
errno = err; \
return (r); \
} \
diff --git a/src/basic/ordered-set.h b/src/basic/ordered-set.h
index 766a1f2e83..6c617ab305 100644
--- a/src/basic/ordered-set.h
+++ b/src/basic/ordered-set.h
@@ -47,12 +47,12 @@ static inline bool ordered_set_isempty(OrderedSet *s) {
return ordered_hashmap_isempty((OrderedHashmap*) s);
}
-static inline void *ordered_set_iterate(OrderedSet *s, Iterator *i) {
- return ordered_hashmap_iterate((OrderedHashmap*) s, i, NULL);
+static inline bool ordered_set_iterate(OrderedSet *s, Iterator *i, void **value) {
+ return ordered_hashmap_iterate((OrderedHashmap*) s, i, value, NULL);
}
#define ORDERED_SET_FOREACH(e, s, i) \
- for ((i) = ITERATOR_FIRST, (e) = ordered_set_iterate((s), &(i)); (e); (e) = ordered_set_iterate((s), &(i)))
+ for ((i) = ITERATOR_FIRST; ordered_set_iterate((s), &(i), (void**)&(e)); )
DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free);
diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c
index bafd483be2..dbbe817684 100644
--- a/src/basic/rm-rf.c
+++ b/src/basic/rm-rf.c
@@ -182,7 +182,7 @@ int rm_rf(const char *path, RemoveFlags flags) {
if (r >= 0)
return r;
- if (r != -ENOTTY && r != -EINVAL)
+ if (r != -ENOTTY && r != -EINVAL && r != -ENOTDIR)
return r;
/* Not btrfs or not a subvolume */
diff --git a/src/basic/set.h b/src/basic/set.h
index 4dffecd39d..51e40d3a6c 100644
--- a/src/basic/set.h
+++ b/src/basic/set.h
@@ -91,7 +91,7 @@ static inline unsigned set_buckets(Set *s) {
return internal_hashmap_buckets(HASHMAP_BASE(s));
}
-void *set_iterate(Set *s, Iterator *i);
+bool set_iterate(Set *s, Iterator *i, void **value);
static inline void set_clear(Set *s) {
internal_hashmap_clear(HASHMAP_BASE(s));
@@ -125,7 +125,7 @@ int set_put_strdup(Set *s, const char *p);
int set_put_strdupv(Set *s, char **l);
#define SET_FOREACH(e, s, i) \
- for ((i) = ITERATOR_FIRST, (e) = set_iterate((s), &(i)); (e); (e) = set_iterate((s), &(i)))
+ for ((i) = ITERATOR_FIRST; set_iterate((s), &(i), (void**)&(e)); )
DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free);
DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free_free);
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..e0c5069ff8 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -60,8 +60,8 @@
#include <linux/fs.h>
/* When we include libgen.h because we need dirname() we immediately
- * undefine basename() since libgen.h defines it as a macro to the XDG
- * version which is really broken. */
+ * undefine basename() since libgen.h defines it as a macro to the POSIX
+ * version which is really broken. We prefer GNU basename(). */
#include <libgen.h>
#undef basename
@@ -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);