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