From 6fd17a671571aba0c4b8bc59019cd24c4432183f Mon Sep 17 00:00:00 2001 From: Collin Funk Date: Sat, 15 Aug 2026 21:09:23 -0700 Subject: [PATCH] mv: emit warnings when copying extended attributes fails with ENOTSUP * src/copy.c (copy_reg, copy_interal): Don't change the exit status if copying extended attributes fails and we are 'mv'. * src/copy.h (struct cp_options): Update some commentary. * src/mv.c (cp_option_init): Enable require_preserve_xattr in the cp_options struct. * tests/cp/cp-mv-enotsup-xattr.sh: Check that the error is emitted when 'mv' is built with extended attribute support. * doc/coreutils.texi (mv invocation): Mention that all errors are emitted, but do not modify the exit status. * NEWS: Mention the bug fix. Fixes https://bugs.gnu.org/13601 --- NEWS | 4 ++++ doc/coreutils.texi | 3 ++- src/copy.c | 4 ++-- src/copy.h | 3 +-- src/mv.c | 2 +- tests/cp/cp-mv-enotsup-xattr.sh | 12 ++++++++++-- 6 files changed, 20 insertions(+), 8 deletions(-) diff --git a/NEWS b/NEWS index 5415d4d77..3edfbd502 100644 --- a/NEWS +++ b/NEWS @@ -26,6 +26,10 @@ GNU coreutils NEWS -*- outline -*- 'head' and 'tail' now quote names in file headers when needed. [This bug was present in "the beginning".] + 'mv' now warns when copying extended attributes fails with ENOTSUP, e.g., when + moving files to a file system that does not support them. + [bug introduced in coreutils-7.3] + 'numfmt', 'printf', and 'seq' on Solaris, no longer output an extraneous e+00 when using a large precision like "%.5119f". [This bug was present in "the beginning".] diff --git a/doc/coreutils.texi b/doc/coreutils.texi index e4d4db47f..90c2dfcd6 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi @@ -9981,7 +9981,8 @@ original file system. @cindex extended attributes, xattr @command{mv} always tries to copy extended attributes (xattr), which may include SELinux context, ACLs or Capabilities. -Upon failure all but @samp{Operation not supported} warnings are output. +Upon failure all warnings are emitted, but do not modify the exit +status. @cindex prompting, and @command{mv} If a destination file exists but is normally unwritable, standard input diff --git a/src/copy.c b/src/copy.c index a53fb8f8c..c1b72dfb4 100644 --- a/src/copy.c +++ b/src/copy.c @@ -1086,7 +1086,7 @@ copy_reg (char const *src_name, char const *dst_name, if (preserve_xattr) { if (!copy_attr (src_name, source_desc, dst_name, dest_desc, x) - && x->require_preserve_xattr) + && x->require_preserve_xattr && ! x->move_mode) return_val = false; } @@ -2672,7 +2672,7 @@ skip: /* Set xattrs after ownership as changing owners will clear capabilities. */ if (x->preserve_xattr && ! copy_attr (src_name, -1, dst_name, -1, x) - && x->require_preserve_xattr) + && x->require_preserve_xattr && ! x->move_mode) return false; /* The operations beyond this point may dereference a symlink. */ diff --git a/src/copy.h b/src/copy.h index 294cffaaf..f2d10fefd 100644 --- a/src/copy.h +++ b/src/copy.h @@ -234,12 +234,11 @@ struct cp_options while with 'cp --preserve=all' or 'cp -a', it is "false". */ bool require_preserve_xattr; - /* This allows us to output warnings in cases 2 and 4 below, + /* This allows us to output warnings in case 2 below, while being quiet for case 1 (when reduce_diagnostics is true). 1. cp -a try to copy xattrs with no errors 2. cp --preserve=all copy xattrs with all but ENOTSUP warnings 3. cp --preserve=xattr,context copy xattrs with all errors - 4. mv copy xattrs with all but ENOTSUP warnings */ bool reduce_diagnostics; diff --git a/src/mv.c b/src/mv.c index 3ba6f701e..7f0d4f8c3 100644 --- a/src/mv.c +++ b/src/mv.c @@ -145,7 +145,7 @@ cp_option_init (struct cp_options *x) x->require_preserve = false; /* FIXME: maybe make this an option */ x->require_preserve_context = false; x->preserve_xattr = true; - x->require_preserve_xattr = false; + x->require_preserve_xattr = true; x->recursive = true; x->sparse_mode = SPARSE_AUTO; /* FIXME: maybe make this an option */ x->symbolic_link = false; diff --git a/tests/cp/cp-mv-enotsup-xattr.sh b/tests/cp/cp-mv-enotsup-xattr.sh index 8936b5c85..d26f31021 100755 --- a/tests/cp/cp-mv-enotsup-xattr.sh +++ b/tests/cp/cp-mv-enotsup-xattr.sh @@ -110,10 +110,18 @@ compare exp err || fail=1 rm -f err noxattr/a -# This should pass without diagnostics +# POSIX requires a diagnostic to be printed here without +# modifying the exit status. mv xattr/a noxattr/ 2>err || fail=1 test -s noxattr/a || fail=1 # destination file must not be empty -compare /dev/null err || fail=1 +if grep '^#define USE_XATTR 1' $CONFIG_HEADER > /dev/null; then +cat < exp || framework_failure_ +mv: setting attributes for 'noxattr/a': $ENOTSUP +EOF +else +truncate -s0 exp || framework_failure_ +fi +compare exp err || fail=1 # This should pass and copy xattrs of the symlink # since the xattrs used here are not in the 'user.' namespace.