diff options
-rw-r--r-- | coreutils/touch.c | 57 |
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 | } |