Compare commits

..

108 Commits

Author SHA1 Message Date
Leo R. Lundgren
6d39410958 doc: Reword parts of the text, replace rclone with rest-server
The intent here is to make the text more consistent in its use of different
concepts involved in explaining the idea and setup that is explained, and
to make it easier to follow.

We're also replacing rclone with rest-server, not because we dislike rclone
but in order to keep the text to the basic tooling and the main restic eco-
system.

Finally we also remove the previous tip at the end about keeping the SSH tunnel
up, as it will be during the time the SSH session is running (in which the user
is expected to run the restic commands).
2026-02-18 22:19:56 +01:00
JL710
5c3116901e use rclone for rest server instead of docker 2026-01-17 16:29:26 +01:00
JL710
8943ca15ed apply suggestions from Michael Eischer 2025-09-25 13:35:40 +02:00
JL710
a9d51db68d add example for "Pulling a Backup with HTTP over a ssh tunnel" 2025-09-11 16:07:50 +02:00
Michael Eischer
cc1fe6c111 Merge pull request #5493 from greatroar/ioctl
backend,termstatus: Unify foreground/background detection
2025-09-08 10:40:36 +02:00
greatroar
1ed93bd54d backend,termstatus: Unify foreground/background detection
PR #5358 reintroduced a version of the TIOCGPGRP ioctl call that works
on all Unix platforms except Linux, due to a bug/inconsistency in
x/sys/unix. This commit fixes that by introducing termstatus.Tcgetpgrp.

It also introduces termstatus.Getpgrp and termstatus.Tcsetpgrp to deal
with the different signature of unix.Getpgrp in Solaris vs. all other
Unix platforms and an int-overflowing constant on AIX, so that some
AIX/Solaris-specific code can be removed elsewhere and
foreground/background detection is done the same everywhere except on
Windows.
2025-09-08 09:33:44 +02:00
Michael Eischer
c55df65bb6 Merge pull request #5490 from MichaelEischer/sync-compatibility-section
docs: sync compatibility section with website
2025-09-07 11:35:48 +02:00
Michael Eischer
289adebbb7 Merge pull request #5492 from MichaelEischer/update-dependencies
update dependencies
2025-09-07 11:34:37 +02:00
Michael Eischer
eef047cfa4 update dependencies 2025-09-06 22:58:30 +02:00
Michael Eischer
7f1ac5764a Merge pull request #5358 from MichaelEischer/fix-tty-capture-in-background
Fix tty capture when started in background
2025-09-06 21:01:03 +02:00
Michael Eischer
52aa1cd17f docs: sync compatibility section with website
This is no change in policy, just a more precise description of the
status quo.
2025-09-06 20:55:48 +02:00
Michael Eischer
42f690dbab add changelog 2025-09-06 20:50:06 +02:00
Michael Eischer
914bd699be backend: always start backend process in separate process group
The process group is necessary to properly handle ctrl-c.
2025-09-06 19:51:10 +02:00
Michael Eischer
4c19d6410f backend: only move child process to foreground if already in foreground
The rclone and sftp backends require starting a child process. The are
first moved into the foreground and back into the background after the
initial startup is done.

However, this behavior is also active if restic itself is started in the
background. In this case, restic changing the foreground process may
confuse the shell and in case of bash causes it to exit. Thus, disable
modification of the controlling process group of the tty if restic is
run in the background.
2025-09-06 19:51:10 +02:00
Michael Eischer
2ad703bfd8 Merge pull request #5486 from greatroar/duration-panic
Avoid panic in duration parsing
2025-09-06 18:32:36 +02:00
greatroar
0864d04c5c internal/restic: Fix panic in ParseDuration
Fixes #5485. Includes test case by @MichaelEischer.
2025-09-06 10:30:34 +02:00
gregoster
839c38b4c4 EOPNOTSUPP can be returned if the filesystem does not support xattrs (#5344)
---------

Co-authored-by: Greg Oster <oster@netbsd.org>
2025-09-05 19:09:27 +00:00
Michael Eischer
e98c44baaf Merge pull request #5421 from MichaelEischer/fix-backup-metadata-crash
backup: fix possible crash if directory disappears before metadata collection
2025-09-05 19:53:16 +02:00
Michael Eischer
01bc60e96f backup: fix test on windows 2025-09-05 19:35:25 +02:00
Michael Eischer
484b706dd8 add changelog 2025-09-05 19:28:18 +02:00
Michael Eischer
350f6452e7 backup: test that parent directory errors can be correctly filtered 2025-09-05 19:28:18 +02:00
Michael Eischer
484cdf12e5 backup: test that missing parent directory is correctly handled 2025-09-05 19:28:18 +02:00
Michael Eischer
c8bb7bd312 backup: do not fail backup is some parent folder is inaccessible
Handle errors for parent directories of backup directories in the same
way as all other file access errors during a backup.
2025-09-05 19:28:18 +02:00
Michael Eischer
a8ce2e45cc backup: do not crash if nodeFromFileInfo fails
this could crash in two cases:
- if a directory is deleted between restic stating it and trying to list
  its directory content.
- when restic tries to list the parent directory of a backup target, but
  the parent directory has been deleted.

return an error in this case instead.
2025-09-05 19:28:18 +02:00
Michael Eischer
275507fb3e Merge pull request #5452 from dominikschulz/fix/storage
Mark HTTP Error 507 as permanent
2025-09-05 19:17:15 +02:00
Michael Eischer
391c27975a Merge pull request #5460 from restic/dependabot/go_modules/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob-1.6.2
build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/storage/azblob from 1.6.1 to 1.6.2
2025-09-05 19:16:54 +02:00
Michael Eischer
7d47e60e27 Merge pull request #5481 from restic/dependabot/github_actions/actions/checkout-5
build(deps): bump actions/checkout from 4 to 5
2025-09-05 19:07:58 +02:00
Michael Eischer
5c17c277f3 add changelog 2025-09-05 19:07:09 +02:00
Dominik Schulz
48e5c0984e Mark HTTP Error 507 as permanent
This change classifies HTTP error 507 (Insufficient Storage) as a
permanent error that should not be retried. I keep running into
this once in a while and there is literally no point in retrying when
the server is full.

Fixes #5429

Signed-off-by: Dominik Schulz <dominik.schulz@gauner.org>
2025-09-05 19:04:16 +02:00
dependabot[bot]
2414771a59 build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/storage/azblob
Bumps [github.com/Azure/azure-sdk-for-go/sdk/storage/azblob](https://github.com/Azure/azure-sdk-for-go) from 1.6.1 to 1.6.2.
- [Release notes](https://github.com/Azure/azure-sdk-for-go/releases)
- [Changelog](https://github.com/Azure/azure-sdk-for-go/blob/main/documentation/go-mgmt-sdk-release-guideline.md)
- [Commits](https://github.com/Azure/azure-sdk-for-go/compare/sdk/azcore/v1.6.1...sdk/storage/azblob/v1.6.2)

---
updated-dependencies:
- dependency-name: github.com/Azure/azure-sdk-for-go/sdk/storage/azblob
  dependency-version: 1.6.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-05 16:58:21 +00:00
Michael Eischer
0e381bdbf1 Merge pull request #5483 from restic/dependabot/go_modules/google.golang.org/api-0.248.0
build(deps): bump google.golang.org/api from 0.228.0 to 0.248.0
2025-09-05 18:47:58 +02:00
dependabot[bot]
11cd4a0a88 build(deps): bump actions/checkout from 4 to 5
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-05 16:38:46 +00:00
dependabot[bot]
f54989f634 build(deps): bump google.golang.org/api from 0.228.0 to 0.248.0
Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.228.0 to 0.248.0.
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.228.0...v0.248.0)

---
updated-dependencies:
- dependency-name: google.golang.org/api
  dependency-version: 0.248.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-05 16:36:17 +00:00
Michael Eischer
af7f10d16b Merge pull request #5482 from restic/dependabot/github_actions/docker/login-action-3.5.0
build(deps): bump docker/login-action from 3.4.0 to 3.5.0
2025-09-05 18:35:59 +02:00
Michael Eischer
6de95a3d58 Merge pull request #5484 from restic/dependabot/go_modules/golang.org/x/crypto-0.41.0
build(deps): bump golang.org/x/crypto from 0.39.0 to 0.41.0
2025-09-05 18:35:24 +02:00
dependabot[bot]
93f436e999 build(deps): bump golang.org/x/crypto from 0.39.0 to 0.41.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.39.0 to 0.41.0.
- [Commits](https://github.com/golang/crypto/compare/v0.39.0...v0.41.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-version: 0.41.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-01 02:10:03 +00:00
dependabot[bot]
6edb199efd build(deps): bump docker/login-action from 3.4.0 to 3.5.0
Bumps [docker/login-action](https://github.com/docker/login-action) from 3.4.0 to 3.5.0.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](74a5d14239...184bdaa072)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: 3.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-01 01:57:28 +00:00
rawtaz
9b2c0a0c54 Merge pull request #5466 from y0n3d4/gentoo-install-info
Added Gentoo install info
2025-08-07 13:28:17 +02:00
y0n3d4
64273ea027 Update 020_installation.rst removing command options
Removed command options: their use is a user choice
2025-08-06 13:57:29 +02:00
Michele Testa
5a00d26431 Update 020_installation.rst adding instruction for Gentoo Linux 2025-08-05 15:16:37 +02:00
Michele Testa
3faad5751d Revert "Update 020_installation.rst adding install command for Gentoo Linux"
This reverts commit f487eb1c66.
2025-08-05 14:12:04 +02:00
y0n3d4
f487eb1c66 Update 020_installation.rst adding install command for Gentoo Linux
Added basic instructions for restic installation on Gentoo using the official package manager (Portage)
2025-08-05 14:01:10 +02:00
Michael Eischer
72636238d0 Merge pull request #5400 from rhhub/patch-2
docs: clarify ** wildcard must me between path separators
2025-08-04 20:56:07 +02:00
rawtaz
51098157e2 Merge pull request #5462 from TheAlchemistOf42/wasabi-link
Correct Wasabi link
2025-08-02 22:12:57 +02:00
A Crutcher
0b080c44d7 doc: Correct Wasabi link 2025-08-02 13:03:43 -05:00
Michael Eischer
b71fe91643 Merge pull request #5345 from mikix/chmod-enotsup
backend/local: ignore chmod "not supported" errors
2025-07-21 22:28:53 +02:00
Michael Eischer
9c3b8d171a Merge pull request #5434 from restic/dependabot/go_modules/golang.org/x/time-0.12.0
build(deps): bump golang.org/x/time from 0.11.0 to 0.12.0
2025-07-21 22:17:40 +02:00
Michael Eischer
ddb7fb837b Merge pull request #5435 from restic/dependabot/go_modules/github.com/Azure/azure-sdk-for-go/sdk/azidentity-1.10.1
build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/azidentity from 1.10.0 to 1.10.1
2025-07-21 22:14:29 +02:00
Michael Eischer
3433c5abac Merge pull request #5408 from MichaelEischer/fix-walker-crash
walker: fix error handling if tree cannot be loaded
2025-07-21 21:46:59 +02:00
dependabot[bot]
09bc58c950 build(deps): bump golang.org/x/time from 0.11.0 to 0.12.0
Bumps [golang.org/x/time](https://github.com/golang/time) from 0.11.0 to 0.12.0.
- [Commits](https://github.com/golang/time/compare/v0.11.0...v0.12.0)

---
updated-dependencies:
- dependency-name: golang.org/x/time
  dependency-version: 0.12.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-21 19:46:35 +00:00
Michael Eischer
20eb9018a0 Merge pull request #5409 from MichaelEischer/fix-release-notes-typos
Fix release note typos
2025-07-21 21:46:05 +02:00
Michael Eischer
651f553530 Merge pull request #5436 from restic/dependabot/go_modules/github.com/peterbourgon/unixtransport-0.0.6
build(deps): bump github.com/peterbourgon/unixtransport from 0.0.4 to 0.0.6
2025-07-21 21:45:06 +02:00
Michael Eischer
aad4b53ead Merge pull request #5438 from restic/dependabot/go_modules/golang.org/x/crypto-0.39.0
build(deps): bump golang.org/x/crypto from 0.38.0 to 0.39.0
2025-07-21 21:42:06 +02:00
dependabot[bot]
e467496ace build(deps): bump golang.org/x/crypto from 0.38.0 to 0.39.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.38.0 to 0.39.0.
- [Commits](https://github.com/golang/crypto/compare/v0.38.0...v0.39.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-version: 0.39.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-01 05:46:21 +00:00
dependabot[bot]
f2de260524 build(deps): bump github.com/peterbourgon/unixtransport
Bumps [github.com/peterbourgon/unixtransport](https://github.com/peterbourgon/unixtransport) from 0.0.4 to 0.0.6.
- [Release notes](https://github.com/peterbourgon/unixtransport/releases)
- [Commits](https://github.com/peterbourgon/unixtransport/compare/v0.0.4...v0.0.6)

---
updated-dependencies:
- dependency-name: github.com/peterbourgon/unixtransport
  dependency-version: 0.0.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-01 05:07:50 +00:00
dependabot[bot]
c17d5ab2e1 build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/azidentity
Bumps [github.com/Azure/azure-sdk-for-go/sdk/azidentity](https://github.com/Azure/azure-sdk-for-go) from 1.10.0 to 1.10.1.
- [Release notes](https://github.com/Azure/azure-sdk-for-go/releases)
- [Changelog](https://github.com/Azure/azure-sdk-for-go/blob/main/documentation/go-mgmt-sdk-release-guideline.md)
- [Commits](https://github.com/Azure/azure-sdk-for-go/compare/sdk/azcore/v1.10.0...sdk/azidentity/v1.10.1)

---
updated-dependencies:
- dependency-name: github.com/Azure/azure-sdk-for-go/sdk/azidentity
  dependency-version: 1.10.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-01 05:07:41 +00:00
Michael Terry
a8535aba58 backend/local: ignore chmod "not supported" errors 2025-06-02 17:44:30 -04:00
rhhub
521fbad701 docs: clarify ** must me between path separators 2025-06-02 13:46:06 -07:00
Michael Eischer
15b7d7c3fc Fix release note typos 2025-06-02 21:12:37 +02:00
Patrick Wolf
7d39b1bfe8 Update 047_tuning_backup_parameters.rst - local backend (#5355)
users would find it helpful to know how to adjust the "local" backend and they might not get the idea that the local backend is just called local... which in turn leads them to think restic is slow as they can't adjust away  from 2 threads for restore and backup.
2025-06-02 18:40:04 +00:00
Michael Eischer
e4a7f4aadf Merge pull request #5356 from MichaelEischer/fix-backup-stdin-filename
backup: Fix `--stdin-filename` with directory
2025-06-02 20:27:26 +02:00
Michael Eischer
10cfe96cd4 walker: fix error handling if tree cannot be loaded
A tree that cannot be loaded is a fatal error when walking the tree.
Thus, return the error and exit the tree walk.
2025-06-02 20:04:26 +02:00
Michael Eischer
2eaa79d33f Merge pull request #5374 from ilyagr/docprofile
docs: document profiling options a bit better
2025-06-02 19:57:33 +02:00
Ilya Grigoriev
99ee5696f3 bugfix: have --{cpu,mem,...}-profile work even if Restic exits with error code (#5373)
* bugfix: write pprof file for `--{cpu,mem,...}-profile` even on error code

Before this, if `restic backup --cpu-profile dir/ backup-dir/` couldn't
read some of the input files (e.g. they weren't readable by the user
restic was running under), the `cpu.pprof` file it outputs would be
empty.

https://github.com/spf13/cobra/issues/1893

* drop changelog as it's not relevant for end users

---------

Co-authored-by: Michael Eischer <michael.eischer@fau.de>
2025-06-02 17:57:07 +00:00
Ilya Grigoriev
e8dbb69a94 docs: when describing profiling, briefly explain .pprof files 2025-06-02 19:49:19 +02:00
Ilya Grigoriev
f4e21cdb75 docs: document profiling options a bit better
Previously, the docs were a bit mysterious about what "enables profiling
support" means or how one could take advantage of it.
2025-06-02 19:49:19 +02:00
Michael Eischer
e5bdc3c74f Merge pull request #5382 from restic/dependabot/go_modules/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob-1.6.1
build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/storage/azblob from 1.6.0 to 1.6.1
2025-06-02 19:40:33 +02:00
Michael Eischer
7e51c928c4 Merge pull request #5384 from zmanda/feat-gh-5377-check-add-percentage-for-read-data-subset
check: add percentage of repository checked
2025-06-02 19:37:08 +02:00
dependabot[bot]
21e87851aa build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/storage/azblob
Bumps [github.com/Azure/azure-sdk-for-go/sdk/storage/azblob](https://github.com/Azure/azure-sdk-for-go) from 1.6.0 to 1.6.1.
- [Release notes](https://github.com/Azure/azure-sdk-for-go/releases)
- [Changelog](https://github.com/Azure/azure-sdk-for-go/blob/main/documentation/release.md)
- [Commits](https://github.com/Azure/azure-sdk-for-go/compare/sdk/azcore/v1.6.0...sdk/azcore/v1.6.1)

---
updated-dependencies:
- dependency-name: github.com/Azure/azure-sdk-for-go/sdk/storage/azblob
  dependency-version: 1.6.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-02 17:32:18 +00:00
Michael Eischer
2bc1bf2702 Merge pull request #5402 from restic/dependabot/go_modules/github.com/Azure/azure-sdk-for-go/sdk/azidentity-1.10.0
build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/azidentity from 1.8.2 to 1.10.0
2025-06-02 19:19:10 +02:00
dependabot[bot]
df110060d1 build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/azidentity
Bumps [github.com/Azure/azure-sdk-for-go/sdk/azidentity](https://github.com/Azure/azure-sdk-for-go) from 1.8.2 to 1.10.0.
- [Release notes](https://github.com/Azure/azure-sdk-for-go/releases)
- [Changelog](https://github.com/Azure/azure-sdk-for-go/blob/main/documentation/go-mgmt-sdk-release-guideline.md)
- [Commits](https://github.com/Azure/azure-sdk-for-go/compare/sdk/azidentity/v1.8.2...sdk/azcore/v1.10.0)

---
updated-dependencies:
- dependency-name: github.com/Azure/azure-sdk-for-go/sdk/azidentity
  dependency-version: 1.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-02 16:45:38 +00:00
Michael Eischer
337a7d1205 Merge pull request #5385 from Silvenga/windows-docs
docs: updated installation docs for Windows
2025-06-02 18:44:43 +02:00
Michael Eischer
322e271dd2 Merge pull request #5404 from restic/dependabot/go_modules/golang.org/x/sys-0.33.0
build(deps): bump golang.org/x/sys from 0.31.0 to 0.33.0
2025-06-02 18:35:34 +02:00
dependabot[bot]
1ac224458f build(deps): bump golang.org/x/sys from 0.31.0 to 0.33.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.31.0 to 0.33.0.
- [Commits](https://github.com/golang/sys/compare/v0.31.0...v0.33.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-version: 0.33.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-01 01:25:20 +00:00
rawtaz
126ad04568 Merge pull request #5389 from fronesis47/patch-3
Update passwords section of FAQ
2025-05-11 20:35:20 +02:00
Samuel Chambers
e732bdbfb8 updated doc/faq.rst_commitsSquashed 2025-05-11 14:02:07 -04:00
Mark Lopez
2db08fd749 docs: updated installation docs for Windows 2025-05-03 10:27:50 -05:00
Srigovind Nayak
debb110a7c check: add percentage of repository checked 2025-05-03 18:08:12 +05:30
rawtaz
5eb4f5af61 Merge pull request #5360 from makuhama/master
doc: typo & minor rewording in 'Removing files from snapshots'
2025-05-02 01:05:08 +02:00
Markus Hansmair
287b601f01 doc: typo & minor rewording in 'Removing files from snapshots' 2025-04-16 09:37:26 +02:00
Michael Eischer
64c82a5d9c Merge pull request #5357 from Hello71/patch-1
doc: add fastest, better compression
2025-04-14 20:02:41 +02:00
Alex Xu
12f36ebf07 doc: add fastest, better compression
Follow-up for #5321
2025-04-13 19:33:13 -04:00
Michael Eischer
45e09dca2a add changelog for --stdin-filename with/directory 2025-04-11 22:29:18 +02:00
Michael Eischer
5bb9d0d996 backup: test subdirectories in stdin filenames work 2025-04-11 22:14:32 +02:00
Michael Eischer
9f39e8a1d3 fs/reader: return proper error on invalid filename 2025-04-11 22:07:31 +02:00
Michael Eischer
ddd48f1e98 fs/reader: test file not exist case 2025-04-11 21:57:45 +02:00
Michael Eischer
6e91ea3397 fs/reader: use test helpers 2025-04-11 21:54:15 +02:00
Michael Eischer
e7c1e4f1ff fs/reader: deduplicate test code 2025-04-11 21:50:47 +02:00
Michael Eischer
70e1037a49 fs/reader: fix open+stat handling 2025-04-11 21:49:25 +02:00
Michael Eischer
19f48084ea fs/reader: use modification time for file and directories
This ensures that a fixed input generates a fully deterministic output
file structure.
2025-04-11 21:46:24 +02:00
Michael Eischer
3a995172b7 fs: rewrite Reader to build fs tree up front
This adds proper support for filenames that include directories. For
example, `/foo/bar` would result in an error when trying to open `/foo`.

The directory tree is now build upfront. This ensures let's the
directory tree construction be handled only once. All accessors then
only have to look up the constructed directory entries.
2025-04-11 21:37:40 +02:00
Michael Eischer
0dffa1208d Merge pull request #5243 from zmanda/feat-gh-4868-show-repo-id-in-df-and-mount
mount: append the repository ID to the name of the FUSE mount
2025-04-02 21:16:11 +02:00
Michael Eischer
6fbcce1d1a docs: fix typos in developer information (#5329) 2025-04-02 21:12:43 +02:00
Michael Eischer
e8d458be7e update direct dependencies (#5340) 2025-04-02 21:10:40 +02:00
dependabot[bot]
4471c7847b build(deps): bump docker/login-action from 3.3.0 to 3.4.0 (#5333)
Bumps [docker/login-action](https://github.com/docker/login-action) from 3.3.0 to 3.4.0.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](9780b0c442...74a5d14239)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: 3.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 20:54:17 +02:00
Srigovind Nayak
f13e9c10a4 Add support for additional compression levels fastest and better (#5321)
* repository: expose addtional compression levels

* adding better and fastest compression levels for zstd

* repository: add changelog entry for issue-4728

* chore: fix golint issues

* chore: sort compression modes in the help text

* updating review comments
2025-03-31 21:21:12 +02:00
Michael Eischer
f768683162 Merge pull request #5322 from zmanda/fix-gh-5233-forget-failure-exit-codes
forget: return exit code 3 on partial removal of snapshots
2025-03-31 20:08:33 +02:00
Michael Eischer
0b7bdfed7e Merge pull request #5320 from mjnaderi/patch-1
doc: fix typos
2025-03-31 20:07:51 +02:00
Michael Eischer
a4fe94ec82 Merge pull request #5317 from gilbsgilbs/fix-s3-restore-timeout-unit
docs: fix unit for S3 restore timeout
2025-03-31 20:01:22 +02:00
Michael Eischer
6684d1d2f5 Merge pull request #5327 from MichaelEischer/fix-forget-hostname-default
forget: fix ignored RESTIC_HOST environment variable
2025-03-31 19:21:13 +02:00
Michael Eischer
e1f7522174 forget: fix ignored RESTIC_HOST environment variable 2025-03-31 18:10:17 +02:00
Srigovind Nayak
d1649affb2 chore: update changelog for issue-5233 2025-03-30 14:12:06 +05:30
Srigovind Nayak
936c783c0f forget: exit code 3 for snapshot removal failures 2025-03-30 14:11:32 +05:30
Mohammad Javad Naderi
5614cf4758 doc: fix typos 2025-03-29 12:40:47 +03:30
Srigovind Nayak
6db0d84ab0 changelog: add changelog entry for issue-4868 2025-03-29 13:27:50 +05:30
Srigovind Nayak
88b599c4f3 mount: append repository ID to FS name of FUSE mount
* update review comments

mount: append repository ID to FS name of the FUSE mount
2025-03-29 13:22:10 +05:30
Gilbert Gilb's
eefff0d793 docs: fix unit for S3 restore timeout
"d" is not a valid unit.
2025-03-27 21:20:50 +01:00
Alexander Neumann
3d14e92905 Set development version for 0.18.0 2025-03-27 20:17:36 +01:00
37 changed files with 306 additions and 284 deletions

View File

@@ -1,6 +1,5 @@
# Table of Contents
* [Changelog for 0.18.1](#changelog-for-restic-0181-2025-09-21)
* [Changelog for 0.18.0](#changelog-for-restic-0180-2025-03-27)
* [Changelog for 0.17.3](#changelog-for-restic-0173-2024-11-08)
* [Changelog for 0.17.2](#changelog-for-restic-0172-2024-10-27)
@@ -40,106 +39,6 @@
* [Changelog for 0.6.0](#changelog-for-restic-060-2017-05-29)
# Changelog for restic 0.18.1 (2025-09-21)
The following sections list the changes in restic 0.18.1 relevant to
restic users. The changes are ordered by importance.
## Summary
* Fix #5324: Correctly handle `backup --stdin-filename` with directory paths
* Fix #5325: Accept `RESTIC_HOST` environment variable in `forget` command
* Fix #5342: Ignore "chmod not supported" errors when writing files
* Fix #5344: Ignore `EOPNOTSUPP` errors for extended attributes
* Fix #5421: Fix rare crash if directory is removed during backup
* Fix #5429: Stop retrying uploads when rest-server runs out of space
* Fix #5467: Improve handling of download retries in `check` command
## Details
* Bugfix #5324: Correctly handle `backup --stdin-filename` with directory paths
In restic 0.18.0, the `backup` command failed if a filename that includes at
least a directory was passed to `--stdin-filename`. For example,
`--stdin-filename /foo/bar` resulted in the following error:
```
Fatal: unable to save snapshot: open /foo: no such file or directory
```
This has now been fixed.
https://github.com/restic/restic/issues/5324
https://github.com/restic/restic/pull/5356
* Bugfix #5325: Accept `RESTIC_HOST` environment variable in `forget` command
The `forget` command did not use the host name from the `RESTIC_HOST`
environment variable when filtering snapshots. This has now been fixed.
https://github.com/restic/restic/issues/5325
https://github.com/restic/restic/pull/5327
* Bugfix #5342: Ignore "chmod not supported" errors when writing files
Restic 0.18.0 introduced a bug that caused `chmod xxx: operation not supported`
errors to appear when writing to a local file repository that did not support
chmod (like CIFS or WebDAV mounted via FUSE). Restic now ignores those errors.
https://github.com/restic/restic/issues/5342
* Bugfix #5344: Ignore `EOPNOTSUPP` errors for extended attributes
Restic 0.18.0 added extended attribute support for NetBSD 10+, but not all
NetBSD filesystems support extended attributes. Other BSD systems can likewise
return `EOPNOTSUPP`, so restic now ignores these errors.
https://github.com/restic/restic/issues/5344
* Bugfix #5421: Fix rare crash if directory is removed during backup
In restic 0.18.0, the `backup` command could crash if a directory was removed
between reading its metadata and listing its directory content. This has now
been fixed.
https://github.com/restic/restic/pull/5421
* Bugfix #5429: Stop retrying uploads when rest-server runs out of space
When rest-server returns a `507 Insufficient Storage` error, it indicates that
no more storage capacity is available. Restic now correctly stops retrying
uploads in this case.
https://github.com/restic/restic/issues/5429
https://github.com/restic/restic/pull/5452
* Bugfix #5467: Improve handling of download retries in `check` command
In very rare cases, the `check` command could unnecessarily report repository
damage if the backend returned incomplete, corrupted data on the first download
try which is afterwards resolved by a download retry.
This could result in an error output like the following:
```
Load(<data/34567890ab>, 33918928, 0) returned error, retrying after 871.35598ms: readFull: unexpected EOF
Load(<data/34567890ab>, 33918928, 0) operation successful after 1 retries
check successful on second attempt, original error pack 34567890ab[...] contains 6 errors: [blob 12345678[...]: decrypting blob <data/12345678> from 34567890 failed: ciphertext verification failed ...]
[...]
Fatal: repository contains errors
```
This fix only applies to a very specific case where the log shows `operation
successful after 1 retries` followed by a `check successful on second attempt,
original error` that only reports `ciphertext verification failed` errors in the
pack file. If any other errors are reported in the pack file, then the
repository still has to be considered as damaged.
Now, only the check result of the last download retry is reported as intended.
https://github.com/restic/restic/issues/5467
https://github.com/restic/restic/pull/5495
# Changelog for restic 0.18.0 (2025-03-27)
The following sections list the changes in restic 0.18.0 relevant to
restic users. The changes are ordered by importance.

View File

@@ -1 +1 @@
0.18.1
0.18.0-dev

View File

@@ -1,7 +0,0 @@
Bugfix: Ignore `EOPNOTSUPP` errors for extended attributes
Restic 0.18.0 added extended attribute support for NetBSD 10+, but not all
NetBSD filesystems support extended attributes. Other BSD systems can
likewise return `EOPNOTSUPP`, so restic now ignores these errors.
https://github.com/restic/restic/issues/5344

View File

@@ -1,8 +0,0 @@
Bugfix: Stop retrying uploads when rest-server runs out of space
When rest-server returns a `507 Insufficient Storage` error, it indicates
that no more storage capacity is available. Restic now correctly stops
retrying uploads in this case.
https://github.com/restic/restic/issues/5429
https://github.com/restic/restic/pull/5452

View File

@@ -1,27 +0,0 @@
Bugfix: Improve handling of download retries in `check` command
In very rare cases, the `check` command could unnecessarily report repository
damage if the backend returned incomplete, corrupted data on the first download
try which is afterwards resolved by a download retry.
This could result in an error output like the following:
```
Load(<data/34567890ab>, 33918928, 0) returned error, retrying after 871.35598ms: readFull: unexpected EOF
Load(<data/34567890ab>, 33918928, 0) operation successful after 1 retries
check successful on second attempt, original error pack 34567890ab[...] contains 6 errors: [blob 12345678[...]: decrypting blob <data/12345678> from 34567890 failed: ciphertext verification failed ...]
[...]
Fatal: repository contains errors
```
This fix only applies to a very specific case where the log shows
`operation successful after 1 retries` followed by a
`check successful on second attempt, original error` that only reports
`ciphertext verification failed` errors in the pack file. If any other errors
are reported in the pack file, then the repository still has to be considered
as damaged.
Now, only the check result of the last download retry is reported as intended.
https://github.com/restic/restic/issues/5467
https://github.com/restic/restic/pull/5495

View File

@@ -0,0 +1,7 @@
Enhancement: Added support for zstd compression levels `fastest` and `better`
Restic now supports the zstd compression modes `fastest` and `better`. Set the
environment variable `RESTIC_COMPRESSION` to `fastest` or `better` to use these
compression levels. This can also be set with the `--compression` flag.
https://github.com/restic/restic/issues/4728

View File

@@ -0,0 +1,14 @@
Enhancement: Include repository id in filesystem name used by `mount`
The filesystem created by restic's `mount` command now includes the repository
id in the filesystem name. The repository id is printed by restic when opening
a repository or can be looked up using `restic cat config`.
```
[restic-user@hostname restic]$ df ./test-mount/
Filesystem 1K-blocks Used Available Use% Mounted on
restic:d3b07384d1 0 0 0 - /mnt/my-restic-repo
```
https://github.com/restic/restic/issues/4868
https://github.com/restic/restic/pull/5243

View File

@@ -0,0 +1,8 @@
Bugfix: forget command returns exit code 3 on partial removal of snapshots
The `forget` command now returns exit code 3 when it fails to remove one or
more snapshots. Previously, it returned exit code 0, which could lead to
confusion if the command was used in a script.
https://github.com/restic/restic/issues/5233
https://github.com/restic/restic/pull/5322

View File

@@ -1,14 +1,14 @@
Bugfix: Correctly handle `backup --stdin-filename` with directory paths
Bugfix: Correctly handle `backup --stdin-filename` with directories
In restic 0.18.0, the `backup` command failed if a filename that includes
at least a directory was passed to `--stdin-filename`. For example,
a least a directory was passed to `--stdin-filename`. For example,
`--stdin-filename /foo/bar` resulted in the following error:
```
Fatal: unable to save snapshot: open /foo: no such file or directory
```
This has now been fixed.
This has been fixed now.
https://github.com/restic/restic/issues/5324
https://github.com/restic/restic/pull/5356

View File

@@ -1,7 +1,7 @@
Bugfix: Accept `RESTIC_HOST` environment variable in `forget` command
Bugfix: Correctly handle `RESTIC_HOST` in `forget` command
The `forget` command did not use the host name from the `RESTIC_HOST`
environment variable when filtering snapshots. This has now been fixed.
environment variable. This has been fixed.
https://github.com/restic/restic/issues/5325
https://github.com/restic/restic/pull/5327

View File

@@ -1,6 +1,6 @@
Bugfix: Ignore "chmod not supported" errors when writing files
Restic 0.18.0 introduced a bug that caused `chmod xxx: operation not supported`
Restic 0.18.0 introduced a bug that caused "chmod xxx: operation not supported"
errors to appear when writing to a local file repository that did not support
chmod (like CIFS or WebDAV mounted via FUSE). Restic now ignores those errors.

View File

@@ -0,0 +1,7 @@
Bugfix: Ignore EOPNOTSUPP as an error for xattr
Restic 0.18.0 added xattr support for NetBSD 10+, but not all NetBSD
filesystems support xattrs. Other BSD systems can likewise return
EOPNOTSUPP, so restic now simply ignores EOPNOTSUPP errors for xattrs.
https://github.com/restic/restic/issues/5344

View File

@@ -0,0 +1,12 @@
Bugfix: Allow use of rclone/sftp backend when running restic in background
When starting restic in the background, this could result in unexpected behavior
when using the rclone or sftp backend.
For example running `restic -r rclone:./example --insecure-no-password init &`
could cause the calling `bash` shell to exit unexpectedly.
This has been fixed.
https://github.com/restic/restic/issues/5354
https://github.com/restic/restic/pull/5358

View File

@@ -0,0 +1,8 @@
Bugfix: do not retry if rest-server runs out of space
Rest-server return error `507 Insufficient Storage` if no more storage
capacity is available at the server. Restic now no longer retries uploads
in this case.
https://github.com/restic/restic/issues/5429
https://github.com/restic/restic/pull/5452

View File

@@ -1,7 +1,8 @@
Bugfix: Fix rare crash if directory is removed during backup
In restic 0.18.0, the `backup` command could crash if a directory was removed
between reading its metadata and listing its directory content. This has now
been fixed.
In restic 0.18.0, the `backup` command could crash if a directory is removed
inbetween reading its metadata and listing its directory content.
This has been fixed.
https://github.com/restic/restic/pull/5421

View File

@@ -425,7 +425,8 @@ func runCheck(ctx context.Context, opts CheckOptions, gopts GlobalOptions, args
subsetSize = repoSize
}
packs = selectRandomPacksByFileSize(chkr.GetPacks(), subsetSize, repoSize)
printer.P("read %d bytes of data packs\n", subsetSize)
percentage := float64(subsetSize) / float64(repoSize) * 100.0
printer.P("read %d bytes (%.1f%%) of data packs\n", subsetSize, percentage)
}
if packs == nil {
return summary, errors.Fatal("internal error: failed to select packs to check")

View File

@@ -41,6 +41,7 @@ EXIT STATUS
Exit status is 0 if the command was successful.
Exit status is 1 if there was any error.
Exit status is 3 if there was an error removing one or more snapshots.
Exit status is 10 if the repository does not exist.
Exit status is 11 if the repository is already locked.
Exit status is 12 if the password is incorrect.
@@ -62,6 +63,7 @@ Exit status is 12 if the password is incorrect.
type ForgetPolicyCount int
var ErrNegativePolicyCount = errors.New("negative values not allowed, use 'unlimited' instead")
var ErrFailedToRemoveOneOrMoreSnapshots = errors.New("failed to remove one or more snapshots")
func (c *ForgetPolicyCount) Set(s string) error {
switch s {
@@ -305,12 +307,15 @@ func runForget(ctx context.Context, opts ForgetOptions, pruneOptions PruneOption
return ctx.Err()
}
// these are the snapshots that failed to be removed
failedSnIDs := restic.NewIDSet()
if len(removeSnIDs) > 0 {
if !opts.DryRun {
bar := printer.NewCounter("files deleted")
err := restic.ParallelRemove(ctx, repo, removeSnIDs, restic.WriteableSnapshotFile, func(id restic.ID, err error) error {
if err != nil {
printer.E("unable to remove %v/%v from the repository\n", restic.SnapshotFile, id)
failedSnIDs.Insert(id)
} else {
printer.VV("removed %v/%v\n", restic.SnapshotFile, id)
}
@@ -332,6 +337,10 @@ func runForget(ctx context.Context, opts ForgetOptions, pruneOptions PruneOption
}
}
if len(failedSnIDs) > 0 {
return ErrFailedToRemoveOneOrMoreSnapshots
}
if len(removeSnIDs) > 0 && opts.Prune {
if opts.DryRun {
printer.P("%d snapshots would be removed, running prune dry run\n", len(removeSnIDs))

View File

@@ -5,6 +5,7 @@ package main
import (
"context"
"fmt"
"os"
"strings"
"time"
@@ -148,9 +149,11 @@ func runMount(ctx context.Context, opts MountOptions, gopts GlobalOptions, args
return err
}
fuseMountName := fmt.Sprintf("restic:%s", repo.Config().ID[:10])
mountOptions := []systemFuse.MountOption{
systemFuse.ReadOnly(),
systemFuse.FSName("restic"),
systemFuse.FSName(fuseMountName),
systemFuse.MaxReadahead(128 * 1024),
}

View File

@@ -46,7 +46,7 @@ import (
// to a missing backend storage location or config file
var ErrNoRepository = errors.New("repository does not exist")
var version = "0.18.1"
var version = "0.18.0-dev (compiled manually)"
// TimeFormat is the format used for all timestamps printed by restic.
const TimeFormat = "2006-01-02 15:04:05"
@@ -114,7 +114,7 @@ func (opts *GlobalOptions) AddFlags(f *pflag.FlagSet) {
f.BoolVar(&opts.InsecureNoPassword, "insecure-no-password", false, "use an empty password for the repository, must be passed to every restic command (insecure)")
f.BoolVar(&opts.InsecureTLS, "insecure-tls", false, "skip TLS certificate verification when connecting to the repository (insecure)")
f.BoolVar(&opts.CleanupCache, "cleanup-cache", false, "auto remove old cache directories")
f.Var(&opts.Compression, "compression", "compression mode (only available for repository format version 2), one of (auto|off|max) (default: $RESTIC_COMPRESSION)")
f.Var(&opts.Compression, "compression", "compression mode (only available for repository format version 2), one of (auto|off|fastest|better|max) (default: $RESTIC_COMPRESSION)")
f.BoolVar(&opts.NoExtraVerify, "no-extra-verify", false, "skip additional verification of data before upload (see documentation)")
f.IntVar(&opts.Limits.UploadKb, "limit-upload", 0, "limits uploads to a maximum `rate` in KiB/s. (default: unlimited)")
f.IntVar(&opts.Limits.DownloadKb, "limit-download", 0, "limits downloads to a maximum `rate` in KiB/s. (default: unlimited)")

View File

@@ -206,6 +206,8 @@ func main() {
exitCode = 0
case err == ErrInvalidSourceData:
exitCode = 3
case errors.Is(err, ErrFailedToRemoveOneOrMoreSnapshots):
exitCode = 3
case errors.Is(err, ErrNoRepository):
exitCode = 10
case restic.IsAlreadyLocked(err):

View File

@@ -55,11 +55,10 @@ Compression
===========
For a repository using at least repository format version 2, you can configure how data
is compressed with the option ``--compression``. It can be set to ``auto`` (the default,
which will compress very fast), ``max`` (which will trade backup speed and CPU usage for
slightly better compression), or ``off`` (which disables compression). Each setting is
only applied for the single run of restic. The option can also be set via the environment
variable ``RESTIC_COMPRESSION``.
is compressed with the option ``--compression``. It can be set to ``off``, ``fastest``,
``auto`` (default), ``better``, or ``max``. Each setting uses more CPU but less bandwidth
and storage space. This setting is only applied for the single run of restic, but can also be
set via the environment variable ``RESTIC_COMPRESSION``.
Data Verification

View File

@@ -353,3 +353,72 @@ system.
root@a3e580b6369d:/# sudo -u restic /home/restic/bin/restic --exclude={/dev,/media,/mnt,/proc,/run,/sys,/tmp,/var/tmp} -r /tmp backup /
***********************************************************
Back up to an internal repository server over an SSH tunnel
***********************************************************
Idea
====
The idea is to run `REST-server <https://github.com/restic/rest-server>`__ on
an internal host as the repository server and then back up to it from a remote
restic client through a reverse SSH tunnel.
With this approach, you do not need to publicly expose the repository server
to which the backups are sent, as the restic client can instead connect to it
through the SSH tunnel.
An example use case for this method would be to create backups of a server,
e.g. a VPS in the cloud, to a repository stored on your local computer.
Running a local repository server
=================================
On the internal host, download and run the latest `release <https://github.com/restic/rest-server/releases>`__
of REST-server to act as the repository server. In this example we are using
the ``--no-auth`` option to not require authentication when connecting to it:
.. code-block:: console
rest-server --path /path/to/repo --no-auth
.. note:: REST-server by default listens on all network interfaces and port
``8000``.
Creating a reverse SSH tunnel
=============================
On the repository server (the internal host), use ``ssh -R`` to create what's
called a "reverse" SSH tunnel that listens for connections on the *remote* side
and forwards these back through the tunnel to the *local* side:
.. code-block:: console
ssh -R 8000:localhost:8000 user@server
.. note:: In this example, ``localhost`` refers to the local repository server,
and ``server`` refers to the remote system where restic is to be run.
Running restic on the remote system
===================================
Now that the SSH session and tunnel is established, run restic on the remote
system as usual, but with a repository URL that targets that system's side of
the SSH tunnel, in this example ``localhost:8000``.
This will make restic on the remote system connect to port ``8000`` on its
``localhost``, where the SSH tunnel is listening, after which the connection
is forwarded through the tunnel and finally reaches ``localhost:8000`` on the
local side where REST-server is listening and acting as the repository server.
To initialize the repository:
.. code-block:: console
restic -r rest:http://localhost:8000/ init
You can then use standard restic commands such as ``backup``, ``snapshots`` and
``restore`` with the same repository URL and other options as usual.
.. tip:: The tunnel will be active for the duration of the SSH session.

View File

@@ -1,28 +0,0 @@
//go:build aix || solaris
// +build aix solaris
package util
import (
"os/exec"
"syscall"
"github.com/restic/restic/internal/errors"
)
func startForeground(cmd *exec.Cmd) (bg func() error, err error) {
// run the command in its own process group so that SIGINT
// is not sent to it.
cmd.SysProcAttr = &syscall.SysProcAttr{
Setpgid: true,
}
// start the process
err = cmd.Start()
if err != nil {
return nil, errors.Wrap(err, "cmd.Start")
}
bg = func() error { return nil }
return bg, nil
}

View File

@@ -1,5 +1,4 @@
//go:build !aix && !solaris && !windows
// +build !aix,!solaris,!windows
//go:build unix
package util
@@ -10,35 +9,45 @@ import (
"github.com/restic/restic/internal/debug"
"github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/ui/termstatus"
"golang.org/x/sys/unix"
)
func tcsetpgrp(fd int, pid int) error {
// IoctlSetPointerInt silently casts to int32 internally,
// so this assumes pid fits in 31 bits.
return unix.IoctlSetPointerInt(fd, unix.TIOCSPGRP, pid)
}
func startForeground(cmd *exec.Cmd) (bg func() error, err error) {
// run the command in its own process group
// this ensures that sending ctrl-c to restic will not immediately stop the backend process.
cmd.SysProcAttr = &unix.SysProcAttr{
Setpgid: true,
}
// open the TTY, we need the file descriptor
tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
if err != nil {
debug.Log("unable to open tty: %v", err)
bg = func() error {
return nil
}
return bg, cmd.Start()
return startFallback(cmd)
}
// only move child process to foreground if restic is in the foreground
prev, err := termstatus.Tcgetpgrp(int(tty.Fd()))
if err != nil {
_ = tty.Close()
return nil, err
}
self := termstatus.Getpgrp()
if prev != self {
debug.Log("restic is not controlling the tty; err = %v", err)
if err := tty.Close(); err != nil {
return nil, err
}
return startFallback(cmd)
}
// Prevent getting suspended when interacting with the tty
signal.Ignore(unix.SIGTTIN)
signal.Ignore(unix.SIGTTOU)
// run the command in its own process group
cmd.SysProcAttr = &unix.SysProcAttr{
Setpgid: true,
}
// start the process
err = cmd.Start()
if err != nil {
@@ -47,8 +56,7 @@ func startForeground(cmd *exec.Cmd) (bg func() error, err error) {
}
// move the command's process group into the foreground
prev := unix.Getpgrp()
err = tcsetpgrp(int(tty.Fd()), cmd.Process.Pid)
err = termstatus.Tcsetpgrp(int(tty.Fd()), cmd.Process.Pid)
if err != nil {
_ = tty.Close()
return nil, err
@@ -59,7 +67,7 @@ func startForeground(cmd *exec.Cmd) (bg func() error, err error) {
signal.Reset(unix.SIGTTOU)
// reset the foreground process group
err = tcsetpgrp(int(tty.Fd()), prev)
err = termstatus.Tcsetpgrp(int(tty.Fd()), prev)
if err != nil {
_ = tty.Close()
return err
@@ -70,3 +78,11 @@ func startForeground(cmd *exec.Cmd) (bg func() error, err error) {
return bg, nil
}
func startFallback(cmd *exec.Cmd) (bg func() error, err error) {
bg = func() error {
return nil
}
return bg, cmd.Start()
}

View File

@@ -293,7 +293,7 @@ type errorBackend struct {
func (b errorBackend) Load(ctx context.Context, h backend.Handle, length int, offset int64, consumer func(rd io.Reader) error) error {
return b.Backend.Load(ctx, h, length, offset, func(rd io.Reader) error {
if b.ProduceErrors {
return consumer(errorReadCloser{Reader: rd})
return consumer(errorReadCloser{rd})
}
return consumer(rd)
})
@@ -301,21 +301,12 @@ func (b errorBackend) Load(ctx context.Context, h backend.Handle, length int, of
type errorReadCloser struct {
io.Reader
shortenBy int
maxErrorOffset int // if 0, the error can be injected at any offset
}
func (erd errorReadCloser) Read(p []byte) (int, error) {
n, err := erd.Reader.Read(p)
if n > 0 {
maxOffset := n
if erd.maxErrorOffset > 0 {
maxOffset = min(erd.maxErrorOffset, maxOffset)
}
induceError(p[:maxOffset])
}
if n > erd.shortenBy {
n -= erd.shortenBy
induceError(p[:n])
}
return n, err
}
@@ -329,24 +320,15 @@ func induceError(data []byte) {
// errorOnceBackend randomly modifies data when reading a file for the first time.
type errorOnceBackend struct {
backend.Backend
m sync.Map
shortenBy int
maxErrorOffset int
m sync.Map
}
func (b *errorOnceBackend) Load(ctx context.Context, h backend.Handle, length int, offset int64, consumer func(rd io.Reader) error) error {
_, isRetry := b.m.LoadOrStore(h, struct{}{})
err := b.Backend.Load(ctx, h, length, offset, func(rd io.Reader) error {
if !isRetry && h.Type != restic.ConfigFile {
return consumer(errorReadCloser{Reader: rd, shortenBy: b.shortenBy, maxErrorOffset: b.maxErrorOffset})
}
return consumer(rd)
})
if err == nil {
return nil
}
// retry if the consumer returned an error
return b.Backend.Load(ctx, h, length, offset, func(rd io.Reader) error {
if !isRetry && h.Type != restic.ConfigFile {
return consumer(errorReadCloser{rd})
}
return consumer(rd)
})
}
@@ -386,15 +368,6 @@ func TestCheckerModifiedData(t *testing.T) {
}
},
},
{
// ignore if a backend returns incomplete garbled data on the first try
"corruptPartialOnceBackend",
&errorOnceBackend{Backend: be, shortenBy: 10, maxErrorOffset: 100},
func() {},
func(t *testing.T, err error) {
test.Assert(t, err == nil, "unexpected error found, got %v", err)
},
},
} {
t.Run(test.name, func(t *testing.T) {
checkRepo := repository.TestOpenBackend(t, test.be)

View File

@@ -88,14 +88,10 @@ func checkPackInner(ctx context.Context, r *Repository, id restic.ID, blobs []re
// calculate hash on-the-fly while reading the pack and capture pack header
var hash restic.ID
var hdrBuf []byte
// must use a separate slice from `errs` here as we're only interested in the last retry
var blobErrors []error
h := backend.Handle{Type: backend.PackFile, Name: id.String()}
err := r.be.Load(ctx, h, int(size), 0, func(rd io.Reader) error {
hrd := hashing.NewReader(rd, sha256.New())
bufRd.Reset(hrd)
// reset blob errors for each retry
blobErrors = nil
it := newPackBlobIterator(id, newBufReader(bufRd), 0, blobs, r.Key(), dec)
for {
@@ -112,7 +108,7 @@ func checkPackInner(ctx context.Context, r *Repository, id restic.ID, blobs []re
debug.Log(" check blob %v: %v", val.Handle.ID, val.Handle)
if val.Err != nil {
debug.Log(" error verifying blob %v: %v", val.Handle.ID, val.Err)
blobErrors = append(blobErrors, errors.Errorf("blob %v: %v", val.Handle.ID, val.Err))
errs = append(errs, errors.Errorf("blob %v: %v", val.Handle.ID, val.Err))
}
}
@@ -138,7 +134,6 @@ func checkPackInner(ctx context.Context, r *Repository, id restic.ID, blobs []re
hash = restic.IDFromHash(hrd.Sum(nil))
return nil
})
errs = append(errs, blobErrors...)
if err != nil {
var e *partialReadError
isPartialReadError := errors.As(err, &e)

View File

@@ -73,7 +73,9 @@ const (
CompressionAuto CompressionMode = 0
CompressionOff CompressionMode = 1
CompressionMax CompressionMode = 2
CompressionInvalid CompressionMode = 3
CompressionFastest CompressionMode = 3
CompressionBetter CompressionMode = 4
CompressionInvalid CompressionMode = 5
)
// Set implements the method needed for pflag command flag parsing.
@@ -85,9 +87,13 @@ func (c *CompressionMode) Set(s string) error {
*c = CompressionOff
case "max":
*c = CompressionMax
case "fastest":
*c = CompressionFastest
case "better":
*c = CompressionBetter
default:
*c = CompressionInvalid
return fmt.Errorf("invalid compression mode %q, must be one of (auto|off|max)", s)
return fmt.Errorf("invalid compression mode %q, must be one of (auto|off|fastest|better|max)", s)
}
return nil
@@ -101,6 +107,10 @@ func (c *CompressionMode) String() string {
return "off"
case CompressionMax:
return "max"
case CompressionFastest:
return "fastest"
case CompressionBetter:
return "better"
default:
return "invalid"
}
@@ -305,9 +315,17 @@ func (r *Repository) loadBlob(ctx context.Context, blobs []restic.PackedBlob, bu
func (r *Repository) getZstdEncoder() *zstd.Encoder {
r.allocEnc.Do(func() {
level := zstd.SpeedDefault
if r.opts.Compression == CompressionMax {
var level zstd.EncoderLevel
switch r.opts.Compression {
case CompressionFastest:
level = zstd.SpeedFastest
case CompressionBetter:
level = zstd.SpeedBetterCompression
case CompressionMax:
level = zstd.SpeedBestCompression
default:
level = zstd.SpeedDefault
}
opts := []zstd.EOption{

View File

@@ -1,27 +0,0 @@
package termstatus
import (
"github.com/restic/restic/internal/debug"
"golang.org/x/sys/unix"
)
// IsProcessBackground reports whether the current process is running in the
// background. fd must be a file descriptor for the terminal.
func IsProcessBackground(fd uintptr) bool {
bg, err := isProcessBackground(fd)
if err != nil {
debug.Log("Can't check if we are in the background. Using default behaviour. Error: %s\n", err.Error())
return false
}
return bg
}
func isProcessBackground(fd uintptr) (bool, error) {
// We need to use IoctlGetUint32 here, because pid_t is 32-bit even on
// 64-bit Linux. IoctlGetInt doesn't work on big-endian platforms:
// https://github.com/golang/go/issues/45585
// https://github.com/golang/go/issues/60429
pid, err := unix.IoctlGetUint32(int(fd), unix.TIOCGPGRP)
return int(pid) != unix.Getpgrp(), err
}

View File

@@ -0,0 +1,24 @@
//go:build unix
package termstatus
import "github.com/restic/restic/internal/debug"
// IsProcessBackground reports whether the current process is running in the
// background. fd must be a file descriptor for the terminal.
func IsProcessBackground(fd uintptr) bool {
bg, err := isProcessBackground(int(fd))
if err != nil {
debug.Log("Can't check if we are in the background. Using default behaviour. Error: %s\n", err.Error())
return false
}
return bg
}
func isProcessBackground(fd int) (bg bool, err error) {
pgid, err := Tcgetpgrp(fd)
if err != nil {
return false, err
}
return pgid != Getpgrp(), nil
}

View File

@@ -1,3 +1,5 @@
//go:build unix
package termstatus
import (
@@ -13,7 +15,7 @@ func TestIsProcessBackground(t *testing.T) {
t.Skipf("can't open terminal: %v", err)
}
_, err = isProcessBackground(tty.Fd())
_, err = isProcessBackground(int(tty.Fd()))
rtest.OK(t, err)
_ = tty.Close()

View File

@@ -1,6 +1,3 @@
//go:build !linux
// +build !linux
package termstatus
// IsProcessBackground reports whether the current process is running in the

View File

@@ -0,0 +1,8 @@
package termstatus
import "golang.org/x/sys/unix"
func Getpgrp() int {
pid, _ := unix.Getpgrp()
return pid
}

View File

@@ -0,0 +1,7 @@
//go:build unix && !solaris
package termstatus
import "golang.org/x/sys/unix"
func Getpgrp() int { return unix.Getpgrp() }

View File

@@ -0,0 +1,12 @@
package termstatus
import "golang.org/x/sys/unix"
func Tcgetpgrp(ttyfd int) (int, error) {
// We need to use IoctlGetUint32 here, because pid_t is 32-bit even on
// 64-bit Linux. IoctlGetInt doesn't work on big-endian platforms:
// https://github.com/golang/go/issues/45585
// https://github.com/golang/go/issues/60429
pid, err := unix.IoctlGetUint32(ttyfd, unix.TIOCGPGRP)
return int(pid), err
}

View File

@@ -0,0 +1,9 @@
//go:build unix && !linux
package termstatus
import "golang.org/x/sys/unix"
func Tcgetpgrp(ttyfd int) (int, error) {
return unix.IoctlGetInt(ttyfd, unix.TIOCGPGRP)
}

View File

@@ -0,0 +1,10 @@
package termstatus
import "golang.org/x/sys/unix"
func Tcsetpgrp(fd int, pid int) error {
// The second argument to IoctlSetPointerInt has type int on AIX,
// but the constant overflows 64-bit int, hence the two-step cast.
req := uint(unix.TIOCSPGRP)
return unix.IoctlSetPointerInt(fd, int(req), pid)
}

View File

@@ -0,0 +1,9 @@
//go:build unix && !aix
package termstatus
import "golang.org/x/sys/unix"
func Tcsetpgrp(fd int, pid int) error {
return unix.IoctlSetPointerInt(fd, unix.TIOCSPGRP, pid)
}