VirtualBox

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

Last change on this file since 105087 was 105087, checked in by vboxsync, 8 months ago

doc/manual,include/VBox,Frontends/VBoxManage,HostServices/SharedFolders,
Main/{include,SharedFolder,Console,Machine,VirtualBox.xidl}: Add a
new attribute to ISharedFolder for specifying a symbolic link creation
policy to restrict the source pathname when creating symbolic links
within a guest. The symbolic link policies are represented by a new
enumeration of type SymlinkPolicy_T which includes values for no
restrictions ('any'), symlink sources only within the subtree of the
share ('subtree'), symlink sources as any relative path ('relative'),
and no symlinks allowed ('forbidden'). The symlink policy can only be
applied to permanent shared folders at this stage. bugref:10619

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.6 KB
Line 
1/* $Id: SharedFolderImpl.cpp 105087 2024-07-01 23:27:59Z vboxsync $ */
2/** @file
3 * VirtualBox COM class implementation
4 */
5
6/*
7 * Copyright (C) 2006-2022 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 const 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 unconst(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 RT_NOREF(aWritable);
359 return E_NOTIMPL;
360}
361
362HRESULT SharedFolder::getAutoMount(BOOL *aAutoMount)
363{
364 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
365 *aAutoMount = m->fAutoMount;
366 return S_OK;
367}
368
369HRESULT SharedFolder::setAutoMount(BOOL aAutoMount)
370{
371 RT_NOREF(aAutoMount);
372 return E_NOTIMPL;
373}
374
375HRESULT SharedFolder::getAutoMountPoint(com::Utf8Str &aAutoMountPoint)
376{
377 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
378 aAutoMountPoint = m->strAutoMountPoint;
379 return S_OK;
380}
381
382HRESULT SharedFolder::setAutoMountPoint(com::Utf8Str const &aAutoMountPoint)
383{
384 RT_NOREF(aAutoMountPoint);
385 return E_NOTIMPL;
386}
387
388HRESULT SharedFolder::getLastAccessError(com::Utf8Str &aLastAccessError)
389{
390 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
391 aLastAccessError = m->strLastAccessError;
392 return S_OK;
393}
394
395HRESULT SharedFolder::getSymlinkPolicy(SymlinkPolicy_T *aSymlinkPolicy)
396{
397 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
398 *aSymlinkPolicy = m->enmSymlinkPolicy;
399 return S_OK;
400}
401
402HRESULT SharedFolder::setSymlinkPolicy(SymlinkPolicy_T aSymlinkPolicy)
403{
404 switch (aSymlinkPolicy)
405 {
406 case SymlinkPolicy_AllowedToAnyTarget:
407 case SymlinkPolicy_AllowedInShareSubtree:
408 case SymlinkPolicy_AllowedToRelativeTargets:
409 case SymlinkPolicy_Forbidden:
410 break;
411 default:
412 return setError(E_INVALIDARG, tr("The symbolic link policy specified (%d) is invalid."), aSymlinkPolicy);
413 }
414
415 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
416 m->enmSymlinkPolicy = aSymlinkPolicy;
417 return S_OK;
418}
419
420const Utf8Str& SharedFolder::i_getName() const
421{
422 return m->strName;
423}
424
425const Utf8Str& SharedFolder::i_getHostPath() const
426{
427 return m->strHostPath;
428}
429
430bool SharedFolder::i_isWritable() const
431{
432 return m->fWritable;
433}
434
435bool SharedFolder::i_isAutoMounted() const
436{
437 return m->fAutoMount;
438}
439
440const Utf8Str &SharedFolder::i_getAutoMountPoint() const
441{
442 return m->strAutoMountPoint;
443}
444
445const SymlinkPolicy_T SharedFolder::i_getSymlinkPolicy() const
446{
447 return m->enmSymlinkPolicy;
448}
449
450/* 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