13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
3219b2ee8SDavid du Colombier #include <auth.h>
43e12c5d1SDavid du Colombier #include <fcall.h>
53e12c5d1SDavid du Colombier #include "iotrack.h"
63e12c5d1SDavid du Colombier #include "dat.h"
79a747e4fSDavid du Colombier #include "dosfs.h"
83e12c5d1SDavid du Colombier #include "fns.h"
93e12c5d1SDavid du Colombier
103e12c5d1SDavid du Colombier void
rversion(void)119a747e4fSDavid du Colombier rversion(void)
123e12c5d1SDavid du Colombier {
139a747e4fSDavid du Colombier if(req->msize > Maxiosize)
149a747e4fSDavid du Colombier rep->msize = Maxiosize;
159a747e4fSDavid du Colombier else
169a747e4fSDavid du Colombier rep->msize = req->msize;
179a747e4fSDavid du Colombier rep->version = "9P2000";
183e12c5d1SDavid du Colombier }
197dd7cddfSDavid du Colombier
203e12c5d1SDavid du Colombier void
rauth(void)219a747e4fSDavid du Colombier rauth(void)
223e12c5d1SDavid du Colombier {
239a747e4fSDavid du Colombier errno = Enoauth;
243e12c5d1SDavid du Colombier }
257dd7cddfSDavid du Colombier
263e12c5d1SDavid du Colombier void
rflush(void)273e12c5d1SDavid du Colombier rflush(void)
283e12c5d1SDavid du Colombier {
293e12c5d1SDavid du Colombier }
307dd7cddfSDavid du Colombier
313e12c5d1SDavid du Colombier void
rattach(void)323e12c5d1SDavid du Colombier rattach(void)
333e12c5d1SDavid du Colombier {
34219b2ee8SDavid du Colombier Xfs *xf;
35219b2ee8SDavid du Colombier Xfile *root;
363e12c5d1SDavid du Colombier Dosptr *dp;
373e12c5d1SDavid du Colombier
389a747e4fSDavid du Colombier root = xfile(req->fid, Clean);
393e12c5d1SDavid du Colombier if(!root){
403e12c5d1SDavid du Colombier errno = Enomem;
413e12c5d1SDavid du Colombier goto error;
423e12c5d1SDavid du Colombier }
439a747e4fSDavid du Colombier root->xf = xf = getxfs(req->uname, req->aname);
443e12c5d1SDavid du Colombier if(!xf)
453e12c5d1SDavid du Colombier goto error;
463e12c5d1SDavid du Colombier if(xf->fmt == 0 && dosfs(xf) < 0){
473e12c5d1SDavid du Colombier errno = Eformat;
483e12c5d1SDavid du Colombier goto error;
493e12c5d1SDavid du Colombier }
509a747e4fSDavid du Colombier root->qid.type = QTDIR;
519a747e4fSDavid du Colombier root->qid.path = 0;
523e12c5d1SDavid du Colombier root->qid.vers = 0;
533e12c5d1SDavid du Colombier root->xf->rootqid = root->qid;
543e12c5d1SDavid du Colombier dp = malloc(sizeof(Dosptr));
557dd7cddfSDavid du Colombier if(dp == nil){
567dd7cddfSDavid du Colombier errno = Enomem;
577dd7cddfSDavid du Colombier goto error;
587dd7cddfSDavid du Colombier }
593e12c5d1SDavid du Colombier root->ptr = dp;
607dd7cddfSDavid du Colombier rootfile(root);
619a747e4fSDavid du Colombier rep->qid = root->qid;
623e12c5d1SDavid du Colombier return;
633e12c5d1SDavid du Colombier error:
643e12c5d1SDavid du Colombier if(root)
659a747e4fSDavid du Colombier xfile(req->fid, Clunk);
663e12c5d1SDavid du Colombier }
677dd7cddfSDavid du Colombier
689a747e4fSDavid du Colombier Xfile*
doclone(Xfile * of,int newfid)699a747e4fSDavid du Colombier doclone(Xfile *of, int newfid)
703e12c5d1SDavid du Colombier {
719a747e4fSDavid du Colombier Xfile *nf, *next;
727dd7cddfSDavid du Colombier Dosptr *dp;
733e12c5d1SDavid du Colombier
749a747e4fSDavid du Colombier nf = xfile(newfid, Clean);
757dd7cddfSDavid du Colombier if(!nf){
763e12c5d1SDavid du Colombier errno = Enomem;
779a747e4fSDavid du Colombier return nil;
787dd7cddfSDavid du Colombier }
797dd7cddfSDavid du Colombier dp = malloc(sizeof(Dosptr));
807dd7cddfSDavid du Colombier if(dp == nil){
817dd7cddfSDavid du Colombier errno = Enomem;
829a747e4fSDavid du Colombier return nil;
837dd7cddfSDavid du Colombier }
847dd7cddfSDavid du Colombier next = nf->next;
853e12c5d1SDavid du Colombier *nf = *of;
863e12c5d1SDavid du Colombier nf->next = next;
879a747e4fSDavid du Colombier nf->fid = req->newfid;
883e12c5d1SDavid du Colombier nf->ptr = dp;
893e12c5d1SDavid du Colombier refxfs(nf->xf, 1);
903e12c5d1SDavid du Colombier memmove(dp, of->ptr, sizeof(Dosptr));
917dd7cddfSDavid du Colombier dp->p = nil;
927dd7cddfSDavid du Colombier dp->d = nil;
939a747e4fSDavid du Colombier return nf;
943e12c5d1SDavid du Colombier }
957dd7cddfSDavid du Colombier
963e12c5d1SDavid du Colombier void
rwalk(void)973e12c5d1SDavid du Colombier rwalk(void)
983e12c5d1SDavid du Colombier {
999a747e4fSDavid du Colombier Xfile *f, *nf;
1009a747e4fSDavid du Colombier Dosptr dp[1], savedp[1];
1019a747e4fSDavid du Colombier int r, longtype;
1029a747e4fSDavid du Colombier Qid saveqid;
1033e12c5d1SDavid du Colombier
1049a747e4fSDavid du Colombier rep->nwqid = 0;
1059a747e4fSDavid du Colombier nf = nil;
1069a747e4fSDavid du Colombier f = xfile(req->fid, Asis);
1079a747e4fSDavid du Colombier if(f == nil){
1089a747e4fSDavid du Colombier chat("\tno xfile\n");
109*3ff48bf5SDavid du Colombier goto error2;
1103e12c5d1SDavid du Colombier }
1119a747e4fSDavid du Colombier if(req->fid != req->newfid){
1129a747e4fSDavid du Colombier nf = doclone(f, req->newfid);
1139a747e4fSDavid du Colombier if(nf == nil){
1149a747e4fSDavid du Colombier chat("\tclone failed\n");
115*3ff48bf5SDavid du Colombier goto error2;
1163e12c5d1SDavid du Colombier }
1179a747e4fSDavid du Colombier f = nf;
1183e12c5d1SDavid du Colombier }
1199a747e4fSDavid du Colombier
1209a747e4fSDavid du Colombier saveqid = f->qid;
1219a747e4fSDavid du Colombier memmove(savedp, f->ptr, sizeof(Dosptr));
1229a747e4fSDavid du Colombier for(; rep->nwqid < req->nwname && rep->nwqid < MAXWELEM; rep->nwqid++){
1239a747e4fSDavid du Colombier chat("\twalking %s\n", req->wname[rep->nwqid]);
1249a747e4fSDavid du Colombier if(!(f->qid.type & QTDIR)){
1259a747e4fSDavid du Colombier chat("\tnot dir: type=%#x\n", f->qid.type);
1269a747e4fSDavid du Colombier goto error;
1279a747e4fSDavid du Colombier }
1289a747e4fSDavid du Colombier if(strcmp(req->wname[rep->nwqid], ".") == 0){
1299a747e4fSDavid du Colombier ;
1309a747e4fSDavid du Colombier }else if(strcmp(req->wname[rep->nwqid], "..") == 0){
1319a747e4fSDavid du Colombier if(f->qid.path != f->xf->rootqid.path){
1323e12c5d1SDavid du Colombier r = walkup(f, dp);
1333e12c5d1SDavid du Colombier if(r < 0)
1343e12c5d1SDavid du Colombier goto error;
1353e12c5d1SDavid du Colombier memmove(f->ptr, dp, sizeof(Dosptr));
1367dd7cddfSDavid du Colombier if(isroot(dp->addr))
1373e12c5d1SDavid du Colombier f->qid.path = f->xf->rootqid.path;
1387dd7cddfSDavid du Colombier else
1399a747e4fSDavid du Colombier f->qid.path = QIDPATH(dp);
1409a747e4fSDavid du Colombier }
1413e12c5d1SDavid du Colombier }else{
1429a747e4fSDavid du Colombier fixname(req->wname[rep->nwqid]);
1439a747e4fSDavid du Colombier longtype = classifyname(req->wname[rep->nwqid]);
1449a747e4fSDavid du Colombier if(longtype==Invalid || getfile(f) < 0)
1453e12c5d1SDavid du Colombier goto error;
1467dd7cddfSDavid du Colombier
1477dd7cddfSDavid du Colombier /*
1487dd7cddfSDavid du Colombier * always do a search for the long name,
1497dd7cddfSDavid du Colombier * because it could be filed as such
1507dd7cddfSDavid du Colombier */
1519a747e4fSDavid du Colombier r = searchdir(f, req->wname[rep->nwqid], dp, 0, longtype);
1523e12c5d1SDavid du Colombier putfile(f);
1533e12c5d1SDavid du Colombier if(r < 0)
1543e12c5d1SDavid du Colombier goto error;
1553e12c5d1SDavid du Colombier memmove(f->ptr, dp, sizeof(Dosptr));
1567dd7cddfSDavid du Colombier f->qid.path = QIDPATH(dp);
1579a747e4fSDavid du Colombier f->qid.type = QTFILE;
1587dd7cddfSDavid du Colombier if(isroot(dp->addr))
1593e12c5d1SDavid du Colombier f->qid.path = f->xf->rootqid.path;
1603e12c5d1SDavid du Colombier else if(dp->d->attr & DDIR)
1619a747e4fSDavid du Colombier f->qid.type = QTDIR;
1629a747e4fSDavid du Colombier else if(dp->d->attr & DSYSTEM){
1639a747e4fSDavid du Colombier f->qid.type |= QTEXCL;
1649a747e4fSDavid du Colombier if(iscontig(f->xf, dp->d))
1659a747e4fSDavid du Colombier f->qid.type |= QTAPPEND;
1669a747e4fSDavid du Colombier }
1679a747e4fSDavid du Colombier //ZZZ maybe use other bits than qtexcl & qtapppend
1683e12c5d1SDavid du Colombier putfile(f);
1693e12c5d1SDavid du Colombier }
1709a747e4fSDavid du Colombier rep->wqid[rep->nwqid] = f->qid;
1719a747e4fSDavid du Colombier }
1723e12c5d1SDavid du Colombier return;
1733e12c5d1SDavid du Colombier error:
1749a747e4fSDavid du Colombier f->qid = saveqid;
1759a747e4fSDavid du Colombier memmove(f->ptr, savedp, sizeof(Dosptr));
1769a747e4fSDavid du Colombier if(nf != nil)
1779a747e4fSDavid du Colombier xfile(req->newfid, Clunk);
178*3ff48bf5SDavid du Colombier error2:
1799a747e4fSDavid du Colombier if(!errno && !rep->nwqid)
1803e12c5d1SDavid du Colombier errno = Enonexist;
1813e12c5d1SDavid du Colombier }
1827dd7cddfSDavid du Colombier
1833e12c5d1SDavid du Colombier void
ropen(void)1843e12c5d1SDavid du Colombier ropen(void)
1853e12c5d1SDavid du Colombier {
1863e12c5d1SDavid du Colombier Xfile *f;
1879a747e4fSDavid du Colombier Iosect *p;
1883e12c5d1SDavid du Colombier Dosptr *dp;
1897dd7cddfSDavid du Colombier int attr, omode;
1903e12c5d1SDavid du Colombier
1919a747e4fSDavid du Colombier f = xfile(req->fid, Asis);
1923e12c5d1SDavid du Colombier if(!f || (f->flags&Omodes)){
1933e12c5d1SDavid du Colombier errno = Eio;
1943e12c5d1SDavid du Colombier return;
1953e12c5d1SDavid du Colombier }
1963e12c5d1SDavid du Colombier dp = f->ptr;
1977dd7cddfSDavid du Colombier omode = 0;
1989a747e4fSDavid du Colombier if(!isroot(dp->paddr) && (req->mode & ORCLOSE)){
1993e12c5d1SDavid du Colombier /*
2003e12c5d1SDavid du Colombier * check on parent directory of file to be deleted
2013e12c5d1SDavid du Colombier */
2029a747e4fSDavid du Colombier p = getsect(f->xf, dp->paddr);
2039a747e4fSDavid du Colombier if(p == nil){
2043e12c5d1SDavid du Colombier errno = Eio;
2053e12c5d1SDavid du Colombier return;
2063e12c5d1SDavid du Colombier }
2073e12c5d1SDavid du Colombier attr = ((Dosdir *)&p->iobuf[dp->poffset])->attr;
2083e12c5d1SDavid du Colombier putsect(p);
2093e12c5d1SDavid du Colombier if(attr & DRONLY){
2103e12c5d1SDavid du Colombier errno = Eperm;
2113e12c5d1SDavid du Colombier return;
2123e12c5d1SDavid du Colombier }
2133e12c5d1SDavid du Colombier omode |= Orclose;
2149a747e4fSDavid du Colombier }else if(req->mode & ORCLOSE)
2153e12c5d1SDavid du Colombier omode |= Orclose;
2163e12c5d1SDavid du Colombier if(getfile(f) < 0){
2173e12c5d1SDavid du Colombier errno = Enonexist;
2183e12c5d1SDavid du Colombier return;
2193e12c5d1SDavid du Colombier }
2207dd7cddfSDavid du Colombier if(!isroot(dp->addr))
2213e12c5d1SDavid du Colombier attr = dp->d->attr;
2223e12c5d1SDavid du Colombier else
2233e12c5d1SDavid du Colombier attr = DDIR;
2249a747e4fSDavid du Colombier switch(req->mode & 7){
2253e12c5d1SDavid du Colombier case OREAD:
2263e12c5d1SDavid du Colombier case OEXEC:
2273e12c5d1SDavid du Colombier omode |= Oread;
2283e12c5d1SDavid du Colombier break;
2293e12c5d1SDavid du Colombier case ORDWR:
2303e12c5d1SDavid du Colombier omode |= Oread;
2313e12c5d1SDavid du Colombier /* fall through */
2323e12c5d1SDavid du Colombier case OWRITE:
2333e12c5d1SDavid du Colombier omode |= Owrite;
2343e12c5d1SDavid du Colombier if(attr & DRONLY){
2353e12c5d1SDavid du Colombier errno = Eperm;
2363e12c5d1SDavid du Colombier goto out;
2373e12c5d1SDavid du Colombier }
2383e12c5d1SDavid du Colombier break;
2393e12c5d1SDavid du Colombier default:
2403e12c5d1SDavid du Colombier errno = Eio;
2413e12c5d1SDavid du Colombier goto out;
2423e12c5d1SDavid du Colombier }
2439a747e4fSDavid du Colombier if(req->mode & OTRUNC){
2443e12c5d1SDavid du Colombier if(attr & DDIR || attr & DRONLY){
2453e12c5d1SDavid du Colombier errno = Eperm;
2463e12c5d1SDavid du Colombier goto out;
2473e12c5d1SDavid du Colombier }
2489a747e4fSDavid du Colombier if(truncfile(f, 0) < 0){
2493e12c5d1SDavid du Colombier errno = Eio;
2503e12c5d1SDavid du Colombier goto out;
2513e12c5d1SDavid du Colombier }
2523e12c5d1SDavid du Colombier }
2533e12c5d1SDavid du Colombier f->flags |= omode;
2549a747e4fSDavid du Colombier rep->qid = f->qid;
2559a747e4fSDavid du Colombier rep->iounit = 0;
2563e12c5d1SDavid du Colombier out:
2573e12c5d1SDavid du Colombier putfile(f);
2583e12c5d1SDavid du Colombier }
2597dd7cddfSDavid du Colombier
2607dd7cddfSDavid du Colombier static int
mk8dot3name(Xfile * f,Dosptr * ndp,char * name,char * sname)2619a747e4fSDavid du Colombier mk8dot3name(Xfile *f, Dosptr *ndp, char *name, char *sname)
2627dd7cddfSDavid du Colombier {
2637dd7cddfSDavid du Colombier Dosptr tmpdp;
2649a747e4fSDavid du Colombier int i, longtype;
2657dd7cddfSDavid du Colombier
2667dd7cddfSDavid du Colombier if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
2679a747e4fSDavid du Colombier return Invalid;
2687dd7cddfSDavid du Colombier
2697dd7cddfSDavid du Colombier /*
2707dd7cddfSDavid du Colombier * always do a search for the long name,
2717dd7cddfSDavid du Colombier * because it could be filed as such
2727dd7cddfSDavid du Colombier */
2739a747e4fSDavid du Colombier fixname(name);
2749a747e4fSDavid du Colombier longtype = classifyname(name);
2759a747e4fSDavid du Colombier if(longtype==Invalid || searchdir(f, name, ndp, 1, longtype) < 0)
2769a747e4fSDavid du Colombier return Invalid;
2777dd7cddfSDavid du Colombier
2789a747e4fSDavid du Colombier if(longtype==Short)
2799a747e4fSDavid du Colombier return Short;
2809a747e4fSDavid du Colombier
2819a747e4fSDavid du Colombier if(longtype==ShortLower){
2829a747e4fSDavid du Colombier /*
2839a747e4fSDavid du Colombier * alias is the upper-case version, which we
2849a747e4fSDavid du Colombier * already know does not exist.
2859a747e4fSDavid du Colombier */
2869a747e4fSDavid du Colombier strcpy(sname, name);
2879a747e4fSDavid du Colombier for(i=0; sname[i]; i++)
2889a747e4fSDavid du Colombier if('a' <= sname[i] && sname[i] <= 'z')
2899a747e4fSDavid du Colombier sname[i] += 'A'-'a';
2909a747e4fSDavid du Colombier return ShortLower;
2919a747e4fSDavid du Colombier }
2927dd7cddfSDavid du Colombier
2937dd7cddfSDavid du Colombier /*
2947dd7cddfSDavid du Colombier * find alias for the long name
2957dd7cddfSDavid du Colombier */
2967dd7cddfSDavid du Colombier for(i=1;; i++){
2977dd7cddfSDavid du Colombier mkalias(name, sname, i);
2987dd7cddfSDavid du Colombier if(searchdir(f, sname, &tmpdp, 0, 0) < 0)
2999a747e4fSDavid du Colombier return Long;
3007dd7cddfSDavid du Colombier putsect(tmpdp.p);
3017dd7cddfSDavid du Colombier }
3027dd7cddfSDavid du Colombier }
3037dd7cddfSDavid du Colombier
3047dd7cddfSDavid du Colombier /*
3057dd7cddfSDavid du Colombier * fill in a directory entry for a new file
3067dd7cddfSDavid du Colombier */
3077dd7cddfSDavid du Colombier static int
mkdentry(Xfs * xf,Dosptr * ndp,char * name,char * sname,int longtype,int nattr,long start,long length)3089a747e4fSDavid du Colombier mkdentry(Xfs *xf, Dosptr *ndp, char *name, char *sname, int longtype, int nattr, long start, long length)
3097dd7cddfSDavid du Colombier {
3107dd7cddfSDavid du Colombier Dosdir *nd;
3117dd7cddfSDavid du Colombier
3127dd7cddfSDavid du Colombier /*
3137dd7cddfSDavid du Colombier * fill in the entry
3147dd7cddfSDavid du Colombier */
3157dd7cddfSDavid du Colombier ndp->p = getsect(xf, ndp->addr);
3167dd7cddfSDavid du Colombier if(ndp->p == nil
3179a747e4fSDavid du Colombier || longtype!=Short && putlongname(xf, ndp, name, sname) < 0){
3187dd7cddfSDavid du Colombier errno = Eio;
3197dd7cddfSDavid du Colombier return -1;
3207dd7cddfSDavid du Colombier }
3217dd7cddfSDavid du Colombier
3227dd7cddfSDavid du Colombier ndp->d = (Dosdir *)&ndp->p->iobuf[ndp->offset];
3237dd7cddfSDavid du Colombier nd = ndp->d;
3247dd7cddfSDavid du Colombier memset(nd, 0, DOSDIRSIZE);
3257dd7cddfSDavid du Colombier
3269a747e4fSDavid du Colombier if(longtype!=Short)
3277dd7cddfSDavid du Colombier name = sname;
3287dd7cddfSDavid du Colombier putname(name, nd);
3297dd7cddfSDavid du Colombier
3307dd7cddfSDavid du Colombier nd->attr = nattr;
3317dd7cddfSDavid du Colombier puttime(nd, 0);
3327dd7cddfSDavid du Colombier putstart(xf, nd, start);
3337dd7cddfSDavid du Colombier nd->length[0] = length;
3347dd7cddfSDavid du Colombier nd->length[1] = length>>8;
3357dd7cddfSDavid du Colombier nd->length[2] = length>>16;
3367dd7cddfSDavid du Colombier nd->length[3] = length>>24;
3377dd7cddfSDavid du Colombier
3387dd7cddfSDavid du Colombier ndp->p->flags |= BMOD;
3397dd7cddfSDavid du Colombier
3407dd7cddfSDavid du Colombier return 0;
3417dd7cddfSDavid du Colombier }
3427dd7cddfSDavid du Colombier
3433e12c5d1SDavid du Colombier void
rcreate(void)3443e12c5d1SDavid du Colombier rcreate(void)
3453e12c5d1SDavid du Colombier {
3463e12c5d1SDavid du Colombier Dosbpb *bp;
3473e12c5d1SDavid du Colombier Xfile *f;
3483e12c5d1SDavid du Colombier Dosptr *pdp, *ndp;
3493e12c5d1SDavid du Colombier Iosect *xp;
3507dd7cddfSDavid du Colombier Dosdir *pd, *xd;
3517dd7cddfSDavid du Colombier char sname[13];
3527dd7cddfSDavid du Colombier long start;
3539a747e4fSDavid du Colombier int longtype, attr, omode, nattr;
3543e12c5d1SDavid du Colombier
3559a747e4fSDavid du Colombier f = xfile(req->fid, Asis);
3563e12c5d1SDavid du Colombier if(!f || (f->flags&Omodes) || getfile(f)<0){
3573e12c5d1SDavid du Colombier errno = Eio;
3583e12c5d1SDavid du Colombier return;
3593e12c5d1SDavid du Colombier }
3603e12c5d1SDavid du Colombier pdp = f->ptr;
3617dd7cddfSDavid du Colombier pd = pdp->d;
3627dd7cddfSDavid du Colombier /*
3637dd7cddfSDavid du Colombier * perm check
3647dd7cddfSDavid du Colombier */
3657dd7cddfSDavid du Colombier if(isroot(pdp->addr) && pd != nil)
3667dd7cddfSDavid du Colombier panic("root pd != nil");
3673e12c5d1SDavid du Colombier attr = pd ? pd->attr : DDIR;
3683e12c5d1SDavid du Colombier if(!(attr & DDIR) || (attr & DRONLY)){
3693e12c5d1SDavid du Colombier badperm:
3703e12c5d1SDavid du Colombier putfile(f);
3713e12c5d1SDavid du Colombier errno = Eperm;
3723e12c5d1SDavid du Colombier return;
3733e12c5d1SDavid du Colombier }
3747dd7cddfSDavid du Colombier omode = 0;
3759a747e4fSDavid du Colombier if(req->mode & ORCLOSE)
3763e12c5d1SDavid du Colombier omode |= Orclose;
3779a747e4fSDavid du Colombier switch(req->mode & 7){
3783e12c5d1SDavid du Colombier case OREAD:
3793e12c5d1SDavid du Colombier case OEXEC:
3803e12c5d1SDavid du Colombier omode |= Oread;
3813e12c5d1SDavid du Colombier break;
3823e12c5d1SDavid du Colombier case ORDWR:
3833e12c5d1SDavid du Colombier omode |= Oread;
3843e12c5d1SDavid du Colombier /* fall through */
3853e12c5d1SDavid du Colombier case OWRITE:
3863e12c5d1SDavid du Colombier omode |= Owrite;
3879a747e4fSDavid du Colombier if(req->perm & DMDIR)
3883e12c5d1SDavid du Colombier goto badperm;
3893e12c5d1SDavid du Colombier break;
3903e12c5d1SDavid du Colombier default:
3913e12c5d1SDavid du Colombier goto badperm;
3923e12c5d1SDavid du Colombier }
3937dd7cddfSDavid du Colombier
3947dd7cddfSDavid du Colombier /*
3957dd7cddfSDavid du Colombier * check the name, find the slot for the dentry,
3967dd7cddfSDavid du Colombier * and find a good alias for a long name
3977dd7cddfSDavid du Colombier */
3987dd7cddfSDavid du Colombier ndp = malloc(sizeof(Dosptr));
3997dd7cddfSDavid du Colombier if(ndp == nil){
4007dd7cddfSDavid du Colombier putfile(f);
4017dd7cddfSDavid du Colombier errno = Enomem;
4027dd7cddfSDavid du Colombier return;
4037dd7cddfSDavid du Colombier }
4049a747e4fSDavid du Colombier longtype = mk8dot3name(f, ndp, req->name, sname);
4059a747e4fSDavid du Colombier chat("rcreate %s longtype %d...\n", req->name, longtype);
4069a747e4fSDavid du Colombier if(longtype == Invalid){
4077dd7cddfSDavid du Colombier free(ndp);
4083e12c5d1SDavid du Colombier goto badperm;
4097dd7cddfSDavid du Colombier }
4107dd7cddfSDavid du Colombier
4117dd7cddfSDavid du Colombier /*
4127dd7cddfSDavid du Colombier * allocate first cluster, if making directory
4137dd7cddfSDavid du Colombier */
4147dd7cddfSDavid du Colombier start = 0;
4157dd7cddfSDavid du Colombier bp = nil;
4169a747e4fSDavid du Colombier if(req->perm & DMDIR){
4173e12c5d1SDavid du Colombier bp = f->xf->ptr;
4187dd7cddfSDavid du Colombier mlock(bp);
4193e12c5d1SDavid du Colombier start = falloc(f->xf);
4207dd7cddfSDavid du Colombier unmlock(bp);
4213e12c5d1SDavid du Colombier if(start <= 0){
4223e12c5d1SDavid du Colombier free(ndp);
4233e12c5d1SDavid du Colombier putfile(f);
4243e12c5d1SDavid du Colombier errno = Eio;
4253e12c5d1SDavid du Colombier return;
4263e12c5d1SDavid du Colombier }
4277dd7cddfSDavid du Colombier }
4287dd7cddfSDavid du Colombier
4293e12c5d1SDavid du Colombier /*
4307dd7cddfSDavid du Colombier * make the entry
4313e12c5d1SDavid du Colombier */
4327dd7cddfSDavid du Colombier nattr = 0;
4339a747e4fSDavid du Colombier if((req->perm & 0222) == 0)
4347dd7cddfSDavid du Colombier nattr |= DRONLY;
4359a747e4fSDavid du Colombier if(req->perm & DMDIR)
4367dd7cddfSDavid du Colombier nattr |= DDIR;
4377dd7cddfSDavid du Colombier
4389a747e4fSDavid du Colombier if(mkdentry(f->xf, ndp, req->name, sname, longtype, nattr, start, 0) < 0){
4397dd7cddfSDavid du Colombier if(ndp->p != nil)
4407dd7cddfSDavid du Colombier putsect(ndp->p);
4417dd7cddfSDavid du Colombier free(ndp);
4427dd7cddfSDavid du Colombier if(start > 0)
4437dd7cddfSDavid du Colombier ffree(f->xf, start);
4447dd7cddfSDavid du Colombier putfile(f);
4457dd7cddfSDavid du Colombier return;
4467dd7cddfSDavid du Colombier }
4477dd7cddfSDavid du Colombier
4487dd7cddfSDavid du Colombier if(pd != nil){
449219b2ee8SDavid du Colombier puttime(pd, 0);
4503e12c5d1SDavid du Colombier pdp->p->flags |= BMOD;
4513e12c5d1SDavid du Colombier }
4527dd7cddfSDavid du Colombier
4537dd7cddfSDavid du Colombier /*
4547dd7cddfSDavid du Colombier * fix up the fid
4557dd7cddfSDavid du Colombier */
4563e12c5d1SDavid du Colombier f->ptr = ndp;
4579a747e4fSDavid du Colombier f->qid.type = QTFILE;
4587dd7cddfSDavid du Colombier f->qid.path = QIDPATH(ndp);
4597dd7cddfSDavid du Colombier
4609a747e4fSDavid du Colombier //ZZZ set type for excl, append?
4619a747e4fSDavid du Colombier if(req->perm & DMDIR){
4629a747e4fSDavid du Colombier f->qid.type = QTDIR;
4637dd7cddfSDavid du Colombier xp = getsect(f->xf, clust2sect(bp, start));
4647dd7cddfSDavid du Colombier if(xp == nil){
4657dd7cddfSDavid du Colombier errno = Eio;
4663e12c5d1SDavid du Colombier goto badio;
4677dd7cddfSDavid du Colombier }
4683e12c5d1SDavid du Colombier xd = (Dosdir *)&xp->iobuf[0];
4697dd7cddfSDavid du Colombier memmove(xd, ndp->d, DOSDIRSIZE);
4703e12c5d1SDavid du Colombier memset(xd->name, ' ', sizeof xd->name+sizeof xd->ext);
4713e12c5d1SDavid du Colombier xd->name[0] = '.';
4727dd7cddfSDavid du Colombier xd = (Dosdir *)&xp->iobuf[DOSDIRSIZE];
4733e12c5d1SDavid du Colombier if(pd)
4747dd7cddfSDavid du Colombier memmove(xd, pd, DOSDIRSIZE);
4753e12c5d1SDavid du Colombier else{
4767dd7cddfSDavid du Colombier memset(xd, 0, DOSDIRSIZE);
477219b2ee8SDavid du Colombier puttime(xd, 0);
4783e12c5d1SDavid du Colombier xd->attr = DDIR;
4793e12c5d1SDavid du Colombier }
4803e12c5d1SDavid du Colombier memset(xd->name, ' ', sizeof xd->name+sizeof xd->ext);
4813e12c5d1SDavid du Colombier xd->name[0] = '.';
4823e12c5d1SDavid du Colombier xd->name[1] = '.';
4833e12c5d1SDavid du Colombier xp->flags |= BMOD;
4843e12c5d1SDavid du Colombier putsect(xp);
4853e12c5d1SDavid du Colombier }
4867dd7cddfSDavid du Colombier
4873e12c5d1SDavid du Colombier f->flags |= omode;
4889a747e4fSDavid du Colombier rep->qid = f->qid;
4899a747e4fSDavid du Colombier rep->iounit = 0;
4907dd7cddfSDavid du Colombier
4913e12c5d1SDavid du Colombier badio:
4923e12c5d1SDavid du Colombier putfile(f);
4933e12c5d1SDavid du Colombier putsect(pdp->p);
4943e12c5d1SDavid du Colombier free(pdp);
4953e12c5d1SDavid du Colombier }
4967dd7cddfSDavid du Colombier
4973e12c5d1SDavid du Colombier void
rread(void)4983e12c5d1SDavid du Colombier rread(void)
4993e12c5d1SDavid du Colombier {
5007dd7cddfSDavid du Colombier Xfile *f;
5017dd7cddfSDavid du Colombier int r;
5023e12c5d1SDavid du Colombier
5039a747e4fSDavid du Colombier if (!(f=xfile(req->fid, Asis)) || !(f->flags&Oread))
5043e12c5d1SDavid du Colombier goto error;
5059a747e4fSDavid du Colombier if(req->count > sizeof repdata)
5069a747e4fSDavid du Colombier req->count = sizeof repdata;
5079a747e4fSDavid du Colombier if(f->qid.type & QTDIR){
5083e12c5d1SDavid du Colombier if(getfile(f) < 0)
5093e12c5d1SDavid du Colombier goto error;
5109a747e4fSDavid du Colombier r = readdir(f, repdata, req->offset, req->count);
5113e12c5d1SDavid du Colombier }else{
5123e12c5d1SDavid du Colombier if(getfile(f) < 0)
5133e12c5d1SDavid du Colombier goto error;
5149a747e4fSDavid du Colombier r = readfile(f, repdata, req->offset, req->count);
5153e12c5d1SDavid du Colombier }
5163e12c5d1SDavid du Colombier putfile(f);
5173e12c5d1SDavid du Colombier if(r < 0){
5183e12c5d1SDavid du Colombier error:
5193e12c5d1SDavid du Colombier errno = Eio;
5203e12c5d1SDavid du Colombier }else{
5219a747e4fSDavid du Colombier rep->count = r;
5229a747e4fSDavid du Colombier rep->data = (char*)repdata;
5233e12c5d1SDavid du Colombier }
5243e12c5d1SDavid du Colombier }
5257dd7cddfSDavid du Colombier
5263e12c5d1SDavid du Colombier void
rwrite(void)5273e12c5d1SDavid du Colombier rwrite(void)
5283e12c5d1SDavid du Colombier {
5297dd7cddfSDavid du Colombier Xfile *f;
5307dd7cddfSDavid du Colombier int r;
5313e12c5d1SDavid du Colombier
5329a747e4fSDavid du Colombier if (!(f=xfile(req->fid, Asis)) || !(f->flags&Owrite))
5333e12c5d1SDavid du Colombier goto error;
5343e12c5d1SDavid du Colombier if(getfile(f) < 0)
5353e12c5d1SDavid du Colombier goto error;
5369a747e4fSDavid du Colombier r = writefile(f, req->data, req->offset, req->count);
5373e12c5d1SDavid du Colombier putfile(f);
5383e12c5d1SDavid du Colombier if(r < 0){
5393e12c5d1SDavid du Colombier error:
5403e12c5d1SDavid du Colombier errno = Eio;
5413e12c5d1SDavid du Colombier }else{
5429a747e4fSDavid du Colombier rep->count = r;
5433e12c5d1SDavid du Colombier }
5443e12c5d1SDavid du Colombier }
5457dd7cddfSDavid du Colombier
5463e12c5d1SDavid du Colombier void
rclunk(void)5473e12c5d1SDavid du Colombier rclunk(void)
5483e12c5d1SDavid du Colombier {
5499a747e4fSDavid du Colombier xfile(req->fid, Clunk);
5503e12c5d1SDavid du Colombier sync();
5513e12c5d1SDavid du Colombier }
5527dd7cddfSDavid du Colombier
5537dd7cddfSDavid du Colombier /*
5547dd7cddfSDavid du Colombier * wipe out a dos directory entry
5557dd7cddfSDavid du Colombier */
5567dd7cddfSDavid du Colombier static void
doremove(Xfs * xf,Dosptr * dp)5577dd7cddfSDavid du Colombier doremove(Xfs *xf, Dosptr *dp)
5587dd7cddfSDavid du Colombier {
5597dd7cddfSDavid du Colombier Iosect *p;
5607dd7cddfSDavid du Colombier int prevdo;
5617dd7cddfSDavid du Colombier
5627dd7cddfSDavid du Colombier dp->p->iobuf[dp->offset] = DOSEMPTY;
5637dd7cddfSDavid du Colombier dp->p->flags |= BMOD;
56459cc4ca5SDavid du Colombier for(prevdo = dp->offset-DOSDIRSIZE; prevdo >= 0; prevdo -= DOSDIRSIZE){
5657dd7cddfSDavid du Colombier if(dp->p->iobuf[prevdo+11] != 0xf)
5667dd7cddfSDavid du Colombier break;
5677dd7cddfSDavid du Colombier dp->p->iobuf[prevdo] = DOSEMPTY;
5687dd7cddfSDavid du Colombier }
5697dd7cddfSDavid du Colombier if(prevdo < 0 && dp->prevaddr != -1){
5707dd7cddfSDavid du Colombier p = getsect(xf, dp->prevaddr);
57159cc4ca5SDavid du Colombier for(prevdo = ((Dosbpb*)xf->ptr)->sectsize-DOSDIRSIZE; prevdo >= 0; prevdo -= DOSDIRSIZE){
5727dd7cddfSDavid du Colombier if(p->iobuf[prevdo+11] != 0xf)
5737dd7cddfSDavid du Colombier break;
5747dd7cddfSDavid du Colombier p->iobuf[prevdo] = DOSEMPTY;
5757dd7cddfSDavid du Colombier p->flags |= BMOD;
5767dd7cddfSDavid du Colombier }
5777dd7cddfSDavid du Colombier putsect(p);
5787dd7cddfSDavid du Colombier }
5797dd7cddfSDavid du Colombier }
5807dd7cddfSDavid du Colombier
5813e12c5d1SDavid du Colombier void
rremove(void)5823e12c5d1SDavid du Colombier rremove(void)
5833e12c5d1SDavid du Colombier {
5847dd7cddfSDavid du Colombier Xfile *f;
5853e12c5d1SDavid du Colombier Dosptr *dp;
5867dd7cddfSDavid du Colombier Iosect *parp;
5877dd7cddfSDavid du Colombier Dosdir *pard;
5883e12c5d1SDavid du Colombier
5899a747e4fSDavid du Colombier f = xfile(req->fid, Asis);
5909a747e4fSDavid du Colombier parp = nil;
5919a747e4fSDavid du Colombier if(f == nil){
5923e12c5d1SDavid du Colombier errno = Eio;
5933e12c5d1SDavid du Colombier goto out;
5943e12c5d1SDavid du Colombier }
5953e12c5d1SDavid du Colombier dp = f->ptr;
5967dd7cddfSDavid du Colombier if(isroot(dp->addr)){
5973e12c5d1SDavid du Colombier errno = Eperm;
5983e12c5d1SDavid du Colombier goto out;
5993e12c5d1SDavid du Colombier }
6009a747e4fSDavid du Colombier
6013e12c5d1SDavid du Colombier /*
6029a747e4fSDavid du Colombier * can't remove if parent is read only,
6039a747e4fSDavid du Colombier * it's a non-empty directory,
6049a747e4fSDavid du Colombier * or it's a read only file in the root directory
6053e12c5d1SDavid du Colombier */
6063e12c5d1SDavid du Colombier parp = getsect(f->xf, dp->paddr);
6079a747e4fSDavid du Colombier if(parp == nil
6089a747e4fSDavid du Colombier || getfile(f) < 0){
6093e12c5d1SDavid du Colombier errno = Eio;
6103e12c5d1SDavid du Colombier goto out;
6113e12c5d1SDavid du Colombier }
6123e12c5d1SDavid du Colombier pard = (Dosdir *)&parp->iobuf[dp->poffset];
6139a747e4fSDavid du Colombier if(!isroot(dp->paddr) && (pard->attr & DRONLY)
6149a747e4fSDavid du Colombier || (dp->d->attr & DDIR) && emptydir(f) < 0
6159a747e4fSDavid du Colombier || isroot(dp->paddr) && (dp->d->attr&DRONLY)){
6163e12c5d1SDavid du Colombier errno = Eperm;
6173e12c5d1SDavid du Colombier goto out;
6183e12c5d1SDavid du Colombier }
6199a747e4fSDavid du Colombier if(truncfile(f, 0) < 0){
6203e12c5d1SDavid du Colombier errno = Eio;
6213e12c5d1SDavid du Colombier goto out;
6223e12c5d1SDavid du Colombier }
6237dd7cddfSDavid du Colombier doremove(f->xf, f->ptr);
6247dd7cddfSDavid du Colombier if(!isroot(dp->paddr)){
625219b2ee8SDavid du Colombier puttime(pard, 0);
6263e12c5d1SDavid du Colombier parp->flags |= BMOD;
6273e12c5d1SDavid du Colombier }
6283e12c5d1SDavid du Colombier out:
6299a747e4fSDavid du Colombier if(parp != nil)
6309a747e4fSDavid du Colombier putsect(parp);
6319a747e4fSDavid du Colombier if(f != nil)
6329a747e4fSDavid du Colombier putfile(f);
6339a747e4fSDavid du Colombier xfile(req->fid, Clunk);
6343e12c5d1SDavid du Colombier sync();
6353e12c5d1SDavid du Colombier }
6367dd7cddfSDavid du Colombier
6377dd7cddfSDavid du Colombier static void
dostat(Xfile * f,Dir * d)6387dd7cddfSDavid du Colombier dostat(Xfile *f, Dir *d)
6397dd7cddfSDavid du Colombier {
6407dd7cddfSDavid du Colombier Dosptr *dp;
6417dd7cddfSDavid du Colombier Iosect *p;
6427dd7cddfSDavid du Colombier char *name, namebuf[DOSNAMELEN];
6437dd7cddfSDavid du Colombier int islong, sum, prevdo;
6447dd7cddfSDavid du Colombier
6457dd7cddfSDavid du Colombier dp = f->ptr;
6467dd7cddfSDavid du Colombier if(isroot(dp->addr)){
6477dd7cddfSDavid du Colombier memset(d, 0, sizeof(Dir));
6489a747e4fSDavid du Colombier d->name = "/";
6499a747e4fSDavid du Colombier d->qid.type = QTDIR;
6509a747e4fSDavid du Colombier d->qid.path = f->xf->rootqid.path;
6519a747e4fSDavid du Colombier d->mode = DMDIR|0777;
6529a747e4fSDavid du Colombier d->uid = "bill";
6539a747e4fSDavid du Colombier d->muid = "bill";
6549a747e4fSDavid du Colombier d->gid = "trog";
6557dd7cddfSDavid du Colombier }else{
6567dd7cddfSDavid du Colombier /*
6577dd7cddfSDavid du Colombier * assemble any long file name
6587dd7cddfSDavid du Colombier */
6597dd7cddfSDavid du Colombier sum = aliassum(dp->d);
6607dd7cddfSDavid du Colombier islong = 0;
6617dd7cddfSDavid du Colombier name = namebuf;
66259cc4ca5SDavid du Colombier for(prevdo = dp->offset-DOSDIRSIZE; prevdo >= 0; prevdo -= DOSDIRSIZE){
6637dd7cddfSDavid du Colombier if(dp->p->iobuf[prevdo+11] != 0xf)
6647dd7cddfSDavid du Colombier break;
6657dd7cddfSDavid du Colombier name = getnamesect(namebuf, name, &dp->p->iobuf[prevdo], &islong, &sum, -1);
6667dd7cddfSDavid du Colombier }
6677dd7cddfSDavid du Colombier if(prevdo < 0 && dp->prevaddr != -1){
6687dd7cddfSDavid du Colombier p = getsect(f->xf, dp->prevaddr);
66959cc4ca5SDavid du Colombier for(prevdo = ((Dosbpb*)f->xf->ptr)->sectsize-DOSDIRSIZE; prevdo >= 0; prevdo -= DOSDIRSIZE){
6707dd7cddfSDavid du Colombier if(p->iobuf[prevdo+11] != 0xf)
6717dd7cddfSDavid du Colombier break;
6727dd7cddfSDavid du Colombier name = getnamesect(namebuf, name, &p->iobuf[prevdo], &islong, &sum, -1);
6737dd7cddfSDavid du Colombier }
6747dd7cddfSDavid du Colombier putsect(p);
6757dd7cddfSDavid du Colombier }
6767dd7cddfSDavid du Colombier getdir(f->xf, d, dp->d, dp->addr, dp->offset);
6777dd7cddfSDavid du Colombier if(islong && sum == -1 && nameok(namebuf))
6789a747e4fSDavid du Colombier strcpy(d->name, namebuf);
6797dd7cddfSDavid du Colombier }
6807dd7cddfSDavid du Colombier }
6817dd7cddfSDavid du Colombier
6823e12c5d1SDavid du Colombier void
rstat(void)6833e12c5d1SDavid du Colombier rstat(void)
6843e12c5d1SDavid du Colombier {
6853e12c5d1SDavid du Colombier Dir dir;
6867dd7cddfSDavid du Colombier Xfile *f;
6873e12c5d1SDavid du Colombier
6889a747e4fSDavid du Colombier f = xfile(req->fid, Asis);
6897dd7cddfSDavid du Colombier if(!f || getfile(f) < 0){
6903e12c5d1SDavid du Colombier errno = Eio;
6917dd7cddfSDavid du Colombier return;
6927dd7cddfSDavid du Colombier }
6937dd7cddfSDavid du Colombier
6949a747e4fSDavid du Colombier dir.name = repdata;
6957dd7cddfSDavid du Colombier dostat(f, &dir);
6967dd7cddfSDavid du Colombier
6979a747e4fSDavid du Colombier rep->nstat = convD2M(&dir, statbuf, sizeof statbuf);
6989a747e4fSDavid du Colombier rep->stat = statbuf;
6993e12c5d1SDavid du Colombier putfile(f);
7003e12c5d1SDavid du Colombier }
701219b2ee8SDavid du Colombier
7023e12c5d1SDavid du Colombier void
rwstat(void)7033e12c5d1SDavid du Colombier rwstat(void)
7043e12c5d1SDavid du Colombier {
7057dd7cddfSDavid du Colombier Dir dir, wdir;
7067dd7cddfSDavid du Colombier Xfile *f, pf;
7077dd7cddfSDavid du Colombier Dosptr *dp, ndp, pdp;
7087dd7cddfSDavid du Colombier Iosect *parp;
7097dd7cddfSDavid du Colombier Dosdir *pard, *d, od;
7107dd7cddfSDavid du Colombier char sname[13];
7117dd7cddfSDavid du Colombier ulong oaddr, ooffset;
7127dd7cddfSDavid du Colombier long start, length;
7139a747e4fSDavid du Colombier int i, longtype, changes, attr;
7147dd7cddfSDavid du Colombier
7159a747e4fSDavid du Colombier f = xfile(req->fid, Asis);
7167dd7cddfSDavid du Colombier if(!f || getfile(f) < 0){
7177dd7cddfSDavid du Colombier errno = Eio;
7187dd7cddfSDavid du Colombier return;
7197dd7cddfSDavid du Colombier }
7207dd7cddfSDavid du Colombier dp = f->ptr;
7217dd7cddfSDavid du Colombier
7227dd7cddfSDavid du Colombier if(isroot(dp->addr)){
7233e12c5d1SDavid du Colombier errno = Eperm;
7247dd7cddfSDavid du Colombier goto out;
7257dd7cddfSDavid du Colombier }
7267dd7cddfSDavid du Colombier
7277dd7cddfSDavid du Colombier changes = 0;
7289a747e4fSDavid du Colombier dir.name = repdata;
7297dd7cddfSDavid du Colombier dostat(f, &dir);
7309a747e4fSDavid du Colombier if(convM2D(req->stat, req->nstat, &wdir, (char*)statbuf) != req->nstat){
7319a747e4fSDavid du Colombier errno = Ebadstat;
7329a747e4fSDavid du Colombier goto out;
7339a747e4fSDavid du Colombier }
7349a747e4fSDavid du Colombier
7359a747e4fSDavid du Colombier /*
7369a747e4fSDavid du Colombier * To change length, must have write permission on file.
7379a747e4fSDavid du Colombier * we only allow truncates for now.
7389a747e4fSDavid du Colombier */
7399a747e4fSDavid du Colombier if(wdir.length!=~0 && wdir.length!=dir.length){
7409a747e4fSDavid du Colombier if(wdir.length > dir.length || !dir.mode & 0222){
7419a747e4fSDavid du Colombier errno = Eperm;
7429a747e4fSDavid du Colombier goto out;
7439a747e4fSDavid du Colombier }
7449a747e4fSDavid du Colombier }
7457dd7cddfSDavid du Colombier
7467dd7cddfSDavid du Colombier /*
7477dd7cddfSDavid du Colombier * no chown or chgrp
7487dd7cddfSDavid du Colombier */
7499a747e4fSDavid du Colombier if(wdir.uid[0] != '\0' && strcmp(dir.uid, wdir.uid) != 0
7509a747e4fSDavid du Colombier || wdir.gid[0] != '\0' && strcmp(dir.gid, wdir.gid) != 0){
7517dd7cddfSDavid du Colombier errno = Eperm;
7527dd7cddfSDavid du Colombier goto out;
7537dd7cddfSDavid du Colombier }
7547dd7cddfSDavid du Colombier
7557dd7cddfSDavid du Colombier /*
7567dd7cddfSDavid du Colombier * mode/mtime allowed
7577dd7cddfSDavid du Colombier */
7589a747e4fSDavid du Colombier if(wdir.mtime != ~0 && dir.mtime != wdir.mtime)
7597dd7cddfSDavid du Colombier changes = 1;
7607dd7cddfSDavid du Colombier
7617dd7cddfSDavid du Colombier /*
7629a747e4fSDavid du Colombier * Setting DMAPPEND (make system file contiguous)
7639a747e4fSDavid du Colombier * requires setting DMEXCL (system file).
7647dd7cddfSDavid du Colombier */
7659a747e4fSDavid du Colombier if(wdir.mode != ~0){
7667dd7cddfSDavid du Colombier if((wdir.mode & 7) != ((wdir.mode >> 3) & 7)
7677dd7cddfSDavid du Colombier || (wdir.mode & 7) != ((wdir.mode >> 6) & 7)){
7687dd7cddfSDavid du Colombier errno = Eperm;
7697dd7cddfSDavid du Colombier goto out;
7707dd7cddfSDavid du Colombier }
7719a747e4fSDavid du Colombier if((dir.mode^wdir.mode) & (DMEXCL|DMAPPEND|0777))
7729a747e4fSDavid du Colombier changes = 1;
7739a747e4fSDavid du Colombier if((dir.mode^wdir.mode) & DMAPPEND) {
7749a747e4fSDavid du Colombier if((wdir.mode & (DMEXCL|DMAPPEND)) == DMAPPEND) {
7759a747e4fSDavid du Colombier errno = Eperm;
7769a747e4fSDavid du Colombier goto out;
7779a747e4fSDavid du Colombier }
7789a747e4fSDavid du Colombier if((wdir.mode & DMAPPEND) && makecontig(f, 0) < 0) {
7799a747e4fSDavid du Colombier errno = Econtig;
7809a747e4fSDavid du Colombier goto out;
7819a747e4fSDavid du Colombier }
7829a747e4fSDavid du Colombier }
7839a747e4fSDavid du Colombier }
7849a747e4fSDavid du Colombier
7857dd7cddfSDavid du Colombier
7867dd7cddfSDavid du Colombier /*
7877dd7cddfSDavid du Colombier * to rename:
7887dd7cddfSDavid du Colombier * 1) make up a fake clone
7897dd7cddfSDavid du Colombier * 2) walk to parent
7907dd7cddfSDavid du Colombier * 3) remove the old entry
7917dd7cddfSDavid du Colombier * 4) create entry with new name
7927dd7cddfSDavid du Colombier * 5) write correct mode/mtime info
7937dd7cddfSDavid du Colombier * we need to remove the old entry before creating the new one
7947dd7cddfSDavid du Colombier * to avoid a lock loop.
7957dd7cddfSDavid du Colombier */
7969a747e4fSDavid du Colombier if(wdir.name[0] != '\0' && strcmp(dir.name, wdir.name) != 0){
7979a747e4fSDavid du Colombier if(utflen(wdir.name) >= DOSNAMELEN){
7989a747e4fSDavid du Colombier errno = Etoolong;
7999a747e4fSDavid du Colombier goto out;
8009a747e4fSDavid du Colombier }
8019a747e4fSDavid du Colombier
8027dd7cddfSDavid du Colombier /*
8037dd7cddfSDavid du Colombier * grab parent directory of file to be changed and check for write perm
8047dd7cddfSDavid du Colombier * rename also disallowed for read-only files in root directory
8057dd7cddfSDavid du Colombier */
8067dd7cddfSDavid du Colombier parp = getsect(f->xf, dp->paddr);
8077dd7cddfSDavid du Colombier if(parp == nil){
8087dd7cddfSDavid du Colombier errno = Eio;
8097dd7cddfSDavid du Colombier goto out;
8107dd7cddfSDavid du Colombier }
8117dd7cddfSDavid du Colombier pard = (Dosdir *)&parp->iobuf[dp->poffset];
8127dd7cddfSDavid du Colombier if(!isroot(dp->paddr) && (pard->attr & DRONLY)
8137dd7cddfSDavid du Colombier || isroot(dp->paddr) && (dp->d->attr&DRONLY)){
8147dd7cddfSDavid du Colombier putsect(parp);
8157dd7cddfSDavid du Colombier errno = Eperm;
8167dd7cddfSDavid du Colombier goto out;
8177dd7cddfSDavid du Colombier }
8187dd7cddfSDavid du Colombier
8197dd7cddfSDavid du Colombier /*
8207dd7cddfSDavid du Colombier * retrieve info from old entry
8217dd7cddfSDavid du Colombier */
8227dd7cddfSDavid du Colombier oaddr = dp->addr;
8237dd7cddfSDavid du Colombier ooffset = dp->offset;
8247dd7cddfSDavid du Colombier d = dp->d;
8257dd7cddfSDavid du Colombier od = *d;
8267dd7cddfSDavid du Colombier start = getstart(f->xf, d);
8277dd7cddfSDavid du Colombier length = GLONG(d->length);
8287dd7cddfSDavid du Colombier attr = d->attr;
8297dd7cddfSDavid du Colombier
8307dd7cddfSDavid du Colombier /*
8317dd7cddfSDavid du Colombier * temporarily release file to allow other directory ops:
8327dd7cddfSDavid du Colombier * walk to parent, validate new name
8337dd7cddfSDavid du Colombier * then remove old entry
8347dd7cddfSDavid du Colombier */
8357dd7cddfSDavid du Colombier putfile(f);
8367dd7cddfSDavid du Colombier pf = *f;
8377dd7cddfSDavid du Colombier memset(&pdp, 0, sizeof(Dosptr));
8387dd7cddfSDavid du Colombier pdp.prevaddr = -1;
8397dd7cddfSDavid du Colombier pdp.naddr = -1;
8407dd7cddfSDavid du Colombier pdp.addr = dp->paddr;
8417dd7cddfSDavid du Colombier pdp.offset = dp->poffset;
8427dd7cddfSDavid du Colombier pdp.p = parp;
8437dd7cddfSDavid du Colombier if(!isroot(pdp.addr))
8447dd7cddfSDavid du Colombier pdp.d = (Dosdir *)&parp->iobuf[pdp.offset];
8457dd7cddfSDavid du Colombier pf.ptr = &pdp;
8469a747e4fSDavid du Colombier longtype = mk8dot3name(&pf, &ndp, wdir.name, sname);
8479a747e4fSDavid du Colombier if(longtype==Invalid){
8487dd7cddfSDavid du Colombier putsect(parp);
8497dd7cddfSDavid du Colombier errno = Eperm;
8507dd7cddfSDavid du Colombier return;
8517dd7cddfSDavid du Colombier }
8527dd7cddfSDavid du Colombier if(getfile(f) < 0){
8537dd7cddfSDavid du Colombier putsect(parp);
8547dd7cddfSDavid du Colombier errno = Eio;
8557dd7cddfSDavid du Colombier return;
8567dd7cddfSDavid du Colombier }
8577dd7cddfSDavid du Colombier doremove(f->xf, dp);
8587dd7cddfSDavid du Colombier putfile(f);
8597dd7cddfSDavid du Colombier
8607dd7cddfSDavid du Colombier /*
8617dd7cddfSDavid du Colombier * search for dir entry again, since we may be able to use the old slot,
8627dd7cddfSDavid du Colombier * and we need to set up the naddr field if a long name spans the block.
8637dd7cddfSDavid du Colombier * create new entry.
8647dd7cddfSDavid du Colombier */
8659a747e4fSDavid du Colombier if(searchdir(&pf, wdir.name, dp, 1, longtype) < 0
8669a747e4fSDavid du Colombier || mkdentry(pf.xf, dp, wdir.name, sname, longtype, attr, start, length) < 0){
8677dd7cddfSDavid du Colombier putsect(parp);
8687dd7cddfSDavid du Colombier errno = Eio;
8697dd7cddfSDavid du Colombier goto out;
8707dd7cddfSDavid du Colombier }
8717dd7cddfSDavid du Colombier
8727dd7cddfSDavid du Colombier /*
8737dd7cddfSDavid du Colombier * copy invisible fields
8747dd7cddfSDavid du Colombier */
8757dd7cddfSDavid du Colombier d = dp->d;
8767dd7cddfSDavid du Colombier for(i = 0; i < 2; i++)
8777dd7cddfSDavid du Colombier d->ctime[i] = od.ctime[i];
8787dd7cddfSDavid du Colombier for(i = 0; i < nelem(od.cdate); i++)
8797dd7cddfSDavid du Colombier d->cdate[i] = od.cdate[i];
8807dd7cddfSDavid du Colombier for(i = 0; i < nelem(od.adate); i++)
8817dd7cddfSDavid du Colombier d->adate[i] = od.adate[i];
8827dd7cddfSDavid du Colombier
8837dd7cddfSDavid du Colombier putsect(parp);
8847dd7cddfSDavid du Colombier
8857dd7cddfSDavid du Colombier /*
8867dd7cddfSDavid du Colombier * relocate up other fids to the same file, if it moved
8877dd7cddfSDavid du Colombier */
8889a747e4fSDavid du Colombier f->qid.path = QIDPATH(dp);
8897dd7cddfSDavid du Colombier if(oaddr != dp->addr || ooffset != dp->offset)
8907dd7cddfSDavid du Colombier dosptrreloc(f, dp, oaddr, ooffset);
8919a747e4fSDavid du Colombier
8929a747e4fSDavid du Colombier /*
8939a747e4fSDavid du Colombier * copy fields that are not supposed to change
8949a747e4fSDavid du Colombier */
8959a747e4fSDavid du Colombier if(wdir.mtime == ~0)
8969a747e4fSDavid du Colombier wdir.mtime = dir.mtime;
8979a747e4fSDavid du Colombier if(wdir.mode == ~0)
8989a747e4fSDavid du Colombier wdir.mode = dir.mode;
8997dd7cddfSDavid du Colombier changes = 1;
9007dd7cddfSDavid du Colombier }
9017dd7cddfSDavid du Colombier
9029a747e4fSDavid du Colombier /*
9039a747e4fSDavid du Colombier * do the actual truncate
9049a747e4fSDavid du Colombier */
9059a747e4fSDavid du Colombier if(wdir.length != ~0 && wdir.length != dir.length && truncfile(f, wdir.length) < 0)
9069a747e4fSDavid du Colombier errno = Eio;
9079a747e4fSDavid du Colombier
9087dd7cddfSDavid du Colombier if(changes){
9097dd7cddfSDavid du Colombier putdir(dp->d, &wdir);
9107dd7cddfSDavid du Colombier dp->p->flags |= BMOD;
9117dd7cddfSDavid du Colombier }
9127dd7cddfSDavid du Colombier
9137dd7cddfSDavid du Colombier out:
9147dd7cddfSDavid du Colombier putfile(f);
9157dd7cddfSDavid du Colombier sync();
9163e12c5d1SDavid du Colombier }
917