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"); 5729f2601aSMarkus Armbruster QDECREF(opts); 58e3aff4f6Saliguori return 1; 59e3aff4f6Saliguori } 60e3aff4f6Saliguori 616db95603SChristoph Hellwig if (growable) { 622e40134bSMax Reitz if (bdrv_open(&qemuio_bs, name, NULL, opts, flags | BDRV_O_PROTOCOL, 632e40134bSMax Reitz NULL, &local_err)) 642e40134bSMax Reitz { 65543f7befSMarkus Armbruster fprintf(stderr, "%s: can't open%s%s: %s\n", progname, 66543f7befSMarkus Armbruster name ? " device " : "", name ?: "", 6734b5d2c6SMax Reitz error_get_pretty(local_err)); 6834b5d2c6SMax Reitz error_free(local_err); 696db95603SChristoph Hellwig return 1; 706db95603SChristoph Hellwig } 716db95603SChristoph Hellwig } else { 7298522f63SKevin Wolf qemuio_bs = bdrv_new("hda", &error_abort); 73e3aff4f6Saliguori 74ddf5636dSMax Reitz if (bdrv_open(&qemuio_bs, name, NULL, opts, flags, NULL, &local_err) 75ddf5636dSMax Reitz < 0) 76ddf5636dSMax Reitz { 77543f7befSMarkus Armbruster fprintf(stderr, "%s: can't open%s%s: %s\n", progname, 78543f7befSMarkus Armbruster name ? " device " : "", name ?: "", 7934b5d2c6SMax Reitz error_get_pretty(local_err)); 8034b5d2c6SMax Reitz error_free(local_err); 814f6fd349SFam Zheng bdrv_unref(qemuio_bs); 82734c3b85SKevin Wolf qemuio_bs = NULL; 83e3aff4f6Saliguori return 1; 84e3aff4f6Saliguori } 859c4bab26SChristoph Hellwig } 866db95603SChristoph Hellwig 87e3aff4f6Saliguori return 0; 88e3aff4f6Saliguori } 89e3aff4f6Saliguori 9043642b38SDevin Nakamura static void open_help(void) 91e3aff4f6Saliguori { 92e3aff4f6Saliguori printf( 93e3aff4f6Saliguori "\n" 94e3aff4f6Saliguori " opens a new file in the requested mode\n" 95e3aff4f6Saliguori "\n" 96e3aff4f6Saliguori " Example:\n" 97e3aff4f6Saliguori " 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n" 98e3aff4f6Saliguori "\n" 99e3aff4f6Saliguori " Opens a file for subsequent use by all of the other qemu-io commands.\n" 100e3aff4f6Saliguori " -r, -- open file read-only\n" 101e3aff4f6Saliguori " -s, -- use snapshot file\n" 102e3aff4f6Saliguori " -n, -- disable host cache\n" 103b543c5cdSMax Reitz " -g, -- allow file to grow (only applies to protocols)\n" 104b543c5cdSMax Reitz " -o, -- options to be given to the block driver" 105e3aff4f6Saliguori "\n"); 106e3aff4f6Saliguori } 107e3aff4f6Saliguori 108734c3b85SKevin Wolf static int open_f(BlockDriverState *bs, int argc, char **argv); 10922a2bdcbSBlue Swirl 11022a2bdcbSBlue Swirl static const cmdinfo_t open_cmd = { 11122a2bdcbSBlue Swirl .name = "open", 11222a2bdcbSBlue Swirl .altname = "o", 11322a2bdcbSBlue Swirl .cfunc = open_f, 11422a2bdcbSBlue Swirl .argmin = 1, 11522a2bdcbSBlue Swirl .argmax = -1, 11622a2bdcbSBlue Swirl .flags = CMD_NOFILE_OK, 117b543c5cdSMax Reitz .args = "[-Crsn] [-o options] [path]", 11822a2bdcbSBlue Swirl .oneline = "open the file specified by path", 11922a2bdcbSBlue Swirl .help = open_help, 12022a2bdcbSBlue Swirl }; 121e3aff4f6Saliguori 122b543c5cdSMax Reitz static QemuOptsList empty_opts = { 123b543c5cdSMax Reitz .name = "drive", 124443422fdSMarkus Armbruster .merge_lists = true, 125b543c5cdSMax Reitz .head = QTAILQ_HEAD_INITIALIZER(empty_opts.head), 126b543c5cdSMax Reitz .desc = { 127b543c5cdSMax Reitz /* no elements => accept any params */ 128b543c5cdSMax Reitz { /* end of list */ } 129b543c5cdSMax Reitz }, 130b543c5cdSMax Reitz }; 131b543c5cdSMax Reitz 132734c3b85SKevin Wolf static int open_f(BlockDriverState *bs, int argc, char **argv) 133e3aff4f6Saliguori { 134e3aff4f6Saliguori int flags = 0; 135e3aff4f6Saliguori int readonly = 0; 1369c4bab26SChristoph Hellwig int growable = 0; 137e3aff4f6Saliguori int c; 138b543c5cdSMax Reitz QemuOpts *qopts; 139443422fdSMarkus Armbruster QDict *opts; 140e3aff4f6Saliguori 141b543c5cdSMax Reitz while ((c = getopt(argc, argv, "snrgo:")) != EOF) { 142e3aff4f6Saliguori switch (c) { 143e3aff4f6Saliguori case 's': 144e3aff4f6Saliguori flags |= BDRV_O_SNAPSHOT; 145e3aff4f6Saliguori break; 146e3aff4f6Saliguori case 'n': 147a6599793SChristoph Hellwig flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB; 148e3aff4f6Saliguori break; 149e3aff4f6Saliguori case 'r': 150e3aff4f6Saliguori readonly = 1; 151e3aff4f6Saliguori break; 1529c4bab26SChristoph Hellwig case 'g': 1539c4bab26SChristoph Hellwig growable = 1; 1549c4bab26SChristoph Hellwig break; 155b543c5cdSMax Reitz case 'o': 156443422fdSMarkus Armbruster if (!qemu_opts_parse(&empty_opts, optarg, 0)) { 157b543c5cdSMax Reitz printf("could not parse option list -- %s\n", optarg); 158443422fdSMarkus Armbruster qemu_opts_reset(&empty_opts); 159b543c5cdSMax Reitz return 0; 160b543c5cdSMax Reitz } 161b543c5cdSMax Reitz break; 162e3aff4f6Saliguori default: 163443422fdSMarkus Armbruster qemu_opts_reset(&empty_opts); 164c2cdf5c5SKevin Wolf return qemuio_command_usage(&open_cmd); 165e3aff4f6Saliguori } 166e3aff4f6Saliguori } 167e3aff4f6Saliguori 168f5edb014SNaphtali Sprei if (!readonly) { 169e3aff4f6Saliguori flags |= BDRV_O_RDWR; 170f5edb014SNaphtali Sprei } 171e3aff4f6Saliguori 172443422fdSMarkus Armbruster qopts = qemu_opts_find(&empty_opts, NULL); 173443422fdSMarkus Armbruster opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : NULL; 174443422fdSMarkus Armbruster qemu_opts_reset(&empty_opts); 175443422fdSMarkus Armbruster 176fd0fee34SMax Reitz if (optind == argc - 1) { 177fd0fee34SMax Reitz return openfile(argv[optind], flags, growable, opts); 178fd0fee34SMax Reitz } else if (optind == argc) { 179fd0fee34SMax Reitz return openfile(NULL, flags, growable, opts); 180fd0fee34SMax Reitz } else { 18129f2601aSMarkus Armbruster QDECREF(opts); 182c2cdf5c5SKevin Wolf return qemuio_command_usage(&open_cmd); 18343642b38SDevin Nakamura } 184e3aff4f6Saliguori } 185e3aff4f6Saliguori 186e681be7eSKevin Wolf static int quit_f(BlockDriverState *bs, int argc, char **argv) 187e681be7eSKevin Wolf { 188e681be7eSKevin Wolf return 1; 189e681be7eSKevin Wolf } 190e681be7eSKevin Wolf 191e681be7eSKevin Wolf static const cmdinfo_t quit_cmd = { 192e681be7eSKevin Wolf .name = "quit", 193e681be7eSKevin Wolf .altname = "q", 194e681be7eSKevin Wolf .cfunc = quit_f, 195e681be7eSKevin Wolf .argmin = -1, 196e681be7eSKevin Wolf .argmax = -1, 197e681be7eSKevin Wolf .flags = CMD_FLAG_GLOBAL, 198e681be7eSKevin Wolf .oneline = "exit the program", 199e681be7eSKevin Wolf }; 200e681be7eSKevin Wolf 201e3aff4f6Saliguori static void usage(const char *name) 202e3aff4f6Saliguori { 203e3aff4f6Saliguori printf( 204d208cc35SMaria Kustova "Usage: %s [-h] [-V] [-rsnm] [-c STRING] ... [file]\n" 20584844a20SStefan Weil "QEMU Disk exerciser\n" 206e3aff4f6Saliguori "\n" 207d208cc35SMaria Kustova " -c, --cmd STRING execute command with its arguments\n" 208d208cc35SMaria Kustova " from the given string\n" 209e3aff4f6Saliguori " -r, --read-only export read-only\n" 210e3aff4f6Saliguori " -s, --snapshot use snapshot file\n" 211e3aff4f6Saliguori " -n, --nocache disable host cache\n" 2121db6947dSChristoph Hellwig " -g, --growable allow file to grow (only applies to protocols)\n" 213e3aff4f6Saliguori " -m, --misalign misalign allocations for O_DIRECT\n" 2145c6c3a6cSChristoph Hellwig " -k, --native-aio use kernel AIO implementation (on Linux only)\n" 215592fa070SKevin Wolf " -t, --cache=MODE use the given cache mode for the image\n" 216d7bb72c8SStefan Hajnoczi " -T, --trace FILE enable trace events listed in the given file\n" 217e3aff4f6Saliguori " -h, --help display this help and exit\n" 218e3aff4f6Saliguori " -V, --version output version information and exit\n" 219d208cc35SMaria Kustova "\n" 220d208cc35SMaria Kustova "See '%s -c help' for information on available commands." 221e3aff4f6Saliguori "\n", 222d208cc35SMaria Kustova name, name); 223e3aff4f6Saliguori } 224e3aff4f6Saliguori 225d1174f13SKevin Wolf static char *get_prompt(void) 226d1174f13SKevin Wolf { 227d1174f13SKevin Wolf static char prompt[FILENAME_MAX + 2 /*"> "*/ + 1 /*"\0"*/ ]; 228d1174f13SKevin Wolf 229d1174f13SKevin Wolf if (!prompt[0]) { 230d1174f13SKevin Wolf snprintf(prompt, sizeof(prompt), "%s> ", progname); 231d1174f13SKevin Wolf } 232d1174f13SKevin Wolf 233d1174f13SKevin Wolf return prompt; 234d1174f13SKevin Wolf } 235d1174f13SKevin Wolf 236d5d1507bSStefan Weil static void GCC_FMT_ATTR(2, 3) readline_printf_func(void *opaque, 237d5d1507bSStefan Weil const char *fmt, ...) 238d1174f13SKevin Wolf { 2390cf17e18SStefan Hajnoczi va_list ap; 2400cf17e18SStefan Hajnoczi va_start(ap, fmt); 2410cf17e18SStefan Hajnoczi vprintf(fmt, ap); 2420cf17e18SStefan Hajnoczi va_end(ap); 2430cf17e18SStefan Hajnoczi } 2440cf17e18SStefan Hajnoczi 2450cf17e18SStefan Hajnoczi static void readline_flush_func(void *opaque) 2460cf17e18SStefan Hajnoczi { 2470cf17e18SStefan Hajnoczi fflush(stdout); 2480cf17e18SStefan Hajnoczi } 2490cf17e18SStefan Hajnoczi 2500cf17e18SStefan Hajnoczi static void readline_func(void *opaque, const char *str, void *readline_opaque) 2510cf17e18SStefan Hajnoczi { 2520cf17e18SStefan Hajnoczi char **line = readline_opaque; 2530cf17e18SStefan Hajnoczi *line = g_strdup(str); 2540cf17e18SStefan Hajnoczi } 2550cf17e18SStefan Hajnoczi 2564694020dSStefan Hajnoczi static void completion_match(const char *cmd, void *opaque) 2574694020dSStefan Hajnoczi { 2584694020dSStefan Hajnoczi readline_add_completion(readline_state, cmd); 2594694020dSStefan Hajnoczi } 2604694020dSStefan Hajnoczi 2610cf17e18SStefan Hajnoczi static void readline_completion_func(void *opaque, const char *str) 2620cf17e18SStefan Hajnoczi { 2634694020dSStefan Hajnoczi readline_set_completion_index(readline_state, strlen(str)); 2644694020dSStefan Hajnoczi qemuio_complete_command(str, completion_match, NULL); 2650cf17e18SStefan Hajnoczi } 2660cf17e18SStefan Hajnoczi 2670cf17e18SStefan Hajnoczi static char *fetchline_readline(void) 2680cf17e18SStefan Hajnoczi { 2690cf17e18SStefan Hajnoczi char *line = NULL; 2700cf17e18SStefan Hajnoczi 2710cf17e18SStefan Hajnoczi readline_start(readline_state, get_prompt(), 0, readline_func, &line); 2720cf17e18SStefan Hajnoczi while (!line) { 2730cf17e18SStefan Hajnoczi int ch = getchar(); 2740cf17e18SStefan Hajnoczi if (ch == EOF) { 2750cf17e18SStefan Hajnoczi break; 2760cf17e18SStefan Hajnoczi } 2770cf17e18SStefan Hajnoczi readline_handle_byte(readline_state, ch); 278d1174f13SKevin Wolf } 279d1174f13SKevin Wolf return line; 280d1174f13SKevin Wolf } 281d1174f13SKevin Wolf 282d1174f13SKevin Wolf #define MAXREADLINESZ 1024 2830cf17e18SStefan Hajnoczi static char *fetchline_fgets(void) 284d1174f13SKevin Wolf { 285d1174f13SKevin Wolf char *p, *line = g_malloc(MAXREADLINESZ); 286d1174f13SKevin Wolf 287d1174f13SKevin Wolf if (!fgets(line, MAXREADLINESZ, stdin)) { 288d1174f13SKevin Wolf g_free(line); 289d1174f13SKevin Wolf return NULL; 290d1174f13SKevin Wolf } 291d1174f13SKevin Wolf 292d1174f13SKevin Wolf p = line + strlen(line); 293d1174f13SKevin Wolf if (p != line && p[-1] == '\n') { 294d1174f13SKevin Wolf p[-1] = '\0'; 295d1174f13SKevin Wolf } 296d1174f13SKevin Wolf 297d1174f13SKevin Wolf return line; 298d1174f13SKevin Wolf } 2990cf17e18SStefan Hajnoczi 3000cf17e18SStefan Hajnoczi static char *fetchline(void) 3010cf17e18SStefan Hajnoczi { 3020cf17e18SStefan Hajnoczi if (readline_state) { 3030cf17e18SStefan Hajnoczi return fetchline_readline(); 3040cf17e18SStefan Hajnoczi } else { 3050cf17e18SStefan Hajnoczi return fetchline_fgets(); 3060cf17e18SStefan Hajnoczi } 3070cf17e18SStefan Hajnoczi } 308d1174f13SKevin Wolf 309d1174f13SKevin Wolf static void prep_fetchline(void *opaque) 310d1174f13SKevin Wolf { 311d1174f13SKevin Wolf int *fetchable = opaque; 312d1174f13SKevin Wolf 313d1174f13SKevin Wolf qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL); 314d1174f13SKevin Wolf *fetchable= 1; 315d1174f13SKevin Wolf } 316d1174f13SKevin Wolf 317d1174f13SKevin Wolf static void command_loop(void) 318d1174f13SKevin Wolf { 319d1174f13SKevin Wolf int i, done = 0, fetchable = 0, prompted = 0; 320d1174f13SKevin Wolf char *input; 321d1174f13SKevin Wolf 322d1174f13SKevin Wolf for (i = 0; !done && i < ncmdline; i++) { 3233d21994fSKevin Wolf done = qemuio_command(qemuio_bs, cmdline[i]); 324d1174f13SKevin Wolf } 325d1174f13SKevin Wolf if (cmdline) { 326d1174f13SKevin Wolf g_free(cmdline); 327d1174f13SKevin Wolf return; 328d1174f13SKevin Wolf } 329d1174f13SKevin Wolf 330d1174f13SKevin Wolf while (!done) { 331d1174f13SKevin Wolf if (!prompted) { 332d1174f13SKevin Wolf printf("%s", get_prompt()); 333d1174f13SKevin Wolf fflush(stdout); 334d1174f13SKevin Wolf qemu_set_fd_handler(STDIN_FILENO, prep_fetchline, NULL, &fetchable); 335d1174f13SKevin Wolf prompted = 1; 336d1174f13SKevin Wolf } 337d1174f13SKevin Wolf 338d1174f13SKevin Wolf main_loop_wait(false); 339d1174f13SKevin Wolf 340d1174f13SKevin Wolf if (!fetchable) { 341d1174f13SKevin Wolf continue; 342d1174f13SKevin Wolf } 343d1174f13SKevin Wolf 344d1174f13SKevin Wolf input = fetchline(); 345d1174f13SKevin Wolf if (input == NULL) { 346d1174f13SKevin Wolf break; 347d1174f13SKevin Wolf } 3483d21994fSKevin Wolf done = qemuio_command(qemuio_bs, input); 349d1174f13SKevin Wolf g_free(input); 350d1174f13SKevin Wolf 351d1174f13SKevin Wolf prompted = 0; 352d1174f13SKevin Wolf fetchable = 0; 353d1174f13SKevin Wolf } 354d1174f13SKevin Wolf qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL); 355d1174f13SKevin Wolf } 356d1174f13SKevin Wolf 357d1174f13SKevin Wolf static void add_user_command(char *optarg) 358d1174f13SKevin Wolf { 359d1174f13SKevin Wolf cmdline = g_realloc(cmdline, ++ncmdline * sizeof(char *)); 360d1174f13SKevin Wolf cmdline[ncmdline-1] = optarg; 361d1174f13SKevin Wolf } 362d1174f13SKevin Wolf 3630cf17e18SStefan Hajnoczi static void reenable_tty_echo(void) 3640cf17e18SStefan Hajnoczi { 3650cf17e18SStefan Hajnoczi qemu_set_tty_echo(STDIN_FILENO, true); 3660cf17e18SStefan Hajnoczi } 3670cf17e18SStefan Hajnoczi 368e3aff4f6Saliguori int main(int argc, char **argv) 369e3aff4f6Saliguori { 370e3aff4f6Saliguori int readonly = 0; 3719c4bab26SChristoph Hellwig int growable = 0; 3729e8f1835SPaolo Bonzini const char *sopt = "hVc:d:rsnmgkt:T:"; 373b32bb952SBlue Swirl const struct option lopt[] = { 374660f11beSBlue Swirl { "help", 0, NULL, 'h' }, 375660f11beSBlue Swirl { "version", 0, NULL, 'V' }, 376660f11beSBlue Swirl { "offset", 1, NULL, 'o' }, 377660f11beSBlue Swirl { "cmd", 1, NULL, 'c' }, 378660f11beSBlue Swirl { "read-only", 0, NULL, 'r' }, 379660f11beSBlue Swirl { "snapshot", 0, NULL, 's' }, 380660f11beSBlue Swirl { "nocache", 0, NULL, 'n' }, 381660f11beSBlue Swirl { "misalign", 0, NULL, 'm' }, 382660f11beSBlue Swirl { "growable", 0, NULL, 'g' }, 3835c6c3a6cSChristoph Hellwig { "native-aio", 0, NULL, 'k' }, 3849e8f1835SPaolo Bonzini { "discard", 1, NULL, 'd' }, 385592fa070SKevin Wolf { "cache", 1, NULL, 't' }, 386d7bb72c8SStefan Hajnoczi { "trace", 1, NULL, 'T' }, 387660f11beSBlue Swirl { NULL, 0, NULL, 0 } 388e3aff4f6Saliguori }; 389e3aff4f6Saliguori int c; 390e3aff4f6Saliguori int opt_index = 0; 3919e8f1835SPaolo Bonzini int flags = BDRV_O_UNMAP; 392e3aff4f6Saliguori 393526eda14SMORITA Kazutaka #ifdef CONFIG_POSIX 394526eda14SMORITA Kazutaka signal(SIGPIPE, SIG_IGN); 395526eda14SMORITA Kazutaka #endif 396526eda14SMORITA Kazutaka 397e3aff4f6Saliguori progname = basename(argv[0]); 39810f5bff6SFam Zheng qemu_init_exec_dir(argv[0]); 399e3aff4f6Saliguori 400e3aff4f6Saliguori while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) { 401e3aff4f6Saliguori switch (c) { 402e3aff4f6Saliguori case 's': 403e3aff4f6Saliguori flags |= BDRV_O_SNAPSHOT; 404e3aff4f6Saliguori break; 405e3aff4f6Saliguori case 'n': 406a6599793SChristoph Hellwig flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB; 407e3aff4f6Saliguori break; 4089e8f1835SPaolo Bonzini case 'd': 4099e8f1835SPaolo Bonzini if (bdrv_parse_discard_flags(optarg, &flags) < 0) { 4109e8f1835SPaolo Bonzini error_report("Invalid discard option: %s", optarg); 4119e8f1835SPaolo Bonzini exit(1); 4129e8f1835SPaolo Bonzini } 4139e8f1835SPaolo Bonzini break; 414e3aff4f6Saliguori case 'c': 415e3aff4f6Saliguori add_user_command(optarg); 416e3aff4f6Saliguori break; 417e3aff4f6Saliguori case 'r': 418e3aff4f6Saliguori readonly = 1; 419e3aff4f6Saliguori break; 420e3aff4f6Saliguori case 'm': 421f9883880SStefan Weil qemuio_misalign = true; 422e3aff4f6Saliguori break; 4239c4bab26SChristoph Hellwig case 'g': 4249c4bab26SChristoph Hellwig growable = 1; 4259c4bab26SChristoph Hellwig break; 4265c6c3a6cSChristoph Hellwig case 'k': 4275c6c3a6cSChristoph Hellwig flags |= BDRV_O_NATIVE_AIO; 4285c6c3a6cSChristoph Hellwig break; 429592fa070SKevin Wolf case 't': 430592fa070SKevin Wolf if (bdrv_parse_cache_flags(optarg, &flags) < 0) { 431592fa070SKevin Wolf error_report("Invalid cache option: %s", optarg); 432592fa070SKevin Wolf exit(1); 433592fa070SKevin Wolf } 434592fa070SKevin Wolf break; 435d7bb72c8SStefan Hajnoczi case 'T': 436*5b808275SLluís Vilanova if (!trace_init_backends(optarg, NULL)) { 437d7bb72c8SStefan Hajnoczi exit(1); /* error message will have been printed */ 438d7bb72c8SStefan Hajnoczi } 439d7bb72c8SStefan Hajnoczi break; 440e3aff4f6Saliguori case 'V': 44102da386aSKevin Wolf printf("%s version %s\n", progname, QEMU_VERSION); 442e3aff4f6Saliguori exit(0); 443e3aff4f6Saliguori case 'h': 444e3aff4f6Saliguori usage(progname); 445e3aff4f6Saliguori exit(0); 446e3aff4f6Saliguori default: 447e3aff4f6Saliguori usage(progname); 448e3aff4f6Saliguori exit(1); 449e3aff4f6Saliguori } 450e3aff4f6Saliguori } 451e3aff4f6Saliguori 452e3aff4f6Saliguori if ((argc - optind) > 1) { 453e3aff4f6Saliguori usage(progname); 454e3aff4f6Saliguori exit(1); 455e3aff4f6Saliguori } 456e3aff4f6Saliguori 457a57d1143SZhi Yong Wu qemu_init_main_loop(); 4582592c59aSPaolo Bonzini bdrv_init(); 459a57d1143SZhi Yong Wu 460e3aff4f6Saliguori /* initialize commands */ 461c2cdf5c5SKevin Wolf qemuio_add_command(&quit_cmd); 462c2cdf5c5SKevin Wolf qemuio_add_command(&open_cmd); 463c2cdf5c5SKevin Wolf qemuio_add_command(&close_cmd); 464e3aff4f6Saliguori 4650cf17e18SStefan Hajnoczi if (isatty(STDIN_FILENO)) { 4660cf17e18SStefan Hajnoczi readline_state = readline_init(readline_printf_func, 4670cf17e18SStefan Hajnoczi readline_flush_func, 4680cf17e18SStefan Hajnoczi NULL, 4690cf17e18SStefan Hajnoczi readline_completion_func); 4700cf17e18SStefan Hajnoczi qemu_set_tty_echo(STDIN_FILENO, false); 4710cf17e18SStefan Hajnoczi atexit(reenable_tty_echo); 4720cf17e18SStefan Hajnoczi } 4730cf17e18SStefan Hajnoczi 474e3aff4f6Saliguori /* open the device */ 475f5edb014SNaphtali Sprei if (!readonly) { 476e3aff4f6Saliguori flags |= BDRV_O_RDWR; 477f5edb014SNaphtali Sprei } 478e3aff4f6Saliguori 47943642b38SDevin Nakamura if ((argc - optind) == 1) { 480b543c5cdSMax Reitz openfile(argv[optind], flags, growable, NULL); 48143642b38SDevin Nakamura } 482e3aff4f6Saliguori command_loop(); 483e3aff4f6Saliguori 48495533d5fSChristoph Hellwig /* 485922453bcSStefan Hajnoczi * Make sure all outstanding requests complete before the program exits. 48695533d5fSChristoph Hellwig */ 487922453bcSStefan Hajnoczi bdrv_drain_all(); 48895533d5fSChristoph Hellwig 489734c3b85SKevin Wolf if (qemuio_bs) { 4904f6fd349SFam Zheng bdrv_unref(qemuio_bs); 49143642b38SDevin Nakamura } 4920cf17e18SStefan Hajnoczi g_free(readline_state); 493e3aff4f6Saliguori return 0; 494e3aff4f6Saliguori } 495