]> rtime.felk.cvut.cz Git - novaboot.git/blobdiff - contrib/gen_cpio
server: Document how to use shell function for console_cmd
[novaboot.git] / contrib / gen_cpio
index 0a76ca791d65edc7019b9083e944b919f4d87427..8b9f1aac5abcfb319bb125e256f0e43a776452c6 100755 (executable)
@@ -9,20 +9,62 @@
 #
 # Released under the terms of the GNU GPL
 
-# Usage: gen_cpio rootfs.cpio myapp->/bin/ start.sh->/etc/init.d/S90startmyapp
+# 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="<mkimage params>"] [-u <uid>] [-g <gid>] {<cpio_source>}...
+       --gzip         Compress the resulting image with gzip
+       --mkimage=...  Pack the resulting image with U-Boot's "mkimage ..."
+       -u <uid>       User ID to map to user ID 0 (root).
+                      <uid> is only meaningful if <cpio_source> is a
+                      directory.  "squash" forces all files to uid 0.
+                      Default: $root_uid (you)
+       -g <gid>       Group ID to map to group ID 0 (root).
+                      <gid> is only meaningful if <cpio_source> is a
+                      directory.  "squash" forces all files to gid 0.
+                      Default: $root_gid (you)
+       <cpio_source>  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
+<cpio_source> options so an explicit "-u 0 -g 0" is required to reset
+the root/group mapping.
+EOF
+}
+
 while [ $# -gt 0 ]; do
     case "$1" in
-       --mkimage=*) mkimage=${1#--mkimage=};;
+       --gzip)
+           gzip=1
+           ;;
+       --mkimage=*)
+           mkimage=${1#--mkimage=}
+           ;;
+       "-h"|"--help")
+           usage
+           exit 0
+           ;;
        *) break;;
     esac
     shift
 done
 
-if [ -n "$mkimage" ]; then
+if [ -n "$mkimage" -o -n "$gzip" ]; then
     tmp=$(mktemp)
     exec 3<&1 1>$tmp
 fi
@@ -33,6 +75,12 @@ gen_cpio_from_list() {
     cpio_list=
 }
 
+# awk style field access
+# $1 - field number; rest is argument string
+field() {
+       shift $1 ; echo $1
+}
+
 filetype() {
     local argv1="$1"
 
@@ -55,9 +103,72 @@ filetype() {
     return 0
 }
 
-ends_with() { [ x"${1}" != x"${1#$2}" ]; }
+# 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
+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")
 
-gen_list() {
+    # 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
 
@@ -69,39 +180,61 @@ gen_list() {
        echo "dir $dir 0755 0 0"
        dir=$(dirname $dir)
     done
-    echo "$(filetype $src) $dst $src $(find $src -printf '%m') 0 0"
+    echo "file $dst $src $(find $src -printf '%m') 0 0"
 }
 
 while [ $# -gt 0 ]; do
     arg="$1"
     shift
-    if [ -f "$arg" ]; then
-       case "$(file $arg)" in
-           *"cpio archive"*)
-               gen_cpio_from_list
-               cat $arg
-               ;;
-           *)
-               echo >&2 "Unsuported file format: $arg"
-               exit 1
-               ;;
-       esac
-    else
-       case "$arg" in
-           *"->"*)
-               src=${arg%%->*}
-               dst=${arg#*->}
-               cpio_list="$cpio_list$(gen_list $src $dst)"
-               ;;
-           *)
+    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
-       esac
-    fi
+           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)