summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2015-06-13 09:35:40 +0300
committerLars Wirzenius <liw@liw.fi>2015-06-13 09:35:40 +0300
commitc20af9c9ca8f562a5c51a6f4c333cbceb55369b7 (patch)
treecd0c4b81b2914197a87ad1f6ddf6cb8f3349b767
parentbfce4f638fcf9986c527d493e412021fd448e624 (diff)
downloadobnam-c20af9c9ca8f562a5c51a6f4c333cbceb55369b7.tar.gz
Prevent restores to a non-empty --to directory
-rw-r--r--NEWS4
-rw-r--r--debian/changelog8
-rw-r--r--obnamlib/plugins/restore_plugin.py13
-rw-r--r--yarns/0030-basics.yarn25
4 files changed, 49 insertions, 1 deletions
diff --git a/NEWS b/NEWS
index ea572205..4ed885c2 100644
--- a/NEWS
+++ b/NEWS
@@ -38,6 +38,10 @@ Minor fixes:
text. This is now done in `python setup.py docs` instead. The latter
is an optional build step, and probably only works on Debian.
+* `obnam restore --to=DIR` now requires that the directory `DIR`
+ either doesn't exist, or it is empty when the restore starts. This
+ is to prevent users from restore on top of a running system.
+
Version 1.9, released 2015-03-22
--------------------------------
diff --git a/debian/changelog b/debian/changelog
index 7bbc8abb..7f59d522 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+obnam (1.10-1) UNRELEASED; urgency=medium
+
+ * New upstream version.
+ * Fix "restore to /tmp messes up directory perms" by preventing
+ restores to a non-empty directory. (Closes: #760492)
+
+ -- Lars Wirzenius <liw@liw.fi> Sat, 13 Jun 2015 09:34:51 +0300
+
obnam (1.9-1) unstable; urgency=low
* Update debian/copyright years. Thanks to Jan Niggemann.
diff --git a/obnamlib/plugins/restore_plugin.py b/obnamlib/plugins/restore_plugin.py
index 88ea15b7..677d8200 100644
--- a/obnamlib/plugins/restore_plugin.py
+++ b/obnamlib/plugins/restore_plugin.py
@@ -37,6 +37,11 @@ class RestoreErrors(obnamlib.ObnamError):
'''
+class RestoreTargetNotEmpty(obnamlib.ObnamError):
+
+ msg = '''The restore --to directory ({to}) is not empty.'''
+
+
class Hardlinks(object):
'''Keep track of inodes with unrestored hardlinks.'''
@@ -82,7 +87,8 @@ class RestorePlugin(obnamlib.ObnamPlugin):
arg_synopsis='[DIRECTORY]...')
self.app.settings.string(
['to'],
- 'where to restore or FUSE mount')
+ 'where to restore or FUSE mount; '
+ 'for restores, must be empty or must not exist')
self.app.settings.string_list(
['generation'],
'which generation to restore',
@@ -138,6 +144,11 @@ class RestorePlugin(obnamlib.ObnamPlugin):
self.fs = self.app.fsf.new(self.app.settings['to'], create=True)
self.fs.connect()
+ # The --to directory MUST be empty, to prevent users from
+ # accidentally restoring over /.
+ if self.fs.listdir('.') != []:
+ raise RestoreTargetNotEmpty(to=self.app.settings['to'])
+
# Set permissions on this directory to be quite
# restrictive, so that nobody else can access the files
# while the restore is happening. The directory named by
diff --git a/yarns/0030-basics.yarn b/yarns/0030-basics.yarn
index 4bc8439b..631177a3 100644
--- a/yarns/0030-basics.yarn
+++ b/yarns/0030-basics.yarn
@@ -200,6 +200,31 @@ the manifest to avoid getting an error.
AND user U restores file L/F to X from their latest generation in repository R
THEN L/F, restored to X, matches manifest M
+Restores must happen to a non-existent or an empty directory
+------------------------------------------------------------
+
+To avoid people doing unfortunate things such as `obnam restore
+--to=/` we make sure the target directory of restore either does not
+exist, or it's empty.
+
+ SCENARIO restore only to empty or new target
+ GIVEN 1kB of new data in directory L
+ AND a manifest of L in M
+ AND 0kB of new data in directory EMPTY
+ AND 2kB of new data in directory NOTEMPTY
+
+ WHEN user U backs up directory L to repository R
+ AND user U restores their latest generation in repository R into EMPTY
+ THEN L, restored to EMPTY, matches manifest M
+
+ WHEN user U restores their latest generation in repository R into NOTEXIST
+ THEN L, restored to NOTEXIST, matches manifest M
+
+ WHEN user U attempts to restore their latest generation
+ ... in repository R into NOTEMPTY
+ THEN the attempt failed with exit code 1
+
+
Pretend backing up: the `--pretend` setting
-------------------------------------------