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