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