xref: /inferno-os/liblogfs/open.c (revision 28942ead413418b56c5be78e8c4c400881fba72e)
1*28942eadSforsyth #include "logfsos.h"
237da2899SCharles.Forsyth #include "logfs.h"
337da2899SCharles.Forsyth #include "local.h"
437da2899SCharles.Forsyth 
537da2899SCharles.Forsyth char *
logfsserveropen(LogfsServer * server,u32int fid,uchar mode,Qid * qid)637da2899SCharles.Forsyth logfsserveropen(LogfsServer *server, u32int fid, uchar mode, Qid *qid)
737da2899SCharles.Forsyth {
837da2899SCharles.Forsyth 	Fid *f;
937da2899SCharles.Forsyth 	Entry *e;
1037da2899SCharles.Forsyth 	ulong modemask;
1137da2899SCharles.Forsyth 
1237da2899SCharles.Forsyth 	if(server->trace > 1)
1337da2899SCharles.Forsyth 		print("logfsserveropen(%ud, %d)\n",  fid, mode);
1437da2899SCharles.Forsyth 	f = logfsfidmapfindentry(server->fidmap, fid);
1537da2899SCharles.Forsyth 	if(f == nil)
1637da2899SCharles.Forsyth 		return logfsebadfid;
1737da2899SCharles.Forsyth 	if(f->openmode >= 0)
1837da2899SCharles.Forsyth 		return logfsefidopen;
1937da2899SCharles.Forsyth 	e = f->entry;
2037da2899SCharles.Forsyth 	SET(modemask);
2137da2899SCharles.Forsyth 	switch(mode & 3) {
2237da2899SCharles.Forsyth 	case OEXEC:
2337da2899SCharles.Forsyth 		modemask = DMEXEC;
2437da2899SCharles.Forsyth 		break;
2537da2899SCharles.Forsyth 	case OREAD:
2637da2899SCharles.Forsyth 		modemask = DMREAD;
2737da2899SCharles.Forsyth 		break;
2837da2899SCharles.Forsyth 	case OWRITE:
2937da2899SCharles.Forsyth 		modemask = DMWRITE;
3037da2899SCharles.Forsyth 		break;
3137da2899SCharles.Forsyth 	case ORDWR:
3237da2899SCharles.Forsyth 		modemask = DMWRITE | DMREAD;
3337da2899SCharles.Forsyth 		break;
3437da2899SCharles.Forsyth 	}
3537da2899SCharles.Forsyth 	if(e->qid.type & QTDIR) {
3637da2899SCharles.Forsyth 		if((modemask & DMWRITE) != 0 || (mode & (ORCLOSE | OTRUNC)) != 0)
3737da2899SCharles.Forsyth 			return Eperm;
3837da2899SCharles.Forsyth 	}
3937da2899SCharles.Forsyth 	else {
4037da2899SCharles.Forsyth 		if(mode & OTRUNC)
4137da2899SCharles.Forsyth 			modemask |= DMWRITE;
4237da2899SCharles.Forsyth 		if((mode & ORCLOSE) != 0 && !logfsuserpermcheck(server, e->parent, f, DMWRITE))
4337da2899SCharles.Forsyth 			return Eperm;
4437da2899SCharles.Forsyth 	}
4537da2899SCharles.Forsyth 	if(!logfsuserpermcheck(server, e, f, modemask))
4637da2899SCharles.Forsyth 		return Eperm;
4737da2899SCharles.Forsyth 	if((e->qid.type & QTDIR) == 0 && (mode & OTRUNC) != 0 && (e->perm & DMAPPEND) == 0 && e->u.file.length != 0) {
4837da2899SCharles.Forsyth 		LogMessage s;
4937da2899SCharles.Forsyth 		char *errmsg;
5037da2899SCharles.Forsyth 		s.type = LogfsLogTtrunc;
5137da2899SCharles.Forsyth 		s.path = e->qid.path;
5237da2899SCharles.Forsyth 		s.u.trunc.mtime = logfsnow();
5337da2899SCharles.Forsyth 		s.u.trunc.cvers = e->u.file.cvers + 1;
5437da2899SCharles.Forsyth 		s.u.trunc.muid = logfsisfindidfromname(server->is, f->uname);
5537da2899SCharles.Forsyth 		errmsg = logfslog(server, 1, &s);
5637da2899SCharles.Forsyth 		if(errmsg)
5737da2899SCharles.Forsyth 			return errmsg;
5837da2899SCharles.Forsyth 		e->muid = s.u.trunc.muid;
5937da2899SCharles.Forsyth 		e->mtime = s.u.trunc.mtime;
6037da2899SCharles.Forsyth 		e->qid.vers++;
6137da2899SCharles.Forsyth 		e->u.file.cvers = s.u.trunc.cvers;
6237da2899SCharles.Forsyth 		/*
6337da2899SCharles.Forsyth 		 * zap all data and extents
6437da2899SCharles.Forsyth 		 */
6537da2899SCharles.Forsyth 		logfsextentlistwalk(e->u.file.extent, logfsunconditionallymarkfreeanddirty, server);
6637da2899SCharles.Forsyth 		logfsextentlistreset(e->u.file.extent);
6737da2899SCharles.Forsyth 		e->u.file.length = 0;
6837da2899SCharles.Forsyth 	}
6937da2899SCharles.Forsyth 	f->openmode = mode;
7037da2899SCharles.Forsyth 	*qid = e->qid;
7137da2899SCharles.Forsyth 	return nil;
7237da2899SCharles.Forsyth }
73