aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fat
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fat')
-rw-r--r--fs/fat/file.c24
-rw-r--r--fs/fat/inode.c18
2 files changed, 39 insertions, 3 deletions
diff --git a/fs/fat/file.c b/fs/fat/file.c
index e73f13a13792..d604bb132422 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -280,11 +280,27 @@ static int fat_check_mode(const struct msdos_sb_info *sbi, struct inode *inode,
280 return 0; 280 return 0;
281} 281}
282 282
283static int fat_allow_set_time(struct msdos_sb_info *sbi, struct inode *inode)
284{
285 mode_t allow_utime = sbi->options.allow_utime;
286
287 if (current->fsuid != inode->i_uid) {
288 if (in_group_p(inode->i_gid))
289 allow_utime >>= 3;
290 if (allow_utime & MAY_WRITE)
291 return 1;
292 }
293
294 /* use a default check */
295 return 0;
296}
297
283int fat_setattr(struct dentry *dentry, struct iattr *attr) 298int fat_setattr(struct dentry *dentry, struct iattr *attr)
284{ 299{
285 struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb); 300 struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
286 struct inode *inode = dentry->d_inode; 301 struct inode *inode = dentry->d_inode;
287 int mask, error = 0; 302 int mask, error = 0;
303 unsigned int ia_valid;
288 304
289 lock_kernel(); 305 lock_kernel();
290 306
@@ -302,7 +318,15 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)
302 } 318 }
303 } 319 }
304 320
321 /* Check for setting the inode time. */
322 ia_valid = attr->ia_valid;
323 if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) {
324 if (fat_allow_set_time(sbi, inode))
325 attr->ia_valid &= ~(ATTR_MTIME_SET | ATTR_ATIME_SET);
326 }
327
305 error = inode_change_ok(inode, attr); 328 error = inode_change_ok(inode, attr);
329 attr->ia_valid = ia_valid;
306 if (error) { 330 if (error) {
307 if (sbi->options.quiet) 331 if (sbi->options.quiet)
308 error = 0; 332 error = 0;
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index f22f287e507a..886f6095a378 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -785,6 +785,8 @@ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt)
785 seq_printf(m, ",gid=%u", opts->fs_gid); 785 seq_printf(m, ",gid=%u", opts->fs_gid);
786 seq_printf(m, ",fmask=%04o", opts->fs_fmask); 786 seq_printf(m, ",fmask=%04o", opts->fs_fmask);
787 seq_printf(m, ",dmask=%04o", opts->fs_dmask); 787 seq_printf(m, ",dmask=%04o", opts->fs_dmask);
788 if (opts->allow_utime)
789 seq_printf(m, ",allow_utime=%04o", opts->allow_utime);
788 if (sbi->nls_disk) 790 if (sbi->nls_disk)
789 seq_printf(m, ",codepage=%s", sbi->nls_disk->charset); 791 seq_printf(m, ",codepage=%s", sbi->nls_disk->charset);
790 if (isvfat) { 792 if (isvfat) {
@@ -840,9 +842,9 @@ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt)
840 842
841enum { 843enum {
842 Opt_check_n, Opt_check_r, Opt_check_s, Opt_uid, Opt_gid, 844 Opt_check_n, Opt_check_r, Opt_check_s, Opt_uid, Opt_gid,
843 Opt_umask, Opt_dmask, Opt_fmask, Opt_codepage, Opt_usefree, Opt_nocase, 845 Opt_umask, Opt_dmask, Opt_fmask, Opt_allow_utime, Opt_codepage,
844 Opt_quiet, Opt_showexec, Opt_debug, Opt_immutable, 846 Opt_usefree, Opt_nocase, Opt_quiet, Opt_showexec, Opt_debug,
845 Opt_dots, Opt_nodots, 847 Opt_immutable, Opt_dots, Opt_nodots,
846 Opt_charset, Opt_shortname_lower, Opt_shortname_win95, 848 Opt_charset, Opt_shortname_lower, Opt_shortname_win95,
847 Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes, 849 Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes,
848 Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, 850 Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes,
@@ -861,6 +863,7 @@ static match_table_t fat_tokens = {
861 {Opt_umask, "umask=%o"}, 863 {Opt_umask, "umask=%o"},
862 {Opt_dmask, "dmask=%o"}, 864 {Opt_dmask, "dmask=%o"},
863 {Opt_fmask, "fmask=%o"}, 865 {Opt_fmask, "fmask=%o"},
866 {Opt_allow_utime, "allow_utime=%o"},
864 {Opt_codepage, "codepage=%u"}, 867 {Opt_codepage, "codepage=%u"},
865 {Opt_usefree, "usefree"}, 868 {Opt_usefree, "usefree"},
866 {Opt_nocase, "nocase"}, 869 {Opt_nocase, "nocase"},
@@ -932,6 +935,7 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
932 opts->fs_uid = current->uid; 935 opts->fs_uid = current->uid;
933 opts->fs_gid = current->gid; 936 opts->fs_gid = current->gid;
934 opts->fs_fmask = opts->fs_dmask = current->fs->umask; 937 opts->fs_fmask = opts->fs_dmask = current->fs->umask;
938 opts->allow_utime = -1;
935 opts->codepage = fat_default_codepage; 939 opts->codepage = fat_default_codepage;
936 opts->iocharset = fat_default_iocharset; 940 opts->iocharset = fat_default_iocharset;
937 if (is_vfat) 941 if (is_vfat)
@@ -1019,6 +1023,11 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
1019 return 0; 1023 return 0;
1020 opts->fs_fmask = option; 1024 opts->fs_fmask = option;
1021 break; 1025 break;
1026 case Opt_allow_utime:
1027 if (match_octal(&args[0], &option))
1028 return 0;
1029 opts->allow_utime = option & (S_IWGRP | S_IWOTH);
1030 break;
1022 case Opt_codepage: 1031 case Opt_codepage:
1023 if (match_int(&args[0], &option)) 1032 if (match_int(&args[0], &option))
1024 return 0; 1033 return 0;
@@ -1101,6 +1110,9 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
1101 " for FAT filesystems, filesystem will be case sensitive!\n"); 1110 " for FAT filesystems, filesystem will be case sensitive!\n");
1102 } 1111 }
1103 1112
1113 /* If user doesn't specify allow_utime, it's initialized from dmask. */
1114 if (opts->allow_utime == (unsigned short)-1)
1115 opts->allow_utime = ~opts->fs_dmask & (S_IWGRP | S_IWOTH);
1104 if (opts->unicode_xlate) 1116 if (opts->unicode_xlate)
1105 opts->utf8 = 0; 1117 opts->utf8 = 0;
1106 1118