4 __pb_mount_dir=/var/petitboot/mnt/dev/
7 plugin_meta=pb-plugin.conf
8 plugin_meta_dir=etc/preboot-plugins/
9 plugin_meta_path=$plugin_meta_dir$plugin_meta
10 plugin_wrapper_dir=/var/lib/pb-plugins/bin
17 Where <command> is one of:
18 install <FILE|URL> - install plugin from FILE/URL
19 scan - look for available plugins on attached devices
20 create <DIR> - create a new plugin archive from DIR
41 wget -O - "$url" > $file
44 ncftpget -c "$url" > $file
47 echo "error: Unsuported protocol $proto" >&2
55 if [ "$PLUGIN_VENDOR" ]
57 title="$PLUGIN_VENDOR: $PLUGIN_NAME"
63 echo " (version $PLUGIN_VERSION)"
66 # How the ABI versioning works:
68 # - This script has an ABI defined ($plugin_abi)
70 # - Plugins have a current ABI number ($PLUGIN_ABI), and a minimum supported
71 # ABI number ($PLUGIN_ABI_MIN).
73 # - A plugin is OK to run if:
74 # - the plugin's ABI matches the script ABI, or
75 # - the plugin's minimum ABI is lower than or equal to the script ABI
78 [ -n "$PLUGIN_ABI" ] &&
79 ( [ $PLUGIN_ABI -eq $plugin_abi ] ||
80 [ $PLUGIN_ABI_MIN -le $plugin_abi ] )
91 for dir in etc dev sys proc var
93 [ -e "$base/$dir" ] || mkdir -p "$base/$dir"
96 cp /etc/resolv.conf $base/etc
97 mount -o bind /dev $base/dev
98 mount -o bind /sys $base/sys
99 mount -o bind /proc $base/proc
100 mount -o bind /var $base/var
102 chroot "$base" "$binary" "$@"
112 local base binary wrapper
116 wrapper=$plugin_wrapper_dir/$(basename $binary)
118 mkdir -p $plugin_wrapper_dir
123 exec $(realpath $0) __wrap '$base' '$binary' "\$@"
131 local url name file __dest
137 echo "error: install requires a file/URL argument." >&2
146 trap "rm '$file'" EXIT
147 download "$url" "$file"
150 echo "error: failed to download $url" >&2
157 echo "error: $file doesn't exist or is not readable" >&2
162 echo "File '$name' has the following sha256 checksum:"
164 sha256sum "$file" | cut -f1 -d' '
167 echo "Do you want to install this plugin? (y/N)"
180 gunzip -c "$file" | ( cd $__dest && cpio -i -d)
184 echo "error: Failed to extract archive $url, exiting"
189 . $__dest/$plugin_meta_path
191 if ! plugin_abi_check
193 echo "Plugin at $url is incompatible with this firmware," \
199 for binary in ${PLUGIN_EXECUTABLES}
201 __create_wrapper "$__dest" "$binary"
204 echo "Plugin installed"
210 local mnt dev plugin_path __meta_tmp
214 for plugin_path in $mnt/*.$plugin_ext
216 [ -e "$plugin_path" ] || continue
218 # extract plugin metadata to a temporary directory
219 __meta_tmp=$(mktemp -d)
220 [ -d $__meta_tmp ] || continue
221 gunzip -c "$plugin_path" 2>/dev/null |
223 cpio -i -d $plugin_meta_path 2>/dev/null)
224 if ! [ $? = 0 -a -e "$plugin_path" ]
231 . $__meta_tmp/$plugin_meta_path
233 plugin_abi_check || exit 1
235 printf "Plugin found on %s:\n" $dev
238 printf "To run this plugin:\n"
239 printf " $0 run $plugin_path\n"
254 for mnt in $__pb_mount_dir/*
261 echo "No plugins found"
267 local vendorname vendorshortname
268 local pluginname pluginnhortname
269 local version date executable
276 Enter the vendor company / author name. This can contain spaces.
277 (eg. 'Example Corporation')
282 Enter the vendor shortname. This should be a single-word abbreviation, in all
283 lower-case. This is only used in internal filenames.
285 Typically, a stock-ticker name is used for this (eg 'exco')
291 Enter the descriptive plugin name. This can contain spaces, but should only be
292 a few words in length (eg 'RAID configuration utility')
298 Enter the plugin shortname. This should not contain spaces, but hyphens are
299 fine (eg 'raid-config'). This is only used in internal filnames.
306 Enter the plugin version. This should not contain spaces (eg 1.2):
312 Enter the full path (within the plugin root) to the plugin executable file(s).
313 These will be exposed as wrapper scripts, to be run from the standard petitboot
314 shell environment (eg, /usr/bin/my-raid-config).
316 If multiple executables are provided, separate with a space.
320 date=$(date +%Y-%m-%d)
322 mkdir -p $(dirname $file)
325 PLUGIN_ABI='$plugin_abi'
327 PLUGIN_VENDOR='$vendorname'
328 PLUGIN_VENDOR_ID='$vendorshortname'
329 PLUGIN_NAME='$pluginname'
330 PLUGIN_ID='$pluginshortname'
331 PLUGIN_VERSION='$version'
333 PLUGIN_EXECUTABLES='$executables'
340 local src meta_dir_abs meta_file
345 echo "error: missing source directory" >&2
352 echo "error: source directory missing" >&2
356 meta_file=$src/$plugin_meta_path
358 if [ ! -e $meta_file ]
360 echo "No plugin metadata file found. " \
361 "Would you like to create one? (Y/n)"
365 echo "Cancelled, exiting"
369 guided_meta $meta_file || exit
372 # Sanity check metadata file
374 if [ ! -n "$PLUGIN_ABI" ]
376 echo "error: no PLUGIN_ABI defined in metadata" &>2
379 if [ "$PLUGIN_ABI" != "$plugin_abi" ]
381 echo "warning: PLUGIN_ABI (=$PLUGIN_ABI) is not $plugin_abi" &>2
383 if [ ! -n "$PLUGIN_VENDOR" ]
385 echo "error: no PLUGIN_VENDOR defined in metadata" &>2
388 if [ ! -n "$PLUGIN_VENDOR_ID" ]
390 echo "error: no PLUGIN_VENDOR_ID defined in metadata" &>2
393 if [ ! -n "$PLUGIN_NAME" ]
395 echo "error: no PLUGIN_NAME defined in metadata" &>2
398 if [ ! -n "$PLUGIN_ID" ]
400 echo "error: no PLUGIN_ID defined in metadata" &>2
403 if [ ! -n "$PLUGIN_VERSION" ]
405 echo "error: no PLUGIN_VERSION defined in metadata" &>2
408 if [ ! -n "$PLUGIN_DATE" ]
410 echo "error: no PLUGIN_DATE defined in metadata" &>2
413 if [ ! -n "$PLUGIN_EXECUTABLES" ]
415 echo "error: no PLUGIN_EXECUTABLES defined in metadata" &>2
419 outfile=${PLUGIN_ID}-${PLUGIN_VERSION}.${plugin_ext}
423 find -mindepth 1 | cpio -o -Hnewc -v
424 ) | gzip -c > $outfile
427 echo "Plugin metadata:"
428 sed -e 's/^/ /' $meta_file
431 echo "User-visible metadata:"
432 plugin_info | sed -e 's/^/ /'
440 Ship this file in the top-level-directory of a USB device or CD to have it
441 automatically discoverable by 'pb-plugin scan'. This file can be re-named,
442 but must retain the .$plugin_ext extension to be discoverable.
450 tmp=$(mktemp -p $test_tmpdir)
451 ref=$(mktemp -p $test_tmpdir)
460 download http://example.com/test $tmp
468 tmp=$(mktemp -p $test_tmpdir)
469 ref=$(mktemp -p $test_tmpdir)
478 download ftp://example.com/test $tmp
494 __pb_mount_dir="$test_tmpdir/mnt"
495 mnt_dir="$__pb_mount_dir/sda"
496 mkdir -p $mnt_dir/$plugin_meta_dir
498 echo "PLUGIN_ABI=$plugin_abi"
499 echo "PLUGIN_NAME=test"
500 echo "PLUGIN_VERSION=1"
501 echo "PLUGIN_EXECUTABLES=/bin/sh"
502 ) > $mnt_dir/$plugin_meta_path
505 find -mindepth 1 | cpio -o -Hnewc 2>/dev/null
506 ) | gzip -c > $mnt_dir/test.$plugin_ext
508 do_scan | grep -q 'test'
513 __pb_mount_dir="$test_tmpdir/mnt"
514 mnt_dir="$__pb_mount_dir/sda"
515 stderr_file="$test_tmpdir/stderr"
518 echo "invalid" > $mnt_dir/nogzip.$plugin_ext
520 do_scan 2>$stderr_file | grep -q 'No plugins'
522 [ $? = 0 ] || return 1
524 if [ -s "$stderr_file" ]
526 echo "Scan with invalid (non-gzip) file produced error output" \
536 __pb_mount_dir="$test_tmpdir/mnt"
537 mnt_dir="$__pb_mount_dir/sda"
538 stderr_file="$test_tmpdir/stderr"
541 echo "invalid" | gzip -c > $mnt_dir/nogzip.$plugin_ext
543 do_scan 2>$stderr_file | grep -q 'No plugins'
545 [ $? = 0 ] || return 1
547 if [ -s "$stderr_file" ]
549 echo "Scan with invalid (non-cpio) file produced error output" \
559 __pb_mount_dir="$test_tmpdir/mnt"
560 mnt_dir="$__pb_mount_dir/sda"
561 outfile=$test_tmpdir/scan.out
565 mkdir -p $mnt_dir/$plugin_meta_dir
567 echo "PLUGIN_ABI=$plugin_abi"
568 echo "PLUGIN_NAME=test-$i"
569 echo "PLUGIN_VERSION=1"
570 echo "PLUGIN_EXECUTABLES=/bin/sh"
571 ) > $mnt_dir/$plugin_meta_path
574 find -mindepth 1 | cpio -o -Hnewc 2>/dev/null
575 ) | gzip -c > $mnt_dir/test-${i}.$plugin_ext
576 rm -rf $mnt_dir/$plugin_meta_dir
581 grep -q 'test-1' $outfile && grep -q 'test-2' $outfile
586 __pb_mount_dir="$test_tmpdir/mnt"
587 mnt_dir="$__pb_mount_dir/sda"
588 mkdir -p $mnt_dir/$plugin_meta_dir
590 echo "PLUGIN_ABI=$(($plugin_abi + 1))"
591 echo "PLUGIN_ABI_MIN=$(($plugin_abi + 1))"
592 echo "PLUGIN_NAME=test"
593 echo "PLUGIN_VERSION=1"
594 echo "PLUGIN_EXECUTABLES=/bin/sh"
595 ) > $mnt_dir/$plugin_meta_path
598 find -mindepth 1 | cpio -o -Hnewc 2>/dev/null
599 ) | gzip -c > $mnt_dir/test.$plugin_ext
601 do_scan | grep -q 'No plugins'
606 __pb_mount_dir="$test_tmpdir/mnt"
607 mkdir -p $__pb_mount_dir
608 do_scan | grep -q "No plugins"
615 test_tmpdir="$tests_tmpdir/$n"
657 tests_tmpdir=$(mktemp -d)
660 do_test ! is_url "/test"
661 do_test ! is_url "./test"
662 do_test ! is_url "../test"
663 do_test ! is_url "test"
664 do_test is_url "http://example.com/path"
665 do_test is_url "git+ssh://example.com/path"
666 do_test test_http_download
667 do_test test_ftp_download
668 do_test ! test_abi_check
669 do_test ! test_abi_check 1
670 do_test test_abi_check 1 1
671 do_test test_abi_check 1 1 1
672 do_test test_abi_check 1 2 0
673 do_test test_abi_check 1 2 1
674 do_test ! test_abi_check 1 2 2
676 do_test test_scan_nogzip
677 do_test test_scan_nocpio
678 do_test test_scan_multiple
679 do_test test_scan_wrongabi
680 do_test test_empty_scan
682 if [ $test_failed = 0 ]
684 echo "$n tests passed"
688 rm -rf "$tests_tmpdir"
715 echo "error: Missing command" >&2
720 echo "Invalid command: $s" >&2