2021-06-13 17:22:58 +00:00
|
|
|
#include <u.h>
|
|
|
|
#include <libc.h>
|
|
|
|
#include <fcall.h>
|
|
|
|
#include <thread.h>
|
|
|
|
#include <9p.h>
|
|
|
|
#include <stdio.h>
|
2021-06-24 07:17:34 +00:00
|
|
|
#include <dirent.h>
|
|
|
|
#include <libString.h>
|
2021-06-28 21:37:59 +00:00
|
|
|
#include <mp.h>
|
|
|
|
#include <libsec.h>
|
2021-06-24 07:17:34 +00:00
|
|
|
|
|
|
|
#define CARTSLOC "./carts/"
|
2021-06-28 21:37:59 +00:00
|
|
|
#define CTL_HASHV 139931
|
|
|
|
#define SHUTDOWN_HASHV 11192337284248
|
2021-06-13 17:22:58 +00:00
|
|
|
/* 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 */
|
2021-06-28 21:37:59 +00:00
|
|
|
int chatty9p = 1;
|
|
|
|
static int serving = 1;
|
2021-06-13 17:22:58 +00:00
|
|
|
|
2021-06-16 05:46:47 +00:00
|
|
|
static char Ebad[] = "something bad happened";
|
|
|
|
static char Enomem[] = "no memory";
|
|
|
|
|
|
|
|
typedef struct Ramfile Ramfile;
|
|
|
|
struct Ramfile {
|
|
|
|
char* data;
|
|
|
|
int ndata;
|
|
|
|
};
|
2021-06-14 20:23:06 +00:00
|
|
|
|
2021-06-13 17:22:58 +00:00
|
|
|
void fsread(Req* r) {
|
2021-06-16 05:46:47 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2021-06-28 21:37:59 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2021-06-16 05:46:47 +00:00
|
|
|
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;
|
2021-06-13 17:22:58 +00:00
|
|
|
respond(r, nil);
|
|
|
|
}
|
|
|
|
|
2021-06-28 21:37:59 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-16 05:46:47 +00:00
|
|
|
void fscreate(Req* r) {
|
|
|
|
Ramfile* rf;
|
|
|
|
File* f;
|
2021-06-28 21:37:59 +00:00
|
|
|
printf("eee");
|
2021-06-23 06:48:23 +00:00
|
|
|
if (f = createfile(r->fid->file, r->ifcall.name, nil, r->ifcall.perm, nil)) {
|
2021-06-16 05:46:47 +00:00
|
|
|
rf = emalloc9p(sizeof *rf);
|
|
|
|
f->aux = rf;
|
|
|
|
r->fid->file = f;
|
|
|
|
r->ofcall.qid = f->dir.qid;
|
|
|
|
respond(r, nil);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
respond(r, Ebad);
|
|
|
|
}
|
|
|
|
|
2021-06-28 21:37:59 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-16 05:46:47 +00:00
|
|
|
void fsopen(Req* r) {
|
|
|
|
Ramfile* rf;
|
2021-06-28 21:37:59 +00:00
|
|
|
printf("ooo");
|
2021-06-16 05:46:47 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-24 07:17:34 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2021-06-23 06:48:23 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2021-06-28 21:37:59 +00:00
|
|
|
void xrxswstat(Req* r) {
|
|
|
|
r->fid->omode = OWRITE;
|
|
|
|
respond(r, nil);
|
|
|
|
}
|
|
|
|
|
2021-06-13 17:22:58 +00:00
|
|
|
Srv fs = {
|
2021-06-16 05:46:47 +00:00
|
|
|
.open = fsopen,
|
2021-06-13 17:22:58 +00:00
|
|
|
.read = fsread,
|
2021-06-28 21:37:59 +00:00
|
|
|
.write = xrxswrite,
|
|
|
|
.create = xrxscreate,
|
|
|
|
.wstat = xrxswstat
|
2021-06-13 17:22:58 +00:00
|
|
|
};
|
|
|
|
|
2021-06-23 06:48:23 +00:00
|
|
|
int threadmaybackground(void) { return 1; }
|
2021-06-16 05:46:47 +00:00
|
|
|
|
2021-06-14 20:23:06 +00:00
|
|
|
void threadmain(int argc, char* argv[]) {
|
2021-06-13 17:22:58 +00:00
|
|
|
Tree* tree;
|
2021-06-14 20:23:06 +00:00
|
|
|
char* mtpt = nil;
|
|
|
|
char* usocket = nil;
|
|
|
|
int i;
|
2021-06-24 07:17:34 +00:00
|
|
|
String** cart;
|
|
|
|
char cartsloc[256] = "./carts/";
|
2021-06-28 21:37:59 +00:00
|
|
|
char ctlbuf[128] = "some data";
|
|
|
|
Ramfile ctlfile = {ctlbuf, 128};
|
2021-06-14 20:23:06 +00:00
|
|
|
|
|
|
|
/* 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) */
|
2021-06-13 17:22:58 +00:00
|
|
|
|
2021-06-14 20:23:06 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-23 06:48:23 +00:00
|
|
|
fs.tree = alloctree(nil, nil, DMDIR | 0777, fsdestroyfile);
|
|
|
|
tree = fs.tree;
|
2021-06-24 07:17:34 +00:00
|
|
|
createfile(tree->root, "carts", nil, DMDIR | 0555, nil);
|
2021-06-28 21:37:59 +00:00
|
|
|
createfile(tree->root, "ctl", nil, 0600, &ctlfile);
|
|
|
|
|
2021-06-24 07:17:34 +00:00
|
|
|
String** carts = listdir("carts/");
|
|
|
|
cart = carts;
|
|
|
|
while (*cart) {
|
|
|
|
createfile(walkfile(tree->root, "carts"), (*cart)->base, nil, 0444, nil);
|
|
|
|
cart++;
|
|
|
|
}
|
2021-06-23 06:48:23 +00:00
|
|
|
fs.foreground = 1;
|
2021-06-13 17:22:58 +00:00
|
|
|
|
2021-06-28 21:37:59 +00:00
|
|
|
while (serving) {
|
|
|
|
if (argc >= 3) {
|
|
|
|
if (mtpt != nil && access(mtpt, AEXIST) < 0 && access(mtpt, AEXIST) < 0)
|
|
|
|
sysfatal("mountpoint %s does not exist", mtpt);
|
2021-06-13 17:22:58 +00:00
|
|
|
|
2021-06-28 21:37:59 +00:00
|
|
|
threadpostmountsrv(&fs, usocket, mtpt, MREPL | MCREATE);
|
|
|
|
threadexits(0);
|
|
|
|
} else {
|
|
|
|
srv(&fs);
|
|
|
|
}
|
2021-06-14 20:23:06 +00:00
|
|
|
}
|
|
|
|
}
|