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 27e3aff4f6Saliguori char *progname; 28e3aff4f6Saliguori 29734c3b85SKevin Wolf BlockDriverState *qemuio_bs; 30797ac58cSKevin Wolf extern int qemuio_misalign; 31191c2890SKevin Wolf 32d1174f13SKevin Wolf /* qemu-io commands passed using -c */ 33d1174f13SKevin Wolf static int ncmdline; 34d1174f13SKevin Wolf static char **cmdline; 35d1174f13SKevin Wolf 360cf17e18SStefan Hajnoczi static ReadLineState *readline_state; 370cf17e18SStefan Hajnoczi 38734c3b85SKevin Wolf static int close_f(BlockDriverState *bs, int argc, char **argv) 39e3aff4f6Saliguori { 404f6fd349SFam Zheng bdrv_unref(bs); 41734c3b85SKevin Wolf qemuio_bs = NULL; 42e3aff4f6Saliguori return 0; 43e3aff4f6Saliguori } 44e3aff4f6Saliguori 45e3aff4f6Saliguori static const cmdinfo_t close_cmd = { 46e3aff4f6Saliguori .name = "close", 47e3aff4f6Saliguori .altname = "c", 48e3aff4f6Saliguori .cfunc = close_f, 49e3aff4f6Saliguori .oneline = "close the current open file", 50e3aff4f6Saliguori }; 51e3aff4f6Saliguori 52b543c5cdSMax Reitz static int openfile(char *name, int flags, int growable, QDict *opts) 53e3aff4f6Saliguori { 5434b5d2c6SMax Reitz Error *local_err = NULL; 5534b5d2c6SMax Reitz 56734c3b85SKevin Wolf if (qemuio_bs) { 57e3aff4f6Saliguori fprintf(stderr, "file open already, try 'help close'\n"); 58e3aff4f6Saliguori return 1; 59e3aff4f6Saliguori } 60e3aff4f6Saliguori 616db95603SChristoph Hellwig if (growable) { 6272daa72eSMax Reitz if (bdrv_file_open(&qemuio_bs, name, NULL, opts, flags, &local_err)) { 6334b5d2c6SMax Reitz fprintf(stderr, "%s: can't open device %s: %s\n", progname, name, 6434b5d2c6SMax Reitz error_get_pretty(local_err)); 6534b5d2c6SMax Reitz error_free(local_err); 666db95603SChristoph Hellwig return 1; 676db95603SChristoph Hellwig } 686db95603SChristoph Hellwig } else { 69734c3b85SKevin Wolf qemuio_bs = bdrv_new("hda"); 70e3aff4f6Saliguori 71b543c5cdSMax Reitz if (bdrv_open(qemuio_bs, name, opts, flags, NULL, &local_err) < 0) { 7234b5d2c6SMax Reitz fprintf(stderr, "%s: can't open device %s: %s\n", progname, name, 7334b5d2c6SMax Reitz error_get_pretty(local_err)); 7434b5d2c6SMax Reitz error_free(local_err); 754f6fd349SFam Zheng bdrv_unref(qemuio_bs); 76734c3b85SKevin Wolf qemuio_bs = NULL; 77e3aff4f6Saliguori return 1; 78e3aff4f6Saliguori } 799c4bab26SChristoph Hellwig } 806db95603SChristoph Hellwig 81e3aff4f6Saliguori return 0; 82e3aff4f6Saliguori } 83e3aff4f6Saliguori 8443642b38SDevin Nakamura static void open_help(void) 85e3aff4f6Saliguori { 86e3aff4f6Saliguori printf( 87e3aff4f6Saliguori "\n" 88e3aff4f6Saliguori " opens a new file in the requested mode\n" 89e3aff4f6Saliguori "\n" 90e3aff4f6Saliguori " Example:\n" 91e3aff4f6Saliguori " 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n" 92e3aff4f6Saliguori "\n" 93e3aff4f6Saliguori " Opens a file for subsequent use by all of the other qemu-io commands.\n" 94e3aff4f6Saliguori " -r, -- open file read-only\n" 95e3aff4f6Saliguori " -s, -- use snapshot file\n" 96e3aff4f6Saliguori " -n, -- disable host cache\n" 97b543c5cdSMax Reitz " -g, -- allow file to grow (only applies to protocols)\n" 98b543c5cdSMax Reitz " -o, -- options to be given to the block driver" 99e3aff4f6Saliguori "\n"); 100e3aff4f6Saliguori } 101e3aff4f6Saliguori 102734c3b85SKevin Wolf static int open_f(BlockDriverState *bs, int argc, char **argv); 10322a2bdcbSBlue Swirl 10422a2bdcbSBlue Swirl static const cmdinfo_t open_cmd = { 10522a2bdcbSBlue Swirl .name = "open", 10622a2bdcbSBlue Swirl .altname = "o", 10722a2bdcbSBlue Swirl .cfunc = open_f, 10822a2bdcbSBlue Swirl .argmin = 1, 10922a2bdcbSBlue Swirl .argmax = -1, 11022a2bdcbSBlue Swirl .flags = CMD_NOFILE_OK, 111b543c5cdSMax Reitz .args = "[-Crsn] [-o options] [path]", 11222a2bdcbSBlue Swirl .oneline = "open the file specified by path", 11322a2bdcbSBlue Swirl .help = open_help, 11422a2bdcbSBlue Swirl }; 115e3aff4f6Saliguori 116b543c5cdSMax Reitz static QemuOptsList empty_opts = { 117b543c5cdSMax Reitz .name = "drive", 118b543c5cdSMax Reitz .head = QTAILQ_HEAD_INITIALIZER(empty_opts.head), 119b543c5cdSMax Reitz .desc = { 120b543c5cdSMax Reitz /* no elements => accept any params */ 121b543c5cdSMax Reitz { /* end of list */ } 122b543c5cdSMax Reitz }, 123b543c5cdSMax Reitz }; 124b543c5cdSMax Reitz 125734c3b85SKevin Wolf static int open_f(BlockDriverState *bs, int argc, char **argv) 126e3aff4f6Saliguori { 127e3aff4f6Saliguori int flags = 0; 128e3aff4f6Saliguori int readonly = 0; 1299c4bab26SChristoph Hellwig int growable = 0; 130e3aff4f6Saliguori int c; 131b543c5cdSMax Reitz QemuOpts *qopts; 132b543c5cdSMax Reitz QDict *opts = NULL; 133e3aff4f6Saliguori 134b543c5cdSMax Reitz while ((c = getopt(argc, argv, "snrgo:")) != EOF) { 135e3aff4f6Saliguori switch (c) { 136e3aff4f6Saliguori case 's': 137e3aff4f6Saliguori flags |= BDRV_O_SNAPSHOT; 138e3aff4f6Saliguori break; 139e3aff4f6Saliguori case 'n': 140a6599793SChristoph Hellwig flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB; 141e3aff4f6Saliguori break; 142e3aff4f6Saliguori case 'r': 143e3aff4f6Saliguori readonly = 1; 144e3aff4f6Saliguori break; 1459c4bab26SChristoph Hellwig case 'g': 1469c4bab26SChristoph Hellwig growable = 1; 1479c4bab26SChristoph Hellwig break; 148b543c5cdSMax Reitz case 'o': 149b543c5cdSMax Reitz qopts = qemu_opts_parse(&empty_opts, optarg, 0); 150b543c5cdSMax Reitz if (qopts == NULL) { 151b543c5cdSMax Reitz printf("could not parse option list -- %s\n", optarg); 152b543c5cdSMax Reitz return 0; 153b543c5cdSMax Reitz } 154b543c5cdSMax Reitz opts = qemu_opts_to_qdict(qopts, opts); 155b543c5cdSMax Reitz qemu_opts_del(qopts); 156b543c5cdSMax Reitz break; 157e3aff4f6Saliguori default: 158c2cdf5c5SKevin Wolf return qemuio_command_usage(&open_cmd); 159e3aff4f6Saliguori } 160e3aff4f6Saliguori } 161e3aff4f6Saliguori 162f5edb014SNaphtali Sprei if (!readonly) { 163e3aff4f6Saliguori flags |= BDRV_O_RDWR; 164f5edb014SNaphtali Sprei } 165e3aff4f6Saliguori 166*fd0fee34SMax Reitz if (optind == argc - 1) { 167*fd0fee34SMax Reitz return openfile(argv[optind], flags, growable, opts); 168*fd0fee34SMax Reitz } else if (optind == argc) { 169*fd0fee34SMax Reitz return openfile(NULL, flags, growable, opts); 170*fd0fee34SMax Reitz } else { 171c2cdf5c5SKevin Wolf return qemuio_command_usage(&open_cmd); 17243642b38SDevin Nakamura } 173e3aff4f6Saliguori } 174e3aff4f6Saliguori 175e681be7eSKevin Wolf static int quit_f(BlockDriverState *bs, int argc, char **argv) 176e681be7eSKevin Wolf { 177e681be7eSKevin Wolf return 1; 178e681be7eSKevin Wolf } 179e681be7eSKevin Wolf 180e681be7eSKevin Wolf static const cmdinfo_t quit_cmd = { 181e681be7eSKevin Wolf .name = "quit", 182e681be7eSKevin Wolf .altname = "q", 183e681be7eSKevin Wolf .cfunc = quit_f, 184e681be7eSKevin Wolf .argmin = -1, 185e681be7eSKevin Wolf .argmax = -1, 186e681be7eSKevin Wolf .flags = CMD_FLAG_GLOBAL, 187e681be7eSKevin Wolf .oneline = "exit the program", 188e681be7eSKevin Wolf }; 189e681be7eSKevin Wolf 190e3aff4f6Saliguori static void usage(const char *name) 191e3aff4f6Saliguori { 192e3aff4f6Saliguori printf( 1939a2d77adSChristoph Hellwig "Usage: %s [-h] [-V] [-rsnm] [-c cmd] ... [file]\n" 19484844a20SStefan Weil "QEMU Disk exerciser\n" 195e3aff4f6Saliguori "\n" 196e3aff4f6Saliguori " -c, --cmd command to execute\n" 197e3aff4f6Saliguori " -r, --read-only export read-only\n" 198e3aff4f6Saliguori " -s, --snapshot use snapshot file\n" 199e3aff4f6Saliguori " -n, --nocache disable host cache\n" 2001db6947dSChristoph Hellwig " -g, --growable allow file to grow (only applies to protocols)\n" 201e3aff4f6Saliguori " -m, --misalign misalign allocations for O_DIRECT\n" 2025c6c3a6cSChristoph Hellwig " -k, --native-aio use kernel AIO implementation (on Linux only)\n" 203592fa070SKevin Wolf " -t, --cache=MODE use the given cache mode for the image\n" 204d7bb72c8SStefan Hajnoczi " -T, --trace FILE enable trace events listed in the given file\n" 205e3aff4f6Saliguori " -h, --help display this help and exit\n" 206e3aff4f6Saliguori " -V, --version output version information and exit\n" 207e3aff4f6Saliguori "\n", 208e3aff4f6Saliguori name); 209e3aff4f6Saliguori } 210e3aff4f6Saliguori 211d1174f13SKevin Wolf static char *get_prompt(void) 212d1174f13SKevin Wolf { 213d1174f13SKevin Wolf static char prompt[FILENAME_MAX + 2 /*"> "*/ + 1 /*"\0"*/ ]; 214d1174f13SKevin Wolf 215d1174f13SKevin Wolf if (!prompt[0]) { 216d1174f13SKevin Wolf snprintf(prompt, sizeof(prompt), "%s> ", progname); 217d1174f13SKevin Wolf } 218d1174f13SKevin Wolf 219d1174f13SKevin Wolf return prompt; 220d1174f13SKevin Wolf } 221d1174f13SKevin Wolf 2220cf17e18SStefan Hajnoczi static void readline_printf_func(void *opaque, const char *fmt, ...) 223d1174f13SKevin Wolf { 2240cf17e18SStefan Hajnoczi va_list ap; 2250cf17e18SStefan Hajnoczi va_start(ap, fmt); 2260cf17e18SStefan Hajnoczi vprintf(fmt, ap); 2270cf17e18SStefan Hajnoczi va_end(ap); 2280cf17e18SStefan Hajnoczi } 2290cf17e18SStefan Hajnoczi 2300cf17e18SStefan Hajnoczi static void readline_flush_func(void *opaque) 2310cf17e18SStefan Hajnoczi { 2320cf17e18SStefan Hajnoczi fflush(stdout); 2330cf17e18SStefan Hajnoczi } 2340cf17e18SStefan Hajnoczi 2350cf17e18SStefan Hajnoczi static void readline_func(void *opaque, const char *str, void *readline_opaque) 2360cf17e18SStefan Hajnoczi { 2370cf17e18SStefan Hajnoczi char **line = readline_opaque; 2380cf17e18SStefan Hajnoczi *line = g_strdup(str); 2390cf17e18SStefan Hajnoczi } 2400cf17e18SStefan Hajnoczi 2414694020dSStefan Hajnoczi static void completion_match(const char *cmd, void *opaque) 2424694020dSStefan Hajnoczi { 2434694020dSStefan Hajnoczi readline_add_completion(readline_state, cmd); 2444694020dSStefan Hajnoczi } 2454694020dSStefan Hajnoczi 2460cf17e18SStefan Hajnoczi static void readline_completion_func(void *opaque, const char *str) 2470cf17e18SStefan Hajnoczi { 2484694020dSStefan Hajnoczi readline_set_completion_index(readline_state, strlen(str)); 2494694020dSStefan Hajnoczi qemuio_complete_command(str, completion_match, NULL); 2500cf17e18SStefan Hajnoczi } 2510cf17e18SStefan Hajnoczi 2520cf17e18SStefan Hajnoczi static char *fetchline_readline(void) 2530cf17e18SStefan Hajnoczi { 2540cf17e18SStefan Hajnoczi char *line = NULL; 2550cf17e18SStefan Hajnoczi 2560cf17e18SStefan Hajnoczi readline_start(readline_state, get_prompt(), 0, readline_func, &line); 2570cf17e18SStefan Hajnoczi while (!line) { 2580cf17e18SStefan Hajnoczi int ch = getchar(); 2590cf17e18SStefan Hajnoczi if (ch == EOF) { 2600cf17e18SStefan Hajnoczi break; 2610cf17e18SStefan Hajnoczi } 2620cf17e18SStefan Hajnoczi readline_handle_byte(readline_state, ch); 263d1174f13SKevin Wolf } 264d1174f13SKevin Wolf return line; 265d1174f13SKevin Wolf } 266d1174f13SKevin Wolf 267d1174f13SKevin Wolf #define MAXREADLINESZ 1024 2680cf17e18SStefan Hajnoczi static char *fetchline_fgets(void) 269d1174f13SKevin Wolf { 270d1174f13SKevin Wolf char *p, *line = g_malloc(MAXREADLINESZ); 271d1174f13SKevin Wolf 272d1174f13SKevin Wolf if (!fgets(line, MAXREADLINESZ, stdin)) { 273d1174f13SKevin Wolf g_free(line); 274d1174f13SKevin Wolf return NULL; 275d1174f13SKevin Wolf } 276d1174f13SKevin Wolf 277d1174f13SKevin Wolf p = line + strlen(line); 278d1174f13SKevin Wolf if (p != line && p[-1] == '\n') { 279d1174f13SKevin Wolf p[-1] = '\0'; 280d1174f13SKevin Wolf } 281d1174f13SKevin Wolf 282d1174f13SKevin Wolf return line; 283d1174f13SKevin Wolf } 2840cf17e18SStefan Hajnoczi 2850cf17e18SStefan Hajnoczi static char *fetchline(void) 2860cf17e18SStefan Hajnoczi { 2870cf17e18SStefan Hajnoczi if (readline_state) { 2880cf17e18SStefan Hajnoczi return fetchline_readline(); 2890cf17e18SStefan Hajnoczi } else { 2900cf17e18SStefan Hajnoczi return fetchline_fgets(); 2910cf17e18SStefan Hajnoczi } 2920cf17e18SStefan Hajnoczi } 293d1174f13SKevin Wolf 294d1174f13SKevin Wolf static void prep_fetchline(void *opaque) 295d1174f13SKevin Wolf { 296d1174f13SKevin Wolf int *fetchable = opaque; 297d1174f13SKevin Wolf 298d1174f13SKevin Wolf qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL); 299d1174f13SKevin Wolf *fetchable= 1; 300d1174f13SKevin Wolf } 301d1174f13SKevin Wolf 302d1174f13SKevin Wolf static void command_loop(void) 303d1174f13SKevin Wolf { 304d1174f13SKevin Wolf int i, done = 0, fetchable = 0, prompted = 0; 305d1174f13SKevin Wolf char *input; 306d1174f13SKevin Wolf 307d1174f13SKevin Wolf for (i = 0; !done && i < ncmdline; i++) { 3083d21994fSKevin Wolf done = qemuio_command(qemuio_bs, cmdline[i]); 309d1174f13SKevin Wolf } 310d1174f13SKevin Wolf if (cmdline) { 311d1174f13SKevin Wolf g_free(cmdline); 312d1174f13SKevin Wolf return; 313d1174f13SKevin Wolf } 314d1174f13SKevin Wolf 315d1174f13SKevin Wolf while (!done) { 316d1174f13SKevin Wolf if (!prompted) { 317d1174f13SKevin Wolf printf("%s", get_prompt()); 318d1174f13SKevin Wolf fflush(stdout); 319d1174f13SKevin Wolf qemu_set_fd_handler(STDIN_FILENO, prep_fetchline, NULL, &fetchable); 320d1174f13SKevin Wolf prompted = 1; 321d1174f13SKevin Wolf } 322d1174f13SKevin Wolf 323d1174f13SKevin Wolf main_loop_wait(false); 324d1174f13SKevin Wolf 325d1174f13SKevin Wolf if (!fetchable) { 326d1174f13SKevin Wolf continue; 327d1174f13SKevin Wolf } 328d1174f13SKevin Wolf 329d1174f13SKevin Wolf input = fetchline(); 330d1174f13SKevin Wolf if (input == NULL) { 331d1174f13SKevin Wolf break; 332d1174f13SKevin Wolf } 3333d21994fSKevin Wolf done = qemuio_command(qemuio_bs, input); 334d1174f13SKevin Wolf g_free(input); 335d1174f13SKevin Wolf 336d1174f13SKevin Wolf prompted = 0; 337d1174f13SKevin Wolf fetchable = 0; 338d1174f13SKevin Wolf } 339d1174f13SKevin Wolf qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL); 340d1174f13SKevin Wolf } 341d1174f13SKevin Wolf 342d1174f13SKevin Wolf static void add_user_command(char *optarg) 343d1174f13SKevin Wolf { 344d1174f13SKevin Wolf cmdline = g_realloc(cmdline, ++ncmdline * sizeof(char *)); 345d1174f13SKevin Wolf cmdline[ncmdline-1] = optarg; 346d1174f13SKevin Wolf } 347d1174f13SKevin Wolf 3480cf17e18SStefan Hajnoczi static void reenable_tty_echo(void) 3490cf17e18SStefan Hajnoczi { 3500cf17e18SStefan Hajnoczi qemu_set_tty_echo(STDIN_FILENO, true); 3510cf17e18SStefan Hajnoczi } 3520cf17e18SStefan Hajnoczi 353e3aff4f6Saliguori int main(int argc, char **argv) 354e3aff4f6Saliguori { 355e3aff4f6Saliguori int readonly = 0; 3569c4bab26SChristoph Hellwig int growable = 0; 3579e8f1835SPaolo Bonzini const char *sopt = "hVc:d:rsnmgkt:T:"; 358b32bb952SBlue Swirl const struct option lopt[] = { 359660f11beSBlue Swirl { "help", 0, NULL, 'h' }, 360660f11beSBlue Swirl { "version", 0, NULL, 'V' }, 361660f11beSBlue Swirl { "offset", 1, NULL, 'o' }, 362660f11beSBlue Swirl { "cmd", 1, NULL, 'c' }, 363660f11beSBlue Swirl { "read-only", 0, NULL, 'r' }, 364660f11beSBlue Swirl { "snapshot", 0, NULL, 's' }, 365660f11beSBlue Swirl { "nocache", 0, NULL, 'n' }, 366660f11beSBlue Swirl { "misalign", 0, NULL, 'm' }, 367660f11beSBlue Swirl { "growable", 0, NULL, 'g' }, 3685c6c3a6cSChristoph Hellwig { "native-aio", 0, NULL, 'k' }, 3699e8f1835SPaolo Bonzini { "discard", 1, NULL, 'd' }, 370592fa070SKevin Wolf { "cache", 1, NULL, 't' }, 371d7bb72c8SStefan Hajnoczi { "trace", 1, NULL, 'T' }, 372660f11beSBlue Swirl { NULL, 0, NULL, 0 } 373e3aff4f6Saliguori }; 374e3aff4f6Saliguori int c; 375e3aff4f6Saliguori int opt_index = 0; 3769e8f1835SPaolo Bonzini int flags = BDRV_O_UNMAP; 377e3aff4f6Saliguori 378526eda14SMORITA Kazutaka #ifdef CONFIG_POSIX 379526eda14SMORITA Kazutaka signal(SIGPIPE, SIG_IGN); 380526eda14SMORITA Kazutaka #endif 381526eda14SMORITA Kazutaka 382e3aff4f6Saliguori progname = basename(argv[0]); 383e3aff4f6Saliguori 384e3aff4f6Saliguori while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) { 385e3aff4f6Saliguori switch (c) { 386e3aff4f6Saliguori case 's': 387e3aff4f6Saliguori flags |= BDRV_O_SNAPSHOT; 388e3aff4f6Saliguori break; 389e3aff4f6Saliguori case 'n': 390a6599793SChristoph Hellwig flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB; 391e3aff4f6Saliguori break; 3929e8f1835SPaolo Bonzini case 'd': 3939e8f1835SPaolo Bonzini if (bdrv_parse_discard_flags(optarg, &flags) < 0) { 3949e8f1835SPaolo Bonzini error_report("Invalid discard option: %s", optarg); 3959e8f1835SPaolo Bonzini exit(1); 3969e8f1835SPaolo Bonzini } 3979e8f1835SPaolo Bonzini break; 398e3aff4f6Saliguori case 'c': 399e3aff4f6Saliguori add_user_command(optarg); 400e3aff4f6Saliguori break; 401e3aff4f6Saliguori case 'r': 402e3aff4f6Saliguori readonly = 1; 403e3aff4f6Saliguori break; 404e3aff4f6Saliguori case 'm': 405797ac58cSKevin Wolf qemuio_misalign = 1; 406e3aff4f6Saliguori break; 4079c4bab26SChristoph Hellwig case 'g': 4089c4bab26SChristoph Hellwig growable = 1; 4099c4bab26SChristoph Hellwig break; 4105c6c3a6cSChristoph Hellwig case 'k': 4115c6c3a6cSChristoph Hellwig flags |= BDRV_O_NATIVE_AIO; 4125c6c3a6cSChristoph Hellwig break; 413592fa070SKevin Wolf case 't': 414592fa070SKevin Wolf if (bdrv_parse_cache_flags(optarg, &flags) < 0) { 415592fa070SKevin Wolf error_report("Invalid cache option: %s", optarg); 416592fa070SKevin Wolf exit(1); 417592fa070SKevin Wolf } 418592fa070SKevin Wolf break; 419d7bb72c8SStefan Hajnoczi case 'T': 420d7bb72c8SStefan Hajnoczi if (!trace_backend_init(optarg, NULL)) { 421d7bb72c8SStefan Hajnoczi exit(1); /* error message will have been printed */ 422d7bb72c8SStefan Hajnoczi } 423d7bb72c8SStefan Hajnoczi break; 424e3aff4f6Saliguori case 'V': 42502da386aSKevin Wolf printf("%s version %s\n", progname, QEMU_VERSION); 426e3aff4f6Saliguori exit(0); 427e3aff4f6Saliguori case 'h': 428e3aff4f6Saliguori usage(progname); 429e3aff4f6Saliguori exit(0); 430e3aff4f6Saliguori default: 431e3aff4f6Saliguori usage(progname); 432e3aff4f6Saliguori exit(1); 433e3aff4f6Saliguori } 434e3aff4f6Saliguori } 435e3aff4f6Saliguori 436e3aff4f6Saliguori if ((argc - optind) > 1) { 437e3aff4f6Saliguori usage(progname); 438e3aff4f6Saliguori exit(1); 439e3aff4f6Saliguori } 440e3aff4f6Saliguori 441a57d1143SZhi Yong Wu qemu_init_main_loop(); 4422592c59aSPaolo Bonzini bdrv_init(); 443a57d1143SZhi Yong Wu 444e3aff4f6Saliguori /* initialize commands */ 445c2cdf5c5SKevin Wolf qemuio_add_command(&quit_cmd); 446c2cdf5c5SKevin Wolf qemuio_add_command(&open_cmd); 447c2cdf5c5SKevin Wolf qemuio_add_command(&close_cmd); 448e3aff4f6Saliguori 4490cf17e18SStefan Hajnoczi if (isatty(STDIN_FILENO)) { 4500cf17e18SStefan Hajnoczi readline_state = readline_init(readline_printf_func, 4510cf17e18SStefan Hajnoczi readline_flush_func, 4520cf17e18SStefan Hajnoczi NULL, 4530cf17e18SStefan Hajnoczi readline_completion_func); 4540cf17e18SStefan Hajnoczi qemu_set_tty_echo(STDIN_FILENO, false); 4550cf17e18SStefan Hajnoczi atexit(reenable_tty_echo); 4560cf17e18SStefan Hajnoczi } 4570cf17e18SStefan Hajnoczi 458e3aff4f6Saliguori /* open the device */ 459f5edb014SNaphtali Sprei if (!readonly) { 460e3aff4f6Saliguori flags |= BDRV_O_RDWR; 461f5edb014SNaphtali Sprei } 462e3aff4f6Saliguori 46343642b38SDevin Nakamura if ((argc - optind) == 1) { 464b543c5cdSMax Reitz openfile(argv[optind], flags, growable, NULL); 46543642b38SDevin Nakamura } 466e3aff4f6Saliguori command_loop(); 467e3aff4f6Saliguori 46895533d5fSChristoph Hellwig /* 469922453bcSStefan Hajnoczi * Make sure all outstanding requests complete before the program exits. 47095533d5fSChristoph Hellwig */ 471922453bcSStefan Hajnoczi bdrv_drain_all(); 47295533d5fSChristoph Hellwig 473734c3b85SKevin Wolf if (qemuio_bs) { 4744f6fd349SFam Zheng bdrv_unref(qemuio_bs); 47543642b38SDevin Nakamura } 4760cf17e18SStefan Hajnoczi g_free(readline_state); 477e3aff4f6Saliguori return 0; 478e3aff4f6Saliguori } 479