Random bug fixes from code inspection, by Wang Cheng Yeh.
[qemu] / block-raw.c
index 3ed4b32..29882e1 100644 (file)
@@ -44,6 +44,8 @@
 #endif
 
 #ifdef __sun__
+#define _POSIX_PTHREAD_SEMANTICS 1
+#include <signal.h>
 #include <sys/dkio.h>
 #endif
 #ifdef __linux__
@@ -51,6 +53,9 @@
 #include <linux/cdrom.h>
 #include <linux/fd.h>
 #endif
+#ifdef __FreeBSD__
+#include <sys/disk.h>
+#endif
 
 //#define DEBUG_FLOPPY
 
@@ -247,6 +252,17 @@ void qemu_aio_poll(void)
  the_end: ;
 }
 
+/* Wait for all IO requests to complete.  */
+void qemu_aio_flush(void)
+{
+    qemu_aio_wait_start();
+    qemu_aio_poll();
+    while (first_aio) {
+        qemu_aio_wait();
+    }
+    qemu_aio_wait_end();
+}
+
 /* wait until at least one AIO was handled */
 static sigset_t wait_oset;
 
@@ -822,6 +838,7 @@ BlockDriver bdrv_host_device = {
 
 #define FTYPE_FILE 0
 #define FTYPE_CD     1
+#define FTYPE_HARDDISK 2
 
 typedef struct BDRVRawState {
     HANDLE hfile;
@@ -890,15 +907,20 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
         create_flags = OPEN_EXISTING;
     }
 #ifdef QEMU_TOOL
-    overlapped = 0;
+    overlapped = FILE_ATTRIBUTE_NORMAL;
 #else
     overlapped = FILE_FLAG_OVERLAPPED;
 #endif
     s->hfile = CreateFile(filename, access_flags, 
                           FILE_SHARE_READ, NULL,
-                          create_flags, overlapped, 0);
-    if (s->hfile == INVALID_HANDLE_VALUE) 
+                          create_flags, overlapped, NULL);
+    if (s->hfile == INVALID_HANDLE_VALUE) {
+        int err = GetLastError();
+
+        if (err == ERROR_ACCESS_DENIED)
+            return -EACCES;
         return -1;
+    }
     return 0;
 }
 
@@ -946,6 +968,7 @@ static int raw_pwrite(BlockDriverState *bs, int64_t offset,
     return ret_count;
 }
 
+#if 0
 #ifndef QEMU_TOOL
 static void raw_aio_cb(void *opaque)
 {
@@ -1048,10 +1071,12 @@ static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
     qemu_aio_release(acb);
 #endif
 }
+#endif /* #if 0 */
 
 static void raw_flush(BlockDriverState *bs)
 {
-    /* XXX: add it */
+    BDRVRawState *s = bs->opaque;
+    FlushFileBuffers(s->hfile);
 }
 
 static void raw_close(BlockDriverState *bs)
@@ -1079,6 +1104,9 @@ static int64_t raw_getlength(BlockDriverState *bs)
     BDRVRawState *s = bs->opaque;
     LARGE_INTEGER l;
     ULARGE_INTEGER available, total, total_free; 
+    DISK_GEOMETRY dg;
+    DWORD count;
+    BOOL status;
 
     switch(s->type) {
     case FTYPE_FILE:
@@ -1091,6 +1119,14 @@ static int64_t raw_getlength(BlockDriverState *bs)
             return -EIO;
         l.QuadPart = total.QuadPart;
         break;
+    case FTYPE_HARDDISK:
+        status = DeviceIoControl(s->hfile, IOCTL_DISK_GET_DRIVE_GEOMETRY,
+                                 NULL, 0, &dg, sizeof(dg), &count, NULL);
+        if (status != FALSE) {
+            l.QuadPart = dg.Cylinders.QuadPart * dg.TracksPerCylinder
+                * dg.SectorsPerTrack * dg.BytesPerSector;
+        }
+        break;
     default:
         return -EIO;
     }
@@ -1123,6 +1159,10 @@ void qemu_aio_poll(void)
 {
 }
 
+void qemu_aio_flush(void)
+{
+}
+
 void qemu_aio_wait_start(void)
 {
 }
@@ -1193,6 +1233,8 @@ static int find_device_type(BlockDriverState *bs, const char *filename)
 
     if (strstart(filename, "\\\\.\\", &p) ||
         strstart(filename, "//./", &p)) {
+        if (stristart(p, "PhysicalDrive", NULL))
+            return FTYPE_HARDDISK;
         snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", p[0]);
         type = GetDriveType(s->drive_path);
         if (type == DRIVE_CDROM)
@@ -1225,7 +1267,7 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
         }
     }
     s->type = find_device_type(bs, filename);
-
+    
     if ((flags & BDRV_O_ACCESS) == O_RDWR) {
         access_flags = GENERIC_READ | GENERIC_WRITE;
     } else {
@@ -1234,15 +1276,20 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
     create_flags = OPEN_EXISTING;
 
 #ifdef QEMU_TOOL
-    overlapped = 0;
+    overlapped = FILE_ATTRIBUTE_NORMAL;
 #else
     overlapped = FILE_FLAG_OVERLAPPED;
 #endif
     s->hfile = CreateFile(filename, access_flags, 
                           FILE_SHARE_READ, NULL,
-                          create_flags, overlapped, 0);
-    if (s->hfile == INVALID_HANDLE_VALUE) 
+                          create_flags, overlapped, NULL);
+    if (s->hfile == INVALID_HANDLE_VALUE) {
+        int err = GetLastError();
+
+        if (err == ERROR_ACCESS_DENIED)
+            return -EACCES;
         return -1;
+    }
     return 0;
 }