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