/
diskimage-sign.sh
executable file
·235 lines (204 loc) · 7.07 KB
/
diskimage-sign.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
#!/bin/bash
#
# Create a signed and notarized JMRI macOS disk image (from diskimage.sh) from an unsigned one
# This is structured to use the Mac OS X tools when run on a Mac, and native Linux tools when run on a Linux box,
# but only the OS X version is being actively developed because it relies on some Apple-specific
# tools for notarization.
#
# arguments are:
# Release version string e.g. "4.5.5", e.g. "${release.version-string}" from Ant
# Output DMG file pathname e.g. dist/release/JMRI.4.5.5.dmg, "${dist.release}/JMRI.${release.version-string}.dmg" in Ant
# Input DMG file pathname e.g. dist/release/JMRI.4.5.5-unsigned.dmg,
# ID of signing certificate, i.e. "Developer ID Application: My Name"
# Apple ID for notarization
# Application-specific password on that Apple ID (see appleid.apple.com)
# Location of keychain file containing that certificate
# Password to unlock that keychain file
#
# Although it might be consuming additional space on the final disk image,
# we do the signing and jar-updating there to ensure this doesn't
# cause issues for other uses of the raw as-built files
#
# Copyright 2007, 2011, 2016, 2019 Bob Jacobsen, david d zuhn
#
set -e # bail on errors
set -x # show our work
REL_VER=$1
OUTPUT=$2
INPUTIMAGEFILE=$3
CERTIFICATE=$4
AC_USER=$5
AC_PASSWORD=$6
KEYCHAIN_FILE=$7
KEYCHAIN_PWD=$8
# -----------------------------------------
function trapExitHandler {
trap - 1 2 3 15
umount "$tmpimage2" && echo "Unmounted tmpimage2"
umount "$tmpindir" && echo "Unmounted tempindir"
umount "$INPUTIMAGEFILE" && echo "Unmounted input image"
rm -rf "$tmpimage1" "$tmpimage2" "$tmpoutdir" "$tmpindir" >/dev/null 2>&1
}
# -----------------------------------------
# Retry a command up to a specific number of times until it exits successfully.
# Waits 1 minute between retries
#
# $ retry 5 echo Hello
# Hello
#
#
function retry {
local retries=$1
shift
local count=0
until "$@"; do
exit=$?
wait=60
count=$(($count + 1))
if [ $count -lt $retries ]; then
echo "Retry $count/$retries exited $exit, retrying in $wait seconds..."
sleep $wait
else
echo "Retry $count/$retries exited $exit, no more retries left."
return $exit
fi
done
return 0
}
# -----------------------------------------
# Sign a file (2nd arg) with a jar file (1st arg) in place
#
function signJarMember {
local jar=$1
local file=$2
jar xf $jar $file
signFile $file
jar uvf $jar $file
rm $file
return 0
}
# -----------------------------------------
# Sign a single file (1st arg)
#
function signFile {
local file=$1
codesign -v -s "$CERTIFICATE" --force --deep $file
return 0
}
# -----------------------------------------
if [ "$REL_VER" = "" -o "$OUTPUT" = "" -o "$INPUTIMAGEFILE" = "" ]
then
echo "usage: $0 VERSION OUTPUTIMAGEFILE INPUTIMAGEFILE" 1>&2
exit 1
fi
if [ -x /usr/bin/hdiutil ]
then
# if a Linux box were to have hdiutil, I think that would be the preferable route to follow
# although it's pretty unlikely
SYSTEM=MACOSX
else
SYSTEM=LINUX
fi
if ! tmpoutdir=`mktemp -d -t JMRI.output`
then
echo "Cannot create output temporary directory"
exit 1
fi
if ! tmpindir=`mktemp -d -t JMRI.input`
then
echo "Cannot create input temporary directory"
exit 1
fi
if ! tmpimage1=`mktemp -t JMRI.tmp.image.1`
then
echo "Cannot create temp image 1"
exit 1
fi
if ! tmpimage2=`mktemp -t JMRI.tmp.image.2`
then
echo "Cannot create temp image 1"
exit 1
fi
# handle cleanup on exit
trap trapExitHandler 0
# handle error signals by aborting
trap 'exit 2' 1 2 3 15
# shouldn't be anything left over, but if so, clean up
rm -f "$tmpimage1" "$tmpimage2"
# mount input image (needs Linux varient)
hdiutil attach "$INPUTIMAGEFILE" -mountpoint "$tmpindir" -nobrowse
# create disk image and mount
jmrisize=`du -ms "$tmpindir" | awk '{print $1}'`
imagesize=`expr $jmrisize + 80`
if [ "$SYSTEM" = "MACOSX" ]
then
hdiutil create -size ${imagesize}MB -fs HFS+ -layout SPUD -volname "JMRI ${REL_VER}" "$tmpimage2"
hdiutil attach ${tmpimage2}.dmg -mountpoint "$tmpoutdir" -nobrowse
else
dd if=/dev/zero of="$tmpimage2" bs=1M count=${imagesize}
mkfs.hfsplus -v "JMRI ${REL_VER}" "${tmpimage2}"
sudo mount -t hfsplus -o loop,rw,uid=$UID "$tmpimage2" $tmpoutdir
fi
# wait for the mountpoint to settle down...
# I don't think we need this on macOS
#sleep 10
if [ -w "$tmpoutdir" ]
then
SUDO=
else
SUDO=sudo
fi
# copy contents of the Mac OS X distribution to the newly mounted filesysten
tar -C "$tmpindir" -cf - JMRI | $SUDO tar -C "$tmpoutdir" -xf -
# unlock the keychain containing the certification
security unlock-keychain -p "$KEYCHAIN_PWD" "$KEYCHAIN_FILE"
# sign the app files in output
signFile $tmpoutdir/JMRI/PanelPro.app
signFile $tmpoutdir/JMRI/DecoderPro.app
signFile $tmpoutdir/JMRI/SoundPro.app
# sign the individual library files
signFile $tmpoutdir/JMRI/lib/macosx/libgluegen-rt.jnilib
signFile $tmpoutdir/JMRI/lib/macosx/libjinput-osx.jnilib
signFile $tmpoutdir/JMRI/lib/macosx/libjoal.jnilib
signFile $tmpoutdir/JMRI/lib/macosx/libopenal.1.15.1.dylib
signFile $tmpoutdir/JMRI/lib/macosx/libopenal.1.dylib
signFile $tmpoutdir/JMRI/lib/macosx/libopenal.dylib
# sign libraries inside jar files
signJarMember $tmpoutdir/JMRI/lib/libusb4java-1.2.0-osx-x86_64.jar org/usb4java/osx-x86_64/libusb4java.dylib
signJarMember $tmpoutdir/JMRI/lib/bluecove-2.1.1-SNAPSHOT.jar libbluecove.jnilib
signJarMember $tmpoutdir/JMRI/lib/jna-4.4.0.jar com/sun/jna/darwin/libjnidispatch.jnilib
signJarMember $tmpoutdir/JMRI/lib/hid4java-0.5.0.jar darwin/libhidapi.dylib
signJarMember $tmpoutdir/JMRI/lib/libusb4java-1.2.0-osx-x86.jar org/usb4java/osx-x86/libusb4java.dylib
# signJarMember $tmpoutdir/JMRI/lib/selenium-server-standalone-3.6.0.jar com/sun/jna/darwin/libjnidispatch.jnilib # OMITTED DUE TO TOC ISSUE
signJarMember $tmpoutdir/JMRI/lib/jython-standalone-2.7.1.jar META-INF/native/osx/libjansi.jnilib
signJarMember $tmpoutdir/JMRI/lib/jython-standalone-2.7.1.jar jni/Darwin/libjffi-1.2.jnilib
# add an Applications icon
$SUDO ln -s /Applications "$tmpoutdir"
# now, how do we make a nice background picture in the folder with directions on how to drag'n'drop to Applications?
# eject the mounted disk image
if [ "$SYSTEM" = "MACOSX" ]
then
hdiutil detach "$tmpoutdir" && EJECTED=1
else
sudo umount "$tmpoutdir" && EJECTED=1
fi
# pack into a smaller disk image for distribution
if [ "$SYSTEM" = "MACOSX" ]
then
rm -f "$OUTPUT"
hdiutil convert ${tmpimage2}.dmg -format UDZO -imagekey zlib-level=9 -o "$OUTPUT"
else
# this relies on the 'dmg' tool from https://github.com/erwint/libdmg-hfsplus
dmg dmg "$tmpimage2" "$OUTPUT"
fi
# sign image file
signFile "$OUTPUT"
# notarize distribution: start by uploading
xcrun altool --notarize-app --verbose --primary-bundle-id "org.jmri" --username "$AC_USER" --password "$AC_PASSWORD" --file "$OUTPUT"
# stapling result will temporarily fail while the notatization is still happening at Apple
sleep 30
retry 20 xcrun stapler staple "$OUTPUT"
# clean up
hdiutil detach $tmpindir
# this should also be handled by the trap, but it doesn't hurt...
rm -rf $tmpimage1 $tmpimage2 $tmpoutdir