From 6931631adc930bc1303e5d870c5c51e3727ee07a Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Sat, 11 Nov 2023 11:45:08 +0000 Subject: [PATCH] Dockerfile: add logic for optional install Universal interfaces on startup Define a docker-entrypoint.sh that checks for the environment variables INTERFACES. If INTERFACES is set to "universal" then we do the following: - If the universal/RIncludes directory is not empty, assume that the Universal interfaces are already installed. Call interfaces-and-libraries.sh to link the Universal interfaces instead of the default multiversal interfaces. - Otherwise check the INTERFACESFILE environment variable to locate a suitable Macbinary DiskCopy image of MPW-GM.img.bin containing the "Interfaces&Libraries" directory, which can be a path within the container image itself or an external URL. If the file is a URL then download it first, then decompress the file using ConvertDiskImage and then use the in-built hfsutils to extract the relevant files under /tmp/InterfacesAndLibraries. Finally call interfaces-and-libraries.sh to link the Universal interfaces instead of the default multiversal interfaces. Otherwise use the multiversal interfaces which are included by default. --- Dockerfile | 7 +++ docker-entrypoint.sh | 65 ++++++++++++++++++++ install-universal-interfaces.sh | 101 ++++++++++++++++++++++++++++++++ 3 files changed, 173 insertions(+) create mode 100755 docker-entrypoint.sh create mode 100755 install-universal-interfaces.sh diff --git a/Dockerfile b/Dockerfile index 58b1f5280b..653d4975b1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,12 +25,19 @@ RUN mkdir /Retro68-build && \ # Release image FROM base AS release +ENV INTERFACES=multiversal + COPY --from=build \ /Retro68/interfaces-and-libraries.sh \ /Retro68/prepare-headers.sh \ /Retro68/prepare-rincludes.sh \ + /Retro68/install-universal-interfaces.sh \ + /Retro68/docker-entrypoint.sh \ /Retro68-build/bin/ COPY --from=build /Retro68-build/toolchain /Retro68-build/toolchain LABEL org.opencontainers.image.source https://github.com/autc04/Retro68 + +CMD [ "/bin/bash" ] +ENTRYPOINT [ "/Retro68-build/bin/docker-entrypoint.sh" ] diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh new file mode 100755 index 0000000000..792a753266 --- /dev/null +++ b/docker-entrypoint.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +set -e + +TMPDIR=/tmp +BUILDDIR=/Retro68-build + +if [[ $INTERFACES == "universal" ]]; +then + # If the universal RIncludes directory is empty, download and install the universal headers + if [ ! "$(ls -A $BUILDDIR/toolchain/universal/RIncludes 2> /dev/null)" ]; then + # If INTERFACESFILE is empty, exit + if [[ -z $INTERFACESFILE ]]; + then + echo -n "Universal interfaces not present, please specify the location of a suitable " + echo "MacBinary DiskCopy image using the INTERFACESFILE environment variable." + exit 1 + fi + + BASEINTERFACESFILE=`basename $INTERFACESFILE` + + # If INTERFACESFILE is a URL, download it first to TMPDIR. Otherwise assume the file is + # already present and copy it to TMPDIR for installation + if [[ $INTERFACESFILE == http* ]]; + then + echo "Downloading Universal interfaces from MacBinary DiskCopy image $BASEINTERFACESFILE..." + curl -s $INTERFACESFILE -o $TMPDIR/$BASEINTERFACESFILE + echo "done" + else + if [[ -z $INTERFACESFILE ]]; + then + echo "Unable to locate universal interfaces file $INTERFACESFILE" + exit 1 + else + echo "Using Universal intefaces from MacBinary Diskcopy image $BASEINTERFACESFILE" + cp $INTERFACESFILE $TMPDIR/$BASEINTERFACESFILE + fi + fi + + # Extract the file + $BUILDDIR/bin/install-universal-interfaces.sh $TMPDIR $BASEINTERFACESFILE + + # Switch to universal + echo "Linking Universal interfaces..." + $BUILDDIR/bin/interfaces-and-libraries.sh $BUILDDIR/toolchain $TMPDIR/InterfacesAndLibraries + echo "done" + else + echo "Linking Universal interfaces..." + + # Link to existing universal interfaces + PREFIX=$BUILDDIR/toolchain + . "$BUILDDIR/bin/interfaces-and-libraries.sh" + BUILD_68K=true + BUILD_PPC=true + + unlinkInterfacesAndLibraries + linkInterfacesAndLibraries "universal" + echo "done" + fi +else + echo "Using multiversal interfaces" +fi + +# Execute command +exec "$@" diff --git a/install-universal-interfaces.sh b/install-universal-interfaces.sh new file mode 100755 index 0000000000..013aeaf644 --- /dev/null +++ b/install-universal-interfaces.sh @@ -0,0 +1,101 @@ +#!/bin/bash + +# +# install-universal-interfaces.sh +# +# Optionally download and attempt to install the universal interfaces from +# a Macbinary disk image containing the Interfaces&Libraries directory +# +# Usage: +# install-universal-interfaces.sh +# +# Decompress the Macbinary image at / into +# /InterfacesAndLibraries in the correct format for +# interfaces-and-libraries.sh. +# + +set -e + +TMPDIR=$1 +FILENAME=$2 + +if [[ ! -f $TMPDIR/$FILENAME ]]; +then + echo "$TMPDIR/$FILENAME not found" + exit 1 +fi + +echo "Decompressing $FILENAME..." +ConvertDiskImage $TMPDIR/$FILENAME $TMPDIR/$FILENAME.img +echo "Decompression complete" + +# Copy over Interfaces&Libraries files +echo "Copying Interfaces&Libraries files..." +hmount $TMPDIR/$FILENAME.img + +# Find Interfaces&Libraries directory, get recursive directory listing +HFSINTERFACESANDLIBSDIR=`hls -R | grep 'Interfaces&Libraries:$'` +IFS="$(printf '\n')" +echo "Found Interfaces&Libraries at $HFSINTERFACESANDLIBSDIR" +FILES=`hls -FR1 $HFSINTERFACESANDLIBSDIR` + +UNIXINTERFACESANDLIBSDIR=$TMPDIR/InterfacesAndLibraries +mkdir -p $UNIXINTERFACESANDLIBSDIR + +# Parse results: first line is the HFS path, following lines contain one file +# per line terminated by an empty line +while IFS= read -r LINE; do + if [[ $LINE == :* ]]; + then + # If it starts with : then it is a HFS path + HFSPATH=$LINE + UNIXRELPATH=$(echo "$HFSPATH" | sed "s#$HFSINTERFACESANDLIBSDIR##g" | sed "s#:#/"#g) + UNIXPATH="$UNIXINTERFACESANDLIBSDIR/$UNIXRELPATH" + + # Make UNIX directory + mkdir -p $UNIXPATH + else + # If it ends with : it is a directory so ignore (we will find it during the descent) + if [[ ! $LINE == *: ]]; + then + # If it isn't empty, it must be a filename + if [[ ! -z $LINE ]]; + then + HFSFULLPATH="$HFSPATH$LINE" + UNIXFULLPATH="$UNIXPATH$LINE" + + echo "Copying $HFSFULLPATH to $UNIXFULLPATH" + + # PPC libraries need a resource fork, but the code in + # interfaces-and-libraries.sh doesn't correctly detect InterfaceLib in + # Macbinary format. Work around this for now by using Basilisk II format + # which can be parsed by ResourceFile and still allows the filename + # detection logic to work. + if [[ $HFSPATH == *SharedLibraries: ]]; + then + if [[ ! -d $UNIXPATH.rsrc ]]; + then + mkdir $UNIXPATH.rsrc + fi + + # First copy as Macbinary + hcopy -m $HFSFULLPATH $UNIXFULLPATH.bin + + # Extract data fork using normal name + bash -c "cd $UNIXPATH && macunpack -d $UNIXFULLPATH.bin && mv $UNIXFULLPATH.data $UNIXFULLPATH" + + # Extract resource fork into .rsrc directory + bash -c "cd $UNIXPATH && macunpack -r $UNIXFULLPATH.bin && mv $UNIXFULLPATH.rsrc $UNIXPATH.rsrc/$LINE" + + # Delete original Macbinary + rm -rf $UNIXFULLPATH.bin + else + hcopy -r $HFSFULLPATH $UNIXFULLPATH + fi + fi + fi + fi +done <<< "$FILES" + +# Unmount image +humount