VirtualBox

source: vbox/trunk/src/VBox/Additions/darwin/VBoxSF/VBoxSF-VNodeOps.cpp@ 106061

Last change on this file since 106061 was 106061, checked in by vboxsync, 3 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: 27.9 KB
Line 
1/* $Id: VBoxSF-VNodeOps.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * VBoxSF - Darwin Shared Folders, VNode Operations.
4 */
5
6
7/*
8 * Copyright (C) 2013-2024 Oracle and/or its affiliates.
9 *
10 * This file is part of VirtualBox base platform packages, as
11 * available from https://www.virtualbox.org.
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation, in version 3 of the
16 * License.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see <https://www.gnu.org/licenses>.
25 *
26 * SPDX-License-Identifier: GPL-3.0-only
27 */
28
29
30/*********************************************************************************************************************************
31* Header Files *
32*********************************************************************************************************************************/
33#define LOG_GROUP LOG_GROUP_SHARED_FOLDERS
34#include "VBoxSFInternal.h"
35
36#include <iprt/mem.h>
37#include <iprt/assert.h>
38#include <VBox/log.h>
39
40
41/*********************************************************************************************************************************
42* Structures and Typedefs *
43*********************************************************************************************************************************/
44struct default_error_args_hack
45{
46 struct default_error_vdesc_hack
47 {
48 int vdesc_offset;
49 const char *vdesc_name;
50 } const *a_desc;
51};
52
53
54
55/**
56 * Default implementation that returns ENOTSUP.
57 */
58static int vboxSfDwnVnDefaultError(struct default_error_args_hack *pArgs)
59{
60 Log(("vboxSfDwnVnDefaultError: %s\n", RT_VALID_PTR(pArgs) && RT_VALID_PTR(pArgs->a_desc) ? pArgs->a_desc->vdesc_name : "??"));
61 RT_NOREF(pArgs);
62 return ENOTSUP;
63}
64
65
66static int vboxFsDwnVnGetAttr(struct vnop_getattr_args *pArgs)
67{
68#if 1
69 RT_NOREF(pArgs);
70 return ENOTSUP;
71#else
72
73 vboxvfs_mount_t *pMount;
74 struct vnode_attr *vnode_args;
75 vboxvfs_vnode_t *pVnodeData;
76
77 struct timespec timespec;
78
79 SHFLFSOBJINFO Info;
80 mount_t mp;
81 vnode_t vnode;
82 int rc;
83
84 PDEBUG("Getting vnode attribute...");
85
86 AssertReturn(pArgs, EINVAL);
87
88 vnode = pArgs->a_vp; AssertReturn(vnode, EINVAL);
89 vnode_args = pArgs->a_vap; AssertReturn(vnode_args, EINVAL);
90 mp = vnode_mount(vnode); AssertReturn(mp, EINVAL);
91 pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp); AssertReturn(pMount, EINVAL);
92 pVnodeData = (vboxvfs_vnode_t *)vnode_fsnode(vnode); AssertReturn(pVnodeData, EINVAL);
93
94 lck_rw_lock_shared(pVnodeData->pLock);
95
96 rc = vboxvfs_get_info_internal(mp, pVnodeData->pPath, &Info);
97 if (rc == 0)
98 {
99 /* Set timestamps */
100 RTTimeSpecGetTimespec(&Info.BirthTime, &timespec); VATTR_RETURN(vnode_args, va_create_time, timespec);
101 RTTimeSpecGetTimespec(&Info.AccessTime, &timespec); VATTR_RETURN(vnode_args, va_access_time, timespec);
102 RTTimeSpecGetTimespec(&Info.ModificationTime, &timespec); VATTR_RETURN(vnode_args, va_modify_time, timespec);
103 RTTimeSpecGetTimespec(&Info.ChangeTime, &timespec); VATTR_RETURN(vnode_args, va_change_time, timespec);
104 VATTR_CLEAR_ACTIVE(vnode_args, va_backup_time);
105
106 /* Set owner info. */
107 VATTR_RETURN(vnode_args, va_uid, pMount->owner);
108 VATTR_CLEAR_ACTIVE(vnode_args, va_gid);
109
110 /* Access mode and flags */
111 VATTR_RETURN(vnode_args, va_mode, vboxvfs_h2g_mode_inernal(Info.Attr.fMode));
112 VATTR_RETURN(vnode_args, va_flags, Info.Attr.u.Unix.fFlags);
113
114 /* The current generation number (0 if this information is not available) */
115 VATTR_RETURN(vnode_args, va_gen, Info.Attr.u.Unix.GenerationId);
116
117 VATTR_RETURN(vnode_args, va_rdev, 0);
118 VATTR_RETURN(vnode_args, va_nlink, 2);
119
120 VATTR_RETURN(vnode_args, va_data_size, sizeof(struct dirent)); /* Size of data returned per each readdir() request */
121
122 /* Hope, when it overflows nothing catastrophical will heppen! If we will not assign
123 * a uniq va_fileid to each vnode, `ls`, 'find' (and simmilar tools that uses fts_read() calls) will think that
124 * each sub-directory is self-cycled. */
125 VATTR_RETURN(vnode_args, va_fileid, (pMount->cFileIdCounter++));
126
127 /* Not supported */
128 VATTR_CLEAR_ACTIVE(vnode_args, va_linkid);
129 VATTR_CLEAR_ACTIVE(vnode_args, va_parentid);
130 VATTR_CLEAR_ACTIVE(vnode_args, va_fsid);
131 VATTR_CLEAR_ACTIVE(vnode_args, va_filerev);
132
133 /* Not present on 10.6 */
134 //VATTR_CLEAR_ACTIVE(vnode_args, va_addedtime);
135
136 /** @todo take care about va_encoding (file name encoding) */
137 VATTR_CLEAR_ACTIVE(vnode_args, va_encoding);
138 /** @todo take care about: va_acl */
139 VATTR_CLEAR_ACTIVE(vnode_args, va_acl);
140
141 VATTR_CLEAR_ACTIVE(vnode_args, va_name);
142 VATTR_CLEAR_ACTIVE(vnode_args, va_uuuid);
143 VATTR_CLEAR_ACTIVE(vnode_args, va_guuid);
144
145 VATTR_CLEAR_ACTIVE(vnode_args, va_total_size);
146 VATTR_CLEAR_ACTIVE(vnode_args, va_total_alloc);
147 VATTR_CLEAR_ACTIVE(vnode_args, va_data_alloc);
148 VATTR_CLEAR_ACTIVE(vnode_args, va_iosize);
149
150 VATTR_CLEAR_ACTIVE(vnode_args, va_nchildren);
151 VATTR_CLEAR_ACTIVE(vnode_args, va_dirlinkcount);
152 }
153 else
154 {
155 PDEBUG("getattr: unable to get VBoxVFS object info");
156 }
157
158 lck_rw_unlock_shared(pVnodeData->pLock);
159
160 return rc;
161#endif
162}
163
164#if 0
165/**
166 * Helper function for vboxvfs_vnode_lookup(): create new vnode.
167 */
168static int
169vboxvfs_vnode_lookup_instantinate_vnode(vnode_t parent_vnode, char *entry_name, vnode_t *result_vnode)
170{
171 /* We need to construct full path to vnode in order to get
172 * vboxvfs_get_info_internal() to understand us! */
173
174 char *pszCurDirPath;
175 int cbCurDirPath = MAXPATHLEN;
176
177 mount_t mp = vnode_mount(parent_vnode); AssertReturn(mp, EINVAL);
178 vnode_t vnode;
179
180 int rc;
181
182 pszCurDirPath = (char *)RTMemAllocZ(cbCurDirPath);
183 if (pszCurDirPath)
184 {
185 rc = vn_getpath(parent_vnode, pszCurDirPath, &cbCurDirPath);
186 if (rc == 0 && cbCurDirPath < MAXPATHLEN)
187 {
188 SHFLFSOBJINFO Info;
189 PSHFLSTRING pSHFLPath;
190
191 /* Add '/' between path parts and truncate name if it is too long */
192 strncat(pszCurDirPath, "/", 1); strncat(pszCurDirPath, entry_name, MAXPATHLEN - cbCurDirPath - 1);
193
194 rc = vboxvfs_guest_path_to_shflstring_path_internal(mp, pszCurDirPath, strlen(pszCurDirPath) + 1, &pSHFLPath);
195 if (rc == 0)
196 {
197 rc = vboxvfs_get_info_internal(mp, pSHFLPath, (PSHFLFSOBJINFO)&Info);
198 if (rc == 0)
199 {
200 enum vtype type;
201
202 if (RTFS_IS_DIRECTORY(Info.Attr.fMode)) type = VDIR;
203 else if (RTFS_IS_FILE (Info.Attr.fMode)) type = VREG;
204 else
205 {
206 PDEBUG("Not supported VFS object (%s) type: mode 0x%X",
207 entry_name,
208 Info.Attr.fMode);
209
210 RTMemFree(pszCurDirPath);
211 vboxvfs_put_path_internal((void **)&pSHFLPath);
212 return ENOENT;
213 }
214 /* Create new vnode */
215 rc = vboxvfs_create_vnode_internal(mp, type, parent_vnode, FALSE, pSHFLPath, &vnode);
216 if (rc == 0)
217 {
218 PDEBUG("new vnode object '%s' has been created", entry_name);
219
220 *result_vnode = vnode;
221 RTMemFree(pszCurDirPath);
222
223 return 0;
224 }
225 else
226 PDEBUG("Unable to create vnode: %d", rc);
227 }
228 else
229 PDEBUG("Unable to get host object info: %d", rc);
230
231 vboxvfs_put_path_internal((void **)&pSHFLPath);
232 }
233 else
234 PDEBUG("Unable to convert guest<->host path");
235 }
236 else
237 PDEBUG("Unable to construct vnode path: %d", rc);
238
239 RTMemFree(pszCurDirPath);
240 }
241 else
242 {
243 PDEBUG("Unable to allocate memory for path buffer");
244 rc = ENOMEM;
245 }
246
247 return rc;
248}
249
250/**
251 * Helper function for vboxvfs_vnode_lookup(): take care
252 * about '.' and '..' directory entries.
253 */
254static int
255vboxvfs_vnode_lookup_dot_handler(struct vnop_lookup_args *pArgs, vnode_t *result_vnode)
256{
257 vnode_t vnode = NULL;
258
259 if (pArgs->a_cnp->cn_flags & ISDOTDOT)
260 {
261 vnode = vnode_getparent(pArgs->a_dvp);
262 if (vnode)
263 {
264 PDEBUG("return parent directory");
265 *result_vnode = vnode;
266 return 0;
267 }
268 else
269 {
270 PDEBUG("return parent directory not found, return current directory");
271 *result_vnode = pArgs->a_dvp;
272 return 0;
273 }
274 }
275 else if ((strncmp(pArgs->a_cnp->cn_nameptr, ".", 1) == 0) &&
276 pArgs->a_cnp->cn_namelen == 1)
277 {
278 PDEBUG("return current directory");
279 *result_vnode = pArgs->a_dvp;
280 return 0;
281 }
282
283 return ENOENT;
284}
285#endif
286
287static int vboxSfDwnVnLookup(struct vnop_lookup_args *pArgs)
288{
289#if 1
290 RT_NOREF(pArgs);
291 return ENOTSUP;
292#else
293 int rc;
294
295 vnode_t vnode;
296 vboxvfs_vnode_t *pVnodeData;
297
298 PDEBUG("Looking up for vnode...");
299
300 AssertReturn(pArgs, EINVAL);
301 AssertReturn(pArgs->a_dvp, EINVAL);
302 AssertReturn(vnode_isdir(pArgs->a_dvp), EINVAL);
303 AssertReturn(pArgs->a_cnp, EINVAL);
304 AssertReturn(pArgs->a_cnp->cn_nameptr, EINVAL);
305 AssertReturn(pArgs->a_vpp, EINVAL);
306
307 pVnodeData = (vboxvfs_vnode_t *)vnode_fsnode(pArgs->a_dvp);
308 AssertReturn(pVnodeData, EINVAL);
309 AssertReturn(pVnodeData->pLock, EINVAL);
310
311 /*
312 todo: take care about pArgs->a_cnp->cn_nameiop
313 */
314
315 if (pArgs->a_cnp->cn_nameiop == LOOKUP) PDEBUG("LOOKUP");
316 else if (pArgs->a_cnp->cn_nameiop == CREATE) PDEBUG("CREATE");
317 else if (pArgs->a_cnp->cn_nameiop == RENAME) PDEBUG("RENAME");
318 else if (pArgs->a_cnp->cn_nameiop == DELETE) PDEBUG("DELETE");
319 else PDEBUG("Unknown cn_nameiop: 0x%X", (int)pArgs->a_cnp->cn_nameiop);
320
321 lck_rw_lock_exclusive(pVnodeData->pLock);
322
323 /* Take care about '.' and '..' entries */
324 if (vboxvfs_vnode_lookup_dot_handler(pArgs, &vnode) == 0)
325 {
326 vnode_get(vnode);
327 *pArgs->a_vpp = vnode;
328
329 lck_rw_unlock_exclusive(pVnodeData->pLock);
330
331 return 0;
332 }
333
334 /* Look into VFS cache and attempt to find previously allocated vnode there. */
335 rc = cache_lookup(pArgs->a_dvp, &vnode, pArgs->a_cnp);
336 if (rc == -1) /* Record found */
337 {
338 PDEBUG("Found record in VFS cache");
339
340 /* Check if VFS object still exist on a host side */
341 if (vboxvfs_exist_internal(vnode))
342 {
343 /* Prepare & return cached vnode */
344 vnode_get(vnode);
345 *pArgs->a_vpp = vnode;
346
347 rc = 0;
348 }
349 else
350 {
351 /* If vnode exist in guets VFS cache, but not exist on a host -- just forget it. */
352 cache_purge(vnode);
353 /** @todo free vnode data here */
354 rc = ENOENT;
355 }
356 }
357 else
358 {
359 PDEBUG("cache_lookup() returned %d, create new VFS vnode", rc);
360
361 rc = vboxvfs_vnode_lookup_instantinate_vnode(pArgs->a_dvp, pArgs->a_cnp->cn_nameptr, &vnode);
362 if (rc == 0)
363 {
364 cache_enter(pArgs->a_dvp, vnode, pArgs->a_cnp);
365 *pArgs->a_vpp = vnode;
366 }
367 else
368 {
369 rc = ENOENT;
370 }
371 }
372
373 lck_rw_unlock_exclusive(pVnodeData->pLock);
374
375 return rc;
376#endif
377}
378
379static int vboxSfDwnVnOpen(struct vnop_open_args *pArgs)
380{
381#if 1
382 RT_NOREF(pArgs);
383 return ENOTSUP;
384#else
385 vnode_t vnode;
386 vboxvfs_vnode_t *pVnodeData;
387 uint32_t fHostFlags;
388 mount_t mp;
389 vboxvfs_mount_t *pMount;
390
391 int rc;
392
393 PDEBUG("Opening vnode...");
394
395 AssertReturn(pArgs, EINVAL);
396
397 vnode = pArgs->a_vp; AssertReturn(vnode, EINVAL);
398 pVnodeData = (vboxvfs_vnode_t *)vnode_fsnode(vnode); AssertReturn(pVnodeData, EINVAL);
399 mp = vnode_mount(vnode); AssertReturn(mp, EINVAL);
400 pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp); AssertReturn(pMount, EINVAL);
401
402 lck_rw_lock_exclusive(pVnodeData->pLock);
403
404 if (vnode_isinuse(vnode, 0))
405 {
406 PDEBUG("vnode '%s' (handle 0x%X) already has VBoxVFS object handle assigned, just return ok",
407 (char *)pVnodeData->pPath->String.utf8,
408 (int)pVnodeData->pHandle);
409
410 lck_rw_unlock_exclusive(pVnodeData->pLock);
411 return 0;
412 }
413
414 /* At this point we must make sure that nobody is using VBoxVFS object handle */
415 //if (pVnodeData->Handle != SHFL_HANDLE_NIL)
416 //{
417 // PDEBUG("vnode has active VBoxVFS object handle set, aborting");
418 // lck_rw_unlock_exclusive(pVnodeData->pLock);
419 // return EINVAL;
420 //}
421
422 fHostFlags = vboxvfs_g2h_mode_inernal(pArgs->a_mode);
423 fHostFlags |= (vnode_isdir(vnode) ? SHFL_CF_DIRECTORY : 0);
424
425 SHFLHANDLE Handle;
426 rc = vboxvfs_open_internal(pMount, pVnodeData->pPath, fHostFlags, &Handle);
427 if (rc == 0)
428 {
429 PDEBUG("Open success: '%s' (handle 0x%X)",
430 (char *)pVnodeData->pPath->String.utf8,
431 (int)Handle);
432
433 pVnodeData->pHandle = Handle;
434 }
435 else
436 {
437 PDEBUG("Unable to open: '%s': %d",
438 (char *)pVnodeData->pPath->String.utf8,
439 rc);
440 }
441
442 lck_rw_unlock_exclusive(pVnodeData->pLock);
443
444 return rc;
445#endif
446}
447
448static int vboxSfDwnVnClose(struct vnop_close_args *pArgs)
449{
450#if 1
451 RT_NOREF(pArgs);
452 return ENOTSUP;
453#else
454
455 vnode_t vnode;
456 mount_t mp;
457 vboxvfs_vnode_t *pVnodeData;
458 vboxvfs_mount_t *pMount;
459
460 int rc;
461
462 PDEBUG("Closing vnode...");
463
464 AssertReturn(pArgs, EINVAL);
465
466 vnode = pArgs->a_vp; AssertReturn(vnode, EINVAL);
467 pVnodeData = (vboxvfs_vnode_t *)vnode_fsnode(vnode); AssertReturn(pVnodeData, EINVAL);
468 mp = vnode_mount(vnode); AssertReturn(mp, EINVAL);
469 pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp); AssertReturn(pMount, EINVAL);
470
471 lck_rw_lock_exclusive(pVnodeData->pLock);
472
473 if (vnode_isinuse(vnode, 0))
474 {
475 PDEBUG("vnode '%s' (handle 0x%X) is still in use, just return ok",
476 (char *)pVnodeData->pPath->String.utf8,
477 (int)pVnodeData->pHandle);
478
479 lck_rw_unlock_exclusive(pVnodeData->pLock);
480 return 0;
481 }
482
483 /* At this point we must make sure that vnode has VBoxVFS object handle assigned */
484 if (pVnodeData->pHandle == SHFL_HANDLE_NIL)
485 {
486 PDEBUG("vnode has no active VBoxVFS object handle set, aborting");
487 lck_rw_unlock_exclusive(pVnodeData->pLock);
488 return EINVAL;
489 }
490
491 rc = vboxvfs_close_internal(pMount, pVnodeData->pHandle);
492 if (rc == 0)
493 {
494 PDEBUG("Close success: '%s' (handle 0x%X)",
495 (char *)pVnodeData->pPath->String.utf8,
496 (int)pVnodeData->pHandle);
497
498 /* Forget about previously assigned VBoxVFS object handle */
499 pVnodeData->pHandle = SHFL_HANDLE_NIL;
500 }
501 else
502 {
503 PDEBUG("Unable to close: '%s' (handle 0x%X): %d",
504 (char *)pVnodeData->pPath->String.utf8,
505 (int)pVnodeData->pHandle, rc);
506 }
507
508 lck_rw_unlock_exclusive(pVnodeData->pLock);
509
510 return rc;
511#endif
512}
513
514#if 0
515/**
516 * Convert SHFLDIRINFO to struct dirent and copy it back to user.
517 */
518static int
519vboxvfs_vnode_readdir_copy_data(ino_t index, SHFLDIRINFO *Info, struct uio *uio, int *numdirent)
520{
521 struct dirent entry;
522
523 int rc;
524
525 entry.d_ino = index;
526 entry.d_reclen = (__uint16_t)sizeof(entry);
527
528 /* Detect dir entry type */
529 if (RTFS_IS_DIRECTORY(Info->Info.Attr.fMode))
530 entry.d_type = DT_DIR;
531 else if (RTFS_IS_FILE(Info->Info.Attr.fMode))
532 entry.d_type = DT_REG;
533 else
534 {
535 PDEBUG("Unknown type of host file: mode 0x%X", (int)Info->Info.Attr.fMode);
536 return ENOTSUP;
537 }
538
539 entry.d_namlen = (__uint8_t)min(sizeof(entry.d_name), Info->name.u16Size);
540 memcpy(entry.d_name, Info->name.String.utf8, entry.d_namlen);
541
542 rc = uiomove((char *)&entry, sizeof(entry), uio);
543 if (rc == 0)
544 {
545 uio_setoffset(uio, index * sizeof(struct dirent));
546 *numdirent = (int)index;
547
548 PDEBUG("discovered entry: '%s' (%d bytes), item #%d", entry.d_name, (int)entry.d_namlen, (int)index);
549 }
550 else
551 {
552 PDEBUG("Failed to return dirent data item #%d (%d)", (int)index, rc);
553 }
554
555 return rc;
556}
557#endif
558
559static int vboxSfDwnVnReadDir(struct vnop_readdir_args *pArgs)
560{
561#if 1
562 RT_NOREF(pArgs);
563 return ENOTSUP;
564#else
565 vboxvfs_mount_t *pMount;
566 vboxvfs_vnode_t *pVnodeData;
567 SHFLDIRINFO *Info;
568 uint32_t cbInfo;
569 mount_t mp;
570 vnode_t vnode;
571 struct uio *uio;
572
573 int rc = 0, rc2;
574
575 PDEBUG("Reading directory...");
576
577 AssertReturn(pArgs, EINVAL);
578 AssertReturn(pArgs->a_eofflag, EINVAL);
579 AssertReturn(pArgs->a_numdirent, EINVAL);
580
581 uio = pArgs->a_uio; AssertReturn(uio, EINVAL);
582 vnode = pArgs->a_vp; AssertReturn(vnode, EINVAL); AssertReturn(vnode_isdir(vnode), EINVAL);
583 pVnodeData = (vboxvfs_vnode_t *)vnode_fsnode(vnode); AssertReturn(pVnodeData, EINVAL);
584 mp = vnode_mount(vnode); AssertReturn(mp, EINVAL);
585 pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp); AssertReturn(pMount, EINVAL);
586
587 lck_rw_lock_shared(pVnodeData->pLock);
588
589 cbInfo = sizeof(Info) + MAXPATHLEN;
590 Info = (SHFLDIRINFO *)RTMemAllocZ(cbInfo);
591 if (!Info)
592 {
593 PDEBUG("No memory to allocate internal data");
594 lck_rw_unlock_shared(pVnodeData->pLock);
595 return ENOMEM;
596 }
597
598 uint32_t index = (uint32_t)uio_offset(uio) / (uint32_t)sizeof(struct dirent);
599 uint32_t cFiles = 0;
600
601 PDEBUG("Exploring VBoxVFS directory (%s), handle (0x%.8X), offset (0x%X), count (%d)", (char *)pVnodeData->pPath->String.utf8, (int)pVnodeData->pHandle, index, uio_iovcnt(uio));
602
603 /* Currently, there is a problem when VbglR0SfDirInfo() is not able to
604 * continue retrieve directory content if the same VBoxVFS handle is used.
605 * This macro forces to use a new handle in readdir() callback. If enabled,
606 * the original handle (obtained in open() callback is ignored). */
607
608 SHFLHANDLE Handle;
609 rc = vboxvfs_open_internal(pMount,
610 pVnodeData->pPath,
611 SHFL_CF_DIRECTORY | SHFL_CF_ACCESS_READ | SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW,
612 &Handle);
613 if (rc != 0)
614 {
615 PDEBUG("Unable to open dir: %d", rc);
616 RTMemFree(Info);
617 lck_rw_unlock_shared(pVnodeData->pLock);
618 return rc;
619 }
620
621#if 0
622 rc = VbglR0SfDirInfo(&g_vboxSFClient, &pMount->pMap, Handle, 0, 0, index, &cbInfo, (PSHFLDIRINFO)Info, &cFiles);
623#else
624 SHFLSTRING *pMask = vboxvfs_construct_shflstring("*", strlen("*"));
625 if (pMask)
626 {
627 for (uint32_t cSkip = 0; (cSkip < index + 1) && (rc == VINF_SUCCESS); cSkip++)
628 {
629 //rc = VbglR0SfDirInfo(&g_vboxSFClient, &pMount->pMap, Handle, 0 /* pMask */, 0 /* SHFL_LIST_RETURN_ONE */, 0, &cbInfo, (PSHFLDIRINFO)Info, &cFiles);
630
631 uint32_t cbReturned = cbInfo;
632 //rc = VbglR0SfDirInfo(&g_vboxSFClient, &pMount->pMap, Handle, pMask, SHFL_LIST_RETURN_ONE, 0, &cbReturned, (PSHFLDIRINFO)Info, &cFiles);
633 rc = VbglR0SfDirInfo(&g_SfClientDarwin, &pMount->pMap, Handle, 0, SHFL_LIST_RETURN_ONE, 0,
634 &cbReturned, (PSHFLDIRINFO)Info, &cFiles);
635
636 }
637
638 PDEBUG("read %d files", cFiles);
639 RTMemFree(pMask);
640 }
641 else
642 {
643 PDEBUG("Can't alloc mask");
644 rc = ENOMEM;
645 }
646#endif
647 rc2 = vboxvfs_close_internal(pMount, Handle);
648 if (rc2 != 0)
649 {
650 PDEBUG("Unable to close directory: %s: %d",
651 pVnodeData->pPath->String.utf8,
652 rc2);
653 }
654
655 switch (rc)
656 {
657 case VINF_SUCCESS:
658 {
659 rc = vboxvfs_vnode_readdir_copy_data((ino_t)(index + 1), Info, uio, pArgs->a_numdirent);
660 break;
661 }
662
663 case VERR_NO_MORE_FILES:
664 {
665 PDEBUG("No more entries in directory");
666 *(pArgs->a_eofflag) = 1;
667 break;
668 }
669
670 default:
671 {
672 PDEBUG("VbglR0SfDirInfo() for item #%d has failed: %d", (int)index, (int)rc);
673 rc = EINVAL;
674 break;
675 }
676 }
677
678 RTMemFree(Info);
679 lck_rw_unlock_shared(pVnodeData->pLock);
680
681 return rc;
682#endif
683}
684
685
686static int vboxSfDwnVnPathConf(struct vnop_pathconf_args *pArgs)
687{
688 Log(("vboxSfDwnVnPathConf:\n"));
689 RT_NOREF(pArgs);
690 return 0;
691}
692
693
694/**
695 * vnop_reclaim implementation.
696 *
697 * VBoxVFS reclaim callback.
698 * Called when vnode is going to be deallocated. Should release
699 * all the VBoxVFS resources that correspond to current vnode object.
700 *
701 * @param pArgs Operation arguments passed from VFS layer.
702 *
703 * @return 0 on success, BSD error code otherwise.
704 */
705static int vboxSfDwnVnReclaim(struct vnop_reclaim_args *pArgs)
706{
707 AssertReturn(pArgs && pArgs->a_vp, EINVAL);
708
709 /* Check that it's not a root node that's in use. */
710 PVBOXSFMNTDATA pMntData = (PVBOXSFMNTDATA)vfs_fsprivate(vnode_mount(pArgs->a_vp));
711 AssertReturn(!pMntData || pMntData->pVnRoot != pArgs->a_vp, EBUSY);
712
713 /* Get the private data and free it. */
714 PVBOXSFDWNVNDATA pVnData = (PVBOXSFDWNVNDATA)vnode_fsnode(pArgs->a_vp);
715 AssertPtrReturn(pVnData, 0);
716
717 if (pVnData->hHandle != SHFL_HANDLE_NIL)
718 {
719 /** @todo can this happen? */
720 pVnData->hHandle = SHFL_HANDLE_NIL;
721 }
722
723 RTMemFree(pVnData);
724 return 0;
725}
726
727
728/**
729 * Allocates a vnode.
730 *
731 * @returns Pointer to the new VNode, NULL if out of memory.
732 * @param pMount The file system mount structure.
733 * @param enmType The vnode type.
734 * @param pParent The parent vnode, NULL if root.
735 * @param cbFile The file size
736 */
737vnode_t vboxSfDwnVnAlloc(mount_t pMount, enum vtype enmType, vnode_t pParent, uint64_t cbFile)
738{
739 /*
740 * Create our private data.
741 */
742 PVBOXSFDWNVNDATA pVnData = (PVBOXSFDWNVNDATA)RTMemAllocZ(sizeof(*pVnData));
743 if (pVnData)
744 {
745 pVnData->hHandle = SHFL_HANDLE_NIL;
746
747 struct vnode_fsparam VnParms;
748 RT_ZERO(VnParms);
749 VnParms.vnfs_mp = pMount;
750 VnParms.vnfs_vtype = enmType;
751 VnParms.vnfs_str = "vboxsf";
752 VnParms.vnfs_dvp = pParent;
753 VnParms.vnfs_fsnode = pVnData;
754 VnParms.vnfs_vops = g_papfnVBoxSfDwnVnDirOpsVector;
755 VnParms.vnfs_markroot = pParent == NULL;
756 VnParms.vnfs_marksystem = 0;
757 VnParms.vnfs_rdev = 0;
758 VnParms.vnfs_filesize = cbFile;
759 VnParms.vnfs_cnp = 0;
760 VnParms.vnfs_flags = VNFS_NOCACHE;
761
762 vnode_t pVnRet;
763 int rc = vnode_create(VNCREATE_FLAVOR, VCREATESIZE, &VnParms, &pVnRet);
764 if (rc == 0)
765 return pVnRet;
766 RTMemFree(pVnData);
767 }
768 printf("vboxSfDwnVnAlloc: out of memory!\n");
769 return NULL;
770}
771
772
773/**
774 * Vnode operations.
775 */
776static struct vnodeopv_entry_desc g_VBoxSfDirOpsDescList[] =
777{
778#define VNODEOPFUNC int(*)(void *)
779 { &vnop_default_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
780 //{ &vnop_access_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, - probably not needed.
781 //{ &vnop_advlock_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, - later.
782 //{ &vnop_allocate_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, - maybe, need shfl function
783 { &vnop_blktooff_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
784 //{ &vnop_blockmap_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
785 //{ &vnop_bwrite_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
786 { &vnop_close_desc, (VNODEOPFUNC)vboxSfDwnVnClose },
787 //{ &vnop_copyfile_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
788 { &vnop_create_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
789 //{ &vnop_exchange_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
790 { &vnop_fsync_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
791 { &vnop_getattr_desc, (VNODEOPFUNC)vboxFsDwnVnGetAttr },
792 //{ &vnop_getnamedstream_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
793 //{ &vnop_getxattr_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
794 { &vnop_inactive_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
795 { &vnop_ioctl_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
796 { &vnop_link_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
797 //{ &vnop_listxattr_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
798 { &vnop_lookup_desc, (VNODEOPFUNC)vboxSfDwnVnLookup },
799 { &vnop_mkdir_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
800 { &vnop_mknod_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
801 { &vnop_mmap_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
802 { &vnop_mnomap_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
803 { &vnop_offtoblk_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
804 { &vnop_open_desc, (VNODEOPFUNC)vboxSfDwnVnOpen },
805 { &vnop_pagein_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
806 { &vnop_pageout_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
807 { &vnop_pathconf_desc, (VNODEOPFUNC)vboxSfDwnVnPathConf },
808 /* { &vnop_print_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, undefined in ML */
809 { &vnop_read_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
810 { &vnop_readdir_desc, (VNODEOPFUNC)vboxSfDwnVnReadDir },
811 //{ &vnop_readdirattr_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, - hfs specific.
812 { &vnop_readlink_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
813 { &vnop_reclaim_desc, (VNODEOPFUNC)vboxSfDwnVnReclaim },
814 { &vnop_remove_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
815 //{ &vnop_removexattr_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
816 { &vnop_rename_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
817 //{ &vnop_revoke_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, - not needed
818 { &vnop_rmdir_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
819 { &vnop_searchfs_desc, (VNODEOPFUNC)err_searchfs },
820 //{ &vnop_select_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, - not needed
821 { &vnop_setattr_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
822 { &vnop_setxattr_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
823 //{ &vnop_strategy_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, - not needed
824 { &vnop_symlink_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
825 /* { &vnop_truncate_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, undefined in ML */
826 //{ &vnop_whiteout_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError }, - not needed/supported
827 { &vnop_write_desc, (VNODEOPFUNC)vboxSfDwnVnDefaultError },
828 { NULL, (VNODEOPFUNC)NULL },
829#undef VNODEOPFUNC
830};
831
832/** ??? */
833int (**g_papfnVBoxSfDwnVnDirOpsVector)(void *);
834
835/**
836 * VNode operation descriptors.
837 */
838struct vnodeopv_desc g_VBoxSfVnodeOpvDesc =
839{
840 &g_papfnVBoxSfDwnVnDirOpsVector,
841 g_VBoxSfDirOpsDescList
842};
843
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