aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-05-14 09:18:53 +0100
committerRon Yorston <rmy@pobox.com>2021-05-14 09:18:53 +0100
commite5b7d2b2c17b1bd80d759350bb6d3cfa1303f687 (patch)
tree09c611f64361cde273c81a9f4bd8734cd3431f72
parenta3f5a1b7f4275f713acf22f534f95c0da8392e53 (diff)
downloadbusybox-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.h10
-rw-r--r--win32/mingw.c82
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
357int utimensat(int fd, const char *path, const struct timespec times[2],
358 int flags);
359int 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
711static 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
711int utimes(const char *file_name, const struct timeval tims[2]) 719int 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
749static 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
781int 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
794int 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
741unsigned int sleep (unsigned int seconds) 821unsigned int sleep (unsigned int seconds)
742{ 822{
743 Sleep(seconds*1000); 823 Sleep(seconds*1000);