4 __pb_mount_dir=/var/petitboot/mnt/dev/
6 plugin_meta=pb-plugin.conf
7 plugin_meta_dir=etc/preboot-plugins/
8 plugin_meta_path=$plugin_meta_dir$plugin_meta
9 plugin_wrapper_dir=/var/lib/pb-plugins/bin
16 Where <command> is one of:
17 install <FILE|URL> - install plugin from FILE/URL
18 scan - look for available plugins on attached devices
19 create <DIR> - create a new plugin archive from DIR
40 wget -O - "$url" > $file
43 ncftpget -c "$url" > $file
46 echo "error: Unsuported protocol $proto" >&2
54 if [ "$PLUGIN_VENDOR" ]
56 title="$PLUGIN_VENDOR: $PLUGIN_NAME"
62 echo " (version $PLUGIN_VERSION)"
73 for dir in etc dev sys proc var
75 [ -e "$base/$dir" ] || mkdir -p "$base/$dir"
78 cp /etc/resolv.conf $base/etc
79 mount -o bind /dev $base/dev
80 mount -o bind /sys $base/sys
81 mount -o bind /proc $base/proc
82 mount -o bind /var $base/var
84 chroot "$base" "$binary" "$@"
94 local base binary wrapper
98 wrapper=$plugin_wrapper_dir/$(basename $binary)
100 mkdir -p $plugin_wrapper_dir
105 exec $(realpath $0) __wrap '$base' '$binary' "\$@"
113 local url name file __dest
119 echo "error: install requires a file/URL argument." >&2
128 trap "rm '$file'" EXIT
129 download "$url" "$file"
132 echo "error: failed to download $url" >&2
139 echo "error: $file doesn't exist or is not readable" >&2
144 echo "File '$name' has the following sha256 checksum:"
146 sha256sum "$file" | cut -f1 -d' '
148 echo "Do you want to install this plugin? (y/N)"
161 gunzip -c "$file" | ( cd $__dest && cpio -i -d)
165 echo "error: Failed to extract archive $url, exiting"
170 . $__dest/$plugin_meta_path
172 for binary in ${PLUGIN_EXECUTABLES}
174 __create_wrapper "$__dest" "$binary"
177 echo "Plugin installed"
183 local mnt dev plugin_path __meta_tmp
187 for plugin_path in $mnt/*.$plugin_ext
189 [ -e "$plugin_path" ] || continue
191 # extract plugin metadata to a temporary directory
192 __meta_tmp=$(mktemp -d)
193 [ -d $__meta_tmp ] || continue
194 gunzip -c "$plugin_path" 2>/dev/null |
196 cpio -i -d $plugin_meta_path 2>/dev/null)
197 if ! [ $? = 0 -a -e "$plugin_path" ]
204 . $__meta_tmp/$plugin_meta_path
206 printf "Plugin found on %s:\n" $dev
209 printf "To run this plugin:\n"
210 printf " $0 run $plugin_path\n"
222 for mnt in $__pb_mount_dir/*
229 echo "No plugins found"
235 local vendorname vendorshortname
236 local pluginname pluginnhortname
237 local version date executable
244 Enter the vendor company / author name. This can contain spaces.
245 (eg. 'Example Corporation')
250 Enter the vendor shortname. This should be a single-word abbreviation, in all
251 lower-case. This is only used in internal filenames.
253 Typically, a stock-ticker name is used for this (eg 'exco')
259 Enter the descriptive plugin name. This can contain spaces, but should only be
260 a few words in length (eg 'RAID configuration utility')
266 Enter the plugin shortname. This should not contain spaces, but hyphens are
267 fine (eg 'raid-config'). This is only used in internal filnames.
274 Enter the plugin version. This should not contain spaces (eg 1.2):
280 Enter the full path (within the plugin root) to the plugin executable file(s).
281 These will be exposed as wrapper scripts, to be run from the standard petitboot
282 shell environment (eg, /usr/bin/my-raid-config).
284 If multiple executables are provided, separate with a space.
288 date=$(date +%Y-%m-%d)
290 mkdir -p $(dirname $file)
293 PLUGIN_VENDOR='$vendorname'
294 PLUGIN_VENDOR_ID='$vendorshortname'
295 PLUGIN_NAME='$pluginname'
296 PLUGIN_ID='$pluginshortname'
297 PLUGIN_VERSION='$version'
299 PLUGIN_EXECUTABLES='$executables'
306 local src meta_dir_abs meta_file
311 echo "error: missing source directory" >&2
318 echo "error: source directory missing" >&2
322 meta_file=$src/$plugin_meta_path
324 if [ ! -e $meta_file ]
326 echo "No plugin metadata file found. " \
327 "Would you like to create one? (Y/n)"
331 echo "Cancelled, exiting"
335 guided_meta $meta_file || exit
338 # Sanity check metadata file
340 if [ ! -n "$PLUGIN_VENDOR" ]
342 echo "error: no PLUGIN_VENDOR defined in metadata" &>2
345 if [ ! -n "$PLUGIN_VENDOR_ID" ]
347 echo "error: no PLUGIN_VENDOR_ID defined in metadata" &>2
350 if [ ! -n "$PLUGIN_NAME" ]
352 echo "error: no PLUGIN_NAME defined in metadata" &>2
355 if [ ! -n "$PLUGIN_ID" ]
357 echo "error: no PLUGIN_ID defined in metadata" &>2
360 if [ ! -n "$PLUGIN_VERSION" ]
362 echo "error: no PLUGIN_VERSION defined in metadata" &>2
365 if [ ! -n "$PLUGIN_DATE" ]
367 echo "error: no PLUGIN_DATE defined in metadata" &>2
370 if [ ! -n "$PLUGIN_EXECUTABLES" ]
372 echo "error: no PLUGIN_EXECUTABLES defined in metadata" &>2
376 outfile=${PLUGIN_ID}-${PLUGIN_VERSION}.${plugin_ext}
380 find -mindepth 1 | cpio -o -Hnewc -v
381 ) | gzip -c > $outfile
384 echo "Plugin metadata:"
385 sed -e 's/^/ /' $meta_file
388 echo "User-visible metadata:"
389 plugin_info | sed -e 's/^/ /'
397 Ship this file in the top-level-directory of a USB device or CD to have it
398 automatically discoverable by 'pb-plugin scan'. This file can be re-named,
399 but must retain the .$plugin_ext extension to be discoverable.
407 tmp=$(mktemp -p $test_tmpdir)
408 ref=$(mktemp -p $test_tmpdir)
417 download http://example.com/test $tmp
425 tmp=$(mktemp -p $test_tmpdir)
426 ref=$(mktemp -p $test_tmpdir)
435 download ftp://example.com/test $tmp
441 __pb_mount_dir="$test_tmpdir/mnt"
442 mnt_dir="$__pb_mount_dir/sda"
443 mkdir -p $mnt_dir/$plugin_meta_dir
445 echo "PLUGIN_NAME=test"
446 echo "PLUGIN_VERSION=1"
447 echo "PLUGIN_EXECUTABLES=/bin/sh"
448 ) > $mnt_dir/$plugin_meta_path
451 find -mindepth 1 | cpio -o -Hnewc 2>/dev/null
452 ) | gzip -c > $mnt_dir/test.$plugin_ext
454 do_scan | grep -q 'test'
459 __pb_mount_dir="$test_tmpdir/mnt"
460 mnt_dir="$__pb_mount_dir/sda"
461 stderr_file="$test_tmpdir/stderr"
464 echo "invalid" > $mnt_dir/nogzip.$plugin_ext
466 do_scan 2>$stderr_file | grep -q 'No plugins'
468 [ $? = 0 ] || return 1
470 if [ -s "$stderr_file" ]
472 echo "Scan with invalid (non-gzip) file produced error output" \
482 __pb_mount_dir="$test_tmpdir/mnt"
483 mnt_dir="$__pb_mount_dir/sda"
484 stderr_file="$test_tmpdir/stderr"
487 echo "invalid" | gzip -c > $mnt_dir/nogzip.$plugin_ext
489 do_scan 2>$stderr_file | grep -q 'No plugins'
491 [ $? = 0 ] || return 1
493 if [ -s "$stderr_file" ]
495 echo "Scan with invalid (non-cpio) file produced error output" \
505 __pb_mount_dir="$test_tmpdir/mnt"
506 mnt_dir="$__pb_mount_dir/sda"
507 outfile=$test_tmpdir/scan.out
511 mkdir -p $mnt_dir/$plugin_meta_dir
513 echo "PLUGIN_NAME=test-$i"
514 echo "PLUGIN_VERSION=1"
515 echo "PLUGIN_EXECUTABLES=/bin/sh"
516 ) > $mnt_dir/$plugin_meta_path
519 find -mindepth 1 | cpio -o -Hnewc 2>/dev/null
520 ) | gzip -c > $mnt_dir/test-${i}.$plugin_ext
521 rm -rf $mnt_dir/$plugin_meta_dir
526 grep -q 'test-1' $outfile && grep -q 'test-2' $outfile
531 __pb_mount_dir="$test_tmpdir/mnt"
532 mkdir -p $__pb_mount_dir
533 do_scan | grep -q "No plugins"
540 test_tmpdir="$tests_tmpdir/$n"
582 tests_tmpdir=$(mktemp -d)
585 do_test ! is_url "/test"
586 do_test ! is_url "./test"
587 do_test ! is_url "../test"
588 do_test ! is_url "test"
589 do_test is_url "http://example.com/path"
590 do_test is_url "git+ssh://example.com/path"
591 do_test test_http_download
592 do_test test_ftp_download
594 do_test test_scan_nogzip
595 do_test test_scan_nocpio
596 do_test test_scan_multiple
597 do_test test_empty_scan
599 if [ $test_failed = 0 ]
601 echo "$n tests passed"
605 rm -rf "$tests_tmpdir"
632 echo "error: Missing command" >&2
637 echo "Invalid command: $s" >&2