VirtualBox

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

Last change on this file since 75666 was 75666, checked in by vboxsync, 7 years ago

darwin/VBoxSF: updates

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