1*1119Sbill static char *sccsid = "@(#)tar.c 4.1 (Berkeley) 10/01/80"; 2*1119Sbill #include <stdio.h> 3*1119Sbill #include <sys/types.h> 4*1119Sbill #include <sys/stat.h> 5*1119Sbill #include <sys/dir.h> 6*1119Sbill #include <signal.h> 7*1119Sbill 8*1119Sbill char *sprintf(); 9*1119Sbill char *strcat(); 10*1119Sbill daddr_t bsrch(); 11*1119Sbill #define TBLOCK 512 12*1119Sbill #define NBLOCK 40 13*1119Sbill #define NAMSIZ 100 14*1119Sbill union hblock { 15*1119Sbill char dummy[TBLOCK]; 16*1119Sbill struct header { 17*1119Sbill char name[NAMSIZ]; 18*1119Sbill char mode[8]; 19*1119Sbill char uid[8]; 20*1119Sbill char gid[8]; 21*1119Sbill char size[12]; 22*1119Sbill char mtime[12]; 23*1119Sbill char chksum[8]; 24*1119Sbill char linkflag; 25*1119Sbill char linkname[NAMSIZ]; 26*1119Sbill } dbuf; 27*1119Sbill } dblock, tbuf[NBLOCK]; 28*1119Sbill 29*1119Sbill struct linkbuf { 30*1119Sbill ino_t inum; 31*1119Sbill dev_t devnum; 32*1119Sbill int count; 33*1119Sbill char pathname[NAMSIZ]; 34*1119Sbill struct linkbuf *nextp; 35*1119Sbill } *ihead; 36*1119Sbill 37*1119Sbill struct stat stbuf; 38*1119Sbill 39*1119Sbill int rflag, xflag, vflag, tflag, mt, cflag, mflag, fflag, oflag, pflag; 40*1119Sbill int term, chksum, wflag, recno, first, linkerrok; 41*1119Sbill int freemem = 1; 42*1119Sbill int nblock = 1; 43*1119Sbill 44*1119Sbill daddr_t low; 45*1119Sbill daddr_t high; 46*1119Sbill 47*1119Sbill FILE *tfile; 48*1119Sbill char tname[] = "/tmp/tarXXXXXX"; 49*1119Sbill 50*1119Sbill 51*1119Sbill char *usefile; 52*1119Sbill char magtape[] = "/dev/rmt8"; 53*1119Sbill 54*1119Sbill char *malloc(); 55*1119Sbill 56*1119Sbill main(argc, argv) 57*1119Sbill int argc; 58*1119Sbill char *argv[]; 59*1119Sbill { 60*1119Sbill char *cp; 61*1119Sbill int onintr(), onquit(), onhup(), onterm(); 62*1119Sbill 63*1119Sbill if (argc < 2) 64*1119Sbill usage(); 65*1119Sbill 66*1119Sbill tfile = NULL; 67*1119Sbill usefile = magtape; 68*1119Sbill argv[argc] = 0; 69*1119Sbill argv++; 70*1119Sbill for (cp = *argv++; *cp; cp++) 71*1119Sbill switch(*cp) { 72*1119Sbill case 'f': 73*1119Sbill usefile = *argv++; 74*1119Sbill fflag++; 75*1119Sbill if (nblock == 1) 76*1119Sbill nblock = 0; 77*1119Sbill break; 78*1119Sbill case 'c': 79*1119Sbill cflag++; 80*1119Sbill rflag++; 81*1119Sbill break; 82*1119Sbill case 'o': 83*1119Sbill oflag++; 84*1119Sbill break; 85*1119Sbill case 'p': 86*1119Sbill pflag++; 87*1119Sbill break; 88*1119Sbill case 'u': 89*1119Sbill mktemp(tname); 90*1119Sbill if ((tfile = fopen(tname, "w")) == NULL) { 91*1119Sbill fprintf(stderr, "Tar: cannot create temporary file (%s)\n", tname); 92*1119Sbill done(1); 93*1119Sbill } 94*1119Sbill fprintf(tfile, "!!!!!/!/!/!/!/!/!/! 000\n"); 95*1119Sbill /* FALL THROUGH */ 96*1119Sbill case 'r': 97*1119Sbill rflag++; 98*1119Sbill noupdate: 99*1119Sbill if (nblock != 1 && cflag == 0) { 100*1119Sbill fprintf(stderr, "Tar: Blocked tapes cannot be updated (yet)\n"); 101*1119Sbill done(1); 102*1119Sbill } 103*1119Sbill break; 104*1119Sbill case 'v': 105*1119Sbill vflag++; 106*1119Sbill break; 107*1119Sbill case 'w': 108*1119Sbill wflag++; 109*1119Sbill break; 110*1119Sbill case 'x': 111*1119Sbill xflag++; 112*1119Sbill break; 113*1119Sbill case 't': 114*1119Sbill tflag++; 115*1119Sbill break; 116*1119Sbill case 'm': 117*1119Sbill mflag++; 118*1119Sbill break; 119*1119Sbill case '-': 120*1119Sbill break; 121*1119Sbill case '0': 122*1119Sbill case '1': 123*1119Sbill case '4': 124*1119Sbill case '5': 125*1119Sbill case '7': 126*1119Sbill case '8': 127*1119Sbill magtape[8] = *cp; 128*1119Sbill usefile = magtape; 129*1119Sbill break; 130*1119Sbill case 'b': 131*1119Sbill nblock = atoi(*argv++); 132*1119Sbill if (nblock > NBLOCK || nblock <= 0) { 133*1119Sbill fprintf(stderr, "Invalid blocksize. (Max %d)\n", NBLOCK); 134*1119Sbill done(1); 135*1119Sbill } 136*1119Sbill if (rflag && !cflag) 137*1119Sbill goto noupdate; 138*1119Sbill break; 139*1119Sbill case 'l': 140*1119Sbill linkerrok++; 141*1119Sbill break; 142*1119Sbill default: 143*1119Sbill fprintf(stderr, "tar: %c: unknown option\n", *cp); 144*1119Sbill usage(); 145*1119Sbill } 146*1119Sbill 147*1119Sbill if (rflag) { 148*1119Sbill if (cflag && tfile != NULL) { 149*1119Sbill usage(); 150*1119Sbill done(1); 151*1119Sbill } 152*1119Sbill if (signal(SIGINT, SIG_IGN) != SIG_IGN) 153*1119Sbill signal(SIGINT, onintr); 154*1119Sbill if (signal(SIGHUP, SIG_IGN) != SIG_IGN) 155*1119Sbill signal(SIGHUP, onhup); 156*1119Sbill if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) 157*1119Sbill signal(SIGQUIT, onquit); 158*1119Sbill /* 159*1119Sbill if (signal(SIGTERM, SIG_IGN) != SIG_IGN) 160*1119Sbill signal(SIGTERM, onterm); 161*1119Sbill */ 162*1119Sbill if (strcmp(usefile, "-") == 0) { 163*1119Sbill if (cflag == 0) { 164*1119Sbill fprintf(stderr, "Can only create standard output archives\n"); 165*1119Sbill done(1); 166*1119Sbill } 167*1119Sbill mt = dup(1); 168*1119Sbill nblock = 1; 169*1119Sbill } 170*1119Sbill else if ((mt = open(usefile, 2)) < 0) { 171*1119Sbill if (cflag == 0 || (mt = creat(usefile, 0666)) < 0) { 172*1119Sbill fprintf(stderr, "tar: cannot open %s\n", usefile); 173*1119Sbill done(1); 174*1119Sbill } 175*1119Sbill } 176*1119Sbill if (cflag == 0 && nblock == 0) 177*1119Sbill nblock = 1; 178*1119Sbill dorep(argv); 179*1119Sbill } 180*1119Sbill else if (xflag) { 181*1119Sbill if (strcmp(usefile, "-") == 0) { 182*1119Sbill mt = dup(0); 183*1119Sbill nblock = 1; 184*1119Sbill } 185*1119Sbill else if ((mt = open(usefile, 0)) < 0) { 186*1119Sbill fprintf(stderr, "tar: cannot open %s\n", usefile); 187*1119Sbill done(1); 188*1119Sbill } 189*1119Sbill doxtract(argv); 190*1119Sbill } 191*1119Sbill else if (tflag) { 192*1119Sbill if (strcmp(usefile, "-") == 0) { 193*1119Sbill mt = dup(0); 194*1119Sbill nblock = 1; 195*1119Sbill } 196*1119Sbill else if ((mt = open(usefile, 0)) < 0) { 197*1119Sbill fprintf(stderr, "tar: cannot open %s\n", usefile); 198*1119Sbill done(1); 199*1119Sbill } 200*1119Sbill dotable(); 201*1119Sbill } 202*1119Sbill else 203*1119Sbill usage(); 204*1119Sbill done(0); 205*1119Sbill } 206*1119Sbill 207*1119Sbill usage() 208*1119Sbill { 209*1119Sbill fprintf(stderr, "tar: usage tar -{txru}[cvfblm] [tapefile] [blocksize] file1 file2...\n"); 210*1119Sbill done(1); 211*1119Sbill } 212*1119Sbill 213*1119Sbill dorep(argv) 214*1119Sbill char *argv[]; 215*1119Sbill { 216*1119Sbill register char *cp, *cp2; 217*1119Sbill char wdir[60]; 218*1119Sbill 219*1119Sbill if (!cflag) { 220*1119Sbill getdir(); 221*1119Sbill do { 222*1119Sbill passtape(); 223*1119Sbill if (term) 224*1119Sbill done(0); 225*1119Sbill getdir(); 226*1119Sbill } while (!endtape()); 227*1119Sbill if (tfile != NULL) { 228*1119Sbill char buf[200]; 229*1119Sbill 230*1119Sbill strcat(buf, "sort +0 -1 +1nr "); 231*1119Sbill strcat(buf, tname); 232*1119Sbill strcat(buf, " -o "); 233*1119Sbill strcat(buf, tname); 234*1119Sbill sprintf(buf, "sort +0 -1 +1nr %s -o %s; awk '$1 != prev {print; prev=$1}' %s >%sX;mv %sX %s", 235*1119Sbill tname, tname, tname, tname, tname, tname); 236*1119Sbill fflush(tfile); 237*1119Sbill system(buf); 238*1119Sbill freopen(tname, "r", tfile); 239*1119Sbill fstat(fileno(tfile), &stbuf); 240*1119Sbill high = stbuf.st_size; 241*1119Sbill } 242*1119Sbill } 243*1119Sbill 244*1119Sbill getwdir(wdir); 245*1119Sbill while (*argv && ! term) { 246*1119Sbill cp2 = *argv; 247*1119Sbill if (!strcmp(cp2, "-C") && argv[1]) { 248*1119Sbill argv++; 249*1119Sbill if (chdir(*argv) < 0) 250*1119Sbill perror(*argv); 251*1119Sbill else 252*1119Sbill getwdir(wdir); 253*1119Sbill argv++; 254*1119Sbill continue; 255*1119Sbill } 256*1119Sbill for (cp = *argv; *cp; cp++) 257*1119Sbill if (*cp == '/') 258*1119Sbill cp2 = cp; 259*1119Sbill if (cp2 != *argv) { 260*1119Sbill *cp2 = '\0'; 261*1119Sbill chdir(*argv); 262*1119Sbill *cp2 = '/'; 263*1119Sbill cp2++; 264*1119Sbill } 265*1119Sbill putfile(*argv++, cp2); 266*1119Sbill chdir(wdir); 267*1119Sbill } 268*1119Sbill putempty(); 269*1119Sbill putempty(); 270*1119Sbill flushtape(); 271*1119Sbill if (linkerrok == 1) 272*1119Sbill for (; ihead != NULL; ihead = ihead->nextp) 273*1119Sbill if (ihead->count != 0) 274*1119Sbill fprintf(stderr, "Missing links to %s\n", ihead->pathname); 275*1119Sbill } 276*1119Sbill 277*1119Sbill endtape() 278*1119Sbill { 279*1119Sbill if (dblock.dbuf.name[0] == '\0') { 280*1119Sbill backtape(); 281*1119Sbill return(1); 282*1119Sbill } 283*1119Sbill else 284*1119Sbill return(0); 285*1119Sbill } 286*1119Sbill 287*1119Sbill getdir() 288*1119Sbill { 289*1119Sbill register struct stat *sp; 290*1119Sbill int i; 291*1119Sbill 292*1119Sbill readtape( (char *) &dblock); 293*1119Sbill if (dblock.dbuf.name[0] == '\0') 294*1119Sbill return; 295*1119Sbill sp = &stbuf; 296*1119Sbill sscanf(dblock.dbuf.mode, "%o", &i); 297*1119Sbill sp->st_mode = i; 298*1119Sbill sscanf(dblock.dbuf.uid, "%o", &i); 299*1119Sbill sp->st_uid = i; 300*1119Sbill sscanf(dblock.dbuf.gid, "%o", &i); 301*1119Sbill sp->st_gid = i; 302*1119Sbill sscanf(dblock.dbuf.size, "%lo", &sp->st_size); 303*1119Sbill sscanf(dblock.dbuf.mtime, "%lo", &sp->st_mtime); 304*1119Sbill sscanf(dblock.dbuf.chksum, "%o", &chksum); 305*1119Sbill if (chksum != checksum()) { 306*1119Sbill fprintf(stderr, "directory checksum error\n"); 307*1119Sbill done(2); 308*1119Sbill } 309*1119Sbill if (tfile != NULL) 310*1119Sbill fprintf(tfile, "%s %s\n", dblock.dbuf.name, dblock.dbuf.mtime); 311*1119Sbill } 312*1119Sbill 313*1119Sbill passtape() 314*1119Sbill { 315*1119Sbill long blocks; 316*1119Sbill char buf[TBLOCK]; 317*1119Sbill 318*1119Sbill if (dblock.dbuf.linkflag == '1') 319*1119Sbill return; 320*1119Sbill blocks = stbuf.st_size; 321*1119Sbill blocks += TBLOCK-1; 322*1119Sbill blocks /= TBLOCK; 323*1119Sbill 324*1119Sbill while (blocks-- > 0) 325*1119Sbill readtape(buf); 326*1119Sbill } 327*1119Sbill 328*1119Sbill putfile(longname, shortname) 329*1119Sbill char *longname; 330*1119Sbill char *shortname; 331*1119Sbill { 332*1119Sbill int infile; 333*1119Sbill long blocks; 334*1119Sbill char buf[TBLOCK]; 335*1119Sbill register char *cp, *cp2; 336*1119Sbill struct direct dbuf; 337*1119Sbill int i, j; 338*1119Sbill 339*1119Sbill infile = open(shortname, 0); 340*1119Sbill if (infile < 0) { 341*1119Sbill fprintf(stderr, "tar: %s: cannot open file\n", longname); 342*1119Sbill return; 343*1119Sbill } 344*1119Sbill 345*1119Sbill fstat(infile, &stbuf); 346*1119Sbill 347*1119Sbill if (tfile != NULL && checkupdate(longname) == 0) { 348*1119Sbill close(infile); 349*1119Sbill return; 350*1119Sbill } 351*1119Sbill if (checkw('r', longname) == 0) { 352*1119Sbill close(infile); 353*1119Sbill return; 354*1119Sbill } 355*1119Sbill 356*1119Sbill if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { 357*1119Sbill for (i = 0, cp = buf; *cp++ = longname[i++];); 358*1119Sbill *--cp = '/'; 359*1119Sbill *++cp = 0 ; 360*1119Sbill i = 0; 361*1119Sbill if (!oflag) { 362*1119Sbill if( (cp - buf) >= NAMSIZ) { 363*1119Sbill fprintf(stderr, "%s: file name too long\n", longname); 364*1119Sbill close(infile); 365*1119Sbill return; 366*1119Sbill } 367*1119Sbill stbuf.st_size = 0; 368*1119Sbill tomodes(&stbuf); 369*1119Sbill strcpy(dblock.dbuf.name,buf); 370*1119Sbill sprintf(dblock.dbuf.chksum, "%6o", checksum()); 371*1119Sbill writetape( (char *) &dblock); 372*1119Sbill } 373*1119Sbill chdir(shortname); 374*1119Sbill while (read(infile, (char *)&dbuf, sizeof(dbuf)) > 0 && !term) { 375*1119Sbill if (dbuf.d_ino == 0) { 376*1119Sbill i++; 377*1119Sbill continue; 378*1119Sbill } 379*1119Sbill if (strcmp(".", dbuf.d_name) == 0 || strcmp("..", dbuf.d_name) == 0) { 380*1119Sbill i++; 381*1119Sbill continue; 382*1119Sbill } 383*1119Sbill cp2 = cp; 384*1119Sbill for (j=0; j < DIRSIZ; j++) 385*1119Sbill *cp2++ = dbuf.d_name[j]; 386*1119Sbill *cp2 = '\0'; 387*1119Sbill close(infile); 388*1119Sbill putfile(buf, cp); 389*1119Sbill infile = open(".", 0); 390*1119Sbill i++; 391*1119Sbill lseek(infile, (long) (sizeof(dbuf) * i), 0); 392*1119Sbill } 393*1119Sbill close(infile); 394*1119Sbill chdir(".."); 395*1119Sbill return; 396*1119Sbill } 397*1119Sbill if ((stbuf.st_mode & S_IFMT) != S_IFREG) { 398*1119Sbill fprintf(stderr, "tar: %s is not a file. Not dumped\n", longname); 399*1119Sbill return; 400*1119Sbill } 401*1119Sbill 402*1119Sbill tomodes(&stbuf); 403*1119Sbill 404*1119Sbill cp2 = longname; 405*1119Sbill for (cp = dblock.dbuf.name, i=0; (*cp++ = *cp2++) && i < NAMSIZ; i++); 406*1119Sbill if (i >= NAMSIZ) { 407*1119Sbill fprintf(stderr, "%s: file name too long\n", longname); 408*1119Sbill close(infile); 409*1119Sbill return; 410*1119Sbill } 411*1119Sbill 412*1119Sbill if (stbuf.st_nlink > 1) { 413*1119Sbill struct linkbuf *lp; 414*1119Sbill int found = 0; 415*1119Sbill 416*1119Sbill for (lp = ihead; lp != NULL; lp = lp->nextp) { 417*1119Sbill if (lp->inum == stbuf.st_ino && lp->devnum == stbuf.st_dev) { 418*1119Sbill found++; 419*1119Sbill break; 420*1119Sbill } 421*1119Sbill } 422*1119Sbill if (found) { 423*1119Sbill strcpy(dblock.dbuf.linkname, lp->pathname); 424*1119Sbill dblock.dbuf.linkflag = '1'; 425*1119Sbill sprintf(dblock.dbuf.chksum, "%6o", checksum()); 426*1119Sbill writetape( (char *) &dblock); 427*1119Sbill if (vflag) { 428*1119Sbill fprintf(stderr, "a %s ", longname); 429*1119Sbill fprintf(stderr, "link to %s\n", lp->pathname); 430*1119Sbill } 431*1119Sbill lp->count--; 432*1119Sbill close(infile); 433*1119Sbill return; 434*1119Sbill } 435*1119Sbill else { 436*1119Sbill lp = (struct linkbuf *) malloc(sizeof(*lp)); 437*1119Sbill if (lp == NULL) { 438*1119Sbill if (freemem) { 439*1119Sbill fprintf(stderr, "Out of memory. Link information lost\n"); 440*1119Sbill freemem = 0; 441*1119Sbill } 442*1119Sbill } 443*1119Sbill else { 444*1119Sbill lp->nextp = ihead; 445*1119Sbill ihead = lp; 446*1119Sbill lp->inum = stbuf.st_ino; 447*1119Sbill lp->devnum = stbuf.st_dev; 448*1119Sbill lp->count = stbuf.st_nlink - 1; 449*1119Sbill strcpy(lp->pathname, longname); 450*1119Sbill } 451*1119Sbill } 452*1119Sbill } 453*1119Sbill 454*1119Sbill blocks = (stbuf.st_size + (TBLOCK-1)) / TBLOCK; 455*1119Sbill if (vflag) { 456*1119Sbill fprintf(stderr, "a %s ", longname); 457*1119Sbill fprintf(stderr, "%ld blocks\n", blocks); 458*1119Sbill } 459*1119Sbill sprintf(dblock.dbuf.chksum, "%6o", checksum()); 460*1119Sbill writetape( (char *) &dblock); 461*1119Sbill 462*1119Sbill while ((i = read(infile, buf, TBLOCK)) > 0 && blocks > 0) { 463*1119Sbill writetape(buf); 464*1119Sbill blocks--; 465*1119Sbill } 466*1119Sbill close(infile); 467*1119Sbill if (blocks != 0 || i != 0) 468*1119Sbill fprintf(stderr, "%s: file changed size\n", longname); 469*1119Sbill while (blocks-- > 0) 470*1119Sbill putempty(); 471*1119Sbill } 472*1119Sbill 473*1119Sbill 474*1119Sbill 475*1119Sbill doxtract(argv) 476*1119Sbill char *argv[]; 477*1119Sbill { 478*1119Sbill long blocks, bytes; 479*1119Sbill char buf[TBLOCK]; 480*1119Sbill char **cp; 481*1119Sbill int ofile; 482*1119Sbill 483*1119Sbill for (;;) { 484*1119Sbill getdir(); 485*1119Sbill if (endtape()) 486*1119Sbill break; 487*1119Sbill 488*1119Sbill if (*argv == 0) 489*1119Sbill goto gotit; 490*1119Sbill 491*1119Sbill for (cp = argv; *cp; cp++) 492*1119Sbill if (prefix(*cp, dblock.dbuf.name)) 493*1119Sbill goto gotit; 494*1119Sbill passtape(); 495*1119Sbill continue; 496*1119Sbill 497*1119Sbill gotit: 498*1119Sbill if (checkw('x', dblock.dbuf.name) == 0) { 499*1119Sbill passtape(); 500*1119Sbill continue; 501*1119Sbill } 502*1119Sbill 503*1119Sbill if(checkdir(dblock.dbuf.name)) 504*1119Sbill continue; 505*1119Sbill 506*1119Sbill if (dblock.dbuf.linkflag == '1') { 507*1119Sbill unlink(dblock.dbuf.name); 508*1119Sbill if (link(dblock.dbuf.linkname, dblock.dbuf.name) < 0) { 509*1119Sbill fprintf(stderr, "%s: cannot link\n", dblock.dbuf.name); 510*1119Sbill continue; 511*1119Sbill } 512*1119Sbill if (vflag) 513*1119Sbill fprintf(stderr, "%s linked to %s\n", dblock.dbuf.name, dblock.dbuf.linkname); 514*1119Sbill continue; 515*1119Sbill } 516*1119Sbill if ((ofile = creat(dblock.dbuf.name, stbuf.st_mode & 07777)) < 0) { 517*1119Sbill fprintf(stderr, "tar: %s - cannot create\n", dblock.dbuf.name); 518*1119Sbill passtape(); 519*1119Sbill continue; 520*1119Sbill } 521*1119Sbill 522*1119Sbill blocks = ((bytes = stbuf.st_size) + TBLOCK-1)/TBLOCK; 523*1119Sbill if (vflag) 524*1119Sbill fprintf(stderr, "x %s, %ld bytes, %ld tape blocks\n", dblock.dbuf.name, bytes, blocks); 525*1119Sbill while (blocks-- > 0) { 526*1119Sbill readtape(buf); 527*1119Sbill if (bytes > TBLOCK) { 528*1119Sbill if (write(ofile, buf, TBLOCK) < 0) { 529*1119Sbill fprintf(stderr, "tar: %s: HELP - extract write error\n", dblock.dbuf.name); 530*1119Sbill done(2); 531*1119Sbill } 532*1119Sbill } else 533*1119Sbill if (write(ofile, buf, (int) bytes) < 0) { 534*1119Sbill fprintf(stderr, "tar: %s: HELP - extract write error\n", dblock.dbuf.name); 535*1119Sbill done(2); 536*1119Sbill } 537*1119Sbill bytes -= TBLOCK; 538*1119Sbill } 539*1119Sbill close(ofile); 540*1119Sbill if (mflag == 0) { 541*1119Sbill time_t timep[2]; 542*1119Sbill 543*1119Sbill timep[0] = time(NULL); 544*1119Sbill timep[1] = stbuf.st_mtime; 545*1119Sbill utime(dblock.dbuf.name, timep); 546*1119Sbill } 547*1119Sbill if(pflag) { 548*1119Sbill chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid); 549*1119Sbill chmod(dblock.dbuf.name, stbuf.st_mode & 07777); 550*1119Sbill } 551*1119Sbill } 552*1119Sbill } 553*1119Sbill 554*1119Sbill dotable() 555*1119Sbill { 556*1119Sbill for (;;) { 557*1119Sbill getdir(); 558*1119Sbill if (endtape()) 559*1119Sbill break; 560*1119Sbill if (vflag) 561*1119Sbill longt(&stbuf); 562*1119Sbill printf("%s", dblock.dbuf.name); 563*1119Sbill if (dblock.dbuf.linkflag == '1') 564*1119Sbill printf(" linked to %s", dblock.dbuf.linkname); 565*1119Sbill printf("\n"); 566*1119Sbill passtape(); 567*1119Sbill } 568*1119Sbill } 569*1119Sbill 570*1119Sbill putempty() 571*1119Sbill { 572*1119Sbill char buf[TBLOCK]; 573*1119Sbill char *cp; 574*1119Sbill 575*1119Sbill for (cp = buf; cp < &buf[TBLOCK]; ) 576*1119Sbill *cp++ = '\0'; 577*1119Sbill writetape(buf); 578*1119Sbill } 579*1119Sbill 580*1119Sbill longt(st) 581*1119Sbill register struct stat *st; 582*1119Sbill { 583*1119Sbill register char *cp; 584*1119Sbill char *ctime(); 585*1119Sbill 586*1119Sbill pmode(st); 587*1119Sbill printf("%3d/%1d", st->st_uid, st->st_gid); 588*1119Sbill printf("%7D", st->st_size); 589*1119Sbill cp = ctime(&st->st_mtime); 590*1119Sbill printf(" %-12.12s %-4.4s ", cp+4, cp+20); 591*1119Sbill } 592*1119Sbill 593*1119Sbill #define SUID 04000 594*1119Sbill #define SGID 02000 595*1119Sbill #define ROWN 0400 596*1119Sbill #define WOWN 0200 597*1119Sbill #define XOWN 0100 598*1119Sbill #define RGRP 040 599*1119Sbill #define WGRP 020 600*1119Sbill #define XGRP 010 601*1119Sbill #define ROTH 04 602*1119Sbill #define WOTH 02 603*1119Sbill #define XOTH 01 604*1119Sbill #define STXT 01000 605*1119Sbill int m1[] = { 1, ROWN, 'r', '-' }; 606*1119Sbill int m2[] = { 1, WOWN, 'w', '-' }; 607*1119Sbill int m3[] = { 2, SUID, 's', XOWN, 'x', '-' }; 608*1119Sbill int m4[] = { 1, RGRP, 'r', '-' }; 609*1119Sbill int m5[] = { 1, WGRP, 'w', '-' }; 610*1119Sbill int m6[] = { 2, SGID, 's', XGRP, 'x', '-' }; 611*1119Sbill int m7[] = { 1, ROTH, 'r', '-' }; 612*1119Sbill int m8[] = { 1, WOTH, 'w', '-' }; 613*1119Sbill int m9[] = { 2, STXT, 't', XOTH, 'x', '-' }; 614*1119Sbill 615*1119Sbill int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9}; 616*1119Sbill 617*1119Sbill pmode(st) 618*1119Sbill register struct stat *st; 619*1119Sbill { 620*1119Sbill register int **mp; 621*1119Sbill 622*1119Sbill for (mp = &m[0]; mp < &m[9];) 623*1119Sbill select(*mp++, st); 624*1119Sbill } 625*1119Sbill 626*1119Sbill select(pairp, st) 627*1119Sbill int *pairp; 628*1119Sbill struct stat *st; 629*1119Sbill { 630*1119Sbill register int n, *ap; 631*1119Sbill 632*1119Sbill ap = pairp; 633*1119Sbill n = *ap++; 634*1119Sbill while (--n>=0 && (st->st_mode&*ap++)==0) 635*1119Sbill ap++; 636*1119Sbill printf("%c", *ap); 637*1119Sbill } 638*1119Sbill 639*1119Sbill checkdir(name) 640*1119Sbill register char *name; 641*1119Sbill { 642*1119Sbill register char *cp; 643*1119Sbill int i; 644*1119Sbill for (cp = name; *cp; cp++) { 645*1119Sbill if (*cp == '/') { 646*1119Sbill *cp = '\0'; 647*1119Sbill if (access(name, 01) < 0) { 648*1119Sbill register int pid, rp; 649*1119Sbill 650*1119Sbill if ((pid = fork()) == 0) { 651*1119Sbill execl("/bin/mkdir", "mkdir", name, 0); 652*1119Sbill execl("/usr/bin/mkdir", "mkdir", name, 0); 653*1119Sbill fprintf(stderr, "tar: cannot find mkdir!\n"); 654*1119Sbill done(0); 655*1119Sbill } 656*1119Sbill while ((rp = wait(&i)) >= 0 && rp != pid) 657*1119Sbill ; 658*1119Sbill if(pflag) { 659*1119Sbill chown(name, stbuf.st_uid, stbuf.st_gid); 660*1119Sbill chmod(dblock.dbuf.name, stbuf.st_mode & 0777); 661*1119Sbill } 662*1119Sbill } 663*1119Sbill *cp = '/'; 664*1119Sbill } 665*1119Sbill } 666*1119Sbill return(cp[-1]=='/'); 667*1119Sbill } 668*1119Sbill 669*1119Sbill onintr() 670*1119Sbill { 671*1119Sbill signal(SIGINT, SIG_IGN); 672*1119Sbill term++; 673*1119Sbill } 674*1119Sbill 675*1119Sbill onquit() 676*1119Sbill { 677*1119Sbill signal(SIGQUIT, SIG_IGN); 678*1119Sbill term++; 679*1119Sbill } 680*1119Sbill 681*1119Sbill onhup() 682*1119Sbill { 683*1119Sbill signal(SIGHUP, SIG_IGN); 684*1119Sbill term++; 685*1119Sbill } 686*1119Sbill 687*1119Sbill onterm() 688*1119Sbill { 689*1119Sbill signal(SIGTERM, SIG_IGN); 690*1119Sbill term++; 691*1119Sbill } 692*1119Sbill 693*1119Sbill tomodes(sp) 694*1119Sbill register struct stat *sp; 695*1119Sbill { 696*1119Sbill register char *cp; 697*1119Sbill 698*1119Sbill for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++) 699*1119Sbill *cp = '\0'; 700*1119Sbill sprintf(dblock.dbuf.mode, "%6o ", sp->st_mode & 07777); 701*1119Sbill sprintf(dblock.dbuf.uid, "%6o ", sp->st_uid); 702*1119Sbill sprintf(dblock.dbuf.gid, "%6o ", sp->st_gid); 703*1119Sbill sprintf(dblock.dbuf.size, "%11lo ", sp->st_size); 704*1119Sbill sprintf(dblock.dbuf.mtime, "%11lo ", sp->st_mtime); 705*1119Sbill } 706*1119Sbill 707*1119Sbill checksum() 708*1119Sbill { 709*1119Sbill register i; 710*1119Sbill register char *cp; 711*1119Sbill 712*1119Sbill for (cp = dblock.dbuf.chksum; cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)]; cp++) 713*1119Sbill *cp = ' '; 714*1119Sbill i = 0; 715*1119Sbill for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++) 716*1119Sbill i += *cp; 717*1119Sbill return(i); 718*1119Sbill } 719*1119Sbill 720*1119Sbill checkw(c, name) 721*1119Sbill char *name; 722*1119Sbill { 723*1119Sbill if (wflag) { 724*1119Sbill printf("%c ", c); 725*1119Sbill if (vflag) 726*1119Sbill longt(&stbuf); 727*1119Sbill printf("%s: ", name); 728*1119Sbill if (response() == 'y'){ 729*1119Sbill return(1); 730*1119Sbill } 731*1119Sbill return(0); 732*1119Sbill } 733*1119Sbill return(1); 734*1119Sbill } 735*1119Sbill 736*1119Sbill response() 737*1119Sbill { 738*1119Sbill char c; 739*1119Sbill 740*1119Sbill c = getchar(); 741*1119Sbill if (c != '\n') 742*1119Sbill while (getchar() != '\n'); 743*1119Sbill else c = 'n'; 744*1119Sbill return(c); 745*1119Sbill } 746*1119Sbill 747*1119Sbill checkupdate(arg) 748*1119Sbill char *arg; 749*1119Sbill { 750*1119Sbill char name[100]; 751*1119Sbill long mtime; 752*1119Sbill daddr_t seekp; 753*1119Sbill daddr_t lookup(); 754*1119Sbill 755*1119Sbill rewind(tfile); 756*1119Sbill for (;;) { 757*1119Sbill if ((seekp = lookup(arg)) < 0) 758*1119Sbill return(1); 759*1119Sbill fseek(tfile, seekp, 0); 760*1119Sbill fscanf(tfile, "%s %lo", name, &mtime); 761*1119Sbill if (stbuf.st_mtime > mtime) 762*1119Sbill return(1); 763*1119Sbill else 764*1119Sbill return(0); 765*1119Sbill } 766*1119Sbill } 767*1119Sbill 768*1119Sbill done(n) 769*1119Sbill { 770*1119Sbill unlink(tname); 771*1119Sbill exit(n); 772*1119Sbill } 773*1119Sbill 774*1119Sbill prefix(s1, s2) 775*1119Sbill register char *s1, *s2; 776*1119Sbill { 777*1119Sbill while (*s1) 778*1119Sbill if (*s1++ != *s2++) 779*1119Sbill return(0); 780*1119Sbill if (*s2) 781*1119Sbill return(*s2 == '/'); 782*1119Sbill return(1); 783*1119Sbill } 784*1119Sbill 785*1119Sbill getwdir(s) 786*1119Sbill char *s; 787*1119Sbill { 788*1119Sbill int i; 789*1119Sbill int pipdes[2]; 790*1119Sbill 791*1119Sbill pipe(pipdes); 792*1119Sbill if ((i = fork()) == 0) { 793*1119Sbill close(1); 794*1119Sbill dup(pipdes[1]); 795*1119Sbill execl("/bin/pwd", "pwd", 0); 796*1119Sbill execl("/usr/bin/pwd", "pwd", 0); 797*1119Sbill fprintf(stderr, "pwd failed!\n"); 798*1119Sbill printf("/\n"); 799*1119Sbill exit(1); 800*1119Sbill } 801*1119Sbill while (wait((int *)NULL) != -1) 802*1119Sbill ; 803*1119Sbill read(pipdes[0], s, 50); 804*1119Sbill while(*s != '\n') 805*1119Sbill s++; 806*1119Sbill *s = '\0'; 807*1119Sbill close(pipdes[0]); 808*1119Sbill close(pipdes[1]); 809*1119Sbill } 810*1119Sbill 811*1119Sbill #define N 200 812*1119Sbill int njab; 813*1119Sbill daddr_t 814*1119Sbill lookup(s) 815*1119Sbill char *s; 816*1119Sbill { 817*1119Sbill register i; 818*1119Sbill daddr_t a; 819*1119Sbill 820*1119Sbill for(i=0; s[i]; i++) 821*1119Sbill if(s[i] == ' ') 822*1119Sbill break; 823*1119Sbill a = bsrch(s, i, low, high); 824*1119Sbill return(a); 825*1119Sbill } 826*1119Sbill 827*1119Sbill daddr_t 828*1119Sbill bsrch(s, n, l, h) 829*1119Sbill daddr_t l, h; 830*1119Sbill char *s; 831*1119Sbill { 832*1119Sbill register i, j; 833*1119Sbill char b[N]; 834*1119Sbill daddr_t m, m1; 835*1119Sbill 836*1119Sbill njab = 0; 837*1119Sbill 838*1119Sbill loop: 839*1119Sbill if(l >= h) 840*1119Sbill return(-1L); 841*1119Sbill m = l + (h-l)/2 - N/2; 842*1119Sbill if(m < l) 843*1119Sbill m = l; 844*1119Sbill fseek(tfile, m, 0); 845*1119Sbill fread(b, 1, N, tfile); 846*1119Sbill njab++; 847*1119Sbill for(i=0; i<N; i++) { 848*1119Sbill if(b[i] == '\n') 849*1119Sbill break; 850*1119Sbill m++; 851*1119Sbill } 852*1119Sbill if(m >= h) 853*1119Sbill return(-1L); 854*1119Sbill m1 = m; 855*1119Sbill j = i; 856*1119Sbill for(i++; i<N; i++) { 857*1119Sbill m1++; 858*1119Sbill if(b[i] == '\n') 859*1119Sbill break; 860*1119Sbill } 861*1119Sbill i = cmp(b+j, s, n); 862*1119Sbill if(i < 0) { 863*1119Sbill h = m; 864*1119Sbill goto loop; 865*1119Sbill } 866*1119Sbill if(i > 0) { 867*1119Sbill l = m1; 868*1119Sbill goto loop; 869*1119Sbill } 870*1119Sbill return(m); 871*1119Sbill } 872*1119Sbill 873*1119Sbill cmp(b, s, n) 874*1119Sbill char *b, *s; 875*1119Sbill { 876*1119Sbill register i; 877*1119Sbill 878*1119Sbill if(b[0] != '\n') 879*1119Sbill exit(2); 880*1119Sbill for(i=0; i<n; i++) { 881*1119Sbill if(b[i+1] > s[i]) 882*1119Sbill return(-1); 883*1119Sbill if(b[i+1] < s[i]) 884*1119Sbill return(1); 885*1119Sbill } 886*1119Sbill return(b[i+1] == ' '? 0 : -1); 887*1119Sbill } 888*1119Sbill 889*1119Sbill readtape(buffer) 890*1119Sbill char *buffer; 891*1119Sbill { 892*1119Sbill int i, j; 893*1119Sbill 894*1119Sbill if (recno >= nblock || first == 0) { 895*1119Sbill if (first == 0 && nblock == 0) 896*1119Sbill j = fflag ? NBLOCK : 1; /* orignally, NBLOCK; */ 897*1119Sbill else 898*1119Sbill j = nblock; 899*1119Sbill if ((i = read(mt, tbuf, TBLOCK*j)) < 0) { 900*1119Sbill fprintf(stderr, "Tar: tape read error\n"); 901*1119Sbill done(3); 902*1119Sbill } 903*1119Sbill if (first == 0) { 904*1119Sbill if ((i % TBLOCK) != 0) { 905*1119Sbill fprintf(stderr, "Tar: tape blocksize error\n"); 906*1119Sbill done(3); 907*1119Sbill } 908*1119Sbill i /= TBLOCK; 909*1119Sbill if (rflag && i != 1) { 910*1119Sbill fprintf(stderr, "Tar: Cannot update blocked tapes (yet)\n"); 911*1119Sbill done(4); 912*1119Sbill } 913*1119Sbill if (i != nblock && (i != 1 || nblock == 0)) { 914*1119Sbill fprintf(stderr, "Tar: blocksize = %d\n", i); 915*1119Sbill nblock = i; 916*1119Sbill } 917*1119Sbill } 918*1119Sbill recno = 0; 919*1119Sbill } 920*1119Sbill first = 1; 921*1119Sbill copy(buffer, &tbuf[recno++]); 922*1119Sbill return(TBLOCK); 923*1119Sbill } 924*1119Sbill 925*1119Sbill writetape(buffer) 926*1119Sbill char *buffer; 927*1119Sbill { 928*1119Sbill first = 1; 929*1119Sbill if (nblock == 0) 930*1119Sbill nblock = 1; 931*1119Sbill if (recno >= nblock) { 932*1119Sbill if (write(mt, tbuf, TBLOCK*nblock) < 0) { 933*1119Sbill fprintf(stderr, "Tar: tape write error\n"); 934*1119Sbill done(2); 935*1119Sbill } 936*1119Sbill recno = 0; 937*1119Sbill } 938*1119Sbill copy(&tbuf[recno++], buffer); 939*1119Sbill if (recno >= nblock) { 940*1119Sbill if (write(mt, tbuf, TBLOCK*nblock) < 0) { 941*1119Sbill fprintf(stderr, "Tar: tape write error\n"); 942*1119Sbill done(2); 943*1119Sbill } 944*1119Sbill recno = 0; 945*1119Sbill } 946*1119Sbill return(TBLOCK); 947*1119Sbill } 948*1119Sbill 949*1119Sbill backtape() 950*1119Sbill { 951*1119Sbill lseek(mt, (long) -TBLOCK, 1); 952*1119Sbill if (recno >= nblock) { 953*1119Sbill recno = nblock - 1; 954*1119Sbill if (read(mt, tbuf, TBLOCK*nblock) < 0) { 955*1119Sbill fprintf(stderr, "Tar: tape read error after seek\n"); 956*1119Sbill done(4); 957*1119Sbill } 958*1119Sbill lseek(mt, (long) -TBLOCK, 1); 959*1119Sbill } 960*1119Sbill } 961*1119Sbill 962*1119Sbill flushtape() 963*1119Sbill { 964*1119Sbill write(mt, tbuf, TBLOCK*nblock); 965*1119Sbill } 966*1119Sbill 967*1119Sbill copy(to, from) 968*1119Sbill register char *to, *from; 969*1119Sbill { 970*1119Sbill register i; 971*1119Sbill 972*1119Sbill i = TBLOCK; 973*1119Sbill do { 974*1119Sbill *to++ = *from++; 975*1119Sbill } while (--i); 976*1119Sbill } 977