LBA48 support (Jens Axboe)
[qemu] / qemu-img.c
index 480dff9..3a18c93 100644 (file)
@@ -113,7 +113,7 @@ void __attribute__((noreturn)) error(const char *fmt, ...)
 {
     va_list ap;
     va_start(ap, fmt);
-    fprintf(stderr, "qemuimg: ");
+    fprintf(stderr, "qemu-img: ");
     vfprintf(stderr, fmt, ap);
     fprintf(stderr, "\n");
     exit(1);
@@ -127,8 +127,8 @@ static void format_print(void *opaque, const char *name)
 
 void help(void)
 {
-    printf("qemuimg version " QEMU_VERSION ", Copyright (c) 2004 Fabrice Bellard\n"
-           "usage: qemuimg command [command options]\n"
+    printf("qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2005 Fabrice Bellard\n"
+           "usage: qemu-img command [command options]\n"
            "QEMU disk image utility\n"
            "\n"
            "Command syntax:\n"
@@ -165,7 +165,7 @@ static void get_human_readable_size(char *buf, int buf_size, int64_t size)
     int i;
 
     if (size <= 999) {
-        snprintf(buf, buf_size, "%lld", size);
+        snprintf(buf, buf_size, "%lld", (long long) size);
     } else {
         base = 1024;
         for(i = 0; i < NB_SUFFIXES; i++) {
@@ -176,7 +176,7 @@ static void get_human_readable_size(char *buf, int buf_size, int64_t size)
                 break;
             } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) {
                 snprintf(buf, buf_size, "%lld%c", 
-                         (size + (base >> 1)) / base,
+                         (long long) ((size + (base >> 1)) / base),
                          suffixes[i]);
                 break;
             }
@@ -273,6 +273,36 @@ int read_password(char *buf, int buf_size)
 }
 #endif
 
+static BlockDriverState *bdrv_new_open(const char *filename,
+                                       const char *fmt)
+{
+    BlockDriverState *bs;
+    BlockDriver *drv;
+    char password[256];
+
+    bs = bdrv_new("");
+    if (!bs)
+        error("Not enough memory");
+    if (fmt) {
+        drv = bdrv_find_format(fmt);
+        if (!drv)
+            error("Unknown file format '%s'", fmt);
+    } else {
+        drv = NULL;
+    }
+    if (bdrv_open2(bs, filename, 0, drv) < 0) {
+        error("Could not open '%s'", filename);
+    }
+    if (bdrv_is_encrypted(bs)) {
+        printf("Disk image '%s' is encrypted.\n", filename);
+        if (read_password(password, sizeof(password)) < 0)
+            error("No password given");
+        if (bdrv_set_key(bs, password) < 0)
+            error("invalid password");
+    }
+    return bs;
+}
+
 static int img_create(int argc, char **argv)
 {
     int c, ret, encrypted;
@@ -303,12 +333,17 @@ static int img_create(int argc, char **argv)
             break;
         }
     }
-    optind++;
     if (optind >= argc) 
         help();
     filename = argv[optind++];
     size = 0;
-    if (!base_filename) {
+    if (base_filename) {
+        BlockDriverState *bs;
+        bs = bdrv_new_open(base_filename, NULL);
+        bdrv_get_geometry(bs, &size);
+        size *= 512;
+        bdrv_delete(bs);
+    } else {
         if (optind >= argc)
             help();
         p = argv[optind];
@@ -330,15 +365,15 @@ static int img_create(int argc, char **argv)
            filename, fmt);
     if (encrypted)
         printf(", encrypted");
-    if (base_filename)
-        printf(", backing_file=%s\n",
+    if (base_filename) {
+        printf(", backing_file=%s",
                base_filename);
-    else
-        printf(", size=%lld kB\n", size / 1024);
+    }
+    printf(", size=%lld kB\n", (long long) (size / 1024));
     ret = bdrv_create(drv, filename, size / 512, base_filename, encrypted);
     if (ret < 0) {
         if (ret == -ENOTSUP) {
-            error("Formatting or formatting option not suppored for file format '%s'", fmt);
+            error("Formatting or formatting option not supported for file format '%s'", fmt);
         } else {
             error("Error while formatting");
         }
@@ -367,7 +402,6 @@ static int img_commit(int argc, char **argv)
             break;
         }
     }
-    optind++;
     if (optind >= argc) 
         help();
     filename = argv[optind++];
@@ -437,36 +471,6 @@ static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum)
     return v;
 }
 
-static BlockDriverState *bdrv_new_open(const char *filename,
-                                       const char *fmt)
-{
-    BlockDriverState *bs;
-    BlockDriver *drv;
-    char password[256];
-
-    bs = bdrv_new("");
-    if (!bs)
-        error("Not enough memory");
-    if (fmt) {
-        drv = bdrv_find_format(fmt);
-        if (!drv)
-            error("Unknown file format '%s'", fmt);
-    } else {
-        drv = NULL;
-    }
-    if (bdrv_open2(bs, filename, 0, drv) < 0) {
-        error("Could not open '%s'", filename);
-    }
-    if (bdrv_is_encrypted(bs)) {
-        printf("Disk image '%s' is encrypted.\n", filename);
-        if (read_password(password, sizeof(password)) < 0)
-            error("No password given");
-        if (bdrv_set_key(bs, password) < 0)
-            error("invalid password");
-    }
-    return bs;
-}
-
 #define IO_BUF_SIZE 65536
 
 static int img_convert(int argc, char **argv)
@@ -505,7 +509,6 @@ static int img_convert(int argc, char **argv)
             break;
         }
     }
-    optind++;
     if (optind >= argc) 
         help();
     filename = argv[optind++];
@@ -528,7 +531,7 @@ static int img_convert(int argc, char **argv)
     ret = bdrv_create(drv, out_filename, total_sectors, NULL, encrypt);
     if (ret < 0) {
         if (ret == -ENOTSUP) {
-            error("Formatting not suppored for file format '%s'", fmt);
+            error("Formatting not supported for file format '%s'", fmt);
         } else {
             error("Error while formatting '%s'", out_filename);
         }
@@ -592,6 +595,24 @@ static int img_convert(int argc, char **argv)
     return 0;
 }
 
+#ifdef _WIN32
+static int64_t get_allocated_file_size(const char *filename)
+{
+    struct _stati64 st;
+    if (_stati64(filename, &st) < 0) 
+        return -1;
+    return st.st_size;
+}
+#else
+static int64_t get_allocated_file_size(const char *filename)
+{
+    struct stat st;
+    if (stat(filename, &st) < 0) 
+        return -1;
+    return (int64_t)st.st_blocks * 512;
+}
+#endif
+
 static int img_info(int argc, char **argv)
 {
     int c;
@@ -599,8 +620,7 @@ static int img_info(int argc, char **argv)
     BlockDriver *drv;
     BlockDriverState *bs;
     char fmt_name[128], size_buf[128], dsize_buf[128];
-    int64_t total_sectors;
-    struct stat st;
+    int64_t total_sectors, allocated_size;
 
     fmt = NULL;
     for(;;) {
@@ -616,7 +636,6 @@ static int img_info(int argc, char **argv)
             break;
         }
     }
-    optind++;
     if (optind >= argc) 
         help();
     filename = argv[optind++];
@@ -637,16 +656,18 @@ static int img_info(int argc, char **argv)
     bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
     bdrv_get_geometry(bs, &total_sectors);
     get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
-    if (stat(filename, &st) < 0) 
-        error("Could not stat '%s'", filename);
-    get_human_readable_size(dsize_buf, sizeof(dsize_buf), 
-                            (int64_t)st.st_blocks * 512);
+    allocated_size = get_allocated_file_size(filename);
+    if (allocated_size < 0)
+       sprintf(dsize_buf, "unavailable");
+    else
+        get_human_readable_size(dsize_buf, sizeof(dsize_buf), 
+                                allocated_size);
     printf("image: %s\n"
            "file format: %s\n"
            "virtual size: %s (%lld bytes)\n"
            "disk size: %s\n",
            filename, fmt_name, size_buf, 
-           total_sectors * 512,
+           (long long) (total_sectors * 512),
            dsize_buf);
     if (bdrv_is_encrypted(bs))
         printf("encrypted: yes\n");
@@ -662,6 +683,7 @@ int main(int argc, char **argv)
     if (argc < 2)
         help();
     cmd = argv[1];
+    optind++;
     if (!strcmp(cmd, "create")) {
         img_create(argc, argv);
     } else if (!strcmp(cmd, "commit")) {