--- /dev/null
+#!/bin/sh
+"""": # -*-python-*-
+# https://sourceware.org/bugzilla/show_bug.cgi?id=26034
+export "BUP_ARGV_0"="$0"
+arg_i=1
+for arg in "$@"; do
+ export "BUP_ARGV_${arg_i}"="$arg"
+ shift
+ arg_i=$((arg_i + 1))
+done
+# Here to end of preamble replaced during install
+bup_python="$(dirname "$0")/../../../config/bin/python" || exit $?
+exec "$bup_python" "$0"
+"""
+# end of bup preamble
+
+from __future__ import absolute_import, print_function
+
+# Intentionally replace the dirname "$0" that python prepends
+import os, sys
+sys.path[0] = os.path.dirname(os.path.realpath(__file__)) + '/../..'
+
+import errno
+
+try:
+ import fuse
+except ImportError:
+ print('error: cannot find the python "fuse" module; please install it',
+ file=sys.stderr)
+ sys.exit(2)
+if not hasattr(fuse, '__version__'):
+ print('error: fuse module is too old for fuse.__version__', file=sys.stderr)
+ sys.exit(2)
+fuse.fuse_python_api = (0, 2)
+
+if sys.version_info[0] > 2:
+ try:
+ fuse_ver = fuse.__version__.split('.')
+ fuse_ver_maj = int(fuse_ver[0])
+ except:
+ log('error: cannot determine the fuse major version; please report',
+ file=sys.stderr)
+ sys.exit(2)
+ if len(fuse_ver) < 3 or fuse_ver_maj < 1:
+ print("error: fuse module can't handle binary data; please upgrade to 1.0+\n",
+ file=sys.stderr)
+ sys.exit(2)
+
+from bup import compat, options, git, vfs, xstat
+from bup.compat import argv_bytes, fsdecode, py_maj
+from bup.helpers import log
+from bup.repo import LocalRepo
+
+
+# FIXME: self.meta and want_meta?
+
+# The path handling is just wrong, but the current fuse module can't
+# handle bytes paths.
+
+class BupFs(fuse.Fuse):
+ def __init__(self, repo, verbose=0, fake_metadata=False):
+ fuse.Fuse.__init__(self)
+ self.repo = repo
+ self.verbose = verbose
+ self.fake_metadata = fake_metadata
+
+ def getattr(self, path):
+ path = argv_bytes(path)
+ global opt
+ if self.verbose > 0:
+ log('--getattr(%r)\n' % path)
+ res = vfs.resolve(self.repo, path, want_meta=(not self.fake_metadata),
+ follow=False)
+ name, item = res[-1]
+ if not item:
+ return -errno.ENOENT
+ if self.fake_metadata:
+ item = vfs.augment_item_meta(self.repo, item, include_size=True)
+ else:
+ item = vfs.ensure_item_has_metadata(self.repo, item,
+ include_size=True)
+ meta = item.meta
+ # FIXME: do we want/need to do anything more with nlink?
+ st = fuse.Stat(st_mode=meta.mode, st_nlink=1, st_size=meta.size)
+ st.st_mode = meta.mode
+ st.st_uid = meta.uid or 0
+ st.st_gid = meta.gid or 0
+ st.st_atime = max(0, xstat.fstime_floor_secs(meta.atime))
+ st.st_mtime = max(0, xstat.fstime_floor_secs(meta.mtime))
+ st.st_ctime = max(0, xstat.fstime_floor_secs(meta.ctime))
+ return st
+
+ def readdir(self, path, offset):
+ path = argv_bytes(path)
+ assert not offset # We don't return offsets, so offset should be unused
+ res = vfs.resolve(self.repo, path, follow=False)
+ dir_name, dir_item = res[-1]
+ if not dir_item:
+ yield -errno.ENOENT
+ yield fuse.Direntry('..')
+ # FIXME: make sure want_meta=False is being completely respected
+ for ent_name, ent_item in vfs.contents(repo, dir_item, want_meta=False):
+ fusename = fsdecode(ent_name.replace(b'/', b'-'))
+ yield fuse.Direntry(fusename)
+
+ def readlink(self, path):
+ path = argv_bytes(path)
+ if self.verbose > 0:
+ log('--readlink(%r)\n' % path)
+ res = vfs.resolve(self.repo, path, follow=False)
+ name, item = res[-1]
+ if not item:
+ return -errno.ENOENT
+ return fsdecode(vfs.readlink(repo, item))
+
+ def open(self, path, flags):
+ path = argv_bytes(path)
+ if self.verbose > 0:
+ log('--open(%r)\n' % path)
+ res = vfs.resolve(self.repo, path, follow=False)
+ name, item = res[-1]
+ if not item:
+ return -errno.ENOENT
+ accmode = os.O_RDONLY | os.O_WRONLY | os.O_RDWR
+ if (flags & accmode) != os.O_RDONLY:
+ return -errno.EACCES
+ # Return None since read doesn't need the file atm...
+ # If we *do* return the file, it'll show up as the last argument
+ #return vfs.fopen(repo, item)
+
+ def read(self, path, size, offset):
+ path = argv_bytes(path)
+ if self.verbose > 0:
+ log('--read(%r)\n' % path)
+ res = vfs.resolve(self.repo, path, follow=False)
+ name, item = res[-1]
+ if not item:
+ return -errno.ENOENT
+ with vfs.fopen(repo, item) as f:
+ f.seek(offset)
+ return f.read(size)
+
+
+optspec = """
+bup fuse [-d] [-f] <mountpoint>
+--
+f,foreground run in foreground
+d,debug run in the foreground and display FUSE debug information
+o,allow-other allow other users to access the filesystem
+meta report original metadata for paths when available
+v,verbose increase log output (can be used more than once)
+"""
+o = options.Options(optspec)
+opt, flags, extra = o.parse(compat.argv[1:])
+if not opt.verbose:
+ opt.verbose = 0
+
+# Set stderr to be line buffered, even if it's not connected to the console
+# so that we'll be able to see diagnostics in a timely fashion.
+errfd = sys.stderr.fileno()
+sys.stderr.flush()
+sys.stderr = os.fdopen(errfd, 'w', 1)
+
+if len(extra) != 1:
+ o.fatal('only one mount point argument expected')
+
+git.check_repo_or_die()
+repo = LocalRepo()
+f = BupFs(repo=repo, verbose=opt.verbose, fake_metadata=(not opt.meta))
+
+# This is likely wrong, but the fuse module doesn't currently accept bytes
+f.fuse_args.mountpoint = extra[0]
+
+if opt.debug:
+ f.fuse_args.add('debug')
+if opt.foreground:
+ f.fuse_args.setmod('foreground')
+f.multithreaded = False
+if opt.allow_other:
+ f.fuse_args.add('allow_other')
+f.main()
+++ /dev/null
-#!/bin/sh
-"""": # -*-python-*-
-# https://sourceware.org/bugzilla/show_bug.cgi?id=26034
-export "BUP_ARGV_0"="$0"
-arg_i=1
-for arg in "$@"; do
- export "BUP_ARGV_${arg_i}"="$arg"
- shift
- arg_i=$((arg_i + 1))
-done
-# Here to end of preamble replaced during install
-bup_python="$(dirname "$0")/../../config/bin/python" || exit $?
-exec "$bup_python" "$0"
-"""
-# end of bup preamble
-
-from __future__ import absolute_import, print_function
-
-# Intentionally replace the dirname "$0" that python prepends
-import os, sys
-sys.path[0] = os.path.dirname(os.path.realpath(__file__)) + '/..'
-
-import errno
-
-try:
- import fuse
-except ImportError:
- print('error: cannot find the python "fuse" module; please install it',
- file=sys.stderr)
- sys.exit(2)
-if not hasattr(fuse, '__version__'):
- print('error: fuse module is too old for fuse.__version__', file=sys.stderr)
- sys.exit(2)
-fuse.fuse_python_api = (0, 2)
-
-if sys.version_info[0] > 2:
- try:
- fuse_ver = fuse.__version__.split('.')
- fuse_ver_maj = int(fuse_ver[0])
- except:
- log('error: cannot determine the fuse major version; please report',
- file=sys.stderr)
- sys.exit(2)
- if len(fuse_ver) < 3 or fuse_ver_maj < 1:
- print("error: fuse module can't handle binary data; please upgrade to 1.0+\n",
- file=sys.stderr)
- sys.exit(2)
-
-from bup import compat, options, git, vfs, xstat
-from bup.compat import argv_bytes, fsdecode, py_maj
-from bup.helpers import log
-from bup.repo import LocalRepo
-
-
-# FIXME: self.meta and want_meta?
-
-# The path handling is just wrong, but the current fuse module can't
-# handle bytes paths.
-
-class BupFs(fuse.Fuse):
- def __init__(self, repo, verbose=0, fake_metadata=False):
- fuse.Fuse.__init__(self)
- self.repo = repo
- self.verbose = verbose
- self.fake_metadata = fake_metadata
-
- def getattr(self, path):
- path = argv_bytes(path)
- global opt
- if self.verbose > 0:
- log('--getattr(%r)\n' % path)
- res = vfs.resolve(self.repo, path, want_meta=(not self.fake_metadata),
- follow=False)
- name, item = res[-1]
- if not item:
- return -errno.ENOENT
- if self.fake_metadata:
- item = vfs.augment_item_meta(self.repo, item, include_size=True)
- else:
- item = vfs.ensure_item_has_metadata(self.repo, item,
- include_size=True)
- meta = item.meta
- # FIXME: do we want/need to do anything more with nlink?
- st = fuse.Stat(st_mode=meta.mode, st_nlink=1, st_size=meta.size)
- st.st_mode = meta.mode
- st.st_uid = meta.uid or 0
- st.st_gid = meta.gid or 0
- st.st_atime = max(0, xstat.fstime_floor_secs(meta.atime))
- st.st_mtime = max(0, xstat.fstime_floor_secs(meta.mtime))
- st.st_ctime = max(0, xstat.fstime_floor_secs(meta.ctime))
- return st
-
- def readdir(self, path, offset):
- path = argv_bytes(path)
- assert not offset # We don't return offsets, so offset should be unused
- res = vfs.resolve(self.repo, path, follow=False)
- dir_name, dir_item = res[-1]
- if not dir_item:
- yield -errno.ENOENT
- yield fuse.Direntry('..')
- # FIXME: make sure want_meta=False is being completely respected
- for ent_name, ent_item in vfs.contents(repo, dir_item, want_meta=False):
- fusename = fsdecode(ent_name.replace(b'/', b'-'))
- yield fuse.Direntry(fusename)
-
- def readlink(self, path):
- path = argv_bytes(path)
- if self.verbose > 0:
- log('--readlink(%r)\n' % path)
- res = vfs.resolve(self.repo, path, follow=False)
- name, item = res[-1]
- if not item:
- return -errno.ENOENT
- return fsdecode(vfs.readlink(repo, item))
-
- def open(self, path, flags):
- path = argv_bytes(path)
- if self.verbose > 0:
- log('--open(%r)\n' % path)
- res = vfs.resolve(self.repo, path, follow=False)
- name, item = res[-1]
- if not item:
- return -errno.ENOENT
- accmode = os.O_RDONLY | os.O_WRONLY | os.O_RDWR
- if (flags & accmode) != os.O_RDONLY:
- return -errno.EACCES
- # Return None since read doesn't need the file atm...
- # If we *do* return the file, it'll show up as the last argument
- #return vfs.fopen(repo, item)
-
- def read(self, path, size, offset):
- path = argv_bytes(path)
- if self.verbose > 0:
- log('--read(%r)\n' % path)
- res = vfs.resolve(self.repo, path, follow=False)
- name, item = res[-1]
- if not item:
- return -errno.ENOENT
- with vfs.fopen(repo, item) as f:
- f.seek(offset)
- return f.read(size)
-
-
-optspec = """
-bup fuse [-d] [-f] <mountpoint>
---
-f,foreground run in foreground
-d,debug run in the foreground and display FUSE debug information
-o,allow-other allow other users to access the filesystem
-meta report original metadata for paths when available
-v,verbose increase log output (can be used more than once)
-"""
-o = options.Options(optspec)
-opt, flags, extra = o.parse(compat.argv[1:])
-if not opt.verbose:
- opt.verbose = 0
-
-# Set stderr to be line buffered, even if it's not connected to the console
-# so that we'll be able to see diagnostics in a timely fashion.
-errfd = sys.stderr.fileno()
-sys.stderr.flush()
-sys.stderr = os.fdopen(errfd, 'w', 1)
-
-if len(extra) != 1:
- o.fatal('only one mount point argument expected')
-
-git.check_repo_or_die()
-repo = LocalRepo()
-f = BupFs(repo=repo, verbose=opt.verbose, fake_metadata=(not opt.meta))
-
-# This is likely wrong, but the fuse module doesn't currently accept bytes
-f.fuse_args.mountpoint = extra[0]
-
-if opt.debug:
- f.fuse_args.add('debug')
-if opt.foreground:
- f.fuse_args.setmod('foreground')
-f.multithreaded = False
-if opt.allow_other:
- f.fuse_args.add('allow_other')
-f.main()