root/fs/ext2/ioctl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ext2_ioctl
  2. ext2_compat_ioctl

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * linux/fs/ext2/ioctl.c
   4  *
   5  * Copyright (C) 1993, 1994, 1995
   6  * Remy Card (card@masi.ibp.fr)
   7  * Laboratoire MASI - Institut Blaise Pascal
   8  * Universite Pierre et Marie Curie (Paris VI)
   9  */
  10 
  11 #include "ext2.h"
  12 #include <linux/capability.h>
  13 #include <linux/time.h>
  14 #include <linux/sched.h>
  15 #include <linux/compat.h>
  16 #include <linux/mount.h>
  17 #include <asm/current.h>
  18 #include <linux/uaccess.h>
  19 
  20 
  21 long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  22 {
  23         struct inode *inode = file_inode(filp);
  24         struct ext2_inode_info *ei = EXT2_I(inode);
  25         unsigned int flags;
  26         unsigned short rsv_window_size;
  27         int ret;
  28 
  29         ext2_debug ("cmd = %u, arg = %lu\n", cmd, arg);
  30 
  31         switch (cmd) {
  32         case EXT2_IOC_GETFLAGS:
  33                 flags = ei->i_flags & EXT2_FL_USER_VISIBLE;
  34                 return put_user(flags, (int __user *) arg);
  35         case EXT2_IOC_SETFLAGS: {
  36                 unsigned int oldflags;
  37 
  38                 ret = mnt_want_write_file(filp);
  39                 if (ret)
  40                         return ret;
  41 
  42                 if (!inode_owner_or_capable(inode)) {
  43                         ret = -EACCES;
  44                         goto setflags_out;
  45                 }
  46 
  47                 if (get_user(flags, (int __user *) arg)) {
  48                         ret = -EFAULT;
  49                         goto setflags_out;
  50                 }
  51 
  52                 flags = ext2_mask_flags(inode->i_mode, flags);
  53 
  54                 inode_lock(inode);
  55                 /* Is it quota file? Do not allow user to mess with it */
  56                 if (IS_NOQUOTA(inode)) {
  57                         inode_unlock(inode);
  58                         ret = -EPERM;
  59                         goto setflags_out;
  60                 }
  61                 oldflags = ei->i_flags;
  62 
  63                 ret = vfs_ioc_setflags_prepare(inode, oldflags, flags);
  64                 if (ret) {
  65                         inode_unlock(inode);
  66                         goto setflags_out;
  67                 }
  68 
  69                 flags = flags & EXT2_FL_USER_MODIFIABLE;
  70                 flags |= oldflags & ~EXT2_FL_USER_MODIFIABLE;
  71                 ei->i_flags = flags;
  72 
  73                 ext2_set_inode_flags(inode);
  74                 inode->i_ctime = current_time(inode);
  75                 inode_unlock(inode);
  76 
  77                 mark_inode_dirty(inode);
  78 setflags_out:
  79                 mnt_drop_write_file(filp);
  80                 return ret;
  81         }
  82         case EXT2_IOC_GETVERSION:
  83                 return put_user(inode->i_generation, (int __user *) arg);
  84         case EXT2_IOC_SETVERSION: {
  85                 __u32 generation;
  86 
  87                 if (!inode_owner_or_capable(inode))
  88                         return -EPERM;
  89                 ret = mnt_want_write_file(filp);
  90                 if (ret)
  91                         return ret;
  92                 if (get_user(generation, (int __user *) arg)) {
  93                         ret = -EFAULT;
  94                         goto setversion_out;
  95                 }
  96 
  97                 inode_lock(inode);
  98                 inode->i_ctime = current_time(inode);
  99                 inode->i_generation = generation;
 100                 inode_unlock(inode);
 101 
 102                 mark_inode_dirty(inode);
 103 setversion_out:
 104                 mnt_drop_write_file(filp);
 105                 return ret;
 106         }
 107         case EXT2_IOC_GETRSVSZ:
 108                 if (test_opt(inode->i_sb, RESERVATION)
 109                         && S_ISREG(inode->i_mode)
 110                         && ei->i_block_alloc_info) {
 111                         rsv_window_size = ei->i_block_alloc_info->rsv_window_node.rsv_goal_size;
 112                         return put_user(rsv_window_size, (int __user *)arg);
 113                 }
 114                 return -ENOTTY;
 115         case EXT2_IOC_SETRSVSZ: {
 116 
 117                 if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode))
 118                         return -ENOTTY;
 119 
 120                 if (!inode_owner_or_capable(inode))
 121                         return -EACCES;
 122 
 123                 if (get_user(rsv_window_size, (int __user *)arg))
 124                         return -EFAULT;
 125 
 126                 ret = mnt_want_write_file(filp);
 127                 if (ret)
 128                         return ret;
 129 
 130                 if (rsv_window_size > EXT2_MAX_RESERVE_BLOCKS)
 131                         rsv_window_size = EXT2_MAX_RESERVE_BLOCKS;
 132 
 133                 /*
 134                  * need to allocate reservation structure for this inode
 135                  * before set the window size
 136                  */
 137                 /*
 138                  * XXX What lock should protect the rsv_goal_size?
 139                  * Accessed in ext2_get_block only.  ext3 uses i_truncate.
 140                  */
 141                 mutex_lock(&ei->truncate_mutex);
 142                 if (!ei->i_block_alloc_info)
 143                         ext2_init_block_alloc_info(inode);
 144 
 145                 if (ei->i_block_alloc_info){
 146                         struct ext2_reserve_window_node *rsv = &ei->i_block_alloc_info->rsv_window_node;
 147                         rsv->rsv_goal_size = rsv_window_size;
 148                 }
 149                 mutex_unlock(&ei->truncate_mutex);
 150                 mnt_drop_write_file(filp);
 151                 return 0;
 152         }
 153         default:
 154                 return -ENOTTY;
 155         }
 156 }
 157 
 158 #ifdef CONFIG_COMPAT
 159 long ext2_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 160 {
 161         /* These are just misnamed, they actually get/put from/to user an int */
 162         switch (cmd) {
 163         case EXT2_IOC32_GETFLAGS:
 164                 cmd = EXT2_IOC_GETFLAGS;
 165                 break;
 166         case EXT2_IOC32_SETFLAGS:
 167                 cmd = EXT2_IOC_SETFLAGS;
 168                 break;
 169         case EXT2_IOC32_GETVERSION:
 170                 cmd = EXT2_IOC_GETVERSION;
 171                 break;
 172         case EXT2_IOC32_SETVERSION:
 173                 cmd = EXT2_IOC_SETVERSION;
 174                 break;
 175         default:
 176                 return -ENOIOCTLCMD;
 177         }
 178         return ext2_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
 179 }
 180 #endif

/* [<][>][^][v][top][bottom][index][help] */