]> rtime.felk.cvut.cz Git - novaboot.git/blob - contrib/gen_cpio
tests: Make shebangs NixOS compatible
[novaboot.git] / contrib / gen_cpio
1 #!/bin/sh
2 #
3 # Copyright (C) Michal Sojka <sojkam1@fel.cvut.cz>
4 #
5 # Includes pieces from gen_initramfs_list.sh:
6 #
7 # Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org>
8 # Copyright (C) 2006 Sam Ravnborg <sam@ravnborg.org>
9 #
10 # Released under the terms of the GNU GPL
11
12 # Usage: gen_cpio rootfs.cpio "myapp->/bin/" "start.sh->/etc/init.d/S90startmyapp"
13 #        gen_cpio --mkimage="-T ramdisk -A powerpc -O linux" ...
14
15 set -e
16
17 root_uid=$(id -u)
18 root_gid=$(id -g)
19
20 usage() {
21 cat >&2 << EOF
22 Usage:
23 $0 [--mkimage="<mkimage params>"] [-u <uid>] [-g <gid>] {<cpio_source>}...
24         --gzip         Compress the resulting image with gzip
25         --mkimage=...  Pack the resulting image with U-Boot's "mkimage ..."
26         -u <uid>       User ID to map to user ID 0 (root).
27                        <uid> is only meaningful if <cpio_source> is a
28                        directory.  "squash" forces all files to uid 0.
29                        Default: $root_uid (you)
30         -g <gid>       Group ID to map to group ID 0 (root).
31                        <gid> is only meaningful if <cpio_source> is a
32                        directory.  "squash" forces all files to gid 0.
33                        Default: $root_gid (you)
34         <cpio_source>  One of:
35                        - *.cpio: Included directly into the output
36                        - directory: Content of the directory is included
37                          in the output
38                        - src/file->/dst/file: src/file appear in the output
39                          as dst/file
40                        - src/file->/dst/dir/: src/file appear in the output
41                          as dsr/dir/file
42
43 All options except --mkimage may be repeated and are interpreted
44 sequentially and immediately. -u and -g states are preserved across
45 <cpio_source> options so an explicit "-u 0 -g 0" is required to reset
46 the root/group mapping.
47 EOF
48 }
49
50 while [ $# -gt 0 ]; do
51     case "$1" in
52         --gzip)
53             gzip=1
54             ;;
55         --mkimage=*)
56             mkimage=${1#--mkimage=}
57             ;;
58         "-h"|"--help")
59             usage
60             exit 0
61             ;;
62         *) break;;
63     esac
64     shift
65 done
66
67 if [ -n "$mkimage" -o -n "$gzip" ]; then
68     tmp=$(mktemp)
69     exec 3<&1 1>$tmp
70 fi
71
72 gen_cpio_from_list() {
73     [ "$cpio_list" ] || return 0
74     echo "$cpio_list" | LANG=C sort -u | gen_init_cpio -
75     cpio_list=
76 }
77
78 # awk style field access
79 # $1 - field number; rest is argument string
80 field() {
81         shift $1 ; echo $1
82 }
83
84 filetype() {
85     local argv1="$1"
86
87     # symlink test must come before file test
88     if [ -L "${argv1}" ]; then
89         echo "slink"
90     elif [ -f "${argv1}" ]; then
91         echo "file"
92     elif [ -d "${argv1}" ]; then
93         echo "dir"
94     elif [ -b "${argv1}" -o -c "${argv1}" ]; then
95         echo "nod"
96     elif [ -p "${argv1}" ]; then
97         echo "pipe"
98     elif [ -S "${argv1}" ]; then
99         echo "sock"
100     else
101         echo "invalid"
102     fi
103     return 0
104 }
105
106 # for each file print a line in following format
107 # <filetype> <name> <path to file> <octal mode> <uid> <gid>
108 # for links, devices etc the format differs. See gen_init_cpio for details
109 parse() {
110         local location="$1"
111         local name="/${location#${srcdir}}"
112         # change '//' into '/'
113         name=$(echo "$name" | sed -e 's://*:/:g')
114         local mode="$2"
115         local uid="$3"
116         local gid="$4"
117         local ftype=$(filetype "${location}")
118         # remap uid/gid to 0 if necessary
119         [ "$root_uid" = "squash" ] && uid=0 || [ "$uid" -eq "$root_uid" ] && uid=0
120         [ "$root_gid" = "squash" ] && gid=0 || [ "$gid" -eq "$root_gid" ] && gid=0
121         local str="${mode} ${uid} ${gid}"
122
123         [ "${ftype}" = "invalid" ] && return 0
124         [ "${location}" = "${srcdir}" ] && return 0
125
126         case "${ftype}" in
127                 "file")
128                         str="${ftype} ${name} ${location} ${str}"
129                         ;;
130                 "nod")
131                         local dev=`LC_ALL=C ls -l "${location}"`
132                         local maj=`field 5 ${dev}`
133                         local min=`field 6 ${dev}`
134                         maj=${maj%,}
135
136                         [ -b "${location}" ] && dev="b" || dev="c"
137
138                         str="${ftype} ${name} ${str} ${dev} ${maj} ${min}"
139                         ;;
140                 "slink")
141                         local target=`readlink "${location}"`
142                         str="${ftype} ${name} ${target} ${str}"
143                         ;;
144                 *)
145                         str="${ftype} ${name} ${str}"
146                         ;;
147         esac
148
149         echo "${str}"
150
151         return 0
152 }
153
154 # process one directory (incl sub-directories)
155 gen_dirlist() {
156     srcdir=$(echo "$1" | sed -e 's://*:/:g')
157     dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n")
158
159     # If $dirlist is only one line, then the directory is empty
160     if [  "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then
161         echo "${dirlist}" | \
162             while read x; do
163             parse ${x}
164         done
165     fi
166 }
167
168
169 ends_with() { [ x"${1}" != x"${1%$2}" ]; }
170
171 gen_filelist() {
172     local src=$1
173     local dst=$2
174
175     if ends_with "$dst" "/"; then
176         dst="$dst$(basename $src)"
177     fi
178     local dir=$(dirname $dst)
179     while [ -n "$dir" -a "$dir" != "." -a "$dir" != "/" ]; do
180         echo "dir $dir 0755 0 0"
181         dir=$(dirname $dir)
182     done
183     echo "file $dst $src $(find $src -printf '%m') 0 0"
184 }
185
186 while [ $# -gt 0 ]; do
187     arg="$1"
188     shift
189     case "$arg" in
190         "-u")   # map $1 to uid=0 (root)
191             root_uid="$1"
192             shift
193             ;;
194         "-g")   # map $1 to gid=0 (root)
195             root_gid="$1"
196             shift
197             ;;
198         *"->"*)
199             src=${arg%%->*}
200             dst=${arg#*->}
201             cpio_list=$(echo "$cpio_list"; gen_filelist $src $dst)
202             ;;
203         *)
204             if [ -d "$arg" ]; then
205                 cpio_list="$cpio_list$(gen_dirlist $arg)"
206             elif [ -f "$arg" ]; then
207                 case "$(file -L $arg)" in
208                     *"cpio archive"*)
209                         gen_cpio_from_list
210                         cat $arg
211                         ;;
212                     *)
213                         echo >&2 "Unsuported file format: $arg"
214                         usage
215                         exit 1
216                         ;;
217                 esac
218             else
219                 echo >&2 "No file: $arg"
220                 exit 1
221             fi
222     esac
223 done
224
225 gen_cpio_from_list
226
227 if [ -n "$gzip" ]; then
228     if [ -n "$mkimage" ]; then
229         exec >${tmp}.gz
230     else
231         exec 1<&3
232     fi
233     gzip -n -c ${tmp}
234     rm $tmp
235     tmp=${tmp}.gz
236 fi
237
238 if [ -n "$mkimage" ]; then
239     exec 1<&3
240     tmp2=$(mktemp)
241     mkimage $mkimage -d $tmp $tmp2 >&2
242     cat $tmp2
243     rm $tmp $tmp2
244 fi