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