Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <libsec.h>
5 #include <ctype.h>
7 #include "iso9660.h"
9 /*
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.
16 */
17 char*
18 isostring(uchar *buf, int len)
19 {
20 char *p, *q;
22 p = emalloc(len+1);
23 memmove(p, buf, len);
24 p[len] = '\0';
25 while(len > 0 && p[len-1] == ' ')
26 p[--len] = '\0';
27 for(q=p; *q; q++)
28 *q = tolower((uchar)*q);
29 q = atom(p);
30 free(p);
31 return q;
32 }
34 int
35 isisofrog(char c)
36 {
37 if(c >= '0' && c <= '9')
38 return 0;
39 if(c >= 'a' && c <= 'z')
40 return 0;
41 if(c == '_')
42 return 0;
44 return 1;
45 }
47 int
48 isbadiso9660(char *s)
49 {
50 char *p, *q;
51 int i;
53 if((p = strchr(s, '.')) != nil) {
54 if(p-s > 8)
55 return 1;
56 for(q=s; q<p; q++)
57 if(isisofrog(*q))
58 return 1;
59 if(strlen(p+1) > 3)
60 return 1;
61 for(q=p+1; *q; q++)
62 if(isisofrog(*q))
63 return 1;
64 } else {
65 if(strlen(s) > 8)
66 return 1;
67 for(q=s; *q; q++)
68 if(isisofrog(*q))
69 return 1;
71 /*
72 * we rename files of the form [FD]dddddd
73 * so they don't interfere with us.
74 */
75 if(strlen(s) == 7 && (s[0] == 'D' || s[0] == 'F')) {
76 for(i=1; i<7; i++)
77 if(s[i] < '0' || s[i] > '9')
78 break;
79 if(i == 7)
80 return 1;
81 }
82 }
83 return 0;
84 }
86 /*
87 * ISO9660 name comparison
88 *
89 * The standard algorithm is as follows:
90 * Take the filenames without extensions, pad the shorter with 0x20s (spaces),
91 * and do strcmp. If they are equal, go on.
92 * Take the extensions, pad the shorter with 0x20s (spaces),
93 * and do strcmp. If they are equal, go on.
94 * Compare the version numbers.
95 *
96 * Since Plan 9 names are not allowed to contain characters 0x00-0x1F,
97 * the padded comparisons are equivalent to using strcmp directly.
98 * We still need to handle the base and extension differently,
99 * so that .foo sorts before !foo.foo.
100 */
101 int
102 isocmp(const void *va, const void *vb)
104 int i;
105 char s1[32], s2[32], *b1, *b2, *e1, *e2;
106 const Direc *a, *b;
108 a = va;
109 b = vb;
111 strecpy(s1, s1+sizeof s1, a->confname);
112 b1 = s1;
113 strecpy(s2, s2+sizeof s2, b->confname);
114 b2 = s2;
115 if((e1 = strchr(b1, '.')) != nil)
116 *e1++ = '\0';
117 else
118 e1 = "";
119 if((e2 = strchr(b2, '.')) != nil)
120 *e2++ = '\0';
121 else
122 e2 = "";
124 if((i = strcmp(b1, b2)) != 0)
125 return i;
127 return strcmp(e1, e2);
130 static char*
131 mkisostring(char *isobuf, int n, char *s)
133 char *p, *q, *eq;
135 eq = isobuf+n;
136 for(p=s, q=isobuf; *p && q < eq; p++)
137 if('a' <= *p && *p <= 'z')
138 *q++ = *p+'A'-'a';
139 else
140 *q++ = *p;
142 while(q < eq)
143 *q++ = ' ';
145 return isobuf;
148 void
149 Cputisopvd(Cdimg *cd, Cdinfo info)
151 char buf[130];
153 Cputc(cd, 1); /* primary volume descriptor */
154 Cputs(cd, "CD001", 5); /* standard identifier */
155 Cputc(cd, 1); /* volume descriptor version */
156 Cputc(cd, 0); /* unused */
158 assert(~info.flags & (CDplan9|CDrockridge));
160 /* system identifier */
161 strcpy(buf, "");
162 if(info.flags & CDplan9)
163 strcat(buf, "plan 9 ");
164 if(info.flags & CDrockridge)
165 strcat(buf, "rrip ");
166 if(info.flags & CDbootable)
167 strcat(buf, "boot ");
168 if(info.flags & CDconform)
169 strcat(buf, "iso9660");
170 else
171 strcat(buf, "utf8");
173 struprcpy(buf, buf);
174 Cputs(cd, buf, 32);
176 Cputs(cd, mkisostring(buf, 32, info.volumename), 32); /* volume identifier */
178 Crepeat(cd, 0, 8); /* unused */
179 Cputn(cd, 0, 4); /* volume space size */
180 Crepeat(cd, 0, 32); /* unused */
181 Cputn(cd, 1, 2); /* volume set size */
182 Cputn(cd, 1, 2); /* volume sequence number */
183 Cputn(cd, Blocksize, 2); /* logical block size */
184 Cputn(cd, 0, 4); /* path table size */
185 Cputnl(cd, 0, 4); /* location of Lpath */
186 Cputnl(cd, 0, 4); /* location of optional Lpath */
187 Cputnm(cd, 0, 4); /* location of Mpath */
188 Cputnm(cd, 0, 4); /* location of optional Mpath */
189 Cputisodir(cd, nil, DTroot, 1, Cwoffset(cd)); /* root directory */
191 Cputs(cd, mkisostring(buf, 128, info.volumeset), 128); /* volume set identifier */
192 Cputs(cd, mkisostring(buf, 128, info.publisher), 128); /* publisher identifier */
193 Cputs(cd, mkisostring(buf, 128, info.preparer), 128); /* data preparer identifier */
194 Cputs(cd, mkisostring(buf, 128, info.application), 128); /* application identifier */
196 Cputs(cd, "", 37); /* copyright notice */
197 Cputs(cd, "", 37); /* abstract */
198 Cputs(cd, "", 37); /* bibliographic file */
199 Cputdate1(cd, now); /* volume creation date */
200 Cputdate1(cd, now); /* volume modification date */
201 Cputdate1(cd, 0); /* volume expiration date */
202 Cputdate1(cd, 0); /* volume effective date */
203 Cputc(cd, 1); /* file structure version */
204 Cpadblock(cd);