VirtualBox

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

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

Burn fix.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.1 KB
Line 
1/* $Id: VBoxServiceAutoMount.cpp 31317 2010-08-02 16:01:02Z 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.215389.xyz. 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#if 0
261 /* Check for a fixed/virtual auto-mount share. */
262 if (VbglR3SharedFolderExists(u32ClientId, "vbsfAutoMount"))
263 {
264 VBoxServiceVerbose(3, "VBoxServiceAutoMountWorker: Host supports auto-mount root\n");
265 }
266 else
267 {
268#endif
269 VBoxServiceVerbose(3, "VBoxServiceAutoMountWorker: Got %u shared folder mappings\n", cMappings);
270 for (uint32_t i = 0; i < cMappings && RT_SUCCESS(rc); i++)
271 {
272 char *pszShareName = NULL;
273 rc = VbglR3SharedFolderGetName(u32ClientId, paMappings[i].u32Root, &pszShareName);
274 if ( RT_SUCCESS(rc)
275 && *pszShareName)
276 {
277 VBoxServiceVerbose(3, "VBoxServiceAutoMountWorker: Connecting share %u (%s) ...\n", i+1, pszShareName);
278
279 char *pszMountPoint = NULL;
280#ifdef RT_OS_SOLARIS
281 if ( RTStrAPrintf(&pszMountPoint, "/mnt/sf_%s", pszShareName) > 0
282#else
283 if ( RTStrAPrintf(&pszMountPoint, "/media/sf_%s", pszShareName) > 0
284#endif
285 && pszMountPoint)
286 {
287 struct group *grp_vboxsf = getgrnam("vboxsf");
288 if (grp_vboxsf)
289 {
290 struct vbsf_mount_opts mount_opts =
291 {
292 0, /* uid */
293 grp_vboxsf->gr_gid, /* gid */
294 0, /* ttl */
295 0770, /* dmode, owner and group "vboxsf" have full access */
296 0770, /* fmode, owner and group "vboxsf" have full access */
297 0, /* dmask */
298 0, /* fmask */
299 0, /* ronly */
300 0, /* noexec */
301 0, /* nodev */
302 0, /* nosuid */
303 0, /* remount */
304 "\0", /* nls_name */
305 NULL, /* convertcp */
306 };
307
308 /* We always use "/media" as our root mounting directory. */
309 /** @todo Detect the correct "media/mnt" directory, based on the current guest (?). */
310 rc = VBoxServiceAutoMountSharedFolder(pszShareName, pszMountPoint, &mount_opts);
311 }
312 else
313 VBoxServiceError("VBoxServiceAutoMountWorker: Group \"vboxsf\" does not exist\n");
314 RTStrFree(pszMountPoint);
315 }
316 else
317 rc = VERR_NO_MEMORY;
318 RTStrFree(pszShareName);
319 }
320 else
321 VBoxServiceError("VBoxServiceAutoMountWorker: Error while getting the shared folder name for root node = %u, rc = %Rrc\n",
322 paMappings[i].u32Root, rc);
323 }
324#if 0
325 }
326#endif
327 RTMemFree(paMappings);
328 }
329 else
330 VBoxServiceError("VBoxServiceAutoMountWorker: Error while getting the shared folder mappings, rc = %Rrc\n", rc);
331 VbglR3SharedFolderDisconnect(u32ClientId);
332 }
333
334 RTSemEventMultiDestroy(g_AutoMountEvent);
335 g_AutoMountEvent = NIL_RTSEMEVENTMULTI;
336
337 VBoxServiceVerbose(3, "VBoxServiceAutoMountWorker: Finished\n");
338 return 0;
339}
340
341/** @copydoc VBOXSERVICE::pfnTerm */
342static DECLCALLBACK(void) VBoxServiceAutoMountTerm(void)
343{
344 VBoxServiceVerbose(3, "VBoxServiceAutoMountTerm\n");
345 return;
346}
347
348
349/** @copydoc VBOXSERVICE::pfnStop */
350static DECLCALLBACK(void) VBoxServiceAutoMountStop(void)
351{
352 RTSemEventMultiSignal(g_AutoMountEvent);
353}
354
355
356/**
357 * The 'automount' service description.
358 */
359VBOXSERVICE g_AutoMount =
360{
361 /* pszName. */
362 "automount",
363 /* pszDescription. */
364 "Auto-mount for Shared Folders",
365 /* pszUsage. */
366 NULL,
367 /* pszOptions. */
368 NULL,
369 /* methods */
370 VBoxServiceAutoMountPreInit,
371 VBoxServiceAutoMountOption,
372 VBoxServiceAutoMountInit,
373 VBoxServiceAutoMountWorker,
374 VBoxServiceAutoMountStop,
375 VBoxServiceAutoMountTerm
376};
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