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