BSD 3 development
[unix-history] / usr / src / cmd / dump.c
CommitLineData
4f011000
BJ
1#define NI 16
2#define DIRPB (BSIZE/sizeof(struct direct))
3
4#include <stdio.h>
5#include <sys/param.h>
6#include <sys/inode.h>
7#include <sys/ino.h>
8#include <sys/fblk.h>
9#include <sys/filsys.h>
10#include <sys/dir.h>
11#include <dumprestor.h>
12
13#define MWORD(m,i) (m[(unsigned)(i-1)/MLEN])
14#define MBIT(i) (1<<((unsigned)(i-1)%MLEN))
15#define BIS(i,w) (MWORD(w,i) |= MBIT(i))
16#define BIC(i,w) (MWORD(w,i) &= ~MBIT(i))
17#define BIT(i,w) (MWORD(w,i) & MBIT(i))
18
19struct filsys sblock;
20struct dinode itab[INOPB*NI];
21short clrmap[MSIZ];
22short dirmap[MSIZ];
23short nodmap[MSIZ];
24
25char *disk;
26char *tape;
27char *increm;
28char incno;
29int uflag;
30int fi;
31int to;
32ino_t ino;
33int nsubdir;
34int ntape;
35int nadded;
36int dadded;
37int density = 160;
38
39char *ctime();
40char *prdate();
41long atol();
42int fi;
43long tsize;
44long esize;
45long asize;
46int mark();
47int add();
48int dump();
49int tapsrec();
50int dmpspc();
51int dsrch();
52int nullf();
53
54#define HOUR (60L*60L)
55#define DAY (24L*HOUR)
56#define YEAR (365L*DAY)
57
58main(argc, argv)
59char *argv[];
60{
61 char *arg;
62 register i;
63
64 time(&spcl.c_date);
65
66 tsize = 2300L*12L*10L;
67 tape = "/dev/rmt1";
68 disk = "/dev/rrp1g";
69 increm = "/etc/ddate";
70 incno = '9';
71 uflag = 0;
72 arg = "u";
73 if(argc > 1) {
74 argv++;
75 argc--;
76 arg = *argv;
77 }
78 while(*arg)
79 switch (*arg++) {
80
81 case 'f':
82 if(argc > 1) {
83 argv++;
84 argc--;
85 tape = *argv;
86 }
87 break;
88
89 case 'd':
90 if (argc > 1) {
91 argv++;
92 argc--;
93 density = atoi(*argv);
94 }
95 break;
96
97 case 's':
98 if(argc > 1) {
99 argv++;
100 argc--;
101 tsize = atol(*argv);
102 tsize *= 12L*10L;
103 }
104 break;
105
106 case '0':
107 case '1':
108 case '2':
109 case '3':
110 case '4':
111 case '5':
112 case '6':
113 case '7':
114 case '8':
115 case '9':
116 incno = arg[-1];
117 break;
118
119 case 'u':
120 uflag++;
121 break;
122
123 default:
124 printf("bad key '%c%'\n", arg[-1]);
125 exit(1);
126 }
127 if(argc > 1) {
128 argv++;
129 argc--;
130 disk = *argv;
131 }
132
133 getitime();
134 printf(" date = %s\n", prdate(spcl.c_date));
135 printf("dump date = %s\n", prdate(spcl.c_ddate));
136 printf("dumping %s to %s\n", disk, tape);
137 fi = open(disk, 0);
138 if(fi < 0) {
139 printf("dump: cannot open %s\n", disk);
140 exit(1);
141 }
142 otape();
143 printf("I\n");
144 esize = 0;
145 CLR(clrmap);
146 CLR(dirmap);
147 CLR(nodmap);
148
149 pass(mark, (short *)NULL);
150 do {
151 printf("II\n");
152 nadded = 0;
153 pass(add, dirmap);
154 } while(nadded);
155
156 bmapest(clrmap);
157 bmapest(nodmap);
158 printf("estimated %ld tape blocks on %d tape(s)\n",
159 esize, 0);
160
161 printf("III\n");
162 bitmap(clrmap, TS_CLRI);
163 pass(dump, dirmap);
164 printf("IV\n");
165 pass(dump, nodmap);
166 putitime();
167 printf("DONE\n");
168 spcl.c_type = TS_END;
169 for(i=0; i<NTREC; i++)
170 spclrec();
171 printf("%ld tape blocks on %d tape(s)\n",
172 spcl.c_tapea, spcl.c_volume);
173}
174
175pass(fn, map)
176int (*fn)();
177short *map;
178{
179 register i, j;
180 int bits;
181 ino_t mino;
182 daddr_t d;
183
184 sync();
185 bread((daddr_t)1, (char *)&sblock, sizeof(sblock));
186 mino = (sblock.s_isize-2) * INOPB;
187 ino = 0;
188 for(i=2;; i+=NI) {
189 if(ino >= mino)
190 break;
191 d = (unsigned)i;
192 for(j=0; j<INOPB*NI; j++) {
193 if(ino >= mino)
194 break;
195 if((ino % MLEN) == 0) {
196 bits = ~0;
197 if(map != NULL)
198 bits = *map++;
199 }
200 ino++;
201 if(bits & 1) {
202 if(d != 0) {
203 bread(d, (char *)itab, sizeof(itab));
204 d = 0;
205 }
206 (*fn)(&itab[j]);
207 }
208 bits >>= 1;
209 }
210 }
211}
212
213icat(ip, fn1, fn2)
214struct dinode *ip;
215int (*fn1)(), (*fn2)();
216{
217 register i;
218 daddr_t d[NADDR];
219
220 l3tol(&d[0], &ip->di_addr[0], NADDR);
221 (*fn2)(d, NADDR-3);
222 for(i=0; i<NADDR; i++) {
223 if(d[i] != 0) {
224 if(i < NADDR-3)
225 (*fn1)(d[i]); else
226 indir(d[i], fn1, fn2, i-(NADDR-3));
227 }
228 }
229}
230
231indir(d, fn1, fn2, n)
232daddr_t d;
233int (*fn1)(), (*fn2)();
234{
235 register i;
236 daddr_t idblk[NINDIR];
237
238 bread(d, (char *)idblk, sizeof(idblk));
239 if(n <= 0) {
240 spcl.c_type = TS_ADDR;
241 (*fn2)(idblk, NINDIR);
242 for(i=0; i<NINDIR; i++) {
243 d = idblk[i];
244 if(d != 0)
245 (*fn1)(d);
246 }
247 } else {
248 n--;
249 for(i=0; i<NINDIR; i++) {
250 d = idblk[i];
251 if(d != 0)
252 indir(d, fn1, fn2, n);
253 }
254 }
255}
256
257mark(ip)
258struct dinode *ip;
259{
260 register f;
261
262 f = ip->di_mode & IFMT;
263 if(f == 0)
264 return;
265 BIS(ino, clrmap);
266 if(f == IFDIR)
267 BIS(ino, dirmap);
268 if(ip->di_mtime >= spcl.c_ddate ||
269 ip->di_ctime >= spcl.c_ddate) {
270 BIS(ino, nodmap);
271 if (f != IFREG)
272 return;
273 est(ip);
274 }
275}
276
277add(ip)
278struct dinode *ip;
279{
280
281 if(BIT(ino, nodmap))
282 return;
283 nsubdir = 0;
284 dadded = 0;
285 icat(ip, dsrch, nullf);
286 if(dadded) {
287 BIS(ino, nodmap);
288 est(ip);
289 nadded++;
290 }
291 if(nsubdir == 0)
292 if(!BIT(ino, nodmap))
293 BIC(ino, dirmap);
294}
295
296dump(ip)
297struct dinode *ip;
298{
299 register i;
300
301 if(ntape) {
302 ntape = 0;
303 bitmap(nodmap, TS_BITS);
304 }
305 BIC(ino, nodmap);
306 spcl.c_dinode = *ip;
307 spcl.c_type = TS_INODE;
308 spcl.c_count = 0;
309 i = ip->di_mode & IFMT;
310 if(i != IFDIR && i != IFREG) {
311 spclrec();
312 return;
313 }
314 icat(ip, tapsrec, dmpspc);
315}
316
317dmpspc(dp, n)
318daddr_t *dp;
319{
320 register i, t;
321
322 spcl.c_count = n;
323 for(i=0; i<n; i++) {
324 t = 0;
325 if(dp[i] != 0)
326 t++;
327 spcl.c_addr[i] = t;
328 }
329 spclrec();
330}
331
332bitmap(map, typ)
333short *map;
334{
335 register i, n;
336 char *cp;
337
338 n = -1;
339 for(i=0; i<MSIZ; i++)
340 if(map[i])
341 n = i;
342 if(n < 0)
343 return;
344 spcl.c_type = typ;
345 spcl.c_count = (n*sizeof(map[0]) + BSIZE)/BSIZE;
346 spclrec();
347 cp = (char *)map;
348 for(i=0; i<spcl.c_count; i++) {
349 taprec(cp);
350 cp += BSIZE;
351 }
352}
353
354spclrec()
355{
356 register i, *ip, s;
357
358 spcl.c_inumber = ino;
359 spcl.c_magic = MAGIC;
360 spcl.c_checksum = 0;
361 ip = (int *)&spcl;
362 s = 0;
363 for(i=0; i<BSIZE/sizeof(*ip); i++)
364 s += *ip++;
365 spcl.c_checksum = CHECKSUM - s;
366 taprec((char *)&spcl);
367}
368
369dsrch(d)
370daddr_t d;
371{
372 register char *cp;
373 register i;
374 register ino_t in;
375 struct direct dblk[DIRPB];
376
377 if(dadded)
378 return;
379 bread(d, (char *)dblk, sizeof(dblk));
380 for(i=0; i<DIRPB; i++) {
381 in = dblk[i].d_ino;
382 if(in == 0)
383 continue;
384 cp = dblk[i].d_name;
385 if(cp[0] == '.') {
386 if(cp[1] == '\0')
387 continue;
388 if(cp[1] == '.' && cp[2] == '\0')
389 continue;
390 }
391 if(BIT(in, nodmap)) {
392 dadded++;
393 return;
394 }
395 if(BIT(in, dirmap))
396 nsubdir++;
397 }
398}
399
400nullf()
401{
402}
403
404bread(da, ba, c)
405daddr_t da;
406char *ba;
407{
408 register n;
409
410 lseek(fi, da*BSIZE, 0);
411 n = read(fi, ba, c);
412 if(n != c)
413 printf("asked %d; got %d\n", c, n);
414}
415
416CLR(map)
417register short *map;
418{
419 register n;
420
421 n = MSIZ;
422 do
423 *map++ = 0;
424 while(--n);
425}
426
427
428char tblock[NTREC][BSIZE];
429daddr_t tdaddr[NTREC];
430int trecno;
431
432taprec(dp)
433char *dp;
434{
435 register i;
436
437 for(i=0; i<BSIZE; i++)
438 tblock[trecno][i] = *dp++;
439 tdaddr[trecno] = 0;
440 trecno++;
441 spcl.c_tapea++;
442 if(trecno >= NTREC)
443 flusht();
444}
445
446tapsrec(d)
447daddr_t d;
448{
449
450 if(d == 0)
451 return;
452 tdaddr[trecno] = d;
453 trecno++;
454 spcl.c_tapea++;
455 if(trecno >= NTREC)
456 flusht();
457}
458
459flusht()
460{
461 char place[100];
462 register i, si;
463 daddr_t d;
464
465 while(trecno < NTREC)
466 tdaddr[trecno++] = 1;
467
468loop:
469 d = 0;
470 for(i=0; i<NTREC; i++)
471 if(tdaddr[i] != 0)
472 if(d == 0 || tdaddr[i] < d) {
473 si = i;
474 d = tdaddr[i];
475 }
476 if(d != 0) {
477 bread(d, tblock[si], BSIZE);
478 tdaddr[si] = 0;
479 goto loop;
480 }
481 trecno = 0;
482 write(to, tblock[0], sizeof(tblock));
483 asize += sizeof(tblock)/density;
484 asize += 7;
485 if(asize > tsize) {
486 close(to);
487 printf("change tapes\n");
488 read(0, place, sizeof(place));
489 otape();
490 }
491}
492
493otape()
494{
495 to = creat(tape, 0666);
496 if(to < 0) {
497 printf("dump: cannot create %s\n", tape);
498 exit(1);
499 }
500 asize = 0;
501 ntape++;
502 spcl.c_volume++;
503 spcl.c_type = TS_TAPE;
504 spclrec();
505}
506
507char *
508prdate(d)
509time_t d;
510{
511 char *p;
512
513 if(d == 0)
514 return("the epoch");
515 p = ctime(&d);
516 p[24] = 0;
517 return(p);
518}
519
520getitime()
521{
522 register i, df;
523 struct idates idbuf;
524 char *fname;
525
526 fname = disk;
527l1:
528 for(i=0; fname[i]; i++)
529 if(fname[i] == '/') {
530 fname += i+1;
531 goto l1;
532 }
533
534 spcl.c_ddate = 0;
535 df = open(increm, 0);
536 if(df < 0) {
537 printf("cannot open %s\n", increm);
538 exit(1);
539 }
540
541l2:
542 i = read(df, (char *)&idbuf, sizeof(idbuf));
543 if(i != sizeof(idbuf)) {
544 close(df);
545 return;
546 }
547 for(i=0;; i++) {
548 if(fname[i] != idbuf.id_name[i])
549 goto l2;
550 if(fname[i] == '\0')
551 break;
552 }
553 if(idbuf.id_incno >= incno)
554 goto l2;
555 if(idbuf.id_ddate <= spcl.c_ddate)
556 goto l2;
557 spcl.c_ddate = idbuf.id_ddate;
558 goto l2;
559}
560
561putitime()
562{
563 register i, n, df;
564 struct idates idbuf;
565 char *fname;
566
567 if(uflag == 0)
568 return;
569 fname = disk;
570l1:
571 for(i=0; fname[i]; i++)
572 if(fname[i] == '/') {
573 fname += i+1;
574 goto l1;
575 }
576
577 spcl.c_ddate = 0;
578 df = open(increm, 2);
579 if(df < 0) {
580 printf("cannot open %s\n", increm);
581 exit(1);
582 }
583 n = 0;
584l2:
585 i = read(df, (char *)&idbuf, sizeof(idbuf));
586 if(i != sizeof(idbuf))
587 goto l3;
588 n++;
589 for(i=0;; i++) {
590 if(fname[i] != idbuf.id_name[i])
591 goto l2;
592 if(fname[i] == '\0')
593 break;
594 }
595 if(idbuf.id_incno != incno)
596 goto l2;
597l3:
598 lseek(df, (long)n*sizeof(idbuf), 0);
599 for(i=0;; i++) {
600 idbuf.id_name[i] = fname[i];
601 if(fname[i] == '\0')
602 break;
603 }
604 idbuf.id_incno = incno;
605 idbuf.id_ddate = spcl.c_date;
606 write(df, (char *)&idbuf, sizeof(idbuf));
607 close(df);
608 printf("level %c dump on %s\n", incno, prdate(spcl.c_date));
609}
610
611est(ip)
612struct dinode *ip;
613{
614 long s;
615
616 esize++;
617 s = (ip->di_size + BSIZE-1) / BSIZE;
618 esize += s;
619 if(s > NADDR-3) {
620 s -= NADDR-3;
621 s = (s + (BSIZE/sizeof(daddr_t))-1) / (BSIZE/sizeof(daddr_t));
622 esize += s;
623 }
624}
625
626bmapest(map)
627short *map;
628{
629 register i, n;
630
631 n = -1;
632 for(i=0; i<MSIZ; i++)
633 if(map[i])
634 n = i;
635 if(n < 0)
636 return;
637 esize++;
638 esize += (n + (BSIZE/sizeof(short))-1) / (BSIZE/sizeof(short));
639}