Example #1
0
long
qidpathgen(Device *dev)
{
	Iobuf *p;
	Superb *sb;
	long path;

	p = getbuf(*dev, superaddr((*dev)), Bread|Bmod);
	if(!p || checktag(p, Tsuper, QPSUPER))
		panic("newqid: super block");
	sb = (Superb*)p->iobuf;
	sb->qidgen++;
	path = sb->qidgen;
	putbuf(p);
	return path;
}
Example #2
0
/* zero bytes past new file length; return an error code */
int
trunczero(Truncstate *ts)
{
	int blkoff = ts->newsize % BUFSIZE;
	Iobuf *pd;

	pd = dnodebuf(ts->p, ts->d, ts->lastblk, Tfile, ts->uid);
	if (pd == nil || checktag(pd, Tfile, QPNONE)) {
		if (pd != nil)
			putbuf(pd);
		ts->err = Ephase;
		return Ephase;
	}
	memset(pd->iobuf+blkoff, 0, BUFSIZE - blkoff);
	putbuf(pd);
	return 0;
}
Example #3
0
Qid
newqid(Device dev)
{
	Iobuf *p;
	Superb *sb;
	Qid qid;

	p = getbuf(dev, superaddr(dev), Bread|Bmod);
	if(!p || checktag(p, Tsuper, QPSUPER))
		panic("newqid: super block");
	sb = (Superb*)p->iobuf;
	sb->qidgen++;
	qid.path = sb->qidgen;
	qid.vers = 0;
	qid.type = 0;
	putbuf(p);
	return qid;
}
Example #4
0
void
bfree(Device dev, long addr, int d)
{
	Iobuf *p;
	long a;
	int i;

	if(!addr)
		return;
	if(d > 0) {
		d--;
		p = getbuf(dev, addr, Bread);
		if(p) {
			for(i=INDPERBUF-1; i>=0; i--) {
				a = ((long*)p->iobuf)[i];
				bfree(dev, a, d);
			}
			putbuf(p);
		}
	}
	/*
	 * stop outstanding i/o
	 */
	p = getbuf(dev, addr, Bprobe);
	if(p) {
		p->flags &= ~(Bmod|Bimm);
		putbuf(p);
	}
	/*
	 * dont put written worm
	 * blocks into free list
	 */
	if(nofree(dev, addr))
		return;
	p = getbuf(dev, superaddr(dev), Bread|Bmod);
	if(!p || checktag(p, Tsuper, QPSUPER))
		panic("bfree: super block");
	addfree(dev, addr, (Superb*)p->iobuf);
	putbuf(p);
}
Example #5
0
void
f_stat(Chan *cp, Oldfcall *in, Oldfcall *ou)
{
	Iobuf *p;
	Dentry *d;
	File *f;

	if(CHAT(cp)) {
		print("c_stat %d\n", cp->chan);
		print("	fid = %d\n", in->fid);
	}

	p = 0;
	memset(ou->stat, 0, sizeof(ou->stat));
	f = filep(cp, in->fid, 0);
	if(!f) {
		ou->err = Efid;
		goto out;
	}
	p = getbuf(f->fs->dev, f->addr, Bread);
	d = getdir(p, f->slot);
	if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
		ou->err = Ealloc;
		goto out;
	}
	if(ou->err = mkqidcmp(&f->qid, d))
		goto out;
	if(d->qid.path == QPROOT)	/* stat of root gives time */
		d->atime = time(0);
	if(convD2M9p1(d, ou->stat) != DIRREC)
		print("stat convD2M\n");

out:
	if(p)
		putbuf(p);
	if(f)
		qunlock(f);
	ou->fid = in->fid;
}
Example #6
0
void
f_attach(Chan *cp, Oldfcall *in, Oldfcall *ou)
{
	Iobuf *p;
	Dentry *d;
	File *f;
	int u;
	Filsys *fs;
	int32_t raddr;

	if(CHAT(cp)) {
		print("c_attach %d\n", cp->chan);
		print("	fid = %d\n", in->fid);
		print("	uid = %s\n", in->uname);
		print("	arg = %s\n", in->aname);
	}

	ou->qid = QID9P1(0,0);
	ou->fid = in->fid;
	if(!in->aname[0])	/* default */
		strncpy(in->aname, filesys[0].name, sizeof(in->aname));
	p = 0;
	f = filep(cp, in->fid, 1);
	if(!f) {
		ou->err = Efid;
		goto out;
	}
	u = -1;
	if(cp != cons.chan){
		if(authorize(cp, in, ou) == 0 || strcmp(in->uname, "adm") == 0){
			ou->err = Eauth;
			goto out;
		}
		u = strtouid(in->uname);
		if(u < 0){
			ou->err = Ebadu;
			goto out;
		}
	}

	fs = fsstr(in->aname);
	if(fs == 0) {
		ou->err = Ebadspc;
		goto out;
	}
	raddr = getraddr(fs->dev);
	p = getbuf(fs->dev, raddr, Bread);
	d = getdir(p, 0);
	if(!d || checktag(p, Tdir, QPROOT) || !(d->mode & DALLOC)) {
		ou->err = Ealloc;
		goto out;
	}
	f->uid = u;
	if(iaccess(f, d, DREAD)) {
		ou->err = Eaccess;
		goto out;
	}
	accessdir(p, d, FREAD);
	mkqid(&f->qid, d, 1);
	f->fs = fs;
	f->addr = raddr;
	f->slot = 0;
	f->open = 0;
	freewp(f->wpath);
	f->wpath = 0;

	mkqid9p1(&ou->qid, &f->qid);

out:
	if(p)
		putbuf(p);
	if(f) {
		qunlock(f);
		if(ou->err)
			freefp(f);
	}
}
Example #7
0
void
sysinit(void)
{
	int error;
	char *cp, *ep;
	Device *d;
	Filsys *fs;
	Fspar *fsp;
	Iobuf *p;

	cons.chan = fs_chaninit(Devcon, 1, 0);

start:
	/*
	 * part 1 -- read the config file
	 */
	devnone = iconfig("n");

	cp = nvrgetconfig();
	print("config %s\n", cp);

	confdev = d = iconfig(cp);
	devinit(d);
	if(f.newconf) {
		p = getbuf(d, 0, Bmod);
		memset(p->iobuf, 0, RBUFSIZE);
		settag(p, Tconfig, 0);
	} else
		p = getbuf(d, 0, Brd|Bmod);
	if(!p || checktag(p, Tconfig, 0))
		panic("config io");

	mergeconf(p);

	if (resetparams) {
		for (fsp = fspar; fsp->name != nil; fsp++)
			fsp->declared = 0;
		resetparams = 0;
	}

	for (fsp = fspar; fsp->name != nil; fsp++) {
		/* supply defaults from this cwfs instance */
		if (fsp->declared == 0) {
			fsp->declared = fsp->actual;
			f.modconf = 1;
		}
		/* warn if declared value is not our compiled-in value */
		if (fsp->declared != fsp->actual)
			print("warning: config %s %ld != compiled-in %ld\n",
				fsp->name, fsp->declared, fsp->actual);
	}

	if(f.modconf) {
		memset(p->iobuf, 0, BUFSIZE);
		p->flags |= Bmod|Bimm;
		cp = p->iobuf;
		ep = p->iobuf + RBUFSIZE - 1;
		if(service[0])
			cp = seprint(cp, ep, "service %s\n", service);
		for(fs=filsys; fs->name; fs++)
			if(fs->conf && fs->conf[0] != '\0')
				cp = seprint(cp, ep, "filsys %s %s\n", fs->name,
					fs->conf);

		for (fsp = fspar; fsp->name != nil; fsp++)
			cp = seprint(cp, ep, "%s %ld\n",
				fsp->name, fsp->declared);

		putbuf(p);
		f.modconf = f.newconf = 0;
		print("config block written\n");
		goto start;
	}
	putbuf(p);

	print("service    %s\n", service);

loop:
	/*
	 * part 2 -- squeeze out the deleted filesystems
	 */
	for(fs=filsys; fs->name; fs++)
		if(fs->conf == nil || fs->conf[0] == '\0') {
			for(; fs->name; fs++)
				*fs = *(fs+1);
			goto loop;
		}
	if(filsys[0].name == nil)
		panic("no filsys");

	/*
	 * part 3 -- compile the device expression
	 */
	error = 0;
	for(fs=filsys; fs->name; fs++) {
		print("filsys %s %s\n", fs->name, fs->conf);
		fs->dev = iconfig(fs->conf);
		if(f.error) {
			error = 1;
			continue;
		}
	}
	if(error)
		panic("fs config");

	/*
	 * part 4 -- initialize the devices
	 */
	for(fs=filsys; fs->name; fs++) {
		delay(3000);
		print("sysinit: %s\n", fs->name);
		if(fs->flags & FREAM)
			devream(fs->dev, 1);
		if(fs->flags & FRECOVER)
			devrecover(fs->dev);
		devinit(fs->dev);
	}

	/*
	 * part 5 -- optionally copy devices or worms
	 */
	if (copyworm) {
		dowormcopy();		/* can return if user quits early */
		panic("copyworm bailed out!");
	}
	if (copydev)
		if (dodevcopy() < 0)
			panic("copydev failed!");
		else
			panic("copydev done.");
}
Example #8
0
File: bind.c Project: ccxvii/mio
static int ffi_anim_len(lua_State *L)
{
	struct anim *anim = checktag(L, 1, TAG_ANIM);
	lua_pushnumber(L, anim->frames - 1);
	return 1;
}
Example #9
0
int 
parseConfig(int argc, char *argv[], int *port_divert,
		unsigned int *roEnable, struct sockaddr_in *bAddr, struct in_addr *coa, 
		MNLLIST *mn_ip_list, LLIST *all_if_list, LLIST *inner_if_list)
{
	FILE *fp;
	int  confFile = 0;
	long fpos = 0;
	int  tagmask  = 0;
	char tag[30];
	char token[30];


	/* if((!strcmp(argv[1], "-f")) && (argc == 5)){
		confFile = 1;
	}else if(!strcmp(argv[1], "-ha")){
		*isha = 1;
		confFile = 0;
	}else if(!strcmp(argv[1], "-fa")){
		*isfa = 1;
		confFile = 0;
	}else{
		printCmdUsage();
		exit(1);
	} */

	if(argc == 2){
		confFile = 1;
	}else{
		printCmdUsage();
		exit(1);
	}
	
	if(confFile){
		if((fp = fopen(argv[1], "r")) == NULL){
			fprintf(stderr, "[X] Open agent config file fail.\n");
			exit(1);
		}

		tagmask = gentagmask();
		/* enable RO or not coresponding to the cmdline parameter. */
		/* if(!strcmp(argv[3], "RO")){
			tagmask ^= T_RO;
			*roEnable = 1;
		}else if(!strcmp(argv[3], "NORO")){
			tagmask ^= T_RO;
			*roEnable = 0;
		} */

		/* set the port for divert socket. */
		/* *port_divert = atoi(argv[4]); */

#ifdef DEBUG_PARSECONF
		printf("tagmask: %d\n", tagmask); 
#endif

		while(fscanf(fp, "%s", tag) != EOF){
#ifdef DEBUG_PARSECONF
			printf("tag: %s ", tag); 
#endif
			switch (checktag(tag, &tagmask)){
				case T_RO:
					fpos = ftell(fp);
					while(fscanf(fp, "%s", token) != EOF){
#ifdef DEBUG_PARSECONF
						printf("token: %s, ", token); 
#endif
						if(isTag(token)){
							fseek(fp, fpos, SEEK_SET);
							break;
						}
						fpos = ftell(fp);
#ifdef DEBUG_PARSECONF
						printf("RO: %s.\n", token);
#endif
						if(!strcmp(token, "DISABLE")){
							*roEnable = 0;
						}else if(!strcmp(token, "ENABLE")){
							*roEnable = 1;
						}
					}
					break;
				case T_ALLIP:
					fpos = ftell(fp);
					while(fscanf(fp, "%s", token) != EOF){
#ifdef DEBUG_PARSECONF
						printf("token: %s, ", token); 
#endif
						if(isTag(token)){
							fseek(fp, fpos, SEEK_SET);
							break;
						}
						fpos = ftell(fp);
#ifdef DEBUG_PARSECONF
						printf("add %s to all_if_list.\n", token);
#endif
						addEntry(all_if_list, token);
					}
					break;
				case T_INNERIP:
					fpos = ftell(fp);
					while(fscanf(fp, "%s", token) != EOF){
						if(isTag(token)){
							fseek(fp, fpos, SEEK_SET);
							break;
						}
						fpos = ftell(fp);
#ifdef DEBUG_PARSECONF
						printf("add %s to inner_if_list.\n", token);
#endif
						addEntry(inner_if_list, token);
					}
					break;
				case T_DPORT:
					fpos = ftell(fp);
					while(fscanf(fp, "%s", token) != EOF){
						if(isTag(token)){
							fseek(fp, fpos, SEEK_SET);
							break;
						}
						fpos = ftell(fp);
#ifdef DEBUG_PARSECONF
						printf("DIVERT_PORT: %s.\n", token);
#endif
						*port_divert = atoi(token);
					}
					break;
				case T_COA:
					fpos = ftell(fp);
					while(fscanf(fp, "%s", token) != EOF){
						if(isTag(token)){
							fseek(fp, fpos, SEEK_SET);
							break;
						}
						fpos = ftell(fp);
#ifdef DEBUG_PARSECONF
						printf("set %s to care of addr.\n", token);
#endif
						coa->s_addr = inet_addr(token);
					}
					break;
				/* case T_BCAST:
					fpos = ftell(fp);
					while(fscanf(fp, "%s", token) != EOF){
						if(isTag(token)){
							fseek(fp, fpos, SEEK_SET);
							break;
						}
						fpos = ftell(fp);
#ifdef DEBUG_PARSECONF
						printf("set %s to broadcast addr.\n", token);
#endif
						bAddr->sin_addr.s_addr = inet_addr(token);
					}
					break; */
				case T_MN:
					fpos = ftell(fp);
					while(fscanf(fp, "%s", token) != EOF){
						if(isTag(token)){
							fseek(fp, fpos, SEEK_SET);
							break;
						}
						fpos = ftell(fp);
#ifdef DEBUG_PARSECONF
						printf("add %s to mn_ip_list.\n", token);
#endif
						addMNEntry(mn_ip_list, token, "",  NA);
					}
					break;
				case T_ERR:
					printf("T_ERR--");
					printConfFileUsage();
					exit(1);
			}
		}

		/* check whether all necessary field is equipped. */
		if(tagmask != 0){
			printf("tagmask = %d != 0\n", tagmask);
			printConfFileUsage();
			exit(1);
		}

		if(fclose(fp) == EOF){
			fprintf(stderr, "[X] Close agent config file fail.\n");
			/* Though fail to close, but we continue to execute. */
		}

	}else{
	}

	return 0;
}
Example #10
0
File: sub.c Project: npe9/harvey
Off
bufalloc(Device *dev, int tag, int32_t qid, int uid)
{
	Iobuf *bp, *p;
	Superb *sb;
	Off a, n;

	p = getbuf(dev, superaddr(dev), Brd|Bmod);
	if(!p || checktag(p, Tsuper, QPSUPER)) {
		print("bufalloc: super block\n");
		if(p)
			putbuf(p);
		return 0;
	}
	sb = (Superb*)p->iobuf;

loop:
	n = --sb->fbuf.nfree;
	sb->tfree--;
	if(n < 0 || n >= FEPERBUF) {
		print("bufalloc: %Z: bad freelist\n", dev);
		n = 0;
		sb->fbuf.free[0] = 0;
	}
	a = sb->fbuf.free[n];
	if(n <= 0) {
		if(a == 0) {
			sb->tfree = 0;
			sb->fbuf.nfree = 1;
			if(dev->type == Devcw) {
				n = uid;
				if(n < 0 || n >= nelem(growacct))
					n = 0;
				growacct[n]++;
				if(cwgrow(dev, sb, uid))
					goto loop;
			}
			putbuf(p);
			print("fs %Z full uid=%d\n", dev, uid);
			return 0;
		}
		bp = getbuf(dev, a, Brd);
		if(!bp || checktag(bp, Tfree, QPNONE)) {
			if(bp)
				putbuf(bp);
			putbuf(p);
			return 0;
		}
		sb->fbuf = *(Fbuf*)bp->iobuf;
		putbuf(bp);
	}

	bp = getbuf(dev, a, Bmod);
	memset(bp->iobuf, 0, RBUFSIZE);
	settag(bp, tag, qid);
	if(tag == Tind1 || tag == Tind2 ||
#ifndef COMPAT32
	    tag == Tind3 || tag == Tind4 ||  /* add more Tind tags here ... */
#endif
	    tag == Tdir)
		bp->flags |= Bimm;
	putbuf(bp);
	putbuf(p);
	return a;
}
Example #11
0
int
doremove(File *f, int iscon)
{
	Iobuf *p, *p1;
	Dentry *d, *d1;
	int32_t addr;
	int slot, err;

	p = 0;
	p1 = 0;
	if(isro(f->fs->dev) || (f->cp != cons.chan && writegroup && !ingroup(f->uid, writegroup))) {
		err = Eronly;
		goto out;
	}
	/*
	 * check on parent directory of file to be deleted
	 */
	if(f->wpath == 0 || f->wpath->addr == f->addr) {
		err = Ephase;
		goto out;
	}
	p1 = getbuf(f->fs->dev, f->wpath->addr, Bread);
	d1 = getdir(p1, f->wpath->slot);
	if(!d1 || checktag(p1, Tdir, QPNONE) || !(d1->mode & DALLOC)) {
		err = Ephase;
		goto out;
	}
	if(!iscon && iaccess(f, d1, DWRITE)) {
		err = Eaccess;
		goto out;
	}
	accessdir(p1, d1, FWRITE);
	putbuf(p1);
	p1 = 0;

	/*
	 * check on file to be deleted
	 */
	p = getbuf(f->fs->dev, f->addr, Bread);
	d = getdir(p, f->slot);
	if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
		err = Ealloc;
		goto out;
	}
	if(err = mkqidcmp(&f->qid, d))
		goto out;

	/*
	 * if deleting a directory, make sure it is empty
	 */
	if((d->mode & DDIR))
	for(addr=0;; addr++) {
		p1 = dnodebuf(p, d, addr, 0);
		if(!p1)
			break;
		if(checktag(p1, Tdir, d->qid.path)) {
			err = Ephase;
			goto out;
		}
		for(slot=0; slot<DIRPERBUF; slot++) {
			d1 = getdir(p1, slot);
			if(!(d1->mode & DALLOC))
				continue;
			err = Eempty;
			goto out;
		}
		putbuf(p1);
	}

	/*
	 * do it
	 */
	dtrunc(p, d);
	memset(d, 0, sizeof(Dentry));
	settag(p, Tdir, QPNONE);

out:
	if(p1)
		putbuf(p1);
	if(p)
		putbuf(p);
	return err;
}
Example #12
0
void
f_write(Chan *cp, Oldfcall *in, Oldfcall *ou)
{
	Iobuf *p, *p1;
	Dentry *d;
	File *f;
	Tlock *t;
	int32_t offset, addr, tim;
	int count, nwrite, o, n;

	if(CHAT(cp)) {
		print("c_write %d\n", cp->chan);
		print("	fid = %d\n", in->fid);
		print("	offset = %ld\n", in->offset);
		print("	count = %ld\n", in->count);
	}

	offset = in->offset;
	count = in->count;
	nwrite = 0;
	p = 0;
	f = filep(cp, in->fid, 0);
	if(!f) {
		ou->err = Efid;
		goto out;
	}
	if(!(f->open & FWRITE)) {
		ou->err = Eopen;
		goto out;
	}
	if(isro(f->fs->dev) || (cp != cons.chan && writegroup && !ingroup(f->uid, writegroup))) {
		ou->err = Eronly;
		goto out;
	}
	if(count < 0 || count > MAXDAT) {
		ou->err = Ecount;
		goto out;
	}
	if(offset < 0) {
		ou->err = Eoffset;
		goto out;
	}
	p = getbuf(f->fs->dev, f->addr, Bread|Bmod);
	d = getdir(p, f->slot);
	if(!d || !(d->mode & DALLOC)) {
		ou->err = Ealloc;
		goto out;
	}
	if(ou->err = mkqidcmp(&f->qid, d))
		goto out;
	if(t = f->tlock) {
		tim = time(0);
		if(t->time < tim || t->file != f) {
			ou->err = Ebroken;
			goto out;
		}
		/* renew the lock */
		t->time = tim + TLOCK;
	}
	accessdir(p, d, FWRITE);
	if(d->mode & DAPND)
		offset = d->size;
	if(offset+count > d->size)
		d->size = offset+count;
	while(count > 0) {
		addr = offset / BUFSIZE;
		o = offset % BUFSIZE;
		n = BUFSIZE - o;
		if(n > count)
			n = count;
		p1 = dnodebuf(p, d, addr, Tfile);
		if(p1 == 0) {
			ou->err = Efull;
			goto out;
		}
		if(checktag(p1, Tfile, d->qid.path)) {
			putbuf(p1);
			ou->err = Ephase;
			goto out;
		}
		memmove(p1->iobuf+o, in->data+nwrite, n);
		p1->flags |= Bmod;
		putbuf(p1);
		count -= n;
		nwrite += n;
		offset += n;
	}
	if(CHAT(cp))
		print("	nwrite = %d\n", nwrite);

out:
	if(p)
		putbuf(p);
	if(f)
		qunlock(f);
	ou->fid = in->fid;
	ou->count = nwrite;
}
Example #13
0
void
f_read(Chan *cp, Oldfcall *in, Oldfcall *ou)
{
	Iobuf *p, *p1;
	File *f;
	Dentry *d, *d1;
	Tlock *t;
	int32_t addr, offset, tim;
	int nread, count, n, o, slot;

	if(CHAT(cp)) {
		print("c_read %d\n", cp->chan);
		print("	fid = %d\n", in->fid);
		print("	offset = %ld\n", in->offset);
		print("	count = %ld\n", in->count);
	}

	p = 0;
	count = in->count;
	offset = in->offset;
	nread = 0;
	f = filep(cp, in->fid, 0);
	if(!f) {
		ou->err = Efid;
		goto out;
	}
	if(!(f->open & FREAD)) {
		ou->err = Eopen;
		goto out;
	}
	if(count < 0 || count > MAXDAT) {
		ou->err = Ecount;
		goto out;
	}
	if(offset < 0) {
		ou->err = Eoffset;
		goto out;
	}
	p = getbuf(f->fs->dev, f->addr, Bread);
	d = getdir(p, f->slot);
	if(!d || !(d->mode & DALLOC)) {
		ou->err = Ealloc;
		goto out;
	}
	if(ou->err = mkqidcmp(&f->qid, d))
		goto out;
	if(t = f->tlock) {
		tim = time(0);
		if(t->time < tim || t->file != f) {
			ou->err = Ebroken;
			goto out;
		}
		/* renew the lock */
		t->time = tim + TLOCK;
	}
	accessdir(p, d, FREAD);
	if(d->mode & DDIR) {
		addr = 0;
		goto dread;
	}
	if(offset+count > d->size)
		count = d->size - offset;
	while(count > 0) {
		addr = offset / BUFSIZE;
		if(addr == f->lastra+1)
			dbufread(p, d, addr+1);
		f->lastra = addr;
		o = offset % BUFSIZE;
		n = BUFSIZE - o;
		if(n > count)
			n = count;
		p1 = dnodebuf(p, d, addr, 0);
		if(p1) {
			if(checktag(p1, Tfile, QPNONE)) {
				ou->err = Ephase;
				putbuf(p1);
				goto out;
			}
			memmove(ou->data+nread, p1->iobuf+o, n);
			putbuf(p1);
		} else
			memset(ou->data+nread, 0, n);
		count -= n;
		nread += n;
		offset += n;
	}
	goto out;

dread:
	p1 = dnodebuf(p, d, addr, 0);
	if(!p1)
		goto out;
	if(checktag(p1, Tdir, QPNONE)) {
		ou->err = Ephase;
		putbuf(p1);
		goto out;
	}
	n = DIRREC;
	for(slot=0; slot<DIRPERBUF; slot++) {
		d1 = getdir(p1, slot);
		if(!(d1->mode & DALLOC))
			continue;
		if(offset >= n) {
			offset -= n;
			continue;
		}
		if(count < n) {
			putbuf(p1);
			goto out;
		}
		if(convD2M9p1(d1, ou->data+nread) != n)
			print("dirread convD2M\n");
		nread += n;
		count -= n;
	}
	putbuf(p1);
	addr++;
	goto dread;

out:
	count = in->count - nread;
	if(count > 0)
		memset(ou->data+nread, 0, count);
	if(p)
		putbuf(p);
	if(f)
		qunlock(f);
	ou->fid = in->fid;
	ou->count = nread;
	if(CHAT(cp))
		print("	nread = %d\n", nread);
}
Example #14
0
void
f_create(Chan *cp, Oldfcall *in, Oldfcall *ou)
{
	Iobuf *p, *p1;
	Dentry *d, *d1;
	File *f;
	int slot, slot1, fmod;
	int32_t addr, addr1, path;
	Qid qid;
	Tlock *t;
	Wpath *w;

	if(CHAT(cp)) {
		print("c_create %d\n", cp->chan);
		print("	fid = %d\n", in->fid);
		print("	name = %s\n", in->name);
		print("	perm = %lx+%lo\n", (in->perm>>28)&0xf,
				in->perm&0777);
		print("	mode = %d\n", in->mode);
	}

	p = 0;
	f = filep(cp, in->fid, 0);
	if(!f) {
		ou->err = Efid;
		goto out;
	}
	if(isro(f->fs->dev) || (cp != cons.chan && writegroup && !ingroup(f->uid, writegroup))) {
		ou->err = Eronly;
		goto out;
	}

	p = getbuf(f->fs->dev, f->addr, Bread);
	d = getdir(p, f->slot);
	if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
		ou->err = Ealloc;
		goto out;
	}
	if(ou->err = mkqidcmp(&f->qid, d))
		goto out;
	if(!(d->mode & DDIR)) {
		ou->err = Edir2;
		goto out;
	}
	if(cp != cons.chan && iaccess(f, d, DWRITE) && !writeallow) {
		ou->err = Eaccess;
		goto out;
	}
	accessdir(p, d, FREAD);
	if(!strncmp(in->name, ".", sizeof(in->name)) ||
	   !strncmp(in->name, "..", sizeof(in->name))) {
		ou->err = Edot;
		goto out;
	}
	if(checkname(in->name)) {
		ou->err = Ename;
		goto out;
	}
	addr1 = 0;
	slot1 = 0;	/* set */
	for(addr=0;; addr++) {
		p1 = dnodebuf(p, d, addr, 0);
		if(!p1) {
			if(addr1)
				break;
			p1 = dnodebuf(p, d, addr, Tdir);
		}
		if(p1 == 0) {
			ou->err = Efull;
			goto out;
		}
		if(checktag(p1, Tdir, d->qid.path)) {
			putbuf(p1);
			goto phase;
		}
		for(slot=0; slot<DIRPERBUF; slot++) {
			d1 = getdir(p1, slot);
			if(!(d1->mode & DALLOC)) {
				if(!addr1) {
					addr1 = p1->addr;
					slot1 = slot + addr*DIRPERBUF;
				}
				continue;
			}
			if(!strncmp(in->name, d1->name, sizeof(in->name))) {
				putbuf(p1);
				ou->err = Eexist;
				goto out;
			}
		}
		putbuf(p1);
	}
	switch(in->mode & 7) {
	case MEXEC:
	case MREAD:		/* seems only useful to make directories */
		fmod = FREAD;
		break;

	case MWRITE:
		fmod = FWRITE;
		break;

	case MBOTH:
		fmod = FREAD+FWRITE;
		break;

	default:
		ou->err = Emode;
		goto out;
	}
	if(in->perm & PDIR)
		if((in->mode & MTRUNC) || (in->perm & PAPND) || (fmod & FWRITE))
			goto badaccess;
	/*
	 * do it
	 */
	path = qidpathgen(&f->fs->dev);
	p1 = getbuf(f->fs->dev, addr1, Bread|Bimm|Bmod);
	d1 = getdir(p1, slot1);
	if(!d1 || checktag(p1, Tdir, d->qid.path)) {
		if(p1)
			putbuf(p1);
		goto phase;
	}
	if(d1->mode & DALLOC) {
		putbuf(p1);
		goto phase;
	}

	strncpy(d1->name, in->name, sizeof(in->name));
	/*
	 * bogus argument passing -- see console.c
	 */
	if(cp == cons.chan) {
		d1->uid = cons.uid;
		d1->gid = cons.gid;
	} else {
		d1->uid = f->uid;
		d1->gid = d->gid;
		in->perm &= d->mode | ~0666;
		if(in->perm & PDIR)
			in->perm &= d->mode | ~0777;
	}
	d1->qid.path = path;
	d1->qid.version = 0;
	d1->mode = DALLOC | (in->perm & 0777);
	if(in->perm & PDIR) {
		d1->mode |= DDIR;
		d1->qid.path |= QPDIR;
	}
	if(in->perm & PAPND)
		d1->mode |= DAPND;
	t = 0;
	if(in->perm & PLOCK) {
		d1->mode |= DLOCK;
		t = tlocked(p1, d1);
	}
	accessdir(p1, d1, FWRITE);
	mkqid(&qid, d1, 0);
	putbuf(p1);
	accessdir(p, d, FWRITE);

	/*
	 * do a walk to new directory entry
	 */
	w = newwp();
	if(!w) {
		ou->err = Ewalk;
		goto out;
	}
	w->addr = f->addr;
	w->slot = f->slot;
	w->up = f->wpath;
	f->wpath = w;
	f->qid = qid;
	f->tlock = t;
	f->lastra = 0;
	if(in->mode & MRCLOSE)
		fmod |= FREMOV;
	f->open = fmod;
	f->addr = addr1;
	f->slot = slot1;
	if(t)
		t->file = f;
	mkqid9p1(&ou->qid, &qid);
	goto out;

badaccess:
	ou->err = Eaccess;
	goto out;

phase:
	ou->err = Ephase;

out:
	if(p)
		putbuf(p);
	if(f)
		qunlock(f);
	ou->fid = in->fid;
}
Example #15
0
void
f_open(Chan *cp, Oldfcall *in, Oldfcall *ou)
{
	Iobuf *p;
	Dentry *d;
	File *f;
	Tlock *t;
	Qid qid;
	int ro, fmod;

	if(CHAT(cp)) {
		print("c_open %d\n", cp->chan);
		print("	fid = %d\n", in->fid);
		print("	mode = %o\n", in->mode);
	}

	p = 0;
	f = filep(cp, in->fid, 0);
	if(!f) {
		ou->err = Efid;
		goto out;
	}

	/*
	 * if remove on close, check access here
	 */
	ro = isro(f->fs->dev) || (cp != cons.chan && writegroup && !ingroup(f->uid, writegroup));
	if(in->mode & MRCLOSE) {
		if(ro) {
			ou->err = Eronly;
			goto out;
		}
		/*
		 * check on parent directory of file to be deleted
		 */
		if(f->wpath == 0 || f->wpath->addr == f->addr) {
			ou->err = Ephase;
			goto out;
		}
		p = getbuf(f->fs->dev, f->wpath->addr, Bread);
		d = getdir(p, f->wpath->slot);
		if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
			ou->err = Ephase;
			goto out;
		}
		if(iaccess(f, d, DWRITE)) {
			ou->err = Eaccess;
			goto out;
		}
		putbuf(p);
	}
	p = getbuf(f->fs->dev, f->addr, Bread);
	d = getdir(p, f->slot);
	if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
		ou->err = Ealloc;
		goto out;
	}
	if(ou->err = mkqidcmp(&f->qid, d))
		goto out;
	mkqid(&qid, d, 1);
	switch(in->mode & 7) {

	case MREAD:
		if(iaccess(f, d, DREAD) && !writeallow)
			goto badaccess;
		fmod = FREAD;
		break;

	case MWRITE:
		if((d->mode & DDIR) ||
		   (iaccess(f, d, DWRITE) && !writeallow))
			goto badaccess;
		if(ro) {
			ou->err = Eronly;
			goto out;
		}
		fmod = FWRITE;
		break;

	case MBOTH:
		if((d->mode & DDIR) ||
		   (iaccess(f, d, DREAD) && !writeallow) ||
		   (iaccess(f, d, DWRITE) && !writeallow))
			goto badaccess;
		if(ro) {
			ou->err = Eronly;
			goto out;
		}
		fmod = FREAD+FWRITE;
		break;

	case MEXEC:
		if((d->mode & DDIR) ||
		   iaccess(f, d, DEXEC))
			goto badaccess;
		fmod = FREAD;
		break;

	default:
		ou->err = Emode;
		goto out;
	}
	if(in->mode & MTRUNC) {
		if((d->mode & DDIR) ||
		   (iaccess(f, d, DWRITE) && !writeallow))
			goto badaccess;
		if(ro) {
			ou->err = Eronly;
			goto out;
		}
	}
	t = 0;
	if(d->mode & DLOCK) {
		t = tlocked(p, d);
		if(t == 0) {
			ou->err = Elocked;
			goto out;
		}
		t->file = f;
	}
	if(in->mode & MRCLOSE)
		fmod |= FREMOV;
	f->open = fmod;
	if(in->mode & MTRUNC)
		if(!(d->mode & DAPND))
			dtrunc(p, d);
	f->tlock = t;
	f->lastra = 0;
	mkqid9p1(&ou->qid, &qid);
	goto out;

badaccess:
	ou->err = Eaccess;
	f->open = 0;

out:
	if(p)
		putbuf(p);
	if(f)
		qunlock(f);
	ou->fid = in->fid;
}
Example #16
0
void
f_walk(Chan *cp, Oldfcall *in, Oldfcall *ou)
{
	Iobuf *p, *p1;
	Dentry *d, *d1;
	File *f;
	Wpath *w, *ow;
	int slot;
	int32_t addr;

	if(CHAT(cp)) {
		print("c_walk %d\n", cp->chan);
		print("	fid = %d\n", in->fid);
		print("	name = %s\n", in->name);
	}

	ou->fid = in->fid;
	ou->qid = QID9P1(0,0);
	p = 0;
	f = filep(cp, in->fid, 0);
	if(!f) {
		ou->err = Efid;
		goto out;
	}
	p = getbuf(f->fs->dev, f->addr, Bread);
	d = getdir(p, f->slot);
	if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
		ou->err = Ealloc;
		goto out;
	}
	if(!(d->mode & DDIR)) {
		ou->err = Edir1;
		goto out;
	}
	if(ou->err = mkqidcmp(&f->qid, d))
		goto out;
	if(cp != cons.chan && iaccess(f, d, DEXEC)) {
		ou->err = Eaccess;
		goto out;
	}
	accessdir(p, d, FREAD);
	if(strcmp(in->name, ".") == 0)
		goto setdot;
	if(strcmp(in->name, "..") == 0) {
		if(f->wpath == 0)
			goto setdot;
		putbuf(p);
		p = 0;
		addr = f->wpath->addr;
		slot = f->wpath->slot;
		p1 = getbuf(f->fs->dev, addr, Bread);
		d1 = getdir(p1, slot);
		if(!d1 || checktag(p1, Tdir, QPNONE) || !(d1->mode & DALLOC)) {
			if(p1)
				putbuf(p1);
			ou->err = Ephase;
			goto out;
		}
		ow = f->wpath;
		f->wpath = ow->up;
		putwp(ow);
		goto found;
	}
	for(addr=0;; addr++) {
		p1 = dnodebuf(p, d, addr, 0);
		if(!p1 || checktag(p1, Tdir, d->qid.path) ) {
			if(p1)
				putbuf(p1);
			ou->err = Eentry;
			goto out;
		}
		for(slot=0; slot<DIRPERBUF; slot++) {
			d1 = getdir(p1, slot);
			if(!(d1->mode & DALLOC))
				continue;
			if(strncmp(in->name, d1->name, sizeof(in->name)))
				continue;
			/*
			 * update walk path
			 */
			w = newwp();
			if(!w) {
				ou->err = Ewalk;
				putbuf(p1);
				goto out;
			}
			w->addr = f->addr;
			w->slot = f->slot;
			w->up = f->wpath;
			f->wpath = w;
			slot += DIRPERBUF*addr;
			goto found;
		}
		putbuf(p1);
	}

found:
	f->addr = p1->addr;
	mkqid(&f->qid, d1, 1);
	putbuf(p1);
	f->slot = slot;

setdot:
	mkqid9p1(&ou->qid, &f->qid);
	f->open = 0;

out:
	if(p)
		putbuf(p);
	if(f)
		qunlock(f);
}
Example #17
0
void
f_wstat(Chan *cp, Oldfcall *in, Oldfcall *ou)
{
	Iobuf *p, *p1;
	Dentry *d, *d1, xd;
	File *f;
	int slot;
	int32_t addr;

	if(CHAT(cp)) {
		print("c_wstat %d\n", cp->chan);
		print("	fid = %d\n", in->fid);
	}

	p = 0;
	p1 = 0;
	d1 = 0;
	f = filep(cp, in->fid, 0);
	if(!f) {
		ou->err = Efid;
		goto out;
	}
	if(isro(f->fs->dev) || (cp != cons.chan && writegroup && !ingroup(f->uid, writegroup))) {
		ou->err = Eronly;
		goto out;
	}

	/*
	 * first get parent
	 */
	if(f->wpath) {
		p1 = getbuf(f->fs->dev, f->wpath->addr, Bread);
		d1 = getdir(p1, f->wpath->slot);
		if(!d1 || checktag(p1, Tdir, QPNONE) || !(d1->mode & DALLOC)) {
			ou->err = Ephase;
			goto out;
		}
	}

	p = getbuf(f->fs->dev, f->addr, Bread);
	d = getdir(p, f->slot);
	if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
		ou->err = Ealloc;
		goto out;
	}
	if(ou->err = mkqidcmp(&f->qid, d))
		goto out;

	convM2D9p1(in->stat, &xd);
	if(CHAT(cp)) {
		print("	d.name = %s\n", xd.name);
		print("	d.uid  = %d\n", xd.uid);
		print("	d.gid  = %d\n", xd.gid);
		print("	d.mode = %.4x\n", xd.mode);
	}

	/*
	 * if chown,
	 * must be god
	 */
	while(xd.uid != d->uid) {
		if(wstatallow)			/* set to allow chown during boot */
			break;
		ou->err = Enotu;
		goto out;
	}

	/*
	 * if chgroup,
	 * must be either
	 *	a) owner and in new group
	 *	b) leader of both groups
	 */
	while(xd.gid != d->gid) {
		if(wstatallow || writeallow)		/* set to allow chgrp during boot */
			break;
		if(d->uid == f->uid && ingroup(f->uid, xd.gid))
			break;
		if(leadgroup(f->uid, xd.gid))
			if(leadgroup(f->uid, d->gid))
				break;
		ou->err = Enotg;
		goto out;
	}

	/*
	 * if rename,
	 * must have write permission in parent
	 */
	if(xd.name[0] == 0)
		strncpy(xd.name, d->name, sizeof(xd.name));
	while(strncmp(d->name, xd.name, sizeof(d->name)) != 0) {
		if(checkname(xd.name)) {
			ou->err = Ename;
			goto out;
		}

		if(strcmp(xd.name, ".") == 0 || strcmp(xd.name, "..") == 0) {
			ou->err = Ename;
			goto out;
		}

		/*
		 * drop entry to prevent lock, then
		 * check that destination name is unique,
		 */
		putbuf(p);
		for(addr=0;; addr++) {
			p = dnodebuf(p1, d1, addr, 0);
			if(!p)
				break;
			if(checktag(p, Tdir, d1->qid.path)) {
				putbuf(p);
				continue;
			}
			for(slot=0; slot<DIRPERBUF; slot++) {
				d = getdir(p, slot);
				if(!(d->mode & DALLOC))
					continue;
				if(!strncmp(xd.name, d->name, sizeof(xd.name))) {
					ou->err = Eexist;
					goto out;
				}
			}
			putbuf(p);
		}

		/*
		 * reacquire entry
		 */
		p = getbuf(f->fs->dev, f->addr, Bread);
		d = getdir(p, f->slot);
		if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
			ou->err = Ephase;
			goto out;
		}

		if(wstatallow || writeallow) /* set to allow rename during boot */
			break;
		if(!d1 || iaccess(f, d1, DWRITE)) {
			ou->err = Eaccess;
			goto out;
		}
		break;
	}

	/*
	 * if mode/time, either
	 *	a) owner
	 *	b) leader of either group
	 */
	while(d->mtime != xd.mtime ||
	     ((d->mode^xd.mode) & (DAPND|DLOCK|0777))) {
		if(wstatallow)			/* set to allow chmod during boot */
			break;
		if(d->uid == f->uid)
			break;
		if(leadgroup(f->uid, xd.gid))
			break;
		if(leadgroup(f->uid, d->gid))
			break;
		ou->err = Enotu;
		goto out;
	}
	d->mtime = xd.mtime;
	d->uid = xd.uid;
	d->gid = xd.gid;
	d->mode = (xd.mode & (DAPND|DLOCK|0777)) | (d->mode & (DALLOC|DDIR));

	strncpy(d->name, xd.name, sizeof(d->name));
	if(wstatallow) {
		p->flags |= Bmod;
		if(xd.atime)
			d->atime = xd.atime;
		if(xd.mtime)
			d->mtime = xd.mtime;
	} else
		accessdir(p, d, FWSTAT);

out:
	if(p)
		putbuf(p);
	if(p1)
		putbuf(p1);
	if(f)
		qunlock(f);
	ou->fid = in->fid;
}