1e3aff4f6Saliguori /* 2e3aff4f6Saliguori * Command line utility to exercise the QEMU I/O path. 3e3aff4f6Saliguori * 4e3aff4f6Saliguori * Copyright (C) 2009 Red Hat, Inc. 5e3aff4f6Saliguori * Copyright (c) 2003-2005 Silicon Graphics, Inc. 6e3aff4f6Saliguori * 7e3aff4f6Saliguori * This work is licensed under the terms of the GNU GPL, version 2 or later. 8e3aff4f6Saliguori * See the COPYING file in the top-level directory. 9e3aff4f6Saliguori */ 10c32d766aSStefan Weil #include <sys/time.h> 11e3aff4f6Saliguori #include <sys/types.h> 12e3aff4f6Saliguori #include <stdarg.h> 13e3aff4f6Saliguori #include <stdio.h> 14e3aff4f6Saliguori #include <getopt.h> 15c32d766aSStefan Weil #include <libgen.h> 16e3aff4f6Saliguori 173d21994fSKevin Wolf #include "qemu-io.h" 181de7afc9SPaolo Bonzini #include "qemu/main-loop.h" 19b543c5cdSMax Reitz #include "qemu/option.h" 20b543c5cdSMax Reitz #include "qemu/config-file.h" 210cf17e18SStefan Hajnoczi #include "qemu/readline.h" 22737e150eSPaolo Bonzini #include "block/block_int.h" 23d7bb72c8SStefan Hajnoczi #include "trace/control.h" 24e3aff4f6Saliguori 25e3aff4f6Saliguori #define CMD_NOFILE_OK 0x01 26e3aff4f6Saliguori 27f9883880SStefan Weil static char *progname; 28e3aff4f6Saliguori 29f9883880SStefan Weil static BlockDriverState *qemuio_bs; 30191c2890SKevin Wolf 31d1174f13SKevin Wolf /* qemu-io commands passed using -c */ 32d1174f13SKevin Wolf static int ncmdline; 33d1174f13SKevin Wolf static char **cmdline; 34d1174f13SKevin Wolf 350cf17e18SStefan Hajnoczi static ReadLineState *readline_state; 360cf17e18SStefan Hajnoczi 37734c3b85SKevin Wolf static int close_f(BlockDriverState *bs, int argc, char **argv) 38e3aff4f6Saliguori { 394f6fd349SFam Zheng bdrv_unref(bs); 40734c3b85SKevin Wolf qemuio_bs = NULL; 41e3aff4f6Saliguori return 0; 42e3aff4f6Saliguori } 43e3aff4f6Saliguori 44e3aff4f6Saliguori static const cmdinfo_t close_cmd = { 45e3aff4f6Saliguori .name = "close", 46e3aff4f6Saliguori .altname = "c", 47e3aff4f6Saliguori .cfunc = close_f, 48e3aff4f6Saliguori .oneline = "close the current open file", 49e3aff4f6Saliguori }; 50e3aff4f6Saliguori 51b543c5cdSMax Reitz static int openfile(char *name, int flags, int growable, QDict *opts) 52e3aff4f6Saliguori { 5334b5d2c6SMax Reitz Error *local_err = NULL; 5434b5d2c6SMax Reitz 55734c3b85SKevin Wolf if (qemuio_bs) { 56e3aff4f6Saliguori fprintf(stderr, "file open already, try 'help close'\n"); 57e3aff4f6Saliguori return 1; 58e3aff4f6Saliguori } 59e3aff4f6Saliguori 606db95603SChristoph Hellwig if (growable) { 612e40134bSMax Reitz if (bdrv_open(&qemuio_bs, name, NULL, opts, flags | BDRV_O_PROTOCOL, 622e40134bSMax Reitz NULL, &local_err)) 632e40134bSMax Reitz { 6434b5d2c6SMax Reitz fprintf(stderr, "%s: can't open device %s: %s\n", progname, name, 6534b5d2c6SMax Reitz error_get_pretty(local_err)); 6634b5d2c6SMax Reitz error_free(local_err); 676db95603SChristoph Hellwig return 1; 686db95603SChristoph Hellwig } 696db95603SChristoph Hellwig } else { 70734c3b85SKevin Wolf qemuio_bs = bdrv_new("hda"); 71e3aff4f6Saliguori 72ddf5636dSMax Reitz if (bdrv_open(&qemuio_bs, name, NULL, opts, flags, NULL, &local_err) 73ddf5636dSMax Reitz < 0) 74ddf5636dSMax Reitz { 7534b5d2c6SMax Reitz fprintf(stderr, "%s: can't open device %s: %s\n", progname, name, 7634b5d2c6SMax Reitz error_get_pretty(local_err)); 7734b5d2c6SMax Reitz error_free(local_err); 784f6fd349SFam Zheng bdrv_unref(qemuio_bs); 79734c3b85SKevin Wolf qemuio_bs = NULL; 80e3aff4f6Saliguori return 1; 81e3aff4f6Saliguori } 829c4bab26SChristoph Hellwig } 836db95603SChristoph Hellwig 84e3aff4f6Saliguori return 0; 85e3aff4f6Saliguori } 86e3aff4f6Saliguori 8743642b38SDevin Nakamura static void open_help(void) 88e3aff4f6Saliguori { 89e3aff4f6Saliguori printf( 90e3aff4f6Saliguori "\n" 91e3aff4f6Saliguori " opens a new file in the requested mode\n" 92e3aff4f6Saliguori "\n" 93e3aff4f6Saliguori " Example:\n" 94e3aff4f6Saliguori " 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n" 95e3aff4f6Saliguori "\n" 96e3aff4f6Saliguori " Opens a file for subsequent use by all of the other qemu-io commands.\n" 97e3aff4f6Saliguori " -r, -- open file read-only\n" 98e3aff4f6Saliguori " -s, -- use snapshot file\n" 99e3aff4f6Saliguori " -n, -- disable host cache\n" 100b543c5cdSMax Reitz " -g, -- allow file to grow (only applies to protocols)\n" 101b543c5cdSMax Reitz " -o, -- options to be given to the block driver" 102e3aff4f6Saliguori "\n"); 103e3aff4f6Saliguori } 104e3aff4f6Saliguori 105734c3b85SKevin Wolf static int open_f(BlockDriverState *bs, int argc, char **argv); 10622a2bdcbSBlue Swirl 10722a2bdcbSBlue Swirl static const cmdinfo_t open_cmd = { 10822a2bdcbSBlue Swirl .name = "open", 10922a2bdcbSBlue Swirl .altname = "o", 11022a2bdcbSBlue Swirl .cfunc = open_f, 11122a2bdcbSBlue Swirl .argmin = 1, 11222a2bdcbSBlue Swirl .argmax = -1, 11322a2bdcbSBlue Swirl .flags = CMD_NOFILE_OK, 114b543c5cdSMax Reitz .args = "[-Crsn] [-o options] [path]", 11522a2bdcbSBlue Swirl .oneline = "open the file specified by path", 11622a2bdcbSBlue Swirl .help = open_help, 11722a2bdcbSBlue Swirl }; 118e3aff4f6Saliguori 119b543c5cdSMax Reitz static QemuOptsList empty_opts = { 120b543c5cdSMax Reitz .name = "drive", 121b543c5cdSMax Reitz .head = QTAILQ_HEAD_INITIALIZER(empty_opts.head), 122b543c5cdSMax Reitz .desc = { 123b543c5cdSMax Reitz /* no elements => accept any params */ 124b543c5cdSMax Reitz { /* end of list */ } 125b543c5cdSMax Reitz }, 126b543c5cdSMax Reitz }; 127b543c5cdSMax Reitz 128734c3b85SKevin Wolf static int open_f(BlockDriverState *bs, int argc, char **argv) 129e3aff4f6Saliguori { 130e3aff4f6Saliguori int flags = 0; 131e3aff4f6Saliguori int readonly = 0; 1329c4bab26SChristoph Hellwig int growable = 0; 133e3aff4f6Saliguori int c; 134b543c5cdSMax Reitz QemuOpts *qopts; 135b543c5cdSMax Reitz QDict *opts = NULL; 136e3aff4f6Saliguori 137b543c5cdSMax Reitz while ((c = getopt(argc, argv, "snrgo:")) != EOF) { 138e3aff4f6Saliguori switch (c) { 139e3aff4f6Saliguori case 's': 140e3aff4f6Saliguori flags |= BDRV_O_SNAPSHOT; 141e3aff4f6Saliguori break; 142e3aff4f6Saliguori case 'n': 143a6599793SChristoph Hellwig flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB; 144e3aff4f6Saliguori break; 145e3aff4f6Saliguori case 'r': 146e3aff4f6Saliguori readonly = 1; 147e3aff4f6Saliguori break; 1489c4bab26SChristoph Hellwig case 'g': 1499c4bab26SChristoph Hellwig growable = 1; 1509c4bab26SChristoph Hellwig break; 151b543c5cdSMax Reitz case 'o': 152b543c5cdSMax Reitz qopts = qemu_opts_parse(&empty_opts, optarg, 0); 153b543c5cdSMax Reitz if (qopts == NULL) { 154b543c5cdSMax Reitz printf("could not parse option list -- %s\n", optarg); 155b543c5cdSMax Reitz return 0; 156b543c5cdSMax Reitz } 157b543c5cdSMax Reitz opts = qemu_opts_to_qdict(qopts, opts); 158b543c5cdSMax Reitz qemu_opts_del(qopts); 159b543c5cdSMax Reitz break; 160e3aff4f6Saliguori default: 161c2cdf5c5SKevin Wolf return qemuio_command_usage(&open_cmd); 162e3aff4f6Saliguori } 163e3aff4f6Saliguori } 164e3aff4f6Saliguori 165f5edb014SNaphtali Sprei if (!readonly) { 166e3aff4f6Saliguori flags |= BDRV_O_RDWR; 167f5edb014SNaphtali Sprei } 168e3aff4f6Saliguori 169fd0fee34SMax Reitz if (optind == argc - 1) { 170fd0fee34SMax Reitz return openfile(argv[optind], flags, growable, opts); 171fd0fee34SMax Reitz } else if (optind == argc) { 172fd0fee34SMax Reitz return openfile(NULL, flags, growable, opts); 173fd0fee34SMax Reitz } else { 174c2cdf5c5SKevin Wolf return qemuio_command_usage(&open_cmd); 17543642b38SDevin Nakamura } 176e3aff4f6Saliguori } 177e3aff4f6Saliguori 178e681be7eSKevin Wolf static int quit_f(BlockDriverState *bs, int argc, char **argv) 179e681be7eSKevin Wolf { 180e681be7eSKevin Wolf return 1; 181e681be7eSKevin Wolf } 182e681be7eSKevin Wolf 183e681be7eSKevin Wolf static const cmdinfo_t quit_cmd = { 184e681be7eSKevin Wolf .name = "quit", 185e681be7eSKevin Wolf .altname = "q", 186e681be7eSKevin Wolf .cfunc = quit_f, 187e681be7eSKevin Wolf .argmin = -1, 188e681be7eSKevin Wolf .argmax = -1, 189e681be7eSKevin Wolf .flags = CMD_FLAG_GLOBAL, 190e681be7eSKevin Wolf .oneline = "exit the program", 191e681be7eSKevin Wolf }; 192e681be7eSKevin Wolf 193e3aff4f6Saliguori static void usage(const char *name) 194e3aff4f6Saliguori { 195e3aff4f6Saliguori printf( 196*d208cc35SMaria Kustova "Usage: %s [-h] [-V] [-rsnm] [-c STRING] ... [file]\n" 19784844a20SStefan Weil "QEMU Disk exerciser\n" 198e3aff4f6Saliguori "\n" 199*d208cc35SMaria Kustova " -c, --cmd STRING execute command with its arguments\n" 200*d208cc35SMaria Kustova " from the given string\n" 201e3aff4f6Saliguori " -r, --read-only export read-only\n" 202e3aff4f6Saliguori " -s, --snapshot use snapshot file\n" 203e3aff4f6Saliguori " -n, --nocache disable host cache\n" 2041db6947dSChristoph Hellwig " -g, --growable allow file to grow (only applies to protocols)\n" 205e3aff4f6Saliguori " -m, --misalign misalign allocations for O_DIRECT\n" 2065c6c3a6cSChristoph Hellwig " -k, --native-aio use kernel AIO implementation (on Linux only)\n" 207592fa070SKevin Wolf " -t, --cache=MODE use the given cache mode for the image\n" 208d7bb72c8SStefan Hajnoczi " -T, --trace FILE enable trace events listed in the given file\n" 209e3aff4f6Saliguori " -h, --help display this help and exit\n" 210e3aff4f6Saliguori " -V, --version output version information and exit\n" 211*d208cc35SMaria Kustova "\n" 212*d208cc35SMaria Kustova "See '%s -c help' for information on available commands." 213e3aff4f6Saliguori "\n", 214*d208cc35SMaria Kustova name, name); 215e3aff4f6Saliguori } 216e3aff4f6Saliguori 217d1174f13SKevin Wolf static char *get_prompt(void) 218d1174f13SKevin Wolf { 219d1174f13SKevin Wolf static char prompt[FILENAME_MAX + 2 /*"> "*/ + 1 /*"\0"*/ ]; 220d1174f13SKevin Wolf 221d1174f13SKevin Wolf if (!prompt[0]) { 222d1174f13SKevin Wolf snprintf(prompt, sizeof(prompt), "%s> ", progname); 223d1174f13SKevin Wolf } 224d1174f13SKevin Wolf 225d1174f13SKevin Wolf return prompt; 226d1174f13SKevin Wolf } 227d1174f13SKevin Wolf 228d5d1507bSStefan Weil static void GCC_FMT_ATTR(2, 3) readline_printf_func(void *opaque, 229d5d1507bSStefan Weil const char *fmt, ...) 230d1174f13SKevin Wolf { 2310cf17e18SStefan Hajnoczi va_list ap; 2320cf17e18SStefan Hajnoczi va_start(ap, fmt); 2330cf17e18SStefan Hajnoczi vprintf(fmt, ap); 2340cf17e18SStefan Hajnoczi va_end(ap); 2350cf17e18SStefan Hajnoczi } 2360cf17e18SStefan Hajnoczi 2370cf17e18SStefan Hajnoczi static void readline_flush_func(void *opaque) 2380cf17e18SStefan Hajnoczi { 2390cf17e18SStefan Hajnoczi fflush(stdout); 2400cf17e18SStefan Hajnoczi } 2410cf17e18SStefan Hajnoczi 2420cf17e18SStefan Hajnoczi static void readline_func(void *opaque, const char *str, void *readline_opaque) 2430cf17e18SStefan Hajnoczi { 2440cf17e18SStefan Hajnoczi char **line = readline_opaque; 2450cf17e18SStefan Hajnoczi *line = g_strdup(str); 2460cf17e18SStefan Hajnoczi } 2470cf17e18SStefan Hajnoczi 2484694020dSStefan Hajnoczi static void completion_match(const char *cmd, void *opaque) 2494694020dSStefan Hajnoczi { 2504694020dSStefan Hajnoczi readline_add_completion(readline_state, cmd); 2514694020dSStefan Hajnoczi } 2524694020dSStefan Hajnoczi 2530cf17e18SStefan Hajnoczi static void readline_completion_func(void *opaque, const char *str) 2540cf17e18SStefan Hajnoczi { 2554694020dSStefan Hajnoczi readline_set_completion_index(readline_state, strlen(str)); 2564694020dSStefan Hajnoczi qemuio_complete_command(str, completion_match, NULL); 2570cf17e18SStefan Hajnoczi } 2580cf17e18SStefan Hajnoczi 2590cf17e18SStefan Hajnoczi static char *fetchline_readline(void) 2600cf17e18SStefan Hajnoczi { 2610cf17e18SStefan Hajnoczi char *line = NULL; 2620cf17e18SStefan Hajnoczi 2630cf17e18SStefan Hajnoczi readline_start(readline_state, get_prompt(), 0, readline_func, &line); 2640cf17e18SStefan Hajnoczi while (!line) { 2650cf17e18SStefan Hajnoczi int ch = getchar(); 2660cf17e18SStefan Hajnoczi if (ch == EOF) { 2670cf17e18SStefan Hajnoczi break; 2680cf17e18SStefan Hajnoczi } 2690cf17e18SStefan Hajnoczi readline_handle_byte(readline_state, ch); 270d1174f13SKevin Wolf } 271d1174f13SKevin Wolf return line; 272d1174f13SKevin Wolf } 273d1174f13SKevin Wolf 274d1174f13SKevin Wolf #define MAXREADLINESZ 1024 2750cf17e18SStefan Hajnoczi static char *fetchline_fgets(void) 276d1174f13SKevin Wolf { 277d1174f13SKevin Wolf char *p, *line = g_malloc(MAXREADLINESZ); 278d1174f13SKevin Wolf 279d1174f13SKevin Wolf if (!fgets(line, MAXREADLINESZ, stdin)) { 280d1174f13SKevin Wolf g_free(line); 281d1174f13SKevin Wolf return NULL; 282d1174f13SKevin Wolf } 283d1174f13SKevin Wolf 284d1174f13SKevin Wolf p = line + strlen(line); 285d1174f13SKevin Wolf if (p != line && p[-1] == '\n') { 286d1174f13SKevin Wolf p[-1] = '\0'; 287d1174f13SKevin Wolf } 288d1174f13SKevin Wolf 289d1174f13SKevin Wolf return line; 290d1174f13SKevin Wolf } 2910cf17e18SStefan Hajnoczi 2920cf17e18SStefan Hajnoczi static char *fetchline(void) 2930cf17e18SStefan Hajnoczi { 2940cf17e18SStefan Hajnoczi if (readline_state) { 2950cf17e18SStefan Hajnoczi return fetchline_readline(); 2960cf17e18SStefan Hajnoczi } else { 2970cf17e18SStefan Hajnoczi return fetchline_fgets(); 2980cf17e18SStefan Hajnoczi } 2990cf17e18SStefan Hajnoczi } 300d1174f13SKevin Wolf 301d1174f13SKevin Wolf static void prep_fetchline(void *opaque) 302d1174f13SKevin Wolf { 303d1174f13SKevin Wolf int *fetchable = opaque; 304d1174f13SKevin Wolf 305d1174f13SKevin Wolf qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL); 306d1174f13SKevin Wolf *fetchable= 1; 307d1174f13SKevin Wolf } 308d1174f13SKevin Wolf 309d1174f13SKevin Wolf static void command_loop(void) 310d1174f13SKevin Wolf { 311d1174f13SKevin Wolf int i, done = 0, fetchable = 0, prompted = 0; 312d1174f13SKevin Wolf char *input; 313d1174f13SKevin Wolf 314d1174f13SKevin Wolf for (i = 0; !done && i < ncmdline; i++) { 3153d21994fSKevin Wolf done = qemuio_command(qemuio_bs, cmdline[i]); 316d1174f13SKevin Wolf } 317d1174f13SKevin Wolf if (cmdline) { 318d1174f13SKevin Wolf g_free(cmdline); 319d1174f13SKevin Wolf return; 320d1174f13SKevin Wolf } 321d1174f13SKevin Wolf 322d1174f13SKevin Wolf while (!done) { 323d1174f13SKevin Wolf if (!prompted) { 324d1174f13SKevin Wolf printf("%s", get_prompt()); 325d1174f13SKevin Wolf fflush(stdout); 326d1174f13SKevin Wolf qemu_set_fd_handler(STDIN_FILENO, prep_fetchline, NULL, &fetchable); 327d1174f13SKevin Wolf prompted = 1; 328d1174f13SKevin Wolf } 329d1174f13SKevin Wolf 330d1174f13SKevin Wolf main_loop_wait(false); 331d1174f13SKevin Wolf 332d1174f13SKevin Wolf if (!fetchable) { 333d1174f13SKevin Wolf continue; 334d1174f13SKevin Wolf } 335d1174f13SKevin Wolf 336d1174f13SKevin Wolf input = fetchline(); 337d1174f13SKevin Wolf if (input == NULL) { 338d1174f13SKevin Wolf break; 339d1174f13SKevin Wolf } 3403d21994fSKevin Wolf done = qemuio_command(qemuio_bs, input); 341d1174f13SKevin Wolf g_free(input); 342d1174f13SKevin Wolf 343d1174f13SKevin Wolf prompted = 0; 344d1174f13SKevin Wolf fetchable = 0; 345d1174f13SKevin Wolf } 346d1174f13SKevin Wolf qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL); 347d1174f13SKevin Wolf } 348d1174f13SKevin Wolf 349d1174f13SKevin Wolf static void add_user_command(char *optarg) 350d1174f13SKevin Wolf { 351d1174f13SKevin Wolf cmdline = g_realloc(cmdline, ++ncmdline * sizeof(char *)); 352d1174f13SKevin Wolf cmdline[ncmdline-1] = optarg; 353d1174f13SKevin Wolf } 354d1174f13SKevin Wolf 3550cf17e18SStefan Hajnoczi static void reenable_tty_echo(void) 3560cf17e18SStefan Hajnoczi { 3570cf17e18SStefan Hajnoczi qemu_set_tty_echo(STDIN_FILENO, true); 3580cf17e18SStefan Hajnoczi } 3590cf17e18SStefan Hajnoczi 360e3aff4f6Saliguori int main(int argc, char **argv) 361e3aff4f6Saliguori { 362e3aff4f6Saliguori int readonly = 0; 3639c4bab26SChristoph Hellwig int growable = 0; 3649e8f1835SPaolo Bonzini const char *sopt = "hVc:d:rsnmgkt:T:"; 365b32bb952SBlue Swirl const struct option lopt[] = { 366660f11beSBlue Swirl { "help", 0, NULL, 'h' }, 367660f11beSBlue Swirl { "version", 0, NULL, 'V' }, 368660f11beSBlue Swirl { "offset", 1, NULL, 'o' }, 369660f11beSBlue Swirl { "cmd", 1, NULL, 'c' }, 370660f11beSBlue Swirl { "read-only", 0, NULL, 'r' }, 371660f11beSBlue Swirl { "snapshot", 0, NULL, 's' }, 372660f11beSBlue Swirl { "nocache", 0, NULL, 'n' }, 373660f11beSBlue Swirl { "misalign", 0, NULL, 'm' }, 374660f11beSBlue Swirl { "growable", 0, NULL, 'g' }, 3755c6c3a6cSChristoph Hellwig { "native-aio", 0, NULL, 'k' }, 3769e8f1835SPaolo Bonzini { "discard", 1, NULL, 'd' }, 377592fa070SKevin Wolf { "cache", 1, NULL, 't' }, 378d7bb72c8SStefan Hajnoczi { "trace", 1, NULL, 'T' }, 379660f11beSBlue Swirl { NULL, 0, NULL, 0 } 380e3aff4f6Saliguori }; 381e3aff4f6Saliguori int c; 382e3aff4f6Saliguori int opt_index = 0; 3839e8f1835SPaolo Bonzini int flags = BDRV_O_UNMAP; 384e3aff4f6Saliguori 385526eda14SMORITA Kazutaka #ifdef CONFIG_POSIX 386526eda14SMORITA Kazutaka signal(SIGPIPE, SIG_IGN); 387526eda14SMORITA Kazutaka #endif 388526eda14SMORITA Kazutaka 389e3aff4f6Saliguori progname = basename(argv[0]); 39010f5bff6SFam Zheng qemu_init_exec_dir(argv[0]); 391e3aff4f6Saliguori 392e3aff4f6Saliguori while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) { 393e3aff4f6Saliguori switch (c) { 394e3aff4f6Saliguori case 's': 395e3aff4f6Saliguori flags |= BDRV_O_SNAPSHOT; 396e3aff4f6Saliguori break; 397e3aff4f6Saliguori case 'n': 398a6599793SChristoph Hellwig flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB; 399e3aff4f6Saliguori break; 4009e8f1835SPaolo Bonzini case 'd': 4019e8f1835SPaolo Bonzini if (bdrv_parse_discard_flags(optarg, &flags) < 0) { 4029e8f1835SPaolo Bonzini error_report("Invalid discard option: %s", optarg); 4039e8f1835SPaolo Bonzini exit(1); 4049e8f1835SPaolo Bonzini } 4059e8f1835SPaolo Bonzini break; 406e3aff4f6Saliguori case 'c': 407e3aff4f6Saliguori add_user_command(optarg); 408e3aff4f6Saliguori break; 409e3aff4f6Saliguori case 'r': 410e3aff4f6Saliguori readonly = 1; 411e3aff4f6Saliguori break; 412e3aff4f6Saliguori case 'm': 413f9883880SStefan Weil qemuio_misalign = true; 414e3aff4f6Saliguori break; 4159c4bab26SChristoph Hellwig case 'g': 4169c4bab26SChristoph Hellwig growable = 1; 4179c4bab26SChristoph Hellwig break; 4185c6c3a6cSChristoph Hellwig case 'k': 4195c6c3a6cSChristoph Hellwig flags |= BDRV_O_NATIVE_AIO; 4205c6c3a6cSChristoph Hellwig break; 421592fa070SKevin Wolf case 't': 422592fa070SKevin Wolf if (bdrv_parse_cache_flags(optarg, &flags) < 0) { 423592fa070SKevin Wolf error_report("Invalid cache option: %s", optarg); 424592fa070SKevin Wolf exit(1); 425592fa070SKevin Wolf } 426592fa070SKevin Wolf break; 427d7bb72c8SStefan Hajnoczi case 'T': 428d7bb72c8SStefan Hajnoczi if (!trace_backend_init(optarg, NULL)) { 429d7bb72c8SStefan Hajnoczi exit(1); /* error message will have been printed */ 430d7bb72c8SStefan Hajnoczi } 431d7bb72c8SStefan Hajnoczi break; 432e3aff4f6Saliguori case 'V': 43302da386aSKevin Wolf printf("%s version %s\n", progname, QEMU_VERSION); 434e3aff4f6Saliguori exit(0); 435e3aff4f6Saliguori case 'h': 436e3aff4f6Saliguori usage(progname); 437e3aff4f6Saliguori exit(0); 438e3aff4f6Saliguori default: 439e3aff4f6Saliguori usage(progname); 440e3aff4f6Saliguori exit(1); 441e3aff4f6Saliguori } 442e3aff4f6Saliguori } 443e3aff4f6Saliguori 444e3aff4f6Saliguori if ((argc - optind) > 1) { 445e3aff4f6Saliguori usage(progname); 446e3aff4f6Saliguori exit(1); 447e3aff4f6Saliguori } 448e3aff4f6Saliguori 449a57d1143SZhi Yong Wu qemu_init_main_loop(); 4502592c59aSPaolo Bonzini bdrv_init(); 451a57d1143SZhi Yong Wu 452e3aff4f6Saliguori /* initialize commands */ 453c2cdf5c5SKevin Wolf qemuio_add_command(&quit_cmd); 454c2cdf5c5SKevin Wolf qemuio_add_command(&open_cmd); 455c2cdf5c5SKevin Wolf qemuio_add_command(&close_cmd); 456e3aff4f6Saliguori 4570cf17e18SStefan Hajnoczi if (isatty(STDIN_FILENO)) { 4580cf17e18SStefan Hajnoczi readline_state = readline_init(readline_printf_func, 4590cf17e18SStefan Hajnoczi readline_flush_func, 4600cf17e18SStefan Hajnoczi NULL, 4610cf17e18SStefan Hajnoczi readline_completion_func); 4620cf17e18SStefan Hajnoczi qemu_set_tty_echo(STDIN_FILENO, false); 4630cf17e18SStefan Hajnoczi atexit(reenable_tty_echo); 4640cf17e18SStefan Hajnoczi } 4650cf17e18SStefan Hajnoczi 466e3aff4f6Saliguori /* open the device */ 467f5edb014SNaphtali Sprei if (!readonly) { 468e3aff4f6Saliguori flags |= BDRV_O_RDWR; 469f5edb014SNaphtali Sprei } 470e3aff4f6Saliguori 47143642b38SDevin Nakamura if ((argc - optind) == 1) { 472b543c5cdSMax Reitz openfile(argv[optind], flags, growable, NULL); 47343642b38SDevin Nakamura } 474e3aff4f6Saliguori command_loop(); 475e3aff4f6Saliguori 47695533d5fSChristoph Hellwig /* 477922453bcSStefan Hajnoczi * Make sure all outstanding requests complete before the program exits. 47895533d5fSChristoph Hellwig */ 479922453bcSStefan Hajnoczi bdrv_drain_all(); 48095533d5fSChristoph Hellwig 481734c3b85SKevin Wolf if (qemuio_bs) { 4824f6fd349SFam Zheng bdrv_unref(qemuio_bs); 48343642b38SDevin Nakamura } 4840cf17e18SStefan Hajnoczi g_free(readline_state); 485e3aff4f6Saliguori return 0; 486e3aff4f6Saliguori } 487