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