1*944Sbill static char *sccsid = "@(#)512restor.c 4.1 (Berkeley) 10/01/80"; 2*944Sbill #define MAXINO 3000 3*944Sbill #define BITS 8 4*944Sbill #define MAXXTR 60 5*944Sbill #define NCACHE 3 6*944Sbill 7*944Sbill #ifndef STANDALONE 8*944Sbill #include <stdio.h> 9*944Sbill #include <signal.h> 10*944Sbill #endif 11*944Sbill #include <sys/param.h> 12*944Sbill #include <sys/inode.h> 13*944Sbill #include <sys/ino.h> 14*944Sbill #include <sys/fblk.h> 15*944Sbill #include <sys/filsys.h> 16*944Sbill #include <sys/dir.h> 17*944Sbill 18*944Sbill #define OBSIZE 512 19*944Sbill 20*944Sbill /* from old <ino.h> */ 21*944Sbill 22*944Sbill #define OINOPB 8 /* 8 inodes per block */ 23*944Sbill 24*944Sbill /* old <dumprestor.h> */ 25*944Sbill #define NTREC 20 26*944Sbill #define MLEN 16 27*944Sbill #define MSIZ 4096 28*944Sbill 29*944Sbill #define TS_TAPE 1 30*944Sbill #define TS_INODE 2 31*944Sbill #define TS_BITS 3 32*944Sbill #define TS_ADDR 4 33*944Sbill #define TS_END 5 34*944Sbill #define TS_CLRI 6 35*944Sbill #define MAGIC (int)60011 36*944Sbill #define CHECKSUM (int)84446 37*944Sbill struct spcl 38*944Sbill { 39*944Sbill int c_type; 40*944Sbill time_t c_date; 41*944Sbill time_t c_ddate; 42*944Sbill int c_volume; 43*944Sbill daddr_t c_tapea; 44*944Sbill ino_t c_inumber; 45*944Sbill int c_magic; 46*944Sbill int c_checksum; 47*944Sbill struct dinode c_dinode; 48*944Sbill int c_count; 49*944Sbill char c_addr[OBSIZE]; 50*944Sbill } spcl; 51*944Sbill 52*944Sbill struct idates 53*944Sbill { 54*944Sbill char id_name[16]; 55*944Sbill char id_incno; 56*944Sbill time_t id_ddate; 57*944Sbill }; 58*944Sbill 59*944Sbill /* end of old <dumprestor.h> */ 60*944Sbill 61*944Sbill #define MWORD(m,i) (m[(unsigned)(i-1)/MLEN]) 62*944Sbill #define MBIT(i) (1<<((unsigned)(i-1)%MLEN)) 63*944Sbill #define BIS(i,w) (MWORD(w,i) |= MBIT(i)) 64*944Sbill #define BIC(i,w) (MWORD(w,i) &= ~MBIT(i)) 65*944Sbill #define BIT(i,w) (MWORD(w,i) & MBIT(i)) 66*944Sbill 67*944Sbill struct filsys sblock; 68*944Sbill 69*944Sbill int fi; 70*944Sbill ino_t ino, maxi, curino; 71*944Sbill 72*944Sbill int mt; 73*944Sbill char tapename[] = "/dev/rmt1"; 74*944Sbill char *magtape = tapename; 75*944Sbill #ifdef STANDALONE 76*944Sbill char mbuf[50]; 77*944Sbill #endif 78*944Sbill 79*944Sbill #ifndef STANDALONE 80*944Sbill daddr_t seekpt; 81*944Sbill int df, ofile; 82*944Sbill char dirfile[] = "rstXXXXXX"; 83*944Sbill 84*944Sbill struct { 85*944Sbill ino_t t_ino; 86*944Sbill daddr_t t_seekpt; 87*944Sbill } inotab[MAXINO]; 88*944Sbill int ipos; 89*944Sbill 90*944Sbill #define ONTAPE 1 91*944Sbill #define XTRACTD 2 92*944Sbill #define XINUSE 4 93*944Sbill struct xtrlist { 94*944Sbill ino_t x_ino; 95*944Sbill char x_flags; 96*944Sbill } xtrlist[MAXXTR]; 97*944Sbill 98*944Sbill char name[12]; 99*944Sbill 100*944Sbill char drblock[BSIZE]; 101*944Sbill int bpt; 102*944Sbill #endif 103*944Sbill 104*944Sbill int eflag; 105*944Sbill 106*944Sbill int volno = 1; 107*944Sbill 108*944Sbill struct dinode tino, dino; 109*944Sbill daddr_t taddr[NADDR]; 110*944Sbill 111*944Sbill daddr_t curbno; 112*944Sbill 113*944Sbill short dumpmap[MSIZ]; 114*944Sbill short clrimap[MSIZ]; 115*944Sbill 116*944Sbill 117*944Sbill int bct = NTREC+1; 118*944Sbill char tbf[NTREC*OBSIZE]; 119*944Sbill 120*944Sbill struct cache { 121*944Sbill daddr_t c_bno; 122*944Sbill int c_time; 123*944Sbill char c_block[BSIZE]; 124*944Sbill } cache[NCACHE]; 125*944Sbill int curcache; 126*944Sbill 127*944Sbill main(argc, argv) 128*944Sbill char *argv[]; 129*944Sbill { 130*944Sbill register char *cp; 131*944Sbill char command; 132*944Sbill int done(); 133*944Sbill 134*944Sbill #ifndef STANDALONE 135*944Sbill mktemp(dirfile); 136*944Sbill if (argc < 2) { 137*944Sbill usage: 138*944Sbill printf("Usage: oldrestor x file file..., oldrestor r filesys, or oldrestor t\n"); 139*944Sbill exit(1); 140*944Sbill } 141*944Sbill argv++; 142*944Sbill argc -= 2; 143*944Sbill for (cp = *argv++; *cp; cp++) { 144*944Sbill switch (*cp) { 145*944Sbill case '-': 146*944Sbill break; 147*944Sbill case 'f': 148*944Sbill magtape = *argv++; 149*944Sbill argc--; 150*944Sbill break; 151*944Sbill case 'r': 152*944Sbill case 'R': 153*944Sbill case 't': 154*944Sbill case 'x': 155*944Sbill command = *cp; 156*944Sbill break; 157*944Sbill default: 158*944Sbill printf("Bad key character %c\n", *cp); 159*944Sbill goto usage; 160*944Sbill } 161*944Sbill } 162*944Sbill if (command == 'x') { 163*944Sbill if (signal(SIGINT, done) == SIG_IGN) 164*944Sbill signal(SIGINT, SIG_IGN); 165*944Sbill if (signal(SIGTERM, done) == SIG_IGN) 166*944Sbill signal(SIGTERM, SIG_IGN); 167*944Sbill 168*944Sbill df = creat(dirfile, 0666); 169*944Sbill if (df < 0) { 170*944Sbill printf("restor: %s - cannot create directory temporary\n", dirfile); 171*944Sbill exit(1); 172*944Sbill } 173*944Sbill close(df); 174*944Sbill df = open(dirfile, 2); 175*944Sbill } 176*944Sbill doit(command, argc, argv); 177*944Sbill if (command == 'x') 178*944Sbill unlink(dirfile); 179*944Sbill exit(0); 180*944Sbill #else 181*944Sbill magtape = "tape"; 182*944Sbill doit('r', 1, 0); 183*944Sbill #endif 184*944Sbill } 185*944Sbill 186*944Sbill doit(command, argc, argv) 187*944Sbill char command; 188*944Sbill int argc; 189*944Sbill char *argv[]; 190*944Sbill { 191*944Sbill extern char *ctime(); 192*944Sbill register i, k; 193*944Sbill ino_t d; 194*944Sbill #ifndef STANDALONE 195*944Sbill int xtrfile(), skip(); 196*944Sbill #endif 197*944Sbill int rstrfile(), rstrskip(); 198*944Sbill struct dinode *ip, *ip1; 199*944Sbill 200*944Sbill #ifndef STANDALONE 201*944Sbill if ((mt = open(magtape, 0)) < 0) { 202*944Sbill printf("%s: cannot open tape\n", magtape); 203*944Sbill exit(1); 204*944Sbill } 205*944Sbill #else 206*944Sbill do { 207*944Sbill printf("Tape? "); 208*944Sbill gets(mbuf); 209*944Sbill mt = open(mbuf, 0); 210*944Sbill } while (mt == -1); 211*944Sbill magtape = mbuf; 212*944Sbill #endif 213*944Sbill switch(command) { 214*944Sbill #ifndef STANDALONE 215*944Sbill case 't': 216*944Sbill if (readhdr(&spcl) == 0) { 217*944Sbill printf("Tape is not a dump tape\n"); 218*944Sbill exit(1); 219*944Sbill } 220*944Sbill printf("Dump date: %s", ctime(&spcl.c_date)); 221*944Sbill printf("Dumped from: %s", ctime(&spcl.c_ddate)); 222*944Sbill return; 223*944Sbill case 'x': 224*944Sbill if (readhdr(&spcl) == 0) { 225*944Sbill printf("Tape is not a dump tape\n"); 226*944Sbill exit(1); 227*944Sbill } 228*944Sbill if (checkvol(&spcl, 1) == 0) { 229*944Sbill printf("Tape is not volume 1 of the dump\n"); 230*944Sbill exit(1); 231*944Sbill } 232*944Sbill pass1(); /* This sets the various maps on the way by */ 233*944Sbill i = 0; 234*944Sbill while (i < MAXXTR-1 && argc--) { 235*944Sbill if ((d = psearch(*argv)) == 0 || BIT(d, dumpmap) == 0) { 236*944Sbill printf("%s: not on the tape\n", *argv++); 237*944Sbill continue; 238*944Sbill } 239*944Sbill xtrlist[i].x_ino = d; 240*944Sbill xtrlist[i].x_flags |= XINUSE; 241*944Sbill printf("%s: inode %u\n", *argv, d); 242*944Sbill argv++; 243*944Sbill i++; 244*944Sbill } 245*944Sbill newvol: 246*944Sbill flsht(); 247*944Sbill close(mt); 248*944Sbill getvol: 249*944Sbill printf("Mount desired tape volume: Specify volume #: "); 250*944Sbill if (gets(tbf) == NULL) 251*944Sbill return; 252*944Sbill volno = atoi(tbf); 253*944Sbill if (volno <= 0) { 254*944Sbill printf("Volume numbers are positive numerics\n"); 255*944Sbill goto getvol; 256*944Sbill } 257*944Sbill mt = open(magtape, 0); 258*944Sbill if (readhdr(&spcl) == 0) { 259*944Sbill printf("tape is not dump tape\n"); 260*944Sbill goto newvol; 261*944Sbill } 262*944Sbill if (checkvol(&spcl, volno) == 0) { 263*944Sbill printf("Wrong volume (%d)\n", spcl.c_volume); 264*944Sbill goto newvol; 265*944Sbill } 266*944Sbill rbits: 267*944Sbill while (gethead(&spcl) == 0) 268*944Sbill ; 269*944Sbill if (checktype(&spcl, TS_INODE) == 1) { 270*944Sbill printf("Can't find inode mask!\n"); 271*944Sbill goto newvol; 272*944Sbill } 273*944Sbill if (checktype(&spcl, TS_BITS) == 0) 274*944Sbill goto rbits; 275*944Sbill readbits(dumpmap); 276*944Sbill i = 0; 277*944Sbill for (k = 0; xtrlist[k].x_flags; k++) { 278*944Sbill if (BIT(xtrlist[k].x_ino, dumpmap)) { 279*944Sbill xtrlist[k].x_flags |= ONTAPE; 280*944Sbill i++; 281*944Sbill } 282*944Sbill } 283*944Sbill while (i > 0) { 284*944Sbill again: 285*944Sbill if (ishead(&spcl) == 0) 286*944Sbill while(gethead(&spcl) == 0) 287*944Sbill ; 288*944Sbill if (checktype(&spcl, TS_END) == 1) { 289*944Sbill printf("end of tape\n"); 290*944Sbill checkdone: 291*944Sbill for (k = 0; xtrlist[k].x_flags; k++) 292*944Sbill if ((xtrlist[k].x_flags&XTRACTD) == 0) 293*944Sbill goto newvol; 294*944Sbill return; 295*944Sbill } 296*944Sbill if (checktype(&spcl, TS_INODE) == 0) { 297*944Sbill gethead(&spcl); 298*944Sbill goto again; 299*944Sbill } 300*944Sbill d = spcl.c_inumber; 301*944Sbill for (k = 0; xtrlist[k].x_flags; k++) { 302*944Sbill if (d == xtrlist[k].x_ino) { 303*944Sbill printf("extract file %u\n", xtrlist[k].x_ino); 304*944Sbill sprintf(name, "%u", xtrlist[k].x_ino); 305*944Sbill if ((ofile = creat(name, 0666)) < 0) { 306*944Sbill printf("%s: cannot create file\n", name); 307*944Sbill i--; 308*944Sbill continue; 309*944Sbill } 310*944Sbill chown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid); 311*944Sbill getfile(ino, xtrfile, skip, spcl.c_dinode.di_size); 312*944Sbill i--; 313*944Sbill xtrlist[k].x_flags |= XTRACTD; 314*944Sbill close(ofile); 315*944Sbill goto done; 316*944Sbill } 317*944Sbill } 318*944Sbill gethead(&spcl); 319*944Sbill done: 320*944Sbill ; 321*944Sbill } 322*944Sbill goto checkdone; 323*944Sbill #endif 324*944Sbill case 'r': 325*944Sbill case 'R': 326*944Sbill #ifndef STANDALONE 327*944Sbill if ((fi = open(*argv, 2)) < 0) { 328*944Sbill printf("%s: cannot open\n", *argv); 329*944Sbill exit(1); 330*944Sbill } 331*944Sbill #else 332*944Sbill do { 333*944Sbill char charbuf[50]; 334*944Sbill 335*944Sbill printf("Disk? "); 336*944Sbill gets(charbuf); 337*944Sbill fi = open(charbuf, 2); 338*944Sbill } while (fi == -1); 339*944Sbill #endif 340*944Sbill #ifndef STANDALONE 341*944Sbill if (command == 'R') { 342*944Sbill printf("Enter starting volume number: "); 343*944Sbill if (gets(tbf) == EOF) { 344*944Sbill volno = 1; 345*944Sbill printf("\n"); 346*944Sbill } 347*944Sbill else 348*944Sbill volno = atoi(tbf); 349*944Sbill } 350*944Sbill else 351*944Sbill #endif 352*944Sbill volno = 1; 353*944Sbill printf("Last chance before scribbling on %s. ", 354*944Sbill #ifdef STANDALONE 355*944Sbill "disk"); 356*944Sbill #else 357*944Sbill *argv); 358*944Sbill #endif 359*944Sbill while (getchar() != '\n'); 360*944Sbill dread((daddr_t)1, (char *)&sblock, sizeof(sblock)); 361*944Sbill maxi = (sblock.s_isize-2)*INOPB; 362*944Sbill if (readhdr(&spcl) == 0) { 363*944Sbill printf("Missing volume record\n"); 364*944Sbill exit(1); 365*944Sbill } 366*944Sbill if (checkvol(&spcl, volno) == 0) { 367*944Sbill printf("Tape is not volume %d\n", volno); 368*944Sbill exit(1); 369*944Sbill } 370*944Sbill gethead(&spcl); 371*944Sbill for (;;) { 372*944Sbill ragain: 373*944Sbill if (ishead(&spcl) == 0) { 374*944Sbill printf("Missing header block\n"); 375*944Sbill while (gethead(&spcl) == 0) 376*944Sbill ; 377*944Sbill eflag++; 378*944Sbill } 379*944Sbill if (checktype(&spcl, TS_END) == 1) { 380*944Sbill printf("End of tape\n"); 381*944Sbill close(mt); 382*944Sbill dwrite( (daddr_t) 1, (char *) &sblock); 383*944Sbill return; 384*944Sbill } 385*944Sbill if (checktype(&spcl, TS_CLRI) == 1) { 386*944Sbill readbits(clrimap); 387*944Sbill for (ino = 1; ino <= maxi; ino++) 388*944Sbill if (BIT(ino, clrimap) == 0) { 389*944Sbill getdino(ino, &tino); 390*944Sbill if (tino.di_mode == 0) 391*944Sbill continue; 392*944Sbill itrunc(&tino); 393*944Sbill clri(&tino); 394*944Sbill putdino(ino, &tino); 395*944Sbill } 396*944Sbill dwrite( (daddr_t) 1, (char *) &sblock); 397*944Sbill goto ragain; 398*944Sbill } 399*944Sbill if (checktype(&spcl, TS_BITS) == 1) { 400*944Sbill readbits(dumpmap); 401*944Sbill goto ragain; 402*944Sbill } 403*944Sbill if (checktype(&spcl, TS_INODE) == 0) { 404*944Sbill printf("Unknown header type\n"); 405*944Sbill eflag++; 406*944Sbill gethead(&spcl); 407*944Sbill goto ragain; 408*944Sbill } 409*944Sbill ino = spcl.c_inumber; 410*944Sbill if (eflag) 411*944Sbill printf("Resynced at inode %u\n", ino); 412*944Sbill eflag = 0; 413*944Sbill if (ino > maxi) { 414*944Sbill printf("%u: ilist too small\n", ino); 415*944Sbill gethead(&spcl); 416*944Sbill goto ragain; 417*944Sbill } 418*944Sbill dino = spcl.c_dinode; 419*944Sbill getdino(ino, &tino); 420*944Sbill curbno = 0; 421*944Sbill itrunc(&tino); 422*944Sbill clri(&tino); 423*944Sbill for (i = 0; i < NADDR; i++) 424*944Sbill taddr[i] = 0; 425*944Sbill l3tol(taddr, dino.di_addr, 1); 426*944Sbill getfile(d, rstrfile, rstrskip, dino.di_size); 427*944Sbill ip = &tino; 428*944Sbill ltol3(ip->di_addr, taddr, NADDR); 429*944Sbill ip1 = &dino; 430*944Sbill ip->di_mode = ip1->di_mode; 431*944Sbill ip->di_nlink = ip1->di_nlink; 432*944Sbill ip->di_uid = ip1->di_uid; 433*944Sbill ip->di_gid = ip1->di_gid; 434*944Sbill ip->di_size = ip1->di_size; 435*944Sbill ip->di_atime = ip1->di_atime; 436*944Sbill ip->di_mtime = ip1->di_mtime; 437*944Sbill ip->di_ctime = ip1->di_ctime; 438*944Sbill putdino(ino, &tino); 439*944Sbill } 440*944Sbill } 441*944Sbill } 442*944Sbill 443*944Sbill /* 444*944Sbill * Read the tape, bulding up a directory structure for extraction 445*944Sbill * by name 446*944Sbill */ 447*944Sbill #ifndef STANDALONE 448*944Sbill pass1() 449*944Sbill { 450*944Sbill register i; 451*944Sbill struct dinode *ip; 452*944Sbill int putdir(), null(); 453*944Sbill 454*944Sbill while (gethead(&spcl) == 0) { 455*944Sbill printf("Can't find directory header!\n"); 456*944Sbill } 457*944Sbill for (;;) { 458*944Sbill if (checktype(&spcl, TS_BITS) == 1) { 459*944Sbill readbits(dumpmap); 460*944Sbill continue; 461*944Sbill } 462*944Sbill if (checktype(&spcl, TS_CLRI) == 1) { 463*944Sbill readbits(clrimap); 464*944Sbill continue; 465*944Sbill } 466*944Sbill if (checktype(&spcl, TS_INODE) == 0) { 467*944Sbill finish: 468*944Sbill flsh(); 469*944Sbill close(mt); 470*944Sbill return; 471*944Sbill } 472*944Sbill ip = &spcl.c_dinode; 473*944Sbill i = ip->di_mode & IFMT; 474*944Sbill if (i != IFDIR) { 475*944Sbill goto finish; 476*944Sbill } 477*944Sbill inotab[ipos].t_ino = spcl.c_inumber; 478*944Sbill inotab[ipos++].t_seekpt = seekpt; 479*944Sbill getfile(spcl.c_inumber, putdir, null, spcl.c_dinode.di_size); 480*944Sbill putent("\000\000/"); 481*944Sbill } 482*944Sbill } 483*944Sbill #endif 484*944Sbill 485*944Sbill /* 486*944Sbill * Do the file extraction, calling the supplied functions 487*944Sbill * with the blocks 488*944Sbill */ 489*944Sbill getfile(n, f1, f2, size) 490*944Sbill ino_t n; 491*944Sbill int (*f2)(), (*f1)(); 492*944Sbill long size; 493*944Sbill { 494*944Sbill register i; 495*944Sbill struct spcl addrblock; 496*944Sbill char buf[BSIZE]; 497*944Sbill 498*944Sbill addrblock = spcl; 499*944Sbill curino = n; 500*944Sbill goto start; 501*944Sbill for (;;) { 502*944Sbill if (gethead(&addrblock) == 0) { 503*944Sbill printf("Missing address (header) block\n"); 504*944Sbill goto eloop; 505*944Sbill } 506*944Sbill if (checktype(&addrblock, TS_ADDR) == 0) { 507*944Sbill spcl = addrblock; 508*944Sbill curino = 0; 509*944Sbill curino = 0; 510*944Sbill return; 511*944Sbill } 512*944Sbill start: 513*944Sbill for (i = 0; i < addrblock.c_count; i += 2) { 514*944Sbill if (addrblock.c_addr[i]) 515*944Sbill readtape(buf, 0); 516*944Sbill else 517*944Sbill clearbuf(buf, 0); 518*944Sbill if (size > OBSIZE && addrblock.c_addr[i+1]) 519*944Sbill readtape(buf, 1); 520*944Sbill else 521*944Sbill clearbuf(buf, 1); 522*944Sbill if (addrblock.c_addr[i] || size > OBSIZE && addrblock.c_addr[i + 1]) 523*944Sbill (*f1)(buf, size > BSIZE ? (long) BSIZE : size); 524*944Sbill else 525*944Sbill (*f2)(buf, size > BSIZE ? (long) BSIZE : size); 526*944Sbill if ((size -= BSIZE) <= 0) { 527*944Sbill eloop: 528*944Sbill while (gethead(&spcl) == 0) 529*944Sbill ; 530*944Sbill if (checktype(&spcl, TS_ADDR) == 1) 531*944Sbill goto eloop; 532*944Sbill curino = 0; 533*944Sbill return; 534*944Sbill } 535*944Sbill } 536*944Sbill } 537*944Sbill } 538*944Sbill 539*944Sbill /* 540*944Sbill * Do the tape i\/o, dealling with volume changes 541*944Sbill * etc.. 542*944Sbill */ 543*944Sbill readtape(b, part) 544*944Sbill char *b; 545*944Sbill { 546*944Sbill register i; 547*944Sbill struct spcl tmpbuf; 548*944Sbill 549*944Sbill if (bct >= NTREC) { 550*944Sbill for (i = 0; i < NTREC; i++) 551*944Sbill ((struct spcl *)&tbf[i*OBSIZE])->c_magic = 0; 552*944Sbill bct = 0; 553*944Sbill if ((i = read(mt, tbf, NTREC*OBSIZE)) < 0) { 554*944Sbill printf("Tape read error: inode %u\n", curino); 555*944Sbill eflag++; 556*944Sbill exit(1); 557*944Sbill } 558*944Sbill if (i == 0) { 559*944Sbill bct = NTREC + 1; 560*944Sbill volno++; 561*944Sbill loop: 562*944Sbill flsht(); 563*944Sbill close(mt); 564*944Sbill printf("Mount volume %d\n", volno); 565*944Sbill while (getchar() != '\n') 566*944Sbill ; 567*944Sbill if ((mt = open(magtape, 0)) == -1) { 568*944Sbill printf("Cannot open tape!\n"); 569*944Sbill goto loop; 570*944Sbill } 571*944Sbill if (readhdr(&tmpbuf) == 0) { 572*944Sbill printf("Not a dump tape.Try again\n"); 573*944Sbill goto loop; 574*944Sbill } 575*944Sbill if (checkvol(&tmpbuf, volno) == 0) { 576*944Sbill printf("Wrong tape. Try again\n"); 577*944Sbill goto loop; 578*944Sbill } 579*944Sbill readtape(b, part); 580*944Sbill return; 581*944Sbill } 582*944Sbill } 583*944Sbill copy(&tbf[(bct++*OBSIZE)], b + part * OBSIZE, OBSIZE); 584*944Sbill } 585*944Sbill 586*944Sbill flsht() 587*944Sbill { 588*944Sbill bct = NTREC+1; 589*944Sbill } 590*944Sbill 591*944Sbill copy(f, t, s) 592*944Sbill register char *f, *t; 593*944Sbill { 594*944Sbill register i; 595*944Sbill 596*944Sbill i = s; 597*944Sbill do 598*944Sbill *t++ = *f++; 599*944Sbill while (--i); 600*944Sbill } 601*944Sbill 602*944Sbill clearbuf(cp, part) 603*944Sbill register char *cp; 604*944Sbill { 605*944Sbill register i; 606*944Sbill 607*944Sbill cp += part * OBSIZE; 608*944Sbill i = OBSIZE; 609*944Sbill do 610*944Sbill *cp++ = 0; 611*944Sbill while (--i); 612*944Sbill } 613*944Sbill 614*944Sbill /* 615*944Sbill * Put and get the directory entries from the compressed 616*944Sbill * directory file 617*944Sbill */ 618*944Sbill #ifndef STANDALONE 619*944Sbill putent(cp) 620*944Sbill char *cp; 621*944Sbill { 622*944Sbill register i; 623*944Sbill 624*944Sbill for (i = 0; i < sizeof(ino_t); i++) 625*944Sbill writec(*cp++); 626*944Sbill for (i = 0; i < DIRSIZ; i++) { 627*944Sbill writec(*cp); 628*944Sbill if (*cp++ == 0) 629*944Sbill return; 630*944Sbill } 631*944Sbill return; 632*944Sbill } 633*944Sbill 634*944Sbill getent(bf) 635*944Sbill register char *bf; 636*944Sbill { 637*944Sbill register i; 638*944Sbill 639*944Sbill for (i = 0; i < sizeof(ino_t); i++) 640*944Sbill *bf++ = readc(); 641*944Sbill for (i = 0; i < DIRSIZ; i++) 642*944Sbill if ((*bf++ = readc()) == 0) 643*944Sbill return; 644*944Sbill return; 645*944Sbill } 646*944Sbill 647*944Sbill /* 648*944Sbill * read/write te directory file 649*944Sbill */ 650*944Sbill writec(c) 651*944Sbill char c; 652*944Sbill { 653*944Sbill drblock[bpt++] = c; 654*944Sbill seekpt++; 655*944Sbill if (bpt >= BSIZE) { 656*944Sbill bpt = 0; 657*944Sbill write(df, drblock, BSIZE); 658*944Sbill } 659*944Sbill } 660*944Sbill 661*944Sbill readc() 662*944Sbill { 663*944Sbill if (bpt >= BSIZE) { 664*944Sbill read(df, drblock, BSIZE); 665*944Sbill bpt = 0; 666*944Sbill } 667*944Sbill return(drblock[bpt++]); 668*944Sbill } 669*944Sbill 670*944Sbill mseek(pt) 671*944Sbill daddr_t pt; 672*944Sbill { 673*944Sbill bpt = BSIZE; 674*944Sbill lseek(df, pt, 0); 675*944Sbill } 676*944Sbill 677*944Sbill flsh() 678*944Sbill { 679*944Sbill write(df, drblock, bpt+1); 680*944Sbill } 681*944Sbill 682*944Sbill /* 683*944Sbill * search the directory inode ino 684*944Sbill * looking for entry cp 685*944Sbill */ 686*944Sbill ino_t 687*944Sbill search(inum, cp) 688*944Sbill ino_t inum; 689*944Sbill char *cp; 690*944Sbill { 691*944Sbill register i; 692*944Sbill struct direct dir; 693*944Sbill 694*944Sbill for (i = 0; i < MAXINO; i++) 695*944Sbill if (inotab[i].t_ino == inum) { 696*944Sbill goto found; 697*944Sbill } 698*944Sbill return(0); 699*944Sbill found: 700*944Sbill mseek(inotab[i].t_seekpt); 701*944Sbill do { 702*944Sbill getent((char *)&dir); 703*944Sbill if (direq(dir.d_name, "/")) 704*944Sbill return(0); 705*944Sbill } while (direq(dir.d_name, cp) == 0); 706*944Sbill return(dir.d_ino); 707*944Sbill } 708*944Sbill 709*944Sbill /* 710*944Sbill * Search the directory tree rooted at inode 2 711*944Sbill * for the path pointed at by n 712*944Sbill */ 713*944Sbill psearch(n) 714*944Sbill char *n; 715*944Sbill { 716*944Sbill register char *cp, *cp1; 717*944Sbill char c; 718*944Sbill 719*944Sbill ino = 2; 720*944Sbill if (*(cp = n) == '/') 721*944Sbill cp++; 722*944Sbill next: 723*944Sbill cp1 = cp + 1; 724*944Sbill while (*cp1 != '/' && *cp1) 725*944Sbill cp1++; 726*944Sbill c = *cp1; 727*944Sbill *cp1 = 0; 728*944Sbill ino = search(ino, cp); 729*944Sbill if (ino == 0) { 730*944Sbill *cp1 = c; 731*944Sbill return(0); 732*944Sbill } 733*944Sbill *cp1 = c; 734*944Sbill if (c == '/') { 735*944Sbill cp = cp1+1; 736*944Sbill goto next; 737*944Sbill } 738*944Sbill return(ino); 739*944Sbill } 740*944Sbill 741*944Sbill direq(s1, s2) 742*944Sbill register char *s1, *s2; 743*944Sbill { 744*944Sbill register i; 745*944Sbill 746*944Sbill for (i = 0; i < DIRSIZ; i++) 747*944Sbill if (*s1++ == *s2) { 748*944Sbill if (*s2++ == 0) 749*944Sbill return(1); 750*944Sbill } else 751*944Sbill return(0); 752*944Sbill return(1); 753*944Sbill } 754*944Sbill #endif 755*944Sbill 756*944Sbill /* 757*944Sbill * read/write a disk block, be sure to update the buffer 758*944Sbill * cache if needed. 759*944Sbill */ 760*944Sbill dwrite(bno, b) 761*944Sbill daddr_t bno; 762*944Sbill char *b; 763*944Sbill { 764*944Sbill register i; 765*944Sbill 766*944Sbill for (i = 0; i < NCACHE; i++) { 767*944Sbill if (cache[i].c_bno == bno) { 768*944Sbill copy(b, cache[i].c_block, BSIZE); 769*944Sbill cache[i].c_time = 0; 770*944Sbill break; 771*944Sbill } 772*944Sbill else 773*944Sbill cache[i].c_time++; 774*944Sbill } 775*944Sbill lseek(fi, bno*BSIZE, 0); 776*944Sbill if(write(fi, b, BSIZE) != BSIZE) { 777*944Sbill #ifdef STANDALONE 778*944Sbill printf("disk write error %D\n", bno); 779*944Sbill #else 780*944Sbill fprintf(stderr, "disk write error %ld\n", bno); 781*944Sbill #endif 782*944Sbill exit(1); 783*944Sbill } 784*944Sbill } 785*944Sbill 786*944Sbill dread(bno, buf, cnt) 787*944Sbill daddr_t bno; 788*944Sbill char *buf; 789*944Sbill { 790*944Sbill register i, j; 791*944Sbill 792*944Sbill j = 0; 793*944Sbill for (i = 0; i < NCACHE; i++) { 794*944Sbill if (++curcache >= NCACHE) 795*944Sbill curcache = 0; 796*944Sbill if (cache[curcache].c_bno == bno) { 797*944Sbill copy(cache[curcache].c_block, buf, cnt); 798*944Sbill cache[curcache].c_time = 0; 799*944Sbill return; 800*944Sbill } 801*944Sbill else { 802*944Sbill cache[curcache].c_time++; 803*944Sbill if (cache[j].c_time < cache[curcache].c_time) 804*944Sbill j = curcache; 805*944Sbill } 806*944Sbill } 807*944Sbill 808*944Sbill lseek(fi, bno*BSIZE, 0); 809*944Sbill if (read(fi, cache[j].c_block, BSIZE) != BSIZE) { 810*944Sbill #ifdef STANDALONE 811*944Sbill printf("read error %D\n", bno); 812*944Sbill #else 813*944Sbill printf("read error %ld\n", bno); 814*944Sbill #endif 815*944Sbill exit(1); 816*944Sbill } 817*944Sbill copy(cache[j].c_block, buf, cnt); 818*944Sbill cache[j].c_time = 0; 819*944Sbill cache[j].c_bno = bno; 820*944Sbill } 821*944Sbill 822*944Sbill /* 823*944Sbill * the inode manpulation routines. Like the system. 824*944Sbill * 825*944Sbill * clri zeros the inode 826*944Sbill */ 827*944Sbill clri(ip) 828*944Sbill struct dinode *ip; 829*944Sbill { 830*944Sbill int i, *p; 831*944Sbill i = sizeof(struct dinode)/sizeof(int); 832*944Sbill p = (int *)ip; 833*944Sbill do 834*944Sbill *p++ = 0; 835*944Sbill while(--i); 836*944Sbill } 837*944Sbill 838*944Sbill /* 839*944Sbill * itrunc/tloop/bfree free all of the blocks pointed at by the inode 840*944Sbill */ 841*944Sbill itrunc(ip) 842*944Sbill register struct dinode *ip; 843*944Sbill { 844*944Sbill register i; 845*944Sbill daddr_t bn, iaddr[NADDR]; 846*944Sbill 847*944Sbill if (ip->di_mode == 0) 848*944Sbill return; 849*944Sbill i = ip->di_mode & IFMT; 850*944Sbill if (i != IFDIR && i != IFREG) 851*944Sbill return; 852*944Sbill l3tol(iaddr, ip->di_addr, NADDR); 853*944Sbill for(i=NADDR-1;i>=0;i--) { 854*944Sbill bn = iaddr[i]; 855*944Sbill if(bn == 0) continue; 856*944Sbill switch(i) { 857*944Sbill 858*944Sbill default: 859*944Sbill bfree(bn); 860*944Sbill break; 861*944Sbill 862*944Sbill case NADDR-3: 863*944Sbill tloop(bn, 0, 0); 864*944Sbill break; 865*944Sbill 866*944Sbill case NADDR-2: 867*944Sbill tloop(bn, 1, 0); 868*944Sbill break; 869*944Sbill 870*944Sbill case NADDR-1: 871*944Sbill tloop(bn, 1, 1); 872*944Sbill } 873*944Sbill } 874*944Sbill ip->di_size = 0; 875*944Sbill } 876*944Sbill 877*944Sbill tloop(bn, f1, f2) 878*944Sbill daddr_t bn; 879*944Sbill int f1, f2; 880*944Sbill { 881*944Sbill register i; 882*944Sbill daddr_t nb; 883*944Sbill union { 884*944Sbill char data[BSIZE]; 885*944Sbill daddr_t indir[NINDIR]; 886*944Sbill } ibuf; 887*944Sbill 888*944Sbill dread(bn, ibuf.data, BSIZE); 889*944Sbill for(i=NINDIR-1;i>=0;i--) { 890*944Sbill nb = ibuf.indir[i]; 891*944Sbill if(nb) { 892*944Sbill if(f1) 893*944Sbill tloop(nb, f2, 0); 894*944Sbill else 895*944Sbill bfree(nb); 896*944Sbill } 897*944Sbill } 898*944Sbill bfree(bn); 899*944Sbill } 900*944Sbill 901*944Sbill bfree(bn) 902*944Sbill daddr_t bn; 903*944Sbill { 904*944Sbill register i; 905*944Sbill union { 906*944Sbill char data[BSIZE]; 907*944Sbill struct fblk frees; 908*944Sbill } fbuf; 909*944Sbill 910*944Sbill if(sblock.s_nfree >= NICFREE) { 911*944Sbill fbuf.df_nfree = sblock.s_nfree; 912*944Sbill for(i=0;i<NICFREE;i++) 913*944Sbill fbuf.df_free[i] = sblock.s_free[i]; 914*944Sbill sblock.s_nfree = 0; 915*944Sbill dwrite(bn, fbuf.data); 916*944Sbill } 917*944Sbill sblock.s_free[sblock.s_nfree++] = bn; 918*944Sbill } 919*944Sbill 920*944Sbill /* 921*944Sbill * allocate a block off the free list. 922*944Sbill */ 923*944Sbill daddr_t 924*944Sbill balloc() 925*944Sbill { 926*944Sbill daddr_t bno; 927*944Sbill register i; 928*944Sbill static char zeroes[BSIZE]; 929*944Sbill union { 930*944Sbill char data[BSIZE]; 931*944Sbill struct fblk frees; 932*944Sbill } fbuf; 933*944Sbill 934*944Sbill if(sblock.s_nfree == 0 || (bno=sblock.s_free[--sblock.s_nfree]) == 0) { 935*944Sbill #ifdef STANDALONE 936*944Sbill printf("Out of space\n"); 937*944Sbill #else 938*944Sbill fprintf(stderr, "Out of space.\n"); 939*944Sbill #endif 940*944Sbill exit(1); 941*944Sbill } 942*944Sbill if(sblock.s_nfree == 0) { 943*944Sbill dread(bno, fbuf.data, BSIZE); 944*944Sbill sblock.s_nfree = fbuf.df_nfree; 945*944Sbill for(i=0;i<NICFREE;i++) 946*944Sbill sblock.s_free[i] = fbuf.df_free[i]; 947*944Sbill } 948*944Sbill dwrite(bno, zeroes); 949*944Sbill return(bno); 950*944Sbill } 951*944Sbill 952*944Sbill /* 953*944Sbill * map a block number into a block address, ensuring 954*944Sbill * all of the correct indirect blocks are around. Allocate 955*944Sbill * the block requested. 956*944Sbill */ 957*944Sbill daddr_t 958*944Sbill bmap(iaddr, bn) 959*944Sbill daddr_t iaddr[NADDR]; 960*944Sbill daddr_t bn; 961*944Sbill { 962*944Sbill register i; 963*944Sbill int j, sh; 964*944Sbill daddr_t nb, nnb; 965*944Sbill daddr_t indir[NINDIR]; 966*944Sbill 967*944Sbill /* 968*944Sbill * blocks 0..NADDR-4 are direct blocks 969*944Sbill */ 970*944Sbill if(bn < NADDR-3) { 971*944Sbill iaddr[bn] = nb = balloc(); 972*944Sbill return(nb); 973*944Sbill } 974*944Sbill 975*944Sbill /* 976*944Sbill * addresses NADDR-3, NADDR-2, and NADDR-1 977*944Sbill * have single, double, triple indirect blocks. 978*944Sbill * the first step is to determine 979*944Sbill * how many levels of indirection. 980*944Sbill */ 981*944Sbill sh = 0; 982*944Sbill nb = 1; 983*944Sbill bn -= NADDR-3; 984*944Sbill for(j=3; j>0; j--) { 985*944Sbill sh += NSHIFT; 986*944Sbill nb <<= NSHIFT; 987*944Sbill if(bn < nb) 988*944Sbill break; 989*944Sbill bn -= nb; 990*944Sbill } 991*944Sbill if(j == 0) { 992*944Sbill return((daddr_t)0); 993*944Sbill } 994*944Sbill 995*944Sbill /* 996*944Sbill * fetch the address from the inode 997*944Sbill */ 998*944Sbill if((nb = iaddr[NADDR-j]) == 0) { 999*944Sbill iaddr[NADDR-j] = nb = balloc(); 1000*944Sbill } 1001*944Sbill 1002*944Sbill /* 1003*944Sbill * fetch through the indirect blocks 1004*944Sbill */ 1005*944Sbill for(; j<=3; j++) { 1006*944Sbill dread(nb, (char *)indir, BSIZE); 1007*944Sbill sh -= NSHIFT; 1008*944Sbill i = (bn>>sh) & NMASK; 1009*944Sbill nnb = indir[i]; 1010*944Sbill if(nnb == 0) { 1011*944Sbill nnb = balloc(); 1012*944Sbill indir[i] = nnb; 1013*944Sbill dwrite(nb, (char *)indir); 1014*944Sbill } 1015*944Sbill nb = nnb; 1016*944Sbill } 1017*944Sbill return(nb); 1018*944Sbill } 1019*944Sbill 1020*944Sbill /* 1021*944Sbill * read the tape into buf, then return whether or 1022*944Sbill * or not it is a header block. 1023*944Sbill */ 1024*944Sbill gethead(buf) 1025*944Sbill struct spcl *buf; 1026*944Sbill { 1027*944Sbill readtape((char *)buf, 0); 1028*944Sbill if (buf->c_magic != MAGIC || checksum((int *) buf) == 0) 1029*944Sbill return(0); 1030*944Sbill return(1); 1031*944Sbill } 1032*944Sbill 1033*944Sbill /* 1034*944Sbill * return whether or not the buffer contains a header block 1035*944Sbill */ 1036*944Sbill ishead(buf) 1037*944Sbill struct spcl *buf; 1038*944Sbill { 1039*944Sbill if (buf->c_magic != MAGIC || checksum((int *) buf) == 0) 1040*944Sbill return(0); 1041*944Sbill return(1); 1042*944Sbill } 1043*944Sbill 1044*944Sbill checktype(b, t) 1045*944Sbill struct spcl *b; 1046*944Sbill int t; 1047*944Sbill { 1048*944Sbill return(b->c_type == t); 1049*944Sbill } 1050*944Sbill 1051*944Sbill 1052*944Sbill checksum(b) 1053*944Sbill int *b; 1054*944Sbill { 1055*944Sbill register i, j; 1056*944Sbill 1057*944Sbill j = OBSIZE/sizeof(int); 1058*944Sbill i = 0; 1059*944Sbill do 1060*944Sbill i += *b++; 1061*944Sbill while (--j); 1062*944Sbill if (i != CHECKSUM) { 1063*944Sbill printf("Checksum error %o\n", i); 1064*944Sbill return(0); 1065*944Sbill } 1066*944Sbill return(1); 1067*944Sbill } 1068*944Sbill 1069*944Sbill checkvol(b, t) 1070*944Sbill struct spcl *b; 1071*944Sbill int t; 1072*944Sbill { 1073*944Sbill if (b->c_volume == t) 1074*944Sbill return(1); 1075*944Sbill return(0); 1076*944Sbill } 1077*944Sbill 1078*944Sbill readhdr(b) 1079*944Sbill struct spcl *b; 1080*944Sbill { 1081*944Sbill if (gethead(b) == 0) 1082*944Sbill return(0); 1083*944Sbill if (checktype(b, TS_TAPE) == 0) 1084*944Sbill return(0); 1085*944Sbill return(1); 1086*944Sbill } 1087*944Sbill 1088*944Sbill /* 1089*944Sbill * The next routines are called during file extraction to 1090*944Sbill * put the data into the right form and place. 1091*944Sbill */ 1092*944Sbill #ifndef STANDALONE 1093*944Sbill xtrfile(b, size) 1094*944Sbill char *b; 1095*944Sbill long size; 1096*944Sbill { 1097*944Sbill write(ofile, b, (int) size); 1098*944Sbill } 1099*944Sbill 1100*944Sbill null() {;} 1101*944Sbill 1102*944Sbill skip() 1103*944Sbill { 1104*944Sbill lseek(ofile, (long) OBSIZE, 1); 1105*944Sbill } 1106*944Sbill #endif 1107*944Sbill 1108*944Sbill 1109*944Sbill rstrfile(b, s) 1110*944Sbill char *b; 1111*944Sbill long s; 1112*944Sbill { 1113*944Sbill daddr_t d; 1114*944Sbill 1115*944Sbill d = bmap(taddr, curbno); 1116*944Sbill dwrite(d, b); 1117*944Sbill curbno += 1; 1118*944Sbill } 1119*944Sbill 1120*944Sbill rstrskip(b, s) 1121*944Sbill char *b; 1122*944Sbill long s; 1123*944Sbill { 1124*944Sbill curbno += 1; 1125*944Sbill } 1126*944Sbill 1127*944Sbill #ifndef STANDALONE 1128*944Sbill putdir(b) 1129*944Sbill char *b; 1130*944Sbill { 1131*944Sbill register struct direct *dp; 1132*944Sbill register i; 1133*944Sbill 1134*944Sbill for (dp = (struct direct *) b, i = 0; i < BSIZE; dp++, i += sizeof(*dp)) { 1135*944Sbill if (dp->d_ino == 0) 1136*944Sbill continue; 1137*944Sbill putent((char *) dp); 1138*944Sbill } 1139*944Sbill } 1140*944Sbill #endif 1141*944Sbill 1142*944Sbill /* 1143*944Sbill * read/write an inode from the disk 1144*944Sbill */ 1145*944Sbill getdino(inum, b) 1146*944Sbill ino_t inum; 1147*944Sbill struct dinode *b; 1148*944Sbill { 1149*944Sbill daddr_t bno; 1150*944Sbill char buf[BSIZE]; 1151*944Sbill 1152*944Sbill bno = (ino - 1)/INOPB; 1153*944Sbill bno += 2; 1154*944Sbill dread(bno, buf, BSIZE); 1155*944Sbill copy(&buf[((inum-1)%INOPB)*sizeof(struct dinode)], (char *) b, sizeof(struct dinode)); 1156*944Sbill } 1157*944Sbill 1158*944Sbill putdino(inum, b) 1159*944Sbill ino_t inum; 1160*944Sbill struct dinode *b; 1161*944Sbill { 1162*944Sbill daddr_t bno; 1163*944Sbill char buf[BSIZE]; 1164*944Sbill 1165*944Sbill bno = ((ino - 1)/INOPB) + 2; 1166*944Sbill dread(bno, buf, BSIZE); 1167*944Sbill copy((char *) b, &buf[((inum-1)%INOPB)*sizeof(struct dinode)], sizeof(struct dinode)); 1168*944Sbill dwrite(bno, buf); 1169*944Sbill } 1170*944Sbill 1171*944Sbill /* 1172*944Sbill * read a bit mask from the tape into m. 1173*944Sbill */ 1174*944Sbill readbits(m) 1175*944Sbill short *m; 1176*944Sbill { 1177*944Sbill register i; 1178*944Sbill 1179*944Sbill i = spcl.c_count; 1180*944Sbill 1181*944Sbill while (i--) { 1182*944Sbill readtape((char *) m, 0); 1183*944Sbill m += (OBSIZE/(MLEN/BITS)); 1184*944Sbill } 1185*944Sbill while (gethead(&spcl) == 0) 1186*944Sbill ; 1187*944Sbill } 1188*944Sbill 1189*944Sbill done() 1190*944Sbill { 1191*944Sbill unlink(dirfile); 1192*944Sbill exit(0); 1193*944Sbill } 1194