1*28942eadSforsyth #include "logfsos.h"
237da2899SCharles.Forsyth #include "logfs.h"
337da2899SCharles.Forsyth #include "local.h"
437da2899SCharles.Forsyth
537da2899SCharles.Forsyth char *
logfsservercreate(LogfsServer * server,u32int fid,char * name,u32int perm,uchar mode,Qid * qid)637da2899SCharles.Forsyth logfsservercreate(LogfsServer *server, u32int fid, char *name, u32int perm, uchar mode, Qid *qid)
737da2899SCharles.Forsyth {
837da2899SCharles.Forsyth Fid *f;
937da2899SCharles.Forsyth char *uid;
1037da2899SCharles.Forsyth ulong newpath;
1137da2899SCharles.Forsyth char *errmsg;
1237da2899SCharles.Forsyth Entry *e, *xe, *pe;
1337da2899SCharles.Forsyth Path *pp;
1437da2899SCharles.Forsyth LogMessage s;
1537da2899SCharles.Forsyth
1637da2899SCharles.Forsyth if(server->trace > 1)
1737da2899SCharles.Forsyth print("logfsservercreate(%ud, %s, 0%uo, %.2ux)\n", fid, name, perm, mode);
1837da2899SCharles.Forsyth f = logfsfidmapfindentry(server->fidmap, fid);
1937da2899SCharles.Forsyth if(f == nil)
2037da2899SCharles.Forsyth return logfsebadfid;
2137da2899SCharles.Forsyth if(f->openmode >= 0)
2237da2899SCharles.Forsyth return logfsefidopen;
2337da2899SCharles.Forsyth pe = f->entry;
2437da2899SCharles.Forsyth if((pe->qid.type & QTDIR) == 0)
2537da2899SCharles.Forsyth return Enotdir;
2637da2899SCharles.Forsyth if((perm & DMDIR) != 0 && ((mode & OTRUNC) != 0 || (mode & 3) != OREAD))
2737da2899SCharles.Forsyth return Eperm;
2837da2899SCharles.Forsyth if(!logfsuserpermcheck(server, pe, f, DMWRITE))
2937da2899SCharles.Forsyth return Eperm;
3037da2899SCharles.Forsyth /*
3137da2899SCharles.Forsyth * illegal names
3237da2899SCharles.Forsyth */
3337da2899SCharles.Forsyth if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
3437da2899SCharles.Forsyth return Eperm;
3537da2899SCharles.Forsyth for(xe = pe->u.dir.list; xe; xe = xe->next)
3637da2899SCharles.Forsyth if(strcmp(xe->name, name) == 0)
3737da2899SCharles.Forsyth return Eexist;
3837da2899SCharles.Forsyth newpath = ++server->path;
3937da2899SCharles.Forsyth while(logfspathmapfindentry(server->pathmap, newpath))
4037da2899SCharles.Forsyth newpath++; /* shouldn't happen */
4137da2899SCharles.Forsyth uid = logfsisfindidfromname(server->is, f->uname);
4237da2899SCharles.Forsyth errmsg = logfsentrynew(server, 1, newpath,
4337da2899SCharles.Forsyth pe, name, uid, f->entry->gid, logfsnow(), uid, perm, 0, 0, &e);
4437da2899SCharles.Forsyth if(errmsg)
4537da2899SCharles.Forsyth return errmsg;
4637da2899SCharles.Forsyth errmsg = logfspathmapnewentry(server->pathmap, newpath, e, &pp);
4737da2899SCharles.Forsyth /* pp is guaranteed to be non-null */
4837da2899SCharles.Forsyth if(errmsg) {
4937da2899SCharles.Forsyth logfsfreemem(e);
5037da2899SCharles.Forsyth return errmsg;
5137da2899SCharles.Forsyth }
5237da2899SCharles.Forsyth s.type = LogfsLogTcreate;
5337da2899SCharles.Forsyth s.path = e->parent->qid.path;
5437da2899SCharles.Forsyth s.u.create.perm = e->perm;
5537da2899SCharles.Forsyth s.u.create.newpath = e->qid.path;
5637da2899SCharles.Forsyth s.u.create.mtime = e->mtime;
5737da2899SCharles.Forsyth /* TODO - check with forsyth whether cvers is needed in dirs */
5837da2899SCharles.Forsyth s.u.create.cvers = (e->qid.type & QTDIR) ? 0 : e->u.file.cvers;
5937da2899SCharles.Forsyth s.u.create.name = e->name;
6037da2899SCharles.Forsyth s.u.create.uid = e->uid;
6137da2899SCharles.Forsyth s.u.create.gid = e->gid;
6237da2899SCharles.Forsyth errmsg = logfslog(server, 1, &s);
6337da2899SCharles.Forsyth if(errmsg) {
6437da2899SCharles.Forsyth logfsfreemem(e);
6537da2899SCharles.Forsyth logfspathmapdeleteentry(server->pathmap, newpath);
6637da2899SCharles.Forsyth return errmsg;
6737da2899SCharles.Forsyth }
6837da2899SCharles.Forsyth server->path = newpath;
6937da2899SCharles.Forsyth e->inuse++;
7037da2899SCharles.Forsyth e->qid.vers++;
7137da2899SCharles.Forsyth e->next = pe->u.dir.list;
7237da2899SCharles.Forsyth pe->u.dir.list = e;
7337da2899SCharles.Forsyth f->openmode = mode;
7437da2899SCharles.Forsyth /*
7537da2899SCharles.Forsyth * TODO why does forsyth increment inuse for dir? - we're moving the fid onto the new file
7637da2899SCharles.Forsyth * so a decrement seems better
7737da2899SCharles.Forsyth */
7837da2899SCharles.Forsyth logfsentryclunk(pe);
7937da2899SCharles.Forsyth f->entry = e;
8037da2899SCharles.Forsyth *qid = e->qid;
8137da2899SCharles.Forsyth return nil;
8237da2899SCharles.Forsyth }
83