-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfuse-cmd.py
executable file
·129 lines (116 loc) · 4.25 KB
/
fuse-cmd.py
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
#!/bin/sh
"""": # -*-python-*-
bup_python="$(dirname "$0")/bup-python" || exit $?
exec "$bup_python" "$0" ${1+"$@"}
"""
# end of bup preamble
from __future__ import absolute_import
import sys, os, errno
try:
import fuse
except ImportError:
log('error: cannot find the python "fuse" module; please install it\n')
sys.exit(1)
if not hasattr(fuse, '__version__'):
raise RuntimeError, "your fuse module is too old for fuse.__version__"
fuse.fuse_python_api = (0, 2)
from bup import options, git, vfs, xstat
from bup.helpers import log
from bup.repo import LocalRepo
# FIXME: self.meta and want_meta?
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):
global opt
if self.verbose > 0:
log('--getattr(%r)\n' % path)
res = vfs.lresolve(self.repo, path, want_meta=(not self.fake_metadata))
log('res: %r\n' % (res,))
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
st.st_gid = meta.gid
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):
assert not offset # We don't return offsets, so offset should be unused
res = vfs.lresolve(self.repo, path)
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):
yield fuse.Direntry(ent_name.replace('/', '-'))
def readlink(self, path):
if self.verbose > 0:
log('--readlink(%r)\n' % path)
res = vfs.lresolve(self.repo, path)
name, item = res[-1]
if not item:
return -errno.ENOENT
return vfs.readlink(repo, item)
def open(self, path, flags):
if self.verbose > 0:
log('--open(%r)\n' % path)
res = vfs.lresolve(self.repo, path)
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):
if self.verbose > 0:
log('--read(%r)\n' % path)
res = vfs.lresolve(self.repo, path)
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(sys.argv[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))
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()