VirtualBox

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

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

Shared Folders/AutoMount: Update for non-Windows guests.

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