Clean some PCI defines (Stefan Weil)
[qemu] / block-cow.c
index 81bd334..b9a1971 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Block driver for the COW format
- * 
+ *
  * Copyright (c) 2004 Fabrice Bellard
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
  * in the Software without restriction, including without limitation the rights
@@ -22,7 +22,7 @@
  * THE SOFTWARE.
  */
 #ifndef _WIN32
-#include "vl.h"
+#include "qemu-common.h"
 #include "block_int.h"
 #include <sys/mman.h>
 
@@ -54,14 +54,15 @@ static int cow_probe(const uint8_t *buf, int buf_size, const char *filename)
 {
     const struct cow_header_v2 *cow_header = (const void *)buf;
 
-    if (be32_to_cpu(cow_header->magic) == COW_MAGIC &&
-        be32_to_cpu(cow_header->version) == COW_VERSION) 
+    if (buf_size >= sizeof(struct cow_header_v2) &&
+        be32_to_cpu(cow_header->magic) == COW_MAGIC &&
+        be32_to_cpu(cow_header->version) == COW_VERSION)
         return 100;
     else
         return 0;
 }
 
-static int cow_open(BlockDriverState *bs, const char *filename)
+static int cow_open(BlockDriverState *bs, const char *filename, int flags)
 {
     BDRVCowState *s = bs->opaque;
     int fd;
@@ -84,34 +85,18 @@ static int cow_open(BlockDriverState *bs, const char *filename)
         be32_to_cpu(cow_header.version) != COW_VERSION) {
         goto fail;
     }
-        
+
     /* cow image found */
     size = be64_to_cpu(cow_header.size);
     bs->total_sectors = size / 512;
 
-    pstrcpy(bs->backing_file, sizeof(bs->backing_file), 
+    pstrcpy(bs->backing_file, sizeof(bs->backing_file),
             cow_header.backing_file);
-    
-#if 0
-    if (cow_header.backing_file[0] != '\0') {
-        if (stat(cow_header.backing_file, &st) != 0) {
-            fprintf(stderr, "%s: could not find original disk image '%s'\n", filename, cow_header.backing_file);
-            goto fail;
-        }
-        if (st.st_mtime != be32_to_cpu(cow_header.mtime)) {
-            fprintf(stderr, "%s: original raw disk image '%s' does not match saved timestamp\n", filename, cow_header.backing_file);
-            goto fail;
-            }
-        fd = open(cow_header.backing_file, O_RDONLY | O_LARGEFILE);
-        if (fd < 0)
-            goto fail;
-        bs->fd = fd;
-    }
-#endif
+
     /* mmap the bitmap */
     s->cow_bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header);
-    s->cow_bitmap_addr = mmap(get_mmap_addr(s->cow_bitmap_size), 
-                              s->cow_bitmap_size, 
+    s->cow_bitmap_addr = mmap(get_mmap_addr(s->cow_bitmap_size),
+                              s->cow_bitmap_size,
                               PROT_READ | PROT_WRITE,
                               MAP_SHARED, s->fd, 0);
     if (s->cow_bitmap_addr == MAP_FAILED)
@@ -124,7 +109,7 @@ static int cow_open(BlockDriverState *bs, const char *filename)
     return -1;
 }
 
-static inline void set_bit(uint8_t *bitmap, int64_t bitnum)
+static inline void cow_set_bit(uint8_t *bitmap, int64_t bitnum)
 {
     bitmap[bitnum / 8] |= (1 << (bitnum%8));
 }
@@ -158,28 +143,35 @@ static inline int is_changed(uint8_t *bitmap,
     return changed;
 }
 
-static int cow_is_allocated(BlockDriverState *bs, int64_t sector_num, 
+static int cow_is_allocated(BlockDriverState *bs, int64_t sector_num,
                             int nb_sectors, int *pnum)
 {
     BDRVCowState *s = bs->opaque;
     return is_changed(s->cow_bitmap, sector_num, nb_sectors, pnum);
 }
 
-static int cow_read(BlockDriverState *bs, int64_t sector_num, 
+static int cow_read(BlockDriverState *bs, int64_t sector_num,
                     uint8_t *buf, int nb_sectors)
 {
     BDRVCowState *s = bs->opaque;
     int ret, n;
-    
+
     while (nb_sectors > 0) {
         if (is_changed(s->cow_bitmap, sector_num, nb_sectors, &n)) {
             lseek(s->fd, s->cow_sectors_offset + sector_num * 512, SEEK_SET);
             ret = read(s->fd, buf, n * 512);
-            if (ret != n * 512) 
+            if (ret != n * 512)
                 return -1;
         } else {
+            if (bs->backing_hd) {
+                /* read from the base image */
+                ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
+                if (ret < 0)
+                    return -1;
+            } else {
             memset(buf, 0, n * 512);
         }
+        }
         nb_sectors -= n;
         sector_num += n;
         buf += n * 512;
@@ -187,18 +179,18 @@ static int cow_read(BlockDriverState *bs, int64_t sector_num,
     return 0;
 }
 
-static int cow_write(BlockDriverState *bs, int64_t sector_num, 
+static int cow_write(BlockDriverState *bs, int64_t sector_num,
                      const uint8_t *buf, int nb_sectors)
 {
     BDRVCowState *s = bs->opaque;
     int ret, i;
-    
+
     lseek(s->fd, s->cow_sectors_offset + sector_num * 512, SEEK_SET);
     ret = write(s->fd, buf, nb_sectors * 512);
-    if (ret != nb_sectors * 512) 
+    if (ret != nb_sectors * 512)
         return -1;
     for (i = 0; i < nb_sectors; i++)
-        set_bit(s->cow_bitmap, sector_num + i);
+        cow_set_bit(s->cow_bitmap, sector_num + i);
     return 0;
 }
 
@@ -219,7 +211,7 @@ static int cow_create(const char *filename, int64_t image_sectors,
     if (flags)
         return -ENOTSUP;
 
-    cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 
+    cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
               0644);
     if (cow_fd < 0)
         return -1;
@@ -227,18 +219,23 @@ static int cow_create(const char *filename, int64_t image_sectors,
     cow_header.magic = cpu_to_be32(COW_MAGIC);
     cow_header.version = cpu_to_be32(COW_VERSION);
     if (image_filename) {
+        /* Note: if no file, we put a dummy mtime */
+        cow_header.mtime = cpu_to_be32(0);
+
         fd = open(image_filename, O_RDONLY | O_BINARY);
         if (fd < 0) {
             close(cow_fd);
-            return -1;
+            goto mtime_fail;
         }
         if (fstat(fd, &st) != 0) {
             close(fd);
-            return -1;
+            goto mtime_fail;
         }
         close(fd);
         cow_header.mtime = cpu_to_be32(st.st_mtime);
-        realpath(image_filename, cow_header.backing_file);
+    mtime_fail:
+        pstrcpy(cow_header.backing_file, sizeof(cow_header.backing_file),
+                image_filename);
     }
     cow_header.sectorsize = cpu_to_be32(512);
     cow_header.size = cpu_to_be64(image_sectors * 512);
@@ -249,15 +246,22 @@ static int cow_create(const char *filename, int64_t image_sectors,
     return 0;
 }
 
+static void cow_flush(BlockDriverState *bs)
+{
+    BDRVCowState *s = bs->opaque;
+    fsync(s->fd);
+}
+
 BlockDriver bdrv_cow = {
-    "cow",
-    sizeof(BDRVCowState),
-    cow_probe,
-    cow_open,
-    cow_read,
-    cow_write,
-    cow_close,
-    cow_create,
-    cow_is_allocated,
+    .format_name       = "cow",
+    .instance_size     = sizeof(BDRVCowState),
+    .bdrv_probe                = cow_probe,
+    .bdrv_open         = cow_open,
+    .bdrv_read         = cow_read,
+    .bdrv_write                = cow_write,
+    .bdrv_close                = cow_close,
+    .bdrv_create       = cow_create,
+    .bdrv_flush                = cow_flush,
+    .bdrv_is_allocated = cow_is_allocated,
 };
 #endif