Bug 1877916 - rdiff-backup crashes with Python exception when using filters while restoring subdirectory
Summary: rdiff-backup crashes with Python exception when using filters while restoring...
Keywords:
Status: CLOSED EOL
Alias: None
Product: Fedora
Classification: Fedora
Component: rdiff-backup
Version: 32
Hardware: x86_64
OS: Linux
unspecified
medium
Target Milestone: ---
Assignee: Frank Crawford
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2020-09-10 18:36 UTC by Laurentiu Pancescu
Modified: 2021-05-25 17:48 UTC (History)
3 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2021-05-25 17:48:25 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)
Archive with the files used for this bug report (384 bytes, application/x-xz)
2020-09-10 18:36 UTC, Laurentiu Pancescu
no flags Details


Links
System ID Private Priority Status Summary Last Updated
Github rdiff-backup rdiff-backup issues 463 0 None open [BUG] restoring a subdirectory doesn't play well with include/exclude filters 2020-09-11 22:04:12 UTC

Description Laurentiu Pancescu 2020-09-10 18:36:52 UTC
Created attachment 1714465 [details]
Archive with the files used for this bug report

Created attachment 1714465 [details]
Archive with the files used for this bug report

Description of problem:
rdiff-backup crashes due to a Python OSError exception while trying to restore a subdirectory and I also specify include/exclude filters.

Version-Release number of selected component (if applicable):
2.0.5-2.fc32

How reproducible:
Always

Steps to Reproduce:

1. Unpack the attached archive in a new directory, to have some files to play with:

    $ tar xaf demo.tar.xz

2. Create a new backup of directory 'original' in empty directory 'backup':

    $ rdiff-backup original/ backup/

3. Overwrite one of the files and check it has changed:

    $ cat original/dir1/file1.txt 
    file1
    $ echo garbage > original/dir1/file1.txt 
    $ cat original/dir1/file1.txt 
    garbage

4. Try to restore only some files from dir1:

    $ rdiff-backup -r now --include 'original/dir1/file1.txt' --exclude '**' backup/dir1 original/dir1
    Fatal Error: Restore target original/dir1 already exists, specify --force to overwrite.

5. Also add the --force parameter as suggested:

    $ rdiff-backup -r now --force --include 'original/dir1/file1.txt' --exclude '**' backup/dir1 original/dir1
    Exception '[Errno 39] Directory not empty: b'original/dir1'' raised of class '<class 'OSError'>':
      File "/usr/lib64/python3.8/site-packages/rdiff_backup/Main.py", line 395, in error_check_Main
        Main(arglist)
      File "/usr/lib64/python3.8/site-packages/rdiff_backup/Main.py", line 417, in Main
        take_action(rps)
      File "/usr/lib64/python3.8/site-packages/rdiff_backup/Main.py", line 373, in take_action
        Restore(rps[0], rps[1], 1)
      File "/usr/lib64/python3.8/site-packages/rdiff_backup/Main.py", line 720, in Restore
        restore.Restore(
      File "/usr/lib64/python3.8/site-packages/rdiff_backup/restore.py", line 42, in Restore
        TargetS.patch(target, diff_iter)
      File "/usr/lib64/python3.8/site-packages/rdiff_backup/restore.py", line 337, in patch
        ITR.Finish()
      File "/usr/lib64/python3.8/site-packages/rdiff_backup/rorpiter.py", line 277, in Finish
        to_be_finished.end_process()
      File "/usr/lib64/python3.8/site-packages/rdiff_backup/restore.py", line 762, in end_process
        self.base_rp.rmdir()
      File "/usr/lib64/python3.8/site-packages/rdiff_backup/rpath.py", line 1222, in rmdir
        self.conn.os.rmdir(self.path)

    Traceback (most recent call last):
      File "/usr/bin/rdiff-backup", line 32, in <module>
        rdiff_backup.Main.error_check_Main(sys.argv[1:])
      File "/usr/lib64/python3.8/site-packages/rdiff_backup/Main.py", line 395, in error_check_Main
        Main(arglist)
      File "/usr/lib64/python3.8/site-packages/rdiff_backup/Main.py", line 417, in Main
        take_action(rps)
      File "/usr/lib64/python3.8/site-packages/rdiff_backup/Main.py", line 373, in take_action
        Restore(rps[0], rps[1], 1)
      File "/usr/lib64/python3.8/site-packages/rdiff_backup/Main.py", line 720, in Restore
        restore.Restore(
      File "/usr/lib64/python3.8/site-packages/rdiff_backup/restore.py", line 42, in Restore
        TargetS.patch(target, diff_iter)
      File "/usr/lib64/python3.8/site-packages/rdiff_backup/restore.py", line 337, in patch
        ITR.Finish()
      File "/usr/lib64/python3.8/site-packages/rdiff_backup/rorpiter.py", line 277, in Finish
        to_be_finished.end_process()
      File "/usr/lib64/python3.8/site-packages/rdiff_backup/restore.py", line 762, in end_process
        self.base_rp.rmdir()
      File "/usr/lib64/python3.8/site-packages/rdiff_backup/rpath.py", line 1222, in rmdir
        self.conn.os.rmdir(self.path)
    OSError: [Errno 39] Directory not empty: b'original/dir1'


Actual results:
rdiff-backup crashes with a Python exception because it tries twice to rmdir a non-empty directory, the actual directory we were restoring to (in my actual case, I was trying to restore some file to /root, it's pretty scary to see it trying to remove /root because I was restoring three older files there).

Expected results:
rdiff-backup restores only the desired files and doesn't crash.

Additional info:
I believe this is a bug, otherwise rdiff-backup would probably display a normal error message about usage error, rather than crashing. I found several workarounds:

1. restore the entire directory:
    $ rdiff-backup -r now --force backup/dir1 original/dir1

2. use rsync, which has similar include/exclude options, but this only works for restoring the latest version of the backed up files
    $ rsync -a --include 'file1.txt' --exclude '**' backup/dir1/ original/dir1

3. only use include/exclude filters, but not any subdirectory:
    $ rdiff-backup -v5 -r now --force --include 'original/dir1/file1.txt' --exclude '**' backup original
    Starting restore of backup to original as it was as of Thu Sep 10 20:31:57 2020.
    Processing changed file .
    Processing changed file dir1
    Processing changed file dir1/file1.txt
    Restore finished

Comment 1 Frank Crawford 2020-09-11 12:20:05 UTC
Thanks for the report and it does look like a bug.

It would be best to take this upstream.  Do you want to do this, or would you prefer if I did?

Regards
Frank

Comment 2 Laurentiu Pancescu 2020-09-11 22:04:12 UTC
Thanks, I'm fine with it either way. I created upstream issue #463 on GitHub and created a link here. I also discovered the file I was trying to restore disappears completely from the destination directory, but it's still recoverable from the backup directory, so no data loss.

Comment 3 Frank Crawford 2020-09-12 03:20:54 UTC
In that case I'll leave it to upstream.  I follow the activity there and will see what they recommend.

Thanks
Frank

Comment 4 Fedora Program Management 2021-04-29 17:06:10 UTC
This message is a reminder that Fedora 32 is nearing its end of life.
Fedora will stop maintaining and issuing updates for Fedora 32 on 2021-05-25.
It is Fedora's policy to close all bug reports from releases that are no longer
maintained. At that time this bug will be closed as EOL if it remains open with a
Fedora 'version' of '32'.

Package Maintainer: If you wish for this bug to remain open because you
plan to fix it in a currently maintained version, simply change the 'version' 
to a later Fedora version.

Thank you for reporting this issue and we are sorry that we were not 
able to fix it before Fedora 32 is end of life. If you would still like 
to see this bug fixed and are able to reproduce it against a later version 
of Fedora, you are encouraged  change the 'version' to a later Fedora 
version prior this bug is closed as described in the policy above.

Although we aim to fix as many bugs as possible during every release's 
lifetime, sometimes those efforts are overtaken by events. Often a 
more recent Fedora release includes newer upstream software that fixes 
bugs or makes them obsolete.

Comment 5 Ben Cotton 2021-05-25 17:48:25 UTC
Fedora 32 changed to end-of-life (EOL) status on 2021-05-25. Fedora 32 is
no longer maintained, which means that it will not receive any further
security or bug fix updates. As a result we are closing this bug.

If you can reproduce this bug against a currently maintained version of
Fedora please feel free to reopen this bug against that version. If you
are unable to reopen this bug, please file a new report against the
current release. If you experience problems, please add a comment to this
bug.

Thank you for reporting this bug and we are sorry it could not be fixed.


Note You need to log in before you can comment on or make changes to this bug.