ee5817c |
Jamozed |
2020-07-09 22:03:19 |
0
|
// touch.c, version 1.0.2 |
214225f |
Jamozed |
2020-06-28 00:01:03 |
1
|
// OMKOV coreutils implementation of POSIX touch |
214225f |
Jamozed |
2020-06-28 00:01:03 |
2
|
// Copyright (C) 2020, Jakob Wakeling |
e2140ec |
Jamozed |
2022-03-06 15:27:45 |
3
|
// MIT Licence |
214225f |
Jamozed |
2020-06-28 00:01:03 |
4
|
|
214225f |
Jamozed |
2020-06-28 00:01:03 |
5
|
/* |
214225f |
Jamozed |
2020-06-28 00:01:03 |
6
|
TODO Implement [.frac] support for -d option. |
214225f |
Jamozed |
2020-06-28 00:01:03 |
7
|
*/ |
214225f |
Jamozed |
2020-06-28 00:01:03 |
8
|
|
214225f |
Jamozed |
2020-06-28 00:01:03 |
9
|
#define _XOPEN_SOURCE 700 |
214225f |
Jamozed |
2020-06-28 00:01:03 |
10
|
|
b181413 |
Jamozed |
2022-02-05 22:32:00 |
11
|
#include "util/error.h" |
b181413 |
Jamozed |
2022-02-05 22:32:00 |
12
|
#include "util/optget.h" |
214225f |
Jamozed |
2020-06-28 00:01:03 |
13
|
|
214225f |
Jamozed |
2020-06-28 00:01:03 |
14
|
#include <fcntl.h> |
214225f |
Jamozed |
2020-06-28 00:01:03 |
15
|
#include <sys/stat.h> |
214225f |
Jamozed |
2020-06-28 00:01:03 |
16
|
#include <time.h> |
214225f |
Jamozed |
2020-06-28 00:01:03 |
17
|
#include <unistd.h> |
214225f |
Jamozed |
2020-06-28 00:01:03 |
18
|
|
214225f |
Jamozed |
2020-06-28 00:01:03 |
19
|
#include <errno.h> |
214225f |
Jamozed |
2020-06-28 00:01:03 |
20
|
#include <stdbool.h> |
214225f |
Jamozed |
2020-06-28 00:01:03 |
21
|
#include <stdio.h> |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
22
|
#include <string.h> |
214225f |
Jamozed |
2020-06-28 00:01:03 |
23
|
|
e8367ed |
Jamozed |
2020-07-06 23:46:31 |
24
|
#define VERSION "1.0.1" |
214225f |
Jamozed |
2020-06-28 00:01:03 |
25
|
|
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
26
|
static struct lop lops[] = { |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
27
|
{ "help", ARG_NUL, 256 }, |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
28
|
{ "version", ARG_NUL, 257 }, |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
29
|
{ NULL, 0, 0 } |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
30
|
}; |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
31
|
|
214225f |
Jamozed |
2020-06-28 00:01:03 |
32
|
static bool aflag, cflag, mflag; |
214225f |
Jamozed |
2020-06-28 00:01:03 |
33
|
static bool rflag, notnow; |
214225f |
Jamozed |
2020-06-28 00:01:03 |
34
|
|
214225f |
Jamozed |
2020-06-28 00:01:03 |
35
|
static struct timespec times[2] = {{ .tv_nsec = UTIME_NOW }}; |
214225f |
Jamozed |
2020-06-28 00:01:03 |
36
|
|
214225f |
Jamozed |
2020-06-28 00:01:03 |
37
|
static inline void dparse(const char *str); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
38
|
static inline void tparse(const char *str); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
39
|
static inline void rparse(const char *str); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
40
|
|
214225f |
Jamozed |
2020-06-28 00:01:03 |
41
|
static inline int touch(const char *file); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
42
|
|
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
43
|
static void hlp(void); |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
44
|
static void ver(void); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
45
|
|
e8367ed |
Jamozed |
2020-07-06 23:46:31 |
46
|
int main(int ac, char *av[]) { A0 = av[0]; |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
47
|
struct opt opt = OPTGET_INIT; opt.str = "acd:mr:t:"; opt.lops = lops; int o; |
e8367ed |
Jamozed |
2020-07-06 23:46:31 |
48
|
while ((o = optget(&opt, av, 1)) != -1) switch (o) { |
214225f |
Jamozed |
2020-06-28 00:01:03 |
49
|
case 'a': { aflag = true; break; } |
214225f |
Jamozed |
2020-06-28 00:01:03 |
50
|
case 'c': { cflag = true; break; } |
214225f |
Jamozed |
2020-06-28 00:01:03 |
51
|
case 'd': { if (notnow) { goto invalid; } dparse(opt.arg); break; } |
214225f |
Jamozed |
2020-06-28 00:01:03 |
52
|
case 'm': { mflag = true; break; } |
214225f |
Jamozed |
2020-06-28 00:01:03 |
53
|
case 'r': { if (notnow) { goto invalid; } rparse(opt.arg); break; } |
214225f |
Jamozed |
2020-06-28 00:01:03 |
54
|
case 't': { if (notnow) { goto invalid; } tparse(opt.arg); break; } |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
55
|
case 256: { hlp(); return 0; } |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
56
|
case 257: { ver(); return 0; } |
214225f |
Jamozed |
2020-06-28 00:01:03 |
57
|
default: { return 1; } |
e8367ed |
Jamozed |
2020-07-06 23:46:31 |
58
|
invalid: { error(1, "invalid option combination"); } |
214225f |
Jamozed |
2020-06-28 00:01:03 |
59
|
} |
214225f |
Jamozed |
2020-06-28 00:01:03 |
60
|
|
e8367ed |
Jamozed |
2020-07-06 23:46:31 |
61
|
if (opt.ind == ac) { error(1, "missing operand"); } |
214225f |
Jamozed |
2020-06-28 00:01:03 |
62
|
|
214225f |
Jamozed |
2020-06-28 00:01:03 |
63
|
if (!rflag) { times[1] = times[0]; } |
214225f |
Jamozed |
2020-06-28 00:01:03 |
64
|
if (!aflag && !mflag) { aflag = mflag = true; } |
214225f |
Jamozed |
2020-06-28 00:01:03 |
65
|
else if (!aflag) { times[0].tv_nsec = UTIME_OMIT; } |
214225f |
Jamozed |
2020-06-28 00:01:03 |
66
|
else if (!mflag) { times[1].tv_nsec = UTIME_OMIT; } |
214225f |
Jamozed |
2020-06-28 00:01:03 |
67
|
|
214225f |
Jamozed |
2020-06-28 00:01:03 |
68
|
bool warned = false; |
214225f |
Jamozed |
2020-06-28 00:01:03 |
69
|
|
e8367ed |
Jamozed |
2020-07-06 23:46:31 |
70
|
for (char **p = &av[opt.ind]; *p; ++p) if (touch(*p)) { |
e8367ed |
Jamozed |
2020-07-06 23:46:31 |
71
|
warn("%s: %s", *p, serr()); warned = true; |
214225f |
Jamozed |
2020-06-28 00:01:03 |
72
|
} |
214225f |
Jamozed |
2020-06-28 00:01:03 |
73
|
|
214225f |
Jamozed |
2020-06-28 00:01:03 |
74
|
return warned; |
214225f |
Jamozed |
2020-06-28 00:01:03 |
75
|
} |
214225f |
Jamozed |
2020-06-28 00:01:03 |
76
|
|
214225f |
Jamozed |
2020-06-28 00:01:03 |
77
|
static inline void dparse(const char *str) { |
214225f |
Jamozed |
2020-06-28 00:01:03 |
78
|
struct tm t = { 0 }; t.tm_isdst = -1; |
214225f |
Jamozed |
2020-06-28 00:01:03 |
79
|
|
214225f |
Jamozed |
2020-06-28 00:01:03 |
80
|
register size_t len = strlen(str); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
81
|
if (len == 19 && strptime(str, "%Y-%m-%dT%H:%M:%S", &t)); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
82
|
else if (len == 20 && strptime(str, "%Y-%m-%dT%H:%M:%SZ", &t)) { |
214225f |
Jamozed |
2020-06-28 00:01:03 |
83
|
tzset(); t.tm_sec -= timezone; |
e8367ed |
Jamozed |
2020-07-06 23:46:31 |
84
|
} else { error(1, "%s: invalid time format", str); } |
214225f |
Jamozed |
2020-06-28 00:01:03 |
85
|
|
214225f |
Jamozed |
2020-06-28 00:01:03 |
86
|
struct timespec ts; ts.tv_sec = mktime(&t); ts.tv_nsec = 0; |
214225f |
Jamozed |
2020-06-28 00:01:03 |
87
|
times[0] = ts; notnow = true; return; |
214225f |
Jamozed |
2020-06-28 00:01:03 |
88
|
} |
214225f |
Jamozed |
2020-06-28 00:01:03 |
89
|
|
214225f |
Jamozed |
2020-06-28 00:01:03 |
90
|
static inline void tparse(const char *str) { |
214225f |
Jamozed |
2020-06-28 00:01:03 |
91
|
time_t now; struct tm *cur, t = { 0 }; |
214225f |
Jamozed |
2020-06-28 00:01:03 |
92
|
if ((now = time(NULL)) == -1 || !(cur = localtime(&now))) { |
e8367ed |
Jamozed |
2020-07-06 23:46:31 |
93
|
error(1, "%s: %s", str, serr()); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
94
|
} t.tm_isdst = -1; |
214225f |
Jamozed |
2020-06-28 00:01:03 |
95
|
|
214225f |
Jamozed |
2020-06-28 00:01:03 |
96
|
register size_t len = strlen(str); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
97
|
if (len == 8 && strptime(str, "%m%d%H%M", &t)); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
98
|
else if (len == 10 && strptime(str, "%y%m%d%H%M", &t)); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
99
|
else if (len == 11 && strptime(str, "%m%d%H%M.%S", &t)); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
100
|
else if (len == 12 && strptime(str, "%Y%m%d%H%M", &t)); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
101
|
else if (len == 13 && strptime(str, "%y%m%d%H%M.%S", &t)); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
102
|
else if (len == 15 && strptime(str, "%Y%m%d%H%M.%S", &t)); |
e8367ed |
Jamozed |
2020-07-06 23:46:31 |
103
|
else { error(1, "%s: invalid time format", str); } |
214225f |
Jamozed |
2020-06-28 00:01:03 |
104
|
|
214225f |
Jamozed |
2020-06-28 00:01:03 |
105
|
struct timespec ts; ts.tv_sec = mktime(&t); ts.tv_nsec = 0; |
214225f |
Jamozed |
2020-06-28 00:01:03 |
106
|
times[0] = ts; notnow = true; return; |
214225f |
Jamozed |
2020-06-28 00:01:03 |
107
|
} |
214225f |
Jamozed |
2020-06-28 00:01:03 |
108
|
|
214225f |
Jamozed |
2020-06-28 00:01:03 |
109
|
static inline void rparse(const char *file) { |
214225f |
Jamozed |
2020-06-28 00:01:03 |
110
|
struct stat fs; if (stat(file, &fs)) { |
e8367ed |
Jamozed |
2020-07-06 23:46:31 |
111
|
error(1, "%s: %s", file, serr()); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
112
|
} times[0] = fs.st_atim; times[1] = fs.st_mtim; |
214225f |
Jamozed |
2020-06-28 00:01:03 |
113
|
rflag = true; notnow = true; return; |
214225f |
Jamozed |
2020-06-28 00:01:03 |
114
|
} |
214225f |
Jamozed |
2020-06-28 00:01:03 |
115
|
|
214225f |
Jamozed |
2020-06-28 00:01:03 |
116
|
static inline int touch(const char *file) { |
214225f |
Jamozed |
2020-06-28 00:01:03 |
117
|
if (utimensat(AT_FDCWD, file, times, 0)) { |
214225f |
Jamozed |
2020-06-28 00:01:03 |
118
|
if (errno != ENOENT) { return 1; } if (cflag) { return 0; } |
ee5817c |
Jamozed |
2020-07-09 22:03:19 |
119
|
unsigned m = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; |
ee5817c |
Jamozed |
2020-07-09 22:03:19 |
120
|
register int fd; if ((fd = creat(file, m)) == -1) { return 1; } |
214225f |
Jamozed |
2020-06-28 00:01:03 |
121
|
if (futimens(fd, times)) { close(fd); return 1; } close(fd); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
122
|
} return 0; |
214225f |
Jamozed |
2020-06-28 00:01:03 |
123
|
} |
214225f |
Jamozed |
2020-06-28 00:01:03 |
124
|
|
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
125
|
static void hlp(void) { |
214225f |
Jamozed |
2020-06-28 00:01:03 |
126
|
puts("touch - change file access and modify times\n"); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
127
|
puts("usage: touch [-acm] [-d time|-r file|-t time] file...\n"); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
128
|
puts("options:"); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
129
|
puts(" -a Change the access time only"); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
130
|
puts(" -c Do not create new files"); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
131
|
puts(" -d time Use YYYY-MM-DDThh:mm:SS[.frac][tz]"); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
132
|
puts(" -m Change the modification time only"); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
133
|
puts(" -r file Use a specified files times"); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
134
|
puts(" -t time Use [[CC]YY]MMDDhhmm[.SS]"); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
135
|
puts(" --help Display help information"); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
136
|
puts(" --version Display version information"); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
137
|
} |
214225f |
Jamozed |
2020-06-28 00:01:03 |
138
|
|
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
139
|
static void ver(void) { |
e8367ed |
Jamozed |
2020-07-06 23:46:31 |
140
|
puts("OMKOV coreutils touch, version " VERSION); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
141
|
puts("Copyright (C) 2020, Jakob Wakeling"); |
e2140ec |
Jamozed |
2022-03-06 15:27:45 |
142
|
puts("MIT Licence (https://opensource.org/licenses/MIT)"); |
214225f |
Jamozed |
2020-06-28 00:01:03 |
143
|
} |
|
|
|
144
|
|