#/bin/sh
# $Id: extract_initramfs.sh,v 1.12 2023/01/05 15:30:48 eha Exp eha $
# ----------------------------------------------------------------------------
# Purpose:
#   Create or extract initramfs archives.
# Usage:
#   extract_initramfs <archivename> <target_directory>
#   create_initramfs <archivename> <source_directory>
#
# Author:
#   Eric Hameleers <alien@slackware.com>
#
# ----------------------------------------------------------------------------

# My paranoia:
set -e
# Debugging:
#set -x

# Names by which the script can be called (use symlinks for this!):
EXTRACT_NAME=extract_initramfs.sh
CREATE_NAME=create_initramfs.sh

# Used compression techniques:
A7Z=$(which 7za 2>/dev/null) || true
GZIP=$(which gzip 2>/dev/null) || true
LZIP=$(which lzip 2>/dev/null) || true
ZIP=$(which zip 2>/dev/null) || true
XZ=$(which xz 2>/dev/null) || true

usage() {
cat <<EOT__

$0 :
   Create or extract initramfs archives.
Usage:
   extract_initramfs <archivename> <target_directory>
   create_initramfs <archivename> <source_directory>
NOTE:
   The target directory will be created if it does not yet exist.
   The initramfs contents will be extracted to this target directory.
   The target directory's existing contents will *not* be erased
    prior to extracting the initramfs, in case the directory already exists.

EOT__
}

compressfs () {
if [ "$(echo "${1}" |rev |cut -d. -f1 | rev)" = "7z" -a -n "$A7Z" ]; then
  7za a ${1} -si
elif [ "$(echo "${1}" |rev |cut -d. -f1 | rev)" = "zip" -a -n "$ZIP" ]; then
  zip "${1}" -
elif [ "$(echo "${1}" |rev |cut -d. -f1 | rev)" = "gz" -a -n "$GZIP" ]; then
  gzip -c > "${1}"
elif [ "$(echo "${1}" |rev |cut -d. -f1 | rev)" = "lz" -a -n "$LZIP" ]; then
  lzip -c > "${1}"
elif [ "$(echo "${1}" |rev |cut -d. -f1 | rev)" = "lzma" -a -n "$XZ" ]; then
  xz --format=lzma -C crc32 -c > "${1}"
elif [ "$(echo "${1}" |rev |cut -d. -f1 | rev)" = "xz" -a -n "$XZ" ]; then
  xz -C crc32 -c > "${1}"
else
  # Use a safe default and hope for the best:
  xz -C crc32 -c > "${1}"
fi
}

uncompressfs () {
if $(file "${1}" | grep -qi ": 7-zip"); then
  7za x "${1}" -so
elif $(file "${1}" | grep -qi ": zip"); then
  unzip -p "${1}"
elif $(file "${1}" | grep -qi ": gzip"); then
  gzip -cd "${1}"
elif $(file "${1}" | grep -qi ": lzip"); then
  lzip -cd "${1}"
elif $(file "${1}" | grep -qi ": LZMA"); then
  xz --format=lzma -cd "${1}"
elif $(file "${1}" | grep -qi ": XZ"); then
  xz -cd "${1}"
else
  # And hope for the best:
  gunzip -cd "${1}"
fi
}

if [ -z "$1" ]; then
  usage
  exit 1
else
  INITRD=$1
  [ "${INITRD:0:1}" != "/" ] && INITRD=$(pwd)/${INITRD}
fi

if [ -z "$2" ]; then
  usage
  exit 2
else
  DIR=$2
fi


if [ "`basename $0`" = "${EXTRACT_NAME}" ]; then
  if [ ! -r ${INITRD} ]; then
    echo "***ERROR*** Can not read initramfs file '${INITRD}'!"
    exit 11
  fi
  if [ ! -d ${DIR} ]; then
    # Try to create the target directory:
    if ! mkdir -p ${DIR} ; then
      echo "***ERROR*** Can not create directory '${DIR}'!"
      exit 11
    fi
  fi
  cd ${DIR}
  echo "--- Extracting the initramfs into the directory '${DIR}'"
  uncompressfs ${INITRD} | cpio -i -d -m -H newc
elif [ "`basename $0`" = "${CREATE_NAME}" ]; then
  if [ ! -d ${DIR} ]; then
    echo "***ERROR*** Directory '${DIR}' does not exist!"
    exit 12
  fi
  # Compress the initrd (this is a cpio archive for the 2.6 kernel's initramfs):
  cd ${DIR}
  echo "--- Creating the initramfs from content below '${DIR}'"
  find . | cpio -o -H newc | compressfs ${INITRD}
  RET=$?
  [ $RET -ne 0 ] && echo "An error occured in creating $INITRD (code $RET)"
fi

