Blame view

fs/jfs/ioctl.c 3.18 KB
d9e902668   Herbert Poetzl   JFS: Add missing ...
1
2
3
4
5
6
7
8
  /*
   * linux/fs/jfs/ioctl.c
   *
   * Copyright (C) 2006 Herbert Poetzl
   * adapted from Remy Card's ext2/ioctl.c
   */
  
  #include <linux/fs.h>
d9e902668   Herbert Poetzl   JFS: Add missing ...
9
10
  #include <linux/ctype.h>
  #include <linux/capability.h>
42a74f206   Dave Hansen   [PATCH] r/o bind ...
11
  #include <linux/mount.h>
d9e902668   Herbert Poetzl   JFS: Add missing ...
12
  #include <linux/time.h>
914e26379   Al Viro   [PATCH] severing ...
13
  #include <linux/sched.h>
d9e902668   Herbert Poetzl   JFS: Add missing ...
14
15
16
17
18
19
20
21
22
23
24
25
  #include <asm/current.h>
  #include <asm/uaccess.h>
  
  #include "jfs_incore.h"
  #include "jfs_dinode.h"
  #include "jfs_inode.h"
  
  
  static struct {
  	long jfs_flag;
  	long ext2_flag;
  } jfs_map[] = {
36695673b   David Howells   [PATCH] BLOCK: Mo...
26
27
28
29
30
31
32
  	{JFS_NOATIME_FL,	FS_NOATIME_FL},
  	{JFS_DIRSYNC_FL,	FS_DIRSYNC_FL},
  	{JFS_SYNC_FL,		FS_SYNC_FL},
  	{JFS_SECRM_FL,		FS_SECRM_FL},
  	{JFS_UNRM_FL,		FS_UNRM_FL},
  	{JFS_APPEND_FL,		FS_APPEND_FL},
  	{JFS_IMMUTABLE_FL,	FS_IMMUTABLE_FL},
d9e902668   Herbert Poetzl   JFS: Add missing ...
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
  	{0, 0},
  };
  
  static long jfs_map_ext2(unsigned long flags, int from)
  {
  	int index=0;
  	long mapped=0;
  
  	while (jfs_map[index].jfs_flag) {
  		if (from) {
  			if (jfs_map[index].ext2_flag & flags)
  				mapped |= jfs_map[index].jfs_flag;
  		} else {
  			if (jfs_map[index].jfs_flag & flags)
  				mapped |= jfs_map[index].ext2_flag;
  		}
  		index++;
  	}
  	return mapped;
  }
baab81fa5   Andi Kleen   BKL-removal: Use ...
53
  long jfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
d9e902668   Herbert Poetzl   JFS: Add missing ...
54
  {
baab81fa5   Andi Kleen   BKL-removal: Use ...
55
  	struct inode *inode = filp->f_dentry->d_inode;
d9e902668   Herbert Poetzl   JFS: Add missing ...
56
57
58
59
60
  	struct jfs_inode_info *jfs_inode = JFS_IP(inode);
  	unsigned int flags;
  
  	switch (cmd) {
  	case JFS_IOC_GETFLAGS:
3e2221c73   Dave Kleikamp   Copy i_flags to j...
61
  		jfs_get_inode_flags(jfs_inode);
d9e902668   Herbert Poetzl   JFS: Add missing ...
62
63
64
65
66
  		flags = jfs_inode->mode2 & JFS_FL_USER_VISIBLE;
  		flags = jfs_map_ext2(flags, 0);
  		return put_user(flags, (int __user *) arg);
  	case JFS_IOC_SETFLAGS: {
  		unsigned int oldflags;
42a74f206   Dave Hansen   [PATCH] r/o bind ...
67
  		int err;
d9e902668   Herbert Poetzl   JFS: Add missing ...
68

a561be710   Al Viro   switch a bunch of...
69
  		err = mnt_want_write_file(filp);
42a74f206   Dave Hansen   [PATCH] r/o bind ...
70
71
  		if (err)
  			return err;
d9e902668   Herbert Poetzl   JFS: Add missing ...
72

2e1496707   Serge E. Hallyn   userns: rename is...
73
  		if (!inode_owner_or_capable(inode)) {
42a74f206   Dave Hansen   [PATCH] r/o bind ...
74
75
76
77
78
79
80
  			err = -EACCES;
  			goto setflags_out;
  		}
  		if (get_user(flags, (int __user *) arg)) {
  			err = -EFAULT;
  			goto setflags_out;
  		}
d9e902668   Herbert Poetzl   JFS: Add missing ...
81
82
83
84
  
  		flags = jfs_map_ext2(flags, 1);
  		if (!S_ISDIR(inode->i_mode))
  			flags &= ~JFS_DIRSYNC_FL;
e47776a0a   Jan Kara   Forbid user to ch...
85
  		/* Is it quota file? Do not allow user to mess with it */
42a74f206   Dave Hansen   [PATCH] r/o bind ...
86
87
88
89
  		if (IS_NOQUOTA(inode)) {
  			err = -EPERM;
  			goto setflags_out;
  		}
baab81fa5   Andi Kleen   BKL-removal: Use ...
90
91
92
  
  		/* Lock against other parallel changes of flags */
  		mutex_lock(&inode->i_mutex);
3e2221c73   Dave Kleikamp   Copy i_flags to j...
93
  		jfs_get_inode_flags(jfs_inode);
d9e902668   Herbert Poetzl   JFS: Add missing ...
94
95
96
97
98
99
100
101
102
  		oldflags = jfs_inode->mode2;
  
  		/*
  		 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
  		 * the relevant capability.
  		 */
  		if ((oldflags & JFS_IMMUTABLE_FL) ||
  			((flags ^ oldflags) &
  			(JFS_APPEND_FL | JFS_IMMUTABLE_FL))) {
baab81fa5   Andi Kleen   BKL-removal: Use ...
103
104
  			if (!capable(CAP_LINUX_IMMUTABLE)) {
  				mutex_unlock(&inode->i_mutex);
42a74f206   Dave Hansen   [PATCH] r/o bind ...
105
106
  				err = -EPERM;
  				goto setflags_out;
baab81fa5   Andi Kleen   BKL-removal: Use ...
107
  			}
d9e902668   Herbert Poetzl   JFS: Add missing ...
108
109
110
111
112
113
114
  		}
  
  		flags = flags & JFS_FL_USER_MODIFIABLE;
  		flags |= oldflags & ~JFS_FL_USER_MODIFIABLE;
  		jfs_inode->mode2 = flags;
  
  		jfs_set_inode_flags(inode);
baab81fa5   Andi Kleen   BKL-removal: Use ...
115
  		mutex_unlock(&inode->i_mutex);
d9e902668   Herbert Poetzl   JFS: Add missing ...
116
117
  		inode->i_ctime = CURRENT_TIME_SEC;
  		mark_inode_dirty(inode);
42a74f206   Dave Hansen   [PATCH] r/o bind ...
118
  setflags_out:
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
119
  		mnt_drop_write_file(filp);
42a74f206   Dave Hansen   [PATCH] r/o bind ...
120
  		return err;
d9e902668   Herbert Poetzl   JFS: Add missing ...
121
122
123
124
125
  	}
  	default:
  		return -ENOTTY;
  	}
  }
ef1fc2f01   Andi Kleen   BKL-removal: Impl...
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
  #ifdef CONFIG_COMPAT
  long jfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  {
  	/* While these ioctl numbers defined with 'long' and have different
  	 * numbers than the 64bit ABI,
  	 * the actual implementation only deals with ints and is compatible.
  	 */
  	switch (cmd) {
  	case JFS_IOC_GETFLAGS32:
  		cmd = JFS_IOC_GETFLAGS;
  		break;
  	case JFS_IOC_SETFLAGS32:
  		cmd = JFS_IOC_SETFLAGS;
  		break;
  	}
  	return jfs_ioctl(filp, cmd, arg);
  }
  #endif