@@ -65,11 +65,14 @@ static int exfat_d_revalidate(struct dentry *dentry, unsigned int flags)
6565 return ret ;
6666}
6767
68- /* returns the length of a struct qstr, ignoring trailing dots */
69- static unsigned int exfat_striptail_len (unsigned int len , const char * name )
68+ /* returns the length of a struct qstr, ignoring trailing dots if necessary */
69+ static unsigned int exfat_striptail_len (unsigned int len , const char * name ,
70+ bool keep_last_dots )
7071{
71- while (len && name [len - 1 ] == '.' )
72- len -- ;
72+ if (!keep_last_dots ) {
73+ while (len && name [len - 1 ] == '.' )
74+ len -- ;
75+ }
7376 return len ;
7477}
7578
@@ -83,7 +86,8 @@ static int exfat_d_hash(const struct dentry *dentry, struct qstr *qstr)
8386 struct super_block * sb = dentry -> d_sb ;
8487 struct nls_table * t = EXFAT_SB (sb )-> nls_io ;
8588 const unsigned char * name = qstr -> name ;
86- unsigned int len = exfat_striptail_len (qstr -> len , qstr -> name );
89+ unsigned int len = exfat_striptail_len (qstr -> len , qstr -> name ,
90+ EXFAT_SB (sb )-> options .keep_last_dots );
8791 unsigned long hash = init_name_hash (dentry );
8892 int i , charlen ;
8993 wchar_t c ;
@@ -104,8 +108,10 @@ static int exfat_d_cmp(const struct dentry *dentry, unsigned int len,
104108{
105109 struct super_block * sb = dentry -> d_sb ;
106110 struct nls_table * t = EXFAT_SB (sb )-> nls_io ;
107- unsigned int alen = exfat_striptail_len (name -> len , name -> name );
108- unsigned int blen = exfat_striptail_len (len , str );
111+ unsigned int alen = exfat_striptail_len (name -> len , name -> name ,
112+ EXFAT_SB (sb )-> options .keep_last_dots );
113+ unsigned int blen = exfat_striptail_len (len , str ,
114+ EXFAT_SB (sb )-> options .keep_last_dots );
109115 wchar_t c1 , c2 ;
110116 int charlen , i ;
111117
@@ -136,7 +142,8 @@ static int exfat_utf8_d_hash(const struct dentry *dentry, struct qstr *qstr)
136142{
137143 struct super_block * sb = dentry -> d_sb ;
138144 const unsigned char * name = qstr -> name ;
139- unsigned int len = exfat_striptail_len (qstr -> len , qstr -> name );
145+ unsigned int len = exfat_striptail_len (qstr -> len , qstr -> name ,
146+ EXFAT_SB (sb )-> options .keep_last_dots );
140147 unsigned long hash = init_name_hash (dentry );
141148 int i , charlen ;
142149 unicode_t u ;
@@ -161,8 +168,11 @@ static int exfat_utf8_d_cmp(const struct dentry *dentry, unsigned int len,
161168 const char * str , const struct qstr * name )
162169{
163170 struct super_block * sb = dentry -> d_sb ;
164- unsigned int alen = exfat_striptail_len (name -> len , name -> name );
165- unsigned int blen = exfat_striptail_len (len , str );
171+ unsigned int alen = exfat_striptail_len (name -> len , name -> name ,
172+ EXFAT_SB (sb )-> options .keep_last_dots );
173+ unsigned int blen = exfat_striptail_len (len , str ,
174+ EXFAT_SB (sb )-> options .keep_last_dots );
175+
166176 unicode_t u_a , u_b ;
167177 int charlen , i ;
168178
@@ -416,13 +426,25 @@ static int __exfat_resolve_path(struct inode *inode, const unsigned char *path,
416426 struct super_block * sb = inode -> i_sb ;
417427 struct exfat_sb_info * sbi = EXFAT_SB (sb );
418428 struct exfat_inode_info * ei = EXFAT_I (inode );
429+ int pathlen = strlen (path );
419430
420- /* strip all trailing periods */
421- namelen = exfat_striptail_len (strlen (path ), path );
431+ /*
432+ * get the length of the pathname excluding
433+ * trailing periods, if any.
434+ */
435+ namelen = exfat_striptail_len (pathlen , path , false);
436+ if (EXFAT_SB (sb )-> options .keep_last_dots ) {
437+ /*
438+ * Do not allow the creation of files with names
439+ * ending with period(s).
440+ */
441+ if (!lookup && (namelen < pathlen ))
442+ return - EINVAL ;
443+ namelen = pathlen ;
444+ }
422445 if (!namelen )
423446 return - ENOENT ;
424-
425- if (strlen (path ) > (MAX_NAME_LENGTH * MAX_CHARSET_SIZE ))
447+ if (pathlen > (MAX_NAME_LENGTH * MAX_CHARSET_SIZE ))
426448 return - ENAMETOOLONG ;
427449
428450 /*
@@ -554,7 +576,6 @@ static int exfat_create(struct user_namespace *mnt_userns, struct inode *dir,
554576 exfat_set_volume_dirty (sb );
555577 err = exfat_add_entry (dir , dentry -> d_name .name , & cdir , TYPE_FILE ,
556578 & info );
557- exfat_clear_volume_dirty (sb );
558579 if (err )
559580 goto unlock ;
560581
@@ -812,7 +833,6 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry)
812833
813834 /* This doesn't modify ei */
814835 ei -> dir .dir = DIR_DELETED ;
815- exfat_clear_volume_dirty (sb );
816836
817837 inode_inc_iversion (dir );
818838 dir -> i_mtime = dir -> i_atime = current_time (dir );
@@ -846,7 +866,6 @@ static int exfat_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
846866 exfat_set_volume_dirty (sb );
847867 err = exfat_add_entry (dir , dentry -> d_name .name , & cdir , TYPE_DIR ,
848868 & info );
849- exfat_clear_volume_dirty (sb );
850869 if (err )
851870 goto unlock ;
852871
@@ -976,7 +995,6 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
976995 goto unlock ;
977996 }
978997 ei -> dir .dir = DIR_DELETED ;
979- exfat_clear_volume_dirty (sb );
980998
981999 inode_inc_iversion (dir );
9821000 dir -> i_mtime = dir -> i_atime = current_time (dir );
@@ -1311,7 +1329,6 @@ static int __exfat_rename(struct inode *old_parent_inode,
13111329 */
13121330 new_ei -> dir .dir = DIR_DELETED ;
13131331 }
1314- exfat_clear_volume_dirty (sb );
13151332out :
13161333 return ret ;
13171334}
0 commit comments