Hi, right now, i had to do some tests that required symlinks with specifically crafted access and modification times.
For that purpose, NetBSD, FreeBSD and Linux agree on having the non-POSIX touch(1) -h flag, in analogy to chown(8) and chgrp(1). Here is a simple patch to add it to our touch(1). NetBSD, FreeBSD and Linux also agree to have -h imply -c, that is, to never create any new files when -h is given. I see no compelling reason for that restriction, but prefer to keep semantics consistent across systems. NetBSD and FreeBSD *silently* skip non-existent files given on the command line when -h is given, even when -c is not given. That seems surprising behaviour to me, so with -h, i suggest to report missing files to stderr unless -c is given, too. The toughest call is the exit value when -h is given, but -c is not, and at least one file is missing. NetBSD and FreeBSD return success, Linux returns failure. I prefer success, even though i'm printing a warning, because all other files are still processed, even those given *after* the missing one. Any OKs or concerns? Ingo Index: touch.1 =================================================================== RCS file: /cvs/src/usr.bin/touch/touch.1,v retrieving revision 1.28 diff -u -p -r1.28 touch.1 --- touch.1 16 Sep 2011 19:36:07 -0000 1.28 +++ touch.1 11 Jul 2012 12:19:09 -0000 @@ -41,7 +41,7 @@ .Nd change file access and modification times .Sh SYNOPSIS .Nm touch -.Op Fl acm +.Op Fl achm .Sm off .Op Fl "d " Ar ccyy No - Ar mm No - Ar ddTHH : Ar MM : Ar SS Oo \&. Ar frac Oc Op Ar Z .Sm on @@ -110,6 +110,13 @@ The timezone specifier, a capital letter indicating that the time is in UTC. If not specified, the time is in the local timezone. .El +.It Fl h +Do not follow symbolic links but change the times of the links themselves. +This option implies +.Fl c , +except that missing files are reported unless +.Fl c +is also specified. .It Fl m Change the modification time of the file. The access time of the file is not changed unless the @@ -158,6 +165,10 @@ The utility is compliant with the .St -p1003.1-2008 specification. +.Pp +The flag +.Fl h +is an extension to that specification. .Pp The obsolescent form of .Nm touch , Index: touch.c =================================================================== RCS file: /cvs/src/usr.bin/touch/touch.c,v retrieving revision 1.21 diff -u -p -r1.21 touch.c --- touch.c 31 Aug 2011 08:48:40 -0000 1.21 +++ touch.c 11 Jul 2012 12:19:09 -0000 @@ -56,13 +56,14 @@ int main(int argc, char *argv[]) { struct timespec ts[2]; - int aflag, cflag, mflag, ch, fd, len, rval, timeset; + int aflag, cflag, hflag, mflag, timeset; + int ch, fd, len, rval; char *p; (void)setlocale(LC_ALL, ""); - aflag = cflag = mflag = timeset = 0; - while ((ch = getopt(argc, argv, "acd:fmr:t:")) != -1) + aflag = cflag = hflag = mflag = timeset = 0; + while ((ch = getopt(argc, argv, "acd:fhmr:t:")) != -1) switch (ch) { case 'a': aflag = 1; @@ -76,6 +77,9 @@ main(int argc, char *argv[]) break; case 'f': break; + case 'h': + hflag = AT_SYMLINK_NOFOLLOW; + break; case 'm': mflag = 1; break; @@ -124,7 +128,7 @@ main(int argc, char *argv[]) for (rval = 0; *argv; ++argv) { /* Update the file's timestamp if it exists. */ - if (! utimensat(AT_FDCWD, *argv, ts, 0)) + if (! utimensat(AT_FDCWD, *argv, ts, hflag)) continue; if (errno != ENOENT) { rval = 1; @@ -135,6 +139,10 @@ main(int argc, char *argv[]) /* Didn't exist; should we create it? */ if (cflag) continue; + if (hflag) { + warn("%s", *argv); + continue; + } /* Create the file. */ fd = open(*argv, O_WRONLY | O_CREAT, DEFFILEMODE); @@ -326,7 +334,7 @@ __dead void usage(void) { (void)fprintf(stderr, -"usage: touch [-acm] [-d ccyy-mm-ddTHH:MM:SS[.frac][Z]] [-r file]\n" +"usage: touch [-achm] [-d ccyy-mm-ddTHH:MM:SS[.frac][Z]] [-r file]\n" " [-t [[cc]yy]mmddHHMM[.SS]] file ...\n"); exit(1); }