# # Function library for buildpkg framework # It adds support for creating Irix packages in 'inst' format # # Define tool programs # *only* platform specific packaging tools should be listed here # generic tools go in buildpkg.functions GENDIST="/usr/sbin/gendist" GZIP=/usr/people/tgc/bin/gzip BZIP2=/usr/local/bin/bzip2 # This is the hostname command we'll want on Irix HOSTNAME=/usr/bsd/hostname # Configuration vars imageconf=$buildpkgbase/scripts/image.conf subsysconf=$buildpkgbase/scripts/subsys.conf idbfile=$metadir/$topdir.idb specfile=$metadir/$topdir.spec depends=$metadir/depends opsfile=$metadir/ops hidefile=$metadir/hide # Preformat manpages since Irix is not likely to have nroff available catman=1 # strip? dostrip=1 # Setup default args for strip. They match /usr/bin/strip in Irix 6.2 # Change these if you're using strip from GNU Binutils (recommended) strip_elf_args="" # GNU default is -g strip_shared_args="-f" # GNU default is --strip-unneeded strip_static_args="" # GNU default is -g # Other usedepend=1 # Don't use depend file even if it's available usescripts=1 # Don't add ops even if they're available ignore_unpackaged_files=0 # default to check for unpackaged files in the stage area # ver_width controls the width of the pkgversion numbers created # do *not* change this blindly ver_width=8 # Comment these declarations to get it to run with ksh declare -a pc # Array of product categories (image.subsys) declare -a pd # Array of matching descriptions declare -a ps # Array of subsystem properties - default or nodefault declare -a pctop # Array of toplevel product categories (image) declare -a pdtop # Array of matching descriptions declare -a reqs # Array of subsystems with prereqs declare -a reqp # Array of prereqs (should match up with reqs) declare -a hide # Files that should be "hidden" with nohist declare -a opfiles # Files that should have an ops associated declare -a opscript # Ops to associate with opfiles #override defaults pkgprefix=tgc_ pkgname=$pkgprefix$topdir os=irix`$UNAME -r` cpu=mips3 configure_args='--prefix=$prefix' META_CLEAN="$topdir.spec $topdir.idb files.tmp" # Host specific configuration [ -r $buildpkgbase/scripts/config.$($HOSTNAME -s).irix ] && . $buildpkgbase/scripts/config.$($HOSTNAME -s).irix distfile='$topdir-$version-$pkgver.tgc-$os-$cpu-$pkgdirdesig.tardist' ##################################################### # Internal helper functions ##################################################### indent4=" " indent8=" " indent12=" " indent16=" " indent24=" " # fix_ver(): "normalize" a version-pkgver pair # params: $1=version # Removes any '.' and '-' characters from a version string # It also extends the width to $ver_width by padding with zeroes on the # right side fix_ver() { local ver=`echo $1 | $SED -e 's/\.//g' -e 's/-//g' -e 's/[a-zA-Z]//g'` let "numpad = $ver_width - ${#ver}" ver="$($PRINTF "%s%.0${numpad}u" $ver 0)" echo $ver } # spec_header() # param: $1=product name $2=description spec_header() { echo "product $1" echo "$indent4 id \"$2\"" } spec_footer() { echo "endproduct" } # spec_img_header() # param: $1=image name $2=image description $3=version spec_img_header() { local nver=$(fix_ver $3) echo "$indent4 image $1" echo "$indent8 id \"$2\"" echo "$indent8 version $nver" echo "$indent8 order 9999" } # spec_img_footer() spec_img_footer() { echo "$indent4 endimage" } # spec_subsys_header() # param: $1=image $2=subsys $3=description $4=subsys property spec_subsys_header() { echo "$indent8 subsys $2 $4" echo "$indent12 id \"$3\"" echo "$indent12 replaces self" echo "$indent12 exp $pkgname.$1.$2" } # spec_subsys_req_header() # param: none spec_subsys_req_header() { echo "$indent16 prereq (" } # spec_subsys_req() # param: $1=prereq spec_subsys_req() { echo "$indent24 $1" } # spec_subsys_req_footer() # param: none spec_subsys_req_footer() { echo "$indent24"")" } # spec_subsys_footer() # param: none spec_subsys_footer() { echo "$indent8 endsubsys" } # check_ops(): Is there an opscript associated with $1 # param: $1=file to check check_ops() { local file="$1" local return="" if [ "$usescripts" -eq 0 ]; then echo $return fi #echo "file is $file" >> /tmp/debug for ((i=0; $i < ${#opfiles[@]}; i++)) do #echo "opfiles $i is ${opfiles[$i]}" >> /tmp/debug if [ "${opfiles[$i]}" == "$file" ]; then return="${opscript[$i]}" fi done echo $return } # fix_fname(): Sanitize filename # param: $1=filename to fix # The purpose is to "fix" filenames that gendist won't like # ie. names with space are a no-no. fix_fname() { local name="$1" local return # Replace ' ' with '_' return=$(echo $name|$SED -e 's/ /_/g') echo $return } # add_files() # Create IDB entries for all files in a specfic product category # Takes the following parameters # $1 = dirname to descend into # $2 = product_category to assign files # $3 = permissions to set on the files we find # $4 = user # $5 = group # $6 = special attribute add_files() { local fspec=$(_upls $1) local prodcat=$2 local defperm=$3 local owner=$4 local group=$5 local specattr=$6 local FILES=$($FIND $fspec -type f -print|$TEE -a $metadir/files.tmp) OIFS=$IFS # We play IFS tricks so we can handle filenames with embedded spaces IFS=" " for i in $FILES do IFS=$OIFS if [ "$defperm" == "-" ]; then permlist=`$LS -l "$i" | $CUT -d " " -f 1` perm=$(compute_octal $permlist) else perm=$defperm fi doop=$(check_ops "$i") fname=$(fix_fname "$i") if [ ! -z "$specattr" ]; then echo "f $perm $owner $group ${topinstalldir:1}/$fname $i ${pkgname}.${prodcat} $specattr" >>$idbfile else if [ ! -z "$doop" ]; then echo "f $perm $owner $group ${topinstalldir:1}/$fname $i ${pkgname}.${prodcat} $doop" >>$idbfile else echo "f $perm $owner $group ${topinstalldir:1}/$fname $i ${pkgname}.${prodcat}" >>$idbfile fi fi done IFS=$OIFS # Handle symlinks local FILES=$($FIND $fspec -type l -print|$TEE -a $metadir/files.tmp) OIFS=$IFS IFS=" " for i in $FILES do IFS=$OIFS if [ "$defperm" == "-" ]; then permlist=`$LS -l "$i" | $CUT -d " " -f 1` perm=$(compute_octal $permlist) else perm=$defperm fi local temp=`$LS -l "$i"|$CUT -d '>' -f 2` local symval=${temp# } fname=$(fix_fname "$i") echo "l $perm $owner $group ${topinstalldir:1}/$fname $i ${pkgname}.${prodcat} symval($symval)" >>$idbfile done IFS=$OIFS } # fetch_imageconf(): Fetch a list of toplevel image entries with descriptions # params: none # Discard the ones that we don't have any subsystems for fetch_imageconf() { local pctopidx=0 local numloops=${#pc[@]} local i=0 while read image desc do for ((i=0; i < $numloops; i++)) do temp="${pc[$i]%%.*}" if [ "$image" == "$temp" ]; then pctop[$pctopidx]=$image pdtop[$pctopidx]=$desc let "pctopidx = $pctopidx + 1" break # We found a match no need to loop further fi done done < $imageconf } # fetch_subsysdesc(): Fetch a list of subsystem descriptions # params: none fetch_subsysdesc() { local i=0 local numloops=${#pc[@]} local ss local sp local desc while read ss sp desc do for ((i=0; i < $numloops; i++)) # Find subsystem... do if [ "${pc[$i]}" = "$ss" ]; then pd[$i]="$desc" if [ "$sp" == "nodefault" ]; then ps[$i]="" else ps[$i]=$sp fi break # Found it, skip to the next line fi done done < $subsysconf } # fetch_depends(): Fetch a list of subsystems and their prereqs # params: none # fetch_depends() { if [ -r $depends ]; then reqidx=0 while read ss req do reqs[$reqidx]=$ss if [ "$req" == "auto" ]; then # auto create depend on sw.base nver=$(fix_ver "$version-$pkgver") req="$pkgname.sw.base $nver $nver" fi reqp[$reqidx]=$req let "reqidx = $reqidx + 1" done < $depends fi } # fetch_ops(): Fetch ops # params: none # Populates the firstop and lastop variables # and the opfiles and opscript arrays fetch_ops() { if [ -r $opsfile ]; then opsidx=0 while read optype op do case $optype in 'firstop') firstop="$op" ;; 'lastop') lastop="$op" ;; esac opfiles[$opsidx]=$optype opscript[$opsidx]=$op let "opsidx = $opsidx + 1" done < $opsfile fi } # do_strip_bin(): Strip binaries # params: none do_strip_bin() { echo "Stripping ELF binaries..." for f in `$FIND . -type f \( -perm -0100 -o -perm -0010 -o -perm -0001 \) -exec $FILE {} \; | \ $GREP -v ' dynamic lib ' | \ $SED -n -e 's/^\(.*\):[ ]*ELF.*\(not stripped\).*/\1/p'`; do $STRIP $strip_elf_args $f || : done } # do_strip_shared(): Strip shared libraries # params: none do_strip_shared() { echo "Stripping ELF shared objects..." # Strip ELF shared objects (see brp-strip-shared from RPM) # Please note we don't restrict our search to executable files because # our libraries are not (should not be, at least) +x. for f in `$FIND . -type f -a -exec $FILE {} \; | \ grep ' dynamic lib ' | \ $SED -n -e 's/^\(.*\):[ ]*ELF.*\(not stripped\).*/\1/p'`; do $STRIP $strip_shared_args $f done } # do_strip_static(): Strip static archives # params: none do_strip_static() { echo "Stripping static archives..." # Strip static libraries. (see brp-strip-static-archive from RPM) for f in `$FIND . -type f -a -exec $FILE {} \; | \ $GREP 'current ar archive' | \ $SED -n -e 's/^\(.*\):[ ]*current ar archive .*/\1/p'`; do $STRIP $strip_static_args $f done } ################################## # "external" functions ################################## # create_idb(): Create the .idb file # params: none # Create idb file and insert any firstop/lastops # Note that parse_def does most of the work. create_idb() { fetch_ops parse_def # hackish - FIXME perhaps? local pcpos=${#pc[@]} # First vacant position in the subsys list array $pc if [ -d src ]; then # We have a srcdir which means we have patches, so add them to the idb file add_files "src" opt.src - root sys "" pc[$pcpos]="opt.src" let "pcpos = pcpos + 1" fi if [ -d relnotes ]; then # We have releasenotes, add them to idb file add_files "relnotes" opt.relnotes - root sys "" pc[$pcpos]="opt.relnotes" let "pcpos = pcpos + 1" fi if [ -d dist ]; then # We have spec & idb files add_files "dist" opt.dist - root sys "" pc[$pcpos]="opt.dist" fi # Add entries for the spec & idb files (opt.dist), they will be installed later, after they've actually been created echo "f 644 root sys ${topinstalldir:1}/dist/$topdir-$version-$pkgver/$topdir.idb dist/$topdir-$version-$pkgver/$topdir.idb ${pkgname}.opt.dist" >>$idbfile echo "f 644 root sys ${topinstalldir:1}/dist/$topdir-$version-$pkgver/$topdir.spec dist/$topdir-$version-$pkgver/$topdir.spec ${pkgname}.opt.dist" >>$idbfile echo "dist/$topdir-$version-$pkgver/$topdir.idb" >> $metadir/files.tmp echo "dist/$topdir-$version-$pkgver/$topdir.spec" >> $metadir/files.tmp $SORT +4u -6 < $idbfile > $metadir/idbtemp lines=$(wc -l < $metadir/idbtemp) if [ ! -z $firstop ]; then echo "$(head -1 $metadir/idbtemp) $firstop" > $metadir/idbtemp2 tail +2 $metadir/idbtemp >> $metadir/idbtemp2 else mv $metadir/idbtemp $metadir/idbtemp2 fi if [ ! -z $lastop ]; then let "lines=$lines - 1" echo "$(head -$lines $metadir/idbtemp2)" > $idbfile echo "$(tail -1 $metadir/idbtemp2) $lastop" >> $idbfile else mv $metadir/idbtemp2 $idbfile fi $RM -f $metadir/idbtemp $metadir/idbtemp2 } # create_spec(): Create the .spec file. # params: none # Uses name, pkgname & pkgver variables # Iterate through pctop and for each iteration find # all entries in pc belonging to that image # create_spec() { fetch_imageconf fetch_subsysdesc fetch_depends spec_header $pkgname "$name $version-$pkgver" > $specfile local pcsize=${#pc[@]} local pctopsize=${#pctop[@]} for ((i=0; i < $pctopsize; i++)) do local pcidx=0 spec_img_header ${pctop[$i]} "${pdtop[$i]}" $version-$pkgver >> $specfile while [ "$pcidx" -lt "$pcsize" ] do rv=`$EXPR match "${pc[$pcidx]}" ''${pctop[$i]}''` if [ ! "$rv" -eq 0 ]; then # We got a hit! spec_subsys_header ${pctop[$i]} `echo ${pc[$pcidx]}|$CUT -d . -f 2` "${pd[$pcidx]}" "${ps[$pcidx]}" >> $specfile reqsize=${#reqs[@]} declare -a reqidlist reqidlidx=0 for ((j=0; j < $reqsize; j++)) do if [ "${reqs[$j]}" == "${pc[$pcidx]}" ]; then reqidlist[$reqidlidx]=$j let "reqidlidx=$reqidlidx + 1" fi done reqidlsize=${#reqidlist[@]} if [ "$reqidlsize" -eq 1 ]; then id=${reqidlist[1]} spec_subsys_req_header >> $specfile spec_subsys_req "${reqp[$id]}" >> $specfile spec_subsys_req_footer >> $specfile fi if [ "$reqidlsize" -gt 1 ]; then spec_subsys_req_header >> $specfile for ((j=1; j < $reqidlsize; j++)) do id=${reqidlist[$j]} spec_subsys_req "${reqp[$id]}" >> $specfile done spec_subsys_req_footer >> $specfile fi spec_subsys_footer >> $specfile fi let "pcidx = $pcidx + 1" done spec_img_footer >> $specfile done spec_footer >> $specfile } # make_dist(): Create inst image # params: none # Run gendist to create the instimage make_dist() { if [ "$1" == "shortroot" ]; then error $E_ARG_OBSO make_dist fi if [ "$shortroot" -eq 1 ]; then sbase=$stagedir else sbase=$stagedir/$topinstalldir fi local disttmp=/tmp/disttmp$$ $MKDIR $disttmp local dfile=$(_upls $distfile) $GENDIST -rbase $topinstalldir -sbase $sbase -idb $idbfile -spec $specfile -dist $disttmp setdir $disttmp $VTAR -cf $distdir/$dfile $pkgname* setdir stage $RM -rf $disttmp echo "Done. Package was created as $dfile" } # parse_pkgdef(): Read in $metadir/pkgdef # params: none # This will parse the package descriptions in # pkgdef that tells us how many packages there # should be and what they include. parse_def() { local section=0 local foundfiles=0 local secname="" local secpos=0 local legalend=0 local index=0 local found=0 local i=0 local equalindex="" while read line do case ${line:0:1} in '#') ;; '[') if [ $section -eq 1 ]; then error $E_BAD_SECTION_BEGIN parse_def else section=1 secname="${line:1:((${#line}-2))}" legalend=0 fi ;; '') if [ $section -eq 0 ]; then error $E_BAD_SECTION_END parse_def else section=0 # Finished this section foundfiles=0 # legalend=1 # We encountered a syntacticly correct section end fi ;; *) equalindex=$(expr index "$line" "\=") if [ $equalindex -ne 0 ]; then case "${line:0:(($equalindex-1))}" in 'pkgname') pkgname="$(_upls ${line:$equalindex:${#line}})" ;; 'name') name="$(_upls ${line:$equalindex:${#line}})" ;; 'pkgver') pkgver="$(_upls ${line:$equalindex:${#line}})" ;; 'subsys') subsys="$(_upls ${line:$equalindex:${#line}})" found=0 for i in ${pc[@]} # If $subsys is already there then don't add it again do if [ "$i" = "$subsys" ]; then found=1 break # It's already there so skip out fi done if [ $found -eq 0 ]; then pc[$index]=$subsys let "index = $index + 1" fi ;; esac else # Perhaps we hit 'files'? if [ "${line:0:5}" == "files" ]; then triplet="${line:6:((${#line}-5-2))}" defaultperms=$(echo $triplet | $AWK -F, '{ print $1 }') defaultuid=$(echo $triplet | $AWK -F, '{ print $2 }') defaultgid=$(echo $triplet | $AWK -F, '{ print $3 }') foundfiles=1 else if [ $foundfiles -eq 1 ]; then # We already found the 'files' line so this must be the filelist if [ "${line:0:5}" == "hide " ]; then specattr="nohist" line=${line:5} fi if [ "${line:0:4}" == "dir " ]; then echo "Hit unsupported 'dir' directive" #add_dir $defaultperms $defaultuid $defaultgid "${line:4}" $secname # Add dir entry else add_files "$line" $subsys $defaultperms $defaultuid $defaultgid "$specattr" # Build idb file from filespec fi specattr="" # Reset special attribute fi fi fi ;; esac done < $metadir/pkgdef # If there is no blank line at the end of a pkgdef section (if there is only one section that is very # likely) then we end up here without having executed the 'section end' actions (case '' above) if [ $legalend -eq 0 ]; then if [ $section -eq 0 ]; then error $E_BAD_SECTION_END parse_def else section=0 # Finished this section foundfiles=0 # fi fi } # check_unpackaged(): Check if there are unpackaged files in the stage area # params: none check_unpackaged() { local upf local i $FIND . -type f -print|$SED -e 's/\.\///g' > $tmpdir/files.tmp $FIND . -type l -print|$SED -e 's/\.\///g' >> $tmpdir/files.tmp # $FIND . -type d -print|$SED -e 's/\.\///g'|$GREP -v '^\.' >> $tmpdir/files.tmp $SORT $metadir/files.tmp|$UNIQ > $tmpdir/f1 $SORT $tmpdir/files.tmp > $tmpdir/f2 if [ ! "$($CMP $tmpdir/f1 $tmpdir/f2)" == "" ]; then upf="$($CAT $tmpdir/f1 $tmpdir/f2 | $SORT | $UNIQ -u)" if [ ! -z "$upf" ]; then echo "There are unpackaged files in the stagedir:" for i in $upf do echo "${indent4}${i}" done fi $RM -f $tmpdir/f1 $tmpdir/f2 if [ "$ignore_unpackaged_files" -eq 0 ]; then error $E_UNPACKAGED_FILES check_unpackaged fi fi $RM -f $tmpdir/f1 $tmpdir/f2 } # auto_src(): Automatically place any patches into the correct location for packaging # params: none # Grabs any patches and shoves them into $prefix/src/$topdir-$version-$pkgver # for adding to the opt.src subsystem auto_src() { local numpatch=${#patch[@]} local pnum=0 if [ "$numpatch" -gt 0 ]; then local distsrcdir="src/$topdir-$version-$pkgver" $MKDIR -p $distsrcdir for ((pnum=0; pnum < $numpatch; pnum++)) do if [ ! -z ${patch[$pnum]} ]; then # They didn't give us an empty string if [ "${patch[$pnum]:0:1}" != "/" ]; then # We have a relative pathname # expand to absolute patch[$pnum]=$patchdir/${patch[$pnum]} fi # We are now sure that $patch[$pnum] contains file with absolute path echo "Processing patch[$pnum] - ${patch[$pnum]}" if [ -r ${patch[$pnum]} ]; then # file is readable $CP ${patch[$pnum]} $distsrcdir else error $E_BAD_FILE patch fi else echo "Patch $pnum has empty filename" fi done fi } # auto_rel(): Fix up and add releasenotes to stagedir # params: none # This will make some substitutions on a release note template # and then copy the result to $stagedir/$prefix/relnotes/$topdir-$version-$pkgver.txt auto_rel() { if [ -r $metadir/relnotes ]; then local relmetadir=relnotes/$topdir-$version-$pkgver local cf="$(_upls $configure_args)" local fullcf="./configure $cf" local compiler="gcc $(gcc --version 2>&1)" local pkgnam_temp=$(grep 'pkgname=' $metadir/pkgdef) local pkgnam=$(_upls ${pkgnam_temp#pkgname=*}) $MKDIR -p $relmetadir $SED -e "s;%%PKGNAME%%;${pkgnam};g" \ -e "s;%%SOURCE_AND_VER%%;${topdir}-${version};g" \ -e "s;%%CONFIGURE%%;${fullcf};g" \ -e "s;%%COMPILER%%;${compiler};g" \ $metadir/relnotes > "$relmetadir/${topdir}.txt" else echo "auto_rel: No release notes found!" fi } # auto_dist(): Add idb & spec files to stagedir # params: none # This will copy the newly created idb & spec files to # the stagedir under dist/$topdir-$version-$pkgver auto_dist() { local distmetadir=dist/$topdir-$version-$pkgver $MKDIR -p $distmetadir $CP $idbfile $distmetadir $CP $specfile $distmetadir } # generic_pack(): Build package using files from 'install' stage # params: $1 - indicating whether or not the root is complete as described below # We expect generic_install to have made $stagedir the "root" dir # in that all paths below will be complete (ie. /usr/local/bin and not # just bin) *unless* shortroot=1. generic_pack() { if [ "$1" == "shortroot" ]; then error $E_ARG_OBSO generic_pack fi clean meta # Compute manpage location local dir_prefix="${prefix#$topinstalldir*}" if [ "$shortroot" -eq 1 ]; then if [ $catman -eq 1 -a -d $stagedir/man ]; then setdir $stagedir/man fix_man fi setdir stage else if [ $catman -eq 1 -a -d ${stagedir}${topinstalldir}${dir_prefix}/man ]; then setdir ${stagedir}${topinstalldir}${dir_prefix}/man fix_man fi setdir $stagedir$topinstalldir fi auto_src # Add any patches auto_rel # Fix up and add releasenotes create_idb create_spec auto_dist # Add idb & specfiles to stagedir check_unpackaged make_dist }