📄 dosfs.c
字号:
#include <u.h>#include <libc.h>#include <auth.h>#include <fcall.h>#include "iotrack.h"#include "dat.h"#include "dosfs.h"#include "fns.h"voidrversion(void){ if(req->msize > Maxiosize) rep->msize = Maxiosize; else rep->msize = req->msize; rep->version = "9P2000";}voidrauth(void){ errno = Enoauth;}voidrflush(void){}voidrattach(void){ Xfs *xf; Xfile *root; Dosptr *dp; root = xfile(req->fid, Clean); if(!root){ errno = Enomem; goto error; } root->xf = xf = getxfs(req->uname, req->aname); if(!xf) goto error; if(xf->fmt == 0 && dosfs(xf) < 0){ errno = Eformat; goto error; } root->qid.type = QTDIR; root->qid.path = 0; root->qid.vers = 0; root->xf->rootqid = root->qid; dp = malloc(sizeof(Dosptr)); if(dp == nil){ errno = Enomem; goto error; } root->ptr = dp; rootfile(root); rep->qid = root->qid; return;error: if(root) xfile(req->fid, Clunk);}Xfile*doclone(Xfile *of, int newfid){ Xfile *nf, *next; Dosptr *dp; nf = xfile(newfid, Clean); if(!nf){ errno = Enomem; return nil; } dp = malloc(sizeof(Dosptr)); if(dp == nil){ errno = Enomem; return nil; } next = nf->next; *nf = *of; nf->next = next; nf->fid = req->newfid; nf->ptr = dp; refxfs(nf->xf, 1); memmove(dp, of->ptr, sizeof(Dosptr)); dp->p = nil; dp->d = nil; return nf;}voidrwalk(void){ Xfile *f, *nf; Dosptr dp[1], savedp[1]; int r, longtype; Qid saveqid; rep->nwqid = 0; nf = nil; f = xfile(req->fid, Asis); if(f == nil){ chat("\tno xfile\n"); goto error2; } if(req->fid != req->newfid){ nf = doclone(f, req->newfid); if(nf == nil){ chat("\tclone failed\n"); goto error2; } f = nf; } saveqid = f->qid; memmove(savedp, f->ptr, sizeof(Dosptr)); for(; rep->nwqid < req->nwname && rep->nwqid < MAXWELEM; rep->nwqid++){ chat("\twalking %s\n", req->wname[rep->nwqid]); if(!(f->qid.type & QTDIR)){ chat("\tnot dir: type=%#x\n", f->qid.type); goto error; } if(strcmp(req->wname[rep->nwqid], ".") == 0){ ; }else if(strcmp(req->wname[rep->nwqid], "..") == 0){ if(f->qid.path != f->xf->rootqid.path){ r = walkup(f, dp); if(r < 0) goto error; memmove(f->ptr, dp, sizeof(Dosptr)); if(isroot(dp->addr)) f->qid.path = f->xf->rootqid.path; else f->qid.path = QIDPATH(dp); } }else{ fixname(req->wname[rep->nwqid]); longtype = classifyname(req->wname[rep->nwqid]); if(longtype==Invalid || getfile(f) < 0) goto error; /* * always do a search for the long name, * because it could be filed as such */ r = searchdir(f, req->wname[rep->nwqid], dp, 0, longtype); putfile(f); if(r < 0) goto error; memmove(f->ptr, dp, sizeof(Dosptr)); f->qid.path = QIDPATH(dp); f->qid.type = QTFILE; if(isroot(dp->addr)) f->qid.path = f->xf->rootqid.path; else if(dp->d->attr & DDIR) f->qid.type = QTDIR; else if(dp->d->attr & DSYSTEM){ f->qid.type |= QTEXCL; if(iscontig(f->xf, dp->d)) f->qid.type |= QTAPPEND; }//ZZZ maybe use other bits than qtexcl & qtapppend putfile(f); } rep->wqid[rep->nwqid] = f->qid; } return;error: f->qid = saveqid; memmove(f->ptr, savedp, sizeof(Dosptr)); if(nf != nil) xfile(req->newfid, Clunk);error2: if(!errno && !rep->nwqid) errno = Enonexist;}voidropen(void){ Xfile *f; Iosect *p; Dosptr *dp; int attr, omode; f = xfile(req->fid, Asis); if(!f || (f->flags&Omodes)){ errno = Eio; return; } dp = f->ptr; omode = 0; if(!isroot(dp->paddr) && (req->mode & ORCLOSE)){ /* * check on parent directory of file to be deleted */ p = getsect(f->xf, dp->paddr); if(p == nil){ errno = Eio; return; } attr = ((Dosdir *)&p->iobuf[dp->poffset])->attr; putsect(p); if(attr & DRONLY){ errno = Eperm; return; } omode |= Orclose; }else if(req->mode & ORCLOSE) omode |= Orclose; if(getfile(f) < 0){ errno = Enonexist; return; } if(!isroot(dp->addr)) attr = dp->d->attr; else attr = DDIR; switch(req->mode & 7){ case OREAD: case OEXEC: omode |= Oread; break; case ORDWR: omode |= Oread; /* fall through */ case OWRITE: omode |= Owrite; if(attr & DRONLY){ errno = Eperm; goto out; } break; default: errno = Eio; goto out; } if(req->mode & OTRUNC){ if(attr & DDIR || attr & DRONLY){ errno = Eperm; goto out; } if(truncfile(f, 0) < 0){ errno = Eio; goto out; } } f->flags |= omode; rep->qid = f->qid; rep->iounit = 0;out: putfile(f);}static intmk8dot3name(Xfile *f, Dosptr *ndp, char *name, char *sname){ Dosptr tmpdp; int i, longtype; if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) return Invalid; /* * always do a search for the long name, * because it could be filed as such */ fixname(name); longtype = classifyname(name); if(longtype==Invalid || searchdir(f, name, ndp, 1, longtype) < 0) return Invalid; if(longtype==Short) return Short; if(longtype==ShortLower){ /* * alias is the upper-case version, which we * already know does not exist. */ strcpy(sname, name); for(i=0; sname[i]; i++) if('a' <= sname[i] && sname[i] <= 'z') sname[i] += 'A'-'a'; return ShortLower; } /* * find alias for the long name */ for(i=1;; i++){ mkalias(name, sname, i); if(searchdir(f, sname, &tmpdp, 0, 0) < 0) return Long; putsect(tmpdp.p); }}/* * fill in a directory entry for a new file */static intmkdentry(Xfs *xf, Dosptr *ndp, char *name, char *sname, int longtype, int nattr, long start, long length){ Dosdir *nd; /* * fill in the entry */ ndp->p = getsect(xf, ndp->addr); if(ndp->p == nil || longtype!=Short && putlongname(xf, ndp, name, sname) < 0){ errno = Eio; return -1; } ndp->d = (Dosdir *)&ndp->p->iobuf[ndp->offset]; nd = ndp->d; memset(nd, 0, DOSDIRSIZE); if(longtype!=Short) name = sname; putname(name, nd); nd->attr = nattr; puttime(nd, 0); putstart(xf, nd, start); nd->length[0] = length; nd->length[1] = length>>8; nd->length[2] = length>>16; nd->length[3] = length>>24; ndp->p->flags |= BMOD; return 0;}voidrcreate(void){ Dosbpb *bp; Xfile *f; Dosptr *pdp, *ndp; Iosect *xp; Dosdir *pd, *xd; char sname[13]; long start; int longtype, attr, omode, nattr; f = xfile(req->fid, Asis); if(!f || (f->flags&Omodes) || getfile(f)<0){ errno = Eio; return; } pdp = f->ptr; pd = pdp->d; /* * perm check */ if(isroot(pdp->addr) && pd != nil) panic("root pd != nil"); attr = pd ? pd->attr : DDIR; if(!(attr & DDIR) || (attr & DRONLY)){badperm: putfile(f); errno = Eperm; return; } omode = 0; if(req->mode & ORCLOSE) omode |= Orclose; switch(req->mode & 7){ case OREAD: case OEXEC: omode |= Oread; break; case ORDWR: omode |= Oread; /* fall through */ case OWRITE: omode |= Owrite; if(req->perm & DMDIR) goto badperm; break; default: goto badperm; } /* * check the name, find the slot for the dentry, * and find a good alias for a long name */ ndp = malloc(sizeof(Dosptr)); if(ndp == nil){ putfile(f); errno = Enomem; return; } longtype = mk8dot3name(f, ndp, req->name, sname); chat("rcreate %s longtype %d...\n", req->name, longtype); if(longtype == Invalid){ free(ndp); goto badperm; } /* * allocate first cluster, if making directory */ start = 0; bp = nil; if(req->perm & DMDIR){ bp = f->xf->ptr; mlock(bp); start = falloc(f->xf); unmlock(bp); if(start <= 0){ free(ndp); putfile(f); errno = Eio; return; } } /* * make the entry */ nattr = 0; if((req->perm & 0222) == 0) nattr |= DRONLY; if(req->perm & DMDIR) nattr |= DDIR; if(mkdentry(f->xf, ndp, req->name, sname, longtype, nattr, start, 0) < 0){ if(ndp->p != nil) putsect(ndp->p); free(ndp); if(start > 0) ffree(f->xf, start); putfile(f); return; } if(pd != nil){ puttime(pd, 0); pdp->p->flags |= BMOD; } /* * fix up the fid */ f->ptr = ndp; f->qid.type = QTFILE; f->qid.path = QIDPATH(ndp);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -