Jean-Francois Dockes via GNU coreutils Bug Reports <[email protected]> writes:
> Paul Eggert writes: > > On 12/11/23 12:03, Abraham S.A.H. via GNU coreutils Bug Reports wrote: > > > a sane default behaviour regarding extended attributes in mv and others? > > > > What's wrong with the default behavior in current GNU mv? Please give a > > specific example (specify platform, filesystems, mv version, etc.). > > mv still silently discards the extended attributes when asked to move a file > from > e.g. an ext4 fs to e.g., a VFAT one. > > Again: the data is gone. mv lost the data. > > For example (on Ubuntu 26.04, but this is probably irrelevant): > > hm3$ mv --version > mv (GNU coreutils) 9.7 > Packaged by Ubuntu (9.7-3ubuntu2) > Copyright (C) 2025 Free Software Foundation, Inc. > License GPLv3+: GNU GPL version 3 or later > <https://gnu.org/licenses/gpl.html>. > This is free software: you are free to change and redistribute it. > There is NO WARRANTY, to the extent permitted by law. > > Written by Mike Parker, David MacKenzie, and Jim Meyering. > > hm3$ getfattr myfile.txt > # file: myfile.txt > user.myattr > > hm3$ mv myfile.txt /run/media/dockes/C052-0E64/ > > hm3$ getfattr /run/media/dockes/C052-0E64/myfile.txt > > hm3$ mv /run/media/dockes/C052-0E64/myfile.txt . > > hm3$ getfattr myfile.txt > > > mv just casually discarding data... > > You are asking what's wrong. IMO this is wrong. > > If the target file system is full ("No space left on device"), mv keeps the > original file. It should do the same for an extended attribute problem. Just to avoid confusing any other readers, I want to clarify that the "data loss" mentioned here is the extended attributes of the given file, not the file contents. E.g., see the result of the following commands: $ echo a > a && setfattr --name=user.charset --value=utf-8 a \ && mv a /mnt/vfat-mount/ \ && getfattr --encoding=text --dump /mnt/vfat-mount/a \ && cat /mnt/vfat-mount/a a This is because VFAT does not support extended attributes. You can see the behavior by adding 'strace' before the 'mv' invocation: renameat2(AT_FDCWD, "a", AT_FDCWD, "/mnt/vfat-mount/", RENAME_NOREPLACE) = -1 EEXIST (File exists) openat(AT_FDCWD, "/mnt/vfat-mount/", O_RDONLY|O_PATH|O_DIRECTORY) = 3 renameat2(AT_FDCWD, "a", 3, "a", RENAME_NOREPLACE) = -1 EXDEV (Invalid cross-device link) newfstatat(AT_FDCWD, "a", {st_mode=S_IFREG|0644, st_size=2, ...}, AT_SYMLINK_NOFOLLOW) = 0 newfstatat(3, "a", {st_mode=S_IFREG|0755, st_size=2, ...}, AT_SYMLINK_NOFOLLOW) = 0 geteuid() = 0 renameat(AT_FDCWD, "a", 3, "a") = -1 EXDEV (Invalid cross-device link) unlinkat(3, "a", 0) = 0 lgetxattr("a", "security.selinux", "unconfined_u:object_r:admin_home"..., 255) = 38 futex(0x7f275cc00580, FUTEX_WAKE_PRIVATE, 2147483647) = 0 openat(AT_FDCWD, "/proc/thread-self/attr/fscreate", O_RDWR|O_CLOEXEC) = 4 write(4, "unconfined_u:object_r:admin_home"..., 38) = 38 close(4) = 0 openat(AT_FDCWD, "a", O_RDONLY|O_NOFOLLOW) = 4 fstat(4, {st_mode=S_IFREG|0644, st_size=2, ...}) = 0 openat(3, "a", O_WRONLY|O_CREAT|O_EXCL, 0600) = 5 ioctl(5, BTRFS_IOC_CLONE or FICLONE, 4) = -1 EXDEV (Invalid cross-device link) fstat(5, {st_mode=S_IFREG|0755, st_size=0, ...}) = 0 copy_file_range(4, NULL, 5, NULL, 9223372035781033984, 0) = -1 EXDEV (Invalid cross-device link) mmap(NULL, 270336, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f275c89d000 read(4, "a\n", 262144) = 2 write(5, "a\n", 2) = 2 read(4, "", 262144) = 0 munmap(0x7f275c89d000, 270336) = 0 utimensat(5, NULL, [{tv_sec=1786821834, tv_nsec=183963469} /* 2026-08-15T12:23:54.183963469-0700 */, {tv_sec=1786821834, tv_nsec=183963469} /* 2026-08-15T12:23:54.183963469-0700 */], 0) = 0 flistxattr(4, "user.charset\0security.selinux\0", 511) = 30 openat(AT_FDCWD, "/etc/xattr.conf", O_RDONLY) = 6 fstat(6, {st_mode=S_IFREG|0644, st_size=817, ...}) = 0 read(6, "# /etc/xattr.conf\n#\n# Format:\n# "..., 4096) = 817 read(6, "", 4096) = 0 close(6) = 0 openat(AT_FDCWD, "/usr/lib64/gconv/gconv-modules.cache", O_RDONLY|O_CLOEXEC) = 6 fstat(6, {st_mode=S_IFREG|0644, st_size=27012, ...}) = 0 mmap(NULL, 27012, PROT_READ, MAP_SHARED, 6, 0) = 0x7f275cc37000 close(6) = 0 futex(0x7f275cbb26ec, FUTEX_WAKE_PRIVATE, 2147483647) = 0 fgetxattr(4, "user.charset", "utf-8", 512) = 5 fsetxattr(5, "user.charset", "utf-8", 5, 0) = -1 EOPNOTSUPP (Operation not supported) Are you suggesting we remove the moved file after fsetxattr fails and preserve a copy to restore the orignal file that was renamed with its extended attributes intact? That behavior seems a bit strange to me... Why not just move the file as the user requested? It seems strange to me that a user would depend on extended attributes, but use a file system that does not support them... Collin
