Merge branch 'master'
[linux-2.6] / scripts / gen_initramfs_list.sh
1 #!/bin/bash
2 # Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org>
3 # Released under the terms of the GNU GPL
4 #
5 # Generate a newline separated list of entries from the file/directory
6 # supplied as an argument.
7 #
8 # If a file/directory is not supplied then generate a small dummy file.
9 #
10 # The output is suitable for gen_init_cpio built from usr/gen_init_cpio.c.
11 #
12
13 default_initramfs() {
14         cat <<-EOF
15                 # This is a very simple, default initramfs
16
17                 dir /dev 0755 0 0
18                 nod /dev/console 0600 0 0 c 5 1
19                 dir /root 0700 0 0
20         EOF
21 }
22
23 filetype() {
24         local argv1="$1"
25
26         # symlink test must come before file test
27         if [ -L "${argv1}" ]; then
28                 echo "slink"
29         elif [ -f "${argv1}" ]; then
30                 echo "file"
31         elif [ -d "${argv1}" ]; then
32                 echo "dir"
33         elif [ -b "${argv1}" -o -c "${argv1}" ]; then
34                 echo "nod"
35         elif [ -p "${argv1}" ]; then
36                 echo "pipe"
37         elif [ -S "${argv1}" ]; then
38                 echo "sock"
39         else
40                 echo "invalid"
41         fi
42         return 0
43 }
44
45 print_mtime() {
46         local argv1="$1"
47         local my_mtime="0"
48
49         if [ -e "${argv1}" ]; then
50                 my_mtime=$(find "${argv1}" -printf "%T@\n" | sort -r | head -n 1)
51         fi
52         
53         echo "# Last modified: ${my_mtime}"
54         echo
55 }
56
57 parse() {
58         local location="$1"
59         local name="${location/${srcdir}//}"
60         # change '//' into '/'
61         name="${name//\/\///}"
62         local mode="$2"
63         local uid="$3"
64         local gid="$4"
65         local ftype=$(filetype "${location}")
66         # remap uid/gid to 0 if necessary
67         [ "$uid" -eq "$root_uid" ] && uid=0
68         [ "$gid" -eq "$root_gid" ] && gid=0
69         local str="${mode} ${uid} ${gid}"
70
71         [ "${ftype}" == "invalid" ] && return 0
72         [ "${location}" == "${srcdir}" ] && return 0
73
74         case "${ftype}" in
75                 "file")
76                         str="${ftype} ${name} ${location} ${str}"
77                         ;;
78                 "nod")
79                         local dev_type=
80                         local maj=$(LC_ALL=C ls -l "${location}" | \
81                                         gawk '{sub(/,/, "", $5); print $5}')
82                         local min=$(LC_ALL=C ls -l "${location}" | \
83                                         gawk '{print $6}')
84
85                         if [ -b "${location}" ]; then
86                                 dev_type="b"
87                         else
88                                 dev_type="c"
89                         fi
90                         str="${ftype} ${name} ${str} ${dev_type} ${maj} ${min}"
91                         ;;
92                 "slink")
93                         local target=$(LC_ALL=C ls -l "${location}" | \
94                                         gawk '{print $11}')
95                         str="${ftype} ${name} ${target} ${str}"
96                         ;;
97                 *)
98                         str="${ftype} ${name} ${str}"
99                         ;;
100         esac
101
102         echo "${str}"
103
104         return 0
105 }
106
107 usage() {
108         printf    "Usage:\n"
109         printf    "$0 [ [-u <root_uid>] [-g <root_gid>] [-d | <cpio_source>] ] . . .\n"
110         printf    "\n"
111         printf -- "-u <root_uid>  User ID to map to user ID 0 (root).\n"
112         printf    "               <root_uid> is only meaningful if <cpio_source>\n"
113         printf    "               is a directory.\n"
114         printf -- "-g <root_gid>  Group ID to map to group ID 0 (root).\n"
115         printf    "               <root_gid> is only meaningful if <cpio_source>\n"
116         printf    "               is a directory.\n"
117         printf    "<cpio_source>  File list or directory for cpio archive.\n"
118         printf    "               If <cpio_source> is not provided then a\n"
119         printf    "               a default list will be output.\n"
120         printf -- "-d             Output the default cpio list.  If no <cpio_source>\n"
121         printf    "               is given then the default cpio list will be output.\n"
122         printf    "\n"
123         printf    "All options may be repeated and are interpreted sequentially\n"
124         printf    "and immediately.  -u and -g states are preserved across\n"
125         printf    "<cpio_source> options so an explicit \"-u 0 -g 0\" is required\n"
126         printf    "to reset the root/group mapping.\n"
127 }
128
129 build_list() {
130         printf "\n#####################\n# $cpio_source\n"
131
132         if [ -f "$cpio_source" ]; then
133                 print_mtime "$cpio_source"
134                 cat "$cpio_source"
135         elif [ -d "$cpio_source" ]; then
136                 srcdir=$(echo "$cpio_source" | sed -e 's://*:/:g')
137                 dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n" 2>/dev/null)
138
139                 # If $dirlist is only one line, then the directory is empty
140                 if [  "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then
141                         print_mtime "$cpio_source"
142                 
143                         echo "${dirlist}" | \
144                         while read x; do
145                                 parse ${x}
146                         done
147                 else
148                         # Failsafe in case directory is empty
149                         default_initramfs
150                 fi
151         else
152                 echo "  $0: Cannot open '$cpio_source'" >&2
153                 exit 1
154         fi
155 }
156
157
158 root_uid=0
159 root_gid=0
160
161 while [ $# -gt 0 ]; do
162         arg="$1"
163         shift
164         case "$arg" in
165                 "-u")
166                         root_uid="$1"
167                         shift
168                         ;;
169                 "-g")
170                         root_gid="$1"
171                         shift
172                         ;;
173                 "-d")
174                         default_list="$arg"
175                         default_initramfs
176                         ;;
177                 "-h")
178                         usage
179                         exit 0
180                         ;;
181                 *)
182                         case "$arg" in
183                                 "-"*)
184                                         printf "ERROR: unknown option \"$arg\"\n" >&2
185                                         printf "If the filename validly begins with '-', then it must be prefixed\n" >&2
186                                         printf "by './' so that it won't be interpreted as an option." >&2
187                                         printf "\n" >&2
188                                         usage >&2
189                                         exit 1
190                                         ;;
191                                 *)
192                                         cpio_source="$arg"
193                                         build_list
194                                         ;;
195                         esac
196                         ;;
197         esac
198 done
199
200 # spit out the default cpio list if a source hasn't been specified
201 [ -z "$cpio_source" -a -z "$default_list" ] && default_initramfs
202
203 exit 0