Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fuse options (fwd port to master) #3843

Merged
merged 2 commits into from
May 18, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 45 additions & 14 deletions src/borg/fuse.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,12 +230,15 @@ def __init__(self, key, manifest, repository, args, decrypted_repository):
self.contents = defaultdict(dict)
self.default_uid = os.getuid()
self.default_gid = os.getgid()
self.default_dir = Item(mode=0o40755, mtime=int(time.time() * 1e9), uid=self.default_uid, gid=self.default_gid)
self.default_dir = None
# Archives to be loaded when first accessed, mapped by their placeholder inode
self.pending_archives = {}
self.cache = ItemCache(decrypted_repository)
self.allow_damaged_files = False
self.versions = False
self.uid_forced = None
self.gid_forced = None
self.umask = 0

def _create_filesystem(self):
self._create_dir(parent=1) # first call, create root dir (inode == 1)
Expand Down Expand Up @@ -443,19 +446,47 @@ def sig_info_handler(self, sig_no, stack):

def mount(self, mountpoint, mount_options, foreground=False):
"""Mount filesystem on *mountpoint* with *mount_options*."""

def pop_option(options, key, present, not_present, wanted_type, int_base=0):
assert isinstance(options, list) # we mutate this
for idx, option in enumerate(options):
if option == key:
options.pop(idx)
return present
if option.startswith(key + '='):
options.pop(idx)
value = option.split('=', 1)[1]
if wanted_type is bool:
v = value.lower()
if v in ('y', 'yes', 'true', '1'):
return True
if v in ('n', 'no', 'false', '0'):
return False
raise ValueError('unsupported value in option: %s' % option)
if wanted_type is int:
try:
return int(value, base=int_base)
except ValueError:
raise ValueError('unsupported value in option: %s' % option) from None
try:
return wanted_type(value)
except ValueError:
raise ValueError('unsupported value in option: %s' % option) from None
else:
return not_present

options = ['fsname=borgfs', 'ro']
if mount_options:
options.extend(mount_options.split(','))
try:
options.remove('allow_damaged_files')
self.allow_damaged_files = True
except ValueError:
pass
try:
options.remove('versions')
self.versions = True
except ValueError:
pass
self.allow_damaged_files = pop_option(options, 'allow_damaged_files', True, False, bool)
self.versions = pop_option(options, 'versions', True, False, bool)
self.uid_forced = pop_option(options, 'uid', None, None, int)
self.gid_forced = pop_option(options, 'gid', None, None, int)
self.umask = pop_option(options, 'umask', 0, 0, int, int_base=8) # umask is octal, e.g. 222 or 0222
dir_uid = self.uid_forced if self.uid_forced is not None else self.default_uid
dir_gid = self.gid_forced if self.gid_forced is not None else self.default_gid
dir_mode = 0o40755 & ~self.umask
self.default_dir = Item(mode=dir_mode, mtime=int(time.time() * 1e9), uid=dir_uid, gid=dir_gid)
self._create_filesystem()
llfuse.init(self, mountpoint, options)
if not foreground:
Expand Down Expand Up @@ -498,10 +529,10 @@ def getattr(self, inode, ctx=None):
entry.generation = 0
entry.entry_timeout = 300
entry.attr_timeout = 300
entry.st_mode = item.mode
entry.st_mode = item.mode & ~self.umask
entry.st_nlink = item.get('nlink', 1)
entry.st_uid = item.uid if item.uid >= 0 else self.default_uid
entry.st_gid = item.gid if item.gid >= 0 else self.default_gid
entry.st_uid = self.uid_forced if self.uid_forced is not None else item.uid if item.uid >= 0 else self.default_uid
entry.st_gid = self.gid_forced if self.gid_forced is not None else item.gid if item.gid >= 0 else self.default_gid
entry.st_rdev = item.get('rdev', 0)
entry.st_size = item.get_size()
entry.st_blksize = 512
Expand Down