|  | #include <u.h> | 
|  | #include <libc.h> | 
|  | #include <bio.h> | 
|  | #include <libsec.h> | 
|  |  | 
|  | #include "iso9660.h" | 
|  |  | 
|  | char* | 
|  | jolietstring(uchar *buf, int len) | 
|  | { | 
|  | char *p, *q; | 
|  | int i; | 
|  | Rune *rp; | 
|  |  | 
|  | rp = emalloc(sizeof(Rune)*(len/2+1)); | 
|  | p = emalloc(UTFmax*(len/2+1)); | 
|  |  | 
|  | for(i=0; i<len/2; i++) | 
|  | rp[i] = (buf[2*i]<<8) | buf[2*i+1]; | 
|  | rp[i] = (Rune)'\0'; | 
|  |  | 
|  | snprint(p, UTFmax*(len/2+1), "%S", rp); | 
|  | q = atom(p); | 
|  | free(p); | 
|  | return q; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Joliet name validity check | 
|  | * | 
|  | * Joliet names have length at most 128 bytes (64 runes), | 
|  | * and cannot contain '*', '/', ':', ';', '?', or '\'. | 
|  | */ | 
|  | int | 
|  | isjolietfrog(Rune r) | 
|  | { | 
|  | return r==L'*' || r==L'/' || r==L':' | 
|  | || r==';' || r=='?' || r=='\\'; | 
|  | } | 
|  |  | 
|  | int | 
|  | isbadjoliet(char *s) | 
|  | { | 
|  | Rune r[256], *p; | 
|  |  | 
|  | if(utflen(s) > 64) | 
|  | return 1; | 
|  | strtorune(r, s); | 
|  | for(p=r; *p; p++) | 
|  | if(isjolietfrog(*p)) | 
|  | return 1; | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Joliet name comparison | 
|  | * | 
|  | * The standard algorithm is the ISO9660 algorithm but | 
|  | * on the encoded Runes.  Runes are encoded in big endian | 
|  | * format, so we can just use runecmp. | 
|  | * | 
|  | * Padding is with zeros, but that still doesn't affect us. | 
|  | */ | 
|  |  | 
|  | static Rune emptystring[] = { (Rune)0 }; | 
|  | int | 
|  | jolietcmp(const void *va, const void *vb) | 
|  | { | 
|  | int i; | 
|  | Rune s1[256], s2[256], *b1, *b2, *e1, *e2;	/*BUG*/ | 
|  | const Direc *a, *b; | 
|  |  | 
|  | a = va; | 
|  | b = vb; | 
|  |  | 
|  | b1 = strtorune(s1, a->confname); | 
|  | b2 = strtorune(s2, b->confname); | 
|  | if((e1 = runechr(b1, (Rune)'.')) != nil) | 
|  | *e1++ = '\0'; | 
|  | else | 
|  | e1 = emptystring; | 
|  |  | 
|  | if((e2 = runechr(b2, (Rune)'.')) != nil) | 
|  | *e2++ = '\0'; | 
|  | else | 
|  | e2 = emptystring; | 
|  |  | 
|  | if((i = runecmp(b1, b2)) != 0) | 
|  | return i; | 
|  |  | 
|  | return runecmp(e1, e2); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Write a Joliet secondary volume descriptor. | 
|  | */ | 
|  | void | 
|  | Cputjolietsvd(Cdimg *cd, Cdinfo info) | 
|  | { | 
|  | Cputc(cd, 2);				/* secondary volume descriptor */ | 
|  | Cputs(cd, "CD001", 5);			/* standard identifier */ | 
|  | Cputc(cd, 1);				/* volume descriptor version */ | 
|  | Cputc(cd, 0);				/* unused */ | 
|  |  | 
|  | Cputrscvt(cd, "Joliet Plan 9", 32);			/* system identifier */ | 
|  | Cputrscvt(cd, info.volumename, 32);			/* volume identifier */ | 
|  |  | 
|  | Crepeat(cd, 0, 8);				/* unused */ | 
|  | Cputn(cd, 0, 4);				/* volume space size */ | 
|  | Cputc(cd, 0x25);				/* escape sequences: UCS-2 Level 2 */ | 
|  | Cputc(cd, 0x2F); | 
|  | Cputc(cd, 0x43); | 
|  |  | 
|  | Crepeat(cd, 0, 29); | 
|  | Cputn(cd, 1, 2);				/* volume set size */ | 
|  | Cputn(cd, 1, 2);				/* volume sequence number */ | 
|  | Cputn(cd, Blocksize, 2);			/* logical block size */ | 
|  | Cputn(cd, 0, 4);				/* path table size */ | 
|  | Cputnl(cd, 0, 4);				/* location of Lpath */ | 
|  | Cputnl(cd, 0, 4);				/* location of optional Lpath */ | 
|  | Cputnm(cd, 0, 4);				/* location of Mpath */ | 
|  | Cputnm(cd, 0, 4);				/* location of optional Mpath */ | 
|  | Cputjolietdir(cd, nil, DTroot, 1, Cwoffset(cd));			/* root directory */ | 
|  | Cputrscvt(cd, info.volumeset, 128);		/* volume set identifier */ | 
|  | Cputrscvt(cd, info.publisher, 128);			/* publisher identifier */ | 
|  | Cputrscvt(cd, info.preparer, 128);			/* data preparer identifier */ | 
|  | Cputrscvt(cd, info.application, 128);		/* application identifier */ | 
|  | Cputrscvt(cd, "", 37);			/* copyright notice */ | 
|  | Cputrscvt(cd, "", 37);			/* abstract */ | 
|  | Cputrscvt(cd, "", 37);			/* bibliographic file */ | 
|  | Cputdate1(cd, now);				/* volume creation date */ | 
|  | Cputdate1(cd, now);				/* volume modification date */ | 
|  | Cputdate1(cd, 0);				/* volume expiration date */ | 
|  | Cputdate1(cd, 0);				/* volume effective date */ | 
|  | Cputc(cd, 1);				/* file structure version */ | 
|  | Cpadblock(cd); | 
|  | } | 
|  |  |