diff --git a/borg/archiver.py b/borg/archiver.py index 07086709b..ecc44be76 100644 --- a/borg/archiver.py +++ b/borg/archiver.py @@ -34,6 +34,7 @@ from .keymanager import KeyManager from .archive import backup_io, BackupOSError, Archive, ArchiveChecker, CHUNKER_PARAMS, is_special from .remote import RepositoryServer, RemoteRepository, cache_if_remote +from .platform import umount has_lchflags = hasattr(os, 'lchflags') @@ -539,6 +540,10 @@ def do_mount(self, args, repository, manifest, key): self.exit_code = EXIT_ERROR return self.exit_code + def do_umount(self, args): + """un-mount the FUSE filesystem""" + return umount(args.mountpoint) + @with_repository() def do_list(self, args, repository, manifest, key): """List archive or repository contents""" @@ -1476,6 +1481,21 @@ def build_parser(self, args=None, prog=None): subparser.add_argument('-o', dest='options', type=str, help='Extra mount options') + umount_epilog = textwrap.dedent(""" + This command un-mounts a FUSE filesystem that was mounted with ``borg mount``. + + This is a convenience wrapper that just calls the platform-specific shell + command - usually this is either umount or fusermount -u. + """) + subparser = subparsers.add_parser('umount', parents=[common_parser], + description=self.do_umount.__doc__, + epilog=umount_epilog, + formatter_class=argparse.RawDescriptionHelpFormatter, + help='umount repository') + subparser.set_defaults(func=self.do_umount) + subparser.add_argument('mountpoint', metavar='MOUNTPOINT', type=str, + help='mountpoint of the filesystem to umount') + info_epilog = textwrap.dedent(""" This command displays some detailed information about the specified archive. diff --git a/borg/helpers.py b/borg/helpers.py index a4469c990..72129f08e 100644 --- a/borg/helpers.py +++ b/borg/helpers.py @@ -88,7 +88,7 @@ def check_extension_modules(): raise ExtensionModuleError if crypto.API_VERSION != 2: raise ExtensionModuleError - if platform.API_VERSION != 2: + if platform.API_VERSION != 3: raise ExtensionModuleError diff --git a/borg/platform.py b/borg/platform.py index e1cffd87a..be7a2bcd1 100644 --- a/borg/platform.py +++ b/borg/platform.py @@ -1,5 +1,6 @@ import errno import os +import subprocess import sys @@ -17,14 +18,19 @@ def sync_dir(path): os.close(fd) +# most POSIX platforms (but not Linux), see also borg 1.1 platform.base +def umount(mountpoint): + return subprocess.call(['umount', mountpoint]) + + if sys.platform.startswith('linux'): # pragma: linux only - from .platform_linux import acl_get, acl_set, API_VERSION + from .platform_linux import acl_get, acl_set, umount, API_VERSION elif sys.platform.startswith('freebsd'): # pragma: freebsd only from .platform_freebsd import acl_get, acl_set, API_VERSION elif sys.platform == 'darwin': # pragma: darwin only from .platform_darwin import acl_get, acl_set, API_VERSION else: # pragma: unknown platform only - API_VERSION = 2 + API_VERSION = 3 def acl_get(path, item, st, numeric_owner=False): pass diff --git a/borg/platform_darwin.pyx b/borg/platform_darwin.pyx index edb41f715..4dc25b83a 100644 --- a/borg/platform_darwin.pyx +++ b/borg/platform_darwin.pyx @@ -1,7 +1,7 @@ import os from .helpers import user2uid, group2gid, safe_decode, safe_encode -API_VERSION = 2 +API_VERSION = 3 cdef extern from "sys/acl.h": ctypedef struct _acl_t: diff --git a/borg/platform_freebsd.pyx b/borg/platform_freebsd.pyx index 27d636263..ae69af68a 100644 --- a/borg/platform_freebsd.pyx +++ b/borg/platform_freebsd.pyx @@ -1,7 +1,7 @@ import os from .helpers import posix_acl_use_stored_uid_gid, safe_encode, safe_decode -API_VERSION = 2 +API_VERSION = 3 cdef extern from "errno.h": int errno diff --git a/borg/platform_linux.pyx b/borg/platform_linux.pyx index f9ed42415..0185268c1 100644 --- a/borg/platform_linux.pyx +++ b/borg/platform_linux.pyx @@ -1,9 +1,10 @@ import os import re +import subprocess from stat import S_ISLNK from .helpers import posix_acl_use_stored_uid_gid, user2uid, group2gid, safe_decode, safe_encode -API_VERSION = 2 +API_VERSION = 3 cdef extern from "sys/types.h": int ACL_TYPE_ACCESS @@ -141,3 +142,7 @@ def acl_set(path, item, numeric_owner=False): acl_set_file(p, ACL_TYPE_DEFAULT, default_acl) finally: acl_free(default_acl) + + +def umount(mountpoint): + return subprocess.call(['fusermount', '-u', mountpoint]) diff --git a/borg/testsuite/__init__.py b/borg/testsuite/__init__.py index 42b935d1e..8d757d2bd 100644 --- a/borg/testsuite/__init__.py +++ b/borg/testsuite/__init__.py @@ -9,6 +9,7 @@ import unittest from ..xattr import get_all from ..logger import setup_logging +from ..platform import umount try: import llfuse @@ -110,11 +111,7 @@ def fuse_mount(self, location, mountpoint, *options): self.cmd(*args, fork=True) self.wait_for_mount(mountpoint) yield - if sys.platform.startswith('linux'): - cmd = 'fusermount -u %s' % mountpoint - else: - cmd = 'umount %s' % mountpoint - os.system(cmd) + umount(mountpoint) os.rmdir(mountpoint) # Give the daemon some time to exit time.sleep(.2) diff --git a/docs/usage.rst b/docs/usage.rst index 8743f6ac0..2a3538b22 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -545,6 +545,8 @@ Examples .. include:: usage/mount.rst.inc +.. include:: usage/umount.rst.inc + Examples ~~~~~~~~ :: @@ -552,7 +554,7 @@ Examples $ borg mount /path/to/repo::root-2016-02-15 /tmp/mymountpoint $ ls /tmp/mymountpoint bin boot etc home lib lib64 lost+found media mnt opt root sbin srv tmp usr var - $ fusermount -u /tmp/mymountpoint + $ borg umount /tmp/mymountpoint .. include:: usage/key_export.rst.inc diff --git a/docs/usage/umount.rst.inc b/docs/usage/umount.rst.inc new file mode 100644 index 000000000..febacda06 --- /dev/null +++ b/docs/usage/umount.rst.inc @@ -0,0 +1,40 @@ +.. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit! + +.. _borg_umount: + +borg umount +----------- +:: + + usage: borg umount [-h] [--critical] [--error] [--warning] [--info] [--debug] + [--lock-wait N] [--show-rc] [--no-files-cache] [--umask M] + [--remote-path PATH] + MOUNTPOINT + + un-mount the FUSE filesystem + + positional arguments: + MOUNTPOINT mountpoint of the filesystem to umount + + optional arguments: + -h, --help show this help message and exit + --critical work on log level CRITICAL + --error work on log level ERROR + --warning work on log level WARNING (default) + --info, -v, --verbose + work on log level INFO + --debug work on log level DEBUG + --lock-wait N wait for the lock, but max. N seconds (default: 1). + --show-rc show/log the return code (rc) + --no-files-cache do not load/update the file metadata cache used to + detect unchanged files + --umask M set umask to M (local and remote, default: 0077) + --remote-path PATH set remote path to executable (default: "borg") + +Description +~~~~~~~~~~~ + +This command un-mounts a FUSE filesystem that was mounted with ``borg mount``. + +This is a convenience wrapper that just calls the platform-specific shell +command - usually this is either umount or fusermount -u.