保存文件时元数据去哪里了?

jun*_*ist 31 linux unix metadata

假设 Johnny 创建了一个 EMPTY 文件。它被称为foobar.py。当 Johnny 允许执行它时,他运行chmod 755 foobar.py. 该文件现在具有元数据

-rw-r--r-- 1 johnny staff    0 Dec 27 22:53 foobar.py
Run Code Online (Sandbox Code Playgroud)

该文件中存储的所有元数据在哪里?文件大小为0,那么当它转移到另一个驱动器时它如何保留元数据?

use*_*686 45

它没有存储该文件中。它存储在文件系统中,所有参数都是手动一一复制的(尽管有些根本无法复制)。

也就是说,大多数操作系统实际上并没有“使用元数据复制文件”调用。文件复制程序只是创建一个名为 的新文件foobar.py,复制整个 0 字节的数据,然后使用utime()SetFileTime()使其修改时间看起来与原始文件相同。同样,文件权限将通过使用 chmod() 重新设置它们或通过复制 POSIX ACL 属性来“复制”。

某些元数据不会被复制。设置所有权需要 root 权限,因此其他人的文件副本属于您并占用您的磁盘配额。ctime(属性更改时间)在 Unix 上无法手动设置;btime(出生/创建时间)通常也不会被复制。

比较cp -a foo bar(复制元数据)和cp foo bar(不复制):

$ strace -v cp foo bar
…
打开(“富”,O_RDONLY)= 3
打开(“酒吧”,O_WRONLY|O_TRUNC)= 4
读(3,“测试\n”,131072)= 5
写(4,“测试\n”,5)= 5
读(3,“”,131072)= 0
关闭(4)= 0
关闭(3)= 0
…
$ strace -v cp -a foo bar
…
 -- 检索原始元数据
lstat("foo", {st_dev=makedev(254, 0), st_ino=60569468, st_mode=S_IFREG|0644,
             st_nlink=1, st_uid=1000, st_gid=1000, st_blksize=4096, st_blocks=8,
             st_size=5, st_atime=2016-12-28T09:16:59+0200.879714332,
             st_mtime=2016-12-28T09:16:55+0200.816363098,
             st_ctime=2016-12-28T09:16:55+0200.816363098}) = 0
 -- 数据被复制
open("foo", O_RDONLY|O_NOFOLLOW) = 3
打开(“酒吧”,O_WRONLY|O_TRUNC)= 4
读(3,“测试\n”,131072)= 5
写(4,“测试\n”,5)= 5
读(3,“”,131072)= 0
 -- 修改时间被复制
utimensat(4, NULL, [{tv_sec=1482909419, tv_nsec=879714332},
                    {tv_sec=1482909415, tv_nsec=816363098}], 0) = 0
 -- 所有权被复制(仅使用 'sudo [strace] cp')
fchown(4, 1000, 1000) = 0
 -- 复制扩展属性(xdg.origin.url 由浏览器设置,wget)
flistxattr(3, NULL, 0) = 0
flistxattr(3, "user.xdg.origin.url\0", 20) = 20
fgetxattr(3, "user.xdg.origin.url", "https://superuser.com/", 22) = 22
fsetxattr(4, "user.xdg.origin.url", "https://superuser.com/", 22, 0) = 0
 -- POSIX ACL 不存在,因此基本 ACL 是从 st_mode 构建的
 --(在这种情况下,一个简单的 fchmod() 也可以工作)
fgetxattr(3, "system.posix_acl_access", 0x7ffc87a50be0, 132) = -1 ENODATA (无可用数据)
fsetxattr(4, "system.posix_acl_access", "\2\0\0\0\1\0\6\0\377\377\377\377\4\0\4\0\377\377\377\ 377 \0\4\0\377\377\377\377", 28, 0) = 0
关闭(4)= 0
关闭(3)= 0
…

  • 为了补充这个答案,您应该提到: - 复制到另一个驱动器时:从源读取元数据,如果适当的设置(或选项)(例如:保持日期,保持权利,甚至保持“一切”)都被使用了(正如你所提到的)。2)另一种方法是首先对文件进行存档(.zip、.tar 等),然后在目标上从该存档中提取,再次为程序提供某个位置(以存档格式)以查找元数据,和特定的选项/设置允许保留(或不保留)这些元数据。 (3认同)

dir*_*rkt 11

它通常因存储元数据的文件系统而异。在 ext2 系列文件系统上,您提到的元数据(所有者、组、权限、时间)存储在inode 中。inode 还存储(指向)文件在磁盘上占用的块。该索引节点并没有存储的文件名。

您可以使用stat系统调用 ( man 2 stat)访问此数据,并使用该stat工具打印它 ( man stat)。可以linux/include/linux/fs.h在内核源代码中找到对 inode 字段的详细说明。

还有其他种类的元数据(例如ACL 权限)存储在不同的地方。

复制文件时默认不复制元数据。相反,会创建一个具有默认元数据值的新文件。cp( -p, --preserve)有多种选项,它们指示cp通过读取旧元数据stat并相应地修改新元数据来复制元数据。