VirtualBox

source: vbox/trunk/src/VBox/Additions/darwin/vboxfs/VBoxVFS-VNODEOps.cpp@ 68643

Last change on this file since 68643 was 63566, checked in by vboxsync, 8 years ago

scm: cleaning up todos

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