From c49d250d45962698bbdb731e0b96e7db17b4aa06 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?=
 <grubba@grubba.org>
Date: Wed, 5 Sep 2012 14:10:51 +0200
Subject: [PATCH] System: Added sync().

---
 src/modules/system/configure.in |  2 +-
 src/modules/system/system.c     | 62 +++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+), 1 deletion(-)

diff --git a/src/modules/system/configure.in b/src/modules/system/configure.in
index 67fc074dd4..a3fed2363c 100644
--- a/src/modules/system/configure.in
+++ b/src/modules/system/configure.in
@@ -92,7 +92,7 @@ AC_HAVE_FUNCS(syslog link symlink readlink resolvepath realpath chown lchown \
 	getpwnam getspnam getgrnam getpwuid getgrgid \
 	getgrent setgrent endgrent getpwent setpwent endpwent \
 	gethostname gethostbyname getservbyname \
-	chroot fchroot uname sysinfo \
+	chroot fchroot uname sysinfo sync \
         getgrnam_r getgrent_r getgrgid_r \
         getpwnam_r getpwent_r getpwuid_r \
 	getspnam_r innetgr utime _utime lutimes sleep usleep nanosleep \
diff --git a/src/modules/system/system.c b/src/modules/system/system.c
index 72f16aa270..93bbf69fe6 100644
--- a/src/modules/system/system.c
+++ b/src/modules/system/system.c
@@ -690,6 +690,64 @@ void f_utime(INT32 args)
 }
 #endif
 
+#if !defined(HAVE_SYNC) && defined(__NT__)
+static void sync(void)
+{
+  /* NB: For some stupid reason FindFirstVolume()/FindNextVolume()
+   *     will only list local filesystems. So we have to fall
+   *     back to using GetLogicalDrives().
+   */
+  /* NB: \\.\ is the DOS device namespace prefix. */
+  char drive[8] = "\\\\.\\A:";
+  char *driveletter = drive + 4;
+  DWORD drives = GetLogicalDrives();
+  DWORD mask = 1;
+  /* Loop over all mounted volumes. */
+  while (mask) {
+    if (mask & drives) {
+      char device[MAX_PATH*2];
+      HANDLE volfile;
+
+      if (QueryDosDeviceA(driveletter, device, MAX_PATH*2)) {
+	volfile = CreateFileA(device, FILE_READ_DATA, FILE_SHARE_READ,
+			      NULL, OPEN_EXISTING, 0, NULL);
+	if (volfile != INVALID_HANDLE_VALUE) {
+	  CloseHandle(volfile);
+	}
+      }
+
+      /* Flush the drive. */
+      volfile = CreateFileA(drive, FILE_READ_DATA, FILE_SHARE_READ,
+			    NULL, OPEN_EXISTING, 0, NULL);
+      if (volfile != INVALID_HANDLE_VALUE) {
+	CloseHandle(volfile);
+      }
+    }
+    *driveletter++;
+    mask = mask << 1;
+  }
+}
+#define HAVE_SYNC
+#endif
+
+#ifdef HAVE_SYNC
+/*! @decl void sync()
+ *!
+ *! Flush operating system disk buffers to permanent storage.
+ *!
+ *! @note
+ *!   On some operating systems this may require
+ *!   administrative privileges.
+ */
+void f_sync(INT32 args)
+{
+  pop_n_elems(args);
+  THREADS_ALLOW_UID()
+  sync();
+  THREADS_DISALLOW_UID();
+}
+#endif
+
 #ifdef HAVE_INITGROUPS
 /*! @decl void initgroups(string name, int base_gid)
  *!
@@ -3261,6 +3319,10 @@ PIKE_MODULE_INIT
 		0, OPT_SIDE_EFFECT);
 #endif
 
+#ifdef HAVE_SYNC
+  ADD_FUNCTION2("sync", f_sync, tFunc(tNone, tVoid), 0, OPT_SIDE_EFFECT);
+#endif
+
 #ifdef HAVE_INITGROUPS
   
 /* function(string, int:void) */
-- 
GitLab