Skip to content

Questions about tpxz / file index format #96

@Rogdham

Description

@Rogdham

Hello,

I am really interested in the “tpxz” format, i.e. indexed tar.xz format used by pixz.

I am planning on implementing a Python library that would support that format, and I have written below a few questions, I hope that you will have some time to answer them @vasi!

0. Popularity of tpxz

Is the format really named “tpxz”? What does that stand for?

Do you have any insights of how much tpxz format is used?

Do you know if reader or writers of that format have been written in other languages?

I think it is the main selling point of pixz (out of the one listed in the readme anyways), now that xz supports multi-threading itself. Do you know if people still use pixz just for the tpxz feature?

1. Structure of pixz's tar file index

Here is my understanding of the file index, did I get it right?

file index:
+-+-+-+-+-+-+-+-+==============+     +==============+-+-+-+-+-+-+-+-+-+
|  index magic  | index record | ... | index record |  index footer   |
+-+-+-+-+-+-+-+-+==============+     +==============+-+-+-+-+-+-+-+-+-+


index record:
+==========+-----------+-+-+-+-+-+-+-+-+
| filename | null byte |     offset    |
+==========+-----------+-+-+-+-+-+-+-+-+


index footer:
+-----------+-+-+-+-+-+-+-+-+
| null byte |     offset    |
+-----------+-+-+-+-+-+-+-+-+

Where:

  • index magic (8 bytes): the constant \xa6L2.\xd6\x14\xae\xdb

  • index record is defined as follows:

    • filename: name of the file in the index (without the null byte), cannot be empty
    • offset (8 bytes): 64-bits integer packed as low-endian, pointing to the tar header block
  • index footer is defined as follows:

    • offset (8 bytes): 64-bits integer packed as low-endian, pointing to the start of the index magic

2. Position of file index

The file index is appended just after the tar data. No padding is added, right?

Also, when reading the file index, do you just do the following?

  1. go to 8 bytes before the end of file
  2. read the 8 bytes as 64-bit integer
  3. seek to that offset
  4. you are now at the beginning of the file index

An alternative would be to go to the start of the last XZ block, but it may be less reliable (see question 6b).

3. File index alone in one XZ block?

I noticed that the whole file index is alone inside the last xz block. It could have been appended to the tar data in the previous block. Is there any reason for that? Is it mandatory?

I first thought that maybe this would allow you to drop it easily to write more data to the tar archive, but it seems not to be the case as you would need to read the last block of tar data anyways.

4. Null byte at the start of the index footer

I noticed that the null byte at the end of the index footer is used in the code as a marker to stop the list of index records.

However, I feel like it would not be really needed, as you know that you reached the end of the index record when you are at the end of the stream minus 9 bytes.

It's not really a question, but just to make sure that I did not miss anything.

5. Filenames occurring several times in archive

Nothing special happens here, each occurrence is stored in the index file; pixz -l will list them all, in the same order as they appear in the tar:

$ ### example file ###
$ base64 -d << EOF > a.tpxz
/Td6WFoAAAFpIt42A8B5gFAhARYAAAAAm+b72eAn/wBxXQAwi4qHxA7yl6T4dT3Fqe3Zl6mYJcaN
Zum5yTtyoaU5BF/n144YGFDDP0Cb9DMh0wr9fnpMBYHquIISbxNF/67v2icGv7eRoa7Pyl2xY1uQ
vRZgKlQ7XtUBsswq41/oV9JRQe9wRnv8PXhJ2s1J1EsAAAAAAACbWW+eAgAhARYAAAB0L+Wj4AA6
ACBdAFMTAkLm8KfZ0WA6AnzzrMxoWqk8HuB5cDMJi0pKC7XAAA4u0rgAAo0BgFA4O6Itgko+MA2L
AgAAAAABWVo=
EOF
$ sha1sum a.tpxz
d9e6a30ba77216bd7613ba46bf5586819a5758a6  a.tpxz

$ pixz -l a.tpxz
a.txt
b.txt
a.txt

$ # here yo can see the offsets are in order: 0x0, 0x400, 0x800
$ unxz < a.tpxz | (head -c 10240 >/dev/null; hexdump -C) # only show file index
00000000  a6 4c 32 2e d6 14 ae db  61 2e 74 78 74 00 00 00  |.L2.....a.txt...|
00000010  00 00 00 00 00 00 62 2e  74 78 74 00 00 04 00 00  |......b.txt.....|
00000020  00 00 00 00 61 2e 74 78  74 00 00 08 00 00 00 00  |....a.txt.......|
00000030  00 00 00 00 28 00 00 00  00 00 00                 |....(......|
0000003b

It's not really a question, but just to make sure that I did not miss anything.

6a. Xz block size

It seems that pixz creates an xz block every 0x1000000 bytes of input. It that always the case? How would pixz behave reading xz blocks of various sizes?

6b. Xz file index block size

Also, if there are many files in the tar, is the pixz file index could be greater than 0x1000000 bytes: would it be stored in more than one block?

6c. Synchronizing xz block size with tar files

When adding a tar file (including tar header, etc.), if there is not enough space left in the current xz block, we could move to a new xz block before adding that tar file.

If we want to extract only that file later, this would allow us to read only one block instead of two (or to be precise one less block in total).

What are your thoughts on that optimization? Would such an tpxz archive be fully compatible with pixz (i.e. would pixz read that kind of archive happily)?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions