diff options
Diffstat (limited to 'fs/9p/vfs_inode.c')
| -rw-r--r-- | fs/9p/vfs_inode.c | 60 |
1 files changed, 57 insertions, 3 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 68f02973c338..88419073c654 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
| @@ -1527,7 +1527,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) | |||
| 1527 | if (IS_ERR(fid)) | 1527 | if (IS_ERR(fid)) |
| 1528 | return PTR_ERR(fid); | 1528 | return PTR_ERR(fid); |
| 1529 | 1529 | ||
| 1530 | if (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)) | 1530 | if (!v9fs_proto_dotu(v9ses)) |
| 1531 | return -EBADF; | 1531 | return -EBADF; |
| 1532 | 1532 | ||
| 1533 | st = p9_client_stat(fid); | 1533 | st = p9_client_stat(fid); |
| @@ -1995,6 +1995,60 @@ error: | |||
| 1995 | return err; | 1995 | return err; |
| 1996 | } | 1996 | } |
| 1997 | 1997 | ||
| 1998 | static int | ||
| 1999 | v9fs_vfs_readlink_dotl(struct dentry *dentry, char *buffer, int buflen) | ||
| 2000 | { | ||
| 2001 | int retval; | ||
| 2002 | struct p9_fid *fid; | ||
| 2003 | char *target = NULL; | ||
| 2004 | |||
| 2005 | P9_DPRINTK(P9_DEBUG_VFS, " %s\n", dentry->d_name.name); | ||
| 2006 | retval = -EPERM; | ||
| 2007 | fid = v9fs_fid_lookup(dentry); | ||
| 2008 | if (IS_ERR(fid)) | ||
| 2009 | return PTR_ERR(fid); | ||
| 2010 | |||
| 2011 | retval = p9_client_readlink(fid, &target); | ||
| 2012 | if (retval < 0) | ||
| 2013 | return retval; | ||
| 2014 | |||
| 2015 | strncpy(buffer, target, buflen); | ||
| 2016 | P9_DPRINTK(P9_DEBUG_VFS, "%s -> %s\n", dentry->d_name.name, buffer); | ||
| 2017 | |||
| 2018 | retval = strnlen(buffer, buflen); | ||
| 2019 | return retval; | ||
| 2020 | } | ||
| 2021 | |||
| 2022 | /** | ||
| 2023 | * v9fs_vfs_follow_link_dotl - follow a symlink path | ||
| 2024 | * @dentry: dentry for symlink | ||
| 2025 | * @nd: nameidata | ||
| 2026 | * | ||
| 2027 | */ | ||
| 2028 | |||
| 2029 | static void * | ||
| 2030 | v9fs_vfs_follow_link_dotl(struct dentry *dentry, struct nameidata *nd) | ||
| 2031 | { | ||
| 2032 | int len = 0; | ||
| 2033 | char *link = __getname(); | ||
| 2034 | |||
| 2035 | P9_DPRINTK(P9_DEBUG_VFS, "%s n", dentry->d_name.name); | ||
| 2036 | |||
| 2037 | if (!link) | ||
| 2038 | link = ERR_PTR(-ENOMEM); | ||
| 2039 | else { | ||
| 2040 | len = v9fs_vfs_readlink_dotl(dentry, link, PATH_MAX); | ||
| 2041 | if (len < 0) { | ||
| 2042 | __putname(link); | ||
| 2043 | link = ERR_PTR(len); | ||
| 2044 | } else | ||
| 2045 | link[min(len, PATH_MAX-1)] = 0; | ||
| 2046 | } | ||
| 2047 | nd_set_link(nd, link); | ||
| 2048 | |||
| 2049 | return NULL; | ||
| 2050 | } | ||
| 2051 | |||
| 1998 | static const struct inode_operations v9fs_dir_inode_operations_dotu = { | 2052 | static const struct inode_operations v9fs_dir_inode_operations_dotu = { |
| 1999 | .create = v9fs_vfs_create, | 2053 | .create = v9fs_vfs_create, |
| 2000 | .lookup = v9fs_vfs_lookup, | 2054 | .lookup = v9fs_vfs_lookup, |
| @@ -2064,8 +2118,8 @@ static const struct inode_operations v9fs_symlink_inode_operations = { | |||
| 2064 | }; | 2118 | }; |
| 2065 | 2119 | ||
| 2066 | static const struct inode_operations v9fs_symlink_inode_operations_dotl = { | 2120 | static const struct inode_operations v9fs_symlink_inode_operations_dotl = { |
| 2067 | .readlink = generic_readlink, | 2121 | .readlink = v9fs_vfs_readlink_dotl, |
| 2068 | .follow_link = v9fs_vfs_follow_link, | 2122 | .follow_link = v9fs_vfs_follow_link_dotl, |
| 2069 | .put_link = v9fs_vfs_put_link, | 2123 | .put_link = v9fs_vfs_put_link, |
| 2070 | .getattr = v9fs_vfs_getattr_dotl, | 2124 | .getattr = v9fs_vfs_getattr_dotl, |
| 2071 | .setattr = v9fs_vfs_setattr_dotl, | 2125 | .setattr = v9fs_vfs_setattr_dotl, |
