int sf_get_volume_info(struct super_block *sb, STRUCT_STATFS *stat) { struct sf_glob_info *sf_g; SHFLVOLINFO SHFLVolumeInfo; uint32_t cbBuffer; int rc; sf_g = GET_GLOB_INFO(sb); cbBuffer = sizeof(SHFLVolumeInfo); rc = VbglR0SfFsInfo(&client_handle, &sf_g->map, 0, SHFL_INFO_GET | SHFL_INFO_VOLUME, &cbBuffer, (PSHFLDIRINFO)&SHFLVolumeInfo); if (RT_FAILURE(rc)) return -RTErrConvertToErrno(rc); stat->f_type = NFS_SUPER_MAGIC; /* XXX vboxsf type? */ stat->f_bsize = SHFLVolumeInfo.ulBytesPerAllocationUnit; stat->f_blocks = SHFLVolumeInfo.ullTotalAllocationBytes / SHFLVolumeInfo.ulBytesPerAllocationUnit; stat->f_bfree = SHFLVolumeInfo.ullAvailableAllocationBytes / SHFLVolumeInfo.ulBytesPerAllocationUnit; stat->f_bavail = SHFLVolumeInfo.ullAvailableAllocationBytes / SHFLVolumeInfo.ulBytesPerAllocationUnit; stat->f_files = 1000; stat->f_ffree = 1000; /* don't return 0 here since the guest may think * that it is not possible to create any more files */ stat->f_fsid.val[0] = 0; stat->f_fsid.val[1] = 0; stat->f_namelen = 255; return 0; }
int sf_setattr(struct dentry *dentry, struct iattr *iattr) { struct sf_glob_info *sf_g; struct sf_inode_info *sf_i; SHFLCREATEPARMS params; SHFLFSOBJINFO info; uint32_t cbBuffer; int rc, err; TRACE(); sf_g = GET_GLOB_INFO(dentry->d_inode->i_sb); sf_i = GET_INODE_INFO(dentry->d_inode); err = 0; RT_ZERO(params); params.Handle = SHFL_HANDLE_NIL; params.CreateFlags = SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW | SHFL_CF_ACCESS_ATTR_WRITE; /* this is at least required for Posix hosts */ if (iattr->ia_valid & ATTR_SIZE) params.CreateFlags |= SHFL_CF_ACCESS_WRITE; rc = VbglR0SfCreate(&client_handle, &sf_g->map, sf_i->path, ¶ms); if (RT_FAILURE(rc)) { LogFunc(("VbglR0SfCreate(%s) failed rc=%Rrc\n", sf_i->path->String.utf8, rc)); err = -RTErrConvertToErrno(rc); goto fail2; } if (params.Result != SHFL_FILE_EXISTS) { LogFunc(("file %s does not exist\n", sf_i->path->String.utf8)); err = -ENOENT; goto fail1; } /* Setting the file size and setting the other attributes has to be * handled separately, see implementation of vbsfSetFSInfo() in * vbsf.cpp */ if (iattr->ia_valid & (ATTR_MODE | ATTR_ATIME | ATTR_MTIME)) { #define mode_set(r) ((iattr->ia_mode & (S_##r)) ? RTFS_UNIX_##r : 0) RT_ZERO(info); if (iattr->ia_valid & ATTR_MODE) { info.Attr.fMode = mode_set(ISUID); info.Attr.fMode |= mode_set(ISGID); info.Attr.fMode |= mode_set(IRUSR); info.Attr.fMode |= mode_set(IWUSR); info.Attr.fMode |= mode_set(IXUSR); info.Attr.fMode |= mode_set(IRGRP); info.Attr.fMode |= mode_set(IWGRP); info.Attr.fMode |= mode_set(IXGRP); info.Attr.fMode |= mode_set(IROTH); info.Attr.fMode |= mode_set(IWOTH); info.Attr.fMode |= mode_set(IXOTH); if (iattr->ia_mode & S_IFDIR) info.Attr.fMode |= RTFS_TYPE_DIRECTORY; else info.Attr.fMode |= RTFS_TYPE_FILE; } if (iattr->ia_valid & ATTR_ATIME) sf_timespec_from_ftime(&info.AccessTime, &iattr->ia_atime); if (iattr->ia_valid & ATTR_MTIME) sf_timespec_from_ftime(&info.ModificationTime, &iattr->ia_mtime); /* ignore ctime (inode change time) as it can't be set from userland anyway */ cbBuffer = sizeof(info); rc = VbglR0SfFsInfo(&client_handle, &sf_g->map, params.Handle, SHFL_INFO_SET | SHFL_INFO_FILE, &cbBuffer, (PSHFLDIRINFO)&info); if (RT_FAILURE(rc)) { LogFunc(("VbglR0SfFsInfo(%s, FILE) failed rc=%Rrc\n", sf_i->path->String.utf8, rc)); err = -RTErrConvertToErrno(rc); goto fail1; } } if (iattr->ia_valid & ATTR_SIZE) { RT_ZERO(info); info.cbObject = iattr->ia_size; cbBuffer = sizeof(info); rc = VbglR0SfFsInfo(&client_handle, &sf_g->map, params.Handle, SHFL_INFO_SET | SHFL_INFO_SIZE, &cbBuffer, (PSHFLDIRINFO)&info); if (RT_FAILURE(rc)) { LogFunc(("VbglR0SfFsInfo(%s, SIZE) failed rc=%Rrc\n", sf_i->path->String.utf8, rc)); err = -RTErrConvertToErrno(rc); goto fail1; } } rc = VbglR0SfClose(&client_handle, &sf_g->map, params.Handle); if (RT_FAILURE(rc)) LogFunc(("VbglR0SfClose(%s) failed rc=%Rrc\n", sf_i->path->String.utf8, rc)); return sf_inode_revalidate(dentry); fail1: rc = VbglR0SfClose(&client_handle, &sf_g->map, params.Handle); if (RT_FAILURE(rc)) LogFunc(("VbglR0SfClose(%s) failed rc=%Rrc\n", sf_i->path->String.utf8, rc)); fail2: return err; }
/** * VBoxVFS get VFS layer object attribute callback. * * @param mp Mount data provided by VFS layer. * @param pAttr Output buffer to return attributes. * @param pContext kAuth context needed in order to authentificate mount operation. * * @returns 0 for success, else an error code. */ static int vboxvfs_getattr(struct mount *mp, struct vfs_attr *pAttr, vfs_context_t pContext) { NOREF(pContext); vboxvfs_mount_t *pMount; SHFLVOLINFO SHFLVolumeInfo; int rc; uint32_t cbBuffer = sizeof(SHFLVolumeInfo); uint32_t u32bsize; uint64_t u64blocks; uint64_t u64bfree; PDEBUG("Getting attribute...\n"); AssertReturn(mp, EINVAL); pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp); AssertReturn(pMount, EINVAL); AssertReturn(pMount->pShareName, EINVAL); rc = VbglR0SfFsInfo(&g_vboxSFClient, &pMount->pMap, 0, SHFL_INFO_GET | SHFL_INFO_VOLUME, &cbBuffer, (PSHFLDIRINFO)&SHFLVolumeInfo); AssertReturn(rc == 0, EPROTO); u32bsize = (uint32_t)SHFLVolumeInfo.ulBytesPerAllocationUnit; AssertReturn(u32bsize > 0, ENOTSUP); u64blocks = (uint64_t)SHFLVolumeInfo.ullTotalAllocationBytes / (uint64_t)u32bsize; u64bfree = (uint64_t)SHFLVolumeInfo.ullAvailableAllocationBytes / (uint64_t)u32bsize; VFSATTR_RETURN(pAttr, f_bsize, u32bsize); VFSATTR_RETURN(pAttr, f_blocks, u64blocks); VFSATTR_RETURN(pAttr, f_bfree, u64bfree); VFSATTR_RETURN(pAttr, f_bavail, u64bfree); VFSATTR_RETURN(pAttr, f_bused, u64blocks - u64bfree); VFSATTR_RETURN(pAttr, f_owner, pMount->owner); VFSATTR_CLEAR_ACTIVE(pAttr, f_iosize); VFSATTR_CLEAR_ACTIVE(pAttr, f_files); VFSATTR_CLEAR_ACTIVE(pAttr, f_ffree); VFSATTR_CLEAR_ACTIVE(pAttr, f_fssubtype); /* todo: take care about f_capabilities and f_attributes, f_fsid */ VFSATTR_CLEAR_ACTIVE(pAttr, f_capabilities); VFSATTR_CLEAR_ACTIVE(pAttr, f_attributes); VFSATTR_CLEAR_ACTIVE(pAttr, f_fsid); /* todo: take care about f_create_time, f_modify_time, f_access_time, f_backup_time */ VFSATTR_CLEAR_ACTIVE(pAttr, f_create_time); VFSATTR_CLEAR_ACTIVE(pAttr, f_modify_time); VFSATTR_CLEAR_ACTIVE(pAttr, f_access_time); VFSATTR_CLEAR_ACTIVE(pAttr, f_backup_time); VFSATTR_CLEAR_ACTIVE(pAttr, f_signature); VFSATTR_CLEAR_ACTIVE(pAttr, f_carbon_fsid); VFSATTR_CLEAR_ACTIVE(pAttr, f_uuid); if (VFSATTR_IS_ACTIVE(pAttr, f_vol_name)) { strlcpy(pAttr->f_vol_name, (char*)pMount->pShareName->String.utf8, MAXPATHLEN); VFSATTR_SET_SUPPORTED(pAttr, f_vol_name); } VFSATTR_ALL_SUPPORTED(pAttr); return 0; }