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