aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--coreutils/touch.c57
1 files changed, 16 insertions, 41 deletions
diff --git a/coreutils/touch.c b/coreutils/touch.c
index 690517e66..8d3f8dbbe 100644
--- a/coreutils/touch.c
+++ b/coreutils/touch.c
@@ -25,7 +25,6 @@
25//config: depends on TOUCH 25//config: depends on TOUCH
26//config: help 26//config: help
27//config: Enable touch to have the -h option. 27//config: Enable touch to have the -h option.
28//config: This requires libc support for lutimes() function.
29//config: 28//config:
30//config:config FEATURE_TOUCH_SUSV3 29//config:config FEATURE_TOUCH_SUSV3
31//config: bool "Add support for SUSV3 features (-a -d -m -t -r)" 30//config: bool "Add support for SUSV3 features (-a -d -m -t -r)"
@@ -97,8 +96,6 @@ int touch_main(int argc UNUSED_PARAM, char **argv)
97 OPT_a = (1 << (4+ENABLE_FEATURE_TOUCH_NODEREF)) * ENABLE_FEATURE_TOUCH_SUSV3, 96 OPT_a = (1 << (4+ENABLE_FEATURE_TOUCH_NODEREF)) * ENABLE_FEATURE_TOUCH_SUSV3,
98 OPT_m = (1 << (5+ENABLE_FEATURE_TOUCH_NODEREF)) * ENABLE_FEATURE_TOUCH_SUSV3, 97 OPT_m = (1 << (5+ENABLE_FEATURE_TOUCH_NODEREF)) * ENABLE_FEATURE_TOUCH_SUSV3,
99 }; 98 };
100 /* NULL = use current time */
101 const struct timeval *newtime = NULL;
102#if ENABLE_LONG_OPTS 99#if ENABLE_LONG_OPTS
103 static const char touch_longopts[] ALIGN1 = 100 static const char touch_longopts[] ALIGN1 =
104 /* name, has_arg, val */ 101 /* name, has_arg, val */
@@ -112,12 +109,11 @@ int touch_main(int argc UNUSED_PARAM, char **argv)
112 char *reference_file = NULL; 109 char *reference_file = NULL;
113 char *date_str = NULL; 110 char *date_str = NULL;
114 /* timebuf[0] is atime, timebuf[1] is mtime */ 111 /* timebuf[0] is atime, timebuf[1] is mtime */
115 struct timeval timebuf[2]; 112 struct timespec timebuf[2];
116 timebuf[1].tv_usec = timebuf[0].tv_usec = 0;
117#else 113#else
118# define reference_file NULL 114# define reference_file NULL
119# define date_str NULL 115# define date_str NULL
120# define timebuf ((struct timeval*)NULL) 116# define timebuf ((struct timespec*)NULL)
121#endif 117#endif
122 118
123 /* -d and -t both set time. In coreutils, 119 /* -d and -t both set time. In coreutils,
@@ -140,16 +136,15 @@ int touch_main(int argc UNUSED_PARAM, char **argv)
140 bb_show_usage(); 136 bb_show_usage();
141 } 137 }
142 138
139 timebuf[0].tv_nsec = timebuf[1].tv_nsec = UTIME_NOW;
140
143 if (reference_file) { 141 if (reference_file) {
144 struct stat stbuf; 142 struct stat stbuf;
145 xstat(reference_file, &stbuf); 143 xstat(reference_file, &stbuf);
146 timebuf[0].tv_sec = stbuf.st_atime; 144 timebuf[0].tv_sec = stbuf.st_atime;
147 timebuf[1].tv_sec = stbuf.st_mtime; 145 timebuf[1].tv_sec = stbuf.st_mtime;
148 /* Can use .st_mtim.tv_nsec 146 timebuf[0].tv_nsec = stbuf.st_atim.tv_nsec;
149 * (or is it .st_mtimensec?? see date.c) 147 timebuf[1].tv_nsec = stbuf.st_mtim.tv_nsec;
150 * to set microseconds too.
151 */
152 newtime = timebuf;
153 } 148 }
154 149
155 if (date_str) { 150 if (date_str) {
@@ -167,39 +162,19 @@ int touch_main(int argc UNUSED_PARAM, char **argv)
167 t = validate_tm_time(date_str, &tm_time); 162 t = validate_tm_time(date_str, &tm_time);
168 163
169 timebuf[1].tv_sec = timebuf[0].tv_sec = t; 164 timebuf[1].tv_sec = timebuf[0].tv_sec = t;
170 newtime = timebuf; 165 timebuf[1].tv_nsec = timebuf[0].tv_nsec = 0;
171 } 166 }
172 167
173 if ((opts & (OPT_a | OPT_m)) && !newtime) { 168 if (opts & OPT_a) {
174 time(&timebuf[0].tv_sec); 169 timebuf[1].tv_nsec = UTIME_OMIT;
175 timebuf[1].tv_sec = timebuf[0].tv_sec; 170 }
176 newtime = timebuf; 171 if (opts & OPT_m) {
172 timebuf[0].tv_nsec = UTIME_OMIT;
177 } 173 }
178 174
179 do { 175 do {
180 int result; 176 int result = utimensat(AT_FDCWD, *argv, timebuf,
181 177 (opts & OPT_h) ? AT_SYMLINK_NOFOLLOW : 0);
182 if (opts & (OPT_a | OPT_m)) {
183 /* Save original times */
184 struct stat stbuf;
185 if (stat(*argv, &stbuf) == 0) {
186 /* As we must set both times, we lose original
187 * file time microseconds.
188 * Can use .st_mtim.tv_nsec
189 * (or is it .st_mtimensec?? see date.c)
190 * to set microseconds too.
191 * Also, utimensat(2) allows to omit one of the
192 * times to be set. But it is SUSv4.
193 */
194 if (!(opts & OPT_a))
195 timebuf[0].tv_sec = stbuf.st_atime;
196 if (!(opts & OPT_m))
197 timebuf[1].tv_sec = stbuf.st_mtime;
198 }
199 }
200
201 result = (ENABLE_FEATURE_TOUCH_NODEREF && (opts & OPT_h) ? lutimes : utimes)(*argv, newtime);
202
203 if (result != 0) { 178 if (result != 0) {
204 if (errno == ENOENT) { /* no such file? */ 179 if (errno == ENOENT) { /* no such file? */
205 if (opts & OPT_c) { 180 if (opts & OPT_c) {
@@ -209,9 +184,9 @@ int touch_main(int argc UNUSED_PARAM, char **argv)
209 /* Try to create the file */ 184 /* Try to create the file */
210 fd = open(*argv, O_RDWR | O_CREAT, 0666); 185 fd = open(*argv, O_RDWR | O_CREAT, 0666);
211 if (fd >= 0) { 186 if (fd >= 0) {
212 xclose(fd);
213 if (reference_file || date_str) 187 if (reference_file || date_str)
214 utimes(*argv, newtime); 188 futimens(fd, timebuf);
189 xclose(fd);
215 continue; 190 continue;
216 } 191 }
217 } 192 }