| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: arch.c,v 1.101 2020/08/28 04:48:56 rillig Exp $ */ | | 1 | /* $NetBSD: arch.c,v 1.102 2020/08/28 18:34:45 rillig Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1988, 1989, 1990, 1993 | | 4 | * Copyright (c) 1988, 1989, 1990, 1993 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to Berkeley by | | 7 | * This code is derived from software contributed to Berkeley by |
8 | * Adam de Boor. | | 8 | * Adam de Boor. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -59,34 +59,34 @@ | | | @@ -59,34 +59,34 @@ |
59 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 59 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
60 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 60 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
61 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 61 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
62 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 62 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
63 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 63 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
64 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 64 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
65 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 65 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
66 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 66 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
67 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 67 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
68 | * SUCH DAMAGE. | | 68 | * SUCH DAMAGE. |
69 | */ | | 69 | */ |
70 | | | 70 | |
71 | #ifndef MAKE_NATIVE | | 71 | #ifndef MAKE_NATIVE |
72 | static char rcsid[] = "$NetBSD: arch.c,v 1.101 2020/08/28 04:48:56 rillig Exp $"; | | 72 | static char rcsid[] = "$NetBSD: arch.c,v 1.102 2020/08/28 18:34:45 rillig Exp $"; |
73 | #else | | 73 | #else |
74 | #include <sys/cdefs.h> | | 74 | #include <sys/cdefs.h> |
75 | #ifndef lint | | 75 | #ifndef lint |
76 | #if 0 | | 76 | #if 0 |
77 | static char sccsid[] = "@(#)arch.c 8.2 (Berkeley) 1/2/94"; | | 77 | static char sccsid[] = "@(#)arch.c 8.2 (Berkeley) 1/2/94"; |
78 | #else | | 78 | #else |
79 | __RCSID("$NetBSD: arch.c,v 1.101 2020/08/28 04:48:56 rillig Exp $"); | | 79 | __RCSID("$NetBSD: arch.c,v 1.102 2020/08/28 18:34:45 rillig Exp $"); |
80 | #endif | | 80 | #endif |
81 | #endif /* not lint */ | | 81 | #endif /* not lint */ |
82 | #endif | | 82 | #endif |
83 | | | 83 | |
84 | /*- | | 84 | /*- |
85 | * arch.c -- | | 85 | * arch.c -- |
86 | * Functions to manipulate libraries, archives and their members. | | 86 | * Functions to manipulate libraries, archives and their members. |
87 | * | | 87 | * |
88 | * Once again, cacheing/hashing comes into play in the manipulation | | 88 | * Once again, cacheing/hashing comes into play in the manipulation |
89 | * of archives. The first time an archive is referenced, all of its members' | | 89 | * of archives. The first time an archive is referenced, all of its members' |
90 | * headers are read and hashed and the archive closed again. All hashed | | 90 | * headers are read and hashed and the archive closed again. All hashed |
91 | * archives are kept on a list which is searched each time an archive member | | 91 | * archives are kept on a list which is searched each time an archive member |
92 | * is referenced. | | 92 | * is referenced. |
| @@ -155,93 +155,72 @@ __RCSID("$NetBSD: arch.c,v 1.101 2020/08 | | | @@ -155,93 +155,72 @@ __RCSID("$NetBSD: arch.c,v 1.101 2020/08 |
155 | #endif | | 155 | #endif |
156 | | | 156 | |
157 | static Lst archives; /* Lst of archives we've already examined */ | | 157 | static Lst archives; /* Lst of archives we've already examined */ |
158 | | | 158 | |
159 | typedef struct Arch { | | 159 | typedef struct Arch { |
160 | char *name; /* Name of archive */ | | 160 | char *name; /* Name of archive */ |
161 | Hash_Table members; /* All the members of the archive described | | 161 | Hash_Table members; /* All the members of the archive described |
162 | * by <name, struct ar_hdr *> key/value pairs */ | | 162 | * by <name, struct ar_hdr *> key/value pairs */ |
163 | char *fnametab; /* Extended name table strings */ | | 163 | char *fnametab; /* Extended name table strings */ |
164 | size_t fnamesize; /* Size of the string table */ | | 164 | size_t fnamesize; /* Size of the string table */ |
165 | } Arch; | | 165 | } Arch; |
166 | | | 166 | |
167 | static int ArchFindArchive(const void *, const void *); | | 167 | static int ArchFindArchive(const void *, const void *); |
168 | #ifdef CLEANUP | | | |
169 | static void ArchFree(void *); | | | |
170 | #endif | | | |
171 | static struct ar_hdr *ArchStatMember(const char *, const char *, Boolean); | | 168 | static struct ar_hdr *ArchStatMember(const char *, const char *, Boolean); |
172 | static FILE *ArchFindMember(const char *, const char *, | | 169 | static FILE *ArchFindMember(const char *, const char *, |
173 | struct ar_hdr *, const char *); | | 170 | struct ar_hdr *, const char *); |
174 | #if defined(__svr4__) || defined(__SVR4) || defined(__ELF__) | | 171 | #if defined(__svr4__) || defined(__SVR4) || defined(__ELF__) |
175 | #define SVR4ARCHIVES | | 172 | #define SVR4ARCHIVES |
176 | static int ArchSVR4Entry(Arch *, char *, size_t, FILE *); | | 173 | static int ArchSVR4Entry(Arch *, char *, size_t, FILE *); |
177 | #endif | | 174 | #endif |
178 | | | 175 | |
179 | #ifdef CLEANUP | | 176 | #ifdef CLEANUP |
180 | /*- | | | |
181 | *----------------------------------------------------------------------- | | | |
182 | * ArchFree -- | | | |
183 | * Free memory used by an archive | | | |
184 | * | | | |
185 | * Results: | | | |
186 | * None. | | | |
187 | * | | | |
188 | * Side Effects: | | | |
189 | * None. | | | |
190 | * | | | |
191 | *----------------------------------------------------------------------- | | | |
192 | */ | | | |
193 | static void | | 177 | static void |
194 | ArchFree(void *ap) | | 178 | ArchFree(void *ap) |
195 | { | | 179 | { |
196 | Arch *a = (Arch *)ap; | | 180 | Arch *a = (Arch *)ap; |
197 | Hash_Search search; | | 181 | Hash_Search search; |
198 | Hash_Entry *entry; | | 182 | Hash_Entry *entry; |
199 | | | 183 | |
200 | /* Free memory from hash entries */ | | 184 | /* Free memory from hash entries */ |
201 | for (entry = Hash_EnumFirst(&a->members, &search); | | 185 | for (entry = Hash_EnumFirst(&a->members, &search); |
202 | entry != NULL; | | 186 | entry != NULL; |
203 | entry = Hash_EnumNext(&search)) | | 187 | entry = Hash_EnumNext(&search)) |
204 | free(Hash_GetValue(entry)); | | 188 | free(Hash_GetValue(entry)); |
205 | | | 189 | |
206 | free(a->name); | | 190 | free(a->name); |
207 | free(a->fnametab); | | 191 | free(a->fnametab); |
208 | Hash_DeleteTable(&a->members); | | 192 | Hash_DeleteTable(&a->members); |
209 | free(a); | | 193 | free(a); |
210 | } | | 194 | } |
211 | #endif | | 195 | #endif |
212 | | | 196 | |
213 | | | 197 | |
214 | | | | |
215 | /*- | | 198 | /*- |
216 | *----------------------------------------------------------------------- | | 199 | *----------------------------------------------------------------------- |
217 | * Arch_ParseArchive -- | | 200 | * Arch_ParseArchive -- |
218 | * Parse the archive specification in the given line and find/create | | 201 | * Parse the archive specification in the given line and find/create |
219 | * the nodes for the specified archive members, placing their nodes | | 202 | * the nodes for the specified archive members, placing their nodes |
220 | * on the given list. | | 203 | * on the given list. |
221 | * | | 204 | * |
222 | * Input: | | 205 | * Input: |
223 | * linePtr Pointer to start of specification | | 206 | * linePtr Pointer to start of specification |
224 | * nodeLst Lst on which to place the nodes | | 207 | * nodeLst Lst on which to place the nodes |
225 | * ctxt Context in which to expand variables | | 208 | * ctxt Context in which to expand variables |
226 | * | | 209 | * |
227 | * Results: | | 210 | * Results: |
228 | * TRUE if it was a valid specification. The linePtr is updated | | 211 | * TRUE if it was a valid specification. The linePtr is updated |
229 | * to point to the first non-space after the archive spec. The | | 212 | * to point to the first non-space after the archive spec. The |
230 | * nodes for the members are placed on the given list. | | 213 | * nodes for the members are placed on the given list. |
231 | * | | | |
232 | * Side Effects: | | | |
233 | * Some nodes may be created. The given list is extended. | | | |
234 | * | | | |
235 | *----------------------------------------------------------------------- | | 214 | *----------------------------------------------------------------------- |
236 | */ | | 215 | */ |
237 | Boolean | | 216 | Boolean |
238 | Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt) | | 217 | Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt) |
239 | { | | 218 | { |
240 | char *cp; /* Pointer into line */ | | 219 | char *cp; /* Pointer into line */ |
241 | GNode *gn; /* New node */ | | 220 | GNode *gn; /* New node */ |
242 | char *libName; /* Library-part of specification */ | | 221 | char *libName; /* Library-part of specification */ |
243 | char *memName; /* Member-part of specification */ | | 222 | char *memName; /* Member-part of specification */ |
244 | char saveChar; /* Ending delimiter of member-name */ | | 223 | char saveChar; /* Ending delimiter of member-name */ |
245 | Boolean subLibName; /* TRUE if libName should have/had | | 224 | Boolean subLibName; /* TRUE if libName should have/had |
246 | * variable substitution performed on it */ | | 225 | * variable substitution performed on it */ |
247 | | | 226 | |
| @@ -478,59 +457,52 @@ Arch_ParseArchive(char **linePtr, Lst no | | | @@ -478,59 +457,52 @@ Arch_ParseArchive(char **linePtr, Lst no |
478 | | | 457 | |
479 | /*- | | 458 | /*- |
480 | *----------------------------------------------------------------------- | | 459 | *----------------------------------------------------------------------- |
481 | * ArchFindArchive -- | | 460 | * ArchFindArchive -- |
482 | * See if the given archive is the one we are looking for. Called | | 461 | * See if the given archive is the one we are looking for. Called |
483 | * From ArchStatMember and ArchFindMember via Lst_Find. | | 462 | * From ArchStatMember and ArchFindMember via Lst_Find. |
484 | * | | 463 | * |
485 | * Input: | | 464 | * Input: |
486 | * ar Current list element | | 465 | * ar Current list element |
487 | * archName Name we want | | 466 | * archName Name we want |
488 | * | | 467 | * |
489 | * Results: | | 468 | * Results: |
490 | * 0 if it is, non-zero if it isn't. | | 469 | * 0 if it is, non-zero if it isn't. |
491 | * | | | |
492 | * Side Effects: | | | |
493 | * None. | | | |
494 | * | | | |
495 | *----------------------------------------------------------------------- | | 470 | *----------------------------------------------------------------------- |
496 | */ | | 471 | */ |
497 | static int | | 472 | static int |
498 | ArchFindArchive(const void *ar, const void *archName) | | 473 | ArchFindArchive(const void *ar, const void *archName) |
499 | { | | 474 | { |
500 | return strcmp(archName, ((const Arch *)ar)->name); | | 475 | return strcmp(archName, ((const Arch *)ar)->name); |
501 | } | | 476 | } |
502 | | | 477 | |
503 | /*- | | 478 | /*- |
504 | *----------------------------------------------------------------------- | | 479 | *----------------------------------------------------------------------- |
505 | * ArchStatMember -- | | 480 | * ArchStatMember -- |
506 | * Locate a member of an archive, given the path of the archive and | | 481 | * Locate a member of an archive, given the path of the archive and |
507 | * the path of the desired member. | | 482 | * the path of the desired member. |
508 | * | | 483 | * |
509 | * Input: | | 484 | * Input: |
510 | * archive Path to the archive | | 485 | * archive Path to the archive |
511 | * member Name of member. If it is a path, only the last | | 486 | * member Name of member. If it is a path, only the last |
512 | * component is used. | | 487 | * component is used. |
513 | * hash TRUE if archive should be hashed if not already so. | | 488 | * hash TRUE if archive should be hashed if not already so. |
514 | * | | 489 | * |
515 | * Results: | | 490 | * Results: |
516 | * A pointer to the current struct ar_hdr structure for the member. Note | | 491 | * A pointer to the current struct ar_hdr structure for the member. Note |
517 | * That no position is returned, so this is not useful for touching | | 492 | * That no position is returned, so this is not useful for touching |
518 | * archive members. This is mostly because we have no assurances that | | 493 | * archive members. This is mostly because we have no assurances that |
519 | * The archive will remain constant after we read all the headers, so | | 494 | * The archive will remain constant after we read all the headers, so |
520 | * there's not much point in remembering the position... | | 495 | * there's not much point in remembering the position... |
521 | * | | | |
522 | * Side Effects: | | | |
523 | * | | | |
524 | *----------------------------------------------------------------------- | | 496 | *----------------------------------------------------------------------- |
525 | */ | | 497 | */ |
526 | static struct ar_hdr * | | 498 | static struct ar_hdr * |
527 | ArchStatMember(const char *archive, const char *member, Boolean hash) | | 499 | ArchStatMember(const char *archive, const char *member, Boolean hash) |
528 | { | | 500 | { |
529 | #define AR_MAX_NAME_LEN (sizeof(arh.ar_name)-1) | | 501 | #define AR_MAX_NAME_LEN (sizeof(arh.ar_name)-1) |
530 | FILE * arch; /* Stream to archive */ | | 502 | FILE * arch; /* Stream to archive */ |
531 | size_t size; /* Size of archive member */ | | 503 | size_t size; /* Size of archive member */ |
532 | char magic[SARMAG]; | | 504 | char magic[SARMAG]; |
533 | LstNode ln; /* Lst member containing archive descriptor */ | | 505 | LstNode ln; /* Lst member containing archive descriptor */ |
534 | Arch *ar; /* Archive descriptor */ | | 506 | Arch *ar; /* Archive descriptor */ |
535 | Hash_Entry *he; /* Entry containing member's description */ | | 507 | Hash_Entry *he; /* Entry containing member's description */ |
536 | struct ar_hdr arh; /* archive-member header for reading archive */ | | 508 | struct ar_hdr arh; /* archive-member header for reading archive */ |
| @@ -719,37 +691,34 @@ badarch: | | | @@ -719,37 +691,34 @@ badarch: |
719 | free(ar->fnametab); | | 691 | free(ar->fnametab); |
720 | free(ar); | | 692 | free(ar); |
721 | return NULL; | | 693 | return NULL; |
722 | } | | 694 | } |
723 | | | 695 | |
724 | #ifdef SVR4ARCHIVES | | 696 | #ifdef SVR4ARCHIVES |
725 | /*- | | 697 | /*- |
726 | *----------------------------------------------------------------------- | | 698 | *----------------------------------------------------------------------- |
727 | * ArchSVR4Entry -- | | 699 | * ArchSVR4Entry -- |
728 | * Parse an SVR4 style entry that begins with a slash. | | 700 | * Parse an SVR4 style entry that begins with a slash. |
729 | * If it is "//", then load the table of filenames | | 701 | * If it is "//", then load the table of filenames |
730 | * If it is "/<offset>", then try to substitute the long file name | | 702 | * If it is "/<offset>", then try to substitute the long file name |
731 | * from offset of a table previously read. | | 703 | * from offset of a table previously read. |
| | | 704 | * If a table is read, the file pointer is moved to the next archive |
| | | 705 | * member. |
732 | * | | 706 | * |
733 | * Results: | | 707 | * Results: |
734 | * -1: Bad data in archive | | 708 | * -1: Bad data in archive |
735 | * 0: A table was loaded from the file | | 709 | * 0: A table was loaded from the file |
736 | * 1: Name was successfully substituted from table | | 710 | * 1: Name was successfully substituted from table |
737 | * 2: Name was not successfully substituted from table | | 711 | * 2: Name was not successfully substituted from table |
738 | * | | | |
739 | * Side Effects: | | | |
740 | * If a table is read, the file pointer is moved to the next archive | | | |
741 | * member | | | |
742 | * | | | |
743 | *----------------------------------------------------------------------- | | 712 | *----------------------------------------------------------------------- |
744 | */ | | 713 | */ |
745 | static int | | 714 | static int |
746 | ArchSVR4Entry(Arch *ar, char *name, size_t size, FILE *arch) | | 715 | ArchSVR4Entry(Arch *ar, char *name, size_t size, FILE *arch) |
747 | { | | 716 | { |
748 | #define ARLONGNAMES1 "//" | | 717 | #define ARLONGNAMES1 "//" |
749 | #define ARLONGNAMES2 "/ARFILENAMES" | | 718 | #define ARLONGNAMES2 "/ARFILENAMES" |
750 | size_t entry; | | 719 | size_t entry; |
751 | char *ptr, *eptr; | | 720 | char *ptr, *eptr; |
752 | | | 721 | |
753 | if (strncmp(name, ARLONGNAMES1, sizeof(ARLONGNAMES1) - 1) == 0 || | | 722 | if (strncmp(name, ARLONGNAMES1, sizeof(ARLONGNAMES1) - 1) == 0 || |
754 | strncmp(name, ARLONGNAMES2, sizeof(ARLONGNAMES2) - 1) == 0) { | | 723 | strncmp(name, ARLONGNAMES2, sizeof(ARLONGNAMES2) - 1) == 0) { |
755 | | | 724 | |
| @@ -818,42 +787,39 @@ ArchSVR4Entry(Arch *ar, char *name, size | | | @@ -818,42 +787,39 @@ ArchSVR4Entry(Arch *ar, char *name, size |
818 | | | 787 | |
819 | snprintf(name, MAXPATHLEN + 1, "%s", &ar->fnametab[entry]); | | 788 | snprintf(name, MAXPATHLEN + 1, "%s", &ar->fnametab[entry]); |
820 | return 1; | | 789 | return 1; |
821 | } | | 790 | } |
822 | #endif | | 791 | #endif |
823 | | | 792 | |
824 | | | 793 | |
825 | /*- | | 794 | /*- |
826 | *----------------------------------------------------------------------- | | 795 | *----------------------------------------------------------------------- |
827 | * ArchFindMember -- | | 796 | * ArchFindMember -- |
828 | * Locate a member of an archive, given the path of the archive and | | 797 | * Locate a member of an archive, given the path of the archive and |
829 | * the path of the desired member. If the archive is to be modified, | | 798 | * the path of the desired member. If the archive is to be modified, |
830 | * the mode should be "r+", if not, it should be "r". | | 799 | * the mode should be "r+", if not, it should be "r". |
| | | 800 | * The passed struct ar_hdr structure is filled in. |
831 | * | | 801 | * |
832 | * Input: | | 802 | * Input: |
833 | * archive Path to the archive | | 803 | * archive Path to the archive |
834 | * member Name of member. If it is a path, only the last | | 804 | * member Name of member. If it is a path, only the last |
835 | * component is used. | | 805 | * component is used. |
836 | * arhPtr Pointer to header structure to be filled in | | 806 | * arhPtr Pointer to header structure to be filled in |
837 | * mode The mode for opening the stream | | 807 | * mode The mode for opening the stream |
838 | * | | 808 | * |
839 | * Results: | | 809 | * Results: |
840 | * An FILE *, opened for reading and writing, positioned at the | | 810 | * An FILE *, opened for reading and writing, positioned at the |
841 | * start of the member's struct ar_hdr, or NULL if the member was | | 811 | * start of the member's struct ar_hdr, or NULL if the member was |
842 | * nonexistent. The current struct ar_hdr for member. | | 812 | * nonexistent. The current struct ar_hdr for member. |
843 | * | | | |
844 | * Side Effects: | | | |
845 | * The passed struct ar_hdr structure is filled in. | | | |
846 | * | | | |
847 | *----------------------------------------------------------------------- | | 813 | *----------------------------------------------------------------------- |
848 | */ | | 814 | */ |
849 | static FILE * | | 815 | static FILE * |
850 | ArchFindMember(const char *archive, const char *member, struct ar_hdr *arhPtr, | | 816 | ArchFindMember(const char *archive, const char *member, struct ar_hdr *arhPtr, |
851 | const char *mode) | | 817 | const char *mode) |
852 | { | | 818 | { |
853 | FILE * arch; /* Stream to archive */ | | 819 | FILE * arch; /* Stream to archive */ |
854 | int size; /* Size of archive member */ | | 820 | int size; /* Size of archive member */ |
855 | char magic[SARMAG]; | | 821 | char magic[SARMAG]; |
856 | size_t len, tlen; | | 822 | size_t len, tlen; |
857 | const char * base; | | 823 | const char * base; |
858 | | | 824 | |
859 | arch = fopen(archive, mode); | | 825 | arch = fopen(archive, mode); |
| @@ -979,158 +945,123 @@ skip: | | | @@ -979,158 +945,123 @@ skip: |
979 | | | 945 | |
980 | /* | | 946 | /* |
981 | * We've looked everywhere, but the member is not to be found. Close the | | 947 | * We've looked everywhere, but the member is not to be found. Close the |
982 | * archive and return NULL -- an error. | | 948 | * archive and return NULL -- an error. |
983 | */ | | 949 | */ |
984 | fclose(arch); | | 950 | fclose(arch); |
985 | return NULL; | | 951 | return NULL; |
986 | } | | 952 | } |
987 | | | 953 | |
988 | /*- | | 954 | /*- |
989 | *----------------------------------------------------------------------- | | 955 | *----------------------------------------------------------------------- |
990 | * Arch_Touch -- | | 956 | * Arch_Touch -- |
991 | * Touch a member of an archive. | | 957 | * Touch a member of an archive. |
| | | 958 | * The modification time of the entire archive is also changed. |
| | | 959 | * For a library, this could necessitate the re-ranlib'ing of the |
| | | 960 | * whole thing. |
992 | * | | 961 | * |
993 | * Input: | | 962 | * Input: |
994 | * gn Node of member to touch | | 963 | * gn Node of member to touch |
995 | * | | 964 | * |
996 | * Results: | | 965 | * Results: |
997 | * The 'time' field of the member's header is updated. | | 966 | * The 'time' field of the member's header is updated. |
998 | * | | | |
999 | * Side Effects: | | | |
1000 | * The modification time of the entire archive is also changed. | | | |
1001 | * For a library, this could necessitate the re-ranlib'ing of the | | | |
1002 | * whole thing. | | | |
1003 | * | | | |
1004 | *----------------------------------------------------------------------- | | 967 | *----------------------------------------------------------------------- |
1005 | */ | | 968 | */ |
1006 | void | | 969 | void |
1007 | Arch_Touch(GNode *gn) | | 970 | Arch_Touch(GNode *gn) |
1008 | { | | 971 | { |
1009 | FILE * arch; /* Stream open to archive, positioned properly */ | | 972 | FILE * arch; /* Stream open to archive, positioned properly */ |
1010 | struct ar_hdr arh; /* Current header describing member */ | | 973 | struct ar_hdr arh; /* Current header describing member */ |
1011 | char *p1, *p2; | | 974 | char *p1, *p2; |
1012 | | | 975 | |
1013 | arch = ArchFindMember(Var_Value(ARCHIVE, gn, &p1), | | 976 | arch = ArchFindMember(Var_Value(ARCHIVE, gn, &p1), |
1014 | Var_Value(MEMBER, gn, &p2), | | 977 | Var_Value(MEMBER, gn, &p2), |
1015 | &arh, "r+"); | | 978 | &arh, "r+"); |
1016 | | | 979 | |
1017 | bmake_free(p1); | | 980 | bmake_free(p1); |
1018 | bmake_free(p2); | | 981 | bmake_free(p2); |
1019 | | | 982 | |
1020 | snprintf(arh.ar_date, sizeof(arh.ar_date), "%-12ld", (long) now); | | 983 | snprintf(arh.ar_date, sizeof(arh.ar_date), "%-12ld", (long) now); |
1021 | | | 984 | |
1022 | if (arch != NULL) { | | 985 | if (arch != NULL) { |
1023 | (void)fwrite((char *)&arh, sizeof(struct ar_hdr), 1, arch); | | 986 | (void)fwrite((char *)&arh, sizeof(struct ar_hdr), 1, arch); |
1024 | fclose(arch); | | 987 | fclose(arch); |
1025 | } | | 988 | } |
1026 | } | | 989 | } |
1027 | | | 990 | |
1028 | /*- | | 991 | /* Given a node which represents a library, touch the thing, making sure that |
1029 | *----------------------------------------------------------------------- | | 992 | * the table of contents also is touched. |
1030 | * Arch_TouchLib -- | | 993 | * |
1031 | * Given a node which represents a library, touch the thing, making | | 994 | * Both the modification time of the library and of the RANLIBMAG member are |
1032 | * sure that the table of contents also is touched. | | 995 | * set to 'now'. |
1033 | * | | 996 | * |
1034 | * Input: | | 997 | * Input: |
1035 | * gn The node of the library to touch | | 998 | * gn The node of the library to touch |
1036 | * | | | |
1037 | * Results: | | | |
1038 | * None. | | | |
1039 | * | | | |
1040 | * Side Effects: | | | |
1041 | * Both the modification time of the library and of the RANLIBMAG | | | |
1042 | * member are set to 'now'. | | | |
1043 | * | | | |
1044 | *----------------------------------------------------------------------- | | | |
1045 | */ | | 999 | */ |
1046 | void | | 1000 | void |
1047 | Arch_TouchLib(GNode *gn) | | 1001 | Arch_TouchLib(GNode *gn) |
1048 | { | | 1002 | { |
1049 | #ifdef RANLIBMAG | | 1003 | #ifdef RANLIBMAG |
1050 | FILE * arch; /* Stream open to archive */ | | 1004 | FILE * arch; /* Stream open to archive */ |
1051 | struct ar_hdr arh; /* Header describing table of contents */ | | 1005 | struct ar_hdr arh; /* Header describing table of contents */ |
1052 | struct utimbuf times; /* Times for utime() call */ | | 1006 | struct utimbuf times; /* Times for utime() call */ |
1053 | | | 1007 | |
1054 | arch = ArchFindMember(gn->path, RANLIBMAG, &arh, "r+"); | | 1008 | arch = ArchFindMember(gn->path, RANLIBMAG, &arh, "r+"); |
1055 | snprintf(arh.ar_date, sizeof(arh.ar_date), "%-12ld", (long) now); | | 1009 | snprintf(arh.ar_date, sizeof(arh.ar_date), "%-12ld", (long) now); |
1056 | | | 1010 | |
1057 | if (arch != NULL) { | | 1011 | if (arch != NULL) { |
1058 | (void)fwrite((char *)&arh, sizeof(struct ar_hdr), 1, arch); | | 1012 | (void)fwrite((char *)&arh, sizeof(struct ar_hdr), 1, arch); |
1059 | fclose(arch); | | 1013 | fclose(arch); |
1060 | | | 1014 | |
1061 | times.actime = times.modtime = now; | | 1015 | times.actime = times.modtime = now; |
1062 | utime(gn->path, ×); | | 1016 | utime(gn->path, ×); |
1063 | } | | 1017 | } |
1064 | #else | | 1018 | #else |
1065 | (void)gn; | | 1019 | (void)gn; |
1066 | #endif | | 1020 | #endif |
1067 | } | | 1021 | } |
1068 | | | 1022 | |
1069 | /*- | | 1023 | /* Return the modification time of a member of an archive. The mtime field |
1070 | *----------------------------------------------------------------------- | | 1024 | * of the given node is filled in with the value returned by the function. |
1071 | * Arch_MTime -- | | | |
1072 | * Return the modification time of a member of an archive. | | | |
1073 | * | | 1025 | * |
1074 | * Input: | | 1026 | * Input: |
1075 | * gn Node describing archive member | | 1027 | * gn Node describing archive member |
1076 | * | | | |
1077 | * Results: | | | |
1078 | * The modification time(seconds). | | | |
1079 | * | | | |
1080 | * Side Effects: | | | |
1081 | * The mtime field of the given node is filled in with the value | | | |
1082 | * returned by the function. | | | |
1083 | * | | | |
1084 | *----------------------------------------------------------------------- | | | |
1085 | */ | | 1028 | */ |
1086 | time_t | | 1029 | time_t |
1087 | Arch_MTime(GNode *gn) | | 1030 | Arch_MTime(GNode *gn) |
1088 | { | | 1031 | { |
1089 | struct ar_hdr *arhPtr; /* Header of desired member */ | | 1032 | struct ar_hdr *arhPtr; /* Header of desired member */ |
1090 | time_t modTime; /* Modification time as an integer */ | | 1033 | time_t modTime; /* Modification time as an integer */ |
1091 | char *p1, *p2; | | 1034 | char *p1, *p2; |
1092 | | | 1035 | |
1093 | arhPtr = ArchStatMember(Var_Value(ARCHIVE, gn, &p1), | | 1036 | arhPtr = ArchStatMember(Var_Value(ARCHIVE, gn, &p1), |
1094 | Var_Value(MEMBER, gn, &p2), | | 1037 | Var_Value(MEMBER, gn, &p2), |
1095 | TRUE); | | 1038 | TRUE); |
1096 | | | 1039 | |
1097 | bmake_free(p1); | | 1040 | bmake_free(p1); |
1098 | bmake_free(p2); | | 1041 | bmake_free(p2); |
1099 | | | 1042 | |
1100 | if (arhPtr != NULL) { | | 1043 | if (arhPtr != NULL) { |
1101 | modTime = (time_t)strtol(arhPtr->ar_date, NULL, 10); | | 1044 | modTime = (time_t)strtol(arhPtr->ar_date, NULL, 10); |
1102 | } else { | | 1045 | } else { |
1103 | modTime = 0; | | 1046 | modTime = 0; |
1104 | } | | 1047 | } |
1105 | | | 1048 | |
1106 | gn->mtime = modTime; | | 1049 | gn->mtime = modTime; |
1107 | return modTime; | | 1050 | return modTime; |
1108 | } | | 1051 | } |
1109 | | | 1052 | |
1110 | /*- | | 1053 | /* Given a non-existent archive member's node, get its modification time from |
1111 | *----------------------------------------------------------------------- | | 1054 | * its archived form, if it exists. gn->mtime is filled in as well. */ |
1112 | * Arch_MemMTime -- | | | |
1113 | * Given a non-existent archive member's node, get its modification | | | |
1114 | * time from its archived form, if it exists. | | | |
1115 | * | | | |
1116 | * Results: | | | |
1117 | * The modification time. | | | |
1118 | * | | | |
1119 | * Side Effects: | | | |
1120 | * The mtime field is filled in. | | | |
1121 | * | | | |
1122 | *----------------------------------------------------------------------- | | | |
1123 | */ | | | |
1124 | time_t | | 1055 | time_t |
1125 | Arch_MemMTime(GNode *gn) | | 1056 | Arch_MemMTime(GNode *gn) |
1126 | { | | 1057 | { |
1127 | LstNode ln; | | 1058 | LstNode ln; |
1128 | GNode *pgn; | | 1059 | GNode *pgn; |
1129 | | | 1060 | |
1130 | Lst_Open(gn->parents); | | 1061 | Lst_Open(gn->parents); |
1131 | while ((ln = Lst_Next(gn->parents)) != NULL) { | | 1062 | while ((ln = Lst_Next(gn->parents)) != NULL) { |
1132 | pgn = Lst_Datum(ln); | | 1063 | pgn = Lst_Datum(ln); |
1133 | | | 1064 | |
1134 | if (pgn->type & OP_ARCHV) { | | 1065 | if (pgn->type & OP_ARCHV) { |
1135 | /* | | 1066 | /* |
1136 | * If the parent is an archive specification and is being made | | 1067 | * If the parent is an archive specification and is being made |
| @@ -1152,108 +1083,93 @@ Arch_MemMTime(GNode *gn) | | | @@ -1152,108 +1083,93 @@ Arch_MemMTime(GNode *gn) |
1152 | * Something which isn't a library depends on the existence of | | 1083 | * Something which isn't a library depends on the existence of |
1153 | * this target, so it needs to exist. | | 1084 | * this target, so it needs to exist. |
1154 | */ | | 1085 | */ |
1155 | gn->mtime = 0; | | 1086 | gn->mtime = 0; |
1156 | break; | | 1087 | break; |
1157 | } | | 1088 | } |
1158 | } | | 1089 | } |
1159 | | | 1090 | |
1160 | Lst_Close(gn->parents); | | 1091 | Lst_Close(gn->parents); |
1161 | | | 1092 | |
1162 | return gn->mtime; | | 1093 | return gn->mtime; |
1163 | } | | 1094 | } |
1164 | | | 1095 | |
1165 | /*- | | 1096 | /* Search for a library along the given search path. |
1166 | *----------------------------------------------------------------------- | | 1097 | * |
1167 | * Arch_FindLib -- | | 1098 | * The node's 'path' field is set to the found path (including the |
1168 | * Search for a library along the given search path. | | 1099 | * actual file name, not -l...). If the system can handle the -L |
| | | 1100 | * flag when linking (or we cannot find the library), we assume that |
| | | 1101 | * the user has placed the .LIBS variable in the final linking |
| | | 1102 | * command (or the linker will know where to find it) and set the |
| | | 1103 | * TARGET variable for this node to be the node's name. Otherwise, |
| | | 1104 | * we set the TARGET variable to be the full path of the library, |
| | | 1105 | * as returned by Dir_FindFile. |
1169 | * | | 1106 | * |
1170 | * Input: | | 1107 | * Input: |
1171 | * gn Node of library to find | | 1108 | * gn Node of library to find |
1172 | * path Search path | | 1109 | * path Search path |
1173 | * | | | |
1174 | * Results: | | | |
1175 | * None. | | | |
1176 | * | | | |
1177 | * Side Effects: | | | |
1178 | * The node's 'path' field is set to the found path (including the | | | |
1179 | * actual file name, not -l...). If the system can handle the -L | | | |
1180 | * flag when linking (or we cannot find the library), we assume that | | | |
1181 | * the user has placed the .LIBRARIES variable in the final linking | | | |
1182 | * command (or the linker will know where to find it) and set the | | | |
1183 | * TARGET variable for this node to be the node's name. Otherwise, | | | |
1184 | * we set the TARGET variable to be the full path of the library, | | | |
1185 | * as returned by Dir_FindFile. | | | |
1186 | * | | | |
1187 | *----------------------------------------------------------------------- | | | |
1188 | */ | | 1110 | */ |
1189 | void | | 1111 | void |
1190 | Arch_FindLib(GNode *gn, Lst path) | | 1112 | Arch_FindLib(GNode *gn, Lst path) |
1191 | { | | 1113 | { |
1192 | char *libName; /* file name for archive */ | | 1114 | char *libName; /* file name for archive */ |
1193 | size_t sz = strlen(gn->name) + 6 - 2; | | 1115 | size_t sz = strlen(gn->name) + 6 - 2; |
1194 | | | 1116 | |
1195 | libName = bmake_malloc(sz); | | 1117 | libName = bmake_malloc(sz); |
1196 | snprintf(libName, sz, "lib%s.a", &gn->name[2]); | | 1118 | snprintf(libName, sz, "lib%s.a", &gn->name[2]); |
1197 | | | 1119 | |
1198 | gn->path = Dir_FindFile(libName, path); | | 1120 | gn->path = Dir_FindFile(libName, path); |
1199 | | | 1121 | |
1200 | free(libName); | | 1122 | free(libName); |
1201 | | | 1123 | |
1202 | #ifdef LIBRARIES | | 1124 | #ifdef LIBRARIES |
1203 | Var_Set(TARGET, gn->name, gn); | | 1125 | Var_Set(TARGET, gn->name, gn); |
1204 | #else | | 1126 | #else |
1205 | Var_Set(TARGET, gn->path == NULL ? gn->name : gn->path, gn); | | 1127 | Var_Set(TARGET, gn->path == NULL ? gn->name : gn->path, gn); |
1206 | #endif /* LIBRARIES */ | | 1128 | #endif /* LIBRARIES */ |
1207 | } | | 1129 | } |
1208 | | | 1130 | |
1209 | /*- | | 1131 | /* Decide if a node with the OP_LIB attribute is out-of-date. Called from |
1210 | *----------------------------------------------------------------------- | | 1132 | * Make_OODate to make its life easier. |
1211 | * Arch_LibOODate -- | | 1133 | * The library will be hashed if it hasn't been already. |
1212 | * Decide if a node with the OP_LIB attribute is out-of-date. Called | | 1134 | * |
1213 | * from Make_OODate to make its life easier. | | 1135 | * There are several ways for a library to be out-of-date that are |
1214 | * | | 1136 | * not available to ordinary files. In addition, there are ways |
1215 | * There are several ways for a library to be out-of-date that are | | 1137 | * that are open to regular files that are not available to |
1216 | * not available to ordinary files. In addition, there are ways | | 1138 | * libraries. A library that is only used as a source is never |
1217 | * that are open to regular files that are not available to | | 1139 | * considered out-of-date by itself. This does not preclude the |
1218 | * libraries. A library that is only used as a source is never | | 1140 | * library's modification time from making its parent be out-of-date. |
1219 | * considered out-of-date by itself. This does not preclude the | | 1141 | * A library will be considered out-of-date for any of these reasons, |
1220 | * library's modification time from making its parent be out-of-date. | | 1142 | * given that it is a target on a dependency line somewhere: |
1221 | * A library will be considered out-of-date for any of these reasons, | | 1143 | * |
1222 | * given that it is a target on a dependency line somewhere: | | 1144 | * Its modification time is less than that of one of its sources |
1223 | * Its modification time is less than that of one of its | | 1145 | * (gn->mtime < gn->cmgn->mtime). |
1224 | * sources (gn->mtime < gn->cmgn->mtime). | | 1146 | * |
1225 | * Its modification time is greater than the time at which the | | 1147 | * Its modification time is greater than the time at which the make |
1226 | * make began (i.e. it's been modified in the course | | 1148 | * began (i.e. it's been modified in the course of the make, probably |
1227 | * of the make, probably by archiving). | | 1149 | * by archiving). |
1228 | * The modification time of one of its sources is greater than | | 1150 | * |
1229 | * the one of its RANLIBMAG member (i.e. its table of contents | | 1151 | * The modification time of one of its sources is greater than the one |
1230 | * is out-of-date). We don't compare of the archive time | | 1152 | * of its RANLIBMAG member (i.e. its table of contents is out-of-date). |
1231 | * vs. TOC time because they can be too close. In my | | 1153 | * We don't compare of the archive time vs. TOC time because they can be |
1232 | * opinion we should not bother with the TOC at all since | | 1154 | * too close. In my opinion we should not bother with the TOC at all |
1233 | * this is used by 'ar' rules that affect the data contents | | 1155 | * since this is used by 'ar' rules that affect the data contents of the |
1234 | * of the archive, not by ranlib rules, which affect the | | 1156 | * archive, not by ranlib rules, which affect the TOC. |
1235 | * TOC. | | | |
1236 | * | | 1157 | * |
1237 | * Input: | | 1158 | * Input: |
1238 | * gn The library's graph node | | 1159 | * gn The library's graph node |
1239 | * | | 1160 | * |
1240 | * Results: | | 1161 | * Results: |
1241 | * TRUE if the library is out-of-date. FALSE otherwise. | | 1162 | * TRUE if the library is out-of-date. FALSE otherwise. |
1242 | * | | | |
1243 | * Side Effects: | | | |
1244 | * The library will be hashed if it hasn't been already. | | | |
1245 | * | | | |
1246 | *----------------------------------------------------------------------- | | | |
1247 | */ | | 1163 | */ |
1248 | Boolean | | 1164 | Boolean |
1249 | Arch_LibOODate(GNode *gn) | | 1165 | Arch_LibOODate(GNode *gn) |
1250 | { | | 1166 | { |
1251 | Boolean oodate; | | 1167 | Boolean oodate; |
1252 | | | 1168 | |
1253 | if (gn->type & OP_PHONY) { | | 1169 | if (gn->type & OP_PHONY) { |
1254 | oodate = TRUE; | | 1170 | oodate = TRUE; |
1255 | } else if (OP_NOP(gn->type) && Lst_IsEmpty(gn->children)) { | | 1171 | } else if (OP_NOP(gn->type) && Lst_IsEmpty(gn->children)) { |
1256 | oodate = FALSE; | | 1172 | oodate = FALSE; |
1257 | } else if ((!Lst_IsEmpty(gn->children) && gn->cmgn == NULL) || | | 1173 | } else if ((!Lst_IsEmpty(gn->children) && gn->cmgn == NULL) || |
1258 | (gn->mtime > now) || | | 1174 | (gn->mtime > now) || |
1259 | (gn->cmgn != NULL && gn->mtime < gn->cmgn->mtime)) { | | 1175 | (gn->cmgn != NULL && gn->mtime < gn->cmgn->mtime)) { |
| @@ -1294,45 +1210,32 @@ Arch_Init(void) | | | @@ -1294,45 +1210,32 @@ Arch_Init(void) |
1294 | { | | 1210 | { |
1295 | archives = Lst_Init(); | | 1211 | archives = Lst_Init(); |
1296 | } | | 1212 | } |
1297 | | | 1213 | |
1298 | /* Clean up things for this module. */ | | 1214 | /* Clean up things for this module. */ |
1299 | void | | 1215 | void |
1300 | Arch_End(void) | | 1216 | Arch_End(void) |
1301 | { | | 1217 | { |
1302 | #ifdef CLEANUP | | 1218 | #ifdef CLEANUP |
1303 | Lst_Destroy(archives, ArchFree); | | 1219 | Lst_Destroy(archives, ArchFree); |
1304 | #endif | | 1220 | #endif |
1305 | } | | 1221 | } |
1306 | | | 1222 | |
1307 | /*- | | 1223 | Boolean |
1308 | *----------------------------------------------------------------------- | | | |
1309 | * Arch_IsLib -- | | | |
1310 | * Check if the node is a library | | | |
1311 | * | | | |
1312 | * Results: | | | |
1313 | * True or False. | | | |
1314 | * | | | |
1315 | * Side Effects: | | | |
1316 | * None. | | | |
1317 | * | | | |
1318 | *----------------------------------------------------------------------- | | | |
1319 | */ | | | |
1320 | int | | | |
1321 | Arch_IsLib(GNode *gn) | | 1224 | Arch_IsLib(GNode *gn) |
1322 | { | | 1225 | { |
1323 | static const char armag[] = "!<arch>\n"; | | 1226 | static const char armag[] = "!<arch>\n"; |
1324 | char buf[sizeof(armag)-1]; | | 1227 | char buf[sizeof armag - 1]; |
1325 | int fd; | | 1228 | int fd; |
1326 | | | 1229 | |
1327 | if ((fd = open(gn->path, O_RDONLY)) == -1) | | 1230 | if ((fd = open(gn->path, O_RDONLY)) == -1) |
1328 | return FALSE; | | 1231 | return FALSE; |
1329 | | | 1232 | |
1330 | if (read(fd, buf, sizeof(buf)) != sizeof(buf)) { | | 1233 | if (read(fd, buf, sizeof buf) != sizeof buf) { |
1331 | (void)close(fd); | | 1234 | (void)close(fd); |
1332 | return FALSE; | | 1235 | return FALSE; |
1333 | } | | 1236 | } |
1334 | | | 1237 | |
1335 | (void)close(fd); | | 1238 | (void)close(fd); |
1336 | | | 1239 | |
1337 | return memcmp(buf, armag, sizeof(buf)) == 0; | | 1240 | return memcmp(buf, armag, sizeof buf) == 0; |
1338 | } | | 1241 | } |