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*
createcd(char * file,Cdinfo info)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;
47f7db6155SDavid du Colombier cd->loader = info.loader;
4843751f27SDavid du Colombier cd->flags |= info.flags & (CDbootable|CDbootnoemu);
499a747e4fSDavid du Colombier Cputbootvol(cd);
509a747e4fSDavid du Colombier }
5180ee5cbfSDavid du Colombier
5280ee5cbfSDavid du Colombier if(readisodesc(cd, &cd->iso) < 0)
5380ee5cbfSDavid du Colombier assert(0);
5480ee5cbfSDavid du Colombier if(info.flags & CDplan9)
5580ee5cbfSDavid du Colombier cd->flags |= CDplan9;
5680ee5cbfSDavid du Colombier else if(info.flags & CDrockridge)
5780ee5cbfSDavid du Colombier cd->flags |= CDrockridge;
5880ee5cbfSDavid du Colombier if(info.flags & CDjoliet) {
5980ee5cbfSDavid du Colombier Cputjolietsvd(cd, info);
6080ee5cbfSDavid du Colombier if(readjolietdesc(cd, &cd->joliet) < 0)
6180ee5cbfSDavid du Colombier assert(0);
6280ee5cbfSDavid du Colombier cd->flags |= CDjoliet;
6380ee5cbfSDavid du Colombier }
6480ee5cbfSDavid du Colombier Cputendvd(cd);
6580ee5cbfSDavid du Colombier
6680ee5cbfSDavid du Colombier if(info.flags & CDdump){
6780ee5cbfSDavid du Colombier cd->nulldump = Cputdumpblock(cd);
6880ee5cbfSDavid du Colombier cd->flags |= CDdump;
6980ee5cbfSDavid du Colombier }
709a747e4fSDavid du Colombier if(cd->flags & CDbootable){
719a747e4fSDavid du Colombier Cputbootcat(cd);
729a747e4fSDavid du Colombier Cupdatebootvol(cd);
739a747e4fSDavid du Colombier }
7480ee5cbfSDavid du Colombier
7580ee5cbfSDavid du Colombier if(info.flags & CDconform)
7680ee5cbfSDavid du Colombier cd->flags |= CDconform;
7780ee5cbfSDavid du Colombier
7880ee5cbfSDavid du Colombier cd->flags |= CDnew;
7980ee5cbfSDavid du Colombier cd->nextblock = Cwoffset(cd) / Blocksize;
8080ee5cbfSDavid du Colombier assert(cd->nextblock != 0);
8180ee5cbfSDavid du Colombier
8280ee5cbfSDavid du Colombier return cd;
8380ee5cbfSDavid du Colombier }
8480ee5cbfSDavid du Colombier
8580ee5cbfSDavid du Colombier Cdimg*
opencd(char * file,Cdinfo info)8680ee5cbfSDavid du Colombier opencd(char *file, Cdinfo info)
8780ee5cbfSDavid du Colombier {
8880ee5cbfSDavid du Colombier int fd, xfd;
8980ee5cbfSDavid du Colombier Cdimg *cd;
909a747e4fSDavid du Colombier Dir *d;
9180ee5cbfSDavid du Colombier
9280ee5cbfSDavid du Colombier if((fd = open(file, ORDWR)) < 0) {
9380ee5cbfSDavid du Colombier if(access(file, AEXIST) == 0)
9480ee5cbfSDavid du Colombier return nil;
9580ee5cbfSDavid du Colombier return createcd(file, info);
9680ee5cbfSDavid du Colombier }
9780ee5cbfSDavid du Colombier
989a747e4fSDavid du Colombier if((d = dirfstat(fd)) == nil) {
9980ee5cbfSDavid du Colombier close(fd);
10080ee5cbfSDavid du Colombier return nil;
10180ee5cbfSDavid du Colombier }
1029a747e4fSDavid du Colombier if(d->length == 0 || d->length % Blocksize) {
1039a747e4fSDavid du Colombier werrstr("bad length %lld", d->length);
10480ee5cbfSDavid du Colombier close(fd);
1059a747e4fSDavid du Colombier free(d);
10680ee5cbfSDavid du Colombier return nil;
10780ee5cbfSDavid du Colombier }
10880ee5cbfSDavid du Colombier
10980ee5cbfSDavid du Colombier cd = emalloc(sizeof *cd);
11080ee5cbfSDavid du Colombier cd->file = atom(file);
1119a747e4fSDavid du Colombier cd->nextblock = d->length / Blocksize;
11280ee5cbfSDavid du Colombier assert(cd->nextblock != 0);
1139a747e4fSDavid du Colombier free(d);
11480ee5cbfSDavid du Colombier
11580ee5cbfSDavid du Colombier Binit(&cd->brd, fd, OREAD);
11680ee5cbfSDavid du Colombier
11780ee5cbfSDavid du Colombier if((xfd = open(file, ORDWR)) < 0)
11880ee5cbfSDavid du Colombier sysfatal("can't open file again: %r");
11980ee5cbfSDavid du Colombier Binit(&cd->bwr, xfd, OWRITE);
12080ee5cbfSDavid du Colombier
12180ee5cbfSDavid du Colombier if(readisodesc(cd, &cd->iso) < 0) {
12280ee5cbfSDavid du Colombier free(cd);
12380ee5cbfSDavid du Colombier close(fd);
12480ee5cbfSDavid du Colombier close(xfd);
12580ee5cbfSDavid du Colombier return nil;
12680ee5cbfSDavid du Colombier }
12780ee5cbfSDavid du Colombier
12880ee5cbfSDavid du Colombier /* lowercase because of isostring */
12980ee5cbfSDavid du Colombier if(strstr(cd->iso.systemid, "iso9660") == nil
13080ee5cbfSDavid du Colombier && strstr(cd->iso.systemid, "utf8") == nil) {
13180ee5cbfSDavid du Colombier werrstr("unknown systemid %s", cd->iso.systemid);
13280ee5cbfSDavid du Colombier free(cd);
13380ee5cbfSDavid du Colombier close(fd);
13480ee5cbfSDavid du Colombier close(xfd);
13580ee5cbfSDavid du Colombier return nil;
13680ee5cbfSDavid du Colombier }
13780ee5cbfSDavid du Colombier
13880ee5cbfSDavid du Colombier if(strstr(cd->iso.systemid, "plan 9"))
13980ee5cbfSDavid du Colombier cd->flags |= CDplan9;
14080ee5cbfSDavid du Colombier if(strstr(cd->iso.systemid, "iso9660"))
14180ee5cbfSDavid du Colombier cd->flags |= CDconform;
14280ee5cbfSDavid du Colombier if(strstr(cd->iso.systemid, "rrip"))
14380ee5cbfSDavid du Colombier cd->flags |= CDrockridge;
1449a747e4fSDavid du Colombier if(strstr(cd->iso.systemid, "boot"))
1459a747e4fSDavid du Colombier cd->flags |= CDbootable;
14680ee5cbfSDavid du Colombier if(readjolietdesc(cd, &cd->joliet) == 0)
14780ee5cbfSDavid du Colombier cd->flags |= CDjoliet;
14880ee5cbfSDavid du Colombier if(hasdump(cd))
14980ee5cbfSDavid du Colombier cd->flags |= CDdump;
15080ee5cbfSDavid du Colombier
15180ee5cbfSDavid du Colombier return cd;
15280ee5cbfSDavid du Colombier }
15380ee5cbfSDavid du Colombier
15480ee5cbfSDavid du Colombier ulong
big(void * a,int n)15580ee5cbfSDavid du Colombier big(void *a, int n)
15680ee5cbfSDavid du Colombier {
15780ee5cbfSDavid du Colombier uchar *p;
15880ee5cbfSDavid du Colombier ulong v;
15980ee5cbfSDavid du Colombier int i;
16080ee5cbfSDavid du Colombier
16180ee5cbfSDavid du Colombier p = a;
16280ee5cbfSDavid du Colombier v = 0;
16380ee5cbfSDavid du Colombier for(i=0; i<n; i++)
16480ee5cbfSDavid du Colombier v = (v<<8) | *p++;
16580ee5cbfSDavid du Colombier return v;
16680ee5cbfSDavid du Colombier }
16780ee5cbfSDavid du Colombier
16880ee5cbfSDavid du Colombier ulong
little(void * a,int n)16980ee5cbfSDavid du Colombier little(void *a, int n)
17080ee5cbfSDavid du Colombier {
17180ee5cbfSDavid du Colombier uchar *p;
17280ee5cbfSDavid du Colombier ulong v;
17380ee5cbfSDavid du Colombier int i;
17480ee5cbfSDavid du Colombier
17580ee5cbfSDavid du Colombier p = a;
17680ee5cbfSDavid du Colombier v = 0;
17780ee5cbfSDavid du Colombier for(i=0; i<n; i++)
17880ee5cbfSDavid du Colombier v |= (*p++<<(i*8));
17980ee5cbfSDavid du Colombier return v;
18080ee5cbfSDavid du Colombier }
18180ee5cbfSDavid du Colombier
18280ee5cbfSDavid du Colombier void
Creadblock(Cdimg * cd,void * buf,ulong block,ulong len)18380ee5cbfSDavid du Colombier Creadblock(Cdimg *cd, void *buf, ulong block, ulong len)
18480ee5cbfSDavid du Colombier {
18580ee5cbfSDavid du Colombier assert(block != 0); /* nothing useful there */
18680ee5cbfSDavid du Colombier
18780ee5cbfSDavid du Colombier Bflush(&cd->bwr);
18873ee67a1SDavid du Colombier if(Bseek(&cd->brd, (vlong)block * Blocksize, 0) !=
18973ee67a1SDavid du Colombier (vlong)block * Blocksize)
19080ee5cbfSDavid du Colombier sysfatal("error seeking to block %lud", block);
19180ee5cbfSDavid du Colombier if(Bread(&cd->brd, buf, len) != len)
19273ee67a1SDavid du Colombier sysfatal("error reading %lud bytes at block %lud: %r %lld",
19373ee67a1SDavid du Colombier len, block, Bseek(&cd->brd, 0, 2));
19480ee5cbfSDavid du Colombier }
19580ee5cbfSDavid du Colombier
19680ee5cbfSDavid du Colombier int
parsedir(Cdimg * cd,Direc * d,uchar * buf,int len,char * (* cvtname)(uchar *,int))19780ee5cbfSDavid du Colombier parsedir(Cdimg *cd, Direc *d, uchar *buf, int len, char *(*cvtname)(uchar*, int))
19880ee5cbfSDavid du Colombier {
1999a747e4fSDavid du Colombier enum { NAMELEN = 28 };
20080ee5cbfSDavid du Colombier char name[NAMELEN];
20180ee5cbfSDavid du Colombier uchar *p;
20280ee5cbfSDavid du Colombier Cdir *c;
20380ee5cbfSDavid du Colombier
20480ee5cbfSDavid du Colombier memset(d, 0, sizeof *d);
20580ee5cbfSDavid du Colombier
20680ee5cbfSDavid du Colombier c = (Cdir*)buf;
20780ee5cbfSDavid du Colombier
20880ee5cbfSDavid du Colombier if(c->len > len) {
20980ee5cbfSDavid du Colombier werrstr("buffer too small");
21080ee5cbfSDavid du Colombier return -1;
21180ee5cbfSDavid du Colombier }
21280ee5cbfSDavid du Colombier
21380ee5cbfSDavid du Colombier if(c->namelen == 1 && c->name[0] == '\0')
21480ee5cbfSDavid du Colombier d->name = atom(".");
21580ee5cbfSDavid du Colombier else if(c->namelen == 1 && c->name[0] == '\001')
21680ee5cbfSDavid du Colombier d->name = atom("..");
21780ee5cbfSDavid du Colombier else if(cvtname)
21880ee5cbfSDavid du Colombier d->name = cvtname(c->name, c->namelen);
21980ee5cbfSDavid du Colombier
22080ee5cbfSDavid du Colombier d->block = little(c->dloc, 4);
22180ee5cbfSDavid du Colombier d->length = little(c->dlen, 4);
22280ee5cbfSDavid du Colombier
22380ee5cbfSDavid du Colombier if(c->flags & 2)
2249a747e4fSDavid du Colombier d->mode |= DMDIR;
22580ee5cbfSDavid du Colombier
22680ee5cbfSDavid du Colombier /*BUG: do we really need to parse the plan 9 fields? */
22780ee5cbfSDavid du Colombier /* plan 9 use fields */
22880ee5cbfSDavid du Colombier if((cd->flags & CDplan9) && cvtname == isostring
22980ee5cbfSDavid du Colombier && (c->namelen != 1 || c->name[0] > 1)) {
23080ee5cbfSDavid du Colombier p = buf+33+c->namelen;
23180ee5cbfSDavid du Colombier if((p-buf)&1)
23280ee5cbfSDavid du Colombier p++;
23380ee5cbfSDavid du Colombier assert(p < buf+c->len);
23480ee5cbfSDavid du Colombier assert(*p < NAMELEN);
23580ee5cbfSDavid du Colombier if(*p != 0) {
23680ee5cbfSDavid du Colombier memmove(name, p+1, *p);
23780ee5cbfSDavid du Colombier name[*p] = '\0';
23880ee5cbfSDavid du Colombier d->confname = d->name;
23980ee5cbfSDavid du Colombier d->name = atom(name);
24080ee5cbfSDavid du Colombier }
24180ee5cbfSDavid du Colombier p += *p+1;
24280ee5cbfSDavid du Colombier assert(*p < NAMELEN);
24380ee5cbfSDavid du Colombier memmove(name, p+1, *p);
24480ee5cbfSDavid du Colombier name[*p] = '\0';
24580ee5cbfSDavid du Colombier d->uid = atom(name);
24680ee5cbfSDavid du Colombier p += *p+1;
24780ee5cbfSDavid du Colombier assert(*p < NAMELEN);
24880ee5cbfSDavid du Colombier memmove(name, p+1, *p);
24980ee5cbfSDavid du Colombier name[*p] = '\0';
25080ee5cbfSDavid du Colombier d->gid = atom(name);
25180ee5cbfSDavid du Colombier p += *p+1;
25280ee5cbfSDavid du Colombier if((p-buf)&1)
25380ee5cbfSDavid du Colombier p++;
25480ee5cbfSDavid du Colombier d->mode = little(p, 4);
25580ee5cbfSDavid du Colombier }
25680ee5cbfSDavid du Colombier
25780ee5cbfSDavid du Colombier // BUG: rock ridge extensions
25880ee5cbfSDavid du Colombier return 0;
25980ee5cbfSDavid du Colombier }
26080ee5cbfSDavid du Colombier
26180ee5cbfSDavid du Colombier void
setroot(Cdimg * cd,ulong block,ulong dloc,ulong dlen)26280ee5cbfSDavid du Colombier setroot(Cdimg *cd, ulong block, ulong dloc, ulong dlen)
26380ee5cbfSDavid du Colombier {
26480ee5cbfSDavid du Colombier assert(block != 0);
26580ee5cbfSDavid du Colombier
26673ee67a1SDavid du Colombier Cwseek(cd, (vlong)block * Blocksize + offsetof(Cvoldesc, rootdir[0]) +
26773ee67a1SDavid du Colombier offsetof(Cdir, dloc[0]));
26880ee5cbfSDavid du Colombier Cputn(cd, dloc, 4);
26980ee5cbfSDavid du Colombier Cputn(cd, dlen, 4);
27080ee5cbfSDavid du Colombier }
27180ee5cbfSDavid du Colombier
27280ee5cbfSDavid du Colombier void
setvolsize(Cdimg * cd,uvlong block,ulong size)2733e33a36fSDavid du Colombier setvolsize(Cdimg *cd, uvlong block, ulong size)
27480ee5cbfSDavid du Colombier {
27580ee5cbfSDavid du Colombier assert(block != 0);
27680ee5cbfSDavid du Colombier
2773e33a36fSDavid du Colombier Cwseek(cd, block * Blocksize + offsetof(Cvoldesc, volsize[0]));
278*a587111cSDavid du Colombier Cputn(cd, size, 4); /* size in blocks */
27980ee5cbfSDavid du Colombier }
28080ee5cbfSDavid du Colombier
28180ee5cbfSDavid du Colombier void
setpathtable(Cdimg * cd,ulong block,ulong sz,ulong lloc,ulong bloc)28280ee5cbfSDavid du Colombier setpathtable(Cdimg *cd, ulong block, ulong sz, ulong lloc, ulong bloc)
28380ee5cbfSDavid du Colombier {
28480ee5cbfSDavid du Colombier assert(block != 0);
28580ee5cbfSDavid du Colombier
28673ee67a1SDavid du Colombier Cwseek(cd, (vlong)block * Blocksize + offsetof(Cvoldesc, pathsize[0]));
28780ee5cbfSDavid du Colombier Cputn(cd, sz, 4);
28880ee5cbfSDavid du Colombier Cputnl(cd, lloc, 4);
28980ee5cbfSDavid du Colombier Cputnl(cd, 0, 4);
29080ee5cbfSDavid du Colombier Cputnm(cd, bloc, 4);
29180ee5cbfSDavid du Colombier Cputnm(cd, 0, 4);
29273ee67a1SDavid du Colombier assert(Cwoffset(cd) == (vlong)block * Blocksize +
29373ee67a1SDavid du Colombier offsetof(Cvoldesc, rootdir[0]));
29480ee5cbfSDavid du Colombier }
29580ee5cbfSDavid du Colombier
29680ee5cbfSDavid du Colombier
29780ee5cbfSDavid du Colombier static void
parsedesc(Voldesc * v,Cvoldesc * cv,char * (* string)(uchar *,int))29880ee5cbfSDavid du Colombier parsedesc(Voldesc *v, Cvoldesc *cv, char *(*string)(uchar*, int))
29980ee5cbfSDavid du Colombier {
30080ee5cbfSDavid du Colombier v->systemid = string(cv->systemid, sizeof cv->systemid);
30180ee5cbfSDavid du Colombier
30280ee5cbfSDavid du Colombier v->pathsize = little(cv->pathsize, 4);
30380ee5cbfSDavid du Colombier v->lpathloc = little(cv->lpathloc, 4);
30480ee5cbfSDavid du Colombier v->mpathloc = little(cv->mpathloc, 4);
30580ee5cbfSDavid du Colombier
30680ee5cbfSDavid du Colombier v->volumeset = string(cv->volumeset, sizeof cv->volumeset);
30780ee5cbfSDavid du Colombier v->publisher = string(cv->publisher, sizeof cv->publisher);
30880ee5cbfSDavid du Colombier v->preparer = string(cv->preparer, sizeof cv->preparer);
30980ee5cbfSDavid du Colombier v->application = string(cv->application, sizeof cv->application);
31080ee5cbfSDavid du Colombier
31180ee5cbfSDavid du Colombier v->abstract = string(cv->abstract, sizeof cv->abstract);
31280ee5cbfSDavid du Colombier v->biblio = string(cv->biblio, sizeof cv->biblio);
31380ee5cbfSDavid du Colombier v->notice = string(cv->notice, sizeof cv->notice);
31480ee5cbfSDavid du Colombier }
31580ee5cbfSDavid du Colombier
31680ee5cbfSDavid du Colombier static int
readisodesc(Cdimg * cd,Voldesc * v)31780ee5cbfSDavid du Colombier readisodesc(Cdimg *cd, Voldesc *v)
31880ee5cbfSDavid du Colombier {
31980ee5cbfSDavid du Colombier static uchar magic[] = { 0x01, 'C', 'D', '0', '0', '1', 0x01, 0x00 };
32080ee5cbfSDavid du Colombier Cvoldesc cv;
32180ee5cbfSDavid du Colombier
32280ee5cbfSDavid du Colombier memset(v, 0, sizeof *v);
32380ee5cbfSDavid du Colombier
32480ee5cbfSDavid du Colombier Creadblock(cd, &cv, 16, sizeof cv);
32580ee5cbfSDavid du Colombier if(memcmp(cv.magic, magic, sizeof magic) != 0) {
32680ee5cbfSDavid du Colombier werrstr("bad pvd magic");
32780ee5cbfSDavid du Colombier return -1;
32880ee5cbfSDavid du Colombier }
32980ee5cbfSDavid du Colombier
33080ee5cbfSDavid du Colombier if(little(cv.blocksize, 2) != Blocksize) {
33180ee5cbfSDavid du Colombier werrstr("block size not %d", Blocksize);
33280ee5cbfSDavid du Colombier return -1;
33380ee5cbfSDavid du Colombier }
33480ee5cbfSDavid du Colombier
33580ee5cbfSDavid du Colombier cd->iso9660pvd = 16;
33680ee5cbfSDavid du Colombier parsedesc(v, &cv, isostring);
33780ee5cbfSDavid du Colombier
33880ee5cbfSDavid du Colombier return parsedir(cd, &v->root, cv.rootdir, sizeof cv.rootdir, isostring);
33980ee5cbfSDavid du Colombier }
34080ee5cbfSDavid du Colombier
34180ee5cbfSDavid du Colombier static int
readjolietdesc(Cdimg * cd,Voldesc * v)34280ee5cbfSDavid du Colombier readjolietdesc(Cdimg *cd, Voldesc *v)
34380ee5cbfSDavid du Colombier {
34480ee5cbfSDavid du Colombier int i;
34580ee5cbfSDavid du Colombier static uchar magic[] = { 0x02, 'C', 'D', '0', '0', '1', 0x01, 0x00 };
34680ee5cbfSDavid du Colombier Cvoldesc cv;
34780ee5cbfSDavid du Colombier
34880ee5cbfSDavid du Colombier memset(v, 0, sizeof *v);
34980ee5cbfSDavid du Colombier
35080ee5cbfSDavid du Colombier for(i=16; i<24; i++) {
35180ee5cbfSDavid du Colombier Creadblock(cd, &cv, i, sizeof cv);
35280ee5cbfSDavid du Colombier if(memcmp(cv.magic, magic, sizeof magic) != 0)
35380ee5cbfSDavid du Colombier continue;
35480ee5cbfSDavid du Colombier if(cv.charset[0] != 0x25 || cv.charset[1] != 0x2F
35580ee5cbfSDavid du Colombier || (cv.charset[2] != 0x40 && cv.charset[2] != 0x43 && cv.charset[2] != 0x45))
35680ee5cbfSDavid du Colombier continue;
35780ee5cbfSDavid du Colombier break;
35880ee5cbfSDavid du Colombier }
35980ee5cbfSDavid du Colombier
36080ee5cbfSDavid du Colombier if(i==24) {
36180ee5cbfSDavid du Colombier werrstr("could not find Joliet SVD");
36280ee5cbfSDavid du Colombier return -1;
36380ee5cbfSDavid du Colombier }
36480ee5cbfSDavid du Colombier
36580ee5cbfSDavid du Colombier if(little(cv.blocksize, 2) != Blocksize) {
36680ee5cbfSDavid du Colombier werrstr("block size not %d", Blocksize);
36780ee5cbfSDavid du Colombier return -1;
36880ee5cbfSDavid du Colombier }
36980ee5cbfSDavid du Colombier
37080ee5cbfSDavid du Colombier cd->jolietsvd = i;
37180ee5cbfSDavid du Colombier parsedesc(v, &cv, jolietstring);
37280ee5cbfSDavid du Colombier
37380ee5cbfSDavid du Colombier return parsedir(cd, &v->root, cv.rootdir, sizeof cv.rootdir, jolietstring);
37480ee5cbfSDavid du Colombier }
37580ee5cbfSDavid du Colombier
37680ee5cbfSDavid du Colombier /*
37780ee5cbfSDavid du Colombier * CD image buffering routines.
37880ee5cbfSDavid du Colombier */
37980ee5cbfSDavid du Colombier void
Cputc(Cdimg * cd,int c)38080ee5cbfSDavid du Colombier Cputc(Cdimg *cd, int c)
38180ee5cbfSDavid du Colombier {
38280ee5cbfSDavid du Colombier assert(Boffset(&cd->bwr) >= 16*Blocksize || c == 0);
38380ee5cbfSDavid du Colombier
38480ee5cbfSDavid du Colombier if(Boffset(&cd->bwr) == 0x9962)
38580ee5cbfSDavid du Colombier if(c >= 256) abort();
38680ee5cbfSDavid du Colombier if(Bputc(&cd->bwr, c) < 0)
38780ee5cbfSDavid du Colombier sysfatal("Bputc: %r");
38880ee5cbfSDavid du Colombier Bflush(&cd->brd);
38980ee5cbfSDavid du Colombier }
39080ee5cbfSDavid du Colombier
39180ee5cbfSDavid du Colombier void
Cputnl(Cdimg * cd,uvlong val,int size)3923e33a36fSDavid du Colombier Cputnl(Cdimg *cd, uvlong val, int size)
39380ee5cbfSDavid du Colombier {
39480ee5cbfSDavid du Colombier switch(size) {
39580ee5cbfSDavid du Colombier default:
3963e33a36fSDavid du Colombier sysfatal("bad size %d in Cputnl", size);
39780ee5cbfSDavid du Colombier case 2:
3983e33a36fSDavid du Colombier if(val >= (1<<16))
3993e33a36fSDavid du Colombier sysfatal("value %llud too big for size %d in Cputnl",
4003e33a36fSDavid du Colombier val, size);
40180ee5cbfSDavid du Colombier Cputc(cd, val);
40280ee5cbfSDavid du Colombier Cputc(cd, val>>8);
40380ee5cbfSDavid du Colombier break;
40480ee5cbfSDavid du Colombier case 4:
4053e33a36fSDavid du Colombier if(val >= (1ULL<<32))
4063e33a36fSDavid du Colombier sysfatal("value %llud too big for size %d in Cputnl",
4073e33a36fSDavid du Colombier val, size);
40880ee5cbfSDavid du Colombier Cputc(cd, val);
40980ee5cbfSDavid du Colombier Cputc(cd, val>>8);
41080ee5cbfSDavid du Colombier Cputc(cd, val>>16);
41180ee5cbfSDavid du Colombier Cputc(cd, val>>24);
41280ee5cbfSDavid du Colombier break;
4133e33a36fSDavid du Colombier case 8:
4143e33a36fSDavid du Colombier Cputc(cd, val);
4153e33a36fSDavid du Colombier Cputc(cd, val>>8);
4163e33a36fSDavid du Colombier Cputc(cd, val>>16);
4173e33a36fSDavid du Colombier Cputc(cd, val>>24);
4183e33a36fSDavid du Colombier Cputc(cd, val>>32);
4193e33a36fSDavid du Colombier Cputc(cd, val>>40);
4203e33a36fSDavid du Colombier Cputc(cd, val>>48);
4213e33a36fSDavid du Colombier Cputc(cd, val>>56);
4223e33a36fSDavid du Colombier break;
42380ee5cbfSDavid du Colombier }
42480ee5cbfSDavid du Colombier }
42580ee5cbfSDavid du Colombier
42680ee5cbfSDavid du Colombier void
Cputnm(Cdimg * cd,uvlong val,int size)4273e33a36fSDavid du Colombier Cputnm(Cdimg *cd, uvlong val, int size)
42880ee5cbfSDavid du Colombier {
42980ee5cbfSDavid du Colombier switch(size) {
43080ee5cbfSDavid du Colombier default:
4313e33a36fSDavid du Colombier sysfatal("bad size %d in Cputnm", size);
43280ee5cbfSDavid du Colombier case 2:
4333e33a36fSDavid du Colombier if(val >= (1<<16))
4343e33a36fSDavid du Colombier sysfatal("value %llud too big for size %d in Cputnl",
4353e33a36fSDavid du Colombier val, size);
43680ee5cbfSDavid du Colombier Cputc(cd, val>>8);
43780ee5cbfSDavid du Colombier Cputc(cd, val);
43880ee5cbfSDavid du Colombier break;
43980ee5cbfSDavid du Colombier case 4:
4403e33a36fSDavid du Colombier if(val >= (1ULL<<32))
4413e33a36fSDavid du Colombier sysfatal("value %llud too big for size %d in Cputnl",
4423e33a36fSDavid du Colombier val, size);
4433e33a36fSDavid du Colombier Cputc(cd, val>>24);
4443e33a36fSDavid du Colombier Cputc(cd, val>>16);
4453e33a36fSDavid du Colombier Cputc(cd, val>>8);
4463e33a36fSDavid du Colombier Cputc(cd, val);
4473e33a36fSDavid du Colombier break;
4483e33a36fSDavid du Colombier case 8:
4493e33a36fSDavid du Colombier Cputc(cd, val>>56);
4503e33a36fSDavid du Colombier Cputc(cd, val>>48);
4513e33a36fSDavid du Colombier Cputc(cd, val>>40);
4523e33a36fSDavid du Colombier Cputc(cd, val>>32);
45380ee5cbfSDavid du Colombier Cputc(cd, val>>24);
45480ee5cbfSDavid du Colombier Cputc(cd, val>>16);
45580ee5cbfSDavid du Colombier Cputc(cd, val>>8);
45680ee5cbfSDavid du Colombier Cputc(cd, val);
45780ee5cbfSDavid du Colombier break;
45880ee5cbfSDavid du Colombier }
45980ee5cbfSDavid du Colombier }
46080ee5cbfSDavid du Colombier
46180ee5cbfSDavid du Colombier void
Cputn(Cdimg * cd,uvlong val,int size)4623e33a36fSDavid du Colombier Cputn(Cdimg *cd, uvlong val, int size)
46380ee5cbfSDavid du Colombier {
46480ee5cbfSDavid du Colombier Cputnl(cd, val, size);
46580ee5cbfSDavid du Colombier Cputnm(cd, val, size);
46680ee5cbfSDavid du Colombier }
46780ee5cbfSDavid du Colombier
46880ee5cbfSDavid du Colombier /*
46980ee5cbfSDavid du Colombier * ASCII/UTF string writing
47080ee5cbfSDavid du Colombier */
47180ee5cbfSDavid du Colombier void
Crepeat(Cdimg * cd,int c,int n)47280ee5cbfSDavid du Colombier Crepeat(Cdimg *cd, int c, int n)
47380ee5cbfSDavid du Colombier {
47480ee5cbfSDavid du Colombier while(n-- > 0)
47580ee5cbfSDavid du Colombier Cputc(cd, c);
47680ee5cbfSDavid du Colombier }
47780ee5cbfSDavid du Colombier
47880ee5cbfSDavid du Colombier void
Cputs(Cdimg * cd,char * s,int size)47980ee5cbfSDavid du Colombier Cputs(Cdimg *cd, char *s, int size)
48080ee5cbfSDavid du Colombier {
48180ee5cbfSDavid du Colombier int n;
48280ee5cbfSDavid du Colombier
48380ee5cbfSDavid du Colombier if(s == nil) {
48480ee5cbfSDavid du Colombier Crepeat(cd, ' ', size);
48580ee5cbfSDavid du Colombier return;
48680ee5cbfSDavid du Colombier }
48780ee5cbfSDavid du Colombier
48880ee5cbfSDavid du Colombier for(n=0; n<size && *s; n++)
48980ee5cbfSDavid du Colombier Cputc(cd, *s++);
49080ee5cbfSDavid du Colombier if(n<size)
49180ee5cbfSDavid du Colombier Crepeat(cd, ' ', size-n);
49280ee5cbfSDavid du Colombier }
49380ee5cbfSDavid du Colombier
49480ee5cbfSDavid du Colombier void
Cwrite(Cdimg * cd,void * buf,int n)49580ee5cbfSDavid du Colombier Cwrite(Cdimg *cd, void *buf, int n)
49680ee5cbfSDavid du Colombier {
49780ee5cbfSDavid du Colombier assert(Boffset(&cd->bwr) >= 16*Blocksize);
49880ee5cbfSDavid du Colombier
49980ee5cbfSDavid du Colombier if(Bwrite(&cd->bwr, buf, n) != n)
50080ee5cbfSDavid du Colombier sysfatal("Bwrite: %r");
50180ee5cbfSDavid du Colombier Bflush(&cd->brd);
50280ee5cbfSDavid du Colombier }
50380ee5cbfSDavid du Colombier
50480ee5cbfSDavid du Colombier void
Cputr(Cdimg * cd,Rune r)50580ee5cbfSDavid du Colombier Cputr(Cdimg *cd, Rune r)
50680ee5cbfSDavid du Colombier {
50780ee5cbfSDavid du Colombier Cputc(cd, r>>8);
50880ee5cbfSDavid du Colombier Cputc(cd, r);
50980ee5cbfSDavid du Colombier }
51080ee5cbfSDavid du Colombier
51180ee5cbfSDavid du Colombier void
Crepeatr(Cdimg * cd,Rune r,int n)51280ee5cbfSDavid du Colombier Crepeatr(Cdimg *cd, Rune r, int n)
51380ee5cbfSDavid du Colombier {
51480ee5cbfSDavid du Colombier int i;
51580ee5cbfSDavid du Colombier
51680ee5cbfSDavid du Colombier for(i=0; i<n; i++)
51780ee5cbfSDavid du Colombier Cputr(cd, r);
51880ee5cbfSDavid du Colombier }
51980ee5cbfSDavid du Colombier
52080ee5cbfSDavid du Colombier void
Cputrs(Cdimg * cd,Rune * s,int osize)52180ee5cbfSDavid du Colombier Cputrs(Cdimg *cd, Rune *s, int osize)
52280ee5cbfSDavid du Colombier {
52380ee5cbfSDavid du Colombier int n, size;
52480ee5cbfSDavid du Colombier
52580ee5cbfSDavid du Colombier size = osize/2;
52680ee5cbfSDavid du Colombier if(s == nil)
52780ee5cbfSDavid du Colombier Crepeatr(cd, (Rune)' ', size);
52880ee5cbfSDavid du Colombier else {
52980ee5cbfSDavid du Colombier for(n=0; *s && n<size; n++)
53080ee5cbfSDavid du Colombier Cputr(cd, *s++);
53180ee5cbfSDavid du Colombier if(n<size)
53280ee5cbfSDavid du Colombier Crepeatr(cd, ' ', size-n);
53380ee5cbfSDavid du Colombier }
53480ee5cbfSDavid du Colombier if(osize&1)
53580ee5cbfSDavid du Colombier Cputc(cd, 0); /* what else can we do? */
53680ee5cbfSDavid du Colombier }
53780ee5cbfSDavid du Colombier
53880ee5cbfSDavid du Colombier void
Cputrscvt(Cdimg * cd,char * s,int size)53980ee5cbfSDavid du Colombier Cputrscvt(Cdimg *cd, char *s, int size)
54080ee5cbfSDavid du Colombier {
54180ee5cbfSDavid du Colombier Rune r[256];
54280ee5cbfSDavid du Colombier
54380ee5cbfSDavid du Colombier strtorune(r, s);
54480ee5cbfSDavid du Colombier Cputrs(cd, strtorune(r, s), size);
54580ee5cbfSDavid du Colombier }
54680ee5cbfSDavid du Colombier
54780ee5cbfSDavid du Colombier void
Cpadblock(Cdimg * cd)54880ee5cbfSDavid du Colombier Cpadblock(Cdimg *cd)
54980ee5cbfSDavid du Colombier {
55080ee5cbfSDavid du Colombier int n;
55180ee5cbfSDavid du Colombier ulong nb;
55280ee5cbfSDavid du Colombier
55380ee5cbfSDavid du Colombier n = Blocksize - (Boffset(&cd->bwr) % Blocksize);
55480ee5cbfSDavid du Colombier if(n != Blocksize)
55580ee5cbfSDavid du Colombier Crepeat(cd, 0, n);
55680ee5cbfSDavid du Colombier
55780ee5cbfSDavid du Colombier nb = Boffset(&cd->bwr)/Blocksize;
55880ee5cbfSDavid du Colombier assert(nb != 0);
55980ee5cbfSDavid du Colombier if(nb > cd->nextblock)
56080ee5cbfSDavid du Colombier cd->nextblock = nb;
56180ee5cbfSDavid du Colombier }
56280ee5cbfSDavid du Colombier
56380ee5cbfSDavid du Colombier void
Cputdate(Cdimg * cd,ulong ust)56480ee5cbfSDavid du Colombier Cputdate(Cdimg *cd, ulong ust)
56580ee5cbfSDavid du Colombier {
56680ee5cbfSDavid du Colombier Tm *tm;
56780ee5cbfSDavid du Colombier
56880ee5cbfSDavid du Colombier if(ust == 0) {
56980ee5cbfSDavid du Colombier Crepeat(cd, 0, 7);
57080ee5cbfSDavid du Colombier return;
57180ee5cbfSDavid du Colombier }
57280ee5cbfSDavid du Colombier tm = gmtime(ust);
57380ee5cbfSDavid du Colombier Cputc(cd, tm->year);
57480ee5cbfSDavid du Colombier Cputc(cd, tm->mon+1);
57580ee5cbfSDavid du Colombier Cputc(cd, tm->mday);
57680ee5cbfSDavid du Colombier Cputc(cd, tm->hour);
57780ee5cbfSDavid du Colombier Cputc(cd, tm->min);
57880ee5cbfSDavid du Colombier Cputc(cd, tm->sec);
57980ee5cbfSDavid du Colombier Cputc(cd, 0);
58080ee5cbfSDavid du Colombier }
58180ee5cbfSDavid du Colombier
58280ee5cbfSDavid du Colombier void
Cputdate1(Cdimg * cd,ulong ust)58380ee5cbfSDavid du Colombier Cputdate1(Cdimg *cd, ulong ust)
58480ee5cbfSDavid du Colombier {
58580ee5cbfSDavid du Colombier Tm *tm;
58680ee5cbfSDavid du Colombier char str[20];
58780ee5cbfSDavid du Colombier
58880ee5cbfSDavid du Colombier if(ust == 0) {
58980ee5cbfSDavid du Colombier Crepeat(cd, '0', 16);
59080ee5cbfSDavid du Colombier Cputc(cd, 0);
59180ee5cbfSDavid du Colombier return;
59280ee5cbfSDavid du Colombier }
59380ee5cbfSDavid du Colombier tm = gmtime(ust);
59480ee5cbfSDavid du Colombier sprint(str, "%.4d%.2d%.2d%.2d%.2d%.4d",
59580ee5cbfSDavid du Colombier tm->year+1900,
59680ee5cbfSDavid du Colombier tm->mon+1,
59780ee5cbfSDavid du Colombier tm->mday,
59880ee5cbfSDavid du Colombier tm->hour,
59980ee5cbfSDavid du Colombier tm->min,
60080ee5cbfSDavid du Colombier tm->sec*100);
60180ee5cbfSDavid du Colombier Cputs(cd, str, 16);
60280ee5cbfSDavid du Colombier Cputc(cd, 0);
60380ee5cbfSDavid du Colombier }
60480ee5cbfSDavid du Colombier
60580ee5cbfSDavid du Colombier void
Cwseek(Cdimg * cd,vlong offset)60673ee67a1SDavid du Colombier Cwseek(Cdimg *cd, vlong offset)
60780ee5cbfSDavid du Colombier {
60880ee5cbfSDavid du Colombier Bseek(&cd->bwr, offset, 0);
60980ee5cbfSDavid du Colombier }
61080ee5cbfSDavid du Colombier
61173ee67a1SDavid du Colombier uvlong
Cwoffset(Cdimg * cd)61280ee5cbfSDavid du Colombier Cwoffset(Cdimg *cd)
61380ee5cbfSDavid du Colombier {
61480ee5cbfSDavid du Colombier return Boffset(&cd->bwr);
61580ee5cbfSDavid du Colombier }
61680ee5cbfSDavid du Colombier
61780ee5cbfSDavid du Colombier void
Cwflush(Cdimg * cd)61880ee5cbfSDavid du Colombier Cwflush(Cdimg *cd)
61980ee5cbfSDavid du Colombier {
62080ee5cbfSDavid du Colombier Bflush(&cd->bwr);
62180ee5cbfSDavid du Colombier }
62280ee5cbfSDavid du Colombier
62373ee67a1SDavid du Colombier uvlong
Croffset(Cdimg * cd)62480ee5cbfSDavid du Colombier Croffset(Cdimg *cd)
62580ee5cbfSDavid du Colombier {
62680ee5cbfSDavid du Colombier return Boffset(&cd->brd);
62780ee5cbfSDavid du Colombier }
62880ee5cbfSDavid du Colombier
62980ee5cbfSDavid du Colombier void
Crseek(Cdimg * cd,vlong offset)63073ee67a1SDavid du Colombier Crseek(Cdimg *cd, vlong offset)
63180ee5cbfSDavid du Colombier {
63280ee5cbfSDavid du Colombier Bseek(&cd->brd, offset, 0);
63380ee5cbfSDavid du Colombier }
63480ee5cbfSDavid du Colombier
63580ee5cbfSDavid du Colombier int
Cgetc(Cdimg * cd)63680ee5cbfSDavid du Colombier Cgetc(Cdimg *cd)
63780ee5cbfSDavid du Colombier {
63880ee5cbfSDavid du Colombier int c;
63980ee5cbfSDavid du Colombier
64080ee5cbfSDavid du Colombier Cwflush(cd);
64180ee5cbfSDavid du Colombier if((c = Bgetc(&cd->brd)) == Beof) {
64273ee67a1SDavid du Colombier fprint(2, "getc at %llud\n", Croffset(cd));
64380ee5cbfSDavid du Colombier assert(0);
64480ee5cbfSDavid du Colombier //sysfatal("Bgetc: %r");
64580ee5cbfSDavid du Colombier }
64680ee5cbfSDavid du Colombier return c;
64780ee5cbfSDavid du Colombier }
64880ee5cbfSDavid du Colombier
64980ee5cbfSDavid du Colombier void
Cread(Cdimg * cd,void * buf,int n)65080ee5cbfSDavid du Colombier Cread(Cdimg *cd, void *buf, int n)
65180ee5cbfSDavid du Colombier {
65280ee5cbfSDavid du Colombier Cwflush(cd);
65380ee5cbfSDavid du Colombier if(Bread(&cd->brd, buf, n) != n)
65480ee5cbfSDavid du Colombier sysfatal("Bread: %r");
65580ee5cbfSDavid du Colombier }
65680ee5cbfSDavid du Colombier
65780ee5cbfSDavid du Colombier char*
Crdline(Cdimg * cd,int c)65880ee5cbfSDavid du Colombier Crdline(Cdimg *cd, int c)
65980ee5cbfSDavid du Colombier {
66080ee5cbfSDavid du Colombier Cwflush(cd);
66180ee5cbfSDavid du Colombier return Brdline(&cd->brd, c);
66280ee5cbfSDavid du Colombier }
66380ee5cbfSDavid du Colombier
66480ee5cbfSDavid du Colombier int
Clinelen(Cdimg * cd)66580ee5cbfSDavid du Colombier Clinelen(Cdimg *cd)
66680ee5cbfSDavid du Colombier {
66780ee5cbfSDavid du Colombier return Blinelen(&cd->brd);
66880ee5cbfSDavid du Colombier }
66980ee5cbfSDavid du Colombier
670