Quellcode durchsuchen

Merge pull request #3391 from borgbackup/rel113

Release 1.1.3
TW vor 7 Jahren
Ursprung
Commit
bb6e86628f

+ 5 - 0
docs/3rd_party/README

@@ -0,0 +1,5 @@
+Here we store 3rd party documentation, licenses, etc.
+
+Please note that all files inside the "borg" package directory (except the
+stuff excluded in setup.py) will be INSTALLED, so don't keep docs or licenses
+there.

+ 0 - 0
src/borg/algorithms/blake2/COPYING → docs/3rd_party/blake2/COPYING


+ 0 - 0
src/borg/algorithms/blake2/README.md → docs/3rd_party/blake2/README.md


+ 7 - 3
docs/changes.rst

@@ -131,8 +131,8 @@ The best check that everything is ok is to run a dry-run extraction::
 Changelog
 =========
 
-Version 1.1.3 (not released yet)
---------------------------------
+Version 1.1.3 (2017-11-27)
+--------------------------
 
 Compatibility notes:
 
@@ -153,7 +153,11 @@ Compatibility notes:
 
 Fixes:
 
-- XXX SECFIX XXX
+- Security Fix for CVE-2017-15914: Incorrect implementation of access controls
+  allows remote users to override repository restrictions in Borg servers.
+  A user able to access a remote Borg SSH server is able to circumvent access
+  controls post-authentication.
+  Affected releases: 1.1.0, 1.1.1, 1.1.2. Releases 1.0.x are NOT affected.
 - crc32: deal with unaligned buffer, add tests - this broke borg on older ARM
   CPUs that can not deal with unaligned 32bit memory accesses and raise a bus
   error in such cases. the fix might also improve performance on some CPUs as

+ 1 - 7
docs/man/borg-benchmark-crud.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-BENCHMARK-CRUD 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-BENCHMARK-CRUD 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-benchmark-crud \- Benchmark Create, Read, Update, Delete for archives.
 .
@@ -60,13 +60,7 @@ C\-R\- == random files. no dedup, measuring throughput through all processing st
 .B R\- == borg extract (extract archive, dry\-run, do everything, but do not write files to disk)
 R\-Z\- == all zero files. Measuring heavily duplicated files.
 R\-R\- == random files. No duplication here, measuring throughput through all processing
-.IP "System Message: ERROR/3 (docs/virtmanpage.rst:, line 56)"
-Unexpected indentation.
-.INDENT 7.0
-.INDENT 3.5
 stages, except writing to disk.
-.UNINDENT
-.UNINDENT
 .TP
 .B U\- == borg create (2nd archive creation of unchanged input files, measure files cache speed)
 The throughput value is kind of virtual here, it does not actually read the file.

+ 1 - 1
docs/man/borg-benchmark.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-BENCHMARK 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-BENCHMARK 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-benchmark \- benchmark command
 .

+ 1 - 1
docs/man/borg-break-lock.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-BREAK-LOCK 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-BREAK-LOCK 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-break-lock \- Break the repository lock (e.g. in case it was left by a dead borg.
 .

+ 1 - 1
docs/man/borg-change-passphrase.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-CHANGE-PASSPHRASE 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-CHANGE-PASSPHRASE 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-change-passphrase \- Change repository key file passphrase
 .

+ 1 - 1
docs/man/borg-check.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-CHECK 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-CHECK 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-check \- Check repository consistency
 .

+ 1 - 1
docs/man/borg-common.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-COMMON 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-COMMON 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-common \- Common options of Borg commands
 .

+ 1 - 1
docs/man/borg-compression.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-COMPRESSION 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-COMPRESSION 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-compression \- Details regarding compression
 .

+ 105 - 0
docs/man/borg-config.1

@@ -0,0 +1,105 @@
+.\" Man page generated from reStructuredText.
+.
+.TH BORG-CONFIG 1 "2017-11-26" "" "borg backup tool"
+.SH NAME
+borg-config \- get, set, and delete values in a repository or cache config file
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH SYNOPSIS
+.sp
+borg [common options] config [options] REPOSITORY NAME [VALUE]
+.SH DESCRIPTION
+.sp
+This command gets and sets options in a local repository or cache config file.
+For security reasons, this command only works on local repositories.
+.sp
+To delete a config value entirely, use \fB\-\-delete\fP\&. To get an existing key, pass
+only the key name. To set a key, pass both the key name and the new value. Keys
+can be specified in the format "section.name" or simply "name"; the section will
+default to "repository" and "cache" for the repo and cache configs, respectively.
+.sp
+By default, borg config manipulates the repository config file. Using \fB\-\-cache\fP
+edits the repository cache\(aqs config file instead.
+.SH OPTIONS
+.sp
+See \fIborg\-common(1)\fP for common options of Borg commands.
+.SS arguments
+.INDENT 0.0
+.TP
+.B REPOSITORY
+repository to configure
+.TP
+.B NAME
+name of config key
+.TP
+.B VALUE
+new value for key
+.UNINDENT
+.SS optional arguments
+.INDENT 0.0
+.TP
+.B \-c\fP,\fB  \-\-cache
+get and set values from the repo cache
+.TP
+.B \-d\fP,\fB  \-\-delete
+delete the key from the config file
+.UNINDENT
+.SH EXAMPLES
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+The repository & cache config files are some of the only directly manipulable
+parts of a repository that aren\(aqt versioned or backed up, so be careful when
+making changes!
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# find cache directory
+$ cd ~/.cache/borg/$(borg config /path/to/repo id)
+
+# reserve some space
+$ borg config /path/to/repo additional_free_space 2G
+
+# make a repo append\-only
+$ borg config /path/to/repo append_only 1
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SH SEE ALSO
+.sp
+\fIborg\-common(1)\fP
+.SH AUTHOR
+The Borg Collective
+.\" Generated by docutils manpage writer.
+.

+ 2 - 2
docs/man/borg-create.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-CREATE 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-CREATE 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-create \- Create new archive
 .
@@ -252,7 +252,7 @@ $ borg create /path/to/repo::my\-files /home \e
 
 # Backup the root filesystem into an archive named "root\-YYYY\-MM\-DD"
 # use zlib compression (good, but slow) \- default is lz4 (fast, low compression ratio)
-$ borg create \-C zlib,6 /path/to/repo::root\-{now:%Y\-%m\-%d} / \-\-one\-file\-system
+$ borg create \-C zlib,6 \-\-one\-file\-system /path/to/repo::root\-{now:%Y\-%m\-%d} /
 
 # Backup a remote host locally ("pull" style) using sshfs
 $ mkdir sshfs\-mount

+ 1 - 1
docs/man/borg-delete.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-DELETE 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-DELETE 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-delete \- Delete an existing repository or archives
 .

+ 1 - 1
docs/man/borg-diff.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-DIFF 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-DIFF 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-diff \- Diff contents of two archives
 .

+ 4 - 4
docs/man/borg-export-tar.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-EXPORT-TAR 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-EXPORT-TAR 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-export-tar \- Export archive contents as a tarball
 .
@@ -127,11 +127,11 @@ $ borg export\-tar /path/to/repo::Monday Monday.tar
 $ borg export\-tar /path/to/repo::Monday Monday.tar.gz \-\-exclude \(aq*.so\(aq
 
 # use higher compression level with gzip
-$ borg export\-tar testrepo::linux \-\-tar\-filter="gzip \-9" Monday.tar.gz
+$ borg export\-tar \-\-tar\-filter="gzip \-9" testrepo::linux Monday.tar.gz
 
-# export a gzipped tar, but instead of storing it on disk,
+# export a tar, but instead of storing it on disk,
 # upload it to a remote site using curl.
-$ borg export\-tar ... \-\-tar\-filter="gzip" \- | curl \-\-data\-binary @\- https://somewhere/to/POST
+$ borg export\-tar /path/to/repo::Monday \- | curl \-\-data\-binary @\- https://somewhere/to/POST
 
 # remote extraction via "tarpipe"
 $ borg export\-tar /path/to/repo::Monday \- | ssh somewhere "cd extracted; tar x"

+ 1 - 1
docs/man/borg-extract.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-EXTRACT 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-EXTRACT 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-extract \- Extract archive contents
 .

+ 1 - 1
docs/man/borg-info.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-INFO 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-INFO 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-info \- Show archive details such as disk space used
 .

+ 1 - 1
docs/man/borg-init.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-INIT 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-INIT 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-init \- Initialize an empty repository
 .

+ 1 - 1
docs/man/borg-key-change-passphrase.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-KEY-CHANGE-PASSPHRASE 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-KEY-CHANGE-PASSPHRASE 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-key-change-passphrase \- Change repository key file passphrase
 .

+ 1 - 1
docs/man/borg-key-export.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-KEY-EXPORT 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-KEY-EXPORT 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-key-export \- Export the repository key for backup
 .

+ 1 - 1
docs/man/borg-key-import.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-KEY-IMPORT 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-KEY-IMPORT 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-key-import \- Import the repository key from backup
 .

+ 1 - 1
docs/man/borg-key-migrate-to-repokey.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-KEY-MIGRATE-TO-REPOKEY 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-KEY-MIGRATE-TO-REPOKEY 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-key-migrate-to-repokey \- Migrate passphrase -> repokey
 .

+ 1 - 1
docs/man/borg-key.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-KEY 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-KEY 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-key \- Manage a keyfile or repokey of a repository
 .

+ 1 - 1
docs/man/borg-list.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-LIST 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-LIST 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-list \- List archive or repository contents
 .

+ 1 - 1
docs/man/borg-mount.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-MOUNT 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-MOUNT 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-mount \- Mount archive or an entire repository as a FUSE filesystem
 .

+ 1 - 1
docs/man/borg-patterns.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-PATTERNS 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-PATTERNS 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-patterns \- Details regarding patterns
 .

+ 1 - 1
docs/man/borg-placeholders.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-PLACEHOLDERS 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-PLACEHOLDERS 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-placeholders \- Details regarding placeholders
 .

+ 2 - 15
docs/man/borg-prune.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-PRUNE 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-PRUNE 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-prune \- Prune repository archives according to specified rules
 .
@@ -175,20 +175,7 @@ $ borg prune \-v \-\-list \-\-keep\-within=10d \-\-keep\-weekly=4 \-\-keep\-mont
 .UNINDENT
 .UNINDENT
 .sp
-There is also a visualized prune example in \fBdocs/misc/prune\-example.txt\fP:
-.IP "System Message: ERROR/3 (docs/virtmanpage.rst:, line 145)"
-Unknown directive type "highlight".
-.INDENT 0.0
-.INDENT 3.5
-.sp
-.nf
-.ft C
-\&.. highlight:: none
-
-.ft P
-.fi
-.UNINDENT
-.UNINDENT
+There is also a visualized prune example in \fBdocs/misc/prune\-example.txt\fP.
 .SH SEE ALSO
 .sp
 \fIborg\-common(1)\fP

+ 1 - 1
docs/man/borg-recreate.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-RECREATE 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-RECREATE 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-recreate \- Re-create archives
 .

+ 1 - 1
docs/man/borg-rename.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-RENAME 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-RENAME 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-rename \- Rename an existing archive
 .

+ 1 - 1
docs/man/borg-serve.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-SERVE 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-SERVE 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-serve \- Start in server mode. This command is usually not used manually.
 .

+ 6 - 1
docs/man/borg-umount.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-UMOUNT 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-UMOUNT 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-umount \- un-mount the FUSE filesystem
 .
@@ -82,6 +82,11 @@ $ borg umount /tmp/mymountpoint
 # These are especially handy for the "versions view",
 # which does not support lazy processing of archives.
 $ borg mount \-o versions \-\-glob\-archives \(aq*\-my\-home\(aq \-\-last 10 /path/to/repo /tmp/mymountpoint
+
+# Exclusion options are supported.
+# These can speed up mounting and lower memory needs significantly.
+$ borg mount /path/to/repo /tmp/mymountpoint only/that/path
+$ borg mount \-\-exclude \(aq...\(aq /path/to/repo /tmp/mymountpoint
 .ft P
 .fi
 .UNINDENT

+ 1 - 1
docs/man/borg-upgrade.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-UPGRADE 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-UPGRADE 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-upgrade \- upgrade a repository from a previous version
 .

+ 1 - 1
docs/man/borg-with-lock.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORG-WITH-LOCK 1 "2017-11-25" "" "borg backup tool"
+.TH BORG-WITH-LOCK 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borg-with-lock \- run a user specified command with the repository lock held
 .

+ 22 - 0
docs/man/borg.1

@@ -186,6 +186,26 @@ get other informational messages.
 .UNINDENT
 .UNINDENT
 .SH NOTES
+.SS Positional Arguments and Options: Order matters
+.sp
+Borg only supports taking options (\fB\-s\fP and \fB\-\-progress\fP in the example)
+to the left or right of all positional arguments (\fBrepo::archive\fP and \fBpath\fP
+in the example), but not in between them:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+borg create \-s \-\-progress repo::archive path  # good and preferred
+borg create repo::archive path \-s \-\-progress  # also works
+borg create \-s repo::archive path \-\-progress  # works, but ugly
+borg create repo::archive \-s \-\-progress path  # BAD
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+This is due to a problem in the argparse module: \fI\%http://bugs.python.org/issue15112\fP
 .SS Repository URLs
 .sp
 \fBLocal filesystem\fP (or locally mounted network filesystem):
@@ -614,6 +634,8 @@ hardlinked regular files, devices, FIFOs (considering all items in the same arch
 .IP \(bu 2
 timestamps in nanosecond precision: mtime, atime, ctime
 .IP \(bu 2
+other timestamps: birthtime (on platforms supporting it)
+.IP \(bu 2
 permissions:
 .INDENT 2.0
 .IP \(bu 2

+ 1 - 1
docs/man/borgfs.1

@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH BORGFS 1 "2017-11-25" "" "borg backup tool"
+.TH BORGFS 1 "2017-11-26" "" "borg backup tool"
 .SH NAME
 borgfs \- Mount archive or an entire repository as a FUSE filesystem
 .

+ 1 - 1
docs/usage/benchmark_crud.rst.inc

@@ -70,7 +70,7 @@ C- == borg create (1st archive creation, no compression, do not use files cache)
 R- == borg extract (extract archive, dry-run, do everything, but do not write files to disk)
       R-Z- == all zero files. Measuring heavily duplicated files.
       R-R- == random files. No duplication here, measuring throughput through all processing
-              stages, except writing to disk.
+      stages, except writing to disk.
 
 U- == borg create (2nd archive creation of unchanged input files, measure files cache speed)
       The throughput value is kind of virtual here, it does not actually read the file.

+ 1 - 3
src/borg/algorithms/crc32_slice_by_8.c

@@ -332,14 +332,12 @@ uint32_t crc32_slice_by_8(const void* data, size_t length, uint32_t previousCrc3
   uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF
 
   const uint32_t* current;
-  const uint8_t* currentChar;
+  const uint8_t* currentChar = (const uint8_t*) data;
 
   // enabling optimization (at least -O2) automatically unrolls the inner for-loop
   const size_t Unroll = 4;
   const size_t BytesAtOnce = 8 * Unroll;
 
-  currentChar = (const uint8_t*) data;
-
   // wanted: 32 bit / 4 Byte alignment, compute leading, unaligned bytes length
   uintptr_t unaligned_length = (4 - (((uintptr_t) currentChar) & 3)) & 3;
   // process unaligned bytes, if any (standard algorithm)

+ 1 - 0
src/borg/archiver.py

@@ -3997,6 +3997,7 @@ class Archiver:
                 return forced_result
             # we only take specific options from the forced "borg serve" command:
             result.restrict_to_paths = forced_result.restrict_to_paths
+            result.restrict_to_repositories = forced_result.restrict_to_repositories
             result.append_only = forced_result.append_only
         return result
 

+ 1 - 1
src/borg/fuse.py

@@ -398,7 +398,7 @@ class FuseOperations(llfuse.Operations):
             return name + version_enc + ext
 
         if 'source' in item and hardlinkable(item.mode):
-            source = os.path.join(*item.source.split(os.sep)[stripped_components:])
+            source = os.sep.join(item.source.split(os.sep)[stripped_components:])
             chunks, link_target = hardlink_masters.get(item.source, (None, source))
             if link_target:
                 # Hard link was extracted previously, just link

+ 12 - 0
src/borg/testsuite/archiver.py

@@ -3552,10 +3552,22 @@ def test_get_args():
     assert args.restrict_to_paths == ['/p1', '/p2']
     assert args.umask == 0o027
     assert args.log_level == 'info'
+    # similar, but with --restrict-to-repository
+    args = archiver.get_args(['borg', 'serve', '--restrict-to-repository=/r1', '--restrict-to-repository=/r2', ],
+                             'borg serve --info --umask=0027')
+    assert args.restrict_to_repositories == ['/r1', '/r2']
     # trying to cheat - break out of path restriction
     args = archiver.get_args(['borg', 'serve', '--restrict-to-path=/p1', '--restrict-to-path=/p2', ],
                              'borg serve --restrict-to-path=/')
     assert args.restrict_to_paths == ['/p1', '/p2']
+    # trying to cheat - break out of repository restriction
+    args = archiver.get_args(['borg', 'serve', '--restrict-to-repository=/r1', '--restrict-to-repository=/r2', ],
+                             'borg serve --restrict-to-repository=/')
+    assert args.restrict_to_repositories == ['/r1', '/r2']
+    # trying to cheat - break below repository restriction
+    args = archiver.get_args(['borg', 'serve', '--restrict-to-repository=/r1', '--restrict-to-repository=/r2', ],
+                             'borg serve --restrict-to-repository=/r1/below')
+    assert args.restrict_to_repositories == ['/r1', '/r2']
     # trying to cheat - try to execute different subcommand
     args = archiver.get_args(['borg', 'serve', '--restrict-to-path=/p1', '--restrict-to-path=/p2', ],
                              'borg init --encryption=repokey /')