summaryrefslogtreecommitdiffstats
path: root/mkinitcpio
diff options
context:
space:
mode:
Diffstat (limited to 'mkinitcpio')
-rw-r--r--mkinitcpio253
1 files changed, 253 insertions, 0 deletions
diff --git a/mkinitcpio b/mkinitcpio
new file mode 100644
index 0000000..50d3647
--- /dev/null
+++ b/mkinitcpio
@@ -0,0 +1,253 @@
+#!/bin/sh
+# mkinitcpio - modular tool for building an init ramfs cpio image
+#
+# IMPORTANT: We need to keep a common base syntax here
+# because some of these hooks/scripts need to run under
+# the klibc shell or even busybox's ash - therefore, the
+# following constraints should be enforced:
+# variables should be quoted and bracketed "${SOMEVAR}"
+# inline execution should be done with $() instead of backticks
+# use "x${var}" = "x" to test for nulls/empty strings
+# incase of embedded spaces, quote all path names and string comaprissons
+#
+# TODO
+# sudo cp img /boot
+
+HOOKDIR="hooks"
+
+# Settings
+BASEDIR=""
+KERNELVERSION="$(uname -r)"
+CONFIG="mkinitcpio.conf"
+SAVELIST=""
+GENIMG=""
+APPEND=""
+
+usage ()
+{
+ echo "TODO usage..."
+ exit 1
+}
+
+while getopts 'c:k:sb:g:a' arg; do
+ case "$arg" in
+ c) CONFIG="$OPTARG" ;;
+ k) KERNELVERSION="$OPTARG" ;;
+ s) SAVELIST="y" ;;
+ b) BASEDIR="$OPTARG" ;;
+ g) GENIMG="$OPTARG" ;;
+ a) APPEND="y" ;;
+ ?) usage ;;
+ *) echo "invalid argument '$arg'"; usage ;;
+ esac
+done
+shift $(($OPTIND - 1))
+
+# append a trailing / if needed
+if [ "${BASEDIR:${#BASEDIR}}" == "/" ]; then
+ BASEDIR="${BASEDIR:0:${#BASEDIR}-1}"
+fi
+
+MODULEDIR="${BASEDIR}/lib/modules/${KERNELVERSION}"
+FILELIST=${1:-"initcpio.filelist"}
+
+if [ "x${BASEDIR}" != "x" ]; then
+ if [ "${BASEDIR:0:1}" != "/" ]; then
+ echo "base directory '${BASEDIR}' must be an absolute path"
+ exit 1
+ elif [ ! -d "${BASEDIR}" ]; then
+ echo "base directory '${BASEDIR}' does not exist or is not a directory"
+ exit 1
+ fi
+fi
+
+if [ ! -f "${CONFIG}" ]; then
+ echo "config file '${CONFIG}' cannot be found, aborting..."
+ exit 1
+fi
+source "${CONFIG}"
+
+if [ -f "${FILELIST}" -a "x${APPEND}" == "x" ]; then
+ echo "destination file list '${FILELIST}' exists - remove before running"
+ exit 1
+elif [ -f "${DESTIMG}" ]; then
+ echo "destination image '${DESTIMG}' exists - remove before running"
+ exit 1
+else
+ touch "${FILELIST}"
+fi
+
+# this function is a helper for the *-auto install functions
+auto_modules ()
+{
+ aliases=$(find /sys/devices/ -name modalias -exec cat {} \;)
+ modprobe --show-depends -a $aliases 2>/dev/null |\
+ sed "s|insmod \(.*\)|\1|" | sort -u
+}
+
+add_dir()
+{
+ local dir
+ dir="${1}"
+ if [ "x${dir}" != "x" -a "${dir}" != "/" ]; then
+ dir="${dir}" #this got stripped off above... put it back
+
+ if ! grep "dir ${dir} " "${FILELIST}" 2>&1 > /dev/null; then
+ add_dir $(dirname ${dir})
+ echo " adding dir ${dir}"
+ echo "dir ${dir} 755 0 0" >> "${FILELIST}"
+ fi
+ fi
+}
+
+add_symlink ()
+{
+ local fil dest dir
+ if [ -L ${1} ]; then
+ fil="${1}"
+ dest="${fil##$BASEDIR}"
+ dir=$(dirname "${dest}")
+ add_dir "${dir}"
+ if ! grep "slink ${fil} " "${FILELIST}" 2>&1 > /dev/null; then
+ echo " adding symlink ${dest}"
+ echo "slink ${dest} ${fil} $(stat -c '%a %u %g' ${fil})" >> "${FILELIST}"
+ fi
+ fi
+}
+
+add_file ()
+{
+ local fil lnk dir dest
+ if [ -e "${1}" ]; then
+ fil="${1}"
+ lnk=$(readlink -f "${fil}")
+ if [ -n "${lnk}" ]; then
+ add_symlink "${fil}"
+ fil="${lnk}"
+ fi
+ if [ $# -eq 2 ]; then
+ dest="${2}"
+ else
+ dest="${fil##$BASEDIR}"
+ fi
+
+ dir=$(dirname "${dest}")
+ add_dir "${dir}"
+
+ if ! grep "file ${fil} " "${FILELIST}" 2>&1 > /dev/null; then
+ echo " adding file ${dest}"
+ echo "file ${dest} ${fil} $(stat -c '%a %u %g' ${fil})" >> "${FILELIST}"
+ fi
+ fi
+}
+
+HAS_MODULES="n"
+add_module()
+{
+ local fil path mod deps
+ #cleanup - remove .ko, replace - and _ with [-_] to match either
+ fil=$(basename "${1}" | sed -e "s|[-_]|\[-_\]|g" -e "s|\.ko$||g")
+
+ for path in $(find "${MODULEDIR}" -type f -name "${fil}.ko"); do
+ for mod in $(modinfo -F depends "${path}" | tr ',' ' '); do
+ if [ "x${mod}" != "x" ]; then
+ add_module "${mod}"
+ HAS_MODULES="y"
+ fi
+ done
+ add_file "${path}"
+ done
+}
+
+add_binary()
+{
+ local bin type lib
+ bin=$(which "${1}")
+ if [ $? -ne 0 ]; then
+ bin="${1}"
+ fi
+
+ if [ ! -f "${bin}" ]; then
+ echo "add_binary: '${bin}' is not a file"
+ return 1
+ fi
+
+ if [ $? -eq 0 ]; then
+ type=$(file -b "${bin}")
+ case "${type}" in
+ *script*)
+ msg " adding '${type}' script, ensure proper interp exists..."
+ add_file "${bin}"
+ ;;
+ *executable*)
+ add_file "${bin}"
+ #note, this will also handle 'not a dynamic executable' spit out by
+ # static binaries... the deps will produce nothing
+ for lib in $(ldd ${bin} 2>/dev/null | sed "s|.*=>\(.*\)|\1|"); do
+ if [ "x${lib}" != "x" ]; then
+ #remove TLS libraries
+ notls=$(echo ${lib} | sed 's|/lib/tls.*/\(lib.*\)|/lib/\1|')
+ [ -e "${notls}" ] && lib="${notls}"
+ [ -f "${lib}" ] && add_file "${lib}"
+ fi
+ done
+ ;;
+ *)
+ echo "add_binary: unknown type '${type}' for binary '${bin}'"
+ return 1
+ ;;
+ esac
+ fi
+}
+
+function parse_hook()
+{
+ local mod bin fil
+ for mod in $MODULES; do
+ if [ "x${mod}" != "x" ]; then
+ add_module "${mod}"
+ fi
+ done
+
+ for bin in $BINARIES; do
+ if [ "x${bin}" != "x" ]; then
+ add_binary "${bin}"
+ fi
+ done
+
+ for fil in $FILES; do
+ if [ "x${fil}" != "x" ]; then
+ add_file "${fil}"
+ fi
+ done
+}
+
+#parse 'global' hook, as defined in ${CONFIG}
+parse_hook
+
+for hook in $HOOKS; do
+ unset MODULES
+ unset BINARIES
+ unset FILES
+ install () { msg "$hook: no install function..."; }
+ source "${HOOKDIR}/${hook}"
+ install
+ parse_hook
+ #quick test to check for existance... need a better way...
+ if grep "run_hook" "${HOOKDIR}/${hook}" 2>&1>/dev/null; then
+ add_file "${HOOKDIR}/${hook}" "/hooks/${hook}"
+ fi
+done
+
+if [ "${HAS_MODULES}" == "y" ]; then
+ add_file "${MODULEDIR}/modules.dep"
+ add_file "${MODULEDIR}/modules.alias"
+ add_file "${MODULEDIR}/modules.symbols"
+fi
+
+if [ "x$GENIMG" != "x" ]; then
+ gen_init_cpio ${FILELIST} | gzip -9 > "${GENIMG}"
+ if [ "x${SAVELIST}" == "x" ]; then
+ rm ${FILELIST}
+ fi
+fi