xref: /haiku/build/scripts/build_haiku_image (revision 225b6382637a7346d5378ee45a6581b4e2616055)
1#!/bin/sh
2set -o errexit
3
4# The first argument is the shell script that initializes the variables:
5# sourceDir
6# outputDir
7# tmpDir
8# addBuildCompatibilityLibDir
9# systemPackages, commonPackages - lists of the hpkg packages copied/updated
10#   (in "system" and "common" respectively)
11# repositories - all repository files
12# downloadDir
13# The following are only for image types:
14# installDir
15# isImage
16# imagePath
17# imageSize
18# imageLabel
19# resolvePackageDependencies
20# updateOnly
21# dontClearImage
22# isVMwareImage
23#
24# addattr
25# copyattr
26# getPackageDependencies
27# package
28# rc
29# rmAttrs
30# unzip
31# The following are only for image types:
32# bfsShell
33# fsShellCommand
34# makebootable
35# resattr
36# vmdkimage
37# The following is only for cd types:
38# generate_attribute_stores
39# isCD
40#
41if [ $# -gt 0 ]; then
42	. $1
43	shift
44fi
45
46if [ ! $isCD ]; then
47	# If the haiku image path is a symlink resolve it now (makebootable needs the
48	# path of the actual device path under Linux).
49	normalizedImagePath=''
50	if readlink -f "$imagePath" > /dev/null 2>&1 ; then
51		normalizedImagePath=$(readlink -f "$imagePath")
52	elif realpath "$imagePath" > /dev/null 2>&1 ; then
53		normalizedImagePath=$(realpath "$imagePath")
54	elif greadlink -f "$imagePath" > /dev/null 2>&1 ; then
55		normalizedImagePath=$(greadlink -f "$imagePath")
56	fi
57	if [ -n "$normalizedImagePath" ]; then
58		imagePath="$normalizedImagePath"
59	fi
60fi
61
62# this adds the build library dir to LD_LIBRARY_PATH
63eval "$addBuildCompatibilityLibDir"
64
65# map the shell commands
66if [ $isCD ]; then
67	outputDir=$tmpDir/cdsource
68
69	sPrefix=
70	tPrefix="$outputDir/"
71	cd=cd
72	scd=:
73	cp="$copyattr -d"
74	copyAttrs="$copyattr"
75	ln=ln
76	mkdir=mkdir
77	rm=rm
78elif [ $isImage ]; then
79	# If FIFOs are used for the communication with the FS shell, prepare them.
80	if $fsShellCommand --uses-fifos; then
81		fifoBasePath=/tmp/build_haiku_image-$$-fifo
82		toFSShellFifo=${fifoBasePath}-to-shell
83		fromFSShellFifo=${fifoBasePath}-from-shell
84
85		rm -f $toFSShellFifo $fromFSShellFifo
86		mkfifo $toFSShellFifo $fromFSShellFifo
87
88		# Open the FIFOs such that they are ready for the fsShellCommand. This
89		# also makes sure that they remain open until this script exits. When we
90		# exit while the FS shell is still running and waiting for commands,
91		# closing of our file descriptors will break the FIFOs and the FS shell
92		# will exit, too.
93		# Note: A bit of trickery is needed since opening one end blocks until
94		# someone opens the other end.
95		sleep 3<$fromFSShellFifo 1 &
96		exec 6>$fromFSShellFifo 3<$fromFSShellFifo
97		sleep 5<$toFSShellFifo 1 &
98		exec 4>$toFSShellFifo 5<$toFSShellFifo
99
100		# Remove the FIFO files again -- we have the open FDs, so they can
101		# still be used and this makes sure they won't hang around any further.
102		rm -f $toFSShellFifo $fromFSShellFifo
103
104		# Remap the fsShellCommand and bfsShell such that they don't inherit the
105		# wrong FDs. For both fsShellCommand and bfsShell FD 3 is the input from
106		# the respectively other program, FD 4 is the output to it.
107		actualFSShellCommand="$fsShellCommand"
108		actualBFSShell="$bfsShell"
109
110		fsShellCommandWrapper()
111		{
112			$actualFSShellCommand 5>&- 6>&- "$@"
113		}
114
115		bfsShellWrapper()
116		{
117			$actualBFSShell 3>&5 4<&6 "$@"
118		}
119
120		fsShellCommand=fsShellCommandWrapper
121		bfsShell=bfsShellWrapper
122	fi
123
124	# set up the other commands
125	sPrefix=:
126	tPrefix=/myfs/
127	cd="$fsShellCommand cd"
128	scd="$fsShellCommand cd"
129	cp="$fsShellCommand cp -f"
130	copyAttrs="$fsShellCommand cp -a"
131	ln="$fsShellCommand ln"
132	mkdir="$fsShellCommand mkdir"
133	rm="$fsShellCommand rm"
134	mkindex="$fsShellCommand mkindex"
135else
136	sPrefix=
137	# TODO: This should come from the environment.
138	tPrefix="$installDir/"
139	cd=cd
140	scd=:
141	cp="$copyattr -d"
142	copyAttrs="$copyattr"
143	ln=ln
144	mkdir=mkdir
145	rm=rm
146	mkindex=mkindex
147fi
148
149
150extractFile()
151{
152	# extractFile <archive> <directory> <extractedSubDir>
153	archiveFile=$1
154	targetExtractedDir=$2
155	extractedSubDir=$3
156
157	extractDir=$tmpDir/extract
158	$rmAttrs -rf "$extractDir"
159	mkdir -p "$extractDir"
160
161	case "$archiveFile" in
162		*.zip)
163			echo "Extracting $archiveFile ..."
164			$unzip -q -d "$extractDir" "$archiveFile"
165			;;
166		*.tgz|*.tar.gz)
167			echo "Extracting $archiveFile ..."
168			tar -C "$extractDir" -xf "$archiveFile"
169			;;
170		*.hpkg)
171			echo "Extracting $archiveFile ..."
172			if [ -n "$extractedSubDir" ]; then
173				$package extract -C "$extractDir" "$archiveFile" \
174					"$extractedSubDir"
175			else
176				$package extract -C "$extractDir" "$archiveFile"
177			fi
178			;;
179		*)
180			echo "Unhandled archive extension in build_haiku_image" \
181				"extractFile()"
182			exit 1
183			;;
184	esac
185
186	if [ -f $extractDir/.OptionalPackageDescription ]; then
187		cat $extractDir/.OptionalPackageDescription >> $copyrightsFile
188		echo >> $copyrightsFile
189		rm $extractDir/.OptionalPackageDescription
190	fi
191
192	$cp -r "${sPrefix}$extractDir/$extractedSubDir/." \
193		"${tPrefix}$targetExtractedDir"
194
195	$rmAttrs -rf "$extractDir"
196}
197
198
199downloadFile()
200{
201	url=$1
202	path=$2
203
204	if [ ! -f "$path" ]; then
205		wget -O "$path" "$url"
206	fi
207}
208
209
210mkdir -p $tmpDir
211copyrightsFile=$tmpDir/copyrights
212$rmAttrs -f $copyrightsFile
213
214if [ $isCD ]; then
215	# setup output dir
216	$rmAttrs -rf "$outputDir"
217	mkdir -p "$outputDir"
218fi
219
220# create the image and mount it
221if [ $isImage ]; then
222	echo
223
224	imageOffsetFlags=
225	if [ $isVMwareImage ]; then
226		imageOffsetFlags="--start-offset 65536"
227	fi
228
229	if [ ! $updateOnly ]; then
230		echo "Creating image ..."
231
232		imageFlags="-i${imageSize}M"
233		if [ ! "$dontClearImage" ]; then
234			imageFlags="$imageFlags -c"
235		fi
236
237		if [ $isVMwareImage ]; then
238			$vmdkimage -h 64k $imageFlags "$imagePath"
239		else
240			$createImage $imageFlags "$imagePath"
241		fi
242
243		$bfsShell --initialize $imageOffsetFlags "$imagePath" \
244			"$imageLabel" "block_size 2048"
245		$makebootable $imageOffsetFlags "$imagePath"
246	fi
247
248	$bfsShell -n $imageOffsetFlags "$imagePath" > /dev/null &
249	sleep 1
250
251	# Close FDs 5 and 6. Those represent the pipe ends that are used by the
252	# FS shell. Closing them in the shell process makes sure an unexpected death
253	# of the FS shell causes writing to/reading from the other ends to fail
254	# immediately.
255	exec 5>&- 6>&-
256
257	# bail out, if mounting fails
258	$cd .
259fi
260
261echo "Populating image ..."
262while [ $# -gt 0 ]; do
263	. $1
264	shift
265done
266
267
268# resolve package dependencies
269if [ -n "$resolvePackageDependencies" ]; then
270	echo "Resolving package dependencies ..."
271
272	# additional packages for system
273	packageUrls=`$getPackageDependencies $repositories -- $systemPackages`
274	for packageUrl in $packageUrls; do
275		packageFileName=`basename $packageUrl`
276		packageFilePath="$downloadDir/$packageFileName"
277		downloadFile $packageUrl "$packageFilePath"
278		$cp "${sPrefix}$packageFilePath" "${tPrefix}system/packages"
279		systemPackages="$systemPackages $packageFilePath"
280	done
281
282	# additional packages for common
283	packageUrls=`$getPackageDependencies $repositories -- $systemPackages \
284		$commonPackages`
285	for packageUrl in $packageUrls; do
286		packageFileName=`basename $packageUrl`
287		packageFilePath="$downloadDir/$packageFileName"
288		downloadFile $packageUrl "$packageFilePath"
289		$cp "${sPrefix}$packageFilePath" "${tPrefix}common/packages"
290		commonPackages="$commonPackages $packageFilePath"
291	done
292fi
293
294
295# install default settings for packages
296for packageFile in $systemPackages $commonPackages; do
297	if $package list -p $packageFile | egrep '^settings/' > /dev/null; then
298		extractFile $packageFile common/settings settings
299	fi
300done
301
302
303# add the concatenated copyrights as an attribute to AboutSystem
304# TODO: That might not be necessary, when all third-party software everything
305# is packaged. Though we might not package everything.
306
307# if [ ! $updateOnly ]; then
308# 	if [ -f $copyrightsFile ]; then
309# 		copyrightAttrs=$tmpDir/copyrightAttrs
310# 		$rmAttrs -f $copyrightAttrs
311# 		touch $copyrightAttrs
312# 		$addattr -f $copyrightsFile COPYRIGHTS $copyrightAttrs
313# 		$copyAttrs ${sPrefix}$copyrightAttrs ${tPrefix}system/apps/AboutSystem
314# 	fi
315# fi
316
317if [ $isCD ]; then
318	# generate the attribute stores
319	echo "Generating attribute stores ..."
320	$generate_attribute_stores "$tPrefix"
321
322	echo "Copying boot image ..."
323	$cp "$cdBootFloppy" "$outputDir"
324
325	if [ $(which mkisofs) ]; then
326		# build the iso image using mkisofs
327		echo "Building CD image (mkisofs)..."
328		mkisofs -uid 0 -gid 0 -b `basename $cdBootFloppy` -R -V "$cdLabel" -o "$cdImagePath" "$tPrefix"
329	elif [ $(which genisoimage) ]; then
330		# build the iso image using genisoimage
331		echo "Building CD image (genisoimage)..."
332		echo "WARNING: genisoimage fallback has known problems with long filenames!"
333		echo "         Please install mkisofs before making production releases!"
334		genisoimage -r -iso-level 4 -b `basename $cdBootFloppy` -V "$cdLabel" -o "$cdImagePath" "$tPrefix"
335	else
336		echo "you need mkisofs (preferred) or genisoimage to create a CD image."
337		exit 1
338	fi
339
340	# cleanup output dir
341	$rmAttrs -rf "$outputDir"
342fi
343
344# unmount
345if [ $isImage ]; then
346	echo "Unmounting ..."
347	$fsShellCommand sync
348	$fsShellCommand quit
349fi
350