ia64/xen-unstable

view tools/ioemu/qemu-img.c @ 6946:e703abaf6e3d

Add behaviour to the remove methods to remove the transaction's path itself. This allows us to write Remove(path) to remove the specified path rather than having to slice the path ourselves.
author emellor@ewan
date Sun Sep 18 14:42:13 2005 +0100 (2005-09-18)
parents 8e5fc5fe636c
children f7b43e5c42b9
line source
1 /*
2 * create a COW disk image
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24 #include "vl.h"
26 void *get_mmap_addr(unsigned long size)
27 {
28 return NULL;
29 }
31 void qemu_free(void *ptr)
32 {
33 free(ptr);
34 }
36 void *qemu_malloc(size_t size)
37 {
38 return malloc(size);
39 }
41 void *qemu_mallocz(size_t size)
42 {
43 void *ptr;
44 ptr = qemu_malloc(size);
45 if (!ptr)
46 return NULL;
47 memset(ptr, 0, size);
48 return ptr;
49 }
51 char *qemu_strdup(const char *str)
52 {
53 char *ptr;
54 ptr = qemu_malloc(strlen(str) + 1);
55 if (!ptr)
56 return NULL;
57 strcpy(ptr, str);
58 return ptr;
59 }
61 void pstrcpy(char *buf, int buf_size, const char *str)
62 {
63 int c;
64 char *q = buf;
66 if (buf_size <= 0)
67 return;
69 for(;;) {
70 c = *str++;
71 if (c == 0 || q >= buf + buf_size - 1)
72 break;
73 *q++ = c;
74 }
75 *q = '\0';
76 }
78 /* strcat and truncate. */
79 char *pstrcat(char *buf, int buf_size, const char *s)
80 {
81 int len;
82 len = strlen(buf);
83 if (len < buf_size)
84 pstrcpy(buf + len, buf_size - len, s);
85 return buf;
86 }
88 int strstart(const char *str, const char *val, const char **ptr)
89 {
90 const char *p, *q;
91 p = str;
92 q = val;
93 while (*q != '\0') {
94 if (*p != *q)
95 return 0;
96 p++;
97 q++;
98 }
99 if (ptr)
100 *ptr = p;
101 return 1;
102 }
104 void term_printf(const char *fmt, ...)
105 {
106 va_list ap;
107 va_start(ap, fmt);
108 vprintf(fmt, ap);
109 va_end(ap);
110 }
112 void __attribute__((noreturn)) error(const char *fmt, ...)
113 {
114 va_list ap;
115 va_start(ap, fmt);
116 fprintf(stderr, "qemu-img: ");
117 vfprintf(stderr, fmt, ap);
118 fprintf(stderr, "\n");
119 exit(1);
120 va_end(ap);
121 }
123 static void format_print(void *opaque, const char *name)
124 {
125 printf(" %s", name);
126 }
128 void help(void)
129 {
130 printf("qemu-img version " QEMU_VERSION ", Copyright (c) 2004 Fabrice Bellard\n"
131 "usage: qemu-img command [command options]\n"
132 "QEMU disk image utility\n"
133 "\n"
134 "Command syntax:\n"
135 " create [-e] [-b base_image] [-f fmt] filename [size]\n"
136 " commit [-f fmt] filename\n"
137 " convert [-c] [-e] [-f fmt] filename [-O output_fmt] output_filename\n"
138 " info [-f fmt] filename\n"
139 "\n"
140 "Command parameters:\n"
141 " 'filename' is a disk image filename\n"
142 " 'base_image' is the read-only disk image which is used as base for a copy on\n"
143 " write image; the copy on write image only stores the modified data\n"
144 " 'fmt' is the disk image format. It is guessed automatically in most cases\n"
145 " 'size' is the disk image size in kilobytes. Optional suffixes 'M' (megabyte)\n"
146 " and 'G' (gigabyte) are supported\n"
147 " 'output_filename' is the destination disk image filename\n"
148 " 'output_fmt' is the destination format\n"
149 " '-c' indicates that target image must be compressed (qcow format only)\n"
150 " '-e' indicates that the target image must be encrypted (qcow format only)\n"
151 );
152 printf("\nSupported format:");
153 bdrv_iterate_format(format_print, NULL);
154 printf("\n");
155 exit(1);
156 }
159 #define NB_SUFFIXES 4
161 static void get_human_readable_size(char *buf, int buf_size, int64_t size)
162 {
163 char suffixes[NB_SUFFIXES] = "KMGT";
164 int64_t base;
165 int i;
167 if (size <= 999) {
168 snprintf(buf, buf_size, "%lld", size);
169 } else {
170 base = 1024;
171 for(i = 0; i < NB_SUFFIXES; i++) {
172 if (size < (10 * base)) {
173 snprintf(buf, buf_size, "%0.1f%c",
174 (double)size / base,
175 suffixes[i]);
176 break;
177 } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) {
178 snprintf(buf, buf_size, "%lld%c",
179 (size + (base >> 1)) / base,
180 suffixes[i]);
181 break;
182 }
183 base = base * 1024;
184 }
185 }
186 }
188 #if defined(WIN32)
189 /* XXX: put correct support for win32 */
190 static int read_password(char *buf, int buf_size)
191 {
192 int c, i;
193 printf("Password: ");
194 fflush(stdout);
195 i = 0;
196 for(;;) {
197 c = getchar();
198 if (c == '\n')
199 break;
200 if (i < (buf_size - 1))
201 buf[i++] = c;
202 }
203 buf[i] = '\0';
204 return 0;
205 }
207 #else
209 #include <termios.h>
211 static struct termios oldtty;
213 static void term_exit(void)
214 {
215 tcsetattr (0, TCSANOW, &oldtty);
216 }
218 static void term_init(void)
219 {
220 struct termios tty;
222 tcgetattr (0, &tty);
223 oldtty = tty;
225 tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
226 |INLCR|IGNCR|ICRNL|IXON);
227 tty.c_oflag |= OPOST;
228 tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
229 tty.c_cflag &= ~(CSIZE|PARENB);
230 tty.c_cflag |= CS8;
231 tty.c_cc[VMIN] = 1;
232 tty.c_cc[VTIME] = 0;
234 tcsetattr (0, TCSANOW, &tty);
236 atexit(term_exit);
237 }
239 int read_password(char *buf, int buf_size)
240 {
241 uint8_t ch;
242 int i, ret;
244 printf("password: ");
245 fflush(stdout);
246 term_init();
247 i = 0;
248 for(;;) {
249 ret = read(0, &ch, 1);
250 if (ret == -1) {
251 if (errno == EAGAIN || errno == EINTR) {
252 continue;
253 } else {
254 ret = -1;
255 break;
256 }
257 } else if (ret == 0) {
258 ret = -1;
259 break;
260 } else {
261 if (ch == '\r') {
262 ret = 0;
263 break;
264 }
265 if (i < (buf_size - 1))
266 buf[i++] = ch;
267 }
268 }
269 term_exit();
270 buf[i] = '\0';
271 printf("\n");
272 return ret;
273 }
274 #endif
276 static BlockDriverState *bdrv_new_open(const char *filename,
277 const char *fmt)
278 {
279 BlockDriverState *bs;
280 BlockDriver *drv;
281 char password[256];
283 bs = bdrv_new("");
284 if (!bs)
285 error("Not enough memory");
286 if (fmt) {
287 drv = bdrv_find_format(fmt);
288 if (!drv)
289 error("Unknown file format '%s'", fmt);
290 } else {
291 drv = NULL;
292 }
293 if (bdrv_open2(bs, filename, 0, drv) < 0) {
294 error("Could not open '%s'", filename);
295 }
296 if (bdrv_is_encrypted(bs)) {
297 printf("Disk image '%s' is encrypted.\n", filename);
298 if (read_password(password, sizeof(password)) < 0)
299 error("No password given");
300 if (bdrv_set_key(bs, password) < 0)
301 error("invalid password");
302 }
303 return bs;
304 }
306 static int img_create(int argc, char **argv)
307 {
308 int c, ret, encrypted;
309 const char *fmt = "raw";
310 const char *filename;
311 const char *base_filename = NULL;
312 int64_t size;
313 const char *p;
314 BlockDriver *drv;
316 encrypted = 0;
317 for(;;) {
318 c = getopt(argc, argv, "b:f:he");
319 if (c == -1)
320 break;
321 switch(c) {
322 case 'h':
323 help();
324 break;
325 case 'b':
326 base_filename = optarg;
327 break;
328 case 'f':
329 fmt = optarg;
330 break;
331 case 'e':
332 encrypted = 1;
333 break;
334 }
335 }
336 if (optind >= argc)
337 help();
338 filename = argv[optind++];
339 size = 0;
340 if (base_filename) {
341 BlockDriverState *bs;
342 bs = bdrv_new_open(base_filename, NULL);
343 bdrv_get_geometry(bs, &size);
344 size *= 512;
345 bdrv_delete(bs);
346 } else {
347 if (optind >= argc)
348 help();
349 p = argv[optind];
350 size = strtoul(p, (char **)&p, 0);
351 if (*p == 'M') {
352 size *= 1024 * 1024;
353 } else if (*p == 'G') {
354 size *= 1024 * 1024 * 1024;
355 } else if (*p == 'k' || *p == 'K' || *p == '\0') {
356 size *= 1024;
357 } else {
358 help();
359 }
360 }
361 drv = bdrv_find_format(fmt);
362 if (!drv)
363 error("Unknown file format '%s'", fmt);
364 printf("Formating '%s', fmt=%s",
365 filename, fmt);
366 if (encrypted)
367 printf(", encrypted");
368 if (base_filename) {
369 printf(", backing_file=%s",
370 base_filename);
371 }
372 printf(", size=%lld kB\n", size / 1024);
373 ret = bdrv_create(drv, filename, size / 512, base_filename, encrypted);
374 if (ret < 0) {
375 if (ret == -ENOTSUP) {
376 error("Formatting or formatting option not supported for file format '%s'", fmt);
377 } else {
378 error("Error while formatting");
379 }
380 }
381 return 0;
382 }
384 static int img_commit(int argc, char **argv)
385 {
386 int c, ret;
387 const char *filename, *fmt;
388 BlockDriver *drv;
389 BlockDriverState *bs;
391 fmt = NULL;
392 for(;;) {
393 c = getopt(argc, argv, "f:h");
394 if (c == -1)
395 break;
396 switch(c) {
397 case 'h':
398 help();
399 break;
400 case 'f':
401 fmt = optarg;
402 break;
403 }
404 }
405 if (optind >= argc)
406 help();
407 filename = argv[optind++];
409 bs = bdrv_new("");
410 if (!bs)
411 error("Not enough memory");
412 if (fmt) {
413 drv = bdrv_find_format(fmt);
414 if (!drv)
415 error("Unknown file format '%s'", fmt);
416 } else {
417 drv = NULL;
418 }
419 if (bdrv_open2(bs, filename, 0, drv) < 0) {
420 error("Could not open '%s'", filename);
421 }
422 ret = bdrv_commit(bs);
423 switch(ret) {
424 case 0:
425 printf("Image committed.\n");
426 break;
427 case -ENOENT:
428 error("No disk inserted");
429 break;
430 case -EACCES:
431 error("Image is read-only");
432 break;
433 case -ENOTSUP:
434 error("Image is already committed");
435 break;
436 default:
437 error("Error while committing image");
438 break;
439 }
441 bdrv_delete(bs);
442 return 0;
443 }
445 static int is_not_zero(const uint8_t *sector, int len)
446 {
447 int i;
448 len >>= 2;
449 for(i = 0;i < len; i++) {
450 if (((uint32_t *)sector)[i] != 0)
451 return 1;
452 }
453 return 0;
454 }
456 static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum)
457 {
458 int v, i;
460 if (n <= 0) {
461 *pnum = 0;
462 return 0;
463 }
464 v = is_not_zero(buf, 512);
465 for(i = 1; i < n; i++) {
466 buf += 512;
467 if (v != is_not_zero(buf, 512))
468 break;
469 }
470 *pnum = i;
471 return v;
472 }
474 #define IO_BUF_SIZE 65536
476 static int img_convert(int argc, char **argv)
477 {
478 int c, ret, n, n1, compress, cluster_size, cluster_sectors, encrypt;
479 const char *filename, *fmt, *out_fmt, *out_filename;
480 BlockDriver *drv;
481 BlockDriverState *bs, *out_bs;
482 int64_t total_sectors, nb_sectors, sector_num;
483 uint8_t buf[IO_BUF_SIZE];
484 const uint8_t *buf1;
486 fmt = NULL;
487 out_fmt = "raw";
488 compress = 0;
489 encrypt = 0;
490 for(;;) {
491 c = getopt(argc, argv, "f:O:hce");
492 if (c == -1)
493 break;
494 switch(c) {
495 case 'h':
496 help();
497 break;
498 case 'f':
499 fmt = optarg;
500 break;
501 case 'O':
502 out_fmt = optarg;
503 break;
504 case 'c':
505 compress = 1;
506 break;
507 case 'e':
508 encrypt = 1;
509 break;
510 }
511 }
512 if (optind >= argc)
513 help();
514 filename = argv[optind++];
515 if (optind >= argc)
516 help();
517 out_filename = argv[optind++];
519 bs = bdrv_new_open(filename, fmt);
521 drv = bdrv_find_format(out_fmt);
522 if (!drv)
523 error("Unknown file format '%s'", fmt);
524 if (compress && drv != &bdrv_qcow)
525 error("Compression not supported for this file format");
526 if (encrypt && drv != &bdrv_qcow)
527 error("Encryption not supported for this file format");
528 if (compress && encrypt)
529 error("Compression and encryption not supported at the same time");
530 bdrv_get_geometry(bs, &total_sectors);
531 ret = bdrv_create(drv, out_filename, total_sectors, NULL, encrypt);
532 if (ret < 0) {
533 if (ret == -ENOTSUP) {
534 error("Formatting not supported for file format '%s'", fmt);
535 } else {
536 error("Error while formatting '%s'", out_filename);
537 }
538 }
540 out_bs = bdrv_new_open(out_filename, out_fmt);
542 if (compress) {
543 cluster_size = qcow_get_cluster_size(out_bs);
544 if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE)
545 error("invalid cluster size");
546 cluster_sectors = cluster_size >> 9;
547 sector_num = 0;
548 for(;;) {
549 nb_sectors = total_sectors - sector_num;
550 if (nb_sectors <= 0)
551 break;
552 if (nb_sectors >= cluster_sectors)
553 n = cluster_sectors;
554 else
555 n = nb_sectors;
556 if (bdrv_read(bs, sector_num, buf, n) < 0)
557 error("error while reading");
558 if (n < cluster_sectors)
559 memset(buf + n * 512, 0, cluster_size - n * 512);
560 if (is_not_zero(buf, cluster_size)) {
561 if (qcow_compress_cluster(out_bs, sector_num, buf) != 0)
562 error("error while compressing sector %lld", sector_num);
563 }
564 sector_num += n;
565 }
566 } else {
567 sector_num = 0;
568 for(;;) {
569 nb_sectors = total_sectors - sector_num;
570 if (nb_sectors <= 0)
571 break;
572 if (nb_sectors >= (IO_BUF_SIZE / 512))
573 n = (IO_BUF_SIZE / 512);
574 else
575 n = nb_sectors;
576 if (bdrv_read(bs, sector_num, buf, n) < 0)
577 error("error while reading");
578 /* NOTE: at the same time we convert, we do not write zero
579 sectors to have a chance to compress the image. Ideally, we
580 should add a specific call to have the info to go faster */
581 buf1 = buf;
582 while (n > 0) {
583 if (is_allocated_sectors(buf1, n, &n1)) {
584 if (bdrv_write(out_bs, sector_num, buf1, n1) < 0)
585 error("error while writing");
586 }
587 sector_num += n1;
588 n -= n1;
589 buf1 += n1 * 512;
590 }
591 }
592 }
593 bdrv_delete(out_bs);
594 bdrv_delete(bs);
595 return 0;
596 }
598 #ifdef _WIN32
599 static int64_t get_allocated_file_size(const char *filename)
600 {
601 struct _stati64 st;
602 if (_stati64(filename, &st) < 0)
603 return -1;
604 return st.st_size;
605 }
606 #else
607 static int64_t get_allocated_file_size(const char *filename)
608 {
609 struct stat st;
610 if (stat(filename, &st) < 0)
611 return -1;
612 return (int64_t)st.st_blocks * 512;
613 }
614 #endif
616 static int img_info(int argc, char **argv)
617 {
618 int c;
619 const char *filename, *fmt;
620 BlockDriver *drv;
621 BlockDriverState *bs;
622 char fmt_name[128], size_buf[128], dsize_buf[128];
623 int64_t total_sectors, allocated_size;
625 fmt = NULL;
626 for(;;) {
627 c = getopt(argc, argv, "f:h");
628 if (c == -1)
629 break;
630 switch(c) {
631 case 'h':
632 help();
633 break;
634 case 'f':
635 fmt = optarg;
636 break;
637 }
638 }
639 if (optind >= argc)
640 help();
641 filename = argv[optind++];
643 bs = bdrv_new("");
644 if (!bs)
645 error("Not enough memory");
646 if (fmt) {
647 drv = bdrv_find_format(fmt);
648 if (!drv)
649 error("Unknown file format '%s'", fmt);
650 } else {
651 drv = NULL;
652 }
653 if (bdrv_open2(bs, filename, 0, drv) < 0) {
654 error("Could not open '%s'", filename);
655 }
656 bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
657 bdrv_get_geometry(bs, &total_sectors);
658 get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
659 allocated_size = get_allocated_file_size(filename);
660 if (allocated_size < 0)
661 error("Could not get file size '%s'", filename);
662 get_human_readable_size(dsize_buf, sizeof(dsize_buf),
663 allocated_size);
664 printf("image: %s\n"
665 "file format: %s\n"
666 "virtual size: %s (%lld bytes)\n"
667 "disk size: %s\n",
668 filename, fmt_name, size_buf,
669 total_sectors * 512,
670 dsize_buf);
671 if (bdrv_is_encrypted(bs))
672 printf("encrypted: yes\n");
673 bdrv_delete(bs);
674 return 0;
675 }
677 int main(int argc, char **argv)
678 {
679 const char *cmd;
681 bdrv_init();
682 if (argc < 2)
683 help();
684 cmd = argv[1];
685 optind++;
686 if (!strcmp(cmd, "create")) {
687 img_create(argc, argv);
688 } else if (!strcmp(cmd, "commit")) {
689 img_commit(argc, argv);
690 } else if (!strcmp(cmd, "convert")) {
691 img_convert(argc, argv);
692 } else if (!strcmp(cmd, "info")) {
693 img_info(argc, argv);
694 } else {
695 help();
696 }
697 return 0;
698 }