1 e3aff4f6Saliguori /* 2 e3aff4f6Saliguori * Command line utility to exercise the QEMU I/O path. 3 e3aff4f6Saliguori * 4 e3aff4f6Saliguori * Copyright (C) 2009 Red Hat, Inc. 5 e3aff4f6Saliguori * Copyright (c) 2003-2005 Silicon Graphics, Inc. 6 e3aff4f6Saliguori * 7 e3aff4f6Saliguori * This work is licensed under the terms of the GNU GPL, version 2 or later. 8 e3aff4f6Saliguori * See the COPYING file in the top-level directory. 9 e3aff4f6Saliguori */ 10 452fcdbcSMarkus Armbruster 11 80c71a24SPeter Maydell #include "qemu/osdep.h" 12 e3aff4f6Saliguori #include <getopt.h> 13 c32d766aSStefan Weil #include <libgen.h> 14 0e448a05SDaniel P. Berrange #ifndef _WIN32 15 0e448a05SDaniel P. Berrange #include <termios.h> 16 0e448a05SDaniel P. Berrange #endif 17 e3aff4f6Saliguori 18 a8d25326SMarkus Armbruster #include "qemu-common.h" 19 da34e65cSMarkus Armbruster #include "qapi/error.h" 20 3d21994fSKevin Wolf #include "qemu-io.h" 21 d49b6836SMarkus Armbruster #include "qemu/error-report.h" 22 1de7afc9SPaolo Bonzini #include "qemu/main-loop.h" 23 0b8fa32fSMarkus Armbruster #include "qemu/module.h" 24 b543c5cdSMax Reitz #include "qemu/option.h" 25 b543c5cdSMax Reitz #include "qemu/config-file.h" 26 0cf17e18SStefan Hajnoczi #include "qemu/readline.h" 27 e9a80859SDenis V. Lunev #include "qemu/log.h" 28 98c5d2e7SDaniel P. Berrangé #include "qemu/sockets.h" 29 d49b6836SMarkus Armbruster #include "qapi/qmp/qstring.h" 30 452fcdbcSMarkus Armbruster #include "qapi/qmp/qdict.h" 31 9ba371b6SDaniel P. Berrange #include "qom/object_interfaces.h" 32 26f54e9aSMarkus Armbruster #include "sysemu/block-backend.h" 33 737e150eSPaolo Bonzini #include "block/block_int.h" 34 d7bb72c8SStefan Hajnoczi #include "trace/control.h" 35 c2297088SDaniel P. Berrange #include "crypto/init.h" 36 4face32aSEric Blake #include "qemu-version.h" 37 e3aff4f6Saliguori 38 e3aff4f6Saliguori #define CMD_NOFILE_OK 0x01 39 e3aff4f6Saliguori 40 26f54e9aSMarkus Armbruster static BlockBackend *qemuio_blk; 41 b444d0e9SMax Reitz static bool quit_qemu_io; 42 191c2890SKevin Wolf 43 d1174f13SKevin Wolf /* qemu-io commands passed using -c */ 44 d1174f13SKevin Wolf static int ncmdline; 45 d1174f13SKevin Wolf static char **cmdline; 46 499afa25SDaniel P. Berrange static bool imageOpts; 47 d1174f13SKevin Wolf 48 0cf17e18SStefan Hajnoczi static ReadLineState *readline_state; 49 0cf17e18SStefan Hajnoczi 50 0e448a05SDaniel P. Berrange static int ttyEOF; 51 0e448a05SDaniel P. Berrange 52 0e448a05SDaniel P. Berrange static int get_eof_char(void) 53 0e448a05SDaniel P. Berrange { 54 0e448a05SDaniel P. Berrange #ifdef _WIN32 55 0e448a05SDaniel P. Berrange return 0x4; /* Ctrl-D */ 56 0e448a05SDaniel P. Berrange #else 57 0e448a05SDaniel P. Berrange struct termios tty; 58 0e448a05SDaniel P. Berrange if (tcgetattr(STDIN_FILENO, &tty) != 0) { 59 0e448a05SDaniel P. Berrange if (errno == ENOTTY) { 60 0e448a05SDaniel P. Berrange return 0x0; /* just expect read() == 0 */ 61 0e448a05SDaniel P. Berrange } else { 62 0e448a05SDaniel P. Berrange return 0x4; /* Ctrl-D */ 63 0e448a05SDaniel P. Berrange } 64 0e448a05SDaniel P. Berrange } 65 0e448a05SDaniel P. Berrange 66 0e448a05SDaniel P. Berrange return tty.c_cc[VEOF]; 67 0e448a05SDaniel P. Berrange #endif 68 0e448a05SDaniel P. Berrange } 69 0e448a05SDaniel P. Berrange 70 b32d7a39SMax Reitz static int close_f(BlockBackend *blk, int argc, char **argv) 71 e3aff4f6Saliguori { 72 26f54e9aSMarkus Armbruster blk_unref(qemuio_blk); 73 26f54e9aSMarkus Armbruster qemuio_blk = NULL; 74 b32d7a39SMax Reitz return 0; 75 e3aff4f6Saliguori } 76 e3aff4f6Saliguori 77 e3aff4f6Saliguori static const cmdinfo_t close_cmd = { 78 e3aff4f6Saliguori .name = "close", 79 e3aff4f6Saliguori .altname = "c", 80 e3aff4f6Saliguori .cfunc = close_f, 81 e3aff4f6Saliguori .oneline = "close the current open file", 82 e3aff4f6Saliguori }; 83 e3aff4f6Saliguori 84 459571f7SFam Zheng static int openfile(char *name, int flags, bool writethrough, bool force_share, 85 459571f7SFam Zheng QDict *opts) 86 e3aff4f6Saliguori { 87 34b5d2c6SMax Reitz Error *local_err = NULL; 88 34b5d2c6SMax Reitz 89 1b58b438SMax Reitz if (qemuio_blk) { 90 b9884681SMarkus Armbruster error_report("file open already, try 'help close'"); 91 cb3e7f08SMarc-André Lureau qobject_unref(opts); 92 e3aff4f6Saliguori return 1; 93 e3aff4f6Saliguori } 94 e3aff4f6Saliguori 95 459571f7SFam Zheng if (force_share) { 96 459571f7SFam Zheng if (!opts) { 97 459571f7SFam Zheng opts = qdict_new(); 98 459571f7SFam Zheng } 99 459571f7SFam Zheng if (qdict_haskey(opts, BDRV_OPT_FORCE_SHARE) 100 2a01c01fSMax Reitz && strcmp(qdict_get_str(opts, BDRV_OPT_FORCE_SHARE), "on")) { 101 459571f7SFam Zheng error_report("-U conflicts with image options"); 102 cb3e7f08SMarc-André Lureau qobject_unref(opts); 103 459571f7SFam Zheng return 1; 104 459571f7SFam Zheng } 105 2a01c01fSMax Reitz qdict_put_str(opts, BDRV_OPT_FORCE_SHARE, "on"); 106 459571f7SFam Zheng } 107 efaa7c4eSMax Reitz qemuio_blk = blk_new_open(name, NULL, opts, flags, &local_err); 108 1b58b438SMax Reitz if (!qemuio_blk) { 109 b9884681SMarkus Armbruster error_reportf_err(local_err, "can't open%s%s: ", 110 b9884681SMarkus Armbruster name ? " device " : "", name ?: ""); 111 e3aff4f6Saliguori return 1; 112 e3aff4f6Saliguori } 113 6db95603SChristoph Hellwig 114 e151fc16SKevin Wolf blk_set_enable_write_cache(qemuio_blk, !writethrough); 115 8caf0212SDaniel P. Berrange 116 e3aff4f6Saliguori return 0; 117 e3aff4f6Saliguori } 118 e3aff4f6Saliguori 119 43642b38SDevin Nakamura static void open_help(void) 120 e3aff4f6Saliguori { 121 e3aff4f6Saliguori printf( 122 e3aff4f6Saliguori "\n" 123 e3aff4f6Saliguori " opens a new file in the requested mode\n" 124 e3aff4f6Saliguori "\n" 125 e3aff4f6Saliguori " Example:\n" 126 e4e12bb2SEric Blake " 'open -n -o driver=raw /tmp/data' - opens raw data file read-write, uncached\n" 127 e3aff4f6Saliguori "\n" 128 e3aff4f6Saliguori " Opens a file for subsequent use by all of the other qemu-io commands.\n" 129 e3aff4f6Saliguori " -r, -- open file read-only\n" 130 e3aff4f6Saliguori " -s, -- use snapshot file\n" 131 0f40444cSEric Blake " -C, -- use copy-on-read\n" 132 b8d970f1SEric Blake " -n, -- disable host cache, short for -t none\n" 133 459571f7SFam Zheng " -U, -- force shared permissions\n" 134 1c5a2aecSAarushi Mehta " -k, -- use kernel AIO implementation (Linux only, prefer use of -i)\n" 135 1c5a2aecSAarushi Mehta " -i, -- use AIO mode (threads, native or io_uring)\n" 136 b8d970f1SEric Blake " -t, -- use the given cache mode for the image\n" 137 b8d970f1SEric Blake " -d, -- use the given discard mode for the image\n" 138 b543c5cdSMax Reitz " -o, -- options to be given to the block driver" 139 e3aff4f6Saliguori "\n"); 140 e3aff4f6Saliguori } 141 e3aff4f6Saliguori 142 b32d7a39SMax Reitz static int open_f(BlockBackend *blk, int argc, char **argv); 143 22a2bdcbSBlue Swirl 144 22a2bdcbSBlue Swirl static const cmdinfo_t open_cmd = { 145 22a2bdcbSBlue Swirl .name = "open", 146 22a2bdcbSBlue Swirl .altname = "o", 147 22a2bdcbSBlue Swirl .cfunc = open_f, 148 22a2bdcbSBlue Swirl .argmin = 1, 149 22a2bdcbSBlue Swirl .argmax = -1, 150 22a2bdcbSBlue Swirl .flags = CMD_NOFILE_OK, 151 0f40444cSEric Blake .args = "[-rsCnkU] [-t cache] [-d discard] [-o options] [path]", 152 22a2bdcbSBlue Swirl .oneline = "open the file specified by path", 153 22a2bdcbSBlue Swirl .help = open_help, 154 22a2bdcbSBlue Swirl }; 155 e3aff4f6Saliguori 156 b543c5cdSMax Reitz static QemuOptsList empty_opts = { 157 b543c5cdSMax Reitz .name = "drive", 158 443422fdSMarkus Armbruster .merge_lists = true, 159 b543c5cdSMax Reitz .head = QTAILQ_HEAD_INITIALIZER(empty_opts.head), 160 b543c5cdSMax Reitz .desc = { 161 b543c5cdSMax Reitz /* no elements => accept any params */ 162 b543c5cdSMax Reitz { /* end of list */ } 163 b543c5cdSMax Reitz }, 164 b543c5cdSMax Reitz }; 165 b543c5cdSMax Reitz 166 b32d7a39SMax Reitz static int open_f(BlockBackend *blk, int argc, char **argv) 167 e3aff4f6Saliguori { 168 b8d970f1SEric Blake int flags = BDRV_O_UNMAP; 169 e3aff4f6Saliguori int readonly = 0; 170 e151fc16SKevin Wolf bool writethrough = true; 171 e3aff4f6Saliguori int c; 172 b32d7a39SMax Reitz int ret; 173 b543c5cdSMax Reitz QemuOpts *qopts; 174 443422fdSMarkus Armbruster QDict *opts; 175 459571f7SFam Zheng bool force_share = false; 176 e3aff4f6Saliguori 177 1c5a2aecSAarushi Mehta while ((c = getopt(argc, argv, "snCro:ki:t:d:U")) != -1) { 178 e3aff4f6Saliguori switch (c) { 179 e3aff4f6Saliguori case 's': 180 e3aff4f6Saliguori flags |= BDRV_O_SNAPSHOT; 181 e3aff4f6Saliguori break; 182 e3aff4f6Saliguori case 'n': 183 e151fc16SKevin Wolf flags |= BDRV_O_NOCACHE; 184 e151fc16SKevin Wolf writethrough = false; 185 e3aff4f6Saliguori break; 186 0f40444cSEric Blake case 'C': 187 0f40444cSEric Blake flags |= BDRV_O_COPY_ON_READ; 188 0f40444cSEric Blake break; 189 e3aff4f6Saliguori case 'r': 190 e3aff4f6Saliguori readonly = 1; 191 e3aff4f6Saliguori break; 192 b8d970f1SEric Blake case 'k': 193 b8d970f1SEric Blake flags |= BDRV_O_NATIVE_AIO; 194 b8d970f1SEric Blake break; 195 b8d970f1SEric Blake case 't': 196 b8d970f1SEric Blake if (bdrv_parse_cache_mode(optarg, &flags, &writethrough) < 0) { 197 b8d970f1SEric Blake error_report("Invalid cache option: %s", optarg); 198 b8d970f1SEric Blake qemu_opts_reset(&empty_opts); 199 b32d7a39SMax Reitz return -EINVAL; 200 b8d970f1SEric Blake } 201 b8d970f1SEric Blake break; 202 b8d970f1SEric Blake case 'd': 203 b8d970f1SEric Blake if (bdrv_parse_discard_flags(optarg, &flags) < 0) { 204 b8d970f1SEric Blake error_report("Invalid discard option: %s", optarg); 205 b8d970f1SEric Blake qemu_opts_reset(&empty_opts); 206 b32d7a39SMax Reitz return -EINVAL; 207 b8d970f1SEric Blake } 208 b8d970f1SEric Blake break; 209 1c5a2aecSAarushi Mehta case 'i': 210 1c5a2aecSAarushi Mehta if (bdrv_parse_aio(optarg, &flags) < 0) { 211 1c5a2aecSAarushi Mehta error_report("Invalid aio option: %s", optarg); 212 1c5a2aecSAarushi Mehta qemu_opts_reset(&empty_opts); 213 1c5a2aecSAarushi Mehta return -EINVAL; 214 1c5a2aecSAarushi Mehta } 215 1c5a2aecSAarushi Mehta break; 216 b543c5cdSMax Reitz case 'o': 217 499afa25SDaniel P. Berrange if (imageOpts) { 218 499afa25SDaniel P. Berrange printf("--image-opts and 'open -o' are mutually exclusive\n"); 219 b8d970f1SEric Blake qemu_opts_reset(&empty_opts); 220 b32d7a39SMax Reitz return -EINVAL; 221 499afa25SDaniel P. Berrange } 222 70b94331SMarkus Armbruster if (!qemu_opts_parse_noisily(&empty_opts, optarg, false)) { 223 443422fdSMarkus Armbruster qemu_opts_reset(&empty_opts); 224 b32d7a39SMax Reitz return -EINVAL; 225 b543c5cdSMax Reitz } 226 b543c5cdSMax Reitz break; 227 459571f7SFam Zheng case 'U': 228 459571f7SFam Zheng force_share = true; 229 459571f7SFam Zheng break; 230 e3aff4f6Saliguori default: 231 443422fdSMarkus Armbruster qemu_opts_reset(&empty_opts); 232 b444d0e9SMax Reitz qemuio_command_usage(&open_cmd); 233 b32d7a39SMax Reitz return -EINVAL; 234 e3aff4f6Saliguori } 235 e3aff4f6Saliguori } 236 e3aff4f6Saliguori 237 f5edb014SNaphtali Sprei if (!readonly) { 238 e3aff4f6Saliguori flags |= BDRV_O_RDWR; 239 f5edb014SNaphtali Sprei } 240 e3aff4f6Saliguori 241 499afa25SDaniel P. Berrange if (imageOpts && (optind == argc - 1)) { 242 499afa25SDaniel P. Berrange if (!qemu_opts_parse_noisily(&empty_opts, argv[optind], false)) { 243 499afa25SDaniel P. Berrange qemu_opts_reset(&empty_opts); 244 b32d7a39SMax Reitz return -EINVAL; 245 499afa25SDaniel P. Berrange } 246 499afa25SDaniel P. Berrange optind++; 247 499afa25SDaniel P. Berrange } 248 499afa25SDaniel P. Berrange 249 443422fdSMarkus Armbruster qopts = qemu_opts_find(&empty_opts, NULL); 250 443422fdSMarkus Armbruster opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : NULL; 251 443422fdSMarkus Armbruster qemu_opts_reset(&empty_opts); 252 443422fdSMarkus Armbruster 253 fd0fee34SMax Reitz if (optind == argc - 1) { 254 b32d7a39SMax Reitz ret = openfile(argv[optind], flags, writethrough, force_share, opts); 255 fd0fee34SMax Reitz } else if (optind == argc) { 256 b32d7a39SMax Reitz ret = openfile(NULL, flags, writethrough, force_share, opts); 257 fd0fee34SMax Reitz } else { 258 cb3e7f08SMarc-André Lureau qobject_unref(opts); 259 64ebf556SEric Blake qemuio_command_usage(&open_cmd); 260 b32d7a39SMax Reitz return -EINVAL; 261 e3aff4f6Saliguori } 262 e3aff4f6Saliguori 263 b32d7a39SMax Reitz if (ret) { 264 b32d7a39SMax Reitz return -EINVAL; 265 b32d7a39SMax Reitz } 266 b32d7a39SMax Reitz 267 b32d7a39SMax Reitz return 0; 268 b32d7a39SMax Reitz } 269 b32d7a39SMax Reitz 270 b32d7a39SMax Reitz static int quit_f(BlockBackend *blk, int argc, char **argv) 271 e681be7eSKevin Wolf { 272 b444d0e9SMax Reitz quit_qemu_io = true; 273 b32d7a39SMax Reitz return 0; 274 e681be7eSKevin Wolf } 275 e681be7eSKevin Wolf 276 e681be7eSKevin Wolf static const cmdinfo_t quit_cmd = { 277 e681be7eSKevin Wolf .name = "quit", 278 e681be7eSKevin Wolf .altname = "q", 279 e681be7eSKevin Wolf .cfunc = quit_f, 280 e681be7eSKevin Wolf .argmin = -1, 281 e681be7eSKevin Wolf .argmax = -1, 282 e681be7eSKevin Wolf .flags = CMD_FLAG_GLOBAL, 283 e681be7eSKevin Wolf .oneline = "exit the program", 284 e681be7eSKevin Wolf }; 285 e681be7eSKevin Wolf 286 e3aff4f6Saliguori static void usage(const char *name) 287 e3aff4f6Saliguori { 288 e3aff4f6Saliguori printf( 289 e4e12bb2SEric Blake "Usage: %s [OPTIONS]... [-c STRING]... [file]\n" 290 84844a20SStefan Weil "QEMU Disk exerciser\n" 291 e3aff4f6Saliguori "\n" 292 9ba371b6SDaniel P. Berrange " --object OBJECTDEF define an object such as 'secret' for\n" 293 9ba371b6SDaniel P. Berrange " passwords and/or encryption keys\n" 294 e4e12bb2SEric Blake " --image-opts treat file as option string\n" 295 d208cc35SMaria Kustova " -c, --cmd STRING execute command with its arguments\n" 296 d208cc35SMaria Kustova " from the given string\n" 297 be6273daSKevin Wolf " -f, --format FMT specifies the block driver to use\n" 298 e3aff4f6Saliguori " -r, --read-only export read-only\n" 299 e3aff4f6Saliguori " -s, --snapshot use snapshot file\n" 300 e4e12bb2SEric Blake " -n, --nocache disable host cache, short for -t none\n" 301 0f40444cSEric Blake " -C, --copy-on-read enable copy-on-read\n" 302 e3aff4f6Saliguori " -m, --misalign misalign allocations for O_DIRECT\n" 303 1c5a2aecSAarushi Mehta " -k, --native-aio use kernel AIO implementation\n" 304 1c5a2aecSAarushi Mehta " (Linux only, prefer use of -i)\n" 305 1c5a2aecSAarushi Mehta " -i, --aio=MODE use AIO mode (threads, native or io_uring)\n" 306 592fa070SKevin Wolf " -t, --cache=MODE use the given cache mode for the image\n" 307 e4e12bb2SEric Blake " -d, --discard=MODE use the given discard mode for the image\n" 308 e9a80859SDenis V. Lunev " -T, --trace [[enable=]<pattern>][,events=<file>][,file=<file>]\n" 309 e9a80859SDenis V. Lunev " specify tracing options\n" 310 e9a80859SDenis V. Lunev " see qemu-img(1) man page for full description\n" 311 459571f7SFam Zheng " -U, --force-share force shared permissions\n" 312 e3aff4f6Saliguori " -h, --help display this help and exit\n" 313 e3aff4f6Saliguori " -V, --version output version information and exit\n" 314 d208cc35SMaria Kustova "\n" 315 f5048cb7SEric Blake "See '%s -c help' for information on available commands.\n" 316 f5048cb7SEric Blake "\n" 317 f5048cb7SEric Blake QEMU_HELP_BOTTOM "\n", 318 d208cc35SMaria Kustova name, name); 319 e3aff4f6Saliguori } 320 e3aff4f6Saliguori 321 d1174f13SKevin Wolf static char *get_prompt(void) 322 d1174f13SKevin Wolf { 323 d1174f13SKevin Wolf static char prompt[FILENAME_MAX + 2 /*"> "*/ + 1 /*"\0"*/ ]; 324 d1174f13SKevin Wolf 325 d1174f13SKevin Wolf if (!prompt[0]) { 326 99e98d7cSChristophe Fergeau snprintf(prompt, sizeof(prompt), "%s> ", error_get_progname()); 327 d1174f13SKevin Wolf } 328 d1174f13SKevin Wolf 329 d1174f13SKevin Wolf return prompt; 330 d1174f13SKevin Wolf } 331 d1174f13SKevin Wolf 332 *9edc6313SMarc-André Lureau static void G_GNUC_PRINTF(2, 3) readline_printf_func(void *opaque, 333 d5d1507bSStefan Weil const char *fmt, ...) 334 d1174f13SKevin Wolf { 335 0cf17e18SStefan Hajnoczi va_list ap; 336 0cf17e18SStefan Hajnoczi va_start(ap, fmt); 337 0cf17e18SStefan Hajnoczi vprintf(fmt, ap); 338 0cf17e18SStefan Hajnoczi va_end(ap); 339 0cf17e18SStefan Hajnoczi } 340 0cf17e18SStefan Hajnoczi 341 0cf17e18SStefan Hajnoczi static void readline_flush_func(void *opaque) 342 0cf17e18SStefan Hajnoczi { 343 0cf17e18SStefan Hajnoczi fflush(stdout); 344 0cf17e18SStefan Hajnoczi } 345 0cf17e18SStefan Hajnoczi 346 0cf17e18SStefan Hajnoczi static void readline_func(void *opaque, const char *str, void *readline_opaque) 347 0cf17e18SStefan Hajnoczi { 348 0cf17e18SStefan Hajnoczi char **line = readline_opaque; 349 0cf17e18SStefan Hajnoczi *line = g_strdup(str); 350 0cf17e18SStefan Hajnoczi } 351 0cf17e18SStefan Hajnoczi 352 4694020dSStefan Hajnoczi static void completion_match(const char *cmd, void *opaque) 353 4694020dSStefan Hajnoczi { 354 4694020dSStefan Hajnoczi readline_add_completion(readline_state, cmd); 355 4694020dSStefan Hajnoczi } 356 4694020dSStefan Hajnoczi 357 0cf17e18SStefan Hajnoczi static void readline_completion_func(void *opaque, const char *str) 358 0cf17e18SStefan Hajnoczi { 359 4694020dSStefan Hajnoczi readline_set_completion_index(readline_state, strlen(str)); 360 4694020dSStefan Hajnoczi qemuio_complete_command(str, completion_match, NULL); 361 0cf17e18SStefan Hajnoczi } 362 0cf17e18SStefan Hajnoczi 363 0cf17e18SStefan Hajnoczi static char *fetchline_readline(void) 364 0cf17e18SStefan Hajnoczi { 365 0cf17e18SStefan Hajnoczi char *line = NULL; 366 0cf17e18SStefan Hajnoczi 367 0cf17e18SStefan Hajnoczi readline_start(readline_state, get_prompt(), 0, readline_func, &line); 368 0cf17e18SStefan Hajnoczi while (!line) { 369 0cf17e18SStefan Hajnoczi int ch = getchar(); 370 0e448a05SDaniel P. Berrange if (ttyEOF != 0x0 && ch == ttyEOF) { 371 0e448a05SDaniel P. Berrange printf("\n"); 372 0cf17e18SStefan Hajnoczi break; 373 0cf17e18SStefan Hajnoczi } 374 0cf17e18SStefan Hajnoczi readline_handle_byte(readline_state, ch); 375 d1174f13SKevin Wolf } 376 d1174f13SKevin Wolf return line; 377 d1174f13SKevin Wolf } 378 d1174f13SKevin Wolf 379 d1174f13SKevin Wolf #define MAXREADLINESZ 1024 380 0cf17e18SStefan Hajnoczi static char *fetchline_fgets(void) 381 d1174f13SKevin Wolf { 382 d1174f13SKevin Wolf char *p, *line = g_malloc(MAXREADLINESZ); 383 d1174f13SKevin Wolf 384 d1174f13SKevin Wolf if (!fgets(line, MAXREADLINESZ, stdin)) { 385 d1174f13SKevin Wolf g_free(line); 386 d1174f13SKevin Wolf return NULL; 387 d1174f13SKevin Wolf } 388 d1174f13SKevin Wolf 389 d1174f13SKevin Wolf p = line + strlen(line); 390 d1174f13SKevin Wolf if (p != line && p[-1] == '\n') { 391 d1174f13SKevin Wolf p[-1] = '\0'; 392 d1174f13SKevin Wolf } 393 d1174f13SKevin Wolf 394 d1174f13SKevin Wolf return line; 395 d1174f13SKevin Wolf } 396 0cf17e18SStefan Hajnoczi 397 0cf17e18SStefan Hajnoczi static char *fetchline(void) 398 0cf17e18SStefan Hajnoczi { 399 0cf17e18SStefan Hajnoczi if (readline_state) { 400 0cf17e18SStefan Hajnoczi return fetchline_readline(); 401 0cf17e18SStefan Hajnoczi } else { 402 0cf17e18SStefan Hajnoczi return fetchline_fgets(); 403 0cf17e18SStefan Hajnoczi } 404 0cf17e18SStefan Hajnoczi } 405 d1174f13SKevin Wolf 406 d1174f13SKevin Wolf static void prep_fetchline(void *opaque) 407 d1174f13SKevin Wolf { 408 d1174f13SKevin Wolf int *fetchable = opaque; 409 d1174f13SKevin Wolf 410 d1174f13SKevin Wolf qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL); 411 d1174f13SKevin Wolf *fetchable= 1; 412 d1174f13SKevin Wolf } 413 d1174f13SKevin Wolf 414 78632a3dSVladimir Sementsov-Ogievskiy static int do_qemuio_command(const char *cmd) 415 78632a3dSVladimir Sementsov-Ogievskiy { 416 78632a3dSVladimir Sementsov-Ogievskiy int ret; 417 78632a3dSVladimir Sementsov-Ogievskiy AioContext *ctx = 418 78632a3dSVladimir Sementsov-Ogievskiy qemuio_blk ? blk_get_aio_context(qemuio_blk) : qemu_get_aio_context(); 419 78632a3dSVladimir Sementsov-Ogievskiy 420 78632a3dSVladimir Sementsov-Ogievskiy aio_context_acquire(ctx); 421 78632a3dSVladimir Sementsov-Ogievskiy ret = qemuio_command(qemuio_blk, cmd); 422 78632a3dSVladimir Sementsov-Ogievskiy aio_context_release(ctx); 423 78632a3dSVladimir Sementsov-Ogievskiy 424 78632a3dSVladimir Sementsov-Ogievskiy return ret; 425 78632a3dSVladimir Sementsov-Ogievskiy } 426 78632a3dSVladimir Sementsov-Ogievskiy 427 6b3aa848SMax Reitz static int command_loop(void) 428 d1174f13SKevin Wolf { 429 b444d0e9SMax Reitz int i, fetchable = 0, prompted = 0; 430 6b3aa848SMax Reitz int ret, last_error = 0; 431 d1174f13SKevin Wolf char *input; 432 d1174f13SKevin Wolf 433 b444d0e9SMax Reitz for (i = 0; !quit_qemu_io && i < ncmdline; i++) { 434 78632a3dSVladimir Sementsov-Ogievskiy ret = do_qemuio_command(cmdline[i]); 435 6b3aa848SMax Reitz if (ret < 0) { 436 6b3aa848SMax Reitz last_error = ret; 437 6b3aa848SMax Reitz } 438 d1174f13SKevin Wolf } 439 d1174f13SKevin Wolf if (cmdline) { 440 d1174f13SKevin Wolf g_free(cmdline); 441 6b3aa848SMax Reitz return last_error; 442 d1174f13SKevin Wolf } 443 d1174f13SKevin Wolf 444 b444d0e9SMax Reitz while (!quit_qemu_io) { 445 d1174f13SKevin Wolf if (!prompted) { 446 d1174f13SKevin Wolf printf("%s", get_prompt()); 447 d1174f13SKevin Wolf fflush(stdout); 448 d1174f13SKevin Wolf qemu_set_fd_handler(STDIN_FILENO, prep_fetchline, NULL, &fetchable); 449 d1174f13SKevin Wolf prompted = 1; 450 d1174f13SKevin Wolf } 451 d1174f13SKevin Wolf 452 d1174f13SKevin Wolf main_loop_wait(false); 453 d1174f13SKevin Wolf 454 d1174f13SKevin Wolf if (!fetchable) { 455 d1174f13SKevin Wolf continue; 456 d1174f13SKevin Wolf } 457 d1174f13SKevin Wolf 458 d1174f13SKevin Wolf input = fetchline(); 459 d1174f13SKevin Wolf if (input == NULL) { 460 d1174f13SKevin Wolf break; 461 d1174f13SKevin Wolf } 462 78632a3dSVladimir Sementsov-Ogievskiy ret = do_qemuio_command(input); 463 d1174f13SKevin Wolf g_free(input); 464 d1174f13SKevin Wolf 465 6b3aa848SMax Reitz if (ret < 0) { 466 6b3aa848SMax Reitz last_error = ret; 467 6b3aa848SMax Reitz } 468 6b3aa848SMax Reitz 469 d1174f13SKevin Wolf prompted = 0; 470 d1174f13SKevin Wolf fetchable = 0; 471 d1174f13SKevin Wolf } 472 d1174f13SKevin Wolf qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL); 473 6b3aa848SMax Reitz 474 6b3aa848SMax Reitz return last_error; 475 d1174f13SKevin Wolf } 476 d1174f13SKevin Wolf 477 d1174f13SKevin Wolf static void add_user_command(char *optarg) 478 d1174f13SKevin Wolf { 479 5839e53bSMarkus Armbruster cmdline = g_renew(char *, cmdline, ++ncmdline); 480 d1174f13SKevin Wolf cmdline[ncmdline-1] = optarg; 481 d1174f13SKevin Wolf } 482 d1174f13SKevin Wolf 483 0cf17e18SStefan Hajnoczi static void reenable_tty_echo(void) 484 0cf17e18SStefan Hajnoczi { 485 0cf17e18SStefan Hajnoczi qemu_set_tty_echo(STDIN_FILENO, true); 486 0cf17e18SStefan Hajnoczi } 487 0cf17e18SStefan Hajnoczi 488 9ba371b6SDaniel P. Berrange enum { 489 9ba371b6SDaniel P. Berrange OPTION_OBJECT = 256, 490 499afa25SDaniel P. Berrange OPTION_IMAGE_OPTS = 257, 491 9ba371b6SDaniel P. Berrange }; 492 9ba371b6SDaniel P. Berrange 493 499afa25SDaniel P. Berrange static QemuOptsList file_opts = { 494 499afa25SDaniel P. Berrange .name = "file", 495 499afa25SDaniel P. Berrange .implied_opt_name = "file", 496 499afa25SDaniel P. Berrange .head = QTAILQ_HEAD_INITIALIZER(file_opts.head), 497 499afa25SDaniel P. Berrange .desc = { 498 499afa25SDaniel P. Berrange /* no elements => accept any params */ 499 499afa25SDaniel P. Berrange { /* end of list */ } 500 499afa25SDaniel P. Berrange }, 501 499afa25SDaniel P. Berrange }; 502 499afa25SDaniel P. Berrange 503 e3aff4f6Saliguori int main(int argc, char **argv) 504 e3aff4f6Saliguori { 505 e3aff4f6Saliguori int readonly = 0; 506 1c5a2aecSAarushi Mehta const char *sopt = "hVc:d:f:rsnCmki:t:T:U"; 507 b32bb952SBlue Swirl const struct option lopt[] = { 508 a513416eSDaniel P. Berrange { "help", no_argument, NULL, 'h' }, 509 a513416eSDaniel P. Berrange { "version", no_argument, NULL, 'V' }, 510 a513416eSDaniel P. Berrange { "cmd", required_argument, NULL, 'c' }, 511 a513416eSDaniel P. Berrange { "format", required_argument, NULL, 'f' }, 512 a513416eSDaniel P. Berrange { "read-only", no_argument, NULL, 'r' }, 513 a513416eSDaniel P. Berrange { "snapshot", no_argument, NULL, 's' }, 514 a513416eSDaniel P. Berrange { "nocache", no_argument, NULL, 'n' }, 515 0f40444cSEric Blake { "copy-on-read", no_argument, NULL, 'C' }, 516 a513416eSDaniel P. Berrange { "misalign", no_argument, NULL, 'm' }, 517 a513416eSDaniel P. Berrange { "native-aio", no_argument, NULL, 'k' }, 518 1c5a2aecSAarushi Mehta { "aio", required_argument, NULL, 'i' }, 519 a513416eSDaniel P. Berrange { "discard", required_argument, NULL, 'd' }, 520 a513416eSDaniel P. Berrange { "cache", required_argument, NULL, 't' }, 521 a513416eSDaniel P. Berrange { "trace", required_argument, NULL, 'T' }, 522 a513416eSDaniel P. Berrange { "object", required_argument, NULL, OPTION_OBJECT }, 523 a513416eSDaniel P. Berrange { "image-opts", no_argument, NULL, OPTION_IMAGE_OPTS }, 524 459571f7SFam Zheng { "force-share", no_argument, 0, 'U'}, 525 660f11beSBlue Swirl { NULL, 0, NULL, 0 } 526 e3aff4f6Saliguori }; 527 e3aff4f6Saliguori int c; 528 e3aff4f6Saliguori int opt_index = 0; 529 9e8f1835SPaolo Bonzini int flags = BDRV_O_UNMAP; 530 6b3aa848SMax Reitz int ret; 531 e151fc16SKevin Wolf bool writethrough = true; 532 1b58b438SMax Reitz QDict *opts = NULL; 533 499afa25SDaniel P. Berrange const char *format = NULL; 534 459571f7SFam Zheng bool force_share = false; 535 e3aff4f6Saliguori 536 526eda14SMORITA Kazutaka #ifdef CONFIG_POSIX 537 526eda14SMORITA Kazutaka signal(SIGPIPE, SIG_IGN); 538 526eda14SMORITA Kazutaka #endif 539 526eda14SMORITA Kazutaka 540 98c5d2e7SDaniel P. Berrangé socket_init(); 541 f5852efaSChristophe Fergeau error_init(argv[0]); 542 fe4db84dSDaniel P. Berrange module_call_init(MODULE_INIT_TRACE); 543 10f5bff6SFam Zheng qemu_init_exec_dir(argv[0]); 544 e3aff4f6Saliguori 545 e8f2d272SEduardo Habkost qcrypto_init(&error_fatal); 546 c2297088SDaniel P. Berrange 547 064097d9SDaniel P. Berrange module_call_init(MODULE_INIT_QOM); 548 e9a80859SDenis V. Lunev qemu_add_opts(&qemu_trace_opts); 549 be6273daSKevin Wolf bdrv_init(); 550 be6273daSKevin Wolf 551 e3aff4f6Saliguori while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) { 552 e3aff4f6Saliguori switch (c) { 553 e3aff4f6Saliguori case 's': 554 e3aff4f6Saliguori flags |= BDRV_O_SNAPSHOT; 555 e3aff4f6Saliguori break; 556 e3aff4f6Saliguori case 'n': 557 e151fc16SKevin Wolf flags |= BDRV_O_NOCACHE; 558 e151fc16SKevin Wolf writethrough = false; 559 e3aff4f6Saliguori break; 560 0f40444cSEric Blake case 'C': 561 0f40444cSEric Blake flags |= BDRV_O_COPY_ON_READ; 562 0f40444cSEric Blake break; 563 9e8f1835SPaolo Bonzini case 'd': 564 9e8f1835SPaolo Bonzini if (bdrv_parse_discard_flags(optarg, &flags) < 0) { 565 9e8f1835SPaolo Bonzini error_report("Invalid discard option: %s", optarg); 566 9e8f1835SPaolo Bonzini exit(1); 567 9e8f1835SPaolo Bonzini } 568 9e8f1835SPaolo Bonzini break; 569 be6273daSKevin Wolf case 'f': 570 499afa25SDaniel P. Berrange format = optarg; 571 be6273daSKevin Wolf break; 572 e3aff4f6Saliguori case 'c': 573 e3aff4f6Saliguori add_user_command(optarg); 574 e3aff4f6Saliguori break; 575 e3aff4f6Saliguori case 'r': 576 e3aff4f6Saliguori readonly = 1; 577 e3aff4f6Saliguori break; 578 e3aff4f6Saliguori case 'm': 579 f9883880SStefan Weil qemuio_misalign = true; 580 e3aff4f6Saliguori break; 581 5c6c3a6cSChristoph Hellwig case 'k': 582 5c6c3a6cSChristoph Hellwig flags |= BDRV_O_NATIVE_AIO; 583 5c6c3a6cSChristoph Hellwig break; 584 1c5a2aecSAarushi Mehta case 'i': 585 1c5a2aecSAarushi Mehta if (bdrv_parse_aio(optarg, &flags) < 0) { 586 1c5a2aecSAarushi Mehta error_report("Invalid aio option: %s", optarg); 587 1c5a2aecSAarushi Mehta exit(1); 588 1c5a2aecSAarushi Mehta } 589 1c5a2aecSAarushi Mehta break; 590 592fa070SKevin Wolf case 't': 591 e151fc16SKevin Wolf if (bdrv_parse_cache_mode(optarg, &flags, &writethrough) < 0) { 592 592fa070SKevin Wolf error_report("Invalid cache option: %s", optarg); 593 592fa070SKevin Wolf exit(1); 594 592fa070SKevin Wolf } 595 592fa070SKevin Wolf break; 596 d7bb72c8SStefan Hajnoczi case 'T': 597 92eecfffSPaolo Bonzini trace_opt_parse(optarg); 598 d7bb72c8SStefan Hajnoczi break; 599 e3aff4f6Saliguori case 'V': 600 7e563bfbSThomas Huth printf("%s version " QEMU_FULL_VERSION "\n" 601 99e98d7cSChristophe Fergeau QEMU_COPYRIGHT "\n", error_get_progname()); 602 e3aff4f6Saliguori exit(0); 603 e3aff4f6Saliguori case 'h': 604 99e98d7cSChristophe Fergeau usage(error_get_progname()); 605 e3aff4f6Saliguori exit(0); 606 459571f7SFam Zheng case 'U': 607 459571f7SFam Zheng force_share = true; 608 459571f7SFam Zheng break; 609 b3e79bc6SKevin Wolf case OPTION_OBJECT: 610 b3e79bc6SKevin Wolf user_creatable_process_cmdline(optarg); 611 b3e79bc6SKevin Wolf break; 612 499afa25SDaniel P. Berrange case OPTION_IMAGE_OPTS: 613 499afa25SDaniel P. Berrange imageOpts = true; 614 499afa25SDaniel P. Berrange break; 615 e3aff4f6Saliguori default: 616 99e98d7cSChristophe Fergeau usage(error_get_progname()); 617 e3aff4f6Saliguori exit(1); 618 e3aff4f6Saliguori } 619 e3aff4f6Saliguori } 620 e3aff4f6Saliguori 621 e3aff4f6Saliguori if ((argc - optind) > 1) { 622 99e98d7cSChristophe Fergeau usage(error_get_progname()); 623 e3aff4f6Saliguori exit(1); 624 e3aff4f6Saliguori } 625 e3aff4f6Saliguori 626 499afa25SDaniel P. Berrange if (format && imageOpts) { 627 499afa25SDaniel P. Berrange error_report("--image-opts and -f are mutually exclusive"); 628 499afa25SDaniel P. Berrange exit(1); 629 499afa25SDaniel P. Berrange } 630 499afa25SDaniel P. Berrange 631 f9734d5dSMarkus Armbruster qemu_init_main_loop(&error_fatal); 632 a57d1143SZhi Yong Wu 633 e9a80859SDenis V. Lunev if (!trace_init_backends()) { 634 e9a80859SDenis V. Lunev exit(1); 635 e9a80859SDenis V. Lunev } 636 92eecfffSPaolo Bonzini trace_init_file(); 637 e9a80859SDenis V. Lunev qemu_set_log(LOG_TRACE); 638 e9a80859SDenis V. Lunev 639 e3aff4f6Saliguori /* initialize commands */ 640 c2cdf5c5SKevin Wolf qemuio_add_command(&quit_cmd); 641 c2cdf5c5SKevin Wolf qemuio_add_command(&open_cmd); 642 c2cdf5c5SKevin Wolf qemuio_add_command(&close_cmd); 643 e3aff4f6Saliguori 644 0cf17e18SStefan Hajnoczi if (isatty(STDIN_FILENO)) { 645 0e448a05SDaniel P. Berrange ttyEOF = get_eof_char(); 646 0cf17e18SStefan Hajnoczi readline_state = readline_init(readline_printf_func, 647 0cf17e18SStefan Hajnoczi readline_flush_func, 648 0cf17e18SStefan Hajnoczi NULL, 649 0cf17e18SStefan Hajnoczi readline_completion_func); 650 0cf17e18SStefan Hajnoczi qemu_set_tty_echo(STDIN_FILENO, false); 651 0cf17e18SStefan Hajnoczi atexit(reenable_tty_echo); 652 0cf17e18SStefan Hajnoczi } 653 0cf17e18SStefan Hajnoczi 654 e3aff4f6Saliguori /* open the device */ 655 f5edb014SNaphtali Sprei if (!readonly) { 656 e3aff4f6Saliguori flags |= BDRV_O_RDWR; 657 f5edb014SNaphtali Sprei } 658 e3aff4f6Saliguori 659 43642b38SDevin Nakamura if ((argc - optind) == 1) { 660 499afa25SDaniel P. Berrange if (imageOpts) { 661 499afa25SDaniel P. Berrange QemuOpts *qopts = NULL; 662 499afa25SDaniel P. Berrange qopts = qemu_opts_parse_noisily(&file_opts, argv[optind], false); 663 499afa25SDaniel P. Berrange if (!qopts) { 664 499afa25SDaniel P. Berrange exit(1); 665 499afa25SDaniel P. Berrange } 666 499afa25SDaniel P. Berrange opts = qemu_opts_to_qdict(qopts, NULL); 667 459571f7SFam Zheng if (openfile(NULL, flags, writethrough, force_share, opts)) { 668 b7aa1315SNir Soffer exit(1); 669 b7aa1315SNir Soffer } 670 499afa25SDaniel P. Berrange } else { 671 499afa25SDaniel P. Berrange if (format) { 672 499afa25SDaniel P. Berrange opts = qdict_new(); 673 46f5ac20SEric Blake qdict_put_str(opts, "driver", format); 674 499afa25SDaniel P. Berrange } 675 459571f7SFam Zheng if (openfile(argv[optind], flags, writethrough, 676 459571f7SFam Zheng force_share, opts)) { 677 b7aa1315SNir Soffer exit(1); 678 b7aa1315SNir Soffer } 679 43642b38SDevin Nakamura } 680 499afa25SDaniel P. Berrange } 681 6b3aa848SMax Reitz ret = command_loop(); 682 e3aff4f6Saliguori 683 95533d5fSChristoph Hellwig /* 684 922453bcSStefan Hajnoczi * Make sure all outstanding requests complete before the program exits. 685 95533d5fSChristoph Hellwig */ 686 922453bcSStefan Hajnoczi bdrv_drain_all(); 687 95533d5fSChristoph Hellwig 688 26f54e9aSMarkus Armbruster blk_unref(qemuio_blk); 689 0cf17e18SStefan Hajnoczi g_free(readline_state); 690 6b3aa848SMax Reitz 691 6b3aa848SMax Reitz if (ret < 0) { 692 6b3aa848SMax Reitz return 1; 693 6b3aa848SMax Reitz } else { 694 e3aff4f6Saliguori return 0; 695 e3aff4f6Saliguori } 696 6b3aa848SMax Reitz } 697