arch.c revision 143656
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: head/usr.bin/make/arch.c 143656 2005-03-15 15:05:14Z harti $"); 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. 57141270Sharti * FAILURE 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> 91141104Sharti#include <sys/types.h> 92141104Sharti#include <ar.h> 93141104Sharti#include <ctype.h> 94143656Sharti#include <errno.h> 95143656Sharti#include <inttypes.h> 96141104Sharti#include <regex.h> 97141104Sharti#include <stdlib.h> 98141104Sharti#include <stdio.h> 99141104Sharti#include <string.h> 100141104Sharti#include <utime.h> 1011590Srgrimes 102141104Sharti#include "arch.h" 103142457Sharti#include "buf.h" 104141104Sharti#include "config.h" 105141104Sharti#include "dir.h" 106141104Sharti#include "globals.h" 107141104Sharti#include "GNode.h" 108141104Sharti#include "hash.h" 109141104Sharti#include "make.h" 110141104Sharti#include "targ.h" 111141104Sharti#include "util.h" 112141104Sharti#include "var.h" 113141104Sharti 114138916Sharti/* Lst of archives we've already examined */ 115138916Shartistatic Lst archives = Lst_Initializer(archives); 1161590Srgrimes 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; 1251590Srgrimes} Arch; 1261590Srgrimes 127143656Sharti/* size of the name field in the archive member header */ 128143656Sharti#define AR_NAMSIZ sizeof(((struct ar_hdr *)0)->ar_name) 1291590Srgrimes 130143656Sharti/* 131143656Sharti * This structure is used while reading/writing an archive 132143656Sharti */ 133143656Shartistruct arfile { 134143656Sharti FILE *fp; /* archive file */ 135143656Sharti char *fname; /* name of the file */ 136143656Sharti struct ar_hdr hdr; /* current header */ 137143656Sharti char sname[AR_NAMSIZ + 1]; /* short name */ 138143656Sharti char *member; /* (long) member name */ 139143656Sharti size_t mlen; /* size of the above */ 140143656Sharti char *nametab; /* name table */ 141143656Sharti size_t nametablen; /* size of the table */ 142143656Sharti int64_t time; /* from ar_date */ 143143656Sharti uint64_t size; /* from ar_size */ 144143656Sharti off_t pos; /* header pos of current entry */ 145143656Sharti}; 146143656Sharti 147143656Sharti/* 148143656Sharti * Name of the symbol table. The original BSD used "__.SYMDEF". Rumours go 149143656Sharti * that this name may have a slash appended sometimes. Actually FreeBSD 150143656Sharti * uses "/" which probably came from SVR4. 151143656Sharti */ 152143656Sharti#define SVR4_RANLIBMAG "/" 153143656Sharti#define BSD_RANLIBMAG "__.SYMDEF" 154143656Sharti 155143656Sharti/* 156143656Sharti * Name of the filename table. The 4.4BSD ar format did not use this, but 157143656Sharti * puts long filenames directly between the member header and the object 158143656Sharti * file. 159143656Sharti */ 160143656Sharti#define SVR4_NAMEMAG "//" 161143656Sharti#define BSD_NAMEMAG "ARFILENAMES/" 162143656Sharti 163143656Sharti/* 164143656Sharti * 44BSD long filename key. Use a local define here instead of relying 165143656Sharti * on ar.h because we want this to continue working even when the 166143656Sharti * definition is removed from ar.h. 167143656Sharti */ 168143656Sharti#define BSD_EXT1 "#1/" 169143656Sharti#define BSD_EXT1LEN 3 170143656Sharti 1711590Srgrimes/*- 1721590Srgrimes *----------------------------------------------------------------------- 1731590Srgrimes * Arch_ParseArchive -- 1741590Srgrimes * Parse the archive specification in the given line and find/create 1751590Srgrimes * the nodes for the specified archive members, placing their nodes 176104696Sjmallett * on the given list, given the pointer to the start of the 177104696Sjmallett * specification, a Lst on which to place the nodes, and a context 178104696Sjmallett * in which to expand variables. 1791590Srgrimes * 1801590Srgrimes * Results: 1811590Srgrimes * SUCCESS if it was a valid specification. The linePtr is updated 1821590Srgrimes * to point to the first non-space after the archive spec. The 1831590Srgrimes * nodes for the members are placed on the given list. 1841590Srgrimes * 1851590Srgrimes * Side Effects: 1861590Srgrimes * Some nodes may be created. The given list is extended. 1871590Srgrimes * 1881590Srgrimes *----------------------------------------------------------------------- 1891590Srgrimes */ 1901590SrgrimesReturnStatus 191138512ShartiArch_ParseArchive(char **linePtr, Lst *nodeLst, GNode *ctxt) 1921590Srgrimes{ 193142173Sharti char *cp; /* Pointer into line */ 194142173Sharti GNode *gn; /* New node */ 195142173Sharti char *libName; /* Library-part of specification */ 196142173Sharti char *memName; /* Member-part of specification */ 197142173Sharti char *nameBuf; /* temporary place for node name */ 198142173Sharti char saveChar; /* Ending delimiter of member-name */ 199142173Sharti Boolean subLibName; /* TRUE if libName should have/had 200141270Sharti * variable substitution performed on it */ 2011590Srgrimes 202142173Sharti libName = *linePtr; 2038874Srgrimes 204142173Sharti subLibName = FALSE; 2051590Srgrimes 206142173Sharti for (cp = libName; *cp != '(' && *cp != '\0'; cp++) { 207142173Sharti if (*cp == '$') { 208142173Sharti /* 209142173Sharti * Variable spec, so call the Var module to parse the 210142173Sharti * puppy so we can safely advance beyond it... 211142173Sharti */ 212142937Sharti size_t length = 0; 213142173Sharti Boolean freeIt; 214142173Sharti char *result; 2158874Srgrimes 216142173Sharti result = Var_Parse(cp, ctxt, TRUE, &length, &freeIt); 217142173Sharti if (result == var_Error) { 218142173Sharti return (FAILURE); 219142173Sharti } 220142173Sharti subLibName = TRUE; 2218874Srgrimes 222142173Sharti if (freeIt) { 223142173Sharti free(result); 224142173Sharti } 225142173Sharti cp += length - 1; 226142173Sharti } 2271590Srgrimes } 2281590Srgrimes 229142173Sharti *cp++ = '\0'; 230142173Sharti if (subLibName) { 231143656Sharti libName = Buf_Peel(Var_Subst(NULL, libName, ctxt, TRUE)); 232142173Sharti } 2331590Srgrimes 234142173Sharti for (;;) { 235142173Sharti /* 236142173Sharti * First skip to the start of the member's name, mark that 237142173Sharti * place and skip to the end of it (either white-space or 238142173Sharti * a close paren). 239142173Sharti */ 2401590Srgrimes 2411590Srgrimes /* 242142173Sharti * TRUE if need to substitute in memName 2431590Srgrimes */ 244142173Sharti Boolean doSubst = FALSE; 2451590Srgrimes 246142173Sharti while (*cp != '\0' && *cp != ')' && 247142173Sharti isspace((unsigned char)*cp)) { 248143105Sharti cp++; 2491590Srgrimes } 2501590Srgrimes 251142173Sharti memName = cp; 252142173Sharti while (*cp != '\0' && *cp != ')' && 253142173Sharti !isspace((unsigned char)*cp)) { 254142173Sharti if (*cp == '$') { 255142173Sharti /* 256142173Sharti * Variable spec, so call the Var module to 257142173Sharti * parse the puppy so we can safely advance 258142173Sharti * beyond it... 259142173Sharti */ 260142937Sharti size_t length = 0; 261142173Sharti Boolean freeIt; 262142173Sharti char *result; 263142173Sharti 264142173Sharti result = Var_Parse(cp, ctxt, TRUE, 265142173Sharti &length, &freeIt); 266142173Sharti if (result == var_Error) { 267142173Sharti return (FAILURE); 268142173Sharti } 269142173Sharti doSubst = TRUE; 270142173Sharti 271142173Sharti if (freeIt) { 272142173Sharti free(result); 273142173Sharti } 274142173Sharti cp += length; 275142173Sharti } else { 276142173Sharti cp++; 277142173Sharti } 2781590Srgrimes } 2791590Srgrimes 280142173Sharti /* 281142173Sharti * If the specification ends without a closing parenthesis, 282142173Sharti * chances are there's something wrong (like a missing 283142173Sharti * backslash), so it's better to return failure than allow 284142173Sharti * such things to happen 285142173Sharti */ 286142173Sharti if (*cp == '\0') { 287142173Sharti printf("No closing parenthesis in archive " 288142173Sharti "specification\n"); 289142173Sharti return (FAILURE); 290142173Sharti } 2911590Srgrimes 292142173Sharti /* 293142173Sharti * If we didn't move anywhere, we must be done 294142173Sharti */ 295142173Sharti if (cp == memName) { 296142173Sharti break; 297142173Sharti } 2981590Srgrimes 299142173Sharti saveChar = *cp; 300142173Sharti *cp = '\0'; 3011590Srgrimes 302142173Sharti /* 303142173Sharti * XXX: This should be taken care of intelligently by 304142173Sharti * SuffExpandChildren, both for the archive and the member 305142173Sharti * portions. 306142173Sharti */ 307142173Sharti /* 308142173Sharti * If member contains variables, try and substitute for them. 309142173Sharti * This will slow down archive specs with dynamic sources, of 310142173Sharti * course, since we'll be (non-)substituting them three times, 311142173Sharti * but them's the breaks -- we need to do this since 312142173Sharti * SuffExpandChildren calls us, otherwise we could assume the 313142173Sharti * thing would be taken care of later. 314142173Sharti */ 315142173Sharti if (doSubst) { 316142173Sharti char *buf; 317142173Sharti char *sacrifice; 318142173Sharti char *oldMemName = memName; 319142173Sharti size_t sz; 320142457Sharti Buffer *buf1; 3218874Srgrimes 322142173Sharti /* 323142173Sharti * Now form an archive spec and recurse to deal with 324142173Sharti * nested variables and multi-word variable values.... 325142173Sharti * The results are just placed at the end of the 326142173Sharti * nodeLst we're returning. 327142173Sharti */ 328142457Sharti buf1 = Var_Subst(NULL, memName, ctxt, TRUE); 329142457Sharti memName = Buf_GetAll(buf1, NULL); 3301590Srgrimes 331142173Sharti sz = strlen(memName) + strlen(libName) + 3; 332142457Sharti buf = emalloc(sz); 3331590Srgrimes 334142173Sharti snprintf(buf, sz, "%s(%s)", libName, memName); 33569390Swill 336142457Sharti sacrifice = buf; 337142457Sharti 338142173Sharti if (strchr(memName, '$') && 339142173Sharti strcmp(memName, oldMemName) == 0) { 340142173Sharti /* 341142173Sharti * Must contain dynamic sources, so we can't 342142173Sharti * deal with it now. 343142173Sharti * Just create an ARCHV node for the thing and 344142173Sharti * let SuffExpandChildren handle it... 345142173Sharti */ 346142173Sharti gn = Targ_FindNode(buf, TARG_CREATE); 3471590Srgrimes 348142173Sharti if (gn == NULL) { 349142173Sharti free(buf); 350142457Sharti Buf_Destroy(buf1, FALSE); 351142173Sharti return (FAILURE); 352142173Sharti } 353142173Sharti gn->type |= OP_ARCHV; 354142173Sharti Lst_AtEnd(nodeLst, (void *)gn); 355142173Sharti } else if (Arch_ParseArchive(&sacrifice, nodeLst, 356142173Sharti ctxt) != SUCCESS) { 357142173Sharti /* 358142173Sharti * Error in nested call -- free buffer and 359142173Sharti * return FAILURE ourselves. 360142173Sharti */ 361142173Sharti free(buf); 362142457Sharti Buf_Destroy(buf1, FALSE); 363142173Sharti return (FAILURE); 364142173Sharti } 365142457Sharti 366142457Sharti /* Free buffer and continue with our work. */ 367142173Sharti free(buf); 368142457Sharti Buf_Destroy(buf1, FALSE); 369142457Sharti 370142173Sharti } else if (Dir_HasWildcards(memName)) { 371142173Sharti Lst members = Lst_Initializer(members); 372142173Sharti char *member; 373142173Sharti size_t sz = MAXPATHLEN; 374142173Sharti size_t nsz; 375138196Sharti 376142173Sharti nameBuf = emalloc(sz); 3771590Srgrimes 378142173Sharti Dir_Expand(memName, &dirSearchPath, &members); 379142173Sharti while (!Lst_IsEmpty(&members)) { 380142173Sharti member = Lst_DeQueue(&members); 381142173Sharti nsz = strlen(libName) + strlen(member) + 3; 382142173Sharti if (nsz > sz) { 383142173Sharti sz = nsz * 2; 384142173Sharti nameBuf = erealloc(nameBuf, sz); 385142173Sharti } 3868874Srgrimes 387142173Sharti snprintf(nameBuf, sz, "%s(%s)", 388142173Sharti libName, member); 389142173Sharti free(member); 390142173Sharti gn = Targ_FindNode(nameBuf, TARG_CREATE); 391142173Sharti if (gn == NULL) { 392142173Sharti free(nameBuf); 393142173Sharti /* XXXHB Lst_Destroy(&members) */ 394142173Sharti return (FAILURE); 395142173Sharti } 396142173Sharti /* 397142173Sharti * We've found the node, but have to make sure 398142173Sharti * the rest of the world knows it's an archive 399142173Sharti * member, without having to constantly check 400142173Sharti * for parentheses, so we type the thing with 401142173Sharti * the OP_ARCHV bit before we place it on the 402142173Sharti * end of the provided list. 403142173Sharti */ 404142173Sharti gn->type |= OP_ARCHV; 405142173Sharti Lst_AtEnd(nodeLst, gn); 406142173Sharti } 407142173Sharti free(nameBuf); 4081590Srgrimes } else { 409142173Sharti size_t sz = strlen(libName) + strlen(memName) + 3; 410142173Sharti 411142173Sharti nameBuf = emalloc(sz); 412142173Sharti snprintf(nameBuf, sz, "%s(%s)", libName, memName); 413142173Sharti gn = Targ_FindNode(nameBuf, TARG_CREATE); 414142173Sharti free(nameBuf); 415142173Sharti if (gn == NULL) { 416142173Sharti return (FAILURE); 417142173Sharti } 418142173Sharti /* 419142173Sharti * We've found the node, but have to make sure the 420142173Sharti * rest of the world knows it's an archive member, 421142173Sharti * without having to constantly check for parentheses, 422142173Sharti * so we type the thing with the OP_ARCHV bit before 423142173Sharti * we place it on the end of the provided list. 424142173Sharti */ 425142173Sharti gn->type |= OP_ARCHV; 426142173Sharti Lst_AtEnd(nodeLst, gn); 4271590Srgrimes } 428142173Sharti if (doSubst) { 429142173Sharti free(memName); 430142173Sharti } 431142173Sharti 432142173Sharti *cp = saveChar; 4331590Srgrimes } 434142173Sharti 435142173Sharti /* 436142173Sharti * If substituted libName, free it now, since we need it no longer. 437142173Sharti */ 438142173Sharti if (subLibName) { 439142173Sharti free(libName); 4401590Srgrimes } 4418874Srgrimes 442142173Sharti /* 443142173Sharti * We promised the pointer would be set up at the next non-space, so 444142173Sharti * we must advance cp there before setting *linePtr... (note that on 445142173Sharti * entrance to the loop, cp is guaranteed to point at a ')') 446142173Sharti */ 447142173Sharti do { 448142173Sharti cp++; 449142173Sharti } while (*cp != '\0' && isspace((unsigned char)*cp)); 4501590Srgrimes 451142173Sharti *linePtr = cp; 452142173Sharti return (SUCCESS); 4531590Srgrimes} 4541590Srgrimes 455143656Sharti/* 456143656Sharti * Close an archive file an free all resources 4571590Srgrimes */ 458143656Shartistatic void 459143656ShartiArchArchiveClose(struct arfile *ar) 4601590Srgrimes{ 461138561Sharti 462143656Sharti if (ar->nametab != NULL) 463143656Sharti free(ar->nametab); 464143656Sharti free(ar->member); 465143656Sharti if (ar->fp != NULL) { 466143656Sharti if (fclose(ar->fp) == EOF) 467143656Sharti DEBUGM(ARCH, ("%s: close error", ar->fname)); 468143656Sharti } 469143656Sharti free(ar->fname); 470143656Sharti free(ar); 4711590Srgrimes} 4721590Srgrimes 473143656Sharti/* 474143656Sharti * Open an archive file. 4751590Srgrimes */ 476143656Shartistatic struct arfile * 477143656ShartiArchArchiveOpen(const char *archive, const char *mode) 4781590Srgrimes{ 479143656Sharti struct arfile *ar; 480143656Sharti char magic[SARMAG]; 4811590Srgrimes 482143656Sharti ar = emalloc(sizeof(*ar)); 483143656Sharti ar->fname = estrdup(archive); 484143656Sharti ar->mlen = 100; 485143656Sharti ar->member = emalloc(ar->mlen); 486143656Sharti ar->nametab = NULL; 487143656Sharti ar->nametablen = 0; 488143656Sharti 489143656Sharti if ((ar->fp = fopen(ar->fname, mode)) == NULL) { 490143656Sharti DEBUGM(ARCH, ("%s", ar->fname)); 491143656Sharti ArchArchiveClose(ar); 492142173Sharti return (NULL); 493142173Sharti } 4941590Srgrimes 495143656Sharti /* read MAGIC */ 496143656Sharti if (fread(magic, SARMAG, 1, ar->fp) != 1 || 497143105Sharti strncmp(magic, ARMAG, SARMAG) != 0) { 498143656Sharti DEBUGF(ARCH, ("%s: bad archive magic\n", ar->fname)); 499143656Sharti ArchArchiveClose(ar); 500142173Sharti return (NULL); 501142165Sharti } 5025814Sjkh 503143656Sharti ar->pos = 0; 504143656Sharti return (ar); 505143656Sharti} 506143656Sharti 507143656Sharti#define MMAX(A, B) ((A) > (B) ? (A) : (B)) 508143656Sharti 509143656Sharti/* 510143656Sharti * Read the next header from the archive. The return value will be +1 if 511143656Sharti * the header is read successfully, 0 on EOF and -1 if an error happend. 512143656Sharti * On a successful return sname contains the truncated member name and 513143656Sharti * member the full name. hdr contains the member header. For the symbol table 514143656Sharti * names of length 0 are returned. The entry for the file name table is never 515143656Sharti * returned. 516143656Sharti */ 517143656Shartistatic int 518143656ShartiArchArchiveNext(struct arfile *ar) 519143656Sharti{ 520143656Sharti char *end; 521143656Sharti int have_long_name; 522143656Sharti u_long offs; 523143656Sharti char *ptr; 524143656Sharti size_t ret; 525143656Sharti char buf[MMAX(sizeof(ar->hdr.ar_size), sizeof(ar->hdr.ar_date)) + 1]; 526143656Sharti 527143656Sharti next: 5281590Srgrimes /* 529143656Sharti * Seek to the next header. 530142297Sharti */ 531143656Sharti if (ar->pos == 0) { 532143656Sharti ar->pos = SARMAG; 533143656Sharti } else { 534143656Sharti ar->pos += sizeof(ar->hdr) + ar->size; 535143656Sharti if (ar->size % 2 == 1) 536143656Sharti ar->pos++; 5371590Srgrimes } 538143656Sharti 539143656Sharti if (fseeko(ar->fp, ar->pos, SEEK_SET) == -1) { 540143656Sharti DEBUGM(ARCH, ("%s: cannot seek", ar->fname)); 541143656Sharti return (-1); 542142173Sharti } 5431590Srgrimes 544143656Sharti /* 545143656Sharti * Read next member header 546143656Sharti */ 547143656Sharti ret = fread(&ar->hdr, sizeof(ar->hdr), 1, ar->fp); 548143656Sharti if (ret != 1) { 549143656Sharti if (ferror(ar->fp)) { 550143656Sharti DEBUGM(ARCH, ("%s", ar->fname)); 551143656Sharti return (-1); 552142173Sharti } 553143656Sharti return (0); 554143656Sharti } 555143656Sharti if (strncmp(ar->hdr.ar_fmag, ARFMAG, sizeof(ar->hdr.ar_fmag)) != 0) { 556143656Sharti DEBUGF(ARCH, ("%s: bad entry magic\n", ar->fname)); 557143656Sharti return (-1); 558143656Sharti } 5598874Srgrimes 560143656Sharti /* 561143656Sharti * looks like a member - get name by stripping trailing spaces 562143656Sharti * and NUL terminating. 563143656Sharti */ 564143656Sharti strncpy(ar->sname, ar->hdr.ar_name, AR_NAMSIZ); 565143656Sharti ar->sname[AR_NAMSIZ] = '\0'; 566143656Sharti for (ptr = ar->sname + AR_NAMSIZ; ptr > ar->sname; ptr--) 567143656Sharti if (ptr[-1] != ' ') 568143656Sharti break; 569143656Sharti 570143656Sharti *ptr = '\0'; 571143656Sharti 572143656Sharti /* 573143656Sharti * Parse the size. All entries need to have a size. Be careful 574143656Sharti * to not allow buffer overruns. 575143656Sharti */ 576143656Sharti strncpy(buf, ar->hdr.ar_size, sizeof(ar->hdr.ar_size)); 577143656Sharti buf[sizeof(ar->hdr.ar_size)] = '\0'; 578143656Sharti 579143656Sharti errno = 0; 580143656Sharti ar->size = strtoumax(buf, &end, 10); 581143656Sharti if (errno != 0 || strspn(end, " ") != strlen(end)) { 582143656Sharti DEBUGF(ARCH, ("bad size format in archive '%s'\n", buf)); 583143656Sharti return (-1); 584143656Sharti } 585143656Sharti 586143656Sharti /* 587143656Sharti * Look for the extended name table. Do this before parsing 588143656Sharti * the date because this table doesn't need a date. 589143656Sharti */ 590143656Sharti if (strcmp(ar->sname, BSD_NAMEMAG) == 0 || 591143656Sharti strcmp(ar->sname, SVR4_NAMEMAG) == 0) { 592143656Sharti /* filename table - read it in */ 593143656Sharti ar->nametablen = ar->size; 594143656Sharti ar->nametab = emalloc(ar->nametablen); 595143656Sharti 596143656Sharti ret = fread(ar->nametab, 1, ar->nametablen, ar->fp); 597143656Sharti if (ret != ar->nametablen) { 598143656Sharti DEBUGM(ARCH, ("%s: cannot read nametab", ar->fname)); 599143656Sharti return (-1); 600142173Sharti } 601143656Sharti 60218730Ssteve /* 603143656Sharti * NUL terminate the entries. Entries are \n terminated 604143656Sharti * and may have a trailing / or \. 60518730Ssteve */ 606143656Sharti ptr = ar->nametab; 607143656Sharti while (ptr < ar->nametab + ar->nametablen) { 608143656Sharti if (*ptr == '\n') { 609143656Sharti if (ptr[-1] == '/' || ptr[-1] == '\\') 610143656Sharti ptr[-1] = '\0'; 611143656Sharti *ptr = '\0'; 612142173Sharti } 613143656Sharti ptr++; 61418730Ssteve } 615143656Sharti 616143656Sharti /* get next archive entry */ 617143656Sharti goto next; 6181590Srgrimes } 6191590Srgrimes 620142173Sharti /* 621143656Sharti * Now parse the modification date. Be careful to not overrun 622143656Sharti * buffers. 623142297Sharti */ 624143656Sharti strncpy(buf, ar->hdr.ar_date, sizeof(ar->hdr.ar_date)); 625143656Sharti buf[sizeof(ar->hdr.ar_date)] = '\0'; 626143656Sharti 627143656Sharti errno = 0; 628143656Sharti ar->time = (int64_t)strtoll(buf, &end, 10); 629143656Sharti if (errno != 0 || strspn(end, " ") != strlen(end)) { 630143656Sharti DEBUGF(ARCH, ("bad date format in archive '%s'\n", buf)); 631143656Sharti return (-1); 632143656Sharti } 633143656Sharti 634143656Sharti /* 635143656Sharti * Now check for the symbol table. This should really be the first 636143656Sharti * entry, but we don't check this. 637143656Sharti */ 638143656Sharti if (strcmp(ar->sname, BSD_RANLIBMAG) == 0 || 639143656Sharti strcmp(ar->sname, SVR4_RANLIBMAG) == 0) { 640143656Sharti /* symbol table - return a zero length name */ 641143656Sharti ar->member[0] = '\0'; 642143656Sharti ar->sname[0] = '\0'; 643143656Sharti return (1); 644143656Sharti } 645143656Sharti 646143656Sharti have_long_name = 0; 647143656Sharti 648143656Sharti /* 649143656Sharti * Look whether this is a long name. There are several variants 650143656Sharti * of long names: 651143656Sharti * "#1/12 " - 12 length of following filename 652143656Sharti * "/17 " - index into name table 653143656Sharti * " 17 " - index into name table 654143656Sharti * Note that in the last case we must also check that there is no 655143656Sharti * slash in the name because of filenames with leading spaces: 656143656Sharti * " 777.o/ " - filename 777.o 657143656Sharti */ 658143656Sharti if (ar->sname[0] == '/' || (ar->sname[0] == ' ' && 659143656Sharti strchr(ar->sname, '/') == NULL)) { 660143656Sharti /* SVR4 extended name */ 661143656Sharti errno = 0; 662143656Sharti offs = strtoul(ar->sname + 1, &end, 10); 663143656Sharti if (errno != 0 || *end != '\0' || offs >= ar->nametablen || 664143656Sharti end == ar->sname + 1) { 665143656Sharti DEBUGF(ARCH, ("bad extended name\n")); 666143656Sharti return (-1); 667143656Sharti } 668143656Sharti 669143656Sharti /* fetch the name */ 670143656Sharti if (ar->mlen <= strlen(ar->nametab + offs)) { 671143656Sharti ar->mlen = strlen(ar->nametab + offs) + 1; 672143656Sharti ar->member = erealloc(ar->member, ar->mlen); 673143656Sharti } 674143656Sharti strcpy(ar->member, ar->nametab + offs); 675143656Sharti 676143656Sharti have_long_name = 1; 677143656Sharti 678143656Sharti } else if (strncmp(ar->sname, BSD_EXT1, BSD_EXT1LEN) == 0 && 679143656Sharti isdigit(ar->sname[BSD_EXT1LEN])) { 680143656Sharti /* BSD4.4 extended name */ 681143656Sharti errno = 0; 682143656Sharti offs = strtoul(ar->sname + BSD_EXT1LEN, &end, 10); 683143656Sharti if (errno != 0 || *end != '\0' || 684143656Sharti end == ar->sname + BSD_EXT1LEN) { 685143656Sharti DEBUGF(ARCH, ("%s: bad extended name\n", ar->fname)); 686143656Sharti return (-1); 687143656Sharti } 688143656Sharti 689143656Sharti /* read it from the archive */ 690143656Sharti if (ar->mlen <= offs) { 691143656Sharti ar->mlen = offs + 1; 692143656Sharti ar->member = erealloc(ar->member, ar->mlen); 693143656Sharti } 694143656Sharti ret = fread(ar->member, 1, offs, ar->fp); 695143656Sharti if (ret != offs) { 696143656Sharti DEBUGM(ARCH, ("%s: reading extended name", ar->fname)); 697143656Sharti return (-1); 698143656Sharti } 699143656Sharti ar->member[offs] = '\0'; 700143656Sharti 701143656Sharti have_long_name = 1; 702143656Sharti } 703143656Sharti 704143656Sharti /* 705143656Sharti * Now remove the trailing slash that Svr4 puts at 706143656Sharti * the end of the member name to support trailing spaces in names. 707143656Sharti */ 708143656Sharti if (ptr > ar->sname && ptr[-1] == '/') 709143656Sharti *--ptr = '\0'; 710143656Sharti 711143656Sharti if (!have_long_name) { 712143656Sharti if (strlen(ar->sname) >= ar->mlen) { 713143656Sharti ar->mlen = strlen(ar->sname) + 1; 714143656Sharti ar->member = erealloc(ar->member, ar->mlen); 715143656Sharti } 716143656Sharti strcpy(ar->member, ar->sname); 717143656Sharti } 718143656Sharti 719143656Sharti return (1); 7201590Srgrimes} 7211590Srgrimes 722143656Sharti/* 723143656Sharti * Touch the current archive member by writing a new header with an 724143656Sharti * updated timestamp. The return value is 0 for success and -1 for errors. 725143656Sharti */ 726143656Shartistatic int 727143656ShartiArchArchiveTouch(struct arfile *ar, int64_t ts) 728143656Sharti{ 729143656Sharti 730143656Sharti /* seek to our header */ 731143656Sharti if (fseeko(ar->fp, ar->pos, SEEK_SET) == -1) { 732143656Sharti DEBUGM(ARCH, ("%s: cannot seek", ar->fname)); 733143656Sharti return (-1); 734143656Sharti } 735143656Sharti 736143656Sharti /* 737143656Sharti * change timestamp, be sure to not NUL-terminated it, but 738143656Sharti * to fill with spaces. 739143656Sharti */ 740143656Sharti snprintf(ar->hdr.ar_date, sizeof(ar->hdr.ar_date), "%lld", ts); 741143656Sharti memset(ar->hdr.ar_date + strlen(ar->hdr.ar_date), 742143656Sharti ' ', sizeof(ar->hdr.ar_date) - strlen(ar->hdr.ar_date)); 743143656Sharti 744143656Sharti if (fwrite(&ar->hdr, sizeof(ar->hdr), 1, ar->fp) != 1) { 745143656Sharti DEBUGM(ARCH, ("%s: cannot touch", ar->fname)); 746143656Sharti return (-1); 747143656Sharti } 748143656Sharti return (0); 749143656Sharti} 750143656Sharti 7511590Srgrimes/*- 7521590Srgrimes *----------------------------------------------------------------------- 753143656Sharti * ArchFindMember -- 754143656Sharti * Locate a member of an archive, given the path of the archive and 755143656Sharti * the path of the desired member. If the archive is to be modified, 756143656Sharti * the mode should be "r+", if not, it should be "r". The archive 757143656Sharti * file is returned positioned at the correct header. 75818730Ssteve * 75918730Ssteve * Results: 760143656Sharti * A struct arfile *, opened for reading and, possibly writing, 761143656Sharti * positioned at the member's header, or NULL if the member was 762143656Sharti * nonexistent. 76318730Ssteve * 76418730Ssteve *----------------------------------------------------------------------- 76518730Ssteve */ 766143656Shartistatic struct arfile * 767143656ShartiArchFindMember(const char *archive, const char *member, const char *mode) 76818730Ssteve{ 769143656Sharti struct arfile *ar; 770143656Sharti const char *cp; /* Useful character pointer */ 77118730Ssteve 772143656Sharti if ((ar = ArchArchiveOpen(archive, mode)) == NULL) 773143656Sharti return (NULL); 77418730Ssteve 775143656Sharti /* 776143656Sharti * Because of space constraints and similar things, files are archived 777143656Sharti * using their final path components, not the entire thing, so we need 778143656Sharti * to point 'member' to the final component, if there is one, to make 779143656Sharti * the comparisons easier... 780143656Sharti */ 781143656Sharti if (member != NULL) { 782143656Sharti cp = strrchr(member, '/'); 783143656Sharti if (cp != NULL) { 784143656Sharti member = cp + 1; 785142173Sharti } 786143656Sharti } 78718730Ssteve 788143656Sharti while (ArchArchiveNext(ar) > 0) { 789142173Sharti /* 790143656Sharti * When comparing there are actually three cases: 791143656Sharti * (1) the name fits into the limit og af_name, 792143656Sharti * (2) the name is longer and the archive supports long names, 793143656Sharti * (3) the name is longer and the archive doesn't support long 794143656Sharti * names. 795143656Sharti * Because we don't know whether the archive supports long 796143656Sharti * names or not we need to be carefull. 797142297Sharti */ 798143656Sharti if (member == NULL) { 799143656Sharti /* special case - symbol table */ 800143656Sharti if (ar->member[0] == '\0') 801143656Sharti return (ar); 802143656Sharti } else if (strlen(member) <= AR_NAMSIZ) { 803143656Sharti /* case (1) */ 804143656Sharti if (strcmp(ar->member, member) == 0) 805143656Sharti return (ar); 806143656Sharti } else if (strcmp(ar->member, member) == 0) { 807143656Sharti /* case (3) */ 808143656Sharti return (ar); 809143656Sharti } else { 810143656Sharti /* case (2) */ 811143656Sharti if (strlen(ar->member) == AR_NAMSIZ && 812143656Sharti strncmp(member, ar->member, AR_NAMSIZ) == 0) 813143656Sharti return (ar); 814142173Sharti } 815142173Sharti } 81618730Ssteve 817143656Sharti /* not found */ 818143656Sharti ArchArchiveClose(ar); 819143656Sharti return (NULL); 82018730Ssteve} 82118730Ssteve 82218730Ssteve/*- 82318730Ssteve *----------------------------------------------------------------------- 824142173Sharti * ArchStatMember -- 8251590Srgrimes * Locate a member of an archive, given the path of the archive and 826142173Sharti * the path of the desired member, and a boolean representing whether 827142173Sharti * or not the archive should be hashed (if not already hashed). 8281590Srgrimes * 8291590Srgrimes * Results: 830142173Sharti * A pointer to the current struct ar_hdr structure for the member. Note 831142173Sharti * That no position is returned, so this is not useful for touching 832142173Sharti * archive members. This is mostly because we have no assurances that 833142173Sharti * The archive will remain constant after we read all the headers, so 834142173Sharti * there's not much point in remembering the position... 8351590Srgrimes * 8361590Srgrimes * Side Effects: 8371590Srgrimes * 8381590Srgrimes *----------------------------------------------------------------------- 8391590Srgrimes */ 840143656Shartistatic int64_t 841142173ShartiArchStatMember(const char *archive, const char *member, Boolean hash) 8421590Srgrimes{ 843143656Sharti struct arfile *arf; 844143656Sharti int64_t ret; 845143656Sharti int t; 846142173Sharti char *cp; /* Useful character pointer */ 847142173Sharti LstNode *ln; /* Lst member containing archive descriptor */ 848142173Sharti Arch *ar; /* Archive descriptor */ 849142173Sharti Hash_Entry *he; /* Entry containing member's description */ 850143656Sharti char copy[AR_NAMSIZ + 1]; 8511590Srgrimes 852142173Sharti /* 853142297Sharti * Because of space constraints and similar things, files are archived 854142297Sharti * using their final path components, not the entire thing, so we need 855142297Sharti * to point 'member' to the final component, if there is one, to make 856142297Sharti * the comparisons easier... 857142297Sharti */ 858143656Sharti if (member != NULL) { 859143656Sharti cp = strrchr(member, '/'); 860143656Sharti if (cp != NULL) 861143656Sharti member = cp + 1; 862143656Sharti } 8638874Srgrimes 864143656Sharti LST_FOREACH(ln, &archives) { 865143656Sharti if (strcmp(archive, ((const Arch *)Lst_Datum(ln))->name) == 0) 866143656Sharti break; 867143656Sharti } 868142173Sharti if (ln != NULL) { 869143656Sharti /* found archive */ 870142173Sharti ar = Lst_Datum(ln); 8718874Srgrimes 872143656Sharti } else { 873143656Sharti if (!hash) { 874142173Sharti /* 875143656Sharti * Caller doesn't want the thing hashed, just use 876143656Sharti * ArchFindMember to read the header for the member 877143656Sharti * out and close down the stream again. 878142173Sharti */ 879143656Sharti arf = ArchFindMember(archive, member, "r"); 880143656Sharti if (arf == NULL) { 881143656Sharti return (INT64_MIN); 882143656Sharti } 883143656Sharti ret = arf->time; 884143656Sharti ArchArchiveClose(arf); 885143656Sharti return (ret); 886142173Sharti } 887143656Sharti 8885814Sjkh /* 889143656Sharti * We don't have this archive on the list yet, so we want to 890143656Sharti * find out everything that's in it and cache it so we can get 891143656Sharti * at it quickly. 8925814Sjkh */ 893143656Sharti arf = ArchArchiveOpen(archive, "r"); 894143656Sharti if (arf == NULL) { 895143656Sharti return (INT64_MIN); 896142173Sharti } 8975814Sjkh 898143656Sharti /* create archive data structure */ 899143656Sharti ar = emalloc(sizeof(*ar)); 900143656Sharti ar->name = estrdup(archive); 901143656Sharti Hash_InitTable(&ar->members, -1); 902142173Sharti 903143656Sharti while ((t = ArchArchiveNext(arf)) > 0) { 904143656Sharti he = Hash_CreateEntry(&ar->members, arf->member, NULL); 905143656Sharti Hash_SetValue(he, emalloc(sizeof(int64_t))); 906143656Sharti *(int64_t *)Hash_GetValue(he) = arf->time; 9075814Sjkh } 908142173Sharti 909143656Sharti ArchArchiveClose(arf); 910142173Sharti 911143656Sharti if (t < 0) { 912143656Sharti /* error happend - throw away everything */ 913143656Sharti Hash_DeleteTable(&ar->members); 914143656Sharti free(ar->name); 915143656Sharti free(ar); 916143656Sharti return (INT64_MIN); 9175814Sjkh } 918142173Sharti 919143656Sharti Lst_AtEnd(&archives, ar); 9201590Srgrimes } 9211590Srgrimes 922142173Sharti /* 923142173Sharti * Now that the archive has been read and cached, we can look into 924142173Sharti * the hash table to find the desired member's header. 925142173Sharti */ 926142173Sharti he = Hash_FindEntry(&ar->members, member); 927143656Sharti if (he != NULL) 928143656Sharti return (*(int64_t *)Hash_GetValue (he)); 929142173Sharti 930143656Sharti if (member != NULL && strlen(member) > AR_NAMSIZ) { 931143656Sharti /* Try truncated name */ 932143656Sharti strncpy(copy, member, AR_NAMSIZ); 933143656Sharti copy[AR_NAMSIZ] = '\0'; 934143656Sharti 935143656Sharti if ((he = Hash_FindEntry(&ar->members, copy)) != NULL) 936143656Sharti return (*(int64_t *)Hash_GetValue(he)); 937142173Sharti } 938142173Sharti 939143656Sharti return (INT64_MIN); 9401590Srgrimes} 9411590Srgrimes 9421590Srgrimes/*- 9431590Srgrimes *----------------------------------------------------------------------- 9441590Srgrimes * Arch_Touch -- 9451590Srgrimes * Touch a member of an archive. 9461590Srgrimes * 9471590Srgrimes * Results: 9481590Srgrimes * The 'time' field of the member's header is updated. 9491590Srgrimes * 9501590Srgrimes * Side Effects: 9511590Srgrimes * The modification time of the entire archive is also changed. 9521590Srgrimes * For a library, this could necessitate the re-ranlib'ing of the 9531590Srgrimes * whole thing. 9541590Srgrimes * 9551590Srgrimes *----------------------------------------------------------------------- 9561590Srgrimes */ 9571590Srgrimesvoid 958138232ShartiArch_Touch(GNode *gn) 9591590Srgrimes{ 960143656Sharti struct arfile *ar; 961142173Sharti char *p1, *p2; 9621590Srgrimes 963143656Sharti ar = ArchFindMember(Var_Value(ARCHIVE, gn, &p1), 964143656Sharti Var_Value(TARGET, gn, &p2), "r+"); 965142173Sharti free(p1); 966142173Sharti free(p2); 9671590Srgrimes 968143656Sharti if (ar != NULL) { 969143656Sharti ArchArchiveTouch(ar, (int64_t)now); 970143656Sharti ArchArchiveClose(ar); 971142173Sharti } 9721590Srgrimes} 9731590Srgrimes 9741590Srgrimes/*- 9751590Srgrimes *----------------------------------------------------------------------- 9761590Srgrimes * Arch_TouchLib -- 9771590Srgrimes * Given a node which represents a library, touch the thing, making 9781590Srgrimes * sure that the table of contents also is touched. 9791590Srgrimes * 9801590Srgrimes * Results: 9811590Srgrimes * None. 9821590Srgrimes * 9831590Srgrimes * Side Effects: 9841590Srgrimes * Both the modification time of the library and of the RANLIBMAG 9851590Srgrimes * member are set to 'now'. 9861590Srgrimes * 9871590Srgrimes *----------------------------------------------------------------------- 9881590Srgrimes */ 9891590Srgrimesvoid 990138232ShartiArch_TouchLib(GNode *gn) 9911590Srgrimes{ 992143656Sharti struct arfile *ar; /* Open archive */ 993142173Sharti struct utimbuf times; /* Times for utime() call */ 9941590Srgrimes 995143656Sharti ar = ArchFindMember(gn->path, NULL, "r+"); 996143656Sharti if (ar != NULL) { 997143656Sharti ArchArchiveTouch(ar, (int64_t)now); 998143656Sharti ArchArchiveClose(ar); 9991590Srgrimes 1000142173Sharti times.actime = times.modtime = now; 1001142173Sharti utime(gn->path, ×); 1002142173Sharti } 10031590Srgrimes} 10041590Srgrimes 10051590Srgrimes/*- 10061590Srgrimes *----------------------------------------------------------------------- 10071590Srgrimes * Arch_MTime -- 1008104696Sjmallett * Return the modification time of a member of an archive, given its 1009104696Sjmallett * name. 10101590Srgrimes * 10111590Srgrimes * Results: 1012138232Sharti * The modification time(seconds). 1013142173Sharti * XXXHB this should be a long. 10141590Srgrimes * 10151590Srgrimes * Side Effects: 10161590Srgrimes * The mtime field of the given node is filled in with the value 10171590Srgrimes * returned by the function. 10181590Srgrimes * 10191590Srgrimes *----------------------------------------------------------------------- 10201590Srgrimes */ 10211590Srgrimesint 1022104696SjmallettArch_MTime(GNode *gn) 10231590Srgrimes{ 1024143656Sharti int64_t mtime; 1025143656Sharti char *p1, *p2; 10261590Srgrimes 1027143656Sharti mtime = ArchStatMember(Var_Value(ARCHIVE, gn, &p1), 1028142173Sharti Var_Value(TARGET, gn, &p2), TRUE); 1029142173Sharti free(p1); 1030142173Sharti free(p2); 10315814Sjkh 1032143656Sharti if (mtime == INT_MIN) { 1033143656Sharti mtime = 0; 1034142173Sharti } 1035143656Sharti gn->mtime = (int)mtime; /* XXX */ 1036143656Sharti return (gn->mtime); 10371590Srgrimes} 10381590Srgrimes 10391590Srgrimes/*- 10401590Srgrimes *----------------------------------------------------------------------- 10411590Srgrimes * Arch_MemMTime -- 10421590Srgrimes * Given a non-existent archive member's node, get its modification 10431590Srgrimes * time from its archived form, if it exists. 10441590Srgrimes * 10451590Srgrimes * Results: 10461590Srgrimes * The modification time. 10471590Srgrimes * 10481590Srgrimes * Side Effects: 10491590Srgrimes * The mtime field is filled in. 10501590Srgrimes * 10511590Srgrimes *----------------------------------------------------------------------- 10521590Srgrimes */ 10531590Srgrimesint 1054138232ShartiArch_MemMTime(GNode *gn) 10551590Srgrimes{ 1056142173Sharti LstNode *ln; 1057142173Sharti GNode *pgn; 1058142173Sharti char *nameStart; 1059142173Sharti char *nameEnd; 10601590Srgrimes 1061142173Sharti for (ln = Lst_First(&gn->parents); ln != NULL; ln = Lst_Succ(ln)) { 1062142173Sharti pgn = Lst_Datum(ln); 10631590Srgrimes 1064142173Sharti if (pgn->type & OP_ARCHV) { 1065142173Sharti /* 1066142173Sharti * If the parent is an archive specification and is 1067142173Sharti * being made and its member's name matches the name of 1068142173Sharti * the node we were given, record the modification time 1069142173Sharti * of the parent in the child. We keep searching its 1070142173Sharti * parents in case some other parent requires this 1071142173Sharti * child to exist... 1072142173Sharti */ 1073142173Sharti nameStart = strchr(pgn->name, '(') + 1; 1074142173Sharti nameEnd = strchr(nameStart, ')'); 10751590Srgrimes 1076142173Sharti if (pgn->make && strncmp(nameStart, gn->name, 1077142173Sharti nameEnd - nameStart) == 0) { 1078142173Sharti gn->mtime = Arch_MTime(pgn); 1079142173Sharti } 1080142173Sharti } else if (pgn->make) { 1081142173Sharti /* 1082142173Sharti * Something which isn't a library depends on the 1083142173Sharti * existence of this target, so it needs to exist. 1084142173Sharti */ 1085142173Sharti gn->mtime = 0; 1086142173Sharti break; 1087142173Sharti } 10881590Srgrimes } 1089142173Sharti return (gn->mtime); 10901590Srgrimes} 10911590Srgrimes 10921590Srgrimes/*- 10931590Srgrimes *----------------------------------------------------------------------- 10941590Srgrimes * Arch_FindLib -- 1095104696Sjmallett * Search for a named library along the given search path. 10961590Srgrimes * 10971590Srgrimes * Results: 10981590Srgrimes * None. 10991590Srgrimes * 11001590Srgrimes * Side Effects: 11011590Srgrimes * The node's 'path' field is set to the found path (including the 11021590Srgrimes * actual file name, not -l...). If the system can handle the -L 11031590Srgrimes * flag when linking (or we cannot find the library), we assume that 11041590Srgrimes * the user has placed the .LIBRARIES variable in the final linking 11051590Srgrimes * command (or the linker will know where to find it) and set the 11061590Srgrimes * TARGET variable for this node to be the node's name. Otherwise, 11071590Srgrimes * we set the TARGET variable to be the full path of the library, 11081590Srgrimes * as returned by Dir_FindFile. 11091590Srgrimes * 11101590Srgrimes *----------------------------------------------------------------------- 11111590Srgrimes */ 11121590Srgrimesvoid 1113138512ShartiArch_FindLib(GNode *gn, Lst *path) 11141590Srgrimes{ 1115142173Sharti char *libName; /* file name for archive */ 1116142173Sharti size_t sz; 11171590Srgrimes 1118142173Sharti sz = strlen(gn->name) + 4; 1119142173Sharti libName = emalloc(sz); 1120142173Sharti snprintf(libName, sz, "lib%s.a", &gn->name[2]); 11211590Srgrimes 1122142173Sharti gn->path = Dir_FindFile(libName, path); 11231590Srgrimes 1124142173Sharti free(libName); 11251590Srgrimes 11261590Srgrimes#ifdef LIBRARIES 1127142173Sharti Var_Set(TARGET, gn->name, gn); 11281590Srgrimes#else 1129142173Sharti Var_Set(TARGET, gn->path == NULL ? gn->name : gn->path, gn); 113018730Ssteve#endif /* LIBRARIES */ 11311590Srgrimes} 11321590Srgrimes 11331590Srgrimes/*- 11341590Srgrimes *----------------------------------------------------------------------- 11351590Srgrimes * Arch_LibOODate -- 11361590Srgrimes * Decide if a node with the OP_LIB attribute is out-of-date. Called 1137104696Sjmallett * from Make_OODate to make its life easier, with the library's 1138104696Sjmallett * graph node. 11391590Srgrimes * 11401590Srgrimes * There are several ways for a library to be out-of-date that are 11411590Srgrimes * not available to ordinary files. In addition, there are ways 11421590Srgrimes * that are open to regular files that are not available to 11431590Srgrimes * libraries. A library that is only used as a source is never 11441590Srgrimes * considered out-of-date by itself. This does not preclude the 11451590Srgrimes * library's modification time from making its parent be out-of-date. 11461590Srgrimes * A library will be considered out-of-date for any of these reasons, 11471590Srgrimes * given that it is a target on a dependency line somewhere: 11481590Srgrimes * Its modification time is less than that of one of its 1149141270Sharti * sources (gn->mtime < gn->cmtime). 11501590Srgrimes * Its modification time is greater than the time at which the 1151141270Sharti * make began (i.e. it's been modified in the course 1152141270Sharti * of the make, probably by archiving). 11535814Sjkh * The modification time of one of its sources is greater than 11545814Sjkh * the one of its RANLIBMAG member (i.e. its table of contents 1155141270Sharti * is out-of-date). We don't compare of the archive time 11565814Sjkh * vs. TOC time because they can be too close. In my 11575814Sjkh * opinion we should not bother with the TOC at all since 11585814Sjkh * this is used by 'ar' rules that affect the data contents 11595814Sjkh * of the archive, not by ranlib rules, which affect the 11608874Srgrimes * TOC. 11611590Srgrimes * 11621590Srgrimes * Results: 11631590Srgrimes * TRUE if the library is out-of-date. FALSE otherwise. 11641590Srgrimes * 11651590Srgrimes * Side Effects: 11661590Srgrimes * The library will be hashed if it hasn't been already. 11671590Srgrimes * 11681590Srgrimes *----------------------------------------------------------------------- 11691590Srgrimes */ 11701590SrgrimesBoolean 1171138232ShartiArch_LibOODate(GNode *gn) 11721590Srgrimes{ 1173143656Sharti int64_t mtime; /* The table-of-contents's mod time */ 11741590Srgrimes 1175142173Sharti if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->children)) { 1176142173Sharti return (FALSE); 1177142173Sharti } 1178143105Sharti if (gn->mtime > now || gn->mtime < gn->cmtime) { 1179142173Sharti return (TRUE); 1180142173Sharti } 1181142173Sharti 1182143656Sharti mtime = ArchStatMember(gn->path, NULL, FALSE); 1183143656Sharti if (mtime == INT64_MIN) { 1184142173Sharti /* 1185143656Sharti * Not found. A library w/o a table of contents is out-of-date 1186142173Sharti */ 1187142173Sharti if (DEBUG(ARCH) || DEBUG(MAKE)) { 1188143656Sharti Debug("No TOC..."); 1189142173Sharti } 1190142173Sharti return (TRUE); 11911590Srgrimes } 1192143656Sharti 1193143656Sharti /* XXX choose one. */ 1194143656Sharti if (DEBUG(ARCH) || DEBUG(MAKE)) { 1195143656Sharti Debug("TOC modified %s...", Targ_FmtTime(mtime)); 1196143656Sharti } 1197143656Sharti return (gn->cmtime > mtime); 11981590Srgrimes} 11991590Srgrimes 12001590Srgrimes/*- 12011590Srgrimes *----------------------------------------------------------------------- 12021590Srgrimes * Arch_Init -- 12031590Srgrimes * Initialize things for this module. 12041590Srgrimes * 12051590Srgrimes * Results: 12061590Srgrimes * None. 12071590Srgrimes * 12081590Srgrimes *----------------------------------------------------------------------- 12091590Srgrimes */ 12101590Srgrimesvoid 1211138232ShartiArch_Init(void) 12121590Srgrimes{ 12131590Srgrimes} 1214