1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <libsec.h>
5 
6 #include "iso9660.h"
7 
8 char*
jolietstring(uchar * buf,int len)9 jolietstring(uchar *buf, int len)
10 {
11 	char *p, *q;
12 	int i;
13 	Rune *rp;
14 
15 	rp = emalloc(sizeof(Rune)*(len/2+1));
16 	p = emalloc(UTFmax*(len/2+1));
17 
18 	for(i=0; i<len/2; i++)
19 		rp[i] = (buf[2*i]<<8) | buf[2*i+1];
20 	rp[i] = (Rune)'\0';
21 
22 	snprint(p, UTFmax*(len/2+1), "%S", rp);
23 	q = atom(p);
24 	free(p);
25 	return q;
26 }
27 
28 /*
29  * Joliet name validity check
30  *
31  * Joliet names have length at most 128 bytes (64 runes),
32  * and cannot contain '*', '/', ':', ';', '?', or '\'.
33  */
34 int
isjolietfrog(Rune r)35 isjolietfrog(Rune r)
36 {
37 	return r=='*' || r=='/' || r==':'
38 		|| r==';' || r=='?' || r=='\\';
39 }
40 
41 int
isbadjoliet(char * s)42 isbadjoliet(char *s)
43 {
44 	Rune r[256], *p;
45 
46 	if(utflen(s) > 64)
47 		return 1;
48 	strtorune(r, s);
49 	for(p=r; *p; p++)
50 		if(isjolietfrog(*p))
51 			return 1;
52 	return 0;
53 }
54 
55 /*
56  * Joliet name comparison
57  *
58  * The standard algorithm is the ISO9660 algorithm but
59  * on the encoded Runes.  Runes are encoded in big endian
60  * format, so we can just use runecmp.
61  *
62  * Padding is with zeros, but that still doesn't affect us.
63  */
64 
65 static Rune emptystring[] = { (Rune)0 };
66 int
jolietcmp(const void * va,const void * vb)67 jolietcmp(const void *va, const void *vb)
68 {
69 	int i;
70 	Rune s1[256], s2[256], *b1, *b2, *e1, *e2;	/*BUG*/
71 	const Direc *a, *b;
72 
73 	a = va;
74 	b = vb;
75 
76 	b1 = strtorune(s1, a->confname);
77 	b2 = strtorune(s2, b->confname);
78 	if((e1 = runechr(b1, (Rune)'.')) != nil)
79 		*e1++ = '\0';
80 	else
81 		e1 = emptystring;
82 
83 	if((e2 = runechr(b2, (Rune)'.')) != nil)
84 		*e2++ = '\0';
85 	else
86 		e2 = emptystring;
87 
88 	if((i = runecmp(b1, b2)) != 0)
89 		return i;
90 
91 	return runecmp(e1, e2);
92 }
93 
94 /*
95  * Write a Joliet secondary volume descriptor.
96  */
97 void
Cputjolietsvd(Cdimg * cd,Cdinfo info)98 Cputjolietsvd(Cdimg *cd, Cdinfo info)
99 {
100 	Cputc(cd, 2);				/* secondary volume descriptor */
101 	Cputs(cd, "CD001", 5);			/* standard identifier */
102 	Cputc(cd, 1);				/* volume descriptor version */
103 	Cputc(cd, 0);				/* unused */
104 
105 	Cputrscvt(cd, "Joliet Plan 9", 32);			/* system identifier */
106 	Cputrscvt(cd, info.volumename, 32);			/* volume identifier */
107 
108 	Crepeat(cd, 0, 8);				/* unused */
109 	Cputn(cd, 0, 4);				/* volume space size */
110 	Cputc(cd, 0x25);				/* escape sequences: UCS-2 Level 2 */
111 	Cputc(cd, 0x2F);
112 	Cputc(cd, 0x43);
113 
114 	Crepeat(cd, 0, 29);
115 	Cputn(cd, 1, 2);				/* volume set size */
116 	Cputn(cd, 1, 2);				/* volume sequence number */
117 	Cputn(cd, Blocksize, 2);			/* logical block size */
118 	Cputn(cd, 0, 4);				/* path table size */
119 	Cputnl(cd, 0, 4);				/* location of Lpath */
120 	Cputnl(cd, 0, 4);				/* location of optional Lpath */
121 	Cputnm(cd, 0, 4);				/* location of Mpath */
122 	Cputnm(cd, 0, 4);				/* location of optional Mpath */
123 	Cputjolietdir(cd, nil, DTroot, 1, Cwoffset(cd));			/* root directory */
124 	Cputrscvt(cd, info.volumeset, 128);		/* volume set identifier */
125 	Cputrscvt(cd, info.publisher, 128);			/* publisher identifier */
126 	Cputrscvt(cd, info.preparer, 128);			/* data preparer identifier */
127 	Cputrscvt(cd, info.application, 128);		/* application identifier */
128 	Cputrscvt(cd, "", 37);			/* copyright notice */
129 	Cputrscvt(cd, "", 37);			/* abstract */
130 	Cputrscvt(cd, "", 37);			/* bibliographic file */
131 	Cputdate1(cd, now);				/* volume creation date */
132 	Cputdate1(cd, now);				/* volume modification date */
133 	Cputdate1(cd, 0);				/* volume expiration date */
134 	Cputdate1(cd, 0);				/* volume effective date */
135 	Cputc(cd, 1);				/* file structure version */
136 	Cpadblock(cd);
137 }
138