]> Git Repo - qemu.git/blob - qemu-io-cmds.c
qemu-io: Check for trailing chars
[qemu.git] / qemu-io-cmds.c
1 /*
2  * Command line utility to exercise the QEMU I/O path.
3  *
4  * Copyright (C) 2009 Red Hat, Inc.
5  * Copyright (c) 2003-2005 Silicon Graphics, Inc.
6  *
7  * This work is licensed under the terms of the GNU GPL, version 2 or later.
8  * See the COPYING file in the top-level directory.
9  */
10
11 #include "qemu-io.h"
12 #include "sysemu/block-backend.h"
13 #include "block/block.h"
14 #include "block/block_int.h" /* for info_f() */
15 #include "block/qapi.h"
16 #include "qemu/error-report.h"
17 #include "qemu/main-loop.h"
18 #include "qemu/timer.h"
19 #include "sysemu/block-backend.h"
20
21 #define CMD_NOFILE_OK   0x01
22
23 bool qemuio_misalign;
24
25 static cmdinfo_t *cmdtab;
26 static int ncmds;
27
28 static int compare_cmdname(const void *a, const void *b)
29 {
30     return strcmp(((const cmdinfo_t *)a)->name,
31                   ((const cmdinfo_t *)b)->name);
32 }
33
34 void qemuio_add_command(const cmdinfo_t *ci)
35 {
36     cmdtab = g_renew(cmdinfo_t, cmdtab, ++ncmds);
37     cmdtab[ncmds - 1] = *ci;
38     qsort(cmdtab, ncmds, sizeof(*cmdtab), compare_cmdname);
39 }
40
41 int qemuio_command_usage(const cmdinfo_t *ci)
42 {
43     printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
44     return 0;
45 }
46
47 static int init_check_command(BlockBackend *blk, const cmdinfo_t *ct)
48 {
49     if (ct->flags & CMD_FLAG_GLOBAL) {
50         return 1;
51     }
52     if (!(ct->flags & CMD_NOFILE_OK) && !blk) {
53         fprintf(stderr, "no file open, try 'help open'\n");
54         return 0;
55     }
56     return 1;
57 }
58
59 static int command(BlockBackend *blk, const cmdinfo_t *ct, int argc,
60                    char **argv)
61 {
62     char *cmd = argv[0];
63
64     if (!init_check_command(blk, ct)) {
65         return 0;
66     }
67
68     if (argc - 1 < ct->argmin || (ct->argmax != -1 && argc - 1 > ct->argmax)) {
69         if (ct->argmax == -1) {
70             fprintf(stderr,
71                     "bad argument count %d to %s, expected at least %d arguments\n",
72                     argc-1, cmd, ct->argmin);
73         } else if (ct->argmin == ct->argmax) {
74             fprintf(stderr,
75                     "bad argument count %d to %s, expected %d arguments\n",
76                     argc-1, cmd, ct->argmin);
77         } else {
78             fprintf(stderr,
79                     "bad argument count %d to %s, expected between %d and %d arguments\n",
80                     argc-1, cmd, ct->argmin, ct->argmax);
81         }
82         return 0;
83     }
84     optind = 0;
85     return ct->cfunc(blk, argc, argv);
86 }
87
88 static const cmdinfo_t *find_command(const char *cmd)
89 {
90     cmdinfo_t *ct;
91
92     for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
93         if (strcmp(ct->name, cmd) == 0 ||
94             (ct->altname && strcmp(ct->altname, cmd) == 0))
95         {
96             return (const cmdinfo_t *)ct;
97         }
98     }
99     return NULL;
100 }
101
102 /* Invoke fn() for commands with a matching prefix */
103 void qemuio_complete_command(const char *input,
104                              void (*fn)(const char *cmd, void *opaque),
105                              void *opaque)
106 {
107     cmdinfo_t *ct;
108     size_t input_len = strlen(input);
109
110     for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
111         if (strncmp(input, ct->name, input_len) == 0) {
112             fn(ct->name, opaque);
113         }
114     }
115 }
116
117 static char **breakline(char *input, int *count)
118 {
119     int c = 0;
120     char *p;
121     char **rval = g_new0(char *, 1);
122
123     while (rval && (p = qemu_strsep(&input, " ")) != NULL) {
124         if (!*p) {
125             continue;
126         }
127         c++;
128         rval = g_renew(char *, rval, (c + 1));
129         rval[c - 1] = p;
130         rval[c] = NULL;
131     }
132     *count = c;
133     return rval;
134 }
135
136 static int64_t cvtnum(const char *s)
137 {
138     char *end;
139     int64_t ret;
140
141     ret = qemu_strtosz_suffix(s, &end, QEMU_STRTOSZ_DEFSUFFIX_B);
142     if (*end != '\0') {
143         /* Detritus at the end of the string */
144         return -EINVAL;
145     }
146     return ret;
147 }
148
149 #define EXABYTES(x)     ((long long)(x) << 60)
150 #define PETABYTES(x)    ((long long)(x) << 50)
151 #define TERABYTES(x)    ((long long)(x) << 40)
152 #define GIGABYTES(x)    ((long long)(x) << 30)
153 #define MEGABYTES(x)    ((long long)(x) << 20)
154 #define KILOBYTES(x)    ((long long)(x) << 10)
155
156 #define TO_EXABYTES(x)  ((x) / EXABYTES(1))
157 #define TO_PETABYTES(x) ((x) / PETABYTES(1))
158 #define TO_TERABYTES(x) ((x) / TERABYTES(1))
159 #define TO_GIGABYTES(x) ((x) / GIGABYTES(1))
160 #define TO_MEGABYTES(x) ((x) / MEGABYTES(1))
161 #define TO_KILOBYTES(x) ((x) / KILOBYTES(1))
162
163 static void cvtstr(double value, char *str, size_t size)
164 {
165     char *trim;
166     const char *suffix;
167
168     if (value >= EXABYTES(1)) {
169         suffix = " EiB";
170         snprintf(str, size - 4, "%.3f", TO_EXABYTES(value));
171     } else if (value >= PETABYTES(1)) {
172         suffix = " PiB";
173         snprintf(str, size - 4, "%.3f", TO_PETABYTES(value));
174     } else if (value >= TERABYTES(1)) {
175         suffix = " TiB";
176         snprintf(str, size - 4, "%.3f", TO_TERABYTES(value));
177     } else if (value >= GIGABYTES(1)) {
178         suffix = " GiB";
179         snprintf(str, size - 4, "%.3f", TO_GIGABYTES(value));
180     } else if (value >= MEGABYTES(1)) {
181         suffix = " MiB";
182         snprintf(str, size - 4, "%.3f", TO_MEGABYTES(value));
183     } else if (value >= KILOBYTES(1)) {
184         suffix = " KiB";
185         snprintf(str, size - 4, "%.3f", TO_KILOBYTES(value));
186     } else {
187         suffix = " bytes";
188         snprintf(str, size - 6, "%f", value);
189     }
190
191     trim = strstr(str, ".000");
192     if (trim) {
193         strcpy(trim, suffix);
194     } else {
195         strcat(str, suffix);
196     }
197 }
198
199
200
201 static struct timeval tsub(struct timeval t1, struct timeval t2)
202 {
203     t1.tv_usec -= t2.tv_usec;
204     if (t1.tv_usec < 0) {
205         t1.tv_usec += 1000000;
206         t1.tv_sec--;
207     }
208     t1.tv_sec -= t2.tv_sec;
209     return t1;
210 }
211
212 static double tdiv(double value, struct timeval tv)
213 {
214     return value / ((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0));
215 }
216
217 #define HOURS(sec)      ((sec) / (60 * 60))
218 #define MINUTES(sec)    (((sec) % (60 * 60)) / 60)
219 #define SECONDS(sec)    ((sec) % 60)
220
221 enum {
222     DEFAULT_TIME        = 0x0,
223     TERSE_FIXED_TIME    = 0x1,
224     VERBOSE_FIXED_TIME  = 0x2,
225 };
226
227 static void timestr(struct timeval *tv, char *ts, size_t size, int format)
228 {
229     double usec = (double)tv->tv_usec / 1000000.0;
230
231     if (format & TERSE_FIXED_TIME) {
232         if (!HOURS(tv->tv_sec)) {
233             snprintf(ts, size, "%u:%02u.%02u",
234                     (unsigned int) MINUTES(tv->tv_sec),
235                     (unsigned int) SECONDS(tv->tv_sec),
236                     (unsigned int) (usec * 100));
237             return;
238         }
239         format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */
240     }
241
242     if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) {
243         snprintf(ts, size, "%u:%02u:%02u.%02u",
244                 (unsigned int) HOURS(tv->tv_sec),
245                 (unsigned int) MINUTES(tv->tv_sec),
246                 (unsigned int) SECONDS(tv->tv_sec),
247                 (unsigned int) (usec * 100));
248     } else {
249         snprintf(ts, size, "0.%04u sec", (unsigned int) (usec * 10000));
250     }
251 }
252
253 /*
254  * Parse the pattern argument to various sub-commands.
255  *
256  * Because the pattern is used as an argument to memset it must evaluate
257  * to an unsigned integer that fits into a single byte.
258  */
259 static int parse_pattern(const char *arg)
260 {
261     char *endptr = NULL;
262     long pattern;
263
264     pattern = strtol(arg, &endptr, 0);
265     if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
266         printf("%s is not a valid pattern byte\n", arg);
267         return -1;
268     }
269
270     return pattern;
271 }
272
273 /*
274  * Memory allocation helpers.
275  *
276  * Make sure memory is aligned by default, or purposefully misaligned if
277  * that is specified on the command line.
278  */
279
280 #define MISALIGN_OFFSET     16
281 static void *qemu_io_alloc(BlockBackend *blk, size_t len, int pattern)
282 {
283     void *buf;
284
285     if (qemuio_misalign) {
286         len += MISALIGN_OFFSET;
287     }
288     buf = blk_blockalign(blk, len);
289     memset(buf, pattern, len);
290     if (qemuio_misalign) {
291         buf += MISALIGN_OFFSET;
292     }
293     return buf;
294 }
295
296 static void qemu_io_free(void *p)
297 {
298     if (qemuio_misalign) {
299         p -= MISALIGN_OFFSET;
300     }
301     qemu_vfree(p);
302 }
303
304 static void dump_buffer(const void *buffer, int64_t offset, int64_t len)
305 {
306     uint64_t i;
307     int j;
308     const uint8_t *p;
309
310     for (i = 0, p = buffer; i < len; i += 16) {
311         const uint8_t *s = p;
312
313         printf("%08" PRIx64 ":  ", offset + i);
314         for (j = 0; j < 16 && i + j < len; j++, p++) {
315             printf("%02x ", *p);
316         }
317         printf(" ");
318         for (j = 0; j < 16 && i + j < len; j++, s++) {
319             if (isalnum(*s)) {
320                 printf("%c", *s);
321             } else {
322                 printf(".");
323             }
324         }
325         printf("\n");
326     }
327 }
328
329 static void print_report(const char *op, struct timeval *t, int64_t offset,
330                          int64_t count, int64_t total, int cnt, int Cflag)
331 {
332     char s1[64], s2[64], ts[64];
333
334     timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
335     if (!Cflag) {
336         cvtstr((double)total, s1, sizeof(s1));
337         cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
338         printf("%s %"PRId64"/%"PRId64" bytes at offset %" PRId64 "\n",
339                op, total, count, offset);
340         printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
341                s1, cnt, ts, s2, tdiv((double)cnt, *t));
342     } else {/* bytes,ops,time,bytes/sec,ops/sec */
343         printf("%"PRId64",%d,%s,%.3f,%.3f\n",
344             total, cnt, ts,
345             tdiv((double)total, *t),
346             tdiv((double)cnt, *t));
347     }
348 }
349
350 /*
351  * Parse multiple length statements for vectored I/O, and construct an I/O
352  * vector matching it.
353  */
354 static void *
355 create_iovec(BlockBackend *blk, QEMUIOVector *qiov, char **argv, int nr_iov,
356              int pattern)
357 {
358     size_t *sizes = g_new0(size_t, nr_iov);
359     size_t count = 0;
360     void *buf = NULL;
361     void *p;
362     int i;
363
364     for (i = 0; i < nr_iov; i++) {
365         char *arg = argv[i];
366         int64_t len;
367
368         len = cvtnum(arg);
369         if (len < 0) {
370             printf("non-numeric length argument -- %s\n", arg);
371             goto fail;
372         }
373
374         /* should be SIZE_T_MAX, but that doesn't exist */
375         if (len > INT_MAX) {
376             printf("too large length argument -- %s\n", arg);
377             goto fail;
378         }
379
380         if (len & 0x1ff) {
381             printf("length argument %" PRId64
382                    " is not sector aligned\n", len);
383             goto fail;
384         }
385
386         sizes[i] = len;
387         count += len;
388     }
389
390     qemu_iovec_init(qiov, nr_iov);
391
392     buf = p = qemu_io_alloc(blk, count, pattern);
393
394     for (i = 0; i < nr_iov; i++) {
395         qemu_iovec_add(qiov, p, sizes[i]);
396         p += sizes[i];
397     }
398
399 fail:
400     g_free(sizes);
401     return buf;
402 }
403
404 static int do_read(BlockBackend *blk, char *buf, int64_t offset, int64_t count,
405                    int64_t *total)
406 {
407     int ret;
408
409     if (count >> 9 > INT_MAX) {
410         return -ERANGE;
411     }
412
413     ret = blk_read(blk, offset >> 9, (uint8_t *)buf, count >> 9);
414     if (ret < 0) {
415         return ret;
416     }
417     *total = count;
418     return 1;
419 }
420
421 static int do_write(BlockBackend *blk, char *buf, int64_t offset, int64_t count,
422                     int64_t *total)
423 {
424     int ret;
425
426     if (count >> 9 > INT_MAX) {
427         return -ERANGE;
428     }
429
430     ret = blk_write(blk, offset >> 9, (uint8_t *)buf, count >> 9);
431     if (ret < 0) {
432         return ret;
433     }
434     *total = count;
435     return 1;
436 }
437
438 static int do_pread(BlockBackend *blk, char *buf, int64_t offset,
439                     int64_t count, int64_t *total)
440 {
441     if (count > INT_MAX) {
442         return -ERANGE;
443     }
444
445     *total = blk_pread(blk, offset, (uint8_t *)buf, count);
446     if (*total < 0) {
447         return *total;
448     }
449     return 1;
450 }
451
452 static int do_pwrite(BlockBackend *blk, char *buf, int64_t offset,
453                      int64_t count, int64_t *total)
454 {
455     if (count > INT_MAX) {
456         return -ERANGE;
457     }
458
459     *total = blk_pwrite(blk, offset, (uint8_t *)buf, count);
460     if (*total < 0) {
461         return *total;
462     }
463     return 1;
464 }
465
466 typedef struct {
467     BlockBackend *blk;
468     int64_t offset;
469     int64_t count;
470     int64_t *total;
471     int ret;
472     bool done;
473 } CoWriteZeroes;
474
475 static void coroutine_fn co_write_zeroes_entry(void *opaque)
476 {
477     CoWriteZeroes *data = opaque;
478
479     data->ret = blk_co_write_zeroes(data->blk, data->offset / BDRV_SECTOR_SIZE,
480                                     data->count / BDRV_SECTOR_SIZE, 0);
481     data->done = true;
482     if (data->ret < 0) {
483         *data->total = data->ret;
484         return;
485     }
486
487     *data->total = data->count;
488 }
489
490 static int do_co_write_zeroes(BlockBackend *blk, int64_t offset, int64_t count,
491                               int64_t *total)
492 {
493     Coroutine *co;
494     CoWriteZeroes data = {
495         .blk    = blk,
496         .offset = offset,
497         .count  = count,
498         .total  = total,
499         .done   = false,
500     };
501
502     if (count >> BDRV_SECTOR_BITS > INT_MAX) {
503         return -ERANGE;
504     }
505
506     co = qemu_coroutine_create(co_write_zeroes_entry);
507     qemu_coroutine_enter(co, &data);
508     while (!data.done) {
509         aio_poll(blk_get_aio_context(blk), true);
510     }
511     if (data.ret < 0) {
512         return data.ret;
513     } else {
514         return 1;
515     }
516 }
517
518 static int do_write_compressed(BlockBackend *blk, char *buf, int64_t offset,
519                                int64_t count, int64_t *total)
520 {
521     int ret;
522
523     if (count >> 9 > INT_MAX) {
524         return -ERANGE;
525     }
526
527     ret = blk_write_compressed(blk, offset >> 9, (uint8_t *)buf, count >> 9);
528     if (ret < 0) {
529         return ret;
530     }
531     *total = count;
532     return 1;
533 }
534
535 static int do_load_vmstate(BlockBackend *blk, char *buf, int64_t offset,
536                            int64_t count, int64_t *total)
537 {
538     if (count > INT_MAX) {
539         return -ERANGE;
540     }
541
542     *total = blk_load_vmstate(blk, (uint8_t *)buf, offset, count);
543     if (*total < 0) {
544         return *total;
545     }
546     return 1;
547 }
548
549 static int do_save_vmstate(BlockBackend *blk, char *buf, int64_t offset,
550                            int64_t count, int64_t *total)
551 {
552     if (count > INT_MAX) {
553         return -ERANGE;
554     }
555
556     *total = blk_save_vmstate(blk, (uint8_t *)buf, offset, count);
557     if (*total < 0) {
558         return *total;
559     }
560     return 1;
561 }
562
563 #define NOT_DONE 0x7fffffff
564 static void aio_rw_done(void *opaque, int ret)
565 {
566     *(int *)opaque = ret;
567 }
568
569 static int do_aio_readv(BlockBackend *blk, QEMUIOVector *qiov,
570                         int64_t offset, int *total)
571 {
572     int async_ret = NOT_DONE;
573
574     blk_aio_readv(blk, offset >> 9, qiov, qiov->size >> 9,
575                   aio_rw_done, &async_ret);
576     while (async_ret == NOT_DONE) {
577         main_loop_wait(false);
578     }
579
580     *total = qiov->size;
581     return async_ret < 0 ? async_ret : 1;
582 }
583
584 static int do_aio_writev(BlockBackend *blk, QEMUIOVector *qiov,
585                          int64_t offset, int *total)
586 {
587     int async_ret = NOT_DONE;
588
589     blk_aio_writev(blk, offset >> 9, qiov, qiov->size >> 9,
590                    aio_rw_done, &async_ret);
591     while (async_ret == NOT_DONE) {
592         main_loop_wait(false);
593     }
594
595     *total = qiov->size;
596     return async_ret < 0 ? async_ret : 1;
597 }
598
599 struct multiwrite_async_ret {
600     int num_done;
601     int error;
602 };
603
604 static void multiwrite_cb(void *opaque, int ret)
605 {
606     struct multiwrite_async_ret *async_ret = opaque;
607
608     async_ret->num_done++;
609     if (ret < 0) {
610         async_ret->error = ret;
611     }
612 }
613
614 static int do_aio_multiwrite(BlockBackend *blk, BlockRequest* reqs,
615                              int num_reqs, int *total)
616 {
617     int i, ret;
618     struct multiwrite_async_ret async_ret = {
619         .num_done = 0,
620         .error = 0,
621     };
622
623     *total = 0;
624     for (i = 0; i < num_reqs; i++) {
625         reqs[i].cb = multiwrite_cb;
626         reqs[i].opaque = &async_ret;
627         *total += reqs[i].qiov->size;
628     }
629
630     ret = blk_aio_multiwrite(blk, reqs, num_reqs);
631     if (ret < 0) {
632         return ret;
633     }
634
635     while (async_ret.num_done < num_reqs) {
636         main_loop_wait(false);
637     }
638
639     return async_ret.error < 0 ? async_ret.error : 1;
640 }
641
642 static void read_help(void)
643 {
644     printf(
645 "\n"
646 " reads a range of bytes from the given offset\n"
647 "\n"
648 " Example:\n"
649 " 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
650 "\n"
651 " Reads a segment of the currently open file, optionally dumping it to the\n"
652 " standard output stream (with -v option) for subsequent inspection.\n"
653 " -b, -- read from the VM state rather than the virtual disk\n"
654 " -C, -- report statistics in a machine parsable format\n"
655 " -l, -- length for pattern verification (only with -P)\n"
656 " -p, -- use blk_pread to read the file\n"
657 " -P, -- use a pattern to verify read data\n"
658 " -q, -- quiet mode, do not show I/O statistics\n"
659 " -s, -- start offset for pattern verification (only with -P)\n"
660 " -v, -- dump buffer to standard output\n"
661 "\n");
662 }
663
664 static int read_f(BlockBackend *blk, int argc, char **argv);
665
666 static const cmdinfo_t read_cmd = {
667     .name       = "read",
668     .altname    = "r",
669     .cfunc      = read_f,
670     .argmin     = 2,
671     .argmax     = -1,
672     .args       = "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
673     .oneline    = "reads a number of bytes at a specified offset",
674     .help       = read_help,
675 };
676
677 static int read_f(BlockBackend *blk, int argc, char **argv)
678 {
679     struct timeval t1, t2;
680     int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
681     int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
682     int c, cnt;
683     char *buf;
684     int64_t offset;
685     int64_t count;
686     /* Some compilers get confused and warn if this is not initialized.  */
687     int64_t total = 0;
688     int pattern = 0;
689     int64_t pattern_offset = 0, pattern_count = 0;
690
691     while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != -1) {
692         switch (c) {
693         case 'b':
694             bflag = 1;
695             break;
696         case 'C':
697             Cflag = 1;
698             break;
699         case 'l':
700             lflag = 1;
701             pattern_count = cvtnum(optarg);
702             if (pattern_count < 0) {
703                 printf("non-numeric length argument -- %s\n", optarg);
704                 return 0;
705             }
706             break;
707         case 'p':
708             pflag = 1;
709             break;
710         case 'P':
711             Pflag = 1;
712             pattern = parse_pattern(optarg);
713             if (pattern < 0) {
714                 return 0;
715             }
716             break;
717         case 'q':
718             qflag = 1;
719             break;
720         case 's':
721             sflag = 1;
722             pattern_offset = cvtnum(optarg);
723             if (pattern_offset < 0) {
724                 printf("non-numeric length argument -- %s\n", optarg);
725                 return 0;
726             }
727             break;
728         case 'v':
729             vflag = 1;
730             break;
731         default:
732             return qemuio_command_usage(&read_cmd);
733         }
734     }
735
736     if (optind != argc - 2) {
737         return qemuio_command_usage(&read_cmd);
738     }
739
740     if (bflag && pflag) {
741         printf("-b and -p cannot be specified at the same time\n");
742         return 0;
743     }
744
745     offset = cvtnum(argv[optind]);
746     if (offset < 0) {
747         printf("non-numeric length argument -- %s\n", argv[optind]);
748         return 0;
749     }
750
751     optind++;
752     count = cvtnum(argv[optind]);
753     if (count < 0) {
754         printf("non-numeric length argument -- %s\n", argv[optind]);
755         return 0;
756     } else if (count > SIZE_MAX) {
757         printf("length cannot exceed %" PRIu64 ", given %s\n",
758                (uint64_t) SIZE_MAX, argv[optind]);
759         return 0;
760     }
761
762     if (!Pflag && (lflag || sflag)) {
763         return qemuio_command_usage(&read_cmd);
764     }
765
766     if (!lflag) {
767         pattern_count = count - pattern_offset;
768     }
769
770     if ((pattern_count < 0) || (pattern_count + pattern_offset > count))  {
771         printf("pattern verification range exceeds end of read data\n");
772         return 0;
773     }
774
775     if (!pflag) {
776         if (offset & 0x1ff) {
777             printf("offset %" PRId64 " is not sector aligned\n",
778                    offset);
779             return 0;
780         }
781         if (count & 0x1ff) {
782             printf("count %"PRId64" is not sector aligned\n",
783                    count);
784             return 0;
785         }
786     }
787
788     buf = qemu_io_alloc(blk, count, 0xab);
789
790     gettimeofday(&t1, NULL);
791     if (pflag) {
792         cnt = do_pread(blk, buf, offset, count, &total);
793     } else if (bflag) {
794         cnt = do_load_vmstate(blk, buf, offset, count, &total);
795     } else {
796         cnt = do_read(blk, buf, offset, count, &total);
797     }
798     gettimeofday(&t2, NULL);
799
800     if (cnt < 0) {
801         printf("read failed: %s\n", strerror(-cnt));
802         goto out;
803     }
804
805     if (Pflag) {
806         void *cmp_buf = g_malloc(pattern_count);
807         memset(cmp_buf, pattern, pattern_count);
808         if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
809             printf("Pattern verification failed at offset %"
810                    PRId64 ", %"PRId64" bytes\n",
811                    offset + pattern_offset, pattern_count);
812         }
813         g_free(cmp_buf);
814     }
815
816     if (qflag) {
817         goto out;
818     }
819
820     if (vflag) {
821         dump_buffer(buf, offset, count);
822     }
823
824     /* Finally, report back -- -C gives a parsable format */
825     t2 = tsub(t2, t1);
826     print_report("read", &t2, offset, count, total, cnt, Cflag);
827
828 out:
829     qemu_io_free(buf);
830
831     return 0;
832 }
833
834 static void readv_help(void)
835 {
836     printf(
837 "\n"
838 " reads a range of bytes from the given offset into multiple buffers\n"
839 "\n"
840 " Example:\n"
841 " 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
842 "\n"
843 " Reads a segment of the currently open file, optionally dumping it to the\n"
844 " standard output stream (with -v option) for subsequent inspection.\n"
845 " Uses multiple iovec buffers if more than one byte range is specified.\n"
846 " -C, -- report statistics in a machine parsable format\n"
847 " -P, -- use a pattern to verify read data\n"
848 " -v, -- dump buffer to standard output\n"
849 " -q, -- quiet mode, do not show I/O statistics\n"
850 "\n");
851 }
852
853 static int readv_f(BlockBackend *blk, int argc, char **argv);
854
855 static const cmdinfo_t readv_cmd = {
856     .name       = "readv",
857     .cfunc      = readv_f,
858     .argmin     = 2,
859     .argmax     = -1,
860     .args       = "[-Cqv] [-P pattern ] off len [len..]",
861     .oneline    = "reads a number of bytes at a specified offset",
862     .help       = readv_help,
863 };
864
865 static int readv_f(BlockBackend *blk, int argc, char **argv)
866 {
867     struct timeval t1, t2;
868     int Cflag = 0, qflag = 0, vflag = 0;
869     int c, cnt;
870     char *buf;
871     int64_t offset;
872     /* Some compilers get confused and warn if this is not initialized.  */
873     int total = 0;
874     int nr_iov;
875     QEMUIOVector qiov;
876     int pattern = 0;
877     int Pflag = 0;
878
879     while ((c = getopt(argc, argv, "CP:qv")) != -1) {
880         switch (c) {
881         case 'C':
882             Cflag = 1;
883             break;
884         case 'P':
885             Pflag = 1;
886             pattern = parse_pattern(optarg);
887             if (pattern < 0) {
888                 return 0;
889             }
890             break;
891         case 'q':
892             qflag = 1;
893             break;
894         case 'v':
895             vflag = 1;
896             break;
897         default:
898             return qemuio_command_usage(&readv_cmd);
899         }
900     }
901
902     if (optind > argc - 2) {
903         return qemuio_command_usage(&readv_cmd);
904     }
905
906
907     offset = cvtnum(argv[optind]);
908     if (offset < 0) {
909         printf("non-numeric length argument -- %s\n", argv[optind]);
910         return 0;
911     }
912     optind++;
913
914     if (offset & 0x1ff) {
915         printf("offset %" PRId64 " is not sector aligned\n",
916                offset);
917         return 0;
918     }
919
920     nr_iov = argc - optind;
921     buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, 0xab);
922     if (buf == NULL) {
923         return 0;
924     }
925
926     gettimeofday(&t1, NULL);
927     cnt = do_aio_readv(blk, &qiov, offset, &total);
928     gettimeofday(&t2, NULL);
929
930     if (cnt < 0) {
931         printf("readv failed: %s\n", strerror(-cnt));
932         goto out;
933     }
934
935     if (Pflag) {
936         void *cmp_buf = g_malloc(qiov.size);
937         memset(cmp_buf, pattern, qiov.size);
938         if (memcmp(buf, cmp_buf, qiov.size)) {
939             printf("Pattern verification failed at offset %"
940                    PRId64 ", %zd bytes\n", offset, qiov.size);
941         }
942         g_free(cmp_buf);
943     }
944
945     if (qflag) {
946         goto out;
947     }
948
949     if (vflag) {
950         dump_buffer(buf, offset, qiov.size);
951     }
952
953     /* Finally, report back -- -C gives a parsable format */
954     t2 = tsub(t2, t1);
955     print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
956
957 out:
958     qemu_iovec_destroy(&qiov);
959     qemu_io_free(buf);
960     return 0;
961 }
962
963 static void write_help(void)
964 {
965     printf(
966 "\n"
967 " writes a range of bytes from the given offset\n"
968 "\n"
969 " Example:\n"
970 " 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
971 "\n"
972 " Writes into a segment of the currently open file, using a buffer\n"
973 " filled with a set pattern (0xcdcdcdcd).\n"
974 " -b, -- write to the VM state rather than the virtual disk\n"
975 " -c, -- write compressed data with blk_write_compressed\n"
976 " -p, -- use blk_pwrite to write the file\n"
977 " -P, -- use different pattern to fill file\n"
978 " -C, -- report statistics in a machine parsable format\n"
979 " -q, -- quiet mode, do not show I/O statistics\n"
980 " -z, -- write zeroes using blk_co_write_zeroes\n"
981 "\n");
982 }
983
984 static int write_f(BlockBackend *blk, int argc, char **argv);
985
986 static const cmdinfo_t write_cmd = {
987     .name       = "write",
988     .altname    = "w",
989     .cfunc      = write_f,
990     .argmin     = 2,
991     .argmax     = -1,
992     .args       = "[-bcCpqz] [-P pattern ] off len",
993     .oneline    = "writes a number of bytes at a specified offset",
994     .help       = write_help,
995 };
996
997 static int write_f(BlockBackend *blk, int argc, char **argv)
998 {
999     struct timeval t1, t2;
1000     int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0;
1001     int cflag = 0;
1002     int c, cnt;
1003     char *buf = NULL;
1004     int64_t offset;
1005     int64_t count;
1006     /* Some compilers get confused and warn if this is not initialized.  */
1007     int64_t total = 0;
1008     int pattern = 0xcd;
1009
1010     while ((c = getopt(argc, argv, "bcCpP:qz")) != -1) {
1011         switch (c) {
1012         case 'b':
1013             bflag = 1;
1014             break;
1015         case 'c':
1016             cflag = 1;
1017             break;
1018         case 'C':
1019             Cflag = 1;
1020             break;
1021         case 'p':
1022             pflag = 1;
1023             break;
1024         case 'P':
1025             Pflag = 1;
1026             pattern = parse_pattern(optarg);
1027             if (pattern < 0) {
1028                 return 0;
1029             }
1030             break;
1031         case 'q':
1032             qflag = 1;
1033             break;
1034         case 'z':
1035             zflag = 1;
1036             break;
1037         default:
1038             return qemuio_command_usage(&write_cmd);
1039         }
1040     }
1041
1042     if (optind != argc - 2) {
1043         return qemuio_command_usage(&write_cmd);
1044     }
1045
1046     if (bflag + pflag + zflag > 1) {
1047         printf("-b, -p, or -z cannot be specified at the same time\n");
1048         return 0;
1049     }
1050
1051     if (zflag && Pflag) {
1052         printf("-z and -P cannot be specified at the same time\n");
1053         return 0;
1054     }
1055
1056     offset = cvtnum(argv[optind]);
1057     if (offset < 0) {
1058         printf("non-numeric length argument -- %s\n", argv[optind]);
1059         return 0;
1060     }
1061
1062     optind++;
1063     count = cvtnum(argv[optind]);
1064     if (count < 0) {
1065         printf("non-numeric length argument -- %s\n", argv[optind]);
1066         return 0;
1067     } else if (count > SIZE_MAX) {
1068         printf("length cannot exceed %" PRIu64 ", given %s\n",
1069                (uint64_t) SIZE_MAX, argv[optind]);
1070         return 0;
1071     }
1072
1073     if (!pflag) {
1074         if (offset & 0x1ff) {
1075             printf("offset %" PRId64 " is not sector aligned\n",
1076                    offset);
1077             return 0;
1078         }
1079
1080         if (count & 0x1ff) {
1081             printf("count %"PRId64" is not sector aligned\n",
1082                    count);
1083             return 0;
1084         }
1085     }
1086
1087     if (!zflag) {
1088         buf = qemu_io_alloc(blk, count, pattern);
1089     }
1090
1091     gettimeofday(&t1, NULL);
1092     if (pflag) {
1093         cnt = do_pwrite(blk, buf, offset, count, &total);
1094     } else if (bflag) {
1095         cnt = do_save_vmstate(blk, buf, offset, count, &total);
1096     } else if (zflag) {
1097         cnt = do_co_write_zeroes(blk, offset, count, &total);
1098     } else if (cflag) {
1099         cnt = do_write_compressed(blk, buf, offset, count, &total);
1100     } else {
1101         cnt = do_write(blk, buf, offset, count, &total);
1102     }
1103     gettimeofday(&t2, NULL);
1104
1105     if (cnt < 0) {
1106         printf("write failed: %s\n", strerror(-cnt));
1107         goto out;
1108     }
1109
1110     if (qflag) {
1111         goto out;
1112     }
1113
1114     /* Finally, report back -- -C gives a parsable format */
1115     t2 = tsub(t2, t1);
1116     print_report("wrote", &t2, offset, count, total, cnt, Cflag);
1117
1118 out:
1119     if (!zflag) {
1120         qemu_io_free(buf);
1121     }
1122
1123     return 0;
1124 }
1125
1126 static void
1127 writev_help(void)
1128 {
1129     printf(
1130 "\n"
1131 " writes a range of bytes from the given offset source from multiple buffers\n"
1132 "\n"
1133 " Example:\n"
1134 " 'writev 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1135 "\n"
1136 " Writes into a segment of the currently open file, using a buffer\n"
1137 " filled with a set pattern (0xcdcdcdcd).\n"
1138 " -P, -- use different pattern to fill file\n"
1139 " -C, -- report statistics in a machine parsable format\n"
1140 " -q, -- quiet mode, do not show I/O statistics\n"
1141 "\n");
1142 }
1143
1144 static int writev_f(BlockBackend *blk, int argc, char **argv);
1145
1146 static const cmdinfo_t writev_cmd = {
1147     .name       = "writev",
1148     .cfunc      = writev_f,
1149     .argmin     = 2,
1150     .argmax     = -1,
1151     .args       = "[-Cq] [-P pattern ] off len [len..]",
1152     .oneline    = "writes a number of bytes at a specified offset",
1153     .help       = writev_help,
1154 };
1155
1156 static int writev_f(BlockBackend *blk, int argc, char **argv)
1157 {
1158     struct timeval t1, t2;
1159     int Cflag = 0, qflag = 0;
1160     int c, cnt;
1161     char *buf;
1162     int64_t offset;
1163     /* Some compilers get confused and warn if this is not initialized.  */
1164     int total = 0;
1165     int nr_iov;
1166     int pattern = 0xcd;
1167     QEMUIOVector qiov;
1168
1169     while ((c = getopt(argc, argv, "CqP:")) != -1) {
1170         switch (c) {
1171         case 'C':
1172             Cflag = 1;
1173             break;
1174         case 'q':
1175             qflag = 1;
1176             break;
1177         case 'P':
1178             pattern = parse_pattern(optarg);
1179             if (pattern < 0) {
1180                 return 0;
1181             }
1182             break;
1183         default:
1184             return qemuio_command_usage(&writev_cmd);
1185         }
1186     }
1187
1188     if (optind > argc - 2) {
1189         return qemuio_command_usage(&writev_cmd);
1190     }
1191
1192     offset = cvtnum(argv[optind]);
1193     if (offset < 0) {
1194         printf("non-numeric length argument -- %s\n", argv[optind]);
1195         return 0;
1196     }
1197     optind++;
1198
1199     if (offset & 0x1ff) {
1200         printf("offset %" PRId64 " is not sector aligned\n",
1201                offset);
1202         return 0;
1203     }
1204
1205     nr_iov = argc - optind;
1206     buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, pattern);
1207     if (buf == NULL) {
1208         return 0;
1209     }
1210
1211     gettimeofday(&t1, NULL);
1212     cnt = do_aio_writev(blk, &qiov, offset, &total);
1213     gettimeofday(&t2, NULL);
1214
1215     if (cnt < 0) {
1216         printf("writev failed: %s\n", strerror(-cnt));
1217         goto out;
1218     }
1219
1220     if (qflag) {
1221         goto out;
1222     }
1223
1224     /* Finally, report back -- -C gives a parsable format */
1225     t2 = tsub(t2, t1);
1226     print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
1227 out:
1228     qemu_iovec_destroy(&qiov);
1229     qemu_io_free(buf);
1230     return 0;
1231 }
1232
1233 static void multiwrite_help(void)
1234 {
1235     printf(
1236 "\n"
1237 " writes a range of bytes from the given offset source from multiple buffers,\n"
1238 " in a batch of requests that may be merged by qemu\n"
1239 "\n"
1240 " Example:\n"
1241 " 'multiwrite 512 1k 1k ; 4k 1k'\n"
1242 "  writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n"
1243 "\n"
1244 " Writes into a segment of the currently open file, using a buffer\n"
1245 " filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n"
1246 " by one for each request contained in the multiwrite command.\n"
1247 " -P, -- use different pattern to fill file\n"
1248 " -C, -- report statistics in a machine parsable format\n"
1249 " -q, -- quiet mode, do not show I/O statistics\n"
1250 "\n");
1251 }
1252
1253 static int multiwrite_f(BlockBackend *blk, int argc, char **argv);
1254
1255 static const cmdinfo_t multiwrite_cmd = {
1256     .name       = "multiwrite",
1257     .cfunc      = multiwrite_f,
1258     .argmin     = 2,
1259     .argmax     = -1,
1260     .args       = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]",
1261     .oneline    = "issues multiple write requests at once",
1262     .help       = multiwrite_help,
1263 };
1264
1265 static int multiwrite_f(BlockBackend *blk, int argc, char **argv)
1266 {
1267     struct timeval t1, t2;
1268     int Cflag = 0, qflag = 0;
1269     int c, cnt;
1270     char **buf;
1271     int64_t offset, first_offset = 0;
1272     /* Some compilers get confused and warn if this is not initialized.  */
1273     int total = 0;
1274     int nr_iov;
1275     int nr_reqs;
1276     int pattern = 0xcd;
1277     QEMUIOVector *qiovs;
1278     int i;
1279     BlockRequest *reqs;
1280
1281     while ((c = getopt(argc, argv, "CqP:")) != -1) {
1282         switch (c) {
1283         case 'C':
1284             Cflag = 1;
1285             break;
1286         case 'q':
1287             qflag = 1;
1288             break;
1289         case 'P':
1290             pattern = parse_pattern(optarg);
1291             if (pattern < 0) {
1292                 return 0;
1293             }
1294             break;
1295         default:
1296             return qemuio_command_usage(&writev_cmd);
1297         }
1298     }
1299
1300     if (optind > argc - 2) {
1301         return qemuio_command_usage(&writev_cmd);
1302     }
1303
1304     nr_reqs = 1;
1305     for (i = optind; i < argc; i++) {
1306         if (!strcmp(argv[i], ";")) {
1307             nr_reqs++;
1308         }
1309     }
1310
1311     reqs = g_new0(BlockRequest, nr_reqs);
1312     buf = g_new0(char *, nr_reqs);
1313     qiovs = g_new(QEMUIOVector, nr_reqs);
1314
1315     for (i = 0; i < nr_reqs && optind < argc; i++) {
1316         int j;
1317
1318         /* Read the offset of the request */
1319         offset = cvtnum(argv[optind]);
1320         if (offset < 0) {
1321             printf("non-numeric offset argument -- %s\n", argv[optind]);
1322             goto out;
1323         }
1324         optind++;
1325
1326         if (offset & 0x1ff) {
1327             printf("offset %lld is not sector aligned\n",
1328                    (long long)offset);
1329             goto out;
1330         }
1331
1332         if (i == 0) {
1333             first_offset = offset;
1334         }
1335
1336         /* Read lengths for qiov entries */
1337         for (j = optind; j < argc; j++) {
1338             if (!strcmp(argv[j], ";")) {
1339                 break;
1340             }
1341         }
1342
1343         nr_iov = j - optind;
1344
1345         /* Build request */
1346         buf[i] = create_iovec(blk, &qiovs[i], &argv[optind], nr_iov, pattern);
1347         if (buf[i] == NULL) {
1348             goto out;
1349         }
1350
1351         reqs[i].qiov = &qiovs[i];
1352         reqs[i].sector = offset >> 9;
1353         reqs[i].nb_sectors = reqs[i].qiov->size >> 9;
1354
1355         optind = j + 1;
1356
1357         pattern++;
1358     }
1359
1360     /* If there were empty requests at the end, ignore them */
1361     nr_reqs = i;
1362
1363     gettimeofday(&t1, NULL);
1364     cnt = do_aio_multiwrite(blk, reqs, nr_reqs, &total);
1365     gettimeofday(&t2, NULL);
1366
1367     if (cnt < 0) {
1368         printf("aio_multiwrite failed: %s\n", strerror(-cnt));
1369         goto out;
1370     }
1371
1372     if (qflag) {
1373         goto out;
1374     }
1375
1376     /* Finally, report back -- -C gives a parsable format */
1377     t2 = tsub(t2, t1);
1378     print_report("wrote", &t2, first_offset, total, total, cnt, Cflag);
1379 out:
1380     for (i = 0; i < nr_reqs; i++) {
1381         qemu_io_free(buf[i]);
1382         if (reqs[i].qiov != NULL) {
1383             qemu_iovec_destroy(&qiovs[i]);
1384         }
1385     }
1386     g_free(buf);
1387     g_free(reqs);
1388     g_free(qiovs);
1389     return 0;
1390 }
1391
1392 struct aio_ctx {
1393     BlockBackend *blk;
1394     QEMUIOVector qiov;
1395     int64_t offset;
1396     char *buf;
1397     int qflag;
1398     int vflag;
1399     int Cflag;
1400     int Pflag;
1401     BlockAcctCookie acct;
1402     int pattern;
1403     struct timeval t1;
1404 };
1405
1406 static void aio_write_done(void *opaque, int ret)
1407 {
1408     struct aio_ctx *ctx = opaque;
1409     struct timeval t2;
1410
1411     gettimeofday(&t2, NULL);
1412
1413
1414     if (ret < 0) {
1415         printf("aio_write failed: %s\n", strerror(-ret));
1416         goto out;
1417     }
1418
1419     block_acct_done(blk_get_stats(ctx->blk), &ctx->acct);
1420
1421     if (ctx->qflag) {
1422         goto out;
1423     }
1424
1425     /* Finally, report back -- -C gives a parsable format */
1426     t2 = tsub(t2, ctx->t1);
1427     print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
1428                  ctx->qiov.size, 1, ctx->Cflag);
1429 out:
1430     qemu_io_free(ctx->buf);
1431     qemu_iovec_destroy(&ctx->qiov);
1432     g_free(ctx);
1433 }
1434
1435 static void aio_read_done(void *opaque, int ret)
1436 {
1437     struct aio_ctx *ctx = opaque;
1438     struct timeval t2;
1439
1440     gettimeofday(&t2, NULL);
1441
1442     if (ret < 0) {
1443         printf("readv failed: %s\n", strerror(-ret));
1444         goto out;
1445     }
1446
1447     if (ctx->Pflag) {
1448         void *cmp_buf = g_malloc(ctx->qiov.size);
1449
1450         memset(cmp_buf, ctx->pattern, ctx->qiov.size);
1451         if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
1452             printf("Pattern verification failed at offset %"
1453                    PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size);
1454         }
1455         g_free(cmp_buf);
1456     }
1457
1458     block_acct_done(blk_get_stats(ctx->blk), &ctx->acct);
1459
1460     if (ctx->qflag) {
1461         goto out;
1462     }
1463
1464     if (ctx->vflag) {
1465         dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
1466     }
1467
1468     /* Finally, report back -- -C gives a parsable format */
1469     t2 = tsub(t2, ctx->t1);
1470     print_report("read", &t2, ctx->offset, ctx->qiov.size,
1471                  ctx->qiov.size, 1, ctx->Cflag);
1472 out:
1473     qemu_io_free(ctx->buf);
1474     qemu_iovec_destroy(&ctx->qiov);
1475     g_free(ctx);
1476 }
1477
1478 static void aio_read_help(void)
1479 {
1480     printf(
1481 "\n"
1482 " asynchronously reads a range of bytes from the given offset\n"
1483 "\n"
1484 " Example:\n"
1485 " 'aio_read -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
1486 "\n"
1487 " Reads a segment of the currently open file, optionally dumping it to the\n"
1488 " standard output stream (with -v option) for subsequent inspection.\n"
1489 " The read is performed asynchronously and the aio_flush command must be\n"
1490 " used to ensure all outstanding aio requests have been completed.\n"
1491 " -C, -- report statistics in a machine parsable format\n"
1492 " -P, -- use a pattern to verify read data\n"
1493 " -v, -- dump buffer to standard output\n"
1494 " -q, -- quiet mode, do not show I/O statistics\n"
1495 "\n");
1496 }
1497
1498 static int aio_read_f(BlockBackend *blk, int argc, char **argv);
1499
1500 static const cmdinfo_t aio_read_cmd = {
1501     .name       = "aio_read",
1502     .cfunc      = aio_read_f,
1503     .argmin     = 2,
1504     .argmax     = -1,
1505     .args       = "[-Cqv] [-P pattern ] off len [len..]",
1506     .oneline    = "asynchronously reads a number of bytes",
1507     .help       = aio_read_help,
1508 };
1509
1510 static int aio_read_f(BlockBackend *blk, int argc, char **argv)
1511 {
1512     int nr_iov, c;
1513     struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1514
1515     ctx->blk = blk;
1516     while ((c = getopt(argc, argv, "CP:qv")) != -1) {
1517         switch (c) {
1518         case 'C':
1519             ctx->Cflag = 1;
1520             break;
1521         case 'P':
1522             ctx->Pflag = 1;
1523             ctx->pattern = parse_pattern(optarg);
1524             if (ctx->pattern < 0) {
1525                 g_free(ctx);
1526                 return 0;
1527             }
1528             break;
1529         case 'q':
1530             ctx->qflag = 1;
1531             break;
1532         case 'v':
1533             ctx->vflag = 1;
1534             break;
1535         default:
1536             g_free(ctx);
1537             return qemuio_command_usage(&aio_read_cmd);
1538         }
1539     }
1540
1541     if (optind > argc - 2) {
1542         g_free(ctx);
1543         return qemuio_command_usage(&aio_read_cmd);
1544     }
1545
1546     ctx->offset = cvtnum(argv[optind]);
1547     if (ctx->offset < 0) {
1548         printf("non-numeric length argument -- %s\n", argv[optind]);
1549         g_free(ctx);
1550         return 0;
1551     }
1552     optind++;
1553
1554     if (ctx->offset & 0x1ff) {
1555         printf("offset %" PRId64 " is not sector aligned\n",
1556                ctx->offset);
1557         g_free(ctx);
1558         return 0;
1559     }
1560
1561     nr_iov = argc - optind;
1562     ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov, 0xab);
1563     if (ctx->buf == NULL) {
1564         g_free(ctx);
1565         return 0;
1566     }
1567
1568     gettimeofday(&ctx->t1, NULL);
1569     block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size,
1570                      BLOCK_ACCT_READ);
1571     blk_aio_readv(blk, ctx->offset >> 9, &ctx->qiov,
1572                   ctx->qiov.size >> 9, aio_read_done, ctx);
1573     return 0;
1574 }
1575
1576 static void aio_write_help(void)
1577 {
1578     printf(
1579 "\n"
1580 " asynchronously writes a range of bytes from the given offset source\n"
1581 " from multiple buffers\n"
1582 "\n"
1583 " Example:\n"
1584 " 'aio_write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
1585 "\n"
1586 " Writes into a segment of the currently open file, using a buffer\n"
1587 " filled with a set pattern (0xcdcdcdcd).\n"
1588 " The write is performed asynchronously and the aio_flush command must be\n"
1589 " used to ensure all outstanding aio requests have been completed.\n"
1590 " -P, -- use different pattern to fill file\n"
1591 " -C, -- report statistics in a machine parsable format\n"
1592 " -q, -- quiet mode, do not show I/O statistics\n"
1593 "\n");
1594 }
1595
1596 static int aio_write_f(BlockBackend *blk, int argc, char **argv);
1597
1598 static const cmdinfo_t aio_write_cmd = {
1599     .name       = "aio_write",
1600     .cfunc      = aio_write_f,
1601     .argmin     = 2,
1602     .argmax     = -1,
1603     .args       = "[-Cq] [-P pattern ] off len [len..]",
1604     .oneline    = "asynchronously writes a number of bytes",
1605     .help       = aio_write_help,
1606 };
1607
1608 static int aio_write_f(BlockBackend *blk, int argc, char **argv)
1609 {
1610     int nr_iov, c;
1611     int pattern = 0xcd;
1612     struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
1613
1614     ctx->blk = blk;
1615     while ((c = getopt(argc, argv, "CqP:")) != -1) {
1616         switch (c) {
1617         case 'C':
1618             ctx->Cflag = 1;
1619             break;
1620         case 'q':
1621             ctx->qflag = 1;
1622             break;
1623         case 'P':
1624             pattern = parse_pattern(optarg);
1625             if (pattern < 0) {
1626                 g_free(ctx);
1627                 return 0;
1628             }
1629             break;
1630         default:
1631             g_free(ctx);
1632             return qemuio_command_usage(&aio_write_cmd);
1633         }
1634     }
1635
1636     if (optind > argc - 2) {
1637         g_free(ctx);
1638         return qemuio_command_usage(&aio_write_cmd);
1639     }
1640
1641     ctx->offset = cvtnum(argv[optind]);
1642     if (ctx->offset < 0) {
1643         printf("non-numeric length argument -- %s\n", argv[optind]);
1644         g_free(ctx);
1645         return 0;
1646     }
1647     optind++;
1648
1649     if (ctx->offset & 0x1ff) {
1650         printf("offset %" PRId64 " is not sector aligned\n",
1651                ctx->offset);
1652         g_free(ctx);
1653         return 0;
1654     }
1655
1656     nr_iov = argc - optind;
1657     ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov, pattern);
1658     if (ctx->buf == NULL) {
1659         g_free(ctx);
1660         return 0;
1661     }
1662
1663     gettimeofday(&ctx->t1, NULL);
1664     block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size,
1665                      BLOCK_ACCT_WRITE);
1666     blk_aio_writev(blk, ctx->offset >> 9, &ctx->qiov,
1667                    ctx->qiov.size >> 9, aio_write_done, ctx);
1668     return 0;
1669 }
1670
1671 static int aio_flush_f(BlockBackend *blk, int argc, char **argv)
1672 {
1673     blk_drain_all();
1674     return 0;
1675 }
1676
1677 static const cmdinfo_t aio_flush_cmd = {
1678     .name       = "aio_flush",
1679     .cfunc      = aio_flush_f,
1680     .oneline    = "completes all outstanding aio requests"
1681 };
1682
1683 static int flush_f(BlockBackend *blk, int argc, char **argv)
1684 {
1685     blk_flush(blk);
1686     return 0;
1687 }
1688
1689 static const cmdinfo_t flush_cmd = {
1690     .name       = "flush",
1691     .altname    = "f",
1692     .cfunc      = flush_f,
1693     .oneline    = "flush all in-core file state to disk",
1694 };
1695
1696 static int truncate_f(BlockBackend *blk, int argc, char **argv)
1697 {
1698     int64_t offset;
1699     int ret;
1700
1701     offset = cvtnum(argv[1]);
1702     if (offset < 0) {
1703         printf("non-numeric truncate argument -- %s\n", argv[1]);
1704         return 0;
1705     }
1706
1707     ret = blk_truncate(blk, offset);
1708     if (ret < 0) {
1709         printf("truncate: %s\n", strerror(-ret));
1710         return 0;
1711     }
1712
1713     return 0;
1714 }
1715
1716 static const cmdinfo_t truncate_cmd = {
1717     .name       = "truncate",
1718     .altname    = "t",
1719     .cfunc      = truncate_f,
1720     .argmin     = 1,
1721     .argmax     = 1,
1722     .args       = "off",
1723     .oneline    = "truncates the current file at the given offset",
1724 };
1725
1726 static int length_f(BlockBackend *blk, int argc, char **argv)
1727 {
1728     int64_t size;
1729     char s1[64];
1730
1731     size = blk_getlength(blk);
1732     if (size < 0) {
1733         printf("getlength: %s\n", strerror(-size));
1734         return 0;
1735     }
1736
1737     cvtstr(size, s1, sizeof(s1));
1738     printf("%s\n", s1);
1739     return 0;
1740 }
1741
1742
1743 static const cmdinfo_t length_cmd = {
1744     .name   = "length",
1745     .altname    = "l",
1746     .cfunc      = length_f,
1747     .oneline    = "gets the length of the current file",
1748 };
1749
1750
1751 static int info_f(BlockBackend *blk, int argc, char **argv)
1752 {
1753     BlockDriverState *bs = blk_bs(blk);
1754     BlockDriverInfo bdi;
1755     ImageInfoSpecific *spec_info;
1756     char s1[64], s2[64];
1757     int ret;
1758
1759     if (bs->drv && bs->drv->format_name) {
1760         printf("format name: %s\n", bs->drv->format_name);
1761     }
1762     if (bs->drv && bs->drv->protocol_name) {
1763         printf("format name: %s\n", bs->drv->protocol_name);
1764     }
1765
1766     ret = bdrv_get_info(bs, &bdi);
1767     if (ret) {
1768         return 0;
1769     }
1770
1771     cvtstr(bdi.cluster_size, s1, sizeof(s1));
1772     cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
1773
1774     printf("cluster size: %s\n", s1);
1775     printf("vm state offset: %s\n", s2);
1776
1777     spec_info = bdrv_get_specific_info(bs);
1778     if (spec_info) {
1779         printf("Format specific information:\n");
1780         bdrv_image_info_specific_dump(fprintf, stdout, spec_info);
1781         qapi_free_ImageInfoSpecific(spec_info);
1782     }
1783
1784     return 0;
1785 }
1786
1787
1788
1789 static const cmdinfo_t info_cmd = {
1790     .name       = "info",
1791     .altname    = "i",
1792     .cfunc      = info_f,
1793     .oneline    = "prints information about the current file",
1794 };
1795
1796 static void discard_help(void)
1797 {
1798     printf(
1799 "\n"
1800 " discards a range of bytes from the given offset\n"
1801 "\n"
1802 " Example:\n"
1803 " 'discard 512 1k' - discards 1 kilobyte from 512 bytes into the file\n"
1804 "\n"
1805 " Discards a segment of the currently open file.\n"
1806 " -C, -- report statistics in a machine parsable format\n"
1807 " -q, -- quiet mode, do not show I/O statistics\n"
1808 "\n");
1809 }
1810
1811 static int discard_f(BlockBackend *blk, int argc, char **argv);
1812
1813 static const cmdinfo_t discard_cmd = {
1814     .name       = "discard",
1815     .altname    = "d",
1816     .cfunc      = discard_f,
1817     .argmin     = 2,
1818     .argmax     = -1,
1819     .args       = "[-Cq] off len",
1820     .oneline    = "discards a number of bytes at a specified offset",
1821     .help       = discard_help,
1822 };
1823
1824 static int discard_f(BlockBackend *blk, int argc, char **argv)
1825 {
1826     struct timeval t1, t2;
1827     int Cflag = 0, qflag = 0;
1828     int c, ret;
1829     int64_t offset, count;
1830
1831     while ((c = getopt(argc, argv, "Cq")) != -1) {
1832         switch (c) {
1833         case 'C':
1834             Cflag = 1;
1835             break;
1836         case 'q':
1837             qflag = 1;
1838             break;
1839         default:
1840             return qemuio_command_usage(&discard_cmd);
1841         }
1842     }
1843
1844     if (optind != argc - 2) {
1845         return qemuio_command_usage(&discard_cmd);
1846     }
1847
1848     offset = cvtnum(argv[optind]);
1849     if (offset < 0) {
1850         printf("non-numeric length argument -- %s\n", argv[optind]);
1851         return 0;
1852     }
1853
1854     optind++;
1855     count = cvtnum(argv[optind]);
1856     if (count < 0) {
1857         printf("non-numeric length argument -- %s\n", argv[optind]);
1858         return 0;
1859     } else if (count >> BDRV_SECTOR_BITS > INT_MAX) {
1860         printf("length cannot exceed %"PRIu64", given %s\n",
1861                (uint64_t)INT_MAX << BDRV_SECTOR_BITS,
1862                argv[optind]);
1863         return 0;
1864     }
1865
1866     gettimeofday(&t1, NULL);
1867     ret = blk_discard(blk, offset >> BDRV_SECTOR_BITS,
1868                       count >> BDRV_SECTOR_BITS);
1869     gettimeofday(&t2, NULL);
1870
1871     if (ret < 0) {
1872         printf("discard failed: %s\n", strerror(-ret));
1873         goto out;
1874     }
1875
1876     /* Finally, report back -- -C gives a parsable format */
1877     if (!qflag) {
1878         t2 = tsub(t2, t1);
1879         print_report("discard", &t2, offset, count, count, 1, Cflag);
1880     }
1881
1882 out:
1883     return 0;
1884 }
1885
1886 static int alloc_f(BlockBackend *blk, int argc, char **argv)
1887 {
1888     BlockDriverState *bs = blk_bs(blk);
1889     int64_t offset, sector_num, nb_sectors, remaining;
1890     char s1[64];
1891     int num, ret;
1892     int64_t sum_alloc;
1893
1894     offset = cvtnum(argv[1]);
1895     if (offset < 0) {
1896         printf("non-numeric offset argument -- %s\n", argv[1]);
1897         return 0;
1898     } else if (offset & 0x1ff) {
1899         printf("offset %" PRId64 " is not sector aligned\n",
1900                offset);
1901         return 0;
1902     }
1903
1904     if (argc == 3) {
1905         nb_sectors = cvtnum(argv[2]);
1906         if (nb_sectors < 0) {
1907             printf("non-numeric length argument -- %s\n", argv[2]);
1908             return 0;
1909         } else if (nb_sectors > INT_MAX) {
1910             printf("length argument cannot exceed %d, given %s\n",
1911                    INT_MAX, argv[2]);
1912             return 0;
1913         }
1914     } else {
1915         nb_sectors = 1;
1916     }
1917
1918     remaining = nb_sectors;
1919     sum_alloc = 0;
1920     sector_num = offset >> 9;
1921     while (remaining) {
1922         ret = bdrv_is_allocated(bs, sector_num, remaining, &num);
1923         if (ret < 0) {
1924             printf("is_allocated failed: %s\n", strerror(-ret));
1925             return 0;
1926         }
1927         sector_num += num;
1928         remaining -= num;
1929         if (ret) {
1930             sum_alloc += num;
1931         }
1932         if (num == 0) {
1933             nb_sectors -= remaining;
1934             remaining = 0;
1935         }
1936     }
1937
1938     cvtstr(offset, s1, sizeof(s1));
1939
1940     printf("%"PRId64"/%"PRId64" sectors allocated at offset %s\n",
1941            sum_alloc, nb_sectors, s1);
1942     return 0;
1943 }
1944
1945 static const cmdinfo_t alloc_cmd = {
1946     .name       = "alloc",
1947     .altname    = "a",
1948     .argmin     = 1,
1949     .argmax     = 2,
1950     .cfunc      = alloc_f,
1951     .args       = "off [sectors]",
1952     .oneline    = "checks if a sector is present in the file",
1953 };
1954
1955
1956 static int map_is_allocated(BlockDriverState *bs, int64_t sector_num,
1957                             int64_t nb_sectors, int64_t *pnum)
1958 {
1959     int num, num_checked;
1960     int ret, firstret;
1961
1962     num_checked = MIN(nb_sectors, INT_MAX);
1963     ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
1964     if (ret < 0) {
1965         return ret;
1966     }
1967
1968     firstret = ret;
1969     *pnum = num;
1970
1971     while (nb_sectors > 0 && ret == firstret) {
1972         sector_num += num;
1973         nb_sectors -= num;
1974
1975         num_checked = MIN(nb_sectors, INT_MAX);
1976         ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
1977         if (ret == firstret && num) {
1978             *pnum += num;
1979         } else {
1980             break;
1981         }
1982     }
1983
1984     return firstret;
1985 }
1986
1987 static int map_f(BlockBackend *blk, int argc, char **argv)
1988 {
1989     int64_t offset;
1990     int64_t nb_sectors, total_sectors;
1991     char s1[64];
1992     int64_t num;
1993     int ret;
1994     const char *retstr;
1995
1996     offset = 0;
1997     total_sectors = blk_nb_sectors(blk);
1998     if (total_sectors < 0) {
1999         error_report("Failed to query image length: %s",
2000                      strerror(-total_sectors));
2001         return 0;
2002     }
2003
2004     nb_sectors = total_sectors;
2005
2006     do {
2007         ret = map_is_allocated(blk_bs(blk), offset, nb_sectors, &num);
2008         if (ret < 0) {
2009             error_report("Failed to get allocation status: %s", strerror(-ret));
2010             return 0;
2011         } else if (!num) {
2012             error_report("Unexpected end of image");
2013             return 0;
2014         }
2015
2016         retstr = ret ? "    allocated" : "not allocated";
2017         cvtstr(offset << 9ULL, s1, sizeof(s1));
2018         printf("[% 24" PRId64 "] % 8" PRId64 "/% 8" PRId64 " sectors %s "
2019                "at offset %s (%d)\n",
2020                offset << 9ULL, num, nb_sectors, retstr, s1, ret);
2021
2022         offset += num;
2023         nb_sectors -= num;
2024     } while (offset < total_sectors);
2025
2026     return 0;
2027 }
2028
2029 static const cmdinfo_t map_cmd = {
2030        .name           = "map",
2031        .argmin         = 0,
2032        .argmax         = 0,
2033        .cfunc          = map_f,
2034        .args           = "",
2035        .oneline        = "prints the allocated areas of a file",
2036 };
2037
2038 static void reopen_help(void)
2039 {
2040     printf(
2041 "\n"
2042 " Changes the open options of an already opened image\n"
2043 "\n"
2044 " Example:\n"
2045 " 'reopen -o lazy-refcounts=on' - activates lazy refcount writeback on a qcow2 image\n"
2046 "\n"
2047 " -r, -- Reopen the image read-only\n"
2048 " -c, -- Change the cache mode to the given value\n"
2049 " -o, -- Changes block driver options (cf. 'open' command)\n"
2050 "\n");
2051 }
2052
2053 static int reopen_f(BlockBackend *blk, int argc, char **argv);
2054
2055 static QemuOptsList reopen_opts = {
2056     .name = "reopen",
2057     .merge_lists = true,
2058     .head = QTAILQ_HEAD_INITIALIZER(reopen_opts.head),
2059     .desc = {
2060         /* no elements => accept any params */
2061         { /* end of list */ }
2062     },
2063 };
2064
2065 static const cmdinfo_t reopen_cmd = {
2066        .name           = "reopen",
2067        .argmin         = 0,
2068        .argmax         = -1,
2069        .cfunc          = reopen_f,
2070        .args           = "[-r] [-c cache] [-o options]",
2071        .oneline        = "reopens an image with new options",
2072        .help           = reopen_help,
2073 };
2074
2075 static int reopen_f(BlockBackend *blk, int argc, char **argv)
2076 {
2077     BlockDriverState *bs = blk_bs(blk);
2078     QemuOpts *qopts;
2079     QDict *opts;
2080     int c;
2081     int flags = bs->open_flags;
2082
2083     BlockReopenQueue *brq;
2084     Error *local_err = NULL;
2085
2086     while ((c = getopt(argc, argv, "c:o:r")) != -1) {
2087         switch (c) {
2088         case 'c':
2089             if (bdrv_parse_cache_flags(optarg, &flags) < 0) {
2090                 error_report("Invalid cache option: %s", optarg);
2091                 return 0;
2092             }
2093             break;
2094         case 'o':
2095             if (!qemu_opts_parse_noisily(&reopen_opts, optarg, 0)) {
2096                 qemu_opts_reset(&reopen_opts);
2097                 return 0;
2098             }
2099             break;
2100         case 'r':
2101             flags &= ~BDRV_O_RDWR;
2102             break;
2103         default:
2104             qemu_opts_reset(&reopen_opts);
2105             return qemuio_command_usage(&reopen_cmd);
2106         }
2107     }
2108
2109     if (optind != argc) {
2110         qemu_opts_reset(&reopen_opts);
2111         return qemuio_command_usage(&reopen_cmd);
2112     }
2113
2114     qopts = qemu_opts_find(&reopen_opts, NULL);
2115     opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : NULL;
2116     qemu_opts_reset(&reopen_opts);
2117
2118     brq = bdrv_reopen_queue(NULL, bs, opts, flags);
2119     bdrv_reopen_multiple(brq, &local_err);
2120     if (local_err) {
2121         error_report_err(local_err);
2122     }
2123
2124     return 0;
2125 }
2126
2127 static int break_f(BlockBackend *blk, int argc, char **argv)
2128 {
2129     int ret;
2130
2131     ret = bdrv_debug_breakpoint(blk_bs(blk), argv[1], argv[2]);
2132     if (ret < 0) {
2133         printf("Could not set breakpoint: %s\n", strerror(-ret));
2134     }
2135
2136     return 0;
2137 }
2138
2139 static int remove_break_f(BlockBackend *blk, int argc, char **argv)
2140 {
2141     int ret;
2142
2143     ret = bdrv_debug_remove_breakpoint(blk_bs(blk), argv[1]);
2144     if (ret < 0) {
2145         printf("Could not remove breakpoint %s: %s\n", argv[1], strerror(-ret));
2146     }
2147
2148     return 0;
2149 }
2150
2151 static const cmdinfo_t break_cmd = {
2152        .name           = "break",
2153        .argmin         = 2,
2154        .argmax         = 2,
2155        .cfunc          = break_f,
2156        .args           = "event tag",
2157        .oneline        = "sets a breakpoint on event and tags the stopped "
2158                          "request as tag",
2159 };
2160
2161 static const cmdinfo_t remove_break_cmd = {
2162        .name           = "remove_break",
2163        .argmin         = 1,
2164        .argmax         = 1,
2165        .cfunc          = remove_break_f,
2166        .args           = "tag",
2167        .oneline        = "remove a breakpoint by tag",
2168 };
2169
2170 static int resume_f(BlockBackend *blk, int argc, char **argv)
2171 {
2172     int ret;
2173
2174     ret = bdrv_debug_resume(blk_bs(blk), argv[1]);
2175     if (ret < 0) {
2176         printf("Could not resume request: %s\n", strerror(-ret));
2177     }
2178
2179     return 0;
2180 }
2181
2182 static const cmdinfo_t resume_cmd = {
2183        .name           = "resume",
2184        .argmin         = 1,
2185        .argmax         = 1,
2186        .cfunc          = resume_f,
2187        .args           = "tag",
2188        .oneline        = "resumes the request tagged as tag",
2189 };
2190
2191 static int wait_break_f(BlockBackend *blk, int argc, char **argv)
2192 {
2193     while (!bdrv_debug_is_suspended(blk_bs(blk), argv[1])) {
2194         aio_poll(blk_get_aio_context(blk), true);
2195     }
2196
2197     return 0;
2198 }
2199
2200 static const cmdinfo_t wait_break_cmd = {
2201        .name           = "wait_break",
2202        .argmin         = 1,
2203        .argmax         = 1,
2204        .cfunc          = wait_break_f,
2205        .args           = "tag",
2206        .oneline        = "waits for the suspension of a request",
2207 };
2208
2209 static int abort_f(BlockBackend *blk, int argc, char **argv)
2210 {
2211     abort();
2212 }
2213
2214 static const cmdinfo_t abort_cmd = {
2215        .name           = "abort",
2216        .cfunc          = abort_f,
2217        .flags          = CMD_NOFILE_OK,
2218        .oneline        = "simulate a program crash using abort(3)",
2219 };
2220
2221 static void sigraise_help(void)
2222 {
2223     printf(
2224 "\n"
2225 " raises the given signal\n"
2226 "\n"
2227 " Example:\n"
2228 " 'sigraise %i' - raises SIGTERM\n"
2229 "\n"
2230 " Invokes raise(signal), where \"signal\" is the mandatory integer argument\n"
2231 " given to sigraise.\n"
2232 "\n", SIGTERM);
2233 }
2234
2235 static int sigraise_f(BlockBackend *blk, int argc, char **argv);
2236
2237 static const cmdinfo_t sigraise_cmd = {
2238     .name       = "sigraise",
2239     .cfunc      = sigraise_f,
2240     .argmin     = 1,
2241     .argmax     = 1,
2242     .flags      = CMD_NOFILE_OK,
2243     .args       = "signal",
2244     .oneline    = "raises a signal",
2245     .help       = sigraise_help,
2246 };
2247
2248 static int sigraise_f(BlockBackend *blk, int argc, char **argv)
2249 {
2250     int64_t sig = cvtnum(argv[1]);
2251     if (sig < 0) {
2252         printf("non-numeric signal number argument -- %s\n", argv[1]);
2253         return 0;
2254     } else if (sig > NSIG) {
2255         printf("signal argument '%s' is too large to be a valid signal\n",
2256                argv[1]);
2257         return 0;
2258     }
2259
2260     /* Using raise() to kill this process does not necessarily flush all open
2261      * streams. At least stdout and stderr (although the latter should be
2262      * non-buffered anyway) should be flushed, though. */
2263     fflush(stdout);
2264     fflush(stderr);
2265
2266     raise(sig);
2267     return 0;
2268 }
2269
2270 static void sleep_cb(void *opaque)
2271 {
2272     bool *expired = opaque;
2273     *expired = true;
2274 }
2275
2276 static int sleep_f(BlockBackend *blk, int argc, char **argv)
2277 {
2278     char *endptr;
2279     long ms;
2280     struct QEMUTimer *timer;
2281     bool expired = false;
2282
2283     ms = strtol(argv[1], &endptr, 0);
2284     if (ms < 0 || *endptr != '\0') {
2285         printf("%s is not a valid number\n", argv[1]);
2286         return 0;
2287     }
2288
2289     timer = timer_new_ns(QEMU_CLOCK_HOST, sleep_cb, &expired);
2290     timer_mod(timer, qemu_clock_get_ns(QEMU_CLOCK_HOST) + SCALE_MS * ms);
2291
2292     while (!expired) {
2293         main_loop_wait(false);
2294     }
2295
2296     timer_free(timer);
2297
2298     return 0;
2299 }
2300
2301 static const cmdinfo_t sleep_cmd = {
2302        .name           = "sleep",
2303        .argmin         = 1,
2304        .argmax         = 1,
2305        .cfunc          = sleep_f,
2306        .flags          = CMD_NOFILE_OK,
2307        .oneline        = "waits for the given value in milliseconds",
2308 };
2309
2310 static void help_oneline(const char *cmd, const cmdinfo_t *ct)
2311 {
2312     if (cmd) {
2313         printf("%s ", cmd);
2314     } else {
2315         printf("%s ", ct->name);
2316         if (ct->altname) {
2317             printf("(or %s) ", ct->altname);
2318         }
2319     }
2320
2321     if (ct->args) {
2322         printf("%s ", ct->args);
2323     }
2324     printf("-- %s\n", ct->oneline);
2325 }
2326
2327 static void help_onecmd(const char *cmd, const cmdinfo_t *ct)
2328 {
2329     help_oneline(cmd, ct);
2330     if (ct->help) {
2331         ct->help();
2332     }
2333 }
2334
2335 static void help_all(void)
2336 {
2337     const cmdinfo_t *ct;
2338
2339     for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
2340         help_oneline(ct->name, ct);
2341     }
2342     printf("\nUse 'help commandname' for extended help.\n");
2343 }
2344
2345 static int help_f(BlockBackend *blk, int argc, char **argv)
2346 {
2347     const cmdinfo_t *ct;
2348
2349     if (argc == 1) {
2350         help_all();
2351         return 0;
2352     }
2353
2354     ct = find_command(argv[1]);
2355     if (ct == NULL) {
2356         printf("command %s not found\n", argv[1]);
2357         return 0;
2358     }
2359
2360     help_onecmd(argv[1], ct);
2361     return 0;
2362 }
2363
2364 static const cmdinfo_t help_cmd = {
2365     .name       = "help",
2366     .altname    = "?",
2367     .cfunc      = help_f,
2368     .argmin     = 0,
2369     .argmax     = 1,
2370     .flags      = CMD_FLAG_GLOBAL,
2371     .args       = "[command]",
2372     .oneline    = "help for one or all commands",
2373 };
2374
2375 bool qemuio_command(BlockBackend *blk, const char *cmd)
2376 {
2377     char *input;
2378     const cmdinfo_t *ct;
2379     char **v;
2380     int c;
2381     bool done = false;
2382
2383     input = g_strdup(cmd);
2384     v = breakline(input, &c);
2385     if (c) {
2386         ct = find_command(v[0]);
2387         if (ct) {
2388             done = command(blk, ct, c, v);
2389         } else {
2390             fprintf(stderr, "command \"%s\" not found\n", v[0]);
2391         }
2392     }
2393     g_free(input);
2394     g_free(v);
2395
2396     return done;
2397 }
2398
2399 static void __attribute((constructor)) init_qemuio_commands(void)
2400 {
2401     /* initialize commands */
2402     qemuio_add_command(&help_cmd);
2403     qemuio_add_command(&read_cmd);
2404     qemuio_add_command(&readv_cmd);
2405     qemuio_add_command(&write_cmd);
2406     qemuio_add_command(&writev_cmd);
2407     qemuio_add_command(&multiwrite_cmd);
2408     qemuio_add_command(&aio_read_cmd);
2409     qemuio_add_command(&aio_write_cmd);
2410     qemuio_add_command(&aio_flush_cmd);
2411     qemuio_add_command(&flush_cmd);
2412     qemuio_add_command(&truncate_cmd);
2413     qemuio_add_command(&length_cmd);
2414     qemuio_add_command(&info_cmd);
2415     qemuio_add_command(&discard_cmd);
2416     qemuio_add_command(&alloc_cmd);
2417     qemuio_add_command(&map_cmd);
2418     qemuio_add_command(&reopen_cmd);
2419     qemuio_add_command(&break_cmd);
2420     qemuio_add_command(&remove_break_cmd);
2421     qemuio_add_command(&resume_cmd);
2422     qemuio_add_command(&wait_break_cmd);
2423     qemuio_add_command(&abort_cmd);
2424     qemuio_add_command(&sleep_cmd);
2425     qemuio_add_command(&sigraise_cmd);
2426 }
This page took 0.154161 seconds and 4 git commands to generate.