source: trunk/debirf/fs/usr/bin/debirf @ 914

Last change on this file since 914 was 914, checked in by dkg, 5 years ago

debirf: handling break={top,preunpack,bottom} from kernel command line within nest. (closes #55)

  • Property svn:executable set to *
File size: 11.3 KB
Line 
1#!/bin/bash -e
2
3# debirf: script to build debirf system.
4#
5# The debirf scripts were written by
6# Jameson Rollins <jrollins@fifthhorseman.net>
7# and
8# Daniel Kahn Gillmor <dkg-debian.org@fifthhorseman.net>.
9#
10# They are Copyright 2007, and are all released under the GPL,
11# version 3 or later.
12
13###############################################################
14### VARIABLES
15
16CMD=$(basename $0)
17
18DEBIRF_COMMON=${DEBIRF_COMMON:-"/usr/share/debirf/common"}
19source "$DEBIRF_COMMON"
20
21# default build type
22export ROOT_BUILD=false
23
24# stages to run by default
25STAGE_ROOT=true
26STAGE_MODULES=true
27STAGE_INITRD=true
28
29ROOT_WARNING=true
30
31# location of devices.tar.gz file
32export DEVICE_ARCHIVE=/usr/share/debirf/devices.tar.gz
33
34# list of packages to include/exclude from debootstrap
35export INCLUDE=less,udhcpc
36export EXCLUDE=apt-utils,bsdmainutils,cron,ed,dhcp3-common,dhcp3-client,info,logrotate,man-db,manpages,tasksel,tasksel-data,tcpd,traceroute
37
38###############################################################
39### FUNCTIONS
40
41usage() {
42    cat <<EOF
43Usage: $CMD [options] profile
44Create a debirf kernel and initramfs.  The 'profile' is a path to a debirf
45profile directory.
46
47options:
48  -h|--help               this help message
49  -c|--check-vars         check variables before make
50  -n|--new                create new root, even if old one exists
51  -o|--overwrite          debootstrap on top of old root if it exists
52  -s|--skip               skip debootstrap step if old root exists
53  -r|--root-build         use real chroot to build instead of fakechroot
54                          (requires superuser privileges or CAP_SYS_CHROOT)
55  -w|--no-warning         skip superuser warning
56  -i|--initrd-only        remake initramfs from existing root
57  -k|--kernel=KERNEL      install KERNEL .deb, instead of default kernel
58EOF
59}
60
61usage_profile() {
62    cat <<EOF
63It looks like your profile is not correctly formed.  Please refer to the
64README file included with this package on how to setup a profile.
65EOF
66}
67
68failure() {
69    echo "$1" >&2
70    exit ${2:-'1'}
71}
72
73create_debootstrap() {
74    mkdir -p "$DEBIRF_ROOT"
75    if [ "$ROOT_BUILD" = 'true' ] ; then
76        /usr/sbin/debootstrap --exclude="$EXCLUDE" "$DEBIRF_DISTRO" "$DEBIRF_ROOT" "$DEBIRF_MIRROR"
77    else
78        fakeroot_if_needed fakechroot /usr/sbin/debootstrap --variant=fakechroot --include="$INCLUDE" --exclude="$EXCLUDE" "$DEBIRF_DISTRO" "$DEBIRF_ROOT" "$DEBIRF_MIRROR"
79    fi
80    mv "$DEBIRF_ROOT"/var/log/bootstrap.log "$DEBIRF_BUILDD"/.bootstrap.log
81}
82
83# fix the device tree in the debirf root if fakechroot variant was
84# used with debootstrap (default non-privileged behavior)
85fix_dev() {
86    if [ -L "$DEBIRF_ROOT"/dev -o ! -d "$DEBIRF_ROOT"/dev ] ; then
87        msg "fixing debirf root dev tree..."
88
89        # remove old dev
90        fakeroot_if_needed rm -f "$DEBIRF_ROOT"/dev
91
92        # create new dev from devices archive
93        fakeroot_if_needed sh -c "cd $DEBIRF_ROOT; tar -xzf $DEVICE_ARCHIVE"
94
95        # create /dev/console
96        fakeroot_if_needed sh -c "mknod $DEBIRF_ROOT/dev/console c 5 1; chmod 0600 $DEBIRF_ROOT/dev/console"
97    fi
98}
99export -f fix_dev
100
101run_modules() {
102    # export all the DEBIRF_* environment variables:
103    for var in ${!DEBIRF_*}; do
104        export $var
105    done
106    fakeroot_if_needed run-parts --verbose --exit-on-error "$DEBIRF_MODULES"
107}
108
109# pack the rootfs archive
110# takes one input argument as name of output archive file
111pack_rootfs() {
112    # need to pack archive in fakechroot/chroot so that symlinks correctly
113    # point within debirf root, instead of to host path
114    fakeroot_if_needed fakechroot chroot "$DEBIRF_ROOT" sh -c "find * | cpio --create -H newc" | gzip > "$1"
115}
116export -f pack_rootfs
117
118
119## create_initrd functions
120# stupid simple method
121create_initrd_stupid_simple() {
122    fakeroot_if_needed ln -sf /sbin/init "$DEBIRF_ROOT/init"
123    pack_rootfs "$DEBIRF_INITRD"
124}
125
126# nested cpio archives
127create_initrd_nested() {
128    local util lib
129    local NEST_ROOT="$DEBIRF_BUILDD"/nest
130
131    # make the nested root
132    rm -rf "$NEST_ROOT"
133    mkdir -p "$NEST_ROOT"/{bin,lib}
134
135    # copy needed executables into nest
136    cp -f /bin/{busybox,cpio} "$NEST_ROOT"/bin/
137    for util in sh mkdir mount ls gunzip grep awk free grep umount; do
138        ln "$NEST_ROOT"/bin/busybox "$NEST_ROOT"/bin/"$util"
139    done
140    cp -f /usr/lib/klibc/bin/run-init "$NEST_ROOT"/bin/
141
142    # copy in needed libraries
143    for lib in $(ldd "$NEST_ROOT"/bin/* | egrep '*.so.[[:digit:]]+ \(0x[[:xdigit:]]{8}\)$' | sed -r 's|.*[[:space:]](/[^[[:space:]]*)[[:space:]]\(0x[[:xdigit:]]{8}\)$|\1|' | sort -u) ; do
144        # pull libraries from most basic place libraries can live
145        # (avoid arch change between build env and debirf)
146        lib=/lib/$(basename "$lib")
147        echo -e "$lib\n$(readlink -f $lib)" | cpio --pass-through --make-directories "$NEST_ROOT"/
148    done
149    cp -f /lib/klibc-* "$NEST_ROOT"/lib/
150
151    # create nest init
152    cat > "$NEST_ROOT"/init <<EOF
153#!/bin/sh
154mkdir /proc
155mount -t proc proc /proc
156if (grep -q break=top /proc/cmdline); then
157  echo "honoring break=top kernel arg"
158  /bin/sh
159fi
160mkdir /newroot
161MEMSIZE=\$(free | grep 'Mem:' | awk '{ print \$2 }')
162mount -t tmpfs -o size=\${MEMSIZE}k tmpfs /newroot
163if (grep -q break=preunpack /proc/cmdline); then
164  echo "honoring break=preunpack kernel arg"
165  /bin/sh
166fi
167cd /newroot
168echo unpacking rootfs...
169# specify /bin/cpio so that it gets used instead of the busybox builtin
170# busybox cpio returns "need to fix this" when unpacking hard links
171gunzip - < /rootfs.cgz | /bin/cpio -i
172if (grep -q break=bottom /proc/cmdline); then
173  echo "honoring break=bottom kernel arg"
174  /bin/sh
175fi
176umount /proc
177echo running /sbin/init...
178exec /bin/run-init . /sbin/init < ./dev/console > ./dev/console
179EOF
180    chmod a+x "$NEST_ROOT"/init
181
182    msg "creating rootfs.cgz..."
183    fakeroot_if_needed ln -sf /sbin/init "$DEBIRF_ROOT/init"
184    pack_rootfs "$NEST_ROOT"/rootfs.cgz
185
186    msg "creating wrapper cgz..."
187    fakeroot_if_needed sh -c "cd $NEST_ROOT && find * | cpio --create -H newc" | gzip > "$DEBIRF_INITRD"
188}
189
190###############################################################
191### MAIN
192
193# option parsing
194TEMP=$(getopt --options -hcnosrwik: --longoptions help,check-vars,new,overwrite,skip,root-build,no-warning,initrd-only,kernel: -n "$CMD" -- "$@")
195
196if [ $? != 0 ] ; then
197    echo "Invalid options." >&2
198    usage
199    exit 1
200fi
201
202# Note the quotes around `$TEMP': they are essential!
203eval set -- "$TEMP"
204
205while true ; do
206    case "$1" in
207        -h|--help)
208            usage
209            exit 0
210            ;;
211        -c|--check-vars)
212            CHECK_VARS=true
213            shift 1
214            ;;
215        -n|--new)
216            WRITE_MODE=rewrite
217            shift 1
218            ;;
219        -o|--overwrite)
220            WRITE_MODE=overwrite
221            shift 1
222            ;;
223        -s|--skip)
224            WRITE_MODE=skip
225            shift 1
226            ;;
227        -r|--root-build)
228            ROOT_BUILD=true
229            shift 1
230            ;;
231        -w|--no-warning)
232            ROOT_WARNING=false
233            shift 1
234            ;;
235        -i|--initrd-only)
236            STAGE_ROOT=false
237            STAGE_MODULES=false
238            shift 1
239            ;;
240        -k|--kernel)
241            DEBIRF_KERNEL_PACKAGE="$2"
242            shift 2
243            ;;
244        --)
245            shift
246            ;;
247        *)
248            if (( $# < 1 )) ; then
249                echo "Improper number of input arguments."
250                usage
251                exit 1
252            fi
253            DEBIRF_PROFILE="$1"
254            break
255            ;;
256    esac
257done
258
259if [ $(id -u) = '0' ] ; then
260    cat <<EOF
261Warning: You are running debirf as root.  There is a potential
262for improperly written modules to damage your system.
263EOF
264    if [ "$ROOT_WARNING" = 'true' ] ; then
265        read -p "Are you sure you wish to continue? [y|N]: " OK; OK=${OK:=N}
266        if [ "${OK/y/Y}" != 'Y' ] ; then
267            failure "aborting."
268        fi
269    fi
270fi
271
272if [ "$DEBIRF_KERNEL_PACKAGE" ] ; then
273    if [ -f "$DEBIRF_KERNEL_PACKAGE" ] ; then
274        echo "Using kernel package '$DEBIRF_KERNEL_PACKAGE'."
275    else
276        failure "Kernel package '$DEBIRF_KERNEL_PACKAGE' not found."
277    fi
278fi
279
280# source debirf.conf defaults
281source /usr/share/debirf/debirf.conf.defaults
282
283# check profile
284if [ -d "$DEBIRF_PROFILE" ] ; then
285    echo "Loading profile '$DEBIRF_PROFILE'..."
286    DEBIRF_CONF="$DEBIRF_PROFILE/debirf.conf"
287    DEBIRF_MODULES="$DEBIRF_PROFILE/modules"
288else
289    echo "Profile '$DEBIRF_PROFILE' not found."
290    usage_profile
291    exit 1
292fi
293
294# source profile debirf.conf
295if [ -f "$DEBIRF_CONF" ] ; then
296    source "$DEBIRF_CONF"
297else
298    echo "Configuration file '$DEBIRF_CONF' not found."
299    usage_profile
300    exit 1
301fi
302
303# check modules directory
304if [ ! -d "$DEBIRF_MODULES" ] || [ -z "$(ls "$DEBIRF_MODULES")" ] ; then
305    echo "Modules directoy '$DEBIRF_MODULES' does not exist or is empty."
306    usage_profile
307    exit 1
308fi
309for MODULE in $(find "$DEBIRF_MODULES") ; do
310    if [ ! -s "$MODULE" ] ; then
311        failure "Module '$MODULE' is a broken link or empty file."
312    fi
313done
314
315# check buildd
316if [ -z "$DEBIRF_BUILDD" ] ; then
317    failure "DEBIRF_BUILDD is not set."
318fi
319
320# set root directory
321DEBIRF_ROOT="$DEBIRF_BUILDD/root"
322
323# set fakechroot save file
324DEBIRF_FAKEROOT_STATE="$DEBIRF_BUILDD/.fakeroot-state.${DEBIRF_LABEL}"
325if [ "$ROOT_BUILD" != 'true' ] ; then
326    > "$DEBIRF_FAKEROOT_STATE"
327fi
328
329# check variables
330if [ "$CHECK_VARS" ] ; then
331    echo "Debirf variables:"
332    for var in ${!DEBIRF_*}; do
333        if [ $var ] ; then
334            export $var
335        else
336            failure "Variable '$var' not properly set."
337        fi
338    done
339    env | /bin/grep "^DEBIRF_"
340    read -p "enter to continue: " OK
341fi
342
343### BUILD ROOT
344if [ "$STAGE_ROOT" = 'true' ] ; then
345
346# determine write mode
347if [ -d "$DEBIRF_ROOT" ] ; then
348    echo "Debirf root already exists."
349    if [ -z "$WRITE_MODE" ] ; then
350        echo "Select one of the following:"
351        CASE1='new: delete the old root and create a new one'
352        CASE2='overwrite: leave the old root and debootstrap on top of it'
353        CASE3='skip: skip building the root and go right to installing modules'
354        CASE4='exit'
355        select CASE in "$CASE1" "$CASE2" "$CASE3" "$CASE4" ; do
356            case "$REPLY" in
357                1)
358                    WRITE_MODE=rewrite
359                    ;;
360                2)
361                    WRITE_MODE=overwrite
362                    ;;
363                3)
364                    WRITE_MODE=skip
365                    ;;
366                *)
367                    failure "aborting."
368                    ;;
369            esac
370            break
371        done
372    fi
373else
374    WRITE_MODE=new
375fi
376case "$WRITE_MODE" in
377    'new')
378        msg "creating debirf root..."
379        create_debootstrap
380        ;;
381    'rewrite')
382        msg "clearing old debirf root..."
383        rm -rf "$DEBIRF_ROOT"
384        msg "creating debirf root..."
385        create_debootstrap
386        ;;
387    'overwrite')
388        msg "overwriting old debirf root..."
389        create_debootstrap
390        ;;
391    'skip')
392        msg "skipping debootstrap..."
393        ;;
394    *)
395        failure "aborting."
396        ;;
397esac
398
399# fix the dev tree if running as non-priv user (fakechroot debootstrap)
400fix_dev
401
402else
403    echo "Not building root."
404fi
405### END BUILD ROOT
406
407### RUN MODULES
408if [ "$STAGE_MODULES" = 'true' ] ; then
409    msg "executing modules..."
410    run_modules
411    msg "modules complete."
412else
413    echo "Not running modules."
414fi
415### END RUN MODULES
416
417### BUILD INITRD
418if [ "$STAGE_INITRD" = 'true' ] ; then
419    if [ ! -d "$DEBIRF_ROOT" ] ; then
420        failure "Debirf root '$DEBIRF_ROOT' not found."
421    fi
422    # determine initrd name
423    KERNEL_VERS=$(ls -1 "$DEBIRF_ROOT/lib/modules" | head -n1)
424    DEBIRF_INITRD="${DEBIRF_BUILDD}/${DEBIRF_LABEL}_${DEBIRF_DISTRO}_${KERNEL_VERS}.cgz"
425
426    msg "creating debirf initrd ('$DEBIRF_METHOD')..."
427    create_initrd_${DEBIRF_METHOD} "$DEBIRF_INITRD"
428
429    # final output
430    DEBIRF_KERNEL=$(ls "$DEBIRF_BUILDD" | grep "vmlinu" | grep "$KERNEL_VERS$")
431    msg "debirf initrd created."
432    if [ "$DEBIRF_BUILDD/$DEBIRF_KERNEL" ] ; then
433        msg "kernel: $DEBIRF_BUILDD/$DEBIRF_KERNEL"
434    fi
435    msg "initrd: $DEBIRF_INITRD"
436else
437    echo "Not creating initramfs."
438fi
439### END BUILD INITRD
Note: See TracBrowser for help on using the repository browser.