2005-04-17 02:20:36 +04:00
#!/bin/bash
# Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org>
2007-02-06 04:18:20 +03:00
# Copyright (C) 2006 Sam Ravnborg <sam@ravnborg.org>
2005-04-17 02:20:36 +04:00
#
2006-04-11 15:24:32 +04:00
# Released under the terms of the GNU GPL
2005-04-17 02:20:36 +04:00
#
2006-04-11 15:24:32 +04:00
# Generate a cpio packed initramfs. It uses gen_init_cpio to generate
2009-01-07 11:10:27 +03:00
# the cpio archive, and then compresses it.
2006-04-11 15:24:32 +04:00
# 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>} ...
2009-01-07 11:10:27 +03:00
-o <file> Create compressed initramfs file named <file> using
gen_init_cpio and compressor depending on the extension
2006-04-11 15:24:32 +04:00
-u <uid> User ID to map to user ID 0 ( root) .
2007-05-11 09:44:28 +04:00
<uid> is only meaningful if <cpio_source> is a
directory. "squash" forces all files to uid 0.
2006-04-11 15:24:32 +04:00
-g <gid> Group ID to map to group ID 0 ( root) .
2007-05-11 09:44:28 +04:00
<gid> is only meaningful if <cpio_source> is a
directory. "squash" forces all files to gid 0.
2006-04-11 15:24:32 +04:00
<cpio_source> File list or directory for cpio archive.
2007-02-06 04:18:20 +03:00
If <cpio_source> is a .cpio file it will be used
2006-04-11 15:24:32 +04:00
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
}
2007-02-06 04:18:20 +03:00
# awk style field access
# $1 - field number; rest is argument string
field( ) {
shift $1 ; echo $1
}
2006-04-11 15:24:32 +04:00
list_default_initramfs( ) {
# echo usr/kinit/kinit
:
}
2005-04-17 02:20:36 +04:00
default_initramfs( ) {
2006-04-11 15:24:32 +04:00
cat <<-EOF >> ${ output }
2005-04-17 02:20:36 +04:00
# 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
2006-04-11 15:24:32 +04:00
# file /kinit usr/kinit/kinit 0755 0 0
# slink /init kinit 0755 0 0
2005-04-17 02:20:36 +04:00
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
}
2006-04-11 15:24:32 +04:00
list_print_mtime( ) {
:
}
2005-04-17 02:20:36 +04:00
print_mtime( ) {
local my_mtime = "0"
2006-04-11 15:24:32 +04:00
if [ -e " $1 " ] ; then
my_mtime = $( find " $1 " -printf "%T@\n" | sort -r | head -n 1)
2005-04-17 02:20:36 +04:00
fi
2006-04-11 15:24:32 +04:00
echo " # Last modified: ${ my_mtime } " >> ${ output }
echo "" >> ${ output }
}
list_parse( ) {
2009-02-09 20:49:52 +03:00
[ ! -L " $1 " ] && echo " $1 \\ " || :
2005-04-17 02:20:36 +04:00
}
2006-04-11 15:24:32 +04:00
# 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
2005-04-17 02:20:36 +04:00
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
2007-05-11 09:44:28 +04:00
[ " $root_uid " = "squash" ] && uid = 0 || [ " $uid " -eq " $root_uid " ] && uid = 0
[ " $root_gid " = "squash" ] && gid = 0 || [ " $gid " -eq " $root_gid " ] && gid = 0
2005-04-17 02:20:36 +04:00
local str = " ${ mode } ${ uid } ${ gid } "
[ " ${ ftype } " = = "invalid" ] && return 0
[ " ${ location } " = = " ${ srcdir } " ] && return 0
case " ${ ftype } " in
"file" )
str = " ${ ftype } ${ name } ${ location } ${ str } "
; ;
"nod" )
2007-02-06 04:18:20 +03:00
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 } "
2005-04-17 02:20:36 +04:00
; ;
"slink" )
2008-04-02 16:50:05 +04:00
local target = ` readlink " ${ location } " `
2005-04-17 02:20:36 +04:00
str = " ${ ftype } ${ name } ${ target } ${ str } "
; ;
*)
str = " ${ ftype } ${ name } ${ str } "
; ;
esac
2006-04-11 15:24:32 +04:00
echo " ${ str } " >> ${ output }
2005-04-17 02:20:36 +04:00
return 0
}
2006-04-11 15:24:32 +04:00
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( ) {
2006-11-25 22:09:18 +03:00
:
2006-04-11 15:24:32 +04:00
}
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' )
2007-04-30 09:34:15 +04:00
dirlist = $( find " ${ srcdir } " -printf "%p %m %U %G\n" )
2006-04-11 15:24:32 +04:00
# 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
2005-04-17 02:20:36 +04:00
}
2006-04-11 15:24:32 +04:00
# 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 "
2007-04-26 11:17:29 +04:00
is_cpio = " $( echo " $1 " | sed 's/^.*\.cpio\(\..*\)\?/cpio/' ) "
2006-04-11 15:24:32 +04:00
if [ $2 -eq 0 -a ${ is_cpio } = = "cpio" ] ; then
cpio_file = $1
2007-04-26 11:17:29 +04:00
echo " $1 " | grep -q '^.*\.cpio\..*' && is_cpio_compressed = "compressed"
2006-04-11 15:24:32 +04:00
[ ! -z ${ dep_list } ] && echo " $1 "
return 0
fi
if [ -z ${ dep_list } ] ; then
print_mtime " $1 " >> ${ output }
cat " $1 " >> ${ output }
2005-04-17 02:20:36 +04:00
else
2006-05-01 01:56:33 +04:00
cat " $1 " | while read type dir file perm ; do
if [ " $type " = = "file" ] ; then
echo " $file \\ " ;
fi
done
2005-04-17 02:20:36 +04:00
fi
2006-04-11 15:24:32 +04:00
elif [ -d " $1 " ] ; then
dir_filelist " $1 "
2005-04-17 02:20:36 +04:00
else
2006-04-11 15:24:32 +04:00
echo " ${ prog } : Cannot open ' $1 ' " >& 2
2005-04-17 02:20:36 +04:00
exit 1
fi
}
2006-04-11 15:24:32 +04:00
prog = $0
2005-04-17 02:20:36 +04:00
root_uid = 0
root_gid = 0
2006-04-11 15:24:32 +04:00
dep_list =
cpio_file =
cpio_list =
output = "/dev/stdout"
output_file = ""
2007-04-26 11:17:29 +04:00
is_cpio_compressed =
2009-01-07 11:10:27 +03:00
compr = "gzip -9 -f"
2005-04-17 02:20:36 +04:00
2006-04-11 15:24:32 +04:00
arg = " $1 "
case " $arg " in
"-l" ) # files included in initramfs - used by kbuild
dep_list = "list_"
2006-11-25 22:09:18 +03:00
echo "deps_initramfs := \\"
2006-04-11 15:24:32 +04:00
shift
; ;
2009-01-07 11:10:27 +03:00
"-o" ) # generate compressed cpio image named $1
2006-04-11 15:24:32 +04:00
shift
output_file = " $1 "
cpio_list = " $( mktemp ${ TMPDIR :- /tmp } /cpiolist.XXXXXX) "
output = ${ cpio_list }
2009-01-07 11:10:27 +03:00
echo " $output_file " | grep -q " \.gz $" && compr = "gzip -9 -f"
echo " $output_file " | grep -q " \.bz2 $" && compr = "bzip2 -9 -f"
echo " $output_file " | grep -q " \.lzma $" && compr = "lzma -9 -f"
echo " $output_file " | grep -q " \.cpio $" && compr = "cat"
2006-04-11 15:24:32 +04:00
shift
; ;
esac
2005-04-17 02:20:36 +04:00
while [ $# -gt 0 ] ; do
arg = " $1 "
shift
case " $arg " in
2006-04-11 15:24:32 +04:00
"-u" ) # map $1 to uid=0 (root)
2005-04-17 02:20:36 +04:00
root_uid = " $1 "
shift
; ;
2006-04-11 15:24:32 +04:00
"-g" ) # map $1 to gid=0 (root)
2005-04-17 02:20:36 +04:00
root_gid = " $1 "
shift
; ;
2006-04-11 15:24:32 +04:00
"-d" ) # display default initramfs list
2005-04-17 02:20:36 +04:00
default_list = " $arg "
2006-04-11 15:24:32 +04:00
${ dep_list } default_initramfs
2005-04-17 02:20:36 +04:00
; ;
"-h" )
usage
exit 0
; ;
*)
case " $arg " in
"-" *)
2006-04-11 15:24:32 +04:00
unknown_option
2005-04-17 02:20:36 +04:00
; ;
2006-04-11 15:24:32 +04:00
*) # input file/dir - process it
input_file " $arg " " $# "
2005-04-17 02:20:36 +04:00
; ;
esac
; ;
esac
done
2009-01-07 11:10:27 +03:00
# If output_file is set we will generate cpio archive and compress it
2006-04-11 15:24:32 +04:00
# 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 }
2007-04-26 11:17:29 +04:00
if [ " ${ is_cpio_compressed } " = "compressed" ] ; then
cat ${ cpio_tfile } > ${ output_file }
else
2009-02-20 00:39:21 +03:00
( cat ${ cpio_tfile } | ${ compr } - > ${ output_file } ) \
|| ( rm -f ${ output_file } ; false )
2007-04-26 11:17:29 +04:00
fi
2006-04-11 15:24:32 +04:00
[ -z ${ cpio_file } ] && rm ${ cpio_tfile }
fi
2005-04-17 02:20:36 +04:00
exit 0