summaryrefslogtreecommitdiffstats
path: root/fs/fat/file.c
diff options
context:
space:
mode:
authorOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>2008-11-06 12:53:55 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2008-11-06 15:41:21 -0800
commitdfc209c0064efef5590f608056a48b61a5cac09c (patch)
tree1ace2df7370944dd94b3c8f6a53acf6ea76fdd79 /fs/fat/file.c
parent9183482f5d4a2de00f66641b974e7f351d41b675 (diff)
downloadlinux-stable-dfc209c0064efef5590f608056a48b61a5cac09c.tar.gz
linux-stable-dfc209c0064efef5590f608056a48b61a5cac09c.tar.bz2
linux-stable-dfc209c0064efef5590f608056a48b61a5cac09c.zip
fat: Fix ATTR_RO for directory
FAT has the ATTR_RO (read-only) attribute. But on Windows, the ATTR_RO of the directory will be just ignored actually, and is used by only applications as flag. E.g. it's setted for the customized folder by Explorer. http://msdn2.microsoft.com/en-us/library/aa969337.aspx This adds "rodir" option. If user specified it, ATTR_RO is used as read-only flag even if it's the directory. Otherwise, inode->i_mode is not used to hold ATTR_RO (i.e. fat_mode_can_save_ro() returns 0). 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/file.c')
-rw-r--r--fs/fat/file.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 81b15c623803..f06a4e525ece 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -282,11 +282,18 @@ static int fat_sanitize_mode(const struct msdos_sb_info *sbi,
/*
* Of the r and x bits, all (subject to umask) must be present. Of the
* w bits, either all (subject to umask) or none must be present.
+ *
+ * If fat_mode_can_hold_ro(inode) is false, can't change w bits.
*/
if ((perm & (S_IRUGO | S_IXUGO)) != (inode->i_mode & (S_IRUGO|S_IXUGO)))
return -EPERM;
- if ((perm & S_IWUGO) && ((perm & S_IWUGO) != (S_IWUGO & ~mask)))
- return -EPERM;
+ if (fat_mode_can_hold_ro(inode)) {
+ if ((perm & S_IWUGO) && ((perm & S_IWUGO) != (S_IWUGO & ~mask)))
+ return -EPERM;
+ } else {
+ if ((perm & S_IWUGO) != (S_IWUGO & ~mask))
+ return -EPERM;
+ }
*mode_ptr &= S_IFMT | perm;
@@ -316,8 +323,8 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)
{
struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
struct inode *inode = dentry->d_inode;
- int error = 0;
unsigned int ia_valid;
+ int error;
/*
* Expand the file. Since inode_setattr() updates ->i_size
@@ -371,7 +378,8 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)
attr->ia_valid &= ~ATTR_MODE;
}
- error = inode_setattr(inode, attr);
+ if (attr->ia_valid)
+ error = inode_setattr(inode, attr);
out:
return error;
}