Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When restoring, cannot rewrite files that are readonly #4757

Open
toh995 opened this issue Apr 8, 2024 · 1 comment
Open

When restoring, cannot rewrite files that are readonly #4757

toh995 opened this issue Apr 8, 2024 · 1 comment
Labels

Comments

@toh995
Copy link

toh995 commented Apr 8, 2024

Output of restic version

restic 0.16.4 compiled with go1.22.1 on linux/amd64

What backend/service did you use to store the repository?

Local

Problem description / Steps to reproduce

NOTE: the following script should be copy+pasted into bash! (zsh didn't work for me)

# Initialize a restic repo
export RESTIC_REPOSITORY=/tmp/restic
export RESTIC_PASSWORD=foo
mkdir -p $RESTIC_REPOSITORY
restic init

# Create two new directories
DIR1=/tmp/foo1 && mkdir -p $DIR1
DIR2=/tmp/foo2 && mkdir -p $DIR2

# Create a readonly file in DIR1
# RO == readonly
RO_FILE=readonly.txt
echo "first" > "${DIR1}/${RO_FILE}"
chmod 444 "${DIR1}/${RO_FILE}"

# Create a snapshot of DIR1
cd $DIR1 && restic backup .

# Restore the snapshot to DIR2:
restic restore latest --target $DIR2

# Within DIR2, replace the existing readonly file with a new one with different contents
rm --force "${DIR2}/${RO_FILE}"
echo "second" > "${DIR2}/${RO_FILE}"
chmod 444 "${DIR2}/${RO_FILE}"

# Create a new snapshot of DIR2:
cd $DIR2 && restic backup .

# Here's the error!
# Try to restore the DIR2 snapshot into DIR1
DEBUG_LOG=logfile.txt restic restore latest --target $DIR1

Expected behavior

  1. Successfully restores the new file contents, for the readonly file
  2. The restore returns a 0 exit code
  3. No error messages displayed

Actual behavior

  1. Does NOT restore the new file contents
  2. The restore returns a 1 exit code
  3. Error messages are displayed

For (3), here's the output displayed in the terminal, for the final "restore" command, i.e. DEBUG_LOG=logfile.txt restic restore latest --target $DIR1

debug log file logfile.txt
debug enabled
repository 493cf5ac opened (version 2, compression level auto)

restoring <Snapshot caeea779 of [/tmp/foo2] at ${REDACTED} by ${REDACTED} to /tmp/foo1
ignoring error for /readonly.txt: open /tmp/foo1/readonly.txt: permission denied
Summary: Restored 1 files/dirs (7 B) in 0:00
Fatal: There were 1 errors

I've also attached the debug logs

Do you have any idea what may have caused this?

I'm not certain.

Maybe we should be hitting this codepath, but it's not for some reason?

if f, err = os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600); err != nil {
if fs.IsAccessDenied(err) {
// If file is readonly, clear the readonly flag by resetting the
// permissions of the file and try again
// as the metadata will be set again in the second pass and the
// readonly flag will be applied again if needed.
if err = fs.ResetPermissions(path); err != nil {
return nil, err
}

Also - is this related to this previous issue re: readonly directories? (The current issue is about readonly files)

Did restic help you today? Did it make you happy in any way?

It's a cool tool! 😄


I'm not sure if the maintainers have time to look at this - if not, I am willing to contribute some code to help fix this.

However, I will definitely need some help/guidance. In particular:

  • I don't quite understand the code structure. Seems like there are multiple layers of abstraction:
    • cmd/restic/cmd_restore.go
    • Restorer - seems like this also does some kind of traversal through the file directory tree?
    • filesWriter
  • If we were to write a test, is it more appropriate to write an "integration" test i.e. in cmd/restic/cmd_restore_integration_test.go? Or, write more of a "unit-level" test?
@MichaelEischer
Copy link
Member

MichaelEischer commented Apr 10, 2024

Fixing this restore issue is planned for restic 0.17.0 as part of properly handling in-place restores, see also #4575 . There are a few more corner cases to handle here, the go mod cache is especially hard to handle correctly (the directories are also recursively marked as read-only).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Todo
Development

No branches or pull requests

2 participants