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

Commit 94744567 authored by Christoph Hellwig's avatar Christoph Hellwig
Browse files

hfsplus: split hfsplus_ioctl



Give each ioctl command a function of it's own.

Signed-off-by: default avatarChristoph Hellwig <hch@tuxera.com>
parent 249e6353
Loading
Loading
Loading
Loading
+80 −65
Original line number Diff line number Diff line
@@ -21,78 +21,93 @@
#include <asm/uaccess.h>
#include "hfsplus_fs.h"

long hfsplus_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
{
	struct inode *inode = filp->f_path.dentry->d_inode;
	unsigned int flags;
	struct inode *inode = file->f_path.dentry->d_inode;
	unsigned int flags = 0;

	switch (cmd) {
	case HFSPLUS_IOC_EXT2_GETFLAGS:
		flags = 0;
	if (HFSPLUS_I(inode).rootflags & HFSPLUS_FLG_IMMUTABLE)
			flags |= FS_IMMUTABLE_FL; /* EXT2_IMMUTABLE_FL */
		flags |= FS_IMMUTABLE_FL;
	if (HFSPLUS_I(inode).rootflags & HFSPLUS_FLG_APPEND)
			flags |= FS_APPEND_FL; /* EXT2_APPEND_FL */
		flags |= FS_APPEND_FL;
	if (HFSPLUS_I(inode).userflags & HFSPLUS_FLG_NODUMP)
			flags |= FS_NODUMP_FL; /* EXT2_NODUMP_FL */
		return put_user(flags, (int __user *)arg);
	case HFSPLUS_IOC_EXT2_SETFLAGS: {
		flags |= FS_NODUMP_FL;

	return put_user(flags, user_flags);
}

static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
{
	struct inode *inode = file->f_path.dentry->d_inode;
	unsigned int flags;
	int err = 0;

	lock_kernel();
		err = mnt_want_write(filp->f_path.mnt);
		if (err) {
			unlock_kernel();
			return err;
		}
	err = mnt_want_write(file->f_path.mnt);
	if (err)
		goto out_unlock_kernel;

	if (!is_owner_or_cap(inode)) {
		err = -EACCES;
			goto setflags_out;
		goto out_drop_write;
	}
		if (get_user(flags, (int __user *)arg)) {

	if (get_user(flags, user_flags)) {
		err = -EFAULT;
			goto setflags_out;
		goto out_drop_write;
	}

	if (flags & (FS_IMMUTABLE_FL|FS_APPEND_FL) ||
	    HFSPLUS_I(inode).rootflags & (HFSPLUS_FLG_IMMUTABLE|HFSPLUS_FLG_APPEND)) {
		if (!capable(CAP_LINUX_IMMUTABLE)) {
			err = -EPERM;
				goto setflags_out;
			goto out_drop_write;
		}
	}

	/* don't silently ignore unsupported ext2 flags */
	if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL)) {
		err = -EOPNOTSUPP;
			goto setflags_out;
		goto out_drop_write;
	}
		if (flags & FS_IMMUTABLE_FL) { /* EXT2_IMMUTABLE_FL */
	if (flags & FS_IMMUTABLE_FL) {
		inode->i_flags |= S_IMMUTABLE;
		HFSPLUS_I(inode).rootflags |= HFSPLUS_FLG_IMMUTABLE;
	} else {
		inode->i_flags &= ~S_IMMUTABLE;
		HFSPLUS_I(inode).rootflags &= ~HFSPLUS_FLG_IMMUTABLE;
	}
		if (flags & FS_APPEND_FL) { /* EXT2_APPEND_FL */
	if (flags & FS_APPEND_FL) {
		inode->i_flags |= S_APPEND;
		HFSPLUS_I(inode).rootflags |= HFSPLUS_FLG_APPEND;
	} else {
		inode->i_flags &= ~S_APPEND;
		HFSPLUS_I(inode).rootflags &= ~HFSPLUS_FLG_APPEND;
	}
		if (flags & FS_NODUMP_FL) /* EXT2_NODUMP_FL */
	if (flags & FS_NODUMP_FL)
		HFSPLUS_I(inode).userflags |= HFSPLUS_FLG_NODUMP;
	else
		HFSPLUS_I(inode).userflags &= ~HFSPLUS_FLG_NODUMP;

	inode->i_ctime = CURRENT_TIME_SEC;
	mark_inode_dirty(inode);
setflags_out:
		mnt_drop_write(filp->f_path.mnt);

out_drop_write:
	mnt_drop_write(file->f_path.mnt);
out_unlock_kernel:
	unlock_kernel();
	return err;
}

long hfsplus_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	void __user *argp = (void __user *)arg;

	switch (cmd) {
	case HFSPLUS_IOC_EXT2_GETFLAGS:
		return hfsplus_ioctl_getflags(file, argp);
	case HFSPLUS_IOC_EXT2_SETFLAGS:
		return hfsplus_ioctl_setflags(file, argp);
	default:
		return -ENOTTY;
	}