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