VirtualBox

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

Last change on this file since 105087 was 105087, checked in by vboxsync, 5 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: 10.4 KB
Line 
1/* $Id: ConsoleSharedFolderImpl.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 "ConsoleSharedFolderImpl.h"
30#include "ConsoleImpl.h"
31
32#include "AutoCaller.h"
33
34#include <iprt/param.h>
35#include <iprt/cpp/utils.h>
36#include <iprt/path.h>
37
38/////////////////////////////////////////////////////////////////////////////
39// ConsoleSharedFolder::Data structure
40/////////////////////////////////////////////////////////////////////////////
41
42struct ConsoleSharedFolder::Data
43{
44 Data()
45 : fWritable(false),
46 fAutoMount(false),
47 enmSymlinkPolicy(SymlinkPolicy_None)
48 { }
49
50 const Utf8Str strName;
51 const Utf8Str strHostPath;
52 bool fWritable;
53 bool fAutoMount;
54 const Utf8Str strAutoMountPoint;
55 Utf8Str strLastAccessError;
56 SymlinkPolicy_T enmSymlinkPolicy;
57};
58
59// constructor / destructor
60/////////////////////////////////////////////////////////////////////////////
61
62ConsoleSharedFolder::ConsoleSharedFolder()
63 : mParent(NULL),
64 mConsole(NULL)
65{
66 m = new Data;
67}
68
69ConsoleSharedFolder::~ConsoleSharedFolder()
70{
71 delete m;
72 m = NULL;
73}
74
75HRESULT ConsoleSharedFolder::FinalConstruct()
76{
77 return BaseFinalConstruct();
78}
79
80void ConsoleSharedFolder::FinalRelease()
81{
82 uninit();
83 BaseFinalRelease();
84}
85
86// public initializer/uninitializer for internal purposes only
87/////////////////////////////////////////////////////////////////////////////
88
89/**
90 * Initializes the shared folder object.
91 *
92 * This variant initializes an instance that lives in the console address space.
93 *
94 * @param aConsole Console parent object
95 * @param aName logical name of the shared folder
96 * @param aHostPath full path to the shared folder on the host
97 * @param aWritable writable if true, readonly otherwise
98 * @param aAutoMount if auto mounted by guest true, false otherwise
99 * @param aAutoMountPoint Where the guest should try auto mount it.
100 * @param fFailOnError Whether to fail with an error if the shared folder path is bad.
101 *
102 * @return COM result indicator
103 */
104HRESULT ConsoleSharedFolder::init(Console *aConsole,
105 const Utf8Str &aName,
106 const Utf8Str &aHostPath,
107 bool aWritable,
108 bool aAutoMount,
109 const Utf8Str &aAutoMountPoint,
110 bool fFailOnError)
111{
112 /* Enclose the state transition NotReady->InInit->Ready */
113 AutoInitSpan autoInitSpan(this);
114 AssertReturn(autoInitSpan.isOk(), E_FAIL);
115
116 unconst(mConsole) = aConsole;
117
118 HRESULT hrc = i_protectedInit(aConsole, aName, aHostPath, aWritable, aAutoMount, aAutoMountPoint, fFailOnError);
119
120 /* Confirm a successful initialization when it's the case */
121 if (SUCCEEDED(hrc))
122 autoInitSpan.setSucceeded();
123
124 return hrc;
125}
126
127/**
128 * Shared initialization code. Called from the other constructors.
129 *
130 * @note
131 * Must be called from under the object's lock!
132 */
133HRESULT ConsoleSharedFolder::i_protectedInit(VirtualBoxBase *aParent,
134 const Utf8Str &aName,
135 const Utf8Str &aHostPath,
136 bool aWritable,
137 bool aAutoMount,
138 const Utf8Str &aAutoMountPoint,
139 bool fFailOnError)
140{
141 LogFlowThisFunc(("aName={%s}, aHostPath={%s}, aWritable={%d}, aAutoMount={%d}\n",
142 aName.c_str(), aHostPath.c_str(), aWritable, aAutoMount));
143
144 ComAssertRet(aParent && aName.isNotEmpty() && aHostPath.isNotEmpty(), E_INVALIDARG);
145
146 Utf8Str hostPath = aHostPath;
147 size_t hostPathLen = hostPath.length();
148
149 /* Remove the trailing slash unless it's a root directory
150 * (otherwise the comparison with the RTPathAbs() result will fail at least
151 * on Linux). Note that this isn't really necessary for the shared folder
152 * itself, since adding a mapping eventually results into a
153 * RTDirOpenFiltered() call (see HostServices/SharedFolders) that seems to
154 * accept both the slashified paths and not. */
155#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
156 if ( hostPathLen > 2
157 && RTPATH_IS_SEP(hostPath.c_str()[hostPathLen - 1])
158 && RTPATH_IS_VOLSEP(hostPath.c_str()[hostPathLen - 2]))
159 ;
160#else
161 if (hostPathLen == 1 && RTPATH_IS_SEP(hostPath[0]))
162 ;
163#endif
164 else
165 hostPath.stripTrailingSlash();
166
167 if (fFailOnError)
168 {
169 /* Check whether the path is full (absolute) */
170 char hostPathFull[RTPATH_MAX];
171 int vrc = RTPathAbs(hostPath.c_str(),
172 hostPathFull,
173 sizeof(hostPathFull));
174 if (RT_FAILURE(vrc))
175 return setErrorBoth(E_INVALIDARG, vrc, tr("Invalid shared folder path: '%s' (%Rrc)"), hostPath.c_str(), vrc);
176
177 if (RTPathCompare(hostPath.c_str(), hostPathFull) != 0)
178 return setError(E_INVALIDARG, tr("Shared folder path '%s' is not absolute"), hostPath.c_str());
179
180 RTFSOBJINFO ObjInfo;
181 vrc = RTPathQueryInfoEx(hostPathFull, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_FOLLOW_LINK);
182 if (RT_FAILURE(vrc))
183 return setError(E_INVALIDARG, tr("RTPathQueryInfo failed on shared folder path '%s': %Rrc"), hostPathFull, vrc);
184
185 if (!RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode))
186 return setError(E_INVALIDARG, tr("Shared folder path '%s' is not a directory"), hostPathFull);
187 }
188
189 unconst(mParent) = aParent;
190
191 unconst(m->strName) = aName;
192 unconst(m->strHostPath) = hostPath;
193 m->fWritable = aWritable;
194 m->fAutoMount = aAutoMount;
195 unconst(m->strAutoMountPoint) = aAutoMountPoint;
196
197 return S_OK;
198}
199
200/**
201 * Uninitializes the instance and sets the ready flag to FALSE.
202 * Called either from FinalRelease() or by the parent when it gets destroyed.
203 */
204void ConsoleSharedFolder::uninit()
205{
206 LogFlowThisFunc(("\n"));
207
208 /* Enclose the state transition Ready->InUninit->NotReady */
209 AutoUninitSpan autoUninitSpan(this);
210 if (autoUninitSpan.uninitDone())
211 return;
212
213 unconst(mParent) = NULL;
214 unconst(mConsole) = NULL;
215}
216
217// wrapped ISharedFolder properties
218/////////////////////////////////////////////////////////////////////////////
219HRESULT ConsoleSharedFolder::getName(com::Utf8Str &aName)
220{
221 /* mName is constant during life time, no need to lock */
222 aName = m->strName;
223 return S_OK;
224}
225
226HRESULT ConsoleSharedFolder::getHostPath(com::Utf8Str &aHostPath)
227{
228 /* mHostPath is constant during life time, no need to lock */
229 aHostPath = m->strHostPath;
230 return S_OK;
231}
232
233HRESULT ConsoleSharedFolder::getAccessible(BOOL *aAccessible)
234{
235 /* mName and mHostPath are constant during life time, no need to lock */
236
237 /* check whether the host path exists */
238 Utf8Str hostPath = m->strHostPath;
239 char hostPathFull[RTPATH_MAX];
240 int vrc = RTPathExists(hostPath.c_str()) ? RTPathReal(hostPath.c_str(),
241 hostPathFull,
242 sizeof(hostPathFull))
243 : VERR_PATH_NOT_FOUND;
244 if (RT_SUCCESS(vrc))
245 {
246 *aAccessible = TRUE;
247 return S_OK;
248 }
249
250 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
251
252 m->strLastAccessError = Utf8StrFmt(tr("'%s' is not accessible (%Rrc)"),
253 m->strHostPath.c_str(),
254 vrc);
255
256 Log1WarningThisFunc(("m.lastAccessError=\"%s\"\n", m->strLastAccessError.c_str()));
257
258 *aAccessible = FALSE;
259
260 return S_OK;
261}
262
263HRESULT ConsoleSharedFolder::getWritable(BOOL *aWritable)
264{
265 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
266 *aWritable = m->fWritable;
267 return S_OK;
268}
269
270HRESULT ConsoleSharedFolder::setWritable(BOOL aWritable)
271{
272 RT_NOREF(aWritable);
273 return E_NOTIMPL;
274}
275
276HRESULT ConsoleSharedFolder::getAutoMount(BOOL *aAutoMount)
277{
278 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
279 *aAutoMount = m->fAutoMount;
280 return S_OK;
281}
282
283HRESULT ConsoleSharedFolder::setAutoMount(BOOL aAutoMount)
284{
285 RT_NOREF(aAutoMount);
286 return E_NOTIMPL;
287}
288
289HRESULT ConsoleSharedFolder::getAutoMountPoint(com::Utf8Str &aAutoMountPoint)
290{
291 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
292 aAutoMountPoint = m->strAutoMountPoint;
293 return S_OK;
294}
295
296HRESULT ConsoleSharedFolder::setAutoMountPoint(com::Utf8Str const &aAutoMountPoint)
297{
298 RT_NOREF(aAutoMountPoint);
299 return E_NOTIMPL;
300}
301
302HRESULT ConsoleSharedFolder::getLastAccessError(com::Utf8Str &aLastAccessError)
303{
304 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
305 aLastAccessError = m->strLastAccessError;
306 return S_OK;
307}
308
309HRESULT ConsoleSharedFolder::getSymlinkPolicy(SymlinkPolicy_T *aSymlinkPolicy)
310{
311 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
312 *aSymlinkPolicy = m->enmSymlinkPolicy;
313 return S_OK;
314}
315
316HRESULT ConsoleSharedFolder::setSymlinkPolicy(SymlinkPolicy_T aSymlinkPolicy)
317{
318 RT_NOREF(aSymlinkPolicy);
319 return E_NOTIMPL;
320}
321
322const Utf8Str& ConsoleSharedFolder::i_getName() const
323{
324 return m->strName;
325}
326
327const Utf8Str& ConsoleSharedFolder::i_getHostPath() const
328{
329 return m->strHostPath;
330}
331
332bool ConsoleSharedFolder::i_isWritable() const
333{
334 return m->fWritable;
335}
336
337bool ConsoleSharedFolder::i_isAutoMounted() const
338{
339 return m->fAutoMount;
340}
341
342const Utf8Str &ConsoleSharedFolder::i_getAutoMountPoint() const
343{
344 return m->strAutoMountPoint;
345}
346
347const SymlinkPolicy_T ConsoleSharedFolder::i_getSymlinkPolicy() const
348{
349 return m->enmSymlinkPolicy;
350}
351
352/* 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