"Fossies" - the Fresh Open Source Software Archive

Member "libisoburn-1.5.4/xorriso-dd-target/xorriso-dd-target" (30 Jan 2021, 29581 Bytes) of package /linux/misc/libisoburn-1.5.4.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Bash source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 #!/bin/sh
    2 
    3 # Copyright (c) 2019 - 2021
    4 # Nio Wiklund alias sudodus <nio dot wiklund at gmail dot com>
    5 # Thomas Schmitt <scdbackup@gmx.net>
    6 # Provided under GPL version 2 or later.
    7 
    8 # All names of variables and functions begin by "xdt_" in order to facilitate
    9 # the re-use of this code by inclusion or forking and expansion.
   10 # Before using most of the functions it is necessary to run
   11 #   xdt_init ; xdt_reset_job 
   12 # The only function which may be run earlier is xdt_set_lang_c .
   13 # The function xtd_main gets run by the code at the end of this file
   14 # if $no_xorriso_dd_target_run is empty. It implements what xdt_print_usage
   15 # announces.
   16 
   17 xdt_print_version() {
   18   echo "xorriso-dd-target , version 1.5.4 , 2021.01.30.150001"
   19 }
   20 
   21 
   22 ## This obtrusive setting shall make the script safe against exotic locales.
   23 ## Supposed to stabilize grep expression interpretation and error messages.
   24 ## It is optional but highly advisable.
   25 xdt_set_lang_c() {
   26   export LANG=C
   27   export LC_ALL=C
   28   return 0
   29 }
   30 
   31 ## This function has to be called before any real work can be done.
   32 xdt_init() {
   33   # Check whether we are on GNU/Linux
   34   if uname -s | grep -v '^Linux' >/dev/null
   35   then
   36     echo "This program is entirely specialized on Linux kernel device names." >&2
   37     echo "Found to be on: '$(uname -s)'" >&2
   38     return 2
   39   fi
   40 
   41   # Accept sudo-executable commands only in well known directories.
   42   # (Listed with increasing priority.)
   43   xdt_lsblk_cmd=
   44   xdt_dd_cmd=
   45   xdt_umount_cmd=
   46   if test "$(whoami)" = "root"
   47   then
   48     xdt_sudo_x_dir_list="/usr/bin /bin /usr/sbin /sbin"
   49   else
   50     xdt_sudo_x_dir_list="/usr/sbin /sbin /usr/bin /bin"
   51   fi
   52   for xdt_i in $xdt_sudo_x_dir_list
   53   do
   54     if test -x "$xdt_i"/lsblk
   55     then
   56       xdt_lsblk_cmd="$xdt_i"/lsblk
   57     fi
   58     if test -x "$xdt_i"/dd
   59     then
   60       xdt_dd_cmd="$xdt_i"/dd
   61     fi
   62     if test -x "$xdt_i"/umount
   63     then
   64       xdt_umount_cmd="$xdt_i"/umount
   65     fi
   66   done
   67   if test -z "$xdt_lsblk_cmd"
   68   then
   69     echo "No executable program lsblk found in: $xdt_sudo_x_dir_list" >&2
   70     return 5
   71   fi
   72   return 0
   73 }
   74 
   75 xdt_print_usage() {
   76   echo "usage:  $0 [options] [device_name [device_name ...]]"
   77   echo
   78   echo "Looks on GNU/Linux for USB and Memory Card devices and evaluates"
   79   echo "whether the found devices are plausible targets for image copying."
   80   echo "If no device names and no -list_all are given, then a plain list of"
   81   echo "advisable device names is printed to stdout. One per line."
   82   echo "Device names must not begin by '-' and must be single words. They must"
   83   echo "not begin by '/dev/'. E.g. 'sdc' is valid, '/dev/sdc' is not valid."
   84   echo "If device names are given, then they get listed with advice shown."
   85   echo "If one of the given device names gets not advised, the exit value is 1."
   86   echo
   87   echo "The option -plug_test can determine the desired target device by"
   88   echo "inquiring the system with unplugged device and then with plugged one."
   89   echo
   90   echo "Only if option -DO_WRITE is given and -list_all is not, and if exactly"
   91   echo "one advisable device is listed, it really gets overwritten by the"
   92   echo "file content of the given -image_file. In this case the exit value"
   93   echo "is zero if writing succeeded, non-zero else."
   94   echo "Option -dummy prevents this kind of real action and rather shows the"
   95   echo "unmount and write commands on stdout."
   96   echo
   97   echo "Options:"
   98   echo " -plug_test         Find the target device by asking the user to press"
   99   echo "                    Enter when the desired target is _not_ plugged in,"
  100   echo "                    to then plug it in, and to press Enter again."
  101   echo "                    This overrides device names and option -list_all."
  102   echo "                    The found device is then shown with advice, vendor,"
  103   echo "                    and model. Option -DO_WRITE is obeyed if given."
  104   echo " -list_all          Print list of all found devices with advice, vendor"
  105   echo "                    and model. One per line. Ignore any device names."
  106   echo "                    Ignore -DO_WRITE."
  107   echo " -list_long         With each line printed by -list_all or a submitted"
  108   echo "                    device name, let lsblk print info which led to the"
  109   echo "                    shown reasons."
  110   echo " -with_vendor_model Print vendor and model with each submitted device"
  111   echo "                    name."
  112   echo " -max_size n[M|G|T] Set upper byte size limit for advisable devices."
  113   echo "                    Plain numbers get rounded down to full millions."
  114   echo "                    Suffix: M = million, G = billion, T = trillion."
  115   echo "                    Be generous to avoid problems with GB < GiB."
  116   echo " -min_size n[M|G|T] Set lower byte size limit for advisable devices."
  117   echo "                    After processing like with -max_size, one million"
  118   echo "                    gets added to the size limit."
  119   echo " -look_for_iso      Demand presence of an ISO 9660 filesystem. If so,"
  120   echo "                    any further filesystem type is acceptable on that"
  121   echo "                    device. Else only ISO 9660 and VFAT are accepted."
  122   echo " -with_sudo         Run '$xdt_lsblk_cmd -o FSTYPE' by sudo."
  123   echo "                    If no filesystems are detected and the program"
  124   echo "                    has no superuser power, the device is not advised."
  125   echo "                    If -DO_WRITE is given, run umount and dd by sudo." 
  126   echo " -trust_lsblk_udev  Suppress the reason no_fs_while_not_su- if lsblk"
  127   echo "                    is linked with libudev.so. In this case it is"
  128   echo "                    likely that lsblk can retrieve FSTYPE even if"
  129   echo "                    run by a non-priviledged user."
  130   echo " -image_file PATH   Set the path of the image file which shall be"
  131   echo "                    written to a device. Its size will be set as"
  132   echo "                    -min_size."
  133   echo " -DO_WRITE          Write the given -image_file to the one advisable"
  134   echo "                    device that is found. If more than one such device"
  135   echo "                    is found, then they get listed but no writing"
  136   echo "                    happens. In this case, re-run with one of the"
  137   echo "                    advised device names to get a real write run."
  138   echo " -no_pacifier       Do not use dd options to print progress messages"
  139   echo "                    and to perform synchronized output."
  140   echo " -dummy             Report the -DO_WRITE actions but do not perform"
  141   echo "                    them."
  142   echo " -dummy_force       If a single device name is given, do a run of"
  143   echo "                    -dummy -DO_WRITE even against the advice of"
  144   echo "                    this program. This probably shows you ways to"
  145   echo "                    shoot your own foot."
  146   echo " -version           Print version text and then end the program."
  147   echo " -help              Print this text to stdout and then end the program."
  148   echo "Examples:"
  149   echo " $0 -with_sudo -list_all"
  150   echo " $0 sdc"
  151   echo " $0 -with_sudo -image_file debian-live-10.0.0-amd64-xfce.iso -DO_WRITE -dummy"
  152   echo " $0 -with_sudo -image_file debian-live-10.0.0-amd64-xfce.iso -DO_WRITE -plug_test"
  153   echo
  154   return 0
  155 }
  156 
  157 # Roughly convert human readable sizes and plain numbers to 1 / million
  158 xdt_round_down_div_million() {
  159   sed \
  160     -e 's/^[0-9][0-9][0-9][0-9][0-9][0-9]$/0/' \
  161     -e 's/^[0-9][0-9][0-9][0-9][0-9]$/0/' \
  162     -e 's/^[0-9][0-9][0-9][0-9]$/0/' \
  163     -e 's/^[0-9][0-9][0-9]$/0/' \
  164     -e 's/^[0-9][0-9]$/0/' \
  165     -e 's/^[0-9]$/0/' \
  166     -e 's/\.[0-9]*//' \
  167     -e 's/[0-9][0-9][0-9][0-9][0-9][0-9]$//' \
  168     -e 's/[Mm]$//' \
  169     -e 's/[Gg]$/000/' \
  170     -e 's/[Tt]$/000000/' 
  171   return 0
  172 }
  173 
  174 ## Check for harmless name or number in program argument
  175 xdt_check_parameter() {
  176   if test "X$2" = "Xdevice_name"
  177   then
  178     if echo "X$1" | grep '[^A-Za-z0-9_/-]' >/dev/null
  179     then
  180       echo "SORRY: Given device name contains unexpected character. Ok: [A-za-z0-9_/-]" >&2
  181       return 12
  182     elif echo "X$1" | grep '^X-' >/dev/null
  183     then
  184       echo "SORRY: Given device name begins by '-' character." >&2
  185       return 15
  186     fi
  187   elif test "X$2" = "Ximage_file"
  188   then
  189     if echo "X$1" | grep '[$`[*?<>|&!{\]' >/dev/null
  190     then
  191       echo "SORRY: Given image file name contains unexpected character. Not ok: "'[$`[*?<>|&!{\]' >&2
  192       return 15
  193     elif echo "X$1" | grep '^X[-(]' >/dev/null
  194     then
  195       echo "SORRY: Given image file name begins by problematic character. Not ok: "'[-(]' >&2
  196       return 15
  197     fi
  198   else
  199     if echo "X$1" | grep -v '^X[0-9][0-9]*[0-9MGTmgt]$' >/dev/null
  200     then
  201       echo "SORRY: Number for $2 too short or bad character. Ok: [0-9][0-9MGTmgt]" >&2
  202       return 14
  203     fi
  204   fi
  205   return 0
  206 }
  207 
  208 ### Assessing arguments and setting up the job
  209 
  210 # Settings
  211 xdt_reset_job() {
  212   xdt_list_all=
  213   xdt_do_list_long=
  214   xdt_show_reasons=
  215   xdt_look_for_iso=
  216   xdt_devs=
  217   xdt_devs_named=
  218   xdt_max_size=
  219   xdt_with_vendor_model=
  220   xdt_with_sudo=
  221   xdt_image_file=
  222   xdt_do_write=
  223   xdt_dummy_run=
  224   xdt_dummy_force=
  225   xdt_no_pacifier=
  226   xdt_do_plug_test=
  227   xdt_trust_lsblk_udev=
  228 
  229   # Status
  230   xdt_sudo_cmd=
  231   xdt_have_su_power=
  232   xdt_end_after_setup=
  233   xdt_dev_end=
  234   xdt_dd_bs="bs=1M"
  235   xdt_dd_silent=
  236 
  237   return 0
  238 }
  239 
  240 ## Predict superuser power. Possibly enable sudo with lsblk -o FSTYPE and dd.
  241 ## Also predict whether lsblk -o FSTYPE will bring results as non-root.
  242 xdt_predict_su_power() {
  243   if test "$(whoami)" = "root"
  244   then
  245     xdt_have_su_power=y
  246   elif test -n "$xdt_with_sudo"
  247   then
  248     echo "Testing sudo to possibly get password prompting done now:" >&2
  249     if sudo "$xdt_lsblk_cmd" -h >/dev/null
  250     then
  251       echo "sudo $xdt_lsblk_cmd seems ok." >&2
  252       echo >&2
  253       xdt_sudo_cmd=sudo
  254       xdt_have_su_power=y
  255     else
  256       echo "FAILURE: Cannot execute program $xdt_lsblk_cmd by sudo" >&2
  257       return 11
  258     fi
  259   fi
  260 
  261   # lsblk linked with libudev.so usually can obtain filesystem info
  262   # without superuser powers.
  263   if test -n "$xdt_trust_lsblk_udev"
  264   then
  265     if ldd "$xdt_lsblk_cmd" | grep '\blibudev\.so' >/dev/null
  266     then
  267       xdt_lsblk_fs_wo_su=y
  268     fi
  269   fi
  270   return 0
  271 }
  272 
  273 ## Sets xdt_variables according to its arguments
  274 xdt_arg_interpreter() {
  275   xdt_next_is=
  276   for xdt_i in "$@"
  277   do
  278     # The next_is option parameter readers get programmed by the -options
  279     if test "$xdt_next_is" = "max_size"
  280     then
  281       xdt_check_parameter "$xdt_i" -max_size || return "$?"
  282       xdt_max_size="$(echo "$xdt_i" | xdt_round_down_div_million)"
  283       xdt_next_is=
  284     elif test "$xdt_next_is" = "min_size"
  285     then
  286       xdt_check_parameter "$xdt_i" -min_size || return "$?"
  287       xdt_min_size="$(echo "$xdt_i" | xdt_round_down_div_million)"
  288       xdt_min_size="$(expr $xdt_min_size + 1)"
  289       xdt_next_is=
  290     elif test "$xdt_next_is" = "image_file"
  291     then
  292       xdt_check_parameter "$xdt_i" image_file || return "$?"
  293       xdt_image_file="$xdt_i"
  294       xdt_min_size="$(stat -c '%s' "$xdt_i" \
  295                           | xdt_round_down_div_million)"
  296       if test -z "$xdt_min_size"
  297       then
  298         echo "FAILURE: Cannot obtain size of -image_file '$xdt_i'" >&2
  299         return 13
  300       else
  301         xdt_min_size="$(expr $xdt_min_size + 1)"
  302       fi
  303       xdt_next_is=
  304     elif test "X$xdt_i" = "X-list_all"
  305     then
  306       xdt_list_all=y
  307       xdt_with_vendor_model=y
  308       xdt_show_reasons=y
  309     elif test "X$xdt_i" = "X-list_long"
  310     then
  311       xdt_do_list_long=y
  312     elif test "X$xdt_i" = "X-plug_test"
  313     then
  314       xdt_do_plug_test=y
  315     elif test "X$xdt_i" = "X-max_size"
  316     then
  317       xdt_next_is="max_size"
  318     elif test "X$xdt_i" = "X-min_size"
  319     then
  320       xdt_next_is="min_size"
  321     elif test "X$xdt_i" = "X-with_vendor_model"
  322     then
  323       xdt_with_vendor_model=y
  324     elif test "X$xdt_i" = "X-look_for_iso"
  325     then
  326       xdt_look_for_iso=y
  327     elif test "X$xdt_i" = "X-trust_lsblk_udev"
  328     then
  329       xdt_trust_lsblk_udev=y
  330     elif test "X$xdt_i" = "X-with_sudo"
  331     then
  332       xdt_with_sudo=y
  333     elif test "X$xdt_i" = "X-image_file"
  334     then
  335       xdt_next_is="image_file"
  336     elif test "X$xdt_i" = "X-dummy"
  337     then
  338       xdt_dummy_run=y
  339     elif test "X$xdt_i" = "X-dummy_force"
  340     then
  341       xdt_dummy_run=y
  342       xdt_do_write=y
  343       xdt_dummy_force=y
  344     elif test "X$xdt_i" = "X-DO_WRITE"
  345     then
  346       xdt_do_write=y
  347     elif test "X$xdt_i" = "X-no_pacifier"
  348     then
  349       xdt_no_pacifier=y
  350     elif test "X$xdt_i" = "X-version"
  351     then
  352       xdt_print_version
  353       xdt_end_after_setup=y
  354       return 0
  355     elif test "X$xdt_i" = "X-help"
  356     then
  357       xdt_print_usage
  358       xdt_end_after_setup=y
  359       return 0
  360     elif echo "X$xdt_i" | grep -v '^X-' >/dev/null
  361     then
  362       xdt_check_parameter "$xdt_i" device_name || return "$?"
  363       xdt_devs_named=y
  364       xdt_devs="$xdt_devs $xdt_i"
  365       xdt_show_reasons=y
  366     else
  367       echo "$0 : Unknown option: '$xdt_i'" >&2
  368       echo >&2
  369       echo "For a help text run: $0 -help" >&2
  370       return 16
  371     fi
  372   done
  373   xdt_predict_su_power || return "$?"
  374   # Prepare for using dd pacifier if desired and available
  375   # Prepare for using silent dd with GPT backup erasure if available
  376   xdt_dd_bs="bs=1M"
  377   xdt_dd_silent=
  378   if test -n "$xdt_dd_cmd"
  379   then
  380     if test -z "$xdt_no_pacifier" && \
  381        "$xdt_dd_cmd" if=/dev/zero of=/dev/null count=1 \
  382                      bs=1M status=progress oflag=dsync 2>/dev/null
  383     then
  384       xdt_dd_bs="bs=1M status=progress oflag=dsync"
  385     fi
  386     if "$xdt_dd_cmd" if=/dev/zero of=/dev/null count=1 bs=512 status=none \
  387                      2>/dev/null
  388     then
  389       xdt_dd_silent="status=none"
  390     fi
  391   fi
  392   return 0
  393 }
  394 
  395 ## Obtain a blank separated list of top-level names which do not look like
  396 ## CD, floppy, RAM dev, or loop device.
  397 xdt_collect_devices() {
  398   "$xdt_lsblk_cmd" -d -n -o NAME \
  399     | grep -v '^sr[0-9]' \
  400     | grep -v '^fd[0-9]' \
  401     | grep -v '^zram[0-9]' \
  402     | grep -v '^loop[0-9]' \
  403     | tr '\n\r' '  '
  404   return 0
  405 }
  406 
  407 ## Let lsblk print extra info for the given devices
  408 xdt_list_long() {
  409   if test -z "$xdt_do_list_long"
  410   then
  411     return 0
  412   fi
  413   $xdt_sudo_cmd "$xdt_lsblk_cmd" -o NAME,SIZE,FSTYPE,TRAN,LABEL \
  414                     /dev/"$1"
  415   echo
  416   return 0
  417 }
  418 
  419 ## Trying to find the desired device by watching plug-in effects
  420 xdt_plug_in_watcher() {
  421   # How long to wait for a first device to appear, how long to wait for more
  422   xdt_wait_span_0=10
  423   xdt_wait_span_1=5
  424 
  425   xdt_found_devices=
  426   echo >&2
  427   echo "Caused by option -plug_test: Attempt to find the desired device" >&2
  428   echo "by watching it appear after being plugged in." >&2
  429   echo >&2
  430   echo "Step 1:" >&2
  431   echo "Please make sure that the desired target device is plugged _out_ now." >&2
  432   echo "If it is currently plugged in, make sure to unmount all its fileystems" >&2
  433   echo "and then unplug it." >&2
  434   echo "Press the Enter key when ready." >&2
  435   read xdt_dummy
  436   xdt_old_device_list=' '$(xdt_collect_devices)' '
  437 
  438 # <<< Mock-up to save USB socket wear-off by erasing items from old_device_list
  439 # <<< Their presence in new_device_list will let them appear as fresh plugs
  440 # xdt_old_device_list=' '$(echo -n $xdt_old_device_list | sed -e 's/sdc//')' '
  441 
  442   echo "Found and noted as _not_ desired: $xdt_old_device_list" >&2
  443   echo >&2
  444   echo "Step 2:" >&2
  445   echo "Please plug in the desired target device and then press the Enter key." >&2
  446   read xdt_dummy
  447   echo -n "Waiting up to $xdt_wait_span_0 seconds for a new device to be listed ..." >&2
  448   xdt_end_time="$(expr $(date +'%s') + "$xdt_wait_span_0")"
  449   while test $(date +'%s') -le "$xdt_end_time"
  450   do
  451     xdt_new_device_list=' '$(xdt_collect_devices)' '
  452     for xdt_i in $xdt_new_device_list
  453     do
  454       if echo "$xdt_old_device_list $xdt_found_devices " \
  455          | grep -F -v ' '"$xdt_i"' ' >/dev/null
  456       then
  457         echo " found: $xdt_i" >&2
  458         xdt_found_devices="$xdt_found_devices $xdt_i"
  459         xdt_end_time=$(expr $(date +'%s') + "$xdt_wait_span_1")
  460         echo -n "Now waiting $xdt_wait_span_1 seconds to let it settle ..." >&2
  461       fi
  462     done
  463     sleep 1
  464     echo -n '.' >&2
  465   done
  466   echo >&2
  467   if test -z "$xdt_found_devices"
  468   then
  469     echo "SORRY: No new candidate device was found." >&2
  470     return 8
  471   fi
  472   xdt_num=$(echo $xdt_found_devices | wc -w)
  473   if test "$xdt_num" -gt 1
  474   then
  475     echo "SORRY: More than one new candidate device appeared: $xdt_found_devices" >&2
  476     return 9
  477   fi
  478   echo "Found and noted as desired device: $xdt_found_devices" >&2
  479   if test -n "$xdt_devs"
  480   then
  481     echo "(-plug_test is overriding device list given by arguments: $xdt_devs )" >&2
  482   fi
  483   if test -n "$xdt_list_all"
  484   then
  485     echo "(-plug_test is overriding -list_all)" >&2
  486     xdt_list_all=
  487   fi
  488   xdt_devs_named=y
  489   xdt_with_vendor_model=y
  490   xdt_show_reasons=y
  491   xdt_devs=$(echo -n $xdt_found_devices)
  492   echo >&2
  493 
  494   return 0
  495 }
  496 
  497 ## Evaluation of available devices and suitability
  498 xdt_list_devices() {
  499   if test -n "$xdt_list_all"
  500   then
  501     xdt_devs=
  502   fi
  503   if test -z "$xdt_devs"
  504   then
  505     # Obtain list of top-level names which do not look like CD, floppy, RAM dev
  506     xdt_devs=$(xdt_collect_devices)
  507   fi
  508 
  509   xdt_not_advised=0
  510   for xdt_name in $xdt_devs
  511   do
  512     # Collect reasons
  513     xdt_yucky=
  514     xdt_reasons=
  515     xdt_good_trans=
  516     xdt_good_fs=
  517     xdt_bad_trans=
  518     xdt_bad_fs=
  519 
  520     # Unwanted device name patterns
  521     if (echo "$xdt_name" | grep '^sd[a-z][1-9]' >/dev/null) \
  522        || (echo "$xdt_name" | grep '^mmcblk.*p[0-9]' >/dev/null) \
  523        || (echo "$xdt_name" | grep '^nvme.*p[0-9]' >/dev/null)
  524     then
  525       xdt_yucky=y
  526       xdt_reasons="${xdt_reasons}looks_like_disk_partition- "
  527     elif echo "$xdt_name" | grep '^sr[0-9]' >/dev/null
  528     then
  529       xdt_yucky=y
  530       xdt_reasons="${xdt_reasons}looks_like_cd_drive- "
  531     elif echo "$xdt_name" | grep '^fd[0-9]' >/dev/null
  532     then
  533       xdt_yucky=y
  534       xdt_reasons="${xdt_reasons}looks_like_floppy- "
  535     elif echo "$xdt_name" | grep '^loop[0-9]' >/dev/null
  536     then
  537       xdt_yucky=y
  538       xdt_reasons="${xdt_reasons}looks_like_loopdev- "
  539     elif echo "$xdt_name" | grep '^zram[0-9]' >/dev/null
  540     then
  541       xdt_yucky=y
  542       xdt_reasons="${xdt_reasons}looks_like_ramdev- "
  543     fi
  544 
  545     # >>> recognize the device from which Debian Live booted
  546 
  547     # Connection type. Normally by lsblk TRAN, but in case of mmcblk artificial.
  548     if echo "$xdt_name" | grep '^mmcblk[0-9]' >/dev/null
  549     then
  550       xdt_transports="mmcblk"
  551     elif echo "$xdt_name" | grep -F "/" >/dev/null
  552     then
  553       xdt_transports=not_an_expected_name
  554       xdt_reasons="${xdt_reasons}name_with_slash- "
  555     else
  556       xdt_transports=$("$xdt_lsblk_cmd" -n -o TRAN /dev/"$xdt_name")
  557     fi
  558     for xdt_trans in $xdt_transports
  559     do
  560       if test "$xdt_trans" = "usb" || test "$xdt_trans" = "mmcblk"
  561       then
  562         xdt_good_trans="${xdt_trans}+"
  563       elif test -n "$xdt_trans"
  564       then
  565         xdt_bad_trans="$xdt_trans"
  566         xdt_yucky=y
  567         if test "$xdt_transports" = "not_an_expected_name"
  568         then
  569           xdt_dummy=dummy
  570         else
  571           if echo "$xdt_reasons" | grep -F -v "not_usb" >/dev/null
  572           then
  573             xdt_reasons="${xdt_reasons}not_usb- "
  574           fi
  575         fi
  576       fi
  577     done
  578     if test -z "$xdt_good_trans" && test -z "$xdt_bad_trans"
  579     then
  580       xdt_yucky=y
  581       xdt_reasons="${xdt_reasons}no_bus_info- "
  582     elif test -z "$xdt_bad_trans"
  583     then
  584       xdt_reasons="${xdt_reasons}$xdt_good_trans "
  585     fi
  586 
  587     # Wanted or unwanted filesystem types
  588     xdt_fstypes=$($xdt_sudo_cmd "$xdt_lsblk_cmd" -n -o FSTYPE \
  589                       /dev/"$xdt_name")
  590     if test "$?" -gt 0
  591     then
  592       xdt_fstypes="lsblk_fstype_error"
  593     fi
  594     # Get overview of filesystems
  595     xdt_has_iso=
  596     xdt_has_vfat=
  597     xdt_has_other=
  598     for xdt_fstype in $xdt_fstypes
  599     do
  600       if test "$xdt_fstype" = "iso9660"
  601       then
  602         xdt_has_iso=y
  603         if echo "$xdt_good_fs" | grep -F -v "has_$xdt_fstype" >/dev/null
  604         then
  605           xdt_good_fs="${xdt_good_fs}has_${xdt_fstype}+ "
  606         fi
  607       elif test "$xdt_fstype" = "vfat"
  608       then
  609         xdt_has_vfat=y
  610         if echo "$xdt_good_fs" | grep -F -v "has_$xdt_fstype" >/dev/null
  611         then
  612           xdt_good_fs="${xdt_good_fs}has_${xdt_fstype}+ "
  613         fi
  614       elif test -n "$xdt_fstype"
  615       then
  616         xdt_has_other=y
  617         if echo "$xdt_bad_fs" | grep -F -v "has_$xdt_fstype" >/dev/null
  618         then
  619           xdt_bad_fs="${xdt_bad_fs}has_${xdt_fstype}- "
  620         fi
  621       fi
  622     done
  623     # Decide whether the found filesystems look dispensible enough
  624     xdt_reasons="${xdt_reasons}${xdt_good_fs}${xdt_bad_fs}"
  625     if test "${xdt_bad_fs}${xdt_good_fs}" = "" \
  626        && test -z "$xdt_have_su_power" && test -z "$xdt_lsblk_fs_wo_su"
  627     then
  628       xdt_yucky=y
  629       xdt_reasons="${xdt_reasons}no_fs_while_not_su- "
  630     elif test -n "$xdt_look_for_iso"
  631     then
  632       if test -n "$xdt_has_iso"
  633       then
  634         xdt_reasons="${xdt_reasons}look_for_iso++ "
  635       else
  636         xdt_yucky=y
  637         xdt_reasons="${xdt_reasons}no_iso9660- "
  638       fi
  639     elif test -n "$xdt_has_other"
  640     then
  641       xdt_yucky=y
  642     fi
  643   
  644     # Optional tests for size
  645     if test -n "$xdt_max_size" || test -n "$xdt_min_size"
  646     then
  647       xdt_dev_bytes=$("$xdt_lsblk_cmd" -n -b -o SIZE /dev/"$xdt_name" | head -1)
  648       xdt_size=$(echo "$xdt_dev_bytes" | xdt_round_down_div_million)
  649       if test -z "$xdt_size"
  650       then
  651         xdt_yucky=y
  652         xdt_reasons="${xdt_reasons}lsblk_no_size- "
  653       fi
  654     fi
  655     if test -n "$xdt_max_size" && test -n "$xdt_size"
  656     then
  657       if test "$xdt_size" -gt "$xdt_max_size"
  658       then
  659         xdt_yucky=y
  660         xdt_reasons="${xdt_reasons}size_too_large- "
  661       fi
  662     fi
  663     if test -n "$xdt_min_size" && test -n "$xdt_size"
  664     then
  665       if test "$xdt_size" -lt "$xdt_min_size"
  666       then
  667         xdt_yucky=y
  668         xdt_reasons="${xdt_reasons}size_too_small- "
  669       fi
  670     fi
  671   
  672     # Now decide overall and report
  673     xdt_descr=
  674     if test -n "$xdt_with_vendor_model"
  675     then
  676       xdt_descr=": "$("$xdt_lsblk_cmd" -n -o VENDOR,MODEL \
  677                           /dev/"$xdt_name" | tr '\n\r' '  ' | tr -s ' ')
  678     fi
  679     if test -n "$xdt_yucky"
  680     then
  681       if test -n "$xdt_show_reasons"
  682       then
  683         echo "$xdt_name : NO  : $xdt_reasons$xdt_descr"
  684         xdt_list_long "$xdt_name"
  685       fi
  686       xdt_not_advised=1
  687     else
  688       if test -n "$xdt_show_reasons"
  689       then
  690         echo "$xdt_name : YES : $xdt_reasons$xdt_descr"
  691         xdt_list_long "$xdt_name"
  692       else
  693         echo "$xdt_name"
  694       fi
  695     fi
  696   done
  697   return 0;
  698 }
  699 
  700 ## Puts list of mounted (sub-)devices of $1 into $mounted_devs
  701 xdt_list_mounted_of() {
  702   xdt_partitions=$("$xdt_lsblk_cmd" -l -n -p -o NAME /dev/"$1" \
  703                        | grep -v '^'/dev/"$1"'$' \
  704                        | tr '\n\r' '  ')
  705   xdt_mounted_devs=
  706   for xdt_i in /dev/"$1" $xdt_partitions
  707   do
  708     # Show the found mount lines and add their device paths to list
  709     xdt_mount_line=$(mount | grep '^'"$xdt_i"' ')
  710     if test -n "$xdt_mount_line"
  711     then
  712       echo "  $xdt_mount_line"
  713       xdt_mounted_devs="$xdt_mounted_devs $xdt_i"
  714     fi
  715   done
  716   return 0
  717 }
  718 
  719 ## Unmount xdt_mounted_devs (maybe filled by xdt_list_mounted_of)
  720 ## $1 : base device name
  721 xdt_unmount() {
  722   if test -z "$xdt_mounted_devs"
  723   then
  724     return 0
  725   fi
  726 
  727   for xdt_i in $xdt_mounted_devs
  728   do
  729     if test -n "$xdt_dummy_run"
  730     then
  731       echo "  $xdt_sudo_cmd $xdt_umount_cmd $xdt_i"
  732     elif $xdt_sudo_cmd "$xdt_umount_cmd" "$xdt_i"
  733     then
  734       echo "Unmounted: $xdt_i"
  735     else
  736       echo "FAILURE: Non-zero exit value with:  $xdt_sudo_cmd $xdt_umount_cmd $xdt_i" >&2
  737       return 7
  738     fi
  739   done
  740 
  741   # Check again if any mount points still exist
  742   if test -z "$xdt_dummy_run"
  743   then
  744     xdt_list_mounted_of "$1"
  745     if test -n "$xdt_mounted_devs"
  746     then
  747       echo "FAILURE: $xdt_sudo_cmd $xdt_umount_cmd could not remove all mounts: $xdt_mounted_devs" >&2
  748       return 7
  749     fi
  750   fi
  751   return 0
  752 }
  753 
  754 ## Does the work of unmounting and dd-ing
  755 ## $1 : image file path
  756 ## $2 : base device name
  757 xdt_write_image() {
  758 
  759   if test -z "$xdt_umount_cmd"
  760   then
  761     echo "No executable program umount found in: $xdt_sudo_x_dir_list" >&2
  762     return 6
  763   fi
  764   echo "Looking for mount points of $2:"
  765   xdt_mounted_devs=
  766   xdt_list_mounted_of "$2"
  767 
  768   if test -n "$xdt_dummy_force"
  769   then
  770     echo "AGAINST THE ADVICE BY THIS PROGRAM, a daring user could do:"
  771     xdt_dummy_run=y
  772   elif test -n "$xdt_dummy_run"
  773   then
  774     echo "Would do if not -dummy:"
  775   fi
  776 
  777   xdt_unmount "$2" || return "$?"
  778 
  779   if test -z "$xdt_dd_cmd"
  780   then
  781     echo "No executable program dd found in: $xdt_sudo_x_dir_list" >&2
  782     return 6
  783   fi
  784 
  785   # Erase possible GPT backup table at end of device
  786   # if expr can properly divide device size by 512
  787   xdt_dev_bytes=$("$xdt_lsblk_cmd" -n -b -o SIZE /dev/"${2}" | head -1)
  788   if test -n "$xdt_dev_bytes"
  789   then
  790     xdt_dev_end=$(expr "$xdt_dev_bytes" / 512 2>/dev/null)
  791     if test "$(expr "$xdt_dev_end" '*' 512 2>/dev/null)" = "$xdt_dev_bytes"
  792     then
  793       xdt_dev_end=$(expr "$xdt_dev_end" - 1)
  794     else
  795       xdt_dev_end=
  796     fi
  797   fi
  798   xdt_gpt_erase_line="$xdt_sudo_cmd $xdt_dd_cmd if=/dev/zero of=/dev/'${2}' bs=512 seek='$xdt_dev_end' count=1 $xdt_dd_silent"
  799 
  800   xdt_copy_line="$xdt_sudo_cmd $xdt_dd_cmd if='${1}' of=/dev/'${2}' $xdt_dd_bs ; sync"
  801   if test -n "$xdt_dummy_run"
  802   then
  803     if test -n "$xdt_dev_end"
  804     then
  805       echo "  $xdt_gpt_erase_line"
  806     fi
  807     echo "  $xdt_copy_line"
  808   else
  809     echo "Performing:"
  810     if test -n "$xdt_dev_end"
  811     then
  812       echo "  $xdt_gpt_erase_line"
  813       $xdt_sudo_cmd "$xdt_dd_cmd" if=/dev/zero of=/dev/"${2}" bs=512 seek="$xdt_dev_end" count=1 $xdt_dd_silent
  814     fi
  815     echo "  $xdt_copy_line"
  816     $xdt_sudo_cmd "$xdt_dd_cmd" if="${1}" of=/dev/"${2}" $xdt_dd_bs
  817     xdt_ret="$?"
  818     sync
  819     if test "$xdt_ret" -ne 0
  820     then
  821       echo "FAILURE: $xdt_sudo_cmd $xdt_dd_cmd was not successful" >&2
  822       return 18
  823     fi
  824   fi
  825 
  826   if test -n "$xdt_dummy_force"
  827   then
  828     echo "BE SMART. BE CAUTIOUS. BEWARE."
  829   fi
  830   return 0
  831 }
  832 
  833 ## Inspects the result of listing, decides whether writing is advisable,
  834 ## and starts the write run
  835 xdt_decide_writing()
  836 {
  837   xdt_with_vendor_model=
  838   xdt_show_reasons=
  839   xdt_candidates=$(xdt_list_devices | tr '\n\r' '  ')
  840   xdt_num_cand=$(echo $xdt_candidates | wc -w)
  841   xdt_num_devs=$(echo $xdt_devs| wc -w)
  842   if test -n "$xdt_dummy_force" && test "$xdt_num_devs" -ne 1
  843   then
  844     echo "SORRY: Refusing -dummy_force with not exactly one device given." >&2
  845     return 10
  846   fi
  847   if test -n "$xdt_dummy_force" && test -n "$xdt_dummy_run" \
  848      && test "$xdt_num_cand" -ne 1 
  849   then
  850     # -dummy_force in a situation where the program would normally refuse
  851     echo
  852     echo "Overriding any advice because of -dummy_force"
  853     xdt_candidates="$xdt_devs"
  854     xdt_num_cand=1
  855   elif test -n "$xdt_dummy_force"
  856   then
  857     # Downgrade -dummy_force to -dummy in order to avoid the ugly warning
  858     xdt_dummy_force=
  859     xdt_dummy_run=y
  860   fi
  861   if test "$xdt_num_cand" -eq 1
  862   then
  863     if test -n "$xdt_image_file"
  864     then
  865       if test -n "$xdt_do_plug_test"
  866       then
  867         echo >&2
  868         echo "Step 3:" >&2
  869         if test -n "$xdt_dummy_run"
  870         then
  871           echo "This would be the last chance to abort. Enter the word 'yes' to see -dummy report." >&2
  872         else
  873           echo "Last chance to abort. Enter the word 'yes' to start REAL WRITING." >&2
  874         fi
  875         read xdt_dummy
  876         if test "X$xdt_dummy" = "Xyes" || test "X$xdt_dummy" = "X'yes'" \
  877            || test "X$xdt_dummy" = 'X"yes"'
  878         then
  879           xdt_dummy=dummy
  880         else
  881           echo "WRITE RUN PREVENTED by user input '$xdt_dummy'." >&2
  882           return 17  
  883         fi
  884       fi
  885       xdt_write_image "$xdt_image_file" $xdt_candidates || return "$?"
  886     else
  887       xdt_candidates=$(echo $xdt_candidates)
  888       if test -n "$xdt_dummy_run"
  889       then
  890         echo "Would simulate writing to /dev/$xdt_candidates if an -image_file were given."
  891       else
  892         echo "Would write to /dev/$xdt_candidates if an -image_file were given."
  893       fi
  894       return 0
  895     fi
  896   elif test "$xdt_num_cand" -gt 1
  897   then
  898     echo "WILL NOT WRITE ! More than one candidate found for target device:" >&2
  899     xdt_show_reasons=y
  900     xdt_with_vendor_model=y
  901     xdt_devs="$xdt_candidates"
  902     xdt_list_devices >&2
  903     echo "HINT: Unplug the unwanted devices from the machine," >&2
  904     echo "      or work with option -plug_test," >&2
  905     echo "      or add the desired name out of {$(echo $xdt_candidates | sed -e 's/ /,/g')} as additional argument." >&2
  906     return 3
  907   else
  908     if test -n "$xdt_devs_named"
  909     then
  910       echo "NO CANDIDATE FOR TARGET DEVICE AMONG THE GIVEN NAMES !" >&2
  911     else
  912       echo "NO CANDIDATE FOR TARGET DEVICE FOUND !" >&2
  913     fi
  914     echo "Overall available devices:" >&2
  915     xdt_list_all=y
  916     xdt_list_long=
  917     xdt_show_reasons=y
  918     xdt_with_vendor_model=y
  919     xdt_list_devices >&2
  920     return 4
  921   fi
  922   return 0
  923 }
  924 
  925 ## The main function which runs the others in standalone mode
  926 xdt_main()
  927 {
  928   xdt_set_lang_c
  929   xdt_init || return "$?"
  930   
  931   xdt_reset_job
  932   xdt_arg_interpreter "$@" || return "$?"
  933   if test -n "$xdt_end_after_setup"
  934   then
  935     return 0
  936   fi
  937   
  938   if test -n "$xdt_do_plug_test"
  939   then
  940     xdt_plug_in_watcher || return "$?"
  941   fi
  942   
  943   xdt_list_devices || return "$?"
  944 
  945   if test -z "$xdt_list_all" && test -n "$xdt_do_write"
  946   then
  947     xdt_decide_writing || return "$?"
  948   fi
  949   
  950   if test -n "$xdt_devs_named"
  951   then
  952     return $xdt_not_advised
  953   fi
  954   return 0
  955 }
  956 
  957 if test -z "$no_xorriso_dd_target_run"
  958 then
  959   xdt_main "$@" || exit "$?"
  960 fi
  961