Beispiel #1
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;
}
Beispiel #2
0
int
fcallfmt9p1(Fmt *f1)
{
	Fcall9p1 *f;
	int fid, type, tag, n;
	char buf[512];
	Dir d;

	f = va_arg(f1->args, Fcall9p1*);
	type = f->type;
	fid = f->fid;
	tag = f->tag;
	switch(type){
	case Tnop9p1:	/* 50 */
		sprint(buf, "old Tnop tag %ud", tag);
		break;
	case Rnop9p1:
		sprint(buf, "old Rnop tag %ud", tag);
		break;
	case Tsession9p1:	/* 52 */
		sprint(buf, "old Tsession tag %ud", tag);
		break;
	case Rsession9p1:
		sprint(buf, "old Rsession tag %ud", tag);
		break;
	case Rerror9p1:	/* 55 */
		sprint(buf, "old Rerror tag %ud error %.64s", tag, f->ename);
		break;
	case Tflush9p1:	/* 56 */
		sprint(buf, "old Tflush tag %ud oldtag %d", tag, f->oldtag);
		break;
	case Rflush9p1:
		sprint(buf, "old Rflush tag %ud", tag);
		break;
	case Tattach9p1:	/* 58 */
		sprint(buf, "old Tattach tag %ud fid %d uname %.28s aname %.28s auth %.28s",
			tag, f->fid, f->uname, f->aname, f->auth);
		break;
	case Rattach9p1:
		sprint(buf, "old Rattach tag %ud fid %d qid 0x%lux|0x%lux",
			tag, fid, f->qid.path, f->qid.version);
		break;
	case Tclone9p1:	/* 60 */
		sprint(buf, "old Tclone tag %ud fid %d newfid %d", tag, fid, f->newfid);
		break;
	case Rclone9p1:
		sprint(buf, "old Rclone tag %ud fid %d", tag, fid);
		break;
	case Twalk9p1:	/* 62 */
		sprint(buf, "old Twalk tag %ud fid %d name %.28s", tag, fid, f->name);
		break;
	case Rwalk9p1:
		sprint(buf, "old Rwalk tag %ud fid %d qid 0x%lux|0x%lux",
			tag, fid, f->qid.path, f->qid.version);
		break;
	case Topen9p1:	/* 64 */
		sprint(buf, "old Topen tag %ud fid %d mode %d", tag, fid, f->mode);
		break;
	case Ropen9p1:
		sprint(buf, "old Ropen tag %ud fid %d qid 0x%lux|0x%lux",
			tag, fid, f->qid.path, f->qid.version);
		break;
	case Tcreate9p1:	/* 66 */
		sprint(buf, "old Tcreate tag %ud fid %d name %.28s perm 0x%lux mode %d",
			tag, fid, f->name, f->perm, f->mode);
		break;
	case Rcreate9p1:
		sprint(buf, "old Rcreate tag %ud fid %d qid 0x%lux|0x%lux",
			tag, fid, f->qid.path, f->qid.version);
		break;
	case Tread9p1:	/* 68 */
		sprint(buf, "old Tread tag %ud fid %d offset %ld count %ld",
			tag, fid, f->offset, f->count);
		break;
	case Rread9p1:
		n = sprint(buf, "old Rread tag %ud fid %d count %ld ", tag, fid, f->count);
			dumpsome(buf+n, f->data, f->count);
		break;
	case Twrite9p1:	/* 70 */
		n = sprint(buf, "old Twrite tag %ud fid %d offset %ld count %ld ",
			tag, fid, f->offset, f->count);
		dumpsome(buf+n, f->data, f->count);
		break;
	case Rwrite9p1:
		sprint(buf, "old Rwrite tag %ud fid %d count %ld", tag, fid, f->count);
		break;
	case Tclunk9p1:	/* 72 */
		sprint(buf, "old Tclunk tag %ud fid %d", tag, fid);
		break;
	case Rclunk9p1:
		sprint(buf, "old Rclunk tag %ud fid %d", tag, fid);
		break;
	case Tremove9p1:	/* 74 */
		sprint(buf, "old Tremove tag %ud fid %d", tag, fid);
		break;
	case Rremove9p1:
		sprint(buf, "old Rremove tag %ud fid %d", tag, fid);
		break;
	case Tstat9p1:	/* 76 */
		sprint(buf, "old Tstat tag %ud fid %d", tag, fid);
		break;
	case Rstat9p1:
		convM2D9p1(f->stat, &d);
		sprint(buf, "old Rstat tag %ud fid %d stat %D", tag, fid, &d);
		break;
	case Twstat9p1:	/* 78 */
		convM2D9p1(f->stat, &d);
		sprint(buf, "old Twstat tag %ud fid %d stat %D", tag, fid, &d);
		break;
	case Rwstat9p1:
		sprint(buf, "old Rwstat tag %ud fid %d", tag, fid);
		break;
	case Tclwalk9p1:	/* 81 */
		sprint(buf, "old Tclwalk tag %ud fid %d newfid %d name %.28s",
			tag, fid, f->newfid, f->name);
		break;
	case Rclwalk9p1:
		sprint(buf, "old Rclwalk tag %ud fid %d qid 0x%lux|0x%lux",
			tag, fid, f->qid.path, f->qid.version);
		break;
	default:
		sprint(buf,  "unknown type %d", type);
	}
	return fmtstrcpy(f1, buf);
}
Beispiel #3
0
void
cmd_rename(void)
{
	uint32_t perm;
	Dentry d;
	char stat[DIRREC];
	char oelem[NAMELEN], noelem[NAMELEN], nxelem[NAMELEN];
	int err;

	if(con_clone(FID1, FID2))
		return;
	if(skipbl(1))
		return;
	oelem[0] = 0;
	while(nextelem()) {
		if(oelem[0])
			if(con_walk(FID2, oelem)){
				cprint("file does not exits");
				return;
			}
		memmove(oelem, elem, NAMELEN);
	}
	if(skipbl(1))
		return;
	if(cons.arg[0]=='/'){
		if(con_clone(FID1, FID3))
			return;
		noelem[0] = 0;
		while(nextelem()){
			if(noelem[0])
				if(con_walk(FID3, noelem)){
					cprint("target path %s does not exist", noelem);
					return;
				}
			memmove(noelem, elem, NAMELEN);
		}
		if(!con_walk(FID3, elem)){
			cprint("target %s already exists\n", elem);
			return;
		}
		if(con_walk(FID2, oelem)){
			cprint("src %s does not exist\n", oelem);
			return;
		}
		/*
		 * we know the target does not exist,
		 * the source does exist.
		 * to do the rename, create the target and then
		 * copy the directory entry directly.  then remove the source.
		 */
		if(err = con_stat(FID2, stat)){
			cprint("can't stat file: %s\n", errstring[err]);
			return;
		}
		convM2D9p1(stat, &d);
		perm = (d.mode&0777)|((d.mode&0x7000)<<17);
		if(err = con_create(FID3, elem, d.uid, d.gid, perm, (d.mode&DDIR)?OREAD:ORDWR)){
			cprint("can't create %s: %s\n", elem, errstring[err]);
			return;
		}
		if(err = con_swap(FID2, FID3)){
			cprint("can't swap data: %s\n", errstring[err]);
			return;
		}
		if(err = con_remove(FID2)){
			cprint("can't remove file: %s\n", errstring[err]);
			return;
		}
	}else{
		cname(nxelem);
		if(strchr(nxelem, '/')){
			cprint("bad rename target: not full path, but contains slashes\n");
			return;
		}
		if(!con_walk(FID2, nxelem))
			cprint("file %s already exists\n", nxelem);
		else if(con_walk(FID2, oelem))
			cprint("file does not already exist\n");
		else if(err = con_stat(FID2, stat))
			cprint("can't stat file: %s\n", errstring[err]);
		else{
			convM2D9p1(stat, &d);
			strncpy(d.name, nxelem, NAMELEN);
			convD2M9p1(&d, stat);
			if(err = con_wstat(FID2, stat))
				cprint("can't move file: %s\n", errstring[err]);
		}
	}
}