From 37da2899f40661e3e9631e497da8dc59b971cbd0 Mon Sep 17 00:00:00 2001 From: "Charles.Forsyth" Date: Fri, 22 Dec 2006 17:07:39 +0000 Subject: 20060303a --- liblogfs/create.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 liblogfs/create.c (limited to 'liblogfs/create.c') diff --git a/liblogfs/create.c b/liblogfs/create.c new file mode 100644 index 00000000..be78fdda --- /dev/null +++ b/liblogfs/create.c @@ -0,0 +1,82 @@ +#include "lib9.h" +#include "logfs.h" +#include "local.h" + +char * +logfsservercreate(LogfsServer *server, u32int fid, char *name, u32int perm, uchar mode, Qid *qid) +{ + Fid *f; + char *uid; + ulong newpath; + char *errmsg; + Entry *e, *xe, *pe; + Path *pp; + LogMessage s; + + if(server->trace > 1) + print("logfsservercreate(%ud, %s, 0%uo, %.2ux)\n", fid, name, perm, mode); + f = logfsfidmapfindentry(server->fidmap, fid); + if(f == nil) + return logfsebadfid; + if(f->openmode >= 0) + return logfsefidopen; + pe = f->entry; + if((pe->qid.type & QTDIR) == 0) + return Enotdir; + if((perm & DMDIR) != 0 && ((mode & OTRUNC) != 0 || (mode & 3) != OREAD)) + return Eperm; + if(!logfsuserpermcheck(server, pe, f, DMWRITE)) + return Eperm; + /* + * illegal names + */ + if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) + return Eperm; + for(xe = pe->u.dir.list; xe; xe = xe->next) + if(strcmp(xe->name, name) == 0) + return Eexist; + newpath = ++server->path; + while(logfspathmapfindentry(server->pathmap, newpath)) + newpath++; /* shouldn't happen */ + uid = logfsisfindidfromname(server->is, f->uname); + errmsg = logfsentrynew(server, 1, newpath, + pe, name, uid, f->entry->gid, logfsnow(), uid, perm, 0, 0, &e); + if(errmsg) + return errmsg; + errmsg = logfspathmapnewentry(server->pathmap, newpath, e, &pp); + /* pp is guaranteed to be non-null */ + if(errmsg) { + logfsfreemem(e); + return errmsg; + } + s.type = LogfsLogTcreate; + s.path = e->parent->qid.path; + s.u.create.perm = e->perm; + s.u.create.newpath = e->qid.path; + s.u.create.mtime = e->mtime; + /* TODO - check with forsyth whether cvers is needed in dirs */ + s.u.create.cvers = (e->qid.type & QTDIR) ? 0 : e->u.file.cvers; + s.u.create.name = e->name; + s.u.create.uid = e->uid; + s.u.create.gid = e->gid; + errmsg = logfslog(server, 1, &s); + if(errmsg) { + logfsfreemem(e); + logfspathmapdeleteentry(server->pathmap, newpath); + return errmsg; + } + server->path = newpath; + e->inuse++; + e->qid.vers++; + e->next = pe->u.dir.list; + pe->u.dir.list = e; + f->openmode = mode; + /* + * TODO why does forsyth increment inuse for dir? - we're moving the fid onto the new file + * so a decrement seems better + */ + logfsentryclunk(pe); + f->entry = e; + *qid = e->qid; + return nil; +} -- cgit v1.2.3