diff options
author | Richard Jones <rjones@redhat.com> | 2009-11-25 10:26:48 +0000 |
---|---|---|
committer | Richard Jones <rjones@redhat.com> | 2009-11-25 16:28:26 +0000 |
commit | fdbc5aa711dde73eb448fbe13165c00a44272d00 (patch) | |
tree | c57f791503f1c90a9251132e43440202f1409ba3 | |
parent | c2aad5cd929a9932c010d045462bd923162fb593 (diff) | |
download | libguestfs-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.ac | 12 | ||||
-rw-r--r-- | daemon/daemon.h | 4 | ||||
-rw-r--r-- | daemon/dropcaches.c | 5 | ||||
-rw-r--r-- | daemon/sync.c | 96 |
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 */ |