summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Makefile.in2
-rw-r--r--lib/header.c548
-rw-r--r--lib/header.h29
-rw-r--r--lib/messages.c5
-rw-r--r--lib/rpmlib.h3
-rw-r--r--query.c323
-rw-r--r--rpmio/messages.c5
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 !! */
diff --git a/query.c b/query.c
index 562ad5fbb..4d5f517b9 100644
--- a/query.c
+++ b/query.c
@@ -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;
}