Java 1.7中的符号链接lastModifiedTime

pau*_*len 2 java time symlink

我正在尝试为没有目标的符号链接更改lastModifiedTime值。

例如:foo->

我可以lastModifiedTime使用... 访问值

String fooPath = "/Users/me/test/foo"; 
Path path = new File(fooPath).toPath(); 
FileTime t = Files.getLastModifiedTime(path, LinkOption.NOFOLLOW_LINKS);
Run Code Online (Sandbox Code Playgroud)

但是,我无法使用下面的代码段设置相同的符号链接;这给了我java.nio.file.NoSuchFileException目标

String fooPath = "/Users/me/test/foo";
Path path = new File(fooPath).toPath();
FileTime t = FileTime.fromMillis(date.getTime());
Files.setLastModifiedTime(path, t);
Run Code Online (Sandbox Code Playgroud)

我什至尝试手动设置属性,但这使我出现java.nio.file.FileSystemException“符号链接级别过多或无法访问符号链接的属性”错误:

Files.setAttribute(path, "lastModifiedTime", t, LinkOption.NOFOLLOW_LINKS);
Run Code Online (Sandbox Code Playgroud)

我不想走系统调用路线,因为我需要跨平台支持。

Sim*_*ane 5

可以说这至少在Linux和Solaris上是JDK中的错误或局限性(我没有尝试过Windows)。假设您创建了BasicFileAttributeView没有LinkOption.NOFOLLOW_LINKS。问题在于,sun.nio.fs.UnixFileAttributeViews$Basic.setTimes()调用sun.nio.fs.UnixPath.openForAttributeAccess()会依次调用符号链接上的open/ open64。现在,如果符号链接具有目标,则它将成功并返回指向目标的fd。setTimes()然后调用futimesatfd更新访问和修改时间。但是,这将更新链接目标的修改时间,而不是链接本身的修改时间,这不是您想要的,并且在链接断开时将不起作用。

因此,您会认为答案是LinkOption.NOFOLLOW_LINKS在您请求时通过BasicFileAttributeView。但是,在这种情况下,openForAttributeAccess()传递O_NOFOLLOWopen,指定为ELOOP在发生符号链接时返回错误,这将导致您提到的错误消息。无论如何,由于无法获得符号链接的fd,因此JDK使用的策略将行不通。它需要放弃fd,而使用say utimensatlutimes替代。

不幸的是,这里似乎只有使用系统调用(例如使用JNA)。utimensat这是POSIX 2008的标准方法,但是它足够新,以至于许多类似Unix的操作系统还没有或仅在其最新版本中具有。lutimes在Linux和BSD上已存在,但不是标准的。