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