X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=daemon%2Fsync.c;h=a09c8c15da9ddda552ffa83e3c1bbaab282af529;hp=70962dff2ca584ed02d94330c3d19c68b8b7a831;hb=7f16c346bbeba2f2fe3c31ccb85158178a284d84;hpb=b4d2a01828e5de85e5eee3631f7fe3925a0312ca diff --git a/daemon/sync.c b/daemon/sync.c index 70962df..a09c8c1 100644 --- a/daemon/sync.c +++ b/daemon/sync.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009-2011 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,14 +18,122 @@ #include +#ifdef HAVE_WINDOWS_H +#include +#endif + #include #include +#include "daemon.h" #include "actions.h" +#ifdef WIN32 +static int sync_win32 (void); +#endif + +int +do_sync (void) +{ + if (sync_disks () == -1) { + reply_with_perror ("sync"); + return -1; + } + + return 0; +} + +/* Older versions of libguestfs used to issue separate 'umount_all' + * and 'sync' commands just before closing the handle. Since + * libguestfs 1.9.7 the library issues this 'internal_autosync' + * internal operation instead, allowing more control in the daemon. + */ +int +do_internal_autosync (void) +{ + int r = 0; + + if (autosync_umount) + r = do_umount_all (); + + sync_disks (); + + return r; +} + +/* 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 -do_sync () +sync_disks (void) { +#if defined(HAVE_SYNC) sync (); return 0; +#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; + + /* 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; + + 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 */