1*33828Sbostic /* Copyright (c) 1988 AT&T */ 2*33828Sbostic /* All Rights Reserved */ 3*33828Sbostic 4*33828Sbostic /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */ 5*33828Sbostic /* The copyright notice above does not evidence any */ 6*33828Sbostic /* actual or intended publication of such source code. */ 7*33828Sbostic 8*33828Sbostic #ident "@(#)cpio:cpio.c 1.30.1.11" 9*33828Sbostic /* /sccs/src/cmd/s.cpio.c 10*33828Sbostic cpio.c 1.30.1.11 1/11/86 13:46:48 11*33828Sbostic Reworked cpio which uses getopt(3) to interpret flag arguments and 12*33828Sbostic changes reels to the save file name. 13*33828Sbostic Performance and size improvements. 14*33828Sbostic */ 15*33828Sbostic 16*33828Sbostic /* cpio COMPILE: cc -O cpio.c -s -i -o cpio -lgen -lerr 17*33828Sbostic cpio -- copy file collections 18*33828Sbostic 19*33828Sbostic */ 20*33828Sbostic #include "errmsg.h" 21*33828Sbostic #include <errno.h> 22*33828Sbostic #include <fcntl.h> 23*33828Sbostic #include <memory.h> 24*33828Sbostic #include <stdio.h> 25*33828Sbostic #include <string.h> 26*33828Sbostic #include <signal.h> 27*33828Sbostic #include <varargs.h> 28*33828Sbostic #include <sys/stat.h> 29*33828Sbostic 30*33828Sbostic #define EQ(x,y) (strcmp(x,y)==0) 31*33828Sbostic 32*33828Sbostic /* MKSHORT: for VAX, Interdata, ... */ 33*33828Sbostic /* Take a 4-byte long, lv, and turn it */ 34*33828Sbostic /* into an array of two 2-byte shorts, v*/ 35*33828Sbostic #define MKSHORT(v,lv) {U.l=1L;if(U.c[0]) U.l=lv,v[0]=U.s[1],v[1]=U.s[0]; else U.l=lv,v[0]=U.s[0],v[1]=U.s[1];} 36*33828Sbostic 37*33828Sbostic #define MAGIC 070707 /* cpio magic number */ 38*33828Sbostic #define IN 'i' /* copy in */ 39*33828Sbostic #define OUT 'o' /* copy out */ 40*33828Sbostic #define PASS 'p' /* direct copy */ 41*33828Sbostic #define HDRSIZE (Hdr.h_name - (char *)&Hdr) /* header size minus filename field */ 42*33828Sbostic #define LINKS 500 /* no. of links allocated per bunch */ 43*33828Sbostic #define CHARS 76 /* ASCII header size minus filename field */ 44*33828Sbostic #define BUFSIZE 512 /* In u370, can't use BUFSIZ or BSIZE */ 45*33828Sbostic #define CPIOBSZ 4096 /* file read/write */ 46*33828Sbostic #define MK_USHORT(a) (a & 00000177777) /* Make unsigned shorts for portable */ 47*33828Sbostic /* header. Hardware may only know */ 48*33828Sbostic /* integer operations and sign extend */ 49*33828Sbostic /* the large unsigned short resulting */ 50*33828Sbostic /* in 8 rather than 6 octal char in */ 51*33828Sbostic /* the header. */ 52*33828Sbostic 53*33828Sbostic static struct stat Statb, Xstatb; 54*33828Sbostic 55*33828Sbostic /* Cpio header format */ 56*33828Sbostic static struct header { 57*33828Sbostic short h_magic; 58*33828Sbostic short h_dev; 59*33828Sbostic ushort h_ino; 60*33828Sbostic ushort h_mode, 61*33828Sbostic h_uid, 62*33828Sbostic h_gid; 63*33828Sbostic short h_nlink; 64*33828Sbostic short h_rdev; 65*33828Sbostic short h_mtime[2], 66*33828Sbostic h_namesize, 67*33828Sbostic h_filesize[2]; 68*33828Sbostic char h_name[256]; 69*33828Sbostic } Hdr; 70*33828Sbostic 71*33828Sbostic static unsigned Bufsize = BUFSIZE; /* default record size */ 72*33828Sbostic static char Buf[CPIOBSZ], *Cbuf; 73*33828Sbostic static char *Cp; 74*33828Sbostic 75*33828Sbostic 76*33828Sbostic static 77*33828Sbostic short Option, 78*33828Sbostic Dir, 79*33828Sbostic Uncond, 80*33828Sbostic PassLink, 81*33828Sbostic Rename, 82*33828Sbostic Toc, 83*33828Sbostic Verbose, 84*33828Sbostic Mod_time, 85*33828Sbostic Acc_time, 86*33828Sbostic Cflag, 87*33828Sbostic fflag, 88*33828Sbostic Swap, 89*33828Sbostic byteswap, 90*33828Sbostic bothswap, 91*33828Sbostic halfswap; 92*33828Sbostic 93*33828Sbostic static 94*33828Sbostic int Ifile, 95*33828Sbostic Ofile, 96*33828Sbostic Input = 0, 97*33828Sbostic Output = 1; 98*33828Sbostic /* sBlocks: short Blocks. Cumulative character */ 99*33828Sbostic /* count for short reads in bread(). Encountered */ 100*33828Sbostic /* with communication lines and pipes as in: */ 101*33828Sbostic /* split -100 cpio_archive; cat xa* | cpio -icd */ 102*33828Sbostic static 103*33828Sbostic long sBlocks, 104*33828Sbostic Blocks, 105*33828Sbostic Longfile, 106*33828Sbostic Longtime; 107*33828Sbostic 108*33828Sbostic static 109*33828Sbostic char Fullname[256], 110*33828Sbostic Name[256]; 111*33828Sbostic static 112*33828Sbostic int Pathend; 113*33828Sbostic static 114*33828Sbostic char *swfile; 115*33828Sbostic static 116*33828Sbostic char *eommsg = "Change to part %d and press RETURN key. [q] "; 117*33828Sbostic 118*33828Sbostic static 119*33828Sbostic FILE *Rtty, 120*33828Sbostic *Wtty; 121*33828Sbostic static 122*33828Sbostic char ttyname[] = "/dev/tty"; 123*33828Sbostic 124*33828Sbostic static 125*33828Sbostic char **Pattern = 0; 126*33828Sbostic static 127*33828Sbostic char Chdr[500]; 128*33828Sbostic static 129*33828Sbostic short Dev; 130*33828Sbostic ushort Uid, 131*33828Sbostic A_directory, 132*33828Sbostic A_special, 133*33828Sbostic Filetype = S_IFMT; 134*33828Sbostic 135*33828Sbostic extern errno; 136*33828Sbostic extern void exit(); 137*33828Sbostic extern char *sys_errlist[]; 138*33828Sbostic char *malloc(); 139*33828Sbostic FILE *popen(); 140*33828Sbostic 141*33828Sbostic static 142*33828Sbostic union { 143*33828Sbostic long l; 144*33828Sbostic short s[2]; 145*33828Sbostic char c[4]; 146*33828Sbostic } U; 147*33828Sbostic 148*33828Sbostic /* for VAX, Interdata, ... */ 149*33828Sbostic static 150*33828Sbostic long mklong(v) 151*33828Sbostic short v[]; 152*33828Sbostic { 153*33828Sbostic U.l = 1; 154*33828Sbostic if(U.c[0]) 155*33828Sbostic U.s[0] = v[1], U.s[1] = v[0]; 156*33828Sbostic else 157*33828Sbostic U.s[0] = v[0], U.s[1] = v[1]; 158*33828Sbostic return U.l; 159*33828Sbostic } 160*33828Sbostic 161*33828Sbostic main(argc, argv) 162*33828Sbostic char **argv; 163*33828Sbostic { 164*33828Sbostic register ct; 165*33828Sbostic long filesz; 166*33828Sbostic register char *fullp; 167*33828Sbostic register i; 168*33828Sbostic int ans; 169*33828Sbostic short select; /* set when files are selected */ 170*33828Sbostic extern char *optarg; 171*33828Sbostic extern int optind; 172*33828Sbostic 173*33828Sbostic errsource( *argv ); 174*33828Sbostic errverb("notag,notofix"); 175*33828Sbostic errexit( 2 ); 176*33828Sbostic signal(SIGSYS, 1); 177*33828Sbostic if(*argv[1] != '-') 178*33828Sbostic usage(); 179*33828Sbostic Uid = getuid(); 180*33828Sbostic umask(0); 181*33828Sbostic 182*33828Sbostic while( (ans = getopt( argc, argv, "aBC:ifopcdlmrSsbtuvVM:6eI:O:")) != EOF ) { 183*33828Sbostic 184*33828Sbostic switch( ans ) { 185*33828Sbostic case 'a': /* reset access time */ 186*33828Sbostic Acc_time++; 187*33828Sbostic break; 188*33828Sbostic case 'B': /* change record size to 5120 bytes */ 189*33828Sbostic Bufsize = 5120; 190*33828Sbostic break; 191*33828Sbostic case 'C': /* reset buffer size to arbitrary valu 192*33828Sbostic */ 193*33828Sbostic Bufsize = atoi( optarg ); 194*33828Sbostic if( Bufsize == 0 ) 195*33828Sbostic errmsg( EERROR, 196*33828Sbostic "Illegal argument to -%c, '%s'.", 197*33828Sbostic ans, optarg ); 198*33828Sbostic break; 199*33828Sbostic case 'i': 200*33828Sbostic Option = IN; 201*33828Sbostic break; 202*33828Sbostic case 'f': /* copy files not matched by patterns */ 203*33828Sbostic fflag++; 204*33828Sbostic break; 205*33828Sbostic case 'o': 206*33828Sbostic Option = OUT; 207*33828Sbostic break; 208*33828Sbostic case 'p': 209*33828Sbostic Option = PASS; 210*33828Sbostic break; 211*33828Sbostic case 'c': /* ASCII header */ 212*33828Sbostic Cflag++; 213*33828Sbostic break; 214*33828Sbostic case 'd': /* create directories when needed */ 215*33828Sbostic Dir++; 216*33828Sbostic break; 217*33828Sbostic case 'l': /* link files, when necessary */ 218*33828Sbostic PassLink++; 219*33828Sbostic break; 220*33828Sbostic case 'm': /* retain mod time */ 221*33828Sbostic Mod_time++; 222*33828Sbostic break; 223*33828Sbostic case 'r': /* rename files interactively */ 224*33828Sbostic Rename++; 225*33828Sbostic Rtty = fopen(ttyname, "r"); 226*33828Sbostic Wtty = fopen(ttyname, "w"); 227*33828Sbostic if(Rtty==NULL || Wtty==NULL) { 228*33828Sbostic errmsg( EERROR, "Cannot rename (%s missing)", 229*33828Sbostic ttyname ); 230*33828Sbostic } 231*33828Sbostic break; 232*33828Sbostic case 'S': /* swap halfwords */ 233*33828Sbostic halfswap++; 234*33828Sbostic Swap++; 235*33828Sbostic break; 236*33828Sbostic case 's': /* swap bytes */ 237*33828Sbostic byteswap++; 238*33828Sbostic Swap++; 239*33828Sbostic break; 240*33828Sbostic case 'b': /* swap both bytes and halfwords */ 241*33828Sbostic bothswap++; 242*33828Sbostic Swap++; 243*33828Sbostic break; 244*33828Sbostic case 't': /* table of contents */ 245*33828Sbostic Toc++; 246*33828Sbostic break; 247*33828Sbostic case 'u': /* copy unconditionally */ 248*33828Sbostic Uncond++; 249*33828Sbostic break; 250*33828Sbostic case 'v': /* verbose - print out file names */ 251*33828Sbostic Verbose = 1; 252*33828Sbostic break; 253*33828Sbostic case 'V': /* print a dot '.' for each file */ 254*33828Sbostic Verbose = 2; 255*33828Sbostic break; 256*33828Sbostic case 'M': /* alternate message for end-of-media */ 257*33828Sbostic eommsg = optarg; 258*33828Sbostic break; 259*33828Sbostic case '6': /* for old, sixth-edition files */ 260*33828Sbostic Filetype = 060000; 261*33828Sbostic break; 262*33828Sbostic case 'I': 263*33828Sbostic chkswfile( swfile, ans, Option ); 264*33828Sbostic close( Input ); 265*33828Sbostic if( open( optarg, O_RDONLY ) != Input ) 266*33828Sbostic cannotopen( optarg, "input" ); 267*33828Sbostic swfile = optarg; 268*33828Sbostic break; 269*33828Sbostic case 'O': 270*33828Sbostic chkswfile( swfile, ans, Option ); 271*33828Sbostic close( Output ); 272*33828Sbostic if( open( optarg, O_WRONLY | O_CREAT | O_TRUNC, 0666 ) 273*33828Sbostic != Output) 274*33828Sbostic cannotopen( optarg, "output" ); 275*33828Sbostic swfile = optarg; 276*33828Sbostic break; 277*33828Sbostic default: 278*33828Sbostic usage(); 279*33828Sbostic } 280*33828Sbostic } 281*33828Sbostic if(!Option) { 282*33828Sbostic errmsg( EERROR, "Options must include one: -o, -i, -p."); 283*33828Sbostic } 284*33828Sbostic 285*33828Sbostic if(Option == PASS) { 286*33828Sbostic if(Rename) { 287*33828Sbostic errmsg( EERROR, "Pass and Rename cannot be used together."); 288*33828Sbostic } 289*33828Sbostic if( Bufsize != BUFSIZE ) { 290*33828Sbostic fprintf( stderr, "`B' or `C' option is irrelevant with the '-p' option\n"); 291*33828Sbostic Bufsize = BUFSIZE; 292*33828Sbostic } 293*33828Sbostic 294*33828Sbostic }else { 295*33828Sbostic Cp = Cbuf = (char *)zmalloc( EERROR, Bufsize); 296*33828Sbostic } 297*33828Sbostic argc -= optind; 298*33828Sbostic argv += optind; 299*33828Sbostic 300*33828Sbostic switch(Option) { 301*33828Sbostic case OUT: 302*33828Sbostic if(argc != 0) 303*33828Sbostic usage(); 304*33828Sbostic /* get filename, copy header and file out */ 305*33828Sbostic while(getname()) { 306*33828Sbostic if( mklong(Hdr.h_filesize) == 0L) { 307*33828Sbostic if( Cflag ) 308*33828Sbostic bwrite(Chdr,CHARS+Hdr.h_namesize); 309*33828Sbostic else 310*33828Sbostic bwrite(&Hdr, HDRSIZE+Hdr.h_namesize); 311*33828Sbostic if(Verbose) 312*33828Sbostic verbdot( stderr, Hdr.h_name); 313*33828Sbostic continue; 314*33828Sbostic } 315*33828Sbostic if((Ifile = open(Hdr.h_name, 0)) < 0) { 316*33828Sbostic fperr("<%s> ?\n", Hdr.h_name); 317*33828Sbostic continue; 318*33828Sbostic } 319*33828Sbostic if ( Cflag ) 320*33828Sbostic bwrite(Chdr,CHARS+Hdr.h_namesize); 321*33828Sbostic else 322*33828Sbostic bwrite(&Hdr, HDRSIZE+Hdr.h_namesize); 323*33828Sbostic for(filesz=mklong(Hdr.h_filesize); filesz>0; filesz-= CPIOBSZ){ 324*33828Sbostic ct = filesz>CPIOBSZ? CPIOBSZ: filesz; 325*33828Sbostic if(read(Ifile, Buf, ct) < 0) { 326*33828Sbostic fperr("Cannot read %s\n", Hdr.h_name); 327*33828Sbostic continue; 328*33828Sbostic } 329*33828Sbostic bwrite(Buf,ct); 330*33828Sbostic } 331*33828Sbostic close(Ifile); 332*33828Sbostic if(Acc_time) 333*33828Sbostic utime(Hdr.h_name, &Statb.st_atime); 334*33828Sbostic if(Verbose) 335*33828Sbostic verbdot( stderr, Hdr.h_name); 336*33828Sbostic } 337*33828Sbostic 338*33828Sbostic /* copy trailer, after all files have been copied */ 339*33828Sbostic strcpy(Hdr.h_name, "TRAILER!!!"); 340*33828Sbostic Hdr.h_magic = MAGIC; 341*33828Sbostic MKSHORT(Hdr.h_filesize, 0L); 342*33828Sbostic Hdr.h_namesize = strlen("TRAILER!!!") + 1; 343*33828Sbostic if ( Cflag ) { 344*33828Sbostic bintochar(0L); 345*33828Sbostic bwrite(Chdr, CHARS+Hdr.h_namesize); 346*33828Sbostic } 347*33828Sbostic else 348*33828Sbostic bwrite(&Hdr, HDRSIZE+Hdr.h_namesize); 349*33828Sbostic bwrite(Cbuf, Bufsize); 350*33828Sbostic break; 351*33828Sbostic 352*33828Sbostic case IN: 353*33828Sbostic if(argc > 0 ) { /* save patterns, if any */ 354*33828Sbostic Pattern = argv; 355*33828Sbostic } 356*33828Sbostic pwd(); 357*33828Sbostic chkhdr(); 358*33828Sbostic while(gethdr()) { 359*33828Sbostic if( (select = ckname(Hdr.h_name)) && !Toc ) 360*33828Sbostic Ofile = openout(Hdr.h_name); 361*33828Sbostic else 362*33828Sbostic Ofile = 0; 363*33828Sbostic for(filesz=mklong(Hdr.h_filesize); filesz>0; filesz-= CPIOBSZ){ 364*33828Sbostic ct = filesz>CPIOBSZ? CPIOBSZ: filesz; 365*33828Sbostic bread(Buf, ct); 366*33828Sbostic if(Ofile) { 367*33828Sbostic if(Swap) 368*33828Sbostic swap(Buf,ct); 369*33828Sbostic if(write(Ofile, Buf, ct) < 0) { 370*33828Sbostic fperr("Cannot write %s\n", Hdr.h_name); 371*33828Sbostic continue; 372*33828Sbostic } 373*33828Sbostic } 374*33828Sbostic } 375*33828Sbostic if( Ofile ) { 376*33828Sbostic zclose( EERROR, Ofile ); 377*33828Sbostic zchmod( EWARN, Hdr.h_name, Hdr.h_mode); 378*33828Sbostic set_time(Hdr.h_name, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime)); 379*33828Sbostic } 380*33828Sbostic if(select) { 381*33828Sbostic if(Verbose) 382*33828Sbostic if(Toc) 383*33828Sbostic pentry(Hdr.h_name); 384*33828Sbostic else 385*33828Sbostic verbdot( stdout, Hdr.h_name); 386*33828Sbostic else if(Toc) 387*33828Sbostic puts(Hdr.h_name); 388*33828Sbostic } 389*33828Sbostic } 390*33828Sbostic break; 391*33828Sbostic 392*33828Sbostic case PASS: /* move files around */ 393*33828Sbostic if(argc != 1) 394*33828Sbostic usage(); 395*33828Sbostic if(access(argv[0], 2) == -1) { 396*33828Sbostic errmsg( EERROR, "cannot write in <%s>", argv[0]); 397*33828Sbostic } 398*33828Sbostic strcpy(Fullname, argv[0]); /* destination directory */ 399*33828Sbostic zstat( EERROR, Fullname, &Xstatb ); 400*33828Sbostic if((Xstatb.st_mode&S_IFMT) != S_IFDIR) 401*33828Sbostic errmsg( EERROR, "<%s> not a directory.", Fullname ); 402*33828Sbostic Dev = Xstatb.st_dev; 403*33828Sbostic if( Fullname[ strlen(Fullname) - 1 ] != '/' ) 404*33828Sbostic strcat(Fullname, "/"); 405*33828Sbostic fullp = Fullname + strlen(Fullname); 406*33828Sbostic 407*33828Sbostic while(getname()) { 408*33828Sbostic if (A_directory && !Dir) 409*33828Sbostic fperr("Use `-d' option to copy <%s>\n", 410*33828Sbostic Hdr.h_name); 411*33828Sbostic if(!ckname(Hdr.h_name)) 412*33828Sbostic continue; 413*33828Sbostic i = 0; 414*33828Sbostic while(Hdr.h_name[i] == '/') 415*33828Sbostic i++; 416*33828Sbostic strcpy(fullp, &(Hdr.h_name[i])); 417*33828Sbostic 418*33828Sbostic if( PassLink && !A_directory && Dev == Statb.st_dev ) { 419*33828Sbostic if(link(Hdr.h_name, Fullname) < 0) { 420*33828Sbostic switch(errno) { 421*33828Sbostic case ENOENT: 422*33828Sbostic if(missdir(Fullname) != 0) { 423*33828Sbostic fprintf(stderr, 424*33828Sbostic "cpio: cannot create directory for <%s>: %s\n", 425*33828Sbostic Fullname, sys_errlist[errno]); 426*33828Sbostic continue; 427*33828Sbostic } 428*33828Sbostic break; 429*33828Sbostic case EEXIST: 430*33828Sbostic if(unlink(Fullname) < 0) { 431*33828Sbostic fprintf(stderr, 432*33828Sbostic "cpio: cannot unlink <%s>: %s\n", 433*33828Sbostic Fullname, sys_errlist[errno]); 434*33828Sbostic continue; 435*33828Sbostic } 436*33828Sbostic break; 437*33828Sbostic default: 438*33828Sbostic fprintf(stderr, 439*33828Sbostic "Cpio: cannot link <%s> to <%s>: %s\n", 440*33828Sbostic Hdr.h_name, Fullname, sys_errlist[errno]); 441*33828Sbostic continue; 442*33828Sbostic } 443*33828Sbostic if(link(Hdr.h_name, Fullname) < 0) { 444*33828Sbostic fprintf(stderr, 445*33828Sbostic "cpio: cannot link <%s> to <%s>: %s\n", 446*33828Sbostic Hdr.h_name, Fullname, sys_errlist[errno]); 447*33828Sbostic continue; 448*33828Sbostic } 449*33828Sbostic } 450*33828Sbostic 451*33828Sbostic goto ckverbose; 452*33828Sbostic } 453*33828Sbostic if(!(Ofile = openout(Fullname))) 454*33828Sbostic continue; 455*33828Sbostic if((Ifile = zopen( EWARN, Hdr.h_name, 0)) < 0) { 456*33828Sbostic close(Ofile); 457*33828Sbostic continue; 458*33828Sbostic } 459*33828Sbostic filesz = Statb.st_size; 460*33828Sbostic for(; filesz > 0; filesz -= CPIOBSZ) { 461*33828Sbostic ct = filesz>CPIOBSZ? CPIOBSZ: filesz; 462*33828Sbostic if(read(Ifile, Buf, ct) < 0) { 463*33828Sbostic fperr("Cannot read %s\n", Hdr.h_name); 464*33828Sbostic break; 465*33828Sbostic } 466*33828Sbostic if(Ofile) 467*33828Sbostic if(write(Ofile, Buf, ct) < 0) { 468*33828Sbostic fperr("Cannot write %s\n", Hdr.h_name); 469*33828Sbostic break; 470*33828Sbostic } 471*33828Sbostic /* Removed u370 ifdef which caused cpio */ 472*33828Sbostic /* to report blocks in terms of 4096 bytes. */ 473*33828Sbostic 474*33828Sbostic Blocks += ((ct + (BUFSIZE - 1)) / BUFSIZE); 475*33828Sbostic } 476*33828Sbostic close(Ifile); 477*33828Sbostic if(Acc_time) 478*33828Sbostic utime(Hdr.h_name, &Statb.st_atime); 479*33828Sbostic if(Ofile) { 480*33828Sbostic close(Ofile); 481*33828Sbostic zchmod( EWARN, Fullname, Hdr.h_mode); 482*33828Sbostic set_time(Fullname, Statb.st_atime, mklong(Hdr.h_mtime)); 483*33828Sbostic ckverbose: 484*33828Sbostic if(Verbose) 485*33828Sbostic verbdot( stdout, Fullname ); 486*33828Sbostic } 487*33828Sbostic } 488*33828Sbostic } 489*33828Sbostic /* print number of blocks actually copied */ 490*33828Sbostic Blocks += ((sBlocks + (BUFSIZE - 1)) / BUFSIZE); 491*33828Sbostic fperr("%ld blocks\n", Blocks * (Bufsize>>9)); 492*33828Sbostic exit(0); 493*33828Sbostic } 494*33828Sbostic 495*33828Sbostic static 496*33828Sbostic usage() 497*33828Sbostic { 498*33828Sbostic errusage("%s\n\t%s %s\n\t%s %s\n\t%s %s\n\t%s %s\n", 499*33828Sbostic "-o[acvB] <name-list >collection", 500*33828Sbostic Err.source, "-o[acvB] -Ocollection <name-list", 501*33828Sbostic Err.source, "-i[cdmrstuvfB6] [pattern ...] <collection", 502*33828Sbostic Err.source, "-i[cdmrstuvfB6] -Icollection [pattern ...]", 503*33828Sbostic Err.source, "-p[adlmruv] directory <name-list"); 504*33828Sbostic } 505*33828Sbostic 506*33828Sbostic static 507*33828Sbostic chkswfile( sp, c, option ) 508*33828Sbostic char *sp; 509*33828Sbostic char c; 510*33828Sbostic short option; 511*33828Sbostic { 512*33828Sbostic if( !option ) 513*33828Sbostic errmsg( EERROR, "-%c must be specified before -%c option.", 514*33828Sbostic c == 'I' ? 'i' : 'o', c ); 515*33828Sbostic if( (c == 'I' && option != IN) || (c == 'O' && option != OUT) ) 516*33828Sbostic errmsg( EERROR, "-%c option not permitted with -%c option.", c, 517*33828Sbostic option ); 518*33828Sbostic if( !sp ) 519*33828Sbostic return; 520*33828Sbostic errmsg( EERROR, "No more than one -I or -O flag permitted."); 521*33828Sbostic } 522*33828Sbostic 523*33828Sbostic static 524*33828Sbostic cannotopen( sp, mode ) 525*33828Sbostic char *sp, *mode; 526*33828Sbostic { 527*33828Sbostic errmsg( EERROR, "Cannot open <%s> for %s.", sp, mode ); 528*33828Sbostic } 529*33828Sbostic 530*33828Sbostic static 531*33828Sbostic getname() /* get file name, get info for header */ 532*33828Sbostic { 533*33828Sbostic register char *namep = Name; 534*33828Sbostic register ushort ftype; 535*33828Sbostic long tlong; 536*33828Sbostic 537*33828Sbostic for(;;) { 538*33828Sbostic if(gets(namep) == NULL) 539*33828Sbostic return 0; 540*33828Sbostic while(*namep == '.' && namep[1] == '/') { 541*33828Sbostic namep++; 542*33828Sbostic while(*namep == '/') namep++; 543*33828Sbostic } 544*33828Sbostic strcpy(Hdr.h_name, namep); 545*33828Sbostic if(zstat( EWARN, namep, &Statb) < 0) { 546*33828Sbostic continue; 547*33828Sbostic } 548*33828Sbostic ftype = Statb.st_mode & Filetype; 549*33828Sbostic A_directory = (ftype == S_IFDIR); 550*33828Sbostic A_special = (ftype == S_IFBLK) 551*33828Sbostic || (ftype == S_IFCHR) 552*33828Sbostic || (ftype == S_IFIFO); 553*33828Sbostic Hdr.h_magic = MAGIC; 554*33828Sbostic Hdr.h_namesize = strlen(Hdr.h_name) + 1; 555*33828Sbostic Hdr.h_uid = Statb.st_uid; 556*33828Sbostic Hdr.h_gid = Statb.st_gid; 557*33828Sbostic Hdr.h_dev = Statb.st_dev; 558*33828Sbostic Hdr.h_ino = Statb.st_ino; 559*33828Sbostic Hdr.h_mode = Statb.st_mode; 560*33828Sbostic MKSHORT(Hdr.h_mtime, Statb.st_mtime); 561*33828Sbostic Hdr.h_nlink = Statb.st_nlink; 562*33828Sbostic tlong = (Hdr.h_mode&S_IFMT) == S_IFREG? Statb.st_size: 0L; 563*33828Sbostic MKSHORT(Hdr.h_filesize, tlong); 564*33828Sbostic Hdr.h_rdev = Statb.st_rdev; 565*33828Sbostic if( Cflag ) 566*33828Sbostic bintochar(tlong); 567*33828Sbostic return 1; 568*33828Sbostic } 569*33828Sbostic } 570*33828Sbostic 571*33828Sbostic static 572*33828Sbostic bintochar(t) /* ASCII header write */ 573*33828Sbostic long t; 574*33828Sbostic { 575*33828Sbostic sprintf(Chdr,"%.6o%.6ho%.6ho%.6ho%.6ho%.6ho%.6ho%.6ho%.11lo%.6ho%.11lo%s", 576*33828Sbostic MAGIC, MK_USHORT(Statb.st_dev), MK_USHORT(Statb.st_ino), Statb.st_mode, Statb.st_uid, 577*33828Sbostic Statb.st_gid, Statb.st_nlink, MK_USHORT(Statb.st_rdev), 578*33828Sbostic Statb.st_mtime, (short)strlen(Hdr.h_name)+1, t, Hdr.h_name); 579*33828Sbostic } 580*33828Sbostic 581*33828Sbostic static 582*33828Sbostic chartobin() /* ASCII header read */ 583*33828Sbostic { 584*33828Sbostic sscanf(Chdr, "%6ho%6ho%6ho%6ho%6ho%6ho%6ho%6ho%11lo%6ho%11lo", 585*33828Sbostic &Hdr.h_magic, &Hdr.h_dev, &Hdr.h_ino, &Hdr.h_mode, &Hdr.h_uid, 586*33828Sbostic &Hdr.h_gid, &Hdr.h_nlink, &Hdr.h_rdev, &Longtime, 587*33828Sbostic &Hdr.h_namesize, &Longfile); 588*33828Sbostic MKSHORT(Hdr.h_filesize, Longfile); 589*33828Sbostic MKSHORT(Hdr.h_mtime, Longtime); 590*33828Sbostic } 591*33828Sbostic 592*33828Sbostic 593*33828Sbostic /* Check the header for the magic number. Switch modes automatically to 594*33828Sbostic match the type of header found. 595*33828Sbostic */ 596*33828Sbostic static 597*33828Sbostic chkhdr() 598*33828Sbostic { 599*33828Sbostic bread(Chdr, CHARS); 600*33828Sbostic chartobin(); 601*33828Sbostic if( Hdr.h_magic == MAGIC ) 602*33828Sbostic Cflag = 1; 603*33828Sbostic else { 604*33828Sbostic breread(&Hdr.h_magic, sizeof Hdr.h_magic); 605*33828Sbostic if( Hdr.h_magic == MAGIC ) 606*33828Sbostic Cflag = 0; 607*33828Sbostic else 608*33828Sbostic errmsg( EERROR, 609*33828Sbostic "This is not a cpio file. Bad magic number."); 610*33828Sbostic } 611*33828Sbostic breread(Chdr, 0); 612*33828Sbostic } 613*33828Sbostic 614*33828Sbostic 615*33828Sbostic static 616*33828Sbostic gethdr() /* get file headers */ 617*33828Sbostic { 618*33828Sbostic register ushort ftype; 619*33828Sbostic 620*33828Sbostic if (Cflag) { 621*33828Sbostic bread(Chdr, CHARS); 622*33828Sbostic chartobin(); 623*33828Sbostic } 624*33828Sbostic else 625*33828Sbostic bread(&Hdr, HDRSIZE); 626*33828Sbostic 627*33828Sbostic if( Hdr.h_magic != MAGIC ) { 628*33828Sbostic errmsg( EERROR, "Out of phase--get help."); 629*33828Sbostic } 630*33828Sbostic bread(Hdr.h_name, Hdr.h_namesize); 631*33828Sbostic if(EQ(Hdr.h_name, "TRAILER!!!")) 632*33828Sbostic return 0; 633*33828Sbostic ftype = Hdr.h_mode & Filetype; 634*33828Sbostic A_directory = (ftype == S_IFDIR); 635*33828Sbostic A_special = (ftype == S_IFBLK) 636*33828Sbostic || (ftype == S_IFCHR) 637*33828Sbostic || (ftype == S_IFIFO); 638*33828Sbostic return 1; 639*33828Sbostic } 640*33828Sbostic 641*33828Sbostic static 642*33828Sbostic ckname(namep) /* check filenames with patterns given on cmd line */ 643*33828Sbostic register char *namep; 644*33828Sbostic { 645*33828Sbostic char buf[sizeof Hdr.h_name]; 646*33828Sbostic 647*33828Sbostic if(fflag ^ !nmatch(namep, Pattern)) { 648*33828Sbostic return 0; 649*33828Sbostic } 650*33828Sbostic if(Rename && !A_directory) { /* rename interactively */ 651*33828Sbostic fprintf(Wtty, "Rename <%s>\n", namep); 652*33828Sbostic fflush(Wtty); 653*33828Sbostic fgets(buf, sizeof buf, Rtty); 654*33828Sbostic if(feof(Rtty)) 655*33828Sbostic exit(2); 656*33828Sbostic buf[strlen(buf) - 1] = '\0'; 657*33828Sbostic if(EQ(buf, "")) { 658*33828Sbostic strcpy(namep,buf); 659*33828Sbostic printf("Skipped\n"); 660*33828Sbostic return 0; 661*33828Sbostic } 662*33828Sbostic else if(EQ(buf, ".")) 663*33828Sbostic printf("Same name\n"); 664*33828Sbostic else 665*33828Sbostic strcpy(namep,buf); 666*33828Sbostic } 667*33828Sbostic return 1; 668*33828Sbostic } 669*33828Sbostic 670*33828Sbostic static 671*33828Sbostic openout(namep) /* open files for writing, set all necessary info */ 672*33828Sbostic register char *namep; 673*33828Sbostic { 674*33828Sbostic register f; 675*33828Sbostic register char *np; 676*33828Sbostic int ans; 677*33828Sbostic 678*33828Sbostic if(!strncmp(namep, "./", 2)) 679*33828Sbostic namep += 2; 680*33828Sbostic np = namep; 681*33828Sbostic if(A_directory) { 682*33828Sbostic if( !Dir || Rename || EQ(namep, ".") || EQ(namep, "..") ) 683*33828Sbostic /* do not consider . or .. files */ 684*33828Sbostic return 0; 685*33828Sbostic if(stat(namep, &Xstatb) == -1) { 686*33828Sbostic 687*33828Sbostic /* try creating (only twice) */ 688*33828Sbostic ans = 0; 689*33828Sbostic do { 690*33828Sbostic if(makdir(namep) != 0) { 691*33828Sbostic ans += 1; 692*33828Sbostic }else { 693*33828Sbostic ans = 0; 694*33828Sbostic break; 695*33828Sbostic } 696*33828Sbostic }while(ans < 2 && missdir(namep) == 0); 697*33828Sbostic if(ans == 1) { 698*33828Sbostic fperrno("Cannot create directory for <%s>", 699*33828Sbostic namep); 700*33828Sbostic return(0); 701*33828Sbostic }else if(ans == 2) { 702*33828Sbostic fperrno("Cannot create directory <%s>", namep); 703*33828Sbostic return(0); 704*33828Sbostic } 705*33828Sbostic } 706*33828Sbostic 707*33828Sbostic ret: 708*33828Sbostic zchmod( EWARN, namep, Hdr.h_mode); 709*33828Sbostic if(Uid == 0) 710*33828Sbostic zchown( EWARN, namep, Hdr.h_uid, Hdr.h_gid); 711*33828Sbostic set_time(namep, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime)); 712*33828Sbostic return 0; 713*33828Sbostic } 714*33828Sbostic if(Hdr.h_nlink > 1) 715*33828Sbostic if(!postml(namep, np)) 716*33828Sbostic return 0; 717*33828Sbostic if(stat(namep, &Xstatb) == 0) { 718*33828Sbostic if(Uncond && !((!(Xstatb.st_mode & S_IWRITE) || A_special) && (Uid != 0))) { 719*33828Sbostic if(unlink(namep) < 0) { 720*33828Sbostic fperrno("cannot unlink current <%s>", namep); 721*33828Sbostic } 722*33828Sbostic } 723*33828Sbostic if(!Uncond && (mklong(Hdr.h_mtime) <= Xstatb.st_mtime)) { 724*33828Sbostic /* There's a newer or same aged version of file on destination */ 725*33828Sbostic fperr("current <%s> newer or same age\n", np); 726*33828Sbostic return 0; 727*33828Sbostic } 728*33828Sbostic } 729*33828Sbostic if( Option == PASS 730*33828Sbostic && Hdr.h_ino == Xstatb.st_ino 731*33828Sbostic && Hdr.h_dev == Xstatb.st_dev) { 732*33828Sbostic errmsg( EERROR, "Attempt to pass file to self!"); 733*33828Sbostic } 734*33828Sbostic if(A_special) { 735*33828Sbostic if((Hdr.h_mode & Filetype) == S_IFIFO) 736*33828Sbostic Hdr.h_rdev = 0; 737*33828Sbostic 738*33828Sbostic /* try creating (only twice) */ 739*33828Sbostic ans = 0; 740*33828Sbostic do { 741*33828Sbostic if(mknod(namep, Hdr.h_mode, Hdr.h_rdev) < 0) { 742*33828Sbostic ans += 1; 743*33828Sbostic }else { 744*33828Sbostic ans = 0; 745*33828Sbostic break; 746*33828Sbostic } 747*33828Sbostic }while(ans < 2 && missdir(np) == 0); 748*33828Sbostic if(ans == 1) { 749*33828Sbostic fperrno("Cannot create directory for <%s>", namep); 750*33828Sbostic return(0); 751*33828Sbostic }else if(ans == 2) { 752*33828Sbostic fperrno("Cannot mknod <%s>", namep); 753*33828Sbostic return(0); 754*33828Sbostic } 755*33828Sbostic 756*33828Sbostic goto ret; 757*33828Sbostic } 758*33828Sbostic 759*33828Sbostic /* try creating (only twice) */ 760*33828Sbostic ans = 0; 761*33828Sbostic do { 762*33828Sbostic if((f = creat(namep, Hdr.h_mode)) < 0) { 763*33828Sbostic ans += 1; 764*33828Sbostic }else { 765*33828Sbostic ans = 0; 766*33828Sbostic break; 767*33828Sbostic } 768*33828Sbostic }while(ans < 2 && missdir(np) == 0); 769*33828Sbostic if(ans == 1) { 770*33828Sbostic fperrno("Cannot create directory for <%s>", namep); 771*33828Sbostic return(0); 772*33828Sbostic }else if(ans == 2) { 773*33828Sbostic fperrno("Cannot create <%s>", namep); 774*33828Sbostic return(0); 775*33828Sbostic } 776*33828Sbostic 777*33828Sbostic if(Uid == 0) 778*33828Sbostic zchown( EWARN, namep, Hdr.h_uid, Hdr.h_gid); 779*33828Sbostic return f; 780*33828Sbostic } 781*33828Sbostic 782*33828Sbostic 783*33828Sbostic /* Shared by bread() and breread() 784*33828Sbostic */ 785*33828Sbostic static int nleft = 0; /* unread chars left in Cbuf */ 786*33828Sbostic static char *ip; /* pointer to next char to be read from Cbuf */ 787*33828Sbostic 788*33828Sbostic /* Reread the current buffer Cbuf. 789*33828Sbostic A character count, c, of 0 simply resets the pointer so next bread gets 790*33828Sbostic the same data again. 791*33828Sbostic */ 792*33828Sbostic static 793*33828Sbostic breread(b, c) 794*33828Sbostic char *b; 795*33828Sbostic int c; 796*33828Sbostic { 797*33828Sbostic ip = Cbuf; 798*33828Sbostic if( nleft ) 799*33828Sbostic nleft = Bufsize; 800*33828Sbostic if( !c ) 801*33828Sbostic return; 802*33828Sbostic bread(b, c); 803*33828Sbostic } 804*33828Sbostic 805*33828Sbostic static 806*33828Sbostic bread(b, c) 807*33828Sbostic register char *b; 808*33828Sbostic register int c; 809*33828Sbostic { 810*33828Sbostic register int rv; 811*33828Sbostic register char *p = ip; 812*33828Sbostic 813*33828Sbostic if( !Cflag ) { 814*33828Sbostic /* round c up to an even number */ 815*33828Sbostic c = (c+1)/2; 816*33828Sbostic c *= 2; 817*33828Sbostic } 818*33828Sbostic while( c ) { 819*33828Sbostic if( nleft == 0 ) { 820*33828Sbostic while( (rv = read(Input, Cbuf, Bufsize)) == 0 ) { 821*33828Sbostic Input = chgreel(0, Input, rv); 822*33828Sbostic } 823*33828Sbostic if( rv == Bufsize ) { 824*33828Sbostic nleft = Bufsize; 825*33828Sbostic p = Cbuf; 826*33828Sbostic ++Blocks; 827*33828Sbostic } 828*33828Sbostic else if( rv == -1 ) 829*33828Sbostic errmsg( EERROR, 830*33828Sbostic "Read() in bread() failed\n"); 831*33828Sbostic else if( rv < Bufsize ) { /* short read */ 832*33828Sbostic smemcpy( &Cbuf[ Bufsize - rv ], Cbuf, rv ); 833*33828Sbostic nleft = rv; 834*33828Sbostic p = &Cbuf[ Bufsize - rv ]; 835*33828Sbostic sBlocks += rv; 836*33828Sbostic } 837*33828Sbostic else 838*33828Sbostic errmsg( EHALT, 839*33828Sbostic "Impossible return from read(), %d\n", 840*33828Sbostic rv ); 841*33828Sbostic } 842*33828Sbostic if( nleft <= c ) { 843*33828Sbostic memcpy( b, p, nleft ); 844*33828Sbostic c -= nleft; 845*33828Sbostic b += nleft; 846*33828Sbostic p += nleft; 847*33828Sbostic nleft = 0; 848*33828Sbostic } 849*33828Sbostic else { 850*33828Sbostic memcpy( b, p, c ); 851*33828Sbostic nleft -= c; 852*33828Sbostic b += c; 853*33828Sbostic p += c; 854*33828Sbostic c = 0; 855*33828Sbostic } 856*33828Sbostic } 857*33828Sbostic ip = p; 858*33828Sbostic } 859*33828Sbostic 860*33828Sbostic 861*33828Sbostic static 862*33828Sbostic bwrite(rp, c) 863*33828Sbostic register char *rp; 864*33828Sbostic register c; 865*33828Sbostic { 866*33828Sbostic register char *cp = Cp; 867*33828Sbostic static unsigned Ccnt = 0; 868*33828Sbostic register unsigned Cleft; 869*33828Sbostic register int rv; 870*33828Sbostic 871*33828Sbostic if( !Cflag ) { 872*33828Sbostic /* round c up to an even number */ 873*33828Sbostic c = (c+1)/2; 874*33828Sbostic c *= 2; 875*33828Sbostic } 876*33828Sbostic while( c ) { 877*33828Sbostic if( (Cleft = Bufsize - Ccnt) <= c ) { 878*33828Sbostic memcpy( cp, rp, Cleft ); 879*33828Sbostic rv = write(Output, Cbuf, Bufsize); 880*33828Sbostic if( rv == 0 || ( rv == -1 && errno == ENXIO ) ) { 881*33828Sbostic rv = eomchgreel(); 882*33828Sbostic } 883*33828Sbostic if( rv == Bufsize ) { 884*33828Sbostic Ccnt = 0; 885*33828Sbostic cp = Cbuf; 886*33828Sbostic } 887*33828Sbostic else if( rv == -1 ) 888*33828Sbostic errmsg( EERROR, 889*33828Sbostic "Write() in bwrite() failed\n"); 890*33828Sbostic else if( rv < Bufsize ) { 891*33828Sbostic Output = chgreel(1, Output, 0); 892*33828Sbostic smemcpy( Cbuf, &Cbuf[ Bufsize - rv ], rv ); 893*33828Sbostic Ccnt = Bufsize - rv; 894*33828Sbostic cp = &Cbuf[ rv ]; 895*33828Sbostic } 896*33828Sbostic else 897*33828Sbostic errmsg( EHALT, 898*33828Sbostic "Impossible return from read(), %d\n", 899*33828Sbostic rv ); 900*33828Sbostic ++Blocks; 901*33828Sbostic rp += Cleft; 902*33828Sbostic c -= Cleft; 903*33828Sbostic } 904*33828Sbostic else { 905*33828Sbostic memcpy( cp, rp, c ); 906*33828Sbostic Ccnt += c; 907*33828Sbostic cp += c; 908*33828Sbostic rp += c; 909*33828Sbostic c = 0; 910*33828Sbostic } 911*33828Sbostic } 912*33828Sbostic Cp = cp; 913*33828Sbostic } 914*33828Sbostic 915*33828Sbostic 916*33828Sbostic static int reelcount = 1; /* used below and in chgreel() */ 917*33828Sbostic 918*33828Sbostic /* Change reel due to reaching end-of-media. 919*33828Sbostic Keep trying to get a successful write before considering the 920*33828Sbostic change-of-reel as successful. 921*33828Sbostic */ 922*33828Sbostic static 923*33828Sbostic int 924*33828Sbostic eomchgreel() 925*33828Sbostic { 926*33828Sbostic int rv; 927*33828Sbostic 928*33828Sbostic while( 1 ) { 929*33828Sbostic Output = chgreel(1, Output, 0); 930*33828Sbostic rv = write(Output, Cbuf, Bufsize); 931*33828Sbostic if( rv == Bufsize ) 932*33828Sbostic return rv; 933*33828Sbostic fperr( "Unable to write this medium. Try again.\n" ); 934*33828Sbostic reelcount--; 935*33828Sbostic } 936*33828Sbostic /*NOTREACHED*/ 937*33828Sbostic } 938*33828Sbostic 939*33828Sbostic 940*33828Sbostic static 941*33828Sbostic postml(namep, np) /* linking funtion: Postml() is called after */ 942*33828Sbostic register char *namep, *np; /* namep is created. Postml() checks to see */ 943*33828Sbostic { /* if namep should be linked to np. If so, */ 944*33828Sbostic /* postml() removes the independent instance */ 945*33828Sbostic register i; /* of namep and links namep to np. */ 946*33828Sbostic static struct ml { 947*33828Sbostic short m_dev; 948*33828Sbostic ushort m_ino; 949*33828Sbostic char m_name[2]; 950*33828Sbostic } **ml = 0; 951*33828Sbostic register struct ml *mlp; 952*33828Sbostic static unsigned mlsize = 0; 953*33828Sbostic static unsigned mlinks = 0; 954*33828Sbostic char *lnamep; 955*33828Sbostic int ans; 956*33828Sbostic 957*33828Sbostic if( !ml ) { 958*33828Sbostic mlsize = LINKS; 959*33828Sbostic ml = (struct ml **) zmalloc( EERROR, mlsize * sizeof(struct ml)); 960*33828Sbostic } 961*33828Sbostic else if( mlinks == mlsize ) { 962*33828Sbostic mlsize += LINKS; 963*33828Sbostic ml = (struct ml **) zrealloc( EERROR, ml, mlsize * sizeof(struct ml)); 964*33828Sbostic } 965*33828Sbostic for(i = 0; i < mlinks; ++i) { 966*33828Sbostic mlp = ml[i]; 967*33828Sbostic if(mlp->m_ino==Hdr.h_ino && mlp->m_dev==Hdr.h_dev) { 968*33828Sbostic if(Verbose == 1) 969*33828Sbostic fprintf(stderr, "%s linked to %s\n", mlp->m_name, np); 970*33828Sbostic if(Verbose) 971*33828Sbostic verbdot(stdout, np); 972*33828Sbostic unlink(namep); 973*33828Sbostic if(Option == IN && *(mlp->m_name) != '/') { 974*33828Sbostic Fullname[Pathend] = '\0'; 975*33828Sbostic strcat(Fullname, mlp->m_name); 976*33828Sbostic lnamep = Fullname; 977*33828Sbostic } 978*33828Sbostic lnamep = mlp->m_name; 979*33828Sbostic 980*33828Sbostic /* try linking (only twice) */ 981*33828Sbostic ans = 0; 982*33828Sbostic do { 983*33828Sbostic if(link(lnamep, namep) < 0) { 984*33828Sbostic ans += 1; 985*33828Sbostic }else { 986*33828Sbostic ans = 0; 987*33828Sbostic break; 988*33828Sbostic } 989*33828Sbostic }while(ans < 2 && missdir(np) == 0); 990*33828Sbostic if(ans == 1) { 991*33828Sbostic fperrno("Cannot create directory for <%s>", np); 992*33828Sbostic return(0); 993*33828Sbostic }else if(ans == 2) { 994*33828Sbostic fperrno("Cannot link <%s> & <%s>", lnamep, np); 995*33828Sbostic return(0); 996*33828Sbostic } 997*33828Sbostic 998*33828Sbostic set_time(namep, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime)); 999*33828Sbostic return 0; 1000*33828Sbostic } 1001*33828Sbostic } 1002*33828Sbostic if( !(ml[mlinks] = (struct ml *)zmalloc( EWARN, strlen(np) + 2 + sizeof(struct ml)))) { 1003*33828Sbostic static int first=1; 1004*33828Sbostic 1005*33828Sbostic if(first) 1006*33828Sbostic fperr("No memory for links (%d)\n", mlinks); 1007*33828Sbostic first = 0; 1008*33828Sbostic return 1; 1009*33828Sbostic } 1010*33828Sbostic ml[mlinks]->m_dev = Hdr.h_dev; 1011*33828Sbostic ml[mlinks]->m_ino = Hdr.h_ino; 1012*33828Sbostic strcpy(ml[mlinks]->m_name, np); 1013*33828Sbostic ++mlinks; 1014*33828Sbostic return 1; 1015*33828Sbostic } 1016*33828Sbostic 1017*33828Sbostic static 1018*33828Sbostic pentry(namep) /* print verbose table of contents */ 1019*33828Sbostic register char *namep; 1020*33828Sbostic { 1021*33828Sbostic 1022*33828Sbostic static short lastid = -1; 1023*33828Sbostic #include <pwd.h> 1024*33828Sbostic static struct passwd *pw; 1025*33828Sbostic struct passwd *getpwuid(); 1026*33828Sbostic static char tbuf[32]; 1027*33828Sbostic char *ctime(); 1028*33828Sbostic 1029*33828Sbostic printf("%-7o", MK_USHORT(Hdr.h_mode)); 1030*33828Sbostic if(lastid == Hdr.h_uid) 1031*33828Sbostic printf("%-6s", pw->pw_name); 1032*33828Sbostic else { 1033*33828Sbostic setpwent(); 1034*33828Sbostic if(pw = getpwuid((int)Hdr.h_uid)) { 1035*33828Sbostic printf("%-6s", pw->pw_name); 1036*33828Sbostic lastid = Hdr.h_uid; 1037*33828Sbostic } else { 1038*33828Sbostic printf("%-6d", Hdr.h_uid); 1039*33828Sbostic lastid = -1; 1040*33828Sbostic } 1041*33828Sbostic } 1042*33828Sbostic printf("%7ld ", mklong(Hdr.h_filesize)); 1043*33828Sbostic U.l = mklong(Hdr.h_mtime); 1044*33828Sbostic strcpy(tbuf, ctime((long *)&U.l)); 1045*33828Sbostic tbuf[24] = '\0'; 1046*33828Sbostic printf(" %s %s\n", &tbuf[4], namep); 1047*33828Sbostic } 1048*33828Sbostic 1049*33828Sbostic /* pattern matching functions */ 1050*33828Sbostic static 1051*33828Sbostic nmatch(s, pat) 1052*33828Sbostic char *s, **pat; 1053*33828Sbostic { 1054*33828Sbostic if( !pat ) 1055*33828Sbostic return 1; 1056*33828Sbostic while(*pat) { 1057*33828Sbostic if((**pat == '!' && !gmatch(s, *pat+1)) 1058*33828Sbostic || gmatch(s, *pat)) 1059*33828Sbostic return 1; 1060*33828Sbostic ++pat; 1061*33828Sbostic } 1062*33828Sbostic return 0; 1063*33828Sbostic } 1064*33828Sbostic 1065*33828Sbostic 1066*33828Sbostic static 1067*33828Sbostic gmatch(s, p) 1068*33828Sbostic register char *s, *p; 1069*33828Sbostic { 1070*33828Sbostic register int c; 1071*33828Sbostic register cc, ok, lc, scc; 1072*33828Sbostic 1073*33828Sbostic scc = *s; 1074*33828Sbostic lc = 077777; 1075*33828Sbostic switch (c = *p) { 1076*33828Sbostic 1077*33828Sbostic case '[': 1078*33828Sbostic ok = 0; 1079*33828Sbostic while (cc = *++p) { 1080*33828Sbostic switch (cc) { 1081*33828Sbostic 1082*33828Sbostic case ']': 1083*33828Sbostic if (ok) 1084*33828Sbostic return(gmatch(++s, ++p)); 1085*33828Sbostic else 1086*33828Sbostic return(0); 1087*33828Sbostic 1088*33828Sbostic case '-': 1089*33828Sbostic ok |= ((lc <= scc) && (scc <= (cc=p[1]))); 1090*33828Sbostic } 1091*33828Sbostic if (scc==(lc=cc)) ok++; 1092*33828Sbostic } 1093*33828Sbostic return(0); 1094*33828Sbostic 1095*33828Sbostic case '?': 1096*33828Sbostic caseq: 1097*33828Sbostic if(scc) return(gmatch(++s, ++p)); 1098*33828Sbostic return(0); 1099*33828Sbostic case '*': 1100*33828Sbostic return(umatch(s, ++p)); 1101*33828Sbostic case 0: 1102*33828Sbostic return(!scc); 1103*33828Sbostic } 1104*33828Sbostic if (c==scc) goto caseq; 1105*33828Sbostic return(0); 1106*33828Sbostic } 1107*33828Sbostic 1108*33828Sbostic 1109*33828Sbostic 1110*33828Sbostic static 1111*33828Sbostic umatch(s, p) 1112*33828Sbostic register char *s, *p; 1113*33828Sbostic { 1114*33828Sbostic if(*p==0) return(1); 1115*33828Sbostic while(*s) 1116*33828Sbostic if (gmatch(s++,p)) return(1); 1117*33828Sbostic return(0); 1118*33828Sbostic } 1119*33828Sbostic 1120*33828Sbostic 1121*33828Sbostic 1122*33828Sbostic static 1123*33828Sbostic makdir(namep) /* make needed directories */ 1124*33828Sbostic register char *namep; 1125*33828Sbostic { 1126*33828Sbostic static status; 1127*33828Sbostic register pid; 1128*33828Sbostic 1129*33828Sbostic pid = fork(); 1130*33828Sbostic if (pid == 0) { /* pid == 0 implies child process */ 1131*33828Sbostic close(2); 1132*33828Sbostic execl("/bin/mkdir", "mkdir", namep, 0); 1133*33828Sbostic exit(2); 1134*33828Sbostic } 1135*33828Sbostic if (pid == -1) { /* pid != 0 implies parent process */ 1136*33828Sbostic fprintf(stderr,"Cannot fork, try again\n"); 1137*33828Sbostic exit(2); 1138*33828Sbostic } 1139*33828Sbostic while(wait(&status) != pid); 1140*33828Sbostic 1141*33828Sbostic return ((status>>8) & 0377)? 1: 0; 1142*33828Sbostic } 1143*33828Sbostic 1144*33828Sbostic 1145*33828Sbostic 1146*33828Sbostic static 1147*33828Sbostic swap(buf, ct) /* swap halfwords, bytes or both */ 1148*33828Sbostic register ct; 1149*33828Sbostic register char *buf; 1150*33828Sbostic { 1151*33828Sbostic register char c; 1152*33828Sbostic register union swp { long longw; short shortv[2]; char charv[4]; } *pbuf; 1153*33828Sbostic int savect, n, i; 1154*33828Sbostic char *savebuf; 1155*33828Sbostic short cc; 1156*33828Sbostic 1157*33828Sbostic savect = ct; savebuf = buf; 1158*33828Sbostic if(byteswap || bothswap) { 1159*33828Sbostic if (ct % 2) buf[ct] = 0; 1160*33828Sbostic ct = (ct + 1) / 2; 1161*33828Sbostic while (ct--) { 1162*33828Sbostic c = *buf; 1163*33828Sbostic *buf = *(buf + 1); 1164*33828Sbostic *(buf + 1) = c; 1165*33828Sbostic buf += 2; 1166*33828Sbostic } 1167*33828Sbostic if (bothswap) { 1168*33828Sbostic ct = savect; 1169*33828Sbostic pbuf = (union swp *)savebuf; 1170*33828Sbostic if (n = ct % sizeof(union swp)) { 1171*33828Sbostic if(n % 2) 1172*33828Sbostic for(i = ct + 1; i <= ct + (sizeof(union swp) - n); i++) pbuf->charv[i] = 0; 1173*33828Sbostic else 1174*33828Sbostic for (i = ct; i < ct + (sizeof(union swp) - n); i++) pbuf->charv[i] = 0; 1175*33828Sbostic } 1176*33828Sbostic ct = (ct + (sizeof(union swp) -1)) / sizeof(union swp); 1177*33828Sbostic while(ct--) { 1178*33828Sbostic cc = pbuf->shortv[0]; 1179*33828Sbostic pbuf->shortv[0] = pbuf->shortv[1]; 1180*33828Sbostic pbuf->shortv[1] = cc; 1181*33828Sbostic ++pbuf; 1182*33828Sbostic } 1183*33828Sbostic } 1184*33828Sbostic } 1185*33828Sbostic else if (halfswap) { 1186*33828Sbostic pbuf = (union swp *)buf; 1187*33828Sbostic if (n = ct % sizeof(union swp)) 1188*33828Sbostic for (i = ct; i < ct + (sizeof(union swp) - n); i++) pbuf->charv[i] = 0; 1189*33828Sbostic ct = (ct + (sizeof(union swp) -1)) / sizeof(union swp); 1190*33828Sbostic while (ct--) { 1191*33828Sbostic cc = pbuf->shortv[0]; 1192*33828Sbostic pbuf->shortv[0] = pbuf->shortv[1]; 1193*33828Sbostic pbuf->shortv[1] = cc; 1194*33828Sbostic ++pbuf; 1195*33828Sbostic } 1196*33828Sbostic } 1197*33828Sbostic } 1198*33828Sbostic 1199*33828Sbostic 1200*33828Sbostic static 1201*33828Sbostic set_time(namep, atime, mtime) /* set access and modification times */ 1202*33828Sbostic register char *namep; 1203*33828Sbostic time_t atime, mtime; 1204*33828Sbostic { 1205*33828Sbostic static time_t timevec[2]; 1206*33828Sbostic 1207*33828Sbostic if(!Mod_time) 1208*33828Sbostic return; 1209*33828Sbostic timevec[0] = atime; 1210*33828Sbostic timevec[1] = mtime; 1211*33828Sbostic utime(namep, timevec); 1212*33828Sbostic } 1213*33828Sbostic 1214*33828Sbostic 1215*33828Sbostic 1216*33828Sbostic static 1217*33828Sbostic chgreel(x, fl, rv) 1218*33828Sbostic { 1219*33828Sbostic register f; 1220*33828Sbostic char str[BUFSIZ]; 1221*33828Sbostic struct stat statb; 1222*33828Sbostic 1223*33828Sbostic fstat(fl, &statb); 1224*33828Sbostic if((statb.st_mode&S_IFMT) != S_IFCHR) { 1225*33828Sbostic fperrno("Can't %s: ", x? "write output": "read input"); 1226*33828Sbostic exit(2); 1227*33828Sbostic } 1228*33828Sbostic if( rv == 0 || 1229*33828Sbostic ( rv == -1 && ( errno == ENOSPC || errno == ENXIO ) ) ) 1230*33828Sbostic fperr( "\007Reached end of medium on %s.\n", 1231*33828Sbostic x? "output":"input" ); 1232*33828Sbostic else { 1233*33828Sbostic fperrno( "\007Encountered an error on %s", 1234*33828Sbostic x? "output":"input" ); 1235*33828Sbostic exit(2); 1236*33828Sbostic } 1237*33828Sbostic if( Rtty == NULL ) 1238*33828Sbostic Rtty = zfopen( EERROR, ttyname, "r"); 1239*33828Sbostic close(fl); 1240*33828Sbostic reelcount++; 1241*33828Sbostic again: 1242*33828Sbostic if( swfile ) { 1243*33828Sbostic askagain: 1244*33828Sbostic fperr( eommsg, reelcount ); 1245*33828Sbostic fgets(str, sizeof str, Rtty); 1246*33828Sbostic switch( *str ) { 1247*33828Sbostic case '\n': 1248*33828Sbostic strcpy( str, swfile ); 1249*33828Sbostic break; 1250*33828Sbostic case 'q': 1251*33828Sbostic exit(2); 1252*33828Sbostic default: 1253*33828Sbostic goto askagain; 1254*33828Sbostic } 1255*33828Sbostic } 1256*33828Sbostic else { 1257*33828Sbostic fperr("If you want to go on, type device/file name when ready.\n"); 1258*33828Sbostic fgets(str, sizeof str, Rtty); 1259*33828Sbostic str[strlen(str) - 1] = '\0'; 1260*33828Sbostic if(!*str) 1261*33828Sbostic exit(2); 1262*33828Sbostic } 1263*33828Sbostic if((f = open(str, x? 1: 0)) < 0) { 1264*33828Sbostic fperr("That didn't work, cannot open \"%s\"\n", str); 1265*33828Sbostic if( errno ) 1266*33828Sbostic perror(""); 1267*33828Sbostic goto again; 1268*33828Sbostic } 1269*33828Sbostic return f; 1270*33828Sbostic } 1271*33828Sbostic 1272*33828Sbostic 1273*33828Sbostic 1274*33828Sbostic static 1275*33828Sbostic missdir(namep) 1276*33828Sbostic register char *namep; 1277*33828Sbostic { 1278*33828Sbostic register char *np; 1279*33828Sbostic register ct = 2; 1280*33828Sbostic 1281*33828Sbostic for(np = namep; *np; ++np) 1282*33828Sbostic if(*np == '/') { 1283*33828Sbostic if(np == namep) continue; /* skip over 'root slash' */ 1284*33828Sbostic *np = '\0'; 1285*33828Sbostic if(stat(namep, &Xstatb) == -1) { 1286*33828Sbostic if(Dir) { 1287*33828Sbostic if((ct = makdir(namep)) != 0) { 1288*33828Sbostic *np = '/'; 1289*33828Sbostic return(ct); 1290*33828Sbostic } 1291*33828Sbostic }else { 1292*33828Sbostic fperr("missing 'd' option\n"); 1293*33828Sbostic return(-1); 1294*33828Sbostic } 1295*33828Sbostic } 1296*33828Sbostic *np = '/'; 1297*33828Sbostic } 1298*33828Sbostic if (ct == 2) ct = 0; /* the file already exists */ 1299*33828Sbostic return ct; 1300*33828Sbostic } 1301*33828Sbostic 1302*33828Sbostic 1303*33828Sbostic 1304*33828Sbostic static 1305*33828Sbostic pwd() /* get working directory */ 1306*33828Sbostic { 1307*33828Sbostic FILE *dir; 1308*33828Sbostic 1309*33828Sbostic dir = popen("pwd", "r"); 1310*33828Sbostic fgets(Fullname, sizeof Fullname, dir); 1311*33828Sbostic if(pclose(dir)) 1312*33828Sbostic exit(2); 1313*33828Sbostic Pathend = strlen(Fullname); 1314*33828Sbostic Fullname[Pathend - 1] = '/'; 1315*33828Sbostic } 1316*33828Sbostic 1317*33828Sbostic 1318*33828Sbostic static int verbcount = 0; 1319*33828Sbostic static FILE *verbout = 0; 1320*33828Sbostic /* 1321*33828Sbostic In -V verbose mode, print out a dot for each file processed. 1322*33828Sbostic */ 1323*33828Sbostic static 1324*33828Sbostic verbdot( fp, cp ) 1325*33828Sbostic FILE *fp; 1326*33828Sbostic char *cp; 1327*33828Sbostic { 1328*33828Sbostic 1329*33828Sbostic if( !verbout ) 1330*33828Sbostic verbout = fp; 1331*33828Sbostic if( Verbose == 2 ) { 1332*33828Sbostic fputc( '.', fp ); 1333*33828Sbostic if( ++verbcount >= 50 ) { 1334*33828Sbostic /* start a new line of dots */ 1335*33828Sbostic verbcount = 0; 1336*33828Sbostic fputc( '\n', fp ); 1337*33828Sbostic } 1338*33828Sbostic } 1339*33828Sbostic else { 1340*33828Sbostic fputs( cp, fp ); 1341*33828Sbostic fputc( '\n', fp ); 1342*33828Sbostic } 1343*33828Sbostic } 1344*33828Sbostic 1345*33828Sbostic 1346*33828Sbostic /* 1347*33828Sbostic print message on the stderr 1348*33828Sbostic */ 1349*33828Sbostic static 1350*33828Sbostic fperr( va_alist ) 1351*33828Sbostic va_dcl 1352*33828Sbostic { 1353*33828Sbostic va_list args; 1354*33828Sbostic char *fmt; 1355*33828Sbostic 1356*33828Sbostic resetverbcount(); 1357*33828Sbostic va_start( args ); 1358*33828Sbostic fmt = va_arg( args, char * ); 1359*33828Sbostic vfprintf( stderr, fmt, args ); 1360*33828Sbostic fflush( stderr ); 1361*33828Sbostic } 1362*33828Sbostic 1363*33828Sbostic /* 1364*33828Sbostic print message on the stderr followed by error number and meaning. 1365*33828Sbostic */ 1366*33828Sbostic static 1367*33828Sbostic fperrno( va_alist ) 1368*33828Sbostic va_dcl 1369*33828Sbostic { 1370*33828Sbostic va_list args; 1371*33828Sbostic char *fmt; 1372*33828Sbostic 1373*33828Sbostic resetverbcount(); 1374*33828Sbostic va_start( args ); 1375*33828Sbostic fmt = va_arg( args, char * ); 1376*33828Sbostic vfprintf( stderr, fmt, args ); 1377*33828Sbostic fprintf( stderr, ", errno %d, ", errno ); 1378*33828Sbostic fflush( stderr ); 1379*33828Sbostic perror(""); 1380*33828Sbostic } 1381*33828Sbostic 1382*33828Sbostic 1383*33828Sbostic static 1384*33828Sbostic resetverbcount() 1385*33828Sbostic { 1386*33828Sbostic if( Verbose == 2 && verbcount ) { 1387*33828Sbostic fputc( '\n', verbout ); 1388*33828Sbostic verbcount = 0; 1389*33828Sbostic } 1390*33828Sbostic } 1391*33828Sbostic 1392*33828Sbostic 1393*33828Sbostic void 1394*33828Sbostic errbefore() 1395*33828Sbostic { 1396*33828Sbostic resetverbcount(); 1397*33828Sbostic } 1398