Import NetBSD touch command
Replaces the 'touch' functionality provided by commands/touch.
This commit is contained in:
		
							parent
							
								
									5552d86152
								
							
						
					
					
						commit
						71d1d39e61
					
				| @ -26,7 +26,7 @@ SUBDIR=	add_route arp ash at backup btrace \ | |||||||
| 	slip spell sprofalyze sprofdiff srccrc \
 | 	slip spell sprofalyze sprofdiff srccrc \
 | ||||||
| 	svclog svrctl swifi synctree sysenv \
 | 	svclog svrctl swifi synctree sysenv \
 | ||||||
| 	syslogd tail tcpd tcpdp tcpstat telnet \
 | 	syslogd tail tcpd tcpdp tcpstat telnet \
 | ||||||
| 	telnetd term termcap tget time touch \
 | 	telnetd term termcap tget time \
 | ||||||
| 	truncate udpstat umount \
 | 	truncate udpstat umount \
 | ||||||
| 	unstack update uud uue version vol \
 | 	unstack update uud uue version vol \
 | ||||||
| 	whereis which writeisofs fetch \
 | 	whereis which writeisofs fetch \
 | ||||||
|  | |||||||
| @ -1,6 +0,0 @@ | |||||||
| #	$NetBSD: Makefile,v 1.3 1994/12/07 09:19:47 jtc Exp $
 |  | ||||||
| #	@(#)Makefile	8.1 (Berkeley) 6/6/93
 |  | ||||||
| 
 |  | ||||||
| PROG=	touch |  | ||||||
| 
 |  | ||||||
| .include <bsd.prog.mk> |  | ||||||
| @ -25,7 +25,7 @@ SUBDIR= asa \ | |||||||
| 	\
 | 	\
 | ||||||
| 	sdiff sed seq shlock \
 | 	sdiff sed seq shlock \
 | ||||||
| 	shuffle  sort split stat su \
 | 	shuffle  sort split stat su \
 | ||||||
| 	tee tic tput \
 | 	tee tic touch tput \
 | ||||||
| 	tr true tsort tty ul uname unexpand unifdef \
 | 	tr true tsort tty ul uname unexpand unifdef \
 | ||||||
| 	uniq units unvis unzip users \
 | 	uniq units unvis unzip users \
 | ||||||
| 	uuidgen vis \
 | 	uuidgen vis \
 | ||||||
|  | |||||||
							
								
								
									
										8
									
								
								usr.bin/touch/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								usr.bin/touch/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | |||||||
|  | #	$NetBSD: Makefile,v 1.4 2012/07/25 01:23:46 christos Exp $
 | ||||||
|  | #	@(#)Makefile	8.1 (Berkeley) 6/6/93
 | ||||||
|  | 
 | ||||||
|  | PROG=	touch | ||||||
|  | LDADD+=	-lutil | ||||||
|  | DPADD+=	${LIBUTIL} | ||||||
|  | 
 | ||||||
|  | .include <bsd.prog.mk> | ||||||
| @ -1,5 +1,4 @@ | |||||||
| .\"	$OpenBSD: touch.1,v 1.14 2007/08/06 19:16:06 sobrado Exp $ | .\"	$NetBSD: touch.1,v 1.25 2012/10/24 02:46:25 pgoyette Exp $ | ||||||
| .\"	$NetBSD: touch.1,v 1.8 1995/08/31 22:10:05 jtc Exp $ |  | ||||||
| .\" | .\" | ||||||
| .\" Copyright (c) 1991, 1993 | .\" Copyright (c) 1991, 1993 | ||||||
| .\"	The Regents of the University of California.  All rights reserved. | .\"	The Regents of the University of California.  All rights reserved. | ||||||
| @ -33,27 +32,30 @@ | |||||||
| .\" | .\" | ||||||
| .\"     @(#)touch.1	8.3 (Berkeley) 4/28/95 | .\"     @(#)touch.1	8.3 (Berkeley) 4/28/95 | ||||||
| .\" | .\" | ||||||
| .Dd $Mdocdate: August 6 2007 $ | .Dd October 22, 2012 | ||||||
| .Dt TOUCH 1 | .Dt TOUCH 1 | ||||||
| .Os | .Os | ||||||
| .Sh NAME | .Sh NAME | ||||||
| .Nm touch | .Nm touch | ||||||
| .Nd change file access and modification times | .Nd change file access and modification times | ||||||
| .Sh SYNOPSIS | .Sh SYNOPSIS | ||||||
| .Nm touch | .Nm | ||||||
| .Op Fl acm | .Op Fl acfhm | ||||||
|  | .Op Fl d Ar human-datetime | ||||||
|  | .Op Fl Fl date Ar human-datetime | ||||||
| .Op Fl r Ar file | .Op Fl r Ar file | ||||||
| .Op Fl t Ar [[CC]YY]MMDDhhmm[.SS] | .Op Fl Fl reference Ar file | ||||||
| .Ar | .Op Fl t Ar datetime | ||||||
|  | .Ar file ... | ||||||
| .Sh DESCRIPTION | .Sh DESCRIPTION | ||||||
| The | The | ||||||
| .Nm | .Nm | ||||||
| utility sets the modification and access times of files to the | utility changes the access and modification times of files to the | ||||||
| current time of day. | current time of day. | ||||||
| If the file doesn't exist, it is created with default permissions. | If the file doesn't exist, it is created with default permissions. | ||||||
| .Pp | .Pp | ||||||
| The options are as follows: | The following options are available: | ||||||
| .Bl -tag -width Ds | .Bl -tag -width "-d human-datetime" | ||||||
| .It Fl a | .It Fl a | ||||||
| Change the access time of the file. | 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 the | ||||||
| @ -65,17 +67,35 @@ The | |||||||
| .Nm | .Nm | ||||||
| utility does not treat this as an error. | utility does not treat this as an error. | ||||||
| No error messages are displayed and the exit value is not affected. | No error messages are displayed and the exit value is not affected. | ||||||
|  | .It Fl d Ar human-datetime | ||||||
|  | .It Fl Fl date Ar human-datetime | ||||||
|  | Parse | ||||||
|  | .Ar human-datetime | ||||||
|  | using the human datetime parser | ||||||
|  | .Xr parsedate 3 . | ||||||
|  | .It Fl f | ||||||
|  | This flag has no effect; it is accepted for compatibility reasons. | ||||||
|  | .It Fl h | ||||||
|  | If | ||||||
|  | .Ar file | ||||||
|  | is a symbolic link, access and/or modification time of the link is changed. | ||||||
|  | This option implies | ||||||
|  | .Fl c . | ||||||
| .It Fl m | .It Fl m | ||||||
| Change the modification time of the file. | 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 the | ||||||
| .Fl a | .Fl a | ||||||
| flag is also specified. | flag is also specified. | ||||||
| .It Fl r Ar file | .It Fl r Ar file | ||||||
| Use the access and modification times from the specified file | .It Fl Fl reference Ar file | ||||||
|  | Use the access and modifications times from | ||||||
|  | .Ar file | ||||||
| instead of the current time of day. | instead of the current time of day. | ||||||
| .It Fl t Ar [[CC]YY]MMDDhhmm[.SS] | .It Fl t Ar datetime | ||||||
| Change the access and modification times to the specified time. | Change the access and modification times to the specified time. | ||||||
| The argument should be in the form | The argument | ||||||
|  | .Ar datetime | ||||||
|  | should be in the form | ||||||
| .Dq [[CC]YY]MMDDhhmm[.SS] | .Dq [[CC]YY]MMDDhhmm[.SS] | ||||||
| where each pair of letters represents the following: | where each pair of letters represents the following: | ||||||
| .Pp | .Pp | ||||||
| @ -120,22 +140,21 @@ letter pair is not specified, the value defaults to 0. | |||||||
| .El | .El | ||||||
| .Pp | .Pp | ||||||
| The | The | ||||||
| .Nm | .Fl d , | ||||||
| utility exits 0 on success or >0 if an error occurred. | .Fl r , | ||||||
| .Sh SEE ALSO | and | ||||||
| .Xr utimes 2 | .Fl t | ||||||
| .Sh STANDARDS | options are mutually exclusive. | ||||||
| The | If more than one of these options is present, the last one is used. | ||||||
| .Nm | .Sh EXIT STATUS | ||||||
| utility is compliant with the | .Ex -std | ||||||
| .St -p1003.1-2004 | .Sh COMPATIBILITY | ||||||
| specification. |  | ||||||
| .Pp |  | ||||||
| The obsolescent form of | The obsolescent form of | ||||||
| .Nm touch , | .Nm , | ||||||
| where a time format is specified as the first argument, is supported. | where a time format is specified as the first argument, is supported. | ||||||
| When no | When no | ||||||
| .Fl r | .Fl d , | ||||||
|  | .Fl r , | ||||||
| or | or | ||||||
| .Fl t | .Fl t | ||||||
| option is specified, there are at least two arguments, and the first | option is specified, there are at least two arguments, and the first | ||||||
| @ -154,10 +173,20 @@ letter pairs are treated as their counterparts specified to the | |||||||
| option. | option. | ||||||
| If the | If the | ||||||
| .Dq YY | .Dq YY | ||||||
| letter pair is in the range 69 to 99, the year is set from 1969 to 1999; | letter pair is in the range 69 to 99, the year is set to 1969 to 1999, | ||||||
| otherwise, the year is set in the 21st century. | otherwise, the year is set in the 21st century. | ||||||
|  | .Sh SEE ALSO | ||||||
|  | .Xr utimes 2 | ||||||
|  | .Sh STANDARDS | ||||||
|  | The | ||||||
|  | .Nm | ||||||
|  | utility is expected to be a superset of the | ||||||
|  | .St -p1003.2 | ||||||
|  | specification. | ||||||
| .Sh HISTORY | .Sh HISTORY | ||||||
| A | A | ||||||
| .Nm | .Nm | ||||||
| utility appeared in | utility appeared in | ||||||
| .At v7 . | .At v7 . | ||||||
|  | .Sh BUGS | ||||||
|  | A symbolic link can't be a reference file of access and/or modification time. | ||||||
| @ -1,5 +1,4 @@ | |||||||
| /*	$OpenBSD: touch.c,v 1.17 2007/08/06 19:16:06 sobrado Exp $	*/ | /*	$NetBSD: touch.c,v 1.32 2012/10/22 21:51:58 christos Exp $	*/ | ||||||
| /*	$NetBSD: touch.c,v 1.11 1995/08/31 22:10:06 jtc Exp $	*/ |  | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Copyright (c) 1993 |  * Copyright (c) 1993 | ||||||
| @ -30,11 +29,23 @@ | |||||||
|  * SUCH DAMAGE. |  * SUCH DAMAGE. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | #include <sys/cdefs.h> | ||||||
|  | #ifndef lint | ||||||
|  | __COPYRIGHT("@(#) Copyright (c) 1993\
 | ||||||
|  |  The Regents of the University of California.  All rights reserved."); | ||||||
|  | #endif /* not lint */ | ||||||
|  | 
 | ||||||
|  | #ifndef lint | ||||||
|  | #if 0 | ||||||
|  | static char sccsid[] = "@(#)touch.c	8.2 (Berkeley) 4/28/95"; | ||||||
|  | #endif | ||||||
|  | __RCSID("$NetBSD: touch.c,v 1.32 2012/10/22 21:51:58 christos Exp $"); | ||||||
|  | #endif /* not lint */ | ||||||
|  | 
 | ||||||
| #include <sys/types.h> | #include <sys/types.h> | ||||||
| #include <sys/stat.h> | #include <sys/stat.h> | ||||||
| #include <sys/time.h> | #include <sys/time.h> | ||||||
| 
 | 
 | ||||||
| #include <ctype.h> |  | ||||||
| #include <err.h> | #include <err.h> | ||||||
| #include <errno.h> | #include <errno.h> | ||||||
| #include <fcntl.h> | #include <fcntl.h> | ||||||
| @ -43,33 +54,44 @@ | |||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <locale.h> | #include <locale.h> | ||||||
| #include <time.h> | #include <time.h> | ||||||
| #include <utime.h> |  | ||||||
| #include <tzfile.h> | #include <tzfile.h> | ||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
|  | #include <util.h> | ||||||
|  | #include <getopt.h> | ||||||
| 
 | 
 | ||||||
| void		stime_arg1(char *, struct timeval *); | static void	stime_arg0(char *, struct timeval *); | ||||||
| void		stime_arg2(char *, int, struct timeval *); | static void	stime_arg1(char *, struct timeval *); | ||||||
| void		stime_file(char *, struct timeval *); | static void	stime_arg2(char *, int, struct timeval *); | ||||||
| __dead void	usage(void); | static void	stime_file(char *, struct timeval *); | ||||||
|  | __dead static void	usage(void); | ||||||
| 
 | 
 | ||||||
| char * __progname; | struct option touch_longopts[] = { | ||||||
|  | 	{ "date",		required_argument,	0, | ||||||
|  | 						'd' }, | ||||||
|  | 	{ "reference",		required_argument,	0, | ||||||
|  | 						'r' }, | ||||||
|  | 	{ NULL,			0,			0, | ||||||
|  | 						0 }, | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| int | int | ||||||
| main(int argc, char *argv[]) | main(int argc, char *argv[]) | ||||||
| { | { | ||||||
| 	struct stat sb; | 	struct stat sb; | ||||||
| 	struct timeval tv[2]; | 	struct timeval tv[2]; | ||||||
| 	int		 aflag, cflag, mflag, ch, fd, len, rval, timeset; | 	int aflag, cflag, hflag, mflag, ch, fd, len, rval, timeset; | ||||||
| 	char *p; | 	char *p; | ||||||
|  | 	int (*change_file_times)(const char *, const struct timeval *); | ||||||
|  | 	int (*get_file_status)(const char *, struct stat *); | ||||||
| 
 | 
 | ||||||
| 	(void)setlocale(LC_ALL, ""); | 	setlocale(LC_ALL, ""); | ||||||
| 	__progname = argv[0]; |  | ||||||
| 
 | 
 | ||||||
| 	aflag = cflag = mflag = timeset = 0; | 	aflag = cflag = hflag = mflag = timeset = 0; | ||||||
| 	if (gettimeofday(&tv[0], NULL)) | 	if (gettimeofday(&tv[0], NULL)) | ||||||
| 		err(1, "gettimeofday"); | 		err(1, "gettimeofday"); | ||||||
| 
 | 
 | ||||||
| 	while ((ch = getopt(argc, argv, "acfmr:t:")) != -1) | 	while ((ch = getopt_long(argc, argv, "acd:fhmr:t:", touch_longopts, | ||||||
|  | 	    NULL)) != -1) | ||||||
| 		switch(ch) { | 		switch(ch) { | ||||||
| 		case 'a': | 		case 'a': | ||||||
| 			aflag = 1; | 			aflag = 1; | ||||||
| @ -77,8 +99,15 @@ main(int argc, char *argv[]) | |||||||
| 		case 'c': | 		case 'c': | ||||||
| 			cflag = 1; | 			cflag = 1; | ||||||
| 			break; | 			break; | ||||||
|  | 		case 'd': | ||||||
|  | 			timeset = 1; | ||||||
|  | 			stime_arg0(optarg, tv); | ||||||
|  | 			break; | ||||||
| 		case 'f': | 		case 'f': | ||||||
| 			break; | 			break; | ||||||
|  | 		case 'h': | ||||||
|  | 			hflag = 1; | ||||||
|  | 			break; | ||||||
| 		case 'm': | 		case 'm': | ||||||
| 			mflag = 1; | 			mflag = 1; | ||||||
| 			break; | 			break; | ||||||
| @ -90,6 +119,7 @@ main(int argc, char *argv[]) | |||||||
| 			timeset = 1; | 			timeset = 1; | ||||||
| 			stime_arg1(optarg, tv); | 			stime_arg1(optarg, tv); | ||||||
| 			break; | 			break; | ||||||
|  | 		case '?': | ||||||
| 		default: | 		default: | ||||||
| 			usage(); | 			usage(); | ||||||
| 		} | 		} | ||||||
| @ -100,6 +130,15 @@ main(int argc, char *argv[]) | |||||||
| 	if (aflag == 0 && mflag == 0) | 	if (aflag == 0 && mflag == 0) | ||||||
| 		aflag = mflag = 1; | 		aflag = mflag = 1; | ||||||
| 
 | 
 | ||||||
|  | 	if (hflag) { | ||||||
|  | 		cflag = 1;		/* Don't create new file */ | ||||||
|  | 		change_file_times = lutimes; | ||||||
|  | 		get_file_status = lstat; | ||||||
|  | 	} else { | ||||||
|  | 		change_file_times = utimes; | ||||||
|  | 		get_file_status = stat; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * If no -r or -t flag, at least two operands, the first of which | 	 * If no -r or -t flag, at least two operands, the first of which | ||||||
| 	 * is an 8 or 10 digit number, use the obsolete time specification. | 	 * is an 8 or 10 digit number, use the obsolete time specification. | ||||||
| @ -120,15 +159,15 @@ main(int argc, char *argv[]) | |||||||
| 	if (*argv == NULL) | 	if (*argv == NULL) | ||||||
| 		usage(); | 		usage(); | ||||||
| 
 | 
 | ||||||
| 	for (rval = 0; *argv; ++argv) { | 	for (rval = EXIT_SUCCESS; *argv; ++argv) { | ||||||
| 		/* See if the file exists. */ | 		/* See if the file exists. */ | ||||||
| 		if (stat(*argv, &sb)) { | 		if ((*get_file_status)(*argv, &sb)) { | ||||||
| 			if (!cflag) { | 			if (!cflag) { | ||||||
| 				/* Create the file. */ | 				/* Create the file. */ | ||||||
| 				fd = open(*argv, | 				fd = open(*argv, | ||||||
| 				    O_WRONLY | O_CREAT, DEFFILEMODE); | 				    O_WRONLY | O_CREAT, DEFFILEMODE); | ||||||
| 				if (fd == -1 || fstat(fd, &sb) || close(fd)) { | 				if (fd == -1 || fstat(fd, &sb) || close(fd)) { | ||||||
| 					rval = 1; | 					rval = EXIT_FAILURE; | ||||||
| 					warn("%s", *argv); | 					warn("%s", *argv); | ||||||
| 					continue; | 					continue; | ||||||
| 				} | 				} | ||||||
| @ -139,19 +178,18 @@ main(int argc, char *argv[]) | |||||||
| 			} else | 			} else | ||||||
| 				continue; | 				continue; | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 		if (!aflag) | 		if (!aflag) | ||||||
| 			TIMESPEC_TO_TIMEVAL(&tv[0], &sb.st_atimespec); | 			TIMESPEC_TO_TIMEVAL(&tv[0], &sb.st_atimespec); | ||||||
| 		if (!mflag) | 		if (!mflag) | ||||||
| 			TIMESPEC_TO_TIMEVAL(&tv[1], &sb.st_mtimespec); | 			TIMESPEC_TO_TIMEVAL(&tv[1], &sb.st_mtimespec); | ||||||
| 
 | 
 | ||||||
| 		/* Try utimes(2). */ | 		/* Try utimes(2). */ | ||||||
| 		if (!utimes(*argv, tv)) | 		if (!(*change_file_times)(*argv, tv)) | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
| 		/* If the user specified a time, nothing else we can do. */ | 		/* If the user specified a time, nothing else we can do. */ | ||||||
| 		if (timeset) { | 		if (timeset) { | ||||||
| 			rval = 1; | 			rval = EXIT_FAILURE; | ||||||
| 			warn("%s", *argv); | 			warn("%s", *argv); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| @ -161,10 +199,10 @@ main(int argc, char *argv[]) | |||||||
| 		 * The permission checks are different, too, in that the | 		 * The permission checks are different, too, in that the | ||||||
| 		 * ability to write the file is sufficient.  Take a shot. | 		 * ability to write the file is sufficient.  Take a shot. | ||||||
| 		 */ | 		 */ | ||||||
| 		 if (!utimes(*argv, NULL)) | 		 if (!(*change_file_times)(*argv, NULL)) | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
| 		rval = 1; | 		rval = EXIT_FAILURE; | ||||||
| 		warn("%s", *argv); | 		warn("%s", *argv); | ||||||
| 	} | 	} | ||||||
| 	exit(rval); | 	exit(rval); | ||||||
| @ -172,135 +210,128 @@ main(int argc, char *argv[]) | |||||||
| 
 | 
 | ||||||
| #define	ATOI2(s)	((s) += 2, ((s)[-2] - '0') * 10 + ((s)[-1] - '0')) | #define	ATOI2(s)	((s) += 2, ((s)[-2] - '0') * 10 + ((s)[-1] - '0')) | ||||||
| 
 | 
 | ||||||
| void | static void | ||||||
|  | stime_arg0(char *arg, struct timeval *tvp) | ||||||
|  | { | ||||||
|  | 	tvp[1].tv_sec = tvp[0].tv_sec = parsedate(arg, NULL, NULL); | ||||||
|  | 	if (tvp[0].tv_sec == -1) | ||||||
|  | 		errx(EXIT_FAILURE, "Could not parse `%s'", arg); | ||||||
|  | 	tvp[0].tv_usec = tvp[1].tv_usec = 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void | ||||||
| stime_arg1(char *arg, struct timeval *tvp) | stime_arg1(char *arg, struct timeval *tvp) | ||||||
| { | { | ||||||
| 	struct tm	*lt; | 	struct tm *t; | ||||||
| 	time_t tmptime; | 	time_t tmptime; | ||||||
| 	int yearset; | 	int yearset; | ||||||
| 	char		*dot, *p; | 	char *p; | ||||||
| 					/* Start with the current time. */ | 					/* Start with the current time. */ | ||||||
| 	tmptime = tvp[0].tv_sec; | 	tmptime = tvp[0].tv_sec; | ||||||
| 	if ((lt = localtime(&tmptime)) == NULL) | 	if ((t = localtime(&tmptime)) == NULL) | ||||||
| 		err(1, "localtime"); | 		err(EXIT_FAILURE, "localtime"); | ||||||
| 					/* [[CC]YY]MMDDhhmm[.SS] */ | 					/* [[CC]YY]MMDDhhmm[.SS] */ | ||||||
| 	for (p = arg, dot = NULL; *p != '\0'; p++) { | 	if ((p = strchr(arg, '.')) == NULL) | ||||||
| 		if (*p == '.' && dot == NULL) | 		t->tm_sec = 0;		/* Seconds defaults to 0. */ | ||||||
| 			dot = p; |  | ||||||
| 		else if (!isdigit((unsigned char)*p)) |  | ||||||
| 			goto terr; |  | ||||||
| 	} |  | ||||||
| 	if (dot == NULL) |  | ||||||
| 		lt->tm_sec = 0;		/* Seconds defaults to 0. */ |  | ||||||
| 	else { | 	else { | ||||||
| 		*dot++ = '\0'; | 		if (strlen(p + 1) != 2) | ||||||
| 		if (strlen(dot) != 2) |  | ||||||
| 			goto terr; |  | ||||||
| 		lt->tm_sec = ATOI2(dot); |  | ||||||
| 		if (lt->tm_sec > 61)	/* Could be leap second. */ |  | ||||||
| 			goto terr; | 			goto terr; | ||||||
|  | 		*p++ = '\0'; | ||||||
|  | 		t->tm_sec = ATOI2(p); | ||||||
| 	} | 	} | ||||||
| 		 | 		 | ||||||
| 	yearset = 0; | 	yearset = 0; | ||||||
| 	switch (strlen(arg)) { | 	switch (strlen(arg)) { | ||||||
| 	case 12:			/* CCYYMMDDhhmm */ | 	case 12:			/* CCYYMMDDhhmm */ | ||||||
| 		lt->tm_year = ATOI2(arg) * 100 - TM_YEAR_BASE; | 		t->tm_year = ATOI2(arg) * 100 - TM_YEAR_BASE; | ||||||
| 		yearset = 1; | 		yearset = 1; | ||||||
| 		/* FALLTHROUGH */ | 		/* FALLTHROUGH */ | ||||||
| 	case 10:			/* YYMMDDhhmm */ | 	case 10:			/* YYMMDDhhmm */ | ||||||
| 		if (yearset) { | 		if (yearset) { | ||||||
| 			yearset = ATOI2(arg); | 			t->tm_year += ATOI2(arg); | ||||||
| 			lt->tm_year += yearset; |  | ||||||
| 		} else { | 		} else { | ||||||
| 			yearset = ATOI2(arg); | 			yearset = ATOI2(arg); | ||||||
| 			/* Preserve current century. */ | 			if (yearset < 69) | ||||||
| 			lt->tm_year = ((lt->tm_year / 100) * 100) + yearset; | 				t->tm_year = yearset + 2000 - TM_YEAR_BASE; | ||||||
|  | 			else | ||||||
|  | 				t->tm_year = yearset + 1900 - TM_YEAR_BASE; | ||||||
| 		} | 		} | ||||||
| 		/* FALLTHROUGH */ | 		/* FALLTHROUGH */ | ||||||
| 	case 8:				/* MMDDhhmm */ | 	case 8:				/* MMDDhhmm */ | ||||||
| 		lt->tm_mon = ATOI2(arg); | 		t->tm_mon = ATOI2(arg); | ||||||
| 		if (lt->tm_mon > 12 || lt->tm_mon == 0) | 		--t->tm_mon;		/* Convert from 01-12 to 00-11 */ | ||||||
| 			goto terr; | 		/* FALLTHROUGH */ | ||||||
| 		--lt->tm_mon;		/* Convert from 01-12 to 00-11 */ | 	case 6: | ||||||
| 		lt->tm_mday = ATOI2(arg); | 		t->tm_mday = ATOI2(arg); | ||||||
| 		if (lt->tm_mday > 31 || lt->tm_mday == 0) | 		/* FALLTHROUGH */ | ||||||
| 			goto terr; | 	case 4: | ||||||
| 		lt->tm_hour = ATOI2(arg); | 		t->tm_hour = ATOI2(arg); | ||||||
| 		if (lt->tm_hour > 23) | 		/* FALLTHROUGH */ | ||||||
| 			goto terr; | 	case 2: | ||||||
| 		lt->tm_min = ATOI2(arg); | 		t->tm_min = ATOI2(arg); | ||||||
| 		if (lt->tm_min > 59) |  | ||||||
| 			goto terr; |  | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		goto terr; | 		goto terr; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	lt->tm_isdst = -1;		/* Figure out DST. */ | 	t->tm_isdst = -1;		/* Figure out DST. */ | ||||||
| 	tvp[0].tv_sec = tvp[1].tv_sec = mktime(lt); | 	tvp[0].tv_sec = tvp[1].tv_sec = mktime(t); | ||||||
| 	if (tvp[0].tv_sec == -1) | 	if (tvp[0].tv_sec == -1) | ||||||
| terr:		errx(1, | terr:		errx(EXIT_FAILURE, | ||||||
| 	"out of range or illegal time specification: [[CC]YY]MMDDhhmm[.SS]"); | 	"out of range or illegal time specification: [[CC]YY]MMDDhhmm[.SS]"); | ||||||
| 
 | 
 | ||||||
| 	tvp[0].tv_usec = tvp[1].tv_usec = 0; | 	tvp[0].tv_usec = tvp[1].tv_usec = 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void | static void | ||||||
| stime_arg2(char *arg, int year, struct timeval *tvp) | stime_arg2(char *arg, int year, struct timeval *tvp) | ||||||
| { | { | ||||||
| 	struct tm	*lt; | 	struct tm *t; | ||||||
| 	time_t tmptime; | 	time_t tmptime; | ||||||
| 					/* Start with the current time. */ | 					/* Start with the current time. */ | ||||||
| 	tmptime = tvp[0].tv_sec; | 	tmptime = tvp[0].tv_sec; | ||||||
| 	if ((lt = localtime(&tmptime)) == NULL) | 	if ((t = localtime(&tmptime)) == NULL) | ||||||
| 		err(1, "localtime"); | 		err(EXIT_FAILURE, "localtime"); | ||||||
| 
 | 
 | ||||||
| 	lt->tm_mon = ATOI2(arg);	/* MMDDhhmm[YY] */ | 	t->tm_mon = ATOI2(arg);		/* MMDDhhmm[yy] */ | ||||||
| 	if (lt->tm_mon > 12 || lt->tm_mon == 0) | 	--t->tm_mon;			/* Convert from 01-12 to 00-11 */ | ||||||
| 		goto terr; | 	t->tm_mday = ATOI2(arg); | ||||||
| 	--lt->tm_mon;			/* Convert from 01-12 to 00-11 */ | 	t->tm_hour = ATOI2(arg); | ||||||
| 	lt->tm_mday = ATOI2(arg); | 	t->tm_min = ATOI2(arg); | ||||||
| 	if (lt->tm_mday > 31 || lt->tm_mday == 0) |  | ||||||
| 		goto terr; |  | ||||||
| 	lt->tm_hour = ATOI2(arg); |  | ||||||
| 	if (lt->tm_hour > 23) |  | ||||||
| 		goto terr; |  | ||||||
| 	lt->tm_min = ATOI2(arg); |  | ||||||
| 	if (lt->tm_min > 59) |  | ||||||
| 		goto terr; |  | ||||||
| 	if (year) { | 	if (year) { | ||||||
| 		year = ATOI2(arg);	/* Preserve current century. */ | 		year = ATOI2(arg); | ||||||
| 		lt->tm_year = ((lt->tm_year / 100) * 100) + year; | 		if (year < 69) | ||||||
|  | 			t->tm_year = year + 2000 - TM_YEAR_BASE; | ||||||
|  | 		else | ||||||
|  | 			t->tm_year = year + 1900 - TM_YEAR_BASE; | ||||||
| 	} | 	} | ||||||
| 	lt->tm_sec = 0; | 	t->tm_sec = 0; | ||||||
| 
 | 
 | ||||||
| 	lt->tm_isdst = -1;		/* Figure out DST. */ | 	t->tm_isdst = -1;		/* Figure out DST. */ | ||||||
| 	tvp[0].tv_sec = tvp[1].tv_sec = mktime(lt); | 	tvp[0].tv_sec = tvp[1].tv_sec = mktime(t); | ||||||
| 	if (tvp[0].tv_sec == -1) | 	if (tvp[0].tv_sec == -1) | ||||||
| terr:		errx(1, | 		errx(EXIT_FAILURE, | ||||||
| 	"out of range or illegal time specification: MMDDhhmm[YY]"); | 	"out of range or illegal time specification: MMDDhhmm[yy]"); | ||||||
| 
 | 
 | ||||||
| 	tvp[0].tv_usec = tvp[1].tv_usec = 0; | 	tvp[0].tv_usec = tvp[1].tv_usec = 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void | static void | ||||||
| stime_file(char *fname, struct timeval *tvp) | stime_file(char *fname, struct timeval *tvp) | ||||||
| { | { | ||||||
| 	struct stat sb; | 	struct stat sb; | ||||||
| 
 | 
 | ||||||
| 	if (stat(fname, &sb)) | 	if (stat(fname, &sb)) | ||||||
| 		err(1, "%s", fname); | 		err(1, "%s", fname); | ||||||
| 	TIMESPEC_TO_TIMEVAL(tvp, &sb.st_atimespec); | 	TIMESPEC_TO_TIMEVAL(&tvp[0], &sb.st_atimespec); | ||||||
| 	TIMESPEC_TO_TIMEVAL(tvp + 1, &sb.st_mtimespec); | 	TIMESPEC_TO_TIMEVAL(&tvp[1], &sb.st_mtimespec); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| __dead void | static void | ||||||
| usage(void) | usage(void) | ||||||
| { | { | ||||||
| 	extern char	*__progname; |  | ||||||
| 
 |  | ||||||
| 	(void)fprintf(stderr, | 	(void)fprintf(stderr, | ||||||
| 	    "usage: %s [-acm] [-r file] [-t [[CC]YY]MMDDhhmm[.SS]] file ...\n", | 	    "Usage: %s [-acfhm] [-d|--date datetime] [-r|--reference file] [-t time] file ...\n", | ||||||
| 	    __progname); | 	    getprogname()); | ||||||
| 	exit(1); | 	exit(EXIT_FAILURE); | ||||||
| } | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Zachary Storer
						Zachary Storer