Module Name: src Committed By: rillig Date: Fri Aug 20 06:36:10 UTC 2021
Modified Files: src/tests/usr.bin/mkdep: Makefile t_findcc.sh src/usr.bin/mkdep: findcc.c Log Message: mkdep: avoid memory allocation in findcc This change takes the idea of handling strings as pairs in the form (start, len) by Robert Elz from https://mail-index.netbsd.org/source-changes-d/2021/08/20/msg013427.html and expands it by avoiding one more memory allocation, for iterating the PATH environment variable. No functional change. To generate a diff of this commit: cvs rdiff -u -r1.2 -r1.3 src/tests/usr.bin/mkdep/Makefile \ src/tests/usr.bin/mkdep/t_findcc.sh cvs rdiff -u -r1.9 -r1.10 src/usr.bin/mkdep/findcc.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/tests/usr.bin/mkdep/Makefile diff -u src/tests/usr.bin/mkdep/Makefile:1.2 src/tests/usr.bin/mkdep/Makefile:1.3 --- src/tests/usr.bin/mkdep/Makefile:1.2 Wed Aug 11 20:42:26 2021 +++ src/tests/usr.bin/mkdep/Makefile Fri Aug 20 06:36:10 2021 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.2 2021/08/11 20:42:26 rillig Exp $ +# $NetBSD: Makefile,v 1.3 2021/08/20 06:36:10 rillig Exp $ .include <bsd.own.mk> @@ -13,5 +13,6 @@ PROG= h_findcc SRCS= h_findcc.c findcc.c CPPFLAGS+= -I${NETBSDSRCDIR}/usr.bin/mkdep MAN.h_findcc= # none +WARNS= 6 .include <bsd.test.mk> Index: src/tests/usr.bin/mkdep/t_findcc.sh diff -u src/tests/usr.bin/mkdep/t_findcc.sh:1.2 src/tests/usr.bin/mkdep/t_findcc.sh:1.3 --- src/tests/usr.bin/mkdep/t_findcc.sh:1.2 Fri Aug 20 05:45:19 2021 +++ src/tests/usr.bin/mkdep/t_findcc.sh Fri Aug 20 06:36:10 2021 @@ -1,4 +1,4 @@ -# $NetBSD: t_findcc.sh,v 1.2 2021/08/20 05:45:19 rillig Exp $ +# $NetBSD: t_findcc.sh,v 1.3 2021/08/20 06:36:10 rillig Exp $ # # Copyright (c) 2021 The NetBSD Foundation, Inc. # All rights reserved. @@ -51,6 +51,31 @@ base_found_body() { "$(atf_get_srcdir)"/h_findcc 'echo' } +# A plain program name is searched in the PATH and, in this example, it is +# found in '/bin', which comes second in the PATH. +# +atf_test_case base_found_second +base_found_second_body() { + atf_check -o "inline:/bin/echo$n" \ + env -i PATH='/nonexistent:/bin' \ + "$(atf_get_srcdir)"/h_findcc 'echo' +} + +# A plain program name is searched in the PATH and, in this example, it is +# found in './bin', a relative path in the PATH, which is rather unusual in +# practice. +# +atf_test_case base_found_reldir +base_found_reldir_body() { + mkdir bin + echo '#! /bin/sh' > 'bin/reldir-echo' + chmod +x 'bin/reldir-echo' + + atf_check -o "inline:bin/reldir-echo$n" \ + env -i PATH='/nonexistent:bin' \ + "$(atf_get_srcdir)"/h_findcc 'reldir-echo' +} + # The C compiler can be specified as a program with one or more arguments. # If the program name is a plain name without any slash, the argument is # discarded. @@ -143,6 +168,8 @@ abs_arg_found_body() { atf_init_test_cases() { atf_add_test_case base_not_found atf_add_test_case base_found + atf_add_test_case base_found_second + atf_add_test_case base_found_reldir atf_add_test_case base_arg_found atf_add_test_case rel_not_found Index: src/usr.bin/mkdep/findcc.c diff -u src/usr.bin/mkdep/findcc.c:1.9 src/usr.bin/mkdep/findcc.c:1.10 --- src/usr.bin/mkdep/findcc.c:1.9 Fri Aug 20 05:45:19 2021 +++ src/usr.bin/mkdep/findcc.c Fri Aug 20 06:36:10 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: findcc.c,v 1.9 2021/08/20 05:45:19 rillig Exp $ */ +/* $NetBSD: findcc.c,v 1.10 2021/08/20 06:36:10 rillig Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ #if !defined(lint) __COPYRIGHT("@(#) Copyright (c) 1999 The NetBSD Foundation, Inc.\ All rights reserved."); -__RCSID("$NetBSD: findcc.c,v 1.9 2021/08/20 05:45:19 rillig Exp $"); +__RCSID("$NetBSD: findcc.c,v 1.10 2021/08/20 06:36:10 rillig Exp $"); #endif /* not lint */ #include <sys/param.h> @@ -49,47 +49,40 @@ __RCSID("$NetBSD: findcc.c,v 1.9 2021/08 #include "findcc.h" char * -findcc(const char *cc_command) +findcc(const char *progname) { - char *progname, *path, *dir, *next; - char buffer[MAXPATHLEN]; - - if ((progname = strdup(cc_command)) == NULL) - return NULL; - - if ((next = strchr(progname, ' ')) != NULL) - *next = '\0'; - - if (strchr(progname, '/') != NULL) { - if (access(progname, X_OK) == 0) - return progname; - free(progname); + char *cc; + const char *path, *dir; + char buffer[MAXPATHLEN]; + size_t progname_len, dir_len; + + progname_len = strcspn(progname, " "); + + if (memchr(progname, '/', progname_len) != NULL) { + if ((cc = strndup(progname, progname_len)) == NULL) + return NULL; + if (access(cc, X_OK) == 0) + return cc; + free(cc); return NULL; } - if (((path = getenv("PATH")) == NULL) || - ((path = strdup(path)) == NULL)) { - free(progname); + if ((path = getenv("PATH")) == NULL) return NULL; - } - dir = path; - while (dir != NULL) { - if ((next = strchr(dir, ':')) != NULL) - *next++ = '\0'; - - if (snprintf(buffer, sizeof(buffer), - "%s/%s", dir, progname) < (int)sizeof(buffer)) { - if (access(buffer, X_OK) == 0) { - free(path); - free(progname); - return strdup(buffer); - } - } - dir = next; + for (dir = path; *dir != '\0'; ) { + dir_len = strcspn(dir, ":"); + + if ((size_t)snprintf(buffer, sizeof(buffer), "%.*s/%.*s", + (int)dir_len, dir, (int)progname_len, progname) + < sizeof(buffer) + && access(buffer, X_OK) == 0) + return strdup(buffer); + + dir += dir_len; + if (*dir == ':') + dir++; } - free(path); - free(progname); return NULL; }