ref: 0f18bf0aaf945b20b24f3ec8f3ae37f42c9e08b7
dir: /vcffs.c/
#include <u.h> #include <libc.h> #include <fcall.h> #include <thread.h> #include <9p.h> #include "libvcard/vcard.h" /* rough structure /john-doe/ /fn/ /data (line value) /group (line group) /param (param value) /tel/ /data (line value) /group (line group) /param (param value) /ctl - "write" (save file) /import - write new vcf file to import */ void usage(void) { fprint(2, "usage: %s [-s srv] [-m mtpt] file\n", argv0); exits("usage"); } static void* emalloc(long n) { void *p; p = mallocz(n, 1); if (!p) sysfatal("emalloc: %r"); return p; } static char* estrdup(char *s) { void *t; t = strdup(s); if (!t) sysfatal("estrdup: %r"); return t; } enum { Qroot, Qctl, Qimport, Qcard, Qline, Qdata, Qgroup, Qparams, Qparamdata, }; typedef struct Vfile Vfile; struct Vfile { int level; Vcard *card; Vline *line; Vparam *param; }; char *user = nil; char *mtpt = "/mnt/vcf"; char *service = nil; char *file = nil; Vcard *cards = nil; static Vfile* emkvfile(int level, Vcard *c, Vline *l, Vparam *p) { Vfile *f; f = mallocz(sizeof(Vfile), 1); if (!f) sysfatal("%r"); f->level = level; f->card = c; f->line = l; f->param = p; return f; } static void fsread(Req *r) { Vfile *f; f = r->fid->file->aux; switch (f->level) { case Qctl: respond(r, nil); return; case Qimport: respond(r, nil); return; case Qdata: readstr(r, f->line->value); respond(r, nil); return; case Qgroup: if (!f->line->group) { respond(r, "file not found"); return; } readstr(r, f->line->group); respond(r, nil); return; case Qparamdata: readstr(r, f->param->value); respond(r, nil); return; } respond(r, "not implemented"); } static void fswrite(Req *r) { Vfile *f; f = r->fid->file->aux; switch (f->level) { case Qctl: break; } respond(r, "not implemented"); } Srv fs = { .read = fsread, .write = fswrite, }; /* TODO: LOOKAT: /sys/src/cmd/webcookies.c:/createfile /sys/src/cmd/aux/gps/gpsfs.c:/createfile */ static char* safename(char *n) { char *s; s = estrdup(n); n = s; while (*n) { switch (*n) { case ' ': *n = '_'; break; case '\t': *n = '_'; break; } n++; } return s; } static char* getcardname(Vcard *c) { Vline *l; Vline *fn = nil, *n = nil; for (l = c->content; l; l = l->next) { if (cistrcmp(l->name, "fn") == 0) fn = l; else if (cistrcmp(l->name, "n") == 0) n = l; if (fn && n) break; } if (fn) return safename(fn->value); if (n) return safename(n->value); return nil; } static void initcardfiles(Vcard *chain) { File *fc, *fl, *fp, *f; Vcard *c; Vline *l; Vparam *p; Vfile *vf; char *s; // TODO: fill with Vfile structure, which points to card data for (c = chain; c; c = c->next) { s = getcardname(c); if (!s) continue; vf = emkvfile(Qcard, c, nil, nil); fc = createfile(fs.tree->root, s, user, DMDIR|0555, vf); free(s); if (!fc) sysfatal("%r"); for (l = c->content; l; l = l->next) { vf = emkvfile(Qline, c, l, nil); fl = createfile(fc, l->name, user, DMDIR|0555, vf); vf = emkvfile(Qdata, c, l, nil); f = createfile(fl, "data", user, 0666, vf); // closefile(f); if (l->group) { vf = emkvfile(Qgroup, c, l, nil); f = createfile(fl, "group", user, 0666, vf); // closefile(f); } vf = emkvfile(Qparams, c, l, nil); f = createfile(fl, "params", user, DMDIR|0555, vf); // closefile(f); for (p = l->params; p; p = p->next) { vf = emkvfile(Qparamdata, c, l, p); fp = createfile(f, p->name, user, 0666, vf); // closefile(fp); } // closefile(fl); } // closefile(fc); } } void main(int argc, char **argv) { ARGBEGIN{ case 'D': chatty9p++; break; case 'm': mtpt = EARGF(usage()); break; case 's': service = EARGF(usage()); break; default: usage(); break; }ARGEND; rfork(RFNOTEG); if (argc != 1) usage(); file = argv[0]; cards = vcparsefile(file); if (!cards) sysfatal("%r"); user = getuser(); fs.tree = alloctree("vcf", "vcf", DMDIR|0555, nil); createfile(fs.tree->root, "ctl", user, 0666, emkvfile(Qctl, nil, nil, nil)); createfile(fs.tree->root, "import", user, 0666, emkvfile(Qimport, nil, nil, nil)); initcardfiles(cards); postmountsrv(&fs, service, mtpt, MREPL); exits(nil); }