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
This commit is contained in:
Daniel Reichelt 2016-03-17 01:40:17 +01:00
parent f0cb6379b7
commit e1f6a34820
7 changed files with 57 additions and 1 deletions

View File

@ -8,6 +8,7 @@ Borg Contributors ("The Borg Collective")
- Michael Hanselmann <public@hansmi.ch>
- Teemu Toivanen <public@profnetti.fi>
- Marian Beermann <public@enkore.de>
- Daniel Reichelt <hacking@nachtgeist.net>
Borg is a fork of Attic.

View File

@ -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)

View File

@ -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)

View File

@ -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|.

View File

@ -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

View File

@ -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``

View File

@ -262,6 +262,7 @@ setup(
entry_points={
'console_scripts': [
'borg = borg.archiver:main',
'borgfs = borg.archiver:main',
]
},
cmdclass=cmdclass,