#!/bin/sh # # $Id$ # # The author disclaims all copyrights and releases this script into the # public domain. # # Utility to assist working with Linux initrd image files. print_usage () { echo "usage: $BASENAME pack|unpack action-arg" >&2 exit 1 } ASROOT=sudo BASENAME=initrd-util TMPDIR=/var/tmp if [ -z "$1" ]; then print_usage fi if [ `id -u` -eq 0 ]; then ASROOT= fi if [ "$1" = "unpack" ]; then if [ -z $2 ]; then echo "usage: $BASENAME unpack /path/to/initrd.gz" >&2 exit 1 fi # assume input is gzip'ed initrd image filepath, uncompress somewhere INITRD_RAW=`mktemp $TMPDIR/$BASENAME.initrd-old.XXXXXXX` || exit 1 gunzip -c $2 > $INITRD_RAW || exit 1 # area to mount initrd image to ORIG_IMAGE_MNT=`mktemp -d $TMPDIR/$BASENAME.mnt-old.XXXXXXX` || exit 1 chmod 755 $ORIG_IMAGE_MNT $ASROOT mount -o loop $INITRD_RAW $ORIG_IMAGE_MNT || exit 1 # copy initrd contents to working area WORK_DIR=`mktemp -d $TMPDIR/$BASENAME.workdir.XXXXXXX` || exit 1 chmod 755 $WORK_DIR $ASROOT rsync -a $ORIG_IMAGE_MNT/ $WORK_DIR || exit 1 echo "info: initrd $1 expanded into: $WORK_DIR" >&2 # unpack modules for easy editing ( cd $WORK_DIR || exit 1 # need to track what new files are added so pack can clean them out FILELIST=`ls -A1` gunzip -c modules/modules.cgz | sudo cpio -id -m >/dev/null 2>&1 STATUS=$? if [ $STATUS -ne 0 ]; then echo "error: non-zero exit ($STATUS) on expansion of modules/modules.cgz" >&2 exit 1 fi # compare new directory contents with previous, save to file for # future reference by 'pack' option to this script NEW_STUFF_TMP=`mktemp $TMPDIR/$BASENAME.initrd-tmp.XXXXXXX` || exit 1 ( ls -A1 OLDIFS=$IFS IFS=" " for e in "$FILELIST"; do echo $e; done IFS=$OLDIFS ) | sort | uniq -u > $NEW_STUFF_TMP $ASROOT mv $NEW_STUFF_TMP .delete-before-pack ) # cleanup temporary stuff $ASROOT umount $ORIG_IMAGE_MNT rm $INITRD_RAW rmdir $ORIG_IMAGE_MNT # so can cd on last line of output to stdout # e.g. cd `initrd-util unpack initrd.gz | tail -1` echo $WORK_DIR exit fi if [ "$1" = "pack" ]; then if [ -z $2 ]; then echo "usage: $BASENAME pack /path/to/workdir" >&2 exit 1 fi if [ ! -d $2 ]; then echo "error: not a directory: $2" >&2 exit 1 fi # delete expanded files recorded by 'unpack' above ( cd $2 || exit 1 if [ -f .delete-before-pack ]; then ( cat .delete-before-pack echo .delete-before-pack ) | xargs $ASROOT rm -rf fi ) # this might be needed if one is building a new RedHat distribution; # otherwise, updating the buildstamp file makes the install unhappy, # as I think the date gets compared with other timestamps in later # stage files #BUILDSTAMP=`mktemp $TMPDIR/$BASENAME.tmp-bs.XXXXXXX` || exit 1 #chmod 644 $BUILDSTAMP #date +%Y%m%d%H%M > $BUILDSTAMP #echo Red Hat Linux >> $BUILDSTAMP #echo 9 >> $BUILDSTAMP #$ASROOT mv $BUILDSTAMP $2/.buildstamp # find size of, format new file for image # # KLUGE need to increase the size of the resulting image file a little # as otherwise see problems; still could be boundary conditions here?? INITRD_SIZE=`$ASROOT du -k -s $2 | awk '{print int($1/1024+2)*1024}'` echo "notice: new initrd size: ${INITRD_SIZE}K" >&2 INITRD_RAW=`mktemp $TMPDIR/$BASENAME.initrd-new.XXXXXXX` || exit 1 dd if=/dev/zero bs=1024 count=$INITRD_SIZE of=$INITRD_RAW || exit 1 echo y | mke2fs $INITRD_RAW >/dev/null || exit 1 # mount point for new image file, copy files into it NEW_IMAGE_MNT=`mktemp -d $TMPDIR/$BASENAME.mnt-new.XXXXXXX` || exit 1 chmod 755 $NEW_IMAGE_MNT $ASROOT mount -o loop $INITRD_RAW $NEW_IMAGE_MNT || exit 1 $ASROOT rsync -a $2/ $NEW_IMAGE_MNT || exit 1 # cleanup $ASROOT sync $ASROOT umount $NEW_IMAGE_MNT rmdir $NEW_IMAGE_MNT gzip -n -9 $INITRD_RAW || exit 1 chmod 644 $INITRD_RAW.gz echo "info: initrd packed into: $INITRD_RAW.gz" >&2 echo $INITRD_RAW.gz exit fi # handler routines must exit to avoid hitting this! print_usage