]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
chrattr-util: return EOPNOTSUPP from chrattr_full if no other failure was observed
authorLuca Boccassi <luca.boccassi@microsoft.com>
Sun, 26 Dec 2021 16:45:13 +0000 (16:45 +0000)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 26 Dec 2021 23:28:26 +0000 (08:28 +0900)
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: https://github.com/systemd/systemd/commit/c1631ee124a30abfb9c71e2a1534b8afffc3b6a7

Fixes: https://github.com/systemd/systemd/issues/21901
src/basic/chattr-util.c

index 807288a6498f741d2ab7baae15a3d4617d104b25..eddde132aaea896619225c0e01121dadb761a3b4 100644 (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) {