On Wed, Jul 11, 2012 at 03:06:25PM +0200, Ingo Schwarze wrote: > 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. >
as a user, if -h implies -c, i'd be more surprised that it wasn;t silent. it seems even weirder (actually, horrible) that -h implies -c, but not specifying -c gives a different behaviour to specifying -c. note that you saw no reason for -h to imply -c, but wanted consistency. then you've undone it by changing its behaviour ;) i see that you've documented it, so no one can really complain. but i think if you want to do this, maybe better to just say that -h does not create files, and avoid mentioning -c. everything else looks fine to me (that's an ok, however you decide). one nit inline though... jmc > 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. we use ".Op Fl" everywhere for this text, so please keep it the same. > .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); > }