summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Jones <rjones@redhat.com>2009-11-25 10:26:48 +0000
committerRichard Jones <rjones@redhat.com>2009-11-25 16:28:26 +0000
commitfdbc5aa711dde73eb448fbe13165c00a44272d00 (patch)
treec57f791503f1c90a9251132e43440202f1409ba3
parentc2aad5cd929a9932c010d045462bd923162fb593 (diff)
downloadlibguestfs-fdbc5aa711dde73eb448fbe13165c00a44272d00.tar.gz
libguestfs-fdbc5aa711dde73eb448fbe13165c00a44272d00.tar.xz
libguestfs-fdbc5aa711dde73eb448fbe13165c00a44272d00.zip
sync: Windows implementation of sync() call.
Replace calls to sync() with calls to sync_disks() which supports Win32 via FlushFileBuffers.
-rw-r--r--daemon/configure.ac12
-rw-r--r--daemon/daemon.h4
-rw-r--r--daemon/dropcaches.c5
-rw-r--r--daemon/sync.c96
4 files changed, 110 insertions, 7 deletions
diff --git a/daemon/configure.ac b/daemon/configure.ac
index 7bcdd7e6..d1a9b0ff 100644
--- a/daemon/configure.ac
+++ b/daemon/configure.ac
@@ -181,14 +181,16 @@ AC_CHECK_FUNCS([\
mknod \
posix_fallocate \
removexattr \
- setxattr])
+ setxattr \
+ sync])
dnl Headers.
AC_CHECK_HEADERS([\
- attr/xattr.h \
- printf.h \
- sys/inotify.h \
- sys/xattr.h])
+ attr/xattr.h \
+ printf.h \
+ sys/inotify.h \
+ sys/xattr.h \
+ windows.h])
dnl For modified printf, we need glibc either (old-style)
dnl register_printf_function or (new-style) register_printf_specifier.
diff --git a/daemon/daemon.h b/daemon/daemon.h
index 7ba75990..6872bd75 100644
--- a/daemon/daemon.h
+++ b/daemon/daemon.h
@@ -112,6 +112,10 @@ struct optgroup {
};
extern struct optgroup optgroups[];
+/*-- in sync.c --*/
+/* Use this as a replacement for sync(2). */
+extern int sync_disks (void);
+
/* ordinary daemon functions use these to indicate errors */
extern void reply_with_error (const char *fs, ...)
__attribute__((format (printf,1,2)));
diff --git a/daemon/dropcaches.c b/daemon/dropcaches.c
index a818323d..46bfd076 100644
--- a/daemon/dropcaches.c
+++ b/daemon/dropcaches.c
@@ -34,7 +34,10 @@ do_drop_caches (int what)
{
FILE *fp;
- sync ();
+ if (sync_disks () == -1) {
+ reply_with_perror ("sync");
+ return -1;
+ }
fp = fopen (PROCFILE, "w");
if (fp == NULL) {
diff --git a/daemon/sync.c b/daemon/sync.c
index e96bf032..2cdb10c9 100644
--- a/daemon/sync.c
+++ b/daemon/sync.c
@@ -18,14 +18,108 @@
#include <config.h>
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+#endif
+
#include <stdio.h>
#include <unistd.h>
+#include "daemon.h"
#include "actions.h"
+#ifdef WIN32
+static int sync_win32 (void);
+#endif
+
int
do_sync (void)
{
- sync ();
+ if (sync_disks () == -1) {
+ reply_with_perror ("sync");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* This is a replacement for sync(2) which is called from
+ * this file and from other places in the daemon. It works
+ * on Windows too.
+ */
+int
+sync_disks (void)
+{
+#if defined(HAVE_SYNC)
+ return sync ();
+#elif defined(WIN32)
+ return sync_win32 ();
+#else
+#error "no known sync() API"
+#endif
+}
+
+#ifdef WIN32
+static int
+sync_win32 (void)
+{
+ DWORD n1, n2;
+
+ n1 = GetLogicalDriveStrings (0, NULL);
+ if (n1 == 0)
+ return -1;
+
+ TCHAR buffer[n1+2]; /* sic */
+ n2 = GetLogicalDriveStrings (n1, buffer);
+ if (n2 == 0)
+ return -1;
+
+ TCHAR *p = buffer;
+
+ /* The MSDN example code itself assumes that there is always one
+ * drive in the system. However we will be better than that and not
+ * make the assumption ...
+ */
+ while (*p) {
+ HANDLE drive;
+ DWORD drive_type;
+
+ if (verbose)
+ fprintf (stderr, "sync_win32: examining drive %s\n", p);
+
+ /* Ignore removable drives. */
+ drive_type = GetDriveType (p);
+ if (drive_type == DRIVE_FIXED) {
+ /* To open the volume you have to specify the volume name, not
+ * the mount point. MSDN documents use of the constant 50
+ * below.
+ */
+ TCHAR volname[50];
+ if (!GetVolumeNameForVolumeMountPoint (p, volname, 50))
+ return -1;
+
+ drive = CreateFile (volname, GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL, OPEN_EXISTING, 0, 0);
+ if (drive == INVALID_HANDLE_VALUE)
+ return -1;
+ if (verbose)
+ fprintf (stderr, "sync_win32: flushing %s\n", volname);
+
+ BOOL r;
+ /* This always fails in Wine:
+ * http://bugs.winehq.org/show_bug.cgi?id=14915
+ */
+ r = FlushFileBuffers (drive);
+ CloseHandle (drive);
+ if (!r)
+ return -1;
+ }
+
+ /* Skip to next \0 character. */
+ while (*p++);
+ }
+
return 0;
}
+#endif /* WIN32 */