3 # Copyright (c) 2012-2013 SRI International
4 # Copyright (c) 2012 Robert N. M. Watson
7 # This software was developed by SRI International and the University of
8 # Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
9 # ("CTSRD"), as part of the DARPA CRASH research programme.
11 # Redistribution and use in source and binary forms, with or without
12 # modification, are permitted provided that the following conditions
14 # 1. Redistributions of source code must retain the above copyright
15 # notice, this list of conditions and the following disclaimer.
16 # 2. Redistributions in binary form must reproduce the above copyright
17 # notice, this list of conditions and the following disclaimer in the
18 # documentation and/or other materials provided with the distribution.
20 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 usage: makeroot.sh [-B byte-order] [-d] [-e <extras manifest>] [-f <filelist>]
38 [-k <keydir> [-K <user>]]
39 [-p <master.passwd> [-g <groupfile>]] [-s <size>]
47 echo `basename $0` "$@" 1>&2
60 if [ -z "${DEBUG}" ]; then
63 warn "temp directory left at ${tmpdir}"
68 # Allow duplicate manifest entries when not file list is given because the
69 # FreeBSD METALOG still includes it.
78 while getopts "B:de:f:g:K:k:l:p:s:" opt; do
80 B) BFLAG="-B ${OPTARG}" ;;
82 e) EXTRAS="${EXTRAS} ${OPTARG}" ;;
83 f) FILELIST="${OPTARG}"; DUPFLAG= ;;
84 g) GROUP="${OPTARG}" ;;
85 K) KEYUSERS="${KEYUSERS} ${OPTARG}" ;;
86 k) KEYDIR="${OPTARG}" ;;
87 l) LABEL="${OPTARG}" ;;
88 p) PASSWD="${OPTARG}" ;;
89 s) SIZE="${OPTARG}" ;;
93 shift $(($OPTIND - 1))
99 IMGFILE=$(realpath $(dirname $1))/$(basename $1)
104 if [ ! -r ${BSDROOT}/METALOG ]; then
105 err 1 "${BSDROOT} does not contain a METALOG"
108 if [ -n "${GROUP}" -a -z "${PASSWD}" ]; then
109 warn "-g requires -p"
113 if [ -n "${KEYUSERS}" -a -z "${KEYDIR}" ]; then
114 warn "-K requires -k"
117 if [ -n "${KEYDIR}" -a -z "${KEYUSERS}" ]; then
121 tmpdir=`mktemp -d /tmp/makeroot.XXXXX`
122 if [ -z "${tmpdir}" -o ! -d "${tmpdir}" ]; then
123 err 1 "failed to create tmpdir"
127 manifest=${tmpdir}/manifest
129 echo "#mtree 2.0" > ${manifest}
131 if [ -n "${PASSWD}" ]; then
132 cp ${PASSWD} ${tmpdir}/master.passwd
133 pwd_mkdb -d ${tmpdir} -p ${tmpdir}/master.passwd
134 if [ -z "${GROUP}" ]; then
135 cp ${DBDIR}/group ${tmpdir}
137 cp ${GROUP} ${tmpdir}
140 cat <<EOF >> ${tmpdir}/passwd.mtree
141 ./etc/group type=file uname=root gname=wheel mode=0644 contents=${tmpdir}/group
142 ./etc/master.passwd type=file uname=root gname=wheel mode=0600 contents=${tmpdir}/master.passwd
143 ./etc/passwd type=file mode=0644 uname=root gname=wheel contents=${tmpdir}/passwd
144 ./etc/pwd.db type=file mode=0644 uname=root gname=wheel contents=${tmpdir}/pwd.db
145 ./etc/spwd.db type=file mode=0600 uname=root gname=wheel contents=${tmpdir}/spwd.db
147 EXTRAS="${EXTRAS} ${tmpdir}/passwd.mtree"
152 if [ -n "${FILELIST}" ]; then
153 # build manifest from root manifest and FILELIST
154 (echo .; grep -v ^# ${FILELIST} | while read path; do
155 # Print each included path and all its sub-paths with a ./
156 # prepended. The "sort -u" will then discard all the
157 # duplicate directory entries. This ensures that we
158 # extract the permissions for each unlisted directory
161 while [ -n "${path}" ]; do
165 done) | sort -u ${BSDROOT}/METALOG - | \
167 !/ type=/ { file = $1 }
168 / type=/ { if ($1 == file) {print} }' >> ${manifest}
169 elif [ -n "${EXTRAS}" ]; then
170 # Start with all the files in BSDROOT/METALOG except those in
171 # one of the EXTRAS manifests.
172 grep -h type=file ${EXTRAS} | cut -d' ' -f1 | \
173 sort -u ${BSDROOT}/METALOG - | awk '
174 !/ type=/ { file = $1 }
175 / type=/ { if ($1 != file) {print} }' >> ${manifest}
177 sort -u ${BSDROOT}/METALOG >> ${manifest}
180 # For each extras file, add contents keys relative to the directory the
181 # manifest lives in for each file line that does not have one. Adjust
182 # contents keys relative to ./ to be relative to the same directory.
183 for eman in ${EXTRAS}; do
184 if [ ! -f ${eman} ]; then
185 err 1 "${eman} is not a regular file"
187 extradir=`realpath ${eman}`; extradir=`dirname ${extradir}`
190 if ($0 !~ /type=file/) {
193 if ($0 !~ /contents=/) {
194 printf ("%s contents=%s\n", $0, $1)
200 sed -e "s|contents=\./|contents=${extradir}/|" >> ${manifest}
203 # /etc/rcorder.start allows the startup order to be stable even if
204 # not all startup scripts are installed. In theory it should be
205 # unnecessary, but dependencies in rc.d appear to be under recorded.
206 # This is a hack local to beri/cheribsd.
208 echo /etc/rc.d/FIRST > ${tmpdir}/rcorder.start
209 rcorder -s nostart ${BSDROOT}/etc/rc.d/* | sed -e "s:^${BSDROOT}::" | \
210 grep -v LAST | grep -v FIRST >> \
211 ${tmpdir}/rcorder.start
212 echo /etc/rc.d/LAST >> ${tmpdir}/rcorder.start
213 echo "./etc/rcorder.start type=file mode=644 uname=root gname=wheel" \
214 "contents=${tmpdir}/rcorder.start" >> ${manifest}
216 # Add all public keys in KEYDIR to roots' authorized_keys file.
217 if [ -n "${KEYDIR}" ]; then
218 cat ${KEYDIR}/*.pub > ${tmpdir}/authorized_keys
219 if [ ! -s ${tmpdir}/authorized_keys ]; then
220 err 1 "no keys found in ${KEYDIR}"
222 for user in ${KEYUSERS}; do
223 userdir=`awk -F: "{if (\\\$1 == \"${user}\") {print \\\$9; exit} }" ${DBDIR}/master.passwd`
224 gid=`awk -F: "{if (\\\$1 == \"${user}\") {print \\\$4; exit} }" ${DBDIR}/master.passwd`
225 group=`awk -F: "{if (\\\$3 == \"${gid}\") {print \\\$1; exit} }" ${DBDIR}/group`
226 if [ -z "${userdir}" ]; then
227 err 1 "${user}: not found in ${DBDIR}/master.passwd"
229 echo ".${userdir}/.ssh type=dir mode=700 uname=${user} gname=${group}" >> ${manifest}
230 echo ".${userdir}/.ssh/authorized_keys type=file mode=600 uname=${user} gname=${group} contents=${tmpdir}/authorized_keys" >> ${manifest}
234 if [ -n "${LABEL}" ]; then
235 LABELFLAG="-o label=${LABEL}"
237 if [ -n "${SIZE}" ]; then
238 SIZEFLAG="-s ${SIZE}"
241 cd ${BSDROOT}; makefs ${DUPFLAG} -N ${DBDIR} ${SIZEFLAG} ${BFLAG} \
242 -t ffs ${LABELFLAG} -f 256 ${IMGFILE} ${manifest}