4 _root="$(dirname "${0}")"
5 . "${_root}/lib/env.sh"
10 targets="prepwork admin packages patch overlay prepboot preptmp prepetc prepvar imgboot imgconf imgetc imgvar custom"
13 [ "${*}" ] && printf "${*}\n\n"
14 echo "Usage: $(basename "${0}") <-b basedir> <-t stagedir> <-i pkgsdir> <-p patchdir>"
15 echo " <-r rootdir> <-l logfile> [-h] <targets>"
16 echo ' -b basedir Basedir for automagic defaults'
17 echo ' -t stagedir Staging directory name (Default: ${base}/stage)'
18 echo ' -i pkgsdir Directory holding packages to install (Default: ${base}/pkg)'
19 echo ' -p patchdir Directory holding patches to apply (Default: ${base}/patch)'
20 echo ' -o overlaydir Directory holding an overlay tree (Default: ${base}/overlay)'
21 echo ' -r rootdir Directory holding the virgin source tree (Default: ${root})'
22 echo ' -l logfile File to hold stderr spam (Default: ${stage}/gentree.log'
23 echo ' -h Hello! >^-^<'
25 echo 'Available targets:'
26 for target in ${targets}
33 while getopts "b:t:i:p:o:r:l:h" opt
36 b) base="${OPTARG}" ;;
37 t) stage="${OPTARG}" ;;
38 i) pkgs="${OPTARG}" ;;
39 p) patch="${OPTARG}" ;;
40 o) overlay="${OPTARG}" ;;
41 r) root="${OPTARG}" ;;
42 l) logfile="${OPTARG}" ;;
44 [?]) pebkac "Unrecognized option ${opt}" ;;
47 shift $(( $OPTIND - 1 ))
49 sequence="${*:-${targets}}"
51 base="${base:-/usr/home/cyberleo/world}"
52 stage="${stage:-${base}/tree}"
53 pkgs="${pkgs:-${base}/pkg}"
54 patch="${patch:-${base}/patch}"
55 overlay="${overlay:-${base}/overlay}"
56 root="${root:-${root}}"
57 logfile="${logfile:-${stage}/gentree.log}"
60 stage="$(realpath "${stage}")"
70 # Make sure the provided file(s) have only one link!
73 if [ -f "${1}" -a "$(stat -f '%l' "${1}")" -gt 1 ]
75 cp -p "${1}" "${1}.tmp" && mv "${1}.tmp" "${1}" || err "breaklink failed"
84 if [ -d "${stage}" -a \( -d "${sroot}" -o -d "${sboot}" -o -d "${sconf}" \) ]
86 yn n " ${a_yellow}*${a_normal} Workspace already exists. Delete? [y/N]" || err Aborting
87 chk rm -Rf "${sroot}" "${sboot}" "${sconf}"
89 chk mkdir -p "${sroot}"
90 # Eliminate schg, because it interferes with hardlinks
91 chk chflags -R noschg "${root}/lib"
92 chk chflags -R noschg "${root}/libexec"
93 chk chflags -R noschg "${root}/sbin"
94 chk chflags -R noschg "${root}/usr"
95 ( cd "${root}" && find . | cpio -p --link "${sroot}" ) || chk
99 log Create an emergency user admin/admin
100 # delink passwd to ensure it doesn't get patched in-place
101 chk onelink "${sroot}/etc/passwd" "${sroot}/etc/master.passwd"
102 echo '$1$2rXOWsK/$eiBHA6K7xL96DZbcY24YR0' | chk chroot "${sroot}" /usr/sbin/pw useradd admin -u 999 -g wheel -G operator -c Administrator -d /usr/home/admin -m -s /bin/csh -H 0
106 if [ -d "${pkgs}" -a "$(ls -1 "${pkgs}" | wc -l)" -gt 0 ]
108 count="$(ls -1 "${pkgs}" | wc -l)"
109 log Install ${count} packages from "${pkgs}"
110 chk mkdir -p "${sroot}/pkg"
111 ( cd "${pkgs}" && find . | cpio -p --link "${sroot}/pkg" ) || chk
112 chk chroot "${sroot}" /bin/sh -c 'cd /pkg; exec pkg_add -F *'
113 chk rm -Rf "${sroot}/pkg"
118 log Apply patches from "${patch}"
119 for file in "${patch}"/*
121 note "... $(basename "${file}")"
122 echo "... $(basename "${file}")" >&2
123 ( cd "${sroot}" && patch < "${file}" ) || chk
125 sed -e '/^+++ /!d; s/^+++ //; s/ *.*$//' "${file}" | while read target
127 rm -f "${sroot}/${target}.orig"
133 log Apply overlay from "${overlay}"
134 [ -d "${overlay}" ] || return
135 ( cd "${overlay}" && find . | cpio -p "${sroot}" ) || chk
140 chk mv "${sroot}/boot/boot" "${sroot}/boot/boot.blk"
141 chk ln -sf . "${sroot}/boot/boot"
146 ( cd "${sroot}/tmp" && find . | cpio -p --link ../var/tmp ) || chk
147 chk rm -Rf "${sroot}/tmp"
148 chk ln -sf var/tmp "${sroot}/tmp"
153 chk mkdir -p "${sroot}/etc/local"
154 chk mkdir -p "${sroot}/usr/local/etc" # Silence warnings
155 ( cd "${sroot}/usr/local/etc" && find . | cpio -p --link ../../../etc/local ) || chk
156 chk rm -Rf "${sroot}/usr/local/etc"
157 chk ln -sf ../../etc/local "${sroot}/usr/local/etc"
162 # Nothing necessary here
166 log Create boot imgsrc
167 chk mv "${sroot}/boot" "${stage}"
168 chk mkdir -p "${sroot}/boot"
169 chk rm -f "${sboot}/kernel"/*.symbols
170 # Gzipped kernel is okay
171 gzip -9 "${sboot}/kernel/kernel"
172 # Compress all files in /boot/kernel
173 # Loader cannot handle gzipped modules. Decompress the required modules
174 # kldload cannot handle gzipped modules either
175 #find "${sboot}/kernel" -type f | xargs gzip -9f || chk
176 #cat "${sboot}/loader.conf" | grep '_load=' | sed -e 's/^\(.*\)_load=.*$/\1/' | while read mod
178 # [ -f "${sboot}/kernel/${mod}.ko.gz" ] && gunzip "${sboot}/kernel/${mod}.ko.gz" || chk
181 # Instead: put all modules in the root image, except those needed to boot the kernel
182 chk mkdir -p "${sroot}/boot/boot"
183 chk mkdir -p "${sroot}/boot/kernel"
185 # Link all modules into the root fs
186 ( cd "${sboot}/kernel" && find . -name '*.ko' -o -name 'linker.hints' | cpio -p --link "${sroot}/boot/kernel" ) || chk
188 # Remove all modules from the root fs that are preloaded by the loader
189 cat "${sboot}/loader.conf" | grep '_load=' | sed -e 's#^\(.*\)_load=.*$#'"${sroot}/boot/kernel/"'\1.ko#' | xargs rm -f
191 # Remove all modules from the boot fs that are present in the root fs
192 ( cd "${sroot}/boot/kernel" && ls -1 ) | sed -e 's#^#'"${sboot}/kernel/"'#' | xargs rm -f
194 # Link the preloaded modules from the boot fs to the root fs, to provide a homogenous view
195 ( cd "${sboot}/kernel" && ls -1 ) | while read mod
197 ln -sf "../boot/kernel/${mod}" "${sroot}/boot/kernel/${mod}"
202 log Create conf imgsrc
203 chk mkdir -p "${sroot}/conf"
204 echo "ufs:/dev/ufs/conf" > "${sroot}/conf/diskless_remount" || chk
205 chk mkdir -p "${sconf}/base/etc"
206 chk mkdir -p "${sconf}/base/var"
207 chk mkdir -p "${sconf}/default/etc"
208 chk mkdir -p "${sconf}/default/var"
212 log Create etc imgsrc
213 chk touch "${sroot}/etc/diskless"
214 chk mv "${sroot}/etc" "${stage}"
215 chk mkdir -p "${sroot}/etc"
216 chk cp -p "${stage}/etc/rc" "${stage}/etc/rc.subr" "${stage}/etc/rc.initdiskless" "${stage}/etc/login.conf.db" "${stage}/etc/diskless" "${sroot}/etc"
217 echo "10240" > "${sconf}/base/etc/md_size" || chk
218 ( cd "${stage}" && find etc | cpio -o ) | gzip -9 > "${sconf}/base/etc.cpio.gz" || chk
219 chk rm -Rf "${stage}/etc"
223 log Create var imgsrc
224 chk mv "${sroot}/var" "${stage}"
225 chk mkdir -p "${sroot}/var"
226 echo "131072" > "${sconf}/base/var/md_size" || chk
227 ( cd "${stage}" && find var | cpio -o ) | gzip -9 > "${sconf}/base/var.cpio.gz" || chk
228 chk rm -Rf "${stage}/var"
232 log Patch in custom config
233 ( cd "${base}/conf" && find . | cpio -p --link "${sconf}/default" ) || chk
234 # Make sure files in default are newer than the tagfile, so they will be caught by saveconfig
235 find "${sconf}/default" -type f -print0 | xargs -0 touch
238 for step in ${sequence}
240 echo "${targets}" | grep -q "${step}" || err Unrecognized target "${step}"