diff options
author | Ron Yorston <rmy@pobox.com> | 2021-05-14 09:18:53 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2021-05-14 09:18:53 +0100 |
commit | e5b7d2b2c17b1bd80d759350bb6d3cfa1303f687 (patch) | |
tree | 09c611f64361cde273c81a9f4bd8734cd3431f72 | |
parent | a3f5a1b7f4275f713acf22f534f95c0da8392e53 (diff) | |
download | busybox-w32-e5b7d2b2c17b1bd80d759350bb6d3cfa1303f687.tar.gz busybox-w32-e5b7d2b2c17b1bd80d759350bb6d3cfa1303f687.tar.bz2 busybox-w32-e5b7d2b2c17b1bd80d759350bb6d3cfa1303f687.zip |
win32: implement futimens(2)/utimensat(2)
The touch applet has been changed to use futimens(2)/utimensat(2).
Provide implementations of these for WIN32.
-rw-r--r-- | include/mingw.h | 10 | ||||
-rw-r--r-- | win32/mingw.c | 82 |
2 files changed, 91 insertions, 1 deletions
diff --git a/include/mingw.h b/include/mingw.h index d48237add..89b26762a 100644 --- a/include/mingw.h +++ b/include/mingw.h | |||
@@ -34,6 +34,9 @@ int inet_pton(int af, const char *src, void *dst); | |||
34 | #define O_DIRECT 0 | 34 | #define O_DIRECT 0 |
35 | #define O_SPECIAL 0x800000 | 35 | #define O_SPECIAL 0x800000 |
36 | 36 | ||
37 | #define AT_FDCWD -100 | ||
38 | #define AT_SYMLINK_NOFOLLOW 0x100 | ||
39 | |||
37 | /* | 40 | /* |
38 | * grp.h | 41 | * grp.h |
39 | */ | 42 | */ |
@@ -348,6 +351,13 @@ int mingw_fstat(int fd, struct mingw_stat *buf); | |||
348 | #define stat mingw_stat | 351 | #define stat mingw_stat |
349 | #define fstat mingw_fstat | 352 | #define fstat mingw_fstat |
350 | 353 | ||
354 | #define UTIME_NOW ((1l << 30) - 1l) | ||
355 | #define UTIME_OMIT ((1l << 30) - 2l) | ||
356 | |||
357 | int utimensat(int fd, const char *path, const struct timespec times[2], | ||
358 | int flags); | ||
359 | int futimens(int fd, const struct timespec times[2]); | ||
360 | |||
351 | /* | 361 | /* |
352 | * sys/sysinfo.h | 362 | * sys/sysinfo.h |
353 | */ | 363 | */ |
diff --git a/win32/mingw.c b/win32/mingw.c index 3bb79633a..182e3d4db 100644 --- a/win32/mingw.c +++ b/win32/mingw.c | |||
@@ -708,6 +708,14 @@ static inline void timeval_to_filetime(const struct timeval tv, FILETIME *ft) | |||
708 | ft->dwHighDateTime = winTime >> 32; | 708 | ft->dwHighDateTime = winTime >> 32; |
709 | } | 709 | } |
710 | 710 | ||
711 | static inline void timespec_to_filetime(const struct timespec tv, FILETIME *ft) | ||
712 | { | ||
713 | long long winTime = (tv.tv_sec * 10000000LL) + tv.tv_nsec / 100LL + | ||
714 | 116444736000000000LL; | ||
715 | ft->dwLowDateTime = winTime; | ||
716 | ft->dwHighDateTime = winTime >> 32; | ||
717 | } | ||
718 | |||
711 | int utimes(const char *file_name, const struct timeval tims[2]) | 719 | int utimes(const char *file_name, const struct timeval tims[2]) |
712 | { | 720 | { |
713 | FILETIME mft, aft; | 721 | FILETIME mft, aft; |
@@ -731,13 +739,85 @@ int utimes(const char *file_name, const struct timeval tims[2]) | |||
731 | } | 739 | } |
732 | 740 | ||
733 | if (!SetFileTime(fh, NULL, &aft, &mft)) { | 741 | if (!SetFileTime(fh, NULL, &aft, &mft)) { |
734 | errno = EINVAL; | 742 | errno = err_win_to_posix(); |
735 | rc = -1; | 743 | rc = -1; |
736 | } | 744 | } |
737 | CloseHandle(fh); | 745 | CloseHandle(fh); |
738 | return rc; | 746 | return rc; |
739 | } | 747 | } |
740 | 748 | ||
749 | static int hutimens(HANDLE fh, const struct timespec times[2]) | ||
750 | { | ||
751 | FILETIME now, aft, mft; | ||
752 | FILETIME *pft[2] = {&aft, &mft}; | ||
753 | int i; | ||
754 | |||
755 | GetSystemTimeAsFileTime(&now); | ||
756 | |||
757 | if (times) { | ||
758 | for (i = 0; i < 2; ++i) { | ||
759 | if (times[i].tv_nsec == UTIME_NOW) | ||
760 | *pft[i] = now; | ||
761 | else if (times[i].tv_nsec == UTIME_OMIT) | ||
762 | pft[i] = NULL; | ||
763 | else if (times[i].tv_nsec >= 0 && times[i].tv_nsec < 1000000000L) | ||
764 | timespec_to_filetime(times[i], pft[i]); | ||
765 | else { | ||
766 | errno = EINVAL; | ||
767 | return -1; | ||
768 | } | ||
769 | } | ||
770 | } else { | ||
771 | aft = mft = now; | ||
772 | } | ||
773 | |||
774 | if (!SetFileTime(fh, NULL, pft[0], pft[1])) { | ||
775 | errno = err_win_to_posix(); | ||
776 | return -1; | ||
777 | } | ||
778 | return 0; | ||
779 | } | ||
780 | |||
781 | int futimens(int fd, const struct timespec times[2]) | ||
782 | { | ||
783 | HANDLE fh; | ||
784 | |||
785 | fh = (HANDLE)_get_osfhandle(fd); | ||
786 | if (fh == INVALID_HANDLE_VALUE) { | ||
787 | errno = EBADF; | ||
788 | return -1; | ||
789 | } | ||
790 | |||
791 | return hutimens(fh, times); | ||
792 | } | ||
793 | |||
794 | int utimensat(int fd, const char *path, const struct timespec times[2], | ||
795 | int flags) | ||
796 | { | ||
797 | int rc = -1; | ||
798 | HANDLE fh; | ||
799 | DWORD cflag = FILE_FLAG_BACKUP_SEMANTICS; | ||
800 | |||
801 | if (!is_absolute_path(path) && fd != AT_FDCWD) { | ||
802 | errno = ENOSYS; // partial implementation | ||
803 | return rc; | ||
804 | } | ||
805 | |||
806 | if (flags & AT_SYMLINK_NOFOLLOW) | ||
807 | cflag |= FILE_FLAG_OPEN_REPARSE_POINT; | ||
808 | |||
809 | fh = CreateFile(path, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING, | ||
810 | cflag, NULL); | ||
811 | if (fh == INVALID_HANDLE_VALUE) { | ||
812 | errno = err_win_to_posix(); | ||
813 | return rc; | ||
814 | } | ||
815 | |||
816 | rc = hutimens(fh, times); | ||
817 | CloseHandle(fh); | ||
818 | return rc; | ||
819 | } | ||
820 | |||
741 | unsigned int sleep (unsigned int seconds) | 821 | unsigned int sleep (unsigned int seconds) |
742 | { | 822 | { |
743 | Sleep(seconds*1000); | 823 | Sleep(seconds*1000); |