diff options
author | Natanael Copa <ncopa@alpinelinux.org> | 2015-10-20 12:45:27 +0000 |
---|---|---|
committer | Natanael Copa <ncopa@alpinelinux.org> | 2015-10-21 10:08:06 +0200 |
commit | 12bb12cf973aaf5bb8eed20382443961754e9583 (patch) | |
tree | 8f4f1b0134ea11d8131e7a429aeb4bdb5c08be8b /main/mkinitfs | |
parent | 0ae472b4ea0ec22d51d4b186b4bf368cf1edb3e3 (diff) | |
download | aports-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/APKBUILD | 21 | ||||
-rw-r--r-- | main/mkinitfs/git.patch | 1613 |
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; ++} ++ ++ |