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.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id A58F5139694 for ; Mon, 17 Apr 2017 21:58:04 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id B66D121C121; Mon, 17 Apr 2017 21:54:39 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id 6576021C10A for ; Mon, 17 Apr 2017 21:54:34 +0000 (UTC) Received: from symphony.aura-online.co.uk (154.189.187.81.in-addr.arpa [81.187.189.154]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: chewi) by smtp.gentoo.org (Postfix) with ESMTPSA id C6A5C340988; Mon, 17 Apr 2017 21:54:32 +0000 (UTC) From: James Le Cuirot To: gentoo-dev Cc: James Le Cuirot Subject: [gentoo-dev] [PATCH 01/14] cdrom.eclass: Detect case-insensitively and handle special characters Date: Mon, 17 Apr 2017 22:53:46 +0100 Message-Id: <20170417215359.30641-2-chewi@gentoo.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170417215359.30641-1-chewi@gentoo.org> References: <20170417215359.30641-1-chewi@gentoo.org> Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-dev@lists.gentoo.org Reply-to: gentoo-dev@lists.gentoo.org X-Archives-Salt: 64b1a4b7-27c7-48bb-a4cd-1588b8f5218f X-Archives-Hash: 83730dc3d376db531e8c6619e7443fd3 This eclass previously used "find -iname" but it only checked the file case-insensitively and not the directories. There is "find -ipath" but this does not intelligently skip non-matching paths, making it slow. Globbing is used here instead. The : character has always been used to delimit paths given to cdrom_get_cds, which makes sense because : generally isn't allowed on CDs, while whitespace is. Despite that, whitespace was not being handled properly and neither were wildcard characters. Now all special characters are automatically escaped. --- eclass/cdrom.eclass | 48 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/eclass/cdrom.eclass b/eclass/cdrom.eclass index 41488d2446c2..de72f15563db 100644 --- a/eclass/cdrom.eclass +++ b/eclass/cdrom.eclass @@ -79,12 +79,13 @@ cdrom_get_cds() { export CDROM_ROOT=${CD_ROOT_1:-${CD_ROOT}} einfo "Found CD #${CDROM_CURRENT_CD} root at ${CDROM_ROOT}" export CDROM_SET=-1 - for f in ${CDROM_CHECK_1//:/ } ; do + IFS=: + for f in ${CDROM_CHECK_1} ; do + unset IFS ((++CDROM_SET)) - [[ -e ${CDROM_ROOT}/${f} ]] && break + export CDROM_MATCH=$(_cdrom_glob_match "${CDROM_ROOT}" "${f}") + [[ -n ${CDROM_MATCH} ]] && return done - export CDROM_MATCH=${f} - return fi # User didn't help us out so lets make sure they know they can @@ -181,28 +182,24 @@ _cdrom_locate_file_on_cd() { local showedmsg=0 showjolietmsg=0 while [[ -z ${CDROM_ROOT} ]] ; do - local i=0 - local -a cdset=(${*//:/ }) + local i=0 cdset + IFS=: read -a cdset <<< "${*}" + if [[ -n ${CDROM_SET} ]] ; then - cdset=(${cdset[${CDROM_SET}]}) + cdset=( "${cdset[${CDROM_SET}]}" ) fi while [[ -n ${cdset[${i}]} ]] ; do - local dir=$(dirname ${cdset[${i}]}) - local file=$(basename ${cdset[${i}]}) - local point= node= fs= foo= while read point node fs foo ; do [[ " cd9660 iso9660 udf " != *" ${fs} "* ]] && \ ! [[ ${fs} == "subfs" && ",${opts}," == *",fs=cdfss,"* ]] \ && continue point=${point//\040/ } - [[ ! -d ${point}/${dir} ]] && continue - [[ -z $(find "${point}/${dir}" -maxdepth 1 -iname "${file}") ]] \ - && continue + export CDROM_MATCH=$(_cdrom_glob_match "${point}" "${cdset[${i}]}") + [[ -z ${CDROM_MATCH} ]] && continue export CDROM_ROOT=${point} export CDROM_SET=${i} - export CDROM_MATCH=${cdset[${i}]} return done <<< "$(get_mounts)" @@ -243,4 +240,27 @@ _cdrom_locate_file_on_cd() { done } +# @FUNCTION: _cdrom_glob_match +# @USAGE: +# @INTERNAL +# @DESCRIPTION: +# Locates the given path ($2) within the given root directory ($1) +# case-insensitively and returns the first actual matching path. This +# eclass previously used "find -iname" but it only checked the file +# case-insensitively and not the directories. There is "find -ipath" but +# this does not intelligently skip non-matching paths, making it +# slow. Case-insensitive matching can only be applied to patterns so +# extended globbing is used to turn regular strings into patterns. All +# special characters are escaped so don't worry about breaking this. The +# first person to make this work without an eval wins a cookie. +_cdrom_glob_match() { + local p=\?\($(sed -e 's:[^A-Za-z0-9/]:\\\0:g' -e 's:/:)/?(:g' <<< "$2" || die)\) + ( + cd "$1" 2>/dev/null || return + shopt -s extglob nocaseglob nullglob || die + eval "ARRAY=( ${p} )" + echo ${ARRAY[0]} + ) +} + fi -- 2.11.0