VirtualBox

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

Last change on this file since 98123 was 98103, checked in by vboxsync, 23 months ago

Copyright year updates by scm.

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