diff options
Diffstat (limited to 'fs/ext2/ioctl.c')
-rw-r--r-- | fs/ext2/ioctl.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c new file mode 100644 index 000000000000..709d8676b962 --- /dev/null +++ b/fs/ext2/ioctl.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /* | ||
2 | * linux/fs/ext2/ioctl.c | ||
3 | * | ||
4 | * Copyright (C) 1993, 1994, 1995 | ||
5 | * Remy Card (card@masi.ibp.fr) | ||
6 | * Laboratoire MASI - Institut Blaise Pascal | ||
7 | * Universite Pierre et Marie Curie (Paris VI) | ||
8 | */ | ||
9 | |||
10 | #include "ext2.h" | ||
11 | #include <linux/time.h> | ||
12 | #include <linux/sched.h> | ||
13 | #include <asm/current.h> | ||
14 | #include <asm/uaccess.h> | ||
15 | |||
16 | |||
17 | int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, | ||
18 | unsigned long arg) | ||
19 | { | ||
20 | struct ext2_inode_info *ei = EXT2_I(inode); | ||
21 | unsigned int flags; | ||
22 | |||
23 | ext2_debug ("cmd = %u, arg = %lu\n", cmd, arg); | ||
24 | |||
25 | switch (cmd) { | ||
26 | case EXT2_IOC_GETFLAGS: | ||
27 | flags = ei->i_flags & EXT2_FL_USER_VISIBLE; | ||
28 | return put_user(flags, (int __user *) arg); | ||
29 | case EXT2_IOC_SETFLAGS: { | ||
30 | unsigned int oldflags; | ||
31 | |||
32 | if (IS_RDONLY(inode)) | ||
33 | return -EROFS; | ||
34 | |||
35 | if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) | ||
36 | return -EACCES; | ||
37 | |||
38 | if (get_user(flags, (int __user *) arg)) | ||
39 | return -EFAULT; | ||
40 | |||
41 | if (!S_ISDIR(inode->i_mode)) | ||
42 | flags &= ~EXT2_DIRSYNC_FL; | ||
43 | |||
44 | oldflags = ei->i_flags; | ||
45 | |||
46 | /* | ||
47 | * The IMMUTABLE and APPEND_ONLY flags can only be changed by | ||
48 | * the relevant capability. | ||
49 | * | ||
50 | * This test looks nicer. Thanks to Pauline Middelink | ||
51 | */ | ||
52 | if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL)) { | ||
53 | if (!capable(CAP_LINUX_IMMUTABLE)) | ||
54 | return -EPERM; | ||
55 | } | ||
56 | |||
57 | flags = flags & EXT2_FL_USER_MODIFIABLE; | ||
58 | flags |= oldflags & ~EXT2_FL_USER_MODIFIABLE; | ||
59 | ei->i_flags = flags; | ||
60 | |||
61 | ext2_set_inode_flags(inode); | ||
62 | inode->i_ctime = CURRENT_TIME_SEC; | ||
63 | mark_inode_dirty(inode); | ||
64 | return 0; | ||
65 | } | ||
66 | case EXT2_IOC_GETVERSION: | ||
67 | return put_user(inode->i_generation, (int __user *) arg); | ||
68 | case EXT2_IOC_SETVERSION: | ||
69 | if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) | ||
70 | return -EPERM; | ||
71 | if (IS_RDONLY(inode)) | ||
72 | return -EROFS; | ||
73 | if (get_user(inode->i_generation, (int __user *) arg)) | ||
74 | return -EFAULT; | ||
75 | inode->i_ctime = CURRENT_TIME_SEC; | ||
76 | mark_inode_dirty(inode); | ||
77 | return 0; | ||
78 | default: | ||
79 | return -ENOTTY; | ||
80 | } | ||
81 | } | ||