static int HgfsFollowlink(struct dentry *dentry, // IN: Dentry containing link struct nameidata *nd) // OUT: Contains target dentry #endif { HgfsAttrInfo attr; char *fileName = NULL; int error; ASSERT(dentry); #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) ASSERT(nd); #endif if (!dentry) { LOG(4, (KERN_DEBUG "VMware hgfs: HgfsFollowlink: null input\n")); error = -EINVAL; goto out; } LOG(6, (KERN_DEBUG "VMware hgfs: %s: calling HgfsPrivateGetattr %s\n", __func__, dentry->d_name.name)); error = HgfsPrivateGetattr(dentry, &attr, &fileName); LOG(6, (KERN_DEBUG "VMware hgfs: %s: HgfsPrivateGetattr %s ret %d\n", __func__, dentry->d_name.name, error)); if (!error) { /* Let's make sure we got called on a symlink. */ if (attr.type != HGFS_FILE_TYPE_SYMLINK || fileName == NULL) { LOG(6, (KERN_DEBUG "VMware hgfs: HgfsFollowlink: got called " "on something that wasn't a symlink\n")); error = -EINVAL; kfree(fileName); } else { LOG(6, (KERN_DEBUG "VMware hgfs: %s: calling nd_set_link %s\n", __func__, fileName)); #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) *cookie = fileName; #else nd_set_link(nd, fileName); #endif } } out: #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) if (!error) { return *cookie; } else { return ERR_PTR(error); } #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13) return ERR_PTR(error); #else return error; #endif }
static int HgfsFollowlink(struct dentry *dentry, // IN: Dentry containing link struct nameidata *nd) // OUT: Contains target dentry #endif { HgfsAttrInfo attr; char *fileName = NULL; int error; ASSERT(dentry); ASSERT(nd); if (!dentry) { LOG(4, (KERN_DEBUG "VMware hgfs: HgfsFollowlink: null input\n")); error = -EINVAL; goto out; } LOG(6, (KERN_DEBUG "VMware hgfs: HgfsFollowlink: calling " "HgfsPrivateGetattr\n")); error = HgfsPrivateGetattr(dentry, &attr, &fileName); if (!error) { /* Let's make sure we got called on a symlink. */ if (attr.type != HGFS_FILE_TYPE_SYMLINK || fileName == NULL) { LOG(6, (KERN_DEBUG "VMware hgfs: HgfsFollowlink: got called " "on something that wasn't a symlink\n")); error = -EINVAL; } else { LOG(6, (KERN_DEBUG "VMware hgfs: HgfsFollowlink: calling " "vfs_follow_link\n")); error = vfs_follow_link(nd, fileName); } kfree(fileName); } out: #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13) return ERR_PTR(error); #else return error; #endif }
static int HgfsReadlink(struct dentry *dentry, // IN: Dentry containing link char __user *buffer, // OUT: User buffer to copy link into int buflen) // IN: Length of user buffer { HgfsAttrInfo attr; char *fileName = NULL; int error; ASSERT(dentry); ASSERT(buffer); if (!dentry) { LOG(4, (KERN_DEBUG "VMware hgfs: HgfsReadlink: null input\n")); return -EINVAL; } LOG(6, (KERN_DEBUG "VMware hgfs: %s: calling HgfsPrivateGetattr %s\n", __func__, dentry->d_name.name)); error = HgfsPrivateGetattr(dentry, &attr, &fileName); if (!error) { /* Let's make sure we got called on a symlink. */ if (attr.type != HGFS_FILE_TYPE_SYMLINK || fileName == NULL) { LOG(6, (KERN_DEBUG "VMware hgfs: HgfsReadlink: got called " "on something that wasn't a symlink\n")); error = -EINVAL; } else { LOG(6, (KERN_DEBUG "VMware hgfs: %s: calling vfs_readlink %s\n", __func__, fileName)); error = HGFS_DO_READLINK(dentry, buffer, buflen, fileName); LOG(6, (KERN_DEBUG "VMware hgfs: %s: vfs_readlink %s ret %dn", __func__, fileName, error)); } kfree(fileName); } return error; }
static int HgfsGetRootDentry(struct super_block *sb, // IN: Super block object struct dentry **rootDentry) // OUT: Root dentry { int result = -ENOMEM; struct inode *rootInode; struct dentry *tempRootDentry = NULL; struct HgfsAttrInfo rootDentryAttr; HgfsInodeInfo *iinfo; ASSERT(sb); ASSERT(rootDentry); LOG(6, (KERN_DEBUG "VMware hgfs: %s: entered\n", __func__)); rootInode = HgfsGetInode(sb, HGFS_ROOT_INO); if (rootInode == NULL) { LOG(6, (KERN_DEBUG "VMware hgfs: %s: Could not get the root inode\n", __func__)); goto exit; } /* * On an allocation failure in read_super, the inode will have been * marked "bad". If it was, we certainly don't want to start playing with * the HgfsInodeInfo. So quietly put the inode back and fail. */ if (is_bad_inode(rootInode)) { LOG(6, (KERN_DEBUG "VMware hgfs: %s: encountered bad inode\n", __func__)); goto exit; } tempRootDentry = d_alloc_root(rootInode); if (tempRootDentry == NULL) { LOG(4, (KERN_WARNING "VMware hgfs: %s: Could not get " "root dentry\n", __func__)); goto exit; } rootInode = NULL; result = HgfsPrivateGetattr(tempRootDentry, &rootDentryAttr, NULL); if (result) { LOG(4, (KERN_WARNING "VMware hgfs: HgfsReadSuper: Could not" "instantiate the root dentry\n")); goto exit; } iinfo = INODE_GET_II_P(tempRootDentry->d_inode); iinfo->isFakeInodeNumber = FALSE; iinfo->isReferencedInode = TRUE; if (rootDentryAttr.mask & HGFS_ATTR_VALID_FILEID) { iinfo->hostFileId = rootDentryAttr.hostFileId; } HgfsChangeFileAttributes(tempRootDentry->d_inode, &rootDentryAttr); HgfsDentryAgeReset(tempRootDentry); tempRootDentry->d_op = &HgfsDentryOperations; *rootDentry = tempRootDentry; result = 0; LOG(6, (KERN_DEBUG "VMware hgfs: %s: finished\n", __func__)); exit: if (result) { iput(rootInode); dput(tempRootDentry); *rootDentry = NULL; } return result; }