ref: b8cc5e02b3662d1e98953e35034f33fff9715e7f
dir: /main.c/
#include <u.h>
#include <libc.h>
#include <fcall.h>
#include <thread.h>
#include <9p.h>
enum {
Qroot,
Qnickname,
Qchannels,
};
typedef struct Neinfile Neinfile;
typedef struct NeinAux NeinAux;
struct Neinfile {
char *name;
Qid qid;
ulong mode;
};
struct NeinAux {
char *nickname;
int currentChan;
};
void fsattach(Req*);
void fsstat(Req*);
void fsread(Req*);
void fswrite(Req*);
char *fsclone(Fid*, Fid*);
char *fswalk1(Fid*, char*, Qid*);
int rootgen(int, Dir*, void*);
int channelsgen(int, Dir*, void*);
Neinfile *findfile(uvlong);
void fillstat(Dir*, Neinfile);
Srv fs = {
.attach = fsattach,
.walk1 = fswalk1,
.clone = fsclone,
.stat = fsstat,
.read = fsread,
.write = fswrite,
};
char *username;
Neinfile qroot[] = {
"nickname", {Qnickname, 0, QTFILE}, 0666,
"channels", {Qchannels, 0, QTDIR}, 0555 | DMDIR,
};
Neinfile root = {"/", {Qroot, 0, QTDIR}, 555 | DMDIR};
int nicknamecount;
void
main()
{
chatty9p = 1;
char *mountpoint = "/mnt/neinchat";
username = getuser();
print("Starting neinchat server on %s\n", mountpoint);
postmountsrv(&fs, "neinchat", mountpoint, MREPL|MCREATE);
exits(nil);
}
void
fsattach(Req *r)
{
NeinAux *aux;
r->fid->qid = root.qid;
r->ofcall.qid = r->fid->qid;
aux = emalloc9p(sizeof(NeinAux));
aux->nickname = smprint("RandomUser%d", nicknamecount++);
aux->currentChan = -1;
r->fid->aux = aux;
respond(r, nil);
}
void
fsstat(Req *r)
{
Neinfile *f = findfile(r->fid->qid.path);
if(f == nil){
respond(r, "not found");
return;
}
fillstat(&r->d, *f);
respond(r, nil);
}
void
fsread(Req *r)
{
char *str;
NeinAux *aux;
switch(r->fid->qid.path){
case Qroot:
dirread9p(r, rootgen, nil);
respond(r, nil);
break;
case Qchannels:
dirread9p(r, channelsgen, nil);
respond(r, nil);
break;
case Qnickname:
aux = r->fid->aux;
str = smprint("%s\n", aux->nickname);
readstr(r, str);
free(str);
respond(r, nil);
break;
default:
respond(r, "wut no");
}
}
void
fswrite(Req *r)
{
NeinAux *aux = r->fid->aux;
if(r->fid->qid.path == Qnickname){
if(r->ifcall.count > 64){
respond(r, "nickname too long (max is 64 chars)");
return;
}
if(r->ifcall.offset != 0){
respond(r, "Can't write at offset");
return;
}
char *buf = emalloc9p(r->ifcall.count + 1);
memcpy(buf, r->ifcall.data, r->ifcall.count);
buf[r->ifcall.count] = 0;
free(aux->nickname);
aux->nickname = buf;
r->ofcall.count = r->ifcall.count;
respond(r, nil);
return;
}
respond(r, "write prohibited");
}
char *
fsclone(Fid *old, Fid *new)
{
new->aux = old->aux;
return nil;
}
char *
fswalk1(Fid *fid, char *name, Qid *qid)
{
int i;
if(strcmp("..", name) == 0){
*qid = root.qid;
fid->qid = *qid;
return nil;
}
switch(fid->qid.path){
case Qroot:
for(i = 0; i < nelem(qroot); i++){
if(strcmp(qroot[i].name, name) == 0){
*qid = qroot[i].qid;
fid->qid = *qid;
return nil;
}
}
if(strcmp("..", name) == 0){
*qid = root.qid;
fid->qid = *qid;
return nil;
}
break;
}
return "not found";
}
int
rootgen(int n, Dir *d, void *)
{
if(n >= nelem(qroot))
return -1;
Neinfile f = qroot[n];
fillstat(d, f);
return 0;
}
int
channelsgen(int n, Dir *d, void *)
{
USED(n);
USED(d);
return -1;
}
Neinfile *
findfile(uvlong path)
{
int i;
if(path == Qroot)
return &root;
for(i = 0; i < nelem(qroot); i++){
if(qroot[i].qid.path == path)
return &qroot[i];
}
return nil;
}
void
fillstat(Dir *d, Neinfile f)
{
d->qid = f.qid;
d->mode = f.mode;
d->length = 0;
d->name = estrdup9p(f.name);
d->uid = estrdup9p(username);
d->gid = estrdup9p(username);
d->muid = estrdup9p(username);
d->atime = time(0);
d->mtime = time(0);
}