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