Unix Tools

Implementations of common Unix command-line utilities written in C.


unix-tools / touch.c

touch.c raw | download
1#define _POSIX_C_SOURCE 200809L
2#include <sys/stat.h>
3#include <fcntl.h>
4#include <unistd.h>
5#include <errno.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <time.h>
9
10static int
11touch(const char *name, int nocreate, const struct timespec *times)
12{
13 int fd, status = 0;
14 if (utimensat(AT_FDCWD, name, times, 0) == 0) return 0;
15 if (errno != ENOENT) { perror(name); return 1; }
16 if (nocreate) return 0;
17 fd = open(name, O_WRONLY | O_CREAT, 0666);
18 if (fd < 0) { perror(name); return 1; }
19 if (futimens(fd, times) < 0) { perror(name); status = 1; }
20 if (close(fd) < 0) { perror(name); status = 1; }
21 return status;
22}
23
24int
25main(int argc, char **argv)
26{
27 struct timespec times[2];
28 const struct timespec *when = NULL;
29 int option, nocreate = 0, status = 0;
30 while ((option = getopt(argc, argv, "ct:")) != -1) {
31 if (option == 'c') nocreate = 1;
32 else if (option == 't') {
33 char *end;
34 long long seconds;
35 errno = 0;
36 seconds = strtoll(optarg, &end, 0);
37 if (errno || !*optarg || *end || (long long)(time_t)seconds != seconds) goto usage;
38 times[0].tv_sec = times[1].tv_sec = (time_t)seconds;
39 times[0].tv_nsec = times[1].tv_nsec = 0;
40 when = times;
41 } else goto usage;
42 }
43 if (optind == argc) goto usage;
44 for (; optind < argc; ++optind) status |= touch(argv[optind], nocreate, when);
45 return status;
46usage:
47 fprintf(stderr, "usage: %s [-c] [-t seconds] file...\n", argv[0]);
48 return 1;
49}