1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
#!/usr/bin/env python
import sys, os, errno
from bup import options, git, vfs
from bup.helpers import *
try:
import fuse
except ImportError:
log('bup: error: The python "fuse" module is missing.\n' +
'To use bup fuse, first install the python-fuse package.\n')
sys.exit(1)
class Stat(fuse.Stat):
def __init__(self):
self.st_mode = 0
self.st_ino = 0
self.st_dev = 0
self.st_nlink = 0
self.st_uid = 0
self.st_gid = 0
self.st_size = 0
self.st_atime = 0
self.st_mtime = 0
self.st_ctime = 0
self.st_blocks = 0
self.st_blksize = 0
self.st_rdev = 0
cache = {}
def cache_get(top, path):
parts = path.split('/')
cache[('',)] = top
c = None
max = len(parts)
#log('cache: %r\n' % cache.keys())
for i in range(max):
pre = parts[:max-i]
#log('cache trying: %r\n' % pre)
c = cache.get(tuple(pre))
if c:
rest = parts[max-i:]
for r in rest:
#log('resolving %r from %r\n' % (r, c.fullname()))
c = c.lresolve(r)
key = tuple(pre + [r])
#log('saving: %r\n' % (key,))
cache[key] = c
break
assert(c)
return c
class BupFs(fuse.Fuse):
def __init__(self, top):
fuse.Fuse.__init__(self)
self.top = top
def getattr(self, path):
log('--getattr(%r)\n' % path)
try:
node = cache_get(self.top, path)
st = Stat()
st.st_mode = node.mode
st.st_nlink = node.nlinks()
st.st_size = node.size()
st.st_mtime = node.mtime
st.st_ctime = node.ctime
st.st_atime = node.atime
return st
except vfs.NoSuchFile:
return -errno.ENOENT
def readdir(self, path, offset):
log('--readdir(%r)\n' % path)
node = cache_get(self.top, path)
yield fuse.Direntry('.')
yield fuse.Direntry('..')
for sub in node.subs():
yield fuse.Direntry(sub.name)
def readlink(self, path):
log('--readlink(%r)\n' % path)
node = cache_get(self.top, path)
return node.readlink()
def open(self, path, flags):
log('--open(%r)\n' % path)
node = cache_get(self.top, path)
accmode = os.O_RDONLY | os.O_WRONLY | os.O_RDWR
if (flags & accmode) != os.O_RDONLY:
return -errno.EACCES
node.open()
def release(self, path, flags):
log('--release(%r)\n' % path)
def read(self, path, size, offset):
log('--read(%r)\n' % path)
n = cache_get(self.top, path)
o = n.open()
o.seek(offset)
return o.read(size)
if not hasattr(fuse, '__version__'):
raise RuntimeError, "your fuse module is too old for fuse.__version__"
fuse.fuse_python_api = (0, 2)
optspec = """
bup fuse [-d] [-f] <mountpoint>
--
d,debug increase debug level
f,foreground run in foreground
o,allow-other allow other users to access the filesystem
"""
o = options.Options('bup fuse', optspec)
(opt, flags, extra) = o.parse(sys.argv[1:])
if len(extra) != 1:
o.fatal("exactly one argument expected")
git.check_repo_or_die()
top = vfs.RefList(None)
f = BupFs(top)
f.fuse_args.mountpoint = extra[0]
if opt.debug:
f.fuse_args.add('debug')
if opt.foreground:
f.fuse_args.setmod('foreground')
print f.multithreaded
f.multithreaded = False
if opt.allow_other:
f.fuse_args.add('allow_other')
f.main()
|