This is a departure from using gen_init_cpio, which proved to be a huge bottleneck in performance. Tests for existance change from being a call to grep, to a simple shell test. In the process, we have to modify the behavior of the -s option, and we lose the -a option. Signed-off-by: Dave Reisner <d@falconindy.com> --- functions | 41 +++++++++++++---------------- mkinitcpio | 74 +++++++++++++++++++++++++++-------------------------- mkinitcpio.5.txt | 7 +--- 3 files changed, 58 insertions(+), 64 deletions(-) diff --git a/functions b/functions index 03be8cc..666aeec 100644 --- a/functions +++ b/functions @@ -79,12 +79,12 @@ checked_modules () add_full_dir () { - if [ -n "${1}" -a -d "${1}" ]; then - for f in ${1}/*; do - if [ -d "${f}" ]; then - add_full_dir "${f}" + if [[ -n $1 && -d $1 ]]; then + for f in "$1"/*; do + if [[ -d "$f" ]]; then + add_full_dir "$f" else - add_file "${f}" + add_file "$f" fi done fi @@ -92,28 +92,23 @@ add_full_dir () add_dir () { - #skip root directory and "." for relative directories... i.e. /foo/bar/./blah - if [ -n "${1}" -a "${1}" != "/" -a "${1}" != "." ]; then - if ! grep -q "dir ${1} " "${FILELIST}"; then - add_dir $(get_dirname "${1}") - msg " adding dir ${1}" - echo "dir ${1} 755 0 0" >> "${FILELIST}" - fi + if [[ ! -e "$TMPDIR/root/$1" ]]; then + msg " adding dir ${1}" + command install -dm755 "$TMPDIR/root/$1" fi } -# what the hell does this do? add_symlink () { local fil dest dir - if [ -h ${1} ]; then + if [[ -h $1 ]]; then fil="${1##$BASEDIR}" dest="${2##$BASEDIR}" add_dir $(get_dirname "${dest}") add_dir $(get_dirname "${fil}") - if ! grep -q "slink ${fil} " "${FILELIST}"; then + if [[ ! -e "$TMPDIR/root/$dest" ]]; then msg " adding link ${fil} -> ${dest}" - echo "slink ${fil} ${dest} $(stat -c '%a' ${1}) 0 0" >> "${FILELIST}" + ln -s "$dest" "$TMPDIR/root/$fil" fi fi #fail quietly @@ -122,27 +117,27 @@ add_symlink () add_file () { local fil lnk dir dest - if [ -f "${1}" ]; then - fil="${1}" + if [[ -f "$1" ]]; then + fil=$1 lnk=$(readlink -f "${fil}") - if [ -n "${lnk}" ]; then + if [[ ${lnk} ]]; then add_symlink "${fil}" "${lnk}" fil="${lnk}" fi if [[ $2 ]]; then - dest="${2}" + dest=$2 else dest="${fil##$BASEDIR}" - if [ "${dest}" = "${dest#/}" ]; then + if [[ "${dest}" = "${dest#/}" ]]; then dest="/${dest}" fi fi add_dir $(get_dirname "${dest}") - if ! grep -q "file ${dest} " "${FILELIST}"; then + if [[ ! -e $TMPDIR/root/$dest ]]; then msg " adding file ${dest}" - echo "file ${dest} ${fil} $(stat -c '%a' ${fil}) 0 0" >> "${FILELIST}" + command install -Dm$(stat -c '%a' "$fil") "$fil" "$TMPDIR/root/$dest" fi else err "file '${1}' does not exist" diff --git a/mkinitcpio b/mkinitcpio index ac9522b..c40fb2d 100755 --- a/mkinitcpio +++ b/mkinitcpio @@ -10,11 +10,11 @@ # in case of embedded spaces, quote all path names and string comparisons # +shopt -s extglob # Settings TMPDIR="$(mktemp -d /tmp/mkinitcpio.XXXXXX)" BASEDIR="" -FILELIST="${TMPDIR}/filelist" MESSAGEFILE="${TMPDIR}/message" KERNELVERSION="$(uname -r)" FUNCTIONS="functions" @@ -24,7 +24,6 @@ INSTDIR="install" MODULE_FILE="" SAVELIST="" GENIMG="" -APPEND="" PRESET="" MESSAGE="" SKIPHOOKS=() @@ -49,10 +48,9 @@ usage () echo "${APPNAME}: usage" echo " -c CONFIG Use CONFIG file. default: /etc/mkinitcpio.conf" echo " -k KERNELVERSION Use KERNELVERSION. default: $(uname -r)" - echo " -s NAME Save filelist. default: no" + echo " -s Save build directory. default: no" echo " -b BASEDIR Use BASEDIR. default: /" echo " -g IMAGE Generate a cpio image as IMAGE. default: no" - echo " -a NAME Append to an existing filelist. default: no" echo " -p PRESET Build specified preset." echo " -m MESSAGE Print MESSAGE before passing control to init." echo " -S SKIPHOOKS Skip SKIPHOOKS (comma-separated) when building the image." @@ -67,7 +65,11 @@ usage () cleanup () { - [ -n "${TMPDIR}" -a -d "${TMPDIR}" ] && rm -rf ${TMPDIR} + if [[ $SAVELIST ]]; then + echo ":: build directory saved in $TMPDIR" + else + rm -rf ${TMPDIR} + fi } sighandler() { @@ -77,7 +79,7 @@ sighandler() { trap sighandler TERM INT -while getopts ':c:k:s:b:g:a:p:m:vH:LMhS:' arg; do +while getopts ':c:k:sb:g:p:m:vH:LMhS:' arg; do if [ "${OPTARG#-}" != "${OPTARG}" ]; then echo "error: optional argument to '-${arg}' begins with a '-'" echo " you probably don't want this....aborting." @@ -86,10 +88,9 @@ while getopts ':c:k:s:b:g:a:p:m:vH:LMhS:' arg; do case "${arg}" in c) CONFIG="${OPTARG}" ;; k) KERNELVERSION="${OPTARG}" ;; - s) SAVELIST="y"; FILELIST="${OPTARG}" ;; + s) SAVELIST="y"; ;; b) BASEDIR="${OPTARG}" ;; g) GENIMG="${OPTARG}" ;; - a) APPEND="y"; SAVELIST="y"; FILELIST="${OPTARG}" ;; p) PRESET="${OPTARG}" ;; m) MESSAGE="${OPTARG}" ;; v) QUIET="n" ;; @@ -185,6 +186,15 @@ BASEDIR="${BASEDIR%/}" MODULEDIR="${BASEDIR}/lib/modules/${KERNELVERSION}" +if [[ $GENIMG ]]; then + IMGPATH=$(readlink -f "$GENIMG") + if [[ -z $IMGPATH || ! -w ${IMGPATH%/*} ]]; then + echo "error: unable to write to path: '$GENIMG'" + cleanup + exit 1 + fi +fi + if [ -n "${BASEDIR}" ]; then if [ "${BASEDIR}" = "${BASEDIR#/}" ]; then BASEDIR="$(pwd)/${BASEDIR}" @@ -202,19 +212,6 @@ if [ ! -f "${CONFIG}" ]; then fi . "${CONFIG}" -if [ -f "${FILELIST}" -a -z "${APPEND}" ]; then - if [ -z "${SAVELIST}" ]; then - rm ${FILELIST} - touch "${FILELIST}" - else - echo "destination file list '${FILELIST}' exists - remove before running" - cleanup - exit 1 - fi -else - touch "${FILELIST}" -fi - BASEDIR=$(echo ${BASEDIR} | tr -s /) MODULEDIR=$(echo ${MODULEDIR} | tr -s /) @@ -276,31 +273,36 @@ done if (( ${#ADDED_MODULES[*]} )); then echo ":: Generating module dependencies" - for mod in $(grep "file /lib/modules/${KERNELVERSION}" ${FILELIST} | cut -d' ' -f2); do - install -m 644 -D "${BASEDIR}${mod}" "${TMPDIR}${mod}" - done - /sbin/depmod -b ${TMPDIR} ${KERNELVERSION} - for dmfile in modules.{dep,alias,symbols}.bin; do - add_file "${TMPDIR}/lib/modules/${KERNELVERSION}/$dmfile" "/lib/modules/${KERNELVERSION}/$dmfile" - done + /sbin/depmod -b "${TMPDIR}/root" "${KERNELVERSION}" + rm "$TMPDIR/root/lib/modules/$KERNELVERSION"/modules.!(dep.bin|alias.bin|symbols.bin) fi -status=0 +declare -i status=0 +declare -a pipesave if [ -n "${GENIMG}" ]; then echo ":: Generating image '${GENIMG}'" - shopt -s -o pipefail [ ${COMPRESSION} = "xz" ] && COMPRESSION_OPTIONS="${COMPRESSION_OPTIONS} --check=crc32" - if ! /sbin/gen_init_cpio ${FILELIST} | ${COMPRESSION} ${COMPRESSION_OPTIONS} > "${GENIMG}"; then - echo ":: Image generation FAILED" + + pushd "$TMPDIR/root" >/dev/null + find . -print0 | bsdcpio -0oH newc | $COMPRESSION $COMPRESSION_OPTIONS > "$IMGPATH" + pipesave=("${PIPESTATUS[@]}") # save immediately + popd >/dev/null + + if (( pipesave[0] )); then + errmsg="find reported an error" + elif (( pipesave[1] )); then + errmsg="bsdcpio reported an error" + elif (( pipesave[2] )); then + errmsg="$COMPRESSION reported an error" + fi + + if [[ $errmsg ]]; then + echo ":: Image generation FAILED ($errmsg)" status=1 else echo ":: Image generation successful" - status=0 fi - if [ -z "${SAVELIST}" ]; then - rm ${FILELIST} - fi else echo ":: Dry run complete, use -g IMAGE to generate a real image" fi diff --git a/mkinitcpio.5.txt b/mkinitcpio.5.txt index 1c095dc..3d0fdc9 100644 --- a/mkinitcpio.5.txt +++ b/mkinitcpio.5.txt @@ -21,8 +21,8 @@ Options *-k* 'kernelversion':: Use 'kernelversion'. Default is the current running kernel. -*-s* 'filelist':: - Saves a list of all the files in the initial ramdisk in 'filelist'. Default: no; This means the filelist will not be retained if this option isn't specified. Useful for debugging purposes. +*-s*:: + Saves the build directory for the initial ramdisk. Default: no; This means the directory will not be retained if this option isn't specified. Useful for debugging purposes. *-b* 'basedir':: Use 'basedir' as a starting point for gathering information about the currently running system. Default: /. @@ -30,9 +30,6 @@ Options *-g* 'filename':: Generate a CPIO image as 'filename'. Default: no; this means nothing will be written to the filesystem unless this option is specified. -*-a* 'filelist':: - Append to an existing 'filelist'. Default no. - *-p* 'preset':: Build initial ramdisk according to specified 'preset'. Presets are found in /etc/mkinitcpio.d -- 1.7.5.4