2005-04-17 02:20:36 +04:00
/*
* linux / fs / ext2 / ioctl . c
*
* Copyright ( C ) 1993 , 1994 , 1995
* Remy Card ( card @ masi . ibp . fr )
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie ( Paris VI )
*/
# include "ext2.h"
2006-01-11 23:17:46 +03:00
# include <linux/capability.h>
2005-04-17 02:20:36 +04:00
# include <linux/time.h>
# include <linux/sched.h>
# include <asm/current.h>
# include <asm/uaccess.h>
int ext2_ioctl ( struct inode * inode , struct file * filp , unsigned int cmd ,
unsigned long arg )
{
struct ext2_inode_info * ei = EXT2_I ( inode ) ;
unsigned int flags ;
ext2_debug ( " cmd = %u, arg = %lu \n " , cmd , arg ) ;
switch ( cmd ) {
case EXT2_IOC_GETFLAGS :
flags = ei - > i_flags & EXT2_FL_USER_VISIBLE ;
return put_user ( flags , ( int __user * ) arg ) ;
case EXT2_IOC_SETFLAGS : {
unsigned int oldflags ;
if ( IS_RDONLY ( inode ) )
return - EROFS ;
if ( ( current - > fsuid ! = inode - > i_uid ) & & ! capable ( CAP_FOWNER ) )
return - EACCES ;
if ( get_user ( flags , ( int __user * ) arg ) )
return - EFAULT ;
if ( ! S_ISDIR ( inode - > i_mode ) )
flags & = ~ EXT2_DIRSYNC_FL ;
oldflags = ei - > i_flags ;
/*
* The IMMUTABLE and APPEND_ONLY flags can only be changed by
* the relevant capability .
*
* This test looks nicer . Thanks to Pauline Middelink
*/
if ( ( flags ^ oldflags ) & ( EXT2_APPEND_FL | EXT2_IMMUTABLE_FL ) ) {
if ( ! capable ( CAP_LINUX_IMMUTABLE ) )
return - EPERM ;
}
flags = flags & EXT2_FL_USER_MODIFIABLE ;
flags | = oldflags & ~ EXT2_FL_USER_MODIFIABLE ;
ei - > i_flags = flags ;
ext2_set_inode_flags ( inode ) ;
inode - > i_ctime = CURRENT_TIME_SEC ;
mark_inode_dirty ( inode ) ;
return 0 ;
}
case EXT2_IOC_GETVERSION :
return put_user ( inode - > i_generation , ( int __user * ) arg ) ;
case EXT2_IOC_SETVERSION :
if ( ( current - > fsuid ! = inode - > i_uid ) & & ! capable ( CAP_FOWNER ) )
return - EPERM ;
if ( IS_RDONLY ( inode ) )
return - EROFS ;
if ( get_user ( inode - > i_generation , ( int __user * ) arg ) )
return - EFAULT ;
inode - > i_ctime = CURRENT_TIME_SEC ;
mark_inode_dirty ( inode ) ;
return 0 ;
default :
return - ENOTTY ;
}
}