VirtualBox

source: vbox/trunk/src/VBox/Main/src-all/SharedFolderImpl.cpp@ 73768

Last change on this file since 73768 was 73003, checked in by vboxsync, 6 years ago

Main: Use setErrorBoth when we've got a VBox status code handy. (The COM status codes aren't too specfic and this may help us decode error messages and provide an alternative to strstr for API clients. setErrorBoth isn't new, btw.)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.9 KB
Line 
1/* $Id: SharedFolderImpl.cpp 73003 2018-07-09 11:09:32Z vboxsync $ */
2/** @file
3 *
4 * VirtualBox COM class implementation
5 */
6
7/*
8 * Copyright (C) 2006-2017 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#include "SharedFolderImpl.h"
20#if !defined(VBOX_COM_INPROC)
21# include "VirtualBoxImpl.h"
22# include "MachineImpl.h"
23#endif
24#include "ConsoleImpl.h"
25
26#include "AutoCaller.h"
27#include "Logging.h"
28
29#include <iprt/param.h>
30#include <iprt/cpp/utils.h>
31#include <iprt/path.h>
32
33/////////////////////////////////////////////////////////////////////////////
34// SharedFolder::Data structure
35/////////////////////////////////////////////////////////////////////////////
36
37struct SharedFolder::Data
38{
39 Data()
40 : fWritable(false),
41 fAutoMount(false)
42 { }
43
44 const Utf8Str strName;
45 const Utf8Str strHostPath;
46 bool fWritable;
47 bool fAutoMount;
48 Utf8Str strLastAccessError;
49};
50
51// constructor / destructor
52/////////////////////////////////////////////////////////////////////////////
53
54SharedFolder::SharedFolder()
55 : mParent(NULL),
56#if !defined(VBOX_COM_INPROC)
57 mMachine(NULL),
58 mVirtualBox(NULL)
59#else
60 mConsole(NULL)
61#endif
62{
63 m = new Data;
64}
65
66SharedFolder::~SharedFolder()
67{
68 delete m;
69 m = NULL;
70}
71
72HRESULT SharedFolder::FinalConstruct()
73{
74 return BaseFinalConstruct();
75}
76
77void SharedFolder::FinalRelease()
78{
79 uninit();
80 BaseFinalRelease();
81}
82
83// public initializer/uninitializer for internal purposes only
84/////////////////////////////////////////////////////////////////////////////
85
86#if !defined(VBOX_COM_INPROC)
87/**
88 * Initializes the shared folder object.
89 *
90 * This variant initializes a machine instance that lives in the server address space.
91 *
92 * @param aMachine parent Machine object
93 * @param aName logical name of the shared folder
94 * @param aHostPath full path to the shared folder on the host
95 * @param aWritable writable if true, readonly otherwise
96 * @param aAutoMount if auto mounted by guest true, false otherwise
97 * @param fFailOnError Whether to fail with an error if the shared folder path is bad.
98 *
99 * @return COM result indicator
100 */
101HRESULT SharedFolder::init(Machine *aMachine,
102 const Utf8Str &aName,
103 const Utf8Str &aHostPath,
104 bool aWritable,
105 bool aAutoMount,
106 bool fFailOnError)
107{
108 /* Enclose the state transition NotReady->InInit->Ready */
109 AutoInitSpan autoInitSpan(this);
110 AssertReturn(autoInitSpan.isOk(), E_FAIL);
111
112 unconst(mMachine) = aMachine;
113
114 HRESULT rc = i_protectedInit(aMachine, aName, aHostPath, aWritable, aAutoMount, fFailOnError);
115
116 /* Confirm a successful initialization when it's the case */
117 if (SUCCEEDED(rc))
118 autoInitSpan.setSucceeded();
119
120 return rc;
121}
122
123/**
124 * Initializes the shared folder object given another object
125 * (a kind of copy constructor). This object makes a private copy of data
126 * of the original object passed as an argument.
127 *
128 * @param aMachine parent Machine object
129 * @param aThat shared folder object to copy
130 *
131 * @return COM result indicator
132 */
133HRESULT SharedFolder::initCopy(Machine *aMachine, SharedFolder *aThat)
134{
135 ComAssertRet(aThat, E_INVALIDARG);
136
137 /* Enclose the state transition NotReady->InInit->Ready */
138 AutoInitSpan autoInitSpan(this);
139 AssertReturn(autoInitSpan.isOk(), E_FAIL);
140
141 unconst(mMachine) = aMachine;
142
143 HRESULT rc = i_protectedInit(aMachine,
144 aThat->m->strName,
145 aThat->m->strHostPath,
146 aThat->m->fWritable,
147 aThat->m->fAutoMount,
148 false /* fFailOnError */ );
149
150 /* Confirm a successful initialization when it's the case */
151 if (SUCCEEDED(rc))
152 autoInitSpan.setSucceeded();
153
154 return rc;
155}
156
157# if 0
158
159/**
160 * Initializes the shared folder object.
161 *
162 * This variant initializes a global instance that lives in the server address space. It is not presently used.
163 *
164 * @param aVirtualBox VirtualBox parent object
165 * @param aName logical name of the shared folder
166 * @param aHostPath full path to the shared folder on the host
167 * @param aWritable writable if true, readonly otherwise
168 * @param fFailOnError Whether to fail with an error if the shared folder path is bad.
169 *
170 * @return COM result indicator
171 */
172HRESULT SharedFolder::init(VirtualBox *aVirtualBox,
173 const Utf8Str &aName,
174 const Utf8Str &aHostPath,
175 bool aWritable,
176 bool aAutoMount,
177 bool fFailOnError)
178{
179 /* Enclose the state transition NotReady->InInit->Ready */
180 AutoInitSpan autoInitSpan(this);
181 AssertReturn(autoInitSpan.isOk(), E_FAIL);
182
183 unconst(mVirtualBox) = aVirtualBox;
184
185 HRESULT rc = protectedInit(aVirtualBox, aName, aHostPath, aWritable, aAutoMount);
186
187 /* Confirm a successful initialization when it's the case */
188 if (SUCCEEDED(rc))
189 autoInitSpan.setSucceeded();
190
191 return rc;
192}
193
194# endif
195
196#else
197
198/**
199 * Initializes the shared folder object.
200 *
201 * This variant initializes an instance that lives in the console address space.
202 *
203 * @param aConsole Console parent object
204 * @param aName logical name of the shared folder
205 * @param aHostPath full path to the shared folder on the host
206 * @param aWritable writable if true, readonly otherwise
207 * @param fFailOnError Whether to fail with an error if the shared folder path is bad.
208 *
209 * @return COM result indicator
210 */
211HRESULT SharedFolder::init(Console *aConsole,
212 const Utf8Str &aName,
213 const Utf8Str &aHostPath,
214 bool aWritable,
215 bool aAutoMount,
216 bool fFailOnError)
217{
218 /* Enclose the state transition NotReady->InInit->Ready */
219 AutoInitSpan autoInitSpan(this);
220 AssertReturn(autoInitSpan.isOk(), E_FAIL);
221
222 unconst(mConsole) = aConsole;
223
224 HRESULT rc = i_protectedInit(aConsole, aName, aHostPath, aWritable, aAutoMount, fFailOnError);
225
226 /* Confirm a successful initialization when it's the case */
227 if (SUCCEEDED(rc))
228 autoInitSpan.setSucceeded();
229
230 return rc;
231}
232#endif
233
234/**
235 * Shared initialization code. Called from the other constructors.
236 *
237 * @note
238 * Must be called from under the object's lock!
239 */
240HRESULT SharedFolder::i_protectedInit(VirtualBoxBase *aParent,
241 const Utf8Str &aName,
242 const Utf8Str &aHostPath,
243 bool aWritable,
244 bool aAutoMount,
245 bool fFailOnError)
246{
247 LogFlowThisFunc(("aName={%s}, aHostPath={%s}, aWritable={%d}, aAutoMount={%d}\n",
248 aName.c_str(), aHostPath.c_str(), aWritable, aAutoMount));
249
250 ComAssertRet(aParent && aName.isNotEmpty() && aHostPath.isNotEmpty(), E_INVALIDARG);
251
252 Utf8Str hostPath = aHostPath;
253 size_t hostPathLen = hostPath.length();
254
255 /* Remove the trailing slash unless it's a root directory
256 * (otherwise the comparison with the RTPathAbs() result will fail at least
257 * on Linux). Note that this isn't really necessary for the shared folder
258 * itself, since adding a mapping eventually results into a
259 * RTDirOpenFiltered() call (see HostServices/SharedFolders) that seems to
260 * accept both the slashified paths and not. */
261#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
262 if (hostPathLen > 2 &&
263 RTPATH_IS_SEP (hostPath.c_str()[hostPathLen - 1]) &&
264 RTPATH_IS_VOLSEP (hostPath.c_str()[hostPathLen - 2]))
265 ;
266#else
267 if (hostPathLen == 1 && RTPATH_IS_SEP(hostPath[0]))
268 ;
269#endif
270 else
271 hostPath.stripTrailingSlash();
272
273 if (fFailOnError)
274 {
275 /* Check whether the path is full (absolute) */
276 char hostPathFull[RTPATH_MAX];
277 int vrc = RTPathAbsEx(NULL,
278 hostPath.c_str(),
279 hostPathFull,
280 sizeof (hostPathFull));
281 if (RT_FAILURE(vrc))
282 return setErrorBoth(E_INVALIDARG, vrc, tr("Invalid shared folder path: '%s' (%Rrc)"), hostPath.c_str(), vrc);
283
284 if (RTPathCompare(hostPath.c_str(), hostPathFull) != 0)
285 return setError(E_INVALIDARG, tr("Shared folder path '%s' is not absolute"), hostPath.c_str());
286 }
287
288 unconst(mParent) = aParent;
289
290 unconst(m->strName) = aName;
291 unconst(m->strHostPath) = hostPath;
292 m->fWritable = aWritable;
293 m->fAutoMount = aAutoMount;
294
295 return S_OK;
296}
297
298/**
299 * Uninitializes the instance and sets the ready flag to FALSE.
300 * Called either from FinalRelease() or by the parent when it gets destroyed.
301 */
302void SharedFolder::uninit()
303{
304 LogFlowThisFunc(("\n"));
305
306 /* Enclose the state transition Ready->InUninit->NotReady */
307 AutoUninitSpan autoUninitSpan(this);
308 if (autoUninitSpan.uninitDone())
309 return;
310
311 unconst(mParent) = NULL;
312
313#if !defined(VBOX_COM_INPROC)
314 unconst(mMachine) = NULL;
315 unconst(mVirtualBox) = NULL;
316#else
317 unconst(mConsole) = NULL;
318#endif
319}
320
321// wrapped ISharedFolder properties
322/////////////////////////////////////////////////////////////////////////////
323HRESULT SharedFolder::getName(com::Utf8Str &aName)
324{
325 /* mName is constant during life time, no need to lock */
326 aName = m->strName;
327
328 return S_OK;
329}
330
331HRESULT SharedFolder::getHostPath(com::Utf8Str &aHostPath)
332{
333 /* mHostPath is constant during life time, no need to lock */
334 aHostPath = m->strHostPath;
335
336 return S_OK;
337}
338
339HRESULT SharedFolder::getAccessible(BOOL *aAccessible)
340{
341 /* mName and mHostPath are constant during life time, no need to lock */
342
343 /* check whether the host path exists */
344 Utf8Str hostPath = m->strHostPath;
345 char hostPathFull[RTPATH_MAX];
346 int vrc = RTPathExists(hostPath.c_str()) ? RTPathReal(hostPath.c_str(),
347 hostPathFull,
348 sizeof(hostPathFull))
349 : VERR_PATH_NOT_FOUND;
350 if (RT_SUCCESS(vrc))
351 {
352 *aAccessible = TRUE;
353 return S_OK;
354 }
355
356 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
357
358 m->strLastAccessError = Utf8StrFmt(tr("'%s' is not accessible (%Rrc)"),
359 m->strHostPath.c_str(),
360 vrc);
361
362 Log1WarningThisFunc(("m.lastAccessError=\"%s\"\n", m->strLastAccessError.c_str()));
363
364 *aAccessible = FALSE;
365
366 return S_OK;
367}
368
369HRESULT SharedFolder::getWritable(BOOL *aWritable)
370{
371 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
372
373 *aWritable = !!m->fWritable;
374
375 return S_OK;
376}
377
378HRESULT SharedFolder::getAutoMount(BOOL *aAutoMount)
379{
380 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
381
382 *aAutoMount = !!m->fAutoMount;
383
384 return S_OK;
385}
386
387HRESULT SharedFolder::getLastAccessError(com::Utf8Str &aLastAccessError)
388{
389 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
390
391 aLastAccessError = m->strLastAccessError;
392
393 return S_OK;
394}
395
396
397const Utf8Str& SharedFolder::i_getName() const
398{
399 return m->strName;
400}
401
402const Utf8Str& SharedFolder::i_getHostPath() const
403{
404 return m->strHostPath;
405}
406
407bool SharedFolder::i_isWritable() const
408{
409 return m->fWritable;
410}
411
412bool SharedFolder::i_isAutoMounted() const
413{
414 return m->fAutoMount;
415}
416
417/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use