180ee5cbfSDavid du Colombier #include <u.h> 280ee5cbfSDavid du Colombier #include <libc.h> 380ee5cbfSDavid du Colombier #include <bio.h> 480ee5cbfSDavid du Colombier #include <libsec.h> 580ee5cbfSDavid du Colombier 680ee5cbfSDavid du Colombier #include "iso9660.h" 780ee5cbfSDavid du Colombier 880ee5cbfSDavid du Colombier static int readisodesc(Cdimg*, Voldesc*); 980ee5cbfSDavid du Colombier static int readjolietdesc(Cdimg*, Voldesc*); 1080ee5cbfSDavid du Colombier 1180ee5cbfSDavid du Colombier /* 1280ee5cbfSDavid du Colombier * It's not strictly conforming; instead it's enough to 1380ee5cbfSDavid du Colombier * get us up and running; presumably the real CD writing 1480ee5cbfSDavid du Colombier * will take care of being conforming. 1580ee5cbfSDavid du Colombier * 1680ee5cbfSDavid du Colombier * Things not conforming include: 1780ee5cbfSDavid du Colombier * - no path table 1880ee5cbfSDavid du Colombier * - root directories are of length zero 1980ee5cbfSDavid du Colombier */ 2080ee5cbfSDavid du Colombier Cdimg* 2180ee5cbfSDavid du Colombier createcd(char *file, Cdinfo info) 2280ee5cbfSDavid du Colombier { 2380ee5cbfSDavid du Colombier int fd, xfd; 2480ee5cbfSDavid du Colombier Cdimg *cd; 2580ee5cbfSDavid du Colombier 2680ee5cbfSDavid du Colombier if(access(file, AEXIST) == 0){ 2780ee5cbfSDavid du Colombier werrstr("file already exists"); 2880ee5cbfSDavid du Colombier return nil; 2980ee5cbfSDavid du Colombier } 3080ee5cbfSDavid du Colombier 3180ee5cbfSDavid du Colombier if((fd = create(file, ORDWR, 0666)) < 0) 3280ee5cbfSDavid du Colombier return nil; 3380ee5cbfSDavid du Colombier 3480ee5cbfSDavid du Colombier cd = emalloc(sizeof *cd); 3580ee5cbfSDavid du Colombier cd->file = atom(file); 3680ee5cbfSDavid du Colombier 3780ee5cbfSDavid du Colombier Binit(&cd->brd, fd, OREAD); 3880ee5cbfSDavid du Colombier 3980ee5cbfSDavid du Colombier if((xfd = open(file, ORDWR)) < 0) 4080ee5cbfSDavid du Colombier sysfatal("can't open file again: %r"); 4180ee5cbfSDavid du Colombier Binit(&cd->bwr, xfd, OWRITE); 4280ee5cbfSDavid du Colombier 4380ee5cbfSDavid du Colombier Crepeat(cd, 0, 16*Blocksize); 4480ee5cbfSDavid du Colombier Cputisopvd(cd, info); 459a747e4fSDavid du Colombier if(info.flags & CDbootable){ 469a747e4fSDavid du Colombier cd->bootimage = info.bootimage; 4743751f27SDavid du Colombier cd->flags |= info.flags & (CDbootable|CDbootnoemu); 489a747e4fSDavid du Colombier Cputbootvol(cd); 499a747e4fSDavid du Colombier } 5080ee5cbfSDavid du Colombier 5180ee5cbfSDavid du Colombier if(readisodesc(cd, &cd->iso) < 0) 5280ee5cbfSDavid du Colombier assert(0); 5380ee5cbfSDavid du Colombier if(info.flags & CDplan9) 5480ee5cbfSDavid du Colombier cd->flags |= CDplan9; 5580ee5cbfSDavid du Colombier else if(info.flags & CDrockridge) 5680ee5cbfSDavid du Colombier cd->flags |= CDrockridge; 5780ee5cbfSDavid du Colombier if(info.flags & CDjoliet) { 5880ee5cbfSDavid du Colombier Cputjolietsvd(cd, info); 5980ee5cbfSDavid du Colombier if(readjolietdesc(cd, &cd->joliet) < 0) 6080ee5cbfSDavid du Colombier assert(0); 6180ee5cbfSDavid du Colombier cd->flags |= CDjoliet; 6280ee5cbfSDavid du Colombier } 6380ee5cbfSDavid du Colombier Cputendvd(cd); 6480ee5cbfSDavid du Colombier 6580ee5cbfSDavid du Colombier if(info.flags & CDdump){ 6680ee5cbfSDavid du Colombier cd->nulldump = Cputdumpblock(cd); 6780ee5cbfSDavid du Colombier cd->flags |= CDdump; 6880ee5cbfSDavid du Colombier } 699a747e4fSDavid du Colombier if(cd->flags & CDbootable){ 709a747e4fSDavid du Colombier Cputbootcat(cd); 719a747e4fSDavid du Colombier Cupdatebootvol(cd); 729a747e4fSDavid du Colombier } 7380ee5cbfSDavid du Colombier 7480ee5cbfSDavid du Colombier if(info.flags & CDconform) 7580ee5cbfSDavid du Colombier cd->flags |= CDconform; 7680ee5cbfSDavid du Colombier 7780ee5cbfSDavid du Colombier cd->flags |= CDnew; 7880ee5cbfSDavid du Colombier cd->nextblock = Cwoffset(cd) / Blocksize; 7980ee5cbfSDavid du Colombier assert(cd->nextblock != 0); 8080ee5cbfSDavid du Colombier 8180ee5cbfSDavid du Colombier return cd; 8280ee5cbfSDavid du Colombier } 8380ee5cbfSDavid du Colombier 8480ee5cbfSDavid du Colombier Cdimg* 8580ee5cbfSDavid du Colombier opencd(char *file, Cdinfo info) 8680ee5cbfSDavid du Colombier { 8780ee5cbfSDavid du Colombier int fd, xfd; 8880ee5cbfSDavid du Colombier Cdimg *cd; 899a747e4fSDavid du Colombier Dir *d; 9080ee5cbfSDavid du Colombier 9180ee5cbfSDavid du Colombier if((fd = open(file, ORDWR)) < 0) { 9280ee5cbfSDavid du Colombier if(access(file, AEXIST) == 0) 9380ee5cbfSDavid du Colombier return nil; 9480ee5cbfSDavid du Colombier return createcd(file, info); 9580ee5cbfSDavid du Colombier } 9680ee5cbfSDavid du Colombier 979a747e4fSDavid du Colombier if((d = dirfstat(fd)) == nil) { 9880ee5cbfSDavid du Colombier close(fd); 9980ee5cbfSDavid du Colombier return nil; 10080ee5cbfSDavid du Colombier } 1019a747e4fSDavid du Colombier if(d->length == 0 || d->length % Blocksize) { 1029a747e4fSDavid du Colombier werrstr("bad length %lld", d->length); 10380ee5cbfSDavid du Colombier close(fd); 1049a747e4fSDavid du Colombier free(d); 10580ee5cbfSDavid du Colombier return nil; 10680ee5cbfSDavid du Colombier } 10780ee5cbfSDavid du Colombier 10880ee5cbfSDavid du Colombier cd = emalloc(sizeof *cd); 10980ee5cbfSDavid du Colombier cd->file = atom(file); 1109a747e4fSDavid du Colombier cd->nextblock = d->length / Blocksize; 11180ee5cbfSDavid du Colombier assert(cd->nextblock != 0); 1129a747e4fSDavid du Colombier free(d); 11380ee5cbfSDavid du Colombier 11480ee5cbfSDavid du Colombier Binit(&cd->brd, fd, OREAD); 11580ee5cbfSDavid du Colombier 11680ee5cbfSDavid du Colombier if((xfd = open(file, ORDWR)) < 0) 11780ee5cbfSDavid du Colombier sysfatal("can't open file again: %r"); 11880ee5cbfSDavid du Colombier Binit(&cd->bwr, xfd, OWRITE); 11980ee5cbfSDavid du Colombier 12080ee5cbfSDavid du Colombier if(readisodesc(cd, &cd->iso) < 0) { 12180ee5cbfSDavid du Colombier free(cd); 12280ee5cbfSDavid du Colombier close(fd); 12380ee5cbfSDavid du Colombier close(xfd); 12480ee5cbfSDavid du Colombier return nil; 12580ee5cbfSDavid du Colombier } 12680ee5cbfSDavid du Colombier 12780ee5cbfSDavid du Colombier /* lowercase because of isostring */ 12880ee5cbfSDavid du Colombier if(strstr(cd->iso.systemid, "iso9660") == nil 12980ee5cbfSDavid du Colombier && strstr(cd->iso.systemid, "utf8") == nil) { 13080ee5cbfSDavid du Colombier werrstr("unknown systemid %s", cd->iso.systemid); 13180ee5cbfSDavid du Colombier free(cd); 13280ee5cbfSDavid du Colombier close(fd); 13380ee5cbfSDavid du Colombier close(xfd); 13480ee5cbfSDavid du Colombier return nil; 13580ee5cbfSDavid du Colombier } 13680ee5cbfSDavid du Colombier 13780ee5cbfSDavid du Colombier if(strstr(cd->iso.systemid, "plan 9")) 13880ee5cbfSDavid du Colombier cd->flags |= CDplan9; 13980ee5cbfSDavid du Colombier if(strstr(cd->iso.systemid, "iso9660")) 14080ee5cbfSDavid du Colombier cd->flags |= CDconform; 14180ee5cbfSDavid du Colombier if(strstr(cd->iso.systemid, "rrip")) 14280ee5cbfSDavid du Colombier cd->flags |= CDrockridge; 1439a747e4fSDavid du Colombier if(strstr(cd->iso.systemid, "boot")) 1449a747e4fSDavid du Colombier cd->flags |= CDbootable; 14580ee5cbfSDavid du Colombier if(readjolietdesc(cd, &cd->joliet) == 0) 14680ee5cbfSDavid du Colombier cd->flags |= CDjoliet; 14780ee5cbfSDavid du Colombier if(hasdump(cd)) 14880ee5cbfSDavid du Colombier cd->flags |= CDdump; 14980ee5cbfSDavid du Colombier 15080ee5cbfSDavid du Colombier return cd; 15180ee5cbfSDavid du Colombier } 15280ee5cbfSDavid du Colombier 15380ee5cbfSDavid du Colombier ulong 15480ee5cbfSDavid du Colombier big(void *a, int n) 15580ee5cbfSDavid du Colombier { 15680ee5cbfSDavid du Colombier uchar *p; 15780ee5cbfSDavid du Colombier ulong v; 15880ee5cbfSDavid du Colombier int i; 15980ee5cbfSDavid du Colombier 16080ee5cbfSDavid du Colombier p = a; 16180ee5cbfSDavid du Colombier v = 0; 16280ee5cbfSDavid du Colombier for(i=0; i<n; i++) 16380ee5cbfSDavid du Colombier v = (v<<8) | *p++; 16480ee5cbfSDavid du Colombier return v; 16580ee5cbfSDavid du Colombier } 16680ee5cbfSDavid du Colombier 16780ee5cbfSDavid du Colombier ulong 16880ee5cbfSDavid du Colombier little(void *a, int n) 16980ee5cbfSDavid du Colombier { 17080ee5cbfSDavid du Colombier uchar *p; 17180ee5cbfSDavid du Colombier ulong v; 17280ee5cbfSDavid du Colombier int i; 17380ee5cbfSDavid du Colombier 17480ee5cbfSDavid du Colombier p = a; 17580ee5cbfSDavid du Colombier v = 0; 17680ee5cbfSDavid du Colombier for(i=0; i<n; i++) 17780ee5cbfSDavid du Colombier v |= (*p++<<(i*8)); 17880ee5cbfSDavid du Colombier return v; 17980ee5cbfSDavid du Colombier } 18080ee5cbfSDavid du Colombier 18180ee5cbfSDavid du Colombier void 18280ee5cbfSDavid du Colombier Creadblock(Cdimg *cd, void *buf, ulong block, ulong len) 18380ee5cbfSDavid du Colombier { 18480ee5cbfSDavid du Colombier assert(block != 0); /* nothing useful there */ 18580ee5cbfSDavid du Colombier 18680ee5cbfSDavid du Colombier Bflush(&cd->bwr); 18773ee67a1SDavid du Colombier if(Bseek(&cd->brd, (vlong)block * Blocksize, 0) != 18873ee67a1SDavid du Colombier (vlong)block * Blocksize) 18980ee5cbfSDavid du Colombier sysfatal("error seeking to block %lud", block); 19080ee5cbfSDavid du Colombier if(Bread(&cd->brd, buf, len) != len) 19173ee67a1SDavid du Colombier sysfatal("error reading %lud bytes at block %lud: %r %lld", 19273ee67a1SDavid du Colombier len, block, Bseek(&cd->brd, 0, 2)); 19380ee5cbfSDavid du Colombier } 19480ee5cbfSDavid du Colombier 19580ee5cbfSDavid du Colombier int 19680ee5cbfSDavid du Colombier parsedir(Cdimg *cd, Direc *d, uchar *buf, int len, char *(*cvtname)(uchar*, int)) 19780ee5cbfSDavid du Colombier { 1989a747e4fSDavid du Colombier enum { NAMELEN = 28 }; 19980ee5cbfSDavid du Colombier char name[NAMELEN]; 20080ee5cbfSDavid du Colombier uchar *p; 20180ee5cbfSDavid du Colombier Cdir *c; 20280ee5cbfSDavid du Colombier 20380ee5cbfSDavid du Colombier memset(d, 0, sizeof *d); 20480ee5cbfSDavid du Colombier 20580ee5cbfSDavid du Colombier c = (Cdir*)buf; 20680ee5cbfSDavid du Colombier 20780ee5cbfSDavid du Colombier if(c->len > len) { 20880ee5cbfSDavid du Colombier werrstr("buffer too small"); 20980ee5cbfSDavid du Colombier return -1; 21080ee5cbfSDavid du Colombier } 21180ee5cbfSDavid du Colombier 21280ee5cbfSDavid du Colombier if(c->namelen == 1 && c->name[0] == '\0') 21380ee5cbfSDavid du Colombier d->name = atom("."); 21480ee5cbfSDavid du Colombier else if(c->namelen == 1 && c->name[0] == '\001') 21580ee5cbfSDavid du Colombier d->name = atom(".."); 21680ee5cbfSDavid du Colombier else if(cvtname) 21780ee5cbfSDavid du Colombier d->name = cvtname(c->name, c->namelen); 21880ee5cbfSDavid du Colombier 21980ee5cbfSDavid du Colombier d->block = little(c->dloc, 4); 22080ee5cbfSDavid du Colombier d->length = little(c->dlen, 4); 22180ee5cbfSDavid du Colombier 22280ee5cbfSDavid du Colombier if(c->flags & 2) 2239a747e4fSDavid du Colombier d->mode |= DMDIR; 22480ee5cbfSDavid du Colombier 22580ee5cbfSDavid du Colombier /*BUG: do we really need to parse the plan 9 fields? */ 22680ee5cbfSDavid du Colombier /* plan 9 use fields */ 22780ee5cbfSDavid du Colombier if((cd->flags & CDplan9) && cvtname == isostring 22880ee5cbfSDavid du Colombier && (c->namelen != 1 || c->name[0] > 1)) { 22980ee5cbfSDavid du Colombier p = buf+33+c->namelen; 23080ee5cbfSDavid du Colombier if((p-buf)&1) 23180ee5cbfSDavid du Colombier p++; 23280ee5cbfSDavid du Colombier assert(p < buf+c->len); 23380ee5cbfSDavid du Colombier assert(*p < NAMELEN); 23480ee5cbfSDavid du Colombier if(*p != 0) { 23580ee5cbfSDavid du Colombier memmove(name, p+1, *p); 23680ee5cbfSDavid du Colombier name[*p] = '\0'; 23780ee5cbfSDavid du Colombier d->confname = d->name; 23880ee5cbfSDavid du Colombier d->name = atom(name); 23980ee5cbfSDavid du Colombier } 24080ee5cbfSDavid du Colombier p += *p+1; 24180ee5cbfSDavid du Colombier assert(*p < NAMELEN); 24280ee5cbfSDavid du Colombier memmove(name, p+1, *p); 24380ee5cbfSDavid du Colombier name[*p] = '\0'; 24480ee5cbfSDavid du Colombier d->uid = atom(name); 24580ee5cbfSDavid du Colombier p += *p+1; 24680ee5cbfSDavid du Colombier assert(*p < NAMELEN); 24780ee5cbfSDavid du Colombier memmove(name, p+1, *p); 24880ee5cbfSDavid du Colombier name[*p] = '\0'; 24980ee5cbfSDavid du Colombier d->gid = atom(name); 25080ee5cbfSDavid du Colombier p += *p+1; 25180ee5cbfSDavid du Colombier if((p-buf)&1) 25280ee5cbfSDavid du Colombier p++; 25380ee5cbfSDavid du Colombier d->mode = little(p, 4); 25480ee5cbfSDavid du Colombier } 25580ee5cbfSDavid du Colombier 25680ee5cbfSDavid du Colombier // BUG: rock ridge extensions 25780ee5cbfSDavid du Colombier return 0; 25880ee5cbfSDavid du Colombier } 25980ee5cbfSDavid du Colombier 26080ee5cbfSDavid du Colombier void 26180ee5cbfSDavid du Colombier setroot(Cdimg *cd, ulong block, ulong dloc, ulong dlen) 26280ee5cbfSDavid du Colombier { 26380ee5cbfSDavid du Colombier assert(block != 0); 26480ee5cbfSDavid du Colombier 26573ee67a1SDavid du Colombier Cwseek(cd, (vlong)block * Blocksize + offsetof(Cvoldesc, rootdir[0]) + 26673ee67a1SDavid du Colombier offsetof(Cdir, dloc[0])); 26780ee5cbfSDavid du Colombier Cputn(cd, dloc, 4); 26880ee5cbfSDavid du Colombier Cputn(cd, dlen, 4); 26980ee5cbfSDavid du Colombier } 27080ee5cbfSDavid du Colombier 27180ee5cbfSDavid du Colombier void 272*3e33a36fSDavid du Colombier setvolsize(Cdimg *cd, uvlong block, ulong size) 27380ee5cbfSDavid du Colombier { 27480ee5cbfSDavid du Colombier assert(block != 0); 27580ee5cbfSDavid du Colombier 276*3e33a36fSDavid du Colombier Cwseek(cd, block * Blocksize + offsetof(Cvoldesc, volsize[0])); 27780ee5cbfSDavid du Colombier Cputn(cd, size, 4); 27880ee5cbfSDavid du Colombier } 27980ee5cbfSDavid du Colombier 28080ee5cbfSDavid du Colombier void 28180ee5cbfSDavid du Colombier setpathtable(Cdimg *cd, ulong block, ulong sz, ulong lloc, ulong bloc) 28280ee5cbfSDavid du Colombier { 28380ee5cbfSDavid du Colombier assert(block != 0); 28480ee5cbfSDavid du Colombier 28573ee67a1SDavid du Colombier Cwseek(cd, (vlong)block * Blocksize + offsetof(Cvoldesc, pathsize[0])); 28680ee5cbfSDavid du Colombier Cputn(cd, sz, 4); 28780ee5cbfSDavid du Colombier Cputnl(cd, lloc, 4); 28880ee5cbfSDavid du Colombier Cputnl(cd, 0, 4); 28980ee5cbfSDavid du Colombier Cputnm(cd, bloc, 4); 29080ee5cbfSDavid du Colombier Cputnm(cd, 0, 4); 29173ee67a1SDavid du Colombier assert(Cwoffset(cd) == (vlong)block * Blocksize + 29273ee67a1SDavid du Colombier offsetof(Cvoldesc, rootdir[0])); 29380ee5cbfSDavid du Colombier } 29480ee5cbfSDavid du Colombier 29580ee5cbfSDavid du Colombier 29680ee5cbfSDavid du Colombier static void 29780ee5cbfSDavid du Colombier parsedesc(Voldesc *v, Cvoldesc *cv, char *(*string)(uchar*, int)) 29880ee5cbfSDavid du Colombier { 29980ee5cbfSDavid du Colombier v->systemid = string(cv->systemid, sizeof cv->systemid); 30080ee5cbfSDavid du Colombier 30180ee5cbfSDavid du Colombier v->pathsize = little(cv->pathsize, 4); 30280ee5cbfSDavid du Colombier v->lpathloc = little(cv->lpathloc, 4); 30380ee5cbfSDavid du Colombier v->mpathloc = little(cv->mpathloc, 4); 30480ee5cbfSDavid du Colombier 30580ee5cbfSDavid du Colombier v->volumeset = string(cv->volumeset, sizeof cv->volumeset); 30680ee5cbfSDavid du Colombier v->publisher = string(cv->publisher, sizeof cv->publisher); 30780ee5cbfSDavid du Colombier v->preparer = string(cv->preparer, sizeof cv->preparer); 30880ee5cbfSDavid du Colombier v->application = string(cv->application, sizeof cv->application); 30980ee5cbfSDavid du Colombier 31080ee5cbfSDavid du Colombier v->abstract = string(cv->abstract, sizeof cv->abstract); 31180ee5cbfSDavid du Colombier v->biblio = string(cv->biblio, sizeof cv->biblio); 31280ee5cbfSDavid du Colombier v->notice = string(cv->notice, sizeof cv->notice); 31380ee5cbfSDavid du Colombier } 31480ee5cbfSDavid du Colombier 31580ee5cbfSDavid du Colombier static int 31680ee5cbfSDavid du Colombier readisodesc(Cdimg *cd, Voldesc *v) 31780ee5cbfSDavid du Colombier { 31880ee5cbfSDavid du Colombier static uchar magic[] = { 0x01, 'C', 'D', '0', '0', '1', 0x01, 0x00 }; 31980ee5cbfSDavid du Colombier Cvoldesc cv; 32080ee5cbfSDavid du Colombier 32180ee5cbfSDavid du Colombier memset(v, 0, sizeof *v); 32280ee5cbfSDavid du Colombier 32380ee5cbfSDavid du Colombier Creadblock(cd, &cv, 16, sizeof cv); 32480ee5cbfSDavid du Colombier if(memcmp(cv.magic, magic, sizeof magic) != 0) { 32580ee5cbfSDavid du Colombier werrstr("bad pvd magic"); 32680ee5cbfSDavid du Colombier return -1; 32780ee5cbfSDavid du Colombier } 32880ee5cbfSDavid du Colombier 32980ee5cbfSDavid du Colombier if(little(cv.blocksize, 2) != Blocksize) { 33080ee5cbfSDavid du Colombier werrstr("block size not %d", Blocksize); 33180ee5cbfSDavid du Colombier return -1; 33280ee5cbfSDavid du Colombier } 33380ee5cbfSDavid du Colombier 33480ee5cbfSDavid du Colombier cd->iso9660pvd = 16; 33580ee5cbfSDavid du Colombier parsedesc(v, &cv, isostring); 33680ee5cbfSDavid du Colombier 33780ee5cbfSDavid du Colombier return parsedir(cd, &v->root, cv.rootdir, sizeof cv.rootdir, isostring); 33880ee5cbfSDavid du Colombier } 33980ee5cbfSDavid du Colombier 34080ee5cbfSDavid du Colombier static int 34180ee5cbfSDavid du Colombier readjolietdesc(Cdimg *cd, Voldesc *v) 34280ee5cbfSDavid du Colombier { 34380ee5cbfSDavid du Colombier int i; 34480ee5cbfSDavid du Colombier static uchar magic[] = { 0x02, 'C', 'D', '0', '0', '1', 0x01, 0x00 }; 34580ee5cbfSDavid du Colombier Cvoldesc cv; 34680ee5cbfSDavid du Colombier 34780ee5cbfSDavid du Colombier memset(v, 0, sizeof *v); 34880ee5cbfSDavid du Colombier 34980ee5cbfSDavid du Colombier for(i=16; i<24; i++) { 35080ee5cbfSDavid du Colombier Creadblock(cd, &cv, i, sizeof cv); 35180ee5cbfSDavid du Colombier if(memcmp(cv.magic, magic, sizeof magic) != 0) 35280ee5cbfSDavid du Colombier continue; 35380ee5cbfSDavid du Colombier if(cv.charset[0] != 0x25 || cv.charset[1] != 0x2F 35480ee5cbfSDavid du Colombier || (cv.charset[2] != 0x40 && cv.charset[2] != 0x43 && cv.charset[2] != 0x45)) 35580ee5cbfSDavid du Colombier continue; 35680ee5cbfSDavid du Colombier break; 35780ee5cbfSDavid du Colombier } 35880ee5cbfSDavid du Colombier 35980ee5cbfSDavid du Colombier if(i==24) { 36080ee5cbfSDavid du Colombier werrstr("could not find Joliet SVD"); 36180ee5cbfSDavid du Colombier return -1; 36280ee5cbfSDavid du Colombier } 36380ee5cbfSDavid du Colombier 36480ee5cbfSDavid du Colombier if(little(cv.blocksize, 2) != Blocksize) { 36580ee5cbfSDavid du Colombier werrstr("block size not %d", Blocksize); 36680ee5cbfSDavid du Colombier return -1; 36780ee5cbfSDavid du Colombier } 36880ee5cbfSDavid du Colombier 36980ee5cbfSDavid du Colombier cd->jolietsvd = i; 37080ee5cbfSDavid du Colombier parsedesc(v, &cv, jolietstring); 37180ee5cbfSDavid du Colombier 37280ee5cbfSDavid du Colombier return parsedir(cd, &v->root, cv.rootdir, sizeof cv.rootdir, jolietstring); 37380ee5cbfSDavid du Colombier } 37480ee5cbfSDavid du Colombier 37580ee5cbfSDavid du Colombier /* 37680ee5cbfSDavid du Colombier * CD image buffering routines. 37780ee5cbfSDavid du Colombier */ 37880ee5cbfSDavid du Colombier void 37980ee5cbfSDavid du Colombier Cputc(Cdimg *cd, int c) 38080ee5cbfSDavid du Colombier { 38180ee5cbfSDavid du Colombier assert(Boffset(&cd->bwr) >= 16*Blocksize || c == 0); 38280ee5cbfSDavid du Colombier 38380ee5cbfSDavid du Colombier if(Boffset(&cd->bwr) == 0x9962) 38480ee5cbfSDavid du Colombier if(c >= 256) abort(); 38580ee5cbfSDavid du Colombier if(Bputc(&cd->bwr, c) < 0) 38680ee5cbfSDavid du Colombier sysfatal("Bputc: %r"); 38780ee5cbfSDavid du Colombier Bflush(&cd->brd); 38880ee5cbfSDavid du Colombier } 38980ee5cbfSDavid du Colombier 39080ee5cbfSDavid du Colombier void 391*3e33a36fSDavid du Colombier Cputnl(Cdimg *cd, uvlong val, int size) 39280ee5cbfSDavid du Colombier { 39380ee5cbfSDavid du Colombier switch(size) { 39480ee5cbfSDavid du Colombier default: 395*3e33a36fSDavid du Colombier sysfatal("bad size %d in Cputnl", size); 39680ee5cbfSDavid du Colombier case 2: 397*3e33a36fSDavid du Colombier if(val >= (1<<16)) 398*3e33a36fSDavid du Colombier sysfatal("value %llud too big for size %d in Cputnl", 399*3e33a36fSDavid du Colombier val, size); 40080ee5cbfSDavid du Colombier Cputc(cd, val); 40180ee5cbfSDavid du Colombier Cputc(cd, val>>8); 40280ee5cbfSDavid du Colombier break; 40380ee5cbfSDavid du Colombier case 4: 404*3e33a36fSDavid du Colombier if(val >= (1ULL<<32)) 405*3e33a36fSDavid du Colombier sysfatal("value %llud too big for size %d in Cputnl", 406*3e33a36fSDavid du Colombier val, size); 40780ee5cbfSDavid du Colombier Cputc(cd, val); 40880ee5cbfSDavid du Colombier Cputc(cd, val>>8); 40980ee5cbfSDavid du Colombier Cputc(cd, val>>16); 41080ee5cbfSDavid du Colombier Cputc(cd, val>>24); 41180ee5cbfSDavid du Colombier break; 412*3e33a36fSDavid du Colombier case 8: 413*3e33a36fSDavid du Colombier Cputc(cd, val); 414*3e33a36fSDavid du Colombier Cputc(cd, val>>8); 415*3e33a36fSDavid du Colombier Cputc(cd, val>>16); 416*3e33a36fSDavid du Colombier Cputc(cd, val>>24); 417*3e33a36fSDavid du Colombier Cputc(cd, val>>32); 418*3e33a36fSDavid du Colombier Cputc(cd, val>>40); 419*3e33a36fSDavid du Colombier Cputc(cd, val>>48); 420*3e33a36fSDavid du Colombier Cputc(cd, val>>56); 421*3e33a36fSDavid du Colombier break; 42280ee5cbfSDavid du Colombier } 42380ee5cbfSDavid du Colombier } 42480ee5cbfSDavid du Colombier 42580ee5cbfSDavid du Colombier void 426*3e33a36fSDavid du Colombier Cputnm(Cdimg *cd, uvlong val, int size) 42780ee5cbfSDavid du Colombier { 42880ee5cbfSDavid du Colombier switch(size) { 42980ee5cbfSDavid du Colombier default: 430*3e33a36fSDavid du Colombier sysfatal("bad size %d in Cputnm", size); 43180ee5cbfSDavid du Colombier case 2: 432*3e33a36fSDavid du Colombier if(val >= (1<<16)) 433*3e33a36fSDavid du Colombier sysfatal("value %llud too big for size %d in Cputnl", 434*3e33a36fSDavid du Colombier val, size); 43580ee5cbfSDavid du Colombier Cputc(cd, val>>8); 43680ee5cbfSDavid du Colombier Cputc(cd, val); 43780ee5cbfSDavid du Colombier break; 43880ee5cbfSDavid du Colombier case 4: 439*3e33a36fSDavid du Colombier if(val >= (1ULL<<32)) 440*3e33a36fSDavid du Colombier sysfatal("value %llud too big for size %d in Cputnl", 441*3e33a36fSDavid du Colombier val, size); 442*3e33a36fSDavid du Colombier Cputc(cd, val>>24); 443*3e33a36fSDavid du Colombier Cputc(cd, val>>16); 444*3e33a36fSDavid du Colombier Cputc(cd, val>>8); 445*3e33a36fSDavid du Colombier Cputc(cd, val); 446*3e33a36fSDavid du Colombier break; 447*3e33a36fSDavid du Colombier case 8: 448*3e33a36fSDavid du Colombier Cputc(cd, val>>56); 449*3e33a36fSDavid du Colombier Cputc(cd, val>>48); 450*3e33a36fSDavid du Colombier Cputc(cd, val>>40); 451*3e33a36fSDavid du Colombier Cputc(cd, val>>32); 45280ee5cbfSDavid du Colombier Cputc(cd, val>>24); 45380ee5cbfSDavid du Colombier Cputc(cd, val>>16); 45480ee5cbfSDavid du Colombier Cputc(cd, val>>8); 45580ee5cbfSDavid du Colombier Cputc(cd, val); 45680ee5cbfSDavid du Colombier break; 45780ee5cbfSDavid du Colombier } 45880ee5cbfSDavid du Colombier } 45980ee5cbfSDavid du Colombier 46080ee5cbfSDavid du Colombier void 461*3e33a36fSDavid du Colombier Cputn(Cdimg *cd, uvlong val, int size) 46280ee5cbfSDavid du Colombier { 46380ee5cbfSDavid du Colombier Cputnl(cd, val, size); 46480ee5cbfSDavid du Colombier Cputnm(cd, val, size); 46580ee5cbfSDavid du Colombier } 46680ee5cbfSDavid du Colombier 46780ee5cbfSDavid du Colombier /* 46880ee5cbfSDavid du Colombier * ASCII/UTF string writing 46980ee5cbfSDavid du Colombier */ 47080ee5cbfSDavid du Colombier void 47180ee5cbfSDavid du Colombier Crepeat(Cdimg *cd, int c, int n) 47280ee5cbfSDavid du Colombier { 47380ee5cbfSDavid du Colombier while(n-- > 0) 47480ee5cbfSDavid du Colombier Cputc(cd, c); 47580ee5cbfSDavid du Colombier } 47680ee5cbfSDavid du Colombier 47780ee5cbfSDavid du Colombier void 47880ee5cbfSDavid du Colombier Cputs(Cdimg *cd, char *s, int size) 47980ee5cbfSDavid du Colombier { 48080ee5cbfSDavid du Colombier int n; 48180ee5cbfSDavid du Colombier 48280ee5cbfSDavid du Colombier if(s == nil) { 48380ee5cbfSDavid du Colombier Crepeat(cd, ' ', size); 48480ee5cbfSDavid du Colombier return; 48580ee5cbfSDavid du Colombier } 48680ee5cbfSDavid du Colombier 48780ee5cbfSDavid du Colombier for(n=0; n<size && *s; n++) 48880ee5cbfSDavid du Colombier Cputc(cd, *s++); 48980ee5cbfSDavid du Colombier if(n<size) 49080ee5cbfSDavid du Colombier Crepeat(cd, ' ', size-n); 49180ee5cbfSDavid du Colombier } 49280ee5cbfSDavid du Colombier 49380ee5cbfSDavid du Colombier void 49480ee5cbfSDavid du Colombier Cwrite(Cdimg *cd, void *buf, int n) 49580ee5cbfSDavid du Colombier { 49680ee5cbfSDavid du Colombier assert(Boffset(&cd->bwr) >= 16*Blocksize); 49780ee5cbfSDavid du Colombier 49880ee5cbfSDavid du Colombier if(Bwrite(&cd->bwr, buf, n) != n) 49980ee5cbfSDavid du Colombier sysfatal("Bwrite: %r"); 50080ee5cbfSDavid du Colombier Bflush(&cd->brd); 50180ee5cbfSDavid du Colombier } 50280ee5cbfSDavid du Colombier 50380ee5cbfSDavid du Colombier void 50480ee5cbfSDavid du Colombier Cputr(Cdimg *cd, Rune r) 50580ee5cbfSDavid du Colombier { 50680ee5cbfSDavid du Colombier Cputc(cd, r>>8); 50780ee5cbfSDavid du Colombier Cputc(cd, r); 50880ee5cbfSDavid du Colombier } 50980ee5cbfSDavid du Colombier 51080ee5cbfSDavid du Colombier void 51180ee5cbfSDavid du Colombier Crepeatr(Cdimg *cd, Rune r, int n) 51280ee5cbfSDavid du Colombier { 51380ee5cbfSDavid du Colombier int i; 51480ee5cbfSDavid du Colombier 51580ee5cbfSDavid du Colombier for(i=0; i<n; i++) 51680ee5cbfSDavid du Colombier Cputr(cd, r); 51780ee5cbfSDavid du Colombier } 51880ee5cbfSDavid du Colombier 51980ee5cbfSDavid du Colombier void 52080ee5cbfSDavid du Colombier Cputrs(Cdimg *cd, Rune *s, int osize) 52180ee5cbfSDavid du Colombier { 52280ee5cbfSDavid du Colombier int n, size; 52380ee5cbfSDavid du Colombier 52480ee5cbfSDavid du Colombier size = osize/2; 52580ee5cbfSDavid du Colombier if(s == nil) 52680ee5cbfSDavid du Colombier Crepeatr(cd, (Rune)' ', size); 52780ee5cbfSDavid du Colombier else { 52880ee5cbfSDavid du Colombier for(n=0; *s && n<size; n++) 52980ee5cbfSDavid du Colombier Cputr(cd, *s++); 53080ee5cbfSDavid du Colombier if(n<size) 53180ee5cbfSDavid du Colombier Crepeatr(cd, ' ', size-n); 53280ee5cbfSDavid du Colombier } 53380ee5cbfSDavid du Colombier if(osize&1) 53480ee5cbfSDavid du Colombier Cputc(cd, 0); /* what else can we do? */ 53580ee5cbfSDavid du Colombier } 53680ee5cbfSDavid du Colombier 53780ee5cbfSDavid du Colombier void 53880ee5cbfSDavid du Colombier Cputrscvt(Cdimg *cd, char *s, int size) 53980ee5cbfSDavid du Colombier { 54080ee5cbfSDavid du Colombier Rune r[256]; 54180ee5cbfSDavid du Colombier 54280ee5cbfSDavid du Colombier strtorune(r, s); 54380ee5cbfSDavid du Colombier Cputrs(cd, strtorune(r, s), size); 54480ee5cbfSDavid du Colombier } 54580ee5cbfSDavid du Colombier 54680ee5cbfSDavid du Colombier void 54780ee5cbfSDavid du Colombier Cpadblock(Cdimg *cd) 54880ee5cbfSDavid du Colombier { 54980ee5cbfSDavid du Colombier int n; 55080ee5cbfSDavid du Colombier ulong nb; 55180ee5cbfSDavid du Colombier 55280ee5cbfSDavid du Colombier n = Blocksize - (Boffset(&cd->bwr) % Blocksize); 55380ee5cbfSDavid du Colombier if(n != Blocksize) 55480ee5cbfSDavid du Colombier Crepeat(cd, 0, n); 55580ee5cbfSDavid du Colombier 55680ee5cbfSDavid du Colombier nb = Boffset(&cd->bwr)/Blocksize; 55780ee5cbfSDavid du Colombier assert(nb != 0); 55880ee5cbfSDavid du Colombier if(nb > cd->nextblock) 55980ee5cbfSDavid du Colombier cd->nextblock = nb; 56080ee5cbfSDavid du Colombier } 56180ee5cbfSDavid du Colombier 56280ee5cbfSDavid du Colombier void 56380ee5cbfSDavid du Colombier Cputdate(Cdimg *cd, ulong ust) 56480ee5cbfSDavid du Colombier { 56580ee5cbfSDavid du Colombier Tm *tm; 56680ee5cbfSDavid du Colombier 56780ee5cbfSDavid du Colombier if(ust == 0) { 56880ee5cbfSDavid du Colombier Crepeat(cd, 0, 7); 56980ee5cbfSDavid du Colombier return; 57080ee5cbfSDavid du Colombier } 57180ee5cbfSDavid du Colombier tm = gmtime(ust); 57280ee5cbfSDavid du Colombier Cputc(cd, tm->year); 57380ee5cbfSDavid du Colombier Cputc(cd, tm->mon+1); 57480ee5cbfSDavid du Colombier Cputc(cd, tm->mday); 57580ee5cbfSDavid du Colombier Cputc(cd, tm->hour); 57680ee5cbfSDavid du Colombier Cputc(cd, tm->min); 57780ee5cbfSDavid du Colombier Cputc(cd, tm->sec); 57880ee5cbfSDavid du Colombier Cputc(cd, 0); 57980ee5cbfSDavid du Colombier } 58080ee5cbfSDavid du Colombier 58180ee5cbfSDavid du Colombier void 58280ee5cbfSDavid du Colombier Cputdate1(Cdimg *cd, ulong ust) 58380ee5cbfSDavid du Colombier { 58480ee5cbfSDavid du Colombier Tm *tm; 58580ee5cbfSDavid du Colombier char str[20]; 58680ee5cbfSDavid du Colombier 58780ee5cbfSDavid du Colombier if(ust == 0) { 58880ee5cbfSDavid du Colombier Crepeat(cd, '0', 16); 58980ee5cbfSDavid du Colombier Cputc(cd, 0); 59080ee5cbfSDavid du Colombier return; 59180ee5cbfSDavid du Colombier } 59280ee5cbfSDavid du Colombier tm = gmtime(ust); 59380ee5cbfSDavid du Colombier sprint(str, "%.4d%.2d%.2d%.2d%.2d%.4d", 59480ee5cbfSDavid du Colombier tm->year+1900, 59580ee5cbfSDavid du Colombier tm->mon+1, 59680ee5cbfSDavid du Colombier tm->mday, 59780ee5cbfSDavid du Colombier tm->hour, 59880ee5cbfSDavid du Colombier tm->min, 59980ee5cbfSDavid du Colombier tm->sec*100); 60080ee5cbfSDavid du Colombier Cputs(cd, str, 16); 60180ee5cbfSDavid du Colombier Cputc(cd, 0); 60280ee5cbfSDavid du Colombier } 60380ee5cbfSDavid du Colombier 60480ee5cbfSDavid du Colombier void 60573ee67a1SDavid du Colombier Cwseek(Cdimg *cd, vlong offset) 60680ee5cbfSDavid du Colombier { 60780ee5cbfSDavid du Colombier Bseek(&cd->bwr, offset, 0); 60880ee5cbfSDavid du Colombier } 60980ee5cbfSDavid du Colombier 61073ee67a1SDavid du Colombier uvlong 61180ee5cbfSDavid du Colombier Cwoffset(Cdimg *cd) 61280ee5cbfSDavid du Colombier { 61380ee5cbfSDavid du Colombier return Boffset(&cd->bwr); 61480ee5cbfSDavid du Colombier } 61580ee5cbfSDavid du Colombier 61680ee5cbfSDavid du Colombier void 61780ee5cbfSDavid du Colombier Cwflush(Cdimg *cd) 61880ee5cbfSDavid du Colombier { 61980ee5cbfSDavid du Colombier Bflush(&cd->bwr); 62080ee5cbfSDavid du Colombier } 62180ee5cbfSDavid du Colombier 62273ee67a1SDavid du Colombier uvlong 62380ee5cbfSDavid du Colombier Croffset(Cdimg *cd) 62480ee5cbfSDavid du Colombier { 62580ee5cbfSDavid du Colombier return Boffset(&cd->brd); 62680ee5cbfSDavid du Colombier } 62780ee5cbfSDavid du Colombier 62880ee5cbfSDavid du Colombier void 62973ee67a1SDavid du Colombier Crseek(Cdimg *cd, vlong offset) 63080ee5cbfSDavid du Colombier { 63180ee5cbfSDavid du Colombier Bseek(&cd->brd, offset, 0); 63280ee5cbfSDavid du Colombier } 63380ee5cbfSDavid du Colombier 63480ee5cbfSDavid du Colombier int 63580ee5cbfSDavid du Colombier Cgetc(Cdimg *cd) 63680ee5cbfSDavid du Colombier { 63780ee5cbfSDavid du Colombier int c; 63880ee5cbfSDavid du Colombier 63980ee5cbfSDavid du Colombier Cwflush(cd); 64080ee5cbfSDavid du Colombier if((c = Bgetc(&cd->brd)) == Beof) { 64173ee67a1SDavid du Colombier fprint(2, "getc at %llud\n", Croffset(cd)); 64280ee5cbfSDavid du Colombier assert(0); 64380ee5cbfSDavid du Colombier //sysfatal("Bgetc: %r"); 64480ee5cbfSDavid du Colombier } 64580ee5cbfSDavid du Colombier return c; 64680ee5cbfSDavid du Colombier } 64780ee5cbfSDavid du Colombier 64880ee5cbfSDavid du Colombier void 64980ee5cbfSDavid du Colombier Cread(Cdimg *cd, void *buf, int n) 65080ee5cbfSDavid du Colombier { 65180ee5cbfSDavid du Colombier Cwflush(cd); 65280ee5cbfSDavid du Colombier if(Bread(&cd->brd, buf, n) != n) 65380ee5cbfSDavid du Colombier sysfatal("Bread: %r"); 65480ee5cbfSDavid du Colombier } 65580ee5cbfSDavid du Colombier 65680ee5cbfSDavid du Colombier char* 65780ee5cbfSDavid du Colombier Crdline(Cdimg *cd, int c) 65880ee5cbfSDavid du Colombier { 65980ee5cbfSDavid du Colombier Cwflush(cd); 66080ee5cbfSDavid du Colombier return Brdline(&cd->brd, c); 66180ee5cbfSDavid du Colombier } 66280ee5cbfSDavid du Colombier 66380ee5cbfSDavid du Colombier int 66480ee5cbfSDavid du Colombier Clinelen(Cdimg *cd) 66580ee5cbfSDavid du Colombier { 66680ee5cbfSDavid du Colombier return Blinelen(&cd->brd); 66780ee5cbfSDavid du Colombier } 66880ee5cbfSDavid du Colombier 669