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