1 /* $NetBSD: arch.c,v 1.35 2002/06/15 18:24:55 wiz Exp $ */ 2 3 /* 4 * Copyright (c) 1988, 1989, 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * Copyright (c) 1989 by Berkeley Softworks 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to Berkeley by 10 * Adam de Boor. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 */ 40 41 #ifdef MAKE_BOOTSTRAP 42 static char rcsid[] = "$NetBSD: arch.c,v 1.35 2002/06/15 18:24:55 wiz Exp $"; 43 #else 44 #include <sys/cdefs.h> 45 #ifndef lint 46 #if 0 47 static char sccsid[] = "@(#)arch.c 8.2 (Berkeley) 1/2/94"; 48 #else 49 __RCSID("$NetBSD: arch.c,v 1.35 2002/06/15 18:24:55 wiz Exp $"); 50 #endif 51 #endif /* not lint */ 52 #endif 53 54 /*- 55 * arch.c -- 56 * Functions to manipulate libraries, archives and their members. 57 * 58 * Once again, cacheing/hashing comes into play in the manipulation 59 * of archives. The first time an archive is referenced, all of its members' 60 * headers are read and hashed and the archive closed again. All hashed 61 * archives are kept on a list which is searched each time an archive member 62 * is referenced. 63 * 64 * The interface to this module is: 65 * Arch_ParseArchive Given an archive specification, return a list 66 * of GNode's, one for each member in the spec. 67 * FAILURE is returned if the specification is 68 * invalid for some reason. 69 * 70 * Arch_Touch Alter the modification time of the archive 71 * member described by the given node to be 72 * the current time. 73 * 74 * Arch_TouchLib Update the modification time of the library 75 * described by the given node. This is special 76 * because it also updates the modification time 77 * of the library's table of contents. 78 * 79 * Arch_MTime Find the modification time of a member of 80 * an archive *in the archive*. The time is also 81 * placed in the member's GNode. Returns the 82 * modification time. 83 * 84 * Arch_MemTime Find the modification time of a member of 85 * an archive. Called when the member doesn't 86 * already exist. Looks in the archive for the 87 * modification time. Returns the modification 88 * time. 89 * 90 * Arch_FindLib Search for a library along a path. The 91 * library name in the GNode should be in 92 * -l<name> format. 93 * 94 * Arch_LibOODate Special function to decide if a library node 95 * is out-of-date. 96 * 97 * Arch_Init Initialize this module. 98 * 99 * Arch_End Cleanup this module. 100 */ 101 102 #include <sys/types.h> 103 #include <sys/stat.h> 104 #include <sys/time.h> 105 #include <sys/param.h> 106 107 #include <ar.h> 108 #include <ctype.h> 109 #include <fcntl.h> 110 #include <stdio.h> 111 #include <stdlib.h> 112 #include <utime.h> 113 114 #include "make.h" 115 #include "hash.h" 116 #include "dir.h" 117 #include "config.h" 118 119 #ifdef TARGET_MACHINE 120 #undef MAKE_MACHINE 121 #define MAKE_MACHINE TARGET_MACHINE 122 #endif 123 #ifdef TARGET_MACHINE_ARCH 124 #undef MAKE_MACHINE_ARCH 125 #define MAKE_MACHINE_ARCH TARGET_MACHINE_ARCH 126 #endif 127 128 static Lst archives; /* Lst of archives we've already examined */ 129 130 typedef struct Arch { 131 char *name; /* Name of archive */ 132 Hash_Table members; /* All the members of the archive described 133 * by <name, struct ar_hdr *> key/value pairs */ 134 char *fnametab; /* Extended name table strings */ 135 size_t fnamesize; /* Size of the string table */ 136 } Arch; 137 138 static int ArchFindArchive(ClientData, ClientData); 139 #ifdef CLEANUP 140 static void ArchFree(ClientData); 141 #endif 142 static struct ar_hdr *ArchStatMember(char *, char *, Boolean); 143 static FILE *ArchFindMember(char *, char *, struct ar_hdr *, char *); 144 #if defined(__svr4__) || defined(__SVR4) || defined(__ELF__) 145 #define SVR4ARCHIVES 146 static int ArchSVR4Entry(Arch *, char *, size_t, FILE *); 147 #endif 148 149 #ifdef CLEANUP 150 /*- 151 *----------------------------------------------------------------------- 152 * ArchFree -- 153 * Free memory used by an archive 154 * 155 * Results: 156 * None. 157 * 158 * Side Effects: 159 * None. 160 * 161 *----------------------------------------------------------------------- 162 */ 163 static void 164 ArchFree(ClientData ap) 165 { 166 Arch *a = (Arch *) ap; 167 Hash_Search search; 168 Hash_Entry *entry; 169 170 /* Free memory from hash entries */ 171 for (entry = Hash_EnumFirst(&a->members, &search); 172 entry != (Hash_Entry *)NULL; 173 entry = Hash_EnumNext(&search)) 174 free((Address) Hash_GetValue (entry)); 175 176 free(a->name); 177 if (a->fnametab) 178 free(a->fnametab); 179 Hash_DeleteTable(&a->members); 180 free((Address) a); 181 } 182 #endif 183 184 185 186 /*- 187 *----------------------------------------------------------------------- 188 * Arch_ParseArchive -- 189 * Parse the archive specification in the given line and find/create 190 * the nodes for the specified archive members, placing their nodes 191 * on the given list. 192 * 193 * Input: 194 * linePtr Pointer to start of specification 195 * nodeLst Lst on which to place the nodes 196 * ctxt Context in which to expand variables 197 * 198 * Results: 199 * SUCCESS if it was a valid specification. The linePtr is updated 200 * to point to the first non-space after the archive spec. The 201 * nodes for the members are placed on the given list. 202 * 203 * Side Effects: 204 * Some nodes may be created. The given list is extended. 205 * 206 *----------------------------------------------------------------------- 207 */ 208 ReturnStatus 209 Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt) 210 { 211 char *cp; /* Pointer into line */ 212 GNode *gn; /* New node */ 213 char *libName; /* Library-part of specification */ 214 char *memName; /* Member-part of specification */ 215 char *nameBuf; /* temporary place for node name */ 216 char saveChar; /* Ending delimiter of member-name */ 217 Boolean subLibName; /* TRUE if libName should have/had 218 * variable substitution performed on it */ 219 220 libName = *linePtr; 221 222 subLibName = FALSE; 223 224 for (cp = libName; *cp != '(' && *cp != '\0'; cp++) { 225 if (*cp == '$') { 226 /* 227 * Variable spec, so call the Var module to parse the puppy 228 * so we can safely advance beyond it... 229 */ 230 int length; 231 Boolean freeIt; 232 char *result; 233 234 result=Var_Parse(cp, ctxt, TRUE, &length, &freeIt); 235 if (result == var_Error) { 236 return(FAILURE); 237 } else { 238 subLibName = TRUE; 239 } 240 241 if (freeIt) { 242 free(result); 243 } 244 cp += length-1; 245 } 246 } 247 248 *cp++ = '\0'; 249 if (subLibName) { 250 libName = Var_Subst(NULL, libName, ctxt, TRUE); 251 } 252 253 254 for (;;) { 255 /* 256 * First skip to the start of the member's name, mark that 257 * place and skip to the end of it (either white-space or 258 * a close paren). 259 */ 260 Boolean doSubst = FALSE; /* TRUE if need to substitute in memName */ 261 262 while (*cp != '\0' && *cp != ')' && isspace ((unsigned char)*cp)) { 263 cp++; 264 } 265 memName = cp; 266 while (*cp != '\0' && *cp != ')' && !isspace ((unsigned char)*cp)) { 267 if (*cp == '$') { 268 /* 269 * Variable spec, so call the Var module to parse the puppy 270 * so we can safely advance beyond it... 271 */ 272 int length; 273 Boolean freeIt; 274 char *result; 275 276 result=Var_Parse(cp, ctxt, TRUE, &length, &freeIt); 277 if (result == var_Error) { 278 return(FAILURE); 279 } else { 280 doSubst = TRUE; 281 } 282 283 if (freeIt) { 284 free(result); 285 } 286 cp += length; 287 } else { 288 cp++; 289 } 290 } 291 292 /* 293 * If the specification ends without a closing parenthesis, 294 * chances are there's something wrong (like a missing backslash), 295 * so it's better to return failure than allow such things to happen 296 */ 297 if (*cp == '\0') { 298 printf("No closing parenthesis in archive specification\n"); 299 return (FAILURE); 300 } 301 302 /* 303 * If we didn't move anywhere, we must be done 304 */ 305 if (cp == memName) { 306 break; 307 } 308 309 saveChar = *cp; 310 *cp = '\0'; 311 312 /* 313 * XXX: This should be taken care of intelligently by 314 * SuffExpandChildren, both for the archive and the member portions. 315 */ 316 /* 317 * If member contains variables, try and substitute for them. 318 * This will slow down archive specs with dynamic sources, of course, 319 * since we'll be (non-)substituting them three times, but them's 320 * the breaks -- we need to do this since SuffExpandChildren calls 321 * us, otherwise we could assume the thing would be taken care of 322 * later. 323 */ 324 if (doSubst) { 325 char *buf; 326 char *sacrifice; 327 char *oldMemName = memName; 328 size_t sz; 329 330 memName = Var_Subst(NULL, memName, ctxt, TRUE); 331 332 /* 333 * Now form an archive spec and recurse to deal with nested 334 * variables and multi-word variable values.... The results 335 * are just placed at the end of the nodeLst we're returning. 336 */ 337 sz = strlen(memName)+strlen(libName)+3; 338 buf = sacrifice = emalloc(sz); 339 340 snprintf(buf, sz, "%s(%s)", libName, memName); 341 342 if (strchr(memName, '$') && strcmp(memName, oldMemName) == 0) { 343 /* 344 * Must contain dynamic sources, so we can't deal with it now. 345 * Just create an ARCHV node for the thing and let 346 * SuffExpandChildren handle it... 347 */ 348 gn = Targ_FindNode(buf, TARG_CREATE); 349 350 if (gn == NILGNODE) { 351 free(buf); 352 return(FAILURE); 353 } else { 354 gn->type |= OP_ARCHV; 355 (void)Lst_AtEnd(nodeLst, (ClientData)gn); 356 } 357 } else if (Arch_ParseArchive(&sacrifice, nodeLst, ctxt)!=SUCCESS) { 358 /* 359 * Error in nested call -- free buffer and return FAILURE 360 * ourselves. 361 */ 362 free(buf); 363 return(FAILURE); 364 } 365 /* 366 * Free buffer and continue with our work. 367 */ 368 free(buf); 369 } else if (Dir_HasWildcards(memName)) { 370 Lst members = Lst_Init(FALSE); 371 char *member; 372 size_t sz = MAXPATHLEN, nsz; 373 nameBuf = emalloc(sz); 374 375 Dir_Expand(memName, dirSearchPath, members); 376 while (!Lst_IsEmpty(members)) { 377 member = (char *)Lst_DeQueue(members); 378 nsz = strlen(libName) + strlen(member) + 3; 379 if (sz > nsz) 380 nameBuf = erealloc(nameBuf, sz = nsz * 2); 381 382 snprintf(nameBuf, sz, "%s(%s)", libName, member); 383 free(member); 384 gn = Targ_FindNode (nameBuf, TARG_CREATE); 385 if (gn == NILGNODE) { 386 free(nameBuf); 387 return (FAILURE); 388 } else { 389 /* 390 * We've found the node, but have to make sure the rest of 391 * the world knows it's an archive member, without having 392 * to constantly check for parentheses, so we type the 393 * thing with the OP_ARCHV bit before we place it on the 394 * end of the provided list. 395 */ 396 gn->type |= OP_ARCHV; 397 (void) Lst_AtEnd (nodeLst, (ClientData)gn); 398 } 399 } 400 Lst_Destroy(members, NOFREE); 401 free(nameBuf); 402 } else { 403 size_t sz = strlen(libName) + strlen(memName) + 3; 404 nameBuf = emalloc(sz); 405 snprintf(nameBuf, sz, "%s(%s)", libName, memName); 406 gn = Targ_FindNode (nameBuf, TARG_CREATE); 407 free(nameBuf); 408 if (gn == NILGNODE) { 409 return (FAILURE); 410 } else { 411 /* 412 * We've found the node, but have to make sure the rest of the 413 * world knows it's an archive member, without having to 414 * constantly check for parentheses, so we type the thing with 415 * the OP_ARCHV bit before we place it on the end of the 416 * provided list. 417 */ 418 gn->type |= OP_ARCHV; 419 (void) Lst_AtEnd (nodeLst, (ClientData)gn); 420 } 421 } 422 if (doSubst) { 423 free(memName); 424 } 425 426 *cp = saveChar; 427 } 428 429 /* 430 * If substituted libName, free it now, since we need it no longer. 431 */ 432 if (subLibName) { 433 free(libName); 434 } 435 436 /* 437 * We promised the pointer would be set up at the next non-space, so 438 * we must advance cp there before setting *linePtr... (note that on 439 * entrance to the loop, cp is guaranteed to point at a ')') 440 */ 441 do { 442 cp++; 443 } while (*cp != '\0' && isspace ((unsigned char)*cp)); 444 445 *linePtr = cp; 446 return (SUCCESS); 447 } 448 449 /*- 450 *----------------------------------------------------------------------- 451 * ArchFindArchive -- 452 * See if the given archive is the one we are looking for. Called 453 * From ArchStatMember and ArchFindMember via Lst_Find. 454 * 455 * Input: 456 * ar Current list element 457 * archName Name we want 458 * 459 * Results: 460 * 0 if it is, non-zero if it isn't. 461 * 462 * Side Effects: 463 * None. 464 * 465 *----------------------------------------------------------------------- 466 */ 467 static int 468 ArchFindArchive(ClientData ar, ClientData archName) 469 { 470 return (strcmp((char *) archName, ((Arch *) ar)->name)); 471 } 472 473 /*- 474 *----------------------------------------------------------------------- 475 * ArchStatMember -- 476 * Locate a member of an archive, given the path of the archive and 477 * the path of the desired member. 478 * 479 * Input: 480 * archive Path to the archive 481 * member Name of member. If it is a path, only the last 482 * component is used. 483 * hash TRUE if archive should be hashed if not already so. 484 * 485 * Results: 486 * A pointer to the current struct ar_hdr structure for the member. Note 487 * That no position is returned, so this is not useful for touching 488 * archive members. This is mostly because we have no assurances that 489 * The archive will remain constant after we read all the headers, so 490 * there's not much point in remembering the position... 491 * 492 * Side Effects: 493 * 494 *----------------------------------------------------------------------- 495 */ 496 static struct ar_hdr * 497 ArchStatMember(char *archive, char *member, Boolean hash) 498 { 499 #define AR_MAX_NAME_LEN (sizeof(arh.ar_name)-1) 500 FILE * arch; /* Stream to archive */ 501 int size; /* Size of archive member */ 502 char *cp; /* Useful character pointer */ 503 char magic[SARMAG]; 504 LstNode ln; /* Lst member containing archive descriptor */ 505 Arch *ar; /* Archive descriptor */ 506 Hash_Entry *he; /* Entry containing member's description */ 507 struct ar_hdr arh; /* archive-member header for reading archive */ 508 char memName[MAXPATHLEN+1]; 509 /* Current member name while hashing. */ 510 511 /* 512 * Because of space constraints and similar things, files are archived 513 * using their final path components, not the entire thing, so we need 514 * to point 'member' to the final component, if there is one, to make 515 * the comparisons easier... 516 */ 517 cp = strrchr (member, '/'); 518 if (cp != (char *) NULL) { 519 member = cp + 1; 520 } 521 522 ln = Lst_Find (archives, (ClientData) archive, ArchFindArchive); 523 if (ln != NILLNODE) { 524 ar = (Arch *) Lst_Datum (ln); 525 526 he = Hash_FindEntry (&ar->members, member); 527 528 if (he != (Hash_Entry *) NULL) { 529 return ((struct ar_hdr *) Hash_GetValue (he)); 530 } else { 531 /* Try truncated name */ 532 char copy[AR_MAX_NAME_LEN+1]; 533 int len = strlen (member); 534 535 if (len > AR_MAX_NAME_LEN) { 536 len = AR_MAX_NAME_LEN; 537 strncpy(copy, member, AR_MAX_NAME_LEN); 538 copy[AR_MAX_NAME_LEN] = '\0'; 539 } 540 if ((he = Hash_FindEntry (&ar->members, copy)) != NULL) 541 return ((struct ar_hdr *) Hash_GetValue (he)); 542 return ((struct ar_hdr *) NULL); 543 } 544 } 545 546 if (!hash) { 547 /* 548 * Caller doesn't want the thing hashed, just use ArchFindMember 549 * to read the header for the member out and close down the stream 550 * again. Since the archive is not to be hashed, we assume there's 551 * no need to allocate extra room for the header we're returning, 552 * so just declare it static. 553 */ 554 static struct ar_hdr sarh; 555 556 arch = ArchFindMember(archive, member, &sarh, "r"); 557 558 if (arch == (FILE *)NULL) { 559 return ((struct ar_hdr *)NULL); 560 } else { 561 fclose(arch); 562 return (&sarh); 563 } 564 } 565 566 /* 567 * We don't have this archive on the list yet, so we want to find out 568 * everything that's in it and cache it so we can get at it quickly. 569 */ 570 arch = fopen (archive, "r"); 571 if (arch == (FILE *) NULL) { 572 return ((struct ar_hdr *) NULL); 573 } 574 575 /* 576 * We use the ARMAG string to make sure this is an archive we 577 * can handle... 578 */ 579 if ((fread (magic, SARMAG, 1, arch) != 1) || 580 (strncmp (magic, ARMAG, SARMAG) != 0)) { 581 fclose (arch); 582 return ((struct ar_hdr *) NULL); 583 } 584 585 ar = (Arch *)emalloc (sizeof (Arch)); 586 ar->name = estrdup (archive); 587 ar->fnametab = NULL; 588 ar->fnamesize = 0; 589 Hash_InitTable (&ar->members, -1); 590 memName[AR_MAX_NAME_LEN] = '\0'; 591 592 while (fread ((char *)&arh, sizeof (struct ar_hdr), 1, arch) == 1) { 593 if (strncmp ( arh.ar_fmag, ARFMAG, sizeof (arh.ar_fmag)) != 0) { 594 /* 595 * The header is bogus, so the archive is bad 596 * and there's no way we can recover... 597 */ 598 goto badarch; 599 } else { 600 /* 601 * We need to advance the stream's pointer to the start of the 602 * next header. Files are padded with newlines to an even-byte 603 * boundary, so we need to extract the size of the file from the 604 * 'size' field of the header and round it up during the seek. 605 */ 606 arh.ar_size[sizeof(arh.ar_size)-1] = '\0'; 607 size = (int) strtol(arh.ar_size, NULL, 10); 608 609 (void) strncpy (memName, arh.ar_name, sizeof(arh.ar_name)); 610 for (cp = &memName[AR_MAX_NAME_LEN]; *cp == ' '; cp--) { 611 continue; 612 } 613 cp[1] = '\0'; 614 615 #ifdef SVR4ARCHIVES 616 /* 617 * svr4 names are slash terminated. Also svr4 extended AR format. 618 */ 619 if (memName[0] == '/') { 620 /* 621 * svr4 magic mode; handle it 622 */ 623 switch (ArchSVR4Entry(ar, memName, size, arch)) { 624 case -1: /* Invalid data */ 625 goto badarch; 626 case 0: /* List of files entry */ 627 continue; 628 default: /* Got the entry */ 629 break; 630 } 631 } 632 else { 633 if (cp[0] == '/') 634 cp[0] = '\0'; 635 } 636 #endif 637 638 #ifdef AR_EFMT1 639 /* 640 * BSD 4.4 extended AR format: #1/<namelen>, with name as the 641 * first <namelen> bytes of the file 642 */ 643 if (strncmp(memName, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0 && 644 isdigit(memName[sizeof(AR_EFMT1) - 1])) { 645 646 unsigned int elen = atoi(&memName[sizeof(AR_EFMT1)-1]); 647 648 if (elen > MAXPATHLEN) 649 goto badarch; 650 if (fread (memName, elen, 1, arch) != 1) 651 goto badarch; 652 memName[elen] = '\0'; 653 fseek (arch, -elen, SEEK_CUR); 654 if (DEBUG(ARCH) || DEBUG(MAKE)) { 655 printf("ArchStat: Extended format entry for %s\n", memName); 656 } 657 } 658 #endif 659 660 he = Hash_CreateEntry (&ar->members, memName, (Boolean *)NULL); 661 Hash_SetValue (he, (ClientData)emalloc (sizeof (struct ar_hdr))); 662 memcpy ((Address)Hash_GetValue (he), (Address)&arh, 663 sizeof (struct ar_hdr)); 664 } 665 fseek (arch, (size + 1) & ~1, SEEK_CUR); 666 } 667 668 fclose (arch); 669 670 (void) Lst_AtEnd (archives, (ClientData) ar); 671 672 /* 673 * Now that the archive has been read and cached, we can look into 674 * the hash table to find the desired member's header. 675 */ 676 he = Hash_FindEntry (&ar->members, member); 677 678 if (he != (Hash_Entry *) NULL) { 679 return ((struct ar_hdr *) Hash_GetValue (he)); 680 } else { 681 return ((struct ar_hdr *) NULL); 682 } 683 684 badarch: 685 fclose (arch); 686 Hash_DeleteTable (&ar->members); 687 if (ar->fnametab) 688 free(ar->fnametab); 689 free ((Address)ar); 690 return ((struct ar_hdr *) NULL); 691 } 692 693 #ifdef SVR4ARCHIVES 694 /*- 695 *----------------------------------------------------------------------- 696 * ArchSVR4Entry -- 697 * Parse an SVR4 style entry that begins with a slash. 698 * If it is "//", then load the table of filenames 699 * If it is "/<offset>", then try to substitute the long file name 700 * from offset of a table previously read. 701 * 702 * Results: 703 * -1: Bad data in archive 704 * 0: A table was loaded from the file 705 * 1: Name was successfully substituted from table 706 * 2: Name was not successfully substituted from table 707 * 708 * Side Effects: 709 * If a table is read, the file pointer is moved to the next archive 710 * member 711 * 712 *----------------------------------------------------------------------- 713 */ 714 static int 715 ArchSVR4Entry(Arch *ar, char *name, size_t size, FILE *arch) 716 { 717 #define ARLONGNAMES1 "//" 718 #define ARLONGNAMES2 "/ARFILENAMES" 719 size_t entry; 720 char *ptr, *eptr; 721 722 if (strncmp(name, ARLONGNAMES1, sizeof(ARLONGNAMES1) - 1) == 0 || 723 strncmp(name, ARLONGNAMES2, sizeof(ARLONGNAMES2) - 1) == 0) { 724 725 if (ar->fnametab != NULL) { 726 if (DEBUG(ARCH)) { 727 printf("Attempted to redefine an SVR4 name table\n"); 728 } 729 return -1; 730 } 731 732 /* 733 * This is a table of archive names, so we build one for 734 * ourselves 735 */ 736 ar->fnametab = emalloc(size); 737 ar->fnamesize = size; 738 739 if (fread(ar->fnametab, size, 1, arch) != 1) { 740 if (DEBUG(ARCH)) { 741 printf("Reading an SVR4 name table failed\n"); 742 } 743 return -1; 744 } 745 eptr = ar->fnametab + size; 746 for (entry = 0, ptr = ar->fnametab; ptr < eptr; ptr++) 747 switch (*ptr) { 748 case '/': 749 entry++; 750 *ptr = '\0'; 751 break; 752 753 case '\n': 754 break; 755 756 default: 757 break; 758 } 759 if (DEBUG(ARCH)) { 760 printf("Found svr4 archive name table with %lu entries\n", 761 (u_long)entry); 762 } 763 return 0; 764 } 765 766 if (name[1] == ' ' || name[1] == '\0') 767 return 2; 768 769 entry = (size_t) strtol(&name[1], &eptr, 0); 770 if ((*eptr != ' ' && *eptr != '\0') || eptr == &name[1]) { 771 if (DEBUG(ARCH)) { 772 printf("Could not parse SVR4 name %s\n", name); 773 } 774 return 2; 775 } 776 if (entry >= ar->fnamesize) { 777 if (DEBUG(ARCH)) { 778 printf("SVR4 entry offset %s is greater than %lu\n", 779 name, (u_long)ar->fnamesize); 780 } 781 return 2; 782 } 783 784 if (DEBUG(ARCH)) { 785 printf("Replaced %s with %s\n", name, &ar->fnametab[entry]); 786 } 787 788 (void) strncpy(name, &ar->fnametab[entry], MAXPATHLEN); 789 name[MAXPATHLEN] = '\0'; 790 return 1; 791 } 792 #endif 793 794 795 /*- 796 *----------------------------------------------------------------------- 797 * ArchFindMember -- 798 * Locate a member of an archive, given the path of the archive and 799 * the path of the desired member. If the archive is to be modified, 800 * the mode should be "r+", if not, it should be "r". 801 * 802 * Input: 803 * archive Path to the archive 804 * member Name of member. If it is a path, only the last 805 * component is used. 806 * arhPtr Pointer to header structure to be filled in 807 * mode The mode for opening the stream 808 * 809 * Results: 810 * An FILE *, opened for reading and writing, positioned at the 811 * start of the member's struct ar_hdr, or NULL if the member was 812 * nonexistent. The current struct ar_hdr for member. 813 * 814 * Side Effects: 815 * The passed struct ar_hdr structure is filled in. 816 * 817 *----------------------------------------------------------------------- 818 */ 819 static FILE * 820 ArchFindMember(char *archive, char *member, struct ar_hdr *arhPtr, char *mode) 821 { 822 FILE * arch; /* Stream to archive */ 823 int size; /* Size of archive member */ 824 char *cp; /* Useful character pointer */ 825 char magic[SARMAG]; 826 int len, tlen; 827 828 arch = fopen (archive, mode); 829 if (arch == (FILE *) NULL) { 830 return ((FILE *) NULL); 831 } 832 833 /* 834 * We use the ARMAG string to make sure this is an archive we 835 * can handle... 836 */ 837 if ((fread (magic, SARMAG, 1, arch) != 1) || 838 (strncmp (magic, ARMAG, SARMAG) != 0)) { 839 fclose (arch); 840 return ((FILE *) NULL); 841 } 842 843 /* 844 * Because of space constraints and similar things, files are archived 845 * using their final path components, not the entire thing, so we need 846 * to point 'member' to the final component, if there is one, to make 847 * the comparisons easier... 848 */ 849 cp = strrchr (member, '/'); 850 if (cp != (char *) NULL) { 851 member = cp + 1; 852 } 853 len = tlen = strlen (member); 854 if (len > sizeof (arhPtr->ar_name)) { 855 tlen = sizeof (arhPtr->ar_name); 856 } 857 858 while (fread ((char *)arhPtr, sizeof (struct ar_hdr), 1, arch) == 1) { 859 if (strncmp(arhPtr->ar_fmag, ARFMAG, sizeof (arhPtr->ar_fmag) ) != 0) { 860 /* 861 * The header is bogus, so the archive is bad 862 * and there's no way we can recover... 863 */ 864 fclose (arch); 865 return ((FILE *) NULL); 866 } else if (strncmp (member, arhPtr->ar_name, tlen) == 0) { 867 /* 868 * If the member's name doesn't take up the entire 'name' field, 869 * we have to be careful of matching prefixes. Names are space- 870 * padded to the right, so if the character in 'name' at the end 871 * of the matched string is anything but a space, this isn't the 872 * member we sought. 873 */ 874 if (tlen != sizeof(arhPtr->ar_name) && arhPtr->ar_name[tlen] != ' '){ 875 goto skip; 876 } else { 877 /* 878 * To make life easier, we reposition the file at the start 879 * of the header we just read before we return the stream. 880 * In a more general situation, it might be better to leave 881 * the file at the actual member, rather than its header, but 882 * not here... 883 */ 884 fseek (arch, -sizeof(struct ar_hdr), SEEK_CUR); 885 return (arch); 886 } 887 } else 888 #ifdef AR_EFMT1 889 /* 890 * BSD 4.4 extended AR format: #1/<namelen>, with name as the 891 * first <namelen> bytes of the file 892 */ 893 if (strncmp(arhPtr->ar_name, AR_EFMT1, 894 sizeof(AR_EFMT1) - 1) == 0 && 895 isdigit(arhPtr->ar_name[sizeof(AR_EFMT1) - 1])) { 896 897 unsigned int elen = atoi(&arhPtr->ar_name[sizeof(AR_EFMT1)-1]); 898 char ename[MAXPATHLEN]; 899 900 if (elen > MAXPATHLEN) { 901 fclose (arch); 902 return NULL; 903 } 904 if (fread (ename, elen, 1, arch) != 1) { 905 fclose (arch); 906 return NULL; 907 } 908 ename[elen] = '\0'; 909 if (DEBUG(ARCH) || DEBUG(MAKE)) { 910 printf("ArchFind: Extended format entry for %s\n", ename); 911 } 912 if (strncmp(ename, member, len) == 0) { 913 /* Found as extended name */ 914 fseek (arch, -sizeof(struct ar_hdr) - elen, SEEK_CUR); 915 return (arch); 916 } 917 fseek (arch, -elen, SEEK_CUR); 918 goto skip; 919 } else 920 #endif 921 { 922 skip: 923 /* 924 * This isn't the member we're after, so we need to advance the 925 * stream's pointer to the start of the next header. Files are 926 * padded with newlines to an even-byte boundary, so we need to 927 * extract the size of the file from the 'size' field of the 928 * header and round it up during the seek. 929 */ 930 arhPtr->ar_size[sizeof(arhPtr->ar_size)-1] = '\0'; 931 size = (int) strtol(arhPtr->ar_size, NULL, 10); 932 fseek (arch, (size + 1) & ~1, SEEK_CUR); 933 } 934 } 935 936 /* 937 * We've looked everywhere, but the member is not to be found. Close the 938 * archive and return NULL -- an error. 939 */ 940 fclose (arch); 941 return ((FILE *) NULL); 942 } 943 944 /*- 945 *----------------------------------------------------------------------- 946 * Arch_Touch -- 947 * Touch a member of an archive. 948 * 949 * Input: 950 * gn Node of member to touch 951 * 952 * Results: 953 * The 'time' field of the member's header is updated. 954 * 955 * Side Effects: 956 * The modification time of the entire archive is also changed. 957 * For a library, this could necessitate the re-ranlib'ing of the 958 * whole thing. 959 * 960 *----------------------------------------------------------------------- 961 */ 962 void 963 Arch_Touch(GNode *gn) 964 { 965 FILE * arch; /* Stream open to archive, positioned properly */ 966 struct ar_hdr arh; /* Current header describing member */ 967 char *p1, *p2; 968 969 arch = ArchFindMember(Var_Value (ARCHIVE, gn, &p1), 970 Var_Value (MEMBER, gn, &p2), 971 &arh, "r+"); 972 if (p1) 973 free(p1); 974 if (p2) 975 free(p2); 976 snprintf(arh.ar_date, sizeof(arh.ar_date), "%-12ld", (long) now); 977 978 if (arch != (FILE *) NULL) { 979 (void)fwrite ((char *)&arh, sizeof (struct ar_hdr), 1, arch); 980 fclose (arch); 981 } 982 } 983 984 /*- 985 *----------------------------------------------------------------------- 986 * Arch_TouchLib -- 987 * Given a node which represents a library, touch the thing, making 988 * sure that the table of contents also is touched. 989 * 990 * Input: 991 * gn The node of the library to touch 992 * 993 * Results: 994 * None. 995 * 996 * Side Effects: 997 * Both the modification time of the library and of the RANLIBMAG 998 * member are set to 'now'. 999 * 1000 *----------------------------------------------------------------------- 1001 */ 1002 void 1003 Arch_TouchLib(GNode *gn) 1004 { 1005 #ifdef RANLIBMAG 1006 FILE * arch; /* Stream open to archive */ 1007 struct ar_hdr arh; /* Header describing table of contents */ 1008 struct utimbuf times; /* Times for utime() call */ 1009 1010 arch = ArchFindMember (gn->path, RANLIBMAG, &arh, "r+"); 1011 snprintf(arh.ar_date, sizeof(arh.ar_date), "%-12ld", (long) now); 1012 1013 if (arch != (FILE *) NULL) { 1014 (void)fwrite ((char *)&arh, sizeof (struct ar_hdr), 1, arch); 1015 fclose (arch); 1016 1017 times.actime = times.modtime = now; 1018 utime(gn->path, ×); 1019 } 1020 #endif 1021 } 1022 1023 /*- 1024 *----------------------------------------------------------------------- 1025 * Arch_MTime -- 1026 * Return the modification time of a member of an archive. 1027 * 1028 * Input: 1029 * gn Node describing archive member 1030 * 1031 * Results: 1032 * The modification time (seconds). 1033 * 1034 * Side Effects: 1035 * The mtime field of the given node is filled in with the value 1036 * returned by the function. 1037 * 1038 *----------------------------------------------------------------------- 1039 */ 1040 time_t 1041 Arch_MTime(GNode *gn) 1042 { 1043 struct ar_hdr *arhPtr; /* Header of desired member */ 1044 time_t modTime; /* Modification time as an integer */ 1045 char *p1, *p2; 1046 1047 arhPtr = ArchStatMember (Var_Value (ARCHIVE, gn, &p1), 1048 Var_Value (MEMBER, gn, &p2), 1049 TRUE); 1050 if (p1) 1051 free(p1); 1052 if (p2) 1053 free(p2); 1054 1055 if (arhPtr != (struct ar_hdr *) NULL) { 1056 modTime = (time_t) strtol(arhPtr->ar_date, NULL, 10); 1057 } else { 1058 modTime = 0; 1059 } 1060 1061 gn->mtime = modTime; 1062 return (modTime); 1063 } 1064 1065 /*- 1066 *----------------------------------------------------------------------- 1067 * Arch_MemMTime -- 1068 * Given a non-existent archive member's node, get its modification 1069 * time from its archived form, if it exists. 1070 * 1071 * Results: 1072 * The modification time. 1073 * 1074 * Side Effects: 1075 * The mtime field is filled in. 1076 * 1077 *----------------------------------------------------------------------- 1078 */ 1079 time_t 1080 Arch_MemMTime(GNode *gn) 1081 { 1082 LstNode ln; 1083 GNode *pgn; 1084 char *nameStart, 1085 *nameEnd; 1086 1087 if (Lst_Open (gn->parents) != SUCCESS) { 1088 gn->mtime = 0; 1089 return (0); 1090 } 1091 while ((ln = Lst_Next (gn->parents)) != NILLNODE) { 1092 pgn = (GNode *) Lst_Datum (ln); 1093 1094 if (pgn->type & OP_ARCHV) { 1095 /* 1096 * If the parent is an archive specification and is being made 1097 * and its member's name matches the name of the node we were 1098 * given, record the modification time of the parent in the 1099 * child. We keep searching its parents in case some other 1100 * parent requires this child to exist... 1101 */ 1102 nameStart = strchr (pgn->name, '(') + 1; 1103 nameEnd = strchr (nameStart, ')'); 1104 1105 if ((pgn->flags & REMAKE) && 1106 strncmp(nameStart, gn->name, nameEnd - nameStart) == 0) { 1107 gn->mtime = Arch_MTime(pgn); 1108 } 1109 } else if (pgn->flags & REMAKE) { 1110 /* 1111 * Something which isn't a library depends on the existence of 1112 * this target, so it needs to exist. 1113 */ 1114 gn->mtime = 0; 1115 break; 1116 } 1117 } 1118 1119 Lst_Close (gn->parents); 1120 1121 return (gn->mtime); 1122 } 1123 1124 /*- 1125 *----------------------------------------------------------------------- 1126 * Arch_FindLib -- 1127 * Search for a library along the given search path. 1128 * 1129 * Input: 1130 * gn Node of library to find 1131 * path Search path 1132 * 1133 * Results: 1134 * None. 1135 * 1136 * Side Effects: 1137 * The node's 'path' field is set to the found path (including the 1138 * actual file name, not -l...). If the system can handle the -L 1139 * flag when linking (or we cannot find the library), we assume that 1140 * the user has placed the .LIBRARIES variable in the final linking 1141 * command (or the linker will know where to find it) and set the 1142 * TARGET variable for this node to be the node's name. Otherwise, 1143 * we set the TARGET variable to be the full path of the library, 1144 * as returned by Dir_FindFile. 1145 * 1146 *----------------------------------------------------------------------- 1147 */ 1148 void 1149 Arch_FindLib(GNode *gn, Lst path) 1150 { 1151 char *libName; /* file name for archive */ 1152 size_t sz = strlen(gn->name) + 6 - 2; 1153 1154 libName = (char *)emalloc(sz); 1155 snprintf(libName, sz, "lib%s.a", &gn->name[2]); 1156 1157 gn->path = Dir_FindFile (libName, path); 1158 1159 free (libName); 1160 1161 #ifdef LIBRARIES 1162 Var_Set (TARGET, gn->name, gn, 0); 1163 #else 1164 Var_Set (TARGET, gn->path == (char *) NULL ? gn->name : gn->path, gn, 0); 1165 #endif /* LIBRARIES */ 1166 } 1167 1168 /*- 1169 *----------------------------------------------------------------------- 1170 * Arch_LibOODate -- 1171 * Decide if a node with the OP_LIB attribute is out-of-date. Called 1172 * from Make_OODate to make its life easier. 1173 * 1174 * There are several ways for a library to be out-of-date that are 1175 * not available to ordinary files. In addition, there are ways 1176 * that are open to regular files that are not available to 1177 * libraries. A library that is only used as a source is never 1178 * considered out-of-date by itself. This does not preclude the 1179 * library's modification time from making its parent be out-of-date. 1180 * A library will be considered out-of-date for any of these reasons, 1181 * given that it is a target on a dependency line somewhere: 1182 * Its modification time is less than that of one of its 1183 * sources (gn->mtime < gn->cmtime). 1184 * Its modification time is greater than the time at which the 1185 * make began (i.e. it's been modified in the course 1186 * of the make, probably by archiving). 1187 * The modification time of one of its sources is greater than 1188 * the one of its RANLIBMAG member (i.e. its table of contents 1189 * is out-of-date). We don't compare of the archive time 1190 * vs. TOC time because they can be too close. In my 1191 * opinion we should not bother with the TOC at all since 1192 * this is used by 'ar' rules that affect the data contents 1193 * of the archive, not by ranlib rules, which affect the 1194 * TOC. 1195 * 1196 * Input: 1197 * gn The library's graph node 1198 * 1199 * Results: 1200 * TRUE if the library is out-of-date. FALSE otherwise. 1201 * 1202 * Side Effects: 1203 * The library will be hashed if it hasn't been already. 1204 * 1205 *----------------------------------------------------------------------- 1206 */ 1207 Boolean 1208 Arch_LibOODate(GNode *gn) 1209 { 1210 Boolean oodate; 1211 1212 if (gn->type & OP_PHONY) { 1213 oodate = TRUE; 1214 } else if (OP_NOP(gn->type) && Lst_IsEmpty(gn->children)) { 1215 oodate = FALSE; 1216 } else if ((gn->cmtime == 0) || (gn->mtime > now) || 1217 (gn->mtime < gn->cmtime)) { 1218 oodate = TRUE; 1219 } else { 1220 #ifdef RANLIBMAG 1221 struct ar_hdr *arhPtr; /* Header for __.SYMDEF */ 1222 int modTimeTOC; /* The table-of-contents's mod time */ 1223 1224 arhPtr = ArchStatMember (gn->path, RANLIBMAG, FALSE); 1225 1226 if (arhPtr != (struct ar_hdr *)NULL) { 1227 modTimeTOC = (int) strtol(arhPtr->ar_date, NULL, 10); 1228 1229 if (DEBUG(ARCH) || DEBUG(MAKE)) { 1230 printf("%s modified %s...", RANLIBMAG, Targ_FmtTime(modTimeTOC)); 1231 } 1232 oodate = (gn->cmtime > modTimeTOC); 1233 } else { 1234 /* 1235 * A library w/o a table of contents is out-of-date 1236 */ 1237 if (DEBUG(ARCH) || DEBUG(MAKE)) { 1238 printf("No t.o.c...."); 1239 } 1240 oodate = TRUE; 1241 } 1242 #else 1243 oodate = FALSE; 1244 #endif 1245 } 1246 return (oodate); 1247 } 1248 1249 /*- 1250 *----------------------------------------------------------------------- 1251 * Arch_Init -- 1252 * Initialize things for this module. 1253 * 1254 * Results: 1255 * None. 1256 * 1257 * Side Effects: 1258 * The 'archives' list is initialized. 1259 * 1260 *----------------------------------------------------------------------- 1261 */ 1262 void 1263 Arch_Init(void) 1264 { 1265 archives = Lst_Init (FALSE); 1266 } 1267 1268 1269 1270 /*- 1271 *----------------------------------------------------------------------- 1272 * Arch_End -- 1273 * Cleanup things for this module. 1274 * 1275 * Results: 1276 * None. 1277 * 1278 * Side Effects: 1279 * The 'archives' list is freed 1280 * 1281 *----------------------------------------------------------------------- 1282 */ 1283 void 1284 Arch_End(void) 1285 { 1286 #ifdef CLEANUP 1287 Lst_Destroy(archives, ArchFree); 1288 #endif 1289 } 1290 1291 /*- 1292 *----------------------------------------------------------------------- 1293 * Arch_IsLib -- 1294 * Check if the node is a library 1295 * 1296 * Results: 1297 * True or False. 1298 * 1299 * Side Effects: 1300 * None. 1301 * 1302 *----------------------------------------------------------------------- 1303 */ 1304 int 1305 Arch_IsLib(GNode *gn) 1306 { 1307 static const char armag[] = "!<arch>\n"; 1308 char buf[sizeof(armag)-1]; 1309 int fd; 1310 1311 if ((fd = open(gn->path, O_RDONLY)) == -1) 1312 return FALSE; 1313 1314 if (read(fd, buf, sizeof(buf)) != sizeof(buf)) { 1315 (void) close(fd); 1316 return FALSE; 1317 } 1318 1319 (void) close(fd); 1320 1321 return memcmp(buf, armag, sizeof(buf)) == 0; 1322 } 1323