1 #include "logfsos.h"
2 #include "logfs.h"
3 #include "local.h"
4
5 char *
logfsservercreate(LogfsServer * server,u32int fid,char * name,u32int perm,uchar mode,Qid * qid)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