* The Regents of the University of California. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
static char copyright
[] =
"@(#) Copyright (c) 1993\n\
The Regents of the University of California. All rights reserved.\n";
static char sccsid
[] = "@(#)touch.c 8.2 (Berkeley) 4/28/95";
int rw
__P((char *, struct stat
*, int));
void stime_arg1
__P((char *, struct timeval
*));
void stime_arg2
__P((char *, int, struct timeval
*));
void stime_file
__P((char *, struct timeval
*));
int aflag
, cflag
, fflag
, mflag
, ch
, fd
, len
, rval
, timeset
;
aflag
= cflag
= fflag
= mflag
= timeset
= 0;
if (gettimeofday(&tv
[0], NULL
))
while ((ch
= getopt(argc
, argv
, "acfmr:t:")) != EOF
)
/* Default is both -a and -m. */
if (aflag
== 0 && mflag
== 0)
* 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.
if (!timeset
&& argc
> 1) {
(void)strtol(argv
[0], &p
, 10);
if (*p
== '\0' && (len
== 8 || len
== 10)) {
stime_arg2(*argv
++, len
== 10, tv
);
/* Otherwise use the current time of day. */
for (rval
= 0; *argv
; ++argv
) {
/* See if the file exists. */
O_WRONLY
| O_CREAT
, DEFFILEMODE
);
if (fd
== -1 || fstat(fd
, &sb
) || close(fd
)) {
/* If using the current time, we're done. */
TIMESPEC_TO_TIMEVAL(&tv
[0], &sb
.st_atimespec
);
TIMESPEC_TO_TIMEVAL(&tv
[1], &sb
.st_mtimespec
);
/* If the user specified a time, nothing else we can do. */
* System V and POSIX 1003.1 require that a NULL argument
* set the access/modification times to the current time.
* The permission checks are different, too, in that the
* ability to write the file is sufficient. Take a shot.
if (!utimes(*argv
, NULL
))
/* Try reading/writing. */
if (rw(*argv
, &sb
, fflag
))
#define ATOI2(ar) ((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2;
/* Start with the current time. */
if ((t
= localtime(&tvp
[0].tv_sec
)) == NULL
)
/* [[CC]YY]MMDDhhmm[.SS] */
if ((p
= strchr(arg
, '.')) == NULL
)
t
->tm_sec
= 0; /* Seconds defaults to 0. */
case 12: /* CCYYMMDDhhmm */
case 10: /* YYMMDDhhmm */
t
->tm_year
= yearset
+ 2000;
t
->tm_year
= yearset
+ 1900;
t
->tm_year
-= 1900; /* Convert to UNIX time. */
--t
->tm_mon
; /* Convert from 01-12 to 00-11 */
t
->tm_isdst
= -1; /* Figure out DST. */
tvp
[0].tv_sec
= tvp
[1].tv_sec
= mktime(t
);
"out of range or illegal time specification: [[CC]YY]MMDDhhmm[.SS]");
tvp
[0].tv_usec
= tvp
[1].tv_usec
= 0;
stime_arg2(arg
, year
, tvp
)
/* Start with the current time. */
if ((t
= localtime(&tvp
[0].tv_sec
)) == NULL
)
t
->tm_mon
= ATOI2(arg
); /* MMDDhhmm[yy] */
--t
->tm_mon
; /* Convert from 01-12 to 00-11 */
t
->tm_isdst
= -1; /* Figure out DST. */
tvp
[0].tv_sec
= tvp
[1].tv_sec
= mktime(t
);
"out of range or illegal time specification: MMDDhhmm[yy]");
tvp
[0].tv_usec
= tvp
[1].tv_usec
= 0;
TIMESPEC_TO_TIMEVAL(tvp
, &sb
.st_atimespec
);
TIMESPEC_TO_TIMEVAL(tvp
+ 1, &sb
.st_mtimespec
);
int fd
, needed_chmod
, rval
;
/* Try regular files and directories. */
if (!S_ISREG(sbp
->st_mode
) && !S_ISDIR(sbp
->st_mode
)) {
warnx("%s: %s", fname
, strerror(EFTYPE
));
if ((fd
= open(fname
, O_RDWR
, 0)) == -1) {
if (!force
|| chmod(fname
, DEFFILEMODE
))
if ((fd
= open(fname
, O_RDWR
, 0)) == -1)
if (read(fd
, &byte
, sizeof(byte
)) != sizeof(byte
))
if (lseek(fd
, (off_t
)0, SEEK_SET
) == -1)
if (write(fd
, &byte
, sizeof(byte
)) != sizeof(byte
))
if (write(fd
, &byte
, sizeof(byte
)) != sizeof(byte
)) {
} else if (ftruncate(fd
, (off_t
)0)) {
warn("%s: file modified", fname
);
if (close(fd
) && rval
!= 1) {
if (needed_chmod
&& chmod(fname
, sbp
->st_mode
) && rval
!= 1) {
warn("%s: permissions modified", fname
);
"usage: touch [-acfm] [-r file] [-t time] file ...\n");