summaryrefslogtreecommitdiff
path: root/src/VBox/Main/src-client/GuestDirectoryImpl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Main/src-client/GuestDirectoryImpl.cpp')
-rw-r--r--src/VBox/Main/src-client/GuestDirectoryImpl.cpp236
1 files changed, 181 insertions, 55 deletions
diff --git a/src/VBox/Main/src-client/GuestDirectoryImpl.cpp b/src/VBox/Main/src-client/GuestDirectoryImpl.cpp
index 36d262b9..52d0cf95 100644
--- a/src/VBox/Main/src-client/GuestDirectoryImpl.cpp
+++ b/src/VBox/Main/src-client/GuestDirectoryImpl.cpp
@@ -1,11 +1,11 @@
/* $Id: GuestDirectoryImpl.cpp $ */
/** @file
- * VirtualBox Main - XXX.
+ * VirtualBox Main - Guest directory handling.
*/
/*
- * Copyright (C) 2012 Oracle Corporation
+ * Copyright (C) 2012-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -58,54 +58,72 @@ void GuestDirectory::FinalRelease(void)
// public initializer/uninitializer for internal purposes only
/////////////////////////////////////////////////////////////////////////////
-int GuestDirectory::init(GuestSession *aSession,
- const Utf8Str &strPath, const Utf8Str &strFilter, uint32_t uFlags)
+int GuestDirectory::init(Console *pConsole, GuestSession *pSession,
+ ULONG uDirID, const GuestDirectoryOpenInfo &openInfo)
{
- LogFlowThisFunc(("strPath=%s, strFilter=%s, uFlags=%x\n",
- strPath.c_str(), strFilter.c_str(), uFlags));
+ LogFlowThisFunc(("pConsole=%p, pSession=%p, uDirID=%RU32, strPath=%s, strFilter=%s, uFlags=%x\n",
+ pConsole, pSession, uDirID, openInfo.mPath.c_str(), openInfo.mFilter.c_str(),
+ openInfo.mFlags));
+
+ AssertPtrReturn(pConsole, VERR_INVALID_POINTER);
+ AssertPtrReturn(pSession, VERR_INVALID_POINTER);
/* Enclose the state transition NotReady->InInit->Ready. */
AutoInitSpan autoInitSpan(this);
AssertReturn(autoInitSpan.isOk(), E_FAIL);
- mData.mSession = aSession;
- mData.mName = strPath;
- mData.mFilter = strFilter;
- mData.mFlags = uFlags;
-
- /* Start the directory process on the guest. */
- GuestProcessStartupInfo procInfo;
- procInfo.mName = Utf8StrFmt(tr("Reading directory \"%s\"", strPath.c_str()));
- procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_LS);
- procInfo.mTimeoutMS = 5 * 60 * 1000; /* 5 minutes timeout. */
- procInfo.mFlags = ProcessCreateFlag_WaitForStdOut;
-
- procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
- /* We want the long output format which contains all the object details. */
- procInfo.mArguments.push_back(Utf8Str("-l"));
+#ifndef VBOX_WITH_GUEST_CONTROL
+ autoInitSpan.setSucceeded();
+ return VINF_SUCCESS;
+#else
+ int vrc = bindToSession(pConsole, pSession, uDirID /* Object ID */);
+ if (RT_SUCCESS(vrc))
+ {
+ mSession = pSession;
+
+ mData.mID = uDirID;
+ mData.mOpenInfo = openInfo;
+ }
+
+ if (RT_SUCCESS(vrc))
+ {
+ /* Start the directory process on the guest. */
+ GuestProcessStartupInfo procInfo;
+ procInfo.mName = Utf8StrFmt(tr("Reading directory \"%s\"", openInfo.mPath.c_str()));
+ procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_LS);
+ procInfo.mTimeoutMS = 5 * 60 * 1000; /* 5 minutes timeout. */
+ procInfo.mFlags = ProcessCreateFlag_WaitForStdOut;
+
+ procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
+ /* We want the long output format which contains all the object details. */
+ procInfo.mArguments.push_back(Utf8Str("-l"));
#if 0 /* Flags are not supported yet. */
- if (uFlags & DirectoryOpenFlag_NoSymlinks)
- procInfo.mArguments.push_back(Utf8Str("--nosymlinks")); /** @todo What does GNU here? */
+ if (uFlags & DirectoryOpenFlag_NoSymlinks)
+ procInfo.mArguments.push_back(Utf8Str("--nosymlinks")); /** @todo What does GNU here? */
#endif
- /** @todo Recursion support? */
- procInfo.mArguments.push_back(strPath); /* The directory we want to open. */
+ /** @todo Recursion support? */
+ procInfo.mArguments.push_back(openInfo.mPath); /* The directory we want to open. */
+
+ /*
+ * Start the process asynchronously and keep it around so that we can use
+ * it later in subsequent read() calls.
+ * Note: No guest rc available because operation is asynchronous.
+ */
+ vrc = mData.mProcessTool.Init(mSession, procInfo,
+ true /* Async */, NULL /* Guest rc */);
+ }
- /*
- * Start the process asynchronously and keep it around so that we can use
- * it later in subsequent read() calls.
- * Note: No guest rc available because operation is asynchronous.
- */
- int rc = mData.mProcessTool.Init(mData.mSession, procInfo,
- true /* Async */, NULL /* Guest rc */);
- if (RT_SUCCESS(rc))
+ if (RT_SUCCESS(vrc))
{
/* Confirm a successful initialization when it's the case. */
autoInitSpan.setSucceeded();
- return rc;
+ return vrc;
}
+ else
+ autoInitSpan.setFailed();
- autoInitSpan.setFailed();
- return rc;
+ return vrc;
+#endif /* VBOX_WITH_GUEST_CONTROL */
}
/**
@@ -114,7 +132,7 @@ int GuestDirectory::init(GuestSession *aSession,
*/
void GuestDirectory::uninit(void)
{
- LogFlowThisFunc(("\n"));
+ LogFlowThisFuncEnter();
/* Enclose the state transition Ready->InUninit->NotReady. */
AutoUninitSpan autoUninitSpan(this);
@@ -138,7 +156,7 @@ STDMETHODIMP GuestDirectory::COMGETTER(DirectoryName)(BSTR *aName)
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- mData.mName.cloneTo(aName);
+ mData.mOpenInfo.mPath.cloneTo(aName);
return S_OK;
}
@@ -154,7 +172,7 @@ STDMETHODIMP GuestDirectory::COMGETTER(Filter)(BSTR *aFilter)
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- mData.mFilter.cloneTo(aFilter);
+ mData.mOpenInfo.mFilter.cloneTo(aFilter);
return S_OK;
}
@@ -162,6 +180,96 @@ STDMETHODIMP GuestDirectory::COMGETTER(Filter)(BSTR *aFilter)
// private methods
/////////////////////////////////////////////////////////////////////////////
+int GuestDirectory::callbackDispatcher(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
+{
+ AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER);
+ AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);
+
+ LogFlowThisFunc(("strPath=%s, uContextID=%RU32, uFunction=%RU32, pSvcCb=%p\n",
+ mData.mOpenInfo.mPath.c_str(), pCbCtx->uContextID, pCbCtx->uFunction, pSvcCb));
+
+ int vrc;
+ switch (pCbCtx->uFunction)
+ {
+ case GUEST_DIR_NOTIFY:
+ {
+ int idx = 1; /* Current parameter index. */
+ CALLBACKDATA_DIR_NOTIFY dataCb;
+ /* pSvcCb->mpaParms[0] always contains the context ID. */
+ pSvcCb->mpaParms[idx++].getUInt32(&dataCb.uType);
+ pSvcCb->mpaParms[idx++].getUInt32(&dataCb.rc);
+
+ int guestRc = (int)dataCb.rc; /* uint32_t vs. int. */
+
+ LogFlowFunc(("uType=%RU32, guestRc=%Rrc\n",
+ dataCb.uType, guestRc));
+
+ switch (dataCb.uType)
+ {
+ /* Nothing here yet, nothing to dispatch further. */
+
+ default:
+ vrc = VERR_NOT_SUPPORTED;
+ break;
+ }
+ break;
+ }
+
+ default:
+ /* Silently ignore not implemented functions. */
+ vrc = VERR_NOT_SUPPORTED;
+ break;
+ }
+
+#ifdef DEBUG
+ LogFlowFuncLeaveRC(vrc);
+#endif
+ return vrc;
+}
+
+/* static */
+Utf8Str GuestDirectory::guestErrorToString(int guestRc)
+{
+ Utf8Str strError;
+
+ /** @todo pData->u32Flags: int vs. uint32 -- IPRT errors are *negative* !!! */
+ switch (guestRc)
+ {
+ case VERR_DIR_NOT_EMPTY:
+ strError += Utf8StrFmt("Directoy is not empty");
+ break;
+
+ default:
+ strError += Utf8StrFmt("%Rrc", guestRc);
+ break;
+ }
+
+ return strError;
+}
+
+/**
+ * Called by IGuestSession right before this directory gets
+ * removed from the public directory list.
+ */
+int GuestDirectory::onRemove(void)
+{
+ LogFlowThisFuncEnter();
+
+ int vrc = VINF_SUCCESS;
+
+ LogFlowFuncLeaveRC(vrc);
+ return vrc;
+}
+
+/* static */
+HRESULT GuestDirectory::setErrorExternal(VirtualBoxBase *pInterface, int guestRc)
+{
+ AssertPtr(pInterface);
+ AssertMsg(RT_FAILURE(guestRc), ("Guest rc does not indicate a failure when setting error\n"));
+
+ return pInterface->setError(VBOX_E_IPRT_ERROR, GuestDirectory::guestErrorToString(guestRc).c_str());
+}
+
// implementation of public methods
/////////////////////////////////////////////////////////////////////////////
@@ -175,20 +283,38 @@ STDMETHODIMP GuestDirectory::Close(void)
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
- AssertPtr(mData.mSession);
- int rc = mData.mSession->directoryRemoveFromList(this);
+ HRESULT hr = S_OK;
+
+ int guestRc;
+ int rc = mData.mProcessTool.Terminate(30 * 1000, &guestRc);
+ if (RT_FAILURE(rc))
+ {
+ switch (rc)
+ {
+ case VERR_GSTCTL_GUEST_ERROR:
+ hr = GuestProcess::setErrorExternal(this, guestRc);
+ break;
- mData.mProcessTool.Terminate();
+ case VERR_NOT_SUPPORTED:
+ /* Silently skip old Guest Additions which do not support killing the
+ * the guest directory handling process. */
+ break;
- /*
- * Release autocaller before calling uninit.
- */
- autoCaller.release();
+ default:
+ hr = setError(VBOX_E_IPRT_ERROR,
+ tr("Terminating open guest directory \"%s\" failed: %Rrc"),
+ mData.mOpenInfo.mPath.c_str(), rc);
+ break;
+ }
+ }
- uninit();
+ AssertPtr(mSession);
+ int rc2 = mSession->directoryRemoveFromList(this);
+ if (RT_SUCCESS(rc))
+ rc = rc2;
- LogFlowFuncLeaveRC(rc);
- return S_OK;
+ LogFlowThisFunc(("Returning rc=%Rrc\n", rc));
+ return hr;
#endif /* VBOX_WITH_GUEST_CONTROL */
}
@@ -262,34 +388,34 @@ STDMETHODIMP GuestDirectory::Read(IFsObjInfo **aInfo)
{
switch (rc)
{
- case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ case VERR_GSTCTL_GUEST_ERROR:
hr = GuestProcess::setErrorExternal(this, guestRc);
break;
case VERR_ACCESS_DENIED:
hr = setError(VBOX_E_IPRT_ERROR, tr("Reading directory \"%s\" failed: Unable to read / access denied"),
- mData.mName.c_str());
+ mData.mOpenInfo.mPath.c_str());
break;
case VERR_PATH_NOT_FOUND:
hr = setError(VBOX_E_IPRT_ERROR, tr("Reading directory \"%s\" failed: Path not found"),
- mData.mName.c_str());
+ mData.mOpenInfo.mPath.c_str());
break;
case VERR_NO_MORE_FILES:
/* See SDK reference. */
hr = setError(VBOX_E_OBJECT_NOT_FOUND, tr("No more entries for directory \"%s\""),
- mData.mName.c_str());
+ mData.mOpenInfo.mPath.c_str());
break;
default:
hr = setError(VBOX_E_IPRT_ERROR, tr("Error while reading directory \"%s\": %Rrc\n"),
- mData.mName.c_str(), rc);
+ mData.mOpenInfo.mPath.c_str(), rc);
break;
}
}
- LogFlowFuncLeaveRC(rc);
+ LogFlowThisFunc(("Returning rc=%Rrc\n", rc));
return hr;
#endif /* VBOX_WITH_GUEST_CONTROL */
}