aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXabier Oneca <xoneca@gmail.com>2021-04-09 23:15:29 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2021-04-12 20:05:48 +0200
commit520bb3eac2627e2f6bda05ceb2e3e7db71b73dd3 (patch)
tree15017b67b938f2c8130f513480d7c0cc380aaf4a
parent7323bca1b00d96630f52bc3b4182558d6f8cbc92 (diff)
downloadbusybox-w32-520bb3eac2627e2f6bda05ceb2e3e7db71b73dd3.tar.gz
busybox-w32-520bb3eac2627e2f6bda05ceb2e3e7db71b73dd3.tar.bz2
busybox-w32-520bb3eac2627e2f6bda05ceb2e3e7db71b73dd3.zip
touch: add SUSv3 options -a and -m
Add missing -a and -m options to be fully SUSv3 compliant. function old new delta touch_main 415 510 +95 packed_usage 33824 33865 +41 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 136/0) Total: 136 bytes v2: Ignore -a/-m if not ENABLE_FEATURE_TOUCH_SUSV3. Signed-off-by: Xabier Oneca <xoneca@gmail.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--coreutils/touch.c59
1 files changed, 45 insertions, 14 deletions
diff --git a/coreutils/touch.c b/coreutils/touch.c
index b30811157..dff68cb00 100644
--- a/coreutils/touch.c
+++ b/coreutils/touch.c
@@ -28,7 +28,7 @@
28//config: This requires libc support for lutimes() function. 28//config: This requires libc support for lutimes() function.
29//config: 29//config:
30//config:config FEATURE_TOUCH_SUSV3 30//config:config FEATURE_TOUCH_SUSV3
31//config: bool "Add support for SUSV3 features (-d -t -r)" 31//config: bool "Add support for SUSV3 features (-a -d -m -t -r)"
32//config: default y 32//config: default y
33//config: depends on TOUCH 33//config: depends on TOUCH
34//config: help 34//config: help
@@ -38,11 +38,10 @@
38 38
39//kbuild:lib-$(CONFIG_TOUCH) += touch.o 39//kbuild:lib-$(CONFIG_TOUCH) += touch.o
40 40
41/* BB_AUDIT SUSv3 _NOT_ compliant -- options -a, -m not supported. */
42/* http://www.opengroup.org/onlinepubs/007904975/utilities/touch.html */
43
44//usage:#define touch_trivial_usage 41//usage:#define touch_trivial_usage
45//usage: "[-c]" IF_FEATURE_TOUCH_SUSV3(" [-d DATE] [-t DATE] [-r FILE]") " FILE..." 42//usage: "[-c" IF_FEATURE_TOUCH_SUSV3("am") "]"
43//usage: IF_FEATURE_TOUCH_SUSV3(" [-d DATE] [-t DATE] [-r FILE]")
44//usage: " FILE..."
46//usage:#define touch_full_usage "\n\n" 45//usage:#define touch_full_usage "\n\n"
47//usage: "Update the last-modified date on the given FILE[s]\n" 46//usage: "Update the last-modified date on the given FILE[s]\n"
48//usage: "\n -c Don't create files" 47//usage: "\n -c Don't create files"
@@ -50,6 +49,8 @@
50//usage: "\n -h Don't follow links" 49//usage: "\n -h Don't follow links"
51//usage: ) 50//usage: )
52//usage: IF_FEATURE_TOUCH_SUSV3( 51//usage: IF_FEATURE_TOUCH_SUSV3(
52//usage: "\n -a Change only atime"
53//usage: "\n -m Change only mtime"
53//usage: "\n -d DT Date/time to use" 54//usage: "\n -d DT Date/time to use"
54//usage: "\n -t DT Date/time to use" 55//usage: "\n -t DT Date/time to use"
55//usage: "\n -r FILE Use FILE's date/time" 56//usage: "\n -r FILE Use FILE's date/time"
@@ -92,9 +93,13 @@ int touch_main(int argc UNUSED_PARAM, char **argv)
92 OPT_r = (1 << 1) * ENABLE_FEATURE_TOUCH_SUSV3, 93 OPT_r = (1 << 1) * ENABLE_FEATURE_TOUCH_SUSV3,
93 OPT_d = (1 << 2) * ENABLE_FEATURE_TOUCH_SUSV3, 94 OPT_d = (1 << 2) * ENABLE_FEATURE_TOUCH_SUSV3,
94 OPT_t = (1 << 3) * ENABLE_FEATURE_TOUCH_SUSV3, 95 OPT_t = (1 << 3) * ENABLE_FEATURE_TOUCH_SUSV3,
95 OPT_h = (1 << 4) * ENABLE_FEATURE_TOUCH_NODEREF, 96 OPT_a = (1 << 4) * ENABLE_FEATURE_TOUCH_SUSV3,
97 OPT_m = (1 << 5) * ENABLE_FEATURE_TOUCH_SUSV3,
98 OPT_h = (1 << 6) * ENABLE_FEATURE_TOUCH_NODEREF,
96 }; 99 };
97#if ENABLE_FEATURE_TOUCH_SUSV3 100#if ENABLE_FEATURE_TOUCH_SUSV3
101 /* NULL = use current time */
102 const struct timeval *newtime = NULL;
98# if ENABLE_LONG_OPTS 103# if ENABLE_LONG_OPTS
99 static const char touch_longopts[] ALIGN1 = 104 static const char touch_longopts[] ALIGN1 =
100 /* name, has_arg, val */ 105 /* name, has_arg, val */
@@ -111,6 +116,7 @@ int touch_main(int argc UNUSED_PARAM, char **argv)
111# endif 116# endif
112 char *reference_file = NULL; 117 char *reference_file = NULL;
113 char *date_str = NULL; 118 char *date_str = NULL;
119 /* timebuf[0] is atime, timebuf[1] is mtime */
114 struct timeval timebuf[2]; 120 struct timeval timebuf[2];
115 timebuf[1].tv_usec = timebuf[0].tv_usec = 0; 121 timebuf[1].tv_usec = timebuf[0].tv_usec = 0;
116#else 122#else
@@ -124,9 +130,9 @@ int touch_main(int argc UNUSED_PARAM, char **argv)
124 /* -d and -t both set time. In coreutils, 130 /* -d and -t both set time. In coreutils,
125 * accepted data format differs a bit between -d and -t. 131 * accepted data format differs a bit between -d and -t.
126 * We accept the same formats for both */ 132 * We accept the same formats for both */
127 opts = GETOPT32(argv, "c" IF_FEATURE_TOUCH_SUSV3("r:d:t:") 133 opts = GETOPT32(argv, "c" IF_FEATURE_TOUCH_SUSV3("r:d:t:am")
128 IF_FEATURE_TOUCH_NODEREF("h") 134 IF_FEATURE_TOUCH_NODEREF("h")
129 /*ignored:*/ "fma" 135 /*ignored:*/ "f" IF_NOT_FEATURE_TOUCH_SUSV3("am")
130 LONGOPTS 136 LONGOPTS
131 IF_FEATURE_TOUCH_SUSV3(, &reference_file) 137 IF_FEATURE_TOUCH_SUSV3(, &reference_file)
132 IF_FEATURE_TOUCH_SUSV3(, &date_str) 138 IF_FEATURE_TOUCH_SUSV3(, &date_str)
@@ -146,6 +152,7 @@ int touch_main(int argc UNUSED_PARAM, char **argv)
146 * (or is it .st_mtimensec?? see date.c) 152 * (or is it .st_mtimensec?? see date.c)
147 * to set microseconds too. 153 * to set microseconds too.
148 */ 154 */
155 newtime = timebuf;
149 } 156 }
150 157
151 if (date_str) { 158 if (date_str) {
@@ -163,15 +170,39 @@ int touch_main(int argc UNUSED_PARAM, char **argv)
163 t = validate_tm_time(date_str, &tm_time); 170 t = validate_tm_time(date_str, &tm_time);
164 171
165 timebuf[1].tv_sec = timebuf[0].tv_sec = t; 172 timebuf[1].tv_sec = timebuf[0].tv_sec = t;
173 newtime = timebuf;
174 }
175
176 if ((opts & (OPT_a | OPT_m)) && !newtime) {
177 time(&timebuf[0].tv_sec);
178 timebuf[1].tv_sec = timebuf[0].tv_sec;
179 newtime = timebuf;
166 } 180 }
167 181
168 do { 182 do {
169 int result; 183 int result;
170 result = ( 184
171#if ENABLE_FEATURE_TOUCH_NODEREF 185 if (opts & (OPT_a | OPT_m)) {
172 (opts & OPT_h) ? lutimes : 186 /* Save original times */
173#endif 187 struct stat stbuf;
174 utimes)(*argv, (reference_file || date_str) ? timebuf : NULL); 188 if (stat(*argv, &stbuf) == 0) {
189 /* As we must set both times, we lose original
190 * file time microseconds.
191 * Can use .st_mtim.tv_nsec
192 * (or is it .st_mtimensec?? see date.c)
193 * to set microseconds too.
194 * Also, utimensat(2) allows to omit one of the
195 * times to be set. But it is SUSv4.
196 */
197 if (!(opts & OPT_a))
198 timebuf[0].tv_sec = stbuf.st_atime;
199 if (!(opts & OPT_m))
200 timebuf[1].tv_sec = stbuf.st_mtime;
201 }
202 }
203
204 result = (ENABLE_FEATURE_TOUCH_NODEREF && (opts & OPT_h) ? lutimes : utimes)(*argv, newtime);
205
175 if (result != 0) { 206 if (result != 0) {
176 if (errno == ENOENT) { /* no such file? */ 207 if (errno == ENOENT) { /* no such file? */
177 if (opts & OPT_c) { 208 if (opts & OPT_c) {
@@ -183,7 +214,7 @@ int touch_main(int argc UNUSED_PARAM, char **argv)
183 if (fd >= 0) { 214 if (fd >= 0) {
184 xclose(fd); 215 xclose(fd);
185 if (reference_file || date_str) 216 if (reference_file || date_str)
186 utimes(*argv, timebuf); 217 utimes(*argv, newtime);
187 continue; 218 continue;
188 } 219 }
189 } 220 }