Mon Jul 27 19:06:45 2020 UTC ()
make(1): improve const-correctness in archive handling

The return value of Var_Value must not be modified.  Ideally it would be
declared as const char *, but that still takes a while, especially since
much of the make code is not yet covered by the unit tests.

The variable cp had to be changed to const char * as well, and while here
was split up into one variable per actual use case.


(rillig)
diff -r1.75 -r1.76 src/usr.bin/make/arch.c

cvs diff -r1.75 -r1.76 src/usr.bin/make/arch.c (expand / switch to unified diff)

--- src/usr.bin/make/arch.c 2020/07/26 20:21:31 1.75
+++ src/usr.bin/make/arch.c 2020/07/27 19:06:45 1.76
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: arch.c,v 1.75 2020/07/26 20:21:31 rillig Exp $ */ 1/* $NetBSD: arch.c,v 1.76 2020/07/27 19:06: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
72static char rcsid[] = "$NetBSD: arch.c,v 1.75 2020/07/26 20:21:31 rillig Exp $"; 72static char rcsid[] = "$NetBSD: arch.c,v 1.76 2020/07/27 19:06: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
77static char sccsid[] = "@(#)arch.c 8.2 (Berkeley) 1/2/94"; 77static char sccsid[] = "@(#)arch.c 8.2 (Berkeley) 1/2/94";
78#else 78#else
79__RCSID("$NetBSD: arch.c,v 1.75 2020/07/26 20:21:31 rillig Exp $"); 79__RCSID("$NetBSD: arch.c,v 1.76 2020/07/27 19:06: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.
@@ -158,28 +158,29 @@ static Lst archives; /* Lst of archi @@ -158,28 +158,29 @@ static Lst archives; /* Lst of archi
158 158
159typedef struct Arch { 159typedef 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
167static int ArchFindArchive(const void *, const void *); 167static int ArchFindArchive(const void *, const void *);
168#ifdef CLEANUP 168#ifdef CLEANUP
169static void ArchFree(void *); 169static void ArchFree(void *);
170#endif 170#endif
171static struct ar_hdr *ArchStatMember(char *, char *, Boolean); 171static struct ar_hdr *ArchStatMember(const char *, const char *, Boolean);
172static FILE *ArchFindMember(char *, char *, struct ar_hdr *, const char *); 172static FILE *ArchFindMember(const char *, const char *,
 173 struct ar_hdr *, const char *);
173#if defined(__svr4__) || defined(__SVR4) || defined(__ELF__) 174#if defined(__svr4__) || defined(__SVR4) || defined(__ELF__)
174#define SVR4ARCHIVES 175#define SVR4ARCHIVES
175static int ArchSVR4Entry(Arch *, char *, size_t, FILE *); 176static int ArchSVR4Entry(Arch *, char *, size_t, FILE *);
176#endif 177#endif
177 178
178#ifdef CLEANUP 179#ifdef CLEANUP
179/*- 180/*-
180 *----------------------------------------------------------------------- 181 *-----------------------------------------------------------------------
181 * ArchFree -- 182 * ArchFree --
182 * Free memory used by an archive 183 * Free memory used by an archive
183 * 184 *
184 * Results: 185 * Results:
185 * None. 186 * None.
@@ -513,49 +514,48 @@ ArchFindArchive(const void *ar, const vo @@ -513,49 +514,48 @@ ArchFindArchive(const void *ar, const vo
513 * 514 *
514 * Results: 515 * Results:
515 * A pointer to the current struct ar_hdr structure for the member. Note 516 * A pointer to the current struct ar_hdr structure for the member. Note
516 * That no position is returned, so this is not useful for touching 517 * That no position is returned, so this is not useful for touching
517 * archive members. This is mostly because we have no assurances that 518 * archive members. This is mostly because we have no assurances that
518 * The archive will remain constant after we read all the headers, so 519 * The archive will remain constant after we read all the headers, so
519 * there's not much point in remembering the position... 520 * there's not much point in remembering the position...
520 * 521 *
521 * Side Effects: 522 * Side Effects:
522 * 523 *
523 *----------------------------------------------------------------------- 524 *-----------------------------------------------------------------------
524 */ 525 */
525static struct ar_hdr * 526static struct ar_hdr *
526ArchStatMember(char *archive, char *member, Boolean hash) 527ArchStatMember(const char *archive, const char *member, Boolean hash)
527{ 528{
528#define AR_MAX_NAME_LEN (sizeof(arh.ar_name)-1) 529#define AR_MAX_NAME_LEN (sizeof(arh.ar_name)-1)
529 FILE * arch; /* Stream to archive */ 530 FILE * arch; /* Stream to archive */
530 int size; /* Size of archive member */ 531 int size; /* Size of archive member */
531 char *cp; /* Useful character pointer */ 
532 char magic[SARMAG]; 532 char magic[SARMAG];
533 LstNode ln; /* Lst member containing archive descriptor */ 533 LstNode ln; /* Lst member containing archive descriptor */
534 Arch *ar; /* Archive descriptor */ 534 Arch *ar; /* Archive descriptor */
535 Hash_Entry *he; /* Entry containing member's description */ 535 Hash_Entry *he; /* Entry containing member's description */
536 struct ar_hdr arh; /* archive-member header for reading archive */ 536 struct ar_hdr arh; /* archive-member header for reading archive */
537 char memName[MAXPATHLEN+1]; 537 char memName[MAXPATHLEN+1];
538 /* Current member name while hashing. */ 538 /* Current member name while hashing. */
539 539
540 /* 540 /*
541 * Because of space constraints and similar things, files are archived 541 * Because of space constraints and similar things, files are archived
542 * using their final path components, not the entire thing, so we need 542 * using their final path components, not the entire thing, so we need
543 * to point 'member' to the final component, if there is one, to make 543 * to point 'member' to the final component, if there is one, to make
544 * the comparisons easier... 544 * the comparisons easier...
545 */ 545 */
546 cp = strrchr(member, '/'); 546 const char *base = strrchr(member, '/');
547 if (cp != NULL) { 547 if (base != NULL) {
548 member = cp + 1; 548 member = base + 1;
549 } 549 }
550 550
551 ln = Lst_Find(archives, archive, ArchFindArchive); 551 ln = Lst_Find(archives, archive, ArchFindArchive);
552 if (ln != NULL) { 552 if (ln != NULL) {
553 ar = (Arch *)Lst_Datum(ln); 553 ar = (Arch *)Lst_Datum(ln);
554 554
555 he = Hash_FindEntry(&ar->members, member); 555 he = Hash_FindEntry(&ar->members, member);
556 556
557 if (he != NULL) { 557 if (he != NULL) {
558 return (struct ar_hdr *)Hash_GetValue(he); 558 return (struct ar_hdr *)Hash_GetValue(he);
559 } else { 559 } else {
560 /* Try truncated name */ 560 /* Try truncated name */
561 char copy[AR_MAX_NAME_LEN+1]; 561 char copy[AR_MAX_NAME_LEN+1];
@@ -626,51 +626,52 @@ ArchStatMember(char *archive, char *memb @@ -626,51 +626,52 @@ ArchStatMember(char *archive, char *memb
626 */ 626 */
627 goto badarch; 627 goto badarch;
628 } else { 628 } else {
629 /* 629 /*
630 * We need to advance the stream's pointer to the start of the 630 * We need to advance the stream's pointer to the start of the
631 * next header. Files are padded with newlines to an even-byte 631 * next header. Files are padded with newlines to an even-byte
632 * boundary, so we need to extract the size of the file from the 632 * boundary, so we need to extract the size of the file from the
633 * 'size' field of the header and round it up during the seek. 633 * 'size' field of the header and round it up during the seek.
634 */ 634 */
635 arh.ar_size[sizeof(arh.ar_size)-1] = '\0'; 635 arh.ar_size[sizeof(arh.ar_size)-1] = '\0';
636 size = (int)strtol(arh.ar_size, NULL, 10); 636 size = (int)strtol(arh.ar_size, NULL, 10);
637 637
638 memcpy(memName, arh.ar_name, sizeof(arh.ar_name)); 638 memcpy(memName, arh.ar_name, sizeof(arh.ar_name));
639 for (cp = &memName[AR_MAX_NAME_LEN]; *cp == ' '; cp--) { 639 char *nameend = memName + AR_MAX_NAME_LEN;
640 continue; 640 while (*nameend == ' ') {
 641 nameend--;
641 } 642 }
642 cp[1] = '\0'; 643 nameend[1] = '\0';
643 644
644#ifdef SVR4ARCHIVES 645#ifdef SVR4ARCHIVES
645 /* 646 /*
646 * svr4 names are slash terminated. Also svr4 extended AR format. 647 * svr4 names are slash terminated. Also svr4 extended AR format.
647 */ 648 */
648 if (memName[0] == '/') { 649 if (memName[0] == '/') {
649 /* 650 /*
650 * svr4 magic mode; handle it 651 * svr4 magic mode; handle it
651 */ 652 */
652 switch (ArchSVR4Entry(ar, memName, size, arch)) { 653 switch (ArchSVR4Entry(ar, memName, size, arch)) {
653 case -1: /* Invalid data */ 654 case -1: /* Invalid data */
654 goto badarch; 655 goto badarch;
655 case 0: /* List of files entry */ 656 case 0: /* List of files entry */
656 continue; 657 continue;
657 default: /* Got the entry */ 658 default: /* Got the entry */
658 break; 659 break;
659 } 660 }
660 } 661 }
661 else { 662 else {
662 if (cp[0] == '/') 663 if (nameend[0] == '/')
663 cp[0] = '\0'; 664 nameend[0] = '\0';
664 } 665 }
665#endif 666#endif
666 667
667#ifdef AR_EFMT1 668#ifdef AR_EFMT1
668 /* 669 /*
669 * BSD 4.4 extended AR format: #1/<namelen>, with name as the 670 * BSD 4.4 extended AR format: #1/<namelen>, with name as the
670 * first <namelen> bytes of the file 671 * first <namelen> bytes of the file
671 */ 672 */
672 if (strncmp(memName, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0 && 673 if (strncmp(memName, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0 &&
673 isdigit((unsigned char)memName[sizeof(AR_EFMT1) - 1])) { 674 isdigit((unsigned char)memName[sizeof(AR_EFMT1) - 1])) {
674 675
675 unsigned int elen = atoi(&memName[sizeof(AR_EFMT1)-1]); 676 unsigned int elen = atoi(&memName[sizeof(AR_EFMT1)-1]);
676 677
@@ -836,59 +837,58 @@ ArchSVR4Entry(Arch *ar, char *name, size @@ -836,59 +837,58 @@ ArchSVR4Entry(Arch *ar, char *name, size
836 * mode The mode for opening the stream 837 * mode The mode for opening the stream
837 * 838 *
838 * Results: 839 * Results:
839 * An FILE *, opened for reading and writing, positioned at the 840 * An FILE *, opened for reading and writing, positioned at the
840 * start of the member's struct ar_hdr, or NULL if the member was 841 * start of the member's struct ar_hdr, or NULL if the member was
841 * nonexistent. The current struct ar_hdr for member. 842 * nonexistent. The current struct ar_hdr for member.
842 * 843 *
843 * Side Effects: 844 * Side Effects:
844 * The passed struct ar_hdr structure is filled in. 845 * The passed struct ar_hdr structure is filled in.
845 * 846 *
846 *----------------------------------------------------------------------- 847 *-----------------------------------------------------------------------
847 */ 848 */
848static FILE * 849static FILE *
849ArchFindMember(char *archive, char *member, struct ar_hdr *arhPtr, 850ArchFindMember(const char *archive, const char *member, struct ar_hdr *arhPtr,
850 const char *mode) 851 const char *mode)
851{ 852{
852 FILE * arch; /* Stream to archive */ 853 FILE * arch; /* Stream to archive */
853 int size; /* Size of archive member */ 854 int size; /* Size of archive member */
854 char *cp; /* Useful character pointer */ 
855 char magic[SARMAG]; 855 char magic[SARMAG];
856 size_t len, tlen; 856 size_t len, tlen;
857 857
858 arch = fopen(archive, mode); 858 arch = fopen(archive, mode);
859 if (arch == NULL) { 859 if (arch == NULL) {
860 return NULL; 860 return NULL;
861 } 861 }
862 862
863 /* 863 /*
864 * We use the ARMAG string to make sure this is an archive we 864 * We use the ARMAG string to make sure this is an archive we
865 * can handle... 865 * can handle...
866 */ 866 */
867 if ((fread(magic, SARMAG, 1, arch) != 1) || 867 if ((fread(magic, SARMAG, 1, arch) != 1) ||
868 (strncmp(magic, ARMAG, SARMAG) != 0)) { 868 (strncmp(magic, ARMAG, SARMAG) != 0)) {
869 fclose(arch); 869 fclose(arch);
870 return NULL; 870 return NULL;
871 } 871 }
872 872
873 /* 873 /*
874 * Because of space constraints and similar things, files are archived 874 * Because of space constraints and similar things, files are archived
875 * using their final path components, not the entire thing, so we need 875 * using their final path components, not the entire thing, so we need
876 * to point 'member' to the final component, if there is one, to make 876 * to point 'member' to the final component, if there is one, to make
877 * the comparisons easier... 877 * the comparisons easier...
878 */ 878 */
879 cp = strrchr(member, '/'); 879 const char *base = strrchr(member, '/');
880 if (cp != NULL) { 880 if (base != NULL) {
881 member = cp + 1; 881 member = base + 1;
882 } 882 }
883 len = tlen = strlen(member); 883 len = tlen = strlen(member);
884 if (len > sizeof(arhPtr->ar_name)) { 884 if (len > sizeof(arhPtr->ar_name)) {
885 tlen = sizeof(arhPtr->ar_name); 885 tlen = sizeof(arhPtr->ar_name);
886 } 886 }
887 887
888 while (fread((char *)arhPtr, sizeof(struct ar_hdr), 1, arch) == 1) { 888 while (fread((char *)arhPtr, sizeof(struct ar_hdr), 1, arch) == 1) {
889 if (strncmp(arhPtr->ar_fmag, ARFMAG, sizeof(arhPtr->ar_fmag) ) != 0) { 889 if (strncmp(arhPtr->ar_fmag, ARFMAG, sizeof(arhPtr->ar_fmag) ) != 0) {
890 /* 890 /*
891 * The header is bogus, so the archive is bad 891 * The header is bogus, so the archive is bad
892 * and there's no way we can recover... 892 * and there's no way we can recover...
893 */ 893 */
894 fclose(arch); 894 fclose(arch);