+++ /dev/null
-Index: new/qapi-schema.json
-===================================================================
---- new.orig/qapi-schema.json 2014-11-20 08:59:29.000000000 +0100
-+++ new/qapi-schema.json 2014-11-20 09:03:23.000000000 +0100
-@@ -391,7 +391,7 @@
- # @vma: Proxmox vma backup format
- ##
- { 'enum': 'BackupFormat',
-- 'data': [ 'vma' ] }
-+ 'data': [ 'vma', 'dir' ] }
-
- ##
- # @backup:
-Index: new/blockdev.c
-===================================================================
---- new.orig/blockdev.c 2014-11-20 08:59:29.000000000 +0100
-+++ new/blockdev.c 2014-11-20 09:04:05.000000000 +0100
-@@ -2301,6 +2301,8 @@
- uint8_t dev_id;
- //bool started;
- bool completed;
-+ char targetfile[PATH_MAX];
-+ BlockDriverState *target;
- } PVEBackupDevInfo;
-
- static void pvebackup_run_next_job(void);
-@@ -2369,8 +2371,6 @@
- {
- PVEBackupDevInfo *di = opaque;
-
-- assert(backup_state.vmaw);
--
- di->completed = true;
-
- if (ret < 0 && !backup_state.error) {
-@@ -2381,8 +2381,11 @@
- BlockDriverState *bs = di->bs;
-
- di->bs = NULL;
-+ di->target = NULL;
-
-- vma_writer_close_stream(backup_state.vmaw, di->dev_id);
-+ if (backup_state.vmaw) {
-+ vma_writer_close_stream(backup_state.vmaw, di->dev_id);
-+ }
-
- block_job_cb(bs, ret);
-
-@@ -2461,6 +2464,7 @@
- {
- BlockBackend *blk;
- BlockDriverState *bs = NULL;
-+ const char *backup_dir = NULL;
- Error *local_err = NULL;
- uuid_t uuid;
- VmaWriter *vmaw = NULL;
-@@ -2478,11 +2482,6 @@
- /* Todo: try to auto-detect format based on file name */
- format = has_format ? format : BACKUP_FORMAT_VMA;
-
-- if (format != BACKUP_FORMAT_VMA) {
-- error_set(errp, ERROR_CLASS_GENERIC_ERROR, "unknown backup format");
-- return NULL;
-- }
--
- if (has_devlist) {
- devs = g_strsplit_set(devlist, ",;:", -1);
-
-@@ -2551,27 +2550,63 @@
-
- uuid_generate(uuid);
-
-- vmaw = vma_writer_create(backup_file, uuid, &local_err);
-- if (!vmaw) {
-- if (local_err) {
-- error_propagate(errp, local_err);
-+ if (format == BACKUP_FORMAT_VMA) {
-+ vmaw = vma_writer_create(backup_file, uuid, &local_err);
-+ if (!vmaw) {
-+ if (local_err) {
-+ error_propagate(errp, local_err);
-+ }
-+ goto err;
- }
-- goto err;
-- }
-
-- /* register all devices for vma writer */
-- l = di_list;
-- while (l) {
-- PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
-- l = g_list_next(l);
-+ /* register all devices for vma writer */
-+ l = di_list;
-+ while (l) {
-+ PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
-+ l = g_list_next(l);
-
-- const char *devname = bdrv_get_device_name(di->bs);
-- di->dev_id = vma_writer_register_stream(vmaw, devname, di->size);
-- if (di->dev_id <= 0) {
-- error_set(errp, ERROR_CLASS_GENERIC_ERROR,
-- "register_stream failed");
-+ const char *devname = bdrv_get_device_name(di->bs);
-+ di->dev_id = vma_writer_register_stream(vmaw, devname, di->size);
-+ if (di->dev_id <= 0) {
-+ error_set(errp, ERROR_CLASS_GENERIC_ERROR,
-+ "register_stream failed");
-+ goto err;
-+ }
-+ }
-+ } else if (format == BACKUP_FORMAT_DIR) {
-+ if (mkdir(backup_file, 0640) != 0) {
-+ error_setg_errno(errp, errno, "can't create directory '%s'\n",
-+ backup_file);
- goto err;
- }
-+ backup_dir = backup_file;
-+
-+ l = di_list;
-+ while (l) {
-+ PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
-+ l = g_list_next(l);
-+
-+ const char *devname = bdrv_get_device_name(di->bs);
-+ snprintf(di->targetfile, PATH_MAX, "%s/%s.raw", backup_dir, devname);
-+
-+ int flags = BDRV_O_RDWR|BDRV_O_CACHE_WB;
-+ bdrv_img_create(di->targetfile, "raw", NULL, NULL, NULL,
-+ di->size, flags, &local_err, false);
-+ if (local_err) {
-+ error_propagate(errp, local_err);
-+ goto err;
-+ }
-+
-+ di->target = bdrv_new();
-+ if (bdrv_open(&di->target, di->targetfile, NULL, NULL, flags, NULL, &local_err) < 0) {
-+ bdrv_unref(di->target);
-+ error_propagate(errp, local_err);
-+ goto err;
-+ }
-+ }
-+ } else {
-+ error_set(errp, ERROR_CLASS_GENERIC_ERROR, "unknown backup format");
-+ goto err;
- }
-
- /* add configuration file to archive */
-@@ -2584,12 +2619,27 @@
- goto err;
- }
-
-- const char *basename = g_path_get_basename(config_file);
-- if (vma_writer_add_config(vmaw, basename, cdata, clen) != 0) {
-- error_setg(errp, "unable to add config data to vma archive");
-- g_free(cdata);
-- goto err;
-+ char *basename = g_path_get_basename(config_file);
-+
-+ if (format == BACKUP_FORMAT_VMA) {
-+ if (vma_writer_add_config(vmaw, basename, cdata, clen) != 0) {
-+ error_setg(errp, "unable to add config data to vma archive");
-+ g_free(cdata);
-+ g_free(basename);
-+ goto err;
-+ }
-+ } else if (format == BACKUP_FORMAT_DIR) {
-+ char config_path[PATH_MAX];
-+ snprintf(config_path, PATH_MAX, "%s/%s", backup_dir, basename);
-+ if (!g_file_set_contents(config_path, cdata, clen, &err)) {
-+ error_setg(errp, "unable to write config file '%s'", config_path);
-+ g_free(cdata);
-+ g_free(basename);
-+ goto err;
-+ }
- }
-+
-+ g_free(basename);
- g_free(cdata);
- }
-
-@@ -2629,10 +2679,11 @@
- PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
- l = g_list_next(l);
-
-- backup_start(di->bs, NULL, speed, MIRROR_SYNC_MODE_FULL, NULL,
-+ backup_start(di->bs, di->target, speed, MIRROR_SYNC_MODE_FULL, NULL,
- BLOCKDEV_ON_ERROR_REPORT, BLOCKDEV_ON_ERROR_REPORT,
- pvebackup_dump_cb, pvebackup_complete_cb, di,
- 1, &local_err);
-+
- if (local_err != NULL) {
- error_setg(&backup_state.error, "backup_job_create failed");
- pvebackup_cancel(NULL);
-@@ -2651,8 +2702,17 @@
-
- l = di_list;
- while (l) {
-- g_free(l->data);
-+ PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
- l = g_list_next(l);
-+
-+ if (di->target) {
-+ bdrv_unref(di->target);
-+ }
-+
-+ if (di->targetfile[0]) {
-+ unlink(di->targetfile);
-+ }
-+ g_free(di);
- }
- g_list_free(di_list);
-
-@@ -2666,6 +2726,10 @@
- unlink(backup_file);
- }
-
-+ if (backup_dir) {
-+ rmdir(backup_dir);
-+ }
-+
- return NULL;
- }
-
-Index: new/hmp-commands.hx
-===================================================================
---- new.orig/hmp-commands.hx 2014-11-20 08:59:29.000000000 +0100
-+++ new/hmp-commands.hx 2014-11-20 09:03:23.000000000 +0100
-@@ -89,9 +89,11 @@
-
- {
- .name = "backup",
-- .args_type = "backupfile:s,speed:o?,devlist:s?",
-- .params = "backupfile [speed [devlist]]",
-- .help = "create a VM Backup.",
-+ .args_type = "directory:-d,backupfile:s,speed:o?,devlist:s?",
-+ .params = "[-d] backupfile [speed [devlist]]",
-+ .help = "create a VM Backup."
-+ "\n\t\t\t Use -d to dump data into a directory instead"
-+ "\n\t\t\t of using VMA format.",
- .mhandler.cmd = hmp_backup,
- },
-
-Index: new/hmp.c
-===================================================================
---- new.orig/hmp.c 2014-11-20 08:59:29.000000000 +0100
-+++ new/hmp.c 2014-11-20 09:03:23.000000000 +0100
-@@ -1459,11 +1459,13 @@
- {
- Error *error = NULL;
-
-+ int dir = qdict_get_try_bool(qdict, "directory", 0);
- const char *backup_file = qdict_get_str(qdict, "backupfile");
- const char *devlist = qdict_get_try_str(qdict, "devlist");
- int64_t speed = qdict_get_try_int(qdict, "speed", 0);
-
-- qmp_backup(backup_file, true, BACKUP_FORMAT_VMA, false, NULL, !!devlist,
-+ qmp_backup(backup_file, true, dir ? BACKUP_FORMAT_DIR : BACKUP_FORMAT_VMA,
-+ false, NULL, !!devlist,
- devlist, qdict_haskey(qdict, "speed"), speed, &error);
-
- hmp_handle_error(mon, &error);