Mon Mar 11 17:12:53 2024 UTC (69d)
Pull up following revision(s) (requested by riastradh in ticket #621):

	usr.sbin/certctl/certctl.sh: revision 1.6

certctl(8): Avoid basename(1).

Saves some time running subprocesses.  Since this is only used for
non-directories (i.e., there's never trailing / on the inputs), it
suffices to delete the longest prefix matching glob `*/' with shell
parameter expansion -- much cheaper than spawning a subprocess.

Shaves off about 1/3 of the time spent in `certctl list' on an
aarch64 VM in qemu.

PR bin/57993


(martin)
diff -r1.4.2.3 -r1.4.2.4 src/usr.sbin/certctl/certctl.sh

cvs diff -r1.4.2.3 -r1.4.2.4 src/usr.sbin/certctl/certctl.sh (expand / switch to unified diff)

--- src/usr.sbin/certctl/certctl.sh 2023/09/06 15:04:33 1.4.2.3
+++ src/usr.sbin/certctl/certctl.sh 2024/03/11 17:12:53 1.4.2.4
@@ -1,16 +1,16 @@ @@ -1,16 +1,16 @@
1#!/bin/sh 1#!/bin/sh
2 2
3# $NetBSD: certctl.sh,v 1.4.2.3 2023/09/06 15:04:33 martin Exp $ 3# $NetBSD: certctl.sh,v 1.4.2.4 2024/03/11 17:12:53 martin Exp $
4# 4#
5# Copyright (c) 2023 The NetBSD Foundation, Inc. 5# Copyright (c) 2023 The NetBSD Foundation, Inc.
6# All rights reserved. 6# All rights reserved.
7# 7#
8# Redistribution and use in source and binary forms, with or without 8# Redistribution and use in source and binary forms, with or without
9# modification, are permitted provided that the following conditions 9# modification, are permitted provided that the following conditions
10# are met: 10# are met:
11# 1. Redistributions of source code must retain the above copyright 11# 1. Redistributions of source code must retain the above copyright
12# notice, this list of conditions and the following disclaimer. 12# notice, this list of conditions and the following disclaimer.
13# 2. Redistributions in binary form must reproduce the above copyright 13# 2. Redistributions in binary form must reproduce the above copyright
14# notice, this list of conditions and the following disclaimer in the 14# notice, this list of conditions and the following disclaimer in the
15# documentation and/or other materials provided with the distribution. 15# documentation and/or other materials provided with the distribution.
16# 16#
@@ -20,27 +20,27 @@ @@ -20,27 +20,27 @@
20# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27# POSSIBILITY OF SUCH DAMAGE. 27# POSSIBILITY OF SUCH DAMAGE.
28# 28#
29 29
30set -o pipefail 30set -o pipefail
31set -Ceu 31set -Ceu
32 32
33progname=$(basename -- "$0") 33progname=${0##*/}
34 34
35### Options and arguments 35### Options and arguments
36 36
37usage() 37usage()
38{ 38{
39 exec >&2 39 exec >&2
40 printf 'Usage: %s %s\n' \ 40 printf 'Usage: %s %s\n' \
41 "$progname" \ 41 "$progname" \
42 "[-nv] [-C <config>] [-c <certsdir>] [-u <untrusted>]" 42 "[-nv] [-C <config>] [-c <certsdir>] [-u <untrusted>]"
43 printf ' <cmd> <args>...\n' 43 printf ' <cmd> <args>...\n'
44 printf ' %s list\n' "$progname" 44 printf ' %s list\n' "$progname"
45 printf ' %s rehash\n' "$progname" 45 printf ' %s rehash\n' "$progname"
46 printf ' %s trust <cert>\n' "$progname" 46 printf ' %s trust <cert>\n' "$progname"
@@ -266,28 +266,27 @@ list_default_trusted() @@ -266,28 +266,27 @@ list_default_trusted()
266 # or 266 # or
267 # (b) the shell glob failed to match, 267 # (b) the shell glob failed to match,
268 # so ignore it and move on. 268 # so ignore it and move on.
269 if [ ! -e "$cert" ]; then 269 if [ ! -e "$cert" ]; then
270 if [ -h "$cert" ]; then 270 if [ -h "$cert" ]; then
271 error "broken symlink: $vcert" 271 error "broken symlink: $vcert"
272 status=1 272 status=1
273 fi 273 fi
274 continue 274 continue
275 fi 275 fi
276 276
277 # Print the vis-encoded absolute path to the 277 # Print the vis-encoded absolute path to the
278 # certificate and base name on a single line. 278 # certificate and base name on a single line.
279 vbase=$(basename -- "$vcert.") 279 vbase=${vcert##*/}
280 vbase=${vbase%.} 
281 printf '%s %s\n' "$vcert" "$vbase" 280 printf '%s %s\n' "$vcert" "$vbase"
282 done 281 done
283 done 282 done
284} 283}
285 284
286# list_distrusted 285# list_distrusted
287# 286#
288# List the vis-encoded certificate paths and their base names, 287# List the vis-encoded certificate paths and their base names,
289# separated by a space, for the certificates that have been 288# separated by a space, for the certificates that have been
290# distrusted by the user. 289# distrusted by the user.
291# 290#
292# No order guaranteed; caller must sort. 291# No order guaranteed; caller must sort.
293# 292#
@@ -329,28 +328,27 @@ list_distrusted() @@ -329,28 +328,27 @@ list_distrusted()
329 case $cert in 328 case $cert in
330 /*) 329 /*)
331 ;; 330 ;;
332 *) 331 *)
333 vlink=$(printf '%s' "$link" | vis -M) 332 vlink=$(printf '%s' "$link" | vis -M)
334 vcert=$(printf '%s' "$cert" | vis -M) 333 vcert=$(printf '%s' "$cert" | vis -M)
335 error "distrusted relative symlink: $vlink -> $vcert" 334 error "distrusted relative symlink: $vlink -> $vcert"
336 ;; 335 ;;
337 esac 336 esac
338 337
339 # Print the vis-encoded absolute path to the 338 # Print the vis-encoded absolute path to the
340 # certificate and base name on a single line. 339 # certificate and base name on a single line.
341 vcert=$(printf '%s' "$cert" | vis -M) 340 vcert=$(printf '%s' "$cert" | vis -M)
342 vbase=$(basename -- "$vcert.") 341 vbase=${vcert##*/}
343 vbase=${vbase%.} 
344 printf '%s %s\n' "$vcert" "$vbase" 342 printf '%s %s\n' "$vcert" "$vbase"
345 done 343 done
346 344
347 return $status 345 return $status
348} 346}
349 347
350# list_trusted 348# list_trusted
351# 349#
352# List the trusted certificates, excluding the distrusted one, as 350# List the trusted certificates, excluding the distrusted one, as
353# one vis(3) line per certificate. Reject duplicate base names, 351# one vis(3) line per certificate. Reject duplicate base names,
354# since we will be creating symlinks to the same base names in 352# since we will be creating symlinks to the same base names in
355# the certsdir. Sorted lexicographically by vis-encoding. 353# the certsdir. Sorted lexicographically by vis-encoding.
356# 354#
@@ -552,39 +550,38 @@ cmd_trust() @@ -552,39 +550,38 @@ cmd_trust()
552 550
553 # XXX Accept base name. 551 # XXX Accept base name.
554 552
555 # vis the certificate path for terminal-safe error messages. 553 # vis the certificate path for terminal-safe error messages.
556 vcert=$(printf '%s' "$cert" | vis -M) 554 vcert=$(printf '%s' "$cert" | vis -M)
557 555
558 # Verify the certificate actually exists. 556 # Verify the certificate actually exists.
559 if [ ! -f "$cert" ]; then 557 if [ ! -f "$cert" ]; then
560 error "no such certificate: $vcert" 558 error "no such certificate: $vcert"
561 return 1 559 return 1
562 fi 560 fi
563 561
564 # Verify we currently distrust a certificate by this base name. 562 # Verify we currently distrust a certificate by this base name.
565 certbase=$(basename -- "$cert.") 563 certbase=${cert##*/}
566 certbase=${certbase%.} 
567 if [ ! -h "$distrustdir/$certbase" ]; then 564 if [ ! -h "$distrustdir/$certbase" ]; then
568 error "not currently distrusted: $vcert" 565 error "not currently distrusted: $vcert"
569 return 1 566 return 1
570 fi 567 fi
571 568
572 # Verify the certificate we distrust by this base name is the 569 # Verify the certificate we distrust by this base name is the
573 # same one. 570 # same one.
574 target=$(readlink -n -- "$distrustdir/$certbase" && printf .) 571 target=$(readlink -n -- "$distrustdir/$certbase" && printf .)
575 target=${target%.} 572 target=${target%.}
576 if [ "$cert" != "$target" ]; then 573 if [ "$cert" != "$target" ]; then
577 vcertbase=$(basename -- "$vcert") 574 vcertbase=${vcert##*/}
578 error "distrusted $vcertbase does not point to $vcert" 575 error "distrusted $vcertbase does not point to $vcert"
579 return 1 576 return 1
580 fi 577 fi
581 578
582 # Remove the link from the distrusted directory, and rehash -- 579 # Remove the link from the distrusted directory, and rehash --
583 # quietly, so verbose output emphasizes the distrust part and 580 # quietly, so verbose output emphasizes the distrust part and
584 # not the whole certificate set. 581 # not the whole certificate set.
585 run rm -- "$distrustdir/$certbase" 582 run rm -- "$distrustdir/$certbase"
586 $vflag && echo '# rehash' 583 $vflag && echo '# rehash'
587 vflag=false 584 vflag=false
588 rehash 585 rehash
589} 586}
590 587
@@ -607,28 +604,27 @@ cmd_untrust() @@ -607,28 +604,27 @@ cmd_untrust()
607 vcert=$(printf '%s' "$cert" | vis -M) 604 vcert=$(printf '%s' "$cert" | vis -M)
608 605
609 # Verify the certificate actually exists. Otherwise, you might 606 # Verify the certificate actually exists. Otherwise, you might
610 # fail to distrust a certificate you intended to distrust, 607 # fail to distrust a certificate you intended to distrust,
611 # e.g. if you made a typo in its path. 608 # e.g. if you made a typo in its path.
612 if [ ! -f "$cert" ]; then 609 if [ ! -f "$cert" ]; then
613 error "no such certificate: $vcert" 610 error "no such certificate: $vcert"
614 return 1 611 return 1
615 fi 612 fi
616 613
617 # Check whether this certificate is already distrusted. 614 # Check whether this certificate is already distrusted.
618 # - If the same base name points to the same path, stop here. 615 # - If the same base name points to the same path, stop here.
619 # - Otherwise, fail noisily. 616 # - Otherwise, fail noisily.
620 certbase=$(basename "$cert.") 617 certbase=${cert##*/}
621 certbase=${certbase%.} 
622 if [ -h "$distrustdir/$certbase" ]; then 618 if [ -h "$distrustdir/$certbase" ]; then
623 target=$(readlink -n -- "$distrustdir/$certbase" && printf .) 619 target=$(readlink -n -- "$distrustdir/$certbase" && printf .)
624 target=${target%.} 620 target=${target%.}
625 if [ "$target" = "$cert" ]; then 621 if [ "$target" = "$cert" ]; then
626 $vflag && echo '# already distrusted' 622 $vflag && echo '# already distrusted'
627 return 623 return
628 fi 624 fi
629 vcertbase=$(printf '%s' "$certbase" | vis -M) 625 vcertbase=$(printf '%s' "$certbase" | vis -M)
630 vtarget=$(printf '%s' "$target" | vis -M) 626 vtarget=$(printf '%s' "$target" | vis -M)
631 error "distrusted $vcertbase at different path $vtarget" 627 error "distrusted $vcertbase at different path $vtarget"
632 return 1 628 return 1
633 fi 629 fi
634 630