#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"; enum { CTL = 1, SLOT, CART, REALM, UNIVERSE }; typedef struct Aux Aux; struct Aux { int type; char* data; int count; }; void fsread(Req* r) { Aux* a; vlong offset; long count; a = r->fid->file->aux; offset = r->ifcall.offset; count = r->ifcall.count; /*print("read %ld %lld\n", *count, offset); */ if (offset >= a->count) { r->ofcall.count = 0; respond(r, nil); return; } if (offset + count >= a->count) count = a->count - offset; memmove(r->ofcall.data, a->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; Aux* a; vlong offset; long count; a = r->fid->file->aux; offset = r->ifcall.offset; count = r->ifcall.count; if (offset + count >= a->count) { v = realloc(a->data, offset + count); if (v == nil) { respond(r, Enomem); return; } a->data = v; a->count = offset + count; r->fid->file->dir.length = a->count; } memmove(a->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; int i; for (i = 0; i < r->ifcall.count; i++) { ccat(cmd, *c++); } unsigned long long const cmd_hashv = hash(cmd); switch (cmd_hashv) { case SHUTDOWN_HASHV: printf("what"); break; default: break; } r->ofcall.count = r->ifcall.count; r->fid->file->dir.length = r->ifcall.count; } void xrxswrite(Req* r) { Aux* a = r->fid->file->aux; switch (a->type) { case CTL: handlectl(r); break; default: break; } respond(r, nil); } void fsopen(Req* r) { respond(r, nil); } void wstat(Req* r) { respond(r, nil); } void fsdestroyfile(File* f) { Aux* a = f->aux; if (a && a->data) { free(a->data); free(a); } else if (a) { free(a); } } 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; } Srv fs = { .open = fsopen, .read = fsread, .write = xrxswrite, .create = fsopen, .wstat = wstat}; int threadmaybackground(void) { return 1; } void threadmain(int argc, char* argv[]) { Tree* tree; char* mtpt = nil; char* usocket = nil; int i; String** cart; Aux* ctlfile = malloc(sizeof(Aux)); ctlfile->type = CTL; ctlfile->data = malloc(256 * sizeof(char)); ctlfile->count = 0; /* 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.foreground = 1; fs.tree = alloctree(nil, nil, DMDIR | 0777, fsdestroyfile); tree = fs.tree; closefile(createfile(tree->root, "carts", nil, DMDIR | 0555, nil)); closefile(createfile(tree->root, "ctl", nil, DMAPPEND | 0300, ctlfile)); String** carts = listdir("carts/"); cart = carts; while (*cart) { closefile( createfile(walkfile(tree->root, "carts"), (*cart)->base, nil, 0444, nil)); cart++; } 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); } } }