From db9a42545adaa54d789760f842702816625cc384 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 25 Jun 2018 20:04:07 +0200 Subject: [PATCH] chattr: optionally, return the old flags when updating them --- src/basic/btrfs-util.c | 2 +- src/basic/chattr-util.c | 16 +++++++++++----- src/basic/chattr-util.h | 4 ++-- src/basic/copy.c | 4 ++-- src/import/import-raw.c | 4 ++-- src/import/pull-raw.c | 6 +++--- src/journal/journal-file.c | 4 ++-- src/journal/journalctl.c | 2 +- src/shared/machine-image.c | 8 ++++---- src/tmpfiles/tmpfiles.c | 2 +- 10 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/basic/btrfs-util.c b/src/basic/btrfs-util.c index 0308048..1c9c5fd 100644 --- a/src/basic/btrfs-util.c +++ b/src/basic/btrfs-util.c @@ -1715,7 +1715,7 @@ int btrfs_subvol_snapshot_fd(int old_fd, const char *new_path, BtrfsSnapshotFlag * it: the IMMUTABLE bit. Let's use this here, if this is requested. */ if (flags & BTRFS_SNAPSHOT_FALLBACK_IMMUTABLE) - (void) chattr_path(new_path, FS_IMMUTABLE_FL, FS_IMMUTABLE_FL); + (void) chattr_path(new_path, FS_IMMUTABLE_FL, FS_IMMUTABLE_FL, NULL); } else { r = btrfs_subvol_set_read_only(new_path, true); if (r < 0) diff --git a/src/basic/chattr-util.c b/src/basic/chattr-util.c index 4ec1451..235cfb9 100644 --- a/src/basic/chattr-util.c +++ b/src/basic/chattr-util.c @@ -10,7 +10,7 @@ #include "fd-util.h" #include "macro.h" -int chattr_fd(int fd, unsigned value, unsigned mask) { +int chattr_fd(int fd, unsigned value, unsigned mask, unsigned *previous) { unsigned old_attr, new_attr; struct stat st; @@ -28,23 +28,29 @@ int chattr_fd(int fd, unsigned value, unsigned mask) { if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) return -ENOTTY; - if (mask == 0) + if (mask == 0 && !previous) return 0; if (ioctl(fd, FS_IOC_GETFLAGS, &old_attr) < 0) return -errno; new_attr = (old_attr & ~mask) | (value & mask); - if (new_attr == old_attr) + if (new_attr == old_attr) { + if (previous) + *previous = old_attr; return 0; + } if (ioctl(fd, FS_IOC_SETFLAGS, &new_attr) < 0) return -errno; + if (previous) + *previous = old_attr; + return 1; } -int chattr_path(const char *p, unsigned value, unsigned mask) { +int chattr_path(const char *p, unsigned value, unsigned mask, unsigned *previous) { _cleanup_close_ int fd = -1; assert(p); @@ -56,7 +62,7 @@ int chattr_path(const char *p, unsigned value, unsigned mask) { if (fd < 0) return -errno; - return chattr_fd(fd, value, mask); + return chattr_fd(fd, value, mask, previous); } int read_attr_fd(int fd, unsigned *ret) { diff --git a/src/basic/chattr-util.h b/src/basic/chattr-util.h index 0c08163..7570bba 100644 --- a/src/basic/chattr-util.h +++ b/src/basic/chattr-util.h @@ -1,8 +1,8 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -int chattr_fd(int fd, unsigned value, unsigned mask); -int chattr_path(const char *p, unsigned value, unsigned mask); +int chattr_fd(int fd, unsigned value, unsigned mask, unsigned *previous); +int chattr_path(const char *p, unsigned value, unsigned mask, unsigned *previous); int read_attr_fd(int fd, unsigned *ret); int read_attr_path(const char *p, unsigned *ret); diff --git a/src/basic/copy.c b/src/basic/copy.c index e06a503..714cbb8 100644 --- a/src/basic/copy.c +++ b/src/basic/copy.c @@ -695,7 +695,7 @@ int copy_file(const char *from, const char *to, int flags, mode_t mode, unsigned } if (chattr_flags != 0) - (void) chattr_fd(fdt, chattr_flags, (unsigned) -1); + (void) chattr_fd(fdt, chattr_flags, (unsigned) -1, NULL); r = copy_file_fd(from, fdt, copy_flags); if (r < 0) { @@ -743,7 +743,7 @@ int copy_file_atomic(const char *from, const char *to, mode_t mode, unsigned cha } if (chattr_flags != 0) - (void) chattr_fd(fdt, chattr_flags, (unsigned) -1); + (void) chattr_fd(fdt, chattr_flags, (unsigned) -1, NULL); r = copy_file_fd(from, fdt, copy_flags); if (r < 0) diff --git a/src/import/import-raw.c b/src/import/import-raw.c index 4537c42..f62247c 100644 --- a/src/import/import-raw.c +++ b/src/import/import-raw.c @@ -175,7 +175,7 @@ static int raw_import_maybe_convert_qcow2(RawImport *i) { if (converted_fd < 0) return log_error_errno(errno, "Failed to create %s: %m", t); - r = chattr_fd(converted_fd, FS_NOCOW_FL, FS_NOCOW_FL); + r = chattr_fd(converted_fd, FS_NOCOW_FL, FS_NOCOW_FL, NULL); if (r < 0) log_warning_errno(r, "Failed to set file attributes on %s: %m", t); @@ -260,7 +260,7 @@ static int raw_import_open_disk(RawImport *i) { if (i->output_fd < 0) return log_error_errno(errno, "Failed to open destination %s: %m", i->temp_path); - r = chattr_fd(i->output_fd, FS_NOCOW_FL, FS_NOCOW_FL); + r = chattr_fd(i->output_fd, FS_NOCOW_FL, FS_NOCOW_FL, NULL); if (r < 0) log_warning_errno(r, "Failed to set file attributes on %s: %m", i->temp_path); diff --git a/src/import/pull-raw.c b/src/import/pull-raw.c index e68f197..96800ac 100644 --- a/src/import/pull-raw.c +++ b/src/import/pull-raw.c @@ -237,7 +237,7 @@ static int raw_pull_maybe_convert_qcow2(RawPull *i) { if (converted_fd < 0) return log_error_errno(errno, "Failed to create %s: %m", t); - r = chattr_fd(converted_fd, FS_NOCOW_FL, FS_NOCOW_FL); + r = chattr_fd(converted_fd, FS_NOCOW_FL, FS_NOCOW_FL, NULL); if (r < 0) log_warning_errno(r, "Failed to set file attributes on %s: %m", t); @@ -353,7 +353,7 @@ static int raw_pull_make_local_copy(RawPull *i) { * performance on COW file systems like btrfs, since it * reduces fragmentation caused by not allowing in-place * writes. */ - r = chattr_fd(dfd, FS_NOCOW_FL, FS_NOCOW_FL); + r = chattr_fd(dfd, FS_NOCOW_FL, FS_NOCOW_FL, NULL); if (r < 0) log_warning_errno(r, "Failed to set file attributes on %s: %m", tp); @@ -595,7 +595,7 @@ static int raw_pull_job_on_open_disk_raw(PullJob *j) { if (r < 0) return r; - r = chattr_fd(j->disk_fd, FS_NOCOW_FL, FS_NOCOW_FL); + r = chattr_fd(j->disk_fd, FS_NOCOW_FL, FS_NOCOW_FL, NULL); if (r < 0) log_warning_errno(r, "Failed to set file attributes on %s, ignoring: %m", i->temp_path); diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index ee6e25e..e9dddbc 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -372,7 +372,7 @@ JournalFile* journal_file_close(JournalFile *f) { * reenable all the good bits COW usually provides * (such as data checksumming). */ - (void) chattr_fd(f->fd, 0, FS_NOCOW_FL); + (void) chattr_fd(f->fd, 0, FS_NOCOW_FL, NULL); (void) btrfs_defrag_fd(f->fd); } @@ -3563,7 +3563,7 @@ int journal_file_open_reliably( /* btrfs doesn't cope well with our write pattern and * fragments heavily. Let's defrag all files we rotate */ - (void) chattr_path(p, 0, FS_NOCOW_FL); + (void) chattr_path(p, 0, FS_NOCOW_FL, NULL); (void) btrfs_defrag(p); log_warning_errno(r, "File %s corrupted or uncleanly shut down, renaming and replacing.", fname); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 2f8d2e9..8bed6df 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -1732,7 +1732,7 @@ static int setup_keys(void) { /* Enable secure remove, exclusion from dump, synchronous * writing and in-place updating */ - r = chattr_fd(fd, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL); + r = chattr_fd(fd, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL, NULL); if (r < 0) log_warning_errno(r, "Failed to set file attributes: %m"); diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c index 52cf461..0344771 100644 --- a/src/shared/machine-image.c +++ b/src/shared/machine-image.c @@ -637,7 +637,7 @@ int image_remove(Image *i) { case IMAGE_DIRECTORY: /* Allow deletion of read-only directories */ - (void) chattr_path(i->path, 0, FS_IMMUTABLE_FL); + (void) chattr_path(i->path, 0, FS_IMMUTABLE_FL, NULL); r = rm_rf(i->path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME); if (r < 0) return r; @@ -736,7 +736,7 @@ int image_rename(Image *i, const char *new_name) { (void) read_attr_path(i->path, &file_attr); if (file_attr & FS_IMMUTABLE_FL) - (void) chattr_path(i->path, 0, FS_IMMUTABLE_FL); + (void) chattr_path(i->path, 0, FS_IMMUTABLE_FL, NULL); _fallthrough_; case IMAGE_SUBVOLUME: @@ -777,7 +777,7 @@ int image_rename(Image *i, const char *new_name) { /* Restore the immutable bit, if it was set before */ if (file_attr & FS_IMMUTABLE_FL) - (void) chattr_path(new_path, FS_IMMUTABLE_FL, FS_IMMUTABLE_FL); + (void) chattr_path(new_path, FS_IMMUTABLE_FL, FS_IMMUTABLE_FL, NULL); free_and_replace(i->path, new_path); free_and_replace(i->name, nn); @@ -927,7 +927,7 @@ int image_read_only(Image *i, bool b) { a read-only subvolume, but at least something, and we can read the value back. */ - r = chattr_path(i->path, b ? FS_IMMUTABLE_FL : 0, FS_IMMUTABLE_FL); + r = chattr_path(i->path, b ? FS_IMMUTABLE_FL : 0, FS_IMMUTABLE_FL, NULL); if (r < 0) return r; diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index e994be6..1b3cb5f 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -1232,7 +1232,7 @@ static int fd_set_attribute(Item *item, int fd, const char *path, const struct s if (procfs_fd < 0) return log_error_errno(procfs_fd, "Failed to re-open '%s': %m", path); - r = chattr_fd(procfs_fd, f, item->attribute_mask); + r = chattr_fd(procfs_fd, f, item->attribute_mask, NULL); if (r < 0) log_full_errno(IN_SET(r, -ENOTTY, -EOPNOTSUPP) ? LOG_DEBUG : LOG_WARNING, r, -- 2.7.4