* THE SOFTWARE.
*/
#include "qemu-common.h"
+#include "osdep.h"
#include "block_int.h"
#include <assert.h>
#include <windows.h>
#endif
-static void __attribute__((noreturn)) error(const char *fmt, ...)
+/* Default to cache=writeback as data integrity is not important for qemu-tcg. */
+#define BRDV_O_FLAGS BDRV_O_CACHE_WB
+
+static void noreturn error(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
" commit [-f fmt] filename\n"
" convert [-c] [-e] [-6] [-f fmt] [-O output_fmt] [-B output_base_image] filename [filename2 [...]] output_filename\n"
" info [-f fmt] filename\n"
+ " snapshot [-l|-a snapshot|-c snapshot|-d snapshot] filename\n"
"\n"
"Command parameters:\n"
" 'filename' is a disk image filename\n"
" '-c' indicates that target image must be compressed (qcow format only)\n"
" '-e' indicates that the target image must be encrypted (qcow format only)\n"
" '-6' indicates that the target image must use compatibility level 6 (vmdk format only)\n"
+ "\n"
+ " Parameters to snapshot subcommand:\n"
+ " 'snapshot' is the name of the snapshot to create, apply or delete\n"
+ " '-a' applies a snapshot (revert disk to saved state)\n"
+ " '-c' creates a snapshot\n"
+ " '-d' deletes a snapshot\n"
+ " '-l' lists all snapshots in the given image\n"
);
printf("\nSupported format:");
bdrv_iterate_format(format_print, NULL);
} else {
drv = NULL;
}
- if (bdrv_open2(bs, filename, 0, drv) < 0) {
+ if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
error("Could not open '%s'", filename);
}
if (bdrv_is_encrypted(bs)) {
} else {
drv = NULL;
}
- if (bdrv_open2(bs, filename, 0, drv) < 0) {
+ if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
error("Could not open '%s'", filename);
}
ret = bdrv_commit(bs);
} else {
drv = NULL;
}
- if (bdrv_open2(bs, filename, 0, drv) < 0) {
+ if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
error("Could not open '%s'", filename);
}
bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
return 0;
}
+#define SNAPSHOT_LIST 1
+#define SNAPSHOT_CREATE 2
+#define SNAPSHOT_APPLY 3
+#define SNAPSHOT_DELETE 4
+
+static void img_snapshot(int argc, char **argv)
+{
+ BlockDriverState *bs;
+ QEMUSnapshotInfo sn;
+ char *filename, *snapshot_name = NULL;
+ int c, ret;
+ int action = 0;
+ qemu_timeval tv;
+
+ /* Parse commandline parameters */
+ for(;;) {
+ c = getopt(argc, argv, "la:c:d:h");
+ if (c == -1)
+ break;
+ switch(c) {
+ case 'h':
+ help();
+ return;
+ case 'l':
+ if (action) {
+ help();
+ return;
+ }
+ action = SNAPSHOT_LIST;
+ break;
+ case 'a':
+ if (action) {
+ help();
+ return;
+ }
+ action = SNAPSHOT_APPLY;
+ snapshot_name = optarg;
+ break;
+ case 'c':
+ if (action) {
+ help();
+ return;
+ }
+ action = SNAPSHOT_CREATE;
+ snapshot_name = optarg;
+ break;
+ case 'd':
+ if (action) {
+ help();
+ return;
+ }
+ action = SNAPSHOT_DELETE;
+ snapshot_name = optarg;
+ break;
+ }
+ }
+
+ if (optind >= argc)
+ help();
+ filename = argv[optind++];
+
+ /* Open the image */
+ bs = bdrv_new("");
+ if (!bs)
+ error("Not enough memory");
+
+ if (bdrv_open2(bs, filename, 0, NULL) < 0) {
+ error("Could not open '%s'", filename);
+ }
+
+ /* Perform the requested action */
+ switch(action) {
+ case SNAPSHOT_LIST:
+ dump_snapshots(bs);
+ break;
+
+ case SNAPSHOT_CREATE:
+ memset(&sn, 0, sizeof(sn));
+ pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
+
+ qemu_gettimeofday(&tv);
+ sn.date_sec = tv.tv_sec;
+ sn.date_nsec = tv.tv_usec * 1000;
+
+ ret = bdrv_snapshot_create(bs, &sn);
+ if (ret)
+ error("Could not create snapshot '%s': %d (%s)",
+ snapshot_name, ret, strerror(-ret));
+ break;
+
+ case SNAPSHOT_APPLY:
+ ret = bdrv_snapshot_goto(bs, snapshot_name);
+ if (ret)
+ error("Could not apply snapshot '%s': %d (%s)",
+ snapshot_name, ret, strerror(-ret));
+ break;
+
+ case SNAPSHOT_DELETE:
+ ret = bdrv_snapshot_delete(bs, snapshot_name);
+ if (ret)
+ error("Could not delete snapshot '%s': %d (%s)",
+ snapshot_name, ret, strerror(-ret));
+ break;
+ }
+
+ /* Cleanup */
+ bdrv_delete(bs);
+}
+
int main(int argc, char **argv)
{
const char *cmd;
img_convert(argc, argv);
} else if (!strcmp(cmd, "info")) {
img_info(argc, argv);
+ } else if (!strcmp(cmd, "snapshot")) {
+ img_snapshot(argc, argv);
} else {
help();
}