summaryrefslogtreecommitdiffstats
path: root/usr.bin/touch
diff options
context:
space:
mode:
authorgrog <grog@FreeBSD.org>2007-04-09 02:19:37 +0000
committergrog <grog@FreeBSD.org>2007-04-09 02:19:37 +0000
commit5218e59269bfd7967b2450bff7139983326d156b (patch)
treed0c3aa40489de62896d40b146c2358c03956e660 /usr.bin/touch
parentdd669756437015bcf28c46f23e518ef861752865 (diff)
downloadFreeBSD-src-5218e59269bfd7967b2450bff7139983326d156b.zip
FreeBSD-src-5218e59269bfd7967b2450bff7139983326d156b.tar.gz
Add -A flag to adjust existing time stamps.
Print name by which program was started in usage() message. MFC after: 2 weeks
Diffstat (limited to 'usr.bin/touch')
-rw-r--r--usr.bin/touch/touch.191
-rw-r--r--usr.bin/touch/touch.c62
2 files changed, 130 insertions, 23 deletions
diff --git a/usr.bin/touch/touch.1 b/usr.bin/touch/touch.1
index 8c7ab8b..6231905 100644
--- a/usr.bin/touch/touch.1
+++ b/usr.bin/touch/touch.1
@@ -43,6 +43,7 @@
.Nd change file access and modification times
.Sh SYNOPSIS
.Nm
+.Op Fl A Ar [-][[hh]mm]SS
.Op Fl acfhm
.Op Fl r Ar file
.Op Fl t Ar [[CC]YY]MMDDhhmm[.SS]
@@ -50,17 +51,79 @@
.Sh DESCRIPTION
The
.Nm
-utility sets the modification and access times of files to the
-current time of day.
-If the file does not exist, it is created with default permissions.
+utility sets the modification and access times of files.
+If any file does not exist, it is created with default permissions.
+.Pp
+By default,
+.Nm
+changes both modification and access times. The
+.Fl a
+and
+.Fl m
+flags may be used to select the access time or the modification time
+individually.
+Selecting both is equivalent to the default.
+The base times for the modification are both set to the current time.
+The
+.Fl t
+flag explicitly specifies a single time for both values, and the
+.Fl r
+flag specifies to set the times from those of a different file.
+The
+.Fl A
+flag adjusts the values by a specified amount.
+This adjustment is done after first establishing the base times.
.Pp
The following options are available:
.Bl -tag -width Ds
+.It Fl A
+Adjust the access and modification time stamps for the file by the
+specified value.
+This flag is intended for use in modifying files with a time stamp
+relative to an incorrect time zone.
+It always modifies both the access time and the modification time.
+.Pp
+The argument is of the form
+.Dq [-][[hh]mm]SS
+where each pair of letters represents the following:
+.Pp
+.Bl -tag -width Ds -compact -offset indent
+.It Ar -
+Make the adjustment negative: the new time stamp is set to be before
+the old one.
+.It Ar hh
+The hour of the day, from 00 to 23.
+.It Ar mm
+The minute of the hour, from 00 to 59.
+.It Ar SS
+The second of the minute, from 00 to 59.
+.El
+.Pp
+When used in conjunction with the
+.Fl a
+flag only, the modification time is adjusted by the time specified as
+argument to the
+.Fl A
+flag, while the access time is modified from the base time described
+above.
+Similarly, when used in conjunction with the
+.Fl m
+flag only, the access time is adjusted by the time specified as
+argument to the
+.Fl A
+flag, while the access time is modified from the base time described
+above.
+.Pp
+If the file does not exist, and creation is allowed,
+.Fl A
+does not change its time stamps.
.It Fl a
Change the access time of the file.
-The modification time of the file is not changed unless the
+The modification time of the file is not changed unless one of the
+.Fl A
+or
.Fl m
-flag is also specified.
+flags is also specified.
.It Fl c
Do not create the file if it does not exist.
The
@@ -80,15 +143,17 @@ implies
and thus will not create any new files.
.It Fl m
Change the modification time of the file.
-The access time of the file is not changed unless the
+The access time of the file is not changed unless one of the
+.Fl A
+or
.Fl a
-flag is also specified.
+flags is also specified.
.It Fl r
Use the access and modifications times from the specified file
instead of the current time of day.
.It Fl t
Change the access and modification times to the specified time.
-The argument should be in the form
+The argument is of the form
.Dq [[CC]YY]MMDDhhmm[.SS]
where each pair of letters represents the following:
.Pp
@@ -110,15 +175,15 @@ Otherwise, a
.Dq CC
value of 20 is used.
.It Ar MM
-The month of the year, from 1 to 12.
+The month of the year, from 01 to 12.
.It Ar DD
-the day of the month, from 1 to 31.
+the day of the month, from 01 to 31.
.It Ar hh
-The hour of the day, from 0 to 23.
+The hour of the day, from 00 to 23.
.It Ar mm
-The minute of the hour, from 0 to 59.
+The minute of the hour, from 00 to 59.
.It Ar SS
-The second of the minute, from 0 to 61.
+The second of the minute, from 00 to 61.
.El
.Pp
If the
diff --git a/usr.bin/touch/touch.c b/usr.bin/touch/touch.c
index 8853eca..ef2c6af 100644
--- a/usr.bin/touch/touch.c
+++ b/usr.bin/touch/touch.c
@@ -62,7 +62,8 @@ int rw(char *, struct stat *, int);
void stime_arg1(char *, struct timeval *);
void stime_arg2(char *, int, struct timeval *);
void stime_file(char *, struct timeval *);
-void usage(void);
+int timeoffset(char *);
+void usage(char *);
int
main(int argc, char *argv[])
@@ -71,17 +72,22 @@ main(int argc, char *argv[])
struct timeval tv[2];
int (*stat_f)(const char *, struct stat *);
int (*utimes_f)(const char *, const struct timeval *);
- int aflag, cflag, fflag, mflag, ch, fd, len, rval, timeset;
+ int Aflag, aflag, cflag, fflag, mflag, ch, fd, len, rval, timeset;
char *p;
+ char *myname;
- aflag = cflag = fflag = mflag = timeset = 0;
+ myname = argv[0];
+ Aflag = aflag = cflag = fflag = mflag = timeset = 0;
stat_f = stat;
utimes_f = utimes;
if (gettimeofday(&tv[0], NULL))
err(1, "gettimeofday");
- while ((ch = getopt(argc, argv, "acfhmr:t:")) != -1)
+ while ((ch = getopt(argc, argv, "A:acfhmr:t:")) != -1)
switch(ch) {
+ case 'A':
+ Aflag = timeoffset(optarg);
+ break;
case 'a':
aflag = 1;
break;
@@ -109,13 +115,13 @@ main(int argc, char *argv[])
break;
case '?':
default:
- usage();
+ usage(myname);
}
argc -= optind;
argv += optind;
- /* Default is both -a and -m. */
- if (aflag == 0 && mflag == 0)
+ /* -a and -m are default unless one of them or -A is set. */
+ if (aflag == 0 && mflag == 0 && Aflag == 0)
aflag = mflag = 1;
/*
@@ -136,7 +142,7 @@ main(int argc, char *argv[])
tv[1] = tv[0];
if (*argv == NULL)
- usage();
+ usage(myname);
for (rval = 0; *argv; ++argv) {
/* See if the file exists. */
@@ -158,10 +164,15 @@ main(int argc, char *argv[])
continue;
}
+ /* If -a or -m are not set, base time on current file time. */
if (!aflag)
TIMESPEC_TO_TIMEVAL(&tv[0], &sb.st_atimespec);
if (!mflag)
TIMESPEC_TO_TIMEVAL(&tv[1], &sb.st_mtimespec);
+ if (Aflag) {
+ tv[0].tv_sec += Aflag;
+ tv[1].tv_sec += Aflag;
+ }
/* Try utimes(2). */
if (!utimes_f(*argv, tv))
@@ -286,6 +297,36 @@ stime_arg2(char *arg, int year, struct timeval *tvp)
tvp[0].tv_usec = tvp[1].tv_usec = 0;
}
+/* Calculate a time offset in seconds, given an arg of the format [-]HHMMSS. */
+int
+timeoffset(char *arg)
+{
+ int offset;
+ int isneg;
+
+ offset = 0;
+ isneg = *arg == '-';
+ if (isneg)
+ arg++;
+ switch (strlen(arg)) {
+ default: /* invalid */
+ errx(1, "Invalid offset spec, must be [-][[HH]MM]SS");
+
+ case 6: /* HHMMSS */
+ offset = ATOI2(arg);
+ /* FALLTHROUGH */
+ case 4: /* MMSS */
+ offset = offset * 60 + ATOI2(arg);
+ /* FALLTHROUGH */
+ case 2: /* SS */
+ offset = offset * 60 + ATOI2(arg);
+ }
+ if (isneg)
+ return (-offset);
+ else
+ return (offset);
+}
+
void
stime_file(char *fname, struct timeval *tvp)
{
@@ -347,8 +388,9 @@ err: rval = 1;
}
void
-usage(void)
+usage(char *myname)
{
- (void)fprintf(stderr, "usage: touch [-acfhm] [-r file] [-t [[CC]YY]MMDDhhmm[.SS]] file ...\n");
+ fprintf(stderr, "usage:\n" "%s [-A [-][[hh]mm]SS] [-acfhm] [-r file] "
+ "[-t [[CC]YY]MMDDhhmm[.SS]] file ...\n", myname);
exit(1);
}
OpenPOWER on IntegriCloud