summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/smb/client/cifsproto.h2
-rw-r--r--fs/smb/client/inode.c11
-rw-r--r--fs/smb/client/readdir.c3
3 files changed, 11 insertions, 5 deletions
diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
index 90e3297ea847..754417cb3294 100644
--- a/fs/smb/client/cifsproto.h
+++ b/fs/smb/client/cifsproto.h
@@ -669,7 +669,7 @@ int __cifs_sfu_make_node(unsigned int xid, struct inode *inode,
int cifs_sfu_make_node(unsigned int xid, struct inode *inode,
struct dentry *dentry, struct cifs_tcon *tcon,
const char *full_path, umode_t mode, dev_t dev);
-umode_t wire_mode_to_posix(u32 wire);
+umode_t wire_mode_to_posix(u32 wire, bool is_dir);
#ifdef CONFIG_CIFS_DFS_UPCALL
static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses,
diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c
index ef913d65c67f..668098d3b108 100644
--- a/fs/smb/client/inode.c
+++ b/fs/smb/client/inode.c
@@ -814,13 +814,17 @@ static u32 wire_filetype_to_posix(u32 wire_type)
return posix_filetypes[wire_type];
}
-umode_t wire_mode_to_posix(u32 wire)
+umode_t wire_mode_to_posix(u32 wire, bool is_dir)
{
u32 wire_type;
u32 mode;
wire_type = (wire & POSIX_FILETYPE_MASK) >> POSIX_FILETYPE_SHIFT;
- mode = (wire_perms_to_posix(wire) | wire_filetype_to_posix(wire_type));
+ /* older servers do not set POSIX file type in the mode field in the response */
+ if ((wire_type == 0) && is_dir)
+ mode = wire_perms_to_posix(wire) | S_IFDIR;
+ else
+ mode = (wire_perms_to_posix(wire) | wire_filetype_to_posix(wire_type));
return (umode_t)mode;
}
@@ -860,7 +864,8 @@ static void smb311_posix_info_to_fattr(struct cifs_fattr *fattr,
fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
fattr->cf_createtime = le64_to_cpu(info->CreationTime);
fattr->cf_nlink = le32_to_cpu(info->HardLinks);
- fattr->cf_mode = wire_mode_to_posix(le32_to_cpu(info->Mode));
+ fattr->cf_mode = wire_mode_to_posix(le32_to_cpu(info->Mode),
+ fattr->cf_cifsattrs & ATTR_DIRECTORY);
if (cifs_open_data_reparse(data) &&
cifs_reparse_point_to_fattr(cifs_sb, fattr, data))
diff --git a/fs/smb/client/readdir.c b/fs/smb/client/readdir.c
index b906bf78af1e..273358d20a46 100644
--- a/fs/smb/client/readdir.c
+++ b/fs/smb/client/readdir.c
@@ -261,7 +261,8 @@ cifs_posix_to_fattr(struct cifs_fattr *fattr, struct smb2_posix_info *info,
fattr->cf_cifstag = le32_to_cpu(info->ReparseTag);
/* The Mode field in the response can now include the file type as well */
- fattr->cf_mode = wire_mode_to_posix(le32_to_cpu(info->Mode));
+ fattr->cf_mode = wire_mode_to_posix(le32_to_cpu(info->Mode),
+ fattr->cf_cifsattrs & ATTR_DIRECTORY);
fattr->cf_dtype = S_DT(le32_to_cpu(info->Mode));
switch (fattr->cf_mode & S_IFMT) {