Normal view

There are new articles available, click to refresh the page.
Before yesterdayMain stream

A brief history of bundles

By: hoakley
15 February 2025 at 16:00

In the elegant simplicity of Classic Mac OS, applications were intended to be single files with much of their contents stored in their resource fork, where they kept all the paraphernalia they required, from code resources to windows, icons and dialogs.

prefsresedit

This is QuarkXPress version 4.11 from around 2000, its resources displayed in the resource editor ResEdit. The app icons shown are stored in a resource of type BNDL, a ‘bundle’, but not in the later sense of the term.

In this respect, as in many others, Mac OS X abandoned its Mac past in favour of what had been developed in NeXTSTEP, here a structured directory termed a bundle. These were primarily used for constructs that the user was intended to see as a single item, usually containing executable code and its resources, forming applications, frameworks and plug-ins.

Early bundles

At first, there were two types of bundle in use. Versioned bundles consisted of a file containing executable code, together with a directory containing resources and more directories with further resources, without any Contents directory or top-level property list. New-style bundles contained a minimum of a top-level directory named Contents, and inside that a property list named Info.plist, as continues today. Some implementations of the new-style bundle also contained a file named PkgInfo containing type and creator information that had originated in Classic Mac OS; although apparently not mandatory, PkgInfo has survived to the present in app bundles.

The information property list Info.plist contained key-value pairs in XML format, for attributes such as:

  • bundle name,
  • name of bundle executable,
  • version,
  • type and creator codes, inherited from Classic Mac OS and duplicating those in PkgInfo,
  • app and document icons,
  • other metadata.

Current bundles are direct descendants of those new-style bundles.

Fat apps with support for both Classic Mac OS and Mac OS X had a more complex structure. Inside their Contents directory, they had the following:

  • MacOSClassic directory, containing the Classic version of their executable code,
  • MacOS directory, containing the Mac OS X version of their executable code,
  • Info.plist file,
  • Resources directory, containing resources such as icons, images, and directories of localised resources such as nibs and strings,
  • Other directories such as Frameworks, PlugIns, SharedFrameworks and SharedSupport as necessary.

To enable that to run in Mac OS 9, alongside the Contents directory was an alias to the executable code in Contents/MacOSClassic.

The Finder recognised a directory as a bundle and treated it as a single entity if:

  • the directory name had an extension for a standard bundle type, such as .app, .bundle, .framework, .plugin, .kext and others, or
  • the directory name had an extension identifying it as a type set as a bundle (or package), such as .rtfd, or
  • the directory had its Finder bundle bit set.

Frameworks are an exception to the general rule that the Finder displays bundles as single items, as they are still shown as folders. However, the original reason given by Apple for this, “so that you can browse their header files”, no longer applies.

Packages

By 2005, Apple was drawing a distinction between bundles with the formal structure given above, including the Info.plist inside a Contents directory, and other directories presented to the user as a single item, such as RTFD documents, that had different structures and are strictly termed packages. For example, the Rich Text Format Directory (RTFD) favoured by Apple consists of:

  • Contents, a directory containing a PkgInfo file
  • files containing graphics to be included within the documents
  • TXT.rtf, a Rich Text Format file containing the styled text.

This is closer to the versioned bundles of early Mac OS X. Currently, there are distinct UTI types for com.apple.bundle and com.apple.package, with bundles conforming to both, but packages only to the latter. Unfortunately, this distinction between bundles and packages has largely fallen into disuse because of the name collision with Installer packages.

More recently, in its iWork documents, Apple has moved away from plain document packages or bundles to a custom package in a Zip-compressed archive, for example in .pages documents, which still conform to com.apple.package although they can’t be opened in the Finder. Compression has also become popular with space-inefficient formats such as XML.

Signatures

The introduction of code signing in 2007 brought the requirement to store signature information including code directory hashes (CDHashes) inside the app bundle. This has been implemented using an additional directory, _CodeSignature, containing a CodeResources file. Single-file command tools can instead have their signature embedded in their binary.

Most recently, in 2018, notarization has added the requirement to accommodate its ‘ticket’, which is ‘stapled’ as another CodeResources file inside the Contents directory. However, stapling isn’t required, as notarization can be verified by looking up the CDHashes with Apple’s online service in iCloud. There’s also still no way to staple a notarization ticket to a single-file binary.

Platform-specific code

The transition from Classic Mac OS to Mac OS X used separate directories for executable code within app bundles, with that named MacOS containing code to be run in Mac OS X. When the Mac architecture changed from PowerPC to Intel, from 32-bit to 64-bit, and again from Intel to Arm, app bundles have continued to use the MacOS directory, with executable code for each supported architecture being saved within each file.

Key dates

  • 1984 single-file application with resource fork, type and creator codes
  • 2001 Mac OS X 10.0 Cheetah, with versioned and new-style bundles, PkgInfo for type and creator codes, Info.plist in new-style bundles
  • 2005 bundles and packages
  • 2007 Mac OS X 10.5 Leopard, _CodeSignature directory for code signatures
  • 2018 macOS 10.14 Mojave, CodeResources for notarization ticket.

References

Apple’s Bundle Programming Guide, last updated to 2017
Apple, Inside Mac OS X, System Overview, July 2002, PDF no longer available online.

Add custom file and folder icons in Sequoia

By: hoakley
7 February 2025 at 15:30

Adding your own custom icons to files and folders goes back a long way, to Classic Mac OS where it was widespread. With all the changes brought in recent versions of macOS, particularly Sequoia’s changes to Quick Look, this article explains how you can still replace standard icons with your own.

Add a custom icon

You can copy an icon already used by an app, file or folder on your Mac by selecting it and using the Finder’s Get Info command. In that dialog, select the small icon at the top left of the window, and copy it.

If you want to modify or design your own icons, a good graphics editor like GraphicConverter is fine. Work with a PNG image with a transparent background and dimensions of 1024 x 1024 pixels. When it’s ready, select all and copy it.

To add your custom icon to an app, file or folder, select it in the Finder, open the Get Info dialog, select its current icon at the top left, and paste in your replacement.

Where it doesn’t work

There are some items that you can’t add a custom icon to. Any app, file or folder in the Signed System Volume can’t be modified in any way, and those in folders where you don’t have write access won’t work either. If you really wanted to display one of those with a custom icon, the only way to do that is to create an alias, and paste your replacement icon into Get Info for that alias.

How it works

When you add a custom icon to a file, the icon is converted into a traditional resource of icns type, and written to an extended attribute of type com.apple.ResourceFork attached to that file. That xattr is the modern equivalent of the old resource fork used in Classic Mac OS. It’s also surprisingly large, typically around 330 KB, which can bring its own problems as described later.

When you add a custom icon to a folder, including one that’s enclosing a bundle like an app or RTFD document, it isn’t added as an extended attribute to the folder, but is added to a hidden file named Icon? (the last character isn’t really a ? but is actually Carriage Return, UTF-8 0D) inside that folder. Normally, icons to be displayed for an app are saved as an AppIcon.icns file inside the Resources folder within the app bundle, but modifying that could break the app’s signature. A custom icon dodges that by being saved outside the bundle itself, and in an extended attribute rather than as data.

Aliases are complicated

Add a custom icon to a folder, then make a Finder alias to it. What you’ll then see is a muddle.

In the Get Info dialog, the Preview shows the custom icon, but the icon displayed in the Finder is the default folder with an alias arrow superimposed. To get the alias to display your custom icon, you have to Get Info on the alias and paste that icon into the top left.

This rule, that the Preview shows the icon associated with the original, while the regular icon shown is that for the alias itself, extends to bundled apps. As you can’t add a custom icon to a bundled app, because its bundle can’t be changed in any way, one workaround might be to create an alias to the app and add your custom icon to that alias.

What then happens is that your alias displays its custom icon, but the Preview shown is the original app icon that you can’t change.

The biggest problem with attaching custom icons to aliases comes when the alias needs to be remade, for example by my app Alisma. The remade alias is then likely to lose its custom icon, which you’ll have to paste in again.

iCloud folders are complicated too

Just when you think you’ve understood how custom icons work, you try using them in iCloud Drive, and discover that there are some further subtleties.

iCloud Drive doesn’t like storing Icon? files in the cloud, and even if it would do so, it couldn’t upload the crucial com.apple.ResourceFork extended attribute, as iCloud doesn’t like them. Furthermore, the standard custom folder icons that you see in iCloud Drive aren’t created by the same mechanism, and can’t be overruled by your own icons.

The end result is that, while you can add custom icons to plain folders in iCloud Drive, the only client that will see them is the Mac that customised them in the first place, as that’s the one with the Icon? file and its extended attribute. Other Macs and devices won’t see the custom icon, unless of course you add it to the same folder on them. The same goes for custom icons on files.

In the recent past, custom icons have been unreliable in iCloud Drive. That was because, when the folder was evicted from local storage, the hidden Icon? file was sometimes lost, and couldn’t be replaced when the contents of the folder were downloaded again. That appears to have been fixed recently, and they should now be more stable in macOS Sequoia.

Happy customising!

❌
❌