Skip to content

import-tar: convert GNU tar PAX ACLs, exact PAX ns timestamps - #10499

Merged
ThomasWaldmann merged 4 commits into
borgbackup:masterfrom
ThomasWaldmann:import-tar-acls
Oct 6, 2026
Merged

ThomasWaldmann merged 4 commits into
borgbackup:masterfrom
ThomasWaldmann:import-tar-acls

Conversation

@ThomasWaldmann

Copy link
Copy Markdown
Member

import-tar: convert PAX ACLs to borg's ACL format

GNU tar (tar --format=posix --acls) writes named ACL entries without a numeric id, e.g.:

user::rw-
user:nobody:rw-
group::r--
mask::rw-
other::r--

import-tar copied SCHILY.acl.access / SCHILY.acl.default unchanged into item.acl_access / item.acl_default. Borg's internal ACL format has the uid/gid as a 4th field (user:nobody:rw-:65534), so borg extract crashed in acl_use_local_uid_gid (platform/linux.pyx):

IndexError: list index out of range

Reproduced on master in a Linux container: GNU tar posix tarball → borg import-tar → borg extract crashed with rc 2.

Fix: tar_acl_to_borg() converts the ACL text:

SCHILY.xattr.system.posix_acl_* keys (GNU tar --xattrs-include='*' also stores the ACLs as raw xattrs) are skipped, like borg create does in listxattr, because borg stores the ACLs separately.

The export-tar help table now says that PAX also transfers POSIX ACLs.

export-tar/import-tar: exact ns timestamps in PAX headers

export-tar wrote the atime/ctime/mtime PAX headers via str(ns / 1e9), and import-tar parsed them via float(s) * 1e9. A float has about 240 ns resolution at today's epoch, so the "ns" timestamps of --tar-format=PAX did not roundtrip exactly (...987654321 came back as ...987654400). Both directions now use exact decimal strings (ns_to_pax_time / pax_time_to_ns in helpers/time.py).

Tests

  • test_tar_acl_to_borg (parametrized: GNU tar, star and borg formats, unknown names, comments)
  • test_import_tar_gnu_tar_acls (Linux only): builds a PAX tarball with GNU-tar-style ACL headers, imports it, extracts it and checks the ACLs. On master it fails with the IndexError.
  • test_roundtrip_pax_timestamps: fails with either of the old float conversions.
  • test_ns_to_pax_time, test_pax_time_to_ns

Also checked manually on Linux: a real GNU tar --format=posix --xattrs --xattrs-include='*' --acls tarball goes through import-tar and extract, and the ACLs and xattrs are restored correctly.

🤖 Generated with Claude Code

ThomasWaldmann and others added 2 commits October 6, 2026 02:04
GNU tar (--format=posix --acls) writes named ACL entries without the
numeric uid/gid, e.g. "user:nobody:rw-". import-tar stored the text
unchanged, but borg's ACL format has the id as a 4th field, so borg
extract crashed in acl_use_local_uid_gid with an IndexError.

Named entries without an id now get it from a local user/group name
lookup (falling back to the name, like borg create does). Comma
separated entries (as star writes them) and comments are handled, too.

system.posix_acl_* xattrs (GNU tar --xattrs-include='*') are skipped,
like borg create does, because the ACLs are stored separately.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
export-tar wrote the atime/ctime/mtime PAX headers via str(ns / 1e9) and
import-tar parsed them via float(s) * 1e9. A float has ~240 ns resolution
at today's epoch, so the "ns" timestamps of --tar-format=PAX did not
roundtrip exactly (e.g. ...987654321 came back as ...987654400).

Write and parse them as exact decimal strings now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codecov

codecov Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.12%. Comparing base (e64154b) to head (7e3d305).
⚠️ Report is 5 commits behind head on master.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #10499      +/-   ##
==========================================
+ Coverage   89.08%   89.12%   +0.03%     
==========================================
  Files         103      103              
  Lines       19757    19783      +26     
  Branches     3094     3099       +5     
==========================================
+ Hits        17600    17631      +31     
+ Misses       1494     1490       -4     
+ Partials      663      662       -1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

ThomasWaldmann and others added 2 commits October 6, 2026 02:27
Previously, an invalid atime/ctime/mtime PAX header made import-tar crash
with a ValueError from float().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Haiku has no "root" user, so the name lookup fell back to the name and
the test expected uid 0 in vain.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ThomasWaldmann
ThomasWaldmann merged commit 05302a7 into borgbackup:master Oct 6, 2026
44 of 45 checks passed
@ThomasWaldmann
ThomasWaldmann deleted the import-tar-acls branch October 6, 2026 16:06
ThomasWaldmann added a commit to ThomasWaldmann/borg that referenced this pull request Oct 6, 2026
Like on master (borgbackup#10499):

- test_export_tar_pax_headers: compare the imported item timestamps with
  exact ns precision, not via borg list (only us precision).
- test_import_tar_invalid_pax_timestamp: invalid PAX timestamps get
  ignored, valid ones are used.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant