1 |
This eclass previously used "find -iname" but it only checked the file |
2 |
case-insensitively and not the directories. There is "find -ipath" but |
3 |
this does not intelligently skip non-matching paths, making it |
4 |
slow. Globbing is used here instead. |
5 |
|
6 |
The : character has always been used to delimit paths given to |
7 |
cdrom_get_cds, which makes sense because : generally isn't allowed on |
8 |
CDs, while whitespace is. Despite that, whitespace was not being |
9 |
handled properly and neither were wildcard characters. Now all special |
10 |
characters are automatically escaped. |
11 |
--- |
12 |
eclass/cdrom.eclass | 48 ++++++++++++++++++++++++++++++++++-------------- |
13 |
1 file changed, 34 insertions(+), 14 deletions(-) |
14 |
|
15 |
diff --git a/eclass/cdrom.eclass b/eclass/cdrom.eclass |
16 |
index 41488d2446c2..de72f15563db 100644 |
17 |
--- a/eclass/cdrom.eclass |
18 |
+++ b/eclass/cdrom.eclass |
19 |
@@ -79,12 +79,13 @@ cdrom_get_cds() { |
20 |
export CDROM_ROOT=${CD_ROOT_1:-${CD_ROOT}} |
21 |
einfo "Found CD #${CDROM_CURRENT_CD} root at ${CDROM_ROOT}" |
22 |
export CDROM_SET=-1 |
23 |
- for f in ${CDROM_CHECK_1//:/ } ; do |
24 |
+ IFS=: |
25 |
+ for f in ${CDROM_CHECK_1} ; do |
26 |
+ unset IFS |
27 |
((++CDROM_SET)) |
28 |
- [[ -e ${CDROM_ROOT}/${f} ]] && break |
29 |
+ export CDROM_MATCH=$(_cdrom_glob_match "${CDROM_ROOT}" "${f}") |
30 |
+ [[ -n ${CDROM_MATCH} ]] && return |
31 |
done |
32 |
- export CDROM_MATCH=${f} |
33 |
- return |
34 |
fi |
35 |
|
36 |
# User didn't help us out so lets make sure they know they can |
37 |
@@ -181,28 +182,24 @@ _cdrom_locate_file_on_cd() { |
38 |
local showedmsg=0 showjolietmsg=0 |
39 |
|
40 |
while [[ -z ${CDROM_ROOT} ]] ; do |
41 |
- local i=0 |
42 |
- local -a cdset=(${*//:/ }) |
43 |
+ local i=0 cdset |
44 |
+ IFS=: read -a cdset <<< "${*}" |
45 |
+ |
46 |
if [[ -n ${CDROM_SET} ]] ; then |
47 |
- cdset=(${cdset[${CDROM_SET}]}) |
48 |
+ cdset=( "${cdset[${CDROM_SET}]}" ) |
49 |
fi |
50 |
|
51 |
while [[ -n ${cdset[${i}]} ]] ; do |
52 |
- local dir=$(dirname ${cdset[${i}]}) |
53 |
- local file=$(basename ${cdset[${i}]}) |
54 |
- |
55 |
local point= node= fs= foo= |
56 |
while read point node fs foo ; do |
57 |
[[ " cd9660 iso9660 udf " != *" ${fs} "* ]] && \ |
58 |
! [[ ${fs} == "subfs" && ",${opts}," == *",fs=cdfss,"* ]] \ |
59 |
&& continue |
60 |
point=${point//\040/ } |
61 |
- [[ ! -d ${point}/${dir} ]] && continue |
62 |
- [[ -z $(find "${point}/${dir}" -maxdepth 1 -iname "${file}") ]] \ |
63 |
- && continue |
64 |
+ export CDROM_MATCH=$(_cdrom_glob_match "${point}" "${cdset[${i}]}") |
65 |
+ [[ -z ${CDROM_MATCH} ]] && continue |
66 |
export CDROM_ROOT=${point} |
67 |
export CDROM_SET=${i} |
68 |
- export CDROM_MATCH=${cdset[${i}]} |
69 |
return |
70 |
done <<< "$(get_mounts)" |
71 |
|
72 |
@@ -243,4 +240,27 @@ _cdrom_locate_file_on_cd() { |
73 |
done |
74 |
} |
75 |
|
76 |
+# @FUNCTION: _cdrom_glob_match |
77 |
+# @USAGE: <root directory> <path> |
78 |
+# @INTERNAL |
79 |
+# @DESCRIPTION: |
80 |
+# Locates the given path ($2) within the given root directory ($1) |
81 |
+# case-insensitively and returns the first actual matching path. This |
82 |
+# eclass previously used "find -iname" but it only checked the file |
83 |
+# case-insensitively and not the directories. There is "find -ipath" but |
84 |
+# this does not intelligently skip non-matching paths, making it |
85 |
+# slow. Case-insensitive matching can only be applied to patterns so |
86 |
+# extended globbing is used to turn regular strings into patterns. All |
87 |
+# special characters are escaped so don't worry about breaking this. The |
88 |
+# first person to make this work without an eval wins a cookie. |
89 |
+_cdrom_glob_match() { |
90 |
+ local p=\?\($(sed -e 's:[^A-Za-z0-9/]:\\\0:g' -e 's:/:)/?(:g' <<< "$2" || die)\) |
91 |
+ ( |
92 |
+ cd "$1" 2>/dev/null || return |
93 |
+ shopt -s extglob nocaseglob nullglob || die |
94 |
+ eval "ARRAY=( ${p} )" |
95 |
+ echo ${ARRAY[0]} |
96 |
+ ) |
97 |
+} |
98 |
+ |
99 |
fi |
100 |
-- |
101 |
2.11.0 |