1*11240Smckusick /* Copyright (c) 1983 Regents of the University of California */ 2*11240Smckusick 3*11240Smckusick #ifndef lint 4*11240Smckusick static char sccsid[] = "@(#)cpio.c 4.1 (Berkeley) 02/23/83"; 5*11240Smckusick #endif not lint 6*11240Smckusick 7*11240Smckusick /* cpio COMPILE: cc -O cpio.c -s -i -o cpio 8*11240Smckusick cpio -- copy file collections 9*11240Smckusick 10*11240Smckusick */ 11*11240Smckusick #include <stdio.h> 12*11240Smckusick #include <sys/types.h> 13*11240Smckusick #include <sys/stat.h> 14*11240Smckusick #include <signal.h> 15*11240Smckusick #ifdef RT 16*11240Smckusick #define S_IFEXT 0120000 /* allocated by extents */ 17*11240Smckusick #define S_IF1EXT 0130000 /* one extent */ 18*11240Smckusick #endif 19*11240Smckusick #define EQ(x,y) (strcmp(x,y)==0) 20*11240Smckusick /* for VAX, Interdata, ... */ 21*11240Smckusick #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];} 22*11240Smckusick #define MAGIC 070707 23*11240Smckusick #define IN 1 24*11240Smckusick #define OUT 2 25*11240Smckusick #define PASS 3 26*11240Smckusick #define HDRSIZE ((sizeof Hdr)-256) 27*11240Smckusick #define LINKS 1000 28*11240Smckusick #define MERT 0 29*11240Smckusick #define CHARS 76 30*11240Smckusick #ifdef RT 31*11240Smckusick #define MERT 1 /* yes = 1 ; no = 0 */ 32*11240Smckusick extern long filespace; 33*11240Smckusick #endif 34*11240Smckusick 35*11240Smckusick struct stat Statb, Xstatb; 36*11240Smckusick 37*11240Smckusick struct header { 38*11240Smckusick short h_magic, 39*11240Smckusick h_dev; 40*11240Smckusick unsigned short h_ino, 41*11240Smckusick h_mode, 42*11240Smckusick h_uid, 43*11240Smckusick h_gid; 44*11240Smckusick short h_nlink, 45*11240Smckusick h_rdev, 46*11240Smckusick h_mtime[2], 47*11240Smckusick h_namesize, 48*11240Smckusick h_filesize[2]; 49*11240Smckusick char h_name[256]; 50*11240Smckusick } Hdr; 51*11240Smckusick 52*11240Smckusick int Bufsize = 512; 53*11240Smckusick short Buf[256], *Dbuf; 54*11240Smckusick char BBuf[512]; 55*11240Smckusick char *Cbuf; 56*11240Smckusick int Wct,Wc; 57*11240Smckusick short *Wp; 58*11240Smckusick char *Cp; 59*11240Smckusick #ifdef RT 60*11240Smckusick short Actual_size[2]; /* MERT variable */ 61*11240Smckusick struct{ 62*11240Smckusick long long_size; 63*11240Smckusick }; 64*11240Smckusick #endif 65*11240Smckusick 66*11240Smckusick short Option, 67*11240Smckusick Dir, 68*11240Smckusick Uncond, 69*11240Smckusick Link, 70*11240Smckusick Rename, 71*11240Smckusick Toc, 72*11240Smckusick Verbose, 73*11240Smckusick Select, 74*11240Smckusick Mod_time, 75*11240Smckusick Acc_time, 76*11240Smckusick Cflag, 77*11240Smckusick Swap; 78*11240Smckusick 79*11240Smckusick int Ifile, 80*11240Smckusick Ofile, 81*11240Smckusick Input = 0, 82*11240Smckusick Output = 1; 83*11240Smckusick long Blocks, 84*11240Smckusick Longfile, 85*11240Smckusick Longtime; 86*11240Smckusick 87*11240Smckusick char Fullname[256], 88*11240Smckusick Name[256]; 89*11240Smckusick int Pathend; 90*11240Smckusick 91*11240Smckusick FILE *Rtty, 92*11240Smckusick *Wtty; 93*11240Smckusick 94*11240Smckusick char *Pattern[100]; 95*11240Smckusick char Strhdr[500]; 96*11240Smckusick char *Chdr = Strhdr; 97*11240Smckusick short Dev, 98*11240Smckusick Uid, 99*11240Smckusick Gid, 100*11240Smckusick A_directory, 101*11240Smckusick A_special, 102*11240Smckusick #ifdef RT 103*11240Smckusick One_extent, 104*11240Smckusick Multi_extent, 105*11240Smckusick #endif 106*11240Smckusick Filetype = S_IFMT; 107*11240Smckusick #ifdef RT 108*11240Smckusick short Remove_mode = 0007777; 109*11240Smckusick short New_mode; 110*11240Smckusick #endif 111*11240Smckusick 112*11240Smckusick extern errno; 113*11240Smckusick char *malloc(); 114*11240Smckusick char *cd(); 115*11240Smckusick char *Cd_name; 116*11240Smckusick FILE *popen(); 117*11240Smckusick 118*11240Smckusick union { long l; short s[2]; char c[4]; } U; 119*11240Smckusick 120*11240Smckusick /* for VAX, Interdata, ... */ 121*11240Smckusick long mklong(v) 122*11240Smckusick short v[]; 123*11240Smckusick { 124*11240Smckusick U.l = 1; 125*11240Smckusick if(U.c[0]) 126*11240Smckusick U.s[0] = v[1], U.s[1] = v[0]; 127*11240Smckusick else 128*11240Smckusick U.s[0] = v[0], U.s[1] = v[1]; 129*11240Smckusick return U.l; 130*11240Smckusick } 131*11240Smckusick 132*11240Smckusick main(argc, argv) 133*11240Smckusick char **argv; 134*11240Smckusick { 135*11240Smckusick register ct; 136*11240Smckusick long filesz; 137*11240Smckusick long lng; 138*11240Smckusick register char *fullp; 139*11240Smckusick register i; 140*11240Smckusick 141*11240Smckusick signal(SIGSYS, 1); 142*11240Smckusick if(*argv[1] != '-') 143*11240Smckusick usage(); 144*11240Smckusick Uid = getuid(); 145*11240Smckusick umask(0); 146*11240Smckusick Gid = getgid(); 147*11240Smckusick Pattern[0] = "*"; 148*11240Smckusick 149*11240Smckusick while(*++argv[1]) { 150*11240Smckusick switch(*argv[1]) { 151*11240Smckusick case 'a': 152*11240Smckusick Acc_time++; 153*11240Smckusick break; 154*11240Smckusick case 'B': 155*11240Smckusick Bufsize = 5120; 156*11240Smckusick break; 157*11240Smckusick case 'i': 158*11240Smckusick Option = IN; 159*11240Smckusick if(argc > 2 ) { 160*11240Smckusick for(i = 0; (i+2) < argc; ++i) 161*11240Smckusick Pattern[i] = argv[i+2]; 162*11240Smckusick } 163*11240Smckusick break; 164*11240Smckusick case 'o': 165*11240Smckusick if(argc != 2) 166*11240Smckusick usage(); 167*11240Smckusick Option = OUT; 168*11240Smckusick break; 169*11240Smckusick case 'p': 170*11240Smckusick if(argc != 3) 171*11240Smckusick usage(); 172*11240Smckusick if(access(argv[2], 2) == -1) { 173*11240Smckusick accerr: 174*11240Smckusick err("cannot write in <%s>\n", argv[2]); 175*11240Smckusick exit(2); 176*11240Smckusick } 177*11240Smckusick strcpy(Fullname, argv[2]); 178*11240Smckusick strcat(Fullname, "/"); 179*11240Smckusick stat(Fullname, &Xstatb); 180*11240Smckusick if((Xstatb.st_mode&S_IFMT) != S_IFDIR) 181*11240Smckusick goto accerr; 182*11240Smckusick Option = PASS; 183*11240Smckusick Dev = Xstatb.st_dev; 184*11240Smckusick break; 185*11240Smckusick case 'c': 186*11240Smckusick Cflag++; 187*11240Smckusick break; 188*11240Smckusick case 'd': 189*11240Smckusick Dir++; 190*11240Smckusick break; 191*11240Smckusick case 'l': 192*11240Smckusick Link++; 193*11240Smckusick break; 194*11240Smckusick case 'm': 195*11240Smckusick Mod_time++; 196*11240Smckusick break; 197*11240Smckusick case 'r': 198*11240Smckusick Rename++; 199*11240Smckusick Rtty = fopen("/dev/tty", "r"); 200*11240Smckusick Wtty = fopen("/dev/tty", "w"); 201*11240Smckusick if(Rtty==NULL || Wtty==NULL) { 202*11240Smckusick err( 203*11240Smckusick "Cannot rename (/dev/tty missing)\n"); 204*11240Smckusick exit(2); 205*11240Smckusick } 206*11240Smckusick break; 207*11240Smckusick case 's': 208*11240Smckusick Swap++; 209*11240Smckusick break; 210*11240Smckusick case 't': 211*11240Smckusick Toc++; 212*11240Smckusick break; 213*11240Smckusick case 'u': 214*11240Smckusick Uncond++; 215*11240Smckusick break; 216*11240Smckusick case 'v': 217*11240Smckusick Verbose++; 218*11240Smckusick break; 219*11240Smckusick case '6': 220*11240Smckusick Filetype = 060000; 221*11240Smckusick break; 222*11240Smckusick default: 223*11240Smckusick usage(); 224*11240Smckusick } 225*11240Smckusick } 226*11240Smckusick if(!Option) { 227*11240Smckusick err("Options must include o|i|p\n"); 228*11240Smckusick exit(2); 229*11240Smckusick } 230*11240Smckusick 231*11240Smckusick if (Cflag && Swap) { 232*11240Smckusick err("Swap flag is ignored with Cflag\n"); 233*11240Smckusick Swap = 0; 234*11240Smckusick } 235*11240Smckusick 236*11240Smckusick if(Option != PASS) { 237*11240Smckusick Wp = Dbuf = (short *)malloc(Bufsize); 238*11240Smckusick Cp = Cbuf = (char *)malloc(Bufsize); 239*11240Smckusick } 240*11240Smckusick Wct = Bufsize >> 1; 241*11240Smckusick Wc = Bufsize; 242*11240Smckusick 243*11240Smckusick if(Option == PASS && Rename) { 244*11240Smckusick err("Pass and Rename cannot be used together"); 245*11240Smckusick exit(2); 246*11240Smckusick } 247*11240Smckusick switch(Option) { 248*11240Smckusick 249*11240Smckusick case OUT: 250*11240Smckusick while(getname()) { 251*11240Smckusick if( mklong(Hdr.h_filesize) == 0L) { 252*11240Smckusick if ( Cflag ) 253*11240Smckusick writehdr(Chdr,CHARS+Hdr.h_namesize); 254*11240Smckusick else 255*11240Smckusick bwrite(&Hdr, HDRSIZE+Hdr.h_namesize); 256*11240Smckusick #ifdef RT 257*11240Smckusick if( (MERT) && (((Hdr.h_mode & Filetype) == S_IF1EXT) 258*11240Smckusick || ((Hdr.h_mode & Filetype) == S_IFEXT))) { 259*11240Smckusick actsize(); 260*11240Smckusick bwrite(&Hdr, HDRSIZE+Hdr.h_namesize); 261*11240Smckusick } 262*11240Smckusick #endif 263*11240Smckusick continue; 264*11240Smckusick } 265*11240Smckusick if((Ifile = open(Hdr.h_name, 0)) < 0) { 266*11240Smckusick err("<%s> ?\n", Hdr.h_name); 267*11240Smckusick continue; 268*11240Smckusick } 269*11240Smckusick if ( Cflag ) 270*11240Smckusick writehdr(Chdr,CHARS+Hdr.h_namesize); 271*11240Smckusick else 272*11240Smckusick bwrite(&Hdr, HDRSIZE+Hdr.h_namesize); 273*11240Smckusick #ifdef RT 274*11240Smckusick if( (MERT) && (((Hdr.h_mode & Filetype) == S_IF1EXT) 275*11240Smckusick || ((Hdr.h_mode & Filetype) == S_IFEXT))) { 276*11240Smckusick actsize(); 277*11240Smckusick bwrite(&Hdr, HDRSIZE+Hdr.h_namesize); 278*11240Smckusick } 279*11240Smckusick #endif 280*11240Smckusick for(filesz=mklong(Hdr.h_filesize); filesz>0; filesz-= 512){ 281*11240Smckusick ct = filesz>512? 512: filesz; 282*11240Smckusick if(read(Ifile, Cflag? BBuf: (char *)Buf, ct) < 0) { 283*11240Smckusick err("Cannot read %s\n", Hdr.h_name); 284*11240Smckusick continue; 285*11240Smckusick } 286*11240Smckusick Cflag? writehdr(BBuf,ct): bwrite(Buf,ct); 287*11240Smckusick } 288*11240Smckusick close(Ifile); 289*11240Smckusick if(Acc_time) 290*11240Smckusick utime(Hdr.h_name, &Statb.st_atime); 291*11240Smckusick if(Verbose) 292*11240Smckusick err("%s\n", Hdr.h_name); 293*11240Smckusick } 294*11240Smckusick strcpy(Hdr.h_name, "TRAILER!!!"); 295*11240Smckusick Hdr.h_magic = MAGIC; 296*11240Smckusick MKSHORT(Hdr.h_filesize, 0L); 297*11240Smckusick Hdr.h_namesize = strlen("TRAILER!!!") + 1; 298*11240Smckusick if ( Cflag ) { 299*11240Smckusick lng = 0; 300*11240Smckusick bintochar(lng); 301*11240Smckusick writehdr(Chdr,CHARS+Hdr.h_namesize); 302*11240Smckusick } 303*11240Smckusick else 304*11240Smckusick bwrite(&Hdr, HDRSIZE+Hdr.h_namesize); 305*11240Smckusick Cflag? writehdr(Cbuf, Bufsize): bwrite(Dbuf, Bufsize); 306*11240Smckusick break; 307*11240Smckusick 308*11240Smckusick case IN: 309*11240Smckusick pwd(); 310*11240Smckusick while(gethdr()) { 311*11240Smckusick Ofile = ckname(Hdr.h_name)? openout(Hdr.h_name): 0; 312*11240Smckusick for(filesz=mklong(Hdr.h_filesize); filesz>0; filesz-= 512){ 313*11240Smckusick ct = filesz>512? 512: filesz; 314*11240Smckusick Cflag? readhdr(BBuf, ct): bread(Buf, ct); 315*11240Smckusick if(Ofile) { 316*11240Smckusick if(Swap) 317*11240Smckusick swap(Buf, ct); 318*11240Smckusick if(write(Ofile, Cflag? BBuf: (char *)Buf, ct) < 0) { 319*11240Smckusick err("Cannot write %s\n", Hdr.h_name); 320*11240Smckusick continue; 321*11240Smckusick } 322*11240Smckusick } 323*11240Smckusick } 324*11240Smckusick if(Ofile) { 325*11240Smckusick close(Ofile); 326*11240Smckusick set_time(Cd_name, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime)); 327*11240Smckusick } 328*11240Smckusick if(!Select) 329*11240Smckusick continue; 330*11240Smckusick if(Verbose) 331*11240Smckusick if(Toc) 332*11240Smckusick pentry(Hdr.h_name); 333*11240Smckusick else 334*11240Smckusick puts(Hdr.h_name); 335*11240Smckusick else if(Toc) 336*11240Smckusick puts(Hdr.h_name); 337*11240Smckusick } 338*11240Smckusick break; 339*11240Smckusick 340*11240Smckusick case PASS: 341*11240Smckusick fullp = Fullname + strlen(Fullname); 342*11240Smckusick 343*11240Smckusick while(getname()) { 344*11240Smckusick if(!ckname(Hdr.h_name)) 345*11240Smckusick continue; 346*11240Smckusick strcpy(fullp, Hdr.h_name); 347*11240Smckusick 348*11240Smckusick if(Link 349*11240Smckusick && !A_directory 350*11240Smckusick && Dev == Statb.st_dev) { 351*11240Smckusick /* ??? && (Uid == Statb.st_uid || !Uid)) {*/ 352*11240Smckusick if(link(Hdr.h_name, Fullname) < 0) { /* missing dir.? */ 353*11240Smckusick unlink(Fullname); 354*11240Smckusick missdir(Fullname); 355*11240Smckusick if(link(Hdr.h_name, Fullname) < 0) { 356*11240Smckusick err( 357*11240Smckusick "Cannot link <%s> & <%s>\n", 358*11240Smckusick Hdr.h_name, Fullname); 359*11240Smckusick continue; 360*11240Smckusick } 361*11240Smckusick } 362*11240Smckusick set_time(Hdr.h_name, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime)); 363*11240Smckusick goto ckverbose; 364*11240Smckusick } 365*11240Smckusick if(!(Ofile = openout(Fullname))) 366*11240Smckusick continue; 367*11240Smckusick if((Ifile = open(Hdr.h_name, 0)) < 0) { 368*11240Smckusick err("<%s> ?\n", Hdr.h_name); 369*11240Smckusick close(Ofile); 370*11240Smckusick continue; 371*11240Smckusick } 372*11240Smckusick filesz = Statb.st_size; 373*11240Smckusick for(; filesz > 0; filesz -= 512) { 374*11240Smckusick ct = filesz>512? 512: filesz; 375*11240Smckusick if(read(Ifile, Buf, ct) < 0) { 376*11240Smckusick err("Cannot read %s\n", Hdr.h_name); 377*11240Smckusick break; 378*11240Smckusick } 379*11240Smckusick if(Ofile) 380*11240Smckusick if(write(Ofile, Buf, ct) < 0) { 381*11240Smckusick err("Cannot write %s\n", Hdr.h_name); 382*11240Smckusick break; 383*11240Smckusick } 384*11240Smckusick ++Blocks; 385*11240Smckusick } 386*11240Smckusick close(Ifile); 387*11240Smckusick if(Acc_time) 388*11240Smckusick utime(Hdr.h_name, &Statb.st_atime); 389*11240Smckusick if(Ofile) { 390*11240Smckusick close(Ofile); 391*11240Smckusick set_time(Fullname, Statb.st_atime, mklong(Hdr.h_mtime)); 392*11240Smckusick ckverbose: 393*11240Smckusick if(Verbose) 394*11240Smckusick puts(Fullname); 395*11240Smckusick } 396*11240Smckusick } 397*11240Smckusick } 398*11240Smckusick err("%ld blocks\n", Blocks * (Bufsize>>9)); 399*11240Smckusick exit(0); 400*11240Smckusick } 401*11240Smckusick usage() 402*11240Smckusick { 403*11240Smckusick err("Usage: cpio -o[acvB] <name-list >collection\n%s\n%s\n", 404*11240Smckusick " cpio -i[cdmrstuvB6] [pattern ...] <collection", 405*11240Smckusick " cpio -p[adlmruv] directory <name-list"); 406*11240Smckusick exit(2); 407*11240Smckusick } 408*11240Smckusick 409*11240Smckusick getname() 410*11240Smckusick { 411*11240Smckusick register char *namep = Name; 412*11240Smckusick long tlong; 413*11240Smckusick 414*11240Smckusick for(;;) { 415*11240Smckusick if(gets(namep) == NULL) 416*11240Smckusick return 0; 417*11240Smckusick if(*namep == '.' && namep[1] == '/') 418*11240Smckusick namep += 2; 419*11240Smckusick strcpy(Hdr.h_name, namep); 420*11240Smckusick if(stat(namep, &Statb) < 0) { 421*11240Smckusick err("< %s > ?\n", Hdr.h_name); 422*11240Smckusick continue; 423*11240Smckusick } 424*11240Smckusick A_directory = (Statb.st_mode & Filetype) == S_IFDIR; 425*11240Smckusick A_special = ((Statb.st_mode & Filetype) == S_IFBLK) 426*11240Smckusick || ((Statb.st_mode & Filetype) == S_IFCHR); 427*11240Smckusick #ifdef RT 428*11240Smckusick if(MERT) { 429*11240Smckusick One_extent = (Statb.st_mode & Filetype) == S_IF1EXT; 430*11240Smckusick Multi_extent = (Statb.st_mode & Filetype) == S_IFEXT; 431*11240Smckusick } 432*11240Smckusick #endif 433*11240Smckusick Hdr.h_magic = MAGIC; 434*11240Smckusick Hdr.h_namesize = strlen(Hdr.h_name) + 1; 435*11240Smckusick Hdr.h_uid = Statb.st_uid; 436*11240Smckusick Hdr.h_gid = Statb.st_gid; 437*11240Smckusick Hdr.h_dev = Statb.st_dev; 438*11240Smckusick Hdr.h_ino = Statb.st_ino; 439*11240Smckusick Hdr.h_mode = Statb.st_mode; 440*11240Smckusick MKSHORT(Hdr.h_mtime, Statb.st_mtime); 441*11240Smckusick Hdr.h_nlink = Statb.st_nlink; 442*11240Smckusick tlong = Hdr.h_mode & S_IFREG? Statb.st_size: 0L; 443*11240Smckusick MKSHORT(Hdr.h_filesize, tlong); 444*11240Smckusick Hdr.h_rdev = Statb.st_rdev; 445*11240Smckusick if(Cflag) 446*11240Smckusick bintochar(tlong); 447*11240Smckusick return 1; 448*11240Smckusick } 449*11240Smckusick } 450*11240Smckusick 451*11240Smckusick bintochar(t) 452*11240Smckusick long t; 453*11240Smckusick { 454*11240Smckusick sprintf(Chdr,"%.6o%.6ho%.6ho%.6ho%.6ho%.6ho%.6ho%.6ho%.11lo%.6ho%.11lo%s", 455*11240Smckusick MAGIC,Statb.st_dev,Statb.st_ino,Statb.st_mode,Statb.st_uid, 456*11240Smckusick Statb.st_gid,Statb.st_nlink,Statb.st_rdev & 00000177777, 457*11240Smckusick Statb.st_mtime,(short)strlen(Hdr.h_name)+1,t,Hdr.h_name); 458*11240Smckusick } 459*11240Smckusick 460*11240Smckusick chartobin() 461*11240Smckusick { 462*11240Smckusick sscanf(Chdr,"%6o%6ho%6ho%6ho%6ho%6ho%6ho%6ho%11lo%6ho%11lo", 463*11240Smckusick &Hdr.h_magic,&Hdr.h_dev,&Hdr.h_ino,&Hdr.h_mode,&Hdr.h_uid, 464*11240Smckusick &Hdr.h_gid,&Hdr.h_nlink,&Hdr.h_rdev,&Longtime,&Hdr.h_namesize, 465*11240Smckusick &Longfile); 466*11240Smckusick MKSHORT(Hdr.h_filesize, Longfile); 467*11240Smckusick MKSHORT(Hdr.h_mtime, Longtime); 468*11240Smckusick } 469*11240Smckusick 470*11240Smckusick gethdr() 471*11240Smckusick { 472*11240Smckusick 473*11240Smckusick if ( Cflag ) { 474*11240Smckusick readhdr(Chdr,CHARS); 475*11240Smckusick chartobin(); 476*11240Smckusick } 477*11240Smckusick else 478*11240Smckusick bread(&Hdr, HDRSIZE); 479*11240Smckusick 480*11240Smckusick if(Hdr.h_magic != MAGIC) { 481*11240Smckusick err("Out of phase--get help"); 482*11240Smckusick exit(2); 483*11240Smckusick } 484*11240Smckusick if(!Cflag) 485*11240Smckusick bread(Hdr.h_name, Hdr.h_namesize); 486*11240Smckusick else 487*11240Smckusick readhdr(Hdr.h_name, Hdr.h_namesize); 488*11240Smckusick if(Swap) 489*11240Smckusick swap(Hdr.h_name, Hdr.h_namesize); 490*11240Smckusick if(EQ(Hdr.h_name, "TRAILER!!!")) 491*11240Smckusick return 0; 492*11240Smckusick A_directory = (Hdr.h_mode & Filetype) == S_IFDIR; 493*11240Smckusick A_special =((Hdr.h_mode & Filetype) == S_IFBLK) 494*11240Smckusick || ((Hdr.h_mode & Filetype) == S_IFCHR); 495*11240Smckusick #ifdef RT 496*11240Smckusick if( (MERT) && (((Hdr.h_mode & Filetype) == S_IF1EXT) 497*11240Smckusick || ((Hdr.h_mode & Filetype) == S_IFEXT))) { 498*11240Smckusick One_extent = (Hdr.h_mode & Filetype) == S_IF1EXT; 499*11240Smckusick Multi_extent = (Hdr.h_mode & Filetype) == S_IFEXT; 500*11240Smckusick Actual_size[0] = Hdr.h_filesize[0]; 501*11240Smckusick Actual_size[1] = Hdr.h_filesize[1]; 502*11240Smckusick bread(&Hdr, HDRSIZE); 503*11240Smckusick if(Hdr.h_magic != MAGIC) { 504*11240Smckusick err("Out of phase--get MERT help"); 505*11240Smckusick exit(2); 506*11240Smckusick } 507*11240Smckusick bread(Hdr.h_name, Hdr.h_namesize); 508*11240Smckusick } 509*11240Smckusick #endif 510*11240Smckusick return 1; 511*11240Smckusick } 512*11240Smckusick 513*11240Smckusick ckname(namep) 514*11240Smckusick register char *namep; 515*11240Smckusick { 516*11240Smckusick ++Select; 517*11240Smckusick if(!nmatch(namep, Pattern)) { 518*11240Smckusick Select = 0; 519*11240Smckusick return 0; 520*11240Smckusick } 521*11240Smckusick if(Rename && !A_directory) { 522*11240Smckusick fprintf(Wtty, "Rename <%s>\n", namep); 523*11240Smckusick fflush(Wtty); 524*11240Smckusick fgets(namep, 128, Rtty); 525*11240Smckusick if(feof(Rtty)) 526*11240Smckusick exit(2); 527*11240Smckusick namep[strlen(namep) - 1] = '\0'; 528*11240Smckusick if(EQ(namep, "")) { 529*11240Smckusick printf("Skipped\n"); 530*11240Smckusick return 0; 531*11240Smckusick } 532*11240Smckusick } 533*11240Smckusick return !Toc; 534*11240Smckusick } 535*11240Smckusick 536*11240Smckusick openout(namep) 537*11240Smckusick register char *namep; 538*11240Smckusick { 539*11240Smckusick register f; 540*11240Smckusick register char *np; 541*11240Smckusick 542*11240Smckusick if(!strncmp(namep, "./", 2)) 543*11240Smckusick namep += 2; 544*11240Smckusick np = namep; 545*11240Smckusick if(Option == IN) 546*11240Smckusick Cd_name = namep = cd(namep); 547*11240Smckusick if(A_directory) { 548*11240Smckusick if(!Dir 549*11240Smckusick || Rename 550*11240Smckusick || EQ(namep, ".") 551*11240Smckusick || EQ(namep, "..") 552*11240Smckusick || stat(namep, &Xstatb) == 0) 553*11240Smckusick return 0; 554*11240Smckusick 555*11240Smckusick if(!makdir(namep)) { 556*11240Smckusick missdir(namep); 557*11240Smckusick } 558*11240Smckusick ret: 559*11240Smckusick chmod(namep, Hdr.h_mode); 560*11240Smckusick if(Uid == 0) 561*11240Smckusick chown(namep, Hdr.h_uid, Hdr.h_gid); 562*11240Smckusick set_time(namep, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime)); 563*11240Smckusick return 0; 564*11240Smckusick } 565*11240Smckusick if(Hdr.h_nlink > 1) 566*11240Smckusick if(!postml(namep, np)) 567*11240Smckusick return 0; 568*11240Smckusick if(A_special) { 569*11240Smckusick s_again: 570*11240Smckusick if(mknod(namep, Hdr.h_mode, Hdr.h_rdev) < 0) { 571*11240Smckusick if(missdir(namep)) 572*11240Smckusick goto s_again; 573*11240Smckusick err("Cannot mknod <%s>\n", namep); 574*11240Smckusick return 0; 575*11240Smckusick } 576*11240Smckusick goto ret; 577*11240Smckusick } 578*11240Smckusick if(stat(namep, &Xstatb) == 0) { 579*11240Smckusick if(Uncond && !(Xstatb.st_mode & S_IWRITE)) 580*11240Smckusick unlink(namep); 581*11240Smckusick if(!Uncond && (mklong(Hdr.h_mtime) < Xstatb.st_mtime)) { 582*11240Smckusick err("current <%s> newer\n", namep); 583*11240Smckusick return 0; 584*11240Smckusick } 585*11240Smckusick } 586*11240Smckusick if(Option == PASS 587*11240Smckusick && Hdr.h_ino == Xstatb.st_ino 588*11240Smckusick && Hdr.h_dev == Xstatb.st_dev) { 589*11240Smckusick err("Attempt to pass file to self!\n"); 590*11240Smckusick exit(2); 591*11240Smckusick } 592*11240Smckusick #ifdef RT 593*11240Smckusick one_again: 594*11240Smckusick if(One_extent || Multi_extent) { 595*11240Smckusick if((f = falloc(namep, Hdr.h_mode, Hdr.h_filesize[0].long_size)) < 0) { 596*11240Smckusick if(missdir(namep)) 597*11240Smckusick goto one_again; 598*11240Smckusick err("Cannot create <%s> (errno:%d)\n", namep, errno); 599*11240Smckusick return 0; 600*11240Smckusick } 601*11240Smckusick if(filespace < Hdr.h_filesize[0].long_size){ 602*11240Smckusick err("Cannot create contiguous file <%s> proper size\n", namep); 603*11240Smckusick err(" <%s> will be created as a regular file\n", namep); 604*11240Smckusick if(unlink(Fullname) != 0) 605*11240Smckusick err("<%s> not removed\n", namep); 606*11240Smckusick New_mode = Hdr.h_mode & Remove_mode; 607*11240Smckusick New_mode = New_mode | S_IFREG; 608*11240Smckusick once_again: 609*11240Smckusick if((f = creat(namep, New_mode)) < 0){ 610*11240Smckusick if(missdir(namep)) 611*11240Smckusick goto once_again; 612*11240Smckusick err("Cannot create <%s> (errno:%d)\n", namep, errno); 613*11240Smckusick return (0); 614*11240Smckusick } 615*11240Smckusick } 616*11240Smckusick } 617*11240Smckusick #endif 618*11240Smckusick #ifdef RT 619*11240Smckusick if(MERT && (One_extent || Multi_extent)) 620*11240Smckusick goto skip_c; 621*11240Smckusick #endif 622*11240Smckusick c_again: 623*11240Smckusick if((f = creat(namep, Hdr.h_mode)) < 0) { 624*11240Smckusick if(missdir(namep)) 625*11240Smckusick goto c_again; 626*11240Smckusick err("Cannot create <%s> (errno:%d)\n", namep, errno); 627*11240Smckusick return 0; 628*11240Smckusick } 629*11240Smckusick #ifdef RT 630*11240Smckusick skip_c: 631*11240Smckusick #endif 632*11240Smckusick if(Uid == 0) 633*11240Smckusick chown(namep, Hdr.h_uid, Hdr.h_gid); 634*11240Smckusick return f; 635*11240Smckusick } 636*11240Smckusick 637*11240Smckusick bread(b, c) 638*11240Smckusick register c; 639*11240Smckusick register short *b; 640*11240Smckusick { 641*11240Smckusick static nleft = 0; 642*11240Smckusick static short *ip; 643*11240Smckusick register short *p = ip; 644*11240Smckusick 645*11240Smckusick c = (c+1)>>1; 646*11240Smckusick while(c--) { 647*11240Smckusick if(!nleft) { 648*11240Smckusick again: 649*11240Smckusick if(read(Input, Dbuf, Bufsize)!=Bufsize) { 650*11240Smckusick Input = chgreel(0, Input); 651*11240Smckusick goto again; 652*11240Smckusick } 653*11240Smckusick nleft = Bufsize >> 1; 654*11240Smckusick p = Dbuf; 655*11240Smckusick ++Blocks; 656*11240Smckusick } 657*11240Smckusick *b++ = *p++; 658*11240Smckusick --nleft; 659*11240Smckusick } 660*11240Smckusick ip = p; 661*11240Smckusick } 662*11240Smckusick 663*11240Smckusick readhdr(b, c) 664*11240Smckusick register c; 665*11240Smckusick register char *b; 666*11240Smckusick { 667*11240Smckusick static nleft = 0; 668*11240Smckusick static char *ip; 669*11240Smckusick register char *p = ip; 670*11240Smckusick 671*11240Smckusick while(c--) { 672*11240Smckusick if(!nleft) { 673*11240Smckusick again: 674*11240Smckusick if(read(Input, Cbuf, Bufsize) != Bufsize) { 675*11240Smckusick Input = chgreel(0, Input); 676*11240Smckusick goto again; 677*11240Smckusick } 678*11240Smckusick nleft = Bufsize; 679*11240Smckusick p = Cbuf; 680*11240Smckusick ++Blocks; 681*11240Smckusick } 682*11240Smckusick *b++ = *p++; 683*11240Smckusick --nleft; 684*11240Smckusick } 685*11240Smckusick ip = p; 686*11240Smckusick } 687*11240Smckusick 688*11240Smckusick bwrite(rp, c) 689*11240Smckusick register short *rp; 690*11240Smckusick register c; 691*11240Smckusick { 692*11240Smckusick register short *wp = Wp; 693*11240Smckusick 694*11240Smckusick c = (c+1) >> 1; 695*11240Smckusick while(c--) { 696*11240Smckusick if(!Wct) { 697*11240Smckusick again: 698*11240Smckusick if(write(Output, Dbuf, Bufsize)<0) { 699*11240Smckusick Output = chgreel(1, Output); 700*11240Smckusick goto again; 701*11240Smckusick } 702*11240Smckusick Wct = Bufsize >> 1; 703*11240Smckusick wp = Dbuf; 704*11240Smckusick ++Blocks; 705*11240Smckusick } 706*11240Smckusick *wp++ = *rp++; 707*11240Smckusick --Wct; 708*11240Smckusick } 709*11240Smckusick Wp = wp; 710*11240Smckusick } 711*11240Smckusick writehdr(rp,c) 712*11240Smckusick register char *rp; 713*11240Smckusick register c; 714*11240Smckusick { 715*11240Smckusick register char *cp = Cp; 716*11240Smckusick 717*11240Smckusick while(c--) { 718*11240Smckusick if(!Wc) { 719*11240Smckusick again: 720*11240Smckusick if(write(Output,Cbuf,Bufsize)<0) { 721*11240Smckusick Output = chgreel(1, Output); 722*11240Smckusick goto again; 723*11240Smckusick } 724*11240Smckusick Wc = Bufsize; 725*11240Smckusick cp = Cbuf; 726*11240Smckusick ++Blocks; 727*11240Smckusick } 728*11240Smckusick *cp++ = *rp++; 729*11240Smckusick --Wc; 730*11240Smckusick } 731*11240Smckusick Cp = cp; 732*11240Smckusick } 733*11240Smckusick 734*11240Smckusick 735*11240Smckusick postml(namep, np) 736*11240Smckusick register char *namep, *np; 737*11240Smckusick { 738*11240Smckusick register i; 739*11240Smckusick static struct ml { 740*11240Smckusick short m_dev, 741*11240Smckusick m_ino; 742*11240Smckusick char m_name[2]; 743*11240Smckusick } *ml[LINKS]; 744*11240Smckusick static mlinks = 0; 745*11240Smckusick char *mlp; 746*11240Smckusick 747*11240Smckusick for(i = 0; i < mlinks; ++i) { 748*11240Smckusick if(mlinks == LINKS) break; 749*11240Smckusick if(ml[i]->m_ino==Hdr.h_ino && 750*11240Smckusick ml[i]->m_dev==Hdr.h_dev) { 751*11240Smckusick if(Verbose) 752*11240Smckusick printf("%s linked to %s\n", ml[i]->m_name, 753*11240Smckusick np); 754*11240Smckusick unlink(namep); 755*11240Smckusick if(Option == IN) { 756*11240Smckusick Fullname[Pathend] = '\0'; 757*11240Smckusick strcat(Fullname, ml[i]->m_name); 758*11240Smckusick mlp = Fullname; 759*11240Smckusick } else 760*11240Smckusick mlp = ml[i]->m_name; 761*11240Smckusick l_again: 762*11240Smckusick if(link(mlp, namep) < 0) { 763*11240Smckusick if(missdir(np)) 764*11240Smckusick goto l_again; 765*11240Smckusick err("Cannot link <%s>&<%s>.\n", 766*11240Smckusick ml[i]->m_name, np); 767*11240Smckusick } 768*11240Smckusick set_time(namep, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime)); 769*11240Smckusick return 0; 770*11240Smckusick } 771*11240Smckusick } 772*11240Smckusick if(mlinks == LINKS 773*11240Smckusick || !(ml[mlinks] = (struct ml *)malloc(strlen(np) + 2 + sizeof(struct ml)))) { 774*11240Smckusick static int first=1; 775*11240Smckusick 776*11240Smckusick if(first) 777*11240Smckusick if(mlinks == LINKS) 778*11240Smckusick err("Too many links\n"); 779*11240Smckusick else 780*11240Smckusick err("No memory for links\n"); 781*11240Smckusick mlinks = LINKS; 782*11240Smckusick first = 0; 783*11240Smckusick return 1; 784*11240Smckusick } 785*11240Smckusick ml[mlinks]->m_dev = Hdr.h_dev; 786*11240Smckusick ml[mlinks]->m_ino = Hdr.h_ino; 787*11240Smckusick strcpy(ml[mlinks]->m_name, np); 788*11240Smckusick ++mlinks; 789*11240Smckusick return 1; 790*11240Smckusick } 791*11240Smckusick 792*11240Smckusick pentry(namep) 793*11240Smckusick register char *namep; 794*11240Smckusick { 795*11240Smckusick 796*11240Smckusick register i; 797*11240Smckusick static short lastid = -1; 798*11240Smckusick #include <pwd.h> 799*11240Smckusick static struct passwd *pw; 800*11240Smckusick struct passwd *getpwuid(); 801*11240Smckusick static char tbuf[32]; 802*11240Smckusick 803*11240Smckusick printf("%-7o", Hdr.h_mode & 0177777); 804*11240Smckusick if(lastid == Hdr.h_uid) 805*11240Smckusick printf("%-6s", pw->pw_name); 806*11240Smckusick else { 807*11240Smckusick setpwent(); 808*11240Smckusick if(pw = getpwuid(Hdr.h_uid)) { 809*11240Smckusick printf("%-6s", pw->pw_name); 810*11240Smckusick lastid = Hdr.h_uid; 811*11240Smckusick } else { 812*11240Smckusick printf("%-6d", Hdr.h_uid); 813*11240Smckusick lastid = -1; 814*11240Smckusick } 815*11240Smckusick } 816*11240Smckusick printf("%7ld ", mklong(Hdr.h_filesize)); 817*11240Smckusick U.l = mklong(Hdr.h_mtime); 818*11240Smckusick strcpy(tbuf, ctime(&U.l)); 819*11240Smckusick tbuf[24] = '\0'; 820*11240Smckusick printf(" %s %s\n", &tbuf[4], namep); 821*11240Smckusick } 822*11240Smckusick 823*11240Smckusick nmatch(s, pat) 824*11240Smckusick char *s, **pat; 825*11240Smckusick { 826*11240Smckusick if(EQ(*pat, "*")) 827*11240Smckusick return 1; 828*11240Smckusick while(*pat) { 829*11240Smckusick if((**pat == '!' && !gmatch(s, *pat+1)) 830*11240Smckusick || gmatch(s, *pat)) 831*11240Smckusick return 1; 832*11240Smckusick ++pat; 833*11240Smckusick } 834*11240Smckusick return 0; 835*11240Smckusick } 836*11240Smckusick gmatch(s, p) 837*11240Smckusick register char *s, *p; 838*11240Smckusick { 839*11240Smckusick register int c; 840*11240Smckusick register cc, ok, lc, scc; 841*11240Smckusick 842*11240Smckusick scc = *s; 843*11240Smckusick lc = 077777; 844*11240Smckusick switch (c = *p) { 845*11240Smckusick 846*11240Smckusick case '[': 847*11240Smckusick ok = 0; 848*11240Smckusick while (cc = *++p) { 849*11240Smckusick switch (cc) { 850*11240Smckusick 851*11240Smckusick case ']': 852*11240Smckusick if (ok) 853*11240Smckusick return(gmatch(++s, ++p)); 854*11240Smckusick else 855*11240Smckusick return(0); 856*11240Smckusick 857*11240Smckusick case '-': 858*11240Smckusick ok |= (lc <= scc & scc <= (cc=p[1])); 859*11240Smckusick } 860*11240Smckusick if (scc==(lc=cc)) ok++; 861*11240Smckusick } 862*11240Smckusick return(0); 863*11240Smckusick 864*11240Smckusick case '?': 865*11240Smckusick caseq: 866*11240Smckusick if(scc) return(gmatch(++s, ++p)); 867*11240Smckusick return(0); 868*11240Smckusick case '*': 869*11240Smckusick return(umatch(s, ++p)); 870*11240Smckusick case 0: 871*11240Smckusick return(!scc); 872*11240Smckusick } 873*11240Smckusick if (c==scc) goto caseq; 874*11240Smckusick return(0); 875*11240Smckusick } 876*11240Smckusick 877*11240Smckusick umatch(s, p) 878*11240Smckusick register char *s, *p; 879*11240Smckusick { 880*11240Smckusick if(*p==0) return(1); 881*11240Smckusick while(*s) 882*11240Smckusick if (gmatch(s++,p)) return(1); 883*11240Smckusick return(0); 884*11240Smckusick } 885*11240Smckusick 886*11240Smckusick makdir(namep) 887*11240Smckusick register char *namep; 888*11240Smckusick { 889*11240Smckusick static status; 890*11240Smckusick register pid; 891*11240Smckusick 892*11240Smckusick if(pid = fork()) 893*11240Smckusick while(wait(&status) != pid); 894*11240Smckusick else { 895*11240Smckusick close(2); 896*11240Smckusick execl("/bin/mkdir", "mkdir", namep, 0); 897*11240Smckusick exit(2); 898*11240Smckusick } 899*11240Smckusick return ((status>>8) & 0377)? 0: 1; 900*11240Smckusick } 901*11240Smckusick 902*11240Smckusick swap(buf, ct) 903*11240Smckusick register ct; 904*11240Smckusick register union swp { short shortw; char charv[2]; } *buf; 905*11240Smckusick { 906*11240Smckusick register char c; 907*11240Smckusick 908*11240Smckusick ct = (ct + 1) >> 1; 909*11240Smckusick 910*11240Smckusick while(ct--) { 911*11240Smckusick c = buf->charv[0]; 912*11240Smckusick buf->charv[0] = buf->charv[1]; 913*11240Smckusick buf->charv[1] = c; 914*11240Smckusick ++buf; 915*11240Smckusick } 916*11240Smckusick } 917*11240Smckusick set_time(namep, atime, mtime) 918*11240Smckusick register *namep; 919*11240Smckusick long atime, mtime; 920*11240Smckusick { 921*11240Smckusick static long timevec[2]; 922*11240Smckusick 923*11240Smckusick if(!Mod_time) 924*11240Smckusick return; 925*11240Smckusick timevec[0] = atime; 926*11240Smckusick timevec[1] = mtime; 927*11240Smckusick utime(namep, timevec); 928*11240Smckusick } 929*11240Smckusick chgreel(x, fl) 930*11240Smckusick { 931*11240Smckusick register f; 932*11240Smckusick char str[22]; 933*11240Smckusick FILE *devtty; 934*11240Smckusick struct stat statb; 935*11240Smckusick 936*11240Smckusick err("errno: %d, ", errno); 937*11240Smckusick err("Can't %s\n", x? "write output": "read input"); 938*11240Smckusick fstat(fl, &statb); 939*11240Smckusick #ifdef RT 940*11240Smckusick if(!MERT){ 941*11240Smckusick if((statb.st_mode&S_IFMT) != S_IFCHR) 942*11240Smckusick exit(2); 943*11240Smckusick } 944*11240Smckusick else if((statb.st_mode & (S_IFBLK|S_IFREC))==0) 945*11240Smckusick exit(2); 946*11240Smckusick #endif 947*11240Smckusick #ifndef RT 948*11240Smckusick if((statb.st_mode&S_IFMT) != S_IFCHR) 949*11240Smckusick exit(2); 950*11240Smckusick #endif 951*11240Smckusick again: 952*11240Smckusick err("If you want to go on, type device/file name when ready\n"); 953*11240Smckusick devtty = fopen("/dev/tty", "r"); 954*11240Smckusick fgets(str, 20, devtty); 955*11240Smckusick str[strlen(str) - 1] = '\0'; 956*11240Smckusick if(!*str) 957*11240Smckusick exit(2); 958*11240Smckusick close(fl); 959*11240Smckusick if((f = open(str, x? 1: 0)) < 0) { 960*11240Smckusick err("That didn't work"); 961*11240Smckusick fclose(devtty); 962*11240Smckusick goto again; 963*11240Smckusick } 964*11240Smckusick return f; 965*11240Smckusick } 966*11240Smckusick missdir(namep) 967*11240Smckusick register char *namep; 968*11240Smckusick { 969*11240Smckusick register char *np; 970*11240Smckusick register ct = 0; 971*11240Smckusick 972*11240Smckusick if(!Dir) 973*11240Smckusick return 0; 974*11240Smckusick for(np = namep; *np; ++np) 975*11240Smckusick if(*np == '/') { 976*11240Smckusick *np = '\0'; 977*11240Smckusick if(stat(namep, &Xstatb) == -1) 978*11240Smckusick makdir(namep), ++ct; 979*11240Smckusick *np = '/'; 980*11240Smckusick } 981*11240Smckusick return ct; 982*11240Smckusick } 983*11240Smckusick err(a, b, c) 984*11240Smckusick { 985*11240Smckusick fprintf(stderr, a, b, c); 986*11240Smckusick } 987*11240Smckusick pwd() 988*11240Smckusick { 989*11240Smckusick FILE *dir; 990*11240Smckusick 991*11240Smckusick dir = popen("pwd", "r"); 992*11240Smckusick fgets(Fullname, 256, dir); 993*11240Smckusick if(pclose(dir)) 994*11240Smckusick exit(2); 995*11240Smckusick Pathend = strlen(Fullname); 996*11240Smckusick Fullname[Pathend - 1] = '/'; 997*11240Smckusick } 998*11240Smckusick char * cd(n) 999*11240Smckusick register char *n; 1000*11240Smckusick { 1001*11240Smckusick char *p_save = Name, *n_save = n, *p_end = 0; 1002*11240Smckusick register char *p = Name; 1003*11240Smckusick static char dotdot[]="../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../"; 1004*11240Smckusick int slashes; 1005*11240Smckusick 1006*11240Smckusick if(*n == '/') /* don't try to chdir on full pathnames */ 1007*11240Smckusick return n; 1008*11240Smckusick for(; *p && *n == *p; ++p, ++n) { /* whatever part of strings == */ 1009*11240Smckusick if(*p == '/') 1010*11240Smckusick p_save = p+1, n_save = n+1; 1011*11240Smckusick } 1012*11240Smckusick 1013*11240Smckusick p = p_save; 1014*11240Smckusick *p++ = '\0'; 1015*11240Smckusick for(slashes = 0; *p; ++p) { /* if prev is longer, chdir("..") */ 1016*11240Smckusick if(*p == '/') 1017*11240Smckusick ++slashes; 1018*11240Smckusick } 1019*11240Smckusick p = p_save; 1020*11240Smckusick if(slashes) { 1021*11240Smckusick slashes = slashes * 3 - 1; 1022*11240Smckusick dotdot[slashes] = '\0'; 1023*11240Smckusick chdir(dotdot); 1024*11240Smckusick dotdot[slashes] = '/'; 1025*11240Smckusick } 1026*11240Smckusick 1027*11240Smckusick n = n_save; 1028*11240Smckusick for(; *n; ++n, ++p) { 1029*11240Smckusick *p = *n; 1030*11240Smckusick if(*n == '/') 1031*11240Smckusick p_end = p+1, n_save = n+1; 1032*11240Smckusick } 1033*11240Smckusick *p = '\0'; 1034*11240Smckusick 1035*11240Smckusick if(p_end) { 1036*11240Smckusick *p_end = '\0'; 1037*11240Smckusick if(chdir(p_save) == -1) { 1038*11240Smckusick if(!missdir(p_save)) { 1039*11240Smckusick cd_err: 1040*11240Smckusick err("Cannot chdir (no `d' option)\n"); 1041*11240Smckusick exit(2); 1042*11240Smckusick } else if(chdir(p_save) == -1) 1043*11240Smckusick goto cd_err; 1044*11240Smckusick } 1045*11240Smckusick } else 1046*11240Smckusick *p_save = '\0'; 1047*11240Smckusick return n_save; 1048*11240Smckusick } 1049*11240Smckusick #ifdef RT 1050*11240Smckusick actsize() 1051*11240Smckusick { 1052*11240Smckusick } 1053*11240Smckusick #endif 1054