|
@@ -14,11 +14,18 @@
|
|
|
#include "fns.h"
|
|
|
#include "../port/error.h"
|
|
|
|
|
|
+#define RAM_BLOCK_LEN 32768
|
|
|
+#define RAM_MAGIC 0xbedabb1e
|
|
|
+#define INVALID_FILE "Invalid ram file"
|
|
|
+
|
|
|
struct RamFile {
|
|
|
+ unsigned int magic;
|
|
|
char name[KNAMELEN];
|
|
|
struct RamFile *parent;
|
|
|
struct RamFile *sibling;
|
|
|
uint64_t length;
|
|
|
+ uint64_t alloclength;
|
|
|
+ int busy;
|
|
|
int perm;
|
|
|
int opencount;
|
|
|
int deleteonclose;
|
|
@@ -31,12 +38,49 @@ struct RamFile {
|
|
|
static struct RamFile *ramroot;
|
|
|
static QLock ramlock;
|
|
|
|
|
|
+
|
|
|
+static void
|
|
|
+printramfile(int offset, struct RamFile* file)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ for(i = 0; i < offset; i++) {
|
|
|
+ print(" ");
|
|
|
+ }
|
|
|
+ print("ramfile: %x, magic:%x, name: %s, parent: %x, sibling:%x, length:%d, alloclength: %d, perm: %o\n",
|
|
|
+ file, file->magic, file->name, file->parent, file->sibling, file->length, file->alloclength, file->perm);
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+debugwalkinternal(int offset, struct RamFile* current)
|
|
|
+{
|
|
|
+ printramfile(offset, current);
|
|
|
+ for (current = current->firstchild; current != nil; current = current->sibling) {
|
|
|
+ if(current->perm & DMDIR){
|
|
|
+ debugwalkinternal(offset+1, current);
|
|
|
+ }else{
|
|
|
+ printramfile(offset,current);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+debugwalk()
|
|
|
+{
|
|
|
+ print("***********************\n");
|
|
|
+ debugwalkinternal(0, ramroot);
|
|
|
+}
|
|
|
+
|
|
|
static void
|
|
|
raminit(void)
|
|
|
{
|
|
|
- ramroot = (struct RamFile *)smalloc(sizeof(struct RamFile));
|
|
|
+ ramroot = (struct RamFile *)malloc(sizeof(struct RamFile));
|
|
|
+ if (ramroot == nil) {
|
|
|
+ error(Eperm);
|
|
|
+ }
|
|
|
strcpy(ramroot->name, ".");
|
|
|
+ ramroot->magic = RAM_MAGIC;
|
|
|
ramroot->length = 0;
|
|
|
+ ramroot->alloclength = 0;
|
|
|
ramroot->perm = DMDIR|0777;
|
|
|
ramroot->firstchild = nil;
|
|
|
}
|
|
@@ -57,7 +101,10 @@ ramattach(char *spec)
|
|
|
c->dev = devtabget('@', 0);
|
|
|
if(spec == nil)
|
|
|
spec = "";
|
|
|
- buf = smalloc(1+UTFmax+strlen(spec)+1);
|
|
|
+ buf = malloc(1+UTFmax+strlen(spec)+1);
|
|
|
+ if (buf == nil) {
|
|
|
+ error(Eperm);
|
|
|
+ }
|
|
|
sprint(buf, "#@%s", spec);
|
|
|
c->path = newpath(buf);
|
|
|
c->mode = 0777;
|
|
@@ -126,10 +173,12 @@ ramstat(Chan *c, uint8_t *dp, int32_t n)
|
|
|
Dir dir;
|
|
|
Qid qid;
|
|
|
struct RamFile* current = (struct RamFile*)c->qid.path;
|
|
|
+ if (current->magic != RAM_MAGIC)
|
|
|
+ error(INVALID_FILE);
|
|
|
|
|
|
qlock(&ramlock);
|
|
|
mkqid(&qid, c->qid.path, 0, current->perm & DMDIR ? QTDIR : 0);
|
|
|
- devdir(c, qid, current->name, 0, "harvey", 0555, &dir);
|
|
|
+ devdir(c, qid, current->name, current->length, "harvey", 0555, &dir);
|
|
|
int32_t ret = convD2M(&dir, dp, n);
|
|
|
qunlock(&ramlock);
|
|
|
return ret;
|
|
@@ -145,6 +194,10 @@ ramopen(Chan *c, int omode)
|
|
|
nexterror();
|
|
|
}
|
|
|
Chan* ret = devopen(c, omode, nil, 0, ramgen);
|
|
|
+ struct RamFile* file = (struct RamFile*)c->qid.path;
|
|
|
+ if (file->magic != RAM_MAGIC)
|
|
|
+ error(INVALID_FILE);
|
|
|
+ file->busy++;
|
|
|
qunlock(&ramlock);
|
|
|
poperror();
|
|
|
return ret;
|
|
@@ -154,8 +207,11 @@ static void
|
|
|
delete(struct RamFile* file)
|
|
|
{
|
|
|
qlock(&ramlock);
|
|
|
+ //printramfile(0, file);
|
|
|
+ //debugwalk();
|
|
|
struct RamFile* prev = file->parent->firstchild;
|
|
|
if(prev == file) {
|
|
|
+ // This is the first file - make any sibling the first child
|
|
|
file->parent->firstchild = file->sibling;
|
|
|
} else {
|
|
|
// Find previous file
|
|
@@ -168,10 +224,12 @@ delete(struct RamFile* file)
|
|
|
prev->sibling = file->sibling;
|
|
|
}
|
|
|
}
|
|
|
- if(file->perm & DMDIR){
|
|
|
+ if(!file->perm & DMDIR){
|
|
|
free(file->data);
|
|
|
}
|
|
|
+ file->magic = 0;
|
|
|
free(file);
|
|
|
+ if (0) debugwalk();
|
|
|
qunlock(&ramlock);
|
|
|
}
|
|
|
|
|
@@ -179,6 +237,11 @@ static void
|
|
|
ramclose(Chan* c)
|
|
|
{
|
|
|
struct RamFile* file = (struct RamFile *)c->qid.path;
|
|
|
+ if (file->magic != RAM_MAGIC)
|
|
|
+ error(INVALID_FILE);
|
|
|
+ qlock(&ramlock);
|
|
|
+ file->busy--;
|
|
|
+ qunlock(&ramlock);
|
|
|
if(file->deleteonclose){
|
|
|
delete(file);
|
|
|
}
|
|
@@ -195,6 +258,8 @@ ramread(Chan *c, void *buf, int32_t n, int64_t off)
|
|
|
}
|
|
|
// Read file
|
|
|
struct RamFile *file = (void*)c->qid.path;
|
|
|
+ if (file->magic != RAM_MAGIC)
|
|
|
+ error(INVALID_FILE);
|
|
|
int filelen = file->length;
|
|
|
if (off > filelen){
|
|
|
qunlock(&ramlock);
|
|
@@ -208,19 +273,44 @@ ramread(Chan *c, void *buf, int32_t n, int64_t off)
|
|
|
return n;
|
|
|
}
|
|
|
|
|
|
+typedef double Align;
|
|
|
+typedef union Header Header;
|
|
|
+
|
|
|
+union Header {
|
|
|
+ struct {
|
|
|
+ Header* next;
|
|
|
+ uint size;
|
|
|
+ } s;
|
|
|
+ Align al;
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
static int32_t
|
|
|
ramwrite(Chan* c, void* v, int32_t n, int64_t off)
|
|
|
{
|
|
|
+// Header *p;
|
|
|
+
|
|
|
qlock(&ramlock);
|
|
|
struct RamFile *file = (void*)c->qid.path;
|
|
|
- if(n+off > file->length){
|
|
|
- void *newfile = realloc(file->data, n+off);
|
|
|
- if(newfile == nil){
|
|
|
- return 0;
|
|
|
+ if (file->magic != RAM_MAGIC)
|
|
|
+ error(INVALID_FILE);
|
|
|
+ if(n+off >= file->length){
|
|
|
+ uint64_t alloclength = file->alloclength;
|
|
|
+ while(alloclength < n + off)
|
|
|
+ alloclength += RAM_BLOCK_LEN;
|
|
|
+ if(alloclength > file->alloclength){
|
|
|
+ void *newfile = realloc(file->data, alloclength);
|
|
|
+ if(newfile == nil){
|
|
|
+ qunlock(&ramlock);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ file->data = newfile;
|
|
|
+ file->alloclength = alloclength;
|
|
|
}
|
|
|
- file->data = newfile;
|
|
|
file->length = n+off;
|
|
|
}
|
|
|
+// p = (Header*)file->data - 1;
|
|
|
+// print("length of buffer=%d, header size=%d, header next=%x, start of write=%d, end of write=%d\n", file->alloclength, p->s.size, p->s.next, off, off + n);
|
|
|
memmove(file->data + off, v, n);
|
|
|
qunlock(&ramlock);
|
|
|
return n;
|
|
@@ -235,13 +325,20 @@ ramcreate(Chan* c, char *name, int omode, int perm)
|
|
|
error(Eperm);
|
|
|
|
|
|
struct RamFile* parent = (struct RamFile *)c->qid.path;
|
|
|
+ if (parent->magic != RAM_MAGIC)
|
|
|
+ error(INVALID_FILE);
|
|
|
|
|
|
omode = openmode(omode);
|
|
|
- struct RamFile* file = (struct RamFile*)smalloc(sizeof(struct RamFile));
|
|
|
+ struct RamFile* file = (struct RamFile*)malloc(sizeof(struct RamFile));
|
|
|
+ if (file == nil) {
|
|
|
+ error(Eperm);
|
|
|
+ }
|
|
|
file->length = 0;
|
|
|
+ file->magic = RAM_MAGIC;
|
|
|
strcpy(file->name, name);
|
|
|
file->perm = perm;
|
|
|
file->parent = parent;
|
|
|
+ file->busy = 1;
|
|
|
|
|
|
qlock(&ramlock);
|
|
|
if(waserror()) {
|
|
@@ -253,15 +350,14 @@ ramcreate(Chan* c, char *name, int omode, int perm)
|
|
|
|
|
|
file->sibling = parent->firstchild;
|
|
|
parent->firstchild = file;
|
|
|
- qunlock(&ramlock);
|
|
|
-
|
|
|
mkqid(&c->qid, (uintptr_t)file, 0, file->perm & DMDIR ? QTDIR : 0);
|
|
|
|
|
|
- poperror();
|
|
|
-
|
|
|
c->offset = 0;
|
|
|
c->mode = omode;
|
|
|
c->flag |= COPEN;
|
|
|
+ qunlock(&ramlock);
|
|
|
+
|
|
|
+ poperror();
|
|
|
}
|
|
|
|
|
|
void
|
|
@@ -273,6 +369,8 @@ void
|
|
|
ramremove(Chan* c)
|
|
|
{
|
|
|
struct RamFile* doomed = (struct RamFile *)c->qid.path;
|
|
|
+ if (doomed->magic != RAM_MAGIC)
|
|
|
+ error(INVALID_FILE);
|
|
|
if(doomed->opencount == 0){
|
|
|
delete(doomed);
|
|
|
}
|