From bc0d14ee8eb9720a5df097f5620c4b4c679b6c98 Mon Sep 17 00:00:00 2001
From: Ron Yorston <rmy@pobox.com>
Date: Sun, 16 Jul 2023 08:49:50 +0100
Subject: date: allow system date to be set

Implement clock_settime(2) and enable the '-s' option to allow
the system time to be set.  This requires elevated privileges.

The code in date.c is now identical to upstream BusyBox.

Costs 256-272 bytes.
---
 coreutils/date.c | 25 -------------------------
 include/mingw.h  |  1 +
 win32/mingw.c    | 23 +++++++++++++++++++++++
 3 files changed, 24 insertions(+), 25 deletions(-)

diff --git a/coreutils/date.c b/coreutils/date.c
index d8e56ef3b..3a89b6caf 100644
--- a/coreutils/date.c
+++ b/coreutils/date.c
@@ -97,9 +97,7 @@
 //usage:#define date_full_usage "\n\n"
 //usage:       "Display time (using +FMT), or set time\n"
 //usage:     "\n	-u		Work in UTC (don't convert to local time)"
-//usage:	IF_NOT_PLATFORM_MINGW32(
 //usage:     "\n	[-s] TIME	Set time to TIME"
-//usage:	)
 //usage:     "\n	-d TIME		Display TIME, not 'now'"
 //usage:	IF_FEATURE_DATE_ISOFMT(
 //usage:     "\n	-D FMT		FMT (strptime format) for -s/-d TIME conversion"
@@ -134,30 +132,19 @@
 
 enum {
 	OPT_RFC2822   = (1 << 0), /* R */
-#if !ENABLE_PLATFORM_MINGW32
 	OPT_SET       = (1 << 1), /* s */
 	OPT_UTC       = (1 << 2), /* u */
 	OPT_DATE      = (1 << 3), /* d */
 	OPT_REFERENCE = (1 << 4), /* r */
 	OPT_ISO8601   = (1 << 5) * ENABLE_FEATURE_DATE_ISOFMT, /* I */
 	OPT_STR2DT    = (1 << 6) * ENABLE_FEATURE_DATE_ISOFMT, /* D */
-#else
-	OPT_SET       = (0),      /* s */
-	OPT_UTC       = (1 << 1), /* u */
-	OPT_DATE      = (1 << 2), /* d */
-	OPT_REFERENCE = (1 << 3), /* r */
-	OPT_ISO8601   = (1 << 4) * ENABLE_FEATURE_DATE_ISOFMT, /* I */
-	OPT_STR2DT    = (1 << 5) * ENABLE_FEATURE_DATE_ISOFMT, /* D */
-#endif
 };
 
 #if ENABLE_LONG_OPTS
 static const char date_longopts[] ALIGN1 =
 		"rfc-822\0"   No_argument       "R"
 		"rfc-2822\0"  No_argument       "R"
-#if !ENABLE_PLATFORM_MINGW32
 		"set\0"       Required_argument "s"
-#endif
 		"utc\0"       No_argument       "u"
 	/*	"universal\0" No_argument       "u" */
 		"date\0"      Required_argument "d"
@@ -187,25 +174,13 @@ int date_main(int argc UNUSED_PARAM, char **argv)
 	char *isofmt_arg = NULL;
 
 	opt = getopt32long(argv, "^"
-#if !ENABLE_PLATFORM_MINGW32
 			"Rs:ud:r:"
-#else
-			"Rud:r:"
-#endif
 			IF_FEATURE_DATE_ISOFMT("I::D:")
-#if !ENABLE_PLATFORM_MINGW32
 			"\0"
 			"d--s:s--d"
 			IF_FEATURE_DATE_ISOFMT(":R--I:I--R"),
-#else
-			IF_FEATURE_DATE_ISOFMT("\0R--I:I--R"),
-#endif
 			date_longopts,
-#if !ENABLE_PLATFORM_MINGW32
 			&date_str, &date_str, &filename
-#else
-			&date_str, &filename
-#endif
 			IF_FEATURE_DATE_ISOFMT(, &isofmt_arg, &fmt_str2dt)
 	);
 	argv += optind;
diff --git a/include/mingw.h b/include/mingw.h
index ae34666e8..232ffadd7 100644
--- a/include/mingw.h
+++ b/include/mingw.h
@@ -294,6 +294,7 @@ time_t timegm(struct tm *tm);
 
 int nanosleep(const struct timespec *req, struct timespec *rem);
 int clock_gettime(clockid_t clockid, struct timespec *tp);
+int clock_settime(clockid_t clockid, const struct timespec *tp);
 
 /*
  * sys/stat.h
diff --git a/win32/mingw.c b/win32/mingw.c
index 86dc75861..5e9c71226 100644
--- a/win32/mingw.c
+++ b/win32/mingw.c
@@ -1008,6 +1008,29 @@ int clock_gettime(clockid_t clockid, struct timespec *tp)
 	return 0;
 }
 
+int clock_settime(clockid_t clockid, const struct timespec *tp)
+{
+	SYSTEMTIME st;
+	FILETIME ft;
+
+	if (clockid != CLOCK_REALTIME) {
+		errno = ENOSYS;
+		return -1;
+	}
+
+	timespec_to_filetime(*tp, &ft);
+	if (FileTimeToSystemTime(&ft, &st) == 0) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (SetSystemTime(&st) == 0) {
+		errno = EPERM;
+		return -1;
+	}
+	return 0;
+}
+
 int pipe(int filedes[2])
 {
 	if (_pipe(filedes, PIPE_BUF, 0) < 0)
-- 
cgit v1.2.3-55-g6feb