summaryrefslogtreecommitdiffstats
path: root/fs/cifs/smb1ops.c
diff options
context:
space:
mode:
authorPavel Shilovsky <piastry@etersoft.ru>2013-10-23 17:49:47 +0400
committerSteve French <smfrench@gmail.com>2013-11-11 16:31:03 -0600
commiteb85d94bdd91fb4dbea4ee465d4349cbea4eaaca (patch)
tree217ed41bd6bdf55b5a7263d42ebab386f6377785 /fs/cifs/smb1ops.c
parent6c86ae2928f9e4cbf0d5844f5fcfd549e3450b8c (diff)
downloadlinux-eb85d94bdd91fb4dbea4ee465d4349cbea4eaaca.tar.gz
linux-eb85d94bdd91fb4dbea4ee465d4349cbea4eaaca.tar.bz2
linux-eb85d94bdd91fb4dbea4ee465d4349cbea4eaaca.zip
CIFS: Fix symbolic links usage
Now we treat any reparse point as a symbolic link and map it to a Unix one that is not true in a common case due to many reparse point types supported by SMB servers. Distinguish reparse point types into two groups: 1) that can be accessed directly through a reparse point (junctions, deduplicated files, NFS symlinks); 2) that need to be processed manually (Windows symbolic links, DFS); and map only Windows symbolic links to Unix ones. Cc: <stable@vger.kernel.org> Acked-by: Jeff Layton <jlayton@redhat.com> Reported-and-tested-by: Joao Correia <joaomiguelcorreia@gmail.com> Signed-off-by: Pavel Shilovsky <piastry@etersoft.ru> Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs/cifs/smb1ops.c')
-rw-r--r--fs/cifs/smb1ops.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 384cffe42850..5f5ba0dc2ee1 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -534,10 +534,12 @@ cifs_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
static int
cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
struct cifs_sb_info *cifs_sb, const char *full_path,
- FILE_ALL_INFO *data, bool *adjustTZ)
+ FILE_ALL_INFO *data, bool *adjustTZ, bool *symlink)
{
int rc;
+ *symlink = false;
+
/* could do find first instead but this returns more info */
rc = CIFSSMBQPathInfo(xid, tcon, full_path, data, 0 /* not legacy */,
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
@@ -554,6 +556,23 @@ cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
CIFS_MOUNT_MAP_SPECIAL_CHR);
*adjustTZ = true;
}
+
+ if (!rc && (le32_to_cpu(data->Attributes) & ATTR_REPARSE)) {
+ int tmprc;
+ int oplock = 0;
+ __u16 netfid;
+
+ /* Need to check if this is a symbolic link or not */
+ tmprc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
+ FILE_READ_ATTRIBUTES, 0, &netfid, &oplock,
+ NULL, cifs_sb->local_nls,
+ cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+ if (tmprc == -EOPNOTSUPP)
+ *symlink = true;
+ else
+ CIFSSMBClose(xid, tcon, netfid);
+ }
+
return rc;
}