VirtualBox

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

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

add/darwin/VBoxSF: More renaming, header separation and cleaning up.

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