I support Mac code signing and notarisation for DTS and, as part of that work, I often need to look inside various Apple-specific archive file formats. This post explains how I do this. It’s mostly for the benefit of Future Quinn™, but I figured other folks would appreciate it as well.
IMPORTANT This post explains low-level techniques for inspecting archives. Do not use them to create archives. Instead, create your archives using the highest-level tool that will get the job done [1].
Flat Installer Package
A flat installer package — appropriate for uploading to the Mac App Store or the notary service — is actually a xar archive. Unpack it using the xar tool. For example:
% # List the contents:
%
% xar -tf InstallTest-1.0d1.pkg
com.example.apple-samplecode.InstallTest.pkg
com.example.apple-samplecode.InstallTest.pkg/Bom
com.example.apple-samplecode.InstallTest.pkg/Payload
com.example.apple-samplecode.InstallTest.pkg/PackageInfo
Distribution
%
% # Actually unpack:
#
% mkdir tmp
% cd tmp
% xar -xf ../InstallTest-1.0d1.pkg
% find .
.
./Distribution
./com.example.apple-samplecode.InstallTest.pkg
./com.example.apple-samplecode.InstallTest.pkg/Bom
./com.example.apple-samplecode.InstallTest.pkg/Payload
./com.example.apple-samplecode.InstallTest.pkg/PackageInfo
See the xar man page for more info on that tool.
The resulting Bom file is a ‘bill of materials’. For more on this, see the bom man page for details. Use lsbom to dump this:
% lsbom ./com.example.apple-samplecode.InstallTest.pkg/Bom
. 0 0/0
./InstallTest.app …
./InstallTest.app/Contents …
./InstallTest.app/Contents/Info.plist …
./InstallTest.app/Contents/MacOS …
./InstallTest.app/Contents/MacOS/InstallTest …
…
The Payload file contains… you guessed it… the installer’s payload. This is a gzipped cpio archive. To unpack it, pipe the file through cpio:
% cpio -i < com.example.apple-samplecode.InstallTest.pkg/Payload
5072 blocks
% find InstallTest.app
InstallTest.app
InstallTest.app/Contents
InstallTest.app/Contents/Info.plist
InstallTest.app/Contents/MacOS
InstallTest.app/Contents/MacOS/InstallTest
…
See the cpio man page for more info on that tool.
Note This is a bit of a hassle so most of the time I use a third-party app to unpack installer packages. Which one? Well, I can’t give away all my secrets (-:
Xip Archives
To extract a xip archive (pronounced, I believe, as chip archive), run the xip tool with the --expand argument:
% xip --expand XipTest.xip
However, if that doesn’t work you’ll need to dig into the archive. First, undo the outer xar wrapper:
% xar -xf XipTest.xip
This produces two files, Content and Metadata:
% ls -l
total 7552
-rw-r--r-- 1 quinn staff 1683391 10 Jun 17:05 Content
-rw-r--r-- 1 quinn staff 287 10 Jun 17:08 Metadata
-rw-r--r-- 1 quinn staff 1697157 10 Jun 17:05 XipTest.xip
The Metadata file is an XML property list:
% cat Metadata
…
<dict>
<key>UncompressedSize</key>
<integer>2598653</integer>
<key>Version</key>
<integer>1</integer>
</dict>
</plist>
The Content file is an Apple Archive. Unpack this using the aa tool:
% aa extract -ignore-eperm -i Content -d tmp
% find tmp
tmp
tmp/XipTest
tmp/XipTest/XipTest.app
tmp/XipTest/XipTest.app/Contents
tmp/XipTest/XipTest.app/Contents/Info.plist
tmp/XipTest/XipTest.app/Contents/MacOS
tmp/XipTest/XipTest.app/Contents/MacOS/QCodeIndex
tmp/XipTest/XipTest.app/Contents/MacOS/XipTest
…
See the aa man page for more info on that tool.
Note aa was previously known as yaa.
iOS App Archives
iOS apps are stored in an .ipa file. This is actually a zip archive under the covers. To unpack it, change the file name extension to .zip and then double click it it in the Finder (or use your favourite unzipping tool, like unzip or ditto).
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
[1] For installer package specifically, productbuild is your friend, but you can also use the lower-level tools like productsign, pkgbuild, and pkgutil.
Revision History
2024-02-20 Added the iOS App Archives section. Added a note about third-party apps to the end of the Flat Installer Package section.
2022-09-30 Changed yaa to aa and added a reference to the Apple Archive framework.
2021-02-26 Fixed the formatting.
2020-06-10 First posted.
General
RSS for tagDemystify code signing and its importance in app development. Get help troubleshooting code signing issues and ensure your app is properly signed for distribution.
Post
Replies
Boosts
Views
Activity
Many of the trusted execution problems I see are caused by folks signing their product using the --deep option. While that can work in some circumstances, I generally recommend against it. There are two issues with --deep:
It applies the same code signing options to every code item that it signs, something that’s not appropriate in general. For example, you might have an app containing a nested command-line tool, where the app and the tool need different entitlements. The --deep option will apply the same entitlements to both, which is a serious mistake.
It only signs code that it can find, and it only finds code in nested code sites. If you put code in a place where the system is expecting to find data, --deep won’t sign it.
The first issue is fundamental to how --deep works, and is the main reason you should not use it. Indeed, on macOS it may cause the trusted execution system to block your program from running. For the details, see the Check for Entitlements on Library Code section of Resolving Library Loading Problems.
The second issue is only a problem if you don’t follow the rules for nesting code and data within a bundle, as documented in Placing Content in a Bundle. However, my experience is that the products that don’t follow those rules are exactly the same sort of products that try to use --deep.
The alternative to --deep is to sign each code item separately, from the inside out. If your product has lots of nested code, automate this using a script.
Note One exception to the prohibition on --deep is Automator apps. If you’re signing an Automator app, see this DevForums post.
For detailed information on how to correctly sign and package Mac software, see Creating distribution-signed code for macOS and Packaging Mac software for distribution.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Revision history:
2024-05-06 Update some links to reference the Real Documentation™ rather than my legacy DevForums posts.
2022-06-14 Added a link to Resolving Library Loading Problems. Replaced the link to Signing a Mac Product For Distribution with a link to Creating Distribution-Signed Code for Mac. Made other minor editorial changes.
2021-10-21 Replaced the nested code reference with one to Placing Content in a Bundle. Minor editorial changes.
2020-09-15 Adopted the correct terminology for Automator apps.
2020-03-09 First version.