VirtualBox

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

Last change on this file since 41105 was 35757, checked in by vboxsync, 14 years ago

Main: do not fail loading machine settings if a shared folder path is not absolute (that breaks importing OVF and machine folders from other hosts since the rules about what constitutes an absolute path differ between host OSes). Instead, issue a runtime warning if a shared folder path is not absolute or does not exist on the host when the VM is powered up.

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette