diff --git a/xorriso-dd-target/xorriso-dd-target b/xorriso-dd-target/xorriso-dd-target index 07df6173..983dc5e6 100755 --- a/xorriso-dd-target/xorriso-dd-target +++ b/xorriso-dd-target/xorriso-dd-target @@ -5,50 +5,70 @@ # Thomas Schmitt # Provided under GPL version 2 or later. -export LANG=C -export LC_ALL=C +# All names of variables and functions begin by "xdt_" in order to facilitate +# the re-use of this code by inclusion or forking and expansion. +# Before using most of the functions it is necessary to run +# xdt_init ; xdt_reset_job +# The only function which may be run earlier is xdt_set_lang_c . +# The function xtd_main gets run by the code at the end of this file +# if $no_xorriso_dd_target_run is empty. It implements what xdt_print_usage +# announces. -# Check whether we are on GNU/Linux -if uname -s | grep -v '^Linux' >/dev/null -then - echo "This program is entirely specialized on Linux kernel device names." >&2 - echo "Found to be on: '$(uname -s)'" >&2 - exit 2 -fi -# Accept sudo-executable commands only in well known directories. -# (Listed with increasing priority.) -lsblk_cmd= -dd_cmd= -umount_cmd= -if test "$(whoami)" = "root" -then - sudo_x_dir_list="/usr/bin /bin /usr/sbin /sbin" -else - sudo_x_dir_list="/usr/sbin /sbin /usr/bin /bin" -fi -for i in $sudo_x_dir_list -do - if test -x "$i"/lsblk - then - lsblk_cmd="$i"/lsblk - fi - if test -x "$i"/dd - then - dd_cmd="$i"/dd - fi - if test -x "$i"/umount - then - umount_cmd="$i"/umount - fi -done -if test -z "$lsblk_cmd" -then - echo "No executable program lsblk found in: $sudo_x_dir_list" >&2 - exit 5 -fi +## This obtrusive setting shall make the script safe against exotic locales. +## Supposed to stabilize grep expression interpretation and error messages. +## It is optional but highly advisable. +xdt_set_lang_c() { + export LANG=C + export LC_ALL=C + return 0 +} -print_usage() { +## This function has to be called before any real work can be done. +xdt_init() { + # Check whether we are on GNU/Linux + if uname -s | grep -v '^Linux' >/dev/null + then + echo "This program is entirely specialized on Linux kernel device names." >&2 + echo "Found to be on: '$(uname -s)'" >&2 + return 2 + fi + + # Accept sudo-executable commands only in well known directories. + # (Listed with increasing priority.) + xdt_lsblk_cmd= + xdt_dd_cmd= + xdt_umount_cmd= + if test "$(whoami)" = "root" + then + xdt_sudo_x_dir_list="/usr/bin /bin /usr/sbin /sbin" + else + xdt_sudo_x_dir_list="/usr/sbin /sbin /usr/bin /bin" + fi + for xdt_i in $xdt_sudo_x_dir_list + do + if test -x "$xdt_i"/lsblk + then + xdt_lsblk_cmd="$xdt_i"/lsblk + fi + if test -x "$xdt_i"/dd + then + xdt_dd_cmd="$xdt_i"/dd + fi + if test -x "$xdt_i"/umount + then + xdt_umount_cmd="$xdt_i"/umount + fi + done + if test -z "$xdt_lsblk_cmd" + then + echo "No executable program lsblk found in: $xdt_sudo_x_dir_list" >&2 + return 5 + fi + return 0 +} + +xdt_print_usage() { echo "usage: $0 [options] [device_name [device_name ...]]" echo echo "Looks on GNU/Linux for USB and Memory Card devices and evaluates" @@ -95,7 +115,7 @@ print_usage() { echo " -look_for_iso Demand presence of an ISO 9660 filesystem. If so," echo " any further filesystem type is acceptable on that" echo " device. Else only ISO 9660 and VFAT are accepted." - echo " -with_sudo Run '$lsblk_cmd -o FSTYPE' by sudo." + echo " -with_sudo Run '$xdt_lsblk_cmd -o FSTYPE' by sudo." echo " If no filesystems are detected and the program" echo " has no superuser power, the device is not advised." echo " If -DO_WRITE is given, run umount and dd by sudo." @@ -120,10 +140,11 @@ print_usage() { echo " $0 -with_sudo -image_file debian-live-10.0.0-amd64-xfce.iso -DO_WRITE -dummy" echo " $0 -with_sudo -image_file debian-live-10.0.0-amd64-xfce.iso -DO_WRITE -plug_test" echo + return 0 } # Roughly convert human readable sizes and plain numbers to 1 / million -round_down_div_million() { +xdt_round_down_div_million() { sed \ -e 's/^[0-9][0-9][0-9][0-9][0-9][0-9]$/0/' \ -e 's/^[0-9][0-9][0-9][0-9][0-9]$/0/' \ @@ -136,192 +157,206 @@ round_down_div_million() { -e 's/[Mm]$//' \ -e 's/[Gg]$/000/' \ -e 's/[Tt]$/000000/' + return 0 } ## Check for harmless name or number in program argument -check_parameter() { - if test "$2" = "device_name" - then - if echo "$1" | grep '[^A-Za-z0-9_/-]' >/dev/null - then - echo "SORRY: Given device name contains unexpected character. Ok: [A-za-z0-9_/-]" >&2 - exit 12 - fi - elif test "$2" = "image_file" - then - if echo "$1" | grep '[$`[*?<>|&!{\]' >/dev/null - then - echo "SORRY: Given image file name contains unexpected character. Not ok: "'[$`[*?<>|&!{\]' >&2 - exit 15 - fi - else - if echo "$1" | grep -v '^[0-9][0-9]*[0-9MGTmgt]$' >/dev/null - then - echo "SORRY: Number for $2 too short or bad character. Ok: [0-9][0-9MGTmgt]" >&2 - exit 14 - fi - fi +xdt_check_parameter() { + if test "$2" = "device_name" + then + if echo "$1" | grep '[^A-Za-z0-9_/-]' >/dev/null + then + echo "SORRY: Given device name contains unexpected character. Ok: [A-za-z0-9_/-]" >&2 + return 12 + fi + elif test "$2" = "image_file" + then + if echo "$1" | grep '[$`[*?<>|&!{\]' >/dev/null + then + echo "SORRY: Given image file name contains unexpected character. Not ok: "'[$`[*?<>|&!{\]' >&2 + return 15 + fi + else + if echo "$1" | grep -v '^[0-9][0-9]*[0-9MGTmgt]$' >/dev/null + then + echo "SORRY: Number for $2 too short or bad character. Ok: [0-9][0-9MGTmgt]" >&2 + return 14 + fi + fi + return 0 } ### Assessing arguments and setting up the job # Settings -reset_job() { - list_all= - do_list_long= - show_reasons= - look_for_iso= - devs= - devs_named= - max_size= - with_vendor_model= - with_sudo= - image_file= - do_write= - dummy_run= - dummy_force= - do_plug_test= +xdt_reset_job() { + xdt_list_all= + xdt_do_list_long= + xdt_show_reasons= + xdt_look_for_iso= + xdt_devs= + xdt_devs_named= + xdt_max_size= + xdt_with_vendor_model= + xdt_with_sudo= + xdt_image_file= + xdt_do_write= + xdt_dummy_run= + xdt_dummy_force= + xdt_do_plug_test= # Status - sudo_cmd= - have_su_power= + xdt_sudo_cmd= + xdt_have_su_power= + + return 0 } -arg_interpreter() { - next_is= - for i in "$@" - do - # The next_is option parameter readers get programmed by the -options - if test "$next_is" = "max_size" - then - check_parameter "$i" -max_size - max_size="$(echo "$i" | round_down_div_million)" - next_is= - elif test "$next_is" = "min_size" - then - check_parameter "$i" -min_size - min_size="$(echo "$i" | round_down_div_million)" - min_size="$(expr $min_size + 1)" - next_is= - elif test "$next_is" = "image_file" - then - check_parameter "$i" image_file - image_file="$i" - min_size="$(stat -c '%s' "$i" | round_down_div_million)" - if test -z "$min_size" - then - echo "FAILURE: Cannot obtain size of -image_file '$i'" >&2 - exit 13 - else - min_size="$(expr $min_size + 1)" - fi - next_is= - elif test "$i" = "-list_all" - then - list_all=y - with_vendor_model=y - show_reasons=y - elif test "$i" = "-list_long" - then - do_list_long=y - elif test "$i" = "-plug_test" - then - do_plug_test=y - elif test "$i" = "-max_size" - then - next_is="max_size" - elif test "$i" = "-min_size" - then - next_is="min_size" - elif test "$i" = "-with_vendor_model" - then - with_vendor_model=y - elif test "$i" = "-look_for_iso" - then - look_for_iso=y - elif test "$i" = "-with_sudo" - then - with_sudo=y - elif test "$i" = "-image_file" - then - next_is="image_file" - elif test "$i" = "-dummy" - then - dummy_run=y - elif test "$i" = "-dummy_force" - then - dummy_run=y - do_write=y - dummy_force=y - elif test "$i" = "-DO_WRITE" - then - do_write=y - elif test "$i" = "-help" - then - print_usage - exit 0 - elif echo "$i" | grep -v '^-' >/dev/null - then - check_parameter "$i" device_name - devs_named=y - devs="$devs $i" - show_reasons=y - else - echo "$0 : Unknown option: '$i'" >&2 - echo >&2 - echo "For a help text run: $0 -help" >&2 - exit 1 - fi - done - - # Predict superuser power. Possibly enable sudo with lsblk -o FSTYPE and dd. +## Predict superuser power. Possibly enable sudo with lsblk -o FSTYPE and dd. +xdt_predict_su_power() { if test "$(whoami)" = "root" then - have_su_power=y - elif test -n "$with_sudo" + xdt_have_su_power=y + elif test -n "$xdt_with_sudo" then echo "Testing sudo to possibly get password prompting done now:" >&2 - if sudo "$lsblk_cmd" -h >/dev/null + if sudo "$xdt_lsblk_cmd" -h >/dev/null then - echo "sudo $lsblk_cmd seems ok." >&2 + echo "sudo $xdt_lsblk_cmd seems ok." >&2 echo >&2 - sudo_cmd=sudo - have_su_power=y + xdt_sudo_cmd=sudo + xdt_have_su_power=y else - echo "FAILURE: Cannot execute program $lsblk_cmd by sudo" >&2 - exit 11 + echo "FAILURE: Cannot execute program $xdt_lsblk_cmd by sudo" >&2 + return 11 fi fi + return 0 +} + +## Sets xdt_variables according to its arguments +xdt_arg_interpreter() { + xdt_next_is= + for xdt_i in "$@" + do + # The next_is option parameter readers get programmed by the -options + if test "$xdt_next_is" = "max_size" + then + xdt_check_parameter "$xdt_i" -max_size || return "$?" + xdt_max_size="$(echo "$xdt_i" | xdt_round_down_div_million)" + xdt_next_is= + elif test "$xdt_next_is" = "min_size" + then + xdt_check_parameter "$xdt_i" -min_size || return "$?" + xdt_min_size="$(echo "$xdt_i" | xdt_round_down_div_million)" + xdt_min_size="$(expr $xdt_min_size + 1)" + xdt_next_is= + elif test "$xdt_next_is" = "image_file" + then + xdt_check_parameter "$xdt_i" image_file || return "$?" + xdt_image_file="$xdt_i" + xdt_min_size="$(stat -c '%s' "$xdt_i" \ + | xdt_round_down_div_million)" + if test -z "$xdt_min_size" + then + echo "FAILURE: Cannot obtain size of -image_file '$xdt_i'" >&2 + return 13 + else + xdt_min_size="$(expr $xdt_min_size + 1)" + fi + xdt_next_is= + elif test "$xdt_i" = "-list_all" + then + xdt_list_all=y + xdt_with_vendor_model=y + xdt_show_reasons=y + elif test "$xdt_i" = "-list_long" + then + xdt_do_list_long=y + elif test "$xdt_i" = "-plug_test" + then + xdt_do_plug_test=y + elif test "$xdt_i" = "-max_size" + then + xdt_next_is="max_size" + elif test "$xdt_i" = "-min_size" + then + xdt_next_is="min_size" + elif test "$xdt_i" = "-with_vendor_model" + then + xdt_with_vendor_model=y + elif test "$xdt_i" = "-look_for_iso" + then + xdt_look_for_iso=y + elif test "$xdt_i" = "-with_sudo" + then + xdt_with_sudo=y + elif test "$xdt_i" = "-image_file" + then + xdt_next_is="image_file" + elif test "$xdt_i" = "-dummy" + then + xdt_dummy_run=y + elif test "$xdt_i" = "-dummy_force" + then + xdt_dummy_run=y + xdt_do_write=y + xdt_dummy_force=y + elif test "$xdt_i" = "-DO_WRITE" + then + xdt_do_write=y + elif test "$xdt_i" = "-help" + then + xdt_print_usage + return 0 + elif echo "$xdt_i" | grep -v '^-' >/dev/null + then + xdt_check_parameter "$xdt_i" device_name || return "$?" + xdt_devs_named=y + xdt_devs="$xdt_devs $xdt_i" + xdt_show_reasons=y + else + echo "$0 : Unknown option: '$xdt_i'" >&2 + echo >&2 + echo "For a help text run: $0 -help" >&2 + return 16 + fi + done + xdt_predict_su_power || return "$?" + return 0 } ## Obtain a blank separated list of top-level names which do not look like ## CD, floppy, RAM dev, or loop device. -collect_devices() { - "$lsblk_cmd" -d -n -o NAME \ +xdt_collect_devices() { + "$xdt_lsblk_cmd" -d -n -o NAME \ | grep -v '^sr[0-9]' \ | grep -v '^fd[0-9]' \ | grep -v '^zram[0-9]' \ | grep -v '^loop[0-9]' \ | tr '\n\r' ' ' + return 0 } ## Let lsblk print extra info for the given devices -list_long() { - if test -z "$do_list_long" +xdt_list_long() { + if test -z "$xdt_do_list_long" then return 0 fi - $sudo_cmd "$lsblk_cmd" -o NAME,SIZE,FSTYPE,TRAN,LABEL /dev/"$1" + $xdt_sudo_cmd "$xdt_lsblk_cmd" -o NAME,SIZE,FSTYPE,TRAN,LABEL \ + /dev/"$1" echo + return 0 } ## Trying to find the desired device by watching plug-in effects -plug_in_watcher() { +xdt_plug_in_watcher() { # How long to wait for a first device to appear, how long to wait for more - wait_span_0=10 - wait_span_1=5 + xdt_wait_span_0=10 + xdt_wait_span_1=5 - found_devices= + xdt_found_devices= echo >&2 echo "Caused by option -plug_test: Attempt to find the desired device" >&2 echo "by watching it appear after being plugged in." >&2 @@ -331,260 +366,265 @@ plug_in_watcher() { echo "If it is currently plugged in, make sure to unmount all its fileystems" >&2 echo "and then unplug it." >&2 echo "Press the Enter key when ready." >&2 - read dummy - old_device_list=' '$(collect_devices)' ' + read xdt_dummy + xdt_old_device_list=' '$(xdt_collect_devices)' ' # <<< Mock-up to save USB socket wear-off by erasing items from old_device_list # <<< Their presence in new_device_list will let them appear as fresh plugs -# old_device_list=' '$(echo -n $old_device_list | sed -e 's/sdc//')' ' +# xdt_old_device_list=' '$(echo -n $xdt_old_device_list | sed -e 's/sdc//')' ' - echo "Found and noted as _not_ desired: $old_device_list" >&2 + echo "Found and noted as _not_ desired: $xdt_old_device_list" >&2 echo >&2 echo "Step 2:" >&2 echo "Please plug in the desired target device and then press the Enter key." >&2 - read dummy - echo -n "Waiting up to $wait_span_0 seconds for a new device to be listed ..." >&2 - end_time="$(expr $(date +'%s') + "$wait_span_0")" - while test $(date +'%s') -le "$end_time" + read xdt_dummy + echo -n "Waiting up to $xdt_wait_span_0 seconds for a new device to be listed ..." >&2 + xdt_end_time="$(expr $(date +'%s') + "$xdt_wait_span_0")" + while test $(date +'%s') -le "$xdt_end_time" do - new_device_list=' '$(collect_devices)' ' - for i in $new_device_list + xdt_new_device_list=' '$(xdt_collect_devices)' ' + for xdt_i in $xdt_new_device_list do - if echo "$old_device_list $found_devices " | grep -F -v ' '"$i"' ' >/dev/null + if echo "$xdt_old_device_list $xdt_found_devices " \ + | grep -F -v ' '"$xdt_i"' ' >/dev/null then - echo " found: $i" >&2 - found_devices="$found_devices $i" - end_time=$(expr $(date +'%s') + "$wait_span_1") - echo -n "Now waiting $wait_span_1 seconds to let it settle ..." >&2 + echo " found: $xdt_i" >&2 + xdt_found_devices="$xdt_found_devices $xdt_i" + xdt_end_time=$(expr $(date +'%s') + "$xdt_wait_span_1") + echo -n "Now waiting $xdt_wait_span_1 seconds to let it settle ..." >&2 fi done sleep 1 echo -n '.' >&2 done echo >&2 - if test -z "$found_devices" + if test -z "$xdt_found_devices" then echo "SORRY: No new candidate device was found." >&2 return 8 fi - num=$(echo $found_devices | wc -w) - if test "$num" -gt 1 + xdt_num=$(echo $xdt_found_devices | wc -w) + if test "$xdt_num" -gt 1 then - echo "SORRY: More than one new candidate device appeared: $found_devices" >&2 + echo "SORRY: More than one new candidate device appeared: $xdt_found_devices" >&2 return 9 fi - echo "Found and noted as desired device: $found_devices" >&2 - if test -n "$devs" + echo "Found and noted as desired device: $xdt_found_devices" >&2 + if test -n "$xdt_devs" then - echo "(-plug_test is overriding device list given by arguments: $devs )" >&2 + echo "(-plug_test is overriding device list given by arguments: $xdt_devs )" >&2 fi - if test -n "$list_all" + if test -n "$xdt_list_all" then echo "(-plug_test is overriding -list_all)" >&2 - list_all= + xdt_list_all= fi - devs_named=y - with_vendor_model=y - show_reasons=y - devs=$(echo -n $found_devices) + xdt_devs_named=y + xdt_with_vendor_model=y + xdt_show_reasons=y + xdt_devs=$(echo -n $xdt_found_devices) echo >&2 return 0 } ## Evaluation of available devices and suitability -list_devices() { - if test -n "$list_all" +xdt_list_devices() { + if test -n "$xdt_list_all" then - devs= + xdt_devs= fi - if test -z "$devs" + if test -z "$xdt_devs" then # Obtain list of top-level names which do not look like CD, floppy, RAM dev - devs=$(collect_devices) + xdt_devs=$(xdt_collect_devices) fi - - not_advised=0 - for name in $devs + + xdt_not_advised=0 + for xdt_name in $xdt_devs do # Collect reasons - yucky= - reasons= - good_trans= - good_fs= - bad_trans= - bad_fs= + xdt_yucky= + xdt_reasons= + xdt_good_trans= + xdt_good_fs= + xdt_bad_trans= + xdt_bad_fs= # Unwanted device name patterns - if (echo "$name" | grep '^sd[a-z][1-9]' >/dev/null) \ - || (echo "$name" | grep '^mmcblk.*p[0-9]' >/dev/null) \ - || (echo "$name" | grep '^nvme.*p[0-9]' >/dev/null) + if (echo "$xdt_name" | grep '^sd[a-z][1-9]' >/dev/null) \ + || (echo "$xdt_name" | grep '^mmcblk.*p[0-9]' >/dev/null) \ + || (echo "$xdt_name" | grep '^nvme.*p[0-9]' >/dev/null) then - yucky=y - reasons="${reasons}looks_like_disk_partition- " - elif echo "$name" | grep '^sr[0-9]' >/dev/null + xdt_yucky=y + xdt_reasons="${xdt_reasons}looks_like_disk_partition- " + elif echo "$xdt_name" | grep '^sr[0-9]' >/dev/null then - yucky=y - reasons="${reasons}looks_like_cd_drive- " - elif echo "$name" | grep '^fd[0-9]' >/dev/null + xdt_yucky=y + xdt_reasons="${xdt_reasons}looks_like_cd_drive- " + elif echo "$xdt_name" | grep '^fd[0-9]' >/dev/null then - yucky=y - reasons="${reasons}looks_like_floppy- " - elif echo "$name" | grep '^loop[0-9]' >/dev/null + xdt_yucky=y + xdt_reasons="${xdt_reasons}looks_like_floppy- " + elif echo "$xdt_name" | grep '^loop[0-9]' >/dev/null then - yucky=y - reasons="${reasons}looks_like_loopdev- " - elif echo "$name" | grep '^zram[0-9]' >/dev/null + xdt_yucky=y + xdt_reasons="${xdt_reasons}looks_like_loopdev- " + elif echo "$xdt_name" | grep '^zram[0-9]' >/dev/null then - yucky=y - reasons="${reasons}looks_like_ramdev- " + xdt_yucky=y + xdt_reasons="${xdt_reasons}looks_like_ramdev- " fi # >>> recognize the device from which Debian Live booted # Connection type. Normally by lsblk TRAN, but in case of mmcblk artificial. - if echo "$name" | grep '^mmcblk[0-9]' >/dev/null + if echo "$xdt_name" | grep '^mmcblk[0-9]' >/dev/null then - transports="mmcblk" - elif echo "$name" | grep -F "/" >/dev/null + xdt_transports="mmcblk" + elif echo "$xdt_name" | grep -F "/" >/dev/null then - transports=not_an_expected_name - reasons="${reasons}name_with_slash- " + xdt_transports=not_an_expected_name + xdt_reasons="${xdt_reasons}name_with_slash- " else - transports=$("$lsblk_cmd" -n -o TRAN /dev/"$name") + xdt_transports=$("$xdt_lsblk_cmd" -n -o TRAN /dev/"$xdt_name") fi - for trans in $transports + for xdt_trans in $xdt_transports do - if test "$trans" = "usb" -o "$trans" = "mmcblk" + if test "$xdt_trans" = "usb" -o "$xdt_trans" = "mmcblk" then - good_trans="${trans}+" - elif test -n "$trans" + xdt_good_trans="${xdt_trans}+" + elif test -n "$xdt_trans" then - bad_trans="$trans" - yucky=y - if test "$transports" = "not_an_expected_name" + xdt_bad_trans="$xdt_trans" + xdt_yucky=y + if test "$xdt_transports" = "not_an_expected_name" then - dummy=dummy + xdt_dummy=dummy else - if echo "$reasons" | grep -F -v "not_usb" >/dev/null + if echo "$xdt_reasons" | grep -F -v "not_usb" >/dev/null then - reasons="${reasons}not_usb- " + xdt_reasons="${xdt_reasons}not_usb- " fi fi fi done - if test -z "$good_trans" -a -z "$bad_trans" + if test -z "$xdt_good_trans" -a -z "$xdt_bad_trans" then - yucky=y - reasons="${reasons}no_bus_info- " - elif test -z "$bad_trans" + xdt_yucky=y + xdt_reasons="${xdt_reasons}no_bus_info- " + elif test -z "$xdt_bad_trans" then - reasons="${reasons}$good_trans " + xdt_reasons="${xdt_reasons}$xdt_good_trans " fi # Wanted or unwanted filesystem types - fstypes=$($sudo_cmd "$lsblk_cmd" -n -o FSTYPE /dev/"$name") + xdt_fstypes=$($xdt_sudo_cmd "$xdt_lsblk_cmd" -n -o FSTYPE \ + /dev/"$xdt_name") if test "$?" -gt 0 then - fstypes="lsblk_fstype_error" + xdt_fstypes="lsblk_fstype_error" fi # Get overview of filesystems - has_iso= - has_vfat= - has_other= - for fstype in $fstypes + xdt_has_iso= + xdt_has_vfat= + xdt_has_other= + for xdt_fstype in $xdt_fstypes do - if test "$fstype" = "iso9660" + if test "$xdt_fstype" = "iso9660" then - has_iso=y - if echo "$good_fs" | grep -F -v "has_$fstype" >/dev/null + xdt_has_iso=y + if echo "$xdt_good_fs" | grep -F -v "has_$xdt_fstype" >/dev/null then - good_fs="${good_fs}has_${fstype}+ " + xdt_good_fs="${xdt_good_fs}has_${xdt_fstype}+ " fi - elif test "$fstype" = "vfat" + elif test "$xdt_fstype" = "vfat" then - has_vfat=y - if echo "$good_fs" | grep -F -v "has_$fstype" >/dev/null + xdt_has_vfat=y + if echo "$xdt_good_fs" | grep -F -v "has_$xdt_fstype" >/dev/null then - good_fs="${good_fs}has_${fstype}+ " + xdt_good_fs="${xdt_good_fs}has_${xdt_fstype}+ " fi - elif test -n "$fstype" + elif test -n "$xdt_fstype" then - has_other=y - if echo "$bad_fs" | grep -F -v "has_$fstype" >/dev/null + xdt_has_other=y + if echo "$xdt_bad_fs" | grep -F -v "has_$xdt_fstype" >/dev/null then - bad_fs="${bad_fs}has_${fstype}- " + xdt_bad_fs="${xdt_bad_fs}has_${xdt_fstype}- " fi fi done # Decide whether the found filesystems look dispensible enough - reasons="${reasons}${good_fs}${bad_fs}" - if test "${bad_fs}${good_fs}" = "" -a -z "$have_su_power" + xdt_reasons="${xdt_reasons}${xdt_good_fs}${xdt_bad_fs}" + if test "${xdt_bad_fs}${xdt_good_fs}" = "" \ + -a -z "$xdt_have_su_power" then - yucky=y - reasons="${reasons}no_fs_while_not_su- " - elif test -n "$look_for_iso" + xdt_yucky=y + xdt_reasons="${xdt_reasons}no_fs_while_not_su- " + elif test -n "$xdt_look_for_iso" then - if test -n "$has_iso" + if test -n "$xdt_has_iso" then - reasons="${reasons}look_for_iso++ " + xdt_reasons="${xdt_reasons}look_for_iso++ " else - yucky=y - reasons="${reasons}no_iso9660- " + xdt_yucky=y + xdt_reasons="${xdt_reasons}no_iso9660- " fi - elif test -n "$has_other" + elif test -n "$xdt_has_other" then - yucky=y + xdt_yucky=y fi # Optional tests for size - if test -n "$max_size" -o -n "$min_size" + if test -n "$xdt_max_size" -o -n "$xdt_min_size" then - size=$("$lsblk_cmd" -n -b -o SIZE /dev/"$name" | head -1 | round_down_div_million) - if test -z "$size" + xdt_size=$("$xdt_lsblk_cmd" -n -b -o SIZE /dev/"$xdt_name" \ + | head -1 | xdt_round_down_div_million) + if test -z "$xdt_size" then - yucky=y - reasons="${reasons}lsblk_no_size- " + xdt_yucky=y + xdt_reasons="${xdt_reasons}lsblk_no_size- " fi fi - if test -n "$max_size" -a -n "$size" + if test -n "$xdt_max_size" -a -n "$xdt_size" then - if test "$size" -gt "$max_size" + if test "$xdt_size" -gt "$xdt_max_size" then - yucky=y - reasons="${reasons}size_too_large- " + xdt_yucky=y + xdt_reasons="${xdt_reasons}size_too_large- " fi fi - if test -n "$min_size" -a -n "$size" + if test -n "$xdt_min_size" -a -n "$xdt_size" then - if test "$size" -lt "$min_size" + if test "$xdt_size" -lt "$xdt_min_size" then - yucky=y - reasons="${reasons}size_too_small- " + xdt_yucky=y + xdt_reasons="${xdt_reasons}size_too_small- " fi fi # Now decide overall and report - descr= - if test -n "$with_vendor_model" + xdt_descr= + if test -n "$xdt_with_vendor_model" then - descr=": "$("$lsblk_cmd" -n -o VENDOR,MODEL /dev/"$name" | tr '\n\r' ' ' | tr -s ' ') + xdt_descr=": "$("$xdt_lsblk_cmd" -n -o VENDOR,MODEL \ + /dev/"$xdt_name" | tr '\n\r' ' ' | tr -s ' ') fi - if test -n "$yucky" + if test -n "$xdt_yucky" then - if test -n "$show_reasons" + if test -n "$xdt_show_reasons" then - echo "$name : NO : $reasons$descr" - list_long "$name" + echo "$xdt_name : NO : $xdt_reasons$xdt_descr" + xdt_list_long "$xdt_name" fi - not_advised=1 + xdt_not_advised=1 else - if test -n "$show_reasons" + if test -n "$xdt_show_reasons" then - echo "$name : YES : $reasons$descr" - list_long "$name" + echo "$xdt_name : YES : $xdt_reasons$xdt_descr" + xdt_list_long "$xdt_name" else - echo "$name" + echo "$xdt_name" fi fi done @@ -592,212 +632,233 @@ list_devices() { } ## Puts list of mounted (sub-)devices of $1 into $mounted_devs -list_mounted_of() { - partitions=$("$lsblk_cmd" -l -n -p -o NAME /dev/"$1" \ - | grep -v '^'/dev/"$1"'$' \ - | tr '\n\r' ' ') - mounted_devs= - for i in /dev/"$1" $partitions +xdt_list_mounted_of() { + xdt_partitions=$("$xdt_lsblk_cmd" -l -n -p -o NAME /dev/"$1" \ + | grep -v '^'/dev/"$1"'$' \ + | tr '\n\r' ' ') + xdt_mounted_devs= + for xdt_i in /dev/"$1" $xdt_partitions do # Show the found mount lines and add their device paths to list - mount_line=$(mount | grep '^'"$i"' ') - if test -n "$mount_line" + xdt_mount_line=$(mount | grep '^'"$xdt_i"' ') + if test -n "$xdt_mount_line" then - echo " $mount_line" - mounted_devs="$mounted_devs $i" + echo " $xdt_mount_line" + xdt_mounted_devs="$xdt_mounted_devs $xdt_i" fi done + return 0 +} + +## Unmount xdt_mounted_devs (maybe filled by xdt_list_mounted_of) +xdt_unmount() { + if test -z "$xdt_mounted_devs" + then + return 0 + fi + + for xdt_i in $xdt_mounted_devs + do + if test -n "$xdt_dummy_run" + then + echo " $xdt_sudo_cmd $xdt_umount_cmd $xdt_i" + elif $xdt_sudo_cmd "$xdt_umount_cmd" "$xdt_i" + then + echo "Unmounted: $xdt_i" + else + echo "FAILURE: Non-zero exit value with: $xdt_sudo_cmd $xdt_umount_cmd $xdt_i" >&2 + return 7 + fi + done + + # Check again if any mount points still exist + if test -z "$xdt_dummy_run" + then + xdt_list_mounted_of "$2" + if test -n "$xdt_mounted_devs" + then + echo "FAILURE: $xdt_sudo_cmd $xdt_umount_cmd could not remove all mounts: $xdt_mounted_devs" >&2 + return 7 + fi + fi + return 0 } ## Does the work of unmounting and dd-ing -write_image() { +xdt_write_image() { - if test -z "$umount_cmd" + if test -z "$xdt_umount_cmd" then - echo "No executable program umount found in: $sudo_x_dir_list" >&2 + echo "No executable program umount found in: $xdt_sudo_x_dir_list" >&2 return 6 fi echo "Looking for mount points of $2:" - mounted_devs= - list_mounted_of "$2" + xdt_mounted_devs= + xdt_list_mounted_of "$2" - if test -n "$dummy_force" + if test -n "$xdt_dummy_force" then echo "AGAINST THE ADVICE BY THIS PROGRAM, a daring user could do:" - dummy_run=y - elif test -n "$dummy_run" + xdt_dummy_run=y + elif test -n "$xdt_dummy_run" then echo "Would do if not -dummy:" fi - if test -n "$mounted_devs" - then - for i in $mounted_devs - do - if test -n "$dummy_run" - then - echo " $sudo_cmd $umount_cmd $i" - else - if $sudo_cmd "$umount_cmd" "$i" - then - echo "Unmounted: $i" - else - echo "FAILURE: Non-zero exit value with: $sudo_cmd $umount_cmd $i" >&2 - return 7 - fi - fi - done - # Check again if any mount points still exist - if test -z "$dummy_run" - then - list_mounted_of "$2" - if test -n "$mounted_devs" - then - echo "FAILURE: $sudo_cmd $umount_cmd could not remove all mounts: $mounted_devs" >&2 - return 7 - fi - fi - fi + xdt_unmount || return "$?" - if test -z "$dd_cmd" + if test -z "$xdt_dd_cmd" then - echo "No executable program dd found in: $sudo_x_dir_list" >&2 + echo "No executable program dd found in: $xdt_sudo_x_dir_list" >&2 return 6 fi - if test -n "$dummy_run" + if test -n "$xdt_dummy_run" then - echo " $sudo_cmd $dd_cmd if='${1}' bs=1M of=/dev/'${2}' ; sync" + echo " $xdt_sudo_cmd $xdt_dd_cmd if='${1}' bs=1M of=/dev/'${2}' ; sync" else echo "Performing:" - echo " $sudo_cmd $dd_cmd if='${1}' bs=1M of=/dev/'${2}' ; sync" - $sudo_cmd "$dd_cmd" if="${1}" bs=1M of=/dev/"${2}" - ret="$?" + echo " $xdt_sudo_cmd $xdt_dd_cmd if='${1}' bs=1M of=/dev/'${2}' ; sync" + $xdt_sudo_cmd "$xdt_dd_cmd" if="${1}" bs=1M of=/dev/"${2}" + xdt_ret="$?" sync - if test "$ret" -ne 0 + if test "$xdt_ret" -ne 0 then - echo "FAILURE: $sudo_cmd $dd_cmd was not successful" >&2 + echo "FAILURE: $xdt_sudo_cmd $xdt_dd_cmd was not successful" >&2 return 18 fi fi # >>> ??? Erase possible GPT backup table at end of device ? - if test -n "$dummy_force" + if test -n "$xdt_dummy_force" then echo "BE SMART. BE CAUTIOUS. BEWARE." fi return 0 } -# main() - -reset_job -arg_interpreter "$@" - -if test -n "$do_plug_test" -then - plug_in_watcher - ret=$? - if test "$ret" -ne 0 - then - exit $ret - fi -fi - -list_devices -if test -n "$list_all" -then - dummy=dummy -elif test -n "$do_write" -then - with_vendor_model= - show_reasons= - candidates=$(list_devices | tr '\n\r' ' ') - num_cand=$(echo $candidates | wc -w) - num_devs=$(echo $devs| wc -w) - if test -n "$dummy_force" -a "$num_devs" -ne 1 +## Inspects the result of listing, decides whether writing is advisable, +## and starts the write run +xdt_decide_writing() +{ + xdt_with_vendor_model= + xdt_show_reasons= + xdt_candidates=$(xdt_list_devices | tr '\n\r' ' ') + xdt_num_cand=$(echo $xdt_candidates | wc -w) + xdt_num_devs=$(echo $xdt_devs| wc -w) + if test -n "$xdt_dummy_force" -a "$xdt_num_devs" -ne 1 then echo "SORRY: Refusing -dummy_force with not exactly one device given." >&2 - exit 10 + return 10 fi - if test -n "$dummy_force" -a -n "$dummy_run" -a "$num_cand" -ne 1 + if test -n "$xdt_dummy_force" -a -n "$xdt_dummy_run" \ + -a "$xdt_num_cand" -ne 1 then # -dummy_force in a situation where the program would normally refuse echo echo "Overriding any advice because of -dummy_force" - candidates="$devs" - num_cand=1 - elif test -n "$dummy_force" + xdt_candidates="$xdt_devs" + xdt_num_cand=1 + elif test -n "$xdt_dummy_force" then # Downgrade -dummy_force to -dummy in order to avoid the ugly warning - dummy_force= - dummy_run=y + xdt_dummy_force= + xdt_dummy_run=y fi - if test "$num_cand" -eq 1 + if test "$xdt_num_cand" -eq 1 then - if test -n "$image_file" + if test -n "$xdt_image_file" then - if test -n "$do_plug_test" + if test -n "$xdt_do_plug_test" then echo >&2 echo "Step 3:" >&2 - if test -n "$dummy_run" + if test -n "$xdt_dummy_run" then echo "This would be the last chance to abort. Enter the word 'yes' to see -dummy report." >&2 else echo "Last chance to abort. Enter the word 'yes' to start REAL WRITING." >&2 fi - read dummy - if test "$dummy" = "yes" -o "$dummy" = "'yes'" -o "$dummy" = '"yes"' + read xdt_dummy + if test "$xdt_dummy" = "yes" -o "$xdt_dummy" = "'yes'" \ + -o "$xdt_dummy" = '"yes"' then - dummy=dummy + xdt_dummy=dummy else - echo "WRITE RUN PREVENTED by user input '$dummy'." >&2 - exit 12 + echo "WRITE RUN PREVENTED by user input '$xdt_dummy'." >&2 + return 17 fi fi - write_image "$image_file" $candidates - exit $? + xdt_write_image "$xdt_image_file" $xdt_candidates || return "$?" else - candidates=$(echo $candidates) - if test -n "$dummy_run" + xdt_candidates=$(echo $xdt_candidates) + if test -n "$xdt_dummy_run" then - echo "Would simulate writing to /dev/$candidates if an -image_file were given." + echo "Would simulate writing to /dev/$xdt_candidates if an -image_file were given." else - echo "Would write to /dev/$candidates if an -image_file were given." + echo "Would write to /dev/$xdt_candidates if an -image_file were given." fi - exit 0 + return 0 fi - elif test "$num_cand" -gt 1 + elif test "$xdt_num_cand" -gt 1 then echo "WILL NOT WRITE ! More than one candidate found for target device:" >&2 - show_reasons=y - with_vendor_model=y - devs="$candidates" - list_devices >&2 + xdt_show_reasons=y + xdt_with_vendor_model=y + xdt_devs="$xdt_candidates" + xdt_list_devices >&2 echo "HINT: Unplug the unwanted devices from the machine," >&2 echo " or work with option -plug_test," >&2 - echo " or add the desired name out of {$(echo $candidates | sed -e 's/ /,/g')} as additional argument." >&2 - exit 3 + echo " or add the desired name out of {$(echo $xdt_candidates | sed -e 's/ /,/g')} as additional argument." >&2 + return 3 else - if test -n "$devs_named" + if test -n "$xdt_devs_named" then echo "NO CANDIDATE FOR TARGET DEVICE AMONG THE GIVEN NAMES !" >&2 else echo "NO CANDIDATE FOR TARGET DEVICE FOUND !" >&2 fi echo "Overall available devices:" >&2 - list_all=y - list_long= - show_reasons=y - with_vendor_model=y - list_devices >&2 - exit 4 + xdt_list_all=y + xdt_list_long= + xdt_show_reasons=y + xdt_with_vendor_model=y + xdt_list_devices >&2 + return 4 fi -fi + return 0 +} -if test -n "$devs" +## The main function which runs the others in standalone mode +xdt_main() +{ + xdt_set_lang_c + xdt_init || return "$?" + + xdt_reset_job + xdt_arg_interpreter "$@" || return "$?" + + if test -n "$xdt_do_plug_test" + then + xdt_plug_in_watcher || return "$?" + fi + + xdt_list_devices || return "$?" + + if test -z "$xdt_list_all" -a -n "$xdt_do_write" + then + xdt_decide_writing || return "$?" + fi + + if test -n "$xdt_devs" + then + return $xdt_not_advised + fi + return 0 +} + +if test -z "$no_xorriso_dd_target_run" then - exit $not_advised + xdt_main "$@" || exit "$?" fi