#!/bin/sh # # Copyright (C) Michal Sojka # # Includes pieces from gen_initramfs_list.sh: # # Copyright (C) Martin Schlemmer # Copyright (C) 2006 Sam Ravnborg # # Released under the terms of the GNU GPL # Usage: gen_cpio rootfs.cpio "myapp->/bin/" "start.sh->/etc/init.d/S90startmyapp" # gen_cpio --mkimage="-T ramdisk -A powerpc -O linux" ... set -e root_uid=$(id -u) root_gid=$(id -g) usage() { cat >&2 << EOF Usage: $0 [--mkimage=""] [-u ] [-g ] {}... --gzip Compress the resulting image with gzip --mkimage=... Pack the resulting image with U-Boot's "mkimage ..." -u User ID to map to user ID 0 (root). is only meaningful if is a directory. "squash" forces all files to uid 0. Default: $root_uid (you) -g Group ID to map to group ID 0 (root). is only meaningful if is a directory. "squash" forces all files to gid 0. Default: $root_gid (you) One of: - *.cpio: Included directly into the output - directory: Content of the directory is included in the output - src/file->/dst/file: src/file appear in the output as dst/file - src/file->/dst/dir/: src/file appear in the output as dsr/dir/file All options except --mkimage may be repeated and are interpreted sequentially and immediately. -u and -g states are preserved across options so an explicit "-u 0 -g 0" is required to reset the root/group mapping. EOF } while [ $# -gt 0 ]; do case "$1" in --gzip) gzip=1 ;; --mkimage=*) mkimage=${1#--mkimage=} ;; "-h"|"--help") usage exit 0 ;; *) break;; esac shift done if [ -n "$mkimage" -o -n "$gzip" ]; then tmp=$(mktemp) exec 3<&1 1>$tmp fi gen_cpio_from_list() { [ "$cpio_list" ] || return 0 echo "$cpio_list" | LANG=C sort -u | gen_init_cpio - cpio_list= } # awk style field access # $1 - field number; rest is argument string field() { shift $1 ; echo $1 } 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 } # for each file print a line in following format # # for links, devices etc the format differs. See gen_init_cpio for details parse() { local location="$1" local name="/${location#${srcdir}}" # change '//' into '/' name=$(echo "$name" | sed -e 's://*:/:g') local mode="$2" local uid="$3" local gid="$4" local ftype=$(filetype "${location}") # remap uid/gid to 0 if necessary [ "$root_uid" = "squash" ] && uid=0 || [ "$uid" -eq "$root_uid" ] && uid=0 [ "$root_gid" = "squash" ] && gid=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=`LC_ALL=C ls -l "${location}"` local maj=`field 5 ${dev}` local min=`field 6 ${dev}` maj=${maj%,} [ -b "${location}" ] && dev="b" || dev="c" str="${ftype} ${name} ${str} ${dev} ${maj} ${min}" ;; "slink") local target=`readlink "${location}"` str="${ftype} ${name} ${target} ${str}" ;; *) str="${ftype} ${name} ${str}" ;; esac echo "${str}" return 0 } # process one directory (incl sub-directories) gen_dirlist() { srcdir=$(echo "$1" | sed -e 's://*:/:g') dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n") # If $dirlist is only one line, then the directory is empty if [ "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then echo "${dirlist}" | \ while read x; do parse ${x} done fi } ends_with() { [ x"${1}" != x"${1%$2}" ]; } gen_filelist() { local src=$1 local dst=$2 if ends_with "$dst" "/"; then dst="$dst$(basename $src)" fi local dir=$(dirname $dst) while [ -n "$dir" -a "$dir" != "." -a "$dir" != "/" ]; do echo "dir $dir 0755 0 0" dir=$(dirname $dir) done echo "file $dst $src $(find $src -printf '%m') 0 0" } while [ $# -gt 0 ]; do arg="$1" shift case "$arg" in "-u") # map $1 to uid=0 (root) root_uid="$1" shift ;; "-g") # map $1 to gid=0 (root) root_gid="$1" shift ;; *"->"*) src=${arg%%->*} dst=${arg#*->} cpio_list=$(echo "$cpio_list"; gen_filelist $src $dst) ;; *) if [ -d "$arg" ]; then cpio_list="$cpio_list$(gen_dirlist $arg)" elif [ -f "$arg" ]; then case "$(file -L $arg)" in *"cpio archive"*) gen_cpio_from_list cat $arg ;; *) echo >&2 "Unsuported file format: $arg" usage exit 1 ;; esac else echo >&2 "No file: $arg" exit 1 fi esac done gen_cpio_from_list if [ -n "$gzip" ]; then if [ -n "$mkimage" ]; then exec >${tmp}.gz else exec 1<&3 fi gzip -n -c ${tmp} rm $tmp tmp=${tmp}.gz fi if [ -n "$mkimage" ]; then exec 1<&3 tmp2=$(mktemp) mkimage $mkimage -d $tmp $tmp2 >&2 cat $tmp2 rm $tmp $tmp2 fi