gen_initramfs_list.sh 6.4 KB
Newer Older
L
Linus Torvalds 已提交
1 2
#!/bin/bash
# Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org>
3
# Copyright (c) 2006           Sam Ravnborg <sam@ravnborg.org>
L
Linus Torvalds 已提交
4
#
5
# Released under the terms of the GNU GPL
L
Linus Torvalds 已提交
6
#
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
# Generate a cpio packed initramfs. It uses gen_init_cpio to generate
# the cpio archive, and gzip to pack it.
# The script may also be used to generate the inputfile used for gen_init_cpio
# This script assumes that gen_init_cpio is located in usr/ directory

# error out on errors
set -e

usage() {
cat << EOF
Usage:
$0 [-o <file>] [-u <uid>] [-g <gid>] {-d | <cpio_source>} ...
	-o <file>      Create gzipped initramfs file named <file> using
	               gen_init_cpio and gzip
	-u <uid>       User ID to map to user ID 0 (root).
	               <uid> is only meaningful if <cpio_source>
	               is a directory.
	-g <gid>       Group ID to map to group ID 0 (root).
	               <gid> is only meaningful if <cpio_source>
	               is a directory.
	<cpio_source>  File list or directory for cpio archive.
	               If <cpio_source> is a .cpio file it will be used
		       as direct input to initramfs.
	-d             Output the default cpio list.

All options except -o and -l may be repeated and are interpreted
sequentially and immediately.  -u and -g states are preserved across
<cpio_source> options so an explicit "-u 0 -g 0" is required
to reset the root/group mapping.
EOF
}

list_default_initramfs() {
	# echo usr/kinit/kinit
	:
}
L
Linus Torvalds 已提交
43 44

default_initramfs() {
45
	cat <<-EOF >> ${output}
L
Linus Torvalds 已提交
46 47 48 49 50
		# This is a very simple, default initramfs

		dir /dev 0755 0 0
		nod /dev/console 0600 0 0 c 5 1
		dir /root 0700 0 0
51 52
		# file /kinit usr/kinit/kinit 0755 0 0
		# slink /init kinit 0755 0 0
L
Linus Torvalds 已提交
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
	EOF
}

filetype() {
	local argv1="$1"

	# symlink test must come before file test
	if [ -L "${argv1}" ]; then
		echo "slink"
	elif [ -f "${argv1}" ]; then
		echo "file"
	elif [ -d "${argv1}" ]; then
		echo "dir"
	elif [ -b "${argv1}" -o -c "${argv1}" ]; then
		echo "nod"
	elif [ -p "${argv1}" ]; then
		echo "pipe"
	elif [ -S "${argv1}" ]; then
		echo "sock"
	else
		echo "invalid"
	fi
	return 0
}

78 79 80 81
list_print_mtime() {
	:
}

L
Linus Torvalds 已提交
82 83 84
print_mtime() {
	local my_mtime="0"

85 86
	if [ -e "$1" ]; then
		my_mtime=$(find "$1" -printf "%T@\n" | sort -r | head -n 1)
L
Linus Torvalds 已提交
87
	fi
88 89 90 91 92 93 94

	echo "# Last modified: ${my_mtime}" >> ${output}
	echo "" >> ${output}
}

list_parse() {
	echo "$1 \\"
L
Linus Torvalds 已提交
95 96
}

97 98 99
# for each file print a line in following format
# <filetype> <name> <path to file> <octal mode> <uid> <gid>
# for links, devices etc the format differs. See gen_init_cpio for details
L
Linus Torvalds 已提交
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
parse() {
	local location="$1"
	local name="${location/${srcdir}//}"
	# change '//' into '/'
	name="${name//\/\///}"
	local mode="$2"
	local uid="$3"
	local gid="$4"
	local ftype=$(filetype "${location}")
	# remap uid/gid to 0 if necessary
	[ "$uid" -eq "$root_uid" ] && uid=0
	[ "$gid" -eq "$root_gid" ] && gid=0
	local str="${mode} ${uid} ${gid}"

	[ "${ftype}" == "invalid" ] && return 0
	[ "${location}" == "${srcdir}" ] && return 0

	case "${ftype}" in
		"file")
			str="${ftype} ${name} ${location} ${str}"
			;;
		"nod")
			local dev_type=
			local maj=$(LC_ALL=C ls -l "${location}" | \
					gawk '{sub(/,/, "", $5); print $5}')
			local min=$(LC_ALL=C ls -l "${location}" | \
					gawk '{print $6}')

			if [ -b "${location}" ]; then
				dev_type="b"
			else
				dev_type="c"
			fi
			str="${ftype} ${name} ${str} ${dev_type} ${maj} ${min}"
			;;
		"slink")
			local target=$(LC_ALL=C ls -l "${location}" | \
					gawk '{print $11}')
			str="${ftype} ${name} ${target} ${str}"
			;;
		*)
			str="${ftype} ${name} ${str}"
			;;
	esac

145
	echo "${str}" >> ${output}
L
Linus Torvalds 已提交
146 147 148 149

	return 0
}

150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
unknown_option() {
	printf "ERROR: unknown option \"$arg\"\n" >&2
	printf "If the filename validly begins with '-', " >&2
	printf "then it must be prefixed\n" >&2
	printf "by './' so that it won't be interpreted as an option." >&2
	printf "\n" >&2
	usage >&2
	exit 1
}

list_header() {
	echo "deps_initramfs := \\"
}

header() {
	printf "\n#####################\n# $1\n" >> ${output}
}

# process one directory (incl sub-directories)
dir_filelist() {
	${dep_list}header "$1"

	srcdir=$(echo "$1" | sed -e 's://*:/:g')
	dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n" 2>/dev/null)

	# If $dirlist is only one line, then the directory is empty
	if [  "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then
		${dep_list}print_mtime "$1"

		echo "${dirlist}" | \
		while read x; do
			${dep_list}parse ${x}
		done
	fi
L
Linus Torvalds 已提交
184 185
}

186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
# if only one file is specified and it is .cpio file then use it direct as fs
# if a directory is specified then add all files in given direcotry to fs
# if a regular file is specified assume it is in gen_initramfs format
input_file() {
	source="$1"
	if [ -f "$1" ]; then
		${dep_list}header "$1"
		is_cpio="$(echo "$1" | sed 's/^.*\.cpio/cpio/')"
		if [ $2 -eq 0 -a ${is_cpio} == "cpio" ]; then
			cpio_file=$1
			[ ! -z ${dep_list} ] && echo "$1"
			return 0
		fi
		if [ -z ${dep_list} ]; then
			print_mtime "$1" >> ${output}
			cat "$1"         >> ${output}
L
Linus Torvalds 已提交
202
		else
S
Sam Ravnborg 已提交
203 204 205 206 207
			cat "$1" | while read type dir file perm ; do
				if [ "$type" == "file" ]; then
					echo "$file \\";
				fi
			done
L
Linus Torvalds 已提交
208
		fi
209 210
	elif [ -d "$1" ]; then
		dir_filelist "$1"
L
Linus Torvalds 已提交
211
	else
212
		echo "  ${prog}: Cannot open '$1'" >&2
L
Linus Torvalds 已提交
213 214 215 216
		exit 1
	fi
}

217
prog=$0
L
Linus Torvalds 已提交
218 219
root_uid=0
root_gid=0
220 221 222 223 224
dep_list=
cpio_file=
cpio_list=
output="/dev/stdout"
output_file=""
L
Linus Torvalds 已提交
225

226 227 228 229 230 231 232 233 234 235 236 237 238 239
arg="$1"
case "$arg" in
	"-l")	# files included in initramfs - used by kbuild
		dep_list="list_"
		shift
		;;
	"-o")	# generate gzipped cpio image named $1
		shift
		output_file="$1"
		cpio_list="$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)"
		output=${cpio_list}
		shift
		;;
esac
L
Linus Torvalds 已提交
240 241 242 243
while [ $# -gt 0 ]; do
	arg="$1"
	shift
	case "$arg" in
244
		"-u")	# map $1 to uid=0 (root)
L
Linus Torvalds 已提交
245 246 247
			root_uid="$1"
			shift
			;;
248
		"-g")	# map $1 to gid=0 (root)
L
Linus Torvalds 已提交
249 250 251
			root_gid="$1"
			shift
			;;
252
		"-d")	# display default initramfs list
L
Linus Torvalds 已提交
253
			default_list="$arg"
254
			${dep_list}default_initramfs
L
Linus Torvalds 已提交
255 256 257 258 259 260 261 262
			;;
		"-h")
			usage
			exit 0
			;;
		*)
			case "$arg" in
				"-"*)
263
					unknown_option
L
Linus Torvalds 已提交
264
					;;
265 266
				*)	# input file/dir - process it
					input_file "$arg" "$#"
L
Linus Torvalds 已提交
267 268 269 270 271 272
					;;
			esac
			;;
	esac
done

273 274 275 276 277 278 279 280 281 282 283 284 285
# If output_file is set we will generate cpio archive and gzip it
# we are carefull to delete tmp files
if [ ! -z ${output_file} ]; then
	if [ -z ${cpio_file} ]; then
		cpio_tfile="$(mktemp ${TMPDIR:-/tmp}/cpiofile.XXXXXX)"
		usr/gen_init_cpio ${cpio_list} > ${cpio_tfile}
	else
		cpio_tfile=${cpio_file}
	fi
	rm ${cpio_list}
	cat ${cpio_tfile} | gzip -f -9 - > ${output_file}
	[ -z ${cpio_file} ] && rm ${cpio_tfile}
fi
L
Linus Torvalds 已提交
286
exit 0