根据touch的手册页,可以使用touch -h -t MMDDhhmm mylink来更改符号链接上的时间戳。
这在我的带有APFS的macOS机器上不起作用,链接的时间戳是未修改的,touch跟随链接修改目标的时间戳。
这是关于APFS的已知事实,还是有我不理解的地方?
发布于 2021-08-16 12:52:26
看起来你在macOS中发现了一个bug。操作系统的倒数第二个主要版本根据手动页面工作,但最新版本不能。
要么是手册页过时了,要么是软件有bug (很可能)。
你可以在这里以普通用户的身份向Apple发送反馈:‘
https://www.apple.com/feedback/macos.html
或者,如果您是开发人员,则可以使用反馈助手提交错误报告,如下所述:
https://developer.apple.com/bug-reporting/
目前苹果还没有提供更新版本的touch,所以你无法通过升级来解决这个问题。正如您所指出的,您可以使用touch的GNU版本来完成这项工作。你可以通过安装coreutils在Homebrew中找到它。
touch的GNU版本通过调用较新的futimens()/utimensat()函数来工作(在后一种情况下,将flag参数设置为AT_SYMLINK_NOFOLLOW,以更改链接本身的时间戳)。
Catalina版本的touch (287.100.2)通过调用较旧的lutimes()函数工作,该函数显式设置链接本身的时间戳。较新的API和较旧的API之间的核心区别之一是,较新的API支持以纳秒为单位的时间戳,而较旧的API的分辨率较低。
Big Sur上的lutimes()函数实际上并不实现系统调用本身,而是完全包含在标准库中,使用setattrlist()函数(导致系统调用)来实际执行文件系统修改。APFS高度依赖于文件系统(即它在HFS+文件系统上的工作方式与在setattrlist()文件系统上的工作方式不同)。
Big Sur版本的touch (321.100.11)通过直接调用setattrlist()函数来工作,只有当调用失败时,才会回退到lutimes。不幸的是,程序员似乎忘记了需要指定当指定-h时,修改必须发生在链接本身上。
实际的bug在touch.c的第219行,其中这一行:
if (!setattrlist(*argv, &ts_req, &ts_struct, sizeof(ts_struct), 0))应该是:
if (!setattrlist(*argv, &ts_req, &ts_struct, sizeof(ts_struct), utimes_f == lutimes ? FSOPT_NOFOLLOW : 0))您可以在touch.c中更改它,重新编译它,并获得一个有效的二进制文件。
发布于 2021-08-14 16:05:39
答案是:与macOS捆绑在一起的默认touch不能更改时间戳,但来自GNU coreutils的touch 8.32可以...
有趣的是,2021年BSD版本的touch也有同样的问题,不能正确处理-h标志。
https://stackoverflow.com/questions/68784785
复制相似问题