| #!/bin/bash |
| |
| # Copyright 2011 Thomas Schmitt <scdbackup@gmx.net> |
| # Copyright 2011 George Danchev <danchev@spnet.net> |
| # Licensed under GNU GPL version 2 or later |
| |
| # Test the correct handling of hardlinks by xorriso options |
| # -update_r , -hardlinks perform_update , and -extract |
| # If there is support for ACLs or xattr in xorriso and on the local system, |
| # then test recording and restoring of these features. |
| |
| not_in_releng_exit() { |
| printf "\nPlease execute the tests from releng directory.\n\n" |
| exit 1 |
| } |
| |
| . inc/releng_getopts.inc || not_in_releng_exit |
| |
| print_specific_help() { |
| cat << HLP |
| Specific options: |
| none yet. |
| Overview: |
| Tests ISO image contents by performing various |
| image generation, extractions and comparisons. |
| HLP |
| } |
| |
| if test "$SPECIFIC_HELP" = 1; then |
| print_specific_help |
| exit 0 |
| fi |
| |
| if [ ! -x $RELENG_XORRISO ]; then |
| print_help |
| printf "\n${SELF}: -x absolute or relative path to binary to be run.\n\n" |
| exit 31 |
| fi |
| |
| # check data dir, if any and after checking -x xorriso |
| if [ -d "${GEN_DATA_DIR}" ]; then |
| printf "\n${SELF}: directory %s exists!" ${GEN_DATA_DIR} |
| printf "\n${SELF}: use '${SELF} -c' to remove.\n" |
| exit 8 |
| else |
| mkdir "${GEN_DATA_DIR}" |
| fi |
| |
| export xorriso=${RELENG_XORRISO} |
| export workdir=${GEN_DATA_DIR} |
| export image_file="$workdir"/xorriso_hardlinks.iso |
| export on_disk="$workdir"/xorriso_hardlinks_test_dir |
| export in_iso="" |
| export copy_on_disk="$workdir"/xorriso_hardlinks_copy_dir |
| export failure=0 |
| export simulate_failure=${SIMULATE_FAILURE} |
| export next_is_xorriso=0 |
| export next_is_rc=0 |
| export bad=0 |
| export report_about="-report_about UPDATE" |
| |
| test -z "$in_iso" && in_iso="$on_disk" |
| |
| # mkdir "$workdir" || bad=1 |
| mkdir "$on_disk" || bad=1 |
| if test "$bad" = 1 |
| then |
| echo -e "\nFAIL : ${SELF} : Test environment error : Cannot make directories" |
| exit 3 |
| fi |
| |
| |
| # All must be set at this point |
| printf "\n${SELF}: Setting up $on_disk with several hardlinks\n" >&2 |
| echo test_content >"$on_disk"/file_1 || exit 1 |
| echo test_content >"$on_disk"/file_2 || exit 1 |
| ln "$on_disk"/file_1 "$on_disk"/file_1_link_a || exit 1 |
| ln "$on_disk"/file_1 "$on_disk"/file_1_link_b || exit 1 |
| ln "$on_disk"/file_2 "$on_disk"/file_2_link_a || exit 1 |
| |
| # trivial ISO 9660 image validation routine |
| is_valid_iso9660() { |
| ISOfile="$1" |
| if ! which file >/dev/null 2>&1; then |
| printf "\nFAIL : ${SELF}: Not found: file. Please install the file(1) utility.\n" |
| failure=1 |
| return |
| fi |
| if [ ! -f ${ISOfile} ]; then |
| failure=1 |
| printf "\nFAIL : ${SELF} : Not found: ${ISOfile}\n" |
| return |
| fi |
| |
| file ${ISOfile} |
| if file ${ISOfile} | grep "ISO *9660" >/dev/null 2>&1; then |
| printf "\n${SELF}: Resulting ${ISOfile} OK. Looks like ISO 9660 filesystem.\n" |
| else |
| failure=1 |
| printf "\nFAIL : ${SELF} : ${ISOfile} DOES NOT look like ISO 9660 filesystem data.\n" |
| fi |
| } |
| |
| # Retrieve and evaluate return value of command run under return_wrapper |
| check_xorriso_return() { |
| ret=$(cat "$return_value_file") |
| rm "$return_value_file" |
| if test "$ret" = 0 |
| then |
| return 0 |
| fi |
| failure=1 |
| echo |
| echo "FAIL : ${SELF} : xorriso run exited with value $ret" |
| return 1 |
| } |
| |
| # Create test file and find out whether ACLs and/or xattr are available. |
| # |
| # Users known on GNU/Linux and FreeBSD: root games daemon man |
| # Groups : daemon games bin sshd sys |
| # On both systems, ACLs are manipulated by setfacl/getfacl |
| # |
| acl_xattr_test_file="$on_disk"/acl_xattr_test_file |
| acl_xattr_copy_file="$copy_on_disk"/acl_xattr_test_file |
| acl_xattr_test_dir="$on_disk"/acl_xattr_test_dir |
| acl_xattr_iso_dir="$in_iso"/acl_xattr_test_dir |
| acl_xattr_copy_dir="$copy_on_disk"/acl_xattr_test_dir |
| mkdir "$acl_xattr_test_dir" |
| echo echo hello world >"$acl_xattr_test_file" || exit 1 |
| sys=$(uname -s) |
| acls=no |
| default_acls=no |
| setfacl_opts="" |
| if ( setfacl -m u::rwx,g::r-x,o::---,u:root:rwx,g:sys:rwx,u:daemon:r--,mask::rwx \ |
| "$acl_xattr_test_file" ) >/dev/null 2>&1 |
| then |
| if ( getfacl "$acl_xattr_test_file" ) >/dev/null 2>&1 |
| then |
| if ( setfacl -m u::rwx,g::r-x,o::---,u:root:rwx,g:sys:rwx,u:daemon:r--,mask::rwx \ |
| "$acl_xattr_test_dir" ) >/dev/null 2>&1 |
| then |
| acls=yes |
| # Setting of "default" ACLs will fail on FreeBSD. It will nevertheless be |
| # done in the image by a xorriso command. Restoring is supposed to skip |
| # "default" ACLs if none could be recorded. |
| if setfacl -m u::rwx,g::r-x,o::---,u:root:rwx,g:sys:rwx,u:daemon:r--,mask::rwx,d:u::rwx,d:g::r-x,d:o::---,d:u:root:rwx,d:g:sys:rwx,d:u:daemon:r--,d:mask::rwx "$acl_xattr_iso_dir" 2>/dev/null |
| then |
| default_acls=yes |
| fi |
| setfacl_opts="-setfacl u::rwx,g::r-x,o::---,u:root:rwx,g:sys:rwx,u:daemon:r--,mask::rwx,d:u::rwx,d:g::r-x,d:o::---,d:u:root:rwx,d:g:sys:rwx,d:u:daemon:r--,d:mask::rwx $acl_xattr_iso_dir --" |
| fi |
| fi |
| fi |
| |
| # GNU/Linux and FreeBSD have different tools for Extended Attributes |
| xattrs=no |
| extattrs=no |
| # Try GNU/Linux style setattr/getattr |
| if ( setfattr -n user.test_xattr -v test_value "$acl_xattr_test_file" ) \ |
| >/dev/null 2>&1 |
| then |
| if ( getfattr -d "$acl_xattr_test_file" ) >/dev/null 2>&1 |
| then |
| xattrs=yes |
| setfattr -n user.long_data -v 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 "$acl_xattr_test_file" |
| setfattr -n user.more_data -v 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 "$acl_xattr_test_file" |
| fi |
| fi |
| if test "$xattrs" = no |
| then |
| # Try FreeBSD style setextattr |
| if ( setextattr user test_xattr test_value "$acl_xattr_test_file" ) \ |
| >/dev/null 2>&1 |
| then |
| if ( getextattr user test_xattr "$acl_xattr_test_file" ) >/dev/null 2>&1 |
| then |
| setextattr user long_data 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 "$acl_xattr_test_file" |
| setextattr user more_data 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 "$acl_xattr_test_file" |
| if ( lsextattr user "$acl_xattr_test_file" ) >/dev/null 2>&1 |
| then |
| extattrs=yes |
| fi |
| fi |
| fi |
| fi |
| |
| echo |
| echo "${SELF}: Detected sys='$sys' , acls=$acls , d_acls=$default_acls , xattrs=$xattrs , extattrs=$extattrs" |
| |
| # Examine capabilities of xorriso |
| xorriso_acls=no |
| xorriso_xattrs=no |
| extras=$("$xorriso" -list_extras all 2>/dev/null) |
| if test "$?" = 0 |
| then |
| if echo "$extras" | fgrep 'Local ACL : yes' >/dev/null 2>&1 |
| then |
| xorriso_acls=yes |
| fi |
| if echo "$extras" | fgrep 'Local xattr : yes' >/dev/null 2>&1 |
| then |
| xorriso_xattrs=yes |
| fi |
| fi |
| if test "$xorriso_acls" = no |
| then |
| acls=no |
| setfacl_opts= |
| fi |
| if test "$xorriso_xattrs" = no |
| then |
| xattrs=no |
| extattrs=no |
| fi |
| |
| echo "${SELF}: Detected xorriso_acls=$xorriso_acls , xorriso_xattrs=$xorriso_xattrs" |
| echo |
| ls -l "$on_disk"/* |
| |
| echo -e "\n${SELF}: Producing simple image via -o" >&2 |
| "$xorriso" -as mkisofs "$on_disk" -o "$workdir"/image_minus_o.iso |
| is_valid_iso9660 "$workdir"/image_minus_o.iso |
| |
| echo -e "\n${SELF}: Producing simple image via redirect" >&2 |
| "$xorriso" -as mkisofs "$on_disk" > "$workdir"/image_redirected.iso |
| is_valid_iso9660 "$workdir"/image_redirected.iso |
| |
| echo -e "\n${SELF}: Producing simple image via pipe" >&2 |
| return_wrapper "$xorriso" -as mkisofs "$on_disk" | \ |
| cat > "$workdir"/image_piped.iso |
| check_xorriso_return |
| is_valid_iso9660 "$workdir"/image_piped.iso |
| |
| echo -e "\n${SELF}: Producing simple image with for_backup/update_r/hardlinks" >&2 |
| "$xorriso" \ |
| $report_about \ |
| -version \ |
| -for_backup \ |
| -padding 0 \ |
| -outdev "$image_file" \ |
| -volid TEST_AUTO_ISOCONTENT \ |
| -update_r "$on_disk" "$in_iso" \ |
| $setfacl_opts \ |
| -hardlinks perform_update |
| ret=$? |
| |
| if test "$ret" -gt 0 -a "$ret" -lt 32 |
| then |
| printf "\nFAIL : ${SELF} : xorriso write run failed\n\n" |
| cleanup |
| exit 1 |
| fi |
| is_valid_iso9660 "$image_file" |
| |
| |
| # It must refuse to load and go on with -assert_volid and non-matching pattern. |
| msg=$(\ |
| "$xorriso" \ |
| -abort_on FATAL \ |
| -return_with FAILURE 32 \ |
| -assert_volid 'NON_MATCHING*' FATAL \ |
| -indev "$image_file" \ |
| 2>&1 |
| ) |
| ret=$? |
| if test "$ret" -gt 0 -a "$ret" -lt 32 |
| then |
| printf "\n${SELF}: Ok. -assert_volid snapped.\n" |
| elif test "$ret" -ne 0 |
| then |
| failure=1 |
| echo >&2 |
| echo "$msg" >&2 |
| printf "\nFAIL : ${SELF} : -assert_volid test not properly performed\n\n" |
| else |
| failure=1 |
| printf "\nFAIL : ${SELF} : -assert_volid did not snap\n\n" >&2 |
| fi |
| |
| echo -e "\n${SELF}: Copying from image to temporary disk tree" >&2 |
| "$xorriso" \ |
| $report_about \ |
| -for_backup \ |
| -assert_volid 'TEST_AUTO_ISOCONT*' FATAL \ |
| -indev "$image_file" \ |
| -osirrox on \ |
| -find "$in_iso" -exec lsdl -- \ |
| -extract "$in_iso" "$copy_on_disk" |
| ret=$? |
| if test "$ret" -gt 0 -a "$ret" -lt 32 |
| then |
| printf "\nFAIL : ${SELF} : xorriso file extraction run failed\n\n" |
| cleanup |
| exit 1 |
| fi |
| |
| if test "$simulate_failure" = 1 |
| then |
| echo -e "\n${SELF}: SIMULATING FAILURE BY REMOVING AN EXTRACTED FILE" >&2 |
| echo -e "\nFAIL : ${SELF} : Simulated failure caused by option -fail" |
| rm "$copy_on_disk"/file_1_link_b |
| fi |
| |
| |
| printf "\n${SELF}: Comparing original disk tree and temporary one..." >&2 |
| diff -r "$on_disk" "$copy_on_disk" |
| if test "$?" -ne 0 |
| then |
| echo -e "\nFAIL : ${SELF} : diff -r $on_disk $copy_on_disk reports differences" >&2 |
| echo -e "\nFAIL : ${SELF} : diff -r reports differences" |
| failure=1 |
| else |
| printf "OK" >&2 |
| fi |
| |
| printf "\n${SELF}: Checking for hardlinks being siblings...\n" |
| ls -l "$copy_on_disk"/* |
| x=$(echo $(ls -ld "$copy_on_disk"/*file* | awk '{print $2}')) |
| expected="1 3 3 3 2 2" |
| if test x"$x" = x"$expected" |
| then |
| printf "${SELF}: Checking for hardlinks being siblings done: ok.\n" >&2 |
| else |
| printf "\nFAIL : ${SELF} : Link count of extracted files is not as expected." >&2 |
| printf "\n${SELF}: Expected: $expected" >&2 |
| printf "\n${SELF}: Got : $x\n" >&2 |
| failure=1 |
| fi |
| |
| if test "$acls" = yes |
| then |
| printf "\n${SELF}: Checking ACLs ...\n" >&2 |
| acl_on_disk=$(getfacl "$acl_xattr_test_file" | grep -v '^# file:' | sort) |
| acl_in_copy=$(getfacl "$acl_xattr_copy_file" | grep -v '^# file:' | sort) |
| if test "$acl_on_disk" = "$acl_in_copy" |
| then |
| printf "${SELF}: Checking ACLs done: ok.\n" >&2 |
| else |
| printf "\nFAIL : ${SELF} : ACL mismatch between original and extracted copy\n" |
| printf "\nOriginal:\n${acl_on_disk}\n" |
| printf "\nCopy:\n${acl_in_copy}\n" |
| failure=1 |
| fi |
| fi |
| |
| if test "$xattrs" = yes |
| then |
| printf "\n${SELF}: Checking xattr via getfattr ...\n" >&2 |
| xattr_on_disk=$(getfattr "$acl_xattr_test_file" | \ |
| grep -v '^# file:' | grep -v '^$' | \sort) |
| xattr_in_copy=$(getfattr "$acl_xattr_copy_file" | |
| grep -v '^# file:' | grep -v '^$' | sort) |
| if test "$xattr_on_disk" = "$xattr_in_copy" |
| then |
| num_xattr=$(echo "$xattr_on_disk" | wc -l) |
| printf "${SELF}: Checking xattr done: $num_xattr attributes, ok.\n" >&2 |
| else |
| printf "\nFAIL : ${SELF} : xattr mismatch between original and extracted copy\n" |
| printf "\nOriginal:\n${xattr_on_disk}\n" |
| printf "\nCopy:\n${xattr_in_copy}\n" |
| failure=1 |
| fi |
| elif test "$extattrs" = yes |
| then |
| printf "\n${SELF}: Checking xattr via lsextattr and getextattr ...\n" >&2 |
| lsext_on_disk=$(lsextattr -q user "$acl_xattr_test_file") |
| xattr_on_disk=$(for i in $lsext_on_disk ; do echo $i $(getextattr -q user $i "$acl_xattr_test_file"); done | sort) |
| lsext_in_copy=$(lsextattr -q user "$acl_xattr_copy_file") |
| xattr_in_copy=$(for i in $lsext_in_copy ; do echo $i $(getextattr -q user $i "$acl_xattr_copy_file"); done | sort) |
| if test "$xattr_on_disk" = "$xattr_in_copy" |
| then |
| num_xattr=$(echo "$xattr_on_disk" | wc -l) |
| printf "${SELF}: Checking xattr done: $num_xattr attributes, ok.\n" >&2 |
| else |
| printf "\nFAIL : ${SELF} : xattr mismatch between original and extracted copy\n" |
| printf "\nOriginal:\n${xattr_on_disk}\n" |
| printf "\nCopy:\n${xattr_in_copy}\n" |
| failure=1 |
| fi |
| |
| fi |
| |
| # |
| echo |
| cleanup |
| |
| # Report result |
| echo |
| if test "$failure" = 1 |
| then |
| printf "${SELF}: FAILED" |
| echo |
| exit 1 |
| else |
| printf "${SELF}: Passed" |
| echo |
| fi |
| |
| exit 0 |