Root/fs/jfs/ioctl.c

1/*
2 * linux/fs/jfs/ioctl.c
3 *
4 * Copyright (C) 2006 Herbert Poetzl
5 * adapted from Remy Card's ext2/ioctl.c
6 */
7
8#include <linux/fs.h>
9#include <linux/ctype.h>
10#include <linux/capability.h>
11#include <linux/mount.h>
12#include <linux/time.h>
13#include <linux/sched.h>
14#include <asm/current.h>
15#include <asm/uaccess.h>
16
17#include "jfs_incore.h"
18#include "jfs_dinode.h"
19#include "jfs_inode.h"
20
21
22static struct {
23    long jfs_flag;
24    long ext2_flag;
25} jfs_map[] = {
26    {JFS_NOATIME_FL, FS_NOATIME_FL},
27    {JFS_DIRSYNC_FL, FS_DIRSYNC_FL},
28    {JFS_SYNC_FL, FS_SYNC_FL},
29    {JFS_SECRM_FL, FS_SECRM_FL},
30    {JFS_UNRM_FL, FS_UNRM_FL},
31    {JFS_APPEND_FL, FS_APPEND_FL},
32    {JFS_IMMUTABLE_FL, FS_IMMUTABLE_FL},
33    {0, 0},
34};
35
36static long jfs_map_ext2(unsigned long flags, int from)
37{
38    int index=0;
39    long mapped=0;
40
41    while (jfs_map[index].jfs_flag) {
42        if (from) {
43            if (jfs_map[index].ext2_flag & flags)
44                mapped |= jfs_map[index].jfs_flag;
45        } else {
46            if (jfs_map[index].jfs_flag & flags)
47                mapped |= jfs_map[index].ext2_flag;
48        }
49        index++;
50    }
51    return mapped;
52}
53
54
55long jfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
56{
57    struct inode *inode = filp->f_dentry->d_inode;
58    struct jfs_inode_info *jfs_inode = JFS_IP(inode);
59    unsigned int flags;
60
61    switch (cmd) {
62    case JFS_IOC_GETFLAGS:
63        jfs_get_inode_flags(jfs_inode);
64        flags = jfs_inode->mode2 & JFS_FL_USER_VISIBLE;
65        flags = jfs_map_ext2(flags, 0);
66        return put_user(flags, (int __user *) arg);
67    case JFS_IOC_SETFLAGS: {
68        unsigned int oldflags;
69        int err;
70
71        err = mnt_want_write(filp->f_path.mnt);
72        if (err)
73            return err;
74
75        if (!inode_owner_or_capable(inode)) {
76            err = -EACCES;
77            goto setflags_out;
78        }
79        if (get_user(flags, (int __user *) arg)) {
80            err = -EFAULT;
81            goto setflags_out;
82        }
83
84        flags = jfs_map_ext2(flags, 1);
85        if (!S_ISDIR(inode->i_mode))
86            flags &= ~JFS_DIRSYNC_FL;
87
88        /* Is it quota file? Do not allow user to mess with it */
89        if (IS_NOQUOTA(inode)) {
90            err = -EPERM;
91            goto setflags_out;
92        }
93
94        /* Lock against other parallel changes of flags */
95        mutex_lock(&inode->i_mutex);
96
97        jfs_get_inode_flags(jfs_inode);
98        oldflags = jfs_inode->mode2;
99
100        /*
101         * The IMMUTABLE and APPEND_ONLY flags can only be changed by
102         * the relevant capability.
103         */
104        if ((oldflags & JFS_IMMUTABLE_FL) ||
105            ((flags ^ oldflags) &
106            (JFS_APPEND_FL | JFS_IMMUTABLE_FL))) {
107            if (!capable(CAP_LINUX_IMMUTABLE)) {
108                mutex_unlock(&inode->i_mutex);
109                err = -EPERM;
110                goto setflags_out;
111            }
112        }
113
114        flags = flags & JFS_FL_USER_MODIFIABLE;
115        flags |= oldflags & ~JFS_FL_USER_MODIFIABLE;
116        jfs_inode->mode2 = flags;
117
118        jfs_set_inode_flags(inode);
119        mutex_unlock(&inode->i_mutex);
120        inode->i_ctime = CURRENT_TIME_SEC;
121        mark_inode_dirty(inode);
122setflags_out:
123        mnt_drop_write(filp->f_path.mnt);
124        return err;
125    }
126    default:
127        return -ENOTTY;
128    }
129}
130
131#ifdef CONFIG_COMPAT
132long jfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
133{
134    /* While these ioctl numbers defined with 'long' and have different
135     * numbers than the 64bit ABI,
136     * the actual implementation only deals with ints and is compatible.
137     */
138    switch (cmd) {
139    case JFS_IOC_GETFLAGS32:
140        cmd = JFS_IOC_GETFLAGS;
141        break;
142    case JFS_IOC_SETFLAGS32:
143        cmd = JFS_IOC_SETFLAGS;
144        break;
145    }
146    return jfs_ioctl(filp, cmd, arg);
147}
148#endif
149

Archive Download this file



interactive