mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2024-12-23 06:42:26 +00:00
6f5ccb1707
the mac/macfuse subdirectory needed to be added to the pythonpath in order to build a binary incorporating the mac fuse system. this change should make those modules accessible relative to the mac/ directory which is implicitly included in the .app build process.
714 lines
22 KiB
Python
714 lines
22 KiB
Python
#!/usr/bin/env python
|
|
|
|
#-----------------------------------------------------------------------------------------------
|
|
from allmydata.uri import CHKFileURI, NewDirectoryURI, LiteralFileURI
|
|
from allmydata.scripts.common_http import do_http as do_http_req
|
|
|
|
import base64
|
|
import sha
|
|
import sys
|
|
import os
|
|
import errno
|
|
import stat
|
|
# pull in some spaghetti to make this stuff work without fuse-py being installed
|
|
try:
|
|
import _find_fuse_parts
|
|
junk = _find_fuse_parts
|
|
del junk
|
|
except ImportError:
|
|
pass
|
|
import fuse
|
|
|
|
import time
|
|
import traceback
|
|
import simplejson
|
|
import urllib
|
|
|
|
USAGE = 'usage: tahoe fuse [dir_cap_name] [fuse_options] mountpoint'
|
|
|
|
if not hasattr(fuse, '__version__'):
|
|
raise RuntimeError, \
|
|
"your fuse-py doesn't know of fuse.__version__, probably it's too old."
|
|
|
|
fuse.fuse_python_api = (0, 2)
|
|
fuse.feature_assert('stateful_files', 'has_init')
|
|
|
|
|
|
logfile = file('tfuse.log', 'wb')
|
|
|
|
def log(msg):
|
|
logfile.write("%s: %s\n" % (time.asctime(), msg))
|
|
#time.sleep(0.1)
|
|
logfile.flush()
|
|
|
|
fuse.flog = log
|
|
|
|
def do_http(method, url, body=''):
|
|
resp = do_http_req(method, url, body)
|
|
log('do_http(%s, %s) -> %s, %s' % (method, url, resp.status, resp.reason))
|
|
if resp.status not in (200, 201):
|
|
raise RuntimeError('http response (%s, %s)' % (resp.status, resp.reason))
|
|
else:
|
|
return resp.read()
|
|
|
|
def flag2mode(flags):
|
|
log('flag2mode(%r)' % (flags,))
|
|
#md = {os.O_RDONLY: 'r', os.O_WRONLY: 'w', os.O_RDWR: 'w+'}
|
|
md = {os.O_RDONLY: 'rb', os.O_WRONLY: 'wb', os.O_RDWR: 'w+b'}
|
|
m = md[flags & (os.O_RDONLY | os.O_WRONLY | os.O_RDWR)]
|
|
|
|
if flags | os.O_APPEND:
|
|
m = m.replace('w', 'a', 1)
|
|
|
|
return m
|
|
|
|
def logargsretexc(meth):
|
|
def inner(self, *args, **kwargs):
|
|
log("%s(%r, %r)" % (meth, args, kwargs))
|
|
try:
|
|
ret = meth(self, *args, **kwargs)
|
|
except:
|
|
log('exception:\n%s' % (traceback.format_exc(),))
|
|
raise
|
|
log("ret: %r" % (ret, ))
|
|
return ret
|
|
inner.__name__ = '<logwrap(%s)>' % (meth,)
|
|
return inner
|
|
|
|
def logexc(meth):
|
|
def inner(self, *args, **kwargs):
|
|
try:
|
|
ret = meth(self, *args, **kwargs)
|
|
except:
|
|
log('exception:\n%s' % (traceback.format_exc(),))
|
|
raise
|
|
return ret
|
|
inner.__name__ = '<logwrap(%s)>' % (meth,)
|
|
return inner
|
|
|
|
def log_exc():
|
|
log('exception:\n%s' % (traceback.format_exc(),))
|
|
|
|
class TahoeFuseFile(object):
|
|
|
|
def __init__(self, path, flags, *mode):
|
|
log("TFF: __init__(%r, %r, %r)" % (path, flags, mode))
|
|
|
|
self._path = path # for tahoe put
|
|
try:
|
|
self.parent, self.name, self.fnode = self.tfs.get_parent_name_and_child(path)
|
|
m = flag2mode(flags)
|
|
log('TFF: flags2(mode) -> %s' % (m,))
|
|
if m[0] in 'wa':
|
|
# write
|
|
self.fname = self.tfs.cache.tmp_file(os.urandom(20))
|
|
if self.fnode is None:
|
|
log('TFF: [%s] open(%s) for write: no such file, creating new File' % (self.name, self.fname, ))
|
|
self.fnode = File(0, None, None)
|
|
self.fnode.tmp_fname = self.fname # XXX kill this
|
|
self.parent.add_child(self.name, self.fnode)
|
|
elif hasattr(self.fnode, 'tmp_fname'):
|
|
self.fname = self.fnode.tmp_fname
|
|
self.file = os.fdopen(os.open(self.fname, flags, *mode), m)
|
|
self.fd = self.file.fileno()
|
|
log('TFF: opened(%s) for write' % self.fname)
|
|
self.open_for_write = True
|
|
else:
|
|
# read
|
|
assert self.fnode is not None
|
|
uri = self.fnode.get_uri()
|
|
|
|
# XXX make this go away
|
|
if hasattr(self.fnode, 'tmp_fname'):
|
|
self.fname = self.fnode.tmp_fname
|
|
log('TFF: reopening(%s) for reading' % self.fname)
|
|
else:
|
|
log('TFF: fetching file from cache for reading')
|
|
self.fname = self.tfs.cache.get_file(uri)
|
|
|
|
self.file = os.fdopen(os.open(self.fname, flags, *mode), m)
|
|
self.fd = self.file.fileno()
|
|
self.open_for_write = False
|
|
log('TFF: opened(%s) for read' % self.fname)
|
|
except:
|
|
log_exc()
|
|
raise
|
|
|
|
def log(self, msg):
|
|
log("<TFF(%s:%s)> %s" % (os.path.basename(self.fname), self.name, msg))
|
|
|
|
@logexc
|
|
def read(self, size, offset):
|
|
self.log('read(%r, %r)' % (size, offset, ))
|
|
self.file.seek(offset)
|
|
return self.file.read(size)
|
|
|
|
@logexc
|
|
def write(self, buf, offset):
|
|
self.log("write(-%s-, %r)" % (len(buf), offset))
|
|
if not self.open_for_write:
|
|
return -errno.EACCES
|
|
self.file.seek(offset)
|
|
self.file.write(buf)
|
|
return len(buf)
|
|
|
|
@logexc
|
|
def release(self, flags):
|
|
self.log("release(%r)" % (flags,))
|
|
self.file.close()
|
|
if self.open_for_write:
|
|
size = os.path.getsize(self.fname)
|
|
self.fnode.size = size
|
|
file_cap = self.tfs.upload(self.fname)
|
|
self.fnode.ro_uri = file_cap
|
|
self.tfs.add_child(self.parent.get_uri(), self.name, file_cap)
|
|
self.log("uploaded: %s" % (file_cap,))
|
|
|
|
# dbg
|
|
print_tree()
|
|
|
|
def _fflush(self):
|
|
if 'w' in self.file.mode or 'a' in self.file.mode:
|
|
self.file.flush()
|
|
|
|
@logexc
|
|
def fsync(self, isfsyncfile):
|
|
self.log("fsync(%r)" % (isfsyncfile,))
|
|
self._fflush()
|
|
if isfsyncfile and hasattr(os, 'fdatasync'):
|
|
os.fdatasync(self.fd)
|
|
else:
|
|
os.fsync(self.fd)
|
|
|
|
@logexc
|
|
def flush(self):
|
|
self.log("flush()")
|
|
self._fflush()
|
|
# cf. xmp_flush() in fusexmp_fh.c
|
|
os.close(os.dup(self.fd))
|
|
|
|
@logexc
|
|
def fgetattr(self):
|
|
self.log("fgetattr()")
|
|
s = os.fstat(self.fd)
|
|
self.log("fgetattr() -> %r" % (s,))
|
|
return s
|
|
|
|
@logexc
|
|
def ftruncate(self, len):
|
|
self.log("ftruncate(%r)" % (len,))
|
|
self.file.truncate(len)
|
|
|
|
class ObjFetcher(object):
|
|
def get_tahoe_file(self, path, flags, *mode):
|
|
log('objfetcher.get_tahoe_file(%r, %r, %r, %r)' % (self, path, flags, mode))
|
|
return TahoeFuseFile(path, flags, *mode)
|
|
fetcher = ObjFetcher()
|
|
|
|
class TahoeFuse(fuse.Fuse):
|
|
|
|
def __init__(self, tfs, *args, **kw):
|
|
log("TF: __init__(%r, %r)" % (args, kw))
|
|
|
|
self.tfs = tfs
|
|
_tfs_ = tfs
|
|
class MyFuseFile(TahoeFuseFile):
|
|
tfs = _tfs_
|
|
self.file_class = MyFuseFile
|
|
log("TF: file_class: %r" % (self.file_class,))
|
|
|
|
fuse.Fuse.__init__(self, *args, **kw)
|
|
|
|
#import thread
|
|
#thread.start_new_thread(self.launch_reactor, ())
|
|
|
|
def log(self, msg):
|
|
log("<TF> %s" % (msg, ))
|
|
|
|
@logexc
|
|
def readlink(self, path):
|
|
self.log("readlink(%r)" % (path,))
|
|
return -errno.EOPNOTSUPP
|
|
|
|
@logexc
|
|
def unlink(self, path):
|
|
self.log("unlink(%r)" % (path,))
|
|
return -errno.EOPNOTSUPP
|
|
|
|
@logexc
|
|
def rmdir(self, path):
|
|
self.log("rmdir(%r)" % (path,))
|
|
return -errno.EOPNOTSUPP
|
|
|
|
@logexc
|
|
def symlink(self, path, path1):
|
|
self.log("symlink(%r, %r)" % (path, path1))
|
|
return -errno.EOPNOTSUPP
|
|
|
|
@logexc
|
|
def rename(self, path, path1):
|
|
self.log("rename(%r, %r)" % (path, path1))
|
|
self.tfs.rename(path, path1)
|
|
|
|
@logexc
|
|
def link(self, path, path1):
|
|
self.log("link(%r, %r)" % (path, path1))
|
|
return -errno.EOPNOTSUPP
|
|
|
|
@logexc
|
|
def chmod(self, path, mode):
|
|
self.log("chmod(%r, %r)" % (path, mode))
|
|
return -errno.EOPNOTSUPP
|
|
|
|
@logexc
|
|
def chown(self, path, user, group):
|
|
self.log("chown(%r, %r, %r)" % (path, user, group))
|
|
return -errno.EOPNOTSUPP
|
|
|
|
@logexc
|
|
def truncate(self, path, len):
|
|
self.log("truncate(%r, %r)" % (path, len))
|
|
return -errno.EOPNOTSUPP
|
|
|
|
@logexc
|
|
def utime(self, path, times):
|
|
self.log("utime(%r, %r)" % (path, times))
|
|
return -errno.EOPNOTSUPP
|
|
|
|
@logexc
|
|
def statfs(self):
|
|
self.log("statfs()")
|
|
"""
|
|
Should return an object with statvfs attributes (f_bsize, f_frsize...).
|
|
Eg., the return value of os.statvfs() is such a thing (since py 2.2).
|
|
If you are not reusing an existing statvfs object, start with
|
|
fuse.StatVFS(), and define the attributes.
|
|
|
|
To provide usable information (ie., you want sensible df(1)
|
|
output, you are suggested to specify the following attributes:
|
|
|
|
- f_bsize - preferred size of file blocks, in bytes
|
|
- f_frsize - fundamental size of file blcoks, in bytes
|
|
[if you have no idea, use the same as blocksize]
|
|
- f_blocks - total number of blocks in the filesystem
|
|
- f_bfree - number of free blocks
|
|
- f_files - total number of file inodes
|
|
- f_ffree - nunber of free file inodes
|
|
"""
|
|
|
|
return os.statvfs(".")
|
|
|
|
def fsinit(self):
|
|
self.log("fsinit()")
|
|
|
|
def main(self, *a, **kw):
|
|
self.log("main(%r, %r)" % (a, kw))
|
|
|
|
return fuse.Fuse.main(self, *a, **kw)
|
|
|
|
##################################################################
|
|
|
|
@logexc
|
|
def readdir(self, path, offset):
|
|
log('readdir(%r, %r)' % (path, offset))
|
|
node = self.tfs.get_path(path)
|
|
if node is None:
|
|
return -errno.ENOENT
|
|
dirlist = ['.', '..'] + node.children.keys()
|
|
log('dirlist = %r' % (dirlist,))
|
|
return [fuse.Direntry(d) for d in dirlist]
|
|
|
|
@logexc
|
|
def getattr(self, path):
|
|
log('getattr(%r)' % (path,))
|
|
node = self.tfs.get_path(path)
|
|
if node is None:
|
|
return -errno.ENOENT
|
|
return node.get_stat()
|
|
|
|
@logexc
|
|
def access(self, path, mode):
|
|
self.log("access(%r, %r)" % (path, mode))
|
|
node = self.tfs.get_path(path)
|
|
if not node:
|
|
return -errno.ENOENT
|
|
accmode = os.O_RDONLY | os.O_WRONLY | os.O_RDWR
|
|
if (mode & 0222):
|
|
if not node.writable():
|
|
log('write access denied for %s (req:%o)' % (path, mode, ))
|
|
return -errno.EACCES
|
|
#else:
|
|
#log('access granted for %s' % (path, ))
|
|
|
|
@logexc
|
|
def mkdir(self, path, mode):
|
|
self.log("mkdir(%r, %r)" % (path, mode))
|
|
self.tfs.mkdir(path)
|
|
|
|
def launch_tahoe_fuse(tfs, argv):
|
|
sys.argv = ['tahoe fuse'] + list(argv)
|
|
server = TahoeFuse(tfs, version="%prog " + fuse.__version__,
|
|
usage=USAGE,
|
|
dash_s_do='setsingle')
|
|
server.parse(errex=1)
|
|
server.main()
|
|
|
|
|
|
def getbasedir(cap_name='root_dir'):
|
|
fname = os.path.expanduser("~/.tahoe/private/%s.cap" % (cap_name,))
|
|
if os.path.exists(fname):
|
|
f = file(fname, 'rb')
|
|
bd = f.read().strip()
|
|
f.close()
|
|
return bd
|
|
else:
|
|
return None
|
|
|
|
def getnodeurl():
|
|
f = file(os.path.expanduser("~/.tahoe/node.url"), 'rb')
|
|
nu = f.read().strip()
|
|
f.close()
|
|
if nu[-1] != "/":
|
|
nu += "/"
|
|
return nu
|
|
|
|
def fingerprint(uri):
|
|
if uri is None:
|
|
return None
|
|
return base64.b32encode(sha.new(uri).digest()).lower()[:6]
|
|
|
|
class TStat(fuse.Stat):
|
|
def __init__(self, **kwargs):
|
|
fuse.Stat.__init__(self, **kwargs)
|
|
|
|
def __repr__(self):
|
|
return "<Stat%r" % {
|
|
'st_mode': self.st_mode,
|
|
'st_ino': self.st_ino,
|
|
'st_dev': self.st_dev,
|
|
'st_nlink': self.st_nlink,
|
|
'st_uid': self.st_uid,
|
|
'st_gid': self.st_gid,
|
|
'st_size': self.st_size,
|
|
'st_atime': self.st_atime,
|
|
'st_mtime': self.st_mtime,
|
|
'st_ctime': self.st_ctime,
|
|
}
|
|
|
|
class Directory(object):
|
|
def __init__(self, ro_uri, rw_uri):
|
|
self.ro_uri = ro_uri
|
|
self.rw_uri = rw_uri
|
|
assert (rw_uri or ro_uri)
|
|
self.children = {}
|
|
|
|
def __repr__(self):
|
|
return "<Directory %s>" % (fingerprint(self.get_uri()),)
|
|
|
|
def get_children(self):
|
|
return self.children.keys()
|
|
|
|
def get_child(self, name):
|
|
return self.children[name]
|
|
|
|
def add_child(self, name, file_node):
|
|
self.children[name] = file_node
|
|
|
|
def remove_child(self, name):
|
|
del self.children[name]
|
|
|
|
def get_uri(self):
|
|
return self.rw_uri or self.ro_uri
|
|
|
|
def writable(self):
|
|
return self.rw_uri and self.rw_uri != self.ro_uri
|
|
|
|
def pprint(self, prefix='', printed=None):
|
|
ret = []
|
|
if printed is None:
|
|
printed = set()
|
|
writable = self.writable() and '+' or ' '
|
|
if self in printed:
|
|
ret.append(" %s/%s ... <%s>" % (prefix, writable, fingerprint(self.get_uri()), ))
|
|
else:
|
|
ret.append("[%s] %s/%s" % (fingerprint(self.get_uri()), prefix, writable, ))
|
|
printed.add(self)
|
|
for name,f in sorted(self.children.items()):
|
|
ret.append(f.pprint(' ' * (len(prefix)+1)+name, printed))
|
|
return '\n'.join(ret)
|
|
|
|
def get_stat(self):
|
|
s = TStat(st_mode = stat.S_IFDIR | 0755, st_nlink = 2)
|
|
log("%s.get_stat()->%s" % (self, s))
|
|
return s
|
|
|
|
class File(object):
|
|
def __init__(self, size, ro_uri, metadata):
|
|
self.size = size
|
|
if ro_uri:
|
|
ro_uri = str(ro_uri)
|
|
self.ro_uri = ro_uri
|
|
self.metadata = metadata or {}
|
|
|
|
def __repr__(self):
|
|
return "<File %s>" % (fingerprint(self.ro_uri) or [self.tmp_fname],)
|
|
|
|
def pprint(self, prefix='', printed=None):
|
|
times, remainder = self.get_times()
|
|
return " %s (%s) %s %s" % (prefix, self.size, times, remainder)
|
|
|
|
def get_times(self):
|
|
rem = self.metadata.copy()
|
|
now = time.time()
|
|
times = {}
|
|
for T in ['c', 'm']:
|
|
t = rem.pop('%stime'%T, None)
|
|
if not t:
|
|
t = 'none'
|
|
elif (now-t) < 86400:
|
|
t = time.strftime('%a:%H:%M:%S', time.localtime(t))
|
|
else:
|
|
t = time.strftime('%Y:%b:%d:%H:%M', time.localtime(t))
|
|
times[T] = t
|
|
return times, rem
|
|
|
|
def get_stat(self):
|
|
if hasattr(self, 'tmp_fname'):
|
|
s = os.stat(self.tmp_fname)
|
|
log("%s.get_stat()->%s" % (self, s))
|
|
else:
|
|
s = TStat(st_size=self.size, st_mode = stat.S_IFREG | 0444, st_nlink = 1)
|
|
log("%s.get_stat()->%s" % (self, s))
|
|
return s
|
|
|
|
def get_uri(self):
|
|
return self.ro_uri
|
|
|
|
def writable(self):
|
|
#return not self.ro_uri
|
|
return True
|
|
|
|
class TFS(object):
|
|
def __init__(self, nodeurl, root_uri):
|
|
self.nodeurl = nodeurl
|
|
self.root_uri = root_uri
|
|
self.dirs = {}
|
|
|
|
self.cache = FileCache(nodeurl, os.path.expanduser('~/.tahoe/_cache'))
|
|
ro_uri = NewDirectoryURI.init_from_string(self.root_uri).get_readonly()
|
|
self.root = Directory(ro_uri, self.root_uri)
|
|
self.load_dir('<root>', self.root)
|
|
|
|
def log(self, msg):
|
|
log("<TFS> %s" % (msg, ))
|
|
|
|
def pprint(self):
|
|
return self.root.pprint()
|
|
|
|
def get_parent_name_and_child(self, path):
|
|
dirname, name = os.path.split(path)
|
|
parent = self.get_path(dirname)
|
|
try:
|
|
child = parent.get_child(name)
|
|
return parent, name, child
|
|
except KeyError:
|
|
return parent, name, None
|
|
|
|
def get_path(self, path):
|
|
comps = path.strip('/').split('/')
|
|
if comps == ['']:
|
|
comps = []
|
|
cursor = self.root
|
|
for comp in comps:
|
|
if not isinstance(cursor, Directory):
|
|
self.log('path "%s" is not a dir' % (path,))
|
|
return None
|
|
try:
|
|
cursor = cursor.children[comp]
|
|
except KeyError:
|
|
self.log('path "%s" not found' % (path,))
|
|
return None
|
|
return cursor
|
|
|
|
def load_dir(self, name, dirobj):
|
|
print 'loading', name, dirobj
|
|
url = self.nodeurl + "uri/%s?t=json" % urllib.quote(dirobj.get_uri())
|
|
data = urllib.urlopen(url).read()
|
|
parsed = simplejson.loads(data)
|
|
nodetype, d = parsed
|
|
assert nodetype == 'dirnode'
|
|
for name,details in d['children'].items():
|
|
name = str(name)
|
|
ctype, cattrs = details
|
|
if ctype == 'dirnode':
|
|
cobj = self.dir_for(name, cattrs.get('ro_uri'), cattrs.get('rw_uri'))
|
|
else:
|
|
assert ctype == "filenode"
|
|
cobj = File(cattrs.get('size'), cattrs.get('ro_uri'), cattrs.get('metadata'))
|
|
dirobj.children[name] = cobj
|
|
|
|
def dir_for(self, name, ro_uri, rw_uri):
|
|
if ro_uri:
|
|
ro_uri = str(ro_uri)
|
|
if rw_uri:
|
|
rw_uri = str(rw_uri)
|
|
uri = rw_uri or ro_uri
|
|
assert uri
|
|
dirobj = self.dirs.get(uri)
|
|
if not dirobj:
|
|
dirobj = Directory(ro_uri, rw_uri)
|
|
self.dirs[uri] = dirobj
|
|
self.load_dir(name, dirobj)
|
|
return dirobj
|
|
|
|
def upload(self, fname):
|
|
self.log('upload(%r)' % (fname,))
|
|
fh = file(fname, 'rb')
|
|
url = self.nodeurl + "uri"
|
|
file_cap = do_http('PUT', url, fh)
|
|
self.log('uploaded to: %r' % (file_cap,))
|
|
return file_cap
|
|
|
|
def add_child(self, parent_dir_uri, child_name, child_uri):
|
|
self.log('add_child(%r, %r, %r)' % (parent_dir_uri, child_name, child_uri,))
|
|
url = self.nodeurl + "uri/%s/%s?t=uri" % (urllib.quote(parent_dir_uri), urllib.quote(child_name), )
|
|
child_cap = do_http('PUT', url, child_uri)
|
|
assert child_cap == child_uri
|
|
self.log('added child %r with %r to %r' % (child_name, child_uri, parent_dir_uri))
|
|
return child_uri
|
|
|
|
def remove_child(self, parent_uri, child_name):
|
|
self.log('remove_child(%r, %r)' % (parent_uri, child_name, ))
|
|
url = self.nodeurl + "uri/%s/%s" % (urllib.quote(parent_uri), urllib.quote(child_name))
|
|
resp = do_http('DELETE', url)
|
|
self.log('child removal yielded %r' % (resp,))
|
|
|
|
def mkdir(self, path):
|
|
self.log('mkdir(%r)' % (path,))
|
|
url = self.nodeurl + "uri?t=mkdir"
|
|
new_dir_cap = do_http('PUT', url)
|
|
parent_path, name = os.path.split(path)
|
|
self.log('parent_path, name = %s, %s' % (parent_path, name,))
|
|
parent = self.get_path(parent_path)
|
|
self.log('parent = %s' % (parent, ))
|
|
self.log('new_dir_cap = %s' % (new_dir_cap, ))
|
|
child_uri = self.add_child(parent.get_uri(), name, new_dir_cap)
|
|
ro_uri = NewDirectoryURI.init_from_string(child_uri).get_readonly()
|
|
child = Directory(ro_uri, child_uri)
|
|
parent.add_child(name, child)
|
|
|
|
def rename(self, path, path1):
|
|
self.log('rename(%s, %s)' % (path, path1))
|
|
parent, name, child = self.get_parent_name_and_child(path)
|
|
child_uri = child.get_uri()
|
|
new_parent_path, new_child_name = os.path.split(path1)
|
|
new_parent = self.get_path(new_parent_path)
|
|
self.add_child(new_parent.get_uri(), new_child_name, child_uri)
|
|
self.remove_child(parent.get_uri(), name)
|
|
parent.remove_child(name)
|
|
new_parent.add_child(new_child_name, child)
|
|
|
|
class FileCache(object):
|
|
def __init__(self, nodeurl, cachedir):
|
|
self.nodeurl = nodeurl
|
|
self.cachedir = cachedir
|
|
if not os.path.exists(self.cachedir):
|
|
os.makedirs(self.cachedir)
|
|
self.tmpdir = os.path.join(self.cachedir, 'tmp')
|
|
if not os.path.exists(self.tmpdir):
|
|
os.makedirs(self.tmpdir)
|
|
|
|
def log(self, msg):
|
|
log("<FC> %s" % (msg, ))
|
|
|
|
def get_file(self, uri):
|
|
self.log('get_file(%s)' % (uri,))
|
|
if uri.startswith("URI:LIT"):
|
|
return self.get_literal(uri)
|
|
else:
|
|
return self.get_chk(uri)
|
|
|
|
def get_literal(self, uri):
|
|
h = sha.new(uri).digest()
|
|
u = LiteralFileURI.init_from_string(uri)
|
|
fname = os.path.join(self.cachedir, '__'+base64.b32encode(h).lower())
|
|
size = len(u.data)
|
|
self.log('writing literal file %s (%s)' % (fname, size, ))
|
|
fh = open(fname, 'wb')
|
|
fh.write(u.data)
|
|
fh.close()
|
|
return fname
|
|
|
|
def get_chk(self, uri):
|
|
u = CHKFileURI.init_from_string(str(uri))
|
|
storage_index = u.storage_index
|
|
size = u.size
|
|
fname = os.path.join(self.cachedir, base64.b32encode(storage_index).lower())
|
|
if os.path.exists(fname):
|
|
fsize = os.path.getsize(fname)
|
|
if fsize == size:
|
|
return fname
|
|
else:
|
|
self.log('warning file "%s" is too short %s < %s' % (fname, fsize, size))
|
|
self.log('downloading file %s (%s)' % (fname, size, ))
|
|
fh = open(fname, 'wb')
|
|
url = "%suri/%s" % (self.nodeurl, uri)
|
|
download = urllib.urlopen(''.join([ self.nodeurl, "uri/", uri ]))
|
|
while True:
|
|
chunk = download.read(4096)
|
|
if not chunk:
|
|
break
|
|
fh.write(chunk)
|
|
fh.close()
|
|
return fname
|
|
|
|
def tmp_file(self, id):
|
|
fname = os.path.join(self.tmpdir, base64.b32encode(id).lower())
|
|
return fname
|
|
|
|
def print_tree():
|
|
log('tree:\n' + _tfs.pprint())
|
|
|
|
def main(argv):
|
|
log("\n\nmain(%s)" % (argv,))
|
|
|
|
if not argv:
|
|
argv = ['--help']
|
|
if len(argv) == 1 and argv[0] in ['-h', '--help', '--version']:
|
|
#print USAGE
|
|
launch_tahoe_fuse(None, argv)
|
|
return -2
|
|
|
|
if not argv[0].startswith('-'):
|
|
cap_name = argv[0]
|
|
basedir = getbasedir(cap_name)
|
|
if basedir is None:
|
|
print 'root dir named "%s" not found.' % (cap_name,)
|
|
return -2
|
|
argv = argv[1:]
|
|
else:
|
|
basedir = getbasedir() # default 'root_dir'
|
|
|
|
if argv[-1].startswith('-'):
|
|
print 'mountpoint not given'
|
|
return -2
|
|
mountpoint = os.path.abspath(argv[-1])
|
|
if not os.path.exists(mountpoint):
|
|
#raise OSError(2, 'No such file or directory: "%s"' % (mountpoint,))
|
|
print 'No such file or directory: "%s"' % (mountpoint,)
|
|
return -2
|
|
|
|
nodeurl = getnodeurl()
|
|
|
|
tfs = TFS(nodeurl, basedir)
|
|
print tfs.pprint()
|
|
|
|
# make tfs instance accesible to print_tree() for dbg
|
|
global _tfs
|
|
_tfs = tfs
|
|
|
|
launch_tahoe_fuse(tfs, argv)
|
|
|
|
if __name__ == '__main__':
|
|
main(sys.argv)
|