1141104Sharti/*- 21590Srgrimes * Copyright (c) 1988, 1989, 1990, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * Copyright (c) 1989 by Berkeley Softworks 51590Srgrimes * All rights reserved. 61590Srgrimes * 71590Srgrimes * This code is derived from software contributed to Berkeley by 81590Srgrimes * Adam de Boor. 91590Srgrimes * 101590Srgrimes * Redistribution and use in source and binary forms, with or without 111590Srgrimes * modification, are permitted provided that the following conditions 121590Srgrimes * are met: 131590Srgrimes * 1. Redistributions of source code must retain the above copyright 141590Srgrimes * notice, this list of conditions and the following disclaimer. 151590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 161590Srgrimes * notice, this list of conditions and the following disclaimer in the 171590Srgrimes * documentation and/or other materials provided with the distribution. 181590Srgrimes * 3. All advertising materials mentioning features or use of this software 191590Srgrimes * must display the following acknowledgement: 201590Srgrimes * This product includes software developed by the University of 211590Srgrimes * California, Berkeley and its contributors. 221590Srgrimes * 4. Neither the name of the University nor the names of its contributors 231590Srgrimes * may be used to endorse or promote products derived from this software 241590Srgrimes * without specific prior written permission. 251590Srgrimes * 261590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 271590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 281590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 291590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 301590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 311590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 321590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 331590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 341590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 351590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 361590Srgrimes * SUCH DAMAGE. 3762833Swsanchez * 3862833Swsanchez * @(#)arch.c 8.2 (Berkeley) 1/2/94 391590Srgrimes */ 401590Srgrimes 4162833Swsanchez#include <sys/cdefs.h> 4294587Sobrien__FBSDID("$FreeBSD$"); 431590Srgrimes 441590Srgrimes/*- 451590Srgrimes * arch.c -- 461590Srgrimes * Functions to manipulate libraries, archives and their members. 471590Srgrimes * 481590Srgrimes * Once again, cacheing/hashing comes into play in the manipulation 491590Srgrimes * of archives. The first time an archive is referenced, all of its members' 501590Srgrimes * headers are read and hashed and the archive closed again. All hashed 511590Srgrimes * archives are kept on a list which is searched each time an archive member 521590Srgrimes * is referenced. 531590Srgrimes * 541590Srgrimes * The interface to this module is: 55141270Sharti * Arch_ParseArchive Given an archive specification, return a list 56141270Sharti * of GNode's, one for each member in the spec. 57146338Sharti * FALSE is returned if the specification is 58141270Sharti * invalid for some reason. 591590Srgrimes * 60141270Sharti * Arch_Touch Alter the modification time of the archive 61141270Sharti * member described by the given node to be 62141270Sharti * the current time. 631590Srgrimes * 64141270Sharti * Arch_TouchLib Update the modification time of the library 65141270Sharti * described by the given node. This is special 66141270Sharti * because it also updates the modification time 67141270Sharti * of the library's table of contents. 681590Srgrimes * 69141270Sharti * Arch_MTime Find the modification time of a member of 70141270Sharti * an archive *in the archive*. The time is also 71141270Sharti * placed in the member's GNode. Returns the 72141270Sharti * modification time. 731590Srgrimes * 74141270Sharti * Arch_MemTime Find the modification time of a member of 75141270Sharti * an archive. Called when the member doesn't 76141270Sharti * already exist. Looks in the archive for the 77141270Sharti * modification time. Returns the modification 78141270Sharti * time. 791590Srgrimes * 80141270Sharti * Arch_FindLib Search for a library along a path. The 81141270Sharti * library name in the GNode should be in 82141270Sharti * -l<name> format. 831590Srgrimes * 84141270Sharti * Arch_LibOODate Special function to decide if a library node 85141270Sharti * is out-of-date. 861590Srgrimes * 87141270Sharti * Arch_Init Initialize this module. 881590Srgrimes */ 891590Srgrimes 90141104Sharti#include <sys/param.h> 91144387Sharti#include <sys/queue.h> 92141104Sharti#include <sys/types.h> 93141104Sharti#include <ar.h> 94141104Sharti#include <ctype.h> 95144387Sharti#include <errno.h> 96144387Sharti#include <inttypes.h> 97176799Simp#include <limits.h> 98141104Sharti#include <regex.h> 99141104Sharti#include <stdlib.h> 100141104Sharti#include <stdio.h> 101141104Sharti#include <string.h> 102141104Sharti#include <utime.h> 1031590Srgrimes 104141104Sharti#include "arch.h" 105142457Sharti#include "buf.h" 106200630Sstas#include "config.h" 107141104Sharti#include "dir.h" 108141104Sharti#include "globals.h" 109141104Sharti#include "GNode.h" 110141104Sharti#include "hash.h" 111141104Sharti#include "make.h" 112146066Sharti#include "parse.h" 113141104Sharti#include "targ.h" 114141104Sharti#include "util.h" 115141104Sharti#include "var.h" 116141104Sharti 1171590Srgrimestypedef struct Arch { 118142173Sharti char *name; /* Name of archive */ 119142173Sharti 120142173Sharti /* 121142173Sharti * All the members of the archive described 122142173Sharti * by <name, struct ar_hdr *> key/value pairs 123142173Sharti */ 124142173Sharti Hash_Table members; 125143657Sharti 126144387Sharti TAILQ_ENTRY(Arch) link; /* link all cached archives */ 1271590Srgrimes} Arch; 1281590Srgrimes 129144387Sharti/* Lst of archives we've already examined */ 130144387Shartistatic TAILQ_HEAD(, Arch) archives = TAILQ_HEAD_INITIALIZER(archives); 1311590Srgrimes 132144387Sharti 133144387Sharti/* size of the name field in the archive member header */ 134144387Sharti#define AR_NAMSIZ sizeof(((struct ar_hdr *)0)->ar_name) 135144387Sharti 136144387Sharti/* 137144387Sharti * This structure is used while reading/writing an archive 138144387Sharti */ 139144387Shartistruct arfile { 140144387Sharti FILE *fp; /* archive file */ 141144387Sharti char *fname; /* name of the file */ 142144387Sharti struct ar_hdr hdr; /* current header */ 143144387Sharti char sname[AR_NAMSIZ + 1]; /* short name */ 144144387Sharti char *member; /* (long) member name */ 145144387Sharti size_t mlen; /* size of the above */ 146144387Sharti char *nametab; /* name table */ 147144387Sharti size_t nametablen; /* size of the table */ 148144387Sharti int64_t time; /* from ar_date */ 149144387Sharti uint64_t size; /* from ar_size */ 150144387Sharti off_t pos; /* header pos of current entry */ 151144387Sharti}; 152144387Sharti 153144387Sharti/* 154144387Sharti * Name of the symbol table. The original BSD used "__.SYMDEF". Rumours go 155144387Sharti * that this name may have a slash appended sometimes. Actually FreeBSD 156144387Sharti * uses "/" which probably came from SVR4. 157144387Sharti */ 158144387Sharti#define SVR4_RANLIBMAG "/" 159144387Sharti#define BSD_RANLIBMAG "__.SYMDEF" 160144387Sharti 161144387Sharti/* 162144387Sharti * Name of the filename table. The 4.4BSD ar format did not use this, but 163144387Sharti * puts long filenames directly between the member header and the object 164144387Sharti * file. 165144387Sharti */ 166144387Sharti#define SVR4_NAMEMAG "//" 167144387Sharti#define BSD_NAMEMAG "ARFILENAMES/" 168144387Sharti 169144387Sharti/* 170144387Sharti * 44BSD long filename key. Use a local define here instead of relying 171144387Sharti * on ar.h because we want this to continue working even when the 172144387Sharti * definition is removed from ar.h. 173144387Sharti */ 174144387Sharti#define BSD_EXT1 "#1/" 175144387Sharti#define BSD_EXT1LEN 3 176144387Sharti 177144387Sharti/* if this is TRUE make archive errors fatal */ 178144387ShartiBoolean arch_fatal = TRUE; 179144387Sharti 180144387Sharti/** 181144387Sharti * ArchError 182144387Sharti * An error happend while handling an archive. BSDmake traditionally 183144387Sharti * ignored these errors. Now this is dependend on the global arch_fatal 184144387Sharti * which, if true, makes these errors fatal and, if false, just emits an 185144387Sharti * error message. 186144387Sharti */ 187144387Sharti#define ArchError(ARGS) do { \ 188144387Sharti if (arch_fatal) \ 189144387Sharti Fatal ARGS; \ 190144387Sharti else \ 191144387Sharti Error ARGS; \ 192144387Sharti } while (0) 193144387Sharti 1941590Srgrimes/*- 1951590Srgrimes *----------------------------------------------------------------------- 1961590Srgrimes * Arch_ParseArchive -- 1971590Srgrimes * Parse the archive specification in the given line and find/create 1981590Srgrimes * the nodes for the specified archive members, placing their nodes 199104696Sjmallett * on the given list, given the pointer to the start of the 200104696Sjmallett * specification, a Lst on which to place the nodes, and a context 201104696Sjmallett * in which to expand variables. 2021590Srgrimes * 2031590Srgrimes * Results: 204146338Sharti * TRUE if it was a valid specification. The linePtr is updated 2051590Srgrimes * to point to the first non-space after the archive spec. The 2061590Srgrimes * nodes for the members are placed on the given list. 2071590Srgrimes * 2081590Srgrimes * Side Effects: 2091590Srgrimes * Some nodes may be created. The given list is extended. 2101590Srgrimes * 2111590Srgrimes *----------------------------------------------------------------------- 2121590Srgrimes */ 213146338ShartiBoolean 214138512ShartiArch_ParseArchive(char **linePtr, Lst *nodeLst, GNode *ctxt) 2151590Srgrimes{ 216142173Sharti char *cp; /* Pointer into line */ 217142173Sharti GNode *gn; /* New node */ 218142173Sharti char *libName; /* Library-part of specification */ 219142173Sharti char *memName; /* Member-part of specification */ 220142173Sharti char *nameBuf; /* temporary place for node name */ 221142173Sharti char saveChar; /* Ending delimiter of member-name */ 222142173Sharti Boolean subLibName; /* TRUE if libName should have/had 223141270Sharti * variable substitution performed on it */ 2241590Srgrimes 225142173Sharti libName = *linePtr; 2268874Srgrimes 227142173Sharti subLibName = FALSE; 2281590Srgrimes 229142173Sharti for (cp = libName; *cp != '(' && *cp != '\0'; cp++) { 230142173Sharti if (*cp == '$') { 231142173Sharti /* 232142173Sharti * Variable spec, so call the Var module to parse the 233142173Sharti * puppy so we can safely advance beyond it... 234142173Sharti */ 235142937Sharti size_t length = 0; 236142173Sharti Boolean freeIt; 237142173Sharti char *result; 2388874Srgrimes 239142173Sharti result = Var_Parse(cp, ctxt, TRUE, &length, &freeIt); 240142173Sharti if (result == var_Error) { 241146338Sharti return (FALSE); 242142173Sharti } 243142173Sharti subLibName = TRUE; 2448874Srgrimes 245142173Sharti if (freeIt) { 246142173Sharti free(result); 247142173Sharti } 248142173Sharti cp += length - 1; 249142173Sharti } 2501590Srgrimes } 2511590Srgrimes 252142173Sharti *cp++ = '\0'; 253142173Sharti if (subLibName) { 254146027Sharti libName = Buf_Peel(Var_Subst(libName, ctxt, TRUE)); 255142173Sharti } 2561590Srgrimes 257142173Sharti for (;;) { 258142173Sharti /* 259142173Sharti * First skip to the start of the member's name, mark that 260142173Sharti * place and skip to the end of it (either white-space or 261142173Sharti * a close paren). 262142173Sharti */ 2631590Srgrimes 2641590Srgrimes /* 265142173Sharti * TRUE if need to substitute in memName 2661590Srgrimes */ 267142173Sharti Boolean doSubst = FALSE; 2681590Srgrimes 269142173Sharti while (*cp != '\0' && *cp != ')' && 270142173Sharti isspace((unsigned char)*cp)) { 271143105Sharti cp++; 2721590Srgrimes } 2731590Srgrimes 274142173Sharti memName = cp; 275142173Sharti while (*cp != '\0' && *cp != ')' && 276142173Sharti !isspace((unsigned char)*cp)) { 277142173Sharti if (*cp == '$') { 278142173Sharti /* 279142173Sharti * Variable spec, so call the Var module to 280142173Sharti * parse the puppy so we can safely advance 281142173Sharti * beyond it... 282142173Sharti */ 283142937Sharti size_t length = 0; 284142173Sharti Boolean freeIt; 285142173Sharti char *result; 286142173Sharti 287142173Sharti result = Var_Parse(cp, ctxt, TRUE, 288142173Sharti &length, &freeIt); 289142173Sharti if (result == var_Error) { 290146338Sharti return (FALSE); 291142173Sharti } 292142173Sharti doSubst = TRUE; 293142173Sharti 294142173Sharti if (freeIt) { 295142173Sharti free(result); 296142173Sharti } 297142173Sharti cp += length; 298142173Sharti } else { 299142173Sharti cp++; 300142173Sharti } 3011590Srgrimes } 3021590Srgrimes 303142173Sharti /* 304142173Sharti * If the specification ends without a closing parenthesis, 305142173Sharti * chances are there's something wrong (like a missing 306142173Sharti * backslash), so it's better to return failure than allow 307142173Sharti * such things to happen 308142173Sharti */ 309142173Sharti if (*cp == '\0') { 310142173Sharti printf("No closing parenthesis in archive " 311142173Sharti "specification\n"); 312146338Sharti return (FALSE); 313142173Sharti } 3141590Srgrimes 315142173Sharti /* 316142173Sharti * If we didn't move anywhere, we must be done 317142173Sharti */ 318142173Sharti if (cp == memName) { 319142173Sharti break; 320142173Sharti } 3211590Srgrimes 322142173Sharti saveChar = *cp; 323142173Sharti *cp = '\0'; 3241590Srgrimes 325142173Sharti /* 326142173Sharti * XXX: This should be taken care of intelligently by 327142173Sharti * SuffExpandChildren, both for the archive and the member 328142173Sharti * portions. 329142173Sharti */ 330142173Sharti /* 331142173Sharti * If member contains variables, try and substitute for them. 332142173Sharti * This will slow down archive specs with dynamic sources, of 333142173Sharti * course, since we'll be (non-)substituting them three times, 334142173Sharti * but them's the breaks -- we need to do this since 335142173Sharti * SuffExpandChildren calls us, otherwise we could assume the 336142173Sharti * thing would be taken care of later. 337142173Sharti */ 338142173Sharti if (doSubst) { 339142173Sharti char *buf; 340142173Sharti char *sacrifice; 341142173Sharti char *oldMemName = memName; 342142173Sharti size_t sz; 343142457Sharti Buffer *buf1; 3448874Srgrimes 345142173Sharti /* 346142173Sharti * Now form an archive spec and recurse to deal with 347142173Sharti * nested variables and multi-word variable values.... 348142173Sharti * The results are just placed at the end of the 349142173Sharti * nodeLst we're returning. 350142173Sharti */ 351146027Sharti buf1 = Var_Subst(memName, ctxt, TRUE); 352143959Sharti memName = Buf_Data(buf1); 3531590Srgrimes 354142173Sharti sz = strlen(memName) + strlen(libName) + 3; 355142457Sharti buf = emalloc(sz); 3561590Srgrimes 357142173Sharti snprintf(buf, sz, "%s(%s)", libName, memName); 35869390Swill 359142457Sharti sacrifice = buf; 360142457Sharti 361142173Sharti if (strchr(memName, '$') && 362142173Sharti strcmp(memName, oldMemName) == 0) { 363142173Sharti /* 364142173Sharti * Must contain dynamic sources, so we can't 365142173Sharti * deal with it now. 366142173Sharti * Just create an ARCHV node for the thing and 367142173Sharti * let SuffExpandChildren handle it... 368142173Sharti */ 369142173Sharti gn = Targ_FindNode(buf, TARG_CREATE); 3701590Srgrimes 371142173Sharti if (gn == NULL) { 372142173Sharti free(buf); 373142457Sharti Buf_Destroy(buf1, FALSE); 374146338Sharti return (FALSE); 375142173Sharti } 376142173Sharti gn->type |= OP_ARCHV; 377142173Sharti Lst_AtEnd(nodeLst, (void *)gn); 378146338Sharti } else if (!Arch_ParseArchive(&sacrifice, nodeLst, 379146338Sharti ctxt)) { 380142173Sharti /* 381142173Sharti * Error in nested call -- free buffer and 382146338Sharti * return FALSE ourselves. 383142173Sharti */ 384142173Sharti free(buf); 385142457Sharti Buf_Destroy(buf1, FALSE); 386146338Sharti return (FALSE); 387142173Sharti } 388142457Sharti 389142457Sharti /* Free buffer and continue with our work. */ 390142173Sharti free(buf); 391142457Sharti Buf_Destroy(buf1, FALSE); 392142457Sharti 393142173Sharti } else if (Dir_HasWildcards(memName)) { 394142173Sharti Lst members = Lst_Initializer(members); 395142173Sharti char *member; 396142173Sharti size_t sz = MAXPATHLEN; 397142173Sharti size_t nsz; 398138196Sharti 399142173Sharti nameBuf = emalloc(sz); 4001590Srgrimes 401144020Sharti Path_Expand(memName, &dirSearchPath, &members); 402142173Sharti while (!Lst_IsEmpty(&members)) { 403142173Sharti member = Lst_DeQueue(&members); 404142173Sharti nsz = strlen(libName) + strlen(member) + 3; 405142173Sharti if (nsz > sz) { 406142173Sharti sz = nsz * 2; 407142173Sharti nameBuf = erealloc(nameBuf, sz); 408142173Sharti } 4098874Srgrimes 410142173Sharti snprintf(nameBuf, sz, "%s(%s)", 411142173Sharti libName, member); 412142173Sharti free(member); 413142173Sharti gn = Targ_FindNode(nameBuf, TARG_CREATE); 414142173Sharti if (gn == NULL) { 415142173Sharti free(nameBuf); 416142173Sharti /* XXXHB Lst_Destroy(&members) */ 417146338Sharti return (FALSE); 418142173Sharti } 419142173Sharti /* 420142173Sharti * We've found the node, but have to make sure 421142173Sharti * the rest of the world knows it's an archive 422142173Sharti * member, without having to constantly check 423142173Sharti * for parentheses, so we type the thing with 424142173Sharti * the OP_ARCHV bit before we place it on the 425142173Sharti * end of the provided list. 426142173Sharti */ 427142173Sharti gn->type |= OP_ARCHV; 428142173Sharti Lst_AtEnd(nodeLst, gn); 429142173Sharti } 430142173Sharti free(nameBuf); 4311590Srgrimes } else { 432142173Sharti size_t sz = strlen(libName) + strlen(memName) + 3; 433142173Sharti 434142173Sharti nameBuf = emalloc(sz); 435142173Sharti snprintf(nameBuf, sz, "%s(%s)", libName, memName); 436142173Sharti gn = Targ_FindNode(nameBuf, TARG_CREATE); 437142173Sharti free(nameBuf); 438142173Sharti if (gn == NULL) { 439146338Sharti return (FALSE); 440142173Sharti } 441142173Sharti /* 442142173Sharti * We've found the node, but have to make sure the 443142173Sharti * rest of the world knows it's an archive member, 444142173Sharti * without having to constantly check for parentheses, 445142173Sharti * so we type the thing with the OP_ARCHV bit before 446142173Sharti * we place it on the end of the provided list. 447142173Sharti */ 448142173Sharti gn->type |= OP_ARCHV; 449142173Sharti Lst_AtEnd(nodeLst, gn); 4501590Srgrimes } 451142173Sharti if (doSubst) { 452142173Sharti free(memName); 453142173Sharti } 454142173Sharti 455142173Sharti *cp = saveChar; 4561590Srgrimes } 457142173Sharti 458142173Sharti /* 459142173Sharti * If substituted libName, free it now, since we need it no longer. 460142173Sharti */ 461142173Sharti if (subLibName) { 462142173Sharti free(libName); 4631590Srgrimes } 4648874Srgrimes 465142173Sharti /* 466142173Sharti * We promised the pointer would be set up at the next non-space, so 467142173Sharti * we must advance cp there before setting *linePtr... (note that on 468142173Sharti * entrance to the loop, cp is guaranteed to point at a ')') 469142173Sharti */ 470142173Sharti do { 471142173Sharti cp++; 472142173Sharti } while (*cp != '\0' && isspace((unsigned char)*cp)); 4731590Srgrimes 474142173Sharti *linePtr = cp; 475146338Sharti return (TRUE); 4761590Srgrimes} 4771590Srgrimes 478144387Sharti/* 479144387Sharti * Close an archive file an free all resources 4801590Srgrimes */ 481144387Shartistatic void 482144387ShartiArchArchiveClose(struct arfile *ar) 4831590Srgrimes{ 4841590Srgrimes 485144387Sharti if (ar->nametab != NULL) 486144387Sharti free(ar->nametab); 487144387Sharti free(ar->member); 488144387Sharti if (ar->fp != NULL) { 489144387Sharti if (fclose(ar->fp) == EOF) 490144387Sharti ArchError(("%s: close error", ar->fname)); 491144387Sharti } 492144387Sharti free(ar->fname); 493144387Sharti free(ar); 494144387Sharti} 495144387Sharti 496144387Sharti/* 497144387Sharti * Open an archive file. 498144387Sharti */ 499144387Shartistatic struct arfile * 500144387ShartiArchArchiveOpen(const char *archive, const char *mode) 501144387Sharti{ 502144387Sharti struct arfile *ar; 503144387Sharti char magic[SARMAG]; 504144387Sharti 505144387Sharti ar = emalloc(sizeof(*ar)); 506144387Sharti ar->fname = estrdup(archive); 507144387Sharti ar->mlen = 100; 508144387Sharti ar->member = emalloc(ar->mlen); 509144387Sharti ar->nametab = NULL; 510144387Sharti ar->nametablen = 0; 511144387Sharti 512144387Sharti if ((ar->fp = fopen(ar->fname, mode)) == NULL) { 513144387Sharti DEBUGM(ARCH, ("%s", ar->fname)); 514144387Sharti ArchArchiveClose(ar); 515142173Sharti return (NULL); 516142173Sharti } 5171590Srgrimes 518144387Sharti /* read MAGIC */ 519144387Sharti if (fread(magic, SARMAG, 1, ar->fp) != 1 || 520143105Sharti strncmp(magic, ARMAG, SARMAG) != 0) { 521144387Sharti ArchError(("%s: bad archive magic\n", ar->fname)); 522144387Sharti ArchArchiveClose(ar); 523142173Sharti return (NULL); 524142165Sharti } 5255814Sjkh 526144387Sharti ar->pos = 0; 527144387Sharti return (ar); 528144387Sharti} 529144387Sharti 530144387Sharti/* 531144387Sharti * Read the next header from the archive. The return value will be +1 if 532144387Sharti * the header is read successfully, 0 on EOF and -1 if an error happend. 533144387Sharti * On a successful return sname contains the truncated member name and 534144387Sharti * member the full name. hdr contains the member header. For the symbol table 535144387Sharti * names of length 0 are returned. The entry for the file name table is never 536144387Sharti * returned. 537144387Sharti */ 538144387Shartistatic int 539144387ShartiArchArchiveNext(struct arfile *ar) 540144387Sharti{ 541144387Sharti char *end; 542144387Sharti int have_long_name; 543144387Sharti u_long offs; 544144387Sharti char *ptr; 545144387Sharti size_t ret; 546144387Sharti char buf[MAX(sizeof(ar->hdr.ar_size), sizeof(ar->hdr.ar_date)) + 1]; 547144387Sharti 548144387Sharti next: 5491590Srgrimes /* 550144387Sharti * Seek to the next header. 551142297Sharti */ 552144387Sharti if (ar->pos == 0) { 553144387Sharti ar->pos = SARMAG; 554144387Sharti } else { 555144387Sharti ar->pos += sizeof(ar->hdr) + ar->size; 556144387Sharti if (ar->size % 2 == 1) 557144387Sharti ar->pos++; 5581590Srgrimes } 559144387Sharti 560144387Sharti if (fseeko(ar->fp, ar->pos, SEEK_SET) == -1) { 561144387Sharti ArchError(("%s: cannot seek to %jd: %s", ar->fname, 562144387Sharti (intmax_t)ar->pos, strerror(errno))); 563144387Sharti return (-1); 564142173Sharti } 5651590Srgrimes 566144387Sharti /* 567144387Sharti * Read next member header 568144387Sharti */ 569144387Sharti ret = fread(&ar->hdr, sizeof(ar->hdr), 1, ar->fp); 570144387Sharti if (ret != 1) { 571144387Sharti if (feof(ar->fp)) 572144387Sharti return (0); 573144387Sharti ArchError(("%s: error reading member header: %s", ar->fname, 574144387Sharti strerror(errno))); 575144387Sharti return (-1); 576144387Sharti } 577144387Sharti if (strncmp(ar->hdr.ar_fmag, ARFMAG, sizeof(ar->hdr.ar_fmag)) != 0) { 578144387Sharti ArchError(("%s: bad entry magic", ar->fname)); 579144387Sharti return (-1); 580144387Sharti } 5818874Srgrimes 582144387Sharti /* 583144387Sharti * looks like a member - get name by stripping trailing spaces 584144387Sharti * and NUL terminating. 585144387Sharti */ 586194797Sdelphij strlcpy(ar->sname, ar->hdr.ar_name, AR_NAMSIZ + 1); 587144387Sharti for (ptr = ar->sname + AR_NAMSIZ; ptr > ar->sname; ptr--) 588144387Sharti if (ptr[-1] != ' ') 589144387Sharti break; 590144387Sharti 591144387Sharti *ptr = '\0'; 592144387Sharti 593144387Sharti /* 594144387Sharti * Parse the size. All entries need to have a size. Be careful 595144387Sharti * to not allow buffer overruns. 596144387Sharti */ 597194797Sdelphij strlcpy(buf, ar->hdr.ar_size, sizeof(ar->hdr.ar_size) + 1); 598144387Sharti 599144387Sharti errno = 0; 600144387Sharti ar->size = strtoumax(buf, &end, 10); 601144387Sharti if (errno != 0 || strspn(end, " ") != strlen(end)) { 602144387Sharti ArchError(("%s: bad size format in archive '%s'", 603144387Sharti ar->fname, buf)); 604144387Sharti return (-1); 605144387Sharti } 606144387Sharti 607144387Sharti /* 608144387Sharti * Look for the extended name table. Do this before parsing 609144387Sharti * the date because this table doesn't need a date. 610144387Sharti */ 611144387Sharti if (strcmp(ar->sname, BSD_NAMEMAG) == 0 || 612144387Sharti strcmp(ar->sname, SVR4_NAMEMAG) == 0) { 613144387Sharti /* filename table - read it in */ 614144387Sharti ar->nametablen = ar->size; 615144387Sharti ar->nametab = emalloc(ar->nametablen); 616144387Sharti 617144387Sharti ret = fread(ar->nametab, 1, ar->nametablen, ar->fp); 618144387Sharti if (ret != ar->nametablen) { 619144387Sharti if (ferror(ar->fp)) { 620144387Sharti ArchError(("%s: cannot read nametab: %s", 621144387Sharti ar->fname, strerror(errno))); 622144387Sharti } else { 623144387Sharti ArchError(("%s: cannot read nametab: " 624144387Sharti "short read", ar->fname, strerror(errno))); 625143657Sharti } 626144387Sharti return (-1); 627142173Sharti } 628144387Sharti 62918730Ssteve /* 630144387Sharti * NUL terminate the entries. Entries are \n terminated 631144387Sharti * and may have a trailing / or \. 63218730Ssteve */ 633144387Sharti ptr = ar->nametab; 634144387Sharti while (ptr < ar->nametab + ar->nametablen) { 635144387Sharti if (*ptr == '\n') { 636144387Sharti if (ptr[-1] == '/' || ptr[-1] == '\\') 637144387Sharti ptr[-1] = '\0'; 638144387Sharti *ptr = '\0'; 639144387Sharti } 640144387Sharti ptr++; 641144387Sharti } 642143657Sharti 643144387Sharti /* get next archive entry */ 644144387Sharti goto next; 645144387Sharti } 646144387Sharti 647144387Sharti /* 648144387Sharti * Now parse the modification date. Be careful to not overrun 649144387Sharti * buffers. 650144387Sharti */ 651194797Sdelphij strlcpy(buf, ar->hdr.ar_date, sizeof(ar->hdr.ar_date) + 1); 652144387Sharti 653144387Sharti errno = 0; 654144387Sharti ar->time = (int64_t)strtoll(buf, &end, 10); 655144387Sharti if (errno != 0 || strspn(end, " ") != strlen(end)) { 656144387Sharti ArchError(("%s: bad date format in archive '%s'", 657144387Sharti ar->fname, buf)); 658144387Sharti return (-1); 659144387Sharti } 660144387Sharti 661144387Sharti /* 662144387Sharti * Now check for the symbol table. This should really be the first 663144387Sharti * entry, but we don't check this. 664144387Sharti */ 665144387Sharti if (strcmp(ar->sname, BSD_RANLIBMAG) == 0 || 666144387Sharti strcmp(ar->sname, SVR4_RANLIBMAG) == 0) { 667144387Sharti /* symbol table - return a zero length name */ 668144387Sharti ar->member[0] = '\0'; 669144387Sharti ar->sname[0] = '\0'; 670144387Sharti return (1); 671144387Sharti } 672144387Sharti 673144387Sharti have_long_name = 0; 674144387Sharti 675144387Sharti /* 676144387Sharti * Look whether this is a long name. There are several variants 677144387Sharti * of long names: 678144387Sharti * "#1/12 " - 12 length of following filename 679144387Sharti * "/17 " - index into name table 680144387Sharti * " 17 " - index into name table 681144387Sharti * Note that in the last case we must also check that there is no 682144387Sharti * slash in the name because of filenames with leading spaces: 683144387Sharti * " 777.o/ " - filename 777.o 684144387Sharti */ 685144387Sharti if (ar->sname[0] == '/' || (ar->sname[0] == ' ' && 686144387Sharti strchr(ar->sname, '/') == NULL)) { 687144387Sharti /* SVR4 extended name */ 688144387Sharti errno = 0; 689144387Sharti offs = strtoul(ar->sname + 1, &end, 10); 690144387Sharti if (errno != 0 || *end != '\0' || offs >= ar->nametablen || 691144387Sharti end == ar->sname + 1) { 692144387Sharti ArchError(("%s: bad extended name '%s'", ar->fname, 693144387Sharti ar->sname)); 694144387Sharti return (-1); 695144387Sharti } 696144387Sharti 697144387Sharti /* fetch the name */ 698144387Sharti if (ar->mlen <= strlen(ar->nametab + offs)) { 699144387Sharti ar->mlen = strlen(ar->nametab + offs) + 1; 700144387Sharti ar->member = erealloc(ar->member, ar->mlen); 701144387Sharti } 702144387Sharti strcpy(ar->member, ar->nametab + offs); 703144387Sharti 704144387Sharti have_long_name = 1; 705144387Sharti 706144387Sharti } else if (strncmp(ar->sname, BSD_EXT1, BSD_EXT1LEN) == 0 && 707144387Sharti isdigit(ar->sname[BSD_EXT1LEN])) { 708144387Sharti /* BSD4.4 extended name */ 709144387Sharti errno = 0; 710144387Sharti offs = strtoul(ar->sname + BSD_EXT1LEN, &end, 10); 711144387Sharti if (errno != 0 || *end != '\0' || 712144387Sharti end == ar->sname + BSD_EXT1LEN) { 713144387Sharti ArchError(("%s: bad extended name '%s'", ar->fname, 714144387Sharti ar->sname)); 715144387Sharti return (-1); 716144387Sharti } 717144387Sharti 718144387Sharti /* read it from the archive */ 719144387Sharti if (ar->mlen <= offs) { 720144387Sharti ar->mlen = offs + 1; 721144387Sharti ar->member = erealloc(ar->member, ar->mlen); 722144387Sharti } 723144387Sharti ret = fread(ar->member, 1, offs, ar->fp); 724144387Sharti if (ret != offs) { 725144387Sharti if (ferror(ar->fp)) { 726144387Sharti ArchError(("%s: reading extended name: %s", 727144387Sharti ar->fname, strerror(errno))); 728144387Sharti } else { 729144387Sharti ArchError(("%s: reading extended name: " 730144387Sharti "short read", ar->fname)); 731142173Sharti } 732144387Sharti return (-1); 73318730Ssteve } 734144387Sharti ar->member[offs] = '\0'; 735144387Sharti 736144387Sharti have_long_name = 1; 7371590Srgrimes } 7381590Srgrimes 739142173Sharti /* 740144387Sharti * Now remove the trailing slash that Svr4 puts at 741144387Sharti * the end of the member name to support trailing spaces in names. 742142297Sharti */ 743144387Sharti if (ptr > ar->sname && ptr[-1] == '/') 744144387Sharti *--ptr = '\0'; 745144387Sharti 746144387Sharti if (!have_long_name) { 747144387Sharti if (strlen(ar->sname) >= ar->mlen) { 748144387Sharti ar->mlen = strlen(ar->sname) + 1; 749144387Sharti ar->member = erealloc(ar->member, ar->mlen); 750144387Sharti } 751144387Sharti strcpy(ar->member, ar->sname); 752144387Sharti } 753144387Sharti 754144387Sharti return (1); 755143657Sharti} 756143656Sharti 757144387Sharti/* 758144387Sharti * Touch the current archive member by writing a new header with an 759144387Sharti * updated timestamp. The return value is 0 for success and -1 for errors. 760144387Sharti */ 761144387Shartistatic int 762144387ShartiArchArchiveTouch(struct arfile *ar, int64_t ts) 763144387Sharti{ 764144387Sharti 765144387Sharti /* seek to our header */ 766144387Sharti if (fseeko(ar->fp, ar->pos, SEEK_SET) == -1) { 767144387Sharti ArchError(("%s: cannot seek to %jd: %s", ar->fname, 768144387Sharti (intmax_t)ar->pos, strerror(errno))); 769144387Sharti return (-1); 770144387Sharti } 771144387Sharti 772144387Sharti /* 773144387Sharti * change timestamp, be sure to not NUL-terminated it, but 774144387Sharti * to fill with spaces. 775144387Sharti */ 776146577Sharti snprintf(ar->hdr.ar_date, sizeof(ar->hdr.ar_date), "%jd", 777146577Sharti (intmax_t)ts); 778144387Sharti memset(ar->hdr.ar_date + strlen(ar->hdr.ar_date), 779144387Sharti ' ', sizeof(ar->hdr.ar_date) - strlen(ar->hdr.ar_date)); 780144387Sharti 781144387Sharti if (fwrite(&ar->hdr, sizeof(ar->hdr), 1, ar->fp) != 1) { 782144387Sharti ArchError(("%s: cannot touch: %s", ar->fname, strerror(errno))); 783144387Sharti return (-1); 784144387Sharti } 785144387Sharti return (0); 786144387Sharti} 787144387Sharti 788143657Sharti/*- 789143657Sharti *----------------------------------------------------------------------- 790144387Sharti * ArchFindMember -- 791144387Sharti * Locate a member of an archive, given the path of the archive and 792144387Sharti * the path of the desired member. If the archive is to be modified, 793144387Sharti * the mode should be "r+", if not, it should be "r". The archive 794144387Sharti * file is returned positioned at the correct header. 795143657Sharti * 796143657Sharti * Results: 797144387Sharti * A struct arfile *, opened for reading and, possibly writing, 798144387Sharti * positioned at the member's header, or NULL if the member was 799144387Sharti * nonexistent. 800143657Sharti * 801143657Sharti *----------------------------------------------------------------------- 802143657Sharti */ 803144387Shartistatic struct arfile * 804144387ShartiArchFindMember(const char *archive, const char *member, const char *mode) 805143657Sharti{ 806144387Sharti struct arfile *ar; 807144387Sharti const char *cp; /* Useful character pointer */ 808143656Sharti 809144387Sharti if ((ar = ArchArchiveOpen(archive, mode)) == NULL) 810144387Sharti return (NULL); 811143656Sharti 812144387Sharti /* 813144387Sharti * Because of space constraints and similar things, files are archived 814144387Sharti * using their final path components, not the entire thing, so we need 815144387Sharti * to point 'member' to the final component, if there is one, to make 816144387Sharti * the comparisons easier... 817144387Sharti */ 818144387Sharti if (member != NULL) { 819144387Sharti cp = strrchr(member, '/'); 820144387Sharti if (cp != NULL) { 821144387Sharti member = cp + 1; 822143656Sharti } 823144387Sharti } 824143656Sharti 825144387Sharti while (ArchArchiveNext(ar) > 0) { 826143657Sharti /* 827144387Sharti * When comparing there are actually three cases: 828144387Sharti * (1) the name fits into the limit og af_name, 829144387Sharti * (2) the name is longer and the archive supports long names, 830144387Sharti * (3) the name is longer and the archive doesn't support long 831144387Sharti * names. 832144387Sharti * Because we don't know whether the archive supports long 833144387Sharti * names or not we need to be carefull. 834143657Sharti */ 835144387Sharti if (member == NULL) { 836144387Sharti /* special case - symbol table */ 837144387Sharti if (ar->member[0] == '\0') 838144387Sharti return (ar); 839144387Sharti } else if (strlen(member) <= AR_NAMSIZ) { 840144387Sharti /* case (1) */ 841144387Sharti if (strcmp(ar->member, member) == 0) 842144387Sharti return (ar); 843144387Sharti } else if (strcmp(ar->member, member) == 0) { 844144387Sharti /* case (3) */ 845144387Sharti return (ar); 846144387Sharti } else { 847144387Sharti /* case (2) */ 848144387Sharti if (strlen(ar->member) == AR_NAMSIZ && 849144387Sharti strncmp(member, ar->member, AR_NAMSIZ) == 0) 850144387Sharti return (ar); 851143656Sharti } 852143656Sharti } 853143656Sharti 854144387Sharti /* not found */ 855144387Sharti ArchArchiveClose(ar); 856144387Sharti return (NULL); 85718730Ssteve} 85818730Ssteve 85918730Ssteve/*- 86018730Ssteve *----------------------------------------------------------------------- 861142173Sharti * ArchStatMember -- 8621590Srgrimes * Locate a member of an archive, given the path of the archive and 863142173Sharti * the path of the desired member, and a boolean representing whether 864142173Sharti * or not the archive should be hashed (if not already hashed). 8651590Srgrimes * 8661590Srgrimes * Results: 867142173Sharti * A pointer to the current struct ar_hdr structure for the member. Note 868142173Sharti * That no position is returned, so this is not useful for touching 869142173Sharti * archive members. This is mostly because we have no assurances that 870142173Sharti * The archive will remain constant after we read all the headers, so 871142173Sharti * there's not much point in remembering the position... 8721590Srgrimes * 8731590Srgrimes * Side Effects: 8741590Srgrimes * 8751590Srgrimes *----------------------------------------------------------------------- 8761590Srgrimes */ 877144387Shartistatic int64_t 878142173ShartiArchStatMember(const char *archive, const char *member, Boolean hash) 8791590Srgrimes{ 880144387Sharti struct arfile *arf; 881144387Sharti int64_t ret; 882144387Sharti int t; 883142173Sharti char *cp; /* Useful character pointer */ 884142173Sharti Arch *ar; /* Archive descriptor */ 885142173Sharti Hash_Entry *he; /* Entry containing member's description */ 886144387Sharti char copy[AR_NAMSIZ + 1]; 8871590Srgrimes 888142173Sharti /* 889142297Sharti * Because of space constraints and similar things, files are archived 890142297Sharti * using their final path components, not the entire thing, so we need 891142297Sharti * to point 'member' to the final component, if there is one, to make 892142297Sharti * the comparisons easier... 893142297Sharti */ 894144387Sharti if (member != NULL) { 895144387Sharti cp = strrchr(member, '/'); 896144387Sharti if (cp != NULL) 897144387Sharti member = cp + 1; 898144387Sharti } 8998874Srgrimes 900144387Sharti TAILQ_FOREACH(ar, &archives, link) { 901144387Sharti if (strcmp(archive, ar->name) == 0) 902143975Sharti break; 903143975Sharti } 904144387Sharti if (ar == NULL) { 905144387Sharti /* archive not found */ 906144387Sharti if (!hash) { 907142173Sharti /* 908144387Sharti * Caller doesn't want the thing hashed, just use 909144387Sharti * ArchFindMember to read the header for the member 910144387Sharti * out and close down the stream again. 911142173Sharti */ 912144387Sharti arf = ArchFindMember(archive, member, "r"); 913144387Sharti if (arf == NULL) { 914144387Sharti return (INT64_MIN); 915144387Sharti } 916144387Sharti ret = arf->time; 917144387Sharti ArchArchiveClose(arf); 918144387Sharti return (ret); 919142173Sharti } 920144387Sharti 9215814Sjkh /* 922144387Sharti * We don't have this archive on the list yet, so we want to 923144387Sharti * find out everything that's in it and cache it so we can get 924144387Sharti * at it quickly. 9255814Sjkh */ 926144387Sharti arf = ArchArchiveOpen(archive, "r"); 927144387Sharti if (arf == NULL) { 928144387Sharti return (INT64_MIN); 929142173Sharti } 9305814Sjkh 931144387Sharti /* create archive data structure */ 932144387Sharti ar = emalloc(sizeof(*ar)); 933144387Sharti ar->name = estrdup(archive); 934144387Sharti Hash_InitTable(&ar->members, -1); 935142173Sharti 936144387Sharti while ((t = ArchArchiveNext(arf)) > 0) { 937144387Sharti he = Hash_CreateEntry(&ar->members, arf->member, NULL); 938144387Sharti Hash_SetValue(he, emalloc(sizeof(int64_t))); 939144387Sharti *(int64_t *)Hash_GetValue(he) = arf->time; 9405814Sjkh } 941142173Sharti 942144387Sharti ArchArchiveClose(arf); 943142173Sharti 944144387Sharti if (t < 0) { 945144387Sharti /* error happend - throw away everything */ 946144387Sharti Hash_DeleteTable(&ar->members); 947144387Sharti free(ar->name); 948144387Sharti free(ar); 949144387Sharti return (INT64_MIN); 9505814Sjkh } 951142173Sharti 952144387Sharti TAILQ_INSERT_TAIL(&archives, ar, link); 9531590Srgrimes } 9541590Srgrimes 955142173Sharti /* 956142173Sharti * Now that the archive has been read and cached, we can look into 957142173Sharti * the hash table to find the desired member's header. 958142173Sharti */ 959142173Sharti he = Hash_FindEntry(&ar->members, member); 960144387Sharti if (he != NULL) 961144387Sharti return (*(int64_t *)Hash_GetValue (he)); 962142173Sharti 963144387Sharti if (member != NULL && strlen(member) > AR_NAMSIZ) { 964144387Sharti /* Try truncated name */ 965194797Sdelphij strlcpy(copy, member, AR_NAMSIZ + 1); 966144387Sharti 967144387Sharti if ((he = Hash_FindEntry(&ar->members, copy)) != NULL) 968144387Sharti return (*(int64_t *)Hash_GetValue(he)); 969142173Sharti } 970142173Sharti 971144387Sharti return (INT64_MIN); 9721590Srgrimes} 9731590Srgrimes 9741590Srgrimes/*- 9751590Srgrimes *----------------------------------------------------------------------- 9761590Srgrimes * Arch_Touch -- 9771590Srgrimes * Touch a member of an archive. 9781590Srgrimes * 9791590Srgrimes * Results: 9801590Srgrimes * The 'time' field of the member's header is updated. 9811590Srgrimes * 9821590Srgrimes * Side Effects: 9831590Srgrimes * The modification time of the entire archive is also changed. 9841590Srgrimes * For a library, this could necessitate the re-ranlib'ing of the 9851590Srgrimes * whole thing. 9861590Srgrimes * 9871590Srgrimes *----------------------------------------------------------------------- 9881590Srgrimes */ 9891590Srgrimesvoid 990138232ShartiArch_Touch(GNode *gn) 9911590Srgrimes{ 992144387Sharti struct arfile *ar; 9931590Srgrimes 994146580Sharti ar = ArchFindMember(Var_Value(ARCHIVE, gn), 995146580Sharti Var_Value(TARGET, gn), "r+"); 9961590Srgrimes 997144387Sharti if (ar != NULL) { 998144387Sharti ArchArchiveTouch(ar, (int64_t)now); 999144387Sharti ArchArchiveClose(ar); 1000142173Sharti } 10011590Srgrimes} 10021590Srgrimes 10031590Srgrimes/*- 10041590Srgrimes *----------------------------------------------------------------------- 10051590Srgrimes * Arch_TouchLib -- 10061590Srgrimes * Given a node which represents a library, touch the thing, making 10071590Srgrimes * sure that the table of contents also is touched. 10081590Srgrimes * 10091590Srgrimes * Results: 10101590Srgrimes * None. 10111590Srgrimes * 10121590Srgrimes * Side Effects: 10131590Srgrimes * Both the modification time of the library and of the RANLIBMAG 10141590Srgrimes * member are set to 'now'. 10151590Srgrimes * 10161590Srgrimes *----------------------------------------------------------------------- 10171590Srgrimes */ 10181590Srgrimesvoid 1019138232ShartiArch_TouchLib(GNode *gn) 10201590Srgrimes{ 1021144387Sharti struct arfile *ar; /* Open archive */ 1022142173Sharti struct utimbuf times; /* Times for utime() call */ 10231590Srgrimes 1024144387Sharti ar = ArchFindMember(gn->path, NULL, "r+"); 1025144387Sharti if (ar != NULL) { 1026144387Sharti ArchArchiveTouch(ar, (int64_t)now); 1027144387Sharti ArchArchiveClose(ar); 10281590Srgrimes 1029142173Sharti times.actime = times.modtime = now; 1030142173Sharti utime(gn->path, ×); 1031142173Sharti } 10321590Srgrimes} 10331590Srgrimes 10341590Srgrimes/*- 10351590Srgrimes *----------------------------------------------------------------------- 10361590Srgrimes * Arch_MTime -- 1037104696Sjmallett * Return the modification time of a member of an archive, given its 1038104696Sjmallett * name. 10391590Srgrimes * 10401590Srgrimes * Results: 1041138232Sharti * The modification time(seconds). 1042142173Sharti * XXXHB this should be a long. 10431590Srgrimes * 10441590Srgrimes * Side Effects: 10451590Srgrimes * The mtime field of the given node is filled in with the value 10461590Srgrimes * returned by the function. 10471590Srgrimes * 10481590Srgrimes *----------------------------------------------------------------------- 10491590Srgrimes */ 10501590Srgrimesint 1051104696SjmallettArch_MTime(GNode *gn) 10521590Srgrimes{ 1053144387Sharti int64_t mtime; 10541590Srgrimes 1055146580Sharti mtime = ArchStatMember(Var_Value(ARCHIVE, gn), 1056146580Sharti Var_Value(TARGET, gn), TRUE); 10575814Sjkh 1058144387Sharti if (mtime == INT_MIN) { 1059144387Sharti mtime = 0; 1060142173Sharti } 1061144387Sharti gn->mtime = (int)mtime; /* XXX */ 1062144387Sharti return (gn->mtime); 10631590Srgrimes} 10641590Srgrimes 10651590Srgrimes/*- 10661590Srgrimes *----------------------------------------------------------------------- 10671590Srgrimes * Arch_MemMTime -- 10681590Srgrimes * Given a non-existent archive member's node, get its modification 10691590Srgrimes * time from its archived form, if it exists. 10701590Srgrimes * 10711590Srgrimes * Results: 10721590Srgrimes * The modification time. 10731590Srgrimes * 10741590Srgrimes * Side Effects: 10751590Srgrimes * The mtime field is filled in. 10761590Srgrimes * 10771590Srgrimes *----------------------------------------------------------------------- 10781590Srgrimes */ 10791590Srgrimesint 1080138232ShartiArch_MemMTime(GNode *gn) 10811590Srgrimes{ 1082142173Sharti LstNode *ln; 1083142173Sharti GNode *pgn; 1084142173Sharti char *nameStart; 1085142173Sharti char *nameEnd; 10861590Srgrimes 1087142173Sharti for (ln = Lst_First(&gn->parents); ln != NULL; ln = Lst_Succ(ln)) { 1088142173Sharti pgn = Lst_Datum(ln); 10891590Srgrimes 1090142173Sharti if (pgn->type & OP_ARCHV) { 1091142173Sharti /* 1092142173Sharti * If the parent is an archive specification and is 1093142173Sharti * being made and its member's name matches the name of 1094142173Sharti * the node we were given, record the modification time 1095142173Sharti * of the parent in the child. We keep searching its 1096142173Sharti * parents in case some other parent requires this 1097142173Sharti * child to exist... 1098142173Sharti */ 1099142173Sharti nameStart = strchr(pgn->name, '(') + 1; 1100142173Sharti nameEnd = strchr(nameStart, ')'); 11011590Srgrimes 1102142173Sharti if (pgn->make && strncmp(nameStart, gn->name, 1103142173Sharti nameEnd - nameStart) == 0) { 1104142173Sharti gn->mtime = Arch_MTime(pgn); 1105142173Sharti } 1106142173Sharti } else if (pgn->make) { 1107142173Sharti /* 1108142173Sharti * Something which isn't a library depends on the 1109142173Sharti * existence of this target, so it needs to exist. 1110142173Sharti */ 1111142173Sharti gn->mtime = 0; 1112142173Sharti break; 1113142173Sharti } 11141590Srgrimes } 1115142173Sharti return (gn->mtime); 11161590Srgrimes} 11171590Srgrimes 11181590Srgrimes/*- 11191590Srgrimes *----------------------------------------------------------------------- 11201590Srgrimes * Arch_FindLib -- 1121104696Sjmallett * Search for a named library along the given search path. 11221590Srgrimes * 11231590Srgrimes * Results: 11241590Srgrimes * None. 11251590Srgrimes * 11261590Srgrimes * Side Effects: 11271590Srgrimes * The node's 'path' field is set to the found path (including the 11281590Srgrimes * actual file name, not -l...). If the system can handle the -L 11291590Srgrimes * flag when linking (or we cannot find the library), we assume that 11301590Srgrimes * the user has placed the .LIBRARIES variable in the final linking 11311590Srgrimes * command (or the linker will know where to find it) and set the 11321590Srgrimes * TARGET variable for this node to be the node's name. Otherwise, 11331590Srgrimes * we set the TARGET variable to be the full path of the library, 1134199419Sobrien * as returned by Path_FindFile. 11351590Srgrimes * 11361590Srgrimes *----------------------------------------------------------------------- 11371590Srgrimes */ 11381590Srgrimesvoid 1139144020ShartiArch_FindLib(GNode *gn, struct Path *path) 11401590Srgrimes{ 1141142173Sharti char *libName; /* file name for archive */ 1142142173Sharti size_t sz; 11431590Srgrimes 1144142173Sharti sz = strlen(gn->name) + 4; 1145142173Sharti libName = emalloc(sz); 1146142173Sharti snprintf(libName, sz, "lib%s.a", &gn->name[2]); 11471590Srgrimes 1148144020Sharti gn->path = Path_FindFile(libName, path); 11491590Srgrimes 1150142173Sharti free(libName); 11511590Srgrimes 11521590Srgrimes#ifdef LIBRARIES 1153142173Sharti Var_Set(TARGET, gn->name, gn); 11541590Srgrimes#else 1155142173Sharti Var_Set(TARGET, gn->path == NULL ? gn->name : gn->path, gn); 115618730Ssteve#endif /* LIBRARIES */ 11571590Srgrimes} 11581590Srgrimes 11591590Srgrimes/*- 11601590Srgrimes *----------------------------------------------------------------------- 11611590Srgrimes * Arch_LibOODate -- 11621590Srgrimes * Decide if a node with the OP_LIB attribute is out-of-date. Called 1163104696Sjmallett * from Make_OODate to make its life easier, with the library's 1164104696Sjmallett * graph node. 11651590Srgrimes * 11661590Srgrimes * There are several ways for a library to be out-of-date that are 11671590Srgrimes * not available to ordinary files. In addition, there are ways 11681590Srgrimes * that are open to regular files that are not available to 11691590Srgrimes * libraries. A library that is only used as a source is never 11701590Srgrimes * considered out-of-date by itself. This does not preclude the 11711590Srgrimes * library's modification time from making its parent be out-of-date. 11721590Srgrimes * A library will be considered out-of-date for any of these reasons, 11731590Srgrimes * given that it is a target on a dependency line somewhere: 11741590Srgrimes * Its modification time is less than that of one of its 1175141270Sharti * sources (gn->mtime < gn->cmtime). 11761590Srgrimes * Its modification time is greater than the time at which the 1177141270Sharti * make began (i.e. it's been modified in the course 1178141270Sharti * of the make, probably by archiving). 11795814Sjkh * The modification time of one of its sources is greater than 11805814Sjkh * the one of its RANLIBMAG member (i.e. its table of contents 1181141270Sharti * is out-of-date). We don't compare of the archive time 11825814Sjkh * vs. TOC time because they can be too close. In my 11835814Sjkh * opinion we should not bother with the TOC at all since 11845814Sjkh * this is used by 'ar' rules that affect the data contents 11855814Sjkh * of the archive, not by ranlib rules, which affect the 11868874Srgrimes * TOC. 11871590Srgrimes * 11881590Srgrimes * Results: 11891590Srgrimes * TRUE if the library is out-of-date. FALSE otherwise. 11901590Srgrimes * 11911590Srgrimes * Side Effects: 11921590Srgrimes * The library will be hashed if it hasn't been already. 11931590Srgrimes * 11941590Srgrimes *----------------------------------------------------------------------- 11951590Srgrimes */ 11961590SrgrimesBoolean 1197138232ShartiArch_LibOODate(GNode *gn) 11981590Srgrimes{ 1199144387Sharti int64_t mtime; /* The table-of-contents's mod time */ 12001590Srgrimes 1201142173Sharti if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->children)) { 1202142173Sharti return (FALSE); 1203142173Sharti } 1204143105Sharti if (gn->mtime > now || gn->mtime < gn->cmtime) { 1205142173Sharti return (TRUE); 1206142173Sharti } 1207142173Sharti 1208144387Sharti mtime = ArchStatMember(gn->path, NULL, FALSE); 1209144387Sharti if (mtime == INT64_MIN) { 1210142173Sharti /* 1211144387Sharti * Not found. A library w/o a table of contents is out-of-date 1212142173Sharti */ 1213142173Sharti if (DEBUG(ARCH) || DEBUG(MAKE)) { 1214144387Sharti Debug("No TOC..."); 1215142173Sharti } 1216142173Sharti return (TRUE); 12171590Srgrimes } 12181590Srgrimes 1219144387Sharti /* XXX choose one. */ 1220144387Sharti if (DEBUG(ARCH) || DEBUG(MAKE)) { 1221144387Sharti Debug("TOC modified %s...", Targ_FmtTime(mtime)); 1222144387Sharti } 1223144387Sharti return (gn->cmtime > mtime); 12241590Srgrimes} 1225