Subject: Re: bug#13666: Touch: Cannot use a symbolic link as a reference time

From: Bernhard Voelker <[email-masked]>
Date: Wed, 13 Feb 2013 09:21:02 +0100

tag 13666 notabug
thanks

On 02/09/2013 08:06 PM, Michael_google gmail_Gersten wrote:
> I can set the timestamp of a symbolic link with "-h".
> 
> But I cannot use "-r -h" to use the timestamp on a symbolic link as
> the reference time.

Hello Michael,

thanks for the bug report, however I doubt there is a bug.

> keybounceMBP:QuickTime Player michael$ ls -l capture.mov
> 4 lrwxr-xr-x 1 michael staff 57 Aug 24 04:54 capture.mov ->
> ../../iMovie Events.localized/Season 2 header/capture.mov
> keybounceMBP:QuickTime Player michael$ ls -lL capture.mov
> 365800 -rw-r--r-- 1 michael staff 374572867 Feb  8 23:50 capture.mov
> keybounceMBP:QuickTime Player michael$ touch -r -h capture.mov capture.mov
> touch: failed to get attributes of ‘-h’: No such file or directory

As the -r option requires an argument - the reference file - you
can not use the -h option directly after it. Touch tried to use
"-h" as the file name which obviously didn't work, and therefore
reported that error.

Instead, you can switch the 2 options:

  touch -h -r REFERENCE TARGET

And this _does_ work with symlinks:

  $ touch target

  $ ln -vs target symlink
  ‘symlink’ -> ‘target’

  $ touch -d yesterday -h symlink

  $ ls -ldog symlink target
  lrwxrwxrwx 1 6 Feb 12 08:53 symlink -> target
  -rw-r--r-- 1 0 Feb 13 08:52 target

  $ touch -hr symlink target

  $ ls -ldog symlink target
  lrwxrwxrwx 1 6 Feb 12 08:53 symlink -> target
  -rw-r--r-- 1 0 Feb 12 08:53 target

However, in your case, this will not work, because the -h option
works on both the reference file and the target, i.e. nothing
will effectively happen if you use the symlink both as reference
file and the target:

  $ touch -hr symlink symlink

This has set the time on the symlink - see strace output:

  lstat("symlink", {st_mode=S_IFLNK|0777, st_size=6, ...}) = 0
  utimensat(AT_FDCWD, "symlink", ..., AT_SYMLINK_NOFOLLOW) = 0

As the -h option is used on both the reference file and the target,
you have to resolve the symlink yourself, either as like I did
above, or by using the readlink utility:

  $ touch -hr symlink $(readlink symlink)

This is all documented in the TEXINFO manual:

`-h'
`--no-dereference'
     Attempt to change the timestamps of a symbolic link, rather than
     what the link refers to.  When using this option, empty files are
     not created, but option `-c' must also be used to avoid warning
     about files that do not exist.  Not all systems support changing
     the timestamps of symlinks, since underlying system support for
     this action was not required until POSIX 2008.  Also, on some
     systems, the mere act of examining a symbolic link changes the
     access time, such that only changes to the modification time will
     persist long enough to be observable.  When coupled with option
     `-r', a reference timestamp is taken from a symbolic link rather
     than the file it refers to.

`-r FILE'
`--reference=FILE'
     Use the times of the reference FILE instead of the current time.
     If this option is combined with the `--date=TIME' (`-d TIME')
     option, the reference FILE's time is the origin for any relative
     TIMEs given, but is otherwise ignored.  For example, `-r foo -d
     '-5 seconds'' specifies a time stamp equal to five seconds before
     the corresponding time stamp for `foo'.  If FILE is a symbolic
     link, the reference timestamp is taken from the target of the
     symlink, unless `-h' was also in effect.

There is no option to make touch use no-dereferencing on the reference
file and use dereferencing on the target at the same time, and I doubt
there are enough use cases which would make it worthwhile to add one.
Finally, the situation is complicated enough - and some systems or
file systems do not even support timestamps on symlinks.

As such, I'm closing this bug report, although you may feel free to add
further comments or questions.

Have a nice day,
Berny