"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