patch-2.6.6-vs1.9.0
[linux-2.6.git] / fs / reiserfs / ioctl.c
index ec59e07..eaddaf9 100644 (file)
@@ -20,7 +20,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,6 +36,7 @@ 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 );
+               flags &= REISERFS_FL_USER_VISIBLE;
                return put_user(flags, (int *) arg);
        case REISERFS_IOC_SETFLAGS: {
                if (IS_RDONLY(inode))
@@ -47,7 +48,9 @@ int reiserfs_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
                if (get_user(flags, (int *) arg))
                        return -EFAULT;
 
-               if ( ( ( flags ^ REISERFS_I(inode) -> i_attrs) & ( REISERFS_IMMUTABLE_FL | REISERFS_APPEND_FL)) &&
+               oldflags = REISERFS_I(inode) -> i_attrs;
+               if ( ( ( flags ^ oldflags) &
+                  ( REISERFS_IMMUTABLE_FL | REISERFS_IUNLINK_FL | REISERFS_APPEND_FL)) &&
                     !capable( CAP_LINUX_IMMUTABLE ) )
                        return -EPERM;
                        
@@ -59,6 +62,9 @@ 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;