4 _root="$(dirname "${0}")"
5 . "${_root}/lib/env.sh"
10 targets="prepwork admin packages patch 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 ' -r rootdir Directory holding the virgin source tree (Default: ${root})'
21 echo ' -l logfile File to hold stderr spam (Default: ${stage}/gentree.log'
22 echo ' -h Hello! >^-^<'
24 echo 'Available targets:'
25 for target in ${targets}
32 while getopts "b:t:i:p:r:l:h" opt
35 b) base="${OPTARG}" ;;
36 t) stage="${OPTARG}" ;;
37 i) pkgs="${OPTARG}" ;;
38 p) patch="${OPTARG}" ;;
39 r) root="${OPTARG}" ;;
40 l) logfile="${OPTARG}" ;;
42 [?]) pebkac "Unrecognized option ${opt}" ;;
45 shift $(( $OPTIND - 1 ))
47 sequence="${*:-${targets}}"
49 base="${base:-/usr/home/cyberleo/world}"
50 stage="${stage:-${base}/tree}"
51 pkgs="${pkgs:-${base}/pkg}"
52 patch="${patch:-${base}/patch}"
53 root="${root:-${root}}"
54 logfile="${logfile:-${stage}/gentree.log}"
57 stage="$(realpath "${stage}")"
67 # Make sure the provided file(s) have only one link!
70 if [ -f "${1}" -a "$(stat -f '%l' "${1}")" -gt 1 ]
72 cp -p "${1}" "${1}.tmp" && mv "${1}.tmp" "${1}" || err "breaklink failed"
81 if [ -d "${stage}" -a \( -d "${sroot}" -o -d "${sboot}" -o -d "${sconf}" \) ]
83 yn n " ${a_yellow}*${a_normal} Workspace already exists. Delete? [y/N]" || err Aborting
84 chk rm -Rf "${sroot}" "${sboot}" "${sconf}"
86 chk mkdir -p "${sroot}"
87 # Eliminate schg, because it interferes with hardlinks
88 chk chflags -R noschg "${root}/lib"
89 chk chflags -R noschg "${root}/libexec"
90 chk chflags -R noschg "${root}/sbin"
91 chk chflags -R noschg "${root}/usr"
92 ( cd "${root}" && find . | cpio -p --link "${sroot}" ) || chk
96 log Create an emergency user admin/admin
97 # delink passwd to ensure it doesn't get patched in-place
98 chk onelink "${sroot}/etc/passwd" "${sroot}/etc/master.passwd"
99 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
103 if [ -d "${pkgs}" -a "$(ls -1 "${pkgs}" | wc -l)" -gt 0 ]
105 count="$(ls -1 "${pkgs}" | wc -l)"
106 log Install ${count} packages from "${pkgs}"
107 chk mkdir -p "${sroot}/pkg"
108 ( cd "${pkgs}" && find . | cpio -p --link "${sroot}/pkg" ) || chk
109 chk chroot "${sroot}" /bin/sh -c 'cd /pkg; exec pkg_add -F *'
110 chk rm -Rf "${sroot}/pkg"
115 log Apply patches from "${patch}"
116 for file in "${patch}"/*
118 note "... $(basename "${file}")"
119 echo "... $(basename "${file}")" >&2
120 ( cd "${sroot}"; patch < "${file}" ) || chk
126 chk mv "${sroot}/boot/boot" "${sroot}/boot/boot.blk"
127 chk ln -sf . "${sroot}/boot/boot"
132 ( cd "${sroot}/tmp" && find . | cpio -p --link ../var/tmp ) || chk
133 chk rm -Rf "${sroot}/tmp"
134 chk ln -sf var/tmp "${sroot}/tmp"
139 chk mkdir -p "${sroot}/etc/local"
140 chk mkdir -p "${sroot}/usr/local/etc" # Silence warnings
141 ( cd "${sroot}/usr/local/etc" && find . | cpio -p --link ../../../etc/local ) || chk
142 chk rm -Rf "${sroot}/usr/local/etc"
143 chk ln -sf ../../etc/local "${sroot}/usr/local/etc"
148 # Nothing necessary here
152 log Create boot imgsrc
153 chk mv "${sroot}/boot" "${stage}"
154 chk mkdir -p "${sroot}/boot"
155 chk rm -f "${sboot}/kernel"/*.symbols
156 # Gzipped kernel is okay
157 gzip -9 "${sboot}/kernel/kernel"
158 # Compress all files in /boot/kernel
159 # Loader cannot handle gzipped modules. Decompress the required modules
160 # kldload cannot handle gzipped modules either
161 #find "${sboot}/kernel" -type f | xargs gzip -9f || chk
162 #cat "${sboot}/loader.conf" | grep '_load=' | sed -e 's/^\(.*\)_load=.*$/\1/' | while read mod
164 # [ -f "${sboot}/kernel/${mod}.ko.gz" ] && gunzip "${sboot}/kernel/${mod}.ko.gz" || chk
167 # Instead: put all modules in the root image, except those needed to boot the kernel
168 chk mkdir -p "${sroot}/boot/boot"
169 chk mkdir -p "${sroot}/boot/kernel"
171 # Link all modules into the root fs
172 ( cd "${sboot}/kernel"; find . -name '*.ko' -o -name 'linker.hints' | cpio -p --link "${sroot}/boot/kernel" ) || chk
174 # Remove all modules from the root fs that are preloaded by the loader
175 cat "${sboot}/loader.conf" | grep '_load=' | sed -e 's#^\(.*\)_load=.*$#'"${sroot}/boot/kernel/"'\1.ko#' | xargs rm -f
177 # Remove all modules from the boot fs that are present in the root fs
178 ( cd "${sroot}/boot/kernel"; ls -1 ) | sed -e 's#^#'"${sboot}/kernel/"'#' | xargs rm -f
180 # Link the preloaded modules from the boot fs to the root fs, to provide a homogenous view
181 ( cd "${sboot}/kernel"; ls -1 ) | while read mod
183 ln -sf "../boot/kernel/${mod}" "${sroot}/boot/kernel/${mod}"
188 log Create conf imgsrc
189 chk mkdir -p "${sroot}/conf"
190 echo "ufs:/dev/ufs/conf" > "${sroot}/conf/diskless_remount" || chk
191 chk mkdir -p "${sconf}/base/etc"
192 chk mkdir -p "${sconf}/base/var"
193 chk mkdir -p "${sconf}/default/etc"
194 chk mkdir -p "${sconf}/default/var"
198 log Create etc imgsrc
199 chk touch "${sroot}/etc/diskless"
200 chk mv "${sroot}/etc" "${stage}"
201 chk mkdir -p "${sroot}/etc"
202 chk cp -p "${stage}/etc/rc" "${stage}/etc/rc.subr" "${stage}/etc/rc.initdiskless" "${stage}/etc/login.conf.db" "${stage}/etc/diskless" "${sroot}/etc"
203 echo "10240" > "${sconf}/base/etc/md_size" || chk
204 ( cd "${stage}"; find etc | cpio -o ) | gzip -9 > "${sconf}/base/etc.cpio.gz" || chk
205 chk rm -Rf "${stage}/etc"
209 log Create var imgsrc
210 chk mv "${sroot}/var" "${stage}"
211 chk mkdir -p "${sroot}/var"
212 echo "131072" > "${sconf}/base/var/md_size" || chk
213 ( cd "${stage}"; find var | cpio -o ) | gzip -9 > "${sconf}/base/var.cpio.gz" || chk
214 chk rm -Rf "${stage}/var"
218 log Patch in custom config
219 ( cd "${base}/conf" && find . | cpio -p --link "${sconf}/default" ) || chk
220 # Make sure files in default are newer than the tagfile, so they will be caught by saveconfig
221 find "${sconf}/default" -type f -print0 | xargs -0 touch
224 for step in ${sequence}
226 echo "${targets}" | grep -q "${step}" || err Unrecognized target "${step}"