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