1 #include "lib9.h" 2 #include "logfs.h" 3 #include "local.h" 4 5 char * 6 logfsservercreate(LogfsServer *server, u32int fid, char *name, u32int perm, uchar mode, Qid *qid) 7 { 8 Fid *f; 9 char *uid; 10 ulong newpath; 11 char *errmsg; 12 Entry *e, *xe, *pe; 13 Path *pp; 14 LogMessage s; 15 16 if(server->trace > 1) 17 print("logfsservercreate(%ud, %s, 0%uo, %.2ux)\n", fid, name, perm, mode); 18 f = logfsfidmapfindentry(server->fidmap, fid); 19 if(f == nil) 20 return logfsebadfid; 21 if(f->openmode >= 0) 22 return logfsefidopen; 23 pe = f->entry; 24 if((pe->qid.type & QTDIR) == 0) 25 return Enotdir; 26 if((perm & DMDIR) != 0 && ((mode & OTRUNC) != 0 || (mode & 3) != OREAD)) 27 return Eperm; 28 if(!logfsuserpermcheck(server, pe, f, DMWRITE)) 29 return Eperm; 30 /* 31 * illegal names 32 */ 33 if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) 34 return Eperm; 35 for(xe = pe->u.dir.list; xe; xe = xe->next) 36 if(strcmp(xe->name, name) == 0) 37 return Eexist; 38 newpath = ++server->path; 39 while(logfspathmapfindentry(server->pathmap, newpath)) 40 newpath++; /* shouldn't happen */ 41 uid = logfsisfindidfromname(server->is, f->uname); 42 errmsg = logfsentrynew(server, 1, newpath, 43 pe, name, uid, f->entry->gid, logfsnow(), uid, perm, 0, 0, &e); 44 if(errmsg) 45 return errmsg; 46 errmsg = logfspathmapnewentry(server->pathmap, newpath, e, &pp); 47 /* pp is guaranteed to be non-null */ 48 if(errmsg) { 49 logfsfreemem(e); 50 return errmsg; 51 } 52 s.type = LogfsLogTcreate; 53 s.path = e->parent->qid.path; 54 s.u.create.perm = e->perm; 55 s.u.create.newpath = e->qid.path; 56 s.u.create.mtime = e->mtime; 57 /* TODO - check with forsyth whether cvers is needed in dirs */ 58 s.u.create.cvers = (e->qid.type & QTDIR) ? 0 : e->u.file.cvers; 59 s.u.create.name = e->name; 60 s.u.create.uid = e->uid; 61 s.u.create.gid = e->gid; 62 errmsg = logfslog(server, 1, &s); 63 if(errmsg) { 64 logfsfreemem(e); 65 logfspathmapdeleteentry(server->pathmap, newpath); 66 return errmsg; 67 } 68 server->path = newpath; 69 e->inuse++; 70 e->qid.vers++; 71 e->next = pe->u.dir.list; 72 pe->u.dir.list = e; 73 f->openmode = mode; 74 /* 75 * TODO why does forsyth increment inuse for dir? - we're moving the fid onto the new file 76 * so a decrement seems better 77 */ 78 logfsentryclunk(pe); 79 f->entry = e; 80 *qid = e->qid; 81 return nil; 82 } 83