VirtualBox

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

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