Add proper d- and t-flag support to touch(1)

except the [,frac], [.frac] respectively, but that's ok.
This commit is contained in:
FRIGN 2015-02-19 18:54:56 +01:00
parent c2b400bbd8
commit b00a00703f
3 changed files with 89 additions and 17 deletions

2
README
View File

@ -73,7 +73,7 @@ The following tools are implemented ('*' == finished, '#' == UTF-8 support,
=* tar non-posix none
=* tee yes none
#* test yes none
=* touch yes none (-d) (-t)
=* touch yes none
#* tr yes none
=* true yes none
=* tty yes none

41
touch.1
View File

@ -1,4 +1,4 @@
.Dd February 19, 2015
.Dd February 9, 2015
.Dt TOUCH 1
.Os sbase
.Sh NAME
@ -7,11 +7,11 @@
.Sh SYNOPSIS
.Nm
.Op Fl acm
.Op Fl r Ar ref_file | Fl t Ar timestamp
.Op Fl d Ar time | Fl r Ar ref_file | Fl T Ar time | Fl t Ar time
.Ar file ...
.Sh DESCRIPTION
.Nm
sets the access or modification time of each
sets the access and modification time of each
.Ar file
to the current time of day. If
.Ar file
@ -25,19 +25,30 @@ Set the access | modification time of
Don't create
.Ar file
if it doesn't exist, not affecting exit status.
.It Fl d Ar time
Set the
.Ar time
of the format YYYY-MM-DDThh:mm:SS[Z] used for
.Op Fl am .
.It Fl r Ar ref_file
Set the timestamp
to be used with
Set the
.Ar time
used for
.Op Fl am
to the modification time of
.Ar ref_file .
.It Fl t Ar timestamp
.It Fl T Ar time
Set the
.Ar timestamp
to be used with
.Ar time
used for
.Op Fl am
given as the number of seconds since the
Unix epoch 1970-01-01T00:00:00Z.
.It Fl t Ar time
Set the
.Ar time
of the format [[CC]YY]MMDDhhmm[.SS] used for
.Op Fl am .
.El
.Sh SEE ALSO
.Xr date 1
@ -46,10 +57,10 @@ The
.Nm
utility is compliant with the
.St -p1003.1-2008
specification except for
.Fl d
and the
.Ar timestamp
format of the
.Fl t
flag.
specification, except from fractional seconds in the
.Op Fl d
argument.
.Pp
The
.Op Fl T
flag is an extension to this specification.

63
touch.c
View File

@ -4,6 +4,7 @@
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <utime.h>
@ -43,6 +44,61 @@ touch(const char *file)
touch(file);
}
time_t
parsetime(char *str, time_t current)
{
struct tm *cur, t;
char *format;
size_t len = strlen(str);
cur = localtime(&current);
t.tm_isdst = -1;
switch (len) {
/* -t flag argument */
case 8:
t.tm_sec = 0;
t.tm_year = cur->tm_year;
format = "%m%d%H%M";
break;
case 10:
t.tm_sec = 0;
format = "%y%m%d%H%M";
break;
case 11:
t.tm_year = cur->tm_year;
format = "%m%d%H%M.%S";
break;
case 12:
t.tm_sec = 0;
format = "%Y%m%d%H%M";
break;
case 13:
format = "%y%m%d%H%M.%S";
break;
case 15:
format = "%Y%m%d%H%M.%S";
break;
/* -d flag argument */
case 19:
format = "%Y-%m-%dT%H:%M:%S";
break;
case 20:
/* only Zulu-timezone supported */
if (str[19] != 'Z')
goto default;
format = "%Y-%m-%dT%H:%M:%S%Z";
break;
default:
eprintf("Invalid date format length\n", str);
}
if (!strptime(str, format, &t))
weprintf("strptime %s: Invalid date format\n", str);
return mktime(&t);
}
static void
usage(void)
{
@ -72,15 +128,20 @@ main(int argc, char *argv[])
eprintf("stat '%s':", ref);
t = st.st_mtime;
break;
case 't':
case 'T':
t = estrtonum(EARGF(usage()), 0, LLONG_MAX);
break;
case 't':
t = parsetime(EARGF(usage()), t);
break;
default:
usage();
} ARGEND;
if (argc < 1)
usage();
if (!aflag && !mflag)
aflag = mflag = 1;
for (; argc > 0; argc--, argv++)
touch(argv[0]);