tahoe-lafs/allmydata/filetable.py

99 lines
3.3 KiB
Python
Raw Normal View History

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 validate_name(self, name):
if name == "." or name == ".." or "/" in name:
raise DeadDirectoryNodeError("bad filename component")
# this is private
def get_child(self, name):
self.validate_name(name)
absname = os.path.join(self._basedir, name)
if os.path.isdir(absname):
return MutableDirectoryNode(absname)
raise DeadDirectoryNodeError("no such directory")
# 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, MutableDirectoryNode(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 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 MutableDirectoryNode(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)
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