Skip to content

import/export-tar: --tar-format=PAX (1.4-maint) - #10500

Open
ThomasWaldmann wants to merge 4 commits into
borgbackup:1.4-maintfrom
ThomasWaldmann:pax-tar-format-1.4
Open

ThomasWaldmann wants to merge 4 commits into
borgbackup:1.4-maintfrom
ThomasWaldmann:pax-tar-format-1.4

Conversation

@ThomasWaldmann

Copy link
Copy Markdown
Member

Description

Backports the PAX part of --tar-format to 1.4-maint, refs #7146.

borg export-tar --tar-format=PAX|GNU, the default stays GNU (no behaviour change for existing users).

With PAX, export-tar additionally transfers:

  • atime, ctime and mtime with nanosecond resolution
  • xattrs (SCHILY.xattr.*)
  • POSIX ACLs (SCHILY.acl.access, SCHILY.acl.default)

These are the same PAX header keys star and GNU tar use. Timestamps are written as exact decimal strings (not via float, which only gives ~240 ns precision at today's epoch), so nanosecond timestamps roundtrip exactly.

borg import-tar reads these PAX headers from any tarball:

  • ACL texts are converted to borg's internal format: GNU tar does not append the numeric uid/gid to named entries (user:nobody:rw-), which made borg extract crash in acl_use_local_uid_gid (IndexError). The id is looked up locally, like borg create does.
  • system.posix_acl_* xattrs (stored by tar --xattrs-include='*') are skipped, like borg create does, because ACLs are stored separately.
  • Empty xattr values become None, matching 1.4's xattr.get_all convention.

The BORG tar format from master is intentionally not backported: it serializes borg 1.x-internal item metadata (incompatible with borg2's), and in 1.4 trusting item metadata from a tarball (e.g. chunk lists) would be dangerous because of chunk refcounting.

Based on master's 78e92fa (--tar-format), e0fdaa4 (xattrs) and fe5a991 (POSIX ACLs).

Testing

  • New tests: PAX import/export roundtrip (mtime ns + xattrs), exact PAX header values and timestamp import, non-UTF-8 xattr roundtrip, POSIX ACL roundtrip (Linux), GNU-tar-style ACL import (Linux), and unit tests for the timestamp and ACL conversion helpers.
  • macOS: tar tests pass.
  • Linux (podman container): tar tests pass including the ACL tests.
  • Manual GNU tar interop on Linux, both directions (borg PAX export → GNU tar extract, GNU tar --format=posix --xattrs --acls → borg import-tar → extract): xattrs, access + default ACLs and exact ns mtime preserved.

Checklist

  • PR is against 1.4-maint
  • New code has tests
  • Help texts updated (usage docs not regenerated, that's done at release time)

🤖 Generated with Claude Code

export-tar --tar-format=PAX|GNU (default: GNU, as before).

With PAX, export-tar additionally transfers atime, ctime and mtime with
nanosecond resolution, xattrs and POSIX ACLs, using the same PAX header
keys as star and GNU tar (SCHILY.xattr.*, SCHILY.acl.access/default).

Timestamps are written as exact decimal strings, not via float, so
nanosecond timestamps roundtrip exactly.

import-tar reads these PAX headers from any tarball. ACL texts are
converted to borg's format: GNU tar does not append the numeric uid/gid
to named entries, which made borg extract crash in acl_use_local_uid_gid.
system.posix_acl_* xattrs (GNU tar --xattrs-include='*') are skipped,
like borg create does, because ACLs are stored separately.

Backport of the PAX parts of master's --tar-format (78e92fa),
xattr (e0fdaa4) and POSIX ACL (fe5a991) support.

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 82.26%. Comparing base (c13c9ee) to head (6121648).
⚠️ Report is 1 commits behind head on 1.4-maint.

Additional details and impacted files
@@              Coverage Diff              @@
##           1.4-maint   #10500      +/-   ##
=============================================
+ Coverage      82.10%   82.26%   +0.16%     
=============================================
  Files             38       38              
  Lines          11480    11550      +70     
  Branches        1808     1828      +20     
=============================================
+ Hits            9426     9502      +76     
+ Misses          1468     1465       -3     
+ Partials         586      583       -3     

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

ThomasWaldmann and others added 3 commits October 6, 2026 02:26
- test_tar_acl_to_borg: use uid2user(0) instead of assuming "root"
  (it is "user" on Haiku), like test_get_item_uid_gid does.
- test_export_tar_pax_headers: compare against the timestamps the
  filesystem actually stored (BFS has a coarser resolution).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
- item_to_paxheaders: module-level function, structured like master's
  (without the BORG format parts).
- help texts: same --tar-format table and import-tar text as master
  (without the BORG format).
- tests: same names and structure as master's tests for the same
  functionality (test_roundtrip_pax_timestamps, test_acl_roundtrip,
  test_tar_acl_to_borg, ...).

The 1.4 specific differences are kept: GNU stays the default and empty
xattr values are None (like xattr.get_all in 1.4).

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

This branch has not been deployed

No deployments
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