Random bug fixes from code inspection, by Wang Cheng Yeh.
[qemu] / block-raw.c
index 9f4a0a1..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__
@@ -836,6 +838,7 @@ BlockDriver bdrv_host_device = {
 
 #define FTYPE_FILE 0
 #define FTYPE_CD     1
+#define FTYPE_HARDDISK 2
 
 typedef struct BDRVRawState {
     HANDLE hfile;
@@ -904,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;
 }
 
@@ -960,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)
 {
@@ -1062,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)
@@ -1093,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:
@@ -1105,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;
     }
@@ -1211,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)
@@ -1243,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 {
@@ -1252,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;
 }