code: mafs

ref: 390e726c64ee2aca967617ac7f7fd2a44f27646b
dir: /names.c/

View raw version
#include	"all.h"

s8
searchnames(Dentry *d, char *searchname, u64 *relip)
{
	u16 searchnamelen, slen;
	s8 *namebuf;
	u64 n, reli;
	Name nm;

	/* is this valid? */
	if(d == nil || searchname == nil || relip == nil ||
		d->dblocks[In] == 0 || d->dblocks[Inl] == 0 ||
		d->dblocks[Inle] == 0){
		showdentry(2, (u8*)d);
		panic("searchnames: should not be happening. searchname %s *relip %llud\n",
				searchname, *relip);
	}

	searchnamelen = strlen(searchname);
	if(searchnamelen == 0)
		error(errstring[Ebadname]);

	reli = *relip = 0;
	slen = min(searchnamelen,Nfirst);
	if(searchnamelen > Nfirst){
		namebuf = emalloc9p(searchnamelen);
		if(waserror()){
			free(namebuf);
			nexterror();
		}
	}else
		namebuf = nil;
	while(readfile(d->dblocks[In], d->qpath+1+In,
					(s8*)&nm, sizeof(Name), reli*sizeof(Name)) == sizeof(Name)){
		if(searchnamelen == nm.namelen &&
			strncmp(nm.name, searchname, slen) == 0){
			if(searchnamelen <= Nfirst){
				*relip = reli;
				return 1;
			}else{
				n = readfile(d->dblocks[Inl], d->qpath+1+Inl,
								namebuf, searchnamelen, nm.noffset);
				if(n != searchnamelen)
					error(errstring[Einvread]);
				if(n == searchnamelen &&
					strncmp(searchname, namebuf, searchnamelen) == 0){
					*relip = reli;
					poperror();
					free(namebuf);
					return 1;
				}
			}
		}
		if(*relip == 0 && nm.namelen == 0)
			*relip = reli; /* a zeroed out reli, reuse if none found */
		reli++;
	}

	if(namebuf){
		poperror();
		free(namebuf);
	}

	/* nothing found */
	if(*relip == 0)
		*relip = reli;	/* use a new reli at the end */
	return 0;
}

void
newnames(Dentry *pd, u16 uid, u64 pdblkno, Iobuf **iobufs)
{
	Iobuf *iobuf;
	Dentry *d;
	u8 i;

	for(i = 0; i < 3; i++){
		iobuf = iobufs[i];
		pd->dblocks[i] = iobuf->blkno;
		d = iobuf->d;
		if(i == In)
			d->flags = Fn;
		else if(i == Inle)
			d->flags = Fe;
		d->flags |= Fsys;
		d->pdblkno = pdblkno;
		d->pqpath = pd->qpath;
		d->preli = i;
		d->uid = pd->uid;
		d->gid = pd->gid;
		d->muid = pd->muid;
		d->mode = pd->mode & ~DMDIR;
		d->mtime = nsec();
		d->version = 1;
		putbuf(iobuf, 1);
	}
	addname(pd, uid, 0, ".n");
	addname(pd, uid, 1, ".nl");
	addname(pd, uid, 2, ".nle");
}

/* returns namelen */
u16
readname(Dentry *pd, u64 preli, s8 **namep, u16 *namelen)
{
	u16 n;
	Name nm;

	n = readfile(pd->dblocks[In], pd->qpath+1+In, (s8*)&nm, sizeof(Name), preli*sizeof(Name));
	if(n != sizeof(Name))
		error(errstring[Einvread]);

	*namelen = nm.namelen;
	*namep = emalloc9p(nm.namelen+1);
	if(nm.namelen <= Nfirst){
		strncpy(*namep, nm.name, nm.namelen);
		return nm.namelen;
	}
	return readfile(pd->dblocks[Inl], pd->qpath+1+Inl, *namep, nm.namelen, nm.noffset);
}

void
rmname(Dentry *pd, s16 uid, u64 preli)
{
	u64 n;
	Name nm;
	Extents *nes;
	s8 esname[32];

	n = readfile(pd->dblocks[In], pd->qpath+1+In, (s8*)&nm, sizeof(Name), preli*sizeof(Name));
	if(n != sizeof(Name))
		error(errstring[Einvread]);

	if(nm.namelen > Nfirst){
		nes = emalloc9p(sizeof(Extents));
		if(waserror()){
			freeextents(nes);
			nexterror();
		}
		snprint(esname, 32, ".nle block %llud", pd->dblocks[Inle]);
		initextents(nes, esname, 0, 0, 2, nil, dprintfd, panic, malloc9p);
		loadextentsfile(pd->dblocks[Inle], pd->qpath+1+Inle, nes);
		ufree(nes, nm.noffset, nm.namelen);
		saveextentstofile(pd->dblocks[Inle], pd->qpath+1+Inle, uid, nes);
		poperror();
		freeextents(nes);
	}
	memset(&nm, 0, sizeof(Name));
	n = writefile(pd->dblocks[In], pd->qpath+1+In, uid, (s8*)&nm, sizeof(Name), preli*sizeof(Name));
	if(n != sizeof(Name))
		error(errstring[Einvwrite]);
}

u16
addnamelen(Dentry *pd, u16 uid, u64 preli, s8 *name, u16 namelen)
{
	Extents *nes;
	s8 esname[32];
	u64 start, size;
	Name nm;

//	dprint("addnamelen name %s len %d to In %llud Inl %llud preli %llud\n",
//			name, namelen, pd->dblocks[In], pd->dblocks[Inl], preli);
	nm.namelen = namelen;
	strncpy(nm.name, name, Nfirst);
	if(nm.namelen <= Nfirst){
		nm.noffset = 0;
		if(writefile(pd->dblocks[In], pd->qpath+1+In, uid,
						(s8*)&nm, sizeof(Name), preli*sizeof(Name)) == sizeof(Name))
			return nm.namelen;
		return 0;
	}

	nes = emalloc9p(sizeof(Extents));
	if(waserror()){
		freeextents(nes);
		nexterror();
	}
	snprint(esname, 32, ".nle block %llud", pd->dblocks[Inle]);
	initextents(nes, esname, 0, 0, 2, nil, dprintfd, panic, malloc9p);
	loadextentsfile(pd->dblocks[Inle], pd->qpath+1+Inle, nes);

	/* reusing */
	if(ualloc(nes, namelen, &start)){
		if(writefile(pd->dblocks[Inl], pd->qpath+1+Inl, uid, name, nm.namelen, start) != namelen)
			error(errstring[Einvwrite]);
		nm.noffset = start;
		saveextentstofile(pd->dblocks[Inle], pd->qpath+1+Inle, uid, nes);
	}else{
		nm.noffset = size = readfilesize(pd->dblocks[Inl], pd->qpath+1+Inl);
		if(writefile(pd->dblocks[Inl], pd->qpath+1+Inl, uid, name, nm.namelen, size) != nm.namelen)
			error(errstring[Einvwrite]);
	}
	poperror();
	freeextents(nes);
	if(writefile(pd->dblocks[In], pd->qpath+1+In, uid,
					(s8*)&nm, sizeof(Name), preli*sizeof(Name)) != sizeof(Name))
		error(errstring[Einvwrite]);

	return nm.namelen;
}

u16
addname(Dentry *pd, u16 uid, u64 preli, s8 *name)
{
	return addnamelen(pd, uid, preli, name, strlen(name));
}

u16
updatename(Dentry *pd, u16 uid, u64 preli, s8 *name)
{
	u16 newlen, n;
	Name nm;

//	dprint("updatename name %s to In %llud Inl %llud preli %llud\n",
//		name, pd->dblocks[In], pd->dblocks[Inl], preli);
	/* if the namelen matches with the existing, change in-place */
	newlen = strlen(name);
	n = readfile(pd->dblocks[In], pd->qpath+1+In, (s8*)&nm, sizeof(Name), preli*sizeof(Name));
	if(n != sizeof(Name))
		error(errstring[Einvread]);
	if(nm.namelen > Nfirst)
		rmname(pd, uid, preli);

	return addnamelen(pd, uid, preli, name, newlen);
}