diff options
author | Stefan Metzmacher <metze@samba.org> | 2010-08-05 23:19:56 +0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2010-09-29 23:04:31 +0400 |
commit | 1b12b9c15b4371d83b729b8fc18c670e78a1479b (patch) | |
tree | f82c9b0d01cdc5e64765780403f460e9e0d8496b /fs/cifs/link.c | |
parent | 8713d01db8bf948eb9632726f529ec4f821bb025 (diff) | |
download | linux-1b12b9c15b4371d83b729b8fc18c670e78a1479b.tar.xz |
cifs: use Minshall+French symlink functions
If configured, Minshall+French Symlinks are used against
all servers. If the server supports UNIX Extensions,
we still create Minshall+French Symlinks on write,
but on read we fallback to UNIX Extension symlinks.
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/link.c')
-rw-r--r-- | fs/cifs/link.c | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 1b2a8c971995..cbf7b112287b 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -407,7 +407,8 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd) * but there doesn't seem to be any harm in allowing the client to * read them. */ - if (!(tcon->ses->capabilities & CAP_UNIX)) { + if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) + && !(tcon->ses->capabilities & CAP_UNIX)) { rc = -EACCES; goto out; } @@ -418,8 +419,21 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd) cFYI(1, "Full path: %s inode = 0x%p", full_path, inode); - rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path, - cifs_sb->local_nls); + rc = -EACCES; + /* + * First try Minshall+French Symlinks, if configured + * and fallback to UNIX Extensions Symlinks. + */ + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) + rc = CIFSQueryMFSymLink(xid, tcon, full_path, &target_path, + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); + + if ((rc != 0) && (tcon->ses->capabilities & CAP_UNIX)) + rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path, + cifs_sb->local_nls); + kfree(full_path); out: if (rc != 0) { @@ -459,7 +473,12 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) cFYI(1, "symname is %s", symname); /* BB what if DFS and this volume is on different share? BB */ - if (pTcon->unix_ext) + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) + rc = CIFSCreateMFSymLink(xid, pTcon, full_path, symname, + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); + else if (pTcon->unix_ext) rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname, cifs_sb->local_nls); /* else |