aboutsummaryrefslogtreecommitdiff
path: root/win32
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2019-08-16 09:33:29 +0100
committerRon Yorston <rmy@pobox.com>2019-08-16 09:33:29 +0100
commitae65dc37bcc9b1d9cef0b111131c79dc4ba1bf51 (patch)
tree91cec33a60c2fc7fc90bd9bbd587b65eaf0e55d2 /win32
parent01950ee1937fdb5172673afad5b65bdb48fe89de (diff)
downloadbusybox-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.
Diffstat (limited to 'win32')
-rw-r--r--win32/mingw.c41
1 files changed, 29 insertions, 12 deletions
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
280static 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
280static inline mode_t file_attr_to_st_mode(DWORD attr) 291static 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
597int mingw_fstat(int fd, struct mingw_stat *buf) 611int 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;