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:
M | domfs.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);