Skip to content

Document the impact of the slashdot hack to pattern matching#9647

Merged
ThomasWaldmann merged 1 commit into
borgbackup:1.4-maintfrom
PhrozenByte:docs-slashdot-and-pattern
May 15, 2026
Merged

Document the impact of the slashdot hack to pattern matching#9647
ThomasWaldmann merged 1 commit into
borgbackup:1.4-maintfrom
PhrozenByte:docs-slashdot-and-pattern

Conversation

@PhrozenByte
Copy link
Copy Markdown
Contributor

When using the slashdot hack (e.g. /this/gets/stripped/./this/gets/archived), --pattern and --exclude match against the unstripped path (i.e. this/gets/stripped/this/gets/archived, not against this/gets/archived). Document this with borg help patterns. I thought about also adding a note to borg create --help, but don't think that this is necessary there.

PR is against 1.4-maint because I tested with Borg 1.4. I assume it's the same with Borg 2.0, will open a backport PR later.

Verified with Borg 1.4.4 with the following, click to expand.
$ mkdir borg-test; cd borg-test
$ borg init -e none repo
$ # create some test data (see listing below)
$ find data/ -type f -exec ls -hl {} \;
-rw-r--r-- 1 daniel daniel 6 15. Mai 14:02 data/this/is/also/saved
-rw-r--r-- 1 daniel daniel 4 15. Mai 14:07 data/this/gets/stripped/this/is/too
-rw-r--r-- 1 daniel daniel 9 15. Mai 14:01 data/this/gets/stripped/this/gets/archived
-rw-r--r-- 1 daniel daniel 5 15. Mai 14:01 data/other/data
$ ( cd data; borg create ../repo::archive1 this/gets/stripped/./this/gets/archived this/gets/stripped/./this/is this/is other; )
$ borg list repo::archive1
-rw-r--r-- daniel daniel        9 Fri, 2026-05-15 14:01:18 this/gets/archived
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:07:30 this/is
-rw-r--r-- daniel daniel        4 Fri, 2026-05-15 14:07:30 this/is/too
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:02:01 this/is
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:02:08 this/is/also
-rw-r--r-- daniel daniel        6 Fri, 2026-05-15 14:02:08 this/is/also/saved
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:01:37 other
-rw-r--r-- daniel daniel        5 Fri, 2026-05-15 14:01:37 other/data
$ ( cd data; borg create ../repo::archive2 --pattern '! this' this/gets/stripped/./this/gets/archived this/gets/stripped/./this/is this/is other; )
$ borg list repo::archive2
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:01:37 other
-rw-r--r-- daniel daniel        5 Fri, 2026-05-15 14:01:37 other/data
$ ( cd data; borg create ../repo::archive3 --pattern '! this/gets/stripped' this/gets/stripped/./this/gets/archived this/gets/stripped/./this/is this/is other; )
$ borg list repo::archive3
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:02:01 this/is
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:02:08 this/is/also
-rw-r--r-- daniel daniel        6 Fri, 2026-05-15 14:02:08 this/is/also/saved
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:01:37 other
-rw-r--r-- daniel daniel        5 Fri, 2026-05-15 14:01:37 other/data
$ ( cd data; borg create ../repo::archive4 --pattern '! this/gets/archived' this/gets/stripped/./this/gets/archived this/gets/stripped/./this/is this/is other; )
$ borg list repo::archive4  # pattern excludes nothing
-rw-r--r-- daniel daniel        9 Fri, 2026-05-15 14:01:18 this/gets/archived
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:07:30 this/is
-rw-r--r-- daniel daniel        4 Fri, 2026-05-15 14:07:30 this/is/too
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:02:01 this/is
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:02:08 this/is/also
-rw-r--r-- daniel daniel        6 Fri, 2026-05-15 14:02:08 this/is/also/saved
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:01:37 other
-rw-r--r-- daniel daniel        5 Fri, 2026-05-15 14:01:37 other/data
$ borg create repo::archive5 "$PWD"/data/this/gets/stripped/./this/gets/archived "$PWD"/data/this/gets/stripped/./this/is "$PWD"/data/./this/is "$PWD"/data/./other
$ borg list repo::archive5  # using the slashdot hack for everything yields the same result as archive1
-rw-r--r-- daniel daniel        9 Fri, 2026-05-15 14:01:18 this/gets/archived
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:07:30 this/is
-rw-r--r-- daniel daniel        4 Fri, 2026-05-15 14:07:30 this/is/too
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:02:01 this/is
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:02:08 this/is/also
-rw-r--r-- daniel daniel        6 Fri, 2026-05-15 14:02:08 this/is/also/saved
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:01:37 other
-rw-r--r-- daniel daniel        5 Fri, 2026-05-15 14:01:37 other/data
$ borg create repo::archive6 --pattern "! $PWD/data/this" "$PWD"/data/this/gets/stripped/./this/gets/archived "$PWD"/data/this/gets/stripped/./this/is "$PWD"/data/./this/is "$PWD"/data/./other
$ borg list repo::archive5  # same as archive2
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:01:37 other
-rw-r--r-- daniel daniel        5 Fri, 2026-05-15 14:01:37 other/data
$ borg create repo::archive7 --pattern "! $PWD/data/this/gets/stripped" "$PWD"/data/this/gets/stripped/./this/gets/archived "$PWD"/data/this/gets/stripped/./this/is "$PWD"/data/./this/is "$PWD"/data/./other
$ borg list repo::archive5  # same as archive3
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:02:01 this/is
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:02:08 this/is/also
-rw-r--r-- daniel daniel        6 Fri, 2026-05-15 14:02:08 this/is/also/saved
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:01:37 other
-rw-r--r-- daniel daniel        5 Fri, 2026-05-15 14:01:37 other/data
$ borg create repo::archive8 --pattern "! this/gets/archived" "$PWD"/data/this/gets/stripped/./this/gets/archived "$PWD"/data/this/gets/stripped/./this/is "$PWD"/data/./this/is "$PWD"/data/./other
$ borg list repo::archive8  # pattern isn't matched against resulting paths, so same as archive4
-rw-r--r-- daniel daniel        9 Fri, 2026-05-15 14:01:18 this/gets/archived
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:07:30 this/is
-rw-r--r-- daniel daniel        4 Fri, 2026-05-15 14:07:30 this/is/too
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:02:01 this/is
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:02:08 this/is/also
-rw-r--r-- daniel daniel        6 Fri, 2026-05-15 14:02:08 this/is/also/saved
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:01:37 other
-rw-r--r-- daniel daniel        5 Fri, 2026-05-15 14:01:37 other/data
$ borg create repo::archive9 --pattern "! this" "$PWD"/data/this/gets/stripped/./this/gets/archived "$PWD"/data/this/gets/stripped/./this/is "$PWD"/data/./this/is "$PWD"/data/./other
$ borg list repo::archive9  # pattern isn't matched against resulting paths, so still the same as archive4
-rw-r--r-- daniel daniel        9 Fri, 2026-05-15 14:01:18 this/gets/archived
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:07:30 this/is
-rw-r--r-- daniel daniel        4 Fri, 2026-05-15 14:07:30 this/is/too
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:02:01 this/is
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:02:08 this/is/also
-rw-r--r-- daniel daniel        6 Fri, 2026-05-15 14:02:08 this/is/also/saved
drwxr-xr-x daniel daniel        0 Fri, 2026-05-15 14:01:37 other
-rw-r--r-- daniel daniel        5 Fri, 2026-05-15 14:01:37 other/data

... or rather that the slashdot hack doesn't impact pattern matching at all. Add a note to `borg help patterns`.
@codecov
Copy link
Copy Markdown

codecov Bot commented May 15, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.96%. Comparing base (9060e8a) to head (ae1440e).
⚠️ Report is 9 commits behind head on 1.4-maint.

Additional details and impacted files
@@              Coverage Diff              @@
##           1.4-maint    #9647      +/-   ##
=============================================
- Coverage      81.97%   81.96%   -0.02%     
=============================================
  Files             38       38              
  Lines          11329    11365      +36     
  Branches        1788     1793       +5     
=============================================
+ Hits            9287     9315      +28     
- Misses          1455     1461       +6     
- Partials         587      589       +2     

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

@PhrozenByte
Copy link
Copy Markdown
Contributor Author

Since this is purely a docs update, I'd say that the CI failures are unrelated. If not, just give me a heads up of what might be wrong 👍

@ThomasWaldmann
Copy link
Copy Markdown
Member

netbsd fails frequently due to segfaults of the python interpreter. they ignore the ticket about it since longer...

@ThomasWaldmann
Copy link
Copy Markdown
Member

Do we also have other strip options and do they also need a docs update?

@PhrozenByte
Copy link
Copy Markdown
Contributor Author

PhrozenByte commented May 15, 2026

Do we also have other strip options and do they also need a docs update?

You mean like --strip-components of extract/mount/export-tar? They all work with the archive contents. With the slashdot hack /this/gets/stripped/./this/gets/archived ends up as this/gets/archived in the archive, so extract et. al. will treat it as this/gets/archived (AFAIK Borg has no way of knowing about the slashdot hack at this point). With --strip-components=1 this gets gets/archived (verified that with Borg 1.4.4 just now). I'd say that users won't expect any different. What the slashdot hack itself does is documented in create --help, so IMO this is well documented already.

I'm not aware of any other strip options; AFAIK the slashdot hack is the only way to manipulate archive paths?

The various exclusion options (--exclude, --exclude-from, --pattern, --patterns-from) should behave the same in this regard (and AFAIK actually do). Same is true for selectors (verified that with Borg 1.4.4 just now): One should not replicate the /./ in the pattern, but neither fn:, nor sh:, pp:, and pf: care if one does. The only exception is re:, but re: isn't very forgiving in many ways (e.g., re: also cares about a leading /, no other selector does that, but it's a Regex pattern after all, so this is fine IMHO)… I'd say that my wording (unintentionally until now, but still) covers that detail pretty well already ("patterns must match this/gets/stripped/this/gets/archived").

@ThomasWaldmann
Copy link
Copy Markdown
Member

borg create does not have --strip-components, thus no other strip options there.

Copy link
Copy Markdown
Member

@ThomasWaldmann ThomasWaldmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@ThomasWaldmann ThomasWaldmann merged commit ec366d5 into borgbackup:1.4-maint May 15, 2026
12 of 14 checks passed
@github-actions
Copy link
Copy Markdown

Backport failed for master, because it was unable to cherry-pick the commit(s).

Please cherry-pick the changes locally and resolve any conflicts.

git fetch origin master
git worktree add -d .worktree/backport-9647-to-master origin/master
cd .worktree/backport-9647-to-master
git switch --create backport-9647-to-master
git cherry-pick -x ae1440ed7e8155a3c0807cdbdfd8f18378f40a98

@ThomasWaldmann
Copy link
Copy Markdown
Member

Can you port it to master, please?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants