xref: /qemu/qemu-io.c (revision 9edc6313da34699ebd2bae4573ea22339b26450a)
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