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: 19: struct filsys sblock; 20: struct dinode itab[INOPB*NI]; 21: short clrmap[MSIZ]; 22: short dirmap[MSIZ]; 23: short nodmap[MSIZ]; 24: 25: char *disk; 26: char *tape; 27: char *increm; 28: char incno; 29: int uflag; 30: int fi; 31: int to; 32: ino_t ino; 33: int nsubdir; 34: int ntape; 35: int nadded; 36: int dadded; 37: int density = 160; 38: 39: char *ctime(); 40: char *prdate(); 41: long atol(); 42: int fi; 43: long tsize; 44: long esize; 45: long asize; 46: int mark(); 47: int add(); 48: int dump(); 49: int tapsrec(); 50: int dmpspc(); 51: int dsrch(); 52: int nullf(); 53: 54: #define HOUR (60L*60L) 55: #define DAY (24L*HOUR) 56: #define YEAR (365L*DAY) 57: 58: main(argc, argv) 59: char *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/rrp3"; 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)/10; 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: 175: pass(fn, map) 176: int (*fn)(); 177: short *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: 213: icat(ip, fn1, fn2) 214: struct dinode *ip; 215: int (*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: 231: indir(d, fn1, fn2, n) 232: daddr_t d; 233: int (*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: 257: mark(ip) 258: struct 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: 277: add(ip) 278: struct 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: 296: dump(ip) 297: struct 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: 317: dmpspc(dp, n) 318: daddr_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: 332: bitmap(map, typ) 333: short *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: 354: spclrec() 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: 369: dsrch(d) 370: daddr_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: 400: nullf() 401: { 402: } 403: 404: bread(da, ba, c) 405: daddr_t da; 406: char *ba; 407: { 408: register n; 409: 410: lseek(fi, da*512, 0); 411: n = read(fi, ba, c); 412: if(n != c) 413: printf("asked %d; got %d\n", c, n); 414: } 415: 416: CLR(map) 417: register short *map; 418: { 419: register n; 420: 421: n = MSIZ; 422: do 423: *map++ = 0; 424: while(--n); 425: } 426: 427: 428: char tblock[NTREC][BSIZE]; 429: daddr_t tdaddr[NTREC]; 430: int trecno; 431: 432: taprec(dp) 433: char *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: 446: tapsrec(d) 447: daddr_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: 459: flusht() 460: { 461: char place[100]; 462: register i, si; 463: daddr_t d; 464: 465: while(trecno < NTREC) 466: tdaddr[trecno++] = 1; 467: 468: loop: 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: 493: otape() 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: 507: char * 508: prdate(d) 509: time_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: 520: getitime() 521: { 522: register i, df; 523: struct idates idbuf; 524: char *fname; 525: 526: fname = disk; 527: l1: 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: 541: l2: 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: 561: putitime() 562: { 563: register i, n, df; 564: struct idates idbuf; 565: char *fname; 566: 567: if(uflag == 0) 568: return; 569: fname = disk; 570: l1: 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; 584: l2: 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; 597: l3: 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: 611: est(ip) 612: struct 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: 626: bmapest(map) 627: short *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: }