10 * ISO 9660 file names must be uppercase, digits, or underscore.
11 * We use lowercase, digits, and underscore, translating lower to upper
12 * in mkisostring, and upper to lower in isostring.
13 * Files with uppercase letters in their names are thus nonconforming.
14 * Conforming files also must have a basename
15 * at most 8 letters and at most one suffix of at most 3 letters.
18 isostring(uchar *buf, int len)
25 while(len > 0 && p[len-1] == ' ')
38 if(c >= '0' && c <= '9')
40 if(c >= 'a' && c <= 'z')
54 if((p = strchr(s, '.')) != nil) {
73 * we rename files of the form [FD]dddddd
74 * so they don't interfere with us.
76 if(strlen(s) == 7 && (s[0] == 'D' || s[0] == 'F')) {
78 if(s[i] < '0' || s[i] > '9')
88 * ISO9660 name comparison
90 * The standard algorithm is as follows:
91 * Take the filenames without extensions, pad the shorter with 0x20s (spaces),
92 * and do strcmp. If they are equal, go on.
93 * Take the extensions, pad the shorter with 0x20s (spaces),
94 * and do strcmp. If they are equal, go on.
95 * Compare the version numbers.
97 * Since Plan 9 names are not allowed to contain characters 0x00-0x1F,
98 * the padded comparisons are equivalent to using strcmp directly.
99 * We still need to handle the base and extension differently,
100 * so that .foo sorts before !foo.foo.
103 isocmp(const void *va, const void *vb)
106 char s1[32], s2[32], *b1, *b2, *e1, *e2;
112 strecpy(s1, s1+sizeof s1, a->confname);
114 strecpy(s2, s2+sizeof s2, b->confname);
116 if((e1 = strchr(b1, '.')) != nil)
120 if((e2 = strchr(b2, '.')) != nil)
125 if((i = strcmp(b1, b2)) != 0)
128 return strcmp(e1, e2);
132 mkisostring(char *isobuf, int n, char *s)
137 for(p=s, q=isobuf; *p && q < eq; p++)
138 if('a' <= *p && *p <= 'z')
150 Cputisopvd(Cdimg *cd, Cdinfo info)
154 Cputc(cd, 1); /* primary volume descriptor */
155 Cputs(cd, "CD001", 5); /* standard identifier */
156 Cputc(cd, 1); /* volume descriptor version */
157 Cputc(cd, 0); /* unused */
159 assert(~info.flags & (CDplan9|CDrockridge));
161 /* system identifier */
163 if(info.flags & CDplan9)
164 strcat(buf, "plan 9 ");
165 if(info.flags & CDrockridge)
166 strcat(buf, "rrip ");
167 if(info.flags & CDbootable)
168 strcat(buf, "boot ");
169 if(info.flags & CDconform)
170 strcat(buf, "iso9660");
177 Cputs(cd, mkisostring(buf, 32, info.volumename), 32); /* volume identifier */
179 Crepeat(cd, 0, 8); /* unused */
180 Cputn(cd, 0, 4); /* volume space size */
181 Crepeat(cd, 0, 32); /* unused */
182 Cputn(cd, 1, 2); /* volume set size */
183 Cputn(cd, 1, 2); /* volume sequence number */
184 Cputn(cd, Blocksize, 2); /* logical block size */
185 Cputn(cd, 0, 4); /* path table size */
186 Cputnl(cd, 0, 4); /* location of Lpath */
187 Cputnl(cd, 0, 4); /* location of optional Lpath */
188 Cputnm(cd, 0, 4); /* location of Mpath */
189 Cputnm(cd, 0, 4); /* location of optional Mpath */
190 Cputisodir(cd, nil, DTroot, 1, Cwoffset(cd)); /* root directory */
192 Cputs(cd, mkisostring(buf, 128, info.volumeset), 128); /* volume set identifier */
193 Cputs(cd, mkisostring(buf, 128, info.publisher), 128); /* publisher identifier */
194 Cputs(cd, mkisostring(buf, 128, info.preparer), 128); /* data preparer identifier */
195 Cputs(cd, mkisostring(buf, 128, info.application), 128); /* application identifier */
197 Cputs(cd, "", 37); /* copyright notice */
198 Cputs(cd, "", 37); /* abstract */
199 Cputs(cd, "", 37); /* bibliographic file */
200 Cputdate1(cd, now); /* volume creation date */
201 Cputdate1(cd, now); /* volume modification date */
202 Cputdate1(cd, 0); /* volume expiration date */
203 Cputdate1(cd, 0); /* volume effective date */
204 Cputc(cd, 1); /* file structure version */