@@ -746,6 +746,84 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
746746#endif
747747}
748748
749+ #define POSIX_TYPE_FILE 0
750+ #define POSIX_TYPE_DIR 1
751+ #define POSIX_TYPE_SYMLINK 2
752+ #define POSIX_TYPE_CHARDEV 3
753+ #define POSIX_TYPE_BLKDEV 4
754+ #define POSIX_TYPE_FIFO 5
755+ #define POSIX_TYPE_SOCKET 6
756+
757+ #define POSIX_X_OTH 0000001
758+ #define POSIX_W_OTH 0000002
759+ #define POSIX_R_OTH 0000004
760+ #define POSIX_X_GRP 0000010
761+ #define POSIX_W_GRP 0000020
762+ #define POSIX_R_GRP 0000040
763+ #define POSIX_X_USR 0000100
764+ #define POSIX_W_USR 0000200
765+ #define POSIX_R_USR 0000400
766+ #define POSIX_STICKY 0001000
767+ #define POSIX_SET_GID 0002000
768+ #define POSIX_SET_UID 0004000
769+
770+ #define POSIX_OTH_MASK 0000007
771+ #define POSIX_GRP_MASK 0000070
772+ #define POSIX_USR_MASK 0000700
773+ #define POSIX_PERM_MASK 0000777
774+ #define POSIX_FILETYPE_MASK 0070000
775+
776+ #define POSIX_FILETYPE_SHIFT 12
777+
778+ static u32 wire_perms_to_posix (u32 wire )
779+ {
780+ u32 mode = 0 ;
781+
782+ mode |= (wire & POSIX_X_OTH ) ? S_IXOTH : 0 ;
783+ mode |= (wire & POSIX_W_OTH ) ? S_IWOTH : 0 ;
784+ mode |= (wire & POSIX_R_OTH ) ? S_IROTH : 0 ;
785+ mode |= (wire & POSIX_X_GRP ) ? S_IXGRP : 0 ;
786+ mode |= (wire & POSIX_W_GRP ) ? S_IWGRP : 0 ;
787+ mode |= (wire & POSIX_R_GRP ) ? S_IRGRP : 0 ;
788+ mode |= (wire & POSIX_X_USR ) ? S_IXUSR : 0 ;
789+ mode |= (wire & POSIX_W_USR ) ? S_IWUSR : 0 ;
790+ mode |= (wire & POSIX_R_USR ) ? S_IRUSR : 0 ;
791+ mode |= (wire & POSIX_STICKY ) ? S_ISVTX : 0 ;
792+ mode |= (wire & POSIX_SET_GID ) ? S_ISGID : 0 ;
793+ mode |= (wire & POSIX_SET_UID ) ? S_ISUID : 0 ;
794+
795+ return mode ;
796+ }
797+
798+ static u32 posix_filetypes [] = {
799+ S_IFREG ,
800+ S_IFDIR ,
801+ S_IFLNK ,
802+ S_IFCHR ,
803+ S_IFBLK ,
804+ S_IFIFO ,
805+ S_IFSOCK
806+ };
807+
808+ static u32 wire_filetype_to_posix (u32 wire_type )
809+ {
810+ if (wire_type >= ARRAY_SIZE (posix_filetypes )) {
811+ pr_warn ("Unexpected type %u" , wire_type );
812+ return 0 ;
813+ }
814+ return posix_filetypes [wire_type ];
815+ }
816+
817+ umode_t wire_mode_to_posix (u32 wire )
818+ {
819+ u32 wire_type ;
820+ u32 mode ;
821+
822+ wire_type = (wire & POSIX_FILETYPE_MASK ) >> POSIX_FILETYPE_SHIFT ;
823+ mode = (wire_perms_to_posix (wire ) | wire_filetype_to_posix (wire_type ));
824+ return (umode_t )mode ;
825+ }
826+
749827/* Fill a cifs_fattr struct with info from POSIX info struct */
750828static void smb311_posix_info_to_fattr (struct cifs_fattr * fattr ,
751829 struct cifs_open_info_data * data ,
@@ -782,20 +860,13 @@ static void smb311_posix_info_to_fattr(struct cifs_fattr *fattr,
782860 fattr -> cf_bytes = le64_to_cpu (info -> AllocationSize );
783861 fattr -> cf_createtime = le64_to_cpu (info -> CreationTime );
784862 fattr -> cf_nlink = le32_to_cpu (info -> HardLinks );
785- fattr -> cf_mode = ( umode_t ) le32_to_cpu (info -> Mode );
863+ fattr -> cf_mode = wire_mode_to_posix ( le32_to_cpu (info -> Mode ) );
786864
787865 if (cifs_open_data_reparse (data ) &&
788866 cifs_reparse_point_to_fattr (cifs_sb , fattr , data ))
789867 goto out_reparse ;
790868
791- fattr -> cf_mode &= ~S_IFMT ;
792- if (fattr -> cf_cifsattrs & ATTR_DIRECTORY ) {
793- fattr -> cf_mode |= S_IFDIR ;
794- fattr -> cf_dtype = DT_DIR ;
795- } else { /* file */
796- fattr -> cf_mode |= S_IFREG ;
797- fattr -> cf_dtype = DT_REG ;
798- }
869+ fattr -> cf_dtype = S_DT (fattr -> cf_mode );
799870
800871out_reparse :
801872 if (S_ISLNK (fattr -> cf_mode )) {
0 commit comments