#include #include #include #include #include <9p.h> #include #include #include #include #include #define CARTSLOC "./carts/" #define CTL_HASHV 139931 #define SHUTDOWN_HASHV 11192337284248 /* clang-format off */ char clca(char c) { return c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c; } /* char to lowercase */ char cuca(char c) { return c >= 'a' && c <= 'z' ? c - ('a' - 'A') : c; } /* char to uppercase */ int slen(char *s) { int i = 0; while(s[i] && s[++i]) { ; } return i; } /* string length */ char *st__(char *s, char (*fn)(char)) { int i = 0; char c; while((c = s[i])) s[i++] = fn(c); return s; } char *stuc(char *s) { return st__(s, cuca); } /* string to uppercase */ char *stlc(char *s) { return st__(s, clca); } /* string to lowercase */ char *scpy(char *src, char *dst, int len) { int i = 0; while((dst[i] = src[i]) && i < len - 2) i++; dst[i + 1] = '\0'; return dst; } /* string copy */ int scmp(char *a, char *b) { int i = 0; while(a[i] == b[i]) if(!a[i++]) return 1; return 0; } /* string compare */ char *scsw(char *s, char a, char b) { int i = 0; char c; while((c = s[i])) s[i++] = c == a ? b : c; return s; } /* string char swap */ char *scat(char *dst, const char *src) { char *ptr = dst + slen(dst); while(*src) *ptr++ = *src++; *ptr = '\0'; return dst; } /* string cat */ int ssin(char *s, char *ss) { int a = 0, b = 0; while(s[a]) { if(s[a] == ss[b]) { if(!ss[b + 1]) return a - b; b++; } else b = 0; a++; } return -1; } /* string substring index */ char *ccat(char *dst, char c) { int len = slen(dst); dst[len] = c; dst[len + 1] = '\0'; return dst; } /* clang-format on */ int chatty9p = 1; static int serving = 1; static char Ebad[] = "something bad happened"; static char Enomem[] = "no memory"; typedef struct Ramfile Ramfile; struct Ramfile { char* data; int ndata; }; void fsread(Req* r) { Ramfile* rf; vlong offset; long count; rf = r->fid->file->aux; offset = r->ifcall.offset; count = r->ifcall.count; /*print("read %ld %lld\n", *count, offset); */ if (offset >= rf->ndata) { r->ofcall.count = 0; respond(r, nil); return; } if (offset + count >= rf->ndata) count = rf->ndata - offset; memmove(r->ofcall.data, rf->data + offset, count); r->ofcall.count = count; respond(r, nil); } unsigned long long hash(char* str) { unsigned long long h; unsigned char* p; h = 0; for (p = (unsigned char*)str; *p != '\0'; p++) h = 37 * h + *p; return h; // or, h % ARRAY_SIZE; } void fswrite(Req* r) { void* v; Ramfile* rf; vlong offset; long count; rf = r->fid->file->aux; offset = r->ifcall.offset; count = r->ifcall.count; if (offset + count >= rf->ndata) { v = realloc(rf->data, offset + count); if (v == nil) { respond(r, Enomem); return; } rf->data = v; rf->ndata = offset + count; r->fid->file->dir.length = rf->ndata; } memmove(rf->data + offset, r->ifcall.data, count); r->ofcall.count = count; respond(r, nil); } void handlectl(Req* r) { char cmd[16]; char* c = r->ifcall.data; while (*c && *c != ' ') { ccat(cmd, *c); } unsigned long long const cmd_hashv = hash(cmd); switch (cmd_hashv) { case SHUTDOWN_HASHV: serving = 0; break; default: break; } r->ofcall.count = 16; r->fid->file->dir.length = 16; respond(r, nil); } void xrxswrite(Req* r) { unsigned int filename_hashv = hash(r->ifcall.name); printf(r->ifcall.name); switch (filename_hashv) { case CTL_HASHV: handlectl(r); break; default: fswrite(r); break; } } void fscreate(Req* r) { Ramfile* rf; File* f; printf("eee"); if (f = createfile(r->fid->file, r->ifcall.name, nil, r->ifcall.perm, nil)) { rf = emalloc9p(sizeof *rf); f->aux = rf; r->fid->file = f; r->ofcall.qid = f->dir.qid; respond(r, nil); return; } respond(r, Ebad); } void xrxscreate(Req* r) { unsigned int filename_hashv = hash(r->ifcall.name); printf("fff"); switch (filename_hashv) { case CTL_HASHV: handlectl(r); break; default: fscreate(r); break; } } void fsopen(Req* r) { Ramfile* rf; printf("ooo"); rf = r->fid->file->aux; if (rf && (r->ifcall.mode & OTRUNC)) { rf->ndata = 0; r->fid->file->dir.length = 0; } respond(r, nil); } void fsdestroyfile(File* f) { Ramfile* rf; /*fprint(2, "clunk\n"); */ rf = f->aux; if (rf) { free(rf->data); free(rf); } } String** listdir(char* path) { String** self = malloc(128 * sizeof(String*)); DIR* dir; struct dirent* ent; int i = 0; char* c; if ((dir = opendir(path)) != NULL) { while ((ent = readdir(dir)) != NULL) { c = ent->d_name; if (scmp(c, ".") || scmp(c, "..")) { continue; } self[i] = s_new(); while (*c) { s_putc(self[i], *c++); } s_terminate(self[i++]); } closedir(dir); } self[i] = nil; return self; } Ramfile* createrf(Tree* t, char* path, char* filename, int perm) { Ramfile* rf; File* f = walkfile(t->root, path); createfile(f, filename, nil, perm, nil); rf = (Ramfile*)emalloc9p(sizeof *rf); f->aux = rf; return rf; } void writerf(Tree* t, char* path, char* data) { Ramfile* rf; File* f = walkfile(t->root, path); rf = (Ramfile*)emalloc9p(sizeof *rf); rf->data = data; rf->ndata = slen(data); f->aux = rf; } void xrxswstat(Req* r) { r->fid->omode = OWRITE; respond(r, nil); } Srv fs = { .open = fsopen, .read = fsread, .write = xrxswrite, .create = xrxscreate, .wstat = xrxswstat }; int threadmaybackground(void) { return 1; } void threadmain(int argc, char* argv[]) { Tree* tree; char* mtpt = nil; char* usocket = nil; int i; String** cart; char cartsloc[256] = "./carts/"; char ctlbuf[128] = "some data"; Ramfile ctlfile = {ctlbuf, 128}; /* if -m PATH is supplied, mount on PATH */ /* if -s NAME is supplied, create a socket for the namespace */ /* otherwise, just use srv() (for wrapping with socat or inetd) */ if (argc >= 3) { for (i = 0; i < argc; i++) { if (scmp(argv[i], "-m")) { mtpt = argv[++i]; printf("serving on %s", mtpt); } else if (scmp(argv[i], "-s")) { usocket = argv[++i]; printf("serving socket namespace %s", usocket); } } } fs.tree = alloctree(nil, nil, DMDIR | 0777, fsdestroyfile); tree = fs.tree; createfile(tree->root, "carts", nil, DMDIR | 0555, nil); createfile(tree->root, "ctl", nil, 0600, &ctlfile); String** carts = listdir("carts/"); cart = carts; while (*cart) { createfile(walkfile(tree->root, "carts"), (*cart)->base, nil, 0444, nil); cart++; } fs.foreground = 1; while (serving) { if (argc >= 3) { if (mtpt != nil && access(mtpt, AEXIST) < 0 && access(mtpt, AEXIST) < 0) sysfatal("mountpoint %s does not exist", mtpt); threadpostmountsrv(&fs, usocket, mtpt, MREPL | MCREATE); threadexits(0); } else { srv(&fs); } } }