From e1f6a3482065ccccaad36b83e19a8ed1dabceaef Mon Sep 17 00:00:00 2001 From: Daniel Reichelt Date: Thu, 17 Mar 2016 01:40:17 +0100 Subject: [PATCH] provide wrapper for borg mount, fixes #743 - add archiver.main_mount() - provide borgfs behaviour when the monolithic binary is called via a symlink called borgfs - docs: update usage of mount subcommand, provide examples for borgfs and add symlink creation to standalone binary installation - run build_usage - add entry point in setup.py - patch helpers.py:get_keys_dir() to allow mounting fstab entries with "user" option set Without this, setuid() called at some point by mount changes the HOME environment variable to '/root' and os.expanduser('~') would return '/root' as well, thus the mount would fail with PermissionError: [Errno 13] Permission denied: '/root/.config' After setuid(), the HOME variable stays intact, so we still can explicitly query USER's home. Also, os.path.expanduser() behaves differently for '~' and '~someuser' as parameters: when called with an explicit username, the possibly set environment variable HOME is no longer respected. So we have to check if it is set and only expand the user's home directory if HOME is unset. - add myself to AUTHORS --- AUTHORS | 1 + borg/archiver.py | 11 +++++++++++ borg/helpers.py | 12 +++++++++++- docs/installation.rst | 5 +++++ docs/usage.rst | 21 +++++++++++++++++++++ docs/usage/mount.rst.inc | 7 +++++++ setup.py | 1 + 7 files changed, 57 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 88a111641..f0a38701c 100644 --- a/AUTHORS +++ b/AUTHORS @@ -8,6 +8,7 @@ Borg Contributors ("The Borg Collective") - Michael Hanselmann - Teemu Toivanen - Marian Beermann +- Daniel Reichelt Borg is a fork of Attic. diff --git a/borg/archiver.py b/borg/archiver.py index b9dccbddf..1919a1c16 100644 --- a/borg/archiver.py +++ b/borg/archiver.py @@ -1347,6 +1347,13 @@ class Archiver: browsing an archive or restoring individual files. Unless the ``--foreground`` option is given the command will run in the background until the filesystem is ``umounted``. + + The command ``borgfs`` provides a wrapper for ``borg mount``. This can also be + used in fstab entries: + ``/path/to/repo /mnt/point fuse.borgfs defaults,noauto 0 0`` + + To allow a regular user to use fstab entries, add the ``user`` option: + ``/path/to/repo /mnt/point fuse.borgfs defaults,noauto,user 0 0`` """) subparser = subparsers.add_parser('mount', parents=[common_parser], description=self.do_mount.__doc__, @@ -1650,6 +1657,10 @@ def setup_signal_handlers(): # pragma: no cover def main(): # pragma: no cover + # provide 'borg mount' behaviour when the main script/executable is named borgfs + if os.path.basename(sys.argv[0]) == "borgfs": + sys.argv.insert(1, "mount") + # Make sure stdout and stderr have errors='replace') to avoid unicode # issues when print()-ing unicode file names sys.stdout = io.TextIOWrapper(sys.stdout.buffer, sys.stdout.encoding, 'replace', line_buffering=True) diff --git a/borg/helpers.py b/borg/helpers.py index 8c002d776..327953b2f 100644 --- a/borg/helpers.py +++ b/borg/helpers.py @@ -213,7 +213,17 @@ class Statistics: def get_keys_dir(): """Determine where to repository keys and cache""" - xdg_config = os.environ.get('XDG_CONFIG_HOME', os.path.join(os.path.expanduser('~'), '.config')) + + # os.path.expanduser() behaves differently for '~' and '~someuser' as + # parameters: when called with an explicit username, the possibly set + # environment variable HOME is no longer respected. So we have to check if + # it is set and only expand the user's home directory if HOME is unset. + if os.environ.get('HOME', ''): + home_dir = os.environ.get('HOME') + else: + home_dir = os.path.expanduser('~%s' % os.environ.get('USER')) + + xdg_config = os.environ.get('XDG_CONFIG_HOME', os.path.join(home_dir, '.config')) keys_dir = os.environ.get('BORG_KEYS_DIR', os.path.join(xdg_config, 'borg', 'keys')) if not os.path.exists(keys_dir): os.makedirs(keys_dir) diff --git a/docs/installation.rst b/docs/installation.rst index e6c5ac619..3e5946079 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -78,6 +78,11 @@ make borg readable and executable for its users and then you can run ``borg``:: sudo chown root:root /usr/local/bin/borg sudo chmod 755 /usr/local/bin/borg +Optionally you can create a symlink to have ``borgfs`` available, which is an +alias for ``borg mount``:: + + ln -s /usr/local/bin/borg /usr/local/bin/borgfs + Note that the binary uses /tmp to unpack |project_name| with all dependencies. It will fail if /tmp has not enough free space or is mounted with the ``noexec`` option. You can change the temporary directory by setting the ``TEMP`` environment variable before running |project_name|. diff --git a/docs/usage.rst b/docs/usage.rst index a016e008a..b8284e254 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -454,6 +454,8 @@ Examples Examples ~~~~~~~~ +borg mount/borgfs ++++++++++++++++++ :: $ borg mount /mnt/backup::root-2016-02-15 /tmp/mymountpoint @@ -461,6 +463,25 @@ Examples bin boot etc home lib lib64 lost+found media mnt opt root sbin srv tmp usr var $ fusermount -u /tmp/mymountpoint +borgfs +++++++ +:: + + $ echo '/mnt/backup /tmp/myrepo fuse.borgfs defaults,noauto 0 0' >> /etc/fstab + $ echo '/mnt/backup::root-2016-02-15 /tmp/myarchive fuse.borgfs defaults,noauto 0 0' >> /etc/fstab + $ mount /tmp/myrepo + $ mount /tmp/myarchive + $ ls /tmp/myrepo + root-2016-02-01 root-2016-02-2015 + $ ls /tmp/myarchive + bin boot etc home lib lib64 lost+found media mnt opt root sbin srv tmp usr var + +.. Note:: + + ``borgfs`` will be automatically provided if you used a distribution + package, ``pip`` or ``setup.py`` to install |project_name|. Users of the + standalone binary will have to manually create a symlink (see + :ref:`pyinstaller-binary`). .. include:: usage/change-passphrase.rst.inc diff --git a/docs/usage/mount.rst.inc b/docs/usage/mount.rst.inc index 380df549b..310fbc562 100644 --- a/docs/usage/mount.rst.inc +++ b/docs/usage/mount.rst.inc @@ -38,3 +38,10 @@ This command mounts an archive as a FUSE filesystem. This can be useful for browsing an archive or restoring individual files. Unless the ``--foreground`` option is given the command will run in the background until the filesystem is ``umounted``. + +The command ``borgfs`` provides a wrapper for ``borg mount``. This can also be +used in fstab entries: +``/path/to/repo /mnt/point fuse.borgfs defaults,noauto 0 0`` + +To allow a regular user to use fstab entries, add the ``user`` option: +``/path/to/repo /mnt/point fuse.borgfs defaults,noauto,user 0 0`` diff --git a/setup.py b/setup.py index 23d8b7cda..b9f647568 100644 --- a/setup.py +++ b/setup.py @@ -262,6 +262,7 @@ setup( entry_points={ 'console_scripts': [ 'borg = borg.archiver:main', + 'borgfs = borg.archiver:main', ] }, cmdclass=cmdclass,