summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2020-04-09 11:56:23 +0200
committerLennart Poettering <lennart@poettering.net>2020-04-09 12:12:52 +0200
commitd78a95d751069bcf48395cfd08e455138712f247 (patch)
tree49fa109a5ffdd2927b499756ef053bf9534078ce
parenta1db42eb0b3b3a6e00bc02d724052d1ef41584a9 (diff)
downloadsystemd-d78a95d751069bcf48395cfd08e455138712f247.tar.gz
btrfs-util: define helper that creates a btrfs subvol if we can, and a directory as fallback
-rw-r--r--src/basic/btrfs-util.c25
-rw-r--r--src/basic/btrfs-util.h2
2 files changed, 27 insertions, 0 deletions
diff --git a/src/basic/btrfs-util.c b/src/basic/btrfs-util.c
index 18a7217757..68367dfbd6 100644
--- a/src/basic/btrfs-util.c
+++ b/src/basic/btrfs-util.c
@@ -160,6 +160,31 @@ int btrfs_subvol_make(const char *path) {
return btrfs_subvol_make_fd(fd, subvolume);
}
+int btrfs_subvol_make_fallback(const char *path, mode_t mode) {
+ mode_t old, combined;
+ int r;
+
+ assert(path);
+
+ /* Let's work like mkdir(), i.e. take the specified mode, and mask it with the current umask. */
+ old = umask(~mode);
+ combined = old | ~mode;
+ if (combined != ~mode)
+ umask(combined);
+ r = btrfs_subvol_make(path);
+ umask(old);
+
+ if (r >= 0)
+ return 1; /* subvol worked */
+ if (r != -ENOTTY)
+ return r;
+
+ if (mkdir(path, mode) < 0)
+ return -errno;
+
+ return 0; /* plain directory */
+}
+
int btrfs_subvol_set_read_only_fd(int fd, bool b) {
uint64_t flags, nflags;
struct stat st;
diff --git a/src/basic/btrfs-util.h b/src/basic/btrfs-util.h
index b15667bf2f..c1bbb42ca1 100644
--- a/src/basic/btrfs-util.h
+++ b/src/basic/btrfs-util.h
@@ -66,6 +66,8 @@ int btrfs_quota_scan_ongoing(int fd);
int btrfs_subvol_make(const char *path);
int btrfs_subvol_make_fd(int fd, const char *subvolume);
+int btrfs_subvol_make_fallback(const char *path, mode_t);
+
int btrfs_subvol_snapshot_fd_full(int old_fd, const char *new_path, BtrfsSnapshotFlags flags, copy_progress_path_t progress_path, copy_progress_bytes_t progress_bytes, void *userdata);
static inline int btrfs_subvol_snapshot_fd(int old_fd, const char *new_path, BtrfsSnapshotFlags flags) {
return btrfs_subvol_snapshot_fd_full(old_fd, new_path, flags, NULL, NULL, NULL);