1
0
mirror of https://github.com/systemd/systemd.git synced 2024-10-28 03:25:31 +03:00

chrattr-util: return EOPNOTSUPP from chrattr_full if no other failure was observed

When chattr_full tries to apply flags one-by-one, and one fails,
record which errno was returned. But record EOPNOTSUPP(&friends)
only if no other error is observed, and return it only in that case
(otherwise keep returning ENOANO), so that callers can respond
appropriately to EOPNOTSUPP vs more relevant errors.
For example, this lets tmpfiles.d log at debug level when a filesystem
flag cannot be applied because the filesystem does not support it,
but at warning level if something else went wrong when applying it.
Restores logging behaviour of tmpfiles.d to pre-250.

Follow-up for: c1631ee124

Fixes: https://github.com/systemd/systemd/issues/21901
This commit is contained in:
Luca Boccassi 2021-12-26 16:45:13 +00:00 committed by Yu Watanabe
parent a2ccfc9ccb
commit 7c3b51c469

View File

@ -22,6 +22,7 @@ int chattr_full(const char *path,
_cleanup_close_ int fd_will_close = -1;
unsigned old_attr, new_attr;
int set_flags_errno = 0;
struct stat st;
assert(path || fd >= 0);
@ -109,6 +110,12 @@ int chattr_full(const char *path,
log_full_errno(FLAGS_SET(flags, CHATTR_WARN_UNSUPPORTED_FLAGS) ? LOG_WARNING : LOG_DEBUG,
errno,
"Unable to set file attribute 0x%x on %s, ignoring: %m", mask_one, strna(path));
/* Ensures that we record whether only EOPNOTSUPP&friends are encountered, or if a more serious
* error (thus worth logging at a different level, etc) was seen too. */
if (set_flags_errno == 0 || !ERRNO_IS_NOT_SUPPORTED(errno))
set_flags_errno = -errno;
continue;
}
@ -121,7 +128,10 @@ int chattr_full(const char *path,
if (ret_final)
*ret_final = current_attr;
return current_attr == new_attr ? 1 : -ENOANO; /* -ENOANO indicates that some attributes cannot be set. */
/* -ENOANO indicates that some attributes cannot be set. ERRNO_IS_NOT_SUPPORTED indicates that all
* encountered failures were due to flags not supported by the FS, so return a specific error in
* that case, so callers can handle it properly (e.g.: tmpfiles.d can use debug level logging). */
return current_attr == new_attr ? 1 : ERRNO_IS_NOT_SUPPORTED(set_flags_errno) ? set_flags_errno : -ENOANO;
}
int read_attr_fd(int fd, unsigned *ret) {