From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id 3B3A5159C9B for ; Sun, 11 Aug 2024 10:11:20 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 1BAEE2BC134; Sun, 11 Aug 2024 10:11:16 +0000 (UTC) Received: from smtp.gentoo.org (woodpecker.gentoo.org [IPv6:2001:470:ea4a:1:5054:ff:fec7:86e4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id CBC7C2BC10D for ; Sun, 11 Aug 2024 10:11:15 +0000 (UTC) Received: from oystercatcher.gentoo.org (oystercatcher.gentoo.org [148.251.78.52]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id C0A1D34311C for ; Sun, 11 Aug 2024 10:11:14 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id E851E1EEF for ; Sun, 11 Aug 2024 10:11:10 +0000 (UTC) From: "Sam James" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Sam James" Message-ID: <1723371063.6cf0940b8d336eb35a970af2ffc819f55e3ab429.sam@gentoo> Subject: [gentoo-commits] proj/gentoo-functions:master commit in: functions/, / X-VCS-Repository: proj/gentoo-functions X-VCS-Files: functions.sh functions/rc.sh X-VCS-Directories: functions/ / X-VCS-Committer: sam X-VCS-Committer-Name: Sam James X-VCS-Revision: 6cf0940b8d336eb35a970af2ffc819f55e3ab429 X-VCS-Branch: master Date: Sun, 11 Aug 2024 10:11:10 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-Archives-Salt: 433b0e22-e363-42a2-9d08-dc066bf77df1 X-Archives-Hash: fc57f241c3219051b41dd96970c8765e commit: 6cf0940b8d336eb35a970af2ffc819f55e3ab429 Author: Kerin Millar plushkava net> AuthorDate: Sat Aug 10 05:12:15 2024 +0000 Commit: Sam James gentoo org> CommitDate: Sun Aug 11 10:11:03 2024 +0000 URL: https://gitweb.gentoo.org/proj/gentoo-functions.git/commit/?id=6cf0940b Use the -nt and -ot test primaries again rather than depend on GNU find As regards the test(1) utility, the POSIX.1-2024 specification defines the -nt and -ot primaries as standard features. Given that the specification in question was only recently published, this would not normally be an adequate reason for using them in gentoo-functions, in and as of itself. However, I was already aware that the these primaries are commonly implemented and have been so for years. So, I decided to evaluate a number of shells and see how things stand now. Here is a list of the ones that I tested: - ash (busybox 1.36.1) - dash 0.5.12 - bash 5.2.26 - ksh 93u+ - loksh 7.5 - mksh 59c - oksh 7.5 - sh (FreeBSD 14.1) - sh (NetBSD 10.0) - sh (OpenBSD 7.5) - yash 2.56.1 Of these, bash, ksh93, loksh, mksh, oksh, OpenBSD sh and yash appear to conform with the POSIX-1.2024 specification. The remaining four fail to conform in one particular respect, which is as follows. $ touch existent $ set -- existent nonexistent $ [ "$1" -nt "$2" ]; echo "$?" # should be 0 1 $ [ "$2" -ot "$1" ]; echo "$?" # should be 0 1 To address this, I discerned a reasonably straightforward workaround that involves testing both whether the file under consideration exists and whether the variable keeping track of the newest/oldest file has yet been assigned to. As far as I am concerned, the coverage is more than adequate for both primaries to be used by gentoo-functions. As such, this commit adjusts the following three functions so as to do exactly that. - is_older_than() - newest() - oldest() It also removes the following functions, since they are no longer used. - _find0() - _select_by_mtime() With this, GNU findutils is no longer a required runtime dependency. Of course, should a newly introduced feature of gentoo-functions benefit from the presence of findutils in the future, there is no reason that it cannot be brought back in that capacity. Signed-off-by: Kerin Millar plushkava.net> Signed-off-by: Sam James gentoo.org> functions.sh | 157 +++++++++++++++++++++++++++++++++----------------------- functions/rc.sh | 25 +++++++-- 2 files changed, 113 insertions(+), 69 deletions(-) diff --git a/functions.sh b/functions.sh index 641deb6..43ea385 100644 --- a/functions.sh +++ b/functions.sh @@ -1,6 +1,6 @@ # Copyright 1999-2024 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 -# shellcheck shell=sh disable=2209,3043 +# shellcheck shell=sh disable=2209,3013,3043 # This file contains a series of function declarations followed by some # initialisation code. Functions intended for internal use shall be prefixed @@ -294,17 +294,55 @@ is_anyof() # # Considers one or more pathnames and prints the one having the newest -# modification time. If at least one parameter is provided, all parameters shall -# be considered as pathnames to be compared to one another. Otherwise, the -# pathnames to be compared shall be read from the standard input as -# NUL-delimited records. If no pathnames are given, or those specified do not -# exist, the return value shall be greater than 0. In the case that two or more -# pathnames are candidates, the one having the lexicographically greatest value -# shall be selected. Pathnames containing newline characters shall be ignored. +# modification time. If at least one parameter is provided, all parameters +# shall be considered as pathnames to be compared to one another. Otherwise, +# the pathnames to be compared shall be read from the standard input as +# null-terminated records. In the case that two or more pathnames are +# candidates, whichever was first specified shall take precedence over the +# other. If no pathnames are given, or those specified do not exist, the return +# value shall be greater than 0. +# +# Pathnames containing characters shall be handled correctly if +# conveyed as positional parameters. Otherwise, the behaviour for such +# pathnames is unspecified. Users of the function are duly expected to refrain +# from conveying such pathnames for consumption from the standard input; for +# example, by specifying a predicate of ! -path $'*\n*' to the find utility. +# This constraint is expected to be eliminated by a future amendment to the +# function, once support for read -d becomes sufficiently widespread. +# +# The test utility is required to support the -nt primary, per POSIX-1.2024. +# However, measures are in place to to achieve compatibility with shells that +# implement the primary without yet fully adhering to the specification. # newest() { - _select_by_mtime -r "$@" + local path newest + + newest= + if [ "$#" -gt 0 ]; then + for path; do + # The tests within curly braces address a conformance + # issue whereby [ existent -nt nonexistent ] is + # incorrectly false. As of August 2024, busybox ash, + # dash, FreeBSD sh and NetBSD sh are known to be + # non-conforming in this respect. + if { [ ! "${newest}" ] && [ -e "${path}" ]; } || [ "${path}" -nt "${newest}" ]; then + newest=$path + fi + done + test "${newest}" && printf '%s\n' "${newest}" + else + # Support for read -d '' is not yet sufficiently widespread. + tr '\0' '\n' | + { + while IFS= read -r path; do + if { [ ! "${newest}" ] && [ -e "${path}" ]; } || [ "${path}" -nt "${newest}" ]; then + newest=$path + fi + done + test "${newest}" && printf '%s\n' "${newest}" + } + fi } # @@ -330,17 +368,55 @@ get_nprocs() # # Considers one or more pathnames and prints the one having the oldest -# modification time. If at least one parameter is provided, all parameters shall -# be considered as pathnames to be compared to one another. Otherwise, the -# pathnames to be compared shall be read from the standard input as -# NUL-delimited records. If no pathnames are given, or those specified do not -# exist, the return value shall be greater than 0. In the case that two or more -# pathnames are candidates, the one having the lexicographically lesser value -# shall be selected. Pathnames containing newline characters shall be ignored. +# modification time. If at least one parameter is provided, all parameters +# shall be considered as pathnames to be compared to one another. Otherwise, +# the pathnames to be compared shall be read from the standard input as +# null-terminated records. In the case that two or more pathnames are +# candidates, whichever was first specified shall take precedence over the +# other. If no pathnames are given, or those specified do not exist, the return +# value shall be greater than 0. +# +# Pathnames containing characters shall be handled correctly if +# conveyed as positional parameters. Otherwise, the behaviour for such +# pathnames is unspecified. Users of the function are duly expected to refrain +# from conveying such pathnames for consumption from the standard input; for +# example, by specifying a predicate of ! -path $'*\n*' to the find utility. +# This constraint is expected to be eliminated by a future amendment to the +# function, once support for read -d becomes sufficiently widespread. +# +# The test utility is required to support the -ot primary, per POSIX-1.2024. # oldest() { - _select_by_mtime -- "$@" + local path oldest + + oldest= + if [ "$#" -gt 0 ]; then + for path; do + # The specification has [ nonexistent -ot existent ] as + # being true. Such is a nuisance in this case but the + # preceding tests suffice as a workaround. + if [ ! -e "${path}" ]; then + continue + elif [ ! "${oldest}" ] || [ "${path}" -ot "${oldest}" ]; then + oldest=$path + fi + done + test "${oldest}" && printf '%s\n' "${oldest}" + else + # Support for read -d '' is not yet sufficiently widespread. + tr '\0' '\n' | + { + while IFS= read -r path; do + if [ ! -e "${path}" ]; then + continue + elif [ ! "${oldest}" ] || [ "${path}" -ot "${oldest}" ]; then + oldest=$path + fi + done + test "${oldest}" && printf '%s\n' "${oldest}" + } + fi } # @@ -675,34 +751,6 @@ whenceforth() #------------------------------------------------------------------------------# -# -# See the definitions of _select_by_mtime() and is_older_than(). This function -# requires that GNU findutils >=4.9 be installed. -# -_find0() -{ - # Store the name of the GNU find binary, which may be "gfind". - hash gfind 2>/dev/null && genfun_bin_find=gfind || genfun_bin_find=find - - _find0() - { - local opt - - case $1 in - -[HL]) - opt=$1 - shift - set -- "${opt}" -files0-from - "$@" - ;; - *) - set -- -files0-from - "$@" - esac - "${genfun_bin_find}" "$@" - } - - _find0 "$@" -} - # # Determines whether the terminal is a dumb one. # @@ -734,25 +782,6 @@ if [ "${BASH_VERSINFO-0}" -ge 5 ]; then ' fi -# -# See the definitions of oldest() and newest(). -# -_select_by_mtime() -{ - local sort_opt - - sort_opt=$1 - shift - if [ "$#" -gt 0 ]; then - printf '%s\0' "$@" - else - cat - fi \ - | _find0 -maxdepth 0 ! -path "*${genfun_newline}*" -printf '%T+ %p\n' \ - | sort "${sort_opt}" \ - | { IFS= read -r line && printf '%s\n' "${line#* }"; } -} - # # Considers the first parameter as a number of centiseconds and determines # whether fewer have elapsed since the last occasion on which the function was diff --git a/functions/rc.sh b/functions/rc.sh index 0c14035..4eff3c8 100644 --- a/functions/rc.sh +++ b/functions/rc.sh @@ -1,6 +1,6 @@ # Copyright 1999-2024 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 -# shellcheck shell=sh disable=3043 +# shellcheck shell=sh disable=3013,3043 # This file contains alternative implementations for some of the functions and # utilities provided by OpenRC. Please refer to ../functions.sh for coding @@ -205,9 +205,13 @@ get_bootparam() # Takes the first parameter as a reference file/directory then determines # whether any of the following parameters refer to newer files/directories. # +# The test utility is required to support the -nt primary, per POSIX-1.2024. +# However, measures are in place to to achieve compatibility with shells that +# implement the primary without yet fully adhering to the specification. +# is_older_than() { - local ref + local path ref if [ "$#" -eq 0 ]; then warn "is_older_than: too few arguments (got $#, expected at least 1)" @@ -218,9 +222,20 @@ is_older_than() ref= fi shift - { test "$#" -gt 0 && printf '%s\0' "$@"; } \ - | _find0 -L ${ref:+-newermm} ${ref:+"${ref}"} -printf '\n' -quit \ - | read -r _ + for path; do + # The first branch addresses a conformance issue whereby + # [ existent -nt nonexistent ] is incorrectly false. As of + # August 2024, busybox ash, dash, FreeBSD sh and NetBSD sh are + # known to be non-conforming in this respect. + if [ ! "${ref}" ] && [ -e "${path}" ]; then + return + elif [ "${path}" -nt "${ref}" ]; then + return + elif [ -d "${path}" ] && is_older_than "${ref}" "${path}"/*; then + return + fi + done + false } #