chattr: optionally, return the old flags when updating them

This commit is contained in:
Lennart Poettering 2018-06-25 20:04:07 +02:00
parent 8cbb7d8783
commit db9a42545a
10 changed files with 29 additions and 23 deletions

View File

@ -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)

View File

@ -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) {

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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");

View File

@ -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;

View File

@ -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,