Diff for /qemu/qemu-img.c between versions 1.1.1.7 and 1.1.1.8

version 1.1.1.7, 2018/04/24 17:06:52 version 1.1.1.8, 2018/04/24 17:20:53
Line 22 Line 22
  * THE SOFTWARE.   * THE SOFTWARE.
  */   */
 #include "qemu-common.h"  #include "qemu-common.h"
   #include "qemu-option.h"
 #include "osdep.h"  #include "osdep.h"
 #include "block_int.h"  #include "block_int.h"
 #include <assert.h>  #include <stdio.h>
   
 #ifdef _WIN32  #ifdef _WIN32
 #define WIN32_LEAN_AND_MEAN  
 #include <windows.h>  #include <windows.h>
 #endif  #endif
   
   typedef struct img_cmd_t {
       const char *name;
       int (*handler)(int argc, char **argv);
   } img_cmd_t;
   
 /* Default to cache=writeback as data integrity is not important for qemu-tcg. */  /* Default to cache=writeback as data integrity is not important for qemu-tcg. */
 #define BRDV_O_FLAGS BDRV_O_CACHE_WB  #define BRDV_O_FLAGS BDRV_O_CACHE_WB
   
Line 58  static void help(void) Line 63  static void help(void)
            "QEMU disk image utility\n"             "QEMU disk image utility\n"
            "\n"             "\n"
            "Command syntax:\n"             "Command syntax:\n"
            "  create [-e] [-6] [-b base_image] [-f fmt] filename [size]\n"  #define DEF(option, callback, arg_string)        \
            "  commit [-f fmt] filename\n"             "  " arg_string "\n"
            "  convert [-c] [-e] [-6] [-f fmt] [-O output_fmt] [-B output_base_image] filename [filename2 [...]] output_filename\n"  #include "qemu-img-cmds.h"
            "  info [-f fmt] filename\n"  #undef DEF
            "  snapshot [-l | -a snapshot | -c snapshot | -d snapshot] filename\n"  #undef GEN_DOCS
            "\n"             "\n"
            "Command parameters:\n"             "Command parameters:\n"
            "  'filename' is a disk image filename\n"             "  'filename' is a disk image filename\n"
Line 78  static void help(void) Line 83  static void help(void)
            "    supported any 'k' or 'K' is ignored\n"             "    supported any 'k' or 'K' is ignored\n"
            "  'output_filename' is the destination disk image filename\n"             "  'output_filename' is the destination disk image filename\n"
            "  'output_fmt' is the destination format\n"             "  'output_fmt' is the destination format\n"
              "  'options' is a comma separated list of format specific options in a\n"
              "    name=value format. Use -o ? for an overview of the options supported by the\n"
              "    used format\n"
            "  '-c' indicates that target image must be compressed (qcow format only)\n"             "  '-c' indicates that target image must be compressed (qcow format only)\n"
            "  '-e' indicates that the target image must be encrypted (qcow format only)\n"  
            "  '-6' indicates that the target image must use compatibility level 6 (vmdk format only)\n"  
            "  '-h' with or without a command shows this help and lists the supported formats\n"             "  '-h' with or without a command shows this help and lists the supported formats\n"
            "\n"             "\n"
            "Parameters to snapshot subcommand:\n"             "Parameters to snapshot subcommand:\n"
Line 214  static BlockDriverState *bdrv_new_open(c Line 220  static BlockDriverState *bdrv_new_open(c
     return bs;      return bs;
 }  }
   
   static void add_old_style_options(const char *fmt, QEMUOptionParameter *list,
       int flags, const char *base_filename, const char *base_fmt)
   {
       if (flags & BLOCK_FLAG_ENCRYPT) {
           if (set_option_parameter(list, BLOCK_OPT_ENCRYPT, "on")) {
               error("Encryption not supported for file format '%s'", fmt);
           }
       }
       if (flags & BLOCK_FLAG_COMPAT6) {
           if (set_option_parameter(list, BLOCK_OPT_COMPAT6, "on")) {
               error("VMDK version 6 not supported for file format '%s'", fmt);
           }
       }
   
       if (base_filename) {
           if (set_option_parameter(list, BLOCK_OPT_BACKING_FILE, base_filename)) {
               error("Backing file not supported for file format '%s'", fmt);
           }
       }
       if (base_fmt) {
           if (set_option_parameter(list, BLOCK_OPT_BACKING_FMT, base_fmt)) {
               error("Backing file format not supported for file format '%s'", fmt);
           }
       }
   }
   
 static int img_create(int argc, char **argv)  static int img_create(int argc, char **argv)
 {  {
     int c, ret, flags;      int c, ret, flags;
     const char *fmt = "raw";      const char *fmt = "raw";
       const char *base_fmt = NULL;
     const char *filename;      const char *filename;
     const char *base_filename = NULL;      const char *base_filename = NULL;
     uint64_t size;  
     const char *p;  
     BlockDriver *drv;      BlockDriver *drv;
       QEMUOptionParameter *param = NULL;
       char *options = NULL;
   
     flags = 0;      flags = 0;
     for(;;) {      for(;;) {
         c = getopt(argc, argv, "b:f:he6");          c = getopt(argc, argv, "F:b:f:he6o:");
         if (c == -1)          if (c == -1)
             break;              break;
         switch(c) {          switch(c) {
         case 'h':          case 'h':
             help();              help();
             break;              break;
           case 'F':
               base_fmt = optarg;
               break;
         case 'b':          case 'b':
             base_filename = optarg;              base_filename = optarg;
             break;              break;
Line 245  static int img_create(int argc, char **a Line 281  static int img_create(int argc, char **a
         case '6':          case '6':
             flags |= BLOCK_FLAG_COMPAT6;              flags |= BLOCK_FLAG_COMPAT6;
             break;              break;
           case 'o':
               options = optarg;
               break;
         }          }
     }      }
   
       /* Find driver and parse its options */
       drv = bdrv_find_format(fmt);
       if (!drv)
           error("Unknown file format '%s'", fmt);
   
       if (options && !strcmp(options, "?")) {
           print_option_help(drv->create_options);
           return 0;
       }
   
       if (options) {
           param = parse_option_parameters(options, drv->create_options, param);
           if (param == NULL) {
               error("Invalid options for file format '%s'.", fmt);
           }
       } else {
           param = parse_option_parameters("", drv->create_options, param);
       }
   
       /* Get the filename */
     if (optind >= argc)      if (optind >= argc)
         help();          help();
     filename = argv[optind++];      filename = argv[optind++];
     size = 0;  
     if (base_filename) {      /* Add size to parameters */
         BlockDriverState *bs;      if (optind < argc) {
         bs = bdrv_new_open(base_filename, NULL);          set_option_parameter(param, BLOCK_OPT_SIZE, argv[optind++]);
         bdrv_get_geometry(bs, &size);      }
         size *= 512;  
         bdrv_delete(bs);      /* Add old-style options to parameters */
     } else {      add_old_style_options(fmt, param, flags, base_filename, base_fmt);
         if (optind >= argc)  
             help();      // The size for the image must always be specified, with one exception:
         p = argv[optind];      // If we are using a backing file, we can obtain the size from there
         size = strtoul(p, (char **)&p, 0);      if (get_option_parameter(param, BLOCK_OPT_SIZE)->value.n == 0) {
         if (*p == 'M') {  
             size *= 1024 * 1024;          QEMUOptionParameter *backing_file =
         } else if (*p == 'G') {              get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
             size *= 1024 * 1024 * 1024;          QEMUOptionParameter *backing_fmt =
         } else if (*p == 'k' || *p == 'K' || *p == '\0') {              get_option_parameter(param, BLOCK_OPT_BACKING_FMT);
             size *= 1024;  
           if (backing_file && backing_file->value.s) {
               BlockDriverState *bs;
               uint64_t size;
               const char *fmt = NULL;
               char buf[32];
   
               if (backing_fmt && backing_fmt->value.s) {
                    if (bdrv_find_format(backing_fmt->value.s)) {
                        fmt = backing_fmt->value.s;
                   } else {
                        error("Unknown backing file format '%s'",
                           backing_fmt->value.s);
                   }
               }
   
               bs = bdrv_new_open(backing_file->value.s, fmt);
               bdrv_get_geometry(bs, &size);
               size *= 512;
               bdrv_delete(bs);
   
               snprintf(buf, sizeof(buf), "%" PRId64, size);
               set_option_parameter(param, BLOCK_OPT_SIZE, buf);
         } else {          } else {
             help();              error("Image creation needs a size parameter");
         }          }
     }      }
     drv = bdrv_find_format(fmt);  
     if (!drv)      printf("Formatting '%s', fmt=%s ", filename, fmt);
         error("Unknown file format '%s'", fmt);      print_option_parameters(param);
     printf("Formatting '%s', fmt=%s",      puts("");
            filename, fmt);  
     if (flags & BLOCK_FLAG_ENCRYPT)      ret = bdrv_create(drv, filename, param);
         printf(", encrypted");      free_option_parameters(param);
     if (flags & BLOCK_FLAG_COMPAT6)  
         printf(", compatibility level=6");  
     if (base_filename) {  
         printf(", backing_file=%s",  
                base_filename);  
     }  
     printf(", size=%" PRIu64 " kB\n", size / 1024);  
     ret = bdrv_create(drv, filename, size / 512, base_filename, flags);  
     if (ret < 0) {      if (ret < 0) {
         if (ret == -ENOTSUP) {          if (ret == -ENOTSUP) {
             error("Formatting or formatting option not supported for file format '%s'", fmt);              error("Formatting or formatting option not supported for file format '%s'", fmt);
Line 299  static int img_create(int argc, char **a Line 374  static int img_create(int argc, char **a
     return 0;      return 0;
 }  }
   
   static int img_check(int argc, char **argv)
   {
       int c, ret;
       const char *filename, *fmt;
       BlockDriver *drv;
       BlockDriverState *bs;
   
       fmt = NULL;
       for(;;) {
           c = getopt(argc, argv, "f:h");
           if (c == -1)
               break;
           switch(c) {
           case 'h':
               help();
               break;
           case 'f':
               fmt = optarg;
               break;
           }
       }
       if (optind >= argc)
           help();
       filename = argv[optind++];
   
       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, BRDV_O_FLAGS, drv) < 0) {
           error("Could not open '%s'", filename);
       }
       ret = bdrv_check(bs);
       switch(ret) {
       case 0:
           printf("No errors were found on the image.\n");
           break;
       case -ENOTSUP:
           error("This image format does not support checks");
           break;
       default:
           if (ret < 0) {
               error("An error occurred during the check");
           } else {
               printf("%d errors were found on the image.\n", ret);
           }
           break;
       }
   
       bdrv_delete(bs);
       return 0;
   }
   
 static int img_commit(int argc, char **argv)  static int img_commit(int argc, char **argv)
 {  {
     int c, ret;      int c, ret;
Line 409  static int img_convert(int argc, char ** Line 543  static int img_convert(int argc, char **
     uint8_t buf[IO_BUF_SIZE];      uint8_t buf[IO_BUF_SIZE];
     const uint8_t *buf1;      const uint8_t *buf1;
     BlockDriverInfo bdi;      BlockDriverInfo bdi;
       QEMUOptionParameter *param = NULL;
       char *options = NULL;
   
     fmt = NULL;      fmt = NULL;
     out_fmt = "raw";      out_fmt = "raw";
     out_baseimg = NULL;      out_baseimg = NULL;
     flags = 0;      flags = 0;
     for(;;) {      for(;;) {
         c = getopt(argc, argv, "f:O:B:hce6");          c = getopt(argc, argv, "f:O:B:hce6o:");
         if (c == -1)          if (c == -1)
             break;              break;
         switch(c) {          switch(c) {
Line 440  static int img_convert(int argc, char ** Line 576  static int img_convert(int argc, char **
         case '6':          case '6':
             flags |= BLOCK_FLAG_COMPAT6;              flags |= BLOCK_FLAG_COMPAT6;
             break;              break;
           case 'o':
               options = optarg;
               break;
         }          }
     }      }
   
Line 464  static int img_convert(int argc, char ** Line 603  static int img_convert(int argc, char **
         total_sectors += bs_sectors;          total_sectors += bs_sectors;
     }      }
   
       /* Find driver and parse its options */
     drv = bdrv_find_format(out_fmt);      drv = bdrv_find_format(out_fmt);
     if (!drv)      if (!drv)
         error("Unknown file format '%s'", out_fmt);          error("Unknown file format '%s'", out_fmt);
     if (flags & BLOCK_FLAG_COMPRESS && drv != &bdrv_qcow && drv != &bdrv_qcow2)  
         error("Compression not supported for this file format");  
     if (flags & BLOCK_FLAG_ENCRYPT && drv != &bdrv_qcow && drv != &bdrv_qcow2)  
         error("Encryption not supported for this file format");  
     if (flags & BLOCK_FLAG_COMPAT6 && drv != &bdrv_vmdk)  
         error("Alternative compatibility level not supported for this file format");  
     if (flags & BLOCK_FLAG_ENCRYPT && flags & BLOCK_FLAG_COMPRESS)  
         error("Compression and encryption not supported at the same time");  
   
     ret = bdrv_create(drv, out_filename, total_sectors, out_baseimg, flags);      if (options && !strcmp(options, "?")) {
           print_option_help(drv->create_options);
           return 0;
       }
   
       if (options) {
           param = parse_option_parameters(options, drv->create_options, param);
           if (param == NULL) {
               error("Invalid options for file format '%s'.", out_fmt);
           }
       } else {
           param = parse_option_parameters("", drv->create_options, param);
       }
   
       set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512);
       add_old_style_options(out_fmt, param, flags, out_baseimg, NULL);
   
       /* Check if compression is supported */
       if (flags & BLOCK_FLAG_COMPRESS) {
           QEMUOptionParameter *encryption =
               get_option_parameter(param, BLOCK_OPT_ENCRYPT);
   
           if (!drv->bdrv_write_compressed) {
               error("Compression not supported for this file format");
           }
   
           if (encryption && encryption->value.n) {
               error("Compression and encryption not supported at the same time");
           }
       }
   
       /* Create the new image */
       ret = bdrv_create(drv, out_filename, param);
       free_option_parameters(param);
   
     if (ret < 0) {      if (ret < 0) {
         if (ret == -ENOTSUP) {          if (ret == -ENOTSUP) {
             error("Formatting not supported for file format '%s'", out_fmt);              error("Formatting not supported for file format '%s'", out_fmt);
Line 580  static int img_convert(int argc, char ** Line 746  static int img_convert(int argc, char **
             if (n > bs_offset + bs_sectors - sector_num)              if (n > bs_offset + bs_sectors - sector_num)
                 n = bs_offset + bs_sectors - sector_num;                  n = bs_offset + bs_sectors - sector_num;
   
             /* If the output image is being created as a copy on write image,              if (strcmp(drv->format_name, "host_device")) {
                assume that sectors which are unallocated in the input image                  /* If the output image is being created as a copy on write image,
                are present in both the output's and input's base images (no                     assume that sectors which are unallocated in the input image
                need to copy them). */                     are present in both the output's and input's base images (no
             if (out_baseimg) {                     need to copy them). */
                if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset, n, &n1)) {                  if (out_baseimg) {
                   sector_num += n1;                      if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
                   continue;                                             n, &n1)) {
                }                          sector_num += n1;
                /* The next 'n1' sectors are allocated in the input image. Copy                          continue;
                   only those as they may be followed by unallocated sectors. */                      }
                n = n1;                      /* The next 'n1' sectors are allocated in the input image. Copy
                          only those as they may be followed by unallocated sectors. */
                       n = n1;
                   }
               } else {
                   n1 = n;
             }              }
   
             if (bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n) < 0)               if (bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n) < 0) 
Line 603  static int img_convert(int argc, char ** Line 774  static int img_convert(int argc, char **
             while (n > 0) {              while (n > 0) {
                 /* If the output image is being created as a copy on write image,                  /* If the output image is being created as a copy on write image,
                    copy all sectors even the ones containing only NUL bytes,                     copy all sectors even the ones containing only NUL bytes,
                    because they may differ from the sectors in the base image. */                     because they may differ from the sectors in the base image.
                 if (out_baseimg || is_allocated_sectors(buf1, n, &n1)) {  
                      If the output is to a host device, we also write out
                      sectors that are entirely 0, since whatever data was
                      already there is garbage, not 0s. */
                   if (strcmp(drv->format_name, "host_device") == 0 || out_baseimg ||
                       is_allocated_sectors(buf1, n, &n1)) {
                     if (bdrv_write(out_bs, sector_num, buf1, n1) < 0)                      if (bdrv_write(out_bs, sector_num, buf1, n1) < 0)
                         error("error while writing");                          error("error while writing");
                 }                  }
Line 753  static int img_info(int argc, char **arg Line 929  static int img_info(int argc, char **arg
 #define SNAPSHOT_APPLY  3  #define SNAPSHOT_APPLY  3
 #define SNAPSHOT_DELETE 4  #define SNAPSHOT_DELETE 4
   
 static void img_snapshot(int argc, char **argv)  static int img_snapshot(int argc, char **argv)
 {  {
     BlockDriverState *bs;      BlockDriverState *bs;
     QEMUSnapshotInfo sn;      QEMUSnapshotInfo sn;
Line 770  static void img_snapshot(int argc, char  Line 946  static void img_snapshot(int argc, char 
         switch(c) {          switch(c) {
         case 'h':          case 'h':
             help();              help();
             return;              return 0;
         case 'l':          case 'l':
             if (action) {              if (action) {
                 help();                  help();
                 return;                  return 0;
             }              }
             action = SNAPSHOT_LIST;              action = SNAPSHOT_LIST;
             break;              break;
         case 'a':          case 'a':
             if (action) {              if (action) {
                 help();                  help();
                 return;                  return 0;
             }              }
             action = SNAPSHOT_APPLY;              action = SNAPSHOT_APPLY;
             snapshot_name = optarg;              snapshot_name = optarg;
Line 789  static void img_snapshot(int argc, char  Line 965  static void img_snapshot(int argc, char 
         case 'c':          case 'c':
             if (action) {              if (action) {
                 help();                  help();
                 return;                  return 0;
             }              }
             action = SNAPSHOT_CREATE;              action = SNAPSHOT_CREATE;
             snapshot_name = optarg;              snapshot_name = optarg;
Line 797  static void img_snapshot(int argc, char  Line 973  static void img_snapshot(int argc, char 
         case 'd':          case 'd':
             if (action) {              if (action) {
                 help();                  help();
                 return;                  return 0;
             }              }
             action = SNAPSHOT_DELETE;              action = SNAPSHOT_DELETE;
             snapshot_name = optarg;              snapshot_name = optarg;
Line 855  static void img_snapshot(int argc, char  Line 1031  static void img_snapshot(int argc, char 
   
     /* Cleanup */      /* Cleanup */
     bdrv_delete(bs);      bdrv_delete(bs);
   
       return 0;
 }  }
   
   static const img_cmd_t img_cmds[] = {
   #define DEF(option, callback, arg_string)        \
       { option, callback },
   #include "qemu-img-cmds.h"
   #undef DEF
   #undef GEN_DOCS
       { NULL, NULL, },
   };
   
 int main(int argc, char **argv)  int main(int argc, char **argv)
 {  {
     const char *cmd;      const img_cmd_t *cmd;
       const char *cmdname;
   
     bdrv_init();      bdrv_init();
     if (argc < 2)      if (argc < 2)
         help();          help();
     cmd = argv[1];      cmdname = argv[1];
     argc--; argv++;      argc--; argv++;
     if (!strcmp(cmd, "create")) {  
         img_create(argc, argv);      /* find the command */
     } else if (!strcmp(cmd, "commit")) {      for(cmd = img_cmds; cmd->name != NULL; cmd++) {
         img_commit(argc, argv);          if (!strcmp(cmdname, cmd->name)) {
     } else if (!strcmp(cmd, "convert")) {              return cmd->handler(argc, argv);
         img_convert(argc, argv);          }
     } else if (!strcmp(cmd, "info")) {  
         img_info(argc, argv);  
     } else if (!strcmp(cmd, "snapshot")) {  
         img_snapshot(argc, argv);  
     } else {  
         help();  
     }      }
   
       /* not found */
       help();
     return 0;      return 0;
 }  }

Removed from v.1.1.1.7  
changed lines
  Added in v.1.1.1.8


unix.superglobalmegacorp.com