coreutils

General Software Utilities
git clone http://git.omkov.net/coreutils
Log | Tree | Refs | README | LICENCE | Download

coreutils/src/touch.c (145 lines, 4.4 KiB) -rw-r--r-- file download

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