From: "luislavena (Luis Lavena)" Date: 2012-11-07T06:51:53+09:00 Subject: [ruby-core:48999] [ruby-trunk - Feature #7106][Feedback] FileUtils.touch should allow touching the symlink itself rather than the file the link points to Issue #7106 has been updated by luislavena (Luis Lavena). Status changed from Assigned to Feedback =begin I've combined your patch and Usa's Windows modification (plus other misses) and put it here: https://gist.github.com/4022459 Also, I've created the following files on a drive: * foo: directory * READ: a real file And created the following type of links: * bar: symlinkd (directory symlink) of foo * a-link: symlink of READ * HARD: hardlink of READ * junc: a junction point of foo V:\>dir Volume in drive V is RAMDISK Volume Serial Number is 9A3E-37F6 Directory of V:\ 06/11/2012 12:57 a.m. a-link [READ] 06/11/2012 12:54 a.m. bar [foo] 05/11/2012 09:25 p.m. foo 06/11/2012 12:56 a.m. 7 HARD 06/11/2012 01:02 a.m. junc [V:\foo] 06/11/2012 12:56 a.m. 7 READ 06/11/2012 12:49 a.m. ruby2 As you can see from the output, all have different timestamps Now, from IRB: V:\>irb irb(main):001:0> File.mtime "foo" => 2012-11-05 21:25:54 -0300 irb(main):002:0> File.mtime "bar" => 2012-11-06 00:54:22 -0300 irb(main):003:0> File.mtime "junc" => 2012-11-06 01:02:03 -0300 On Windows, access of modification time gets the link modification time and not the target. Same goes for atime and ctime: irb(main):004:0> ["foo", "bar", "junc"].each { |folder| puts File.atime(folder) } 2012-11-05 21:25:54 -0300 2012-11-06 00:54:22 -0300 2012-11-06 01:02:03 -0300 irb(main):006:0> ["foo", "bar", "junc"].each { |folder| puts File.ctime(folder) }; nil 2012-11-05 21:23:45 -0300 2012-11-06 00:54:22 -0300 2012-11-06 01:02:03 -0300 Now, doing (({File.utime})) on the symlinkd modifies the target: irb(main):016:0> a = File.mtime("foo") => 2012-11-07 00:54:22 -0300 irb(main):017:0> a = File.atime("bar") => 2012-11-06 00:54:22 -0300 irb(main):018:0> File.utime(a, a, "bar") => 1 irb(main):019:0> a = File.atime("bar") => 2012-11-06 00:54:22 -0300 irb(main):020:0> a = File.atime("foo") => 2012-11-06 00:54:22 -0300 But not the symlink, which is expected. Problem is now that the code around (({rb_file_s_lutime})) avoids it getting defined on Windows, even when functions around it were faked. (it checks for (({HAVE_LUTIMES})) and that doesn't exists on Windows) I did a minor tweak and got that passing (is included in my patch), and now: V:\>irb irb(main):001:0> a = File.atime("bar") => 2012-11-06 00:54:22 -0300 irb(main):002:0> b = a + 3600 => 2012-11-06 01:54:22 -0300 irb(main):003:0> File.lutime(b, b, "bar") => 1 irb(main):004:0> File.atime("bar") => 2012-11-06 01:54:22 -0300 irb(main):005:0> File.atime("foo") => 2012-11-06 00:54:22 -0300 Symlinks can only be created by administrators, but modifying the timestamps (access, modification) is totally possible. It also works transparently with junction points (which normal users can create too): irb(main):008:0> File.atime("junc") => 2012-11-06 01:02:03 -0300 irb(main):009:0> File.atime("foo") => 2012-11-06 00:54:22 -0300 irb(main):010:0> File.lutime(b, b, "junc") => 1 irb(main):011:0> File.atime("foo") => 2012-11-06 00:54:22 -0300 irb(main):012:0> File.atime("junc") => 2012-11-06 01:54:22 -0300 And file symlinks (previous were directory symlinks, are two different kind of links): irb(main):018:0> File.atime("READ") => 2012-11-06 00:56:43 -0300 irb(main):019:0> File.atime("a-link") => 2012-11-06 00:57:07 -0300 irb(main):020:0> c = _ + (4 * 3600) => 2012-11-06 04:57:07 -0300 irb(main):021:0> File.lutime(c, c, "a-link") => 1 irb(main):022:0> File.atime("READ") => 2012-11-06 00:56:43 -0300 irb(main):023:0> File.atime("a-link") => 2012-11-06 04:57:07 -0300 The only one that has no effect are hardlinks, but because the file itself is the same (which is expected) irb(main):024:0> File.atime("READ") => 2012-11-06 00:56:43 -0300 irb(main):025:0> File.atime("HARD") => 2012-11-06 00:56:43 -0300 irb(main):026:0> d = _ + (9 * 3600) => 2012-11-06 09:56:43 -0300 irb(main):027:0> File.lutime(d, d, "HARD") => 1 irb(main):028:0> File.atime("READ") => 2012-11-06 09:56:43 -0300 irb(main):029:0> File.atime("HARD") => 2012-11-06 09:56:43 -0300 All this was performed with a normal command prompt (without admin rights) Now, (({File.lutime})) seems to work properly, but the modification to (({FileUtils})) might not work. As you see, FileUtils relies on (({File.symlink?})) to combine with (({:nofollow})) option and then use either (({lutime})) or (({utime})). Problem is, (({File.symlink?})) always return false on Windows: irb(main):001:0> File.symlink?("foo") => false irb(main):002:0> File.symlink?("bar") => false irb(main):003:0> File.symlink?("a-link") => false irb(main):004:0> File.symlink?("HARD") => false irb(main):005:0> File.symlink?("junc") While current Ruby can create hardlinks, it cannot determine a symlink (the code returns directly (({Qfalse})). I think that is the final part to get your code into Ruby (at least working on Windows). Thank you. =end ---------------------------------------- Feature #7106: FileUtils.touch should allow touching the symlink itself rather than the file the link points to https://bugs.ruby-lang.org/issues/7106#change-32517 Author: cirrusthinking (Alessandro Diaferia) Status: Feedback Priority: Normal Assignee: luislavena (Luis Lavena) Category: core Target version: 2.0.0 Most systems support POSIX lutimes sys call that allows a symlink to be touched. I'd like to see this feature implemented. Unfortunately I'd like to see this feature on Solaris as soon as possible but I cannot see lutimes syscall supported there. -- http://bugs.ruby-lang.org/