Skip to content

Commit 37ec118

Browse files
committed
layer: Require ustar (IEEE Std 1003.1-2013)
The idea with a spec like this is to define behavior so that different implementations can interoperate reliably. When there is an interop problem betweem implementations A and B, it should be clear from the spec whether implementation A is broken, implementation B is broken, or the spec is insufficiently clear. For example, pax defines 'g' and 'x' typeflags [1] that aren't part of the older ustar (originally defined in IEEE Std 1003.1-1988) [2]. Before this commit, if implementation A produced a layer with a 'g' or 'x' typeflag and implementation B died unpacking it, it was unclear whose fault it was. With this commit, it is clearly A's fault (because it is using features not defined for ustar). If implementation A had produces a layer with an '2' typeflag (which ustar specifies for symlinks) and implementation B died unpacking it, it is B's fault. If implementation A had produces a layer with an 'S' typeflag (which GNU uses for sparse files [3]) and implementation B died unpacking it, it is neither party's fault, because ustar explicitly makes those values implementation-defined. Interop around them is up to out of band communication between the layer author and layer consumer, and is not covered by this spec. The previous "File Types" section listed sockets, but the ustar spec has: Attempts to archive a socket using ustar interchange format shall produce a diagnostic message. And I see no socket entry in Go's set of typeflag constants [4], so I'm not sure how they were supported before. Go has supported pax since v1.1 [5,6], and pax lets you do things (like having symlink targets longer than 100 characters). But we're avoiding requiring support for PAX because of name-recognition issues [7]. [1]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html#tag_20_92_13_02 [2]: https://github.com/libarchive/libarchive/wiki/ManPageTar5#POSIX_ustar_Archives [3]: https://github.com/libarchive/libarchive/wiki/ManPageTar5#gnu-tar-archives [4]: https://golang.org/pkg/archive/tar/#pkg-constants [5]: https://codereview.appspot.com/6700047 [6]: golang/go@1068279 [7]: #342 (comment) Signed-off-by: W. Trevor King <[email protected]>
1 parent bdc1fde commit 37ec118

File tree

1 file changed

+15
-72
lines changed

1 file changed

+15
-72
lines changed

layer.md

Lines changed: 15 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,14 @@ This document will use a concrete example to illustrate how to create and consum
66

77
## Distributable Format
88

9-
Layer Changesets for the [mediatype](./media-types.md) `application/vnd.oci.image.layer.tar+gzip` MUST be packaged in a [tar archive][tar-archive] compressed with [gzip][gzip].
10-
Layer Changesets for the [mediatype](./media-types.md) `application/vnd.oci.image.layer.tar+gzip` MUST NOT include duplicate entries for file paths in the resulting [tar archive][tar-archive].
9+
Layer changesets have the [media type](media-types.md) `application/vnd.oci.image.layer.tar+gzip`.
10+
Layer changesets SHOULD be packaged in the ustar interchange format, as [specified by IEEE Std 1003.1-2013][ustar], and MUST be compressed using gzip, as [specified by RFC 1952][rfc1952].
11+
Layer changesets MUST NOT include duplicate entries for target paths (the value computed from `prefix` and `name` in the ustar header).
12+
13+
Implementations consuming layer changesets MUST be able to unpack both gzip and ustar.
14+
Portable layers SHOULD NOT use features that [ustar][] leaves unspecified, undefined, or implementation-defined.
15+
For example, pax [extends ustar by specifying `typeflag` values `g` and `x`][pax-header], so support for unpacking such entries may be mixed.
16+
[Sparse files](https://en.wikipedia.org/wiki/Sparse_file) SHOULD NOT be used because they [are a GNU extension][tar.5-gnu].
1117

1218
## Change Types
1319

@@ -21,69 +27,6 @@ Additions and Modifications are represented the same in the changeset tar archiv
2127

2228
Removals are represented using "[whiteout](#whiteouts)" file entries (See [Representing Changes](#representing-changes)).
2329

24-
### File Types
25-
26-
Throughout this document section, the use of word "files" or "entries" includes:
27-
28-
* regular files
29-
* directories
30-
* sockets
31-
* symbolic links
32-
* block devices
33-
* character devices
34-
* FIFOs
35-
36-
### File Attributes
37-
38-
Where supported, MUST include file attributes for Additions and Modifications include:
39-
40-
* Modification Time (`mtime`)
41-
* User ID (`uid`)
42-
* User Name (`uname`) *secondary to `uid`*
43-
* Group ID (`gid `)
44-
* Group Name (`gname`) *secondary to `gid`*
45-
* Mode (`mode`)
46-
* Extended Attributes (`xattrs`)
47-
* Symlink reference (`linkname` + symbolic link type)
48-
* [Hardlink](#hardlinks) reference (`linkname`)
49-
50-
[Sparse files](https://en.wikipedia.org/wiki/Sparse_file) SHOULD NOT be used because they lack consistent support across tar implementations.
51-
52-
#### Hardlinks
53-
54-
Hardlinks are a [POSIX concept](http://pubs.opengroup.org/onlinepubs/9699919799/functions/link.html) for having one or more directory entries for the same file on the same device.
55-
Not all filesystems support hardlinks (e.g. [FAT](https://en.wikipedia.org/wiki/File_Allocation_Table)).
56-
57-
Hardlinks are possible with all [file types](#file-types) except `directories`.
58-
Non-directory files are considered "hardlinked" when their link count is greater than 1.
59-
Hardlinked files are on a same device (i.e. comparing Major:Minor pair) and have the same inode.
60-
The corresponding files that share the link with the > 1 linkcount may be outside the directory that the changeset is being produced from, in which case the `linkname` is not recorded in the changeset.
61-
62-
Hardlinks are stored in a tar archive with type of a `1` char, per the [GNU Basic Tar Format][gnu-tar-standard] and [libarchive tar(5)][libarchive-tar].
63-
64-
While approaches to deriving new or changed hardlinks may vary, a possible approach is:
65-
66-
```
67-
SET LinkMap to map[< Major:Minor String >]map[< inode integer >]< path string >
68-
SET LinkNames to map[< src path string >]< dest path string >
69-
FOR each path in root path
70-
IF path type is directory
71-
CONTINUE
72-
ENDIF
73-
SET filestat to stat(path)
74-
IF filestat num of links == 1
75-
CONTINUE
76-
ENDIF
77-
IF LinkMap[filestat device][filestat inode] is not empty
78-
SET LinkNames[path] to LinkMap[filestat device][filestat inode]
79-
ELSE
80-
SET LinkMap[filestat device][filestat inode] to path
81-
ENDIF
82-
END FOR
83-
```
84-
85-
With this approach, the link map and links names of a directory could be compared against that of another directory to derive additions and changes to hardlinks.
86-
8730
## Creating
8831

8932
### Initial Root Filesystem
@@ -112,7 +55,7 @@ rootfs-c9d-v1/
11255
my-app-tools
11356
```
11457

115-
The `rootfs-c9d-v1` directory is then created as a plain [tar archive][tar-archive] with relative path to `rootfs-c9d-v1`.
58+
The `rootfs-c9d-v1` directory is then created as a plain [tar archive][ustar] with paths relative to `rootfs-c9d-v1`.
11659
Entries for the following files:
11760

11861
```
@@ -127,7 +70,7 @@ Entries for the following files:
12770
### Populate a Comparison Filesystem
12871

12972
Create a new directory and initialize it with a copy or snapshot of the prior root filesystem.
130-
Example commands that can preserve [file attributes](#file-attributes) to make this copy are:
73+
Example commands that can preserve [file attributes][ustar] to make this copy are:
13174
* [cp(1)](http://linux.die.net/man/1/cp): `cp -a rootfs-c9d-v1/ rootfs-c9d-v1.s1/`
13275
* [rsync(1)](http://linux.die.net/man/1/rsync): `rsync -aHAX rootfs-c9d-v1/ rootfs-c9d-v1.s1/`
13376
* [tar(1)](http://linux.die.net/man/1/tar): `mkdir rootfs-c9d-v1.s1 && tar --acls --xattrs -C rootfs-c9d-v1/ -c . | tar -C rootfs-c9d-v1.s1/ --acls --xattrs -x` (including `--selinux` where supported)
@@ -188,7 +131,7 @@ This reflects the removal of `/etc/my-app-config` and creation of a file and dir
188131

189132
### Representing Changes
190133

191-
A [tar archive][tar-archive] is then created which contains *only* this changeset:
134+
A [tar archive][ustar] is then created which contains *only* this changeset:
192135

193136
- Added and modified files and directories in their entirety
194137
- Deleted files or directories marked with a [whiteout file](#whiteouts)
@@ -315,7 +258,7 @@ Layers that have these restrictions SHOULD be tagged with an alternative mediaty
315258
[Descriptors](descriptor.md) referencing these layers MAY include `urls` for downloading these layers.
316259
It is implementation-defined whether or not implementations upload layers tagged with this media type.
317260

318-
[libarchive-tar]: https://github.com/libarchive/libarchive/wiki/ManPageTar5#POSIX_ustar_Archives
319-
[gnu-tar-standard]: http://www.gnu.org/software/tar/manual/html_node/Standard.html
320-
[tar-archive]: https://en.wikipedia.org/wiki/Tar_(computing)
321-
[gzip]: http://www.zlib.org/rfc-gzip.html
261+
[ustar]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html#tag_20_92_13_06
262+
[pax-header]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html#tag_20_92_13_02
263+
[rfc1952]: https://tools.ietf.org/html/rfc1952
264+
[tar.5-gnu]: https://github.com/libarchive/libarchive/wiki/ManPageTar5#gnu-tar-archives

0 commit comments

Comments
 (0)