Commit d60874cd authored by Miklos Szeredi's avatar Miklos Szeredi

vfs: add vfs_get_link() helper

This helper is for filesystems that want to read the symlink and are better
off with the get_link() interface (returning a char *) rather than the
readlink() interface (copy into a userspace buffer).

Also call the LSM hook for readlink (not get_link) since this is for
symlink reading not following.
Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
parent 78a3fa4f
...@@ -4677,6 +4677,31 @@ int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen) ...@@ -4677,6 +4677,31 @@ int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen)
} }
EXPORT_SYMBOL(generic_readlink); EXPORT_SYMBOL(generic_readlink);
/**
* vfs_get_link - get symlink body
* @dentry: dentry on which to get symbolic link
* @done: caller needs to free returned data with this
*
* Calls security hook and i_op->get_link() on the supplied inode.
*
* It does not touch atime. That's up to the caller if necessary.
*
* Does not work on "special" symlinks like /proc/$$/fd/N
*/
const char *vfs_get_link(struct dentry *dentry, struct delayed_call *done)
{
const char *res = ERR_PTR(-EINVAL);
struct inode *inode = d_inode(dentry);
if (d_is_symlink(dentry)) {
res = ERR_PTR(security_inode_readlink(dentry));
if (!res)
res = inode->i_op->get_link(dentry, inode, done);
}
return res;
}
EXPORT_SYMBOL(vfs_get_link);
/* get the link contents into pagecache */ /* get the link contents into pagecache */
const char *page_get_link(struct dentry *dentry, struct inode *inode, const char *page_get_link(struct dentry *dentry, struct inode *inode,
struct delayed_call *callback) struct delayed_call *callback)
......
...@@ -2919,6 +2919,7 @@ extern int vfs_stat(const char __user *, struct kstat *); ...@@ -2919,6 +2919,7 @@ extern int vfs_stat(const char __user *, struct kstat *);
extern int vfs_lstat(const char __user *, struct kstat *); extern int vfs_lstat(const char __user *, struct kstat *);
extern int vfs_fstat(unsigned int, struct kstat *); extern int vfs_fstat(unsigned int, struct kstat *);
extern int vfs_fstatat(int , const char __user *, struct kstat *, int); extern int vfs_fstatat(int , const char __user *, struct kstat *, int);
extern const char *vfs_get_link(struct dentry *, struct delayed_call *);
extern int __generic_block_fiemap(struct inode *inode, extern int __generic_block_fiemap(struct inode *inode,
struct fiemap_extent_info *fieinfo, struct fiemap_extent_info *fieinfo,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment