*** gfs-kernel/src/gfs/gfs_ondisk.h.orig 2004-09-24 17:07:04.933204208 +0400 --- gfs-kernel/src/gfs/gfs_ondisk.h 2004-09-24 17:07:37.271288072 +0400 *************** *** 298,303 **** --- 298,305 ---- #define GFS_DIF_INHERIT_DIRECTIO (0x40000000) #define GFS_DIF_INHERIT_JDATA (0x80000000) + #define GFS_IS_IMMUTABLE(inode) ((inode)->i_di.di_flags & GFS_DIF_IMMUTABLE) + struct gfs_dinode { struct gfs_meta_header di_header; *** gfs-kernel/src/gfs/ioctl.c.orig 2004-09-24 17:32:41.079674448 +0400 --- gfs-kernel/src/gfs/ioctl.c 2004-09-24 17:34:51.454854408 +0400 *************** *** 628,633 **** --- 628,644 ---- break; case GFS_DIF_IMMUTABLE: + /* + * The IMMUTABLE flags can only be changed by + * the relevant capability. + */ + if ((ip->i_di.di_flags ^ flag) & GFS_DIF_IMMUTABLE) { + if (!capable(CAP_LINUX_IMMUTABLE)) { + error = -EPERM; + goto out; + } + } + break; case GFS_DIF_APPENDONLY: case GFS_DIF_NOATIME: case GFS_DIF_SYNC: *** gfs-kernel/src/gfs/ops_inode.c.orig 2004-09-24 15:12:09.000000000 +0400 --- gfs-kernel/src/gfs/ops_inode.c 2004-09-24 18:11:24.335410608 +0400 *************** *** 479,484 **** --- 479,489 ---- if (error) goto fail; + if (GFS_IS_IMMUTABLE(ip)) { + error = -EACCES; + goto fail_gunlock; + } + error = permission(dir, MAY_WRITE | MAY_EXEC, NULL); if (error) goto fail_gunlock; *************** *** 730,735 **** --- 735,745 ---- if (error) goto fail; + if (GFS_IS_IMMUTABLE(ip)) { + error = -EACCES; + goto fail_gunlock; + } + error = permission(dir, MAY_WRITE | MAY_EXEC, NULL); if (error) goto fail_gunlock; *************** *** 950,957 **** if (error) goto fail_uninit; ! /* Check out the old directory */ error = permission(odir, MAY_WRITE | MAY_EXEC, NULL); if (error) goto fail_gunlock; --- 960,971 ---- if (error) goto fail_uninit; ! if (GFS_IS_IMMUTABLE(ip)) { ! error = -EACCES; ! goto fail_gunlock; ! } + /* Check out the old directory */ error = permission(odir, MAY_WRITE | MAY_EXEC, NULL); if (error) goto fail_gunlock; *************** *** 1263,1272 **** error = -EROFS; goto out; } ! if (IS_IMMUTABLE(inode)) { ! printk("anton: IMMUTABLE flag is set\n"); ! error = -EACCES; ! goto out; } } --- 1277,1285 ---- error = -EROFS; goto out; } ! if (GFS_IS_IMMUTABLE(ip)) { ! error = -EACCES; ! goto out; } } *************** *** 1342,1347 **** --- 1355,1365 ---- if (error) return error; + if (GFS_IS_IMMUTABLE(ip)) { + error = -EACCES; + goto fail; + } + error = inode_change_ok(inode, attr); if (error) goto fail; *************** *** 1544,1549 **** --- 1562,1571 ---- char *truncated_name; int error = 0; + if (GFS_IS_IMMUTABLE(ip)) { + error = -EACCES; + } + atomic_inc(&sdp->sd_ops_inode); req.es_type = get_eatype(name, &truncated_name); *** gfs/gfs_tool/main.c.orig 2004-09-23 12:59:28.000000000 +0400 --- gfs/gfs_tool/main.c 2004-09-24 18:18:10.669638416 +0400 *************** *** 150,158 **** printf(" ea_indirect\n"); if (di->di_flags & GFS_DIF_DIRECTIO) printf(" directio\n"); - #if 0 if (di->di_flags & GFS_DIF_IMMUTABLE) printf(" immutable\n"); if (di->di_flags & GFS_DIF_APPENDONLY) printf(" appendonly\n"); if (di->di_flags & GFS_DIF_NOATIME) --- 150,158 ---- printf(" ea_indirect\n"); if (di->di_flags & GFS_DIF_DIRECTIO) printf(" directio\n"); if (di->di_flags & GFS_DIF_IMMUTABLE) printf(" immutable\n"); + #if 0 if (di->di_flags & GFS_DIF_APPENDONLY) printf(" appendonly\n"); if (di->di_flags & GFS_DIF_NOATIME) *************** *** 889,897 **** flag = GFS_DIF_EA_INDIRECT; else if (strcmp(argv[2], "directio") == 0) flag = GFS_DIF_DIRECTIO; - #if 0 else if (strcmp(argv[2], "immutable") == 0) flag = GFS_DIF_IMMUTABLE; else if (strcmp(argv[2], "appendonly") == 0) flag = GFS_DIF_APPENDONLY; else if (strcmp(argv[2], "noatime") == 0) --- 889,897 ---- flag = GFS_DIF_EA_INDIRECT; else if (strcmp(argv[2], "directio") == 0) flag = GFS_DIF_DIRECTIO; else if (strcmp(argv[2], "immutable") == 0) flag = GFS_DIF_IMMUTABLE; + #if 0 else if (strcmp(argv[2], "appendonly") == 0) flag = GFS_DIF_APPENDONLY; else if (strcmp(argv[2], "noatime") == 0)