Skip to content

Commit 8f9f3d8

Browse files
committed
Improve quoting performance
If features or users have added a large number of files or directories to pack into an image, then quoting a very long string takes too much time. Quoting variables is necessary for the correct processing of paths with spaces. The problem is that if we need to process a very large string, character-by-character parsing takes a long time. It so happens that there is no quick way to parse a string character by character in the POSIX shell. But in bash, such a way exists. Since we always use bash, the quoting process can be significantly accelerated by simply reading a single character in a string. Before: [ 2.55ms ] Config file: /etc/initrd.mk [ 5.3m ] Used features: runtime add-modules add-udev-rules cleanup compress depmod-image gpu-drm locales plymouth rdshell rootfs system-glibc ucode [ 5.3m ] Unpacked size: 36M [ 5.3m ] Image size: 16M [ 5.3m ] Image is saved as /boot/initrd-6.16.0.img After: [ 2.47ms ] Config file: /etc/initrd.mk [ 9.43s ] Used features: runtime add-modules add-udev-rules cleanup compress depmod-image gpu-drm locales plymouth rdshell rootfs system-glibc ucode [ 9.43s ] Unpacked size: 36M [ 9.44s ] Image size: 16M [ 9.49s ] Image is saved as /boot/initrd-6.16.0.img Signed-off-by: Alexey Gladkov <[email protected]>
1 parent 226e74e commit 8f9f3d8

File tree

1 file changed

+83
-5
lines changed

1 file changed

+83
-5
lines changed

tools/create-rootfs

Lines changed: 83 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,84 @@ DIRS=()
1515
LIB_PATHS=()
1616
BIN_PATHS=()
1717

18+
quote_bash_args()
19+
{
20+
### This is an internal function to avoid the use of ugly namespace.
21+
__quote_bash_args_toggle() {
22+
### toggle $1 value
23+
eval [ -n \"\$$1\" ] && eval "$1=" || eval "$1=\$$2"
24+
}
25+
__quote_bash_args() {
26+
local i=0 c=''
27+
### backslash/double/single quote mode
28+
local bq='' dq='' sq=''
29+
30+
__quote_bash_args_out=''
31+
32+
for (( i=0; i<${#1}; i++ )); do
33+
c="${1:i:1}"
34+
35+
case "$c" in
36+
\")
37+
### toggle double quote mode unless
38+
### in backslash or single quote mode
39+
[ -n "$bq$sq" ] || __quote_bash_args_toggle dq c
40+
;;
41+
\')
42+
### toggle single quote mode unless
43+
### in backslash or double quote mode
44+
[ -n "$bq$dq" ] || __quote_bash_args_toggle sq c
45+
;;
46+
\$|\`)
47+
### quote special character unless
48+
### in backslash or single quote mode
49+
[ -n "$bq$sq" ] || bq=\\
50+
;;
51+
\\)
52+
### toggle backslash quote mode unless
53+
### in single quote mode
54+
if [ -z "$sq" ]; then
55+
if [ -z "$bq" ]; then
56+
### enter backslash quote mode
57+
bq=\\
58+
continue
59+
else
60+
### leave backslash quote mode
61+
__quote_bash_args_out+="\\"
62+
bq=
63+
fi
64+
fi
65+
;;
66+
[!A-Za-z0-9_\ \ ])
67+
### quote non-regular character unless
68+
### in any quote mode
69+
[ -n "$bq$dq$sq" ] || bq=\\
70+
;;
71+
esac
72+
__quote_bash_args_out+="$bq$c"
73+
### leave backslash quote mode if any
74+
bq=
75+
done
76+
77+
[ -z "$bq$dq$sq" ] ||
78+
{ message "unmatched character ($bq$dq$sq) found"; return 1; }
79+
}
80+
local __quote_bash_args_rc=0
81+
82+
if [[ "$2" =~ [\"\'\$\`\\\\] ]]; then
83+
local __quote_bash_args_out=''
84+
__quote_bash_args "$2" || __quote_bash_args_rc=1
85+
eval "$1=\"\$__quote_bash_args_out\""
86+
else
87+
eval "$1=\"\$2\""
88+
fi
89+
90+
### Remove internal functions from user namespace.
91+
unset -f __quote_bash_args __quote_bash_args_toggle
92+
93+
return $__quote_bash_args_rc
94+
}
95+
1896
in_runtimedir()
1997
{
2098
local f="${1#$LOCALBUILDDIR}"
@@ -34,7 +112,7 @@ append_progs()
34112
[ -n "$1" ] ||
35113
return 0
36114

37-
quote_shell_args args "$1"
115+
quote_bash_args args "$1"
38116
eval "set -- $args"
39117

40118
for n; do
@@ -113,7 +191,7 @@ append_libs()
113191
[ -n "$1" ] ||
114192
return 0
115193

116-
quote_shell_args args "$1"
194+
quote_bash_args args "$1"
117195
eval "set -- $args"
118196

119197
for n; do
@@ -158,7 +236,7 @@ append_libs()
158236
get_bin_paths
159237
get_lib_paths
160238

161-
quote_shell_args args "${PUT_FEATURE_DIRS-} $PUT_DIRS"
239+
quote_bash_args args "${PUT_FEATURE_DIRS-} $PUT_DIRS"
162240
eval "set -- $args"
163241

164242
for n in \
@@ -184,7 +262,7 @@ append_libs required "${PUT_FEATURE_LIBS-}"
184262
append_libs optional "${PUT_FEATURE_OPTIONAL_LIBS-}"
185263

186264
if [ -n "${PUT_FEATURE_PROGS_WILDCARD-}" ]; then
187-
quote_shell_args args "$PUT_FEATURE_PROGS_WILDCARD"
265+
quote_bash_args args "$PUT_FEATURE_PROGS_WILDCARD"
188266
eval "set -- $args"
189267

190268
while read -d: -r n; do
@@ -209,7 +287,7 @@ if [ -n "${PUT_FEATURE_PROGS_WILDCARD-}" ]; then
209287
fi
210288

211289
if [ -n "${PUT_FEATURE_FILES-}" ] || [ -n "${PUT_FILES-}" ]; then
212-
quote_shell_args args "${PUT_FEATURE_FILES-} ${PUT_FILES-}"
290+
quote_bash_args args "${PUT_FEATURE_FILES-} ${PUT_FILES-}"
213291
eval "set -- $args"
214292

215293
for n in "$@"; do

0 commit comments

Comments
 (0)