summaryrefslogtreecommitdiffstats
path: root/usr.bin/touch
diff options
context:
space:
mode:
authorjilles <jilles@FreeBSD.org>2015-01-24 13:50:13 +0000
committerjilles <jilles@FreeBSD.org>2015-01-24 13:50:13 +0000
commit3a9e3cd8d9759079220ebe0f13a1d1a8a458734e (patch)
tree2b470ac738f4b696f867cd706f33163b46c962c6 /usr.bin/touch
parentb126e557b253b006789504806612c8f6dc907bbe (diff)
downloadFreeBSD-src-3a9e3cd8d9759079220ebe0f13a1d1a8a458734e.zip
FreeBSD-src-3a9e3cd8d9759079220ebe0f13a1d1a8a458734e.tar.gz
cp,mv,touch: Set timestamps with nanosecond precision.
This uses utimensat().
Diffstat (limited to 'usr.bin/touch')
-rw-r--r--usr.bin/touch/touch.c79
1 files changed, 38 insertions, 41 deletions
diff --git a/usr.bin/touch/touch.c b/usr.bin/touch/touch.c
index 4439c07..c8bfd28 100644
--- a/usr.bin/touch/touch.c
+++ b/usr.bin/touch/touch.c
@@ -56,10 +56,10 @@ static const char sccsid[] = "@(#)touch.c 8.1 (Berkeley) 6/6/93";
#include <time.h>
#include <unistd.h>
-static void stime_arg1(const char *, struct timeval *);
-static void stime_arg2(const char *, int, struct timeval *);
-static void stime_darg(const char *, struct timeval *);
-static void stime_file(const char *, struct timeval *);
+static void stime_arg1(const char *, struct timespec *);
+static void stime_arg2(const char *, int, struct timespec *);
+static void stime_darg(const char *, struct timespec *);
+static void stime_file(const char *, struct timespec *);
static int timeoffset(const char *);
static void usage(const char *);
@@ -67,19 +67,17 @@ int
main(int argc, char *argv[])
{
struct stat sb;
- struct timeval tv[2];
- int (*stat_f)(const char *, struct stat *);
- int (*utimes_f)(const char *, const struct timeval *);
+ struct timespec ts[2];
+ int atflag;
int Aflag, aflag, cflag, mflag, ch, fd, len, rval, timeset;
char *p;
char *myname;
myname = basename(argv[0]);
Aflag = aflag = cflag = mflag = timeset = 0;
- stat_f = stat;
- utimes_f = utimes;
- if (gettimeofday(&tv[0], NULL) == -1)
- err(1, "gettimeofday");
+ atflag = 0;
+ if (clock_gettime(CLOCK_REALTIME, &ts[0]) == -1)
+ err(1, "clock_gettime(CLOCK_REALTIME)");
while ((ch = getopt(argc, argv, "A:acd:fhmr:t:")) != -1)
switch(ch) {
@@ -94,26 +92,25 @@ main(int argc, char *argv[])
break;
case 'd':
timeset = 1;
- stime_darg(optarg, tv);
+ stime_darg(optarg, ts);
break;
case 'f':
/* No-op for compatibility. */
break;
case 'h':
cflag = 1;
- stat_f = lstat;
- utimes_f = lutimes;
+ atflag = AT_SYMLINK_NOFOLLOW;
break;
case 'm':
mflag = 1;
break;
case 'r':
timeset = 1;
- stime_file(optarg, tv);
+ stime_file(optarg, ts);
break;
case 't':
timeset = 1;
- stime_arg1(optarg, tv);
+ stime_arg1(optarg, ts);
break;
default:
usage(myname);
@@ -132,9 +129,9 @@ main(int argc, char *argv[])
* that time once and for all here.
*/
if (aflag)
- tv[0].tv_sec += Aflag;
+ ts[0].tv_sec += Aflag;
if (mflag)
- tv[1].tv_sec += Aflag;
+ ts[1].tv_sec += Aflag;
Aflag = 0; /* done our job */
}
} else {
@@ -148,11 +145,11 @@ main(int argc, char *argv[])
len = p - argv[0];
if (*p == '\0' && (len == 8 || len == 10)) {
timeset = 1;
- stime_arg2(*argv++, len == 10, tv);
+ stime_arg2(*argv++, len == 10, ts);
}
}
/* Both times default to the same. */
- tv[1] = tv[0];
+ ts[1] = ts[0];
}
if (*argv == NULL)
@@ -163,7 +160,7 @@ main(int argc, char *argv[])
for (rval = 0; *argv; ++argv) {
/* See if the file exists. */
- if (stat_f(*argv, &sb) != 0) {
+ if (fstatat(AT_FDCWD, *argv, &sb, atflag) != 0) {
if (errno != ENOENT) {
rval = 1;
warn("%s", *argv);
@@ -187,9 +184,9 @@ main(int argc, char *argv[])
}
if (!aflag)
- TIMESPEC_TO_TIMEVAL(&tv[0], &sb.st_atim);
+ ts[0] = sb.st_atim;
if (!mflag)
- TIMESPEC_TO_TIMEVAL(&tv[1], &sb.st_mtim);
+ ts[1] = sb.st_mtim;
/*
* We're adjusting the times based on the file times, not a
@@ -197,17 +194,17 @@ main(int argc, char *argv[])
*/
if (Aflag) {
if (aflag) {
- TIMESPEC_TO_TIMEVAL(&tv[0], &sb.st_atim);
- tv[0].tv_sec += Aflag;
+ ts[0] = sb.st_atim;
+ ts[0].tv_sec += Aflag;
}
if (mflag) {
- TIMESPEC_TO_TIMEVAL(&tv[1], &sb.st_mtim);
- tv[1].tv_sec += Aflag;
+ ts[1] = sb.st_mtim;
+ ts[1].tv_sec += Aflag;
}
}
- /* Try utimes(2). */
- if (!utimes_f(*argv, tv))
+ /* Try utimensat(2). */
+ if (!utimensat(AT_FDCWD, *argv, ts, atflag))
continue;
/* If the user specified a time, nothing else we can do. */
@@ -223,7 +220,7 @@ main(int argc, char *argv[])
* The permission checks are different, too, in that the
* ability to write the file is sufficient. Take a shot.
*/
- if (!utimes_f(*argv, NULL))
+ if (!utimensat(AT_FDCWD, *argv, NULL, atflag))
continue;
rval = 1;
@@ -235,7 +232,7 @@ main(int argc, char *argv[])
#define ATOI2(ar) ((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2;
static void
-stime_arg1(const char *arg, struct timeval *tvp)
+stime_arg1(const char *arg, struct timespec *tvp)
{
time_t now;
struct tm *t;
@@ -291,7 +288,7 @@ stime_arg1(const char *arg, struct timeval *tvp)
if (tvp[0].tv_sec == -1)
goto terr;
- tvp[0].tv_usec = tvp[1].tv_usec = 0;
+ tvp[0].tv_nsec = tvp[1].tv_nsec = 0;
return;
terr:
@@ -299,7 +296,7 @@ terr:
}
static void
-stime_arg2(const char *arg, int year, struct timeval *tvp)
+stime_arg2(const char *arg, int year, struct timespec *tvp)
{
time_t now;
struct tm *t;
@@ -325,18 +322,18 @@ stime_arg2(const char *arg, int year, struct timeval *tvp)
errx(1,
"out of range or illegal time specification: MMDDhhmm[yy]");
- tvp[0].tv_usec = tvp[1].tv_usec = 0;
+ tvp[0].tv_nsec = tvp[1].tv_nsec = 0;
}
static void
-stime_darg(const char *arg, struct timeval *tvp)
+stime_darg(const char *arg, struct timespec *tvp)
{
struct tm t = { .tm_sec = 0 };
const char *fmt, *colon;
char *p;
int val, isutc = 0;
- tvp[0].tv_usec = 0;
+ tvp[0].tv_nsec = 0;
t.tm_isdst = -1;
colon = strchr(arg, ':');
if (colon == NULL || strchr(colon + 1, ':') == NULL)
@@ -349,9 +346,9 @@ stime_darg(const char *arg, struct timeval *tvp)
/* POSIX: must have at least one digit after dot */
if ((*p == '.' || *p == ',') && isdigit((unsigned char)p[1])) {
p++;
- val = 100000;
+ val = 100000000;
while (isdigit((unsigned char)*p)) {
- tvp[0].tv_usec += val * (*p - '0');
+ tvp[0].tv_nsec += val * (*p - '0');
p++;
val /= 10;
}
@@ -403,14 +400,14 @@ timeoffset(const char *arg)
}
static void
-stime_file(const char *fname, struct timeval *tvp)
+stime_file(const char *fname, struct timespec *tsp)
{
struct stat sb;
if (stat(fname, &sb))
err(1, "%s", fname);
- TIMESPEC_TO_TIMEVAL(tvp, &sb.st_atim);
- TIMESPEC_TO_TIMEVAL(tvp + 1, &sb.st_mtim);
+ tsp[0] = sb.st_atim;
+ tsp[1] = sb.st_mtim;
}
static void
OpenPOWER on IntegriCloud