diff -urNp rpm-4.5.orig/rpmio/macro.c rpm-4.5/rpmio/macro.c --- rpm-4.5.orig/rpmio/macro.c 2017-10-19 22:48:49.000000000 +0000 +++ rpm-4.5/rpmio/macro.c 2017-10-19 23:16:34.301644733 +0000 @@ -71,6 +71,7 @@ const char * rpmMacrofiles = MACROFILES; #endif #include +#include #include "debug.h" @@ -1200,6 +1201,28 @@ doFoo(MacroBuf mb, int negate, const cha if ((b = strrchr(buf, '/')) != NULL) *b = '\0'; b = buf; + } else if (STREQ("shrink", f, fn)) { + /* + * shrink body by removing all leading and trailing whitespaces and + * reducing intermediate whitespaces to a single space character. + */ + size_t i = 0, j = 0; + size_t buflen = strlen(buf); + int was_space = 0; + while (i < buflen) { + if (risspace(buf[i])) { + was_space = 1; + i++; + continue; + } else if (was_space) { + was_space = 0; + if (j > 0) /* remove leading blanks at all */ + buf[j++] = ' '; + } + buf[j++] = buf[i++]; + } + buf[j] = '\0'; + b = buf; } else if (STREQ("suffix", f, fn)) { if ((b = strrchr(buf, '.')) != NULL) b++; @@ -1549,6 +1572,7 @@ expandMacro(MacroBuf mb) /* XXX necessary but clunky */ if (STREQ("basename", f, fn) || STREQ("dirname", f, fn) || + STREQ("shrink", f, fn) || STREQ("suffix", f, fn) || STREQ("expand", f, fn) || STREQ("verbose", f, fn) || diff -urNp rpm-4.5.orig/rpmio/Makefile.am rpm-4.5/rpmio/Makefile.am --- rpm-4.5.orig/rpmio/Makefile.am 2017-10-19 22:48:49.000000000 +0000 +++ rpm-4.5/rpmio/Makefile.am 2017-10-19 23:16:15.212645871 +0000 @@ -37,7 +37,7 @@ librpmio_la_SOURCES = \ md2.c md4.c rmd128.c rmd160.c rmd256.c rmd320.c sha224.c \ salsa10.c salsa20.c tiger.c \ rpmdav.c rpmhash.c rpmhook.c rpmio.c rpmlog.c rpmlua.c rpmmalloc.c \ - rpmpgp.c rpmrpc.c rpmsq.c rpmsw.c strcasecmp.c strtolocale.c \ + rpmpgp.c rpmrpc.c rpmsq.c rpmstring.c rpmsw.c strcasecmp.c strtolocale.c \ stubs.c url.c ugid.c rpmuuid.c librpmio_la_LDFLAGS = -no-undefined -release $(LT_CURRENT).$(LT_REVISION) $(LDFLAGS) \ @WITH_BEECRYPT_LIB@ \ diff -urNp rpm-4.5.orig/rpmio/Makefile.in rpm-4.5/rpmio/Makefile.in --- rpm-4.5.orig/rpmio/Makefile.in 2008-07-09 09:41:32.000000000 +0000 +++ rpm-4.5/rpmio/Makefile.in 2017-10-19 23:16:15.212645871 +0000 @@ -68,7 +68,7 @@ am_librpmio_la_OBJECTS = argv.lo digest. macro.lo mire.lo md2.lo md4.lo rmd128.lo rmd160.lo rmd256.lo \ rmd320.lo sha224.lo salsa10.lo salsa20.lo tiger.lo rpmdav.lo \ rpmhash.lo rpmhook.lo rpmio.lo rpmlog.lo rpmlua.lo \ - rpmmalloc.lo rpmpgp.lo rpmrpc.lo rpmsq.lo rpmsw.lo \ + rpmmalloc.lo rpmpgp.lo rpmrpc.lo rpmsq.lo rpmstring.lo rpmsw.lo \ strcasecmp.lo strtolocale.lo stubs.lo url.lo ugid.lo \ rpmuuid.lo librpmio_la_OBJECTS = $(am_librpmio_la_OBJECTS) diff -urNp rpm-4.5.orig/rpmio/rpmstring.c rpm-4.5/rpmio/rpmstring.c --- rpm-4.5.orig/rpmio/rpmstring.c 1970-01-01 00:00:00.000000000 +0000 +++ rpm-4.5/rpmio/rpmstring.c 2017-10-19 23:16:15.212645871 +0000 @@ -0,0 +1,192 @@ +/** + * \file rpmio/rpmstring.c + */ + +#include "system.h" + +#include +#include + +#include +#include "debug.h" + + +int rstrcasecmp(const char * s1, const char * s2) +{ + const char * p1 = s1; + const char * p2 = s2; + char c1, c2; + + if (p1 == p2) + return 0; + + do + { + c1 = rtolower (*p1++); + c2 = rtolower (*p2++); + if (c1 == '\0') + break; + } + while (c1 == c2); + + return (int)(c1 - c2); +} + +int rstrncasecmp(const char *s1, const char *s2, size_t n) +{ + const char * p1 = s1; + const char * p2 = s2; + char c1, c2; + + if (p1 == p2 || n == 0) + return 0; + + do + { + c1 = rtolower (*p1++); + c2 = rtolower (*p2++); + if (c1 == '\0' || c1 != c2) + break; + } while (--n > 0); + + return (int)(c1 - c2); +} + +/* + * Simple and stupid asprintf() clone. + * FIXME: write to work with non-C99 vsnprintf or check for one in configure. + */ +int rasprintf(char **strp, const char *fmt, ...) +{ + int n; + va_list ap; + char * p = NULL; + + if (strp == NULL) + return -1; + + va_start(ap, fmt); + n = vsnprintf(NULL, 0, fmt, ap); + va_end(ap); + + if (n >= -1) { + size_t nb = n + 1; + p = xmalloc(nb); + va_start(ap, fmt); + n = vsnprintf(p, nb, fmt, ap); + va_end(ap); + } + *strp = p; + return n; +} + +/* + * Concatenate two strings with dynamically (re)allocated + * memory what prevents static buffer overflows by design. + * *dest is reallocated to the size of strings to concatenate. + * + * Note: + * 1) char *buf = rstrcat(NULL,"string"); is the same like rstrcat(&buf,"string"); + * 2) rstrcat(&buf,NULL) returns buf + * 3) rstrcat(NULL,NULL) returns NULL + * 4) *dest and src can overlap + */ +char *rstrcat(char **dest, const char *src) +{ + if ( src == NULL ) { + return dest != NULL ? *dest : NULL; + } + + if ( dest == NULL ) { + return xstrdup(src); + } + + { + size_t dest_size = *dest != NULL ? strlen(*dest) : 0; + size_t src_size = strlen(src); + + *dest = xrealloc(*dest, dest_size+src_size+1); /* include '\0' */ + memmove(&(*dest)[dest_size], src, src_size+1); + } + + return *dest; +} + +/* + * Concatenate strings with dynamically (re)allocated + * memory what prevents static buffer overflows by design. + * *dest is reallocated to the size of strings to concatenate. + * List of strings has to be NULL terminated. + * + * Note: + * 1) char *buf = rstrscat(NULL,"string",NULL); is the same like rstrscat(&buf,"string",NULL); + * 2) rstrscat(&buf,NULL) returns buf + * 3) rstrscat(NULL,NULL) returns NULL + * 4) *dest and argument strings can overlap + */ +char *rstrscat(char **dest, const char *arg, ...) +{ + va_list ap; + size_t arg_size, dst_size; + const char *s; + char *dst, *p; + + dst = dest ? *dest : NULL; + + if ( arg == NULL ) { + return dst; + } + + va_start(ap, arg); + for (arg_size=0, s=arg; s; s = va_arg(ap, const char *)) + arg_size += strlen(s); + va_end(ap); + + dst_size = dst ? strlen(dst) : 0; + dst = xrealloc(dst, dst_size+arg_size+1); /* include '\0' */ + p = &dst[dst_size]; + + va_start(ap, arg); + for (s = arg; s; s = va_arg(ap, const char *)) { + size_t size = strlen(s); + memmove(p, s, size); + p += size; + } + va_end(ap); + *p = '\0'; + + if ( dest ) { + *dest = dst; + } + + return dst; +} + +/* + * Adapted from OpenBSD, strlcpy() originally developed by + * Todd C. Miller + */ +size_t rstrlcpy(char *dest, const char *src, size_t n) +{ + char *d = dest; + const char *s = src; + size_t len = n; + + /* Copy as many bytes as will fit */ + if (len != 0) { + while (--len != 0) { + if ((*d++ = *s++) == '\0') + break; + } + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (len == 0) { + if (n != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return s - src - 1; /* count does not include NUL */ +} diff -urNp rpm-4.5.orig/rpmio/rpmstring.h rpm-4.5/rpmio/rpmstring.h --- rpm-4.5.orig/rpmio/rpmstring.h 1970-01-01 00:00:00.000000000 +0000 +++ rpm-4.5/rpmio/rpmstring.h 2017-10-19 23:16:15.212645871 +0000 @@ -0,0 +1,187 @@ +#ifndef _RPMSTRING_H_ +#define _RPMSTRING_H_ + +/** \ingroup rpmstring + * \file rpmio/rpmstring.h + * String manipulation helper functions + */ + +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \ingroup rpmstring + * Locale insensitive islower(3) + */ +RPM_GNUC_CONST +static inline int rislower(int c) { + return (c >= 'a' && c <= 'z'); +} + +/** \ingroup rpmstring + * Locale insensitive isupper(3) + */ +RPM_GNUC_CONST +static inline int risupper(int c) { + return (c >= 'A' && c <= 'Z'); +} + +/** \ingroup rpmstring + * Locale insensitive isalpha(3) + */ +RPM_GNUC_CONST +static inline int risalpha(int c) { + return (rislower(c) || risupper(c)); +} + +/** \ingroup rpmstring + * Locale insensitive isdigit(3) + */ +RPM_GNUC_CONST +static inline int risdigit(int c) { + return (c >= '0' && c <= '9'); +} + +/** \ingroup rpmstring + * Locale insensitive isalnum(3) + */ +RPM_GNUC_CONST +static inline int risalnum(int c) { + return (risalpha(c) || risdigit(c)); +} + +/** \ingroup rpmstring + * Locale insensitive isblank(3) + */ +RPM_GNUC_CONST +static inline int risblank(int c) { + return (c == ' ' || c == '\t'); +} + +/** \ingroup rpmstring + * Locale insensitive isspace(3) + */ +RPM_GNUC_CONST +static inline int risspace(int c) { + return (risblank(c) || c == '\n' || c == '\r' || c == '\f' || c == '\v'); +} + +/** \ingroup rpmstring + * Locale insensitive tolower(3) + */ +RPM_GNUC_CONST +static inline int rtolower(int c) { + return ((risupper(c)) ? (c | ('a' - 'A')) : c); +} + +/** \ingroup rpmstring + * Locale insensitive toupper(3) + */ +RPM_GNUC_CONST +static inline int rtoupper(int c) { + return ((rislower(c)) ? (c & ~('a' - 'A')) : c); +} + +/** + * Convert hex to binary nibble. + * @param c hex character + * @return binary nibble + */ +RPM_GNUC_CONST +static inline unsigned char rnibble(char c) +{ + if (c >= '0' && c <= '9') + return (c - '0'); + if (c >= 'a' && c <= 'f') + return (c - 'a') + 10; + if (c >= 'A' && c <= 'F') + return (c - 'A') + 10; + return 0; +} + +/** + * Test for string equality + * @param s1 string 1 + * @param s2 string 2 + * @return 0 if strings differ, 1 if equal + */ +static inline int rstreq(const char *s1, const char *s2) +{ + return (strcmp(s1, s2) == 0); +} + +/** + * Test for string equality + * @param s1 string 1 + * @param s2 string 2 + * @param n compare at most n characters + * @return 0 if strings differ, 1 if equal + */ +static inline int rstreqn(const char *s1, const char *s2, size_t n) +{ + return (strncmp(s1, s2, n) == 0); +} + +/** \ingroup rpmstring + * Locale insensitive strcasecmp(3). + */ +RPM_GNUC_PURE +int rstrcasecmp(const char * s1, const char * s2) ; + +/** \ingroup rpmstring + * Locale insensitive strncasecmp(3). + */ +RPM_GNUC_PURE +int rstrncasecmp(const char *s1, const char * s2, size_t n) ; + +/** \ingroup rpmstring + * asprintf() clone + */ +int rasprintf(char **strp, const char *fmt, ...) RPM_GNUC_PRINTF(2, 3); + +/** \ingroup rpmstring + * Concatenate two strings with dynamically (re)allocated memory. + * @param dest pointer to destination string + * @param src source string + * @return realloc'd dest with src appended + */ +char *rstrcat(char **dest, const char *src); + +/** \ingroup rpmstring + * Concatenate multiple strings with dynamically (re)allocated memory. + * @param dest pointer to destination string + * @param arg NULL terminated list of strings to concatenate + * @return realloc'd dest with strings appended + */ +char *rstrscat(char **dest, const char *arg, ...) RPM_GNUC_NULL_TERMINATED; + +/** \ingroup rpmstring + * strlcpy() clone: + * Copy src to string dest of size n. At most n-1 characters + * will be copied. Always zero-terminates (unless n == 0). + * Length of src is returned; if retval >= n, truncation occurred. + * @param dest destination buffer + * @param src string to copy + * @param n destination buffer size + * @return length of src string + */ +size_t rstrlcpy(char *dest, const char *src, size_t n); + +/** \ingroup rpmstring + * String hashing function + * @param string string to hash + * @return hash id + */ +RPM_GNUC_PURE +unsigned int rstrhash(const char * string); + +#ifdef __cplusplus +} +#endif + +#endif /* _RPMSTRING_H_ */ diff -urNp rpm-4.5.orig/rpmio/rpmutil.h rpm-4.5/rpmio/rpmutil.h --- rpm-4.5.orig/rpmio/rpmutil.h 1970-01-01 00:00:00.000000000 +0000 +++ rpm-4.5/rpmio/rpmutil.h 2017-10-19 23:16:15.213645871 +0000 @@ -0,0 +1,160 @@ +#ifndef _RPMUTIL_H +#define _RPMUTIL_H + +#include + +/** \file rpmio/rpmutil.h + * + * Miscellaneous utility macros: + * - portability wrappers for various gcc extensions like __attribute__() + * - ... + * + * Copied from glib, names replaced to avoid clashing with glib. + * + */ + +/* Here we provide RPM_GNUC_EXTENSION as an alias for __extension__, + * where this is valid. This allows for warningless compilation of + * "long long" types even in the presence of '-ansi -pedantic'. + */ +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8) +# define RPM_GNUC_EXTENSION __extension__ +#else +# define RPM_GNUC_EXTENSION +#endif + +/* Provide macros to feature the GCC function attribute. + */ +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) +#define RPM_GNUC_PURE \ + __attribute__((__pure__)) +#define RPM_GNUC_MALLOC \ + __attribute__((__malloc__)) +#else +#define RPM_GNUC_PURE +#define RPM_GNUC_MALLOC +#endif + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) +#define RPM_GNUC_ALLOC_SIZE(x) __attribute__((__alloc_size__(x))) +#define RPM_GNUC_ALLOC_SIZE2(x,y) __attribute__((__alloc_size__(x,y))) +#else +#define RPM_GNUC_ALLOC_SIZE(x) +#define RPM_GNUC_ALLOC_SIZE2(x,y) +#endif + +#if __GNUC__ >= 4 +#define RPM_GNUC_NULL_TERMINATED __attribute__((__sentinel__)) +#else +#define RPM_GNUC_NULL_TERMINATED +#endif + +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) +#define RPM_GNUC_PRINTF( format_idx, arg_idx ) \ + __attribute__((__format__ (__printf__, format_idx, arg_idx))) +#define RPM_GNUC_SCANF( format_idx, arg_idx ) \ + __attribute__((__format__ (__scanf__, format_idx, arg_idx))) +#define RPM_GNUC_FORMAT( arg_idx ) \ + __attribute__((__format_arg__ (arg_idx))) +#define RPM_GNUC_NORETURN \ + __attribute__((__noreturn__)) +#define RPM_GNUC_CONST \ + __attribute__((__const__)) +#define RPM_GNUC_UNUSED \ + __attribute__((__unused__)) +#define RPM_GNUC_NO_INSTRUMENT \ + __attribute__((__no_instrument_function__)) +#else /* !__GNUC__ */ +#define RPM_GNUC_PRINTF( format_idx, arg_idx ) +#define RPM_GNUC_SCANF( format_idx, arg_idx ) +#define RPM_GNUC_FORMAT( arg_idx ) +#define RPM_GNUC_NORETURN +#define RPM_GNUC_CONST +#define RPM_GNUC_UNUSED +#define RPM_GNUC_NO_INSTRUMENT +#endif /* !__GNUC__ */ + +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) +#define RPM_GNUC_DEPRECATED \ + __attribute__((__deprecated__)) +#else +#define RPM_GNUC_DEPRECATED +#endif /* __GNUC__ */ + +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) +#define RPM_GNUC_MAY_ALIAS __attribute__((may_alias)) +#define RPM_GNUC_NONNULL( ... ) \ + __attribute__((__nonnull__ (__VA_ARGS__))) +#else +#define RPM_GNUC_MAY_ALIAS +#define RPM_GNUC_NONNULL( ... ) +#endif + +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +#define RPM_GNUC_WARN_UNUSED_RESULT \ + __attribute__((warn_unused_result)) +#else +#define RPM_GNUC_WARN_UNUSED_RESULT +#endif /* __GNUC__ */ + +#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) +# define RPM_GNUC_INTERNAL __attribute__((visibility("hidden"))) +#else +# define RPM_GNUC_INTERNAL +#endif + + +/* Guard C code in headers, while including them from C++ */ +#ifdef __cplusplus +# define RPM_BEGIN_DECLS extern "C" { +# define RPM_END_DECLS } +#else +# define RPM_BEGIN_DECLS +# define RPM_END_DECLS +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Rpm specific allocators which never return NULL but terminate on failure */ +RPM_GNUC_MALLOC RPM_GNUC_ALLOC_SIZE(1) +void * rmalloc(size_t size); + +RPM_GNUC_MALLOC RPM_GNUC_ALLOC_SIZE2(1,2) +void * rcalloc(size_t nmemb, size_t size); + +RPM_GNUC_ALLOC_SIZE(2) +void * rrealloc(void *ptr, size_t size); + +char * rstrdup(const char *str); + +/* Rpm specific free() which returns NULL */ +void * rfree(void *ptr); + +/** \ingroup rpmutil + * Memory allocation failure callback prototype. When registered through + * rpmSetMemFail(), this gets called if memory allocation through rmalloc() + * and friends fails. If the application can somehow recover memory here, + * it can return a newly allocated memory block of requested size, otherwise + * it must return NULL after performing it's own shutdown deeds or + * terminate itself. + * @param size Size of allocation request in bytes + * @param data User data (or NULL) + * @return Allocated memory block of requested size or NULL + */ +typedef void * (*rpmMemFailFunc) (size_t size, void *data); + +/** \ingroup rpmutil + * Set memory allocation failure callback. + * @param func Allocation failure callback function + * @param data User data (or NULL) + * @return Previous callback function + */ +rpmMemFailFunc rpmSetMemFail(rpmMemFailFunc func, void *data); + +#ifdef __cplusplus +} +#endif + +#endif /* _RPMUTIL_H */