vserver 1.9.5.x5
[linux-2.6.git] / fs / reiserfs / ioctl.c
index ec59e07..965518e 100644 (file)
@@ -9,6 +9,8 @@
 #include <linux/pagemap.h>
 #include <linux/smp_lock.h>
 
+static int reiserfs_unpack (struct inode * inode, struct file * filp);
+
 /*
 ** reiserfs_ioctl - handler for ioctl for inode
 ** supported commands:
@@ -20,7 +22,7 @@
 int reiserfs_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
                unsigned long arg)
 {
-       unsigned int flags;
+       unsigned int flags, oldflags;
 
        switch (cmd) {
            case REISERFS_IOC_UNPACK:
@@ -36,7 +38,8 @@ int reiserfs_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
        case REISERFS_IOC_GETFLAGS:
                flags = REISERFS_I(inode) -> i_attrs;
                i_attrs_to_sd_attrs( inode, ( __u16 * ) &flags );
-               return put_user(flags, (int *) arg);
+               flags &= REISERFS_FL_USER_VISIBLE;
+               return put_user(flags, (int __user *) arg);
        case REISERFS_IOC_SETFLAGS: {
                if (IS_RDONLY(inode))
                        return -EROFS;
@@ -44,11 +47,15 @@ int reiserfs_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
                if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
                        return -EPERM;
 
-               if (get_user(flags, (int *) arg))
+               if (get_user(flags, (int __user *) arg))
                        return -EFAULT;
 
-               if ( ( ( flags ^ REISERFS_I(inode) -> i_attrs) & ( REISERFS_IMMUTABLE_FL | REISERFS_APPEND_FL)) &&
-                    !capable( CAP_LINUX_IMMUTABLE ) )
+               oldflags = REISERFS_I(inode) -> i_attrs;
+               if ( ( (oldflags & REISERFS_IMMUTABLE_FL) ||
+                       ( (flags ^ oldflags) &
+                       (REISERFS_IMMUTABLE_FL | REISERFS_IUNLINK_FL |
+                        REISERFS_APPEND_FL) ) ) &&
+                       !capable( CAP_LINUX_IMMUTABLE ) )
                        return -EPERM;
                        
                if( ( flags & REISERFS_NOTAIL_FL ) &&
@@ -59,22 +66,25 @@ int reiserfs_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
                                if( result )
                                        return result;
                }
+
+               flags = flags & REISERFS_FL_USER_MODIFYABLE;
+               flags |= oldflags & ~REISERFS_FL_USER_MODIFYABLE;
                sd_attrs_to_i_attrs( flags, inode );
                REISERFS_I(inode) -> i_attrs = flags;
-               inode->i_ctime = CURRENT_TIME;
+               inode->i_ctime = CURRENT_TIME_SEC;
                mark_inode_dirty(inode);
                return 0;
        }
        case REISERFS_IOC_GETVERSION:
-               return put_user(inode->i_generation, (int *) arg);
+               return put_user(inode->i_generation, (int __user *) arg);
        case REISERFS_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 *) arg))
+               if (get_user(inode->i_generation, (int __user *) arg))
                        return -EFAULT; 
-               inode->i_ctime = CURRENT_TIME;
+               inode->i_ctime = CURRENT_TIME_SEC;
                mark_inode_dirty(inode);
                return 0;
        default:
@@ -87,7 +97,7 @@ int reiserfs_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
 ** Function try to convert tail from direct item into indirect.
 ** It set up nopack attribute in the REISERFS_I(inode)->nopack
 */
-int reiserfs_unpack (struct inode * inode, struct file * filp)
+static int reiserfs_unpack (struct inode * inode, struct file * filp)
 {
     int retval = 0;
     int index ;