📄 dosfs.c
字号:
//ZZZ set type for excl, append? if(req->perm & DMDIR){ f->qid.type = QTDIR; xp = getsect(f->xf, clust2sect(bp, start)); if(xp == nil){ errno = Eio; goto badio; } xd = (Dosdir *)&xp->iobuf[0]; memmove(xd, ndp->d, DOSDIRSIZE); memset(xd->name, ' ', sizeof xd->name+sizeof xd->ext); xd->name[0] = '.'; xd = (Dosdir *)&xp->iobuf[DOSDIRSIZE]; if(pd) memmove(xd, pd, DOSDIRSIZE); else{ memset(xd, 0, DOSDIRSIZE); puttime(xd, 0); xd->attr = DDIR; } memset(xd->name, ' ', sizeof xd->name+sizeof xd->ext); xd->name[0] = '.'; xd->name[1] = '.'; xp->flags |= BMOD; putsect(xp); } f->flags |= omode; rep->qid = f->qid; rep->iounit = 0;badio: putfile(f); putsect(pdp->p); free(pdp);}voidrread(void){ Xfile *f; int r; if (!(f=xfile(req->fid, Asis)) || !(f->flags&Oread)) goto error; if(req->count > sizeof repdata) req->count = sizeof repdata; if(f->qid.type & QTDIR){ if(getfile(f) < 0) goto error; r = readdir(f, repdata, req->offset, req->count); }else{ if(getfile(f) < 0) goto error; r = readfile(f, repdata, req->offset, req->count); } putfile(f); if(r < 0){error: errno = Eio; }else{ rep->count = r; rep->data = (char*)repdata; }}voidrwrite(void){ Xfile *f; int r; if (!(f=xfile(req->fid, Asis)) || !(f->flags&Owrite)) goto error; if(getfile(f) < 0) goto error; r = writefile(f, req->data, req->offset, req->count); putfile(f); if(r < 0){error: errno = Eio; }else{ rep->count = r; }}voidrclunk(void){ xfile(req->fid, Clunk); sync();}/* * wipe out a dos directory entry */static voiddoremove(Xfs *xf, Dosptr *dp){ Iosect *p; int prevdo; dp->p->iobuf[dp->offset] = DOSEMPTY; dp->p->flags |= BMOD; for(prevdo = dp->offset-DOSDIRSIZE; prevdo >= 0; prevdo -= DOSDIRSIZE){ if(dp->p->iobuf[prevdo+11] != 0xf) break; dp->p->iobuf[prevdo] = DOSEMPTY; } if(prevdo < 0 && dp->prevaddr != -1){ p = getsect(xf, dp->prevaddr); for(prevdo = ((Dosbpb*)xf->ptr)->sectsize-DOSDIRSIZE; prevdo >= 0; prevdo -= DOSDIRSIZE){ if(p->iobuf[prevdo+11] != 0xf) break; p->iobuf[prevdo] = DOSEMPTY; p->flags |= BMOD; } putsect(p); } }voidrremove(void){ Xfile *f; Dosptr *dp; Iosect *parp; Dosdir *pard; f = xfile(req->fid, Asis); parp = nil; if(f == nil){ errno = Eio; goto out; } dp = f->ptr; if(isroot(dp->addr)){ errno = Eperm; goto out; } /* * can't remove if parent is read only, * it's a non-empty directory, * or it's a read only file in the root directory */ parp = getsect(f->xf, dp->paddr); if(parp == nil || getfile(f) < 0){ errno = Eio; goto out; } pard = (Dosdir *)&parp->iobuf[dp->poffset]; if(!isroot(dp->paddr) && (pard->attr & DRONLY) || (dp->d->attr & DDIR) && emptydir(f) < 0 || isroot(dp->paddr) && (dp->d->attr&DRONLY)){ errno = Eperm; goto out; } if(truncfile(f, 0) < 0){ errno = Eio; goto out; } doremove(f->xf, f->ptr); if(!isroot(dp->paddr)){ puttime(pard, 0); parp->flags |= BMOD; }out: if(parp != nil) putsect(parp); if(f != nil) putfile(f); xfile(req->fid, Clunk); sync();}static voiddostat(Xfile *f, Dir *d){ Dosptr *dp; Iosect *p; char *name, namebuf[DOSNAMELEN]; int islong, sum, prevdo; dp = f->ptr; if(isroot(dp->addr)){ memset(d, 0, sizeof(Dir)); d->name = "/"; d->qid.type = QTDIR; d->qid.path = f->xf->rootqid.path; d->mode = DMDIR|0777; d->uid = "bill"; d->muid = "bill"; d->gid = "trog"; }else{ /* * assemble any long file name */ sum = aliassum(dp->d); islong = 0; name = namebuf; for(prevdo = dp->offset-DOSDIRSIZE; prevdo >= 0; prevdo -= DOSDIRSIZE){ if(dp->p->iobuf[prevdo+11] != 0xf) break; name = getnamesect(namebuf, name, &dp->p->iobuf[prevdo], &islong, &sum, -1); } if(prevdo < 0 && dp->prevaddr != -1){ p = getsect(f->xf, dp->prevaddr); for(prevdo = ((Dosbpb*)f->xf->ptr)->sectsize-DOSDIRSIZE; prevdo >= 0; prevdo -= DOSDIRSIZE){ if(p->iobuf[prevdo+11] != 0xf) break; name = getnamesect(namebuf, name, &p->iobuf[prevdo], &islong, &sum, -1); } putsect(p); } getdir(f->xf, d, dp->d, dp->addr, dp->offset); if(islong && sum == -1 && nameok(namebuf)) strcpy(d->name, namebuf); }}voidrstat(void){ Dir dir; Xfile *f; f = xfile(req->fid, Asis); if(!f || getfile(f) < 0){ errno = Eio; return; } dir.name = repdata; dostat(f, &dir); rep->nstat = convD2M(&dir, statbuf, sizeof statbuf); rep->stat = statbuf; putfile(f);}voidrwstat(void){ Dir dir, wdir; Xfile *f, pf; Dosptr *dp, ndp, pdp; Iosect *parp; Dosdir *pard, *d, od; char sname[13]; ulong oaddr, ooffset; long start, length; int i, longtype, changes, attr; f = xfile(req->fid, Asis); if(!f || getfile(f) < 0){ errno = Eio; return; } dp = f->ptr; if(isroot(dp->addr)){ errno = Eperm; goto out; } changes = 0; dir.name = repdata; dostat(f, &dir); if(convM2D(req->stat, req->nstat, &wdir, (char*)statbuf) != req->nstat){ errno = Ebadstat; goto out; } /* * To change length, must have write permission on file. * we only allow truncates for now. */ if(wdir.length!=~0 && wdir.length!=dir.length){ if(wdir.length > dir.length || !dir.mode & 0222){ errno = Eperm; goto out; } } /* * no chown or chgrp */ if(wdir.uid[0] != '\0' && strcmp(dir.uid, wdir.uid) != 0 || wdir.gid[0] != '\0' && strcmp(dir.gid, wdir.gid) != 0){ errno = Eperm; goto out; } /* * mode/mtime allowed */ if(wdir.mtime != ~0 && dir.mtime != wdir.mtime) changes = 1; /* * Setting DMAPPEND (make system file contiguous) * requires setting DMEXCL (system file). */ if(wdir.mode != ~0){ if((wdir.mode & 7) != ((wdir.mode >> 3) & 7) || (wdir.mode & 7) != ((wdir.mode >> 6) & 7)){ errno = Eperm; goto out; } if((dir.mode^wdir.mode) & (DMEXCL|DMAPPEND|0777)) changes = 1; if((dir.mode^wdir.mode) & DMAPPEND) { if((wdir.mode & (DMEXCL|DMAPPEND)) == DMAPPEND) { errno = Eperm; goto out; } if((wdir.mode & DMAPPEND) && makecontig(f, 0) < 0) { errno = Econtig; goto out; } } } /* * to rename: * 1) make up a fake clone * 2) walk to parent * 3) remove the old entry * 4) create entry with new name * 5) write correct mode/mtime info * we need to remove the old entry before creating the new one * to avoid a lock loop. */ if(wdir.name[0] != '\0' && strcmp(dir.name, wdir.name) != 0){ if(utflen(wdir.name) >= DOSNAMELEN){ errno = Etoolong; goto out; } /* * grab parent directory of file to be changed and check for write perm * rename also disallowed for read-only files in root directory */ parp = getsect(f->xf, dp->paddr); if(parp == nil){ errno = Eio; goto out; } pard = (Dosdir *)&parp->iobuf[dp->poffset]; if(!isroot(dp->paddr) && (pard->attr & DRONLY) || isroot(dp->paddr) && (dp->d->attr&DRONLY)){ putsect(parp); errno = Eperm; goto out; } /* * retrieve info from old entry */ oaddr = dp->addr; ooffset = dp->offset; d = dp->d; od = *d; start = getstart(f->xf, d); length = GLONG(d->length); attr = d->attr; /* * temporarily release file to allow other directory ops: * walk to parent, validate new name * then remove old entry */ putfile(f); pf = *f; memset(&pdp, 0, sizeof(Dosptr)); pdp.prevaddr = -1; pdp.naddr = -1; pdp.addr = dp->paddr; pdp.offset = dp->poffset; pdp.p = parp; if(!isroot(pdp.addr)) pdp.d = (Dosdir *)&parp->iobuf[pdp.offset]; pf.ptr = &pdp; longtype = mk8dot3name(&pf, &ndp, wdir.name, sname); if(longtype==Invalid){ putsect(parp); errno = Eperm; return; } if(getfile(f) < 0){ putsect(parp); errno = Eio; return; } doremove(f->xf, dp); putfile(f); /* * search for dir entry again, since we may be able to use the old slot, * and we need to set up the naddr field if a long name spans the block. * create new entry. */ if(searchdir(&pf, wdir.name, dp, 1, longtype) < 0 || mkdentry(pf.xf, dp, wdir.name, sname, longtype, attr, start, length) < 0){ putsect(parp); errno = Eio; goto out; } /* * copy invisible fields */ d = dp->d; for(i = 0; i < 2; i++) d->ctime[i] = od.ctime[i]; for(i = 0; i < nelem(od.cdate); i++) d->cdate[i] = od.cdate[i]; for(i = 0; i < nelem(od.adate); i++) d->adate[i] = od.adate[i]; putsect(parp); /* * relocate up other fids to the same file, if it moved */ f->qid.path = QIDPATH(dp); if(oaddr != dp->addr || ooffset != dp->offset) dosptrreloc(f, dp, oaddr, ooffset); /* * copy fields that are not supposed to change */ if(wdir.mtime == ~0) wdir.mtime = dir.mtime; if(wdir.mode == ~0) wdir.mode = dir.mode; changes = 1; } /* * do the actual truncate */ if(wdir.length != ~0 && wdir.length != dir.length && truncfile(f, wdir.length) < 0) errno = Eio; if(changes){ putdir(dp->d, &wdir); dp->p->flags |= BMOD; }out: putfile(f); sync();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -