#!/bin/sh

umask 0022

# Defaults
keep="n"
CONFDIR="conf"
verbose="n"
OPTIONS=`getopt -o c:d:s:o:r:v -n "$0" -- "$@"`

# Check for non-GNU getopt
if [ $? != 0 ] ; then echo "W: non-GNU getopt" >&2 ; exit 1 ; fi

eval set -- "$OPTIONS"

while true; do
	case "$1" in
	-c)
		compress="$2"
		shift 2
		;;
	-d)
		CONFDIR="$2"
		shift 2
		if [ ! -d "${CONFDIR}" ]; then
			echo "${0}: ${CONFDIR}: Not a directory" >&2
			exit 1
		fi
		;;
	-s)
		source="$2"
		shift 2
		;;
	-o)
		outfile="$2"
		shift 2
		;;
	-r)
        ROOT=$(readlink -f $2)
		shift 2
		;;
	-v)
		verbose="y"
		shift
		;;
	--)
		shift
		break
		;;
	*)
		echo "Internal error!" >&2
		exit 1
		;;
	esac
done

. ./hook-functions

. "${CONFDIR}/initramfs.conf"
if [ -n "${UMASK:-}" ]; then
	umask "${UMASK}"
fi

if [ -z "${outfile}" ]; then
	usage
fi

touch "$outfile"
outfile="$(readlink -f "$outfile")"

version="${1}"

# Check userspace and kernel support for compressed initramfs images
if [ -z "${compress:-}" ]; then
	compress=${COMPRESS}
else
	COMPRESS=${compress}
fi

if ! command -v "${compress}" >/dev/null 2>&1; then
	compress=gzip
	[ "${verbose}" = y ] && \
		echo "No ${COMPRESS} in ${PATH}, using gzip"
	COMPRESS=gzip
fi

if [ -d "${outfile}" ]; then
	echo "${outfile} is a directory" >&2
	exit 1
fi

MODULESDIR="${ROOT}/lib/modules/${version}"

if [ ! -e "${MODULESDIR}" ]; then
	echo "WARNING: missing ${MODULESDIR}"
	echo "Ensure all necessary drivers are built into the linux image!"
fi
if [ ! -e "${MODULESDIR}/modules.dep" ]; then
	depmod ${version}
fi

# Prepare to clean up temporary files on exit
DESTDIR=
__TMPCPIOGZ=
__TMPEARLYCPIO=
clean_on_exit() {
	if [ "${keep}" = "y" ]; then
		echo "Working files in ${DESTDIR:-<not yet created>}, early initramfs in ${__TMPEARLYCPIO:-<not yet created>} and overlay in ${__TMPCPIOGZ:-<not yet created>}"
	else
		for path in "${DESTDIR}" "${__TMPCPIOGZ}" "${__TMPEARLYCPIO}"; do
			test -z "${path}" || rm -rf "${path}"
		done
	fi
}
trap clean_on_exit EXIT
trap "exit 1" INT TERM	# makes the EXIT trap effective even when killed

# Create temporary directory and files for initramfs contents
[ -n "${TMPDIR}" ] && [ ! -w "${TMPDIR}" ] && unset TMPDIR
DESTDIR="$(mktemp -d ${TMPDIR:-/var/tmp}/mkinitramfs_XXXXXX)" || exit 1
chmod 755 "${DESTDIR}"
__TMPCPIOGZ="$(mktemp ${TMPDIR:-/var/tmp}/mkinitramfs-OL_XXXXXX)" || exit 1
__TMPEARLYCPIO="$(mktemp ${TMPDIR:-/var/tmp}/mkinitramfs-FW_XXXXXX)" || exit 1

# Export environment for hook scripts.
#
export MODULESDIR
export version
export CONFDIR
export DESTDIR
export verbose
export MODULES

# Private, used by 'catenate_cpiogz'.
export __TMPCPIOGZ

if [ -f ${source} ]; then
	echo "extracting base filesystem"
	cd ${DESTDIR}; extract_base ${source} ${DESTDIR} || exit $?
    cd -
fi

for d in conf etc lib/modules; do
	mkdir -p "${DESTDIR}/${d}"
done

mkdir -p "${DESTDIR}/${MODULESDIR##${ROOT}}"

# Copy in modules.builtin and modules.order (not generated by depmod)
for x in modules.builtin modules.order; do
	if [ -f "${MODULESDIR}/${x}" ]; then
		cp -p "${MODULESDIR}/${x}" "${DESTDIR}${MODULESDIR##${ROOT}}/${x}"
	fi
done

# MODULES=list case.  Always honour.
for x in "${CONFDIR}/modules"; do
	if [ -f "${x}" ]; then
		add_modules_from_file "${x}"
	fi
done

# Alway add module from /proc/modules
add_modules_from_proc

for module in "${MODULES}";do
    auto_add_modules ${module}
done

# Resolve hidden dependencies
hidden_dep_add_modules

mkdir -p "${DESTDIR}/etc/modprobe.d" "${DESTDIR}/lib/modprobe.d"
for file in ${ROOT}/etc/modprobe.d/*.conf ${ROOT}/lib/modprobe.d/*.conf ; do
	if test -e "$file" || test -L "$file" ; then
		copy_file config "$file" "${file##${ROOT}}"
	fi
done

run_scripts_optional "${CONFDIR}"/hooks

# generate module deps
depmod -a -b "${DESTDIR}" ${version}
rm -f "${DESTDIR}/lib/modules/${version}"/modules.*map

# Remove any looping or broken symbolic links, since they break cpio.
[ "${verbose}" = y ] && xargs_verbose="-t"
(cd "${DESTDIR}" && find . -type l -printf '%p %Y\n' | sed -n 's/ [LN]$//p' \
	| xargs ${xargs_verbose:-} -rL1 rm -f)

[ "${verbose}" = y ] && echo "Building cpio ${outfile} initramfs"

if [ -s "${__TMPEARLYCPIO}" ]; then
	cat "${__TMPEARLYCPIO}" >"${outfile}" || exit 1
else
	# truncate
	> "${outfile}"
fi

# preserve permissions if root builds the image, see #633582
[ "$(id -ru)" != 0 ] && cpio_owner_root="-R 0:0"

# work around lack of "set -o pipefail" for the following pipe:
cd "${DESTDIR}" && find . | cpio --quiet $cpio_owner_root -o -H newc | gzip >>"${outfile}" || exit 1
exit 0
