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