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/time.h> 12 #include <linux/sched.h> 13 #include <asm/current.h> 14 #include <asm/uaccess.h> 15 16 #include "jfs_incore.h" 17 #include "jfs_dinode.h" 18 #include "jfs_inode.h" 19 20 21 static struct { 22 long jfs_flag; 23 long ext2_flag; 24 } jfs_map[] = { 25 {JFS_NOATIME_FL, FS_NOATIME_FL}, 26 {JFS_DIRSYNC_FL, FS_DIRSYNC_FL}, 27 {JFS_SYNC_FL, FS_SYNC_FL}, 28 {JFS_SECRM_FL, FS_SECRM_FL}, 29 {JFS_UNRM_FL, FS_UNRM_FL}, 30 {JFS_APPEND_FL, FS_APPEND_FL}, 31 {JFS_IMMUTABLE_FL, FS_IMMUTABLE_FL}, 32 {0, 0}, 33 }; 34 35 static long jfs_map_ext2(unsigned long flags, int from) 36 { 37 int index=0; 38 long mapped=0; 39 40 while (jfs_map[index].jfs_flag) { 41 if (from) { 42 if (jfs_map[index].ext2_flag & flags) 43 mapped |= jfs_map[index].jfs_flag; 44 } else { 45 if (jfs_map[index].jfs_flag & flags) 46 mapped |= jfs_map[index].ext2_flag; 47 } 48 index++; 49 } 50 return mapped; 51 } 52 53 54 int jfs_ioctl(struct inode * inode, struct file * filp, unsigned int cmd, 55 unsigned long arg) 56 { 57 struct jfs_inode_info *jfs_inode = JFS_IP(inode); 58 unsigned int flags; 59 60 switch (cmd) { 61 case JFS_IOC_GETFLAGS: 62 jfs_get_inode_flags(jfs_inode); 63 flags = jfs_inode->mode2 & JFS_FL_USER_VISIBLE; 64 flags = jfs_map_ext2(flags, 0); 65 return put_user(flags, (int __user *) arg); 66 case JFS_IOC_SETFLAGS: { 67 unsigned int oldflags; 68 69 if (IS_RDONLY(inode)) 70 return -EROFS; 71 72 if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) 73 return -EACCES; 74 75 if (get_user(flags, (int __user *) arg)) 76 return -EFAULT; 77 78 flags = jfs_map_ext2(flags, 1); 79 if (!S_ISDIR(inode->i_mode)) 80 flags &= ~JFS_DIRSYNC_FL; 81 82 jfs_get_inode_flags(jfs_inode); 83 oldflags = jfs_inode->mode2; 84 85 /* 86 * The IMMUTABLE and APPEND_ONLY flags can only be changed by 87 * the relevant capability. 88 */ 89 if ((oldflags & JFS_IMMUTABLE_FL) || 90 ((flags ^ oldflags) & 91 (JFS_APPEND_FL | JFS_IMMUTABLE_FL))) { 92 if (!capable(CAP_LINUX_IMMUTABLE)) 93 return -EPERM; 94 } 95 96 flags = flags & JFS_FL_USER_MODIFIABLE; 97 flags |= oldflags & ~JFS_FL_USER_MODIFIABLE; 98 jfs_inode->mode2 = flags; 99 100 jfs_set_inode_flags(inode); 101 inode->i_ctime = CURRENT_TIME_SEC; 102 mark_inode_dirty(inode); 103 return 0; 104 } 105 default: 106 return -ENOTTY; 107 } 108 } 109 110