Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1278fdd3 authored by OGAWA Hirofumi's avatar OGAWA Hirofumi Committed by Linus Torvalds
Browse files

fat: fat_notify_change() and check_mode() cleanup



- Rename fat_notify_change() to fat_setattr()
- check_mode() cleanup
- Change layout of code

Signed-off-by: default avatarOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 3754a544
Loading
Loading
Loading
Loading
+84 −99
Original line number Diff line number Diff line
@@ -157,104 +157,6 @@ static int fat_cont_expand(struct inode *inode, loff_t size)
	return err;
}

static int check_mode(const struct msdos_sb_info *sbi, mode_t mode)
{
	mode_t req = mode & ~S_IFMT;

	/*
	 * 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 (S_ISREG(mode)) {
		req &= ~sbi->options.fs_fmask;

		if ((req & (S_IRUGO | S_IXUGO)) !=
		    ((S_IRUGO | S_IXUGO) & ~sbi->options.fs_fmask))
			return -EPERM;

		if ((req & S_IWUGO) != 0 &&
		    (req & S_IWUGO) != (S_IWUGO & ~sbi->options.fs_fmask))
			return -EPERM;
	} else if (S_ISDIR(mode)) {
		req &= ~sbi->options.fs_dmask;

		if ((req & (S_IRUGO | S_IXUGO)) !=
		    ((S_IRUGO | S_IXUGO) & ~sbi->options.fs_dmask))
			return -EPERM;

		if ((req & S_IWUGO) != 0 &&
		    (req & S_IWUGO) != (S_IWUGO & ~sbi->options.fs_dmask))
			return -EPERM;
	} else {
		return -EPERM;
	}

	return 0;
}

int fat_notify_change(struct dentry *dentry, struct iattr *attr)
{
	struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
	struct inode *inode = dentry->d_inode;
	int mask, error = 0;

	lock_kernel();

	/*
	 * Expand the file. Since inode_setattr() updates ->i_size
	 * before calling the ->truncate(), but FAT needs to fill the
	 * hole before it.
	 */
	if (attr->ia_valid & ATTR_SIZE) {
		if (attr->ia_size > inode->i_size) {
			error = fat_cont_expand(inode, attr->ia_size);
			if (error || attr->ia_valid == ATTR_SIZE)
				goto out;
			attr->ia_valid &= ~ATTR_SIZE;
		}
	}

	error = inode_change_ok(inode, attr);
	if (error) {
		if (sbi->options.quiet)
			error = 0;
		goto out;
	}
	if (((attr->ia_valid & ATTR_UID) &&
	     (attr->ia_uid != sbi->options.fs_uid)) ||
	    ((attr->ia_valid & ATTR_GID) &&
	     (attr->ia_gid != sbi->options.fs_gid)))
		error = -EPERM;

	if (error) {
		if (sbi->options.quiet)
			error = 0;
		goto out;
	}

	if (attr->ia_valid & ATTR_MODE) {
		error = check_mode(sbi, attr->ia_mode);
		if (error != 0 && !sbi->options.quiet)
			goto out;
	}

	error = inode_setattr(inode, attr);
	if (error)
		goto out;

	if (S_ISDIR(inode->i_mode))
		mask = sbi->options.fs_dmask;
	else
		mask = sbi->options.fs_fmask;
	inode->i_mode &= S_IFMT | (S_IRWXUGO & ~mask);
out:
	unlock_kernel();
	return error;
}

EXPORT_SYMBOL_GPL(fat_notify_change);

/* Free all clusters after the skip'th cluster. */
static int fat_free(struct inode *inode, int skip)
{
@@ -355,8 +257,91 @@ int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
}
EXPORT_SYMBOL_GPL(fat_getattr);

static int fat_check_mode(const struct msdos_sb_info *sbi, mode_t mode)
{
	mode_t mask, req = mode & ~S_IFMT;

	if (S_ISREG(mode))
		mask = sbi->options.fs_fmask;
	else
		mask = sbi->options.fs_dmask;

	/*
	 * 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.
	 */
	req &= ~mask;
	if ((req & (S_IRUGO | S_IXUGO)) != ((S_IRUGO | S_IXUGO) & ~mask))
		return -EPERM;
	if ((req & S_IWUGO) && ((req & S_IWUGO) != (S_IWUGO & ~mask)))
		return -EPERM;

	return 0;
}

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 mask, error = 0;

	lock_kernel();

	/*
	 * Expand the file. Since inode_setattr() updates ->i_size
	 * before calling the ->truncate(), but FAT needs to fill the
	 * hole before it.
	 */
	if (attr->ia_valid & ATTR_SIZE) {
		if (attr->ia_size > inode->i_size) {
			error = fat_cont_expand(inode, attr->ia_size);
			if (error || attr->ia_valid == ATTR_SIZE)
				goto out;
			attr->ia_valid &= ~ATTR_SIZE;
		}
	}

	error = inode_change_ok(inode, attr);
	if (error) {
		if (sbi->options.quiet)
			error = 0;
		goto out;
	}
	if (((attr->ia_valid & ATTR_UID) &&
	     (attr->ia_uid != sbi->options.fs_uid)) ||
	    ((attr->ia_valid & ATTR_GID) &&
	     (attr->ia_gid != sbi->options.fs_gid)))
		error = -EPERM;

	if (error) {
		if (sbi->options.quiet)
			error = 0;
		goto out;
	}

	if (attr->ia_valid & ATTR_MODE) {
		error = fat_check_mode(sbi, attr->ia_mode);
		if (error != 0 && !sbi->options.quiet)
			goto out;
	}

	error = inode_setattr(inode, attr);
	if (error)
		goto out;

	if (S_ISDIR(inode->i_mode))
		mask = sbi->options.fs_dmask;
	else
		mask = sbi->options.fs_fmask;
	inode->i_mode &= S_IFMT | (S_IRWXUGO & ~mask);
out:
	unlock_kernel();
	return error;
}
EXPORT_SYMBOL_GPL(fat_setattr);

const struct inode_operations fat_file_inode_operations = {
	.truncate	= fat_truncate,
	.setattr	= fat_notify_change,
	.setattr	= fat_setattr,
	.getattr	= fat_getattr,
};
+1 −1
Original line number Diff line number Diff line
@@ -653,7 +653,7 @@ static const struct inode_operations msdos_dir_inode_operations = {
	.mkdir		= msdos_mkdir,
	.rmdir		= msdos_rmdir,
	.rename		= msdos_rename,
	.setattr	= fat_notify_change,
	.setattr	= fat_setattr,
	.getattr	= fat_getattr,
};

+1 −1
Original line number Diff line number Diff line
@@ -1003,7 +1003,7 @@ static const struct inode_operations vfat_dir_inode_operations = {
	.mkdir		= vfat_mkdir,
	.rmdir		= vfat_rmdir,
	.rename		= vfat_rename,
	.setattr	= fat_notify_change,
	.setattr	= fat_setattr,
	.getattr	= fat_getattr,
};

+1 −1
Original line number Diff line number Diff line
@@ -401,7 +401,7 @@ extern int fat_generic_ioctl(struct inode *inode, struct file *filp,
			     unsigned int cmd, unsigned long arg);
extern const struct file_operations fat_file_operations;
extern const struct inode_operations fat_file_inode_operations;
extern int fat_notify_change(struct dentry * dentry, struct iattr * attr);
extern int fat_setattr(struct dentry * dentry, struct iattr * attr);
extern void fat_truncate(struct inode *inode);
extern int fat_getattr(struct vfsmount *mnt, struct dentry *dentry,
		       struct kstat *stat);