Wednesday, June 6, 2012

Mac OS X pkg, bom files, package installation and utilities

List all installed packages:
pkgutil --pkgs --volume /
What files does this package install?
pkgutil --files com.vmware.fusion
Verify file permissions and owner/group is the same as listed in the package BOM in /private/var/db/receipts/ (actually calls repair_packages). See the end of this post for how to verify the file content.
pkgutil --verify com.vmware.fusion
There isn't any uninstall functionality on OS X, this command just drops the metadata out of the receipts directory, which is handy if you want to re-install:
pkgutil --forget com.vmware.fusion
pkgutil has a code signing check feature, but it looks like it is broken or doesn't work how I expected it to:
$ pkgutil --check-signature
Package does not exist:
$ pkgutil --check-signature /Applications/
Package "Safari":
   Status: no signature
$ codesign -d -vvv /Applications/
Format=bundle with Mach-O universal (i386 x86_64)
CodeDirectory v=20100 size=185 flags=0x0(none) hashes=3+3 location=embedded
Hash type=sha1 size=20
Signature size=4064
Authority=Software Signing
Authority=Apple Code Signing Certification Authority
Authority=Apple Root CA
Info.plist entries=37
Sealed Resources rules=11 files=393
Internal requirements count=1 size=108

PKG files

PKG files are just XAR files that contain a bunch of metadata files and the app itself inside a zipped cpio.

To extract the files on OS X, use (note tempdir will be created and can't exist prior to running the command):
pkgutil --expand my.pkg tempdir
Here is a manual unpacking sequence (if you just want metadata use the pkgutil commands to avoid all this unpacking). tar understands xar on OS X but on linux you'll need to install the xar package and use 'xar -xf helloworld.pkg':
$ tar zxvf helloworld.pkg 
x com.totallylegit.helloworld.pkg
x com.totallylegit.helloworld.pkg/Bom
x com.totallylegit.helloworld.pkg/Payload
x com.totallylegit.helloworld.pkg/PackageInfo
x Distribution

$ cd com.totallylegit.helloworld.pkg/
$ ls
Bom  PackageInfo Payload
$ mv Payload Payload.gz
$ gunzip Payload
$ cpio -iv < Payload
87 blocks

BOM files

Use lsbom to inspect bill of materials files (note apple says "The files and directories where receipts are stored are subject to change. Always use pkgutil to query or modify them"). These options are more readable than the defaults:
$ lsbom -p MUGsf /private/var/db/receipts/
drwxr-xr-x  root admin  .
drwxrwxr-x  root admin  ./Applications
-rwxr-xr-x  root admin 82 ./Applications/._VMware
While pkgutil/repair_packages could check file content hasn't changed by calculating the CRC32 and comparing that with the one in the BOM, it doesn't. It would be fairly simple to do. The BOM content for a simple package looks like this (path, octal mode, UID/GID, size, CRC32):
$ lsbom Bom 
. 0 0/0
./ 40755 0/0
./ 40755 0/0
./ 100644 0/0 1429 3178638052
./ 40755 0/0
./ 100755 0/0 13488 1649029420
./ 100644 0/0 8 742937289
./ 40755 0/0
./ 40755 0/0
./ 100644 0/0 436 2072274354
./ 100644 0/0 92 2769355950
./ 100644 0/0 27463 4224082203
and the checksum can be calculated with cksum which prints the size in bytes and the CRC32:
$ cksum helloworld 
1649029420 13488 helloworld


On installation the package app directory is copied to the installation dir (usually /Applications/) and the BOM is written with a plist of installation metadata to the Receipts directory:
$ ls -1 /private/var/db/receipts/com.vmware*


mahasiswa teladan said...

hi...Im student from Informatics engineering nice article,
thanks for sharing :)

Anonymous said...

Hi. Thanks for putting this online. I used the "list all installed packages info" to *finally* successfully install two versions of R. (Knew I needed to forget what I had, but couldn't figure out what that was.)

Anonymous said...

thx a lot
about unpack PKG files can add:
pkgutil --expand PKG DIR

Unknown said...

Excellent read, thank you.