xref: /inferno-os/liblogfs/create.c (revision 28942ead413418b56c5be78e8c4c400881fba72e)
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