1: # 2: 3: /* 4: * restore from incremental dumps 5: */ 6: 7: char *dargv[] 8: { 9: 0, 10: "t", 11: 0 12: }; 13: char *ifile; 14: char *ofile; 15: #include "/usr/sys/ino.h" 16: #include "/usr/sys/filsys.h" 17: 18: struct filsys sblock; 19: int isize; 20: int *talist; 21: int fi; 22: int buf[256]; 23: int dbuf[256]; 24: int cbuf[256]; 25: char *date[2]; 26: char *ddate[2]; 27: int fo; 28: int pher; 29: char *tsize 15000; 30: int iflg; 31: int wflg; 32: int cflg; 33: char file[10]; 34: int ilist[100]; 35: 36: main(argc, argv) 37: char **argv; 38: { 39: char *key; 40: register *tap, *p; 41: register struct inode *ip; 42: int i, com, sz, *q, l; 43: 44: ifile = "/dev/mt0"; 45: if(argc == 1) { 46: argv = dargv; 47: for(argc = 1; dargv[argc]; argc++); 48: } 49: 50: argc--; 51: argv++; 52: key = *argv; 53: while(*key) 54: switch(*key++) { 55: default: 56: printf("bad character in key\n"); 57: exit(); 58: 59: case 't': 60: case 'r': 61: case 'x': 62: com = key[-1]; 63: continue; 64: 65: case 'i': 66: iflg++; 67: continue; 68: 69: case '-': 70: continue; 71: 72: case 'c': 73: cflg++; 74: continue; 75: 76: case 'f': 77: argv++; 78: argc--; 79: ifile = *argv; 80: continue; 81: 82: case 'w': 83: wflg++; 84: continue; 85: 86: } 87: otape(); 88: sread(buf, 0); 89: tap = buf; 90: isize = *tap++; 91: *tap++; /* fsize */ 92: date[0] = *tap++; 93: date[1] = *tap++; 94: ddate[0] = *tap++; 95: ddate[1] = *tap++; 96: tsize = *tap++; 97: i = size(0, isize*32); 98: talist = sbrk(i*512); 99: tap = talist; 100: while(i--) { 101: tread(tap, 0); 102: tap =+ 256; 103: } 104: switch(com) { 105: 106: case 't': 107: l = 0; 108: com = 0; 109: pdate(ddate); 110: pdate(date); 111: tap = talist; 112: for(i=0; i<isize*16; i++) { 113: sz = *tap++; 114: if(sz == 0 || sz == -1) { 115: if(com == 0) 116: continue; 117: if(i == com) { 118: printf("%l", i); 119: l =+ 5; 120: } else { 121: printf("%l-%l", com, i); 122: l =+ 10; 123: } 124: if(l > 60) { 125: printf("\n"); 126: l = 0; 127: } else 128: printf(","); 129: com = 0; 130: } else 131: if(com == 0) 132: com = i+1; 133: } 134: if(com) 135: printf("%l-\n", com); 136: printf("\n"); 137: exit(); 138: 139: case 'r': 140: if(argc <= 1) { 141: printf("no filesystem name\n"); 142: exit(); 143: } 144: ofile = argv[1]; 145: fo = open(ofile, 2); 146: if(fo < 0) { 147: printf("can not open %s\n", ofile); 148: exit(); 149: } 150: printf("last chance before scribbling on %s\n", ofile); 151: getchar(); 152: dread(1, &sblock); 153: tap = talist; 154: for(i=0; i<sblock.s_isize; i++) { 155: if(i >= isize) 156: break; 157: dread(i+2, buf); 158: for(ip = &buf[0]; ip < &buf[256]; ip++) { 159: sz = *tap++; 160: if(sz == 0) 161: continue; 162: dealoc(ip); 163: if(sz == -1) { 164: for(p = ip; p < &ip->i_mtime[2]; ) 165: *p++ = 0; 166: continue; 167: } 168: sread(dbuf, 0); 169: q = dbuf; 170: for(p = ip; p < &ip->i_mtime[2]; ) 171: *p++ = *q++; 172: restor(ip, sz-1); 173: } 174: dwrite(i+2, buf); 175: } 176: dwrite(1, &sblock); 177: com = 0; 178: for(; i < isize; i++) 179: for(l = 0; l < 16; l++) { 180: sz = *tap++; 181: if(sz != 0 && sz != -1) 182: com++; 183: } 184: if(com) 185: printf("%l files not restored - small ilist\n", com); 186: exit(); 187: 188: case 'x': 189: i = 0; 190: tap = ilist; 191: while(argc > 1) { 192: i++; 193: sz = number(argv[1]); 194: argv++; 195: argc--; 196: if(sz <= 0 || sz >=isize*16) { 197: printf("%l not in range\n", sz); 198: continue; 199: } 200: if(talist[sz-1] == 0) { 201: printf("%l not dumped\n", sz); 202: continue; 203: } 204: if(talist[sz-1] == -1) { 205: printf("%l does not exist\n", sz); 206: continue; 207: } 208: *tap++ = sz; 209: } 210: if(i != 0 && ilist[0] == 0) 211: exit(); 212: tap = talist; 213: for(i=1; i<=isize*16; i++) { 214: if(ilist[0] != 0) { 215: for(sz=0; ilist[sz]; sz++) 216: if(ilist[sz] == i) 217: goto yes; 218: sz = *tap++; 219: no: 220: if(sz == -1) 221: sz = 0; 222: while(sz--) 223: tread(dbuf, 1); 224: continue; 225: } 226: yes: 227: sz = *tap++; 228: if(sz == 0 || sz == -1) 229: continue; 230: fo = dwait(i); 231: if(fo < 0) 232: goto no; 233: sz--; 234: sread(buf, 0); 235: ip = buf; 236: while(sz--) { 237: tread(dbuf, 0); 238: com = 512; 239: if(ip->i_size0 == 0 && ip->i_size1 < 512) 240: com = ip->i_size1; 241: write(fo, dbuf, com); 242: if(com > ip->i_size1) 243: ip->i_size0--; 244: ip->i_size1 =- com; 245: } 246: close(fo); 247: chmod(file, ip->i_mode); 248: chown(file, ip->i_uid); 249: } 250: exit(); 251: 252: } 253: } 254: 255: dealoc(p) 256: struct inode *p; 257: { 258: register struct inode *ip; 259: register i, j; 260: int k; 261: int xbuf[256], ybuf[256]; 262: 263: ip = p; 264: if(ip->i_mode & (IFCHR&IFBLK)) 265: return; 266: for(i=7; i>=0; i--) 267: if(ip->i_addr[i]) { 268: if(ip->i_mode&ILARG) { 269: dread(ip->i_addr[i], xbuf); 270: for(j=255; j>=0; j--) 271: if(xbuf[j]) { 272: if(i == 7) { 273: dread(xbuf[j], ybuf); 274: for(k=255; k>=0; k--) 275: if(ybuf[k]) 276: free(ybuf[k]); 277: } 278: free(xbuf[j]); 279: } 280: } 281: free(ip->i_addr[i]); 282: } 283: } 284: 285: restor(p, sz) 286: struct inode *p; 287: { 288: register struct inode *ip; 289: register i, j; 290: int xbuf[256]; 291: 292: ip = p; 293: if(ip->i_mode & (IFCHR&IFBLK)) 294: return; 295: for(i=0; i<8; i++) 296: ip->i_addr[i] = 0; 297: if(sz <= 8) { 298: for(i=0; i<sz; i++) 299: ip->i_addr[i] = rcop(); 300: ip->i_mode =& ~ILARG; 301: return; 302: } 303: for(i=0; i<256; i++) 304: xbuf[i] = 0; 305: for(j=0; sz >= 256; j++) { 306: if(j <= 7) 307: ip->i_addr[j] = alloc(); 308: if(j >= 7) 309: xbuf[j-7] = alloc(); 310: for(i=0; i<256; i++) 311: dbuf[i] = rcop(); 312: if(j < 7) 313: dwrite(ip->i_addr[j], dbuf); else 314: dwrite(xbuf[j-7], dbuf); 315: sz =- 256; 316: } 317: if(sz) { 318: if(j <= 7) 319: ip->i_addr[j] = alloc(); 320: if(j >= 7) 321: xbuf[j-7] = alloc(); 322: for(i=0; i<sz; i++) 323: dbuf[i] = rcop(); 324: for(; i<256; i++) 325: dbuf[i] = 0; 326: if(j < 7) 327: dwrite(ip->i_addr[j], dbuf); else 328: dwrite(xbuf[j-7], dbuf); 329: } 330: if(j >= 7) 331: dwrite(ip->i_addr[7], xbuf); 332: ip->i_mode =| ILARG; 333: } 334: 335: rcop() 336: { 337: register b; 338: 339: b = alloc(); 340: tread(cbuf, 0); 341: dwrite(b, cbuf); 342: return(b); 343: } 344: 345: pdate(d) 346: int *d; 347: { 348: 349: if(d[0] == 0 && d[1] == 0) 350: printf("the epoch\n"); else 351: printf(ctime(d)); 352: } 353: 354: dread(bno, b) 355: { 356: 357: seek(fo, bno, 3); 358: if(read(fo, b, 512) != 512) { 359: printf("disk read error %l\n", bno); 360: exit(); 361: } 362: } 363: 364: dwrite(bno, b) 365: { 366: 367: seek(fo, bno, 3); 368: if(write(fo, b, 512) != 512) { 369: printf("disk write error %l\n", bno); 370: exit(); 371: } 372: } 373: 374: sread(b, flag) 375: int *b; 376: { 377: register i, s, *p; 378: 379: tread(b, flag); 380: if(flag) 381: return; 382: i = 256; 383: s = 0; 384: p = b; 385: while(i--) 386: s =+ *p++; 387: if(s != 031415) { 388: printf("checksum error\n"); 389: if(!iflg) 390: exit(); 391: } 392: } 393: 394: tread(b, flag) 395: int *b; 396: { 397: register c; 398: static char *pta, *ata, ctflg; 399: 400: if(pta++ >= tsize) { 401: pta = 1; 402: ata = 0; 403: close(fi); 404: otape(); 405: ctflg++; 406: } 407: if(flag) 408: return; 409: if(ctflg) { 410: printf("change tapes\n"); 411: if(ctflg > 1) 412: printf("skip %d tapes\n", ctflg-1); 413: while((c = getchar()) != '\n') 414: if(c == 0) 415: exit(); 416: ctflg = 0; 417: } 418: ata++; 419: if(iflg) 420: for(; pta != ata; ata++) 421: read(fi, b, 512); 422: if(pta != ata) { 423: seek(fi, pta-ata, 4); 424: ata = pta; 425: } 426: if(read(fi, b, 512) != 512) { 427: printf("tape read error %l\n", ata-1); 428: if(!iflg) 429: exit(); 430: for(c=0; c<256; c++) 431: b[c] = 0; 432: } 433: } 434: 435: number(s) 436: char *s; 437: { 438: register n, c; 439: 440: n = 0; 441: while(c = *s++) { 442: if(c<'0' || c>'9') 443: continue; 444: n = n*10+c-'0'; 445: } 446: return(n); 447: } 448: 449: size(s0, s1) 450: { 451: register s; 452: extern ldivr; 453: 454: s = ldiv(s0&0377, s1, 512); 455: if(ldivr) 456: s++; 457: return(s); 458: } 459: 460: otape() 461: { 462: register char *p; 463: 464: fi = open(ifile, 0); 465: if(fi < 0) { 466: printf("can not open %s\n", ifile); 467: exit(); 468: } 469: if(!cflg) 470: return; 471: p = ifile; 472: while(*p++) 473: ; 474: p[-2]++; 475: } 476: 477: dwait(ino) 478: { 479: register i; 480: 481: dconv(ino, file); 482: loop: 483: if(wflg) { 484: printf("%s ", file); 485: i = getchar(); 486: if(i == 'x') 487: exit(); 488: if(i == '\n') 489: return(-1); 490: if(i != 'y') 491: goto flush; 492: i = getchar(); 493: if(i != '\n') { 494: flush: 495: while((i=getchar()) != '\n') 496: if(i == '\0') 497: exit(); 498: goto loop; 499: } 500: } 501: i = creat(file, 0666); 502: return(i); 503: } 504: 505: dconv(n, p) 506: char *p; 507: { 508: register i; 509: 510: if(i = ldiv(0, n, 10)) 511: p = dconv(i, p); 512: *p++ = lrem(0, n, 10) + '0'; 513: *p = '\0'; 514: return(p); 515: } 516: 517: alloc() 518: { 519: register b, i; 520: 521: i = --sblock.s_nfree; 522: if(i<0 || i>=100) { 523: printf("bad freeblock\n"); 524: exit(); 525: } 526: b = sblock.s_free[i]; 527: if(b == 0) { 528: printf("out of freelist\n"); 529: exit(); 530: } 531: if(sblock.s_nfree <= 0) { 532: dread(b, cbuf); 533: sblock.s_nfree = cbuf[0]; 534: for(i=0; i<100; i++) 535: sblock.s_free[i] = cbuf[i+1]; 536: } 537: return(b); 538: } 539: 540: free(in) 541: { 542: register i; 543: 544: if(sblock.s_nfree >= 100) { 545: cbuf[0] = sblock.s_nfree; 546: for(i=0; i<100; i++) 547: cbuf[i+1] = sblock.s_free[i]; 548: sblock.s_nfree = 0; 549: dwrite(in, cbuf); 550: } 551: sblock.s_free[sblock.s_nfree++] = in; 552: }