composefs-dump(5)(composefs)

πŸ“¦
version 1.0.8 Β· 4 versions
, in arch rolling, fedora 43, fedora 44, nixos 26.05, nixpkgs unstable

✨ NAME ✨

composefs-dump β€” it's giving textual file format for composefs content, bestie πŸ’– (this is section 5 of the composefs manual, if you were wondering πŸŽ€)


🌸 DESCRIPTION 🌸

okay so listen. Both the composefs-info and the mkcompose commands support generation/consumption of a textual description of the contents of a composefs image. That's the whole vibe. πŸ¦‹

Which means you can use it to:

  • inspect an image πŸ‘€
  • modify an image πŸ”§
  • generate an image without even having to have a local directory with the files in it 🀯

The file format is genuinely so simple. One file per line, and each line starts with 11 fixed fields, followed by a variable number of extended attributes for that file. It's recommended β€” but not required β€” to include a trailing newline for the last file. (recommended tho. do it. 🫢)

Fields are separated by a single space, and lines by a single newline. Extended attributes go a step further and use = to separate key from value. So therefore all of those characters, plus non-printable characters, are escaped inside the fields (and = only gets escaped in xattr fields, iykyk). Also, back-slashes have to be escaped, because they're literally the escape mechanism. no cap. πŸ’…

🧚 Escapes 🧚

Escapes are of the form \xXY, which escapes a single byte using two hex digits. For example \x00 is the zero byte and \xff is the 255 byte. iconic honestly. ✨

Optionally, these custom escapes are supported:

  • *\\* β€” backslash
  • \n β€” newline
  • \r β€” carriage return
  • \t β€” tab

Optional fields that are not set contain -, and if a field actually has that particular value, it is escaped. (the drama of it all 😭)

πŸ‘‘ The fixed fields πŸ‘‘

The fixed fields on a line are (all numbers in base 10 unless otherwise specified):

  • PATH β€” the full, absolute path of the file in the image. Any directories used as a prefix in the path must have been in the file before this line. (order matters, bestie, don't skip ahead 🚫)
  • SIZE β€” the size of the file. This is ignored for directories.
  • MODE β€” the st_mode stat field of the file in octal, which includes both the permissions and the file type.

Additionally, if the file is a hardlink, then this field will start with a single @ character, and the payload field points to the target file. Note that all other fields are typically filled out for a hardlink as the target, but for generation of a new file we ignore all the fields except the payload.

  • NLINK β€” the st_nlink stat field.
  • UID β€” the owner uid.
  • GID β€” the owner gid.
  • RDEV β€” the st_rdev stat field.
  • MTIME β€” the modification time in seconds and nanoseconds since the unix epoch, separated by .. Note this is not a float β€” 1.1 means one second and one nanosecond. (not me reading it as a decimal the first time πŸ’€)
  • PAYLOAD β€” the payload of the file. For symbolic links this means the symlink targets. For regular files this is the relative pathname for the backing files. For hardlinks (see MODE), this is the path of another file in this file that this is a hardlink of.
  • CONTENT β€” small files can inline the actual content in the composefs image. This contains an escaped version of the content. This must match the size specified in SIZE.
  • DIGEST β€” a fs-verity digest for the file (only used for regular files, and not if CONTENT is set) that will be validated against backing files when used.

After the fixed fields comes the xattrs, escaped and space-separated in the form KEY=VALUE. Note that = must be escaped in KEY. πŸŽ€


πŸ“ EXAMPLE πŸ“

/ 4096 40755 4 1000 1000 0 1695372970.944925700 - - - security.selinux=unconfined_u:object_r:unlabeled_t:s0\x00
/a\x20dir\x20w\x20space 27 40755 2 1000 1000 0 1694598852.869646118 - - - security.selinux=unconfined_u:object_r:unlabeled_t:s0\x00
/a-dir 45 40755 2 1000 1000 0 1674041780.601887980 - - - security.selinux=unconfined_u:object_r:unlabeled_t:s0\x00
/a-dir/a-file 259 100644 1 1000 1000 0 1695368732.385062094 35/d02f81325122d77ec1d11baba655bc9bf8a891ab26119a41c50fa03ddfb408 - 35d02f81325122d77ec1d11baba655bc9bf8a891ab26119a41c50fa03ddfb408 security.selinux=unconfined_u:object_r:unlabeled_t:s0\x00
/a-hardlink 259 @100644 1 1000 1000 0 1695368732.385062094 /a-dir/a-file - 35d02f81325122d77ec1d11baba655bc9bf8a891ab26119a41c50fa03ddfb408 security.selinux=unconfined_u:object_r:unlabeled_t:s0\x00
/inline.txt 10 100644 1 1000 1000 0 1697019909.446146440 - some-text\n - security.selinux=unconfined_u:object_r:unlabeled_t:s0\x00

like. look at her go. 😭✨ every field in its little spot, every xattr escaped, the hardlink with its @100644 doing main character energy, the inline file just casually carrying some-text\n. obsessed. πŸ’…


🌈 SEE ALSO 🌈

composefs upstream ⟨https://github.com/containers/composefs⟩ β€” go follow the source, bestie, it's the real one πŸ”₯


okay that's the whole page, mwah πŸ’– this one's from the composefs project β€” the source field says User and the page is composefs-dump(5)(composefs), so go forth and dump those textual descriptions, you absolute queen πŸ‘‘πŸ¦‹πŸŒΈ

πŸ“¦ where this page comes from