diff options
-rw-r--r-- | main/mkinitfs/APKBUILD | 12 | ||||
-rw-r--r-- | main/mkinitfs/git.patch | 1969 |
2 files changed, 4 insertions, 1977 deletions
diff --git a/main/mkinitfs/APKBUILD b/main/mkinitfs/APKBUILD index c24380f29f..229e3b0556 100644 --- a/main/mkinitfs/APKBUILD +++ b/main/mkinitfs/APKBUILD @@ -1,6 +1,6 @@ # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=mkinitfs -pkgver=2.8.0_git20151216 +pkgver=3.0.0 _ver=${pkgver%_git*} pkgrel=0 pkgdesc="Tool to generate initramfs images for Alpine" @@ -10,7 +10,6 @@ depends="acct busybox apk-tools>=2.0 lddtree>=1.25" install="$pkgname.pre-upgrade $pkgname.post-install $pkgname.post-upgrade" triggers="$pkgname.trigger=/usr/share/kernel/*" source="http://dev.alpinelinux.org/archive/$pkgname/$pkgname-$_ver.tar.xz - git.patch " arch="all" license="GPL2" @@ -36,9 +35,6 @@ package() { cd "$_builddir" make install DESTDIR="$pkgdir" || return 1 } -md5sums="1a321336d97b22257349ddd36884ec34 mkinitfs-2.8.0.tar.xz -56f7bf0af2d4262d60a91d335bb44073 git.patch" -sha256sums="5ffe4c5ec9e0ff4581e5b24301fd30d0964120d6b30ee78ea79f31ff48eeab73 mkinitfs-2.8.0.tar.xz -057a4c8be2867db925ac4aa5af18b9a7457d5f2d44f0fdb058270c3ad908d690 git.patch" -sha512sums="c103003f95c7d7d94daa41d0a81b210a0208c93d77203978554fb127a21e2f143b56990865fc53e2c5c732ef663603b297da63d31f915b1e3a3e0f3818aa8f2e mkinitfs-2.8.0.tar.xz -6680ccff560306e6708c94f822d7415616ce920807ab33a26228ab73ed0cbf27c44adf58fe90f590ecab86a72d1f37f2375059bff5775e760bb2a68aa1634111 git.patch" +md5sums="a6ffc5292902994f28dee3700cc9cebb mkinitfs-3.0.0.tar.xz" +sha256sums="45c0bb5972906f5b95e0bb66e45972d0752b1097c83ad31136913a09adbc796f mkinitfs-3.0.0.tar.xz" +sha512sums="a70cfb5e21b26dc15332f92c5633429144ca70053ee095eb3b0fa18900fc73200cf1f42ccd6232dede96f4b2939504f7887b0ac915871200043ed4b62c534624 mkinitfs-3.0.0.tar.xz" diff --git a/main/mkinitfs/git.patch b/main/mkinitfs/git.patch deleted file mode 100644 index ef27ea474d..0000000000 --- a/main/mkinitfs/git.patch +++ /dev/null @@ -1,1969 +0,0 @@ -diff --git a/Makefile b/Makefile -index aaa553e..5ce1962 100644 ---- a/Makefile -+++ b/Makefile -@@ -5,7 +5,7 @@ sysconfdir ?= /etc/mkinitfs - datarootdir ?= /usr/share - datadir ?= $(datarootdir)/mkinitfs - --SBIN_FILES := mkinitfs bootchartd -+SBIN_FILES := mkinitfs bootchartd nlplug-findfs - SHARE_FILES := initramfs-init fstab passwd group - CONF_FILES := mkinitfs.conf \ - features.d/ata.modules \ -@@ -25,13 +25,13 @@ CONF_FILES := mkinitfs.conf \ - features.d/gfs2.modules \ - features.d/jfs.modules \ - features.d/keymap.files \ -- features.d/kms.files \ - features.d/kms.modules \ - features.d/lvm.files \ - features.d/lvm.modules \ - features.d/network.files \ - features.d/network.modules \ - features.d/ocfs2.modules \ -+ features.d/raid.files\ - features.d/raid.modules \ - features.d/reiserfs.modules \ - features.d/scsi.modules \ -@@ -41,7 +41,7 @@ CONF_FILES := mkinitfs.conf \ - features.d/virtio.modules \ - features.d/xfs.modules - --SCRIPTS := $(SBIN_FILES) initramfs-init -+SCRIPTS := mkinitfs bootchartd initramfs-init - IN_FILES := $(addsuffix .in,$(SCRIPTS)) - - GIT_REV := $(shell test -d .git && git describe || echo exported) -@@ -62,7 +62,8 @@ SED_REPLACE := -e 's:@VERSION@:$(FULL_VERSION):g' \ - -e 's:@datadir@:$(datadir):g' - - --all: $(SCRIPTS) -+ -+all: $(SBIN_FILES) $(SCRIPTS) - - clean: - rm -f $(SCRIPTS) -@@ -71,6 +72,26 @@ help: - @echo mkinitfs $(VERSION) - @echo "usage: make install [DESTDIR=]" - -+CFLAGS ?= -Wall -Werror -g -+CFLAGS += -D_GNU_SOURCE -DDEBUG -+ -+PKGCONF ?= pkg-config -+BLKID_CFLAGS := $(shell $(PKGCONF) --cflags blkid) -+BLKID_LIBS := $(shell $(PKGCONF) --libs blkid) -+LIBKMOD_CFLAGS := $(shell $(PKGCONF) --cflags libkmod) -+LIBKMOD_LIBS := $(shell $(PKGCONF) --libs libkmod) -+CRYPTSETUP_CFLAGS := $(shell $(PKGCONF) --cflags libcryptsetup) -+CRYPTSETUP_LIBS := $(shell $(PKGCONF) --libs libcryptsetup) -+ -+CFLAGS += $(BLKID_CFLAGS) $(LIBKMOD_CFLAGS) $(CRYPTSETUP_CFLAGS) -+LIBS = $(BLKID_LIBS) $(LIBKMOD_LIBS) $(CRYPTSETUP_LIBS) -+ -+%.o: %.c -+ $(CC) $(CFLAGS) -o $@ -c $< -+ -+nlplug-findfs: nlplug-findfs.o -+ $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) -+ - .SUFFIXES: .in - .in: - ${SED} ${SED_REPLACE} ${SED_EXTRA} $< > $@ -diff --git a/arg.h b/arg.h -new file mode 100644 -index 0000000..92a313f ---- /dev/null -+++ b/arg.h -@@ -0,0 +1,39 @@ -+/* -+ * Copy me if you can. -+ * by 20h -+ */ -+ -+#ifndef __ARG_H__ -+#define __ARG_H__ -+ -+#define USED(x) ((void)(x)) -+ -+#define ARGBEGIN for (argv++, argc--;\ -+ argv[0] && argv[0][1]\ -+ && argv[0][0] == '-';\ -+ argc--, argv++) {\ -+ char _argc;\ -+ char **_argv;\ -+ if (argv[0][1] == '-' && argv[0][2] == '\0') {\ -+ argv++;\ -+ argc--;\ -+ break;\ -+ }\ -+ for (argv[0]++, _argv = argv; argv[0][0];\ -+ argv[0]++) {\ -+ if (_argv != argv)\ -+ break;\ -+ _argc = argv[0][0];\ -+ switch (_argc) -+ -+#define ARGEND }\ -+ USED(_argc);\ -+ }\ -+ USED(argv);\ -+ USED(argc); -+ -+#define EARGF(x) ((argv[1] == NULL)? ((x), abort(), (char *)0) :\ -+ (argc--, argv++, argv[0])) -+ -+#endif -+ -diff --git a/bootchartd.in b/bootchartd.in -index c4daa35..55a0883 100755 ---- a/bootchartd.in -+++ b/bootchartd.in -@@ -46,7 +46,7 @@ do_logging() - # Enable process accounting if configured - if [ "$PROCESS_ACCOUNTING" = "yes" ]; then - [ -e kernel_pacct ] || : > kernel_pacct -- accton kernel_pacct -+ accton kernel_pacct > /dev/null - fi - - # open file descriptors -@@ -98,7 +98,7 @@ do_logging() - i=$(($i + 1)) - done - -- [ -e kernel_pacct ] && accton -+ [ -e kernel_pacct ] && accton off > /dev/null - } - - # Stop the boot logger. The lock file is removed to force the loggers in -@@ -151,19 +151,18 @@ finalize() - - # Package log files - tar -zcf "$BOOTLOG_DEST" header $pacct *.log -- rm "$LOGDIR"/* -- rmdir "$LOGDIR" -+ rm -rf "$LOGDIR" - } - - case "$1" in - start-initfs) - NEWROOT="$2" -+ mkdir -p "$LOGDIR" - ( - cleanup=true - trap "not_stop_logging=false" USR1 - trap "cleanup=false; not_stop_logging=false" USR2 - -- mkdir "$LOGDIR" - cd "$LOGDIR" - do_logging - if $cleanup; then -@@ -171,18 +170,16 @@ start-initfs) - finalize - fi - ) & -- echo $! > $LOGDIR/bootchart.pid -+ echo $! > "$LOGDIR"/bootchart.pid - ;; - stop-initfs) - NEWROOT="$2" -- -- cd "$LOGDIR" -- mkdir "$NEWROOT$LOGDIR" -- cp /sbin/bootchartd $NEWROOT/sbin -- PID=`cat bootchart.pid` -+ [ -x "$NEWROOT"/sbin/bootchartd ] || cp -a /sbin/bootchartd "$NEWROOT"/sbin -+ rm -rf "$NEWROOT/$LOGDIR" -+ PID=$(cat "$LOGDIR"/bootchart.pid) - kill -USR2 $PID - wait $PID -- mv * "$NEWROOT$LOGDIR" -+ mv "$LOGDIR" "$NEWROOT" - ;; - start-rootfs) - ( -diff --git a/features.d/base.files b/features.d/base.files -index 7dd36e5..23718cb 100644 ---- a/features.d/base.files -+++ b/features.d/base.files -@@ -4,3 +4,4 @@ - /sbin/apk - /etc/modprobe.d/*.conf - /etc/mdev.conf -+/sbin/nlplug-findfs -diff --git a/features.d/bootchart.files b/features.d/bootchart.files -index 8adf4df..6f28294 100644 ---- a/features.d/bootchart.files -+++ b/features.d/bootchart.files -@@ -1,3 +1,4 @@ -+/sbin/bootchartd - /usr/bin/ac - /usr/bin/last - /usr/bin/lastcomm -@@ -5,4 +6,3 @@ - /usr/sbin/dump-acct - /usr/sbin/accton - /usr/sbin/sa -- -diff --git a/features.d/btrfs.modules b/features.d/btrfs.modules -index b5a271f..a114111 100644 ---- a/features.d/btrfs.modules -+++ b/features.d/btrfs.modules -@@ -1,2 +1,5 @@ - kernel/crypto/crc32c* -+kernel/arch/*/crypto/crc32* -+kernel/arch/*/crypto/crc32* -+kernel/crypto/crc32* - kernel/fs/btrfs -diff --git a/features.d/cryptsetup.modules b/features.d/cryptsetup.modules -index 9b63cd3..1469be7 100644 ---- a/features.d/cryptsetup.modules -+++ b/features.d/cryptsetup.modules -@@ -1,2 +1,3 @@ - kernel/crypto/* -+kernel/arch/*/crypto/* - kernel/drivers/md/dm-crypt.ko -diff --git a/features.d/kms.files b/features.d/kms.files -deleted file mode 100644 -index 9d198b2..0000000 ---- a/features.d/kms.files -+++ /dev/null -@@ -1 +0,0 @@ --lib/firmware/radeon/*.bin -diff --git a/features.d/lvm.modules b/features.d/lvm.modules -index 92f0721..3af8ef9 100644 ---- a/features.d/lvm.modules -+++ b/features.d/lvm.modules -@@ -1 +1,2 @@ - kernel/drivers/md/dm-mod.ko -+kernel/drivers/md/dm-snapshot.ko -diff --git a/features.d/raid.files b/features.d/raid.files -new file mode 100644 -index 0000000..c393dc4 ---- /dev/null -+++ b/features.d/raid.files -@@ -0,0 +1,2 @@ -+/etc/mdadm.conf -+/sbin/mdadm -diff --git a/features.d/virtio.modules b/features.d/virtio.modules -index fa74c10..b0e6c22 100644 ---- a/features.d/virtio.modules -+++ b/features.d/virtio.modules -@@ -1,2 +1,3 @@ - kernel/drivers/block/virtio* - kernel/drivers/virtio -+kernel/drivers/net/virtio_net* -diff --git a/features.d/xfs.modules b/features.d/xfs.modules -index f577bf3..2b7fd53 100644 ---- a/features.d/xfs.modules -+++ b/features.d/xfs.modules -@@ -1 +1,4 @@ -+kernel/arch/*/crypto/crc32* -+kernel/arch/*/crypto/crc32* -+kernel/crypto/crc32* - kernel/fs/xfs -diff --git a/initramfs-init.in b/initramfs-init.in -index 934fe92..cdf50b9 100755 ---- a/initramfs-init.in -+++ b/initramfs-init.in -@@ -7,7 +7,7 @@ sysroot=/sysroot - splashfile=/.splash.ctrl - - /bin/busybox mkdir -p /usr/bin /usr/sbin /proc /sys /dev $sysroot \ -- /media/cdrom /media/usb /tmp -+ /media/cdrom /media/usb /tmp /run - /bin/busybox --install -s - - # basic environment -@@ -42,30 +42,6 @@ eend() { - fi - } - --scan_drivers() { -- if [ "$KOPT_autodetect" != no ] ; then -- find /sys -name modalias | xargs sort -u | xargs modprobe -a 2> /dev/null -- fi --} -- --find_ovl() { -- local mnt="$1" -- -- if [ -n "$APKOVL" ]; then -- [ -f "$mnt/$APKOVL" ] && echo "$mnt/$APKOVL" -- return -- fi -- -- # look for apkovl's on mounted media -- set -- "$mnt"/*.apkovl.tar.gz* -- -- if [ $# -gt 1 ] ; then -- echo "ERROR: More than one apkovl file was found on $(basename $mnt). None will be read." >&2 -- return 1 -- fi -- echo "$1" --} -- - retry_mount() { - # usb might need some time to settle so we retry a few times - for i in $(seq 0 9); do -@@ -87,7 +63,6 @@ unpack_apkovl() { - fi - - # we need openssl. let apk handle deps -- find_boot_repositories > /tmp/repositories - apk add --quiet --initdb --repositories-file /tmp/repositories openssl\ - || return 1 - -@@ -110,92 +85,35 @@ unpack_apkovl() { - # find mount dir for given device in an fstab - # returns global MNTOPTS - find_mnt() { -- local search_dev="$1" fstab="$2" -- MNTOPTS= -- [ -r "$fstab" ] || return 1 -- local dev mnt fs chk -+ local search_dev="$1" -+ local fstab="$2" - case "$search_dev" in -- UUID=*|LABEL=*|/dev/*);; -- *) search_dev=/dev/$search_dev;; -+ UUID*|LABEL*) search_dev=$(findfs "$search_dev");; - esac -- local search_real_dev=$(resolve_dev $search_dev) -+ MNTOPTS= -+ [ -r "$fstab" ] || return 1 -+ local search_maj_min=$(stat -L -c '%t,%T' $search_dev) - while read dev mnt fs MNTOPTS chk; do -- local real_dev=$(resolve_dev $dev) -- local i j -- for i in "$search_dev" "$search_real_dev"; do -- [ -z "$i" ] && continue -- for j in "$dev" "$real_dev"; do -- [ -z "$j" ] && continue -- if [ "$i" = "$j" ]; then -- echo "$mnt" -- return -- fi -- done -- done -+ case "$dev" in -+ UUID*|LABEL*) dev=$(findfs "$dev");; -+ esac -+ if [ -b "$dev" ]; then -+ local maj_min=$(stat -L -c '%t,%T' $dev) -+ if [ "$maj_min" = "$search_maj_min" ]; then -+ echo "$mnt" -+ return -+ fi -+ fi - done < $fstab - MNTOPTS= - } - --# Wait for usb to settle --wait_usb() { -- if [ -n "$USB_DONE" ] || ! dmesg | grep '^usb-storage: waiting' >/dev/null; then -- return 0 -- fi -- ebegin "Waiting for USB device to settle" -- while ! dmesg | grep 'usb-storage: device scan complete' >/dev/null; do -- sleep 1 -- done -- USB_DONE=yes -- eend 0 --} -- - # add a boot service to $sysroot - rc_add() { - mkdir -p $sysroot/etc/runlevels/$2 - ln -sf /etc/init.d/$1 $sysroot/etc/runlevels/$2/$1 - } - --find_ovl_blkdev() { -- local fsmoddir=/lib/modules/$(uname -r)/kernel/fs -- blkid | while read line; do -- mod= -- UUID= -- TYPE= -- dev=${line%%: *} -- eval ${line#$dev:} -- for i in $fsmoddir/$TYPE.ko $fsmoddir/*/$TYPE.ko; do -- [ -f $fsmoddir/*/$TYPE.ko ] && mod=$i && break -- done -- [ -n "$mod" ] || continue -- mnt=/media/${UUID:-${dev##*/}} -- mkdir -p "$mnt" -- mount -o ro -t "$TYPE" "$dev" "$mnt" 2>/dev/null || continue -- ovl=$(find_ovl "$mnt") -- if [ -f "$ovl" ]; then -- echo "$ovl" -- break -- fi -- umount "$mnt" -- done --} -- --# we have issues with some slow usb 1 hosts so we add 1 second delay --# with possibility to increase delay at boot prompt with usbdelay=<sec> --find_ovl_delayed_usb() { -- local n i -- # look for apkovl -- for n in $(seq 0 ${KOPT_usbdelay:-1}); do -- # wait for usb to settle if needed -- wait_usb -- ovl=$(find_ovl_blkdev) -- if [ -f "$ovl" ]; then -- ovl_unmount="${ovl%/*}" -- return -- fi -- sleep 1 -- done --} -- - setup_inittab_console(){ - while [ $# -gt 0 ]; do - local tty=${1%,*} -@@ -225,44 +143,6 @@ setup_inittab_console(){ - done - } - --start_raid() { -- local n= i= -- case "$KOPT_root" in -- /dev/md*) n=${KOPT_root#/dev/md} ;; -- esac -- case "$KOPT_autoraid" in -- [0-9]*) n="$n $(echo $KOPT_autoraid | tr ',' ' ')" ;; -- esac -- # if kernel can autostart the raid he will -- for i in $n; do -- mknod /dev/md$i b 9 $i -- raidautorun /dev/md$i -- done -- # kernel cannot autostart newer versions of mdadm metadata -- # so we also check if mdadm binary is there -- if [ -x /sbin/mdadm ]; then -- mdadm --assemble --scan -- fi --} -- --# start cryptsetup if exists --start_cryptsetup() { -- [ -x /sbin/cryptsetup ] || return -- modprobe dm-crypt -- if [ -n "$KOPT_cryptroot" ]; then -- modprobe dm-crypt -- cryptsetup luksOpen $(resolve_dev "$KOPT_cryptroot") "$KOPT_cryptdm" -- fi --} -- --# start lvm if exists --start_lvm() { -- [ -x /sbin/lvm ] || return -- modprobe dm-mod -- lvm vgscan --mknodes --ignorelockingfailure >/dev/null 2>&1 -- lvm vgchange --ignorelockingfailure -a y >/dev/null 2>&1 --} -- - # determine the default interface to use if ip=dhcp is set - # uses the first "eth" interface. - ip_choose_if() { -@@ -332,10 +212,6 @@ configure_ip() { - ip_set "$device" "$client_ip" "$netmask" "$gw_ip" - eend $? - fi -- MAC_ADDRESS=$(cat /sys/class/net/$device/address) -- MACHINE_UUID=$(cat /sys/class/dmi/id/product_uuid) -- OVL_DEV="${OVL_DEV/{MAC\}/$MAC_ADDRESS}" -- OVL_DEV="${OVL_DEV/{UUID\}/$MACHINE_UUID}" - } - - # resolve an uuid or symlink to the real device -@@ -346,37 +222,27 @@ resolve_dev() { - esac - } - --# relocate ALPINE_MNT according given fstab --relocate_alpine_mnt() { -- local fstab="$1" -- local mnt=$(find_mnt $ALPINE_DEV $fstab) -- if [ -n "$mnt" ] && [ "$ALPINE_MNT" != "$mnt" ]; then -- mkdir -p "$mnt" -- mount -o move $ALPINE_MNT $mnt -- ALPINE_MNT=$mnt -+# relocate mountpoint according given fstab -+relocate_mount() { -+ local dir="${1}" -+ local fstab="$2" -+ local dev=$(df -P "$dir" | tail -1 | awk '{print $1}') -+ local mnt=$(find_mnt $dev $fstab) -+ if [ -n "$mnt" ]; then -+ local oldmnt=$(awk -v d=$dev '$1==d {print $2}' /proc/mounts) -+ if [ "$oldmnt" != "$mnt" ]; then -+ mkdir -p "$mnt" -+ mount -o move "$oldmnt" "$mnt" -+ fi - fi - } - --# detect filesystem type on given device/UUID --find_fs_type() { -- local dev=$(findfs $1) -- local i= -- for i in $(blkid $dev); do -- case $i in -- TYPE=*) eval "$i" -- echo $TYPE -- return -- ;; -- esac -- done --} -- - # find the dirs under ALPINE_MNT that are boot repositories - find_boot_repositories() { - if [ -n "$ALPINE_REPO" ]; then - echo "$ALPINE_REPO" - else -- find $ALPINE_MNT -name .boot_repository -type f -maxdepth 3 \ -+ find /media/* -name .boot_repository -type f -maxdepth 3 \ - | sed 's:/.boot_repository$::' - fi - } -@@ -438,63 +304,14 @@ if [ "$KOPT_dma" = no ]; then - modprobe libata dma=0 - fi - --ALPINE_DEV=${KOPT_alpine_dev%%:*} --ALPINE_DEV_FS=${KOPT_alpine_dev##*:} --if [ "$ALPINE_DEV_FS" = "$ALPINE_DEV" ]; then -- unset ALPINE_DEV_FS --fi -- --# /dev/blah:ext3 --if [ -n "$KOPT_ovl_dev" ] ; then -- OVL_DEV=${KOPT_ovl_dev%%:*} -- OVL_DEV_FS=${KOPT_ovl_dev##*:} -- if [ "$OVL_DEV_FS" = "$OVL_DEV" ]; then -- unset OVL_DEV_FS -- fi --fi -- --# http://.../blah.apkovl.tar.gz --case "$KOPT_apkovl" in -- http://*|https://|ftp://*) -- OVL_DEV="$KOPT_apkovl";; -- *:*:*) # apkovl=sda1:ext4:/subdir/host.apkovl.tar.gz -- OVL_DEV="${KOPT_apkovl%%:*}" -- OVL_DEV_FS="${KOPT_apkovl%:*}" -- OVL_DEV_FS="${OVL_DEV_FS#*:}" -- APKOVL="${KOPT_apkovl##*:}" -- ;; -- *:*) # apkovl=sda1:/subdir/host.apkovl.tar.gz -- OVL_DEV=${KOPT_apkovl%%:*} -- APKOVL=${KOPT_apkovl##*:} -- ;; -- *) # apkovl=subdir/host.apkovl.tar.gz -- APKOVL="${KOPT_apkovl}" -- ;; --esac -- --case "$ALPINE_DEV" in -- UUID=*|LABEL=*) ;; -- nfs) -- # nfs:IP:EXPORT -- ALPINE_DEV_FS="$ALPINE_DEV" -- ALPINE_DEV="${KOPT_alpine_dev:4}" -- ;; -- *) ALPINE_DEV=/dev/$ALPINE_DEV ;; --esac -- - # The following values are supported: - # alpine_repo=auto -- default, search for .boot_repository - # alpine_repo=http://... -- network repository - ALPINE_REPO=${KOPT_alpine_repo} - [ "$ALPINE_REPO" = "auto" ] && ALPINE_REPO= - --# look for standard mountpoint locations --ALPINE_MNT=$(find_mnt $ALPINE_DEV /etc/fstab) --[ -z "$ALPINE_MNT" ] && [ "$ALPINE_DEV_FS" = nfs ] && ALPINE_MNT=/media/alpine --[ -z "$ALPINE_MNT" ] && ALPINE_MNT=/media/${ALPINE_DEV##*/} -- - # hide kernel messages --[ "$KOPT_quiet" = yes ] && dmesg -n 1 -+#[ "$KOPT_quiet" = yes ] && dmesg -n 1 - - # optional blacklist - for i in ${KOPT_blacklist/,/ }; do -@@ -502,12 +319,8 @@ for i in ${KOPT_blacklist/,/ }; do - done - - # setup /dev --ebegin "Starting mdev" - mount -t devtmpfs -o exec,nosuid,mode=0755,size=2M devtmpfs /dev 2>/dev/null \ - || mount -t tmpfs -o exec,nosuid,mode=0755,size=2M tmpfs /dev --echo "/sbin/mdev" > /proc/sys/kernel/hotplug --mdev -s --RC=$? - [ -d /dev/pts ] || mkdir -m 755 /dev/pts - [ -c /dev/ptmx ] || mknod -m 666 /dev/ptmx c 5 2 - # make sure /dev/null is setup correctly -@@ -516,7 +329,6 @@ RC=$? - mount -t devpts -o gid=5,mode=0620,noexec,nosuid devpts /dev/pts - [ -d /dev/shm ] || mkdir /dev/shm - mount -t tmpfs -o nodev,nosuid,noexec shm /dev/shm --eend $RC - - # load available drivers to get access to modloop media - ebegin "Loading boot drivers" -@@ -528,34 +340,36 @@ if [ -f /etc/modules ] ; then - modprobe -q $module $args - done - fi --scan_drivers --scan_drivers - eend 0 - -+if [ -n "$KOPT_cryptroot" ]; then -+ cryptopts="-c ${KOPT_cryptroot}" -+ if [ -n "$KOPT_cryptdm" ]; then -+ cryptopts="$cryptopts -m ${KOPT_cryptdm}" -+ fi -+fi -+ - # check if root=... was set - if [ -n "$KOPT_root" ]; then - if [ "$SINGLEMODE" = "yes" ]; then - echo "Entering single mode. Type 'exit' to continue booting." - sh - fi -- # let usb settle in case we boot from usb disks -- [ -n "$KOPT_usbdelay" ] && sleep "$KOPT_usbdelay" -- wait_usb -- start=${KOPT_alpine_start:-raid,cryptsetup,lvm} -- for i in ${start//,/ }; do -- start_$i -- done -+ - ebegin "Mounting root" - if [ "$KOPT_overlaytmpfs" = "yes" ]; then -- mkdir -p /media/root-ro /media/root-rw $sysroot/media/root-ro $sysroot/media/root-rw -- retry_mount -o ro $KOPT_root /media/root-ro 2>/dev/null -+ mkdir -p /media/root-ro /media/root-rw $sysroot/media/root-ro \ -+ $sysroot/media/root-rw -+ nlplug-findfs $cryptopts -p /sbin/mdev $KOPT_root \ -+ && mount -o ro $KOPT_root /media/root-ro - mount -t tmpfs root-tmpfs /media/root-rw - mkdir -p /media/root-rw/work /media/root-rw/root - mount -t overlay -o lowerdir=/media/root-ro,upperdir=/media/root-rw/root,workdir=/media/root-rw/work overlayfs $sysroot - else -- retry_mount ${KOPT_rootfstype:+-t} ${KOPT_rootfstype} \ -+ nlplug-findfs $cryptopts -p /sbin/mdev $KOPT_root -+ mount ${KOPT_rootfstype:+-t} ${KOPT_rootfstype} \ - -o ${KOPT_rootflags:-ro} \ -- $KOPT_root $sysroot 2>/dev/null -+ $KOPT_root $sysroot - fi - - eend $? -@@ -571,35 +385,11 @@ if [ -n "$KOPT_root" ]; then - exec /bin/busybox sh - fi - --# we only want to wait for usb if really needed at this point --if [ -z "${ALPINE_DEV##*usb*}" ]; then -- wait_usb --fi -- --# IP. This shouldn't be needed if root= is set. --configure_ip -- --# incase we have alpine_dev on raid device... --start=${KOPT_alpine_start:-raid,cryptsetup,lvm} --for i in ${start//,/ }; do -- start_$i --done -- - # locate boot media and mount it - ebegin "Mounting boot media" --mkdir -p $ALPINE_MNT -- --# try detect the filesystem --if [ -z "$ALPINE_DEV_FS" ]; then -- ALPINE_DEV_FS=$(find_fs_type $ALPINE_DEV) --fi -- --if [ -n "$ALPINE_DEV_FS" ]; then -- mount_opts="-t $ALPINE_DEV_FS" -- [ "$ALPINE_DEV_FS" = "nfs" ] && mount_opts="$mount_opts -o nolock" --fi -- --retry_mount -o ro $mount_opts $ALPINE_DEV $ALPINE_MNT >/dev/null 2>&1 -+nlplug-findfs $cryptopts -p /sbin/mdev ${KOPT_debug_init:+-d} \ -+ ${KOPT_usbdelay:+-t $(( $KOPT_usbdelay * 1000 ))} \ -+ -b /tmp/repositories -a /tmp/apkovls - eend $? - - # early console? -@@ -620,27 +410,24 @@ fi - - mount -t tmpfs -o $rootflags tmpfs $sysroot - --case "$OVL_DEV" in -+case "$KOPT_apkovl" in - '') -- ovl=$(find_ovl $ALPINE_MNT) -- if ! [ -f "$ovl" ]; then -- find_ovl_delayed_usb -+ if [ -e /tmp/apkovls ]; then -+ ovl=$(head -n 1 /tmp/apkovls) - fi - ;; - http://*|https://*|ftp://*) -- ovl=/tmp/boot.apkovl.tar.gz -- wget -O "$ovl" "$OVL_DEV" || ovl= -+ configure_ip -+ -+ MAC_ADDRESS=$(cat /sys/class/net/$device/address) -+ MACHINE_UUID=$(cat /sys/class/dmi/id/product_uuid) -+ url="${KOPT_apkovl/{MAC\}/$MAC_ADDRESS}" -+ url="${url/{UUID\}/$MACHINE_UUID}" -+ ovl=/tmp/${url##*/} -+ wget -O "$ovl" "$url" || ovl= - ;; - *) -- mkdir -p /media/$OVL_DEV -- unset mount_opts -- if [ -n "$OVL_DEV_FS" ]; then -- mount_opts="-t $OVL_DEV_FS" -- fi -- -- retry_mount -o ro $mount_opts /dev/$OVL_DEV /media/$OVL_DEV \ -- >/dev/null 2>&1 -- ovl=$(find_ovl /media/$OVL_DEV) -+ ovl="$KOPT_apkovl" - ;; - esac - -@@ -660,26 +447,16 @@ if [ -f "$ovl" ]; then - eend $? $errstr || ovlfiles= - # hack, incase /root/.ssh was included in apkovl - [ -d "$sysroot/root" ] && chmod 700 "$sysroot/root" -- pkgs="$pkgs $(sed 's/\#.*//' $sysroot/etc/lbu/packages.list 2>/dev/null)" -- pkgs="$pkgs $(cat $sysroot/var/lib/apk/world \ -- $sysroot/etc/apk/world 2>/dev/null)" -- # clean up after upgrade -- rm -f $sysroot/etc/lbu/packages.list \ -- $sysroot/var/lib/apk/world -- -- # fix up inittab from pre openrc times (alpine v1.8) -- if [ -f "$sysroot"/etc/inittab ]; then -- sed -i -e 's|:/etc/init.d/rcS|:/sbin/rc sysinit|' \ -- -e 's|:/etc/init.d/rcL|:/sbin/rc default|' \ -- -e 's|:/etc/init.d/rcK|:/sbin/rc shutdown|' \ -- "$sysroot"/etc/inittab -- fi -+ pkgs="$pkgs $(cat $sysroot/etc/apk/world 2>/dev/null)" - fi -+ - if [ -f "$sysroot/etc/.default_boot_services" -o ! -f "$ovl" ]; then - # add some boot services by default - rc_add devfs sysinit - rc_add dmesg sysinit - rc_add mdev sysinit -+ rc_add hwdrivers sysinit -+ rc_add modloop sysinit - - rc_add hwclock boot - rc_add modules boot -@@ -695,17 +472,24 @@ if [ -f "$sysroot/etc/.default_boot_services" -o ! -f "$ovl" ]; then - rm -f "$sysroot/etc/.default_boot_services" - fi - --if [ "$KOPT_splash" != "no" -a -e $ALPINE_MNT/fbsplash.ppm ]; then -+if [ "$KOPT_splash" != "no" ]; then -+ for fbsplash in /media/*/fbsplash.ppm; do -+ if [ -e "$fbsplash" ]; then -+ break; -+ fi -+ done -+fi -+ -+if [ -n "$fbsplash" ] && [ -e "$fbsplash" ]; then - local config -- ebegin "Starting bootsplash (from $ALPINE_MNT)" -+ ebegin "Starting bootsplash" - mkfifo $sysroot/$splashfile -- if [ -e $ALPINE_MNT/fbsplash.cfg ]; then -- config=$ALPINE_MNT/fbsplash.cfg -- else -+ config="${fbsplash%.*}.cfg" -+ if ! [ -e "$config" ]; then - config=/tmp/fbsplash.cfg - echo "IMAGE_ALIGN=CM" > $config - fi -- setsid fbsplash -T 16 -s $ALPINE_MNT/fbsplash.ppm -i $config -f $sysroot/$splashfile & -+ setsid fbsplash -T 16 -s "$fbsplash" -i $config -f $sysroot/$splashfile & - eend 0 - else - KOPT_splash="no" -@@ -723,13 +507,13 @@ if [ -f $sysroot/etc/fstab ]; then - # move the ALPINE_MNT if ALPINE_DEV is specified in users fstab - # this is so a generated /etc/apk/repositories will use correct - # mount dir -- relocate_alpine_mnt "$sysroot"/etc/fstab --fi -- --# in case we upgrade we might need those: --rc_add hwdrivers sysinit --rc_add modloop sysinit - -+ if [ -e /tmp/repositores ]; then -+ while read dir; do -+ relocate_mount "$dir" "$sysroot"/etc/fstab -+ done < /tmp/repositories -+ fi -+fi - - # hack so we get openrc - pkgs="$pkgs alpine-base" -@@ -776,11 +560,16 @@ if [ "$KOPT_keep_apk_new" != yes ]; then - apkflags="$apkflags --clean-protected" - [ -n "$ovlfiles" ] && apkflags="$apkflags --overlay-from-stdin" - fi -+mkdir -p $sysroot/sys $sysroot/proc $sysroot/dev -+mount -o bind /sys $sysroot/sys -+mount -o bind /proc $sysroot/proc -+mount -o bind /dev $sysroot/dev - if [ -n "$ovlfiles" ]; then - apk add --root $sysroot $repo_opt $apkflags $pkgs <$ovlfiles - else - apk add --root $sysroot $repo_opt $apkflags $pkgs - fi -+umount $sysroot/sys $sysroot/proc $sysroot/dev - eend $? - - # unmount ovl mount if needed -@@ -788,9 +577,11 @@ if [ -n "$ovl_unmount" ]; then - umount $ovl_unmount 2>/dev/null - fi - --# remount ALPINE_MNT according default fstab from package --if [ -z "$has_fstab" ] && [ -f "$sysroot"/etc/fstab ]; then -- relocate_alpine_mnt "$sysroot"/etc/fstab -+# remount according default fstab from package -+if [ -z "$has_fstab" ] && [ -f "$sysroot"/etc/fstab ] && [ -f /tmp/repositories ]; then -+ while read dir; do -+ relocate_mount "$dir" "$sysroot"/etc/fstab -+ done < /tmp/repositories - fi - - # generate repositories if none exists. this needs to be done after relocation -@@ -810,10 +601,10 @@ fi - setup_inittab_console $CONSOLE - - # copy alpine release info --if ! [ -f "$sysroot"/etc/alpine-release ] && [ -f $ALPINE_MNT/.alpine-release ]; then -- cp $ALPINE_MNT/.alpine-release $sysroot/ -- ln -sf /.alpine-release $sysroot/etc/alpine-release --fi -+#if ! [ -f "$sysroot"/etc/alpine-release ] && [ -f $ALPINE_MNT/.alpine-release ]; then -+# cp $ALPINE_MNT/.alpine-release $sysroot/ -+# ln -sf /.alpine-release $sysroot/etc/alpine-release -+#fi - - ! [ -f "$sysroot"/etc/resolv.conf ] && [ -f /etc/resolv.conf ] && \ - cp /etc/resolv.conf "$sysroot"/etc -diff --git a/mkinitfs.conf b/mkinitfs.conf -index 35cc96a..67a5444 100644 ---- a/mkinitfs.conf -+++ b/mkinitfs.conf -@@ -1,2 +1,2 @@ - # run mkinitfs -L for a list of available features --features="ata base bootchart cdrom cramfs ext2 ext3 ext4 floppy keymap kms raid scsi usb virtio" -+features="ata base cdrom ext2 ext3 ext4 keymap kms mmc raid scsi usb virtio" -diff --git a/mkinitfs.in b/mkinitfs.in -index 04dc99c..c5f6434 100755 ---- a/mkinitfs.in -+++ b/mkinitfs.in -@@ -36,7 +36,7 @@ feature_files() { - - initfs_base() { - local i= dirs= glob= file= -- for i in dev proc sys sbin bin .modloop lib/modules media/cdrom \ -+ for i in dev proc sys sbin bin run .modloop lib/modules media/cdrom \ - etc/apk media/floppy media/usb newroot; do - dirs="$dirs $tmpdir/$i" - done -@@ -115,10 +115,24 @@ initfs_kmods() { - for file in $(find_kmods); do - echo "${file#/}" - done | sort -u | cpio -pdm "$tmpdir" || return 1 -+ for file in modules.order modules.builtin; do -+ if [ -f "$kerneldir"/$file ]; then -+ cp "$kerneldir"/$file "$tmpdir"/lib/modules/$kernel/ -+ fi -+ done - depmod $kernel -b "$tmpdir" - cd "$oldpwd" - } - -+initfs_firmware() { -+ rm -rf "$tmpdir"/lib/firmware -+ mkdir -p "$tmpdir"/lib/firmware -+ find "$tmpdir"/lib/modules -type f -name "*.ko" | xargs modinfo -F firmware | sort -u | while read FW; do -+ [ -e "${basedir}/lib/firmware/${FW}" ] && install -pD "${basedir}/lib/firmware/${FW}" "$tmpdir"/lib/firmware/$FW -+ done -+ return 0 -+} -+ - initfs_apk_keys() { - mkdir -p "$tmpdir"/etc/apk/keys - cp "${basedir}etc/apk/keys/"* "$tmpdir"/etc/apk/keys/ -@@ -179,7 +193,7 @@ done - shift $(( $OPTIND - 1 )) - - . $(readlink -f "$config") --features_dir=${features_dir:-"$sysconfdir/features.d"} -+features_dir=${features_dir:-"${basedir%/:-}/${sysconfdir#/}/features.d"} - [ -n "$myfeatures" ] && features="$myfeatures" - - if [ -n "$list_features" ]; then -@@ -232,6 +246,7 @@ fi - - initfs_base \ - && initfs_kmods \ -+ && initfs_firmware \ - && initfs_apk_keys \ - && initfs_cpio - rc=$? -diff --git a/nlplug-findfs.c b/nlplug-findfs.c -new file mode 100644 -index 0000000..7d1511e ---- /dev/null -+++ b/nlplug-findfs.c -@@ -0,0 +1,1021 @@ -+ -+/* -+ * Copy me if you can. -+ * by 20h -+ * -+ * Copyright (c) 2015 Natanael Copa <ncopa@alpinelinux.org> -+ */ -+ -+#ifndef _GNU_SOURCE -+#define _GNU_SOURCE -+#endif -+ -+#include <dirent.h> -+#include <err.h> -+#include <errno.h> -+#include <glob.h> -+#include <limits.h> -+#include <poll.h> -+#include <pthread.h> -+#include <stdio.h> -+#include <stdlib.h> -+#include <string.h> -+#include <termios.h> -+#include <unistd.h> -+ -+#include <sys/eventfd.h> -+#include <sys/signalfd.h> -+#include <sys/mount.h> -+#include <sys/socket.h> -+#include <sys/stat.h> -+#include <sys/types.h> -+#include <sys/uio.h> -+#include <sys/wait.h> -+ -+#include <linux/netlink.h> -+ -+#include <libkmod.h> -+#include <blkid.h> -+#include <libcryptsetup.h> -+ -+#include "arg.h" -+ -+#define DEFAULT_EVENT_TIMEOUT 250 -+/* usb mass storage needs 1 sec to settle */ -+#define USB_STORAGE_TIMEOUT 1000 -+ -+#define FOUND_DEVICE 0x1 -+#define FOUND_BOOTREPO 0x2 -+#define FOUND_APKOVL 0x4 -+ -+#define TRIGGER_THREAD 0x1 -+#define CRYPTSETUP_THREAD 0x2 -+ -+#define LVM_PATH "/sbin/lvm" -+#define MDADM_PATH "/sbin/mdadm" -+ -+static int dodebug; -+static char *default_envp[2]; -+char *argv0; -+static int use_mdadm, use_lvm; -+ -+#if defined(DEBUG) -+#include <stdarg.h> -+static void dbg(const char *fmt, ...) -+{ -+ va_list fmtargs; -+ if (!dodebug) -+ return; -+ -+ fprintf(stderr, "%s: ", argv0); -+ va_start(fmtargs, fmt); -+ vfprintf(stderr, fmt, fmtargs); -+ va_end(fmtargs); -+ fprintf(stderr, "\n"); -+} -+#else -+#define dbg(...) -+#endif -+ -+#define envcmp(env, key) (strncmp(env, key "=", strlen(key "=")) == 0) -+ -+ -+static char **clone_array(char *const *const a) -+{ -+ size_t i, s; -+ char **c, *p; -+ -+ if (!a) return 0; -+ -+ s = sizeof(char*); -+ for (i = 0; a[i]; i++) -+ s += sizeof(char*) + strlen(a[i]) + 1; -+ c = malloc(s); -+ p = (char*)(c + i + 1); -+ for (i = 0; a[i]; i++) { -+ c[i] = p; -+ p += sprintf(p, "%s", a[i]) + 1; -+ } -+ c[i] = 0; -+ return c; -+} -+ -+struct spawn_task { -+ struct spawn_task *next; -+ char **argv, **envp; -+}; -+struct spawn_manager { -+ int num_running; -+ int max_running; -+ struct spawn_task *first, *last; -+}; -+ -+static struct spawn_manager spawnmgr; -+ -+static void spawn_execute(struct spawn_manager *mgr, char **argv, char **envp) -+{ -+ pid_t pid; -+ -+ dbg("[%d/%d] running %s", mgr->num_running+1, mgr->max_running, argv[0]); -+ if (!(pid = fork())) { -+ if (execve(argv[0], argv, envp ? envp : default_envp) < 0) -+ err(1, argv[0]); -+ exit(0); -+ } -+ if (pid < 0) -+ err(1,"fork"); -+ -+ mgr->num_running++; -+} -+ -+static void spawn_queue(struct spawn_manager *mgr, char **argv, char **envp) -+{ -+ struct spawn_task *task; -+ -+ task = malloc(sizeof *task); -+ if (!task) return; -+ *task = (struct spawn_task) { -+ .next = NULL, -+ .argv = clone_array(argv), -+ .envp = clone_array(envp), -+ }; -+ if (mgr->last) { -+ mgr->last->next = task; -+ mgr->last = task; -+ } else { -+ mgr->first = mgr->last = task; -+ } -+} -+ -+static void spawn_command(struct spawn_manager *mgr, char **argv, char **envp) -+{ -+ if (!mgr->max_running) -+ mgr->max_running = sysconf(_SC_NPROCESSORS_ONLN); -+ if (mgr->num_running < mgr->max_running) -+ spawn_execute(mgr, argv, envp); -+ else -+ spawn_queue(mgr, argv, envp); -+} -+ -+static void spawn_reap(struct spawn_manager *mgr, pid_t pid) -+{ -+ mgr->num_running--; -+ if (mgr->first && mgr->num_running < mgr->max_running) { -+ struct spawn_task *task = mgr->first; -+ if (task->next) -+ mgr->first = task->next; -+ else -+ mgr->first = mgr->last = NULL; -+ spawn_execute(mgr, task->argv, task->envp); -+ free(task->argv); -+ free(task->envp); -+ free(task); -+ } -+} -+ -+static int spawn_active(struct spawn_manager *mgr) -+{ -+ return mgr->num_running || mgr->first; -+} -+ -+struct uevent { -+ char *buf; -+ size_t bufsize; -+ char *message; -+ char *subsystem; -+ char *action; -+ char *modalias; -+ char *devname; -+ char *major; -+ char *minor; -+ char devnode[256]; -+ char *envp[64]; -+}; -+ -+struct ueventconf { -+ char **program_argv; -+ char *search_device; -+ char *crypt_device; -+ char *crypt_name; -+ char crypt_devnode[256]; -+ char *subsystem_filter; -+ int modalias_count; -+ int fork_count; -+ char *bootrepos; -+ char *apkovls; -+ int timeout; -+ int efd; -+ unsigned running_threads; -+ pthread_t cryptsetup_tid; -+ pthread_mutex_t cryptsetup_mutex; -+}; -+ -+ -+static void sighandler(int sig) -+{ -+ switch (sig) { -+ case SIGHUP: -+ case SIGINT: -+ case SIGQUIT: -+ case SIGABRT: -+ case SIGTERM: -+ exit(0); -+ default: -+ break; -+ } -+} -+ -+static void initsignals(void) -+{ -+ signal(SIGHUP, sighandler); -+ signal(SIGINT, sighandler); -+ signal(SIGQUIT, sighandler); -+ signal(SIGABRT, sighandler); -+ signal(SIGTERM, sighandler); -+ signal(SIGCHLD, sighandler); -+ signal(SIGPIPE, SIG_IGN); -+} -+ -+static int init_netlink_socket(void) -+{ -+ struct sockaddr_nl nls; -+ int fd, slen; -+ -+ memset(&nls, 0, sizeof(nls)); -+ nls.nl_family = AF_NETLINK; -+ nls.nl_pid = getpid(); -+ nls.nl_groups = -1; -+ -+ fd = socket(PF_NETLINK, SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC, -+ NETLINK_KOBJECT_UEVENT); -+ if (fd < 0) -+ err(1, "socket"); -+ -+ /* kernel will not create events bigger than 16kb, but we need -+ buffer up all events during coldplug */ -+ slen = 512*1024; -+ if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &slen, -+ sizeof(slen)) < 0) { -+ err(1, "setsockopt"); -+ } -+ slen = 1; -+ if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &slen, -+ sizeof(slen)) < 0) { -+ err(1, "setsockopt"); -+ } -+ -+ if (bind(fd, (void *)&nls, sizeof(nls))) -+ err(1, "bind"); -+ -+ return fd; -+} -+ -+static int load_kmod(const char *modalias, char *driver, size_t len) -+{ -+ static struct kmod_ctx *ctx = NULL; -+ struct kmod_list *list = NULL; -+ struct kmod_list *node; -+ int r, count=0; -+ -+ if (ctx == NULL) { -+ dbg("initializing kmod"); -+ ctx = kmod_new(NULL, NULL); -+ if (ctx == NULL) -+ return -1; -+ kmod_set_log_fn(ctx, NULL, NULL); -+ r = kmod_load_resources(ctx); -+ } -+ -+ r = kmod_module_new_from_lookup(ctx, modalias, &list); -+ if (r < 0) { -+ dbg("alias '%s' lookup failure", modalias); -+ return r; -+ } -+ -+ kmod_list_foreach(node, list) { -+ struct kmod_module *mod = kmod_module_get_module(node); -+ const char *fmt; -+ r = kmod_module_probe_insert_module(mod, -+ KMOD_PROBE_APPLY_BLACKLIST, -+ NULL, NULL, NULL, NULL); -+ if (r == 0) { -+ fmt = "module '%s' inserted"; -+ count++; -+ } else if (r == KMOD_PROBE_APPLY_BLACKLIST) { -+ fmt = "module '%s' is blacklisted"; -+ } else { -+ fmt = "module '%s' failed"; -+ } -+ dbg(fmt, kmod_module_get_name(mod)); -+ if (driver) -+ strncpy(driver, kmod_module_get_name(mod), len); -+ kmod_module_unref(mod); -+ } -+ kmod_module_unref_list(list); -+ return count; -+} -+ -+static void start_mdadm(char *devnode) -+{ -+ char *mdadm_argv[] = { -+ MDADM_PATH, -+ "--incremental", -+ "--quiet", -+ devnode, -+ NULL -+ }; -+ if (use_mdadm) -+ spawn_command(&spawnmgr, mdadm_argv, 0); -+} -+ -+static void start_lvm2(char *devnode) -+{ -+ char *lvm2_argv[] = { -+ LVM_PATH, "vgchange", -+ "--activate" , "ay", "--noudevsync", "--sysinit", "-q", "-q", -+ NULL -+ }; -+ if (use_lvm) -+ spawn_command(&spawnmgr, lvm2_argv, 0); -+} -+ -+ -+static int read_pass(char *pass, size_t pass_size) -+{ -+ struct termios old_flags, new_flags; -+ int r; -+ -+ tcgetattr(STDIN_FILENO, &old_flags); -+ new_flags = old_flags; -+ new_flags.c_lflag &= ~ECHO; -+ new_flags.c_lflag |= ECHONL; -+ -+ r = tcsetattr(STDIN_FILENO, TCSANOW, &new_flags); -+ if (r < 0) { -+ warn("tcsetattr"); -+ return r; -+ } -+ -+ if (fgets(pass, pass_size, stdin) == NULL) { -+ warn("fgets"); -+ return -1; -+ } -+ pass[strlen(pass) - 1] = '\0'; -+ -+ if (tcsetattr(STDIN_FILENO, TCSANOW, &old_flags) < 0) { -+ warn("tcsetattr"); -+ return r; -+ } -+ -+ return 0; -+} -+ -+static void *cryptsetup_thread(void *data) -+{ -+ struct ueventconf *c = (struct ueventconf *)data; -+ uint64_t ok = CRYPTSETUP_THREAD; -+ struct crypt_device *cd; -+ int r, passwd_tries = 5; -+ -+ r = crypt_init(&cd, c->crypt_devnode); -+ if (r < 0) { -+ warnx("crypt_init(%s)", c->crypt_devnode); -+ goto notify_out; -+ } -+ -+ r = crypt_load(cd , CRYPT_LUKS1, NULL); -+ if (r < 0) { -+ warnx("crypt_load(%s)", c->crypt_devnode); -+ goto free_out; -+ } -+ -+ while (passwd_tries > 0) { -+ char pass[1024]; -+ -+ printf("Enter passphrase for %s: ", c->crypt_devnode); -+ fflush(stdout); -+ -+ if (read_pass(pass, sizeof(pass)) < 0) -+ goto free_out; -+ passwd_tries--; -+ -+ pthread_mutex_lock(&c->cryptsetup_mutex); -+ r = crypt_activate_by_passphrase(cd, c->crypt_name, -+ CRYPT_ANY_SLOT, -+ pass, strlen(pass), 0); -+ pthread_mutex_unlock(&c->cryptsetup_mutex); -+ -+ if (r == 0) -+ break; -+ printf("No key available with this passphrase.\n"); -+ } -+ -+free_out: -+ crypt_free(cd); -+notify_out: -+ write(c->efd, &ok, sizeof(ok)); -+ return NULL; -+} -+ -+static void start_cryptsetup(struct ueventconf *conf) -+{ -+ dbg("starting cryptsetup %s -> %s", conf->crypt_devnode, conf->crypt_name); -+ load_kmod("dm-crypt", NULL, 0); -+ pthread_create(&conf->cryptsetup_tid, NULL, cryptsetup_thread, conf); -+ conf->running_threads |= CRYPTSETUP_THREAD; -+} -+ -+static int is_mounted(const char *devnode) { -+ char line[PATH_MAX]; -+ FILE *f = fopen("/proc/mounts", "r"); -+ int r = 0; -+ if (f == NULL) -+ return 0; -+ while (fgets(line, sizeof(line), f) != NULL) { -+ strtok(line, " "); -+ if (strcmp(devnode, line) == 0) { -+ r = 1; -+ break; -+ } -+ } -+ fclose(f); -+ return r; -+} -+ -+struct recurse_opts { -+ const char *searchname; -+ void (*callback)(const char *, const void *); -+ void *userdata; -+}; -+ -+/* pathbuf needs hold PATH_MAX chars */ -+static void recurse_dir(char *pathbuf, struct recurse_opts *opts) -+{ -+ DIR *d = opendir(pathbuf); -+ struct dirent *entry; -+ -+ if (d == NULL) -+ return; -+ -+ while ((entry = readdir(d)) != NULL) { -+ size_t pathlen = strlen(pathbuf); -+ size_t namelen = strlen(entry->d_name); -+ int is_dir; -+ -+ /* d_type is not supported by all filesystems so we need -+ lstat */ -+ if (pathlen + 2 + namelen > PATH_MAX) { -+ dbg("path length overflow"); -+ continue; -+ } -+ -+ pathbuf[pathlen] = '/'; -+ strcpy(&pathbuf[pathlen+1], entry->d_name); -+ -+ if (entry->d_type == DT_UNKNOWN) { -+ /* some filesystems like iso9660 does not support -+ the d_type so we use lstat */ -+ struct stat st; -+ if (lstat(pathbuf, &st) < 0) { -+ dbg("%s: %s", pathbuf, strerror(errno)); -+ goto next; -+ } -+ is_dir = S_ISDIR(st.st_mode); -+ } else -+ is_dir = entry->d_type & DT_DIR; -+ -+ if (is_dir) { -+ if (entry->d_name[0] == '.') -+ goto next; -+ } else if (opts->searchname -+ && strcmp(entry->d_name, opts->searchname) != 0) { -+ goto next; -+ } -+ -+ if (is_dir) -+ recurse_dir(pathbuf, opts); -+ else -+ opts->callback(pathbuf, opts->userdata); -+next: -+ pathbuf[pathlen] = '\0'; -+ } -+ closedir(d); -+} -+ -+struct bootrepos { -+ char *outfile; -+ int count; -+}; -+ -+static void bootrepo_cb(const char *path, const void *data) -+{ -+ struct bootrepos *repos = (struct bootrepos *)data; -+ int fd = open(repos->outfile, O_WRONLY | O_CREAT | O_APPEND); -+ if (fd == -1) -+ err(1, "%s", repos->outfile); -+ -+ write(fd, path, strlen(path) - strlen("/.boot_repository")); -+ write(fd, "\n", 1); -+ close(fd); -+ dbg("added boot repository %s to %s\n", path, repos->outfile); -+ repos->count++; -+} -+ -+static int find_apkovl(const char *dir, const char *outfile) -+{ -+ char pattern[PATH_MAX]; -+ glob_t gl; -+ int r, fd; -+ -+ if (outfile == NULL) -+ return 0; -+ -+ snprintf(pattern, sizeof(pattern), "%s/*.apkovl.tar.gz*", dir); -+ -+ r = glob(pattern, 0, NULL, &gl); -+ if (r != 0) -+ return 0; -+ -+ fd = open(outfile, O_WRONLY | O_CREAT | O_APPEND); -+ if (fd == -1) -+ err(1, "%s", outfile); -+ -+ for (r = 0; r < gl.gl_pathc; r++) { -+ dbg("Found apkovl: %s", gl.gl_pathv[r]); -+ write(fd, gl.gl_pathv[r], strlen(gl.gl_pathv[r])); -+ write(fd, "\n", 1); -+ } -+ close(fd); -+ globfree(&gl); -+ return FOUND_APKOVL; -+} -+ -+static int find_bootrepos(const char *devnode, const char *type, -+ char *bootrepos, const char *apkovls) -+{ -+ char mountdir[PATH_MAX] = ""; -+ char *devname; -+ int r, rc = 0; -+ struct bootrepos repos = { -+ .outfile = bootrepos, -+ .count = 0, -+ }; -+ struct recurse_opts opts = { -+ .searchname = ".boot_repository", -+ .callback = bootrepo_cb, -+ .userdata = &repos, -+ }; -+ -+ -+ /* skip already mounted devices */ -+ if (is_mounted(devnode)) { -+ dbg("%s is mounted (%s). skipping", devnode, type); -+ return 0; -+ } -+ devname = strrchr(devnode, '/'); -+ -+ if (devname) -+ snprintf(mountdir, sizeof(mountdir), "/media%s", devname); -+ -+ dbg("mounting %s on %s. (%s)", devnode, mountdir, type); -+ mkdir(mountdir, 0755); -+ -+ r = mount(devnode, mountdir, type, MS_RDONLY, NULL); -+ if (r < 0) { -+ dbg("Failed to mount %s on %s: %s", -+ devnode, mountdir, strerror(errno)); -+ return 0; -+ } -+ -+ recurse_dir(mountdir, &opts); -+ if (repos.count > 0) -+ rc |= FOUND_BOOTREPO; -+ -+ if (find_apkovl(mountdir, apkovls)) -+ rc |= FOUND_APKOVL; -+ -+ if (rc == 0) -+ umount(mountdir); -+ -+ return rc; -+} -+ -+static int is_same_device(const struct uevent *ev, const char *nodepath) -+{ -+ struct stat st; -+ unsigned int maj, min; -+ if (stat(nodepath, &st) < 0) -+ return 0; -+ -+ if (ev->major == NULL || ev->minor == NULL) -+ return 0; -+ -+ maj = atoi(ev->major); -+ min = atoi(ev->minor); -+ return S_ISBLK(st.st_mode) && makedev(maj, min) == st.st_rdev; -+} -+ -+ -+static int searchdev(struct uevent *ev, const char *searchdev, char *bootrepos, -+ const char *apkovls) -+{ -+ static blkid_cache cache = NULL; -+ char *type = NULL, *label = NULL, *uuid = NULL; -+ int rc = 0; -+ -+ if (searchdev == NULL && bootrepos == NULL && apkovls == NULL) -+ return 0; -+ -+ if (searchdev && (strcmp(ev->devname, searchdev) == 0 -+ || strcmp(ev->devnode, searchdev) == 0 -+ || is_same_device(ev, searchdev))) { -+ return FOUND_DEVICE; -+ } -+ -+ if (cache == NULL) -+ blkid_get_cache(&cache, NULL); -+ -+ type = blkid_get_tag_value(cache, "TYPE", ev->devnode); -+ -+ if (searchdev != NULL) { -+ if (strncmp("LABEL=", searchdev, 6) == 0) { -+ label = blkid_get_tag_value(cache, "LABEL", ev->devnode); -+ if (label && strcmp(label, searchdev+6) == 0) -+ rc = FOUND_DEVICE; -+ } else if (strncmp("UUID=", searchdev, 5) == 0) { -+ uuid = blkid_get_tag_value(cache, "UUID", ev->devnode); -+ if (uuid && strcmp(uuid, searchdev+5) == 0) -+ rc = FOUND_DEVICE; -+ } -+ } -+ -+ if (type || label || uuid) { -+ dbg("%s:\n" -+ "\ttype='%s'\n" -+ "\tlabel='%s'\n" -+ "\tuuid='%s'\n", ev->devnode, -+ type ? type : NULL, -+ label ? label : NULL, -+ uuid ? uuid : NULL); -+ } -+ -+ if (!rc && type) { -+ if (strcmp("linux_raid_member", type) == 0) { -+ start_mdadm(ev->devnode); -+ } else if (strcmp("LVM2_member", type) == 0) { -+ start_lvm2(ev->devnode); -+ } else if (bootrepos) { -+ rc = find_bootrepos(ev->devnode, type, bootrepos, apkovls); -+ } -+ } -+ -+ if (type) -+ free(type); -+ if (label) -+ free(label); -+ if (uuid) -+ free(uuid); -+ -+ return rc; -+} -+ -+static int dispatch_uevent(struct uevent *ev, struct ueventconf *conf) -+{ -+ static int timeout_increment = USB_STORAGE_TIMEOUT; -+ -+ if (conf->subsystem_filter && ev->subsystem -+ && strcmp(ev->subsystem, conf->subsystem_filter) != 0) { -+ dbg("subsystem '%s' filtered out (by '%s').", -+ ev->subsystem, conf->subsystem_filter); -+ return 0; -+ } -+ -+ if (ev->action == NULL) -+ return 0; -+ -+ if (ev->modalias != NULL && strcmp(ev->action, "add") == 0) { -+ char buf[128]; -+ memset(buf, 0, sizeof(buf)); -+ load_kmod(ev->modalias, buf, sizeof(buf)-1); -+ conf->modalias_count++; -+ -+ /* increase timeout so usb drives gets time to settle */ -+ if (strcmp(buf, "usb_storage") == 0) { -+ conf->timeout += timeout_increment; -+ timeout_increment = 0; -+ } -+ -+ } else if (ev->devname != NULL) { -+ if (conf->program_argv[0] != NULL) { -+ spawn_command(&spawnmgr, conf->program_argv, ev->envp); -+ conf->fork_count++; -+ } -+ -+ if (ev->subsystem && strcmp(ev->subsystem, "block") == 0 -+ && strcmp(ev->action, "add") == 0) { -+ int rc; -+ -+ snprintf(ev->devnode, sizeof(ev->devnode), "/dev/%s", -+ ev->devname); -+ pthread_mutex_lock(&conf->cryptsetup_mutex); -+ rc = searchdev(ev, conf->search_device, -+ conf->bootrepos, conf->apkovls); -+ pthread_mutex_unlock(&conf->cryptsetup_mutex); -+ if (rc) -+ return rc; -+ -+ if (searchdev(ev, conf->crypt_device, NULL, NULL)) { -+ strncpy(conf->crypt_devnode, -+ conf->crypt_device[0] == '/' ? conf->crypt_device : ev->devnode, -+ sizeof(conf->crypt_devnode)); -+ start_cryptsetup(conf); -+ } -+ } -+ } -+ return 0; -+} -+ -+static int process_uevent(char *buf, const size_t len, struct ueventconf *conf) -+{ -+ struct uevent ev; -+ -+ int i, nenvp, slen = 0; -+ char *key, *value; -+ -+ memset(&ev, 0, sizeof(ev)); -+ ev.buf = buf; -+ ev.bufsize = len; -+ -+ nenvp = sizeof(default_envp) / sizeof(default_envp[0]) - 1; -+ memcpy(&ev.envp, default_envp, nenvp * sizeof(default_envp[0])); -+ -+ for (i = 0; i < len; i += slen + 1) { -+ key = buf + i; -+ value = strchr(key, '='); -+ slen = strlen(buf+i); -+ -+ if (i == 0 && slen != 0) { -+ /* first line, the message */ -+ ev.message = key; -+ continue; -+ } -+ -+ if (!slen || !value) -+ continue; -+ -+ value++; -+ if (envcmp(key, "MODALIAS")) { -+ ev.modalias = value; -+ } else if (envcmp(key, "ACTION")) { -+ ev.action = value; -+ } else if (envcmp(key, "SUBSYSTEM")) { -+ ev.subsystem = value; -+ } else if (envcmp(key, "DEVNAME")) { -+ ev.devname = value; -+ } else if (envcmp(key, "MAJOR")) { -+ ev.major = value; -+ } else if (envcmp(key, "MINOR")) { -+ ev.minor = value; -+ } -+ -+ if (!envcmp(key, "PATH")) -+ ev.envp[nenvp++]= key; -+ } -+ ev.envp[nenvp++] = 0; -+ -+ return dispatch_uevent(&ev, conf); -+} -+ -+static void trigger_uevent_cb(const char *path, const void *data) -+{ -+ int fd = open(path, O_WRONLY); -+ write(fd, "add", 3); -+ close(fd); -+} -+ -+static void *trigger_thread(void *data) -+{ -+ int fd = *(int *)data; -+ uint64_t ok = TRIGGER_THREAD; -+ struct recurse_opts opts = { -+ .searchname = "uevent", -+ .callback = trigger_uevent_cb, -+ .userdata = NULL, -+ }; -+ char path[PATH_MAX] = "/sys/bus"; -+ -+ recurse_dir(path, &opts); -+ strcpy(path, "/sys/devices"); -+ recurse_dir(path, &opts); -+ write(fd, &ok, sizeof(ok)); -+ return NULL; -+} -+ -+static void usage(int rc) -+{ -+ printf("coldplug system til given device is found\n" -+ "usage: %s [options] DEVICE\n" -+ "\n" -+ "options:\n" -+ " -a OUTFILE add paths to found apkovls to OUTFILE\n" -+ " -b OUTFILE add found boot repositories to OUTFILE\n" -+ " -c CRYPTDEVICE run cryptsetup luksOpen when CRYPTDEVICE is found\n" -+ " -h show this help\n" -+ " -m CRYPTNAME use CRYPTNAME name for crypto device mapping\n" -+ " -d enable debugging ouput\n" -+ " -f SUBSYSTEM filter subsystem\n" -+ " -p PROGRAM use PROGRAM as handler for every event with DEVNAME\n" -+ " -t TIMEOUT timeout after TIMEOUT milliseconds without uevents\n" -+ "\n", argv0); -+ -+ exit(rc); -+} -+ -+int main(int argc, char *argv[]) -+{ -+ struct pollfd fds[3]; -+ int numfds = 3; -+ int r; -+ struct ueventconf conf; -+ int event_count = 0; -+ size_t total_bytes = 0; -+ int found = 0; -+ char *program_argv[2] = {0,0}; -+ pthread_t tid; -+ sigset_t sigchldmask; -+ -+ for (r = 0; environ[r]; r++) { -+ if (envcmp(environ[r], "PATH")) -+ default_envp[0] = environ[r]; -+ } -+ -+ memset(&conf, 0, sizeof(conf)); -+ conf.program_argv = program_argv; -+ conf.timeout = DEFAULT_EVENT_TIMEOUT; -+ use_lvm = access(LVM_PATH, X_OK) == 0; -+ use_mdadm = access(MDADM_PATH, X_OK) == 0; -+ -+ argv0 = strrchr(argv[0], '/'); -+ if (argv0++ == NULL) -+ argv0 = argv[0]; -+ -+ ARGBEGIN { -+ case 'a': -+ conf.apkovls = EARGF(usage(1));; -+ break; -+ case 'b': -+ conf.bootrepos = EARGF(usage(1)); -+ break; -+ case 'c': -+ conf.crypt_device = EARGF(usage(1)); -+ break; -+ case 'h': -+ usage(0); -+ break; -+ case 'm': -+ conf.crypt_name = EARGF(usage(1)); -+ break; -+ case 'd': -+ dodebug = 1; -+ break; -+ case 'f': -+ conf.subsystem_filter = EARGF(usage(1)); -+ break; -+ case 'p': -+ conf.program_argv[0] = EARGF(usage(1)); -+ break; -+ case 't': -+ conf.timeout = atoi(EARGF(usage(1))); -+ break; -+ default: -+ usage(1); -+ } ARGEND; -+ -+ if (argc > 0) -+ conf.search_device = argv[0]; -+ -+ r = pthread_mutex_init(&conf.cryptsetup_mutex, NULL); -+ if (r < 0) -+ err(1, "pthread_mutex_init"); -+ -+ initsignals(); -+ sigemptyset(&sigchldmask); -+ sigaddset(&sigchldmask, SIGCHLD); -+ sigprocmask(SIG_BLOCK, &sigchldmask, NULL); -+ -+ fds[0].fd = init_netlink_socket(); -+ fds[0].events = POLLIN; -+ -+ fds[1].fd = signalfd(-1, &sigchldmask, SFD_NONBLOCK|SFD_CLOEXEC); -+ fds[1].events = POLLIN; -+ -+ fds[2].fd = eventfd(0, EFD_CLOEXEC); -+ fds[2].events = POLLIN; -+ conf.efd = fds[2].fd; -+ pthread_create(&tid, NULL, trigger_thread, &fds[2].fd); -+ conf.running_threads |= TRIGGER_THREAD; -+ -+ while (1) { -+ r = poll(fds, numfds, (spawn_active(&spawnmgr) || conf.running_threads) ? -1 : conf.timeout); -+ if (r == -1) { -+ if (errno == EINTR || errno == ERESTART) -+ continue; -+ err(1, "poll"); -+ } -+ if (r == 0) { -+ dbg("exit due to timeout (%i)", conf.timeout); -+ break; -+ } -+ -+ if (fds[0].revents & POLLIN) { -+ size_t len; -+ struct iovec iov; -+ char cbuf[CMSG_SPACE(sizeof(struct ucred))]; -+ char buf[16384]; -+ struct cmsghdr *chdr; -+ struct ucred *cred; -+ struct msghdr hdr; -+ struct sockaddr_nl cnls; -+ -+ iov.iov_base = &buf; -+ iov.iov_len = sizeof(buf); -+ memset(&hdr, 0, sizeof(hdr)); -+ hdr.msg_iov = &iov; -+ hdr.msg_iovlen = 1; -+ hdr.msg_control = cbuf; -+ hdr.msg_controllen = sizeof(cbuf); -+ hdr.msg_name = &cnls; -+ hdr.msg_namelen = sizeof(cnls); -+ -+ len = recvmsg(fds[0].fd, &hdr, 0); -+ if (len < 0) { -+ if (errno == EINTR) -+ continue; -+ err(1, "recvmsg"); -+ } -+ if (len < 32 || len >= sizeof(buf)) -+ continue; -+ -+ total_bytes += len; -+ chdr = CMSG_FIRSTHDR(&hdr); -+ if (chdr == NULL || chdr->cmsg_type != SCM_CREDENTIALS) -+ continue; -+ -+ /* filter out messages that are not from root or kernel */ -+ cred = (struct ucred *)CMSG_DATA(chdr); -+ if (cred->uid != 0 || cnls.nl_pid > 0) -+ continue; -+ -+ event_count++; -+ found |= process_uevent(buf, len, &conf); -+ -+ if ((found & FOUND_DEVICE) -+ || ((found & FOUND_BOOTREPO) && -+ (found & FOUND_APKOVL))) { -+ if (conf.timeout) -+ dbg("FOUND! setting timeout to 0"); -+ conf.timeout = 0; -+ } -+ } -+ -+ if (fds[0].revents & POLLHUP) { -+ dbg("parent hung up\n"); -+ break; -+ } -+ -+ if (fds[1].revents & POLLIN) { -+ struct signalfd_siginfo fdsi; -+ pid_t pid; -+ int status; -+ -+ while (read(fds[1].fd, &fdsi, sizeof fdsi) > 0) -+ ; -+ while ((pid = waitpid(-1, &status, WNOHANG)) > 0) -+ spawn_reap(&spawnmgr, pid); -+ } -+ -+ if (fds[2].revents & POLLIN) { -+ uint64_t tmask = 0; -+ if (read(fds[2].fd, &tmask, sizeof(tmask)) < 0) -+ warn("eventfd"); -+ if (tmask & TRIGGER_THREAD) { -+ dbg("terminating trigger thread"); -+ pthread_join(tid, NULL); -+ } -+ if (tmask & CRYPTSETUP_THREAD) { -+ dbg("terminating cryptsetup thread"); -+ pthread_join(conf.cryptsetup_tid, NULL); -+ } -+ conf.running_threads &= ~tmask; -+ } -+ } -+ close(fds[2].fd); -+ pthread_mutex_destroy(&conf.cryptsetup_mutex); -+ -+ dbg("modaliases: %i, forks: %i, events: %i, total bufsize: %zu", -+ conf.modalias_count, -+ conf.fork_count, -+ event_count, total_bytes); -+ -+ return found ? 0 : 1; -+} |