#!/bin/sh DIRS="foo foo-bound foo-bound-ro" set -e function do_umount { echo -n unmounting... ( umount foo || true; umount foo-bound || true; umount foo-bound-ro || true; ) 2> /dev/null echo done true } trap do_umount ERR trap do_umount INT # just in case the last invocation left them do_umount function should_fail { eval "$@" > /dev/null 2>&1 \ && ( echo BAD: unexpected success: "$@" ; false) \ || echo GOOD: expected failure: "$@"; } function should_succeed { eval "$@" > /dev/null 2>&1 2>&1 \ && echo GOOD: expected success: "$@" \ || ( echo \ BAD: unexpected failure: "$@"; false) } function should_fail_ro { RO=$1 shift if $RO; then should_fail "$@" else should_succeed "$@" fi } function testdir { RO=$1 shift; i=$1 should_fail_ro $RO touch $i/$i-file should_fail_ro $RO echo foo '>' $i/$i-file should_fail_ro $RO echo foo '>>' $i/$i-file should_fail_ro $RO mkdir $i/$i-dir should_fail_ro $RO mknod $i/$i-null-chardev c 1 3 should_fail_ro $RO chmod 777 $i/$i-null-chardev chattrs $RO $i } function getattr { lsattr -d -v "$1" | awk '{print $1, $2}' } function attr_changed { [ "$2" != "$3" ] } CHECK_XATTRS=true; function chattrs { $CHECK_XATTRS || return 0 RO="$1" file="$2" # chattr exits with a 0 code if the files # don't exist, so don't even bother running if ! [ -e "$file" ]; then return fi ORIG_ATTR="$(getattr "$file")" if [ -z "$ORIG_ATTR" ]; then echo invalid attributes: "'$ORIG_ATTR'" exit 1; fi ( chattr -v 4 $file; chattr +ADdiS $file ) > /dev/null 2>&1 # xfs does not support all of these: # chattr +ADdijsSu $file ) > /dev/null 2>&1 NEW_ATTR="$(getattr "$file")" should_fail_ro $RO attr_changed $file "'$ORIG_ATTR'" "'$NEW_ATTR'" chattr = $file > /dev/null 2>&1 } for i in $DIRS; do rm -r ./$i > /dev/null 2>&1 || true mkdir -p $i; done; if [ -z "$*" ]; then FSTYPES="ext3" else FSTYPES="$*" fi for fstype in $FSTYPES; do image=$fstype.img #echo creating image: $image... #dd if=/dev/zero of=$image bs=$((1<<20)) count=32 2>&1 | grep transferred OPTS="-F" MOUNT_OPTS="-o loop" MKFS="true" if [ "$fstype" == "reiserfs" ]; then OPTS="-f --journal-size 513 -q" MOUNT_OPTS="$MOUNT_OPTS,rw,noatime,nodiratime,user_xattr,attrs" elif [ "$fstype" == "jfs" ]; then OPTS="-f" elif [ "$fstype" == "ramfs" ]; then MKFS="false" OPTS="" elif [ "$fstype" == "nfs" ]; then MKFS="false" OPTS="" image="localhost:/home" MOUNT_OPTS="" CHECK_XATTRS=false; elif [ "$fstype" == "xfs" ]; then OPTS="" fi if $MKFS; then echo -n creating $fstype fs in image: $image... mkfs.$fstype $OPTS $image > /dev/null 2>&1 echo done "($?)" fi echo mount -t $fstype $MOUNT_OPTS $image foo mount -t $fstype $MOUNT_OPTS $image foo mount --bind foo foo-bound/ || exit mount --bind foo foo-bound-ro || exit mount -o remount,ro foo-bound-ro || exit testdir false foo testdir false foo-bound testdir true foo-bound-ro if false; then should_succeed echo foo > foo-bound/foo-null-chardev should_succeed echo foo > foo-bound-ro/foo-null-chardev should_succeed echo foo >> foo-bound/foo-null-chardev should_succeed echo foo >> foo-bound-ro/foo-null-chardev for i in foo-bound-ro/foo-dir \ foo-bound-ro/foo-file ; do should_fail chmod 777 $i should_fail chown nobody $i should_succeed ls $i should_succeed cat $i \> /dev/null chattrs true $i done should_fail rmdir foo-bound-ro/foo-dir fi should_succeed mount -o remount,ro foo-bound/ should_succeed umount foo-bound should_succeed umount foo-bound-ro should_succeed umount foo done