1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
|
#!/bin/ksh93
# Build script for hammerhead-userland
# Packages commands, libraries, headers, and system configuration from proto area
#
# Requires PROTO_AREA to be set to the hammerhead proto path, e.g.:
# export PROTO_AREA=/usr/src/hammerhead-build/root_amd64
#
# Optional: ROOTFS_DIR for rootfs overlay (config files, ownership manifest)
# export ROOTFS_DIR=/usr/src/hammerhead/rootfs
set -e
PROTO_AREA="${PROTO_AREA:?PROTO_AREA must be set to hammerhead proto path}"
# Validate required directories
for dir in bin sbin lib usr etc var; do
if [ ! -d "$PROTO_AREA/$dir" ]; then
printf "ERROR: %s/%s does not exist\n" "$PROTO_AREA" "$dir"
printf "Has the hammerhead build completed successfully?\n"
exit 1
fi
done
# Validate critical files
for f in lib/libc.so.1 lib/ld.so.1 sbin/init; do
if [ ! -f "$PROTO_AREA/$f" ]; then
printf "ERROR: %s not found in proto area\n" "$f"
exit 1
fi
done
# --- /bin (real directory with boot-essential commands) ---
printf "Packaging bin...\n"
mkdir -p "$PKGDIR/bin"
(cd "$PROTO_AREA/bin" && find . | cpio -pdm "$PKGDIR/bin" 2>/dev/null)
# --- /sbin (essential system commands) ---
printf "Packaging sbin...\n"
mkdir -p "$PKGDIR/sbin"
(cd "$PROTO_AREA/sbin" && find . | cpio -pdm "$PKGDIR/sbin" 2>/dev/null)
# --- /lib (essential libraries + SMF infrastructure) ---
printf "Packaging lib...\n"
mkdir -p "$PKGDIR/lib"
(cd "$PROTO_AREA/lib" && find . | cpio -pdm "$PKGDIR/lib" 2>/dev/null)
# --- /usr (commands, libraries, headers, man pages, data) ---
printf "Packaging usr...\n"
mkdir -p "$PKGDIR/usr"
(cd "$PROTO_AREA/usr" && find . | cpio -pdm "$PKGDIR/usr" 2>/dev/null)
# --- /etc (system configuration) ---
# Exclude system-specific runtime files that are populated at install time
# or by the kernel. These must NOT be overwritten on upgrade.
printf "Packaging etc...\n"
mkdir -p "$PKGDIR/etc"
(cd "$PROTO_AREA/etc" && find . \
! -name name_to_major \
! -name path_to_inst \
! -name driver_aliases \
! -name driver_classes \
! -name minor_perm \
! -name device.tab \
! -name devlink.tab \
! -name dacf.conf \
! -name iu.ap \
! -name mnttab \
! -name utmpx \
! -name wtmpx \
| cpio -pdm "$PKGDIR/etc" 2>/dev/null)
# --- /var (state directories — mostly empty structure) ---
printf "Packaging var...\n"
mkdir -p "$PKGDIR/var"
(cd "$PROTO_AREA/var" && find . | cpio -pdm "$PKGDIR/var" 2>/dev/null)
# --- Apply rootfs overlay ---
# These are Hammerhead-specific config files that override proto defaults
if [ -n "$ROOTFS_DIR" ] && [ -d "$ROOTFS_DIR" ]; then
printf "Applying rootfs overlay...\n"
for overlay_dir in etc lib root; do
if [ -d "$ROOTFS_DIR/$overlay_dir" ]; then
(cd "$ROOTFS_DIR/$overlay_dir" && find . | cpio -pdm "$PKGDIR/$overlay_dir" 2>/dev/null)
fi
done
# Copy .zshrc for root
if [ -f "$ROOTFS_DIR/root/.zshrc" ]; then
mkdir -p "$PKGDIR/root"
cp "$ROOTFS_DIR/root/.zshrc" "$PKGDIR/root/.zshrc"
fi
fi
# --- Remove items that should NOT be packaged ---
# Build tools
rm -rf "$PKGDIR/opt/onbld" 2>/dev/null || true
# Test suites (large, not needed on target)
rm -rf "$PKGDIR/opt/"*-tests 2>/dev/null || true
rm -rf "$PKGDIR/opt/test-runner" 2>/dev/null || true
# Build system remnants
rm -rf "$PKGDIR/usr/src" 2>/dev/null || true
# --- Apply ownership from manifest ---
if [ -n "$ROOTFS_DIR" ] && [ -f "$ROOTFS_DIR/ownership.manifest" ]; then
printf "Applying ownership manifest...\n"
# Phase 1: bulk defaults
chown -R root:sys "$PKGDIR/"
chown -R root:bin "$PKGDIR/bin" "$PKGDIR/sbin" \
"$PKGDIR/usr/bin" "$PKGDIR/usr/sbin" \
"$PKGDIR/usr/lib" "$PKGDIR/lib" 2>/dev/null || true
# Phase 2: per-file overrides from manifest
while IFS=' ' read -r path mode owner group; do
# Skip comments and blank lines
[[ -z "$path" || "$path" = \#* ]] && continue
target="$PKGDIR$path"
if [ -e "$target" ] || [ -L "$target" ]; then
chmod "$mode" "$target" 2>/dev/null || true
chown "$owner:$group" "$target" 2>/dev/null || true
fi
done < "$ROOTFS_DIR/ownership.manifest"
else
# No manifest — apply bulk defaults only
printf "WARNING: No ownership manifest found, applying bulk defaults\n"
chown -R root:sys "$PKGDIR/"
chown -R root:bin "$PKGDIR/bin" "$PKGDIR/sbin" \
"$PKGDIR/usr/bin" "$PKGDIR/usr/sbin" \
"$PKGDIR/usr/lib" "$PKGDIR/lib" 2>/dev/null || true
fi
# --- Create .CONFIG (config-protected files) ---
# These files will not be overwritten on upgrade if user has modified them.
# New versions are installed as <file>.pkg for manual merging.
cat > "$PKGDIR/.CONFIG" << 'EOF'
/etc/system
/etc/vfstab
/etc/passwd
/etc/shadow
/etc/group
/etc/hosts
/etc/inet/hosts
/etc/nsswitch.conf
/etc/resolv.conf
/etc/nodename
/etc/pam.conf
/etc/profile
/etc/zshenv
/etc/zshrc
/etc/zprofile
/etc/default/init
/etc/default/login
/etc/default/useradd
/etc/security/policy.conf
/etc/security/crypt.conf
/etc/crypto/pkcs11.conf
/etc/ssh/sshd_config
/etc/syslog.conf
/etc/sudoers.d/zygaena
/etc/svc/profile/site.xml
/etc/coral/coral.conf
EOF
# --- Post-install script ---
mkdir -p "$PKGDIR/.SCRIPTS"
cat > "$PKGDIR/.SCRIPTS/post-install.sh" << 'SCRIPT'
#!/bin/ksh93
# Refresh SMF repository if svc.configd is running (live system upgrade)
if [ -f /lib/svc/bin/svc.configd ]; then
if pgrep -x svc.configd >/dev/null 2>&1; then
printf "Refreshing SMF manifests...\n"
svccfg import /lib/svc/manifest 2>/dev/null || true
fi
fi
SCRIPT
chmod 755 "$PKGDIR/.SCRIPTS/post-install.sh"
# --- Summary ---
CMDS=0
for d in "$PKGDIR/bin" "$PKGDIR/sbin" "$PKGDIR/usr/bin" "$PKGDIR/usr/sbin"; do
if [ -d "$d" ]; then
n=$(find "$d" -type f | wc -l)
CMDS=$((CMDS + n))
fi
done
LIBS=$(find "$PKGDIR/lib" "$PKGDIR/usr/lib" -name "*.so.*" -type f 2>/dev/null | wc -l)
SIZE=$(du -sh "$PKGDIR" | cut -f1)
printf "Packaged %d commands, %d libraries (%s total)\n" "$CMDS" "$LIBS" "$SIZE"
# hammerhead-userland - Commands, libraries, headers, and system configuration
# https://git.sharkos.one/zygaena/hammerhead
[package]
name = "hammerhead-userland"
version = "0.1.0"
release = 1
description = "Hammerhead userland: commands, libraries, headers, and system configuration"
url = "https://git.sharkos.one/zygaena/hammerhead"
license = "CDDL-1.0"
maintainer = "Chris Tusa <chris.tusa@leafscale.com>"
arch = "x86_64"
conflicts = ["illumos-core", "illumos-libs", "illumos-utils", "illumos-config", "illumos-smf"]
[dependencies]
runtime = ["hammerhead-kernel"]
build = []
[build]
parallel = false
|