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