📄 9660srv.c
字号:
#include <u.h>#include <libc.h>#include <auth.h>#include <fcall.h>#include "dat.h"#include "fns.h"#include "iso9660.h"static void ireset(void);static int iattach(Xfile*);static void iclone(Xfile*, Xfile*);static void iwalkup(Xfile*);static void iwalk(Xfile*, char*);static void iopen(Xfile*, int);static void icreate(Xfile*, char*, long, int);static long ireaddir(Xfile*, uchar*, long, long);static long iread(Xfile*, char*, long, long);static long iwrite(Xfile*, char*, long, long);static void iclunk(Xfile*);static void iremove(Xfile*);static void istat(Xfile*, Dir*);static void iwstat(Xfile*, Dir*);static char* nstr(uchar*, int);static char* rdate(uchar*, int);static int getcontin(Xdata*, uchar*, uchar**);static int getdrec(Xfile*, void*);static void ungetdrec(Xfile*);static int opendotdot(Xfile*, Xfile*);static int showdrec(int, int, void*);static long gtime(uchar*);static long l16(void*);static long l32(void*);static void newdrec(Xfile*, Drec*);static int rzdir(Xfs*, Dir*, int, Drec*);Xfsub isosub ={ ireset, iattach, iclone, iwalkup, iwalk, iopen, icreate, ireaddir, iread, iwrite, iclunk, iremove, istat, iwstat};static voidireset(void){}static intiattach(Xfile *root){ Xfs *cd = root->xf; Iobuf *p; Voldesc *v; Isofile *fp; Drec *dp; int fmt, blksize, i, n, l, haveplan9; Iobuf *dirp; uchar dbuf[256]; Drec *rd = (Drec *)dbuf; uchar *q, *s; dirp = nil; blksize = 0; fmt = 0; dp = nil; haveplan9 = 0; for(i=VOLDESC;i<VOLDESC+100; i++){ /* +100 for sanity */ p = getbuf(cd->d, i); v = (Voldesc*)(p->iobuf); if(memcmp(v->byte, "\01CD001\01", 7) == 0){ /* iso */ if(dirp) putbuf(dirp); dirp = p; fmt = 'z'; dp = (Drec*)v->z.desc.rootdir; blksize = l16(v->z.desc.blksize); chat("iso, blksize=%d...", blksize); v = (Voldesc*)(dirp->iobuf); haveplan9 = (strncmp((char*)v->z.boot.sysid, "PLAN 9", 6)==0); if(haveplan9){ if(noplan9) { chat("ignoring plan9"); haveplan9 = 0; } else { fmt = '9'; chat("plan9 iso..."); } } continue; } if(memcmp(&v->byte[8], "\01CDROM\01", 7) == 0){ /* high sierra */ if(dirp) putbuf(dirp); dirp = p; fmt = 'r'; dp = (Drec*)v->r.desc.rootdir; blksize = l16(v->r.desc.blksize); chat("high sierra, blksize=%d...", blksize); continue; } if(haveplan9==0 && !nojoliet && memcmp(v->byte, "\02CD001\01", 7) == 0){chat("%d %d\n", haveplan9, nojoliet); /* * The right thing to do is walk the escape sequences looking * for one of 25 2F 4[035], but Microsoft seems to not honor * the format, which makes it hard to walk over. */ q = v->z.desc.escapes; if(q[0] == 0x25 && q[1] == 0x2F && (q[2] == 0x40 || q[2] == 0x43 || q[2] == 0x45)){ /* Joliet, it appears */ if(dirp) putbuf(dirp); dirp = p; fmt = 'J'; dp = (Drec*)v->z.desc.rootdir; if(blksize != l16(v->z.desc.blksize)) fprint(2, "warning: suspicious Joliet blocksize\n"); chat("joliet..."); continue; } } putbuf(p); if(v->byte[0] == 0xFF) break; } if(fmt == 0){ if(dirp) putbuf(dirp); return -1; } assert(dirp != nil); if(chatty) showdrec(2, fmt, dp); if(blksize > Sectorsize){ chat("blksize too big..."); putbuf(dirp); return -1; } if(waserror()){ putbuf(dirp); nexterror(); } root->len = sizeof(Isofile) - sizeof(Drec) + dp->reclen; root->ptr = fp = ealloc(root->len); if(haveplan9) root->xf->isplan9 = 1; fp->fmt = fmt; fp->blksize = blksize; fp->offset = 0; fp->doffset = 0; memmove(&fp->d, dp, dp->reclen); root->qid.path = l32(dp->addr); root->qid.type = QTDIR; putbuf(dirp); poperror(); if(getdrec(root, rd) >= 0){ n = rd->reclen-(34+rd->namelen); s = (uchar*)rd->name + rd->namelen; if((uintptr)s & 1){ s++; n--; } if(n >= 7 && s[0] == 'S' && s[1] == 'P' && s[2] == 7 && s[3] == 1 && s[4] == 0xBE && s[5] == 0xEF){ root->xf->issusp = 1; root->xf->suspoff = s[6]; n -= root->xf->suspoff; s += root->xf->suspoff; for(; n >= 4; s += l, n -= l){ l = s[2]; if(s[0] == 'E' && s[1] == 'R'){ if(!norock && s[4] == 10 && memcmp(s+8, "RRIP_1991A", 10) == 0) root->xf->isrock = 1; break; } else if(s[0] == 'C' && s[1] == 'E' && s[2] >= 28){ n = getcontin(root->xf->d, s, &s); continue; } else if(s[0] == 'R' && s[1] == 'R'){ if(!norock) root->xf->isrock = 1; break; } else if(s[0] == 'S' && s[1] == 'T') break; } } } if(root->xf->isrock) chat("Rock Ridge..."); fp->offset = 0; fp->doffset = 0; return 0;}static voidiclone(Xfile *of, Xfile *nf){ USED(of, nf);}static voidiwalkup(Xfile *f){ long paddr; uchar dbuf[256]; Drec *d = (Drec *)dbuf; Xfile pf, ppf; Isofile piso, ppiso; memset(&pf, 0, sizeof pf); memset(&ppf, 0, sizeof ppf); pf.ptr = &piso; ppf.ptr = &ppiso; if(opendotdot(f, &pf) < 0) error("can't open pf"); paddr = l32(pf.ptr->d.addr); if(l32(f->ptr->d.addr) == paddr) return; if(opendotdot(&pf, &ppf) < 0) error("can't open ppf"); while(getdrec(&ppf, d) >= 0){ if(l32(d->addr) == paddr){ newdrec(f, d); f->qid.path = paddr; f->qid.type = QTDIR; return; } } error("can't find addr of ..");}static intcasestrcmp(int isplan9, char *a, char *b){ int ca, cb; if(isplan9) return strcmp(a, b); for(;;) { ca = *a++; cb = *b++; if(ca >= 'A' && ca <= 'Z') ca += 'a' - 'A'; if(cb >= 'A' && cb <= 'Z') cb += 'a' - 'A'; if(ca != cb) { if(ca > cb) return 1; return -1; } if(ca == 0) return 0; }}static voidiwalk(Xfile *f, char *name){ Isofile *ip = f->ptr; uchar dbuf[256]; char nbuf[4*Maxname]; Drec *d = (Drec*)dbuf; Dir dir; char *p; int len, vers, dvers; vers = -1; if(p = strchr(name, ';')) { /* assign = */ len = p-name; if(len >= Maxname) len = Maxname-1; memmove(nbuf, name, len); vers = strtoul(p+1, 0, 10); name = nbuf; }/* len = strlen(name); if(len >= Maxname){ len = Maxname-1; if(name != nbuf){ memmove(nbuf, name, len); name = nbuf; } name[len] = 0; }*/ chat("%d \"%s\"...", strlen(name), name); ip->offset = 0; setnames(&dir, nbuf); while(getdrec(f, d) >= 0) { dvers = rzdir(f->xf, &dir, ip->fmt, d); if(casestrcmp(f->xf->isplan9||f->xf->isrock, name, dir.name) != 0) continue; newdrec(f, d); f->qid.path = dir.qid.path; f->qid.type = dir.qid.type; USED(dvers); return; } USED(vers); error(Enonexist);}static voidiopen(Xfile *f, int mode){ mode &= ~OCEXEC; if(mode != OREAD && mode != OEXEC) error(Eperm); f->ptr->offset = 0; f->ptr->doffset = 0;}static voidicreate(Xfile *f, char *name, long perm, int mode){ USED(f, name, perm, mode); error(Eperm);}static longireaddir(Xfile *f, uchar *buf, long offset, long count){ Isofile *ip = f->ptr; Dir d; char names[4*Maxname]; uchar dbuf[256]; Drec *drec = (Drec *)dbuf; int n, rcnt; if(offset==0){ ip->offset = 0; ip->doffset = 0; }else if(offset != ip->doffset) error("seek in directory not allowed"); rcnt = 0; setnames(&d, names); while(rcnt < count && getdrec(f, drec) >= 0){ if(drec->namelen == 1){ if(drec->name[0] == 0) continue; if(drec->name[0] == 1) continue; } rzdir(f->xf, &d, ip->fmt, drec); d.qid.vers = f->qid.vers; if((n = convD2M(&d, buf+rcnt, count-rcnt)) <= BIT16SZ){ ungetdrec(f); break; } rcnt += n; } ip->doffset += rcnt; return rcnt;}static longiread(Xfile *f, char *buf, long offset, long count){ Isofile *ip = f->ptr; long size, addr, o, n; int rcnt = 0; Iobuf *p; size = l32(ip->d.size); if(offset >= size) return 0; if(offset+count > size) count = size - offset; addr = (l32(ip->d.addr)+ip->d.attrlen)*ip->blksize + offset; o = (ulong)addr % Sectorsize; addr = (ulong)addr / Sectorsize; /*chat("d.addr=0x%x, addr=0x%x, o=0x%x...", l32(ip->d.addr), addr, o);*/ n = Sectorsize - o; while(count > 0){ if(n > count) n = count; p = getbuf(f->xf->d, addr); memmove(&buf[rcnt], &p->iobuf[o], n); putbuf(p); count -= n; rcnt += n; ++addr; o = 0; n = Sectorsize; } return rcnt;}static longiwrite(Xfile *f, char *buf, long offset, long count){ USED(f, buf, offset, count); error(Eperm); return 0;}static voidiclunk(Xfile *f){ USED(f);}static voidiremove(Xfile *f){ USED(f); error(Eperm);}static voidistat(Xfile *f, Dir *d){ Isofile *ip = f->ptr; rzdir(f->xf, d, ip->fmt, &ip->d); d->qid.vers = f->qid.vers; if(d->qid.path==f->xf->rootqid.path){ d->qid.path = 0; d->qid.type = QTDIR; }}static voidiwstat(Xfile *f, Dir *d){ USED(f, d); error(Eperm);}static intshowdrec(int fd, int fmt, void *x){ Drec *d = (Drec *)x; int namelen; int syslen;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -