Fix %{uncompress:...} double-expanding arguments + other miscellania

%{uncompress:...} is fairly complicated as far as builtin macros go:
it needs to first expand its argument to discover the actual file
its supposed to look at, then determine whether the file exists and
what sort of compression to use, then determine the macro to use
for decompressing that kind of file, expand said macro and finally
catenate the expanded argument to the lot. That's a lot of goo to
do inline doFoo(), so refactor it into a separate function.

Up to now the last step was implemented by re-expanding the argument
too, which makes it impossible to reliably handle paths with percent
signs. Just expand the command, and catenate the argument as deity
intended.

Additionally make behavior with empty argument consistent with other
builtins: %{uncompress:} expands to nothing instead of printing out
an error message with an empty filename.
This commit is contained in:
Panu Matilainen 2020-02-10 12:31:21 +02:00
parent 94623389ba
commit 227cddca88
2 changed files with 80 additions and 45 deletions

View File

@ -144,6 +144,8 @@ static void doSP(MacroBuf mb, int chkexist, int negate,
const char * f, size_t fn, const char * g, size_t gn);
static void doTrace(MacroBuf mb, int chkexist, int negate,
const char * f, size_t fn, const char * g, size_t gn);
static void doUncompress(MacroBuf mb, int chkexist, int negate,
const char * f, size_t fn, const char * g, size_t gn);
static const char * doDef(MacroBuf mb, const char * se);
static const char * doGlobal(MacroBuf mb, const char * se);
@ -577,7 +579,7 @@ static struct builtins_s {
{ STR_AND_LEN("suffix"), doFoo, NULL, 1 },
{ STR_AND_LEN("trace"), doTrace, NULL, 0 },
{ STR_AND_LEN("u2p"), doFoo, NULL, 1 },
{ STR_AND_LEN("uncompress"),doFoo, NULL, 1 },
{ STR_AND_LEN("uncompress"),doUncompress, NULL, 1 },
{ STR_AND_LEN("undefine"), NULL, doUndefine, 0 },
{ STR_AND_LEN("url2path"), doFoo, NULL, 1 },
{ STR_AND_LEN("verbose"), doFoo, NULL, 1 },
@ -1074,6 +1076,65 @@ doSP(MacroBuf mb, int chkexist, int negate,
free(buf);
}
static void doUncompress(MacroBuf mb, int chkexist, int negate,
const char * f, size_t fn, const char * g, size_t gn)
{
rpmCompressedMagic compressed = COMPRESSED_OTHER;
char *b, *be, *buf = NULL;
int c;
if (gn) {
expandThis(mb, g, gn, &buf);
for (b = buf; (c = *b) && isblank(c);)
b++;
for (be = b; (c = *be) && !isblank(c);)
be++;
*be++ = '\0';
}
if (gn == 0 || *b == '\0')
goto exit;
if (rpmFileIsCompressed(b, &compressed))
mb->error = 1;
switch (compressed) {
default:
case COMPRESSED_NOT:
expandMacro(mb, "%__cat ", 0);
break;
case COMPRESSED_OTHER:
expandMacro(mb, "%__gzip -dc ", 0);
break;
case COMPRESSED_BZIP2:
expandMacro(mb, "%__bzip2 -dc ", 0);
break;
case COMPRESSED_ZIP:
expandMacro(mb, "%__unzip ", 0);
break;
case COMPRESSED_LZMA:
case COMPRESSED_XZ:
expandMacro(mb, "%__xz -dc ", 0);
break;
case COMPRESSED_LZIP:
expandMacro(mb, "%__lzip -dc ", 0);
break;
case COMPRESSED_LRZIP:
expandMacro(mb, "%__lrzip -dqo- ", 0);
break;
case COMPRESSED_7ZIP:
expandMacro(mb, "%__7zip x ", 0);
break;
case COMPRESSED_ZSTD:
expandMacro(mb, "%__zstd -dc ", 0);
break;
}
mbAppendStr(mb, buf);
exit:
free(buf);
}
/**
* Execute macro primitives.
* @param mb macro expansion state
@ -1089,8 +1150,7 @@ doFoo(MacroBuf mb, int chkexist, int negate, const char * f, size_t fn,
const char * g, size_t gn)
{
char *buf = NULL;
char *b = NULL, *be;
int c;
char *b = NULL;
int verbose = (rpmIsVerbose() != 0);
int expand = (g != NULL && gn > 0);
int expandagain = 1;
@ -1158,47 +1218,6 @@ doFoo(MacroBuf mb, int chkexist, int negate, const char * f, size_t fn,
} else if (STREQ("url2path", f, fn) || STREQ("u2p", f, fn)) {
(void)urlPath(buf, (const char **)&b);
if (*b == '\0') b = "/";
} else if (STREQ("uncompress", f, fn)) {
rpmCompressedMagic compressed = COMPRESSED_OTHER;
for (b = buf; (c = *b) && isblank(c);)
b++;
for (be = b; (c = *be) && !isblank(c);)
be++;
*be++ = '\0';
if (rpmFileIsCompressed(b, &compressed))
mb->error = 1;
switch (compressed) {
default:
case COMPRESSED_NOT:
sprintf(be, "%%__cat %s", b);
break;
case COMPRESSED_OTHER:
sprintf(be, "%%__gzip -dc %s", b);
break;
case COMPRESSED_BZIP2:
sprintf(be, "%%__bzip2 -dc %s", b);
break;
case COMPRESSED_ZIP:
sprintf(be, "%%__unzip %s", b);
break;
case COMPRESSED_LZMA:
case COMPRESSED_XZ:
sprintf(be, "%%__xz -dc %s", b);
break;
case COMPRESSED_LZIP:
sprintf(be, "%%__lzip -dc %s", b);
break;
case COMPRESSED_LRZIP:
sprintf(be, "%%__lrzip -dqo- %s", b);
break;
case COMPRESSED_7ZIP:
sprintf(be, "%%__7zip x %s", b);
break;
case COMPRESSED_ZSTD:
sprintf(be, "%%__zstd -dc %s", b);
break;
}
b = be;
} else if (STREQ("getenv", f, fn)) {
b = getenv(buf);
} else if (STREQ("getconfdir", f, fn)) {

View File

@ -189,7 +189,7 @@ runroot rpm \
])
AT_CLEANUP
AT_SETUP([uncompress macro])
AT_SETUP([uncompress macro 1])
AT_KEYWORDS([macros])
AT_CHECK([
runroot rpm \
@ -201,6 +201,18 @@ runroot rpm \
])
AT_CLEANUP
AT_SETUP([uncompress macro 2])
AT_KEYWORDS([macros])
AT_CHECK([
echo xxxxxxxxxxxxxxxxxxxxxxxxx > ${RPMTEST}/tmp/"some%%ath"
runroot rpm \
--eval "%{uncompress:/tmp/some%%%%ath}"
],
[0],
[/usr/bin/cat /tmp/some%%ath
])
AT_CLEANUP
AT_SETUP([basename macro])
AT_KEYWORDS([macros])
AT_CHECK([
@ -251,6 +263,8 @@ AT_CHECK([
runroot rpm --eval "%{dirname}"
runroot rpm --eval "%{dirname:}"
runroot rpm --eval "%{dirname:dir}"
runroot rpm --eval "%{uncompress}"
runroot rpm --eval "%{uncompress:}"
runroot rpm --eval "%{getncpus:}"
runroot rpm --eval "%{getncpus:5}"
runroot rpm --eval "%{define:}"
@ -259,8 +273,10 @@ runroot rpm --eval "%{dump:foo}"
[1],
[
dir
],
[error: %dirname: argument expected
error: %uncompress: argument expected
error: %getncpus: unexpected argument
error: %getncpus: unexpected argument
error: %define: unexpected argument