domfs

Document Object Model as a filesystem for plan9 os
git clone git://nsmpr.xyz/domfs.git
Log | Files | Refs | README

commit a546033de2be89798d3cdbd466dce57255d462af
parent aa1edf01351388f45df7e24e25183e8362cdb61b
Author: Pavel Renev <an2qzavok@gmail.com>
Date:   Sat, 14 Nov 2020 21:01:56 +0000

creating, writing, reading and removing user files

Diffstat:
Mdomfs.c | 234+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 217 insertions(+), 17 deletions(-)

diff --git a/domfs.c b/domfs.c @@ -7,6 +7,7 @@ typedef struct Finf Finf; /* file info */ typedef struct DTree DTree; typedef struct Node Node; +typedef struct Fusr Fusr; enum { /* file types */ ROOT, @@ -14,6 +15,8 @@ enum { /* file types */ NODE, CTRL, USER, + + REMV = -1, }; struct Finf { @@ -24,16 +27,26 @@ struct Finf { }; struct DTree { - Node **nodes; uvlong id; + Node **nodes; uvlong nidcount; Finf *finf; }; struct Node { + uvlong id; + DTree *tree; Node *parent; Node **children; - uvlong id; + Fusr **files; + Finf *finf; +}; + +struct Fusr { + Node *node; + char *name; + char *data; + uvlong nsize; Finf *finf; }; @@ -61,10 +74,24 @@ stackpush(void ***v, void *new) (*v)[n+1] = nil; } +void +stackremv(void ***v, void *w) +{ + long i, n; + int remv; + remv = 0; + n = stacksize(*v); + for (i = 0; i < n; i++) { + if ((*v)[i] == w) remv = 1; + if (remv != 0) (*v)[i] = (*v)[i+1]; + } + if (remv != 0) *v = realloc(*v, (n) * sizeof(void*)); +} + Finf* newfinf(int type, void *aux) { - static uvlong id; + static uvlong id = 0; Finf *new; new = malloc(sizeof(Finf)); switch (type) { @@ -80,9 +107,9 @@ newfinf(int type, void *aux) default: sysfatal("newfinf: unknown file type %d", type); } + new->id = id++; new->type = type; new->aux = aux; - id++; return new; } @@ -103,9 +130,10 @@ newtree(void) DTree* gettree(DTree **trees, uvlong id) { - DTree *tp; - for (tp = trees[0]; tp != nil; tp++) - if (tp->id == id) return tp; + DTree **tp; + if (trees == nil) return nil; + for (tp = trees; *tp != nil; tp++) + if ((*tp)->id == id) return *tp; return nil; } @@ -118,6 +146,7 @@ newnode(DTree *T) new->children = nil; new->id = ++T->nidcount; new->finf = newfinf(NODE, new); + new->tree = T; stackpush(&files, new->finf); return new; } @@ -126,11 +155,33 @@ Node* getnode(DTree *T, uvlong n) { Node **np; - for (np = T->nodes; np != nil; np++) { - if ((*np)->id == n) { - return *np; - } - } + if (T->nodes == nil) return nil; + for (np = T->nodes; *np != nil; np++) + if ((*np)->id == n) return *np; + return nil; +} + +Fusr* +newfile(char *name) +{ + Fusr *new; + new = malloc(sizeof(Fusr)); + new->node = nil; + new->name = strdup(name); + new->data = nil; + new->nsize = 0; + new->finf = newfinf(USER, new); + stackpush(&files, new->finf); + return new; +} + +Fusr* +getfile(Node *node, char *name) +{ + Fusr **fp; + if (node->files == nil) return nil; + for (fp = node->files; *fp != nil; fp++) + if (strcmp(name, (*fp)->name) == 0) return *fp; return nil; } @@ -147,6 +198,7 @@ int dirgenroot(int n, Dir *dir, void*) { DTree *t; + if (trees == nil) return -1; t = trees[n]; if (t == nil) return -1; nulldir(dir); @@ -168,6 +220,8 @@ dirgentree(int n, Dir *dir, void *aux) DTree *tree; Node *node; tree = aux; + if (tree == nil) return -1; + if (tree->nodes == nil) return -1; node = tree->nodes[n]; if (node == nil) return -1; nulldir(dir); @@ -183,6 +237,29 @@ dirgentree(int n, Dir *dir, void *aux) return 0; } +int +dirgennode(int n, Dir *dir, void *aux) +{ + Node *node; + Fusr *file; + node = aux; + if (node == nil) return -1; + if (node->files == nil) return -1; + file = node->files[n]; + if (file == nil) return -1; + nulldir(dir); + dir->qid = file->finf->qid; + dir->mode = 0666; + dir->atime = time(0); + dir->mtime = time(0); + dir->length = file->nsize; + dir->name = strdup(file->name); + dir->uid = strdup("domfs"); + dir->gid = strdup("domfs"); + dir->muid = strdup(""); + return 0; +} + void fsread(Req *r) { @@ -196,13 +273,74 @@ fsread(Req *r) dirread9p(r, dirgentree, f->aux); break; case NODE: + dirread9p(r, dirgennode, f->aux); + break; case CTRL: case USER: + readbuf(r, ((Fusr*)f->aux)->data, ((Fusr*)f->aux)->nsize); + break; + case REMV: + respond(r, "file does not exist"); + return; default: - sysfatal("fsread: unknown file type: %d", f->type); + respond(r, "fsread: unknown file type"); + return; } + respond(r, nil); +} - //dirread9p(r, dirgen, nil); +void +fswrite(Req *r) +{ + Finf *file; + Fusr *f; + file = r->fid->aux; + switch (file->type) { + case USER: + f = file->aux; + f->nsize = r->ifcall.count; + f->data = realloc(f->data, f->nsize); + memmove(f->data, r->ifcall.data, f->nsize); + r->ofcall.count = f->nsize; + respond(r, nil); + break; + default: + respond(r, "permission denied"); + } +} + +void +fscreate(Req *r) +{ + Node *node; + Finf *rf; + Fusr *f; + rf = r->fid->aux; + if (rf->type != NODE) { + respond(r, "permission denied"); + return; + } + node = rf->aux; + f = newfile(r->ifcall.name); + f->node = node; + stackpush(&(node->files), f); + r->fid->qid = f->finf->qid; + r->ofcall.qid = r->fid->qid; + r->fid->aux = f->finf; + respond(r, nil); +} + +void +fsremove(Req *r) +{ + Finf *f; + f = r->fid->aux; + if (f->type != USER) { + respond(r, "remove prohibited"); + return; + } + f->type = REMV; + respond(r, nil); } @@ -216,6 +354,7 @@ fsclone(Fid *oldfid, Fid *newfid) char* fswalk1(Fid *fid, char *name, Qid *qid) { + void *p; char *chp; uvlong id; Finf *f, *nf; @@ -225,15 +364,35 @@ fswalk1(Fid *fid, char *name, Qid *qid) case ROOT: id = strtoull(name, &chp, 10); // TODO: check if parsed correctly - nf = gettree(trees, id)->finf; + p = gettree(trees, id); + if (p == nil) return "file does not exist"; + nf = ((DTree*)p)->finf; break; case TREE: + if (strcmp("..", name) == 0) { + nf = rootf; + break; + } id = strtoull(name, &chp, 10); - nf = getnode(f->aux, id)->finf; + // TODO: check if parsed correctly + p = getnode(f->aux, id); + if (p == nil) return "file does not exist"; + nf = ((Node*)p)->finf; break; case NODE: + if (strcmp("..", name) == 0) { + nf = ((Node*)f->aux)->tree->finf; + break; + } + p = getfile(f->aux, name); + if (p == nil) return "file does not exist"; + nf = ((Fusr*)p)->finf; + break; case CTRL: case USER: + case REMV: + return "walk on file, what?"; + break; default: sysfatal("fswalk1: unknown file type %d", f->type); } @@ -241,6 +400,7 @@ fswalk1(Fid *fid, char *name, Qid *qid) *qid = nf->qid; fid->qid = *qid; fid->aux = nf; + return nil; } @@ -270,15 +430,50 @@ fsstat(Req *r) r->d.mode = 0777|DMDIR; break; case NODE: - case CTRL: + r->d.name = smprint("%ulld", ((Node*)f->aux)->id); + r->d.mode = 0777|DMDIR; + break; case USER: + r->d.name = strdup(((Fusr*)f->aux)->name); + r->d.mode = 0666; + break; + case REMV: + r->d.name = strdup(((Fusr*)f->aux)->name); + r->d.mode = -1; + break; + case CTRL: default: sysfatal("fsstat: unknown file type %d", f->type); } + respond(r, nil); } void +fsdestroyfid(Fid *fid) +{ + /* + * TODO: this whole func is probably not correct; + * 9p(2) man page description of remove func recommends tracking fids that + * access file to be deleted, but I am not sure how to do it + */ + + Finf *f; + Fusr *fu; + f = fid->aux; + if(f != nil && f->type == REMV) { + fu = f->aux; + free(fu->data); + free(fu->name); + fu->nsize = 0; + stackremv(&(fu->node->files), fu); + free(fu); + stackremv(&files, &f); + free(f); + } +} + +void usage(void) { fprint(2, "usage %s [-D][-m /n/dom][-s service]\n", argv0); @@ -316,12 +511,17 @@ main(int argc, char **argv) stackpush(&(trees[0]->nodes), newnode(trees[0])); stackpush(&(trees[0]->nodes), newnode(trees[0])); + Srv fs = { .attach = fsattach, .read = fsread, + .write = fswrite, .clone = fsclone, .walk1 = fswalk1, .stat = fsstat, + .create = fscreate, + .remove = fsremove, + .destroyfid = fsdestroyfid, }; postmountsrv(&fs, srv, mtpt, MREPL);