/** * gvir_storage_vol_download: * @vol: the storage volume to download from * @stream: stream to use as output * @offset: position in @vol to start reading from * @length: limit on amount of data to download, or 0 for downloading all data * @flags: extra flags, not used yet, pass 0 * * Returns: #TRUE of success, #FALSE otherwise */ gboolean gvir_storage_vol_download(GVirStorageVol *vol, GVirStream *stream, guint64 offset, guint64 length, guint flags G_GNUC_UNUSED, GError **err) { virStreamPtr stream_handle = NULL; gboolean ret = FALSE; g_object_get(stream, "handle", &stream_handle, NULL); g_return_val_if_fail(GVIR_IS_STORAGE_VOL(vol), FALSE); g_return_val_if_fail(GVIR_IS_STREAM(stream), FALSE); g_return_val_if_fail(err == NULL || *err == NULL, FALSE); if (virStorageVolDownload(vol->priv->handle, stream_handle, offset, length, 0) < 0) { gvir_set_error_literal(err, GVIR_STORAGE_VOL_ERROR, 0, "Unable to download volume storage"); goto cleanup; } ret = TRUE; cleanup: if (stream_handle != NULL) virStreamFree(stream_handle); return ret; }
Result StorageVolControlThread::downloadStorageVol() { Result result; result.name = QString("%1_%2").arg(task.srcConName).arg(currPoolName); QString name, path; name = task.object; path = task.args.path; //qDebug()<<args.first()<<"download"; if (currStoragePool!=NULL) { virStoragePoolFree(currStoragePool); currStoragePool = NULL; }; currStoragePool = virStoragePoolLookupByName( *task.srcConnPtr, currPoolName.toUtf8().data()); QFile *f = new QFile(path); f->open(QIODevice::WriteOnly); bool downloaded = false; virStreamPtr stream = virStreamNew(*task.srcConnPtr, 0); unsigned long long offset = 0; unsigned long long length = task.args.size; // flags: extra flags; not used yet, so callers should always pass 0 unsigned int flags = 0; virStorageVol *storageVol = virStorageVolLookupByName( currStoragePool, name.toUtf8().data()); if ( storageVol!=NULL ) { int ret = virStorageVolDownload( storageVol, stream, offset, length, flags); if ( ret<0 ) result.err = sendConnErrors(); else { downloaded = true; length = 0; char buf[BLOCK_SIZE]; int got, saved, step; step = 0; while ( 1 && keep_alive ) { got = virStreamRecv(stream, buf, BLOCK_SIZE); if (got < 0) { result.err = sendConnErrors(); downloaded = false; break; }; if (got == 0) break; step++; saved = f->write(buf, got); //qDebug()<<"got<>saved"<<got<<saved<<step; if ( saved+1 ) length += saved; else { QString msg = QString("WriteError after (%2): %1 bytes") .arg(length).arg(step); emit errorMsg( msg, number ); result.err = msg; }; }; virStreamFinish(stream); }; virStorageVolFree(storageVol); } else sendConnErrors(); if ( stream!=NULL ) virStreamFree(stream); f->close(); delete f; f = NULL; result.msg.append( QString("'<b>%1</b>' StorageVol %2 Downloaded into %3 (%4).") .arg(name).arg((downloaded)?"":"don't") .arg(path).arg(length)); result.result = downloaded; return result; }
static bool cmdVolDownload(vshControl *ctl, const vshCmd *cmd) { const char *file = NULL; virStorageVolPtr vol = NULL; bool ret = false; int fd = -1; virStreamPtr st = NULL; const char *name = NULL; unsigned long long offset = 0, length = 0; bool created = false; if (!vshConnectionUsability(ctl, ctl->conn)) return false; if (vshCommandOptULongLong(cmd, "offset", &offset) < 0) { vshError(ctl, _("Unable to parse integer")); return false; } if (vshCommandOptULongLong(cmd, "length", &length) < 0) { vshError(ctl, _("Unable to parse integer")); return false; } if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name))) return false; if (vshCommandOptString(cmd, "file", &file) < 0) { vshError(ctl, _("file must not be empty")); goto cleanup; } if ((fd = open(file, O_WRONLY|O_CREAT|O_EXCL, 0666)) < 0) { if (errno != EEXIST || (fd = open(file, O_WRONLY|O_TRUNC, 0666)) < 0) { vshError(ctl, _("cannot create %s"), file); goto cleanup; } } else { created = true; } st = virStreamNew(ctl->conn, 0); if (virStorageVolDownload(vol, st, offset, length, 0) < 0) { vshError(ctl, _("cannot download from volume %s"), name); goto cleanup; } if (virStreamRecvAll(st, vshStreamSink, &fd) < 0) { vshError(ctl, _("cannot receive data from volume %s"), name); goto cleanup; } if (VIR_CLOSE(fd) < 0) { vshError(ctl, _("cannot close file %s"), file); virStreamAbort(st); goto cleanup; } if (virStreamFinish(st) < 0) { vshError(ctl, _("cannot close volume %s"), name); goto cleanup; } ret = true; cleanup: VIR_FORCE_CLOSE(fd); if (!ret && created) unlink(file); if (vol) virStorageVolFree(vol); if (st) virStreamFree(st); return ret; }