Commit a4d2a829 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] cifs ->follow_link() switched to new scheme, cleaned up

Signed-off-by: default avatarAl Viro <viro@parcelfarce.linux.org.uk>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 2b3fcc10
...@@ -514,6 +514,7 @@ struct inode_operations cifs_file_inode_ops = { ...@@ -514,6 +514,7 @@ struct inode_operations cifs_file_inode_ops = {
struct inode_operations cifs_symlink_inode_ops = { struct inode_operations cifs_symlink_inode_ops = {
.readlink = cifs_readlink, .readlink = cifs_readlink,
.follow_link = cifs_follow_link, .follow_link = cifs_follow_link,
.put_link = cifs_put_link,
.permission = cifs_permission, .permission = cifs_permission,
/* BB add the following two eventually */ /* BB add the following two eventually */
/* revalidate: cifs_revalidate, /* revalidate: cifs_revalidate,
......
...@@ -81,6 +81,7 @@ extern struct dentry_operations cifs_dentry_ops; ...@@ -81,6 +81,7 @@ extern struct dentry_operations cifs_dentry_ops;
/* Functions related to symlinks */ /* Functions related to symlinks */
extern int cifs_follow_link(struct dentry *direntry, struct nameidata *nd); extern int cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
extern void cifs_put_link(struct dentry *direntry, struct nameidata *nd);
extern int cifs_readlink(struct dentry *direntry, char __user *buffer, int buflen); extern int cifs_readlink(struct dentry *direntry, char __user *buffer, int buflen);
extern int cifs_symlink(struct inode *inode, struct dentry *direntry, extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
const char *symname); const char *symname);
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
*/ */
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/namei.h>
#include "cifsfs.h" #include "cifsfs.h"
#include "cifspdu.h" #include "cifspdu.h"
#include "cifsglob.h" #include "cifsglob.h"
...@@ -94,7 +95,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd) ...@@ -94,7 +95,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
int rc = -EACCES; int rc = -EACCES;
int xid; int xid;
char *full_path = NULL; char *full_path = NULL;
char * target_path; char * target_path = ERR_PTR(-ENOMEM);
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
...@@ -104,22 +105,17 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd) ...@@ -104,22 +105,17 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
up(&direntry->d_sb->s_vfs_rename_sem); up(&direntry->d_sb->s_vfs_rename_sem);
if(full_path == NULL) { if (!full_path)
FreeXid(xid); goto out;
return -ENOMEM;
}
cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode)); cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
cifs_sb = CIFS_SB(inode->i_sb); cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
target_path = kmalloc(PATH_MAX, GFP_KERNEL); target_path = kmalloc(PATH_MAX, GFP_KERNEL);
if(target_path == NULL) { if (!target_path) {
if (full_path) target_path = ERR_PTR(-ENOMEM);
kfree(full_path); goto out;
FreeXid(xid);
return -ENOMEM;
} }
/* can not call the following line due to EFAULT in vfs_readlink which is presumably expecting a user space buffer */
/* length = cifs_readlink(direntry,target_path, sizeof(target_path) - 1); */
/* BB add read reparse point symlink code and Unix extensions symlink code here BB */ /* BB add read reparse point symlink code and Unix extensions symlink code here BB */
if (pTcon->ses->capabilities & CAP_UNIX) if (pTcon->ses->capabilities & CAP_UNIX)
...@@ -139,16 +135,16 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd) ...@@ -139,16 +135,16 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
/* BB Add special case check for Samba DFS symlinks */ /* BB Add special case check for Samba DFS symlinks */
target_path[PATH_MAX-1] = 0; target_path[PATH_MAX-1] = 0;
rc = vfs_follow_link(nd, target_path); } else {
kfree(target_path);
target_path = ERR_PTR(rc);
} }
/* else EACCESS */
if (target_path) out:
kfree(target_path);
if (full_path)
kfree(full_path); kfree(full_path);
FreeXid(xid); FreeXid(xid);
return rc; nd_set_link(nd, target_path);
return 0;
} }
int int
...@@ -323,3 +319,10 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) ...@@ -323,3 +319,10 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
FreeXid(xid); FreeXid(xid);
return rc; return rc;
} }
void cifs_put_link(struct dentry *direntry, struct nameidata *nd)
{
char *p = nd_get_link(nd);
if (!IS_ERR(p))
kfree(p);
}
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