1 #ifndef lint 2 static char sccsid[] = "@(#)ar.c 4.4 06/10/83"; 3 #endif 4 5 /* 6 * ar - portable (ascii) format version 7 */ 8 #include <sys/types.h> 9 #include <sys/stat.h> 10 #include <sys/time.h> 11 12 #include <stdio.h> 13 #include <ar.h> 14 #include <signal.h> 15 16 struct stat stbuf; 17 struct ar_hdr arbuf; 18 struct lar_hdr { 19 char lar_name[16]; 20 long lar_date; 21 u_short lar_uid; 22 u_short lar_gid; 23 u_short lar_mode; 24 long lar_size; 25 } larbuf; 26 27 #define SKIP 1 28 #define IODD 2 29 #define OODD 4 30 #define HEAD 8 31 32 char *man = { "mrxtdpq" }; 33 char *opt = { "uvnbailo" }; 34 35 int signum[] = {SIGHUP, SIGINT, SIGQUIT, 0}; 36 int sigdone(); 37 long lseek(); 38 int rcmd(); 39 int dcmd(); 40 int xcmd(); 41 int tcmd(); 42 int pcmd(); 43 int mcmd(); 44 int qcmd(); 45 int (*comfun)(); 46 char flg[26]; 47 char **namv; 48 int namc; 49 char *arnam; 50 char *ponam; 51 char *tmpnam = { "/tmp/vXXXXX" }; 52 char *tmp1nam = { "/tmp/v1XXXXX" }; 53 char *tmp2nam = { "/tmp/v2XXXXX" }; 54 char *tfnam; 55 char *tf1nam; 56 char *tf2nam; 57 char *file; 58 char name[16]; 59 int af; 60 int tf; 61 int tf1; 62 int tf2; 63 int qf; 64 int bastate; 65 char buf[BUFSIZ]; 66 67 char *trim(); 68 char *mktemp(); 69 char *ctime(); 70 71 main(argc, argv) 72 char *argv[]; 73 { 74 register i; 75 register char *cp; 76 77 for(i=0; signum[i]; i++) 78 if(signal(signum[i], SIG_IGN) != SIG_IGN) 79 signal(signum[i], sigdone); 80 if(argc < 3) 81 usage(); 82 cp = argv[1]; 83 for(cp = argv[1]; *cp; cp++) 84 switch(*cp) { 85 case 'o': 86 case 'l': 87 case 'v': 88 case 'u': 89 case 'n': 90 case 'a': 91 case 'b': 92 case 'c': 93 case 'i': 94 flg[*cp - 'a']++; 95 continue; 96 97 case 'r': 98 setcom(rcmd); 99 continue; 100 101 case 'd': 102 setcom(dcmd); 103 continue; 104 105 case 'x': 106 setcom(xcmd); 107 continue; 108 109 case 't': 110 setcom(tcmd); 111 continue; 112 113 case 'p': 114 setcom(pcmd); 115 continue; 116 117 case 'm': 118 setcom(mcmd); 119 continue; 120 121 case 'q': 122 setcom(qcmd); 123 continue; 124 125 default: 126 fprintf(stderr, "ar: bad option `%c'\n", *cp); 127 done(1); 128 } 129 if(flg['l'-'a']) { 130 tmpnam = "vXXXXX"; 131 tmp1nam = "v1XXXXX"; 132 tmp2nam = "v2XXXXX"; 133 } 134 if(flg['i'-'a']) 135 flg['b'-'a']++; 136 if(flg['a'-'a'] || flg['b'-'a']) { 137 bastate = 1; 138 ponam = trim(argv[2]); 139 argv++; 140 argc--; 141 if(argc < 3) 142 usage(); 143 } 144 arnam = argv[2]; 145 namv = argv+3; 146 namc = argc-3; 147 if(comfun == 0) { 148 if(flg['u'-'a'] == 0) { 149 fprintf(stderr, "ar: one of [%s] must be specified\n", man); 150 done(1); 151 } 152 setcom(rcmd); 153 } 154 (*comfun)(); 155 done(notfound()); 156 } 157 158 setcom(fun) 159 int (*fun)(); 160 { 161 162 if(comfun != 0) { 163 fprintf(stderr, "ar: only one of [%s] allowed\n", man); 164 done(1); 165 } 166 comfun = fun; 167 } 168 169 rcmd() 170 { 171 register f; 172 173 init(); 174 getaf(); 175 while(!getdir()) { 176 bamatch(); 177 if(namc == 0 || match()) { 178 f = stats(); 179 if(f < 0) { 180 if(namc) 181 fprintf(stderr, "ar: cannot open %s\n", file); 182 goto cp; 183 } 184 if(flg['u'-'a']) 185 if(stbuf.st_mtime <= larbuf.lar_date) { 186 close(f); 187 goto cp; 188 } 189 mesg('r'); 190 copyfil(af, -1, IODD+SKIP); 191 movefil(f); 192 continue; 193 } 194 cp: 195 mesg('c'); 196 copyfil(af, tf, IODD+OODD+HEAD); 197 } 198 cleanup(); 199 } 200 201 dcmd() 202 { 203 204 init(); 205 if(getaf()) 206 noar(); 207 while(!getdir()) { 208 if(match()) { 209 mesg('d'); 210 copyfil(af, -1, IODD+SKIP); 211 continue; 212 } 213 mesg('c'); 214 copyfil(af, tf, IODD+OODD+HEAD); 215 } 216 install(); 217 } 218 219 xcmd() 220 { 221 register f; 222 struct timeval tv[2]; 223 224 if(getaf()) 225 noar(); 226 while(!getdir()) { 227 if(namc == 0 || match()) { 228 f = creat(file, larbuf.lar_mode & 0777); 229 if(f < 0) { 230 fprintf(stderr, "ar: %s cannot create\n", file); 231 goto sk; 232 } 233 mesg('x'); 234 copyfil(af, f, IODD); 235 close(f); 236 if (flg['o'-'a']) { 237 tv[0].tv_sec = tv[1].tv_sec = larbuf.lar_date; 238 tv[0].tv_usec = tv[1].tv_usec = 0; 239 utimes(file, tv); 240 } 241 continue; 242 } 243 sk: 244 mesg('c'); 245 copyfil(af, -1, IODD+SKIP); 246 if (namc > 0 && !morefil()) 247 done(0); 248 } 249 } 250 251 pcmd() 252 { 253 254 if(getaf()) 255 noar(); 256 while(!getdir()) { 257 if(namc == 0 || match()) { 258 if(flg['v'-'a']) { 259 printf("\n<%s>\n\n", file); 260 fflush(stdout); 261 } 262 copyfil(af, 1, IODD); 263 continue; 264 } 265 copyfil(af, -1, IODD+SKIP); 266 } 267 } 268 269 mcmd() 270 { 271 272 init(); 273 if(getaf()) 274 noar(); 275 tf2nam = mktemp(tmp2nam); 276 close(creat(tf2nam, 0600)); 277 tf2 = open(tf2nam, 2); 278 if(tf2 < 0) { 279 fprintf(stderr, "ar: cannot create third temp\n"); 280 done(1); 281 } 282 while(!getdir()) { 283 bamatch(); 284 if(match()) { 285 mesg('m'); 286 copyfil(af, tf2, IODD+OODD+HEAD); 287 continue; 288 } 289 mesg('c'); 290 copyfil(af, tf, IODD+OODD+HEAD); 291 } 292 install(); 293 } 294 295 tcmd() 296 { 297 298 if(getaf()) 299 noar(); 300 while(!getdir()) { 301 if(namc == 0 || match()) { 302 if(flg['v'-'a']) 303 longt(); 304 printf("%s\n", trim(file)); 305 } 306 copyfil(af, -1, IODD+SKIP); 307 } 308 } 309 310 qcmd() 311 { 312 register i, f; 313 314 if (flg['a'-'a'] || flg['b'-'a']) { 315 fprintf(stderr, "ar: abi not allowed with q\n"); 316 done(1); 317 } 318 getqf(); 319 for(i=0; signum[i]; i++) 320 signal(signum[i], SIG_IGN); 321 lseek(qf, 0l, 2); 322 for(i=0; i<namc; i++) { 323 file = namv[i]; 324 if(file == 0) 325 continue; 326 namv[i] = 0; 327 mesg('q'); 328 f = stats(); 329 if(f < 0) { 330 fprintf(stderr, "ar: %s cannot open\n", file); 331 continue; 332 } 333 tf = qf; 334 movefil(f); 335 qf = tf; 336 } 337 } 338 339 init() 340 { 341 342 tfnam = mktemp(tmpnam); 343 close(creat(tfnam, 0600)); 344 tf = open(tfnam, 2); 345 if(tf < 0) { 346 fprintf(stderr, "ar: cannot create temp file\n"); 347 done(1); 348 } 349 if (write(tf, ARMAG, SARMAG) != SARMAG) 350 wrerr(); 351 } 352 353 getaf() 354 { 355 char mbuf[SARMAG]; 356 357 af = open(arnam, 0); 358 if(af < 0) 359 return(1); 360 if (read(af, mbuf, SARMAG) != SARMAG || strncmp(mbuf, ARMAG, SARMAG)) { 361 fprintf(stderr, "ar: %s not in archive format\n", arnam); 362 done(1); 363 } 364 return(0); 365 } 366 367 getqf() 368 { 369 char mbuf[SARMAG]; 370 371 if ((qf = open(arnam, 2)) < 0) { 372 if(!flg['c'-'a']) 373 fprintf(stderr, "ar: creating %s\n", arnam); 374 if ((qf = creat(arnam, 0666)) < 0) { 375 fprintf(stderr, "ar: cannot create %s\n", arnam); 376 done(1); 377 } 378 if (write(qf, ARMAG, SARMAG) != SARMAG) 379 wrerr(); 380 } else if (read(qf, mbuf, SARMAG) != SARMAG 381 || strncmp(mbuf, ARMAG, SARMAG)) { 382 fprintf(stderr, "ar: %s not in archive format\n", arnam); 383 done(1); 384 } 385 } 386 387 usage() 388 { 389 printf("usage: ar [%s][%s] archive files ...\n", man, opt); 390 done(1); 391 } 392 393 noar() 394 { 395 396 fprintf(stderr, "ar: %s does not exist\n", arnam); 397 done(1); 398 } 399 400 sigdone() 401 { 402 done(100); 403 } 404 405 done(c) 406 { 407 408 if(tfnam) 409 unlink(tfnam); 410 if(tf1nam) 411 unlink(tf1nam); 412 if(tf2nam) 413 unlink(tf2nam); 414 exit(c); 415 } 416 417 notfound() 418 { 419 register i, n; 420 421 n = 0; 422 for(i=0; i<namc; i++) 423 if(namv[i]) { 424 fprintf(stderr, "ar: %s not found\n", namv[i]); 425 n++; 426 } 427 return(n); 428 } 429 430 morefil() 431 { 432 register i, n; 433 434 n = 0; 435 for(i=0; i<namc; i++) 436 if(namv[i]) 437 n++; 438 return(n); 439 } 440 441 cleanup() 442 { 443 register i, f; 444 445 for(i=0; i<namc; i++) { 446 file = namv[i]; 447 if(file == 0) 448 continue; 449 namv[i] = 0; 450 mesg('a'); 451 f = stats(); 452 if(f < 0) { 453 fprintf(stderr, "ar: %s cannot open\n", file); 454 continue; 455 } 456 movefil(f); 457 } 458 install(); 459 } 460 461 install() 462 { 463 register i; 464 465 for(i=0; signum[i]; i++) 466 signal(signum[i], SIG_IGN); 467 if(af < 0) 468 if(!flg['c'-'a']) 469 fprintf(stderr, "ar: creating %s\n", arnam); 470 close(af); 471 af = creat(arnam, 0666); 472 if(af < 0) { 473 fprintf(stderr, "ar: cannot create %s\n", arnam); 474 done(1); 475 } 476 if(tfnam) { 477 lseek(tf, 0l, 0); 478 while((i = read(tf, buf, BUFSIZ)) > 0) 479 if (write(af, buf, i) != i) 480 wrerr(); 481 } 482 if(tf2nam) { 483 lseek(tf2, 0l, 0); 484 while((i = read(tf2, buf, BUFSIZ)) > 0) 485 if (write(af, buf, i) != i) 486 wrerr(); 487 } 488 if(tf1nam) { 489 lseek(tf1, 0l, 0); 490 while((i = read(tf1, buf, BUFSIZ)) > 0) 491 if (write(af, buf, i) != i) 492 wrerr(); 493 } 494 } 495 496 /* 497 * insert the file 'file' 498 * into the temporary file 499 */ 500 movefil(f) 501 { 502 char buf[sizeof(arbuf)+1]; 503 504 sprintf(buf, "%-16s%-12ld%-6u%-6u%-8o%-10ld%-2s", 505 trim(file), 506 stbuf.st_mtime, 507 stbuf.st_uid, 508 stbuf.st_gid, 509 stbuf.st_mode, 510 stbuf.st_size, 511 ARFMAG); 512 strncpy((char *)&arbuf, buf, sizeof(arbuf)); 513 larbuf.lar_size = stbuf.st_size; 514 copyfil(f, tf, OODD+HEAD); 515 close(f); 516 } 517 518 stats() 519 { 520 register f; 521 522 f = open(file, 0); 523 if(f < 0) 524 return(f); 525 if(fstat(f, &stbuf) < 0) { 526 close(f); 527 return(-1); 528 } 529 return(f); 530 } 531 532 /* 533 * copy next file 534 * size given in arbuf 535 */ 536 copyfil(fi, fo, flag) 537 { 538 register i, o; 539 int pe; 540 541 if(flag & HEAD) { 542 for (i=sizeof(arbuf.ar_name)-1; i>=0; i--) { 543 if (arbuf.ar_name[i]==' ') 544 continue; 545 else if (arbuf.ar_name[i]=='\0') 546 arbuf.ar_name[i] = ' '; 547 else 548 break; 549 } 550 if (write(fo, (char *)&arbuf, sizeof arbuf) != sizeof arbuf) 551 wrerr(); 552 } 553 pe = 0; 554 while(larbuf.lar_size > 0) { 555 i = o = BUFSIZ; 556 if(larbuf.lar_size < i) { 557 i = o = larbuf.lar_size; 558 if(i&1) { 559 buf[i] = '\n'; 560 if(flag & IODD) 561 i++; 562 if(flag & OODD) 563 o++; 564 } 565 } 566 if(read(fi, buf, i) != i) 567 pe++; 568 if((flag & SKIP) == 0) 569 if (write(fo, buf, o) != o) 570 wrerr(); 571 larbuf.lar_size -= BUFSIZ; 572 } 573 if(pe) 574 phserr(); 575 } 576 577 getdir() 578 { 579 register char *cp; 580 register i; 581 582 i = read(af, (char *)&arbuf, sizeof arbuf); 583 if(i != sizeof arbuf) { 584 if(tf1nam) { 585 i = tf; 586 tf = tf1; 587 tf1 = i; 588 } 589 return(1); 590 } 591 if (strncmp(arbuf.ar_fmag, ARFMAG, sizeof(arbuf.ar_fmag))) { 592 fprintf(stderr, "ar: malformed archive (at %ld)\n", lseek(af, 0L, 1)); 593 done(1); 594 } 595 cp = arbuf.ar_name + sizeof(arbuf.ar_name); 596 while (*--cp==' ') 597 ; 598 *++cp = '\0'; 599 strncpy(name, arbuf.ar_name, sizeof(arbuf.ar_name)); 600 file = name; 601 strncpy(larbuf.lar_name, name, sizeof(larbuf.lar_name)); 602 sscanf(arbuf.ar_date, "%ld", &larbuf.lar_date); 603 sscanf(arbuf.ar_uid, "%hd", &larbuf.lar_uid); 604 sscanf(arbuf.ar_gid, "%hd", &larbuf.lar_gid); 605 sscanf(arbuf.ar_mode, "%ho", &larbuf.lar_mode); 606 sscanf(arbuf.ar_size, "%ld", &larbuf.lar_size); 607 return(0); 608 } 609 610 match() 611 { 612 register i; 613 614 for(i=0; i<namc; i++) { 615 if(namv[i] == 0) 616 continue; 617 if(strcmp(trim(namv[i]), file) == 0) { 618 file = namv[i]; 619 namv[i] = 0; 620 return(1); 621 } 622 } 623 return(0); 624 } 625 626 bamatch() 627 { 628 register f; 629 630 switch(bastate) { 631 632 case 1: 633 if(strcmp(file, ponam) != 0) 634 return; 635 bastate = 2; 636 if(flg['a'-'a']) 637 return; 638 639 case 2: 640 bastate = 0; 641 tf1nam = mktemp(tmp1nam); 642 close(creat(tf1nam, 0600)); 643 f = open(tf1nam, 2); 644 if(f < 0) { 645 fprintf(stderr, "ar: cannot create second temp\n"); 646 return; 647 } 648 tf1 = tf; 649 tf = f; 650 } 651 } 652 653 phserr() 654 { 655 656 fprintf(stderr, "ar: phase error on %s\n", file); 657 } 658 659 mesg(c) 660 { 661 662 if(flg['v'-'a']) 663 if(c != 'c' || flg['v'-'a'] > 1) 664 printf("%c - %s\n", c, file); 665 } 666 667 char * 668 trim(s) 669 char *s; 670 { 671 register char *p1, *p2; 672 673 for(p1 = s; *p1; p1++) 674 ; 675 while(p1 > s) { 676 if(*--p1 != '/') 677 break; 678 *p1 = 0; 679 } 680 p2 = s; 681 for(p1 = s; *p1; p1++) 682 if(*p1 == '/') 683 p2 = p1+1; 684 return(p2); 685 } 686 687 #define IFMT 060000 688 #define ISARG 01000 689 #define LARGE 010000 690 #define SUID 04000 691 #define SGID 02000 692 #define ROWN 0400 693 #define WOWN 0200 694 #define XOWN 0100 695 #define RGRP 040 696 #define WGRP 020 697 #define XGRP 010 698 #define ROTH 04 699 #define WOTH 02 700 #define XOTH 01 701 #define STXT 01000 702 703 longt() 704 { 705 register char *cp; 706 707 pmode(); 708 printf("%3d/%1d", larbuf.lar_uid, larbuf.lar_gid); 709 printf("%7ld", larbuf.lar_size); 710 cp = ctime(&larbuf.lar_date); 711 printf(" %-12.12s %-4.4s ", cp+4, cp+20); 712 } 713 714 int m1[] = { 1, ROWN, 'r', '-' }; 715 int m2[] = { 1, WOWN, 'w', '-' }; 716 int m3[] = { 2, SUID, 's', XOWN, 'x', '-' }; 717 int m4[] = { 1, RGRP, 'r', '-' }; 718 int m5[] = { 1, WGRP, 'w', '-' }; 719 int m6[] = { 2, SGID, 's', XGRP, 'x', '-' }; 720 int m7[] = { 1, ROTH, 'r', '-' }; 721 int m8[] = { 1, WOTH, 'w', '-' }; 722 int m9[] = { 2, STXT, 't', XOTH, 'x', '-' }; 723 724 int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9}; 725 726 pmode() 727 { 728 register int **mp; 729 730 for (mp = &m[0]; mp < &m[9];) 731 select(*mp++); 732 } 733 734 select(pairp) 735 int *pairp; 736 { 737 register int n, *ap; 738 739 ap = pairp; 740 n = *ap++; 741 while (--n>=0 && (larbuf.lar_mode&*ap++)==0) 742 ap++; 743 putchar(*ap); 744 } 745 746 wrerr() 747 { 748 perror("ar write error"); 749 done(1); 750 } 751