]> arthur.barton.de Git - bup.git/blob - cmd/fuse-cmd.py
fuse: add --verbose argument and use it
[bup.git] / cmd / fuse-cmd.py
1 #!/bin/sh
2 """": # -*-python-*-
3 bup_python="$(dirname "$0")/bup-python" || exit $?
4 exec "$bup_python" "$0" ${1+"$@"}
5 """
6 # end of bup preamble
7
8 import sys, os, errno
9
10 from bup import options, git, vfs, xstat
11 from bup.helpers import buglvl, log
12
13 try:
14     import fuse
15 except ImportError:
16     log('error: cannot find the python "fuse" module; please install it\n')
17     sys.exit(1)
18
19
20 class Stat(fuse.Stat):
21     def __init__(self):
22         self.st_mode = 0
23         self.st_ino = 0
24         self.st_dev = 0
25         self.st_nlink = 0
26         self.st_uid = 0
27         self.st_gid = 0
28         self.st_size = 0
29         self.st_atime = 0
30         self.st_mtime = 0
31         self.st_ctime = 0
32         self.st_blocks = 0
33         self.st_blksize = 0
34         self.st_rdev = 0
35
36
37 cache = {}
38 def cache_get(top, path):
39     parts = path.split('/')
40     cache[('',)] = top
41     c = None
42     max = len(parts)
43     if buglvl >= 1:
44         log('cache: %r\n' % cache.keys())
45     for i in range(max):
46         pre = parts[:max-i]
47         if buglvl >= 1:
48             log('cache trying: %r\n' % pre)
49         c = cache.get(tuple(pre))
50         if c:
51             rest = parts[max-i:]
52             for r in rest:
53                 if buglvl >= 1:
54                     log('resolving %r from %r\n' % (r, c.fullname()))
55                 c = c.lresolve(r)
56                 key = tuple(pre + [r])
57                 if buglvl >= 1:
58                     log('saving: %r\n' % (key,))
59                 cache[key] = c
60             break
61     assert(c)
62     return c
63
64
65 class BupFs(fuse.Fuse):
66     def __init__(self, top, meta=False, verbose=0):
67         fuse.Fuse.__init__(self)
68         self.top = top
69         self.meta = meta
70         self.verbose = verbose
71     
72     def getattr(self, path):
73         if self.verbose > 0:
74             log('--getattr(%r)\n' % path)
75         try:
76             node = cache_get(self.top, path)
77             st = Stat()
78             st.st_mode = node.mode
79             st.st_nlink = node.nlinks()
80             st.st_size = node.size()  # Until/unless we store the size in m.
81             if self.meta:
82                 m = node.metadata()
83                 if m:
84                     st.st_mode = m.mode
85                     st.st_uid = m.uid
86                     st.st_gid = m.gid
87                     st.st_atime = max(0, xstat.fstime_floor_secs(m.atime))
88                     st.st_mtime = max(0, xstat.fstime_floor_secs(m.mtime))
89                     st.st_ctime = max(0, xstat.fstime_floor_secs(m.ctime))
90             return st
91         except vfs.NoSuchFile:
92             return -errno.ENOENT
93
94     def readdir(self, path, offset):
95         if self.verbose > 0:
96             log('--readdir(%r)\n' % path)
97         node = cache_get(self.top, path)
98         yield fuse.Direntry('.')
99         yield fuse.Direntry('..')
100         for sub in node.subs():
101             yield fuse.Direntry(sub.name)
102
103     def readlink(self, path):
104         if self.verbose > 0:
105             log('--readlink(%r)\n' % path)
106         node = cache_get(self.top, path)
107         return node.readlink()
108
109     def open(self, path, flags):
110         if self.verbose > 0:
111             log('--open(%r)\n' % path)
112         node = cache_get(self.top, path)
113         accmode = os.O_RDONLY | os.O_WRONLY | os.O_RDWR
114         if (flags & accmode) != os.O_RDONLY:
115             return -errno.EACCES
116         node.open()
117
118     def release(self, path, flags):
119         if self.verbose > 0:
120             log('--release(%r)\n' % path)
121
122     def read(self, path, size, offset):
123         if self.verbose > 0:
124             log('--read(%r)\n' % path)
125         n = cache_get(self.top, path)
126         o = n.open()
127         o.seek(offset)
128         return o.read(size)
129
130
131 if not hasattr(fuse, '__version__'):
132     raise RuntimeError, "your fuse module is too old for fuse.__version__"
133 fuse.fuse_python_api = (0, 2)
134
135
136 optspec = """
137 bup fuse [-d] [-f] <mountpoint>
138 --
139 f,foreground  run in foreground
140 d,debug       run in the foreground and display FUSE debug information
141 o,allow-other allow other users to access the filesystem
142 meta          report original metadata for paths when available
143 v,verbose     increase log output (can be used more than once)
144 """
145 o = options.Options(optspec)
146 (opt, flags, extra) = o.parse(sys.argv[1:])
147
148 if len(extra) != 1:
149     o.fatal("exactly one argument expected")
150
151 git.check_repo_or_die()
152 top = vfs.RefList(None)
153 f = BupFs(top, meta=opt.meta, verbose=opt.verbose)
154 f.fuse_args.mountpoint = extra[0]
155 if opt.debug:
156     f.fuse_args.add('debug')
157 if opt.foreground:
158     f.fuse_args.setmod('foreground')
159 print f.multithreaded
160 f.multithreaded = False
161 if opt.allow_other:
162     f.fuse_args.add('allow_other')
163
164 f.main()