*/
#include <linux/fs.h>
#include <linux/stat.h>
+#include <linux/namei.h>
#include "cifsfs.h"
#include "cifspdu.h"
#include "cifsglob.h"
int rc = -EACCES;
int xid;
char *full_path = NULL;
- char * target_path;
+ char * target_path = ERR_PTR(-ENOMEM);
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
full_path = build_path_from_dentry(direntry);
up(&direntry->d_sb->s_vfs_rename_sem);
- if(full_path == NULL) {
- FreeXid(xid);
- return -ENOMEM;
- }
+ if (!full_path)
+ goto out_no_free;
+
cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
target_path = kmalloc(PATH_MAX, GFP_KERNEL);
- if(target_path == NULL) {
- if (full_path)
- kfree(full_path);
- FreeXid(xid);
- return -ENOMEM;
+ if (!target_path) {
+ target_path = ERR_PTR(-ENOMEM);
+ goto out;
}
- /* 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 */
if (pTcon->ses->capabilities & CAP_UNIX)
else {
/* rc = CIFSSMBQueryReparseLinkInfo */
/* BB Add code to Query ReparsePoint info */
+ /* BB Add MAC style xsymlink check here if enabled */
}
- /* BB Anything else to do to handle recursive links? */
- /* BB Should we be using page symlink ops here? */
if (rc == 0) {
/* BB Add special case check for Samba DFS symlinks */
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)
- kfree(target_path);
- if (full_path)
- kfree(full_path);
+out:
+ kfree(full_path);
+out_no_free:
FreeXid(xid);
- return rc;
+ nd_set_link(nd, target_path);
+ return 0;
}
int
if(referrals)
kfree(referrals);
kfree(tmp_path);
- if(referrals) {
- kfree(referrals);
- }
- }
+}
/* BB add code like else decode referrals then memcpy to
tmpbuffer and free referrals string array BB */
}
FreeXid(xid);
return rc;
}
+
+void cifs_put_link(struct dentry *direntry, struct nameidata *nd)
+{
+ char *p = nd_get_link(nd);
+ if (!IS_ERR(p))
+ kfree(p);
+}