Author: aum
Date: 2006-05-27 12:22:54 +0000 (Sat, 27 May 2006)
New Revision: 8882
Modified:
trunk/apps/pyFreenet/README.freedisk
trunk/apps/pyFreenet/code.leo
trunk/apps/pyFreenet/fcp/node.py
trunk/apps/pyFreenet/freedisk.py
Log:
Allow retrieve of CHK at blahblah.ext, the .ext gets stripped
Got freedisk working for basic get/put/genkey
Modified: trunk/apps/pyFreenet/README.freedisk
===================================================================
--- trunk/apps/pyFreenet/README.freedisk 2006-05-27 08:49:50 UTC (rev
8881)
+++ trunk/apps/pyFreenet/README.freedisk 2006-05-27 12:22:54 UTC (rev
8882)
@@ -66,26 +66,62 @@
Fetch a key:
- $ cat /mnt/freenet/keys/KSK at hello
+ $ cat /mnt/freenet/get/KSK at hello
See that the key is cached:
- $ ls -las /mnt/freenet/keys
+ $ ls -las /mnt/freenet/get
Clear the key from the cache:
- $ rm /mnt/freenet/keys/KSK at hello
+ $ rm /mnt/freenet/get/KSK at hello
-Generate an SSK private key:
+Generate a couple SSK keypairs:
- $ cat /mnt/freenet/genkey
+ $ cat /mnt/freenet/keys/fred
+ $ cat /mnt/freenet/keys/mary
-Generate a full SSK public,private key pair:
+You'll see in each case a public key on one line, then a private key.
- $ cat /mnt/freenet/genkeypair
+Now, let's insert something:
- (you will see two URIs, the public then private, on separate lines)
+ $ echo "Hello" > /mnt/freenet/put/KSK at something
+Now, wait a bit, and do:
+
+ $ ls -las /mnt/freenet/get
+
+once the key is inserted, you'll see it in the 'get'
+directory.
+
+Now, something smarter - we can insert CHKs...
+
+ $ echo "This is a chk" > /mnt/freenet/put/CHK at mykey.txt
+
+Now test it:
+
+ $ ls -l /mnt/freenet/put
+
+You should see a file CHK at mykey.txt
+
+Type:
+
+ $ cat /mnt/freenet/put/CHK at mykey.txt
+
+and you should get a single word, 'pending'.
+
+After a time, the file's contents will change to either
+'failed', meaning the insert failed, or a freenet URI,
+in which case it succeeded.
+
+If it succeeded, do:
+
+ $ ls -las /mnt/freenet/get
+
+You should see an entry 'CHK at yadayadayadayada.txt'.
+
+You can rm any of these entries.
+
------------------------------------------------------------------
STATUS:
Modified: trunk/apps/pyFreenet/code.leo
===================================================================
--- trunk/apps/pyFreenet/code.leo 2006-05-27 08:49:50 UTC (rev 8881)
+++ trunk/apps/pyFreenet/code.leo 2006-05-27 12:22:54 UTC (rev 8882)
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<leo_file>
<leo_header file_format="2" tnodes="0" max_tnode_index="23" clone_windows="0"/>
-<globals body_outline_ratio="0.321195144725">
- <global_window_position top="3" left="189" height="659" width="1067"/>
+<globals body_outline_ratio="0.2633552015">
+ <global_window_position top="40" left="121" height="659" width="1067"/>
<global_log_window_position top="0" left="0" height="0" width="0"/>
</globals>
<preferences/>
@@ -240,7 +240,7 @@
</v>
</v>
<v t="aum.20060521163241" a="E"><vh>freedisk</vh>
-<v t="aum.20060521163823" a="E"
tnodeList="aum.20060521163823,aum.20060521163823.1,aum.20060521175433,aum.20060521175052,aum.20060521175052.1,aum.20060521175052.2,aum.20060521175052.3,aum.20060521175052.4,aum.20060521175052.5,aum.20060521175052.6,aum.20060521163823.2,aum.20060521163823.5,aum.20060521163823.3,aum.20060521191057,aum.20060526071442,aum.20060526112020,aum.20060521232922,aum.20060521163823.4,aum.20060521185642,aum.20060521163823.6,aum.20060521163823.7,aum.20060521163823.8,aum.20060521163823.9,aum.20060521163823.10,aum.20060521163823.11,aum.20060521163823.12,aum.20060521163823.13,aum.20060521163823.14,aum.20060521163823.15,aum.20060521163823.16,aum.20060521163823.17,aum.20060521163823.18,aum.20060521163823.19,aum.20060521163823.20,aum.20060521163823.21,aum.20060521163823.22,aum.20060521163823.23,aum.20060521163823.24,aum.20060521163823.25,aum.20060521185946,aum.20060525194744,aum.20060522231936,aum.20060522225626,aum.20060521190048,aum.20060521190048.1,aum.20060525225133,aum.20060525225133.1,aum.20060525225603,aum.20060525225713,aum.20060526072230,aum.20060525193858,aum.20060525194744.1,aum.20060521163823.26"><vh>@file
freedisk.py</vh>
+<v t="aum.20060521163823" a="E"
tnodeList="aum.20060521163823,aum.20060521163823.1,aum.20060521175433,aum.20060521175052,aum.20060521175052.1,aum.20060521175052.2,aum.20060521175052.3,aum.20060521175052.4,aum.20060521175052.5,aum.20060521175052.6,aum.20060521163823.2,aum.20060521163823.5,aum.20060521163823.3,aum.20060521191057,aum.20060526071442,aum.20060526112020,aum.20060521232922,aum.20060521163823.4,aum.20060521185642,aum.20060521163823.6,aum.20060527195652,aum.20060526163608,aum.20060526163608.1,aum.20060521163823.7,aum.20060521163823.8,aum.20060521163823.9,aum.20060521163823.10,aum.20060521163823.11,aum.20060521163823.12,aum.20060521163823.13,aum.20060521163823.14,aum.20060521163823.15,aum.20060521163823.16,aum.20060521163823.17,aum.20060521163823.18,aum.20060521163823.19,aum.20060521163823.20,aum.20060521163823.21,aum.20060521163823.22,aum.20060521163823.23,aum.20060521163823.24,aum.20060521163823.25,aum.20060521185946,aum.20060527114534,aum.20060527114743,aum.20060525194744,aum.20060522231936,aum.20060522225626,aum.20060521190048,aum.20060521190048.1,aum.20060525225133,aum.20060525225133.1,aum.20060525225603,aum.20060525225713,aum.20060527140140.2,aum.20060526072230,aum.20060527114053,aum.20060525193858,aum.20060525194744.1,aum.20060521163823.26"><vh>@file
freedisk.py</vh>
<v t="aum.20060521163823.1"><vh>imports</vh></v>
<v t="aum.20060521175433"><vh>globals</vh></v>
<v t="aum.20060521175052"><vh>class ErrnoWrapper</vh></v>
@@ -260,7 +260,11 @@
<v t="aum.20060521232922"><vh>log</vh></v>
<v t="aum.20060521163823.4"><vh>mythread</vh></v>
<v t="aum.20060521185642" a="E"><vh>fs primitives</vh>
-<v t="aum.20060521163823.6"><vh>getattr</vh></v>
+<v t="aum.20060521163823.6" a="E"><vh>getattr</vh>
+<v t="aum.20060527195652"><vh><<generate keypair>></vh></v>
+<v t="aum.20060526163608"><vh><<retrieve/cache key>></vh></v>
+<v t="aum.20060526163608.1"><vh><<try host fs>></vh></v>
+</v>
<v t="aum.20060521163823.7"><vh>readlink</vh></v>
<v t="aum.20060521163823.8"><vh>getdir</vh></v>
<v t="aum.20060521163823.9"><vh>unlink</vh></v>
@@ -282,6 +286,8 @@
<v t="aum.20060521163823.25"><vh>fsync</vh></v>
</v>
<v t="aum.20060521185946"><vh>hashpath</vh></v>
+<v t="aum.20060527114534"><vh>addToCache</vh></v>
+<v t="aum.20060527114743"><vh>delFromCache</vh></v>
<v t="aum.20060525194744"><vh>getDirStat</vh></v>
<v t="aum.20060522231936"><vh>statFromKw</vh></v>
<v t="aum.20060522225626"><vh>statToDict</vh></v>
@@ -292,7 +298,9 @@
<v t="aum.20060525225133.1"><vh>__init__</vh></v>
<v t="aum.20060525225603"><vh>__getattr__</vh></v>
<v t="aum.20060525225713"><vh>__setattr__</vh></v>
+<v t="aum.20060527140140.2"><vh>write</vh></v>
<v t="aum.20060526072230"><vh>addChild</vh></v>
+<v t="aum.20060527114053"><vh>delChild</vh></v>
</v>
<v t="aum.20060525193858"><vh>pathToInode</vh></v>
<v t="aum.20060525194744.1"><vh>timeNow</vh></v>
@@ -892,6 +900,8 @@
else:
opts["DSOnly"] = "false"
+ if uri.startswith("freenet:CHK@") or uri.startswith("CHK@"):
+ uri = os.path.splitext(uri)[0]
opts['URI'] = uri
opts['MaxRetries'] = kw.get("maxretries", 3)
@@ -8872,12 +8882,14 @@
@others
</t>
-<t tx="aum.20060521163823.1">import sys, os, time, stat
+<t tx="aum.20060521163823.1">import sys, os, time, stat, errno
+from StringIO import StringIO
import thread
from threading import Lock
import traceback
from Queue import Queue
-import sha
+import sha, md5
+from UserString import MutableString
from errno import *
from stat import *
@@ -8908,7 +8920,7 @@
Fuse.__init__(self, *args, **kw)
- if 1:
+ if 0:
self.log("xmp.py:Xmp:mountpoint: %s" % repr(self.mountpoint))
self.log("xmp.py:Xmp:unnamed mount options: %s" % self.optlist)
self.log("xmp.py:Xmp:named mount options: %s" % self.optdict)
@@ -8937,9 +8949,10 @@
self.privKeypairLock = Lock()
try:
+ self.node = None
self.connectToNode()
except:
- self.node = None
+ #raise
pass
# do stuff to set up your filesystem here, if you want
@@ -8965,12 +8978,14 @@
initialFiles = [
"/",
- "/cmd/",
- "/cmd/genkey",
- "/cmd/genkeypair",
+# "/cmd/",
+# "/cmd/genkey",
+# "/cmd/genkeypair",
+ "/get/",
+ "/put/",
#"/cmd/invertprivatekey/",
"/keys/",
- "/private/",
+# "/private/",
"/usr/",
]
@@ -8983,94 +8998,15 @@
<t tx="aum.20060521163823.6">def getattr(self, path):
rec = self.files.get(path, None)
-
- #if path in self.knownDirs:
- # print "Return record for known dir %s" % path
- # rec = self.getDirStat(path)
- #else:
-
- # fallback to mainstream fs, delete this later
if not rec:
-
- if 0 or path.startswith("/cmd/invertprivatekey/"):
- prefix = "/cmd/invertprivatekey/"
- prefixlen = len(prefix)
- rec = FileRecord(path=path, isdir=True)
- uri = path[prefixlen:]
-
# retrieving a key?
- elif path.startswith("/keys/"):
- # are we seeking key, or mimetype?
- if path.endswith(".mimetype"):
- getMimetype = True
- path = path[:-9]
- else:
- getMimetype = False
-
- # check the cache
- if not self.files.has_key(path):
- # get a key
- uri = path[6:]
- try:
- self.connectToNode()
- mimetype, data = self.node.get(uri)
- rec = FileRecord(path=path,
- size=len(data),
- isreg=True,
- perm=0444,
- )
- rec.mimetype = mimetype
- rec.data = data
- self.files[path] = rec
- self.files["/keys"].addChild(rec)
-
- except:
- traceback.print_exc()
- print "ehhh?? path=%s" % path
- raise IOError((2, path))
- else:
- rec = self.files[path]
-
- rec1 = FileRecord(rec, path=path)
- if getMimetype:
- rec1.size = len(rec.mimetype)
- rec = rec1
-
+ if path.startswith("/keys/"):
+ <<generate keypair>>
+ elif path.startswith("/get/"):
+ <<retrieve/cache key>>
else:
- print "getattr: no rec for %s, hitting main fs" % path
- rec = FileRecord(os.lstat(path), path=path)
- else:
- print "getattr: found rec for %s" % path
+ <<try host fs>>
- # now gotta do some fudging to pre-cache any required keys
-
- # single private key?
- if path == '/cmd/genkey':
- self.privKeyLock.acquire()
- if not self.privKeyQueue:
- self.connectToNode()
- privkey = self.node.genkey()[1]
- self.privKeyQueue.append(privkey)
- else:
- privkey = self.privKeyQueue[0]
- size = len(privkey)
- self.privKeyLock.release()
- rec.size = size
-
- # key pair?
- elif path == '/cmd/genkeypair':
- self.privKeypairLock.acquire()
- if not self.privKeypairQueue:
- self.connectToNode()
- privkey = "\n".join(self.node.genkey())
- self.privKeypairQueue.append(privkey)
- else:
- privkey = self.privKeypairQueue[0]
- size = len(privkey)
- self.privKeypairLock.release()
- rec.size = size
-
-
self.log("getattr: path=%s" % path)
self.log(" mode=0%o" % rec.mode)
self.log(" inode=0x%x" % rec.inode)
@@ -9082,8 +9018,9 @@
self.log(" atime=%d" % rec.atime)
self.log(" mtime=%d" % rec.mtime)
self.log(" ctime=%d" % rec.ctime)
+ self.log("rec=%s" % str(rec))
- return rec
+ return tuple(rec)
</t>
<t tx="aum.20060521163823.7">def readlink(self, path):
@@ -9117,14 +9054,16 @@
<t tx="aum.20060521163823.9">def unlink(self, path):
# remove existing file?
- if path.startswith("/keys/"):
+ if path.startswith("/get/") \
+ or path.startswith("/put/") \
+ or path.startswith("/keys/"):
rec = self.files.get(path, None)
if not rec:
- raise IOError((2, path))
- self.files["/keys"].children.remove(rec)
- del self.files[path]
+ raise IOError(2, path)
+ self.delFromCache(rec)
return 0
+ # fallback on host fs
ret = os.unlink(path)
self.log("unlink: path=%s\n => %s" % (path, ret))
return ret
@@ -9181,15 +9120,30 @@
</t>
<t tx="aum.20060521163823.17">def mknod(self, path, mode, dev):
- """ Python has no os.mknod, so we can only do some things """
+ """ Python has no os.mknod, so we can only do some things """
+ # start key write, if needed
+ if path.startswith("/put/"):
- if S_ISREG(mode):
- ret = open(path, "w")
- else:
- ret = -EINVAL
+ # see if an existing file
+ if self.files.has_key(path):
+ raise IOError(errno.EEXIST, path)
- self.log("mknod: path=%s mode=%s dev=%s\n => %s" % (path, mode, dev,
ret))
+ rec = self.addToCache(
+ path=path, isreg=True, iswriting=True,
+ perm=0644)
+ ret = 0
+ else:
+ # fall back on host os
+ if S_ISREG(mode):
+ file(path, "w").close()
+ ret = 0
+ else:
+ ret = -EINVAL
+
+ self.log("mknod: path=%s mode=0%o dev=%s\n => %s" % (
+ path, mode, dev, ret))
+
return ret
</t>
@@ -9211,93 +9165,39 @@
self.log("open: path=%s flags=%s" % (path, flags))
- # frig for /keys/
- if path.endswith(".mimetype"):
- isMimetype = True
- path = path[:-9]
- else:
- isMimetype = False
-
# see if it's an existing file
rec = self.files.get(path, None)
- if not rec:
+
+ if rec:
+ # barf if not regular file
+ if not (rec.isreg or rec.ischr):
+ self.log("open: %s is not regular file" % path)
+ raise IOError(errno.EIO, "Not a regular file: %s" % path)
+
+ else:
# fall back to host fs
os.close(os.open(path, flags))
- return 0
- # see if reading genkey files
- if 0:
- if path == '/key/genkey':
- self.connectToNode()
- self.privKeyLock.acquire()
- self.privKeyQueue.append(self.node.genkey()[1])
- self.privKeyLock.release()
- elif path == '/key/genkeypair':
- self.connectToNode()
- self.privKeypairLock.acquire()
- self.privKeypairQueue.append("\n".join(self.node.genkey()))
- self.privKeypairLock.release()
+ self.log("open: open of %s succeeded" % path)
- # try for pseudo-files
- for p in ["/keys/", "/cmd/genkey", "/cmd/invertprivatekey/"]:
- if path.startswith(p):
- return 0
-
- # barf if not regular file
- if not (rec.isreg or rec.ischr):
- raise IOError("Not a regular file: %s" % path)
-
# seems ok
return 0
+
</t>
<t tx="aum.20060521163823.21">def read(self, path, length, offset):
"""
"""
- # see if reading a previously stat-ed key
- if path.startswith("/keys/"):
- # see if we're getting mimetype
- if path.endswith(".mimetype"):
- getMimetype = True
- path = path[:-9]
- else:
- getMimetype = False
-
- # yep, fetch teh record if possible
- rec = self.files[path]
- if getMimetype:
- return rec.mimetype
- else:
- return rec.data
+ # forward to existing file if any
+ rec = self.files.get(path, None)
+ if rec:
+ rec.seek(offset)
+ buf = rec.read(length)
- # intercept magic files
- if path == '/cmd/genkeypair':
- # a genkeypair command, return public,private on 2 lines
- self.privKeypairLock.acquire()
- if not self.privKeypairQueue:
- self.privKeypairLock.release()
- return ''
- privkey = self.privKeypairQueue.pop(0)
- self.privKeypairLock.release()
- buf = privkey
-
- elif path == '/cmd/genkey':
- # a genkey command, just return private key
- self.privKeyLock.acquire()
- if not self.privKeyQueue:
- self.privKeyLock.release()
- return ''
- privkey = self.privKeyQueue.pop(0)
- self.privKeyLock.release()
- buf = privkey
-
- elif path.startswith("/cmd/invertprivatekey"):
- self.connectToNode()
- privkey = os.path.split(path)[-1]
- pubkey = self.node.invertprivate(privkey)
- self.log("read /cmd/invertprivate:\n priv=%s\npub=%s" % (
- privkey, pubkey))
- buf = pubkey.split("\0")[0]
-
+ self.log("read: path=%s length=%s offset=%s\n => %s" % (
+ path, length, offset, len(buf)))
+ #print repr(buf)
+ return buf
+
else:
# fall back on host fs
f = open(path, "r")
@@ -9312,17 +9212,98 @@
</t>
<t tx="aum.20060521163823.22">def write(self, path, buf, off):
+ dataLen = len(buf)
+
+ rec = self.files.get(path, None)
+ if rec:
+ # write to existing 'file'
+ rec.seek(off)
+ rec.write(buf)
+ else:
+ f = open(path, "r+")
+ f.seek(off)
+ nwritten = f.write(buf)
+ f.flush()
+
self.log("write: path=%s buf=[%s bytes] off=%s" % (path, len(buf), off))
- f = open(path, "r+")
- f.seek(off)
- f.write(buf)
- f.flush()
- return len(buf)
+ #return nwritten
+ return dataLen
</t>
<t tx="aum.20060521163823.23">def release(self, path, flags):
+ rec = self.files.get(path, None)
+ if not rec:
+ return
+
+ # if writing, save the thing
+ if rec.iswriting:
+ # what uri?
+ rec.iswriting = False
+ uri = os.path.split(path)[1]
+
+ # frigs to allow fancy CHK@ inserts
+ if uri.startswith("CHK@"):
+ putUri = "CHK@"
+ else:
+ putUri = uri
+ ext = os.path.splitext(uri)[1]
+
+ try:
+ self.log("release: inserting %s" % uri)
+
+ mimetype = fcp.node.guessMimetype(path)
+ data = rec.data
+
+ # empty the pseudo-file till a result is through
+ rec.data = 'inserting'
+
+ self.connectToNode()
+
+ #print "FIXME: data=%s" % repr(data)
+
+ if _no_node:
+ print "FIXME: not inserting"
+ getUri = "NO_URI"
+ else:
+ # perform the insert
+ getUri = self.node.put(
+ putUri,
+ data=data,
+ mimetype=mimetype)
+
+ # strip 'freenet:' prefix
+ if getUri.startswith("freenet:"):
+ getUri = getUri[8:]
+
+ # restore file extension
+ if getUri.startswith("CHK@"):
+ getUri += ext
+
+ # now cache the read-back
+ self.addToCache(
+ path="/get/"+getUri,
+ data=data,
+ perm=0444,
+ isreg=True,
+ )
+
+ # and adjust the written file to reveal read uri
+ rec.data = getUri
+
+ self.log("release: inserted %s as %s ok" % (
+ uri, mimetype))
+
+ except:
+ traceback.print_exc()
+ rec.data = 'failed'
+ self.log("release: insert of %s failed" % uri)
+ raise IOError(errno.EIO, "Failed to insert")
+
+ self.log("release: done with insertion")
+ return 0
+
self.log("release: path=%s flags=%s" % (path, flags))
return 0
@@ -9372,6 +9353,7 @@
try:
return apply(self.func, args, kw)
except (IOError, OSError), detail:
+ traceback.print_exc()
# Sometimes this is an int, sometimes an instance...
if hasattr(detail, "errno"): detail = detail.errno
return -detail
@@ -9413,7 +9395,7 @@
argv = sys.argv
argc = len(argv)
- self.log("argv=%s" % argv)
+ #self.log("argv=%s" % argv)
## physical thing to mount
#self.configfile = argv[1]
@@ -9448,6 +9430,11 @@
if hasattr( self, 'debug'):
d['lopts'] = 'debug';
+ #opts = self.optdict
+ #for k in ['wsize', 'rsize']:
+ # if opts.has_key(k):
+ # d[k] = int(opts[k])
+
k=[]
if hasattr(self,'allow_other'):
k.append('allow_other')
@@ -9478,6 +9465,9 @@
inodes = {}
inodesNext = 1
+# set this to disable hits to node, for debugging
+_no_node = 0
+
</t>
<t tx="aum.20060521180804">def invertprivate(self, privatekey):
"""
@@ -9775,26 +9765,62 @@
Fetch a key:
- $ cat /mnt/freenet/keys/KSK at hello
+ $ cat /mnt/freenet/get/KSK at hello
See that the key is cached:
- $ ls -las /mnt/freenet/keys
+ $ ls -las /mnt/freenet/get
Clear the key from the cache:
- $ rm /mnt/freenet/keys/KSK at hello
+ $ rm /mnt/freenet/get/KSK at hello
-Generate an SSK private key:
+Generate a couple SSK keypairs:
- $ cat /mnt/freenet/genkey
+ $ cat /mnt/freenet/keys/fred
+ $ cat /mnt/freenet/keys/mary
-Generate a full SSK public,private key pair:
+You'll see in each case a public key on one line, then a private key.
- $ cat /mnt/freenet/genkeypair
+Now, let's insert something:
- (you will see two URIs, the public then private, on separate lines)
+ $ echo "Hello" > /mnt/freenet/put/KSK at something
+Now, wait a bit, and do:
+
+ $ ls -las /mnt/freenet/get
+
+once the key is inserted, you'll see it in the 'get'
+directory.
+
+Now, something smarter - we can insert CHKs...
+
+ $ echo "This is a chk" > /mnt/freenet/put/CHK at mykey.txt
+
+Now test it:
+
+ $ ls -l /mnt/freenet/put
+
+You should see a file CHK at mykey.txt
+
+Type:
+
+ $ cat /mnt/freenet/put/CHK at mykey.txt
+
+and you should get a single word, 'pending'.
+
+After a time, the file's contents will change to either
+'failed', meaning the insert failed, or a freenet URI,
+in which case it succeeded.
+
+If it succeeded, do:
+
+ $ ls -las /mnt/freenet/get
+
+You should see an entry 'CHK at yadayadayadayada.txt'.
+
+You can rm any of these entries.
+
------------------------------------------------------------------
STATUS:
@@ -9912,13 +9938,19 @@
if inode != None:
return inode
- # generate whole new inode
- global inodesNext
- inode = inodesNext
- inodesNext += 1
+ # try hashing the path to 32bit
+ inode = int(md5.new(path).hexdigest()[:7], 16)
+
+ # and ensure it's unique
+ while inodes.has_key(inode):
+ inode += 1
+
+ # register it
inodes[path] = inode
+
+ # done
return inode
-
+
</t>
<t tx="aum.20060525194744">def getDirStat(self, path):
"""
@@ -9928,7 +9960,7 @@
</t>
<t tx="aum.20060525194744.1">def timeNow():
- return int(time.time()) & 0xffffffff
+ return int(time.time()) & 0xffffffffL
</t>
<t tx="aum.20060525225133">class FileRecord(list):
@@ -9942,25 +9974,27 @@
<t tx="aum.20060525225133.1">def __init__(self, statrec=None, **kw):
"""
"""
- if statrec == None:
+ # got a statrec arg?
+ if statrec:
+ # yes, extract main items
+ dev = statrec[stat.ST_DEV]
+ nlink = statrec[stat.ST_NLINK]
+ uid = statrec[stat.ST_UID]
+ gid = statrec[stat.ST_GID]
+ size = statrec[stat.ST_SIZE]
+ else:
+ # no, fudge a new one
statrec = [0,0,0,0,0,0,0,0,0,0]
dev = 0
nlink = 1
uid = myuid
gid = mygid
size = 0
- else:
- dev = statrec[stat.ST_DEV]
- nlink = statrec[stat.ST_NLINK]
- uid = statrec[stat.ST_UID]
- gid = statrec[stat.ST_GID]
- size = statrec[stat.ST_SIZE]
+ # convert tuple to list if need be
if not hasattr(statrec, '__setitem__'):
statrec = list(statrec)
- # handle keywords
-
# build mode mask
mode = kw.get('mode', 0)
if kw.get('isdir', False):
@@ -9978,14 +10012,26 @@
if kw.get('issock', False):
mode |= stat.S_IFSOCK
+ # handle non-file-related keywords
perm = kw.get('perm', 0)
mode |= perm
path = kw['path']
self.path = path
+
+ self.stream = StringIO()
+
+ data = kw.get('data', '')
+ self.stream = StringIO(data)
+
+ for key in ['iswriting']:
+ if kw.has_key(key):
+ setattr(self, key, kw[key])
+
+ # child files/dirs
self.children = []
- print "FileRecord.__init__: path=%s" % path
+ #print "FileRecord.__init__: path=%s" % path
# get inode number
inode = pathToInode(path)
@@ -9996,8 +10042,8 @@
mtime = kw.get('mtime', now)
ctime = kw.get('ctime', now)
- print "statrec[stat.ST_MODE]=%s" % statrec[stat.ST_MODE]
- print "mode=%s" % mode
+ #print "statrec[stat.ST_MODE]=%s" % statrec[stat.ST_MODE]
+ #print "mode=%s" % mode
statrec[stat.ST_MODE] |= mode
statrec[stat.ST_INO] = inode
@@ -10006,14 +10052,16 @@
statrec[stat.ST_UID] = uid
statrec[stat.ST_GID] = gid
- if kw.has_key('size'):
- statrec[stat.ST_SIZE] = kw['size']
+ statrec[stat.ST_SIZE] = len(self.stream.getvalue())
+
statrec[stat.ST_ATIME] = atime
statrec[stat.ST_MTIME] = atime
statrec[stat.ST_CTIME] = atime
list.__init__(self, statrec)
+ self.iswriting = kw.get('iswriting', False)
+
</t>
<t tx="aum.20060525225603">def __getattr__(self, attr):
"""
@@ -10071,7 +10119,15 @@
if attr == 'ctime':
return self[stat.ST_ATIME]
+
+ if attr == 'data':
+ return self.stream.getvalue()
+ try:
+ return getattr(self.stream, attr)
+ except:
+ pass
+
raise AttributeError(attr)
</t>
@@ -10138,12 +10194,20 @@
elif attr == 'ctime':
self[stat.ST_CTIME] = val
+ elif attr == 'data':
+ oldPos = self.stream.tell()
+ self.stream = StringIO(val)
+ self.stream.seek(min(oldPos, len(val)))
+ self.size = len(val)
+
else:
self.__dict__[attr] = val
</t>
<t tx="aum.20060526071442">def setupFiles(self):
"""
+ Create initial file/directory layout, according
+ to attributes 'initialFiles' and 'chrFiles'
"""
# easy map of files
self.files = {}
@@ -10152,13 +10216,8 @@
for path in self.initialFiles:
# initial attribs
- isReg = False
- isDir = False
- isChr = False
- isSock = False
- isFifo = False
- perm = 0
- size = 0
+ isReg = isDir = isChr = isSock = isFifo = False
+ perm = size = 0
# determine file type
if path.endswith("/"):
@@ -10176,17 +10235,6 @@
# by default, it's a regular file
isReg = True
- # get parent, if any
- pathBits = path.split("/")
- if len(pathBits) > 1:
- # we have a parent - add this rec to parent
- parentPath = "/".join(pathBits[:-1])
- if not parentPath:
- parentPath = "/"
- parentRec = self.files.get(parentPath, None)
- else:
- parentRec = None
-
# create permissions field
if isDir:
perm |= 0755
@@ -10194,18 +10242,14 @@
perm |= 0444
# create record for this path
- rec = FileRecord(path=path,
- size=size,
- isdir=isDir, isreg=isReg, ischr=isChr,
- issock=isSock, isfifo=isFifo,
- perm=perm)
- self.files[path] = rec
+ self.addToCache(
+ path=path,
+ perm=perm,
+ size=size,
+ isdir=isDir, isreg=isReg, ischr=isChr,
+ issock=isSock, isfifo=isFifo,
+ )
- # add to parent, if any
- if parentRec:
- parentRec.addChild(rec)
-
-
</t>
<t tx="aum.20060526072230">def addChild(self, rec):
"""
@@ -10227,9 +10271,9 @@
self.node = fcp.FCPNode(host=self.fcpHost,
port=self.fcpPort,
verbosity=self.fcpVerbosity)
- self.log("pubkey=%s" % self.pubkey)
- self.log("privkey=%s" % self.privkey)
- self.log("cachedir=%s" % self.cachedir)
+ #self.log("pubkey=%s" % self.pubkey)
+ #self.log("privkey=%s" % self.privkey)
+ #self.log("cachedir=%s" % self.cachedir)
</t>
<t tx="aum.20060526123909">@language c
@@ -10268,5 +10312,111 @@
}
</t>
+<t tx="aum.20060526163608"># check the cache
+if _no_node:
+ print "FIXME: returning IOerror"
+ raise IOError(errno.ENOENT, path)
+
+# get a key
+uri = path.split("/", 2)[-1]
+try:
+ self.connectToNode()
+ mimetype, data = self.node.get(uri)
+ rec = FileRecord(path=path,
+ isreg=True,
+ perm=0644,
+ data=data,
+ )
+ self.addToCache(rec)
+
+except:
+ traceback.print_exc()
+ #print "ehhh?? path=%s" % path
+ raise IOError(errno.ENOENT, path)
+
+</t>
+<t tx="aum.20060526163608.1"># try the host filesystem
+print "getattr: no rec for %s, hitting main fs" % path
+rec = FileRecord(os.lstat(path), path=path)
+
+print rec
+
+</t>
+<t tx="aum.20060527114053">def delChild(self, rec):
+ """
+ Tries to remove a child entry
+ """
+ if rec in self.children:
+ self.children.remove(rec)
+ self.size -= 1
+
+ else:
+ print "eh? trying to remove %s from %s" % (rec.path, self.path)
+
+</t>
+<t tx="aum.20060527114534">def addToCache(self, rec=None, **kw):
+ """
+ Tries to 'cache' a given file/dir record, and
+ adds it to parent dir
+ """
+ if rec == None:
+ rec = FileRecord(**kw)
+
+ path = rec.path
+
+ # barf if file/dir already exists
+ if self.files.has_key(path):
+ self.log("addToCache: already got %s !!!" % path)
+ return
+
+ #print "path=%s" % path
+
+ # if not root, add to parent
+ if path != '/':
+ parentPath = os.path.split(path)[0]
+ parentRec = self.files.get(parentPath, None)
+ parentRec.addChild(rec)
+ if not parentRec:
+ self.log("addToCache: no parent of %s ?!?!" % path)
+ return
+
+ # ok, add to our table
+ self.files[path] = rec
+
+ # done
+ return rec
+
+</t>
+<t tx="aum.20060527114743">def delFromCache(self, rec):
+ """
+ Tries to remove file/dir record from cache
+ """
+ path = rec.path
+ parentPath = os.path.split(path)[0]
+
+ if self.files.has_key(path):
+ del self.files[path]
+
+ parentRec = self.files.get(parentPath, None)
+ if parentRec:
+ parentRec.delChild(rec)
+
+</t>
+<t tx="aum.20060527140140.2">def write(self, buf):
+
+ self.stream.write(buf)
+ self.size = len(self.stream.getvalue())
+
+</t>
+<t tx="aum.20060527195652"># generate a new keypair
+self.connectToNode()
+pubkey, privkey = self.node.genkey()
+rec = self.addToCache(
+ path=path,
+ isreg=True,
+ data=pubkey+"\n"+privkey,
+ perm=0444,
+ )
+</t>
</tnodes>
</leo_file>
Modified: trunk/apps/pyFreenet/fcp/node.py
===================================================================
--- trunk/apps/pyFreenet/fcp/node.py 2006-05-27 08:49:50 UTC (rev 8881)
+++ trunk/apps/pyFreenet/fcp/node.py 2006-05-27 12:22:54 UTC (rev 8882)
@@ -313,6 +313,8 @@
else:
opts["DSOnly"] = "false"
+ if uri.startswith("freenet:CHK@") or uri.startswith("CHK@"):
+ uri = os.path.splitext(uri)[0]
opts['URI'] = uri
opts['MaxRetries'] = kw.get("maxretries", 3)
Modified: trunk/apps/pyFreenet/freedisk.py
===================================================================
--- trunk/apps/pyFreenet/freedisk.py 2006-05-27 08:49:50 UTC (rev 8881)
+++ trunk/apps/pyFreenet/freedisk.py 2006-05-27 12:22:54 UTC (rev 8882)
@@ -19,12 +19,14 @@
#@+others
#@+node:imports
-import sys, os, time, stat
+import sys, os, time, stat, errno
+from StringIO import StringIO
import thread
from threading import Lock
import traceback
from Queue import Queue
-import sha
+import sha, md5
+from UserString import MutableString
from errno import *
from stat import *
@@ -60,6 +62,9 @@
inodes = {}
inodesNext = 1
+# set this to disable hits to node, for debugging
+_no_node = 0
+
#@-node:globals
#@+node:class ErrnoWrapper
class ErrnoWrapper:
@@ -71,6 +76,7 @@
try:
return apply(self.func, args, kw)
except (IOError, OSError), detail:
+ traceback.print_exc()
# Sometimes this is an int, sometimes an instance...
if hasattr(detail, "errno"): detail = detail.errno
return -detail
@@ -114,7 +120,7 @@
argv = sys.argv
argc = len(argv)
- self.log("argv=%s" % argv)
+ #self.log("argv=%s" % argv)
## physical thing to mount
#self.configfile = argv[1]
@@ -152,6 +158,11 @@
if hasattr( self, 'debug'):
d['lopts'] = 'debug';
+ #opts = self.optdict
+ #for k in ['wsize', 'rsize']:
+ # if opts.has_key(k):
+ # d[k] = int(opts[k])
+
k=[]
if hasattr(self,'allow_other'):
k.append('allow_other')
@@ -183,12 +194,14 @@
initialFiles = [
"/",
- "/cmd/",
- "/cmd/genkey",
- "/cmd/genkeypair",
+ # "/cmd/",
+ # "/cmd/genkey",
+ # "/cmd/genkeypair",
+ "/get/",
+ "/put/",
#"/cmd/invertprivatekey/",
"/keys/",
- "/private/",
+ # "/private/",
"/usr/",
]
@@ -203,7 +216,7 @@
Fuse.__init__(self, *args, **kw)
- if 1:
+ if 0:
self.log("xmp.py:Xmp:mountpoint: %s" % repr(self.mountpoint))
self.log("xmp.py:Xmp:unnamed mount options: %s" % self.optlist)
self.log("xmp.py:Xmp:named mount options: %s" % self.optdict)
@@ -232,9 +245,10 @@
self.privKeypairLock = Lock()
try:
+ self.node = None
self.connectToNode()
except:
- self.node = None
+ #raise
pass
# do stuff to set up your filesystem here, if you want
@@ -293,6 +307,8 @@
#@+node:setupFiles
def setupFiles(self):
"""
+ Create initial file/directory layout, according
+ to attributes 'initialFiles' and 'chrFiles'
"""
# easy map of files
self.files = {}
@@ -301,13 +317,8 @@
for path in self.initialFiles:
# initial attribs
- isReg = False
- isDir = False
- isChr = False
- isSock = False
- isFifo = False
- perm = 0
- size = 0
+ isReg = isDir = isChr = isSock = isFifo = False
+ perm = size = 0
# determine file type
if path.endswith("/"):
@@ -325,17 +336,6 @@
# by default, it's a regular file
isReg = True
- # get parent, if any
- pathBits = path.split("/")
- if len(pathBits) > 1:
- # we have a parent - add this rec to parent
- parentPath = "/".join(pathBits[:-1])
- if not parentPath:
- parentPath = "/"
- parentRec = self.files.get(parentPath, None)
- else:
- parentRec = None
-
# create permissions field
if isDir:
perm |= 0755
@@ -343,18 +343,14 @@
perm |= 0444
# create record for this path
- rec = FileRecord(path=path,
- size=size,
- isdir=isDir, isreg=isReg, ischr=isChr,
- issock=isSock, isfifo=isFifo,
- perm=perm)
- self.files[path] = rec
+ self.addToCache(
+ path=path,
+ perm=perm,
+ size=size,
+ isdir=isDir, isreg=isReg, ischr=isChr,
+ issock=isSock, isfifo=isFifo,
+ )
- # add to parent, if any
- if parentRec:
- parentRec.addChild(rec)
-
-
#@-node:setupFiles
#@+node:connectToNode
def connectToNode(self):
@@ -366,9 +362,9 @@
self.node = fcp.FCPNode(host=self.fcpHost,
port=self.fcpPort,
verbosity=self.fcpVerbosity)
- self.log("pubkey=%s" % self.pubkey)
- self.log("privkey=%s" % self.privkey)
- self.log("cachedir=%s" % self.cachedir)
+ #self.log("pubkey=%s" % self.pubkey)
+ #self.log("privkey=%s" % self.privkey)
+ #self.log("cachedir=%s" % self.cachedir)
#@-node:connectToNode
#@+node:log
@@ -397,94 +393,61 @@
def getattr(self, path):
rec = self.files.get(path, None)
-
- #if path in self.knownDirs:
- # print "Return record for known dir %s" % path
- # rec = self.getDirStat(path)
- #else:
-
- # fallback to mainstream fs, delete this later
if not rec:
-
- if 0 or path.startswith("/cmd/invertprivatekey/"):
- prefix = "/cmd/invertprivatekey/"
- prefixlen = len(prefix)
- rec = FileRecord(path=path, isdir=True)
- uri = path[prefixlen:]
-
# retrieving a key?
- elif path.startswith("/keys/"):
- # are we seeking key, or mimetype?
- if path.endswith(".mimetype"):
- getMimetype = True
- path = path[:-9]
- else:
- getMimetype = False
-
+ if path.startswith("/keys/"):
+ #@ <<generate keypair>>
+ #@+node:<<generate keypair>>
+ # generate a new keypair
+ self.connectToNode()
+ pubkey, privkey = self.node.genkey()
+ rec = self.addToCache(
+ path=path,
+ isreg=True,
+ data=pubkey+"\n"+privkey,
+ perm=0444,
+ )
+ #@-node:<<generate keypair>>
+ #@nl
+ elif path.startswith("/get/"):
+ #@ <<retrieve/cache key>>
+ #@+node:<<retrieve/cache key>>
# check the cache
- if not self.files.has_key(path):
- # get a key
- uri = path[6:]
- try:
- self.connectToNode()
- mimetype, data = self.node.get(uri)
- rec = FileRecord(path=path,
- size=len(data),
- isreg=True,
- perm=0444,
- )
- rec.mimetype = mimetype
- rec.data = data
- self.files[path] = rec
- self.files["/keys"].addChild(rec)
-
- except:
- traceback.print_exc()
- print "ehhh?? path=%s" % path
- raise IOError((2, path))
- else:
- rec = self.files[path]
+ if _no_node:
+ print "FIXME: returning IOerror"
+ raise IOError(errno.ENOENT, path)
- rec1 = FileRecord(rec, path=path)
- if getMimetype:
- rec1.size = len(rec.mimetype)
- rec = rec1
-
+ # get a key
+ uri = path.split("/", 2)[-1]
+ try:
+ self.connectToNode()
+ mimetype, data = self.node.get(uri)
+ rec = FileRecord(path=path,
+ isreg=True,
+ perm=0644,
+ data=data,
+ )
+ self.addToCache(rec)
+
+ except:
+ traceback.print_exc()
+ #print "ehhh?? path=%s" % path
+ raise IOError(errno.ENOENT, path)
+
+ #@-node:<<retrieve/cache key>>
+ #@nl
else:
+ #@ <<try host fs>>
+ #@+node:<<try host fs>>
+ # try the host filesystem
print "getattr: no rec for %s, hitting main fs" % path
rec = FileRecord(os.lstat(path), path=path)
- else:
- print "getattr: found rec for %s" % path
+
+ print rec
+
+ #@-node:<<try host fs>>
+ #@nl
- # now gotta do some fudging to pre-cache any required keys
-
- # single private key?
- if path == '/cmd/genkey':
- self.privKeyLock.acquire()
- if not self.privKeyQueue:
- self.connectToNode()
- privkey = self.node.genkey()[1]
- self.privKeyQueue.append(privkey)
- else:
- privkey = self.privKeyQueue[0]
- size = len(privkey)
- self.privKeyLock.release()
- rec.size = size
-
- # key pair?
- elif path == '/cmd/genkeypair':
- self.privKeypairLock.acquire()
- if not self.privKeypairQueue:
- self.connectToNode()
- privkey = "\n".join(self.node.genkey())
- self.privKeypairQueue.append(privkey)
- else:
- privkey = self.privKeypairQueue[0]
- size = len(privkey)
- self.privKeypairLock.release()
- rec.size = size
-
-
self.log("getattr: path=%s" % path)
self.log(" mode=0%o" % rec.mode)
self.log(" inode=0x%x" % rec.inode)
@@ -496,8 +459,9 @@
self.log(" atime=%d" % rec.atime)
self.log(" mtime=%d" % rec.mtime)
self.log(" ctime=%d" % rec.ctime)
+ self.log("rec=%s" % str(rec))
- return rec
+ return tuple(rec)
#@-node:getattr
#@+node:readlink
@@ -534,14 +498,16 @@
def unlink(self, path):
# remove existing file?
- if path.startswith("/keys/"):
+ if path.startswith("/get/") \
+ or path.startswith("/put/") \
+ or path.startswith("/keys/"):
rec = self.files.get(path, None)
if not rec:
- raise IOError((2, path))
- self.files["/keys"].children.remove(rec)
- del self.files[path]
+ raise IOError(2, path)
+ self.delFromCache(rec)
return 0
+ # fallback on host fs
ret = os.unlink(path)
self.log("unlink: path=%s\n => %s" % (path, ret))
return ret
@@ -606,15 +572,30 @@
#@-node:truncate
#@+node:mknod
def mknod(self, path, mode, dev):
- """ Python has no os.mknod, so we can only do some things """
+ """ Python has no os.mknod, so we can only do some things """
+ # start key write, if needed
+ if path.startswith("/put/"):
- if S_ISREG(mode):
- ret = open(path, "w")
- else:
- ret = -EINVAL
+ # see if an existing file
+ if self.files.has_key(path):
+ raise IOError(errno.EEXIST, path)
- self.log("mknod: path=%s mode=%s dev=%s\n => %s" % (path, mode, dev,
ret))
+ rec = self.addToCache(
+ path=path, isreg=True, iswriting=True,
+ perm=0644)
+ ret = 0
+ else:
+ # fall back on host os
+ if S_ISREG(mode):
+ file(path, "w").close()
+ ret = 0
+ else:
+ ret = -EINVAL
+
+ self.log("mknod: path=%s mode=0%o dev=%s\n => %s" % (
+ path, mode, dev, ret))
+
return ret
#@-node:mknod
@@ -639,94 +620,40 @@
self.log("open: path=%s flags=%s" % (path, flags))
- # frig for /keys/
- if path.endswith(".mimetype"):
- isMimetype = True
- path = path[:-9]
- else:
- isMimetype = False
-
# see if it's an existing file
rec = self.files.get(path, None)
- if not rec:
+
+ if rec:
+ # barf if not regular file
+ if not (rec.isreg or rec.ischr):
+ self.log("open: %s is not regular file" % path)
+ raise IOError(errno.EIO, "Not a regular file: %s" % path)
+
+ else:
# fall back to host fs
os.close(os.open(path, flags))
- return 0
- # see if reading genkey files
- if 0:
- if path == '/key/genkey':
- self.connectToNode()
- self.privKeyLock.acquire()
- self.privKeyQueue.append(self.node.genkey()[1])
- self.privKeyLock.release()
- elif path == '/key/genkeypair':
- self.connectToNode()
- self.privKeypairLock.acquire()
- self.privKeypairQueue.append("\n".join(self.node.genkey()))
- self.privKeypairLock.release()
+ self.log("open: open of %s succeeded" % path)
- # try for pseudo-files
- for p in ["/keys/", "/cmd/genkey", "/cmd/invertprivatekey/"]:
- if path.startswith(p):
- return 0
-
- # barf if not regular file
- if not (rec.isreg or rec.ischr):
- raise IOError("Not a regular file: %s" % path)
-
# seems ok
return 0
+
#@-node:open
#@+node:read
def read(self, path, length, offset):
"""
"""
- # see if reading a previously stat-ed key
- if path.startswith("/keys/"):
- # see if we're getting mimetype
- if path.endswith(".mimetype"):
- getMimetype = True
- path = path[:-9]
- else:
- getMimetype = False
-
- # yep, fetch teh record if possible
- rec = self.files[path]
- if getMimetype:
- return rec.mimetype
- else:
- return rec.data
+ # forward to existing file if any
+ rec = self.files.get(path, None)
+ if rec:
+ rec.seek(offset)
+ buf = rec.read(length)
- # intercept magic files
- if path == '/cmd/genkeypair':
- # a genkeypair command, return public,private on 2 lines
- self.privKeypairLock.acquire()
- if not self.privKeypairQueue:
- self.privKeypairLock.release()
- return ''
- privkey = self.privKeypairQueue.pop(0)
- self.privKeypairLock.release()
- buf = privkey
-
- elif path == '/cmd/genkey':
- # a genkey command, just return private key
- self.privKeyLock.acquire()
- if not self.privKeyQueue:
- self.privKeyLock.release()
- return ''
- privkey = self.privKeyQueue.pop(0)
- self.privKeyLock.release()
- buf = privkey
-
- elif path.startswith("/cmd/invertprivatekey"):
- self.connectToNode()
- privkey = os.path.split(path)[-1]
- pubkey = self.node.invertprivate(privkey)
- self.log("read /cmd/invertprivate:\n priv=%s\npub=%s" % (
- privkey, pubkey))
- buf = pubkey.split("\0")[0]
-
+ self.log("read: path=%s length=%s offset=%s\n => %s" % (
+ path, length, offset, len(buf)))
+ #print repr(buf)
+ return buf
+
else:
# fall back on host fs
f = open(path, "r")
@@ -742,18 +669,99 @@
#@+node:write
def write(self, path, buf, off):
+ dataLen = len(buf)
+
+ rec = self.files.get(path, None)
+ if rec:
+ # write to existing 'file'
+ rec.seek(off)
+ rec.write(buf)
+ else:
+ f = open(path, "r+")
+ f.seek(off)
+ nwritten = f.write(buf)
+ f.flush()
+
self.log("write: path=%s buf=[%s bytes] off=%s" % (path, len(buf),
off))
- f = open(path, "r+")
- f.seek(off)
- f.write(buf)
- f.flush()
- return len(buf)
+ #return nwritten
+ return dataLen
#@-node:write
#@+node:release
def release(self, path, flags):
+ rec = self.files.get(path, None)
+ if not rec:
+ return
+
+ # if writing, save the thing
+ if rec.iswriting:
+ # what uri?
+ rec.iswriting = False
+ uri = os.path.split(path)[1]
+
+ # frigs to allow fancy CHK@ inserts
+ if uri.startswith("CHK@"):
+ putUri = "CHK@"
+ else:
+ putUri = uri
+ ext = os.path.splitext(uri)[1]
+
+ try:
+ self.log("release: inserting %s" % uri)
+
+ mimetype = fcp.node.guessMimetype(path)
+ data = rec.data
+
+ # empty the pseudo-file till a result is through
+ rec.data = 'inserting'
+
+ self.connectToNode()
+
+ #print "FIXME: data=%s" % repr(data)
+
+ if _no_node:
+ print "FIXME: not inserting"
+ getUri = "NO_URI"
+ else:
+ # perform the insert
+ getUri = self.node.put(
+ putUri,
+ data=data,
+ mimetype=mimetype)
+
+ # strip 'freenet:' prefix
+ if getUri.startswith("freenet:"):
+ getUri = getUri[8:]
+
+ # restore file extension
+ if getUri.startswith("CHK@"):
+ getUri += ext
+
+ # now cache the read-back
+ self.addToCache(
+ path="/get/"+getUri,
+ data=data,
+ perm=0444,
+ isreg=True,
+ )
+
+ # and adjust the written file to reveal read uri
+ rec.data = getUri
+
+ self.log("release: inserted %s as %s ok" % (
+ uri, mimetype))
+
+ except:
+ traceback.print_exc()
+ rec.data = 'failed'
+ self.log("release: insert of %s failed" % uri)
+ raise IOError(errno.EIO, "Failed to insert")
+
+ self.log("release: done with insertion")
+ return 0
+
self.log("release: path=%s flags=%s" % (path, flags))
return 0
@@ -798,6 +806,56 @@
return sha.new(path).hexdigest()
#@-node:hashpath
+ #@+node:addToCache
+ def addToCache(self, rec=None, **kw):
+ """
+ Tries to 'cache' a given file/dir record, and
+ adds it to parent dir
+ """
+ if rec == None:
+ rec = FileRecord(**kw)
+
+ path = rec.path
+
+ # barf if file/dir already exists
+ if self.files.has_key(path):
+ self.log("addToCache: already got %s !!!" % path)
+ return
+
+ #print "path=%s" % path
+
+ # if not root, add to parent
+ if path != '/':
+ parentPath = os.path.split(path)[0]
+ parentRec = self.files.get(parentPath, None)
+ parentRec.addChild(rec)
+ if not parentRec:
+ self.log("addToCache: no parent of %s ?!?!" % path)
+ return
+
+ # ok, add to our table
+ self.files[path] = rec
+
+ # done
+ return rec
+
+ #@-node:addToCache
+ #@+node:delFromCache
+ def delFromCache(self, rec):
+ """
+ Tries to remove file/dir record from cache
+ """
+ path = rec.path
+ parentPath = os.path.split(path)[0]
+
+ if self.files.has_key(path):
+ del self.files[path]
+
+ parentRec = self.files.get(parentPath, None)
+ if parentRec:
+ parentRec.delChild(rec)
+
+ #@-node:delFromCache
#@+node:getDirStat
def getDirStat(self, path):
"""
@@ -933,25 +991,27 @@
def __init__(self, statrec=None, **kw):
"""
"""
- if statrec == None:
+ # got a statrec arg?
+ if statrec:
+ # yes, extract main items
+ dev = statrec[stat.ST_DEV]
+ nlink = statrec[stat.ST_NLINK]
+ uid = statrec[stat.ST_UID]
+ gid = statrec[stat.ST_GID]
+ size = statrec[stat.ST_SIZE]
+ else:
+ # no, fudge a new one
statrec = [0,0,0,0,0,0,0,0,0,0]
dev = 0
nlink = 1
uid = myuid
gid = mygid
size = 0
- else:
- dev = statrec[stat.ST_DEV]
- nlink = statrec[stat.ST_NLINK]
- uid = statrec[stat.ST_UID]
- gid = statrec[stat.ST_GID]
- size = statrec[stat.ST_SIZE]
+ # convert tuple to list if need be
if not hasattr(statrec, '__setitem__'):
statrec = list(statrec)
- # handle keywords
-
# build mode mask
mode = kw.get('mode', 0)
if kw.get('isdir', False):
@@ -969,14 +1029,26 @@
if kw.get('issock', False):
mode |= stat.S_IFSOCK
+ # handle non-file-related keywords
perm = kw.get('perm', 0)
mode |= perm
path = kw['path']
self.path = path
+
+ self.stream = StringIO()
+
+ data = kw.get('data', '')
+ self.stream = StringIO(data)
+
+ for key in ['iswriting']:
+ if kw.has_key(key):
+ setattr(self, key, kw[key])
+
+ # child files/dirs
self.children = []
- print "FileRecord.__init__: path=%s" % path
+ #print "FileRecord.__init__: path=%s" % path
# get inode number
inode = pathToInode(path)
@@ -987,8 +1059,8 @@
mtime = kw.get('mtime', now)
ctime = kw.get('ctime', now)
- print "statrec[stat.ST_MODE]=%s" % statrec[stat.ST_MODE]
- print "mode=%s" % mode
+ #print "statrec[stat.ST_MODE]=%s" % statrec[stat.ST_MODE]
+ #print "mode=%s" % mode
statrec[stat.ST_MODE] |= mode
statrec[stat.ST_INO] = inode
@@ -997,14 +1069,16 @@
statrec[stat.ST_UID] = uid
statrec[stat.ST_GID] = gid
- if kw.has_key('size'):
- statrec[stat.ST_SIZE] = kw['size']
+ statrec[stat.ST_SIZE] = len(self.stream.getvalue())
+
statrec[stat.ST_ATIME] = atime
statrec[stat.ST_MTIME] = atime
statrec[stat.ST_CTIME] = atime
list.__init__(self, statrec)
+ self.iswriting = kw.get('iswriting', False)
+
#@-node:__init__
#@+node:__getattr__
def __getattr__(self, attr):
@@ -1063,7 +1137,15 @@
if attr == 'ctime':
return self[stat.ST_ATIME]
+
+ if attr == 'data':
+ return self.stream.getvalue()
+ try:
+ return getattr(self.stream, attr)
+ except:
+ pass
+
raise AttributeError(attr)
#@-node:__getattr__
@@ -1131,10 +1213,23 @@
elif attr == 'ctime':
self[stat.ST_CTIME] = val
+ elif attr == 'data':
+ oldPos = self.stream.tell()
+ self.stream = StringIO(val)
+ self.stream.seek(min(oldPos, len(val)))
+ self.size = len(val)
+
else:
self.__dict__[attr] = val
#@-node:__setattr__
+ #@+node:write
+ def write(self, buf):
+
+ self.stream.write(buf)
+ self.size = len(self.stream.getvalue())
+
+ #@-node:write
#@+node:addChild
def addChild(self, rec):
"""
@@ -1147,6 +1242,19 @@
self.size += 1
#@-node:addChild
+ #@+node:delChild
+ def delChild(self, rec):
+ """
+ Tries to remove a child entry
+ """
+ if rec in self.children:
+ self.children.remove(rec)
+ self.size -= 1
+
+ else:
+ print "eh? trying to remove %s from %s" % (rec.path, self.path)
+
+ #@-node:delChild
#@-others
#@-node:class FileRecord
@@ -1160,17 +1268,23 @@
if inode != None:
return inode
- # generate whole new inode
- global inodesNext
- inode = inodesNext
- inodesNext += 1
+ # try hashing the path to 32bit
+ inode = int(md5.new(path).hexdigest()[:7], 16)
+
+ # and ensure it's unique
+ while inodes.has_key(inode):
+ inode += 1
+
+ # register it
inodes[path] = inode
+
+ # done
return inode
-
+
#@-node:pathToInode
#@+node:timeNow
def timeNow():
- return int(time.time()) & 0xffffffff
+ return int(time.time()) & 0xffffffffL
#@-node:timeNow
#@+node:mainline