aboutsummaryrefslogtreecommitdiff
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
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.
-rw-r--r--include/mingw.h35
-rw-r--r--win32/mingw.c41
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
249struct timespec {
250 time_t tv_sec;
251 long int tv_nsec;
252};
253#endif
254
255int 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
310int mingw_lstat(const char *file_name, struct mingw_stat *buf); 326int mingw_lstat(const char *file_name, struct mingw_stat *buf);
311int mingw_stat(const char *file_name, struct mingw_stat *buf); 327int 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
332struct timespec {
333 time_t tv_sec;
334 long int tv_nsec;
335};
336#endif
337
338int 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
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;