From 227cddca88fe99b0e2454a45b941adc3d09bd2ce Mon Sep 17 00:00:00 2001 From: Panu Matilainen Date: Mon, 10 Feb 2020 12:31:21 +0200 Subject: [PATCH] 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. --- rpmio/macro.c | 107 +++++++++++++++++++++++++++------------------- tests/rpmmacro.at | 18 +++++++- 2 files changed, 80 insertions(+), 45 deletions(-) diff --git a/rpmio/macro.c b/rpmio/macro.c index e901328d4..80bafef29 100644 --- a/rpmio/macro.c +++ b/rpmio/macro.c @@ -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)) { diff --git a/tests/rpmmacro.at b/tests/rpmmacro.at index 448af3925..88d22cc89 100644 --- a/tests/rpmmacro.at +++ b/tests/rpmmacro.at @@ -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