18143046ed3c0ad105dd33e38a31eb7ed3bc8756
[openafs.git] / src / packaging / MacOS / pkgbuild.sh.in
1 #!/bin/bash
2 # Portions Copyright (c) 2003, 2006 Apple Computer, Inc.  All rights reserved.
3 echo '**BUILDPKG**' "$@"
4
5 usage() {
6     exec >&2
7
8     echo 'Usage: pkgbuild.sh [-x] [--app-key <appkey>] [--inst-key <instkey>]'
9     echo '                   [--apple-id <appleid> <password>]'
10     echo '                   [--pass N] [--csdb <CellServDB>] <binary-dir>'
11     echo
12     echo '--app-key and --inst-key are for signing. -x prints all comamnds as '
13     echo 'they are run. --apple-id is for notarizing.'
14     echo
15     echo 'Note: the password associated with <appleid> can be a reference to a'
16     echo 'keychain item. Including your password as cleartext is not'
17     echo 'recommended. e.g.'
18     echo
19     echo '--apple-id foo@bar.com "@keychain:PASSWORD"'
20     echo
21     echo 'In this case, keychain must hold a keychain item named PASSWORD with'
22     echo 'an account matching foo@bar.com.'
23     echo
24     echo 'By default, all passes are run. Available passes:'
25     echo '    --pass 1: prepare pkgroot'
26     echo '    --pass 2: create packages/installer from pkgroot'
27     echo 'If you want to alter the pkgroot, run pass 1, then alter what you'
28     echo 'want, and then run pass 2 to create the resulting packages.'
29     echo 'The --pass argument may be given multiple times.'
30     exit 1
31 }
32
33 if [ x"$#" = x0 ]; then
34     usage
35 fi
36
37 anypass=0
38 PASS1=
39 PASS2=
40
41 APP_KEY=
42 INST_KEY=
43 APPLE_ID=
44 APPLE_PW=
45 DEST_DIR=
46 CSDB=
47
48 CODESIGN_OPTS=
49
50 while [ x"$#" != x0 ] ; do
51     key="$1"
52     shift
53
54     case "$key" in
55     --app-key)
56         APP_KEY="$1"
57         shift
58         ;;
59     --inst-key)
60         INST_KEY="$1"
61         shift
62         ;;
63     --apple-id)
64         APPLE_ID="$1"
65         shift
66         APPLE_PW="$1"
67         shift
68         ;;
69     --csdb)
70         CSDB="$1"
71         shift
72         ;;
73     --pass)
74         anypass=1
75         pass_arg="$1"
76         shift
77         case "$pass_arg" in
78         1)
79             PASS1=1
80             ;;
81         2)
82             PASS2=1
83             ;;
84         *)
85             echo "Unknown pass $pass_arg" >&2
86             exit 1
87             ;;
88         esac
89         ;;
90     -x)
91         DO_X=1
92         ;;
93     *)
94         if [ x"$DEST_DIR" = x ] ; then
95             DEST_DIR="$key"
96         else
97             echo "Error: Unknown arg $key" >&2
98             usage
99         fi
100         ;;
101     esac
102 done
103
104 if [ x"$anypass" = x0 ] ; then
105     PASS1=1
106     PASS2=1
107 fi
108
109 if [ x"$DEST_DIR" = x ] ; then
110     echo "Error: binary 'dest' dir not given"
111     usage
112 fi
113
114 set -e
115
116 if [ x"$DO_X" = x1 ] ; then
117     set -x
118 fi
119
120 BINDEST=`cd "$DEST_DIR" && pwd`
121 CURDIR=`pwd`
122 RESSRC=`dirname "$0"`
123 RESSRC=`cd "$RESSRC" && pwd`
124 majorvers=`uname -r | cut -d. -f1`
125
126 if [ x"$majorvers" = x10 ]; then
127     RELNAME="Snowleopard"
128     THISREL=6
129
130 elif [ x"$majorvers" = x11 ]; then
131     RELNAME="Lion"
132     THISREL=7
133
134 elif [ x"$majorvers" = x12 ]; then
135     RELNAME="MountainLion"
136     THISREL=8
137
138 elif [ x"$majorvers" = x13 ]; then
139     RELNAME="Mavericks"
140     THISREL=9
141
142 elif [ x"$majorvers" = x14 ]; then
143     RELNAME="Yosemite"
144     THISREL=10
145
146 elif [ x"$majorvers" = x15 ]; then
147     RELNAME="ElCapitan"
148     THISREL=11
149
150 elif [ x"$majorvers" = x16 ]; then
151     RELNAME="Sierra"
152     THISREL=12
153
154 elif [ x"$majorvers" = x17 ]; then
155     RELNAME="HighSierra"
156     THISREL=13
157
158 elif [ x"$majorvers" = x18 ]; then
159     RELNAME="Mojave"
160     THISREL=14
161
162 elif [ x"$majorvers" = x19 ]; then
163     RELNAME="Catalina"
164     THISREL=15
165
166 elif [ x"$majorvers" = x ] ; then
167     echo "Error running uname" >&2
168     exit 1
169
170 else
171     echo "Unknown major version $majorvers" >&2
172     exit 1
173 fi
174
175 if [ $THISREL -ge 14 ]; then
176     # Enable the Hardened Runtime capability, required as of 10.14.5.
177     CODESIGN_OPTS="--options runtime"
178 fi
179
180 SEP=:
181
182 PKGROOT="$CURDIR"/pkgroot
183 PKGRES="$CURDIR"/pkgres
184 DPKGROOT="$CURDIR"/dpkgroot
185 PLUGINS="$CURDIR"/plugins
186 if test -e /usr/bin/pkgbuild; then
187     :
188 else
189     echo pkgbuild not found >&2
190     exit 1
191 fi
192 if test -e /usr/bin/productbuild; then
193     :
194 else
195     echo productbuild not found >&2
196     exit 1
197 fi
198
199 if [ x"$PASS1" = x1 ]; then
200     if [ -x /usr/bin/curl ] && [ x"$CSDB" = x ]; then
201         echo "No CellServDB provided; downloading one from central.org"
202         /usr/bin/curl -f -O https://www.central.org/dl/cellservdb/CellServDB
203         if [ -f "$CURDIR"/CellServDB ] ; then
204             CSDB="$CURDIR"/CellServDB
205         fi
206     fi
207
208     if [ x"$CSDB" = x ]; then
209         echo "A CellServDB file must be provided with --csdb" >&2
210         die=1
211     else
212         # Turn CSDB into an absolute path
213         case "$CSDB" in
214         /*)
215             ;;
216         *)
217             CSDB="$CURDIR/$CSDB"
218             ;;
219         esac
220
221         if grep -q 'GCO Public CellServDB' "$CSDB" ; then
222             touch "$CSDB"
223         else
224             echo "A proper CellServDB file must be provided" >&2
225             die=1
226         fi
227     fi
228
229     for f in ReadMe.rtf."$majorvers" \
230              License.rtf \
231              CellServDB.list \
232              OpenAFS.info \
233              OpenAFS.post_install \
234              OpenAFS.pre_upgrade \
235              csrvdbmerge.pl \
236              2.0.txt
237     do
238         if [ ! -f "$RESSRC/$f" ]; then
239             echo "file missing: $RESSRC/$f" >&2
240             die=1
241         fi
242     done
243     if [ x"$die" = x1 ]; then
244         echo "Correct above errors; then retry" >&2
245         exit 1
246     fi
247
248     for f in "$BINDEST"/bin/translate_et \
249              "$BINDEST/root.client/usr/vice/etc/afs.kext/Contents/MacOS/afs"
250     do
251         if [ ! -f "$f" ] ; then
252             echo "dest file missing: $f" >&2
253             die=1
254         fi
255     done
256     if [ x"$die" = x1 ]; then
257         echo $BINDEST " is not a valid binary dir. it should be the result of" >&2
258         echo "make dest" >&2
259         exit 1
260     fi
261
262     rm -rf "$PKGROOT" "$PLUGINS"
263     mkdir "$PKGROOT"
264     mkdir "$PLUGINS"
265
266     mkdir -p "$PKGROOT"/Library
267     mkdir -p "$PKGROOT"/Library/PreferencePanes
268     mkdir -p "$PKGROOT"/Library/Security/SecurityAgentPlugins
269
270     chown -R root${SEP}admin "$PKGROOT"
271     chmod -R 755 "$PKGROOT"
272
273     (cd "$BINDEST"/tools && pax -rw OpenAFS.prefPane "$PKGROOT"/Library/PreferencePanes/)
274     (cd "$BINDEST"/tools && pax -rw aklog.bundle \
275     "$PKGROOT"/Library/Security/SecurityAgentPlugins/)
276
277     mkdir -p "$PKGROOT"/Library/OpenAFS/Tools
278     (cd "$BINDEST" && pax -rw * "$PKGROOT"/Library/OpenAFS/Tools)
279
280     cd "$RESSRC"
281     mv "$PKGROOT"/Library/OpenAFS/Tools/installer/* "$PLUGINS"/
282
283     mkdir -p "$PKGROOT"/Library/LaunchDaemons
284     chmod -R o-w "$PKGROOT"/Library
285     chmod -R g-w "$PKGROOT"/Library
286
287     cp openafs.launchd.plist "$PKGROOT"/Library/LaunchDaemons/org.openafs.filesystems.afs.plist
288     chmod 644 "$PKGROOT"/Library/LaunchDaemons/org.openafs.filesystems.afs.plist
289
290     chown root${SEP}admin "$PKGROOT"/Library
291     chown -R root${SEP}wheel "$PKGROOT"/Library/LaunchDaemons
292     chown -R root${SEP}wheel "$PKGROOT"/Library/OpenAFS/Tools
293     chmod -R og-w "$PKGROOT"/Library/OpenAFS/Tools
294
295     mkdir -p "$PKGROOT"/private/var/db/openafs/cache
296     mkdir -p "$PKGROOT"/private/var/db/openafs/etc/config
297
298     cp openafs.launchdaemon "$PKGROOT"/private/var/db/openafs/etc/launchafs.sh
299     chmod 755 "$PKGROOT"/private/var/db/openafs/etc/launchafs.sh
300
301     cp "$CSDB" "$PKGROOT"/private/var/db/openafs/etc/CellServDB.master
302     echo grand.central.org > "$PKGROOT"/private/var/db/openafs/etc/ThisCell.sample
303     echo /afs:/var/db/openafs/cache:100000 > \
304          "$PKGROOT"/private/var/db/openafs/etc/cacheinfo.sample
305
306     cp -RP "$PKGROOT"/Library/OpenAFS/Tools/etc/afssettings \
307            "$PKGROOT"/private/var/db/openafs/etc/config
308     cp settings.plist "$PKGROOT"/private/var/db/openafs/etc/config/settings.plist.orig
309     cp afs.conf "$PKGROOT"/private/var/db/openafs/etc/config/afs.conf.sample
310     cp krb5-weak.conf "$PKGROOT"/private/var/db/openafs/etc/krb5-weak.conf
311
312     cp decode-panic "$PKGROOT"/Library/OpenAFS/Tools/tools
313     chmod a+x "$PKGROOT"/Library/OpenAFS/Tools/tools/decode-panic
314
315     rm -rf "$DPKGROOT"
316     mkdir "$DPKGROOT"
317     mkdir -p "$DPKGROOT"/Library/OpenAFS/Debug
318
319     mv "$PKGROOT"/Library/OpenAFS/Tools/root.client/usr/vice/etc/afs.kext.dSYM \
320        "$DPKGROOT"/Library/OpenAFS/Debug/
321     cp -RP "$PKGROOT"/Library/OpenAFS/Tools/root.client/usr/vice/etc/afs.kext \
322            "$DPKGROOT"/Library/OpenAFS/Debug/
323     chown -R root${SEP}wheel "$DPKGROOT"/Library/OpenAFS/Debug
324     chmod -R og-w "$DPKGROOT"/Library/OpenAFS/Debug
325
326     strip -X -S \
327         "$PKGROOT"/Library/OpenAFS/Tools/root.client/usr/vice/etc/afs.kext/Contents/MacOS/afs
328
329     mkdir -p "$PKGROOT"/private/var/db/openafs
330
331     cp -RP "$PKGROOT"/Library/OpenAFS/Tools/root.client/usr/vice/etc/afs.kext \
332            "$PKGROOT"/Library/OpenAFS/Tools/root.client/usr/vice/etc/C \
333            "$PKGROOT"/private/var/db/openafs/etc
334
335     chown -R root${SEP}wheel "$PKGROOT"/private
336     chmod -R og-w "$PKGROOT"/private
337
338     chown -R root${SEP}wheel "$PKGROOT"/private
339     chmod -R og-w "$PKGROOT"/private
340     chmod  og-rx "$PKGROOT"/private/var/db/openafs/cache
341
342     if [ x"$APP_KEY" != x ] ; then
343         # To be notarized by Apple, all files must be signed.
344         find "$PKGROOT" -type f -exec codesign --verbose --force \
345             --timestamp --sign "$APP_KEY" $CODESIGN_OPTS {} \;
346
347         # Sign each 'thing' that we have (commands, kexts, etc)
348         for obj in "$DPKGROOT"/Library/OpenAFS/Debug/afs.kext \
349                    "$PKGROOT"/Library/OpenAFS/Tools/root.client/usr/vice/etc/afs.kext \
350                    "$PKGROOT"/private/var/db/openafs/etc/afs.kext \
351                    "$PKGROOT"/Library/PreferencePanes/OpenAFS.prefPane/Contents/Resources/AFSBackgrounder.app \
352                    "$PKGROOT"/Library/PreferencePanes/OpenAFS.prefPane \
353                    "$PKGROOT"/Library/Security/SecurityAgentPlugins/aklog.bundle \
354                    "$PKGROOT"/Library/OpenAFS/Tools/tools/growlagent-openafs.app \
355                    "$PKGROOT"/Library/OpenAFS/Tools/tools/aklog.bundle \
356                    "$PKGROOT"/Library/OpenAFS/Tools/tools/OpenAFS.prefPane/Contents/Resources/AFSBackgrounder.app \
357                    "$PKGROOT"/Library/OpenAFS/Tools/tools/OpenAFS.prefPane \
358                    "$PLUGINS"/afscell.bundle
359         do
360             codesign --verbose --force --timestamp --sign "$APP_KEY" $CODESIGN_OPTS "$obj"
361         done
362
363
364         # Check if our signatures for our kexts are valid. 'kextutil' will exit
365         # with an error and print out a message if something is wrong with the
366         # signature. Note that a code signing cert must have the
367         # 1.2.840.113635.100.6.1.18 extension present to be used for kexts
368         # (most code signing certs cannot be used for kexts).
369         for kext in "$DPKGROOT"/Library/OpenAFS/Debug/afs.kext \
370                     "$PKGROOT"/Library/OpenAFS/Tools/root.client/usr/vice/etc/afs.kext \
371                     "$PKGROOT"/private/var/db/openafs/etc/afs.kext
372         do
373             # This check will fail on systems that require notarization, because we haven't
374             # notarized anything yet.  For now, just disable the check for those versions.
375             if [ $THISREL -ge 14 ]; then
376                 echo "Skipping kextutil checks for $kext"
377             else
378                 kextutil -no-load -print-diagnostics "$kext"
379             fi
380         done
381     fi
382
383     if [ $majorvers -ge 15 ]; then
384         # El Capitan and further prevent us from touching /usr/bin directly
385         PREFIX=/opt
386         USRBIN=/opt/openafs/bin
387         USRBIN2TOOLS=../../../Library/OpenAFS/Tools
388
389         USRSBIN=/opt/openafs/sbin
390         USRSBIN2TOOLS=../../../Library/OpenAFS/Tools
391
392         MANDIR=/opt/openafs/share/man
393         MANDIR2TOOLS=../../../../Library/OpenAFS/Tools
394
395         # Add our bin, sbin, and man directories to the default search path
396         mkdir -p "$PKGROOT"/etc/paths.d "$PKGROOT"/etc/manpaths.d
397         echo "$USRBIN" > "$PKGROOT"/etc/paths.d/40-openafs
398         echo "$USRSBIN" >> "$PKGROOT"/etc/paths.d/40-openafs
399         echo "$MANDIR" > "$PKGROOT"/etc/manpaths.d/40-openafs
400     else
401         PREFIX=/usr
402         USRBIN=/usr/bin
403         USRBIN2TOOLS=../../Library/OpenAFS/Tools
404
405         USRSBIN=/usr/sbin
406         USRSBIN2TOOLS="$USRBIN2TOOLS"
407
408         MANDIR=/usr/share/man
409         MANDIR2TOOLS=../../../Library/OpenAFS/Tools
410     fi
411
412     mkdir -p "$PKGROOT$USRBIN" \
413              "$PKGROOT$USRSBIN" \
414              "$PKGROOT$MANDIR"/man1 \
415              "$PKGROOT$MANDIR"/man5 \
416              "$PKGROOT$MANDIR"/man8
417
418     BINLIST="fs klog klog.krb pagsh pagsh.krb pts sys tokens tokens.krb unlog unlog.krb aklog"
419     ETCLIST="vos"
420
421     if [ x"$DO_X" = x1 ] ; then
422         # Don't print out every single 'ln -s'... that's kinda useless
423         : 'Symlinking commands and manpages into place...'
424         set +x
425     fi
426
427     for f in $BINLIST; do
428         ln -s "$USRBIN2TOOLS"/bin/"$f" "$PKGROOT$USRBIN/$f"
429     done
430     for f in $ETCLIST; do
431         ln -s "$USRSBIN2TOOLS"/etc/"$f" "$PKGROOT$USRSBIN/$f"
432     done
433
434     for section in man1 man5 man8 ; do
435         for f in $(ls $PKGROOT/Library/OpenAFS/Tools/man/$section); do
436
437             if [ -L "$PKGROOT/Library/OpenAFS/Tools/man/$section/$f" ] ; then
438                 # If this manpage is a symlink, just change where it's pointing,
439                 # and rename the link; don't actually 'gzip' it.
440                 link=$(readlink "$PKGROOT/Library/OpenAFS/Tools/man/$section/$f")
441                 rm -f "$PKGROOT/Library/OpenAFS/Tools/man/$section/$f"
442                 ln -s "$link".gz "$PKGROOT/Library/OpenAFS/Tools/man/$section/$f".gz
443
444             else
445                 gzip -9 "$PKGROOT/Library/OpenAFS/Tools/man/$section/$f"
446             fi
447             ln -s ../"$MANDIR2TOOLS"/man/"$section/$f".gz \
448                   "$PKGROOT$MANDIR/$section/$f".gz
449         done
450     done
451
452     if [ x"$DO_X" = x1 ] ; then
453         set -x
454     fi
455
456     ln -s "$USRBIN2TOOLS"/bin/kpasswd "$PKGROOT$USRBIN"/kpasswd.afs
457
458     ln -s "$USRSBIN2TOOLS"/root.client/usr/vice/etc/afsd "$PKGROOT$USRSBIN"/afsd
459
460     chown -R root${SEP}wheel "$PKGROOT$PREFIX"
461     chmod -R og-w "$PKGROOT$PREFIX"
462 fi
463
464 if [ x"$PASS2" = x1 ]; then
465     rm -rf "$PKGRES"
466     mkdir "$PKGRES"
467     cd "$RESSRC"
468
469     rm -rf "$CURDIR"/OpenAFS-debug-extension.pkg
470     /usr/bin/pkgbuild --root "$DPKGROOT" --id org.openafs.OpenAFS-debug.pkg \
471                       --version '@PACKAGE_VERSION@' \
472              "$CURDIR"/OpenAFS-debug-extension.pkg
473
474     cd "$RESSRC"
475     cp OpenAFS.post_install "$PKGRES"/postinstall
476     cp OpenAFS.pre_upgrade "$PKGRES"/preupgrade
477     cp OpenAFS.post_install "$PKGRES"/postupgrade
478     cp csrvdbmerge.pl "$PKGRES"
479
480     chmod a+x "$PKGRES"/csrvdbmerge.pl \
481               "$PKGRES"/postinstall \
482               "$PKGRES"/postupgrade \
483               "$PKGRES"/preupgrade
484
485     cp CellServDB.list "$PKGRES"
486     chown -R root${SEP}wheel "$PKGRES"
487
488     rm -rf "$CURDIR"/OpenAFS-dist.pkg
489     /usr/bin/pkgbuild --root "$PKGROOT" --id org.openafs.OpenAFS.pkg \
490                       --version '@PACKAGE_VERSION@' \
491                       --scripts "$PKGRES" "$CURDIR"/OpenAFS-dist.pkg
492
493     rm -rf "$PKGRES"
494     mkdir "$PKGRES"
495     cp background.jpg "$PKGRES"/background.jpg
496     cp License.rtf "$PKGRES"
497     cp ReadMe.rtf."$majorvers" "$PKGRES"/ReadMe.rtf
498     chown -R root${SEP}wheel "$PKGRES"
499
500     if [ $majorvers -ge 15 ] ; then
501         # For El Capitan and further, we have some extra information to tell
502         # the user at the end of the installation process.
503         cp conclusion.txt "$PKGRES"/conclusion.txt
504         PRES_EXTRA="<conclusion file=\"conclusion.txt\"/>"
505     fi
506
507     # generate Distribution.xml from Distribution.xml.in -- nonstandard substs
508     sed -e "s/%%OSX_MAJOR_CUR%%/$THISREL/g" \
509         -e "s/%%OSX_MAJOR_NEXT%%/$(( $THISREL + 1 ))/g" \
510         -e "s,%%PRES_EXTRA%%,$PRES_EXTRA,g" \
511         -e "s/%%OPENAFS_VERSION%%/@PACKAGE_VERSION@/g" \
512         < Distribution.xml.in > Distribution.xml
513
514     rm -rf "$CURDIR/prod"
515     mkdir "$CURDIR/prod"
516     mv "$CURDIR"/OpenAFS-dist.pkg "$CURDIR"/OpenAFS-debug-extension.pkg "$CURDIR"/prod
517     /usr/bin/productbuild --distribution Distribution.xml --resources "$PKGRES" \
518                           --plugins "$PLUGINS" --package-path "$CURDIR"/prod "$CURDIR"/OpenAFS.pkg
519
520     if [ x"$INST_KEY" != x ] ; then
521         mv "$CURDIR"/OpenAFS.pkg "$CURDIR"/OpenAFS-unsigned.pkg
522         productsign --timestamp --sign "$INST_KEY" "$CURDIR"/OpenAFS-unsigned.pkg \
523                     "$CURDIR"/OpenAFS.pkg
524         rm -f "$CURDIR"/OpenAFS-unsigned.pkg
525     fi
526
527     rm -rf "$CURDIR/dmg"
528     rm -f "$CURDIR/TMP.dmg"
529     rm -rf "$CURDIR/OpenAFS-@PACKAGE_VERSION@-$RELNAME.dmg"
530
531     mkdir "$CURDIR"/dmg
532     mv "$CURDIR"/OpenAFS.pkg "$CURDIR"/dmg
533     cp "$RESSRC"/Uninstall.14.15 "$CURDIR"/dmg/Uninstall.command
534     cp "$RESSRC"/DS_Store "$CURDIR"/dmg/.DS_Store
535     mkdir "$CURDIR"/dmg/.background
536     cp "$RESSRC"/afslogo.jpg "$CURDIR"/dmg/.background
537
538     if [ x"$APP_KEY" != x ] ; then
539         codesign --verbose --force --timestamp --sign "$APP_KEY" "$CURDIR"/dmg/Uninstall.command
540         codesign --verbose --force --timestamp --sign "$APP_KEY" "$CURDIR"/dmg/OpenAFS.pkg
541     fi
542
543     hdiutil create -srcfolder "$CURDIR"/dmg -volname OpenAFS \
544             -o "$CURDIR"/TMP.dmg
545     hdiutil convert -format UDZO "$CURDIR"/TMP.dmg \
546             -o "$CURDIR/OpenAFS-@PACKAGE_VERSION@-$RELNAME".dmg
547
548     echo
549     echo "Created $CURDIR/OpenAFS-@PACKAGE_VERSION@-$RELNAME".dmg
550
551     if [ x"$APPLE_ID" != x ] ; then
552         echo "Notarizing package..."
553         ./notarize.pl "$APPLE_ID" "$APPLE_PW" "$CURDIR/OpenAFS-@PACKAGE_VERSION@-$RELNAME.dmg"
554     fi
555 fi