diff options
-rw-r--r-- | lib/Makefile.in | 2 | ||||
-rw-r--r-- | lib/header.c | 548 | ||||
-rw-r--r-- | lib/header.h | 29 | ||||
-rw-r--r-- | lib/messages.c | 5 | ||||
-rw-r--r-- | lib/rpmlib.h | 3 | ||||
-rw-r--r-- | query.c | 323 | ||||
-rw-r--r-- | rpmio/messages.c | 5 |
7 files changed, 598 insertions, 317 deletions
diff --git a/lib/Makefile.in b/lib/Makefile.in index 6f54a18cb..1db7c8e5b 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -8,7 +8,7 @@ LIBOBJECTS = header.o misc.o messages.o \ stringbuf.o rpmlead.o package.o \ uninstall.o oldheader.o install.o \ signature.o verify.o rebuilddb.o \ - tread.o cpio.o + tread.o cpio.o formats.o SOURCES = $(addprefix $(srcdir)/,$(subst .o,.c,$(LIBOBJECTS))) TAGTABLE = tagtable.o diff --git a/lib/header.c b/lib/header.c index af4961a04..a579dda71 100644 --- a/lib/header.c +++ b/lib/header.c @@ -10,10 +10,16 @@ #include "config.h" #include "miscfn.h" +#if HAVE_ALLOCA_H +# include <alloca.h> +#endif + #include <stdlib.h> #include <ctype.h> #include <malloc.h> #include <string.h> +#include <sys/time.h> +#include <sys/types.h> #include <unistd.h> #include <netinet/in.h> @@ -59,6 +65,29 @@ struct indexEntry { int length; /* Computable, but why bother */ }; +struct sprintfTag { + int_32 tag; + int justOne; + char * format; + char * type; + int pad; +}; + +struct sprintfToken { + enum { PTOK_NONE = 0, PTOK_TAG, PTOK_ARRAY, PTOK_STRING } type; + union { + struct { + struct sprintfToken * format; + int numTokens; + } array; + struct sprintfTag tag; + struct { + char * string; + int len; + } string; + } u; +}; + static int indexCmp(const void *ap, const void *bp); static void *doHeaderUnload(Header h, int * lengthPtr); static struct indexEntry *findEntry(Header h, int_32 tag, int_32 type); @@ -66,6 +95,34 @@ static void * grabData(int_32 type, void * p, int_32 c, int * lengthPtr); static int dataLength(int_32 type, void * p, int_32 count, int onDisk); static void copyEntry(struct indexEntry * entry, int_32 *type, void **p, int_32 *c); +static void freeFormat(struct sprintfToken * format, int num); +int parseFormat(char * format, const struct headerTagTableEntry * tags, + const struct headerSprintfExtension * extentions, + struct sprintfToken ** formatPtr, int * numTokensPtr, + char ** endPtr, char ** error); +static char * singleSprintf(Header h, struct sprintfToken * token, + const struct headerSprintfExtension * extensions, + int element); +static char escapedChar(const char ch); +static char * escapeString(const char * src); +static char * formatValue(struct sprintfTag * tag, Header h, + const struct headerSprintfExtension * extensions, + int element); + +static char * octalFormat(int_32 type, const void * data, + char * formatPrefix, int padding, int element); +static char * dateFormat(int_32 type, const void * data, + char * formatPrefix, int padding, int element); +static char * shescapeFormat(int_32 type, const void * data, + char * formatPrefix, int padding, int element); + +const struct headerSprintfExtension headerDefaultFormats[] = { + { HEADER_EXT_FORMAT, "octal", { octalFormat } }, + { HEADER_EXT_FORMAT, "date", { dateFormat } }, + { HEADER_EXT_FORMAT, "shescape", { shescapeFormat } }, + { HEADER_EXT_LAST, NULL, { NULL } } +}; + /********************************************************************/ /* */ @@ -885,3 +942,494 @@ int headerRemoveEntry(Header h, int_32 tag) { return 0; } + +static char escapedChar(const char ch) { + switch (ch) { + case 'a': return '\a'; + case 'b': return '\b'; + case 'f': return '\f'; + case 'n': return '\n'; + case 'r': return '\r'; + case 't': return '\t'; + case 'v': return '\v'; + + default: return ch; + } +} + +static void freeFormat(struct sprintfToken * format, int num) { + int i; + + for (i = 0; i < num; i++) { + if (format[i].type == PTOK_ARRAY) + freeFormat(format[i].u.array.format, format[i].u.array.numTokens); + } + free(format); +} + +int parseFormat(char * str, const struct headerTagTableEntry * tags, + const struct headerSprintfExtension * extensions, + struct sprintfToken ** formatPtr, int * numTokensPtr, + char ** endPtr, char ** error) { + char * chptr, * start, * next, * tagname; + struct sprintfToken * format; + int numTokens; + int currToken; + const struct headerTagTableEntry * entry; + int i; + int done = 0; + + /* upper limit on number of individual formats */ + numTokens = 0; + for (chptr = str; *chptr; chptr++) + if (*chptr == '%') numTokens++; + numTokens = numTokens * 2 + 1; + + format = calloc(sizeof(*format), numTokens); + + start = str; + currToken = -1; + while (*start && !done) { + switch (*start) { + case '%': + currToken++; + + *start++ = '\0'; + format[currToken].u.tag.format = start; + format[currToken].u.tag.pad = 0; + format[currToken].u.tag.justOne = 0; + + chptr = start; + while (*chptr && *chptr != '{') chptr++; + if (!*chptr) { + *error = "missing { after %"; + freeFormat(format, numTokens); + return 1; + } + + *chptr++ = '\0'; + + while (start < chptr) { + if (isdigit(*start)) { + i = strtoul(start, &start, 10); + format[currToken].u.tag.pad += i; + } else { + start++; + } + } + + if (*start == '=') { + format[currToken].u.tag.justOne = 1; + start++; + } + + next = start; + while (*next && *next != '}') next++; + if (!*next) { + *error = "missing } after %{"; + freeFormat(format, numTokens); + return 1; + } + *next++ = '\0'; + + chptr = start; + while (*chptr && *chptr != ':') chptr++; + + if (*chptr) { + *chptr++ = '\0'; + if (!*chptr) { + *error = "empty tag format"; + freeFormat(format, numTokens); + return 1; + } + format[currToken].u.tag.type = chptr; + } else { + format[currToken].u.tag.type = NULL; + } + + if (!*start) { + *error = "empty tag name"; + freeFormat(format, numTokens); + return 1; + } + + if (strncmp("RPMTAG_", start, 7)) { + tagname = malloc(strlen(start) + 10); + strcpy(tagname, "RPMTAG_"); + strcat(tagname, start); + } else { + tagname = strdup(start); + } + + for (entry = tags; entry->name; entry++) + if (!strcasecmp(entry->name, tagname)) break; + + if (!entry->name) { + *error = "unknown tag"; + freeFormat(format, numTokens); + return 1; + } + + format[currToken].u.tag.tag = entry->val; + format[currToken].type = PTOK_TAG; + + start = next; + + break; + + case '[': + *start++ = '\0'; + currToken++; + + if (parseFormat(start, tags, extensions, + &format[currToken].u.array.format, + &format[currToken].u.array.numTokens, + &start, error)) { + freeFormat(format, numTokens); + return 1; + } + + format[currToken].type = PTOK_ARRAY; + + break; + + case ']': + if (!endPtr) { + *error = "unexpected ]"; + freeFormat(format, numTokens); + return 1; + } + *start++ = '\0'; + *endPtr = start; + done = 1; + break; + + default: + if (currToken < 0 || format[currToken].type != PTOK_STRING) { + currToken++; + format[currToken].type = PTOK_STRING; + format[currToken].u.string.string = start; + } + start++; + } + } + + currToken++; + for (i = 0; i < currToken; i++) { + if (format[i].type == PTOK_STRING) + format[i].u.string.len = strlen(format[i].u.string.string); + } + + *numTokensPtr = currToken; + *formatPtr = format; + + return 0; +} + +static char * formatValue(struct sprintfTag * tag, Header h, + const struct headerSprintfExtension * extensions, + int element) { + int len; + char buf[20]; + int_32 count, type; + void * data; + unsigned int intVal; + char * val = NULL; + char ** strarray; + headerTagFormatFunction tagtype = NULL; + const struct headerSprintfExtension * ext; + + if (!headerGetEntry(h, tag->tag, &type, &data, &count)){ + count = 1; + type = RPM_STRING_TYPE; + data = "(none)"; + } + + strcpy(buf, "%"); + strcat(buf, tag->format); + + if (tag->type) { + ext = extensions; + while (ext->type != HEADER_EXT_LAST) { + if (ext->type == HEADER_EXT_FORMAT && + !strcmp(ext->name, tag->type)) { + tagtype = ext->u.formatFunction; + break; + } + + if (ext->type == HEADER_EXT_MORE) + ext = ext->u.more; + else + ext++; + } + } + + switch (type) { + case RPM_STRING_ARRAY_TYPE: + strarray = data; + + if (tagtype) { + val = tagtype(RPM_STRING_TYPE, strarray[element], buf, tag->pad, 0); + } + + if (!val) { + strcat(buf, "s"); + + len = strlen(data) + tag->pad + 20; + val = malloc(len); + sprintf(val, strarray[element], data); + } + + free(strarray); + break; + + case RPM_STRING_TYPE: + if (tagtype) { + val = tagtype(RPM_STRING_ARRAY_TYPE, data, buf, tag->pad, 0); + } + + if (!val) { + strcat(buf, "s"); + + len = strlen(data) + tag->pad + 20; + val = malloc(len); + sprintf(val, buf, data); + } + break; + + case RPM_CHAR_TYPE: + case RPM_INT8_TYPE: + case RPM_INT16_TYPE: + case RPM_INT32_TYPE: + switch (type) { + case RPM_CHAR_TYPE: + case RPM_INT8_TYPE: intVal = *(((int_8 *) data) + element); break; + case RPM_INT16_TYPE: intVal = *(((uint_16 *) data) + element); break; + default: /* keep -Wall quiet */ + case RPM_INT32_TYPE: intVal = *(((int_32 *) data) + element); + } + + if (tagtype) { + val = tagtype(RPM_INT32_TYPE, &intVal, buf, tag->pad, element); + } + + if (!val) { + strcat(buf, "d"); + len = 10 + tag->pad + 20; + val = malloc(len); + sprintf(val, buf, intVal); + } + break; + + default: + val = malloc(20); + strcpy(val, "(unknown type)"); + } + + return val; +} + +static char * singleSprintf(Header h, struct sprintfToken * token, + const struct headerSprintfExtension * extensions, + int element) { + char * val, * thisItem; + int thisItemLen; + int len, alloced; + int i, j; + int numElements; + + /* we assume the token and header have been validated already! */ + + switch (token->type) { + case PTOK_NONE: + break; + + case PTOK_STRING: + val = malloc(token->u.string.len + 1); + sprintf(val, token->u.string.string); + break; + + case PTOK_TAG: + val = formatValue(&token->u.tag, h, extensions, + token->u.tag.justOne ? 1 : element); + break; + + case PTOK_ARRAY: + numElements = -1; + for (i = 0; i < token->u.array.numTokens; i++) { + if (token->u.array.format[i].type != PTOK_TAG || + token->u.array.format[i].u.tag.justOne) continue; + + headerGetEntry(h, token->u.array.format[i].u.tag.tag, NULL, + (void **) &val, &numElements); + break; + } + + if (numElements == -1) { + val = malloc(20); + strcpy(val, "(none)\n"); + } else { + alloced = numElements * token->u.array.numTokens * 20; + val = malloc(alloced); + *val = '\0'; + len = 0; + + for (j = 0; j < numElements; j++) { + for (i = 0; i < token->u.array.numTokens; i++) { + thisItem = singleSprintf(h, token->u.array.format + i, + extensions, j); + thisItemLen = strlen(thisItem); + if ((thisItemLen + len) >= alloced) { + alloced = (thisItemLen + len) + 200; + val = realloc(val, alloced); + } + strcat(val, thisItem); + len += thisItemLen; + free(thisItem); + } + } + } + + break; + } + + return val; +} + +static char * escapeString(const char * src) { + char * rc = malloc(strlen(src) + 1); + char * dst; + + dst = rc; + + while (*src) { + if (*src == '\\') { + src++; + *dst++ = escapedChar(*src++); + } else { + *dst++ = *src++; + } + } + + *dst = '\0'; + + return rc; +} + +char * headerSprintf(Header h, const char * origFmt, + const struct headerTagTableEntry * tags, + const struct headerSprintfExtension * extensions, + char ** error) { + char * fmtString; + struct sprintfToken * format; + int numTokens; + char * answer, * piece; + int answerLength; + int answerAlloced; + int pieceLength; + int i; + + fmtString = escapeString(origFmt); + + if (parseFormat(fmtString, tags, extensions, &format, &numTokens, NULL, error)) { + free(fmtString); + return NULL; + } + + answerAlloced = 1024; + answerLength = 0; + answer = malloc(answerAlloced); + *answer = '\0'; + + for (i = 0; i < numTokens; i++) { + piece = singleSprintf(h, format + i, extensions, 0); + if (piece) { + pieceLength = strlen(piece); + if ((answerLength + pieceLength) >= answerAlloced) { + while ((answerLength + pieceLength) >= answerAlloced) + answerAlloced += 1024; + answer = realloc(answer, answerAlloced); + } + + strcat(answer, piece); + answerLength += pieceLength; + } + } + + free(fmtString); + + return answer; +} + +static char * octalFormat(int_32 type, const void * data, + char * formatPrefix, int padding, int element) { + char * val; + + if (type != RPM_INT32_TYPE) { + val = malloc(20); + strcpy(val, "(not a number)"); + } else { + val = malloc(20 + padding); + strcat(formatPrefix, "#o"); + sprintf(val, formatPrefix, *((int_32 *) data)); + } + + return val; +} + +static char * dateFormat(int_32 type, const void * data, + char * formatPrefix, int padding, int element) { + char * val; + time_t dateint; + struct tm * tstruct; + char buf[50]; + + if (type != RPM_INT32_TYPE) { + val = malloc(20); + strcpy(val, "(not a number)"); + } else { + val = malloc(50 + padding); + strcat(formatPrefix, "s"); + + /* this is important if sizeof(int_32) ! sizeof(time_t) */ + dateint = *((int_32 *) data); + tstruct = localtime(&dateint); + strftime(buf, sizeof(buf) - 1, "%c", tstruct); + sprintf(val, formatPrefix, buf); + } + + return val; +} + +static char * shescapeFormat(int_32 type, const void * data, + char * formatPrefix, int padding, int element) { + char * result, * dst, * src, * buf; + + if (type == RPM_INT32_TYPE) { + result = malloc(padding + 20); + strcat(formatPrefix, "d"); + sprintf(result, formatPrefix, *((int_32 *) data)); + } else { + buf = alloca(strlen(data) + padding + 2); + strcat(formatPrefix, "s"); + sprintf(buf, formatPrefix, data); + + result = dst = malloc(strlen(buf) * 4 + 3); + *dst++ = '\''; + for (src = buf; *src; src++) { + if (*src == '\'') { + *dst++ = '\''; + *dst++ = '\\'; + *dst++ = '\''; + *dst++ = '\''; + } else { + *dst++ = *src; + } + } + *dst++ = '\''; + *dst = '\0'; + + } + + return result; +} diff --git a/lib/header.h b/lib/header.h index 17fff4f03..58fe7188a 100644 --- a/lib/header.h +++ b/lib/header.h @@ -37,6 +37,29 @@ struct headerTagTableEntry { int val; }; +enum headerSprintfExtenstionType { HEADER_EXT_TAG, HEADER_EXT_FORMAT, + HEADER_EXT_MORE, HEADER_EXT_LAST = 0}; + +/* This will only ever be passed RPM_TYPE_INT32 or RPM_TYPE_STRING to + help keep things simple */ +typedef char * (*headerTagFormatFunction)(int_32 type, const void * data, + char * formatPrefix, + int padding, int element); + +struct headerSprintfExtension { + enum headerSprintfExtenstionType type; + char * name; + union { + void * generic; + headerTagFormatFunction formatFunction; + struct headerSprintfExtension * more; + } u; +}; + +/* This defines some basic conversions all header users would probably like + to have */ +extern const struct headerSprintfExtension headerDefaultFormats[]; + /* read and write a header from a file */ Header headerRead(int fd, int magicp); void headerWrite(int fd, Header h, int magicp); @@ -56,6 +79,12 @@ void headerFree(Header h); void headerDump(Header h, FILE *f, int flags, const struct headerTagTableEntry * tags); +/* the returned string must be free()d */ +char * headerSprintf(Header h, const char * fmt, + const struct headerTagTableEntry * tags, + const struct headerSprintfExtension * extentions, + char ** error); + #define HEADER_DUMP_INLINE 1 /* I18N items need an RPM_STRING_TYPE entry (used by default) and an diff --git a/lib/messages.c b/lib/messages.c index 953db687e..eee2290e7 100644 --- a/lib/messages.c +++ b/lib/messages.c @@ -38,26 +38,31 @@ void rpmMessage(int level, char * format, ...) { case RPMMESS_VERBOSE: case RPMMESS_NORMAL: vfprintf(stdout, format, args); + fflush(stdout); break; case RPMMESS_DEBUG: fprintf(stdout, "D: "); vfprintf(stdout, format, args); + fflush(stdout); break; case RPMMESS_WARNING: fprintf(stderr, "warning: "); vfprintf(stderr, format, args); + fflush(stderr); break; case RPMMESS_ERROR: fprintf(stderr, "error: "); vfprintf(stderr, format, args); + fflush(stderr); break; case RPMMESS_FATALERROR: fprintf(stderr, "fatal error: "); vfprintf(stderr, format, args); + fflush(stderr); exit(1); break; } diff --git a/lib/rpmlib.h b/lib/rpmlib.h index 9b285bdcc..c98a71abf 100644 --- a/lib/rpmlib.h +++ b/lib/rpmlib.h @@ -19,6 +19,9 @@ int rpmReadPackageHeader(int fd, Header * hdr, int * isSource, int * major, extern const struct headerTagTableEntry rpmTagTable[]; extern const int rpmTagTableSize; +/* this chains to headerDefaultFormats[] */ +extern const struct headerSprintfExtension rpmHeaderFormats[]; + /* these tags are for both the database and packages */ /* none of these can be 0 !! */ @@ -24,12 +24,6 @@ static char * permsString(int mode); static void printHeader(Header h, int queryFlags, char * queryFormat); -static int queryPartial(Header h, char ** chptrptr, int * cntptr, - int arrayNum); -static int queryHeader(Header h, char * chptr); -static int queryArray(Header h, char ** chptrptr); -static void escapedChar(char ch); -static char * handleFormat(Header h, char * chptr, int * count, int arrayNum); static void showMatches(rpmdb db, dbiIndexSet matches, int queryFlags, char * queryFormat); static int findMatches(rpmdb db, char * name, char * version, char * release, @@ -38,325 +32,22 @@ static void printFileInfo(char * name, unsigned int size, unsigned short mode, unsigned int mtime, unsigned short rdev, char * owner, char * group, int uid, int gid, char * linkto); -static void formatString(const char * format, const char * str, - const char * how); static int queryHeader(Header h, char * chptr) { - int count = 0; + char * str; + char * error; - return queryPartial(h, &chptr, &count, -1); -} - -static int queryArray(Header h, char ** chptrptr) { - int count = 0; - int arrayNum; - char * start = NULL; - - /* first one */ - start = *chptrptr; - if (queryPartial(h, chptrptr, &count, 0)) return 1; - - arrayNum = 1; - while (arrayNum < count) { - *chptrptr = start; - if (queryPartial(h, chptrptr, &count, arrayNum++)) return 1; - } - - return 0; -} - -static int queryPartial(Header h, char ** chptrptr, int * cntptr, - int arrayNum) { - char * chptr = *chptrptr; - int count; - int emptyItem = 0; - - while (chptr && *chptr) { - switch (*chptr) { - case '\\': - chptr++; - if (!*chptr) return 1; - escapedChar(*chptr++); - break; - - case '%': - chptr++; - if (!*chptr) return 1; - if (*chptr == '%') { - putchar('%'); - chptr++; - } - count = *cntptr; - chptr = handleFormat(h, chptr, &count, arrayNum); - if (!count) { - count = 0; - emptyItem = 1; - } else if (count != -1 && !*cntptr && !emptyItem){ - *cntptr = count; - } else if (count != -1 && *cntptr && count != *cntptr) { - fprintf(stderr, _("(parallel array size mismatch)")); - return 1; - } - break; - - case ']': - if (arrayNum == -1) { - printf(_("(unexpected ']')")); - return 1; - } - *chptrptr = chptr + 1; - return 0; - - case '[': - if (arrayNum != -1) { - printf(_("(unexpected ']')")); - return 1; - } - *chptrptr = chptr + 1; - if (queryArray(h, chptrptr)) { - return 1; - } - chptr = *chptrptr; - break; - - default: - putchar(*chptr++); - } + str = headerSprintf(h, chptr, rpmTagTable, rpmHeaderFormats, &error); + if (!str) { + fprintf(stderr, "error in format: %s\n", error); + return 1; } - *chptrptr = chptr; + fputs(str, stdout); return 0; } -static void formatString(const char * format, const char * str, - const char * how) { - char * dst; - const char * src, * buf; - - if (!strcmp(how, "shescape")) { - buf = dst = alloca(strlen(str) * 4 + 3); - *dst++ = '\''; - for (src = str; *src; src++) { - if (*src == '\'') { - *dst++ = '\''; - *dst++ = '\\'; - *dst++ = '\''; - *dst++ = '\''; - } else { - *dst++ = *src; - } - } - *dst++ = '\''; - *dst = '\0'; - } else { - buf = str; - } - - printf(format, buf); -} - -static char * handleFormat(Header h, char * chptr, int * cntptr, - int arrayNum) { - const char * f = chptr; - const char * tagptr; - char * end; - char how[20], format[20]; - int i, tagLength; - char tag[100]; - const struct headerTagTableEntry * t; - void * p; - int type; - int showCount = 0; - int notArray = 0; - time_t dateint; - struct tm * tstruct; - char buf[100]; - int count; - int anint; - - strcpy(format, "%"); - while (*chptr && *chptr != '{') chptr++; - if (!*chptr || (chptr - f > (sizeof(format) - 3))) { - fprintf(stderr, _("bad query format - %s\n"), f); - return NULL; - } - - strncat(format, f, chptr - f); - - tagptr = ++chptr; - while (*chptr && *chptr != '}' && *chptr != ':' ) chptr++; - if (tagptr == chptr || !*chptr) { - fprintf(stderr, _("bad query format - %s\n"), f); - return NULL; - } - - if (*chptr == ':') { - end = chptr + 1; - while (*end && *end != '}') end++; - - if (*end != '}') { - fprintf(stderr, _("bad query format - %s\n"), f); - return NULL; - } - if ((end - chptr + 1) > sizeof(how)) { - fprintf(stderr, _("bad query format - %s\n"), f); - return NULL; - } - strncpy(how, chptr + 1, end - chptr - 1); - how[end - chptr - 1] = '\0'; - } else { - strcpy(how, ""); - end = chptr; - } - - switch (*tagptr) { - case '=': notArray = 1, tagptr++; break; - case '#': showCount = 1, tagptr++; break; - } - - tagLength = chptr - tagptr; - chptr = end + 1; - - if (tagLength > (sizeof(tag) - 20)) { - fprintf(stderr, _("query tag too long\n")); - return NULL; - } - memset(tag, 0, sizeof(tag)); - if (strncmp(tagptr, "RPMTAG_", 7)) { - strcpy(tag, "RPMTAG_"); - } - strncat(tag, tagptr, tagLength); - - for (i = 0, t = rpmTagTable; i < rpmTagTableSize; i++, t++) { - if (!strcasecmp(tag, t->name)) break; - } - - if (i == rpmTagTableSize) { - fprintf(stderr, _("unknown tag %s\n"), tag); - return NULL; - } - - if (!headerGetEntry(h, t->val, &type, &p, &count) || !p) { - p = "(none)"; - count = 1; - type = RPM_STRING_TYPE; - } else if (notArray) { - *cntptr = -1; - } else if (showCount) { - i = count; - p = &i; - type = RPM_INT32_TYPE; - count = 1; - } else if (count > 1 && (arrayNum == -1)) { - p = "(array)"; - count = 1; - type = RPM_STRING_TYPE; - } else if ((count - 1) < arrayNum && arrayNum != -1) { - p = "(past array end)"; - count = 1; - type = RPM_STRING_TYPE; - } else if (arrayNum != -1) - *cntptr = count; - - if (arrayNum == -1) arrayNum = 0; - - switch (type) { - case RPM_STRING_ARRAY_TYPE: - strcat(format, "s"); - formatString(format, ((char **) p)[arrayNum], how); - free(p); - break; - - case RPM_STRING_TYPE: - strcat(format, "s"); - formatString(format, p, how); - break; - - case RPM_CHAR_TYPE: - case RPM_INT8_TYPE: - strcat(format, "d"); - printf(format, *(((int_8 *) p) + arrayNum)); - break; - - case RPM_INT16_TYPE: - if (!strcmp(how, "perms") || !strcmp(how, "permissions")) { - strcat(format, "s"); - printf(format, permsString(*(((int_16 *) p) + arrayNum))); - } else if (!strcmp(how, "octal")) { - strcat(format, "#o"); - printf(format, *(((int_16 *) p) + arrayNum) & 0xFFFF); - } else { - strcat(format, "d"); - printf(format, *(((int_16 *) p) + arrayNum)); - } - break; - - case RPM_INT32_TYPE: - if (!strcmp(how, "date")) { - strcat(format, "s"); - /* this is important if sizeof(int_32) ! sizeof(time_t) */ - dateint = *(((int_32 *) p) + arrayNum); - tstruct = localtime(&dateint); - strftime(buf, sizeof(buf) - 1, "%c", tstruct); - printf(format, buf); - } else if (!strcmp(how, "fflags")) { - strcat(format, "s"); - buf[0] = '\0'; - anint = *(((int_32 *) p) + arrayNum); - if (anint & RPMFILE_DOC) - strcat(buf, "d"); - if (anint & RPMFILE_CONFIG) - strcat(buf, "c"); - printf(format, buf); - } else if (!strcmp(how, "octal")) { - strcat(format, "#o"); - printf(format, *(((int_32 *) p) + arrayNum)); - } else if (!strcmp(how, "perms") || !strcmp(how, "permissions")) { - strcat(format, "s"); - printf(format, permsString(*(((int_32 *) p) + arrayNum))); - } else if (!strcmp(how, "depflags")) { - buf[0] = '\0'; - anint = *(((int_32 *) p) + arrayNum); - if (anint & RPMSENSE_LESS) - strcat(buf, "<"); - if (anint & RPMSENSE_GREATER) - strcat(buf, ">"); - if (anint & RPMSENSE_EQUAL) - strcat(buf, "="); - if (anint & RPMSENSE_SERIAL) - strcat(buf, "S"); - - strcat(format, "s"); - printf(format, buf); - } else { - strcat(format, "d"); - printf(format, *(((int_32 *) p) + arrayNum)); - } - break; - - default: - printf("(can't handle type %d)", type); - break; - } - - return chptr; -} - -static void escapedChar(const char ch) { - switch (ch) { - case 'a': putchar('\a'); break; - case 'b': putchar('\b'); break; - case 'f': putchar('\f'); break; - case 'n': putchar('\n'); break; - case 'r': putchar('\r'); break; - case 't': putchar('\t'); break; - case 'v': putchar('\v'); break; - - default: putchar(ch); break; - } -} - static void printHeader(Header h, int queryFlags, char * queryFormat) { char * name, * version, * release; int_32 count, type; diff --git a/rpmio/messages.c b/rpmio/messages.c index 953db687e..eee2290e7 100644 --- a/rpmio/messages.c +++ b/rpmio/messages.c @@ -38,26 +38,31 @@ void rpmMessage(int level, char * format, ...) { case RPMMESS_VERBOSE: case RPMMESS_NORMAL: vfprintf(stdout, format, args); + fflush(stdout); break; case RPMMESS_DEBUG: fprintf(stdout, "D: "); vfprintf(stdout, format, args); + fflush(stdout); break; case RPMMESS_WARNING: fprintf(stderr, "warning: "); vfprintf(stderr, format, args); + fflush(stderr); break; case RPMMESS_ERROR: fprintf(stderr, "error: "); vfprintf(stderr, format, args); + fflush(stderr); break; case RPMMESS_FATALERROR: fprintf(stderr, "fatal error: "); vfprintf(stderr, format, args); + fflush(stderr); exit(1); break; } |