VirtualBox

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

Last change on this file since 33540 was 32704, checked in by vboxsync, 14 years ago

VBoxServiceAutoMount: cosmetics

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