Commit e3aff4f611bd920768f616e8275945a2adecb6d5

Authored by aliguori
1 parent 178e08a5

Add files not included in previous commit.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6995 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 3 changed files with 1717 additions and 0 deletions
cmd.c 0 → 100644
  1 +/*
  2 + * Copyright (c) 2003-2005 Silicon Graphics, Inc.
  3 + * All Rights Reserved.
  4 + *
  5 + * This program is free software; you can redistribute it and/or
  6 + * modify it under the terms of the GNU General Public License as
  7 + * published by the Free Software Foundation.
  8 + *
  9 + * This program is distributed in the hope that it would be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12 + * GNU General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU General Public License
  15 + * along with this program; if not, write the Free Software Foundation,
  16 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  17 + */
  18 +
  19 +#include <stdio.h>
  20 +#include <stdlib.h>
  21 +#include <string.h>
  22 +#include <ctype.h>
  23 +#include <errno.h>
  24 +
  25 +#include "cmd.h"
  26 +
  27 +#define _(x) x /* not gettext support yet */
  28 +
  29 +extern int optind;
  30 +
  31 +/* from libxcmd/command.c */
  32 +
  33 +cmdinfo_t *cmdtab;
  34 +int ncmds;
  35 +
  36 +static argsfunc_t args_func;
  37 +static checkfunc_t check_func;
  38 +static int ncmdline;
  39 +static char **cmdline;
  40 +
  41 +static int
  42 +compare(const void *a, const void *b)
  43 +{
  44 + return strcmp(((const cmdinfo_t *)a)->name,
  45 + ((const cmdinfo_t *)b)->name);
  46 +}
  47 +
  48 +void
  49 +add_command(
  50 + const cmdinfo_t *ci)
  51 +{
  52 + cmdtab = realloc((void *)cmdtab, ++ncmds * sizeof(*cmdtab));
  53 + cmdtab[ncmds - 1] = *ci;
  54 + qsort(cmdtab, ncmds, sizeof(*cmdtab), compare);
  55 +}
  56 +
  57 +static int
  58 +check_command(
  59 + const cmdinfo_t *ci)
  60 +{
  61 + if (check_func)
  62 + return check_func(ci);
  63 + return 1;
  64 +}
  65 +
  66 +void
  67 +add_check_command(
  68 + checkfunc_t cf)
  69 +{
  70 + check_func = cf;
  71 +}
  72 +
  73 +int
  74 +command_usage(
  75 + const cmdinfo_t *ci)
  76 +{
  77 + printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
  78 + return 0;
  79 +}
  80 +
  81 +int
  82 +command(
  83 + const cmdinfo_t *ct,
  84 + int argc,
  85 + char **argv)
  86 +{
  87 + char *cmd = argv[0];
  88 +
  89 + if (!check_command(ct))
  90 + return 0;
  91 +
  92 + if (argc-1 < ct->argmin || (ct->argmax != -1 && argc-1 > ct->argmax)) {
  93 + if (ct->argmax == -1)
  94 + fprintf(stderr,
  95 + _("bad argument count %d to %s, expected at least %d arguments\n"),
  96 + argc-1, cmd, ct->argmin);
  97 + else if (ct->argmin == ct->argmax)
  98 + fprintf(stderr,
  99 + _("bad argument count %d to %s, expected %d arguments\n"),
  100 + argc-1, cmd, ct->argmin);
  101 + else
  102 + fprintf(stderr,
  103 + _("bad argument count %d to %s, expected between %d and %d arguments\n"),
  104 + argc-1, cmd, ct->argmin, ct->argmax);
  105 + return 0;
  106 + }
  107 + optind = 0;
  108 + return ct->cfunc(argc, argv);
  109 +}
  110 +
  111 +const cmdinfo_t *
  112 +find_command(
  113 + const char *cmd)
  114 +{
  115 + cmdinfo_t *ct;
  116 +
  117 + for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
  118 + if (strcmp(ct->name, cmd) == 0 ||
  119 + (ct->altname && strcmp(ct->altname, cmd) == 0))
  120 + return (const cmdinfo_t *)ct;
  121 + }
  122 + return NULL;
  123 +}
  124 +
  125 +void
  126 +add_user_command(char *optarg)
  127 +{
  128 + ncmdline++;
  129 + cmdline = realloc(cmdline, sizeof(char*) * (ncmdline));
  130 + if (!cmdline) {
  131 + perror("realloc");
  132 + exit(1);
  133 + }
  134 + cmdline[ncmdline-1] = optarg;
  135 +}
  136 +
  137 +static int
  138 +args_command(
  139 + int index)
  140 +{
  141 + if (args_func)
  142 + return args_func(index);
  143 + return 0;
  144 +}
  145 +
  146 +void
  147 +add_args_command(
  148 + argsfunc_t af)
  149 +{
  150 + args_func = af;
  151 +}
  152 +
  153 +void
  154 +command_loop(void)
  155 +{
  156 + int c, i, j = 0, done = 0;
  157 + char *input;
  158 + char **v;
  159 + const cmdinfo_t *ct;
  160 +
  161 + for (i = 0; !done && i < ncmdline; i++) {
  162 + input = strdup(cmdline[i]);
  163 + if (!input) {
  164 + fprintf(stderr,
  165 + _("cannot strdup command '%s': %s\n"),
  166 + cmdline[i], strerror(errno));
  167 + exit(1);
  168 + }
  169 + v = breakline(input, &c);
  170 + if (c) {
  171 + ct = find_command(v[0]);
  172 + if (ct) {
  173 + if (ct->flags & CMD_FLAG_GLOBAL)
  174 + done = command(ct, c, v);
  175 + else {
  176 + j = 0;
  177 + while (!done && (j = args_command(j)))
  178 + done = command(ct, c, v);
  179 + }
  180 + } else
  181 + fprintf(stderr, _("command \"%s\" not found\n"),
  182 + v[0]);
  183 + }
  184 + doneline(input, v);
  185 + }
  186 + if (cmdline) {
  187 + free(cmdline);
  188 + return;
  189 + }
  190 + while (!done) {
  191 + if ((input = fetchline()) == NULL)
  192 + break;
  193 + v = breakline(input, &c);
  194 + if (c) {
  195 + ct = find_command(v[0]);
  196 + if (ct)
  197 + done = command(ct, c, v);
  198 + else
  199 + fprintf(stderr, _("command \"%s\" not found\n"),
  200 + v[0]);
  201 + }
  202 + doneline(input, v);
  203 + }
  204 +}
  205 +
  206 +/* from libxcmd/input.c */
  207 +
  208 +#if defined(ENABLE_READLINE)
  209 +# include <readline/history.h>
  210 +# include <readline/readline.h>
  211 +#elif defined(ENABLE_EDITLINE)
  212 +# include <histedit.h>
  213 +#endif
  214 +
  215 +extern char *progname;
  216 +
  217 +static char *
  218 +get_prompt(void)
  219 +{
  220 + static char prompt[FILENAME_MAX + 2 /*"> "*/ + 1 /*"\0"*/ ];
  221 +
  222 + if (!prompt[0])
  223 + snprintf(prompt, sizeof(prompt), "%s> ", progname);
  224 + return prompt;
  225 +}
  226 +
  227 +#if defined(ENABLE_READLINE)
  228 +char *
  229 +fetchline(void)
  230 +{
  231 + char *line;
  232 +
  233 + line = readline(get_prompt());
  234 + if (line && *line)
  235 + add_history(line);
  236 + return line;
  237 +}
  238 +#elif defined(ENABLE_EDITLINE)
  239 +static char *el_get_prompt(EditLine *e) { return get_prompt(); }
  240 +char *
  241 +fetchline(void)
  242 +{
  243 + static EditLine *el;
  244 + static History *hist;
  245 + HistEvent hevent;
  246 + char *line;
  247 + int count;
  248 +
  249 + if (!el) {
  250 + hist = history_init();
  251 + history(hist, &hevent, H_SETSIZE, 100);
  252 + el = el_init(progname, stdin, stdout, stderr);
  253 + el_source(el, NULL);
  254 + el_set(el, EL_SIGNAL, 1);
  255 + el_set(el, EL_PROMPT, el_get_prompt);
  256 + el_set(el, EL_HIST, history, (const char *)hist);
  257 + }
  258 + line = strdup(el_gets(el, &count));
  259 + if (line) {
  260 + if (count > 0)
  261 + line[count-1] = '\0';
  262 + if (*line)
  263 + history(hist, &hevent, H_ENTER, line);
  264 + }
  265 + return line;
  266 +}
  267 +#else
  268 +# define MAXREADLINESZ 1024
  269 +char *
  270 +fetchline(void)
  271 +{
  272 + char *p, *line = malloc(MAXREADLINESZ);
  273 +
  274 + if (!line)
  275 + return NULL;
  276 + printf("%s", get_prompt());
  277 + fflush(stdout);
  278 + if (!fgets(line, MAXREADLINESZ, stdin)) {
  279 + free(line);
  280 + return NULL;
  281 + }
  282 + p = line + strlen(line);
  283 + if (p != line && p[-1] == '\n')
  284 + p[-1] = '\0';
  285 + return line;
  286 +}
  287 +#endif
  288 +
  289 +char **
  290 +breakline(
  291 + char *input,
  292 + int *count)
  293 +{
  294 + int c = 0;
  295 + char *p;
  296 + char **rval = calloc(sizeof(char *), 1);
  297 +
  298 + while (rval && (p = strsep(&input, " ")) != NULL) {
  299 + if (!*p)
  300 + continue;
  301 + c++;
  302 + rval = realloc(rval, sizeof(*rval) * (c + 1));
  303 + if (!rval) {
  304 + c = 0;
  305 + break;
  306 + }
  307 + rval[c - 1] = p;
  308 + rval[c] = NULL;
  309 + }
  310 + *count = c;
  311 + return rval;
  312 +}
  313 +
  314 +void
  315 +doneline(
  316 + char *input,
  317 + char **vec)
  318 +{
  319 + free(input);
  320 + free(vec);
  321 +}
  322 +
  323 +#define EXABYTES(x) ((long long)(x) << 60)
  324 +#define PETABYTES(x) ((long long)(x) << 50)
  325 +#define TERABYTES(x) ((long long)(x) << 40)
  326 +#define GIGABYTES(x) ((long long)(x) << 30)
  327 +#define MEGABYTES(x) ((long long)(x) << 20)
  328 +#define KILOBYTES(x) ((long long)(x) << 10)
  329 +
  330 +long long
  331 +cvtnum(
  332 + char *s)
  333 +{
  334 + long long i;
  335 + char *sp;
  336 + int c;
  337 +
  338 + i = strtoll(s, &sp, 0);
  339 + if (i == 0 && sp == s)
  340 + return -1LL;
  341 + if (*sp == '\0')
  342 + return i;
  343 +
  344 + if (sp[1] != '\0')
  345 + return -1LL;
  346 +
  347 + c = tolower(*sp);
  348 + switch (c) {
  349 + default:
  350 + return i;
  351 + case 'k':
  352 + return KILOBYTES(i);
  353 + case 'm':
  354 + return MEGABYTES(i);
  355 + case 'g':
  356 + return GIGABYTES(i);
  357 + case 't':
  358 + return TERABYTES(i);
  359 + case 'p':
  360 + return PETABYTES(i);
  361 + case 'e':
  362 + return EXABYTES(i);
  363 + }
  364 + return -1LL;
  365 +}
  366 +
  367 +#define TO_EXABYTES(x) ((x) / EXABYTES(1))
  368 +#define TO_PETABYTES(x) ((x) / PETABYTES(1))
  369 +#define TO_TERABYTES(x) ((x) / TERABYTES(1))
  370 +#define TO_GIGABYTES(x) ((x) / GIGABYTES(1))
  371 +#define TO_MEGABYTES(x) ((x) / MEGABYTES(1))
  372 +#define TO_KILOBYTES(x) ((x) / KILOBYTES(1))
  373 +
  374 +void
  375 +cvtstr(
  376 + double value,
  377 + char *str,
  378 + size_t size)
  379 +{
  380 + const char *fmt;
  381 + int precise;
  382 +
  383 + precise = ((double)value * 1000 == (double)(int)value * 1000);
  384 +
  385 + if (value >= EXABYTES(1)) {
  386 + fmt = precise ? "%.f EiB" : "%.3f EiB";
  387 + snprintf(str, size, fmt, TO_EXABYTES(value));
  388 + } else if (value >= PETABYTES(1)) {
  389 + fmt = precise ? "%.f PiB" : "%.3f PiB";
  390 + snprintf(str, size, fmt, TO_PETABYTES(value));
  391 + } else if (value >= TERABYTES(1)) {
  392 + fmt = precise ? "%.f TiB" : "%.3f TiB";
  393 + snprintf(str, size, fmt, TO_TERABYTES(value));
  394 + } else if (value >= GIGABYTES(1)) {
  395 + fmt = precise ? "%.f GiB" : "%.3f GiB";
  396 + snprintf(str, size, fmt, TO_GIGABYTES(value));
  397 + } else if (value >= MEGABYTES(1)) {
  398 + fmt = precise ? "%.f MiB" : "%.3f MiB";
  399 + snprintf(str, size, fmt, TO_MEGABYTES(value));
  400 + } else if (value >= KILOBYTES(1)) {
  401 + fmt = precise ? "%.f KiB" : "%.3f KiB";
  402 + snprintf(str, size, fmt, TO_KILOBYTES(value));
  403 + } else {
  404 + snprintf(str, size, "%f bytes", value);
  405 + }
  406 +}
  407 +
  408 +struct timeval
  409 +tsub(struct timeval t1, struct timeval t2)
  410 +{
  411 + t1.tv_usec -= t2.tv_usec;
  412 + if (t1.tv_usec < 0) {
  413 + t1.tv_usec += 1000000;
  414 + t1.tv_sec--;
  415 + }
  416 + t1.tv_sec -= t2.tv_sec;
  417 + return t1;
  418 +}
  419 +
  420 +double
  421 +tdiv(double value, struct timeval tv)
  422 +{
  423 + return value / ((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0));
  424 +}
  425 +
  426 +#define HOURS(sec) ((sec) / (60 * 60))
  427 +#define MINUTES(sec) (((sec) % (60 * 60)) / 60)
  428 +#define SECONDS(sec) ((sec) % 60)
  429 +
  430 +void
  431 +timestr(
  432 + struct timeval *tv,
  433 + char *ts,
  434 + size_t size,
  435 + int format)
  436 +{
  437 + double usec = (double)tv->tv_usec / 1000000.0;
  438 +
  439 + if (format & TERSE_FIXED_TIME) {
  440 + if (!HOURS(tv->tv_sec)) {
  441 + snprintf(ts, size, "%u:%02u.%02u",
  442 + (unsigned int) MINUTES(tv->tv_sec),
  443 + (unsigned int) SECONDS(tv->tv_sec),
  444 + (unsigned int) usec * 100);
  445 + return;
  446 + }
  447 + format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */
  448 + }
  449 +
  450 + if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) {
  451 + snprintf(ts, size, "%u:%02u:%02u.%02u",
  452 + (unsigned int) HOURS(tv->tv_sec),
  453 + (unsigned int) MINUTES(tv->tv_sec),
  454 + (unsigned int) SECONDS(tv->tv_sec),
  455 + (unsigned int) usec * 100);
  456 + } else {
  457 + snprintf(ts, size, "0.%04u sec", (unsigned int) usec * 10000);
  458 + }
  459 +}
  460 +
  461 +
  462 +/* from libxcmd/quit.c */
  463 +
  464 +static cmdinfo_t quit_cmd;
  465 +
  466 +/* ARGSUSED */
  467 +static int
  468 +quit_f(
  469 + int argc,
  470 + char **argv)
  471 +{
  472 + return 1;
  473 +}
  474 +
  475 +void
  476 +quit_init(void)
  477 +{
  478 + quit_cmd.name = _("quit");
  479 + quit_cmd.altname = _("q");
  480 + quit_cmd.cfunc = quit_f;
  481 + quit_cmd.argmin = -1;
  482 + quit_cmd.argmax = -1;
  483 + quit_cmd.flags = CMD_FLAG_GLOBAL;
  484 + quit_cmd.oneline = _("exit the program");
  485 +
  486 + add_command(&quit_cmd);
  487 +}
  488 +
  489 +/* from libxcmd/help.c */
  490 +
  491 +static cmdinfo_t help_cmd;
  492 +static void help_onecmd(const char *cmd, const cmdinfo_t *ct);
  493 +static void help_oneline(const char *cmd, const cmdinfo_t *ct);
  494 +
  495 +static void
  496 +help_all(void)
  497 +{
  498 + const cmdinfo_t *ct;
  499 +
  500 + for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++)
  501 + help_oneline(ct->name, ct);
  502 + printf(_("\nUse 'help commandname' for extended help.\n"));
  503 +}
  504 +
  505 +static int
  506 +help_f(
  507 + int argc,
  508 + char **argv)
  509 +{
  510 + const cmdinfo_t *ct;
  511 +
  512 + if (argc == 1) {
  513 + help_all();
  514 + return 0;
  515 + }
  516 + ct = find_command(argv[1]);
  517 + if (ct == NULL) {
  518 + printf(_("command %s not found\n"), argv[1]);
  519 + return 0;
  520 + }
  521 + help_onecmd(argv[1], ct);
  522 + return 0;
  523 +}
  524 +
  525 +static void
  526 +help_onecmd(
  527 + const char *cmd,
  528 + const cmdinfo_t *ct)
  529 +{
  530 + help_oneline(cmd, ct);
  531 + if (ct->help)
  532 + ct->help();
  533 +}
  534 +
  535 +static void
  536 +help_oneline(
  537 + const char *cmd,
  538 + const cmdinfo_t *ct)
  539 +{
  540 + if (cmd)
  541 + printf("%s ", cmd);
  542 + else {
  543 + printf("%s ", ct->name);
  544 + if (ct->altname)
  545 + printf("(or %s) ", ct->altname);
  546 + }
  547 + if (ct->args)
  548 + printf("%s ", ct->args);
  549 + printf("-- %s\n", ct->oneline);
  550 +}
  551 +
  552 +void
  553 +help_init(void)
  554 +{
  555 + help_cmd.name = _("help");
  556 + help_cmd.altname = _("?");
  557 + help_cmd.cfunc = help_f;
  558 + help_cmd.argmin = 0;
  559 + help_cmd.argmax = 1;
  560 + help_cmd.flags = CMD_FLAG_GLOBAL;
  561 + help_cmd.args = _("[command]");
  562 + help_cmd.oneline = _("help for one or all commands");
  563 +
  564 + add_command(&help_cmd);
  565 +}
... ...
cmd.h 0 → 100644
  1 +/*
  2 + * Copyright (c) 2000-2005 Silicon Graphics, Inc.
  3 + * All Rights Reserved.
  4 + *
  5 + * This program is free software; you can redistribute it and/or
  6 + * modify it under the terms of the GNU General Public License as
  7 + * published by the Free Software Foundation.
  8 + *
  9 + * This program is distributed in the hope that it would be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12 + * GNU General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU General Public License
  15 + * along with this program; if not, write the Free Software Foundation,
  16 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  17 + */
  18 +#ifndef __COMMAND_H__
  19 +#define __COMMAND_H__
  20 +
  21 +#define CMD_FLAG_GLOBAL ((int)0x80000000) /* don't iterate "args" */
  22 +
  23 +typedef int (*cfunc_t)(int argc, char **argv);
  24 +typedef void (*helpfunc_t)(void);
  25 +
  26 +typedef struct cmdinfo {
  27 + const char *name;
  28 + const char *altname;
  29 + cfunc_t cfunc;
  30 + int argmin;
  31 + int argmax;
  32 + int canpush;
  33 + int flags;
  34 + const char *args;
  35 + const char *oneline;
  36 + helpfunc_t help;
  37 +} cmdinfo_t;
  38 +
  39 +extern cmdinfo_t *cmdtab;
  40 +extern int ncmds;
  41 +
  42 +extern void help_init(void);
  43 +extern void quit_init(void);
  44 +
  45 +typedef int (*argsfunc_t)(int index);
  46 +typedef int (*checkfunc_t)(const cmdinfo_t *ci);
  47 +
  48 +extern void add_command(const cmdinfo_t *ci);
  49 +extern void add_user_command(char *optarg);
  50 +extern void add_args_command(argsfunc_t af);
  51 +extern void add_check_command(checkfunc_t cf);
  52 +
  53 +extern const cmdinfo_t *find_command(const char *cmd);
  54 +
  55 +extern void command_loop(void);
  56 +extern int command_usage(const cmdinfo_t *ci);
  57 +extern int command(const cmdinfo_t *ci, int argc, char **argv);
  58 +
  59 +/* from input.h */
  60 +extern char **breakline(char *input, int *count);
  61 +extern void doneline(char *input, char **vec);
  62 +extern char *fetchline(void);
  63 +
  64 +extern long long cvtnum(char *s);
  65 +extern void cvtstr(double value, char *str, size_t sz);
  66 +
  67 +extern struct timeval tsub(struct timeval t1, struct timeval t2);
  68 +extern double tdiv(double value, struct timeval tv);
  69 +
  70 +enum {
  71 + DEFAULT_TIME = 0x0,
  72 + TERSE_FIXED_TIME = 0x1,
  73 + VERBOSE_FIXED_TIME = 0x2
  74 +};
  75 +
  76 +extern void timestr(struct timeval *tv, char *str, size_t sz, int flags);
  77 +
  78 +#endif /* __COMMAND_H__ */
... ...
qemu-io.c 0 → 100644
  1 +/*
  2 + * Command line utility to exercise the QEMU I/O path.
  3 + *
  4 + * Copyright (C) 2009 Red Hat, Inc.
  5 + * Copyright (c) 2003-2005 Silicon Graphics, Inc.
  6 + *
  7 + * This work is licensed under the terms of the GNU GPL, version 2 or later.
  8 + * See the COPYING file in the top-level directory.
  9 + */
  10 +#include <sys/types.h>
  11 +#include <stdarg.h>
  12 +#include <stdio.h>
  13 +#include <getopt.h>
  14 +
  15 +#include "qemu-common.h"
  16 +#include "block_int.h"
  17 +#include "cmd.h"
  18 +
  19 +#define VERSION "0.0.1"
  20 +
  21 +#define CMD_NOFILE_OK 0x01
  22 +
  23 +char *progname;
  24 +static BlockDriverState *bs;
  25 +
  26 +static int misalign;
  27 +
  28 +/*
  29 + * Memory allocation helpers.
  30 + *
  31 + * Make sure memory is aligned by default, or purposefully misaligned if
  32 + * that is specified on the command line.
  33 + */
  34 +
  35 +#define MISALIGN_OFFSET 16
  36 +static void *qemu_io_alloc(size_t len, int pattern)
  37 +{
  38 + void *buf;
  39 +
  40 + if (misalign)
  41 + len += MISALIGN_OFFSET;
  42 + buf = qemu_memalign(512, len);
  43 + memset(buf, pattern, len);
  44 + if (misalign)
  45 + buf += MISALIGN_OFFSET;
  46 + return buf;
  47 +}
  48 +
  49 +static void qemu_io_free(void *p)
  50 +{
  51 + if (misalign)
  52 + p -= MISALIGN_OFFSET;
  53 + qemu_vfree(p);
  54 +}
  55 +
  56 +static void
  57 +dump_buffer(char *buffer, int64_t offset, int len)
  58 +{
  59 + int i, j;
  60 + char *p;
  61 +
  62 + for (i = 0, p = buffer; i < len; i += 16) {
  63 + char *s = p;
  64 +
  65 + printf("%08llx: ", (unsigned long long)offset + i);
  66 + for (j = 0; j < 16 && i + j < len; j++, p++)
  67 + printf("%02x ", *p);
  68 + printf(" ");
  69 + for (j = 0; j < 16 && i + j < len; j++, s++) {
  70 + if (isalnum((int)*s))
  71 + printf("%c", *s);
  72 + else
  73 + printf(".");
  74 + }
  75 + printf("\n");
  76 + }
  77 +}
  78 +
  79 +static void
  80 +print_report(const char *op, struct timeval *t, int64_t offset,
  81 + int count, int total, int cnt, int Cflag)
  82 +{
  83 + char s1[64], s2[64], ts[64];
  84 +
  85 + timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
  86 + if (!Cflag) {
  87 + cvtstr((double)total, s1, sizeof(s1));
  88 + cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
  89 + printf("%s %d/%d bytes at offset %lld\n",
  90 + op, total, count, (long long)offset);
  91 + printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
  92 + s1, cnt, ts, s2, tdiv((double)cnt, *t));
  93 + } else {/* bytes,ops,time,bytes/sec,ops/sec */
  94 + printf("%d,%d,%s,%.3f,%.3f\n",
  95 + total, cnt, ts,
  96 + tdiv((double)total, *t),
  97 + tdiv((double)cnt, *t));
  98 + }
  99 +}
  100 +
  101 +static int do_read(char *buf, int64_t offset, int count, int *total)
  102 +{
  103 + int ret;
  104 +
  105 + ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9);
  106 + if (ret < 0)
  107 + return ret;
  108 + *total = count;
  109 + return 1;
  110 +}
  111 +
  112 +static int do_write(char *buf, int64_t offset, int count, int *total)
  113 +{
  114 + int ret;
  115 +
  116 + ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9);
  117 + if (ret < 0)
  118 + return ret;
  119 + *total = count;
  120 + return 1;
  121 +}
  122 +
  123 +static int do_pread(char *buf, int64_t offset, int count, int *total)
  124 +{
  125 + *total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
  126 + if (*total < 0)
  127 + return *total;
  128 + return 1;
  129 +}
  130 +
  131 +static int do_pwrite(char *buf, int64_t offset, int count, int *total)
  132 +{
  133 + *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
  134 + if (*total < 0)
  135 + return *total;
  136 + return 1;
  137 +}
  138 +
  139 +#define NOT_DONE 0x7fffffff
  140 +static void aio_rw_done(void *opaque, int ret)
  141 +{
  142 + *(int *)opaque = ret;
  143 +}
  144 +
  145 +static int do_aio_readv(QEMUIOVector *qiov, int64_t offset, int *total)
  146 +{
  147 + BlockDriverAIOCB *acb;
  148 + int async_ret = NOT_DONE;
  149 +
  150 + acb = bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
  151 + aio_rw_done, &async_ret);
  152 + if (!acb)
  153 + return -EIO;
  154 +
  155 + while (async_ret == NOT_DONE)
  156 + qemu_aio_wait();
  157 +
  158 + *total = qiov->size;
  159 + return async_ret < 0 ? async_ret : 1;
  160 +}
  161 +
  162 +static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total)
  163 +{
  164 + BlockDriverAIOCB *acb;
  165 + int async_ret = NOT_DONE;
  166 +
  167 + acb = bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
  168 + aio_rw_done, &async_ret);
  169 + if (!acb)
  170 + return -EIO;
  171 +
  172 + while (async_ret == NOT_DONE)
  173 + qemu_aio_wait();
  174 +
  175 + *total = qiov->size >> 9;
  176 + return async_ret < 0 ? async_ret : 1;
  177 +}
  178 +
  179 +
  180 +static const cmdinfo_t read_cmd;
  181 +
  182 +static void
  183 +read_help(void)
  184 +{
  185 + printf(
  186 +"\n"
  187 +" reads a range of bytes from the given offset\n"
  188 +"\n"
  189 +" Example:\n"
  190 +" 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n"
  191 +"\n"
  192 +" Reads a segment of the currently open file, optionally dumping it to the\n"
  193 +" standard output stream (with -v option) for subsequent inspection.\n"
  194 +" -p, -- use bdrv_pread to read the file\n"
  195 +" -C, -- report statistics in a machine parsable format\n"
  196 +" -v, -- dump buffer to standard output\n"
  197 +" -q, -- quite mode, do not show I/O statistics\n"
  198 +"\n");
  199 +}
  200 +
  201 +static int
  202 +read_f(int argc, char **argv)
  203 +{
  204 + struct timeval t1, t2;
  205 + int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
  206 + int c, cnt;
  207 + char *buf;
  208 + int64_t offset;
  209 + int count, total;
  210 +
  211 + while ((c = getopt(argc, argv, "Cpqv")) != EOF) {
  212 + switch (c) {
  213 + case 'C':
  214 + Cflag = 1;
  215 + break;
  216 + case 'p':
  217 + pflag = 1;
  218 + break;
  219 + case 'q':
  220 + qflag = 1;
  221 + break;
  222 + case 'v':
  223 + vflag = 1;
  224 + break;
  225 + default:
  226 + return command_usage(&read_cmd);
  227 + }
  228 + }
  229 +
  230 + if (optind != argc - 2)
  231 + return command_usage(&read_cmd);
  232 +
  233 + offset = cvtnum(argv[optind]);
  234 + if (offset < 0) {
  235 + printf("non-numeric length argument -- %s\n", argv[optind]);
  236 + return 0;
  237 + }
  238 +
  239 + optind++;
  240 + count = cvtnum(argv[optind]);
  241 + if (count < 0) {
  242 + printf("non-numeric length argument -- %s\n", argv[optind]);
  243 + return 0;
  244 + }
  245 +
  246 + if (!pflag)
  247 + if (offset & 0x1ff) {
  248 + printf("offset %lld is not sector aligned\n",
  249 + (long long)offset);
  250 + return 0;
  251 +
  252 + if (count & 0x1ff) {
  253 + printf("count %d is not sector aligned\n",
  254 + count);
  255 + return 0;
  256 + }
  257 + }
  258 +
  259 + buf = qemu_io_alloc(count, 0xab);
  260 +
  261 + gettimeofday(&t1, NULL);
  262 + if (pflag)
  263 + cnt = do_pread(buf, offset, count, &total);
  264 + else
  265 + cnt = do_read(buf, offset, count, &total);
  266 + gettimeofday(&t2, NULL);
  267 +
  268 + if (cnt < 0) {
  269 + printf("read failed: %s\n", strerror(-cnt));
  270 + return 0;
  271 + }
  272 +
  273 + if (qflag)
  274 + return 0;
  275 +
  276 + if (vflag)
  277 + dump_buffer(buf, offset, count);
  278 +
  279 + /* Finally, report back -- -C gives a parsable format */
  280 + t2 = tsub(t2, t1);
  281 + print_report("read", &t2, offset, count, total, cnt, Cflag);
  282 +
  283 + qemu_io_free(buf);
  284 +
  285 + return 0;
  286 +}
  287 +
  288 +static const cmdinfo_t read_cmd = {
  289 + .name = "read",
  290 + .altname = "r",
  291 + .cfunc = read_f,
  292 + .argmin = 2,
  293 + .argmax = -1,
  294 + .args = "[-aCpqv] off len",
  295 + .oneline = "reads a number of bytes at a specified offset",
  296 + .help = read_help,
  297 +};
  298 +
  299 +static const cmdinfo_t readv_cmd;
  300 +
  301 +static void
  302 +readv_help(void)
  303 +{
  304 + printf(
  305 +"\n"
  306 +" reads a range of bytes from the given offset into multiple buffers\n"
  307 +"\n"
  308 +" Example:\n"
  309 +" 'readv -v 512 1k 1k ' - dumps 2 kilobytes read from 512 bytes into the file\n"
  310 +"\n"
  311 +" Reads a segment of the currently open file, optionally dumping it to the\n"
  312 +" standard output stream (with -v option) for subsequent inspection.\n"
  313 +" Uses multiple iovec buffers if more than one byte range is specified.\n"
  314 +" -C, -- report statistics in a machine parsable format\n"
  315 +" -v, -- dump buffer to standard output\n"
  316 +" -q, -- quite mode, do not show I/O statistics\n"
  317 +"\n");
  318 +}
  319 +
  320 +static int
  321 +readv_f(int argc, char **argv)
  322 +{
  323 + struct timeval t1, t2;
  324 + int Cflag = 0, qflag = 0, vflag = 0;
  325 + int c, cnt;
  326 + char *buf, *p;
  327 + int64_t offset;
  328 + int count = 0, total;
  329 + int nr_iov, i;
  330 + QEMUIOVector qiov;
  331 +
  332 + while ((c = getopt(argc, argv, "Cqv")) != EOF) {
  333 + switch (c) {
  334 + case 'C':
  335 + Cflag = 1;
  336 + break;
  337 + case 'q':
  338 + qflag = 1;
  339 + break;
  340 + case 'v':
  341 + vflag = 1;
  342 + break;
  343 + default:
  344 + return command_usage(&readv_cmd);
  345 + }
  346 + }
  347 +
  348 + if (optind > argc - 2)
  349 + return command_usage(&readv_cmd);
  350 +
  351 +
  352 + offset = cvtnum(argv[optind]);
  353 + if (offset < 0) {
  354 + printf("non-numeric length argument -- %s\n", argv[optind]);
  355 + return 0;
  356 + }
  357 + optind++;
  358 +
  359 + if (offset & 0x1ff) {
  360 + printf("offset %lld is not sector aligned\n",
  361 + (long long)offset);
  362 + return 0;
  363 + }
  364 +
  365 + if (count & 0x1ff) {
  366 + printf("count %d is not sector aligned\n",
  367 + count);
  368 + return 0;
  369 + }
  370 +
  371 + for (i = optind; i < argc; i++) {
  372 + size_t len;
  373 +
  374 + len = cvtnum(argv[i]);
  375 + if (len < 0) {
  376 + printf("non-numeric length argument -- %s\n", argv[i]);
  377 + return 0;
  378 + }
  379 + count += len;
  380 + }
  381 +
  382 + nr_iov = argc - optind;
  383 + qemu_iovec_init(&qiov, nr_iov);
  384 + buf = p = qemu_io_alloc(count, 0xab);
  385 + for (i = 0; i < nr_iov; i++) {
  386 + size_t len;
  387 +
  388 + len = cvtnum(argv[optind]);
  389 + if (len < 0) {
  390 + printf("non-numeric length argument -- %s\n",
  391 + argv[optind]);
  392 + return 0;
  393 + }
  394 +
  395 + qemu_iovec_add(&qiov, p, len);
  396 + p += len;
  397 + optind++;
  398 + }
  399 +
  400 + gettimeofday(&t1, NULL);
  401 + cnt = do_aio_readv(&qiov, offset, &total);
  402 + gettimeofday(&t2, NULL);
  403 +
  404 + if (cnt < 0) {
  405 + printf("readv failed: %s\n", strerror(-cnt));
  406 + return 0;
  407 + }
  408 +
  409 + if (qflag)
  410 + return 0;
  411 +
  412 + if (vflag)
  413 + dump_buffer(buf, offset, qiov.size);
  414 +
  415 + /* Finally, report back -- -C gives a parsable format */
  416 + t2 = tsub(t2, t1);
  417 + print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
  418 +
  419 + qemu_io_free(buf);
  420 +
  421 + return 0;
  422 +}
  423 +
  424 +static const cmdinfo_t readv_cmd = {
  425 + .name = "readv",
  426 + .cfunc = readv_f,
  427 + .argmin = 2,
  428 + .argmax = -1,
  429 + .args = "[-Cqv] off len [len..]",
  430 + .oneline = "reads a number of bytes at a specified offset",
  431 + .help = readv_help,
  432 +};
  433 +
  434 +static const cmdinfo_t write_cmd;
  435 +
  436 +static void
  437 +write_help(void)
  438 +{
  439 + printf(
  440 +"\n"
  441 +" writes a range of bytes from the given offset\n"
  442 +"\n"
  443 +" Example:\n"
  444 +" 'write 512 1k' - writes 1 kilobyte at 512 bytes into the open file\n"
  445 +"\n"
  446 +" Writes into a segment of the currently open file, using a buffer\n"
  447 +" filled with a set pattern (0xcdcdcdcd).\n"
  448 +" -p, -- use bdrv_pwrite to write the file\n"
  449 +" -P, -- use different pattern to fill file\n"
  450 +" -C, -- report statistics in a machine parsable format\n"
  451 +" -q, -- quite mode, do not show I/O statistics\n"
  452 +"\n");
  453 +}
  454 +
  455 +static int
  456 +write_f(int argc, char **argv)
  457 +{
  458 + struct timeval t1, t2;
  459 + int Cflag = 0, pflag = 0, qflag = 0;
  460 + int c, cnt;
  461 + char *buf;
  462 + int64_t offset;
  463 + int count, total;
  464 + int pattern = 0xcd;
  465 +
  466 + while ((c = getopt(argc, argv, "CpP:q")) != EOF) {
  467 + switch (c) {
  468 + case 'C':
  469 + Cflag = 1;
  470 + break;
  471 + case 'p':
  472 + pflag = 1;
  473 + break;
  474 + case 'P':
  475 + pattern = atoi(optarg);
  476 + break;
  477 + case 'q':
  478 + qflag = 1;
  479 + break;
  480 + default:
  481 + return command_usage(&write_cmd);
  482 + }
  483 + }
  484 +
  485 + if (optind != argc - 2)
  486 + return command_usage(&write_cmd);
  487 +
  488 + offset = cvtnum(argv[optind]);
  489 + if (offset < 0) {
  490 + printf("non-numeric length argument -- %s\n", argv[optind]);
  491 + return 0;
  492 + }
  493 +
  494 + optind++;
  495 + count = cvtnum(argv[optind]);
  496 + if (count < 0) {
  497 + printf("non-numeric length argument -- %s\n", argv[optind]);
  498 + return 0;
  499 + }
  500 +
  501 + if (!pflag) {
  502 + if (offset & 0x1ff) {
  503 + printf("offset %lld is not sector aligned\n",
  504 + (long long)offset);
  505 + return 0;
  506 + }
  507 +
  508 + if (count & 0x1ff) {
  509 + printf("count %d is not sector aligned\n",
  510 + count);
  511 + return 0;
  512 + }
  513 + }
  514 +
  515 + buf = qemu_io_alloc(count, pattern);
  516 +
  517 + gettimeofday(&t1, NULL);
  518 + if (pflag)
  519 + cnt = do_pwrite(buf, offset, count, &total);
  520 + else
  521 + cnt = do_write(buf, offset, count, &total);
  522 + gettimeofday(&t2, NULL);
  523 +
  524 + if (cnt < 0) {
  525 + printf("write failed: %s\n", strerror(-cnt));
  526 + return 0;
  527 + }
  528 +
  529 + if (qflag)
  530 + return 0;
  531 +
  532 + /* Finally, report back -- -C gives a parsable format */
  533 + t2 = tsub(t2, t1);
  534 + print_report("wrote", &t2, offset, count, total, cnt, Cflag);
  535 +
  536 + qemu_io_free(buf);
  537 +
  538 + return 0;
  539 +}
  540 +
  541 +static const cmdinfo_t write_cmd = {
  542 + .name = "write",
  543 + .altname = "w",
  544 + .cfunc = write_f,
  545 + .argmin = 2,
  546 + .argmax = -1,
  547 + .args = "[-aCpq] [-P pattern ] off len",
  548 + .oneline = "writes a number of bytes at a specified offset",
  549 + .help = write_help,
  550 +};
  551 +
  552 +static const cmdinfo_t writev_cmd;
  553 +
  554 +static void
  555 +writev_help(void)
  556 +{
  557 + printf(
  558 +"\n"
  559 +" writes a range of bytes from the given offset source from multiple buffers\n"
  560 +"\n"
  561 +" Example:\n"
  562 +" 'write 512 1k 1k' - writes 2 kilobytes at 512 bytes into the open file\n"
  563 +"\n"
  564 +" Writes into a segment of the currently open file, using a buffer\n"
  565 +" filled with a set pattern (0xcdcdcdcd).\n"
  566 +" -P, -- use different pattern to fill file\n"
  567 +" -C, -- report statistics in a machine parsable format\n"
  568 +" -q, -- quite mode, do not show I/O statistics\n"
  569 +"\n");
  570 +}
  571 +
  572 +static int
  573 +writev_f(int argc, char **argv)
  574 +{
  575 + struct timeval t1, t2;
  576 + int Cflag = 0, qflag = 0;
  577 + int c, cnt;
  578 + char *buf, *p;
  579 + int64_t offset;
  580 + int count = 0, total;
  581 + int nr_iov, i;
  582 + int pattern = 0xcd;
  583 + QEMUIOVector qiov;
  584 +
  585 + while ((c = getopt(argc, argv, "CqP:")) != EOF) {
  586 + switch (c) {
  587 + case 'C':
  588 + Cflag = 1;
  589 + break;
  590 + case 'q':
  591 + qflag = 1;
  592 + break;
  593 + case 'P':
  594 + pattern = atoi(optarg);
  595 + break;
  596 + default:
  597 + return command_usage(&writev_cmd);
  598 + }
  599 + }
  600 +
  601 + if (optind > argc - 2)
  602 + return command_usage(&writev_cmd);
  603 +
  604 + offset = cvtnum(argv[optind]);
  605 + if (offset < 0) {
  606 + printf("non-numeric length argument -- %s\n", argv[optind]);
  607 + return 0;
  608 + }
  609 + optind++;
  610 +
  611 + if (offset & 0x1ff) {
  612 + printf("offset %lld is not sector aligned\n",
  613 + (long long)offset);
  614 + return 0;
  615 + }
  616 +
  617 + if (count & 0x1ff) {
  618 + printf("count %d is not sector aligned\n",
  619 + count);
  620 + return 0;
  621 + }
  622 +
  623 +
  624 + for (i = optind; i < argc; i++) {
  625 + size_t len;
  626 +
  627 + len = cvtnum(argv[optind]);
  628 + if (len < 0) {
  629 + printf("non-numeric length argument -- %s\n", argv[i]);
  630 + return 0;
  631 + }
  632 + count += len;
  633 + }
  634 +
  635 + nr_iov = argc - optind;
  636 + qemu_iovec_init(&qiov, nr_iov);
  637 + buf = p = qemu_io_alloc(count, 0xab);
  638 + for (i = 0; i < nr_iov; i++) {
  639 + size_t len;
  640 +
  641 + len = cvtnum(argv[optind]);
  642 + if (len < 0) {
  643 + printf("non-numeric length argument -- %s\n",
  644 + argv[optind]);
  645 + return 0;
  646 + }
  647 +
  648 + qemu_iovec_add(&qiov, p, len);
  649 + p += len;
  650 + optind++;
  651 + }
  652 +
  653 + gettimeofday(&t1, NULL);
  654 + cnt = do_aio_writev(&qiov, offset, &total);
  655 + gettimeofday(&t2, NULL);
  656 +
  657 + if (cnt < 0) {
  658 + printf("writev failed: %s\n", strerror(-cnt));
  659 + return 0;
  660 + }
  661 +
  662 + if (qflag)
  663 + return 0;
  664 +
  665 + /* Finally, report back -- -C gives a parsable format */
  666 + t2 = tsub(t2, t1);
  667 + print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
  668 +
  669 + qemu_io_free(buf);
  670 +
  671 + return 0;
  672 +}
  673 +
  674 +static const cmdinfo_t writev_cmd = {
  675 + .name = "writev",
  676 + .cfunc = writev_f,
  677 + .argmin = 2,
  678 + .argmax = -1,
  679 + .args = "[-Cq] [-P pattern ] off len [len..]",
  680 + .oneline = "writes a number of bytes at a specified offset",
  681 + .help = writev_help,
  682 +};
  683 +
  684 +static int
  685 +flush_f(int argc, char **argv)
  686 +{
  687 + bdrv_flush(bs);
  688 + return 0;
  689 +}
  690 +
  691 +static const cmdinfo_t flush_cmd = {
  692 + .name = "flush",
  693 + .altname = "f",
  694 + .cfunc = flush_f,
  695 + .oneline = "flush all in-core file state to disk",
  696 +};
  697 +
  698 +static int
  699 +truncate_f(int argc, char **argv)
  700 +{
  701 + int64_t offset;
  702 + int ret;
  703 +
  704 + offset = cvtnum(argv[1]);
  705 + if (offset < 0) {
  706 + printf("non-numeric truncate argument -- %s\n", argv[1]);
  707 + return 0;
  708 + }
  709 +
  710 + ret = bdrv_truncate(bs, offset);
  711 + if (ret < 0) {
  712 + printf("truncate: %s", strerror(ret));
  713 + return 0;
  714 + }
  715 +
  716 + return 0;
  717 +}
  718 +
  719 +static const cmdinfo_t truncate_cmd = {
  720 + .name = "truncate",
  721 + .altname = "t",
  722 + .cfunc = truncate_f,
  723 + .argmin = 1,
  724 + .argmax = 1,
  725 + .args = "off",
  726 + .oneline = "truncates the current file at the given offset",
  727 +};
  728 +
  729 +static int
  730 +length_f(int argc, char **argv)
  731 +{
  732 + int64_t size;
  733 + char s1[64];
  734 +
  735 + size = bdrv_getlength(bs);
  736 + if (size < 0) {
  737 + printf("getlength: %s", strerror(size));
  738 + return 0;
  739 + }
  740 +
  741 + cvtstr(size, s1, sizeof(s1));
  742 + printf("%s\n", s1);
  743 + return 0;
  744 +}
  745 +
  746 +
  747 +static const cmdinfo_t length_cmd = {
  748 + .name = "length",
  749 + .altname = "l",
  750 + .cfunc = length_f,
  751 + .oneline = "gets the length of the current file",
  752 +};
  753 +
  754 +
  755 +static int
  756 +info_f(int argc, char **argv)
  757 +{
  758 + BlockDriverInfo bdi;
  759 + char s1[64], s2[64];
  760 + int ret;
  761 +
  762 + if (bs->drv && bs->drv->format_name)
  763 + printf("format name: %s\n", bs->drv->format_name);
  764 + if (bs->drv && bs->drv->protocol_name)
  765 + printf("format name: %s\n", bs->drv->protocol_name);
  766 +
  767 + ret = bdrv_get_info(bs, &bdi);
  768 + if (ret)
  769 + return 0;
  770 +
  771 + cvtstr(bdi.cluster_size, s1, sizeof(s1));
  772 + cvtstr(bdi.vm_state_offset, s2, sizeof(s2));
  773 +
  774 + printf("cluster size: %s\n", s1);
  775 + printf("vm state offset: %s\n", s2);
  776 +
  777 + return 0;
  778 +}
  779 +
  780 +
  781 +
  782 +static const cmdinfo_t info_cmd = {
  783 + .name = "info",
  784 + .altname = "i",
  785 + .cfunc = info_f,
  786 + .oneline = "prints information about the current file",
  787 +};
  788 +
  789 +static int
  790 +alloc_f(int argc, char **argv)
  791 +{
  792 + int64_t offset;
  793 + int nb_sectors;
  794 + char s1[64];
  795 + int num;
  796 + int ret;
  797 +
  798 + offset = cvtnum(argv[1]);
  799 + if (offset & 0x1ff) {
  800 + printf("offset %lld is not sector aligned\n",
  801 + (long long)offset);
  802 + return 0;
  803 + }
  804 +
  805 + if (argc == 3)
  806 + nb_sectors = cvtnum(argv[2]);
  807 + else
  808 + nb_sectors = 1;
  809 +
  810 + ret = bdrv_is_allocated(bs, offset >> 9, nb_sectors, &num);
  811 + if (ret) {
  812 + printf("is_allocated: %s", strerror(ret));
  813 + return 0;
  814 + }
  815 +
  816 + cvtstr(offset, s1, sizeof(s1));
  817 +
  818 + if (nb_sectors == 1)
  819 + printf("sector allocated at offset %s\n", s1);
  820 + else
  821 + printf("%d/%d sectors allocated at offset %s\n",
  822 + num, nb_sectors, s1);
  823 + return 0;
  824 +}
  825 +
  826 +static const cmdinfo_t alloc_cmd = {
  827 + .name = "alloc",
  828 + .altname = "a",
  829 + .argmin = 1,
  830 + .argmax = 2,
  831 + .cfunc = alloc_f,
  832 + .args = "off [sectors]",
  833 + .oneline = "checks if a sector is present in the file",
  834 +};
  835 +
  836 +static int
  837 +close_f(int argc, char **argv)
  838 +{
  839 + bdrv_close(bs);
  840 + bs = NULL;
  841 + return 0;
  842 +}
  843 +
  844 +static const cmdinfo_t close_cmd = {
  845 + .name = "close",
  846 + .altname = "c",
  847 + .cfunc = close_f,
  848 + .oneline = "close the current open file",
  849 +};
  850 +
  851 +static int openfile(char *name, int flags)
  852 +{
  853 + if (bs) {
  854 + fprintf(stderr, "file open already, try 'help close'\n");
  855 + return 1;
  856 + }
  857 +
  858 + bs = bdrv_new("hda");
  859 + if (!bs)
  860 + return 1;
  861 +
  862 + if (bdrv_open(bs, name, flags) == -1) {
  863 + fprintf(stderr, "%s: can't open device %s\n", progname, name);
  864 + bs = NULL;
  865 + return 1;
  866 + }
  867 +
  868 + return 0;
  869 +}
  870 +
  871 +static void
  872 +open_help(void)
  873 +{
  874 + printf(
  875 +"\n"
  876 +" opens a new file in the requested mode\n"
  877 +"\n"
  878 +" Example:\n"
  879 +" 'open -Cn /tmp/data' - creates/opens data file read-write and uncached\n"
  880 +"\n"
  881 +" Opens a file for subsequent use by all of the other qemu-io commands.\n"
  882 +" -C, -- create new file if it doesn't exist\n"
  883 +" -r, -- open file read-only\n"
  884 +" -s, -- use snapshot file\n"
  885 +" -n, -- disable host cache\n"
  886 +"\n");
  887 +}
  888 +
  889 +static const cmdinfo_t open_cmd;
  890 +
  891 +static int
  892 +open_f(int argc, char **argv)
  893 +{
  894 + int flags = 0;
  895 + int readonly = 0;
  896 + int c;
  897 +
  898 + while ((c = getopt(argc, argv, "snCr")) != EOF) {
  899 + switch (c) {
  900 + case 's':
  901 + flags |= BDRV_O_SNAPSHOT;
  902 + break;
  903 + case 'n':
  904 + flags |= BDRV_O_NOCACHE;
  905 + break;
  906 + case 'C':
  907 + flags |= BDRV_O_CREAT;
  908 + break;
  909 + case 'r':
  910 + readonly = 1;
  911 + break;
  912 + default:
  913 + return command_usage(&open_cmd);
  914 + }
  915 + }
  916 +
  917 + if (readonly)
  918 + flags |= BDRV_O_RDONLY;
  919 + else
  920 + flags |= BDRV_O_RDWR;
  921 +
  922 + if (optind != argc - 1)
  923 + return command_usage(&open_cmd);
  924 +
  925 + return openfile(argv[optind], flags);
  926 +}
  927 +
  928 +static const cmdinfo_t open_cmd = {
  929 + .name = "open",
  930 + .altname = "o",
  931 + .cfunc = open_f,
  932 + .argmin = 1,
  933 + .argmax = -1,
  934 + .flags = CMD_NOFILE_OK,
  935 + .args = "[-Crsn] [path]",
  936 + .oneline = "open the file specified by path",
  937 + .help = open_help,
  938 +};
  939 +
  940 +static int
  941 +init_args_command(
  942 + int index)
  943 +{
  944 + /* only one device allowed so far */
  945 + if (index >= 1)
  946 + return 0;
  947 + return ++index;
  948 +}
  949 +
  950 +static int
  951 +init_check_command(
  952 + const cmdinfo_t *ct)
  953 +{
  954 + if (ct->flags & CMD_FLAG_GLOBAL)
  955 + return 1;
  956 + if (!(ct->flags & CMD_NOFILE_OK) && !bs) {
  957 + fprintf(stderr, "no file open, try 'help open'\n");
  958 + return 0;
  959 + }
  960 + return 1;
  961 +}
  962 +
  963 +static void usage(const char *name)
  964 +{
  965 + printf(
  966 +"Usage: %s [-h] [-V] [-Crsnm] [-c cmd] ... [file]\n"
  967 +"QEMU Disk excerciser\n"
  968 +"\n"
  969 +" -C, --create create new file if it doesn't exist\n"
  970 +" -c, --cmd command to execute\n"
  971 +" -r, --read-only export read-only\n"
  972 +" -s, --snapshot use snapshot file\n"
  973 +" -n, --nocache disable host cache\n"
  974 +" -m, --misalign misalign allocations for O_DIRECT\n"
  975 +" -h, --help display this help and exit\n"
  976 +" -V, --version output version information and exit\n"
  977 +"\n",
  978 + name);
  979 +}
  980 +
  981 +
  982 +int main(int argc, char **argv)
  983 +{
  984 + int readonly = 0;
  985 + const char *sopt = "hVc:Crsnm";
  986 + struct option lopt[] = {
  987 + { "help", 0, 0, 'h' },
  988 + { "version", 0, 0, 'V' },
  989 + { "offset", 1, 0, 'o' },
  990 + { "cmd", 1, 0, 'c' },
  991 + { "create", 0, 0, 'C' },
  992 + { "read-only", 0, 0, 'r' },
  993 + { "snapshot", 0, 0, 's' },
  994 + { "nocache", 0, 0, 'n' },
  995 + { "misalign", 0, 0, 'm' },
  996 + { NULL, 0, 0, 0 }
  997 + };
  998 + int c;
  999 + int opt_index = 0;
  1000 + int flags = 0;
  1001 +
  1002 + progname = basename(argv[0]);
  1003 +
  1004 + while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) {
  1005 + switch (c) {
  1006 + case 's':
  1007 + flags |= BDRV_O_SNAPSHOT;
  1008 + break;
  1009 + case 'n':
  1010 + flags |= BDRV_O_NOCACHE;
  1011 + break;
  1012 + case 'c':
  1013 + add_user_command(optarg);
  1014 + break;
  1015 + case 'C':
  1016 + flags |= BDRV_O_CREAT;
  1017 + break;
  1018 + case 'r':
  1019 + readonly = 1;
  1020 + break;
  1021 + case 'm':
  1022 + misalign = 1;
  1023 + break;
  1024 + case 'V':
  1025 + printf("%s version %s\n", progname, VERSION);
  1026 + exit(0);
  1027 + case 'h':
  1028 + usage(progname);
  1029 + exit(0);
  1030 + default:
  1031 + usage(progname);
  1032 + exit(1);
  1033 + }
  1034 + }
  1035 +
  1036 + if ((argc - optind) > 1) {
  1037 + usage(progname);
  1038 + exit(1);
  1039 + }
  1040 +
  1041 + bdrv_init();
  1042 +
  1043 + /* initialize commands */
  1044 + quit_init();
  1045 + help_init();
  1046 + add_command(&open_cmd);
  1047 + add_command(&close_cmd);
  1048 + add_command(&read_cmd);
  1049 + add_command(&readv_cmd);
  1050 + add_command(&write_cmd);
  1051 + add_command(&writev_cmd);
  1052 + add_command(&flush_cmd);
  1053 + add_command(&truncate_cmd);
  1054 + add_command(&length_cmd);
  1055 + add_command(&info_cmd);
  1056 + add_command(&alloc_cmd);
  1057 +
  1058 + add_args_command(init_args_command);
  1059 + add_check_command(init_check_command);
  1060 +
  1061 + /* open the device */
  1062 + if (readonly)
  1063 + flags |= BDRV_O_RDONLY;
  1064 + else
  1065 + flags |= BDRV_O_RDWR;
  1066 +
  1067 + if ((argc - optind) == 1)
  1068 + openfile(argv[optind], flags);
  1069 + command_loop();
  1070 +
  1071 + if (bs)
  1072 + bdrv_close(bs);
  1073 + return 0;
  1074 +}
... ...