AppImage Format V3 (Proposal) ============================= The image format determines how an AppImage is represented on disk. With the this proposal we intent to correct some of the issues we found in previous versions and formalize all the core components of involved. # Design goals - [x] Fix issues with the ELF specification - [x] Allow multiple payload formats and compresion algorithms - [x] Allow multiple signatures - [x] Allow multiple update sources - [x] Allow variable set of resources/metadata # Speficiation ## Bundle An AppImage bundle must by composed by 4 data chunks: runtime, payload, resources, and signatures. Each has an special role and format which is described below. **File overview** ``` +--------------------------------+ | Runtime (ELF execytable) | |................................| |ELF HEADER | |PROGRAM HEADER | |ELF sections | | <- APPIMAGE HEADER at 0x400 | +--------------------------------+ | PAYLOAD (File System) | +--------------------------------+ | Resources (bson data chunk) | +--------------------------------+ | Signatures (bson data chunk) | +--------------------------------+ ``` ### Runtime * **MUST** be a valid [ELF](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) executable * **MUST** have an section named [.appimage](#APPIMAGE-SECTION-STRUCT). * On execution: * **MUST** launch the binary located at `./AppRun` inside [Payload File System](#Payload). * **MUST** forward the input arguments to the child process. * **MUST** forward the environment to the child process with the exception of the AppImage reserved variables. * **MUST** set path where the Payload is available using the APPDIR environment variable. * **MUST** set path to the itself using the APPIMAGE environment variable. * **MUST** support the following [execution options](#Execution-Options) which will be profided in form of environment variables #### APPIMAGE SECTION STRUCT * **MUST** be named '.appimage' * **MUST** be located at offset 0x400 * **MUST** have the following structure: ``` 0x400 : "AppImageFile" ( magic bytes ) 0x40C : 16 bytes unsigned int ( header revision ) 0x40E : 16 bytes unsigned int ( payload format ) 0x410 : 64 bytes unsigned int ( payload offset ) 0x418 : 64 bytes unsigned int ( metadata offset ) 0x420 : 64 bytes unsigned int ( signatures offset ) ``` #### Execution Options - APPIMAGE_OPT_FILE: speficy an alternate file bundle to be used - APPIMAGE_OPT_MOUNT_POINT: specify a mount point where the payload will be made accessible - APPIMAGE_OPT_PRINT_METADATA: print the json contained in the resources and signatures sections mixed. ### Payload * **MUST** contain a file named AppRun in its root directory * **MAY** contain [desktop files](https://specifications.freedesktop.org/desktop-entry-spec/latest/) at `usr/share/applications` or `share/applications` * **MAY** contain [icon themes](https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html) at `usr/share/icons` or `share/icons` * **MAY** contain [appstream files](https://www.freedesktop.org/wiki/Distributions/AppStream/) at `usr/share/appdata` or `share/appdata` #### AppRun Entry point of the bundle. * **MUST** execute the main applicatoin binary * **MAY** accept specifying a different application binary using *APPRUN_EXEC* environment * **MAY** Setup the runtime environment ##### APPRUN_EXEC Environment variable to control wich binary gets executed when an AppImage executed. It **MUST** start with a binary path and **MAY** be followed by a set of arguments. The execution arguments will be appended to this string. Example: - appimage invocation: `env APPRUN_EXEC="usr/bin/fancy_open --with-colors" ./myapp.AppImage --do-something` - apprun call: `usr/bin/fancy_open --with-colors --do-something` ### Metadata BSon formated data blob. Which may contain arbitratry data. * **MAY** contain an entry name "update-information" with the update sources link * **MUST** not contain entries following names: * `signatures` #### Update Sources Update sources information will be included inside the metadata section using the entry named `sources`. This will be an array of objects of type `source`. Heach `source` object will contain a mandatory entry named `type` and others entries that may vary depending on the type. ##### Know source types ###### zsync Fields: - type: literal `zsync` - url: url, the url to the latest zsync file published ###### github release zsync Retrieve the zsync file and the binary file from Github Releases using the zsync method for delta downloads. Fields: - type: literal `github-releases-zsync` - username: username who owns the github repo - repo: repo name - release: release name to use or `empty` to fetch the latest - file: file name of the zsync file wilcards may be used **MORE TO BE DEFINED** ##### Example sources entry { ... 'sources': [ { 'type': 'zsync', 'url' : 'https://miapp/download/latest.zsync' }, { 'type': 'github-releases-zsync', 'username': 'AppImageCrafters', 'repo': 'appimage-type3-demo', 'release': 'latest', 'file': '*x86_64.AppImage' }, ... ] ... } ``` ### Signatures BSon formated data blob used to store the bundle signatures. Is not part of the metadata section to allow this to also be included while signind the bundle. * **MUST** contain an entry named `signatures` with a array of objects * the signature objects **MUST** have the following structure keys: * `method` method used to sign the bundle * `keyid` key id used to sign the bundle * `data` the signature itself Implementation ============== The following projects contain implementions of the propused specificaion, those are **not ready for production**. * Runtime: https://github.com/AppImageCrafters/appimage-runtime * Creation tool: https://github.com/AppImageCrafters/appimage-builder/tree/feat/type_3_format * Signature verification: https://github.com/AppImageCrafters/appimage-tools Notes ==== - The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt).