/** * Check if VFS object exists on a host side. * * @param vnode Guest VFS vnode that corresponds to host VFS object * * @return 1 if exists, 0 otherwise. */ int vboxvfs_exist_internal(vnode_t vnode) { int rc; PSHFLSTRING pSFPath = NULL; SHFLHANDLE handle; uint32_t fFlags; vboxvfs_mount_t *pMount; mount_t mp; /* Return FALSE if invalid parameter given */ AssertReturn(vnode, 0); mp = vnode_mount(vnode); AssertReturn(mp, EINVAL); pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp); AssertReturn(pMount, EINVAL); fFlags = (vnode_isdir(vnode)) ? SHFL_CF_DIRECTORY : 0; fFlags |= SHFL_CF_ACCESS_READ | SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW; rc = vboxvfs_guest_vnode_to_shflstring_path_internal(vnode, &pSFPath); AssertReturn(rc == 0, rc); if (rc == 0) { rc = vboxvfs_open_internal(pMount, pSFPath, fFlags, &handle); if (rc == 0) { rc = vboxvfs_close_internal(pMount, handle); if (rc != 0) { PDEBUG("Unable to close() VBoxVFS object handle while checking if object exist on host: %d", rc); } } } vboxvfs_put_path_internal((void **)&pSFPath); return (rc == 0); }
static int vboxvfs_vnode_readdir(struct vnop_readdir_args *args) { vboxvfs_mount_t *pMount; vboxvfs_vnode_t *pVnodeData; SHFLDIRINFO *Info; uint32_t cbInfo; mount_t mp; vnode_t vnode; struct uio *uio; int rc = 0, rc2; PDEBUG("Reading directory..."); AssertReturn(args, EINVAL); AssertReturn(args->a_eofflag, EINVAL); AssertReturn(args->a_numdirent, EINVAL); uio = args->a_uio; AssertReturn(uio, EINVAL); vnode = args->a_vp; AssertReturn(vnode, EINVAL); AssertReturn(vnode_isdir(vnode), EINVAL); pVnodeData = (vboxvfs_vnode_t *)vnode_fsnode(vnode); AssertReturn(pVnodeData, EINVAL); mp = vnode_mount(vnode); AssertReturn(mp, EINVAL); pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp); AssertReturn(pMount, EINVAL); lck_rw_lock_shared(pVnodeData->pLock); cbInfo = sizeof(Info) + MAXPATHLEN; Info = (SHFLDIRINFO *)RTMemAllocZ(cbInfo); if (!Info) { PDEBUG("No memory to allocate internal data"); lck_rw_unlock_shared(pVnodeData->pLock); return ENOMEM; } uint32_t index = (uint32_t)uio_offset(uio) / (uint32_t)sizeof(struct dirent); uint32_t cFiles = 0; 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)); /* Currently, there is a problem when VbglR0SfDirInfo() is not able to * continue retrieve directory content if the same VBoxVFS handle is used. * This macro forces to use a new handle in readdir() callback. If enabled, * the original handle (obtained in open() callback is ignored). */ SHFLHANDLE Handle; rc = vboxvfs_open_internal(pMount, pVnodeData->pPath, SHFL_CF_DIRECTORY | SHFL_CF_ACCESS_READ | SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW, &Handle); if (rc != 0) { PDEBUG("Unable to open dir: %d", rc); RTMemFree(Info); lck_rw_unlock_shared(pVnodeData->pLock); return rc; } #if 0 rc = VbglR0SfDirInfo(&g_vboxSFClient, &pMount->pMap, Handle, 0, 0, index, &cbInfo, (PSHFLDIRINFO)Info, &cFiles); #else SHFLSTRING *pMask = vboxvfs_construct_shflstring("*", strlen("*")); if (pMask) { for (uint32_t cSkip = 0; (cSkip < index + 1) && (rc == VINF_SUCCESS); cSkip++) { //rc = VbglR0SfDirInfo(&g_vboxSFClient, &pMount->pMap, Handle, 0 /* pMask */, 0 /* SHFL_LIST_RETURN_ONE */, 0, &cbInfo, (PSHFLDIRINFO)Info, &cFiles); uint32_t cbReturned = cbInfo; //rc = VbglR0SfDirInfo(&g_vboxSFClient, &pMount->pMap, Handle, pMask, SHFL_LIST_RETURN_ONE, 0, &cbReturned, (PSHFLDIRINFO)Info, &cFiles); rc = VbglR0SfDirInfo(&g_vboxSFClient, &pMount->pMap, Handle, 0, SHFL_LIST_RETURN_ONE, 0, &cbReturned, (PSHFLDIRINFO)Info, &cFiles); } PDEBUG("read %d files", cFiles); RTMemFree(pMask); } else { PDEBUG("Can't alloc mask"); rc = ENOMEM; } #endif rc2 = vboxvfs_close_internal(pMount, Handle); if (rc2 != 0) { PDEBUG("Unable to close directory: %s: %d", pVnodeData->pPath->String.utf8, rc2); } switch (rc) { case VINF_SUCCESS: { rc = vboxvfs_vnode_readdir_copy_data((ino_t)(index + 1), Info, uio, args->a_numdirent); break; } case VERR_NO_MORE_FILES: { PDEBUG("No more entries in directory"); *(args->a_eofflag) = 1; break; } default: { PDEBUG("VbglR0SfDirInfo() for item #%d has failed: %d", (int)index, (int)rc); rc = EINVAL; break; } } RTMemFree(Info); lck_rw_unlock_shared(pVnodeData->pLock); return rc; }
static int vboxvfs_vnode_open(struct vnop_open_args *args) { vnode_t vnode; vboxvfs_vnode_t *pVnodeData; uint32_t fHostFlags; mount_t mp; vboxvfs_mount_t *pMount; int rc; PDEBUG("Opening vnode..."); AssertReturn(args, EINVAL); vnode = args->a_vp; AssertReturn(vnode, EINVAL); pVnodeData = (vboxvfs_vnode_t *)vnode_fsnode(vnode); AssertReturn(pVnodeData, EINVAL); mp = vnode_mount(vnode); AssertReturn(mp, EINVAL); pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp); AssertReturn(pMount, EINVAL); lck_rw_lock_exclusive(pVnodeData->pLock); if (vnode_isinuse(vnode, 0)) { PDEBUG("vnode '%s' (handle 0x%X) already has VBoxVFS object handle assigned, just return ok", (char *)pVnodeData->pPath->String.utf8, (int)pVnodeData->pHandle); lck_rw_unlock_exclusive(pVnodeData->pLock); return 0; } /* At this point we must make sure that nobody is using VBoxVFS object handle */ //if (pVnodeData->Handle != SHFL_HANDLE_NIL) //{ // PDEBUG("vnode has active VBoxVFS object handle set, aborting"); // lck_rw_unlock_exclusive(pVnodeData->pLock); // return EINVAL; //} fHostFlags = vboxvfs_g2h_mode_inernal(args->a_mode); fHostFlags |= (vnode_isdir(vnode) ? SHFL_CF_DIRECTORY : 0); SHFLHANDLE Handle; rc = vboxvfs_open_internal(pMount, pVnodeData->pPath, fHostFlags, &Handle); if (rc == 0) { PDEBUG("Open success: '%s' (handle 0x%X)", (char *)pVnodeData->pPath->String.utf8, (int)Handle); pVnodeData->pHandle = Handle; } else { PDEBUG("Unable to open: '%s': %d", (char *)pVnodeData->pPath->String.utf8, rc); } lck_rw_unlock_exclusive(pVnodeData->pLock); return rc; }