xref: /plan9-contrib/sys/src/cmd/dossrv/dosfs.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
3*219b2ee8SDavid du Colombier #include <auth.h>
43e12c5d1SDavid du Colombier #include <fcall.h>
53e12c5d1SDavid du Colombier #include "iotrack.h"
63e12c5d1SDavid du Colombier #include "dat.h"
73e12c5d1SDavid du Colombier #include "fns.h"
83e12c5d1SDavid du Colombier 
93e12c5d1SDavid du Colombier extern Fcall	thdr;
103e12c5d1SDavid du Colombier extern Fcall	rhdr;
113e12c5d1SDavid du Colombier extern char	data[sizeof(Fcall)+MAXFDATA];
123e12c5d1SDavid du Colombier extern char	fdata[MAXFDATA];
133e12c5d1SDavid du Colombier extern int	errno;
143e12c5d1SDavid du Colombier 
153e12c5d1SDavid du Colombier void
163e12c5d1SDavid du Colombier rnop(void)
173e12c5d1SDavid du Colombier {
183e12c5d1SDavid du Colombier 	chat("nop...");
193e12c5d1SDavid du Colombier }
203e12c5d1SDavid du Colombier void
213e12c5d1SDavid du Colombier rsession(void)
223e12c5d1SDavid du Colombier {
23*219b2ee8SDavid du Colombier 	memset(thdr.authid, 0, sizeof(thdr.authid));
24*219b2ee8SDavid du Colombier 	memset(thdr.authdom, 0, sizeof(thdr.authdom));
25*219b2ee8SDavid du Colombier 	memset(thdr.chal, 0, sizeof(thdr.chal));
263e12c5d1SDavid du Colombier 	chat("session...");
273e12c5d1SDavid du Colombier }
283e12c5d1SDavid du Colombier void
293e12c5d1SDavid du Colombier rflush(void)
303e12c5d1SDavid du Colombier {
313e12c5d1SDavid du Colombier 	chat("flush...");
323e12c5d1SDavid du Colombier }
333e12c5d1SDavid du Colombier void
343e12c5d1SDavid du Colombier rattach(void)
353e12c5d1SDavid du Colombier {
36*219b2ee8SDavid du Colombier 	Xfs *xf;
37*219b2ee8SDavid du Colombier 	Xfile *root;
383e12c5d1SDavid du Colombier 	Dosptr *dp;
393e12c5d1SDavid du Colombier 
403e12c5d1SDavid du Colombier 	chat("attach(fid=%d,uname=\"%s\",aname=\"%s\",auth=\"%s\")...",
413e12c5d1SDavid du Colombier 		thdr.fid, thdr.uname, thdr.aname, thdr.auth);
423e12c5d1SDavid du Colombier 
433e12c5d1SDavid du Colombier 	root = xfile(thdr.fid, Clean);
443e12c5d1SDavid du Colombier 	if(!root){
453e12c5d1SDavid du Colombier 		errno = Enomem;
463e12c5d1SDavid du Colombier 		goto error;
473e12c5d1SDavid du Colombier 	}
483e12c5d1SDavid du Colombier 	root->xf = xf = getxfs(thdr.aname);
493e12c5d1SDavid du Colombier 	if(!xf)
503e12c5d1SDavid du Colombier 		goto error;
513e12c5d1SDavid du Colombier 	if(xf->fmt==0 && dosfs(xf)<0){
523e12c5d1SDavid du Colombier 		errno = Eformat;
533e12c5d1SDavid du Colombier 		goto error;
543e12c5d1SDavid du Colombier 	}
553e12c5d1SDavid du Colombier 	root->qid.path = CHDIR;
563e12c5d1SDavid du Colombier 	root->qid.vers = 0;
573e12c5d1SDavid du Colombier 	root->xf->rootqid = root->qid;
583e12c5d1SDavid du Colombier 	dp = malloc(sizeof(Dosptr));
593e12c5d1SDavid du Colombier 	memset(dp, 0, sizeof(Dosptr));
603e12c5d1SDavid du Colombier 	root->ptr = dp;
613e12c5d1SDavid du Colombier 	rhdr.qid = root->qid;
623e12c5d1SDavid du Colombier 	return;
633e12c5d1SDavid du Colombier error:
643e12c5d1SDavid du Colombier 	if(root)
653e12c5d1SDavid du Colombier 		xfile(thdr.fid, Clunk);
663e12c5d1SDavid du Colombier 	return;
673e12c5d1SDavid du Colombier }
683e12c5d1SDavid du Colombier void
693e12c5d1SDavid du Colombier rclone(void)
703e12c5d1SDavid du Colombier {
713e12c5d1SDavid du Colombier 	Xfile *of = xfile(thdr.fid, Asis);
723e12c5d1SDavid du Colombier 	Xfile *nf = xfile(thdr.newfid, Clean);
733e12c5d1SDavid du Colombier 
743e12c5d1SDavid du Colombier 	chat("clone(fid=%d,newfid=%d)...", thdr.fid, thdr.newfid);
753e12c5d1SDavid du Colombier 	if(!of)
763e12c5d1SDavid du Colombier 		errno = Eio;
773e12c5d1SDavid du Colombier 	else if(!nf)
783e12c5d1SDavid du Colombier 		errno = Enomem;
793e12c5d1SDavid du Colombier 	else{
803e12c5d1SDavid du Colombier 		Xfile *next = nf->next;
813e12c5d1SDavid du Colombier 		Dosptr *dp = malloc(sizeof(Dosptr));
823e12c5d1SDavid du Colombier 		*nf = *of;
833e12c5d1SDavid du Colombier 		nf->next = next;
843e12c5d1SDavid du Colombier 		nf->fid = thdr.newfid;
853e12c5d1SDavid du Colombier 		nf->ptr = dp;
863e12c5d1SDavid du Colombier 		refxfs(nf->xf, 1);
873e12c5d1SDavid du Colombier 		memmove(dp, of->ptr, sizeof(Dosptr));
883e12c5d1SDavid du Colombier 		dp->p = 0;
893e12c5d1SDavid du Colombier 		dp->d = 0;
903e12c5d1SDavid du Colombier 	}
913e12c5d1SDavid du Colombier }
923e12c5d1SDavid du Colombier void
933e12c5d1SDavid du Colombier rwalk(void)
943e12c5d1SDavid du Colombier {
953e12c5d1SDavid du Colombier 	Xfile *f=xfile(thdr.fid, Asis);
963e12c5d1SDavid du Colombier 	Dosptr dp[1];
973e12c5d1SDavid du Colombier 	int r;
983e12c5d1SDavid du Colombier 
993e12c5d1SDavid du Colombier 	chat("walk(fid=%d,name=\"%s\")...", thdr.fid, thdr.name);
1003e12c5d1SDavid du Colombier 	if(!f){
1013e12c5d1SDavid du Colombier 		chat("no xfile...");
1023e12c5d1SDavid du Colombier 		goto error;
1033e12c5d1SDavid du Colombier 	}
1043e12c5d1SDavid du Colombier 	if(!(f->qid.path & CHDIR)){
1053e12c5d1SDavid du Colombier 		chat("qid.path=0x%x...", f->qid.path);
1063e12c5d1SDavid du Colombier 		goto error;
1073e12c5d1SDavid du Colombier 	}
1083e12c5d1SDavid du Colombier 	if(strcmp(thdr.name, ".")==0){
1093e12c5d1SDavid du Colombier 		rhdr.qid = f->qid;
1103e12c5d1SDavid du Colombier 		return;
1113e12c5d1SDavid du Colombier 	}else if(strcmp(thdr.name, "..")==0){
1123e12c5d1SDavid du Colombier 		if(f->qid.path==f->xf->rootqid.path){
1133e12c5d1SDavid du Colombier 			chat("walkup from root...");
114*219b2ee8SDavid du Colombier 			rhdr.qid = f->qid;
115*219b2ee8SDavid du Colombier 			return;
1163e12c5d1SDavid du Colombier 		}
1173e12c5d1SDavid du Colombier 		r = walkup(f, dp);
1183e12c5d1SDavid du Colombier 		if(r < 0)
1193e12c5d1SDavid du Colombier 			goto error;
1203e12c5d1SDavid du Colombier 		memmove(f->ptr, dp, sizeof(Dosptr));
1213e12c5d1SDavid du Colombier 		if(dp->addr == 0)
1223e12c5d1SDavid du Colombier 			f->qid.path = f->xf->rootqid.path;
1233e12c5d1SDavid du Colombier 		else{
1243e12c5d1SDavid du Colombier 			Iosect *p; Dosdir *xd;
1253e12c5d1SDavid du Colombier 			p = getsect(f->xf, dp->addr);
1263e12c5d1SDavid du Colombier 			if(p == 0)
1273e12c5d1SDavid du Colombier 				goto error;
1283e12c5d1SDavid du Colombier 			xd = (Dosdir *)&p->iobuf[dp->offset];
1293e12c5d1SDavid du Colombier 			f->qid.path = CHDIR | GSHORT(xd->start);
1303e12c5d1SDavid du Colombier 			putsect(p);
1313e12c5d1SDavid du Colombier 		}
1323e12c5d1SDavid du Colombier 	}else{
1333e12c5d1SDavid du Colombier 		if(getfile(f) < 0)
1343e12c5d1SDavid du Colombier 			goto error;
1353e12c5d1SDavid du Colombier 		r = searchdir(f, thdr.name, dp, 0);
1363e12c5d1SDavid du Colombier 		putfile(f);
1373e12c5d1SDavid du Colombier 		if(r < 0)
1383e12c5d1SDavid du Colombier 			goto error;
1393e12c5d1SDavid du Colombier 		memmove(f->ptr, dp, sizeof(Dosptr));
1403e12c5d1SDavid du Colombier 		f->qid.path = GSHORT(dp->d->start);
1413e12c5d1SDavid du Colombier 		if(f->qid.path == 0)
1423e12c5d1SDavid du Colombier 			f->qid.path = f->xf->rootqid.path;
1433e12c5d1SDavid du Colombier 		else if(dp->d->attr & DDIR)
1443e12c5d1SDavid du Colombier 			f->qid.path |= CHDIR;
1453e12c5d1SDavid du Colombier 		putfile(f);
1463e12c5d1SDavid du Colombier 	}
1473e12c5d1SDavid du Colombier 	rhdr.qid = f->qid;
1483e12c5d1SDavid du Colombier 	return;
1493e12c5d1SDavid du Colombier error:
1503e12c5d1SDavid du Colombier 	errno = Enonexist;
1513e12c5d1SDavid du Colombier 	return;
1523e12c5d1SDavid du Colombier }
1533e12c5d1SDavid du Colombier void
1543e12c5d1SDavid du Colombier ropen(void)
1553e12c5d1SDavid du Colombier {
1563e12c5d1SDavid du Colombier 	Xfile *f;
1573e12c5d1SDavid du Colombier 	Dosptr *dp;
1583e12c5d1SDavid du Colombier 	int attr, omode=0;
1593e12c5d1SDavid du Colombier 
1603e12c5d1SDavid du Colombier 	chat("open(fid=%d,mode=%d)...", thdr.fid, thdr.mode);
1613e12c5d1SDavid du Colombier 	f = xfile(thdr.fid, Asis);
1623e12c5d1SDavid du Colombier 	if(!f || (f->flags&Omodes)){
1633e12c5d1SDavid du Colombier 		errno = Eio;
1643e12c5d1SDavid du Colombier 		return;
1653e12c5d1SDavid du Colombier 	}
1663e12c5d1SDavid du Colombier 	dp = f->ptr;
1673e12c5d1SDavid du Colombier 	if(dp->paddr && (thdr.mode & ORCLOSE)){
1683e12c5d1SDavid du Colombier 		/*
1693e12c5d1SDavid du Colombier 		 * check on parent directory of file to be deleted
1703e12c5d1SDavid du Colombier 		 */
1713e12c5d1SDavid du Colombier 		Iosect *p = getsect(f->xf, dp->paddr);
1723e12c5d1SDavid du Colombier 		if(p == 0){
1733e12c5d1SDavid du Colombier 			errno = Eio;
1743e12c5d1SDavid du Colombier 			return;
1753e12c5d1SDavid du Colombier 		}
1763e12c5d1SDavid du Colombier 		attr = ((Dosdir *)&p->iobuf[dp->poffset])->attr;
1773e12c5d1SDavid du Colombier 		putsect(p);
1783e12c5d1SDavid du Colombier 		if(attr & DRONLY){
1793e12c5d1SDavid du Colombier 			errno = Eperm;
1803e12c5d1SDavid du Colombier 			return;
1813e12c5d1SDavid du Colombier 		}
1823e12c5d1SDavid du Colombier 		omode |= Orclose;
1833e12c5d1SDavid du Colombier 	}else if(thdr.mode & ORCLOSE)
1843e12c5d1SDavid du Colombier 		omode |= Orclose;
1853e12c5d1SDavid du Colombier 	if(getfile(f) < 0){
1863e12c5d1SDavid du Colombier 		errno = Enonexist;
1873e12c5d1SDavid du Colombier 		return;
1883e12c5d1SDavid du Colombier 	}
1893e12c5d1SDavid du Colombier 	if(dp->addr)
1903e12c5d1SDavid du Colombier 		attr = dp->d->attr;
1913e12c5d1SDavid du Colombier 	else
1923e12c5d1SDavid du Colombier 		attr = DDIR;
1933e12c5d1SDavid du Colombier 	switch(thdr.mode & 7){
1943e12c5d1SDavid du Colombier 	case OREAD:
1953e12c5d1SDavid du Colombier 	case OEXEC:
1963e12c5d1SDavid du Colombier 		omode |= Oread;
1973e12c5d1SDavid du Colombier 		break;
1983e12c5d1SDavid du Colombier 	case ORDWR:
1993e12c5d1SDavid du Colombier 		omode |= Oread;
2003e12c5d1SDavid du Colombier 		/* fall through */
2013e12c5d1SDavid du Colombier 	case OWRITE:
2023e12c5d1SDavid du Colombier 		omode |= Owrite;
2033e12c5d1SDavid du Colombier 		if(attr & DRONLY){
2043e12c5d1SDavid du Colombier 			errno = Eperm;
2053e12c5d1SDavid du Colombier 			goto out;
2063e12c5d1SDavid du Colombier 		}
2073e12c5d1SDavid du Colombier 		break;
2083e12c5d1SDavid du Colombier 	default:
2093e12c5d1SDavid du Colombier 		errno = Eio;
2103e12c5d1SDavid du Colombier 		goto out;
2113e12c5d1SDavid du Colombier 	}
2123e12c5d1SDavid du Colombier 	if(thdr.mode & OTRUNC){
2133e12c5d1SDavid du Colombier 		if(attr & DDIR || attr & DRONLY){
2143e12c5d1SDavid du Colombier 			errno = Eperm;
2153e12c5d1SDavid du Colombier 			goto out;
2163e12c5d1SDavid du Colombier 		}
2173e12c5d1SDavid du Colombier 		if(truncfile(f, 0) < 0){
2183e12c5d1SDavid du Colombier 			errno = Eio;
2193e12c5d1SDavid du Colombier 			goto out;
2203e12c5d1SDavid du Colombier 		}
2213e12c5d1SDavid du Colombier 	}
2223e12c5d1SDavid du Colombier 	f->flags |= omode;
2233e12c5d1SDavid du Colombier 	chat("f->qid=0x%8.8lux...", f->qid.path);
2243e12c5d1SDavid du Colombier 	rhdr.qid = f->qid;
2253e12c5d1SDavid du Colombier out:
2263e12c5d1SDavid du Colombier 	putfile(f);
2273e12c5d1SDavid du Colombier }
2283e12c5d1SDavid du Colombier void
2293e12c5d1SDavid du Colombier rcreate(void)
2303e12c5d1SDavid du Colombier {
2313e12c5d1SDavid du Colombier 	Dosbpb *bp;
2323e12c5d1SDavid du Colombier 	Xfile *f;
2333e12c5d1SDavid du Colombier 	Dosptr *pdp, *ndp;
2343e12c5d1SDavid du Colombier 	Iosect *xp;
2353e12c5d1SDavid du Colombier 	Dosdir *pd, *nd, *xd;
2363e12c5d1SDavid du Colombier 	int attr, omode=0, start;
2373e12c5d1SDavid du Colombier 
2383e12c5d1SDavid du Colombier 	chat("create(fid=%d,name=\"%s\",perm=%uo,mode=%d)...",
2393e12c5d1SDavid du Colombier 		thdr.fid, thdr.name, thdr.perm, thdr.mode);
2403e12c5d1SDavid du Colombier 	f = xfile(thdr.fid, Asis);
2413e12c5d1SDavid du Colombier 	if(!f || (f->flags&Omodes) || getfile(f)<0){
2423e12c5d1SDavid du Colombier 		errno = Eio;
2433e12c5d1SDavid du Colombier 		return;
2443e12c5d1SDavid du Colombier 	}
2453e12c5d1SDavid du Colombier 	ndp = malloc(sizeof(Dosptr));
2463e12c5d1SDavid du Colombier 	pdp = f->ptr;
2473e12c5d1SDavid du Colombier 	pd = pdp->addr ? pdp->d : 0;
2483e12c5d1SDavid du Colombier 	attr = pd ? pd->attr : DDIR;
2493e12c5d1SDavid du Colombier 	if(!(attr & DDIR) || (attr & DRONLY)){
2503e12c5d1SDavid du Colombier badperm:
2513e12c5d1SDavid du Colombier 		if(ndp)
2523e12c5d1SDavid du Colombier 			free(ndp);
2533e12c5d1SDavid du Colombier 		putfile(f);
2543e12c5d1SDavid du Colombier 		errno = Eperm;
2553e12c5d1SDavid du Colombier 		return;
2563e12c5d1SDavid du Colombier 	}
2573e12c5d1SDavid du Colombier 	if(thdr.mode & ORCLOSE)
2583e12c5d1SDavid du Colombier 		omode |= Orclose;
2593e12c5d1SDavid du Colombier 	switch(thdr.mode & 7){
2603e12c5d1SDavid du Colombier 	case OREAD:
2613e12c5d1SDavid du Colombier 	case OEXEC:
2623e12c5d1SDavid du Colombier 		omode |= Oread;
2633e12c5d1SDavid du Colombier 		break;
2643e12c5d1SDavid du Colombier 	case ORDWR:
2653e12c5d1SDavid du Colombier 		omode |= Oread;
2663e12c5d1SDavid du Colombier 		/* fall through */
2673e12c5d1SDavid du Colombier 	case OWRITE:
2683e12c5d1SDavid du Colombier 		omode |= Owrite;
2693e12c5d1SDavid du Colombier 		if(thdr.perm & CHDIR)
2703e12c5d1SDavid du Colombier 			goto badperm;
2713e12c5d1SDavid du Colombier 		break;
2723e12c5d1SDavid du Colombier 	default:
2733e12c5d1SDavid du Colombier 		goto badperm;
2743e12c5d1SDavid du Colombier 	}
2753e12c5d1SDavid du Colombier 	if(strcmp(thdr.name, ".") == 0 || strcmp(thdr.name, "..") == 0)
2763e12c5d1SDavid du Colombier 		goto badperm;
2773e12c5d1SDavid du Colombier 	if(searchdir(f, thdr.name, ndp, 1) < 0)
2783e12c5d1SDavid du Colombier 		goto badperm;
2793e12c5d1SDavid du Colombier 	bp = f->xf->ptr;
2803e12c5d1SDavid du Colombier 	lock(bp);
2813e12c5d1SDavid du Colombier 	start = falloc(f->xf);
2823e12c5d1SDavid du Colombier 	unlock(bp);
2833e12c5d1SDavid du Colombier 	if(start <= 0){
2843e12c5d1SDavid du Colombier 		if(ndp)
2853e12c5d1SDavid du Colombier 			free(ndp);
2863e12c5d1SDavid du Colombier 		putfile(f);
2873e12c5d1SDavid du Colombier 		errno = Eio;
2883e12c5d1SDavid du Colombier 		return;
2893e12c5d1SDavid du Colombier 	}
2903e12c5d1SDavid du Colombier 	/*
2913e12c5d1SDavid du Colombier 	 * now we're committed
2923e12c5d1SDavid du Colombier 	 */
2933e12c5d1SDavid du Colombier 	if(pd){
294*219b2ee8SDavid du Colombier 		puttime(pd, 0);
2953e12c5d1SDavid du Colombier 		pdp->p->flags |= BMOD;
2963e12c5d1SDavid du Colombier 	}
2973e12c5d1SDavid du Colombier 	f->ptr = ndp;
2983e12c5d1SDavid du Colombier 	f->qid.path = start;
2993e12c5d1SDavid du Colombier 	ndp->p = getsect(f->xf, ndp->addr);
3003e12c5d1SDavid du Colombier 	if(ndp->p == 0)
3013e12c5d1SDavid du Colombier 		goto badio;
3023e12c5d1SDavid du Colombier 	ndp->d = (Dosdir *)&ndp->p->iobuf[ndp->offset];
3033e12c5d1SDavid du Colombier 	nd = ndp->d;
3043e12c5d1SDavid du Colombier 	memset(nd, 0, sizeof(Dosdir));
3053e12c5d1SDavid du Colombier 	putname(thdr.name, nd);
3063e12c5d1SDavid du Colombier 	if((thdr.perm & 0222) == 0)
3073e12c5d1SDavid du Colombier 		nd->attr |= DRONLY;
308*219b2ee8SDavid du Colombier 	puttime(nd, 0);
3093e12c5d1SDavid du Colombier 	nd->start[0] = start;
3103e12c5d1SDavid du Colombier 	nd->start[1] = start>>8;
3113e12c5d1SDavid du Colombier 	if(thdr.perm & CHDIR){
3123e12c5d1SDavid du Colombier 		nd->attr |= DDIR;
3133e12c5d1SDavid du Colombier 		f->qid.path |= CHDIR;
3143e12c5d1SDavid du Colombier 		xp = getsect(f->xf, bp->dataaddr+(start-2)*bp->clustsize);
3153e12c5d1SDavid du Colombier 		if(xp == 0)
3163e12c5d1SDavid du Colombier 			goto badio;
3173e12c5d1SDavid du Colombier 		xd = (Dosdir *)&xp->iobuf[0];
3183e12c5d1SDavid du Colombier 		memmove(xd, nd, sizeof(Dosdir));
3193e12c5d1SDavid du Colombier 		memset(xd->name, ' ', sizeof xd->name+sizeof xd->ext);
3203e12c5d1SDavid du Colombier 		xd->name[0] = '.';
3213e12c5d1SDavid du Colombier 		xd = (Dosdir *)&xp->iobuf[sizeof(Dosdir)];
3223e12c5d1SDavid du Colombier 		if(pd)
3233e12c5d1SDavid du Colombier 			memmove(xd, pd, sizeof(Dosdir));
3243e12c5d1SDavid du Colombier 		else{
3253e12c5d1SDavid du Colombier 			memset(xd, 0, sizeof(Dosdir));
326*219b2ee8SDavid du Colombier 			puttime(xd, 0);
3273e12c5d1SDavid du Colombier 			xd->attr = DDIR;
3283e12c5d1SDavid du Colombier 		}
3293e12c5d1SDavid du Colombier 		memset(xd->name, ' ', sizeof xd->name+sizeof xd->ext);
3303e12c5d1SDavid du Colombier 		xd->name[0] = '.';
3313e12c5d1SDavid du Colombier 		xd->name[1] = '.';
3323e12c5d1SDavid du Colombier 		xp->flags |= BMOD;
3333e12c5d1SDavid du Colombier 		putsect(xp);
3343e12c5d1SDavid du Colombier 	}
3353e12c5d1SDavid du Colombier 	ndp->p->flags |= BMOD;
3363e12c5d1SDavid du Colombier 	putfile(f);
3373e12c5d1SDavid du Colombier 	putsect(pdp->p);
3383e12c5d1SDavid du Colombier 	free(pdp);
3393e12c5d1SDavid du Colombier 	f->flags |= omode;
3403e12c5d1SDavid du Colombier 	chat("f->qid=0x%8.8lux...", f->qid.path);
3413e12c5d1SDavid du Colombier 	rhdr.qid = f->qid;
3423e12c5d1SDavid du Colombier 	return;
3433e12c5d1SDavid du Colombier badio:
3443e12c5d1SDavid du Colombier 	if(ndp->p)
3453e12c5d1SDavid du Colombier 		putfile(f);
3463e12c5d1SDavid du Colombier 	putsect(pdp->p);
3473e12c5d1SDavid du Colombier 	free(pdp);
3483e12c5d1SDavid du Colombier 	errno = Eio;
3493e12c5d1SDavid du Colombier }
3503e12c5d1SDavid du Colombier void
3513e12c5d1SDavid du Colombier rread(void)
3523e12c5d1SDavid du Colombier {
3533e12c5d1SDavid du Colombier 	Xfile *f; int r;
3543e12c5d1SDavid du Colombier 
3553e12c5d1SDavid du Colombier 	chat("read(fid=%d,offset=%d,count=%d)...",
3563e12c5d1SDavid du Colombier 		thdr.fid, thdr.offset, thdr.count);
3573e12c5d1SDavid du Colombier 	if (!(f=xfile(thdr.fid, Asis)) || !(f->flags&Oread))
3583e12c5d1SDavid du Colombier 		goto error;
3593e12c5d1SDavid du Colombier 	if(f->qid.path & CHDIR){
360*219b2ee8SDavid du Colombier 		thdr.count = (thdr.count/DIRLEN)*DIRLEN;
361*219b2ee8SDavid du Colombier 		if(thdr.count<DIRLEN || thdr.offset%DIRLEN){
362*219b2ee8SDavid du Colombier 			chat("count=%d,offset=%d,DIRLEN=%d...",
363*219b2ee8SDavid du Colombier 				thdr.count, thdr.offset, DIRLEN);
3643e12c5d1SDavid du Colombier 			goto error;
3653e12c5d1SDavid du Colombier 		}
3663e12c5d1SDavid du Colombier 		if(getfile(f) < 0)
3673e12c5d1SDavid du Colombier 			goto error;
3683e12c5d1SDavid du Colombier 		r = readdir(f, fdata, thdr.offset, thdr.count);
3693e12c5d1SDavid du Colombier 	}else{
3703e12c5d1SDavid du Colombier 		if(getfile(f) < 0)
3713e12c5d1SDavid du Colombier 			goto error;
3723e12c5d1SDavid du Colombier 		r = readfile(f, fdata, thdr.offset, thdr.count);
3733e12c5d1SDavid du Colombier 	}
3743e12c5d1SDavid du Colombier 	putfile(f);
3753e12c5d1SDavid du Colombier 	if(r < 0){
3763e12c5d1SDavid du Colombier error:
3773e12c5d1SDavid du Colombier 		errno = Eio;
3783e12c5d1SDavid du Colombier 	}else{
3793e12c5d1SDavid du Colombier 		rhdr.count = r;
3803e12c5d1SDavid du Colombier 		rhdr.data = fdata;
3813e12c5d1SDavid du Colombier 		chat("rcnt=%d...", r);
3823e12c5d1SDavid du Colombier 	}
3833e12c5d1SDavid du Colombier }
3843e12c5d1SDavid du Colombier void
3853e12c5d1SDavid du Colombier rwrite(void)
3863e12c5d1SDavid du Colombier {
3873e12c5d1SDavid du Colombier 	Xfile *f; int r;
3883e12c5d1SDavid du Colombier 
3893e12c5d1SDavid du Colombier 	chat("write(fid=%d,offset=%d,count=%d)...",
3903e12c5d1SDavid du Colombier 		thdr.fid, thdr.offset, thdr.count);
3913e12c5d1SDavid du Colombier 	if (!(f=xfile(thdr.fid, Asis)) || !(f->flags&Owrite))
3923e12c5d1SDavid du Colombier 		goto error;
3933e12c5d1SDavid du Colombier 	if(getfile(f) < 0)
3943e12c5d1SDavid du Colombier 		goto error;
3953e12c5d1SDavid du Colombier 	r = writefile(f, thdr.data, thdr.offset, thdr.count);
3963e12c5d1SDavid du Colombier 	putfile(f);
3973e12c5d1SDavid du Colombier 	if(r < 0){
3983e12c5d1SDavid du Colombier error:
3993e12c5d1SDavid du Colombier 		errno = Eio;
4003e12c5d1SDavid du Colombier 	}else{
4013e12c5d1SDavid du Colombier 		rhdr.count = r;
4023e12c5d1SDavid du Colombier 		chat("rcnt=%d...", r);
4033e12c5d1SDavid du Colombier 	}
4043e12c5d1SDavid du Colombier }
4053e12c5d1SDavid du Colombier void
4063e12c5d1SDavid du Colombier rclunk(void)
4073e12c5d1SDavid du Colombier {
4083e12c5d1SDavid du Colombier 	chat("clunk(fid=%d)...", thdr.fid);
4093e12c5d1SDavid du Colombier 	xfile(thdr.fid, Clunk);
4103e12c5d1SDavid du Colombier 	sync();
4113e12c5d1SDavid du Colombier }
4123e12c5d1SDavid du Colombier void
4133e12c5d1SDavid du Colombier rremove(void)
4143e12c5d1SDavid du Colombier {
4153e12c5d1SDavid du Colombier 	Xfile *f=xfile(thdr.fid, Asis);
4163e12c5d1SDavid du Colombier 	Dosptr *dp;
4173e12c5d1SDavid du Colombier 	Iosect *parp; Dosdir *pard;
4183e12c5d1SDavid du Colombier 
4193e12c5d1SDavid du Colombier 	chat("remove(fid=%d,name=\"%s\")...", thdr.fid, thdr.name);
4203e12c5d1SDavid du Colombier 	if(!f){
4213e12c5d1SDavid du Colombier 		errno = Eio;
4223e12c5d1SDavid du Colombier 		goto out;
4233e12c5d1SDavid du Colombier 	}
4243e12c5d1SDavid du Colombier 	dp = f->ptr;
4253e12c5d1SDavid du Colombier 	if(!dp->addr){
4263e12c5d1SDavid du Colombier 		chat("root...");
4273e12c5d1SDavid du Colombier 		errno = Eperm;
4283e12c5d1SDavid du Colombier 		goto out;
4293e12c5d1SDavid du Colombier 	}
4303e12c5d1SDavid du Colombier 	/*
4313e12c5d1SDavid du Colombier 	 * check on parent directory of file to be deleted
4323e12c5d1SDavid du Colombier 	 */
4333e12c5d1SDavid du Colombier 	parp = getsect(f->xf, dp->paddr);
4343e12c5d1SDavid du Colombier 	if(parp == 0){
4353e12c5d1SDavid du Colombier 		errno = Eio;
4363e12c5d1SDavid du Colombier 		goto out;
4373e12c5d1SDavid du Colombier 	}
4383e12c5d1SDavid du Colombier 	pard = (Dosdir *)&parp->iobuf[dp->poffset];
4393e12c5d1SDavid du Colombier 	if(dp->paddr && (pard->attr & DRONLY)){
440*219b2ee8SDavid du Colombier 		chat("parent read-only...");
441*219b2ee8SDavid du Colombier 		putsect(parp);
4423e12c5d1SDavid du Colombier 		errno = Eperm;
4433e12c5d1SDavid du Colombier 		goto out;
4443e12c5d1SDavid du Colombier 	}
4453e12c5d1SDavid du Colombier 	if(getfile(f) < 0){
4463e12c5d1SDavid du Colombier 		chat("getfile failed...");
4473e12c5d1SDavid du Colombier 		putsect(parp);
4483e12c5d1SDavid du Colombier 		errno = Eio;
4493e12c5d1SDavid du Colombier 		goto out;
4503e12c5d1SDavid du Colombier 	}
4513e12c5d1SDavid du Colombier 	if((dp->d->attr & DDIR) && emptydir(f) < 0){
4523e12c5d1SDavid du Colombier 		chat("non-empty dir...");
4533e12c5d1SDavid du Colombier 		putfile(f);
4543e12c5d1SDavid du Colombier 		putsect(parp);
4553e12c5d1SDavid du Colombier 		errno = Eperm;
4563e12c5d1SDavid du Colombier 		goto out;
4573e12c5d1SDavid du Colombier 	}
458*219b2ee8SDavid du Colombier 	if(dp->paddr == 0 && (dp->d->attr&DRONLY)){
459*219b2ee8SDavid du Colombier 		chat("read-only file in root directory...");
460*219b2ee8SDavid du Colombier 		putfile(f);
461*219b2ee8SDavid du Colombier 		putsect(parp);
462*219b2ee8SDavid du Colombier 		errno = Eperm;
463*219b2ee8SDavid du Colombier 		goto out;
464*219b2ee8SDavid du Colombier 	}
4653e12c5d1SDavid du Colombier 	if(dp->paddr){
466*219b2ee8SDavid du Colombier 		puttime(pard, 0);
4673e12c5d1SDavid du Colombier 		parp->flags |= BMOD;
4683e12c5d1SDavid du Colombier 	}
4693e12c5d1SDavid du Colombier 	putsect(parp);
4703e12c5d1SDavid du Colombier 	if(truncfile(f, 1) < 0)
4713e12c5d1SDavid du Colombier 		errno = Eio;
4723e12c5d1SDavid du Colombier 	dp->d->name[0] = 0xe5;
4733e12c5d1SDavid du Colombier 	dp->p->flags |= BMOD;
4743e12c5d1SDavid du Colombier 	putfile(f);
4753e12c5d1SDavid du Colombier out:
4763e12c5d1SDavid du Colombier 	xfile(thdr.fid, Clunk);
4773e12c5d1SDavid du Colombier 	sync();
4783e12c5d1SDavid du Colombier }
4793e12c5d1SDavid du Colombier void
4803e12c5d1SDavid du Colombier rstat(void)
4813e12c5d1SDavid du Colombier {
4823e12c5d1SDavid du Colombier 	Dir dir;
4833e12c5d1SDavid du Colombier 	Xfile *f=xfile(thdr.fid, Asis);
4843e12c5d1SDavid du Colombier 	Dosptr *dp = f->ptr;
4853e12c5d1SDavid du Colombier 
4863e12c5d1SDavid du Colombier 	chat("stat(fid=%d)...", thdr.fid);
4873e12c5d1SDavid du Colombier 	if(!f || getfile(f)< 0)
4883e12c5d1SDavid du Colombier 		errno = Eio;
4893e12c5d1SDavid du Colombier 	else{
4903e12c5d1SDavid du Colombier 		getdir(&dir, dp->addr ? dp->d : 0);
4913e12c5d1SDavid du Colombier 		convD2M(&dir, rhdr.stat);
4923e12c5d1SDavid du Colombier 		putfile(f);
4933e12c5d1SDavid du Colombier 	}
4943e12c5d1SDavid du Colombier }
495*219b2ee8SDavid du Colombier 
496*219b2ee8SDavid du Colombier static char isfrog[256]={
497*219b2ee8SDavid du Colombier 	/*NUL*/	1, 1, 1, 1, 1, 1, 1, 1,
498*219b2ee8SDavid du Colombier 	/*BKS*/	1, 1, 1, 1, 1, 1, 1, 1,
499*219b2ee8SDavid du Colombier 	/*DLE*/	1, 1, 1, 1, 1, 1, 1, 1,
500*219b2ee8SDavid du Colombier 	/*CAN*/	1, 1, 1, 1, 1, 1, 1, 1,
501*219b2ee8SDavid du Colombier 	[' ']	1,
502*219b2ee8SDavid du Colombier 	['/']	1,
503*219b2ee8SDavid du Colombier 	[0x7f]	1,
504*219b2ee8SDavid du Colombier };
505*219b2ee8SDavid du Colombier 
506*219b2ee8SDavid du Colombier static int
507*219b2ee8SDavid du Colombier nameok(char *elem)
508*219b2ee8SDavid du Colombier {
509*219b2ee8SDavid du Colombier 	char *eelem;
510*219b2ee8SDavid du Colombier 
511*219b2ee8SDavid du Colombier 	eelem = elem+NAMELEN;
512*219b2ee8SDavid du Colombier 	while(*elem){
513*219b2ee8SDavid du Colombier 		if(isfrog[*(uchar*)elem])
514*219b2ee8SDavid du Colombier 			return -1;
515*219b2ee8SDavid du Colombier 		elem++;
516*219b2ee8SDavid du Colombier 		if(elem >= eelem)
517*219b2ee8SDavid du Colombier 			return -1;
518*219b2ee8SDavid du Colombier 	}
519*219b2ee8SDavid du Colombier 	return 0;
520*219b2ee8SDavid du Colombier }
521*219b2ee8SDavid du Colombier 
5223e12c5d1SDavid du Colombier void
5233e12c5d1SDavid du Colombier rwstat(void)
5243e12c5d1SDavid du Colombier {
5253e12c5d1SDavid du Colombier 	errno = Eperm;
5263e12c5d1SDavid du Colombier }
527