[PATCH v2] erofs-utils: tar: support archives without end-of-archive entry
Ivan Mikheykin
ivan.mikheykin at flant.com
Thu Oct 2 03:13:41 AEST 2025
Tar standard https://www.gnu.org/software/tar/manual/html_node/Standard.html
says that archive "terminated by an end-of-archive entry,
which consists of two 512 blocks of zero bytes".
Is also says:
"A reasonable system should write such end-of-file marker at the end
of an archive, but must not assume that such a block exists when
reading an archive. In particular, GNU tar does not treat missing
end-of-file marker as an error and silently ignores the fact."
It is rare for erofs to encounter such problem, as images are mostly
built with docker or buildah. But if you create image using tar library
in Golang directly uploading layers to registry, you'll get tar layers
without end-of-archive block. Running containers with such images will
trigger this error during extraction:
mkfs.erofs --tar=f --aufs --quiet -Enoinline_data test.erofs test-no-end.tar
<E> erofs: failed to read header block @ 42496
<E> erofs: Could not format the device : [Error 5] Input/output error
This patch fixes the problem by assuming that eof is equal to the end-of-archive.
Reproducible tar without end-of-archive (base64-encoded gzipped blob):
H4sICKVi2mgAA3Rlc3QtMTAtMi1ibG9ja3MudGFyAAtzDQr29PdjoCUwAAIzExMwbW5mCqYN
jQzANBgYGTEYmhqYmpqamRoaGTMYGBqaGJkyKBjQ1FVQUFpcklikoMCQkpmYll9ahFNdYkpu
Zh49HERfYKhnoWdowGVkYGSqa2Cua2jKNdAuGgX0BADwFwqsAAQAAA==
Also, add warning about non-conformant tar layers:
mkfs.erofs --tar=f --aufs -Enoinline_data test.erofs test-no-end.tar
mkfs.erofs 1.8.10-g0a2bc574-dirty
<W> erofs: unexpected end of file @ 1024 (may be non-standard tar without end of archive zeros)
Build completed.
...
Signed-off-by: Ivan Mikheykin <ivan.mikheykin at flant.com>
---
lib/tar.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/lib/tar.c b/lib/tar.c
index 100efb3..46a9c92 100644
--- a/lib/tar.c
+++ b/lib/tar.c
@@ -725,6 +725,11 @@ restart:
tar_offset = tar->offset;
ret = erofs_iostream_read(&tar->ios, (void **)&th, sizeof(*th));
if (ret != sizeof(*th)) {
+ if (tar->ios.feof) {
+ erofs_warn("unexpected end of file @ %llu (may be non-standard tar without end of archive zeros)", tar_offset);
+ ret = 1;
+ goto out;
+ }
if (tar->headeronly_mode || tar->ddtaridx_mode) {
ret = 1;
goto out;
--
2.39.3 (Apple Git-146)
More information about the Linux-erofs
mailing list