Blame


1 7285a491 2004-06-17 devnull #include <u.h>
2 7285a491 2004-06-17 devnull #include <libc.h>
3 7285a491 2004-06-17 devnull #include <bio.h>
4 7285a491 2004-06-17 devnull #include <libsec.h>
5 7285a491 2004-06-17 devnull #include <ctype.h>
6 7285a491 2004-06-17 devnull #include "iso9660.h"
7 7285a491 2004-06-17 devnull
8 7285a491 2004-06-17 devnull static void
9 7285a491 2004-06-17 devnull md5cd(Cdimg *cd, ulong block, ulong length, uchar *digest)
10 7285a491 2004-06-17 devnull {
11 7285a491 2004-06-17 devnull int n;
12 7285a491 2004-06-17 devnull uchar buf[Blocksize];
13 7285a491 2004-06-17 devnull DigestState *s;
14 7285a491 2004-06-17 devnull
15 7285a491 2004-06-17 devnull s = md5(nil, 0, nil, nil);
16 7285a491 2004-06-17 devnull while(length > 0) {
17 7285a491 2004-06-17 devnull n = length;
18 7285a491 2004-06-17 devnull if(n > Blocksize)
19 7285a491 2004-06-17 devnull n = Blocksize;
20 7285a491 2004-06-17 devnull
21 7285a491 2004-06-17 devnull Creadblock(cd, buf, block, n);
22 7285a491 2004-06-17 devnull
23 7285a491 2004-06-17 devnull md5(buf, n, nil, s);
24 7285a491 2004-06-17 devnull
25 7285a491 2004-06-17 devnull block++;
26 7285a491 2004-06-17 devnull length -= n;
27 7285a491 2004-06-17 devnull }
28 7285a491 2004-06-17 devnull md5(nil, 0, digest, s);
29 7285a491 2004-06-17 devnull }
30 7285a491 2004-06-17 devnull
31 7285a491 2004-06-17 devnull static Dumpdir*
32 7285a491 2004-06-17 devnull mkdumpdir(char *name, uchar *md5, ulong block, ulong length)
33 7285a491 2004-06-17 devnull {
34 7285a491 2004-06-17 devnull Dumpdir *d;
35 7285a491 2004-06-17 devnull
36 7285a491 2004-06-17 devnull assert(block != 0);
37 7285a491 2004-06-17 devnull
38 7285a491 2004-06-17 devnull d = emalloc(sizeof *d);
39 7285a491 2004-06-17 devnull d->name = name;
40 7285a491 2004-06-17 devnull memmove(d->md5, md5, sizeof d->md5);
41 7285a491 2004-06-17 devnull d->block = block;
42 7285a491 2004-06-17 devnull d->length = length;
43 7285a491 2004-06-17 devnull
44 7285a491 2004-06-17 devnull return d;
45 7285a491 2004-06-17 devnull }
46 7285a491 2004-06-17 devnull
47 7285a491 2004-06-17 devnull static Dumpdir**
48 7285a491 2004-06-17 devnull ltreewalkmd5(Dumpdir **l, uchar *md5)
49 7285a491 2004-06-17 devnull {
50 7285a491 2004-06-17 devnull int i;
51 7285a491 2004-06-17 devnull
52 7285a491 2004-06-17 devnull while(*l) {
53 7285a491 2004-06-17 devnull i = memcmp(md5, (*l)->md5, MD5dlen);
54 7285a491 2004-06-17 devnull if(i < 0)
55 7285a491 2004-06-17 devnull l = &(*l)->md5left;
56 7285a491 2004-06-17 devnull else if(i == 0)
57 7285a491 2004-06-17 devnull return l;
58 7285a491 2004-06-17 devnull else
59 7285a491 2004-06-17 devnull l = &(*l)->md5right;
60 7285a491 2004-06-17 devnull }
61 7285a491 2004-06-17 devnull return l;
62 7285a491 2004-06-17 devnull }
63 7285a491 2004-06-17 devnull
64 7285a491 2004-06-17 devnull static Dumpdir**
65 7285a491 2004-06-17 devnull ltreewalkblock(Dumpdir **l, ulong block)
66 7285a491 2004-06-17 devnull {
67 7285a491 2004-06-17 devnull while(*l) {
68 7285a491 2004-06-17 devnull if(block < (*l)->block)
69 7285a491 2004-06-17 devnull l = &(*l)->blockleft;
70 7285a491 2004-06-17 devnull else if(block == (*l)->block)
71 7285a491 2004-06-17 devnull return l;
72 7285a491 2004-06-17 devnull else
73 7285a491 2004-06-17 devnull l = &(*l)->blockright;
74 7285a491 2004-06-17 devnull }
75 7285a491 2004-06-17 devnull return l;
76 7285a491 2004-06-17 devnull }
77 7285a491 2004-06-17 devnull
78 7285a491 2004-06-17 devnull /*
79 7285a491 2004-06-17 devnull * Add a particular file to our binary tree.
80 7285a491 2004-06-17 devnull */
81 7285a491 2004-06-17 devnull static void
82 7285a491 2004-06-17 devnull addfile(Cdimg *cd, Dump *d, char *name, Direc *dir)
83 7285a491 2004-06-17 devnull {
84 7285a491 2004-06-17 devnull uchar md5[MD5dlen];
85 7285a491 2004-06-17 devnull Dumpdir **lblock;
86 7285a491 2004-06-17 devnull
87 7285a491 2004-06-17 devnull assert((dir->mode & DMDIR) == 0);
88 7285a491 2004-06-17 devnull
89 7285a491 2004-06-17 devnull if(dir->length == 0)
90 7285a491 2004-06-17 devnull return;
91 7285a491 2004-06-17 devnull
92 7285a491 2004-06-17 devnull lblock = ltreewalkblock(&d->blockroot, dir->block);
93 7285a491 2004-06-17 devnull if(*lblock != nil) {
94 7285a491 2004-06-17 devnull if((*lblock)->length == dir->length)
95 7285a491 2004-06-17 devnull return;
96 7285a491 2004-06-17 devnull fprint(2, "block %lud length %lud %s %lud %s\n", dir->block, (*lblock)->length, (*lblock)->name,
97 7285a491 2004-06-17 devnull dir->length, dir->name);
98 7285a491 2004-06-17 devnull assert(0);
99 7285a491 2004-06-17 devnull }
100 7285a491 2004-06-17 devnull
101 7285a491 2004-06-17 devnull md5cd(cd, dir->block, dir->length, md5);
102 7285a491 2004-06-17 devnull if(chatty > 1)
103 7285a491 2004-06-17 devnull fprint(2, "note file %.16H %lud (%s)\n", md5, dir->length, dir->name);
104 7285a491 2004-06-17 devnull insertmd5(d, name, md5, dir->block, dir->length);
105 7285a491 2004-06-17 devnull }
106 7285a491 2004-06-17 devnull
107 7285a491 2004-06-17 devnull void
108 7285a491 2004-06-17 devnull insertmd5(Dump *d, char *name, uchar *md5, ulong block, ulong length)
109 7285a491 2004-06-17 devnull {
110 7285a491 2004-06-17 devnull Dumpdir **lmd5;
111 7285a491 2004-06-17 devnull Dumpdir **lblock;
112 7285a491 2004-06-17 devnull
113 7285a491 2004-06-17 devnull lblock = ltreewalkblock(&d->blockroot, block);
114 7285a491 2004-06-17 devnull if(*lblock != nil) {
115 7285a491 2004-06-17 devnull if((*lblock)->length == length)
116 7285a491 2004-06-17 devnull return;
117 7285a491 2004-06-17 devnull fprint(2, "block %lud length %lud %lud\n", block, (*lblock)->length, length);
118 7285a491 2004-06-17 devnull assert(0);
119 7285a491 2004-06-17 devnull }
120 7285a491 2004-06-17 devnull
121 7285a491 2004-06-17 devnull assert(length != 0);
122 7285a491 2004-06-17 devnull *lblock = mkdumpdir(name, md5, block, length);
123 7285a491 2004-06-17 devnull
124 7285a491 2004-06-17 devnull lmd5 = ltreewalkmd5(&d->md5root, md5);
125 7285a491 2004-06-17 devnull if(*lmd5 != nil)
126 7285a491 2004-06-17 devnull fprint(2, "warning: data duplicated on CD\n");
127 7285a491 2004-06-17 devnull else
128 7285a491 2004-06-17 devnull *lmd5 = *lblock;
129 7285a491 2004-06-17 devnull }
130 7285a491 2004-06-17 devnull
131 7285a491 2004-06-17 devnull /*
132 7285a491 2004-06-17 devnull * Fill all the children entries for a particular directory;
133 7285a491 2004-06-17 devnull * all we care about is block, length, and whether it is a directory.
134 7285a491 2004-06-17 devnull */
135 7285a491 2004-06-17 devnull void
136 7285a491 2004-06-17 devnull readkids(Cdimg *cd, Direc *dir, char *(*cvt)(uchar*, int))
137 7285a491 2004-06-17 devnull {
138 7285a491 2004-06-17 devnull char *dot, *dotdot;
139 7285a491 2004-06-17 devnull int m, n;
140 7285a491 2004-06-17 devnull uchar buf[Blocksize], *ebuf, *p;
141 7285a491 2004-06-17 devnull ulong b, nb;
142 7285a491 2004-06-17 devnull Cdir *c;
143 7285a491 2004-06-17 devnull Direc dx;
144 7285a491 2004-06-17 devnull
145 7285a491 2004-06-17 devnull assert(dir->mode & DMDIR);
146 7285a491 2004-06-17 devnull
147 7285a491 2004-06-17 devnull dot = atom(".");
148 7285a491 2004-06-17 devnull dotdot = atom("..");
149 7285a491 2004-06-17 devnull ebuf = buf+Blocksize;
150 7285a491 2004-06-17 devnull nb = (dir->length+Blocksize-1) / Blocksize;
151 7285a491 2004-06-17 devnull
152 7285a491 2004-06-17 devnull n = 0;
153 7285a491 2004-06-17 devnull for(b=0; b<nb; b++) {
154 7285a491 2004-06-17 devnull Creadblock(cd, buf, dir->block + b, Blocksize);
155 7285a491 2004-06-17 devnull p = buf;
156 7285a491 2004-06-17 devnull while(p < ebuf) {
157 7285a491 2004-06-17 devnull c = (Cdir*)p;
158 7285a491 2004-06-17 devnull if(c->len == 0)
159 7285a491 2004-06-17 devnull break;
160 7285a491 2004-06-17 devnull if(p+c->len > ebuf)
161 7285a491 2004-06-17 devnull break;
162 7285a491 2004-06-17 devnull if(parsedir(cd, &dx, p, ebuf-p, cvt) == 0 && dx.name != dot && dx.name != dotdot)
163 7285a491 2004-06-17 devnull n++;
164 7285a491 2004-06-17 devnull p += c->len;
165 7285a491 2004-06-17 devnull }
166 7285a491 2004-06-17 devnull }
167 7285a491 2004-06-17 devnull
168 7285a491 2004-06-17 devnull m = (n+Ndirblock-1)/Ndirblock * Ndirblock;
169 7285a491 2004-06-17 devnull dir->child = emalloc(m*sizeof dir->child[0]);
170 7285a491 2004-06-17 devnull dir->nchild = n;
171 7285a491 2004-06-17 devnull
172 7285a491 2004-06-17 devnull n = 0;
173 7285a491 2004-06-17 devnull for(b=0; b<nb; b++) {
174 7285a491 2004-06-17 devnull assert(n <= dir->nchild);
175 7285a491 2004-06-17 devnull Creadblock(cd, buf, dir->block + b, Blocksize);
176 7285a491 2004-06-17 devnull p = buf;
177 7285a491 2004-06-17 devnull while(p < ebuf) {
178 7285a491 2004-06-17 devnull c = (Cdir*)p;
179 7285a491 2004-06-17 devnull if(c->len == 0)
180 7285a491 2004-06-17 devnull break;
181 7285a491 2004-06-17 devnull if(p+c->len > ebuf)
182 7285a491 2004-06-17 devnull break;
183 7285a491 2004-06-17 devnull if(parsedir(cd, &dx, p, ebuf-p, cvt) == 0 && dx.name != dot && dx.name != dotdot) {
184 7285a491 2004-06-17 devnull assert(n < dir->nchild);
185 7285a491 2004-06-17 devnull dir->child[n++] = dx;
186 7285a491 2004-06-17 devnull }
187 7285a491 2004-06-17 devnull p += c->len;
188 7285a491 2004-06-17 devnull }
189 7285a491 2004-06-17 devnull }
190 7285a491 2004-06-17 devnull }
191 7285a491 2004-06-17 devnull
192 7285a491 2004-06-17 devnull /*
193 7285a491 2004-06-17 devnull * Free the children. Make sure their children are free too.
194 7285a491 2004-06-17 devnull */
195 7285a491 2004-06-17 devnull void
196 7285a491 2004-06-17 devnull freekids(Direc *dir)
197 7285a491 2004-06-17 devnull {
198 7285a491 2004-06-17 devnull int i;
199 7285a491 2004-06-17 devnull
200 7285a491 2004-06-17 devnull for(i=0; i<dir->nchild; i++)
201 7285a491 2004-06-17 devnull assert(dir->child[i].nchild == 0);
202 7285a491 2004-06-17 devnull
203 7285a491 2004-06-17 devnull free(dir->child);
204 7285a491 2004-06-17 devnull dir->child = nil;
205 7285a491 2004-06-17 devnull dir->nchild = 0;
206 7285a491 2004-06-17 devnull }
207 7285a491 2004-06-17 devnull
208 7285a491 2004-06-17 devnull /*
209 7285a491 2004-06-17 devnull * Add a whole directory and all its children to our binary tree.
210 7285a491 2004-06-17 devnull */
211 7285a491 2004-06-17 devnull static void
212 7285a491 2004-06-17 devnull adddir(Cdimg *cd, Dump *d, Direc *dir)
213 7285a491 2004-06-17 devnull {
214 7285a491 2004-06-17 devnull int i;
215 7285a491 2004-06-17 devnull
216 7285a491 2004-06-17 devnull readkids(cd, dir, isostring);
217 7285a491 2004-06-17 devnull for(i=0; i<dir->nchild; i++) {
218 7285a491 2004-06-17 devnull if(dir->child[i].mode & DMDIR)
219 7285a491 2004-06-17 devnull adddir(cd, d, &dir->child[i]);
220 7285a491 2004-06-17 devnull else
221 7285a491 2004-06-17 devnull addfile(cd, d, atom(dir->name), &dir->child[i]);
222 7285a491 2004-06-17 devnull }
223 7285a491 2004-06-17 devnull freekids(dir);
224 7285a491 2004-06-17 devnull }
225 7285a491 2004-06-17 devnull
226 7285a491 2004-06-17 devnull Dumpdir*
227 7285a491 2004-06-17 devnull lookupmd5(Dump *d, uchar *md5)
228 7285a491 2004-06-17 devnull {
229 7285a491 2004-06-17 devnull return *ltreewalkmd5(&d->md5root, md5);
230 7285a491 2004-06-17 devnull }
231 7285a491 2004-06-17 devnull
232 7285a491 2004-06-17 devnull void
233 7285a491 2004-06-17 devnull adddirx(Cdimg *cd, Dump *d, Direc *dir, int lev)
234 7285a491 2004-06-17 devnull {
235 7285a491 2004-06-17 devnull int i;
236 7285a491 2004-06-17 devnull Direc dd;
237 7285a491 2004-06-17 devnull
238 7285a491 2004-06-17 devnull if(lev == 2){
239 7285a491 2004-06-17 devnull dd = *dir;
240 7285a491 2004-06-17 devnull adddir(cd, d, &dd);
241 7285a491 2004-06-17 devnull return;
242 7285a491 2004-06-17 devnull }
243 7285a491 2004-06-17 devnull for(i=0; i<dir->nchild; i++)
244 7285a491 2004-06-17 devnull adddirx(cd, d, &dir->child[i], lev+1);
245 7285a491 2004-06-17 devnull }
246 7285a491 2004-06-17 devnull
247 7285a491 2004-06-17 devnull Dump*
248 7285a491 2004-06-17 devnull dumpcd(Cdimg *cd, Direc *dir)
249 7285a491 2004-06-17 devnull {
250 7285a491 2004-06-17 devnull Dump *d;
251 7285a491 2004-06-17 devnull
252 7285a491 2004-06-17 devnull d = emalloc(sizeof *d);
253 7285a491 2004-06-17 devnull d->cd = cd;
254 7285a491 2004-06-17 devnull adddirx(cd, d, dir, 0);
255 7285a491 2004-06-17 devnull return d;
256 7285a491 2004-06-17 devnull }
257 7285a491 2004-06-17 devnull
258 7285a491 2004-06-17 devnull /*
259 7285a491 2004-06-17 devnull static ulong
260 7285a491 2004-06-17 devnull minblock(Direc *root, int lev)
261 7285a491 2004-06-17 devnull {
262 7285a491 2004-06-17 devnull int i;
263 7285a491 2004-06-17 devnull ulong m, n;
264 7285a491 2004-06-17 devnull
265 7285a491 2004-06-17 devnull m = root->block;
266 7285a491 2004-06-17 devnull for(i=0; i<root->nchild; i++) {
267 7285a491 2004-06-17 devnull n = minblock(&root->child[i], lev-1);
268 7285a491 2004-06-17 devnull if(m > n)
269 7285a491 2004-06-17 devnull m = n;
270 7285a491 2004-06-17 devnull }
271 7285a491 2004-06-17 devnull return m;
272 7285a491 2004-06-17 devnull }
273 7285a491 2004-06-17 devnull */
274 7285a491 2004-06-17 devnull
275 7285a491 2004-06-17 devnull void
276 7285a491 2004-06-17 devnull copybutname(Direc *d, Direc *s)
277 7285a491 2004-06-17 devnull {
278 7285a491 2004-06-17 devnull Direc x;
279 7285a491 2004-06-17 devnull
280 7285a491 2004-06-17 devnull x = *d;
281 7285a491 2004-06-17 devnull *d = *s;
282 7285a491 2004-06-17 devnull d->name = x.name;
283 7285a491 2004-06-17 devnull d->confname = x.confname;
284 7285a491 2004-06-17 devnull }
285 7285a491 2004-06-17 devnull
286 7285a491 2004-06-17 devnull Direc*
287 7285a491 2004-06-17 devnull createdumpdir(Direc *root, XDir *dir, char *utfname)
288 7285a491 2004-06-17 devnull {
289 7285a491 2004-06-17 devnull char *p;
290 7285a491 2004-06-17 devnull Direc *d;
291 7285a491 2004-06-17 devnull
292 7285a491 2004-06-17 devnull if(utfname[0]=='/')
293 7285a491 2004-06-17 devnull sysfatal("bad dump name '%s'", utfname);
294 7285a491 2004-06-17 devnull p = strchr(utfname, '/');
295 7285a491 2004-06-17 devnull if(p == nil || strchr(p+1, '/'))
296 7285a491 2004-06-17 devnull sysfatal("bad dump name '%s'", utfname);
297 7285a491 2004-06-17 devnull *p++ = '\0';
298 7285a491 2004-06-17 devnull if((d = walkdirec(root, utfname)) == nil)
299 7285a491 2004-06-17 devnull d = adddirec(root, utfname, dir);
300 7285a491 2004-06-17 devnull if(walkdirec(d, p))
301 7285a491 2004-06-17 devnull sysfatal("duplicate dump name '%s/%s'", utfname, p);
302 7285a491 2004-06-17 devnull d = adddirec(d, p, dir);
303 7285a491 2004-06-17 devnull return d;
304 7285a491 2004-06-17 devnull }
305 7285a491 2004-06-17 devnull
306 7285a491 2004-06-17 devnull static void
307 7285a491 2004-06-17 devnull rmdirec(Direc *d, Direc *kid)
308 7285a491 2004-06-17 devnull {
309 7285a491 2004-06-17 devnull Direc *ekid;
310 7285a491 2004-06-17 devnull
311 7285a491 2004-06-17 devnull ekid = d->child+d->nchild;
312 7285a491 2004-06-17 devnull assert(d->child <= kid && kid < ekid);
313 7285a491 2004-06-17 devnull if(ekid != kid+1)
314 7285a491 2004-06-17 devnull memmove(kid, kid+1, (ekid-(kid+1))*sizeof(*kid));
315 7285a491 2004-06-17 devnull d->nchild--;
316 7285a491 2004-06-17 devnull }
317 7285a491 2004-06-17 devnull
318 7285a491 2004-06-17 devnull void
319 7285a491 2004-06-17 devnull rmdumpdir(Direc *root, char *utfname)
320 7285a491 2004-06-17 devnull {
321 7285a491 2004-06-17 devnull char *p;
322 7285a491 2004-06-17 devnull Direc *d, *dd;
323 7285a491 2004-06-17 devnull
324 7285a491 2004-06-17 devnull if(utfname[0]=='/')
325 7285a491 2004-06-17 devnull sysfatal("bad dump name '%s'", utfname);
326 7285a491 2004-06-17 devnull p = strchr(utfname, '/');
327 7285a491 2004-06-17 devnull if(p == nil || strchr(p+1, '/'))
328 7285a491 2004-06-17 devnull sysfatal("bad dump name '%s'", utfname);
329 7285a491 2004-06-17 devnull *p++ = '\0';
330 7285a491 2004-06-17 devnull if((d = walkdirec(root, utfname)) == nil)
331 7285a491 2004-06-17 devnull sysfatal("cannot remove %s/%s: %s does not exist", utfname, p, utfname);
332 7285a491 2004-06-17 devnull p[-1] = '/';
333 7285a491 2004-06-17 devnull
334 7285a491 2004-06-17 devnull if((dd = walkdirec(d, p)) == nil)
335 7285a491 2004-06-17 devnull sysfatal("cannot remove %s: does not exist", utfname);
336 7285a491 2004-06-17 devnull
337 7285a491 2004-06-17 devnull rmdirec(d, dd);
338 7285a491 2004-06-17 devnull if(d->nchild == 0)
339 7285a491 2004-06-17 devnull rmdirec(root, d);
340 7285a491 2004-06-17 devnull }
341 7285a491 2004-06-17 devnull
342 7285a491 2004-06-17 devnull char*
343 7285a491 2004-06-17 devnull adddumpdir(Direc *root, ulong now, XDir *dir)
344 7285a491 2004-06-17 devnull {
345 7285a491 2004-06-17 devnull char buf[40], *p;
346 7285a491 2004-06-17 devnull int n;
347 7285a491 2004-06-17 devnull Direc *dday, *dyear;
348 7285a491 2004-06-17 devnull Tm tm;
349 7285a491 2004-06-17 devnull
350 7285a491 2004-06-17 devnull tm = *localtime(now);
351 7285a491 2004-06-17 devnull
352 7285a491 2004-06-17 devnull sprint(buf, "%d", tm.year+1900);
353 7285a491 2004-06-17 devnull if((dyear = walkdirec(root, buf)) == nil) {
354 7285a491 2004-06-17 devnull dyear = adddirec(root, buf, dir);
355 7285a491 2004-06-17 devnull assert(dyear != nil);
356 7285a491 2004-06-17 devnull }
357 7285a491 2004-06-17 devnull
358 7285a491 2004-06-17 devnull n = 0;
359 7285a491 2004-06-17 devnull sprint(buf, "%.2d%.2d", tm.mon+1, tm.mday);
360 7285a491 2004-06-17 devnull p = buf+strlen(buf);
361 7285a491 2004-06-17 devnull while(walkdirec(dyear, buf))
362 7285a491 2004-06-17 devnull sprint(p, "%d", ++n);
363 7285a491 2004-06-17 devnull
364 7285a491 2004-06-17 devnull dday = adddirec(dyear, buf, dir);
365 7285a491 2004-06-17 devnull assert(dday != nil);
366 7285a491 2004-06-17 devnull
367 7285a491 2004-06-17 devnull sprint(buf, "%s/%s", dyear->name, dday->name);
368 7285a491 2004-06-17 devnull assert(walkdirec(root, buf)==dday);
369 7285a491 2004-06-17 devnull return atom(buf);
370 7285a491 2004-06-17 devnull }
371 7285a491 2004-06-17 devnull
372 7285a491 2004-06-17 devnull /*
373 7285a491 2004-06-17 devnull * The dump directory tree is inferred from a linked list of special blocks.
374 7285a491 2004-06-17 devnull * One block is written at the end of each dump.
375 7285a491 2004-06-17 devnull * The blocks have the form
376 7285a491 2004-06-17 devnull *
377 7285a491 2004-06-17 devnull * plan 9 dump cd
378 7285a491 2004-06-17 devnull * <dump-name> <dump-time> <next-block> <conform-block> <conform-length> \
379 7285a491 2004-06-17 devnull * <iroot-block> <iroot-length> <jroot-block> <jroot-length>
380 7285a491 2004-06-17 devnull *
381 7285a491 2004-06-17 devnull * If only the first line is present, this is the end of the chain.
382 7285a491 2004-06-17 devnull */
383 7285a491 2004-06-17 devnull static char magic[] = "plan 9 dump cd\n";
384 7285a491 2004-06-17 devnull ulong
385 7285a491 2004-06-17 devnull Cputdumpblock(Cdimg *cd)
386 7285a491 2004-06-17 devnull {
387 7285a491 2004-06-17 devnull ulong x;
388 7285a491 2004-06-17 devnull
389 7285a491 2004-06-17 devnull Cwseek(cd, cd->nextblock*Blocksize);
390 7285a491 2004-06-17 devnull x = Cwoffset(cd);
391 7285a491 2004-06-17 devnull Cwrite(cd, magic, sizeof(magic)-1);
392 7285a491 2004-06-17 devnull Cpadblock(cd);
393 7285a491 2004-06-17 devnull return x/Blocksize;
394 7285a491 2004-06-17 devnull }
395 7285a491 2004-06-17 devnull
396 7285a491 2004-06-17 devnull int
397 7285a491 2004-06-17 devnull hasdump(Cdimg *cd)
398 7285a491 2004-06-17 devnull {
399 7285a491 2004-06-17 devnull int i;
400 7285a491 2004-06-17 devnull char buf[128];
401 7285a491 2004-06-17 devnull
402 7285a491 2004-06-17 devnull for(i=16; i<24; i++) {
403 7285a491 2004-06-17 devnull Creadblock(cd, buf, i, sizeof buf);
404 7285a491 2004-06-17 devnull if(memcmp(buf, magic, sizeof(magic)-1) == 0)
405 7285a491 2004-06-17 devnull return i;
406 7285a491 2004-06-17 devnull }
407 7285a491 2004-06-17 devnull return 0;
408 7285a491 2004-06-17 devnull }
409 7285a491 2004-06-17 devnull
410 7285a491 2004-06-17 devnull Direc
411 7285a491 2004-06-17 devnull readdumpdirs(Cdimg *cd, XDir *dir, char *(*cvt)(uchar*, int))
412 7285a491 2004-06-17 devnull {
413 7285a491 2004-06-17 devnull char buf[Blocksize];
414 7285a491 2004-06-17 devnull char *p, *q, *f[16];
415 7285a491 2004-06-17 devnull int i, nf;
416 7285a491 2004-06-17 devnull ulong db, t;
417 7285a491 2004-06-17 devnull Direc *nr, root;
418 7285a491 2004-06-17 devnull XDir xd;
419 7285a491 2004-06-17 devnull
420 7285a491 2004-06-17 devnull mkdirec(&root, dir);
421 7285a491 2004-06-17 devnull db = hasdump(cd);
422 7285a491 2004-06-17 devnull xd = *dir;
423 7285a491 2004-06-17 devnull for(;;){
424 7285a491 2004-06-17 devnull if(db == 0)
425 7285a491 2004-06-17 devnull sysfatal("error in dump blocks");
426 7285a491 2004-06-17 devnull
427 7285a491 2004-06-17 devnull Creadblock(cd, buf, db, sizeof buf);
428 7285a491 2004-06-17 devnull if(memcmp(buf, magic, sizeof(magic)-1) != 0)
429 7285a491 2004-06-17 devnull break;
430 7285a491 2004-06-17 devnull p = buf+sizeof(magic)-1;
431 7285a491 2004-06-17 devnull if(p[0] == '\0')
432 7285a491 2004-06-17 devnull break;
433 7285a491 2004-06-17 devnull if((q = strchr(p, '\n')) != nil)
434 7285a491 2004-06-17 devnull *q = '\0';
435 7285a491 2004-06-17 devnull
436 7285a491 2004-06-17 devnull nf = tokenize(p, f, nelem(f));
437 7285a491 2004-06-17 devnull i = 5;
438 7285a491 2004-06-17 devnull if(nf < i || (cvt==jolietstring && nf < i+2))
439 7285a491 2004-06-17 devnull sysfatal("error in dump block %lud: nf=%d; p='%s'", db, nf, p);
440 7285a491 2004-06-17 devnull nr = createdumpdir(&root, &xd, f[0]);
441 7285a491 2004-06-17 devnull t = strtoul(f[1], 0, 0);
442 7285a491 2004-06-17 devnull xd.mtime = xd.ctime = xd.atime = t;
443 7285a491 2004-06-17 devnull db = strtoul(f[2], 0, 0);
444 7285a491 2004-06-17 devnull if(cvt == jolietstring)
445 7285a491 2004-06-17 devnull i += 2;
446 7285a491 2004-06-17 devnull nr->block = strtoul(f[i], 0, 0);
447 7285a491 2004-06-17 devnull nr->length = strtoul(f[i+1], 0, 0);
448 7285a491 2004-06-17 devnull }
449 7285a491 2004-06-17 devnull cd->nulldump = db;
450 7285a491 2004-06-17 devnull return root;
451 7285a491 2004-06-17 devnull }
452 7285a491 2004-06-17 devnull
453 7285a491 2004-06-17 devnull extern void addtx(char*, char*);
454 7285a491 2004-06-17 devnull
455 7285a491 2004-06-17 devnull static int
456 7285a491 2004-06-17 devnull isalldigit(char *s)
457 7285a491 2004-06-17 devnull {
458 7285a491 2004-06-17 devnull while(*s)
459 3bd56b04 2005-09-09 devnull if(!isdigit((uchar)*s++))
460 7285a491 2004-06-17 devnull return 0;
461 7285a491 2004-06-17 devnull return 1;
462 7285a491 2004-06-17 devnull }
463 7285a491 2004-06-17 devnull
464 7285a491 2004-06-17 devnull void
465 7285a491 2004-06-17 devnull readdumpconform(Cdimg *cd)
466 7285a491 2004-06-17 devnull {
467 7285a491 2004-06-17 devnull char buf[Blocksize];
468 7285a491 2004-06-17 devnull char *p, *q, *f[10];
469 7285a491 2004-06-17 devnull ulong cb, nc, m, db;
470 7285a491 2004-06-17 devnull int nf;
471 7285a491 2004-06-17 devnull
472 7285a491 2004-06-17 devnull db = hasdump(cd);
473 7285a491 2004-06-17 devnull assert(map==nil || map->nt == 0);
474 7285a491 2004-06-17 devnull
475 7285a491 2004-06-17 devnull for(;;){
476 7285a491 2004-06-17 devnull if(db == 0)
477 7285a491 2004-06-17 devnull sysfatal("error0 in dump blocks");
478 7285a491 2004-06-17 devnull
479 7285a491 2004-06-17 devnull Creadblock(cd, buf, db, sizeof buf);
480 7285a491 2004-06-17 devnull if(memcmp(buf, magic, sizeof(magic)-1) != 0)
481 7285a491 2004-06-17 devnull break;
482 7285a491 2004-06-17 devnull p = buf+sizeof(magic)-1;
483 7285a491 2004-06-17 devnull if(p[0] == '\0')
484 7285a491 2004-06-17 devnull break;
485 7285a491 2004-06-17 devnull if((q = strchr(p, '\n')) != nil)
486 7285a491 2004-06-17 devnull *q = '\0';
487 7285a491 2004-06-17 devnull
488 7285a491 2004-06-17 devnull nf = tokenize(p, f, nelem(f));
489 7285a491 2004-06-17 devnull if(nf < 5)
490 7285a491 2004-06-17 devnull sysfatal("error0 in dump block %lud", db);
491 7285a491 2004-06-17 devnull
492 7285a491 2004-06-17 devnull db = strtoul(f[2], 0, 0);
493 7285a491 2004-06-17 devnull cb = strtoul(f[3], 0, 0);
494 7285a491 2004-06-17 devnull nc = strtoul(f[4], 0, 0);
495 7285a491 2004-06-17 devnull
496 7285a491 2004-06-17 devnull Crseek(cd, cb*Blocksize);
497 7285a491 2004-06-17 devnull m = cb*Blocksize+nc;
498 7285a491 2004-06-17 devnull while(Croffset(cd) < m && (p = Crdline(cd, '\n')) != nil){
499 7285a491 2004-06-17 devnull p[Clinelen(cd)-1] = '\0';
500 7285a491 2004-06-17 devnull if(tokenize(p, f, 2) != 2 || (f[0][0] != 'D' && f[0][0] != 'F')
501 7285a491 2004-06-17 devnull || strlen(f[0]) != 7 || !isalldigit(f[0]+1))
502 7285a491 2004-06-17 devnull break;
503 7285a491 2004-06-17 devnull
504 7285a491 2004-06-17 devnull addtx(atom(f[1]), atom(f[0]));
505 7285a491 2004-06-17 devnull }
506 7285a491 2004-06-17 devnull }
507 7285a491 2004-06-17 devnull if(map)
508 7285a491 2004-06-17 devnull cd->nconform = map->nt;
509 7285a491 2004-06-17 devnull else
510 7285a491 2004-06-17 devnull cd->nconform = 0;
511 7285a491 2004-06-17 devnull }