#!/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