mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2024-12-28 16:58:53 +00:00
110 lines
3.6 KiB
Python
110 lines
3.6 KiB
Python
|
|
import os, shutil
|
|
from zope.interface import implements
|
|
from foolscap import Referenceable
|
|
from allmydata.interfaces import RIMutableDirectoryNode
|
|
from twisted.application import service
|
|
from twisted.python import log
|
|
|
|
class DeadDirectoryNodeError(Exception):
|
|
"""The directory referenced by this node has been deleted."""
|
|
|
|
class BadDirectoryError(Exception):
|
|
"""There was a problem with the directory being referenced."""
|
|
class BadFileError(Exception):
|
|
"""The file being referenced does not exist."""
|
|
|
|
class MutableDirectoryNode(Referenceable):
|
|
implements(RIMutableDirectoryNode)
|
|
|
|
def __init__(self, basedir):
|
|
self._basedir = basedir
|
|
|
|
def make_subnode(self, basedir):
|
|
return self.__class__(basedir)
|
|
|
|
def validate_name(self, name):
|
|
if name == "." or name == ".." or "/" in name:
|
|
raise DeadDirectoryNodeError("bad filename component")
|
|
|
|
# these are the public methods, available to anyone who holds a reference
|
|
|
|
def list(self):
|
|
log.msg("Dir(%s).list" % self._basedir)
|
|
results = []
|
|
if not os.path.isdir(self._basedir):
|
|
raise DeadDirectoryNodeError("This directory has been deleted")
|
|
for name in os.listdir(self._basedir):
|
|
absname = os.path.join(self._basedir, name)
|
|
if os.path.isdir(absname):
|
|
results.append( (name, self.make_subnode(absname)) )
|
|
elif os.path.isfile(absname):
|
|
f = open(absname, "rb")
|
|
data = f.read()
|
|
f.close()
|
|
results.append( (name, data) )
|
|
# anything else is ignored
|
|
return results
|
|
remote_list = list
|
|
|
|
def get(self, name):
|
|
self.validate_name(name)
|
|
absname = os.path.join(self._basedir, name)
|
|
if os.path.isdir(absname):
|
|
return self.make_subnode(absname)
|
|
elif os.path.isfile(absname):
|
|
f = open(absname, "rb")
|
|
data = f.read()
|
|
f.close()
|
|
return data
|
|
else:
|
|
raise BadFileError("there is nothing named '%s' in this directory"
|
|
% name)
|
|
remote_get = get
|
|
|
|
def add_directory(self, name):
|
|
self.validate_name(name)
|
|
absname = os.path.join(self._basedir, name)
|
|
if os.path.isdir(absname):
|
|
raise BadDirectoryError("the directory '%s' already exists" % name)
|
|
if os.path.exists(absname):
|
|
raise BadDirectoryError("the directory '%s' already exists "
|
|
"(but isn't a directory)" % name)
|
|
os.mkdir(absname)
|
|
return self.make_subnode(absname)
|
|
remote_add_directory = add_directory
|
|
|
|
def add_file(self, name, data):
|
|
self.validate_name(name)
|
|
f = open(os.path.join(self._basedir, name), "wb")
|
|
f.write(data)
|
|
f.close()
|
|
remote_add_file = add_file
|
|
|
|
def remove(self, name):
|
|
self.validate_name(name)
|
|
absname = os.path.join(self._basedir, name)
|
|
if os.path.isdir(absname):
|
|
shutil.rmtree(absname)
|
|
elif os.path.isfile(absname):
|
|
os.unlink(absname)
|
|
else:
|
|
raise BadFileError("Cannot delete non-existent file '%s'" % name)
|
|
remote_remove = remove
|
|
|
|
|
|
class GlobalVirtualDrive(service.MultiService):
|
|
name = "filetable"
|
|
VDRIVEDIR = "vdrive"
|
|
|
|
def __init__(self, basedir="."):
|
|
service.MultiService.__init__(self)
|
|
vdrive_dir = os.path.join(basedir, self.VDRIVEDIR)
|
|
if not os.path.exists(vdrive_dir):
|
|
os.mkdir(vdrive_dir)
|
|
self._root = MutableDirectoryNode(vdrive_dir)
|
|
|
|
def get_root(self):
|
|
return self._root
|
|
|