VirtualBox

source: vbox/trunk/src/VBox/Additions/common/VBoxService/VBoxServiceAutoMount.cpp@ 31799

Last change on this file since 31799 was 31355, checked in by vboxsync, 15 years ago

SharedFolders/AutoMount: Added support for dynamic mount point prefix.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.9 KB
Line 
1/* $Id: VBoxServiceAutoMount.cpp 31355 2010-08-04 12:37:50Z vboxsync $ */
2/** @file
3 * VBoxService - Auto-mounting for Shared Folders.
4 */
5
6/*
7 * Copyright (C) 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
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#include <iprt/assert.h>
23#include <iprt/dir.h>
24#include <iprt/mem.h>
25#include <iprt/path.h>
26#include <iprt/string.h>
27#include <iprt/semaphore.h>
28#include <VBox/VBoxGuestLib.h>
29#include "VBoxServiceInternal.h"
30#include "VBoxServiceUtils.h"
31
32#include <errno.h>
33#include <grp.h>
34#include <sys/mount.h>
35#ifdef RT_OS_SOLARIS
36#include <sys/vfs.h>
37#endif
38#include <unistd.h>
39
40RT_C_DECLS_BEGIN
41#include "../../linux/sharedfolders/vbsfmount.h"
42RT_C_DECLS_END
43
44/*******************************************************************************
45* Global Variables *
46*******************************************************************************/
47/** The semaphore we're blocking on. */
48static RTSEMEVENTMULTI g_AutoMountEvent = NIL_RTSEMEVENTMULTI;
49
50
51/** @copydoc VBOXSERVICE::pfnPreInit */
52static DECLCALLBACK(int) VBoxServiceAutoMountPreInit(void)
53{
54 return VINF_SUCCESS;
55}
56
57
58/** @copydoc VBOXSERVICE::pfnOption */
59static DECLCALLBACK(int) VBoxServiceAutoMountOption(const char **ppszShort, int argc, char **argv, int *pi)
60{
61 NOREF(ppszShort);
62 NOREF(argc);
63 NOREF(argv);
64 NOREF(pi);
65 return VINF_SUCCESS;
66}
67
68
69/** @copydoc VBOXSERVICE::pfnInit */
70static DECLCALLBACK(int) VBoxServiceAutoMountInit(void)
71{
72 VBoxServiceVerbose(3, "VBoxServiceAutoMountInit\n");
73
74 int rc = RTSemEventMultiCreate(&g_AutoMountEvent);
75 AssertRCReturn(rc, rc);
76
77 return rc;
78}
79
80
81static int VBoxServiceAutoMountPrepareMountPoint(const char *pszMountPoint, vbsf_mount_opts *pOpts)
82{
83 AssertPtr(pOpts);
84
85 RTFMODE fMode = 0770; /* Owner (=root) and the group (=vboxsf) have full access. */
86 int rc = RTDirCreateFullPath(pszMountPoint, fMode);
87 if (RT_SUCCESS(rc))
88 {
89 rc = RTPathSetOwnerEx(pszMountPoint, -1 /* Owner, unchanged */, pOpts->gid, RTPATH_F_ON_LINK);
90 if (RT_SUCCESS(rc))
91 {
92 rc = RTPathSetMode(pszMountPoint, fMode);
93 VBoxServiceVerbose(3, "RTPathSetMode = rc = %Rrc\n");
94 if (RT_FAILURE(rc))
95 VBoxServiceError("VBoxServiceAutoMountPrepareMountPoint: Could not set mode for mount directory \"%s\", rc = %Rrc\n",
96 pszMountPoint, rc);
97 }
98 else
99 VBoxServiceError("VBoxServiceAutoMountPrepareMountPoint: Could not set permissions for mount directory \"%s\", rc = %Rrc\n",
100 pszMountPoint, rc);
101 }
102 else
103 VBoxServiceError("VBoxServiceAutoMountPrepareMountPoint: Could not create mount directory \"%s\", rc = %Rrc\n",
104 pszMountPoint, rc);
105 return rc;
106}
107
108
109static int VBoxServiceAutoMountSharedFolder(const char *pszShareName, const char *pszMountPoint,
110 vbsf_mount_opts *pOpts)
111{
112 AssertPtr(pOpts);
113
114 int rc = VBoxServiceAutoMountPrepareMountPoint(pszMountPoint, pOpts);
115 if (RT_SUCCESS(rc))
116 {
117#ifdef RT_OS_SOLARIS
118 int flags = 0; /* No flags used yet. */
119 int r = mount(pszShareName,
120 pszMountPoint,
121 flags,
122 "vboxsf",
123 NULL, /* char *dataptr */
124 0, /* int datalen */
125 NULL, /* char *optptr */
126 0); /* int optlen */
127 if (r == 0)
128 {
129 VBoxServiceVerbose(0, "VBoxServiceAutoMountWorker: Shared folder \"%s\" was mounted to \"%s\"\n", pszShareName, pszMountPoint);
130 }
131 else
132 {
133 if (errno != EBUSY) /* Share is already mounted? Then skip error msg. */
134 VBoxServiceError("VBoxServiceAutoMountWorker: Could not mount shared folder \"%s\" to \"%s\", error = %s\n",
135 pszShareName, pszMountPoint, strerror(errno));
136 }
137#else /* !RT_OS_SOLARIS */
138 unsigned long flags = MS_NODEV;
139
140 const char *szOptions = { "rw" };
141 struct vbsf_mount_info_new mntinf;
142
143 mntinf.nullchar = '\0';
144 mntinf.signature[0] = VBSF_MOUNT_SIGNATURE_BYTE_0;
145 mntinf.signature[1] = VBSF_MOUNT_SIGNATURE_BYTE_1;
146 mntinf.signature[2] = VBSF_MOUNT_SIGNATURE_BYTE_2;
147 mntinf.length = sizeof(mntinf);
148
149 mntinf.uid = pOpts->uid;
150 mntinf.gid = pOpts->gid;
151 mntinf.ttl = pOpts->ttl;
152 mntinf.dmode = pOpts->dmode;
153 mntinf.fmode = pOpts->fmode;
154 mntinf.dmask = pOpts->dmask;
155 mntinf.fmask = pOpts->fmask;
156
157 strcpy(mntinf.name, pszShareName);
158 strcpy(mntinf.nls_name, "\0");
159
160 int r = mount(NULL,
161 pszMountPoint,
162 "vboxsf",
163 flags,
164 &mntinf);
165 if (r == 0)
166 {
167 VBoxServiceVerbose(0, "VBoxServiceAutoMountWorker: Shared folder \"%s\" was mounted to \"%s\"\n", pszShareName, pszMountPoint);
168
169 r = vbsfmount_complete(pszShareName, pszMountPoint, flags, pOpts);
170 switch (r)
171 {
172 case 0: /* Success. */
173 errno = 0; /* Clear all errors/warnings. */
174 break;
175
176 case 1:
177 VBoxServiceError("VBoxServiceAutoMountWorker: Could not update mount table (failed to create memstream): %s\n", strerror(errno));
178 break;
179
180 case 2:
181 VBoxServiceError("VBoxServiceAutoMountWorker: Could not open mount table for update: %s\n", strerror(errno));
182 break;
183
184 case 3:
185 VBoxServiceError("VBoxServiceAutoMountWorker: Could not add an entry to the mount table: %s\n", strerror(errno));
186 break;
187
188 default:
189 VBoxServiceError("VBoxServiceAutoMountWorker: Unknown error while completing mount operation: %d\n", r);
190 break;
191 }
192 }
193 else /* r != 0 */
194 {
195 if (errno == EPROTO)
196 {
197 /* Sometimes the mount utility messes up the share name. Try to
198 * un-mangle it again. */
199 char szCWD[4096];
200 size_t cchCWD;
201 if (!getcwd(szCWD, sizeof(szCWD)))
202 VBoxServiceError("VBoxServiceAutoMountWorker: Failed to get the current working directory\n");
203 cchCWD = strlen(szCWD);
204 if (!strncmp(pszMountPoint, szCWD, cchCWD))
205 {
206 while (pszMountPoint[cchCWD] == '/')
207 ++cchCWD;
208 /* We checked before that we have enough space */
209 strcpy(mntinf.name, pszMountPoint + cchCWD);
210 }
211 r = mount(NULL, pszMountPoint, "vboxsf", flags, &mntinf);
212 }
213 if (errno == EPROTO)
214 {
215 /* New mount tool with old vboxsf module? Try again using the old
216 * vbsf_mount_info_old structure. */
217 struct vbsf_mount_info_old mntinf_old;
218 memcpy(&mntinf_old.name, &mntinf.name, MAX_HOST_NAME);
219 memcpy(&mntinf_old.nls_name, mntinf.nls_name, MAX_NLS_NAME);
220 mntinf_old.uid = mntinf.uid;
221 mntinf_old.gid = mntinf.gid;
222 mntinf_old.ttl = mntinf.ttl;
223 r = mount(NULL, pszMountPoint, "vboxsf", flags, &mntinf_old);
224 }
225 if (errno != EBUSY) /* Share is already mounted? Then skip error msg. */
226 VBoxServiceError("VBoxServiceAutoMountWorker: Could not mount shared folder \"%s\" to \"%s\", error = %s\n",
227 pszShareName, pszMountPoint, strerror(errno));
228 }
229#endif /* !RT_OS_SOLARIS */
230 }
231
232 VBoxServiceVerbose(3, "VBoxServiceAutoMountWorker: Mounting returned with rc=%Rrc, errno=%d, error=%s\n",
233 rc, errno, strerror(errno));
234 return RTErrConvertFromErrno(errno);
235}
236
237
238/** @copydoc VBOXSERVICE::pfnWorker */
239DECLCALLBACK(int) VBoxServiceAutoMountWorker(bool volatile *pfShutdown)
240{
241 /*
242 * Tell the control thread that it can continue
243 * spawning services.
244 */
245 RTThreadUserSignal(RTThreadSelf());
246
247 uint32_t u32ClientId;
248 int rc = VbglR3SharedFolderConnect(&u32ClientId);
249 if (!RT_SUCCESS(rc))
250 VBoxServiceVerbose(3, "VBoxServiceAutoMountWorker: Failed to connect to the shared folder service, error %Rrc\n", rc);
251 else
252 {
253 uint32_t cMappings;
254 VBGLR3SHAREDFOLDERMAPPING *paMappings;
255
256 rc = VbglR3SharedFolderGetMappings(u32ClientId, true /* Only process auto-mounted folders */,
257 &paMappings, &cMappings);
258 if (RT_SUCCESS(rc))
259 {
260 char *pszSharePrefix;
261 rc = VbglR3SharedFolderGetMountPrefix(&pszSharePrefix);
262 if (RT_SUCCESS(rc))
263 {
264 VBoxServiceVerbose(3, "VBoxServiceAutoMountWorker: Shared folder mount prefix set to \"%s\"\n", pszSharePrefix);
265#if 0
266 /* Check for a fixed/virtual auto-mount share. */
267 if (VbglR3SharedFolderExists(u32ClientId, "vbsfAutoMount"))
268 {
269 VBoxServiceVerbose(3, "VBoxServiceAutoMountWorker: Host supports auto-mount root\n");
270 }
271 else
272 {
273#endif
274 VBoxServiceVerbose(3, "VBoxServiceAutoMountWorker: Got %u shared folder mappings\n", cMappings);
275 for (uint32_t i = 0; i < cMappings && RT_SUCCESS(rc); i++)
276 {
277 char *pszShareName = NULL;
278 rc = VbglR3SharedFolderGetName(u32ClientId, paMappings[i].u32Root, &pszShareName);
279 if ( RT_SUCCESS(rc)
280 && *pszShareName)
281 {
282 VBoxServiceVerbose(3, "VBoxServiceAutoMountWorker: Connecting share %u (%s) ...\n", i+1, pszShareName);
283
284 char *pszMountPoint = NULL;
285 #ifdef RT_OS_SOLARIS
286 if ( RTStrAPrintf(&pszMountPoint, "/mnt/%s%s", pszSharePrefix, pszShareName) > 0
287 #else
288 if ( RTStrAPrintf(&pszMountPoint, "/media/%s%s", pszSharePrefix, pszShareName) > 0
289 #endif
290 && pszMountPoint)
291 {
292 struct group *grp_vboxsf = getgrnam("vboxsf");
293 if (grp_vboxsf)
294 {
295 struct vbsf_mount_opts mount_opts =
296 {
297 0, /* uid */
298 grp_vboxsf->gr_gid, /* gid */
299 0, /* ttl */
300 0770, /* dmode, owner and group "vboxsf" have full access */
301 0770, /* fmode, owner and group "vboxsf" have full access */
302 0, /* dmask */
303 0, /* fmask */
304 0, /* ronly */
305 0, /* noexec */
306 0, /* nodev */
307 0, /* nosuid */
308 0, /* remount */
309 "\0", /* nls_name */
310 NULL, /* convertcp */
311 };
312
313 /* We always use "/media" as our root mounting directory. */
314 /** @todo Detect the correct "media/mnt" directory, based on the current guest (?). */
315 rc = VBoxServiceAutoMountSharedFolder(pszShareName, pszMountPoint, &mount_opts);
316 }
317 else
318 VBoxServiceError("VBoxServiceAutoMountWorker: Group \"vboxsf\" does not exist\n");
319 RTStrFree(pszMountPoint);
320 }
321 else
322 rc = VERR_NO_MEMORY;
323 RTStrFree(pszShareName);
324 }
325 else
326 VBoxServiceError("VBoxServiceAutoMountWorker: Error while getting the shared folder name for root node = %u, rc = %Rrc\n",
327 paMappings[i].u32Root, rc);
328 } /* for cMappings. */
329 #if 0
330 }
331 #endif
332 RTStrFree(pszSharePrefix);
333 } /* Mount prefix. */
334 else
335 VBoxServiceError("VBoxServiceAutoMountWorker: Error while getting the shared folder mount prefix, rc = %Rrc\n", rc);
336 RTMemFree(paMappings);
337 }
338 else
339 VBoxServiceError("VBoxServiceAutoMountWorker: Error while getting the shared folder mappings, rc = %Rrc\n", rc);
340 VbglR3SharedFolderDisconnect(u32ClientId);
341 }
342
343 RTSemEventMultiDestroy(g_AutoMountEvent);
344 g_AutoMountEvent = NIL_RTSEMEVENTMULTI;
345
346 VBoxServiceVerbose(3, "VBoxServiceAutoMountWorker: Finished\n");
347 return 0;
348}
349
350/** @copydoc VBOXSERVICE::pfnTerm */
351static DECLCALLBACK(void) VBoxServiceAutoMountTerm(void)
352{
353 VBoxServiceVerbose(3, "VBoxServiceAutoMountTerm\n");
354 return;
355}
356
357
358/** @copydoc VBOXSERVICE::pfnStop */
359static DECLCALLBACK(void) VBoxServiceAutoMountStop(void)
360{
361 RTSemEventMultiSignal(g_AutoMountEvent);
362}
363
364
365/**
366 * The 'automount' service description.
367 */
368VBOXSERVICE g_AutoMount =
369{
370 /* pszName. */
371 "automount",
372 /* pszDescription. */
373 "Auto-mount for Shared Folders",
374 /* pszUsage. */
375 NULL,
376 /* pszOptions. */
377 NULL,
378 /* methods */
379 VBoxServiceAutoMountPreInit,
380 VBoxServiceAutoMountOption,
381 VBoxServiceAutoMountInit,
382 VBoxServiceAutoMountWorker,
383 VBoxServiceAutoMountStop,
384 VBoxServiceAutoMountTerm
385};
Note: See TracBrowser for help on using the repository browser.

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