aboutsummaryrefslogtreecommitdiffstats
path: root/main/mkinitfs
diff options
context:
space:
mode:
authorNatanael Copa <ncopa@alpinelinux.org>2015-10-20 12:45:27 +0000
committerNatanael Copa <ncopa@alpinelinux.org>2015-10-21 10:08:06 +0200
commit12bb12cf973aaf5bb8eed20382443961754e9583 (patch)
tree8f4f1b0134ea11d8131e7a429aeb4bdb5c08be8b /main/mkinitfs
parent0ae472b4ea0ec22d51d4b186b4bf368cf1edb3e3 (diff)
downloadaports-12bb12cf973aaf5bb8eed20382443961754e9583.tar.bz2
aports-12bb12cf973aaf5bb8eed20382443961754e9583.tar.xz
main/mkinitfs: update to development version with nlplug-findfs
Diffstat (limited to 'main/mkinitfs')
-rw-r--r--main/mkinitfs/APKBUILD21
-rw-r--r--main/mkinitfs/git.patch1613
2 files changed, 1622 insertions, 12 deletions
diff --git a/main/mkinitfs/APKBUILD b/main/mkinitfs/APKBUILD
index be8a44fdc0..4880db3a65 100644
--- a/main/mkinitfs/APKBUILD
+++ b/main/mkinitfs/APKBUILD
@@ -1,18 +1,18 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=mkinitfs
-pkgver=2.8.0
+pkgver=2.8.0_git20151020
_ver=${pkgver%_git*}
-pkgrel=3
+pkgrel=0
pkgdesc="Tool to generate initramfs images for Alpine"
url=http://git.alpinelinux.org/cgit/mkinitfs
-depends="acct busybox apk-tools>=2.0 lddtree>=1.25"
+makedepends="kmod-dev util-linux-dev linux-headers"
+depends="acct busybox apk-tools>=2.0 lddtree>=1.25 kmod"
install="$pkgname.pre-upgrade"
triggers="$pkgname.trigger=/usr/share/kernel/*"
source="http://dev.alpinelinux.org/archive/$pkgname/$pkgname-$_ver.tar.xz
- 0001-mkinitfs-copy-modules.order-and-modules.builtin-if-t.patch
- 0001-improve-default-config.patch
+ git.patch
"
-arch="noarch"
+arch="all"
license="GPL2"
_builddir="$srcdir"/$pkgname-$_ver
@@ -37,11 +37,8 @@ package() {
make install DESTDIR="$pkgdir" || return 1
}
md5sums="1a321336d97b22257349ddd36884ec34 mkinitfs-2.8.0.tar.xz
-25e11e719a8d90e1e19079c1ba517285 0001-mkinitfs-copy-modules.order-and-modules.builtin-if-t.patch
-63132efa1597953b89e63d4993db1e99 0001-improve-default-config.patch"
+14ca0439d28186fc13f2d115411a0a79 git.patch"
sha256sums="5ffe4c5ec9e0ff4581e5b24301fd30d0964120d6b30ee78ea79f31ff48eeab73 mkinitfs-2.8.0.tar.xz
-892248aa8561596845794f1a3682456eaedcb7a158b19be40292363856c0a826 0001-mkinitfs-copy-modules.order-and-modules.builtin-if-t.patch
-64c5ec7dbd15b39e483b9ff51dc6f033a6902601e16fc420a76265f9eb8f0608 0001-improve-default-config.patch"
+f95b76a4d4cdbc58b923ff06da954d357372935317e615274d18b5c85719f93b git.patch"
sha512sums="c103003f95c7d7d94daa41d0a81b210a0208c93d77203978554fb127a21e2f143b56990865fc53e2c5c732ef663603b297da63d31f915b1e3a3e0f3818aa8f2e mkinitfs-2.8.0.tar.xz
-4b5e259a5fccef757bc6c7fe79a6ce71e91c210e7f53cfd8e6fbff2737acb3bae7e915a13f3523ff46689480aa0eb7aba5419ea31c7c814e47f4db06faf7746c 0001-mkinitfs-copy-modules.order-and-modules.builtin-if-t.patch
-2571ce198e3f2b951a0a273b74c76af8465306f66051e92ce221ff087531ad6a64540091e43a9015688b7e59f6c1310042d9839cf58c70759624d912923dc922 0001-improve-default-config.patch"
+624ab23c0ebc5544b4ff1daed28b13643dd4b8e723a0b682c5a2528aaf989f43b82d39884f5ca354b5180db4945a02f18d1fde1b791d95326a70cbc21b8a5aea git.patch"
diff --git a/main/mkinitfs/git.patch b/main/mkinitfs/git.patch
new file mode 100644
index 0000000000..d0f183410c
--- /dev/null
+++ b/main/mkinitfs/git.patch
@@ -0,0 +1,1613 @@
+diff --git a/Makefile b/Makefile
+index aaa553e..a62c294 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 \
+@@ -32,6 +32,7 @@ CONF_FILES := mkinitfs.conf \
+ 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 +42,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 +63,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 +73,24 @@ 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)
++
++CFLAGS += $(BLKID_CFLAGS) $(LIBKMOD_CFLAGS)
++LIBS = $(BLKID_LIBS) $(LIBKMOD_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/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/initramfs-init.in b/initramfs-init.in
+index 934fe92..ca4a5d5 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
+
+@@ -136,66 +111,12 @@ find_mnt() {
+ 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 +146,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 +215,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 +225,23 @@ 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
++# relocate mountpoint according given fstab
++relocate_mount() {
++ local dir="${1%%/}"
++ local fstab="$2"
++ local mnt=$(find_mnt $dir $fstab)
++ if [ -n "$mnt" ] && [ "$dir" != "$mnt" ]; then
+ mkdir -p "$mnt"
+- mount -o move $ALPINE_MNT $mnt
+- ALPINE_MNT=$mnt
++ mount -o move "$dir" "$mnt"
+ 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 +303,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 +318,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 +328,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,8 +339,6 @@ if [ -f /etc/modules ] ; then
+ modprobe -q $module $args
+ done
+ fi
+-scan_drivers
+-scan_drivers
+ eend 0
+
+ # check if root=... was set
+@@ -538,24 +347,27 @@ if [ -n "$KOPT_root" ]; 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
++
++ if [ -n "$KOPT_cryptroot" ]; then
++ cryptopts="-c ${KOPT_cryptroot}"
++ if [ -n "$KOPT_cryptdm" ]; then
++ cryptopts="$cryptopts -m ${KOPT_cryptdm}"
++ fi
++ fi
+ 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 -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 -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 +383,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 -p /sbin/mdev ${KOPT_debug_init:+-d} \
++ ${KOPT_usbdelay:+-t $(( $KOPT_usbdelay * 1000 ))} \
++ -b /tmp/repositories -a /tmp/apkovls
+ eend $?
+
+ # early console?
+@@ -620,27 +408,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 +445,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 +470,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 +505,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
++ cut -d/ -f1-3 < /tmp/repositories | while read dir; do
++ relocate_mount "$dir" "$sysroot"/etc/fstab
++ done
++ fi
++fi
+
+ # hack so we get openrc
+ pkgs="$pkgs alpine-base"
+@@ -776,11 +558,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 +575,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
++ cut -d/ -f1-3 < /tmp/repositories | while read dir; do
++ relocate_mount "$dir" "$sysroot"/etc/fstab
++ done
+ fi
+
+ # generate repositories if none exists. this needs to be done after relocation
+@@ -810,10 +599,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..14c728f 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,6 +115,11 @@ 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"
+ }
+@@ -179,7 +184,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
+diff --git a/nlplug-findfs.c b/nlplug-findfs.c
+new file mode 100644
+index 0000000..547fb76
+--- /dev/null
++++ b/nlplug-findfs.c
+@@ -0,0 +1,778 @@
++
++/*
++ * 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 <unistd.h>
++
++#include <sys/eventfd.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 "arg.h"
++
++#define DEFAULT_EVENT_TIMEOUT 250
++#define USB_STORAGE_TIMEOUT 2000
++
++#define FOUND_DEVICE 0x1
++#define FOUND_BOOTREPO 0x2
++#define FOUND_APKOVL 0x4
++
++static int dodebug;
++char *argv0;
++
++#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
++
++struct uevent {
++ char *buf;
++ size_t bufsize;
++ char *message;
++ char *subsystem;
++ char *action;
++ char *modalias;
++ char *devname;
++ char *major;
++ char *minor;
++ char *driver;
++ char devnode[256];
++};
++
++struct ueventconf {
++ char **program_argv;
++ char *search_device;
++ char *crypt_device;
++ char *crypt_name;
++ char *subsystem_filter;
++ int modalias_count;
++ int fork_count;
++ char *bootrepos;
++ char *apkovls;
++ int timeout;
++};
++
++
++static void sighandler(int sig)
++{
++ switch(sig) {
++ case SIGHUP:
++ case SIGINT:
++ case SIGQUIT:
++ case SIGABRT:
++ case SIGTERM:
++ exit(0);
++ break;
++ default:
++ break;
++ }
++}
++
++static void initsignals(void)
++{
++ signal(SIGHUP, sighandler);
++ signal(SIGINT, sighandler);
++ signal(SIGQUIT, sighandler);
++ signal(SIGABRT, sighandler);
++ signal(SIGTERM, 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;
++}
++
++void run_child(char **argv)
++{
++ pid_t pid;
++
++ if (!(pid = fork())) {
++ dbg("running %s", argv[0]);
++ if (execv(argv[0], argv) < 0)
++ err(1, argv[0]);
++ exit(0);
++ }
++ if (pid < 0)
++ err(1,"fork");
++
++ waitpid(pid, NULL, 0);
++}
++
++
++int load_kmod(const char *modalias)
++{
++ 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));
++ kmod_module_unref(mod);
++ }
++ kmod_module_unref_list(list);
++ return count;
++}
++
++void start_mdadm(char *devnode)
++{
++ char *mdadm_argv[] = {
++ "/sbin/mdadm",
++ "--incremental",
++ "--quiet",
++ devnode,
++ NULL
++ };
++ run_child(mdadm_argv);
++}
++
++void start_lvm2(char *devnode)
++{
++ char *lvm2_argv[] = {
++ "/sbin/lvm", "vgchange",
++ "--activate" , "ay", "--noudevsync", "--sysinit",
++ NULL
++ };
++ run_child(lvm2_argv);
++}
++
++void start_cryptsetup(char *devnode, char *cryptdm)
++{
++ char *cryptsetup_argv[] = {
++ "/sbin/cryptsetup", "luksOpen",
++ devnode, cryptdm ? cryptdm : "crypdm", NULL
++ };
++ load_kmod("dm-crypt");
++ run_child(cryptsetup_argv);
++}
++
++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 */
++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;
++};
++
++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;
++}
++
++int searchdev(char *devname, const char *searchdev, char *bootrepos,
++ const char *apkovls)
++{
++ static blkid_cache cache = NULL;
++ char *type = NULL, *label = NULL, *uuid = NULL;
++ char devnode[256];
++ int rc = 0;
++
++ if (searchdev == NULL && bootrepos == NULL && apkovls == NULL)
++ return 0;
++
++ if (searchdev && strcmp(devname, searchdev) == 0) {
++ return FOUND_DEVICE;
++ }
++
++ if (cache == NULL)
++ blkid_get_cache(&cache, NULL);
++
++ snprintf(devnode, sizeof(devnode), "/dev/%s", devname);
++ type = blkid_get_tag_value(cache, "TYPE", devnode);
++
++ if (searchdev != NULL) {
++ if (strncmp("LABEL=", searchdev, 6) == 0) {
++ label = blkid_get_tag_value(cache, "LABEL", 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", 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", devnode,
++ type ? type : NULL,
++ label ? label : NULL,
++ uuid ? uuid : NULL);
++ }
++
++ if (!rc && type) {
++ if (strcmp("linux_raid_member", type) == 0) {
++ start_mdadm(devnode);
++ } else if (strcmp("LVM2_member", type) == 0) {
++ start_lvm2(devnode);
++ } else if (bootrepos) {
++ rc = find_bootrepos(devnode, type, bootrepos, apkovls);
++ }
++ }
++
++ if (type)
++ free(type);
++ if (label)
++ free(label);
++ if (uuid)
++ free(uuid);
++
++ return rc;
++}
++
++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) {
++ load_kmod(ev->modalias);
++ conf->modalias_count++;
++
++ } else if (ev->driver != NULL && strcmp(ev->driver, "usb-storage") == 0) {
++ conf->timeout += timeout_increment;
++ timeout_increment = 0;
++
++ } else if (ev->devname != NULL) {
++ if (conf->program_argv[0] != NULL) {
++ run_child(conf->program_argv);
++ 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);
++ rc = searchdev(ev->devname, conf->search_device,
++ conf->bootrepos, conf->apkovls);
++ if (rc)
++ return rc;
++
++ if (searchdev(ev->devname, conf->crypt_device, NULL,
++ NULL))
++ start_cryptsetup(ev->devnode, conf->crypt_name);
++ }
++ }
++ return 0;
++}
++
++int process_uevent(char *buf, const size_t len, struct ueventconf *conf)
++{
++ struct uevent ev;
++
++ int i, slen = 0;
++ char *key, *value;
++
++ memset(&ev, 0, sizeof(ev));
++ ev.buf = buf;
++ ev.bufsize = len;
++ clearenv();
++ setenv("PATH", "/sbin:/bin", 1);
++
++ 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)
++ continue;
++
++ value[0] = '\0';
++ value++;
++
++ if (strcmp(key, "MODALIAS") == 0) {
++ ev.modalias = value;
++ } else if (strcmp(key, "ACTION") == 0) {
++ ev.action = value;
++ } else if (strcmp(key, "SUBSYSTEM") == 0) {
++ ev.subsystem = value;
++ } else if (strcmp(key, "DEVNAME") == 0) {
++ ev.devname = value;
++ } else if (strcmp(key, "MAJOR") == 0) {
++ ev.major = value;
++ } else if (strcmp(key, "MINOR") == 0) {
++ ev.minor = value;
++ } else if (strcmp(key, "DRIVER") == 0) {
++ ev.driver = value;
++ }
++
++ if (strcmp(key, "PATH")) {
++ setenv(key, value, 1);
++ }
++ }
++ return dispatch_uevent(&ev, conf);
++}
++
++void trigger_uevent_cb(const char *path, const void *data)
++{
++ int fd = open(path, O_WRONLY);
++ write(fd, "add", 3);
++ close(fd);
++}
++
++void *trigger_thread(void *data)
++{
++ int fd = *(int *)data;
++ uint64_t ok = 1;
++ 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;
++}
++
++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[2];
++ int numfds = 2;
++ int r;
++ struct ueventconf conf;
++ int event_count = 0;
++ size_t total_bytes;
++ int found = 0, trigger_running = 0;
++ char *program_argv[2] = {0,0};
++ pthread_t tid;
++
++ memset(&conf, 0, sizeof(conf));
++ conf.program_argv = program_argv;
++ conf.timeout = DEFAULT_EVENT_TIMEOUT;
++ 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];
++
++ initsignals();
++
++ fds[0].fd = init_netlink_socket();
++ fds[0].events = POLLIN;
++
++ fds[1].fd = eventfd(0, EFD_CLOEXEC);
++ fds[1].events = POLLIN;
++
++ pthread_create(&tid, NULL, trigger_thread, &fds[1].fd);
++ trigger_running = 1;
++
++ while (1) {
++ 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;
++
++ r = poll(fds, numfds, trigger_running ? -1 : conf.timeout);
++ if (r == -1)
++ err(1, "poll");
++
++ if (r == 0) {
++ dbg("exit due to timeout");
++ break;
++ }
++
++ if (numfds > 1 && fds[1].revents & POLLIN) {
++ close(fds[1].fd);
++ fds[1].fd = -1;
++ numfds--;
++ trigger_running = 0;
++ pthread_join(tid, NULL);
++ }
++
++ if (!(fds[0].revents & POLLIN))
++ continue;
++
++ 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))) {
++ dbg("setting timeout to 0");
++ conf.timeout = 0;
++ }
++
++ if (fds[0].revents & POLLHUP) {
++ dbg("parent hung up\n");
++ break;
++ }
++ }
++
++ dbg("modaliases: %i, forks: %i, events: %i, total bufsize: %zu",
++ conf.modalias_count,
++ conf.fork_count,
++ event_count, total_bytes);
++
++ return found ? 0 : 1;
++}
++
++