VFSExplorerImpl.cpp revision a86d69394c2c8fa0fe3d22aa7e9cab4737454236
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence/* $Id$ */
7d32c065c7bb56f281651ae3dd2888f32ce4f1d9Bob Halley/** @file
7d32c065c7bb56f281651ae3dd2888f32ce4f1d9Bob Halley *
7d32c065c7bb56f281651ae3dd2888f32ce4f1d9Bob Halley * IVFSExplorer COM class implementations.
7d32c065c7bb56f281651ae3dd2888f32ce4f1d9Bob Halley */
7d32c065c7bb56f281651ae3dd2888f32ce4f1d9Bob Halley
7d32c065c7bb56f281651ae3dd2888f32ce4f1d9Bob Halley/*
7d32c065c7bb56f281651ae3dd2888f32ce4f1d9Bob Halley * Copyright (C) 2009-2011 Oracle Corporation
7d32c065c7bb56f281651ae3dd2888f32ce4f1d9Bob Halley *
7d32c065c7bb56f281651ae3dd2888f32ce4f1d9Bob Halley * This file is part of VirtualBox Open Source Edition (OSE), as
7d32c065c7bb56f281651ae3dd2888f32ce4f1d9Bob Halley * available from http://www.virtualbox.org. This file is free software;
7d32c065c7bb56f281651ae3dd2888f32ce4f1d9Bob Halley * you can redistribute it and/or modify it under the terms of the GNU
7d32c065c7bb56f281651ae3dd2888f32ce4f1d9Bob Halley * General Public License (GPL) as published by the Free Software
7d32c065c7bb56f281651ae3dd2888f32ce4f1d9Bob Halley * Foundation, in version 2 as it comes in the "COPYING" file of the
7d32c065c7bb56f281651ae3dd2888f32ce4f1d9Bob Halley * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
7d32c065c7bb56f281651ae3dd2888f32ce4f1d9Bob Halley * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence */
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence#include <iprt/dir.h>
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence#include <iprt/path.h>
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence#include <iprt/file.h>
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence#include <iprt/s3.h>
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence#include <iprt/cpp/utils.h>
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence#include <VBox/com/array.h>
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence#include <VBox/param.h>
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence#include <VBox/version.h>
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence#include "VFSExplorerImpl.h"
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence#include "VirtualBoxImpl.h"
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence#include "ProgressImpl.h"
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence#include "AutoCaller.h"
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence#include "Logging.h"
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence#include <memory>
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence////////////////////////////////////////////////////////////////////////////////
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence//
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence// VFSExplorer definitions
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence//
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence////////////////////////////////////////////////////////////////////////////////
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence/* opaque private instance data of VFSExplorer class */
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrencestruct VFSExplorer::Data
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence{
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence struct DirEntry
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence {
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence DirEntry(Utf8Str strName, VFSFileType_T fileType, uint64_t cbSize, uint32_t fMode)
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence : name(strName)
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence , type(fileType)
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence , size(cbSize)
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence , mode(fMode) {}
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence Utf8Str name;
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence VFSFileType_T type;
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence uint64_t size;
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence uint32_t mode;
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence };
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence VFSType_T storageType;
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence Utf8Str strUsername;
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence Utf8Str strPassword;
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence Utf8Str strHostname;
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence Utf8Str strPath;
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence Utf8Str strBucket;
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence std::list<DirEntry> entryList;
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence};
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid LawrenceVFSExplorer::VFSExplorer()
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence : mVirtualBox(NULL)
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence{
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence}
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid LawrenceVFSExplorer::~VFSExplorer()
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence{
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence}
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence/**
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence * VFSExplorer COM initializer.
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence * @param
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence * @return
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence */
487e6abc16c1b2958d371b0d4e808953646b520aDavid LawrenceHRESULT VFSExplorer::init(VFSType_T aType, Utf8Str aFilePath, Utf8Str aHostname, Utf8Str aUsername, Utf8Str aPassword, VirtualBox *aVirtualBox)
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence{
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence /* Enclose the state transition NotReady->InInit->Ready */
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence AutoInitSpan autoInitSpan(this);
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence AssertReturn(autoInitSpan.isOk(), E_FAIL);
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence /* Weak reference to a VirtualBox object */
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence unconst(mVirtualBox) = aVirtualBox;
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence /* initialize data */
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence m = new Data;
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence m->storageType = aType;
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence m->strPath = aFilePath;
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence m->strHostname = aHostname;
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence m->strUsername = aUsername;
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence m->strPassword = aPassword;
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence if (m->storageType == VFSType_S3)
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence {
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence size_t bpos = aFilePath.find("/", 1);
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence if (bpos != Utf8Str::npos)
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence {
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence m->strBucket = aFilePath.substr(1, bpos - 1); /* The bucket without any slashes */
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence aFilePath = aFilePath.substr(bpos); /* The rest of the file path */
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence }
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence }
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence /* Confirm a successful initialization */
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence autoInitSpan.setSucceeded();
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence return S_OK;
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence}
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence/**
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence * VFSExplorer COM uninitializer.
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence * @return
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence */
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrencevoid VFSExplorer::uninit()
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence{
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence delete m;
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence m = NULL;
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence}
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence/**
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence * Public method implementation.
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence * @param
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence * @return
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence */
487e6abc16c1b2958d371b0d4e808953646b520aDavid LawrenceSTDMETHODIMP VFSExplorer::COMGETTER(Path)(BSTR *aPath)
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence{
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence if (!aPath)
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence return E_POINTER;
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence AutoCaller autoCaller(this);
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence if (FAILED(autoCaller.rc())) return autoCaller.rc();
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence Bstr bstrPath(m->strPath);
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence bstrPath.cloneTo(aPath);
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence return S_OK;
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence}
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid LawrenceSTDMETHODIMP VFSExplorer::COMGETTER(Type)(VFSType_T *aType)
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence{
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence if (!aType)
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence return E_POINTER;
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence AutoCaller autoCaller(this);
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence if (FAILED(autoCaller.rc())) return autoCaller.rc();
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence *aType = m->storageType;
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence return S_OK;
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence}
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrencestruct VFSExplorer::TaskVFSExplorer
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence{
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence enum TaskType
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence {
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence Update,
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence Delete
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence };
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence TaskVFSExplorer(TaskType aTaskType, VFSExplorer *aThat, Progress *aProgress)
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence : taskType(aTaskType),
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence pVFSExplorer(aThat),
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence progress(aProgress),
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence rc(S_OK)
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence {}
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence ~TaskVFSExplorer() {}
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence int startThread();
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence static int taskThread(RTTHREAD aThread, void *pvUser);
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence static int uploadProgress(unsigned uPercent, void *pvUser);
487e6abc16c1b2958d371b0d4e808953646b520aDavid Lawrence
TaskType taskType;
VFSExplorer *pVFSExplorer;
ComObjPtr<Progress> progress;
HRESULT rc;
/* task data */
std::list<Utf8Str> filenames;
};
int VFSExplorer::TaskVFSExplorer::startThread()
{
int vrc = RTThreadCreate(NULL, VFSExplorer::TaskVFSExplorer::taskThread, this,
0, RTTHREADTYPE_MAIN_HEAVY_WORKER, 0,
"Explorer::Task");
if (RT_FAILURE(vrc))
return VFSExplorer::setErrorStatic(E_FAIL, Utf8StrFmt("Could not create taskThreadVFS (%Rrc)\n", vrc));
return vrc;
}
/* static */
DECLCALLBACK(int) VFSExplorer::TaskVFSExplorer::taskThread(RTTHREAD /* aThread */, void *pvUser)
{
std::auto_ptr<TaskVFSExplorer> task(static_cast<TaskVFSExplorer*>(pvUser));
AssertReturn(task.get(), VERR_GENERAL_FAILURE);
VFSExplorer *pVFSExplorer = task->pVFSExplorer;
LogFlowFuncEnter();
LogFlowFunc(("VFSExplorer %p\n", pVFSExplorer));
HRESULT rc = S_OK;
switch(task->taskType)
{
case TaskVFSExplorer::Update:
{
if (pVFSExplorer->m->storageType == VFSType_File)
rc = pVFSExplorer->updateFS(task.get());
else if (pVFSExplorer->m->storageType == VFSType_S3)
#ifdef VBOX_WITH_S3
rc = pVFSExplorer->updateS3(task.get());
#else
rc = VERR_NOT_IMPLEMENTED;
#endif
break;
}
case TaskVFSExplorer::Delete:
{
if (pVFSExplorer->m->storageType == VFSType_File)
rc = pVFSExplorer->deleteFS(task.get());
else if (pVFSExplorer->m->storageType == VFSType_S3)
#ifdef VBOX_WITH_S3
rc = pVFSExplorer->deleteS3(task.get());
#else
rc = VERR_NOT_IMPLEMENTED;
#endif
break;
}
default:
AssertMsgFailed(("Invalid task type %u specified!\n", task->taskType));
break;
}
LogFlowFunc(("rc=%Rhrc\n", rc)); NOREF(rc);
LogFlowFuncLeave();
return VINF_SUCCESS;
}
/* static */
int VFSExplorer::TaskVFSExplorer::uploadProgress(unsigned uPercent, void *pvUser)
{
VFSExplorer::TaskVFSExplorer* pTask = *(VFSExplorer::TaskVFSExplorer**)pvUser;
if (pTask &&
!pTask->progress.isNull())
{
BOOL fCanceled;
pTask->progress->COMGETTER(Canceled)(&fCanceled);
if (fCanceled)
return -1;
pTask->progress->SetCurrentOperationProgress(uPercent);
}
return VINF_SUCCESS;
}
VFSFileType_T VFSExplorer::RTToVFSFileType(int aType) const
{
int a = aType & RTFS_TYPE_MASK;
VFSFileType_T t = VFSFileType_Unknown;
if ((a & RTFS_TYPE_DIRECTORY) == RTFS_TYPE_DIRECTORY)
t = VFSFileType_Directory;
else if ((a & RTFS_TYPE_FILE) == RTFS_TYPE_FILE)
t = VFSFileType_File;
else if ((a & RTFS_TYPE_SYMLINK) == RTFS_TYPE_SYMLINK)
t = VFSFileType_SymLink;
else if ((a & RTFS_TYPE_FIFO) == RTFS_TYPE_FIFO)
t = VFSFileType_Fifo;
else if ((a & RTFS_TYPE_DEV_CHAR) == RTFS_TYPE_DEV_CHAR)
t = VFSFileType_DevChar;
else if ((a & RTFS_TYPE_DEV_BLOCK) == RTFS_TYPE_DEV_BLOCK)
t = VFSFileType_DevBlock;
else if ((a & RTFS_TYPE_SOCKET) == RTFS_TYPE_SOCKET)
t = VFSFileType_Socket;
else if ((a & RTFS_TYPE_WHITEOUT) == RTFS_TYPE_WHITEOUT)
t = VFSFileType_WhiteOut;
return t;
}
HRESULT VFSExplorer::updateFS(TaskVFSExplorer *aTask)
{
LogFlowFuncEnter();
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);
HRESULT rc = S_OK;
std::list<VFSExplorer::Data::DirEntry> fileList;
char *pszPath = NULL;
PRTDIR pDir = NULL;
try
{
int vrc = RTDirOpen(&pDir, m->strPath.c_str());
if (RT_FAILURE(vrc))
throw setError(VBOX_E_FILE_ERROR, tr ("Can't open directory '%s' (%Rrc)"), pszPath, vrc);
if (aTask->progress)
aTask->progress->SetCurrentOperationProgress(33);
RTDIRENTRYEX entry;
while (RT_SUCCESS(vrc))
{
vrc = RTDirReadEx(pDir, &entry, NULL, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
if (RT_SUCCESS(vrc))
{
Utf8Str name(entry.szName);
if ( name != "."
&& name != "..")
fileList.push_back(VFSExplorer::Data::DirEntry(name, RTToVFSFileType(entry.Info.Attr.fMode), entry.Info.cbObject, entry.Info.Attr.fMode & (RTFS_UNIX_IRWXU | RTFS_UNIX_IRWXG | RTFS_UNIX_IRWXO)));
}
}
if (aTask->progress)
aTask->progress->SetCurrentOperationProgress(66);
}
catch(HRESULT aRC)
{
rc = aRC;
}
/* Clean up */
if (pszPath)
RTStrFree(pszPath);
if (pDir)
RTDirClose(pDir);
if (aTask->progress)
aTask->progress->SetCurrentOperationProgress(99);
/* Assign the result on success (this clears the old list) */
if (rc == S_OK)
m->entryList.assign(fileList.begin(), fileList.end());
aTask->rc = rc;
if (!aTask->progress.isNull())
aTask->progress->notifyComplete(rc);
LogFlowFunc(("rc=%Rhrc\n", rc));
LogFlowFuncLeave();
return VINF_SUCCESS;
}
HRESULT VFSExplorer::deleteFS(TaskVFSExplorer *aTask)
{
LogFlowFuncEnter();
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);
HRESULT rc = S_OK;
float fPercentStep = 100.0f / aTask->filenames.size();
try
{
char szPath[RTPATH_MAX];
std::list<Utf8Str>::const_iterator it;
size_t i = 0;
for (it = aTask->filenames.begin();
it != aTask->filenames.end();
++it, ++i)
{
int vrc = RTPathJoin(szPath, sizeof(szPath), m->strPath.c_str(), (*it).c_str());
if (RT_FAILURE(vrc))
throw setError(E_FAIL, tr("Internal Error (%Rrc)"), vrc);
vrc = RTFileDelete(szPath);
if (RT_FAILURE(vrc))
throw setError(VBOX_E_FILE_ERROR, tr("Can't delete file '%s' (%Rrc)"), szPath, vrc);
if (aTask->progress)
aTask->progress->SetCurrentOperationProgress((ULONG)(fPercentStep * i));
}
}
catch(HRESULT aRC)
{
rc = aRC;
}
aTask->rc = rc;
if (!aTask->progress.isNull())
aTask->progress->notifyComplete(rc);
LogFlowFunc(("rc=%Rhrc\n", rc));
LogFlowFuncLeave();
return VINF_SUCCESS;
}
#ifdef VBOX_WITH_S3
HRESULT VFSExplorer::updateS3(TaskVFSExplorer *aTask)
{
LogFlowFuncEnter();
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);
HRESULT rc = S_OK;
RTS3 hS3 = NULL;
std::list<VFSExplorer::Data::DirEntry> fileList;
try
{
int vrc = RTS3Create(&hS3, m->strUsername.c_str(), m->strPassword.c_str(), m->strHostname.c_str(), "virtualbox-agent/"VBOX_VERSION_STRING);
if (RT_FAILURE(vrc))
throw setError(E_FAIL, tr ("Can't open S3 storage service (%Rrc)"), vrc);
RTS3SetProgressCallback(hS3, VFSExplorer::TaskVFSExplorer::uploadProgress, &aTask);
/* Do we need the list of buckets or keys? */
if (m->strBucket.isEmpty())
{
PCRTS3BUCKETENTRY pBuckets = NULL;
vrc = RTS3GetBuckets(hS3, &pBuckets);
if (RT_FAILURE(vrc))
throw setError(E_FAIL, tr ("Can't get buckets (%Rrc)"), vrc);
PCRTS3BUCKETENTRY pTmpBuckets = pBuckets;
while (pBuckets)
{
/* Set always read/write permissions of the current logged in user. */
fileList.push_back(VFSExplorer::Data::DirEntry(pBuckets->pszName, VFSFileType_Directory, 0, RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR));
pBuckets = pBuckets->pNext;
}
RTS3BucketsDestroy(pTmpBuckets);
}
else
{
PCRTS3KEYENTRY pKeys = NULL;
vrc = RTS3GetBucketKeys(hS3, m->strBucket.c_str(), &pKeys);
if (RT_FAILURE(vrc))
throw setError(E_FAIL, tr ("Can't get keys for bucket (%Rrc)"), vrc);
PCRTS3KEYENTRY pTmpKeys = pKeys;
while (pKeys)
{
Utf8Str name(pKeys->pszName);
/* Set always read/write permissions of the current logged in user. */
fileList.push_back(VFSExplorer::Data::DirEntry(pKeys->pszName, VFSFileType_File, pKeys->cbFile, RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR));
pKeys = pKeys->pNext;
}
RTS3KeysDestroy(pTmpKeys);
}
}
catch(HRESULT aRC)
{
rc = aRC;
}
if (hS3 != NULL)
RTS3Destroy(hS3);
/* Assign the result on success (this clears the old list) */
if (rc == S_OK)
m->entryList.assign(fileList.begin(), fileList.end());
aTask->rc = rc;
if (!aTask->progress.isNull())
aTask->progress->notifyComplete(rc);
LogFlowFunc(("rc=%Rhrc\n", rc));
LogFlowFuncLeave();
return VINF_SUCCESS;
}
HRESULT VFSExplorer::deleteS3(TaskVFSExplorer *aTask)
{
LogFlowFuncEnter();
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);
HRESULT rc = S_OK;
RTS3 hS3 = NULL;
float fPercentStep = 100.0f / aTask->filenames.size();
try
{
int vrc = RTS3Create(&hS3, m->strUsername.c_str(), m->strPassword.c_str(), m->strHostname.c_str(), "virtualbox-agent/"VBOX_VERSION_STRING);
if (RT_FAILURE(vrc))
throw setError(E_FAIL, tr ("Can't open S3 storage service (%Rrc)"), vrc);
RTS3SetProgressCallback(hS3, VFSExplorer::TaskVFSExplorer::uploadProgress, &aTask);
std::list<Utf8Str>::const_iterator it;
size_t i = 0;
for (it = aTask->filenames.begin();
it != aTask->filenames.end();
++it, ++i)
{
vrc = RTS3DeleteKey(hS3, m->strBucket.c_str(), (*it).c_str());
if (RT_FAILURE(vrc))
throw setError(VBOX_E_FILE_ERROR, tr ("Can't delete file '%s' (%Rrc)"), (*it).c_str(), vrc);
if (aTask->progress)
aTask->progress->SetCurrentOperationProgress((ULONG)(fPercentStep * i));
}
}
catch(HRESULT aRC)
{
rc = aRC;
}
aTask->rc = rc;
if (hS3 != NULL)
RTS3Destroy(hS3);
if (!aTask->progress.isNull())
aTask->progress->notifyComplete(rc);
LogFlowFunc(("rc=%Rhrc\n", rc));
LogFlowFuncLeave();
return VINF_SUCCESS;
}
#endif /* VBOX_WITH_S3 */
STDMETHODIMP VFSExplorer::Update(IProgress **aProgress)
{
CheckComArgOutPointerValid(aProgress);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
HRESULT rc = S_OK;
ComObjPtr<Progress> progress;
try
{
Bstr progressDesc = BstrFmt(tr("Update directory info for '%s'"),
m->strPath.c_str());
/* Create the progress object */
progress.createObject();
rc = progress->init(mVirtualBox,
static_cast<IVFSExplorer*>(this),
progressDesc.raw(),
TRUE /* aCancelable */);
if (FAILED(rc)) throw rc;
/* Initialize our worker task */
std::auto_ptr<TaskVFSExplorer> task(new TaskVFSExplorer(TaskVFSExplorer::Update, this, progress));
rc = task->startThread();
if (FAILED(rc)) throw rc;
/* Don't destruct on success */
task.release();
}
catch (HRESULT aRC)
{
rc = aRC;
}
if (SUCCEEDED(rc))
/* Return progress to the caller */
progress.queryInterfaceTo(aProgress);
return rc;
}
STDMETHODIMP VFSExplorer::Cd(IN_BSTR aDir, IProgress **aProgress)
{
CheckComArgStrNotEmptyOrNull(aDir);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
{
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
m->strPath = aDir;
}
return Update(aProgress);
}
STDMETHODIMP VFSExplorer::CdUp(IProgress **aProgress)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
Utf8Str strUpPath;
{
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
/* Remove lowest dir entry in a platform neutral way. */
char *pszNewPath = RTStrDup(m->strPath.c_str());
RTPathStripTrailingSlash(pszNewPath);
RTPathStripFilename(pszNewPath);
strUpPath = pszNewPath;
RTStrFree(pszNewPath);
}
return Cd(Bstr(strUpPath).raw(), aProgress);
}
STDMETHODIMP VFSExplorer::EntryList(ComSafeArrayOut(BSTR, aNames), ComSafeArrayOut(VFSFileType_T, aTypes), ComSafeArrayOut(LONG64, aSizes), ComSafeArrayOut(ULONG, aModes))
{
if (ComSafeArrayOutIsNull(aNames) ||
ComSafeArrayOutIsNull(aTypes))
return E_POINTER;
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
com::SafeArray<BSTR> sfaNames(m->entryList.size());
com::SafeArray<ULONG> sfaTypes(m->entryList.size());
com::SafeArray<LONG64> sfaSizes(m->entryList.size());
com::SafeArray<ULONG> sfaModes(m->entryList.size());
std::list<VFSExplorer::Data::DirEntry>::const_iterator it;
size_t i = 0;
for (it = m->entryList.begin();
it != m->entryList.end();
++it, ++i)
{
const VFSExplorer::Data::DirEntry &entry = (*it);
Bstr bstr(entry.name);
bstr.cloneTo(&sfaNames[i]);
sfaTypes[i] = entry.type;
sfaSizes[i] = entry.size;
sfaModes[i] = entry.mode;
}
sfaNames.detachTo(ComSafeArrayOutArg(aNames));
sfaTypes.detachTo(ComSafeArrayOutArg(aTypes));
sfaSizes.detachTo(ComSafeArrayOutArg(aSizes));
sfaModes.detachTo(ComSafeArrayOutArg(aModes));
return S_OK;
}
STDMETHODIMP VFSExplorer::Exists(ComSafeArrayIn(IN_BSTR, aNames), ComSafeArrayOut(BSTR, aExists))
{
CheckComArgSafeArrayNotNull(aNames);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
com::SafeArray<IN_BSTR> sfaNames(ComSafeArrayInArg(aNames));
std::list<BSTR> listExists;
for (size_t a=0; a < sfaNames.size(); ++a)
{
std::list<VFSExplorer::Data::DirEntry>::const_iterator it;
for (it = m->entryList.begin();
it != m->entryList.end();
++it)
{
const VFSExplorer::Data::DirEntry &entry = (*it);
if (entry.name == RTPathFilename(Utf8Str(sfaNames[a]).c_str()))
{
BSTR name;
Bstr tmp(sfaNames[a]); /* gcc-3.3 cruft */
tmp.cloneTo(&name);
listExists.push_back(name);
}
}
}
com::SafeArray<BSTR> sfaExists(listExists);
sfaExists.detachTo(ComSafeArrayOutArg(aExists));
return S_OK;
}
STDMETHODIMP VFSExplorer::Remove(ComSafeArrayIn(IN_BSTR, aNames), IProgress **aProgress)
{
CheckComArgSafeArrayNotNull(aNames);
CheckComArgOutPointerValid(aProgress);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
HRESULT rc = S_OK;
com::SafeArray<IN_BSTR> sfaNames(ComSafeArrayInArg(aNames));
ComObjPtr<Progress> progress;
try
{
/* Create the progress object */
progress.createObject();
rc = progress->init(mVirtualBox, static_cast<IVFSExplorer*>(this),
Bstr(tr("Delete files")).raw(),
TRUE /* aCancelable */);
if (FAILED(rc)) throw rc;
/* Initialize our worker task */
std::auto_ptr<TaskVFSExplorer> task(new TaskVFSExplorer(TaskVFSExplorer::Delete, this, progress));
/* Add all filenames to delete as task data */
for (size_t a=0; a < sfaNames.size(); ++a)
task->filenames.push_back(Utf8Str(sfaNames[a]));
rc = task->startThread();
if (FAILED(rc)) throw rc;
/* Don't destruct on success */
task.release();
}
catch (HRESULT aRC)
{
rc = aRC;
}
if (SUCCEEDED(rc))
/* Return progress to the caller */
progress.queryInterfaceTo(aProgress);
return rc;
}