diff options
author | Ron Yorston <rmy@pobox.com> | 2019-08-16 09:33:29 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2019-08-16 09:33:29 +0100 |
commit | ae65dc37bcc9b1d9cef0b111131c79dc4ba1bf51 (patch) | |
tree | 91cec33a60c2fc7fc90bd9bbd587b65eaf0e55d2 | |
parent | 01950ee1937fdb5172673afad5b65bdb48fe89de (diff) | |
download | busybox-w32-ae65dc37bcc9b1d9cef0b111131c79dc4ba1bf51.tar.gz busybox-w32-ae65dc37bcc9b1d9cef0b111131c79dc4ba1bf51.tar.bz2 busybox-w32-ae65dc37bcc9b1d9cef0b111131c79dc4ba1bf51.zip |
win32: allow nanosecond precision in file times
Modern Linux kernels use struct timespec to represent file times,
thus allowing nanosecond precision. Update the WIN32 emulation of
struct stat and stat(2) to do the same.
-rw-r--r-- | include/mingw.h | 35 | ||||
-rw-r--r-- | win32/mingw.c | 41 |
2 files changed, 48 insertions, 28 deletions
diff --git a/include/mingw.h b/include/mingw.h index 07f9857e9..15ead7799 100644 --- a/include/mingw.h +++ b/include/mingw.h | |||
@@ -242,6 +242,19 @@ NOIMPL(mingw_sendto,SOCKET s UNUSED_PARAM, const char *buf UNUSED_PARAM, int len | |||
242 | #define select mingw_select | 242 | #define select mingw_select |
243 | 243 | ||
244 | /* | 244 | /* |
245 | * sys/time.h | ||
246 | */ | ||
247 | #ifndef _TIMESPEC_DEFINED | ||
248 | #define _TIMESPEC_DEFINED | ||
249 | struct timespec { | ||
250 | time_t tv_sec; | ||
251 | long int tv_nsec; | ||
252 | }; | ||
253 | #endif | ||
254 | |||
255 | int nanosleep(const struct timespec *req, struct timespec *rem); | ||
256 | |||
257 | /* | ||
245 | * sys/stat.h | 258 | * sys/stat.h |
246 | */ | 259 | */ |
247 | #define S_ISUID 04000 | 260 | #define S_ISUID 04000 |
@@ -300,12 +313,15 @@ struct mingw_stat { | |||
300 | gid_t st_gid; | 313 | gid_t st_gid; |
301 | dev_t st_rdev; | 314 | dev_t st_rdev; |
302 | off_t st_size; | 315 | off_t st_size; |
303 | time_t st_atime; | 316 | struct timespec st_atim; |
304 | time_t st_mtime; | 317 | struct timespec st_mtim; |
305 | time_t st_ctime; | 318 | struct timespec st_ctim; |
306 | blksize_t st_blksize; | 319 | blksize_t st_blksize; |
307 | blkcnt_t st_blocks; | 320 | blkcnt_t st_blocks; |
308 | }; | 321 | }; |
322 | #define st_atime st_atim.tv_sec | ||
323 | #define st_mtime st_mtim.tv_sec | ||
324 | #define st_ctime st_ctim.tv_sec | ||
309 | 325 | ||
310 | int mingw_lstat(const char *file_name, struct mingw_stat *buf); | 326 | int mingw_lstat(const char *file_name, struct mingw_stat *buf); |
311 | int mingw_stat(const char *file_name, struct mingw_stat *buf); | 327 | int mingw_stat(const char *file_name, struct mingw_stat *buf); |
@@ -325,19 +341,6 @@ int mingw_fstat(int fd, struct mingw_stat *buf); | |||
325 | #define major(x) 0 | 341 | #define major(x) 0 |
326 | 342 | ||
327 | /* | 343 | /* |
328 | * sys/time.h | ||
329 | */ | ||
330 | #ifndef _TIMESPEC_DEFINED | ||
331 | #define _TIMESPEC_DEFINED | ||
332 | struct timespec { | ||
333 | time_t tv_sec; | ||
334 | long int tv_nsec; | ||
335 | }; | ||
336 | #endif | ||
337 | |||
338 | int nanosleep(const struct timespec *req, struct timespec *rem); | ||
339 | |||
340 | /* | ||
341 | * sys/wait.h | 344 | * sys/wait.h |
342 | */ | 345 | */ |
343 | #define WNOHANG 1 | 346 | #define WNOHANG 1 |
diff --git a/win32/mingw.c b/win32/mingw.c index 3f80b53f1..7e4d6a318 100644 --- a/win32/mingw.c +++ b/win32/mingw.c | |||
@@ -277,6 +277,17 @@ static inline time_t filetime_to_time_t(const FILETIME *ft) | |||
277 | return (time_t)(filetime_to_hnsec(ft) / 10000000); | 277 | return (time_t)(filetime_to_hnsec(ft) / 10000000); |
278 | } | 278 | } |
279 | 279 | ||
280 | static inline struct timespec filetime_to_timespec(const FILETIME *ft) | ||
281 | { | ||
282 | struct timespec ts; | ||
283 | long long winTime = filetime_to_hnsec(ft); | ||
284 | |||
285 | ts.tv_sec = (time_t)(winTime / 10000000); | ||
286 | ts.tv_nsec = (long)(winTime % 10000000) * 100; | ||
287 | |||
288 | return ts; | ||
289 | } | ||
290 | |||
280 | static inline mode_t file_attr_to_st_mode(DWORD attr) | 291 | static inline mode_t file_attr_to_st_mode(DWORD attr) |
281 | { | 292 | { |
282 | mode_t fMode = S_IRUSR|S_IRGRP|S_IROTH; | 293 | mode_t fMode = S_IRUSR|S_IRGRP|S_IROTH; |
@@ -530,9 +541,9 @@ static int do_lstat(int follow, const char *file_name, struct mingw_stat *buf) | |||
530 | /* Get the contents of a symlink, not its target. */ | 541 | /* Get the contents of a symlink, not its target. */ |
531 | buf->st_mode = S_IFLNK|S_IRWXU|S_IRWXG|S_IRWXO; | 542 | buf->st_mode = S_IFLNK|S_IRWXU|S_IRWXG|S_IRWXO; |
532 | buf->st_size = name ? strlen(name) : 0; /* should use readlink */ | 543 | buf->st_size = name ? strlen(name) : 0; /* should use readlink */ |
533 | buf->st_atime = filetime_to_time_t(&(findbuf.ftLastAccessTime)); | 544 | buf->st_atim = filetime_to_timespec(&(findbuf.ftLastAccessTime)); |
534 | buf->st_mtime = filetime_to_time_t(&(findbuf.ftLastWriteTime)); | 545 | buf->st_mtim = filetime_to_timespec(&(findbuf.ftLastWriteTime)); |
535 | buf->st_ctime = filetime_to_time_t(&(findbuf.ftCreationTime)); | 546 | buf->st_ctim = filetime_to_timespec(&(findbuf.ftCreationTime)); |
536 | } | 547 | } |
537 | else { | 548 | else { |
538 | /* The file is not a symlink. */ | 549 | /* The file is not a symlink. */ |
@@ -542,9 +553,9 @@ static int do_lstat(int follow, const char *file_name, struct mingw_stat *buf) | |||
542 | buf->st_mode |= S_IXUSR|S_IXGRP|S_IXOTH; | 553 | buf->st_mode |= S_IXUSR|S_IXGRP|S_IXOTH; |
543 | buf->st_size = fdata.nFileSizeLow | | 554 | buf->st_size = fdata.nFileSizeLow | |
544 | (((off64_t)fdata.nFileSizeHigh)<<32); | 555 | (((off64_t)fdata.nFileSizeHigh)<<32); |
545 | buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime)); | 556 | buf->st_atim = filetime_to_timespec(&(fdata.ftLastAccessTime)); |
546 | buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime)); | 557 | buf->st_mtim = filetime_to_timespec(&(fdata.ftLastWriteTime)); |
547 | buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime)); | 558 | buf->st_ctim = filetime_to_timespec(&(fdata.ftCreationTime)); |
548 | } | 559 | } |
549 | buf->st_nlink = S_ISDIR(buf->st_mode) ? 2 : 1; | 560 | buf->st_nlink = S_ISDIR(buf->st_mode) ? 2 : 1; |
550 | 561 | ||
@@ -594,6 +605,9 @@ int mingw_stat(const char *file_name, struct mingw_stat *buf) | |||
594 | return do_lstat(1, file_name, buf); | 605 | return do_lstat(1, file_name, buf); |
595 | } | 606 | } |
596 | 607 | ||
608 | #undef st_atime | ||
609 | #undef st_mtime | ||
610 | #undef st_ctime | ||
597 | int mingw_fstat(int fd, struct mingw_stat *buf) | 611 | int mingw_fstat(int fd, struct mingw_stat *buf) |
598 | { | 612 | { |
599 | HANDLE fh = (HANDLE)_get_osfhandle(fd); | 613 | HANDLE fh = (HANDLE)_get_osfhandle(fd); |
@@ -612,9 +626,12 @@ int mingw_fstat(int fd, struct mingw_stat *buf) | |||
612 | } | 626 | } |
613 | buf->st_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH; | 627 | buf->st_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH; |
614 | buf->st_size = buf64.st_size; | 628 | buf->st_size = buf64.st_size; |
615 | buf->st_atime = buf64.st_atime; | 629 | buf->st_atim.tv_sec = buf64.st_atime; |
616 | buf->st_mtime = buf64.st_mtime; | 630 | buf->st_atim.tv_nsec = 0; |
617 | buf->st_ctime = buf64.st_ctime; | 631 | buf->st_mtim.tv_sec = buf64.st_mtime; |
632 | buf->st_mtim.tv_nsec = 0; | ||
633 | buf->st_ctim.tv_sec = buf64.st_ctime; | ||
634 | buf->st_ctim.tv_nsec = 0; | ||
618 | buf->st_blocks = ((buf64.st_size+4095)>>12)<<3; | 635 | buf->st_blocks = ((buf64.st_size+4095)>>12)<<3; |
619 | #if ENABLE_FEATURE_EXTRA_FILE_DATA | 636 | #if ENABLE_FEATURE_EXTRA_FILE_DATA |
620 | buf->st_dev = 0; | 637 | buf->st_dev = 0; |
@@ -628,9 +645,9 @@ int mingw_fstat(int fd, struct mingw_stat *buf) | |||
628 | buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes); | 645 | buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes); |
629 | buf->st_size = fdata.nFileSizeLow | | 646 | buf->st_size = fdata.nFileSizeLow | |
630 | (((off64_t)fdata.nFileSizeHigh)<<32); | 647 | (((off64_t)fdata.nFileSizeHigh)<<32); |
631 | buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime)); | 648 | buf->st_atim = filetime_to_timespec(&(fdata.ftLastAccessTime)); |
632 | buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime)); | 649 | buf->st_mtim = filetime_to_timespec(&(fdata.ftLastWriteTime)); |
633 | buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime)); | 650 | buf->st_ctim = filetime_to_timespec(&(fdata.ftCreationTime)); |
634 | buf->st_blocks = ((buf->st_size+4095)>>12)<<3; | 651 | buf->st_blocks = ((buf->st_size+4095)>>12)<<3; |
635 | #if ENABLE_FEATURE_EXTRA_FILE_DATA | 652 | #if ENABLE_FEATURE_EXTRA_FILE_DATA |
636 | buf->st_dev = fdata.dwVolumeSerialNumber; | 653 | buf->st_dev = fdata.dwVolumeSerialNumber; |