VirtualBox

source: vbox/trunk/src/VBox/Additions/darwin/VBoxSF/VBoxSF-VfsOps.cpp

Last change on this file was 98103, checked in by vboxsync, 20 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.7 KB
Line 
1/* $Id: VBoxSF-VfsOps.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBoxFS - Darwin Shared Folders, Virtual File System Operations.
4 */
5
6/*
7 * Copyright (C) 2013-2023 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
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_SHARED_FOLDERS
33#include "VBoxSFInternal.h"
34
35#include <iprt/assert.h>
36#include <iprt/asm.h>
37#include <iprt/mem.h>
38#include <iprt/string.h>
39#include <VBox/log.h>
40
41
42
43/**
44 * vfsops::vfs_getattr implementation.
45 *
46 * @returns 0 on success or errno.h value on failure.
47 * @param pMount The mount data structure.
48 * @param pFsAttr Input & output structure.
49 * @param pContext Unused kAuth parameter.
50 */
51static int vboxSfDwnVfsGetAttr(mount_t pMount, struct vfs_attr *pFsAttr, vfs_context_t pContext)
52{
53 PVBOXSFMNTDATA pThis = (PVBOXSFMNTDATA)vfs_fsprivate(pMount);
54 AssertReturn(pThis, EBADMSG);
55 LogFlow(("vboxSfDwnVfsGetAttr: %s\n", pThis->MntInfo.szFolder));
56 RT_NOREF(pContext);
57
58 /*
59 * Get the file system stats from the host.
60 */
61 int rc;
62 struct MyEmbReq
63 {
64 VBGLIOCIDCHGCMFASTCALL Hdr;
65 VMMDevHGCMCall Call;
66 VBoxSFParmInformation Parms;
67 SHFLVOLINFO VolInfo;
68 } *pReq = (struct MyEmbReq *)VbglR0PhysHeapAlloc(sizeof(*pReq));
69 if (pReq)
70 {
71 RT_ZERO(pReq->VolInfo);
72
73 VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClientDarwin.idClient,
74 SHFL_FN_INFORMATION, SHFL_CPARMS_INFORMATION, sizeof(*pReq));
75 pReq->Parms.id32Root.type = VMMDevHGCMParmType_32bit;
76 pReq->Parms.id32Root.u.value32 = pThis->hHostFolder.root;
77 pReq->Parms.u64Handle.type = VMMDevHGCMParmType_64bit;
78 pReq->Parms.u64Handle.u.value64 = 0;
79 pReq->Parms.f32Flags.type = VMMDevHGCMParmType_32bit;
80 pReq->Parms.f32Flags.u.value32 = SHFL_INFO_VOLUME | SHFL_INFO_GET;
81 pReq->Parms.cb32.type = VMMDevHGCMParmType_32bit;
82 pReq->Parms.cb32.u.value32 = sizeof(pReq->VolInfo);
83 pReq->Parms.pInfo.type = VMMDevHGCMParmType_Embedded;
84 pReq->Parms.pInfo.u.Embedded.cbData = sizeof(pReq->VolInfo);
85 pReq->Parms.pInfo.u.Embedded.offData = RT_UOFFSETOF(struct MyEmbReq, VolInfo) - sizeof(VBGLIOCIDCHGCMFASTCALL);
86 pReq->Parms.pInfo.u.Embedded.fFlags = VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST;
87
88 int vrc = VbglR0HGCMFastCall(g_SfClientDarwin.handle, &pReq->Hdr, sizeof(*pReq));
89 if (RT_SUCCESS(vrc))
90 vrc = pReq->Call.header.result;
91 if (RT_SUCCESS(vrc))
92 {
93 /*
94 * Fill in stuff.
95 */
96 /* Copy over the results we got from the host. */
97 uint32_t cbUnit = pReq->VolInfo.ulBytesPerSector * pReq->VolInfo.ulBytesPerAllocationUnit;
98 VFSATTR_RETURN(pFsAttr, f_bsize, cbUnit);
99 VFSATTR_RETURN(pFsAttr, f_iosize, _64K); /** @todo what's a good block size... */
100 VFSATTR_RETURN(pFsAttr, f_blocks, (uint64_t)pReq->VolInfo.ullTotalAllocationBytes / cbUnit);
101 VFSATTR_RETURN(pFsAttr, f_bavail, (uint64_t)pReq->VolInfo.ullAvailableAllocationBytes / cbUnit);
102 VFSATTR_RETURN(pFsAttr, f_bfree, (uint64_t)pReq->VolInfo.ullAvailableAllocationBytes / cbUnit);
103 VFSATTR_RETURN(pFsAttr, f_bused,
104 ((uint64_t)pReq->VolInfo.ullTotalAllocationBytes - (uint64_t)pReq->VolInfo.ullAvailableAllocationBytes) / cbUnit);
105 fsid_t const fsid = { { vfs_statfs(pMount)->f_fsid.val[0], vfs_typenum(pMount) } };
106 VFSATTR_RETURN(pFsAttr, f_fsid, fsid);
107
108 /* f_owner is handled by caller. */
109 /* f_signature is handled by caller. */
110
111 struct timespec TmpTv = { 1084190406, 0 };
112 VFSATTR_RETURN(pFsAttr, f_create_time, TmpTv);
113
114 /*
115 * Unsupported bits.
116 */
117 /* Dummies for some values we don't support. */
118 VFSATTR_RETURN(pFsAttr, f_objcount, 0);
119 VFSATTR_RETURN(pFsAttr, f_filecount, 0);
120 VFSATTR_RETURN(pFsAttr, f_dircount, 0);
121 VFSATTR_RETURN(pFsAttr, f_maxobjcount, UINT32_MAX);
122 VFSATTR_RETURN(pFsAttr, f_files, UINT32_MAX);
123 VFSATTR_RETURN(pFsAttr, f_ffree, UINT32_MAX);
124 VFSATTR_RETURN(pFsAttr, f_fssubtype, 0);
125 VFSATTR_RETURN(pFsAttr, f_carbon_fsid, 0);
126
127 /* Totally not supported: */
128 VFSATTR_CLEAR_ACTIVE(pFsAttr, f_modify_time);
129 VFSATTR_CLEAR_ACTIVE(pFsAttr, f_access_time);
130 VFSATTR_CLEAR_ACTIVE(pFsAttr, f_backup_time);
131
132 /*
133 * Annoying capability stuff.
134 * The 'valid' bits are only supposed to be set when we know for sure.
135 */
136 if (VFSATTR_IS_ACTIVE(pFsAttr, f_capabilities))
137 {
138 vol_capabilities_attr_t *pCaps = &pFsAttr->f_capabilities;
139
140 pCaps->valid[VOL_CAPABILITIES_FORMAT] = VOL_CAP_FMT_PERSISTENTOBJECTIDS
141 | VOL_CAP_FMT_SYMBOLICLINKS
142 | VOL_CAP_FMT_HARDLINKS
143 | VOL_CAP_FMT_JOURNAL
144 | VOL_CAP_FMT_JOURNAL_ACTIVE
145 | VOL_CAP_FMT_NO_ROOT_TIMES
146 | VOL_CAP_FMT_SPARSE_FILES
147 | VOL_CAP_FMT_ZERO_RUNS
148 | VOL_CAP_FMT_CASE_SENSITIVE
149 | VOL_CAP_FMT_CASE_PRESERVING
150 | VOL_CAP_FMT_FAST_STATFS
151 | VOL_CAP_FMT_2TB_FILESIZE
152 | VOL_CAP_FMT_OPENDENYMODES
153 | VOL_CAP_FMT_HIDDEN_FILES
154 | VOL_CAP_FMT_PATH_FROM_ID
155 | VOL_CAP_FMT_NO_VOLUME_SIZES
156 | VOL_CAP_FMT_DECMPFS_COMPRESSION
157 | VOL_CAP_FMT_64BIT_OBJECT_IDS;
158 pCaps->capabilities[VOL_CAPABILITIES_FORMAT] = VOL_CAP_FMT_2TB_FILESIZE
159 /// @todo | VOL_CAP_FMT_SYMBOLICLINKS - later
160 /// @todo | VOL_CAP_FMT_SPARSE_FILES - probably, needs testing.
161 /*| VOL_CAP_FMT_CASE_SENSITIVE - case-insensitive */
162 | VOL_CAP_FMT_CASE_PRESERVING
163 /// @todo | VOL_CAP_FMT_HIDDEN_FILES - if windows host.
164 /// @todo | VOL_CAP_FMT_OPENDENYMODES - if windows host.
165 ;
166 pCaps->valid[VOL_CAPABILITIES_INTERFACES] = VOL_CAP_INT_SEARCHFS
167 | VOL_CAP_INT_ATTRLIST
168 | VOL_CAP_INT_NFSEXPORT
169 | VOL_CAP_INT_READDIRATTR
170 | VOL_CAP_INT_EXCHANGEDATA
171 | VOL_CAP_INT_COPYFILE
172 | VOL_CAP_INT_ALLOCATE
173 | VOL_CAP_INT_VOL_RENAME
174 | VOL_CAP_INT_ADVLOCK
175 | VOL_CAP_INT_FLOCK
176 | VOL_CAP_INT_EXTENDED_SECURITY
177 | VOL_CAP_INT_USERACCESS
178 | VOL_CAP_INT_MANLOCK
179 | VOL_CAP_INT_NAMEDSTREAMS
180 | VOL_CAP_INT_EXTENDED_ATTR;
181 pCaps->capabilities[VOL_CAPABILITIES_INTERFACES] = 0
182 /// @todo | VOL_CAP_INT_SEARCHFS
183 /// @todo | VOL_CAP_INT_COPYFILE
184 /// @todo | VOL_CAP_INT_READDIRATTR
185 ;
186
187 pCaps->valid[VOL_CAPABILITIES_RESERVED1] = 0;
188 pCaps->capabilities[VOL_CAPABILITIES_RESERVED1] = 0;
189
190 pCaps->valid[VOL_CAPABILITIES_RESERVED2] = 0;
191 pCaps->capabilities[VOL_CAPABILITIES_RESERVED2] = 0;
192
193 VFSATTR_SET_SUPPORTED(pFsAttr, f_capabilities);
194 }
195
196
197 /*
198 * Annoying attribute stuff.
199 * The 'valid' bits are only supposed to be set when we know for sure.
200 */
201 if (VFSATTR_IS_ACTIVE(pFsAttr, f_attributes))
202 {
203 vol_attributes_attr_t *pAt = &pFsAttr->f_attributes;
204
205 pAt->validattr.commonattr = ATTR_CMN_NAME
206 | ATTR_CMN_DEVID
207 | ATTR_CMN_FSID
208 | ATTR_CMN_OBJTYPE
209 | ATTR_CMN_OBJTAG
210 | ATTR_CMN_OBJID
211 | ATTR_CMN_OBJPERMANENTID
212 | ATTR_CMN_PAROBJID
213 | ATTR_CMN_SCRIPT
214 | ATTR_CMN_CRTIME
215 | ATTR_CMN_MODTIME
216 | ATTR_CMN_CHGTIME
217 | ATTR_CMN_ACCTIME
218 | ATTR_CMN_BKUPTIME
219 | ATTR_CMN_FNDRINFO
220 | ATTR_CMN_OWNERID
221 | ATTR_CMN_GRPID
222 | ATTR_CMN_ACCESSMASK
223 | ATTR_CMN_FLAGS
224 | ATTR_CMN_USERACCESS
225 | ATTR_CMN_EXTENDED_SECURITY
226 | ATTR_CMN_UUID
227 | ATTR_CMN_GRPUUID
228 | ATTR_CMN_FILEID
229 | ATTR_CMN_PARENTID
230 | ATTR_CMN_FULLPATH
231 | ATTR_CMN_ADDEDTIME;
232 pAt->nativeattr.commonattr = ATTR_CMN_NAME
233 | ATTR_CMN_DEVID
234 | ATTR_CMN_FSID
235 | ATTR_CMN_OBJTYPE
236 | ATTR_CMN_OBJTAG
237 | ATTR_CMN_OBJID
238 //| ATTR_CMN_OBJPERMANENTID
239 | ATTR_CMN_PAROBJID
240 //| ATTR_CMN_SCRIPT
241 | ATTR_CMN_CRTIME
242 | ATTR_CMN_MODTIME
243 | ATTR_CMN_CHGTIME
244 | ATTR_CMN_ACCTIME
245 //| ATTR_CMN_BKUPTIME
246 //| ATTR_CMN_FNDRINFO
247 //| ATTR_CMN_OWNERID
248 //| ATTR_CMN_GRPID
249 | ATTR_CMN_ACCESSMASK
250 //| ATTR_CMN_FLAGS
251 //| ATTR_CMN_USERACCESS
252 //| ATTR_CMN_EXTENDED_SECURITY
253 //| ATTR_CMN_UUID
254 //| ATTR_CMN_GRPUUID
255 | ATTR_CMN_FILEID
256 | ATTR_CMN_PARENTID
257 | ATTR_CMN_FULLPATH
258 //| ATTR_CMN_ADDEDTIME
259 ;
260 pAt->validattr.volattr = ATTR_VOL_FSTYPE
261 | ATTR_VOL_SIGNATURE
262 | ATTR_VOL_SIZE
263 | ATTR_VOL_SPACEFREE
264 | ATTR_VOL_SPACEAVAIL
265 | ATTR_VOL_MINALLOCATION
266 | ATTR_VOL_ALLOCATIONCLUMP
267 | ATTR_VOL_IOBLOCKSIZE
268 | ATTR_VOL_OBJCOUNT
269 | ATTR_VOL_FILECOUNT
270 | ATTR_VOL_DIRCOUNT
271 | ATTR_VOL_MAXOBJCOUNT
272 | ATTR_VOL_MOUNTPOINT
273 | ATTR_VOL_NAME
274 | ATTR_VOL_MOUNTFLAGS
275 | ATTR_VOL_MOUNTEDDEVICE
276 | ATTR_VOL_ENCODINGSUSED
277 | ATTR_VOL_CAPABILITIES
278 | ATTR_VOL_UUID
279 | ATTR_VOL_ATTRIBUTES
280 | ATTR_VOL_INFO;
281 pAt->nativeattr.volattr = ATTR_VOL_FSTYPE
282 //| ATTR_VOL_SIGNATURE
283 | ATTR_VOL_SIZE
284 | ATTR_VOL_SPACEFREE
285 | ATTR_VOL_SPACEAVAIL
286 | ATTR_VOL_MINALLOCATION
287 | ATTR_VOL_ALLOCATIONCLUMP
288 | ATTR_VOL_IOBLOCKSIZE
289 //| ATTR_VOL_OBJCOUNT
290 //| ATTR_VOL_FILECOUNT
291 //| ATTR_VOL_DIRCOUNT
292 //| ATTR_VOL_MAXOBJCOUNT
293 //| ATTR_VOL_MOUNTPOINT - ??
294 | ATTR_VOL_NAME
295 | ATTR_VOL_MOUNTFLAGS
296 | ATTR_VOL_MOUNTEDDEVICE
297 //| ATTR_VOL_ENCODINGSUSED
298 | ATTR_VOL_CAPABILITIES
299 //| ATTR_VOL_UUID
300 | ATTR_VOL_ATTRIBUTES
301 //| ATTR_VOL_INFO
302 ;
303 pAt->validattr.dirattr = ATTR_DIR_LINKCOUNT
304 | ATTR_DIR_ENTRYCOUNT
305 | ATTR_DIR_MOUNTSTATUS;
306 pAt->nativeattr.dirattr = 0 //ATTR_DIR_LINKCOUNT
307 | ATTR_DIR_ENTRYCOUNT
308 | ATTR_DIR_MOUNTSTATUS
309 ;
310 pAt->validattr.fileattr = ATTR_FILE_LINKCOUNT
311 | ATTR_FILE_TOTALSIZE
312 | ATTR_FILE_ALLOCSIZE
313 | ATTR_FILE_IOBLOCKSIZE
314 | ATTR_FILE_DEVTYPE
315 | ATTR_FILE_FORKCOUNT
316 | ATTR_FILE_FORKLIST
317 | ATTR_FILE_DATALENGTH
318 | ATTR_FILE_DATAALLOCSIZE
319 | ATTR_FILE_RSRCLENGTH
320 | ATTR_FILE_RSRCALLOCSIZE;
321 pAt->nativeattr.fileattr = 0
322 //|ATTR_FILE_LINKCOUNT
323 | ATTR_FILE_TOTALSIZE
324 | ATTR_FILE_ALLOCSIZE
325 //| ATTR_FILE_IOBLOCKSIZE
326 | ATTR_FILE_DEVTYPE
327 //| ATTR_FILE_FORKCOUNT
328 //| ATTR_FILE_FORKLIST
329 | ATTR_FILE_DATALENGTH
330 | ATTR_FILE_DATAALLOCSIZE
331 | ATTR_FILE_RSRCLENGTH
332 | ATTR_FILE_RSRCALLOCSIZE
333 ;
334 pAt->validattr.forkattr = ATTR_FORK_TOTALSIZE
335 | ATTR_FORK_ALLOCSIZE;
336 pAt->nativeattr.forkattr = 0
337 //| ATTR_FORK_TOTALSIZE
338 //| ATTR_FORK_ALLOCSIZE
339 ;
340 VFSATTR_SET_SUPPORTED(pFsAttr, f_attributes);
341 }
342
343 if (VFSATTR_IS_ACTIVE(pFsAttr, f_vol_name))
344 {
345 RTStrCopy(pFsAttr->f_vol_name, MAXPATHLEN, pThis->MntInfo.szFolder);
346 VFSATTR_SET_SUPPORTED(pFsAttr, f_vol_name);
347 }
348
349 rc = 0;
350 }
351 else
352 {
353 Log(("vboxSfOs2QueryFileInfo: VbglR0SfFsInfo failed: %Rrc\n", vrc));
354 rc = RTErrConvertToErrno(vrc);
355 }
356
357 VbglR0PhysHeapFree(pReq);
358 }
359 else
360 rc = ENOMEM;
361 return rc;
362}
363
364
365/**
366 * vfsops::vfs_root implementation.
367 *
368 * @returns 0 on success or errno.h value on failure.
369 * @param pMount The mount data structure.
370 * @param ppVnode Where to return the referenced root node on success.
371 * @param pContext Unused kAuth parameter.
372 */
373static int vboxSfDwnVfsRoot(mount_t pMount, vnode_t *ppVnode, vfs_context_t pContext)
374{
375 PVBOXSFMNTDATA pThis = (PVBOXSFMNTDATA)vfs_fsprivate(pMount);
376 AssertReturn(pThis, EBADMSG);
377 LogFlow(("vboxSfDwnVfsRoot: pThis=%p:{%s}\n", pThis, pThis->MntInfo.szFolder));
378 RT_NOREF(pContext);
379
380 /*
381 * We shouldn't be callable during unmount, should we?
382 */
383 AssertReturn(vfs_isunmount(pMount), EBUSY);
384
385 /*
386 * There should always be a root node around.
387 */
388 if (pThis->pVnRoot)
389 {
390 int rc = vnode_get(pThis->pVnRoot);
391 if (rc == 0)
392 {
393 *ppVnode = pThis->pVnRoot;
394 LogFlow(("vboxSfDwnVfsRoot: return %p\n", *ppVnode));
395 return 0;
396 }
397 Log(("vboxSfDwnVfsRoot: vnode_get failed! %d\n", rc));
398 return rc;
399 }
400
401 LogRel(("vboxSfDwnVfsRoot: pVnRoot is NULL!\n"));
402 return EILSEQ;
403}
404
405
406/**
407 * vfsops::vfs_umount implementation.
408 *
409 * @returns 0 on success or errno.h value on failure.
410 * @param pMount The mount data.
411 * @param fFlags Unmount flags.
412 * @param pContext kAuth context which we don't care much about.
413 *
414 */
415static int vboxSfDwnVfsUnmount(mount_t pMount, int fFlags, vfs_context_t pContext)
416{
417 PVBOXSFMNTDATA pThis = (PVBOXSFMNTDATA)vfs_fsprivate(pMount);
418 AssertReturn(pThis, 0);
419 LogFlowFunc(("pThis=%p:{%s} fFlags=%#x\n", pThis, pThis->MntInfo.szFolder, fFlags));
420 RT_NOREF(pContext);
421
422 /*
423 * Flush vnodes.
424 */
425 int rc = vflush(pMount, pThis->pVnRoot, fFlags & MNT_FORCE ? FORCECLOSE : 0);
426 if (rc == 0)
427 {
428 /*
429 * Is the file system still busy?
430 *
431 * Until we find a way of killing any active host calls, we cannot properly
432 * respect the MNT_FORCE flag here. So, MNT_FORCE is ignored here.
433 */
434 if ( !pThis->pVnRoot
435 || !vnode_isinuse(pThis->pVnRoot, 1))
436 {
437 /*
438 * Release our root vnode reference and do another flush.
439 */
440 if (pThis->pVnRoot)
441 {
442 vnode_put(pThis->pVnRoot);
443 pThis->pVnRoot = NULL;
444 }
445 vflush(pMount, NULLVP, FORCECLOSE);
446
447 /*
448 * Unmap the shared folder and destroy our mount info structure.
449 */
450 vfs_setfsprivate(pMount, NULL);
451
452 rc = VbglR0SfUnmapFolder(&g_SfClientDarwin, &pThis->hHostFolder);
453 AssertRC(rc);
454
455 RT_ZERO(*pThis);
456 RTMemFree(pThis);
457
458 vfs_clearflags(pMount, MNT_LOCAL); /* ?? */
459 rc = 0;
460
461 g_cVBoxSfMounts--;
462 }
463 else
464 {
465 Log(("VBoxSF: umount failed: file system busy! (%s)\n", pThis->MntInfo.szFolder));
466 rc = EBUSY;
467 }
468 }
469 return rc;
470}
471
472
473/**
474 * vfsops::vfs_start implementation.
475 */
476static int vboxSfDwnVfsStart(mount_t pMount, int fFlags, vfs_context_t pContext)
477{
478 RT_NOREF(pMount, fFlags, pContext);
479 return 0;
480}
481
482
483/**
484 * vfsops::vfs_mount implementation.
485 *
486 * @returns 0 on success or errno.h value on failure.
487 * @param pMount The mount data structure.
488 * @param pDevVp The device to mount. Not used by us.
489 * @param pUserData User space address of parameters supplied to mount().
490 * We expect a VBOXSFDRWNMOUNTINFO structure.
491 * @param pContext kAuth context needed in order to authentificate mount
492 * operation.
493 */
494static int vboxSfDwnVfsMount(mount_t pMount, vnode_t pDevVp, user_addr_t pUserData, vfs_context_t pContext)
495{
496 RT_NOREF(pDevVp, pContext);
497
498 /*
499 * We don't support mount updating.
500 */
501 if (vfs_isupdate(pMount))
502 {
503 LogRel(("VBoxSF: mount: MNT_UPDATE is not supported.\n"));
504 return ENOTSUP;
505 }
506 if (pUserData == USER_ADDR_NULL)
507 {
508 LogRel(("VBoxSF: mount: pUserData is NULL.\n"));
509 return EINVAL;
510 }
511 struct vfsstatfs *pFsStats = vfs_statfs(pMount);
512 AssertReturn(pFsStats, EINVAL);
513
514 /*
515 * Get the mount information from userland.
516 */
517 PVBOXSFMNTDATA pThis = (PVBOXSFMNTDATA)RTMemAllocZ(sizeof(*pThis));
518 if (!pThis)
519 return ENOMEM;
520 pThis->uidMounter = pFsStats->f_owner;
521
522 int rc = RTR0MemUserCopyFrom(&pThis->MntInfo, (RTR3PTR)pUserData, sizeof(pThis->MntInfo));
523 if (RT_FAILURE(rc))
524 {
525 LogRel(("VBoxSF: mount: Failed to copy in mount user data: %Rrc\n", rc));
526 rc = EFAULT;
527 }
528 else if (pThis->MntInfo.u32Magic != VBOXSFDRWNMOUNTINFO_MAGIC)
529 {
530 LogRel(("VBoxSF: mount: Invalid user data magic (%#x)\n", pThis->MntInfo.u32Magic));
531 rc = EINVAL;
532 }
533 else if ( (rc = RTStrValidateEncodingEx(pThis->MntInfo.szFolder, sizeof(pThis->MntInfo.szFolder),
534 RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED)) != VINF_SUCCESS
535 || pThis->MntInfo.szFolder[0] == '\0')
536 {
537 LogRel(("VBoxSF: mount: Invalid or empty share name!\n"));
538 rc = EINVAL;
539 }
540 else
541 {
542 /*
543 * Try map the shared folder.
544 */
545 if (vboxSfDwnConnect())
546 {
547 PSHFLSTRING pName = ShflStringDupUtf8(pThis->MntInfo.szFolder);
548 if (pName)
549 {
550 rc = VbglR0SfMapFolder(&g_SfClientDarwin, pName, &pThis->hHostFolder);
551 RTMemFree(pName);
552 if (RT_SUCCESS(rc))
553 {
554
555 /*
556 * Create a root node, that avoid races later.
557 */
558 pThis->pVnRoot = vboxSfDwnVnAlloc(pMount, VDIR, NULL /*pParent*/, 0);
559 if (pThis->pVnRoot)
560 {
561 /*
562 * Fill file system stats with dummy data.
563 */
564 pFsStats->f_bsize = 512;
565 pFsStats->f_iosize = _64K;
566 pFsStats->f_blocks = _1M;
567 pFsStats->f_bavail = _1M / 4 * 3;
568 pFsStats->f_bused = _1M / 4;
569 pFsStats->f_files = 1024;
570 pFsStats->f_ffree = _64K;
571 vfs_getnewfsid(pMount); /* f_fsid */
572 /* pFsStats->f_fowner - don't touch */
573 /* pFsStats->f_fstypename - don't touch */
574 /* pFsStats->f_mntonname - don't touch */
575 RTStrCopy(pFsStats->f_mntfromname, sizeof(pFsStats->f_mntfromname), pThis->MntInfo.szFolder);
576 /* pFsStats->f_fssubtype - don't touch? */
577 /* pFsStats->f_reserved[0] - don't touch? */
578 /* pFsStats->f_reserved[1] - don't touch? */
579
580 /*
581 * We're good. Set private data and flags.
582 */
583 vfs_setfsprivate(pMount, pThis);
584 vfs_setflags(pMount, MNT_SYNCHRONOUS | MNT_NOSUID | MNT_NODEV);
585 /** @todo Consider flags like MNT_NOEXEC ? */
586
587 /// @todo vfs_setauthopaque(pMount)?
588 /// @todo vfs_clearauthopaqueaccess(pMount)?
589 /// @todo vfs_clearextendedsecurity(pMount)?
590
591 LogRel(("VBoxSF: mount: Successfully mounted '%s' (uidMounter=%u).\n",
592 pThis->MntInfo.szFolder, pThis->uidMounter));
593 return 0;
594 }
595
596 LogRel(("VBoxSF: mount: Failed to allocate root node!\n"));
597 rc = ENOMEM;
598 }
599 else
600 {
601 LogRel(("VBoxSF: mount: VbglR0SfMapFolder failed on '%s': %Rrc\n", pThis->MntInfo.szFolder, rc));
602 rc = ENOENT;
603 }
604 }
605 else
606 rc = ENOMEM;
607 }
608 else
609 {
610 LogRel(("VBoxSF: mount: Not connected to shared folders service!\n"));
611 rc = ENOTCONN;
612 }
613 }
614 RTMemFree(pThis);
615 return rc;
616}
617
618
619/**
620 * VFS operations
621 */
622struct vfsops g_VBoxSfVfsOps =
623{
624 vboxSfDwnVfsMount,
625 vboxSfDwnVfsStart,
626 vboxSfDwnVfsUnmount,
627 vboxSfDwnVfsRoot,
628 NULL, /* Skipped: vfs_quotactl */
629 vboxSfDwnVfsGetAttr,
630 NULL, /* Skipped: vfs_sync */
631 NULL, /* Skipped: vfs_vget */
632 NULL, /* Skipped: vfs_fhtovp */
633 NULL, /* Skipped: vfs_vptofh */
634 NULL, /* Skipped: vfs_init */
635 NULL, /* Skipped: vfs_sysctl */
636 NULL, /* Skipped: vfs_setattr */
637 /* Reserved */
638 { NULL, NULL, NULL, NULL, NULL, NULL, NULL, },
639};
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