diff options
author | OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> | 2008-04-28 05:16:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-28 11:58:47 -0400 |
commit | 1ae43f826b6cb951fc5b0f9c92372a8d5b63c7f9 (patch) | |
tree | aea00f01d74a40e026974182006e8af903b0b241 /fs/fat | |
parent | e97e8de388723f9491514fa0434ddf1fd713a188 (diff) |
fat: Add allow_utime option
Normally utime(2) checks current process is owner of the file, or it
has CAP_FOWNER capability. But FAT filesystem doesn't have uid/gid as
on disk info, so normal check is too unflexible.
With this option you can relax it.
Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/fat')
-rw-r--r-- | fs/fat/file.c | 24 | ||||
-rw-r--r-- | fs/fat/inode.c | 18 |
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 | ||
283 | static 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 | |||
283 | int fat_setattr(struct dentry *dentry, struct iattr *attr) | 298 | int 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 | ||
841 | enum { | 843 | enum { |
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 | ||