From d02a83cae0886ca07340b56396e79445d6fc936c Mon Sep 17 00:00:00 2001 From: Charles Howes Date: Mon, 2 Apr 2012 17:02:19 -0700 Subject: [PATCH] Fixed bugs, added patches from Bombich Software (Carbon Copy Cloner) --- Makefile | 4 ++ autopilot | 3 +- bbouncer | 15 +++---- copiers.d/10-rsync-apple.cp | 1 + copiers.d/60-pax.cp | 4 +- copiers.d/70-xar-apple.cp | 6 +-- copiers.d/75-xar-svn.cp | 6 +-- tests.d/00-basic-permissions.test | 12 ++++++ tests.d/20-hardlinks.test | 10 +++-- tests.d/30-resource-forks.test | 34 +++++++++++----- tests.d/40-finder-flags.test | 23 +++++------ tests.d/45-finder-locks.test | 1 - tests.d/50-creation-date.test | 1 - tests.d/60-bsd-flags.test | 1 - tests.d/70-extended-attrs.test | 60 +++++++++++++++++++++++----- tests.d/80-access-control-lists.test | 27 ++++++++++++- tests.d/90-fifo.test | 1 - tests.d/95-devices.test | 1 - tests.d/99-combo-tests.test | 6 +-- 19 files changed, 154 insertions(+), 62 deletions(-) diff --git a/Makefile b/Makefile index dc69ba4..b518ea6 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,10 @@ all: cd util && make clean: cd util && make clean +realclean: + -umount /Volumes/Src + -umount /Volumes/Dst + -rm -f Src.sparseimage Dst.sparseimage # # Developer targets. To use this: # 1. Change ./VERSION to reflect the release version diff --git a/autopilot b/autopilot index 8758fb1..3dd1378 100755 --- a/autopilot +++ b/autopilot @@ -9,10 +9,11 @@ echo "We're now going to create two disk images, create some files on one," echo "copy them to the other, and find out what metadata was preserved." echo -set -ex +set -x make ./bbouncer create-vol Src ./bbouncer create-vol Dst ./bbouncer create /Volumes/Src ./bbouncer copy -d /Volumes/Src /Volumes/Dst +#./bbouncer copy -c 16-rsync-fink -t 00-basic-permissions -d /Volumes/Src /Volumes/Dst diff --git a/bbouncer b/bbouncer index 76c47e7..04d9c08 100755 --- a/bbouncer +++ b/bbouncer @@ -110,10 +110,10 @@ read-copiers () { } create-vol () { - hdiutil create -size 40m -fs 'Journaled HFS+' \ + hdiutil create -size 130m -fs 'Journaled HFS+' \ -volname $1 -type SPARSE ./$1 hdiutil attach -owners on ./$1.sparseimage - /usr/bin/which -s fsaclctl && sudo fsaclctl -p /Volumes/$1 -e + /usr/bin/which fsaclctl > /dev/null && sudo fsaclctl -p /Volumes/$1 -e touch /Volumes/$1/bbouncer-vol } @@ -217,6 +217,8 @@ copy () { echo for c in $copiers; do cnice=${c:3} + echo + echo "--------------------------------------------" printf "Copying with: %${printWidth}s ... " "$cnice" mkdir $dst/$c bash util/copy-runner copiers.d/$c.cp $src $dst/$c @@ -225,12 +227,11 @@ copy () { # Make sure the volume can be cleaned touch $dst/$c/bbouncer-vol [ "$code" = "0" ] && echo ok \ - || echo FAIL - done - for c2 in $copiers; do + || echo FAIL/warn\? +# done +# for c2 in $copiers; do + c2=("${c[@]}") # truly, bash has quoting issues cnice=${c2:3} - echo - echo "------------------ $cnice ------------------" if [ -e $dst/$c2/skipped ]; then echo " This copier was skipped" else diff --git a/copiers.d/10-rsync-apple.cp b/copiers.d/10-rsync-apple.cp index d8e1a70..f0c3fdb 100644 --- a/copiers.d/10-rsync-apple.cp +++ b/copiers.d/10-rsync-apple.cp @@ -7,6 +7,7 @@ flags="-aH -E --rsync-path=$rsync" # Should exit with code 0 if the necessary programs exist, 1 otherwise can-copy () { test -e $rsync + false # hangs on fifo } # Should generate some text on stdout identifying which version of the diff --git a/copiers.d/60-pax.cp b/copiers.d/60-pax.cp index 3e492e7..08756ee 100644 --- a/copiers.d/60-pax.cp +++ b/copiers.d/60-pax.cp @@ -11,10 +11,10 @@ can-copy () { version () { ls -l $pax echo - echo "command = cd src; sudo $pax -rw $flags . dst" + echo "command = cd src; sudo $pax -rw -pe $flags . dst" } backup () { cd $1 - sudo $pax -rw $flags . $2 + sudo $pax -rw -pe $flags . $2 } diff --git a/copiers.d/70-xar-apple.cp b/copiers.d/70-xar-apple.cp index ba53e3b..e2ff050 100644 --- a/copiers.d/70-xar-apple.cp +++ b/copiers.d/70-xar-apple.cp @@ -13,16 +13,16 @@ version () { cd src sudo $xar -c -f tmpfile . \ && cd dst \ - && sudo $xar -x -P -f tmpfile" + && sudo $xar -x --keep-setuid -P -f tmpfile" } backup () { cd $1 # xar doesn't work with pipes yet, so we use a tmpfile - tmpfile=`mktemp -t bbouncer-xar` || exit 1 + tmpfile=`mktemp` || exit 1 # Need to use mktemp correctly! sudo $xar -c -f $tmpfile . \ && cd $2 \ - && sudo $xar -x -P -f $tmpfile + && sudo $xar -x --keep-setuid -P -f $tmpfile code=$? rm -f $tmpfile return $code diff --git a/copiers.d/75-xar-svn.cp b/copiers.d/75-xar-svn.cp index a0b08b1..d0b94ca 100644 --- a/copiers.d/75-xar-svn.cp +++ b/copiers.d/75-xar-svn.cp @@ -15,16 +15,16 @@ version () { cd src sudo $xar -c -f tmpfile . \ && cd dst \ - && sudo $xar -x -P -f tmpfile" + && sudo $xar -x --keep-setuid -P -f $tmpfile" } backup () { cd $1 # xar doesn't work with pipes yet, so we use a tmpfile - tmpfile=`mktemp -t bbouncer-xar` || exit 1 + tmpfile=`mktemp` || exit 1 # Need to use mktemp correctly! sudo $xar -c -f $tmpfile . \ && cd $2 \ - && sudo $xar -x -P -f $tmpfile + && sudo $xar -x --keep-setuid -P -f $tmpfile code=$? rm -f $tmpfile return $code diff --git a/tests.d/00-basic-permissions.test b/tests.d/00-basic-permissions.test index 3c8f150..69f11e0 100644 --- a/tests.d/00-basic-permissions.test +++ b/tests.d/00-basic-permissions.test @@ -14,7 +14,16 @@ create () { touch owned-by-me chmod 1777 owned-by-me + + touch owned-by-me-suid + chmod u+s owned-by-me-suid + + touch owned-by-me-guid + chmod g+s owned-by-me-guid + touch owned-by-me-sticky + chmod o+t owned-by-me-sticky + touch owned-by-root sudo chown root:wheel owned-by-root @@ -51,6 +60,9 @@ verify () { cd $1 compare ./owned-by-me $2/owned-by-me \ + && compare ./owned-by-me-suid $2/owned-by-me-suid \ + && compare ./owned-by-me-guid $2/owned-by-me-guid \ + && compare ./owned-by-me-sticky $2/owned-by-me-sticky \ && compare ./owned-by-root $2/owned-by-root \ && compare ./owned-by-www $2/owned-by-www \ && compare ./some-dir $2/some-dir diff --git a/tests.d/20-hardlinks.test b/tests.d/20-hardlinks.test index 32ec454..00e4c5a 100644 --- a/tests.d/20-hardlinks.test +++ b/tests.d/20-hardlinks.test @@ -10,7 +10,10 @@ create () { ln ./some-file link1 ln ./some-file link2 ln ./link1 link3 - + + touch locked_link_source + ln locked_link_source locked_link_target + chflags uchg locked_link_source # Leopard allows hard links to directories # mkdir dir1 # mkdir dir2 @@ -21,13 +24,14 @@ create () { verify () { cd $1 tmpfile=/tmp/hardlinks-test - set +e #begin-subtests stat -f "%i" link1 > $tmpfile stat -f "%i" link2 >> $tmpfile stat -f "%i" link3 >> $tmpfile - test "`uniq $tmpfile | wc -l | awk '{print $1}'`" = "1" + stat -f "%i%f" locked_link_source >> $tmpfile + stat -f "%i%f" locked_link_target >> $tmpfile + test "`uniq $tmpfile | wc -l | awk '{print $1}'`" = "2" #x1=$? #subtest "on files" $x1 diff --git a/tests.d/30-resource-forks.test b/tests.d/30-resource-forks.test index fbf554c..825b763 100644 --- a/tests.d/30-resource-forks.test +++ b/tests.d/30-resource-forks.test @@ -5,21 +5,22 @@ max_priority () { } create () { - cd $1 - set -e - echo "testing 1 2 3" > some-file - echo "Hello world" > some-file/..namedfork/rsrc + echo "testing 1 2 3" > $1/some-file + xattr-util w com.apple.ResourceFork "Hello world" $1/some-file - echo "Apple's rsync had issues with resource forks + hardlinks" > hl-rfork1 - ln hl-rfork1 hl-rfork2 - echo "Let's see what happens..." > hl-rfork1/..namedfork/rsrc + echo "Apple's rsync had issues with resource forks + hardlinks" > $1/hl-rfork1 + ln $1/hl-rfork1 $1/hl-rfork2 + xattr-util w com.apple.ResourceFork "Let's see what happens..." $1/hl-rfork1 + + # Resource forks > 64MB have to be handled specially + echo "big daddy" > $1/large_resource_fork + dd if=/dev/random of="$1/large_resource_fork"/..namedfork/rsrc bs=1000000 count=75 } compare () { - set -e # We only test regular files. Should we test others? if [ -f "$1" ]; then - cmp "$1/..namedfork/rsrc" "$2/..namedfork/rsrc" + cmp "$1"/..namedfork/rsrc "$2"/..namedfork/rsrc else true fi @@ -36,7 +37,7 @@ verify () { test -e ./some-file \ && grep -q '^testing 1 2 3$' ./some-file \ - && grep -q '^Hello world$' ./some-file/..namedfork/rsrc + && compare ./some-file $2/some-file x1=$? subtest "on files" $x1 @@ -49,7 +50,18 @@ verify () { x2=$? subtest "on hardlinked files" $x2 - alltrue $x1 $x2 + test_priority=$Important + test -e ./large_resource_fork \ + && compare ./large_resource_fork $2/large_resource_fork + x3=$? + subtest "with forks > 64MB" $x3 + + + # Truncate this file in the interests of space: + rm -f $1/large_resource_fork $1/._large_resource_fork + echo got result $x3 for this > $1/large_resource_fork + + alltrue $x1 $x2 $x3 } clean () { diff --git a/tests.d/40-finder-flags.test b/tests.d/40-finder-flags.test index 6d6ce79..8300692 100644 --- a/tests.d/40-finder-flags.test +++ b/tests.d/40-finder-flags.test @@ -45,7 +45,6 @@ max_priority () { create () { cd $1 - set -e touch type-and-creator SetFile -c MSWD -t TEXT type-and-creator @@ -67,6 +66,11 @@ create () { touch mucho-flags-file SetFile -a ABCDEIMNSTVZ mucho-flags-file + # Use every flag possible (then lock it) + touch mucho-flags-file-locked + SetFile -a ABCDEIMNSTVZ mucho-flags-file-locked + chflags uchg mucho-flags-file-locked + # All possible on a dir mkdir mucho-flags-dir SetFile -a CDEIVZ mucho-flags-dir @@ -75,18 +79,10 @@ create () { compare () { test "`GetFileInfo -P -a $1`" = "`GetFileInfo -P -a $2`" \ && test "`GetFileInfo -P -m $1`" = "`GetFileInfo -P -m $2`" - x=$? - if [ -f "$1" ]; then - test "`GetFileInfo -P -t $1`" = "`GetFileInfo -P -t $2`" \ - && test "`GetFileInfo -P -c $1`" = "`GetFileInfo -P -c $2`" - x2=$? - elif [ -d "$1" ]; then - x2=0 - else - echo "ERROR: Unknown file type in 40-finder-flags compare test" - x2=1 - fi - alltrue $x $x2 + if [ ! -d $1 ]; then + test "`GetFileInfo -P -t $1`" = "`GetFileInfo -P -t $2`" \ + && test "`GetFileInfo -P -c $1`" = "`GetFileInfo -P -c $2`" + fi } verify () { @@ -99,6 +95,7 @@ verify () { && test "`GetFileInfo -ae hidden-extension.txt`" = "1" \ && test "`GetFileInfo -as system-file`" = "1" \ && compare ./mucho-flags-file $2/mucho-flags-file \ + && compare ./mucho-flags-file-locked $2/mucho-flags-file-locked \ && compare ./mucho-flags-dir $2/mucho-flags-dir } diff --git a/tests.d/45-finder-locks.test b/tests.d/45-finder-locks.test index d75aad0..9463ef5 100644 --- a/tests.d/45-finder-locks.test +++ b/tests.d/45-finder-locks.test @@ -12,7 +12,6 @@ max_priority () { create () { cd $1 - set -e touch 'locked-file' SetFile -a L locked-file } diff --git a/tests.d/50-creation-date.test b/tests.d/50-creation-date.test index 4bbc12e..93cf273 100644 --- a/tests.d/50-creation-date.test +++ b/tests.d/50-creation-date.test @@ -6,7 +6,6 @@ max_priority () { create () { cd $1 - set -e touch creation-date-test # Make sure the creation date isn't the same as the access/modification date # The modification date from SetFile is the same as the standard mtime. diff --git a/tests.d/60-bsd-flags.test b/tests.d/60-bsd-flags.test index 381f485..a1297bd 100644 --- a/tests.d/60-bsd-flags.test +++ b/tests.d/60-bsd-flags.test @@ -33,7 +33,6 @@ max_priority () { create () { cd $1 - set -e mkdir dir-with-flags chflags uappnd,uchg,nodump,opaque dir-with-flags diff --git a/tests.d/70-extended-attrs.test b/tests.d/70-extended-attrs.test index c1b3616..4abd9e9 100644 --- a/tests.d/70-extended-attrs.test +++ b/tests.d/70-extended-attrs.test @@ -9,12 +9,16 @@ max_priority () { create () { cd $1 - set -e touch xattr-test xattr-util w message 'hello world' xattr-test xattr-util w this.that 'the other' xattr-test + touch xattr-test-locked-file + xattr-util w message 'hello world' xattr-test-locked-file + xattr-util w this.that 'the other' xattr-test-locked-file + chflags uchg xattr-test-locked-file + mkdir dir-with-xattrs xattr-util w mamma.mia 'How about a nice pizza pie?' dir-with-xattrs @@ -32,29 +36,67 @@ compare () { for a in `xattr-util l $1`; do test "`xattr-util r $a $1`" = "`xattr-util r $a $2`" || return 1 done - return 0 +} + +compare-mtime () { + test "`stat -f '%m' $1`" = "`stat -f '%m' $2`" +} + +compare-ctime () { + test "`GetFileInfo -d $1`" = "`GetFileInfo -d $2`" } verify () { cd $1 - set +e begin-subtests compare ./xattr-test $2/xattr-test x1=$? - subtest "on files" $x1 + subtest "[ on files ]" $x1 + compare-ctime ./xattr-test $2/xattr-test + x1a=$? + subtest " creation time" $x1a + compare-mtime ./xattr-test $2/xattr-test + x1b=$? + subtest " modification time" $x1b - compare ./dir-with-xattrs $2/dir-with-xattrs + + compare ./xattr-test-locked-file $2/xattr-test-locked-file x2=$? - subtest "on directories" $x2 + subtest "[ on locked files ]" $x2 + compare-ctime ./xattr-test-locked-file $2/xattr-test-locked-file + x2a=$? + subtest " creation time" $x2a + compare-mtime ./xattr-test-locked-file $2/xattr-test-locked-file + x2b=$? + subtest " modification time" $x2b + + compare ./dir-with-xattrs $2/dir-with-xattrs + x3=$? + subtest "[ on directories ]" $x3 + compare-ctime ./dir-with-xattrs $2/dir-with-xattrs + x3a=$? + subtest " creation time" $x3a + compare-mtime ./dir-with-xattrs $2/dir-with-xattrs + x3b=$? + subtest " modification time" $x3b + + test_priority=$Exhaustive compare ./symlink-with-xattrs $2/symlink-with-xattrs - x3=$? - subtest "on symlinks" $x3 + x4=$? + subtest "[ on symlinks ]" $x4 + compare-ctime ./symlink-with-xattrs $2/symlink-with-xattrs + x4a=$? + subtest " creation time" $x4a +# compare-mtime ./symlink-with-xattrs $2/symlink-with-xattrs +# x4b=$? +# subtest " modification time" $x4b + - alltrue $x1 $x2 $x3 + alltrue $x1 $x2 $x3 $x4 $x1a $x2a $x3a $x4a $x1b $x2b $x3b } clean () { diff --git a/tests.d/80-access-control-lists.test b/tests.d/80-access-control-lists.test index f08a146..e8873c8 100644 --- a/tests.d/80-access-control-lists.test +++ b/tests.d/80-access-control-lists.test @@ -6,15 +6,26 @@ max_priority () { create () { cd $1 - set -e touch acl-test chmod +a "www allow read" acl-test + chmod +a "www deny write" acl-test chmod +a "nobody allow read" acl-test + touch acl-test-locked-file + chmod +a "www allow read" acl-test-locked-file + chmod +a "www deny write" acl-test-locked-file + chmod +a "nobody allow read" acl-test-locked-file + chflags uchg acl-test-locked-file + mkdir acl-test-dir + touch acl-test-dir/test_file_before_inherited_acl_applied chmod +a "www allow read" acl-test-dir chmod +a "nobody allow read" acl-test-dir + chmod +a "nobody deny delete_child" acl-test-dir + chmod +a "staff allow list,directory_inherit,file_inherit" acl-test-dir + touch acl-test-dir/test_file_after_inherited_acl_applied + # Want these to be different from the symlink's target so we know # we're getting the right thing. @@ -47,7 +58,19 @@ verify () { # t3=$? # subtest "on symlinks" $t3 - alltrue $t1 $t2 + compare $2/acl-test-locked-file ./acl-test-locked-file + t3=$? + subtest "on locked files" $t3 + + compare $2/acl-test-dir/test_file_before_inherited_acl_applied ./acl-test-dir/test_file_before_inherited_acl_applied + t4=$? + subtest "on non-inherited acls" $t4 + + compare $2/acl-test-dir/test_file_after_inherited_acl_applied ./acl-test-dir/test_file_after_inherited_acl_applied + t5=$? + subtest "on inherited acls" $t5 + + alltrue $t1 $t2 $t3 $t4 $t5 } clean () { diff --git a/tests.d/90-fifo.test b/tests.d/90-fifo.test index 9508f9d..4b13c2b 100644 --- a/tests.d/90-fifo.test +++ b/tests.d/90-fifo.test @@ -6,7 +6,6 @@ max_priority () { create () { cd $1 - set -e mkfifo some-fifo } diff --git a/tests.d/95-devices.test b/tests.d/95-devices.test index 8191ba5..fd00a79 100644 --- a/tests.d/95-devices.test +++ b/tests.d/95-devices.test @@ -5,7 +5,6 @@ max_priority () { create () { cd $1 - set -e sudo mknod devzero c 3 3 sudo mknod devvn0 b 1 0 diff --git a/tests.d/99-combo-tests.test b/tests.d/99-combo-tests.test index 50490ed..c598c09 100644 --- a/tests.d/99-combo-tests.test +++ b/tests.d/99-combo-tests.test @@ -6,7 +6,6 @@ max_priority () { create () { cd $1 - set -e touch xattr-with-rfork echo "I love pancakes so much" > xattr-with-rfork/..namedfork/rsrc @@ -46,7 +45,9 @@ create () { compare-xattrs () { test -e $1 && \ test -e $2 && \ - test "`xattr-util l $1`" = "`xattr-util l $2`" \ + # The order in which the xattrs are listed is not guaranteed to be identical + # across filesystems, so we sort the list before comparing to avoid false negatives + test "`xattr-util l $1 | sort`" = "`xattr-util l $2 | sort`" \ || return 1 for a in `xattr-util l $1`; do test "`xattr-util r $a $1`" = "`xattr-util r $a $2`" || return 1 @@ -64,7 +65,6 @@ compare-acls () { } compare-stats () { - test -e $1 test -e $2 test "`stat -f '%u:%g:%p' $1`" = "`stat -f '%u:%g:%p' $2`" }