1996-04-02 11:36:00 +08:00
|
|
|
#include <alloca.h>
|
1996-03-01 11:29:18 +08:00
|
|
|
#include <ctype.h>
|
1996-01-06 02:12:17 +08:00
|
|
|
#include <errno.h>
|
1995-12-28 04:08:35 +08:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
1996-02-19 12:50:33 +08:00
|
|
|
#include <string.h>
|
|
|
|
#include <sys/stat.h>
|
1995-12-28 04:08:35 +08:00
|
|
|
#include <time.h>
|
1996-04-16 05:06:26 +08:00
|
|
|
#include <sys/param.h>
|
1996-01-06 02:12:17 +08:00
|
|
|
#include <unistd.h>
|
1995-12-28 04:08:35 +08:00
|
|
|
|
1996-02-19 12:50:33 +08:00
|
|
|
#include "lib/messages.h"
|
1996-01-06 02:12:17 +08:00
|
|
|
#include "lib/package.h"
|
1995-12-28 04:08:35 +08:00
|
|
|
#include "rpmlib.h"
|
|
|
|
#include "query.h"
|
|
|
|
|
1996-04-02 11:36:00 +08:00
|
|
|
static void printHeader(Header h, int queryFlags, char * queryFormat);
|
1996-06-09 01:27:10 +08:00
|
|
|
static const char * queryHeader(Header h, const char * incomingFormat,
|
|
|
|
int arrayNum);
|
1996-04-02 11:36:00 +08:00
|
|
|
static void escapedChar(char ch);
|
1996-06-09 01:27:10 +08:00
|
|
|
static const char * handleFormat(Header h, const char * chptr,
|
|
|
|
const int arrayNum);
|
1996-04-02 11:36:00 +08:00
|
|
|
static void showMatches(rpmdb db, dbIndexSet matches, int queryFlags,
|
|
|
|
char * queryFormat);
|
1996-02-15 04:56:22 +08:00
|
|
|
static int findMatches(rpmdb db, char * name, char * version, char * release,
|
|
|
|
dbIndexSet * matches);
|
1996-02-19 12:50:33 +08:00
|
|
|
static void printFileInfo(char * name, unsigned int size, unsigned short mode,
|
|
|
|
unsigned int mtime, unsigned short rdev,
|
1996-02-19 23:17:56 +08:00
|
|
|
char * owner, char * group, int uid, int gid,
|
|
|
|
char * linkto);
|
1996-04-16 06:21:30 +08:00
|
|
|
static void printScript(Header h, char * label, int tag);
|
1996-01-06 02:12:17 +08:00
|
|
|
|
1996-04-03 11:45:27 +08:00
|
|
|
static char * defaultQueryFormat =
|
|
|
|
"Name : %-27{NAME} Distribution: %{DISTRIBUTION}\n"
|
|
|
|
"Version : %-27{VERSION} Vendor: %{VENDOR}\n"
|
|
|
|
"Release : %-27{RELEASE} Build Date: %{-BUILDTIME}\n"
|
|
|
|
"Install date: %-27{-INSTALLTIME} Build Host: %{BUILDHOST}\n"
|
|
|
|
"Group : %-27{GROUP} Source RPM: %{SOURCERPM}\n"
|
|
|
|
"Size : %{SIZE}\n"
|
1996-06-09 01:27:10 +08:00
|
|
|
"Provides : %{PROVIDES}\n"
|
1996-04-03 11:45:27 +08:00
|
|
|
"Description : %{DESCRIPTION}\n";
|
1995-12-28 04:08:35 +08:00
|
|
|
|
1996-06-09 01:27:10 +08:00
|
|
|
static const char * queryHeader(Header h, const char * chptr, int arrayNum) {
|
1996-04-02 11:36:00 +08:00
|
|
|
while (chptr && *chptr) {
|
|
|
|
switch (*chptr) {
|
|
|
|
case '\\':
|
|
|
|
chptr++;
|
1996-06-09 01:27:10 +08:00
|
|
|
if (!*chptr) return NULL;
|
1996-04-02 11:36:00 +08:00
|
|
|
escapedChar(*chptr++);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '%':
|
|
|
|
chptr++;
|
1996-06-09 01:27:10 +08:00
|
|
|
if (!*chptr) return NULL;
|
1996-04-02 11:36:00 +08:00
|
|
|
if (*chptr == '%') {
|
|
|
|
putchar('%');
|
|
|
|
chptr++;
|
|
|
|
}
|
1996-06-09 01:27:10 +08:00
|
|
|
chptr = handleFormat(h, chptr, 0);
|
1996-04-02 11:36:00 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
putchar(*chptr++);
|
|
|
|
}
|
|
|
|
}
|
1996-06-09 01:27:10 +08:00
|
|
|
|
|
|
|
return chptr;
|
1996-04-02 11:36:00 +08:00
|
|
|
}
|
|
|
|
|
1996-06-09 01:27:10 +08:00
|
|
|
static const char * handleFormat(Header h, const char * chptr,
|
|
|
|
const int arrayNum) {
|
1996-04-02 11:36:00 +08:00
|
|
|
const char * f = chptr;
|
|
|
|
const char * tagptr;
|
|
|
|
char format[20];
|
|
|
|
int i, tagLength;
|
|
|
|
char tag[100];
|
|
|
|
const struct rpmTagTableEntry * t;
|
|
|
|
void * p;
|
1996-06-09 01:27:10 +08:00
|
|
|
char ** strarray;
|
1996-04-02 11:36:00 +08:00
|
|
|
int type, count;
|
|
|
|
int isDate = 0;
|
|
|
|
time_t dateint;
|
|
|
|
struct tm * tstruct;
|
|
|
|
char datestr[100];
|
|
|
|
|
|
|
|
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++;
|
|
|
|
if (tagptr == chptr || !*chptr) {
|
|
|
|
fprintf(stderr, "bad query format - %s\n", f);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (*tagptr) {
|
|
|
|
case '-': isDate = 1, tagptr++; break;
|
|
|
|
}
|
|
|
|
|
|
|
|
tagLength = chptr - tagptr;
|
|
|
|
chptr++;
|
|
|
|
|
|
|
|
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 (!strcmp(tag, t->name)) break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i == rpmTagTableSize) {
|
|
|
|
fprintf(stderr, "unknown tag %s\n", tag);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!getEntry(h, t->val, &type, &p, &count) || !p) {
|
1996-06-09 01:27:10 +08:00
|
|
|
p = "(none)";
|
1996-04-02 11:36:00 +08:00
|
|
|
count = 1;
|
|
|
|
type = STRING_TYPE;
|
1996-06-09 01:27:10 +08:00
|
|
|
} else if (count > 1 && (type != STRING_ARRAY_TYPE)) {
|
1996-04-02 11:36:00 +08:00
|
|
|
p = "(array)";
|
|
|
|
count = 1;
|
|
|
|
type = STRING_TYPE;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (type) {
|
1996-06-09 01:27:10 +08:00
|
|
|
case STRING_ARRAY_TYPE:
|
|
|
|
strcat(format, "s ");
|
|
|
|
|
|
|
|
/* now use this format for each string, with a space in between */
|
|
|
|
strarray = p;
|
|
|
|
while (count--) {
|
|
|
|
printf(format, *strarray++);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
1996-04-02 11:36:00 +08:00
|
|
|
case STRING_TYPE:
|
|
|
|
strcat(format, "s");
|
|
|
|
printf(format, p);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case INT32_TYPE:
|
|
|
|
if (isDate) {
|
|
|
|
strcat(format, "s");
|
|
|
|
/* this is important if sizeof(int_32) ! sizeof(time_t) */
|
|
|
|
dateint = *((int_32 *) p);
|
|
|
|
tstruct = localtime(&dateint);
|
|
|
|
strftime(datestr, sizeof(datestr) - 1, "%c", tstruct);
|
|
|
|
printf(format, datestr);
|
|
|
|
} else {
|
|
|
|
strcat(format, "d");
|
|
|
|
printf(format, *((int_32 *) p));
|
|
|
|
}
|
|
|
|
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) {
|
1995-12-28 04:08:35 +08:00
|
|
|
char * name, * version, * release;
|
|
|
|
int_32 count, type;
|
|
|
|
char * prefix = NULL;
|
1996-06-09 01:27:10 +08:00
|
|
|
char ** requiresList, ** strlist;
|
1995-12-28 04:08:35 +08:00
|
|
|
char ** fileList;
|
|
|
|
char * fileStatesList;
|
1996-02-19 12:50:33 +08:00
|
|
|
char ** fileOwnerList, ** fileGroupList;
|
1996-02-19 23:17:56 +08:00
|
|
|
char ** fileLinktoList;
|
1996-02-19 12:50:33 +08:00
|
|
|
int_32 * fileFlagsList, * fileMTimeList, * fileSizeList;
|
|
|
|
int_32 * fileUIDList, * fileGIDList;
|
|
|
|
int_16 * fileModeList;
|
|
|
|
int_16 * fileRdevList;
|
1995-12-28 04:08:35 +08:00
|
|
|
int i;
|
|
|
|
|
|
|
|
getEntry(h, RPMTAG_NAME, &type, (void **) &name, &count);
|
|
|
|
getEntry(h, RPMTAG_VERSION, &type, (void **) &version, &count);
|
|
|
|
getEntry(h, RPMTAG_RELEASE, &type, (void **) &release, &count);
|
|
|
|
|
|
|
|
if (!queryFlags) {
|
|
|
|
printf("%s-%s-%s\n", name, version, release);
|
|
|
|
} else {
|
|
|
|
if (queryFlags & QUERY_FOR_INFO) {
|
1996-04-03 11:45:27 +08:00
|
|
|
if (!queryFormat) {
|
|
|
|
queryFormat = defaultQueryFormat;
|
|
|
|
}
|
|
|
|
|
1996-06-09 01:27:10 +08:00
|
|
|
queryHeader(h, queryFormat, -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (queryFlags & QUERY_FOR_DEPS) {
|
|
|
|
printf("Requires : ");
|
|
|
|
if (!getEntry(h, RPMTAG_REQUIRENAME, &type,
|
|
|
|
(void **) &requiresList, &count) || !count) {
|
|
|
|
puts("(nothing)");
|
|
|
|
} else {
|
|
|
|
char * indent = "";
|
|
|
|
|
|
|
|
strlist = requiresList;
|
|
|
|
|
|
|
|
while (count--) {
|
|
|
|
printf("%s%s\n", indent, *strlist++);
|
|
|
|
indent = " ";
|
|
|
|
}
|
|
|
|
free(requiresList);
|
|
|
|
}
|
1995-12-28 04:08:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (queryFlags & QUERY_FOR_LIST) {
|
1996-01-06 02:12:17 +08:00
|
|
|
if (!getEntry(h, RPMTAG_FILENAMES, &type, (void **) &fileList,
|
|
|
|
&count)) {
|
|
|
|
puts("(contains no files)");
|
|
|
|
} else {
|
1996-03-30 03:24:52 +08:00
|
|
|
if (!getEntry(h, RPMTAG_FILESTATES, &type,
|
|
|
|
(void **) &fileStatesList, &count)) {
|
|
|
|
fileStatesList = NULL;
|
|
|
|
}
|
1996-01-06 02:12:17 +08:00
|
|
|
getEntry(h, RPMTAG_FILEFLAGS, &type,
|
|
|
|
(void **) &fileFlagsList, &count);
|
1996-02-19 12:50:33 +08:00
|
|
|
getEntry(h, RPMTAG_FILESIZES, &type,
|
|
|
|
(void **) &fileSizeList, &count);
|
|
|
|
getEntry(h, RPMTAG_FILEMODES, &type,
|
|
|
|
(void **) &fileModeList, &count);
|
|
|
|
getEntry(h, RPMTAG_FILEMTIMES, &type,
|
|
|
|
(void **) &fileMTimeList, &count);
|
|
|
|
getEntry(h, RPMTAG_FILERDEVS, &type,
|
|
|
|
(void **) &fileRdevList, &count);
|
|
|
|
getEntry(h, RPMTAG_FILEUIDS, &type,
|
|
|
|
(void **) &fileUIDList, &count);
|
|
|
|
getEntry(h, RPMTAG_FILEGIDS, &type,
|
|
|
|
(void **) &fileGIDList, &count);
|
|
|
|
getEntry(h, RPMTAG_FILEUSERNAME, &type,
|
|
|
|
(void **) &fileOwnerList, &count);
|
|
|
|
getEntry(h, RPMTAG_FILEGROUPNAME, &type,
|
|
|
|
(void **) &fileGroupList, &count);
|
1996-02-19 23:17:56 +08:00
|
|
|
getEntry(h, RPMTAG_FILELINKTOS, &type,
|
|
|
|
(void **) &fileLinktoList, &count);
|
1996-01-06 02:12:17 +08:00
|
|
|
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
if (!((queryFlags & QUERY_FOR_DOCS) ||
|
|
|
|
(queryFlags & QUERY_FOR_CONFIG))
|
|
|
|
|| ((queryFlags & QUERY_FOR_DOCS) &&
|
|
|
|
(fileFlagsList[i] & RPMFILE_DOC))
|
|
|
|
|| ((queryFlags & QUERY_FOR_CONFIG) &&
|
|
|
|
(fileFlagsList[i] & RPMFILE_CONFIG))) {
|
|
|
|
|
1996-02-19 12:50:33 +08:00
|
|
|
if (!isVerbose()) {
|
|
|
|
prefix ? fputs(prefix, stdout) : 0;
|
|
|
|
if (queryFlags & QUERY_FOR_STATE) {
|
1996-03-30 03:24:52 +08:00
|
|
|
if (fileStatesList) {
|
|
|
|
switch (fileStatesList[i]) {
|
|
|
|
case RPMFILE_STATE_NORMAL:
|
1996-03-30 04:50:53 +08:00
|
|
|
fputs("normal ", stdout); break;
|
1996-03-30 03:24:52 +08:00
|
|
|
case RPMFILE_STATE_REPLACED:
|
1996-03-30 04:50:53 +08:00
|
|
|
fputs("replaced ", stdout); break;
|
|
|
|
case RPMFILE_STATE_NOTINSTALLED:
|
|
|
|
fputs("not installed ", stdout); break;
|
1996-03-30 03:24:52 +08:00
|
|
|
default:
|
1996-03-30 04:50:53 +08:00
|
|
|
fputs("(unknown) ", stdout);
|
1996-03-30 03:24:52 +08:00
|
|
|
}
|
|
|
|
} else {
|
1996-03-30 04:50:53 +08:00
|
|
|
fputs( "(no state) ", stdout);
|
1996-02-19 12:50:33 +08:00
|
|
|
}
|
1996-01-06 02:12:17 +08:00
|
|
|
}
|
1996-02-19 12:50:33 +08:00
|
|
|
|
|
|
|
puts(fileList[i]);
|
|
|
|
} else if (fileOwnerList)
|
|
|
|
printFileInfo(fileList[i], fileSizeList[i],
|
|
|
|
fileModeList[i], fileMTimeList[i],
|
|
|
|
fileRdevList[i], fileOwnerList[i],
|
|
|
|
fileGroupList[i], fileUIDList[i],
|
1996-02-19 23:17:56 +08:00
|
|
|
fileGIDList[i], fileLinktoList[i]);
|
1996-02-19 12:50:33 +08:00
|
|
|
else
|
|
|
|
printFileInfo(fileList[i], fileSizeList[i],
|
|
|
|
fileModeList[i], fileMTimeList[i],
|
|
|
|
fileRdevList[i], NULL,
|
|
|
|
NULL, fileUIDList[i],
|
1996-02-19 23:17:56 +08:00
|
|
|
fileGIDList[i], fileLinktoList[i]);
|
1995-12-28 04:08:35 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1996-01-06 02:12:17 +08:00
|
|
|
free(fileList);
|
1996-02-19 23:17:56 +08:00
|
|
|
free(fileLinktoList);
|
1996-02-19 12:50:33 +08:00
|
|
|
if (fileOwnerList) free(fileOwnerList);
|
|
|
|
if (fileGroupList) free(fileGroupList);
|
1996-01-06 02:12:17 +08:00
|
|
|
}
|
1995-12-28 04:08:35 +08:00
|
|
|
}
|
1996-04-16 06:21:30 +08:00
|
|
|
|
|
|
|
if (queryFlags & QUERY_FOR_SCRIPTS) {
|
|
|
|
printScript(h, "preinstall script:\n", RPMTAG_PREIN);
|
|
|
|
printScript(h, "postinstall script:\n", RPMTAG_POSTIN);
|
|
|
|
printScript(h, "preuninstall script:\n", RPMTAG_PREUN);
|
|
|
|
printScript(h, "preuninstall script:\n", RPMTAG_POSTUN);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void printScript(Header h, char * label, int tag) {
|
|
|
|
int type, count;
|
|
|
|
char * script;
|
|
|
|
|
|
|
|
if (getEntry(h, tag, &type, (void **) &script, &count)) {
|
|
|
|
printf("%s", label);
|
|
|
|
printf("%s\n", script);
|
1996-01-06 02:12:17 +08:00
|
|
|
}
|
|
|
|
}
|
1995-12-28 04:08:35 +08:00
|
|
|
|
1996-02-19 12:50:33 +08:00
|
|
|
static void printFileInfo(char * name, unsigned int size, unsigned short mode,
|
|
|
|
unsigned int mtime, unsigned short rdev,
|
1996-02-19 23:17:56 +08:00
|
|
|
char * owner, char * group, int uid, int gid,
|
|
|
|
char * linkto) {
|
1996-02-20 00:29:15 +08:00
|
|
|
char perms[11];
|
1996-02-19 12:50:33 +08:00
|
|
|
char sizefield[15];
|
|
|
|
char ownerfield[9], groupfield[9];
|
|
|
|
char timefield[100] = "";
|
|
|
|
time_t themtime;
|
|
|
|
time_t currenttime;
|
|
|
|
static int thisYear = 0;
|
|
|
|
static int thisMonth = 0;
|
|
|
|
struct tm * tstruct;
|
1996-02-19 23:17:56 +08:00
|
|
|
char * namefield = name;
|
1996-02-20 00:29:15 +08:00
|
|
|
|
1996-03-05 06:47:35 +08:00
|
|
|
strcpy(perms, "-----------");
|
1996-02-19 12:50:33 +08:00
|
|
|
|
|
|
|
if (!thisYear) {
|
|
|
|
currenttime = time(NULL);
|
|
|
|
tstruct = localtime(¤ttime);
|
|
|
|
thisYear = tstruct->tm_year;
|
|
|
|
thisMonth = tstruct->tm_mon;
|
|
|
|
}
|
|
|
|
|
1996-03-05 06:47:35 +08:00
|
|
|
if (mode & S_ISVTX) perms[9] = 't';
|
1996-02-19 12:50:33 +08:00
|
|
|
|
1996-03-05 06:47:35 +08:00
|
|
|
if (mode & S_IRUSR) perms[1] = 'r';
|
|
|
|
if (mode & S_IWUSR) perms[2] = 'w';
|
|
|
|
if (mode & S_IXUSR) perms[3] = 'x';
|
|
|
|
|
|
|
|
if (mode & S_IRGRP) perms[4] = 'r';
|
|
|
|
if (mode & S_IWGRP) perms[5] = 'w';
|
|
|
|
if (mode & S_IXGRP) perms[6] = 'x';
|
|
|
|
|
|
|
|
if (mode & S_IROTH) perms[7] = 'r';
|
|
|
|
if (mode & S_IWOTH) perms[8] = 'w';
|
|
|
|
if (mode & S_IXOTH) perms[9] = 'x';
|
|
|
|
|
|
|
|
if (mode & S_ISUID) {
|
|
|
|
if (mode & S_IXUSR)
|
|
|
|
perms[3] = 's';
|
|
|
|
else
|
|
|
|
perms[3] = 'S';
|
|
|
|
}
|
1996-02-19 12:50:33 +08:00
|
|
|
|
1996-03-05 06:47:35 +08:00
|
|
|
if (mode & S_ISGID) {
|
|
|
|
if (mode & S_IXGRP)
|
|
|
|
perms[6] = 's';
|
|
|
|
else
|
|
|
|
perms[6] = 'S';
|
|
|
|
}
|
1996-02-19 12:50:33 +08:00
|
|
|
|
|
|
|
if (owner)
|
|
|
|
strncpy(ownerfield, owner, 8);
|
|
|
|
else
|
|
|
|
sprintf(ownerfield, "%-8d", uid);
|
|
|
|
|
|
|
|
if (group)
|
|
|
|
strncpy(groupfield, group, 8);
|
|
|
|
else
|
|
|
|
sprintf(groupfield, "%-8d", gid);
|
|
|
|
|
|
|
|
/* this is normally right */
|
|
|
|
sprintf(sizefield, "%10d", size);
|
|
|
|
|
|
|
|
/* this knows too much about dev_t */
|
|
|
|
|
|
|
|
if (S_ISDIR(mode))
|
|
|
|
perms[0] = 'd';
|
1996-02-19 23:17:56 +08:00
|
|
|
else if (S_ISLNK(mode)) {
|
1996-02-19 12:50:33 +08:00
|
|
|
perms[0] = 'l';
|
1996-02-19 23:17:56 +08:00
|
|
|
namefield = alloca(strlen(name) + strlen(linkto) + 10);
|
|
|
|
sprintf(namefield, "%s -> %s", name, linkto);
|
|
|
|
}
|
1996-02-19 12:50:33 +08:00
|
|
|
else if (S_ISFIFO(mode))
|
|
|
|
perms[0] = 'p';
|
|
|
|
else if (S_ISSOCK(mode))
|
|
|
|
perms[0] = 'l';
|
|
|
|
else if (S_ISCHR(mode)) {
|
|
|
|
perms[0] = 'c';
|
|
|
|
sprintf(sizefield, "%3d, %3d", rdev >> 8, rdev & 0xFF);
|
|
|
|
} else if (S_ISBLK(mode)) {
|
|
|
|
perms[0] = 'b';
|
|
|
|
sprintf(sizefield, "%3d, %3d", rdev >> 8, rdev & 0xFF);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* this is important if sizeof(int_32) ! sizeof(time_t) */
|
|
|
|
themtime = mtime;
|
|
|
|
tstruct = localtime(&themtime);
|
|
|
|
|
|
|
|
if (tstruct->tm_year == thisYear ||
|
|
|
|
((tstruct->tm_year + 1) == thisYear && tstruct->tm_mon > thisMonth))
|
|
|
|
strftime(timefield, sizeof(timefield) - 1, "%b %d %H:%M", tstruct);
|
|
|
|
else
|
|
|
|
strftime(timefield, sizeof(timefield) - 1, "%b %d %Y", tstruct);
|
|
|
|
|
|
|
|
printf("%s %8s %8s %10s %s %s\n", perms, ownerfield, groupfield,
|
1996-02-19 23:17:56 +08:00
|
|
|
sizefield, timefield, namefield);
|
1996-02-19 12:50:33 +08:00
|
|
|
}
|
|
|
|
|
1996-04-02 11:36:00 +08:00
|
|
|
static void showMatches(rpmdb db, dbIndexSet matches, int queryFlags,
|
|
|
|
char * queryFormat) {
|
1996-01-06 02:12:17 +08:00
|
|
|
int i;
|
|
|
|
Header h;
|
|
|
|
|
|
|
|
for (i = 0; i < matches.count; i++) {
|
1996-02-15 04:56:22 +08:00
|
|
|
if (matches.recs[i].recOffset) {
|
|
|
|
message(MESS_DEBUG, "querying record number %d\n",
|
|
|
|
matches.recs[i].recOffset);
|
|
|
|
|
|
|
|
h = rpmdbGetRecord(db, matches.recs[i].recOffset);
|
|
|
|
if (!h) {
|
|
|
|
fprintf(stderr, "error: could not read database record\n");
|
|
|
|
} else {
|
1996-04-02 11:36:00 +08:00
|
|
|
printHeader(h, queryFlags, queryFormat);
|
1996-02-15 04:56:22 +08:00
|
|
|
freeHeader(h);
|
|
|
|
}
|
1996-01-06 02:12:17 +08:00
|
|
|
}
|
1995-12-28 04:08:35 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1996-04-03 11:45:27 +08:00
|
|
|
int doQuery(char * prefix, enum querysources source, int queryFlags,
|
1996-04-02 11:36:00 +08:00
|
|
|
char * arg, char * queryFormat) {
|
1995-12-28 04:08:35 +08:00
|
|
|
Header h;
|
|
|
|
int offset;
|
1996-01-06 02:12:17 +08:00
|
|
|
int fd;
|
|
|
|
int rc;
|
|
|
|
int isSource;
|
1995-12-28 04:08:35 +08:00
|
|
|
rpmdb db;
|
|
|
|
dbIndexSet matches;
|
1996-03-01 11:29:18 +08:00
|
|
|
int recNumber;
|
1996-04-03 11:45:27 +08:00
|
|
|
int retcode = 0;
|
1995-12-28 04:08:35 +08:00
|
|
|
|
1996-01-09 03:44:29 +08:00
|
|
|
if (source != QUERY_SRPM && source != QUERY_RPM) {
|
1996-02-19 12:50:33 +08:00
|
|
|
if (rpmdbOpen(prefix, &db, O_RDONLY, 0644)) {
|
1996-01-09 03:44:29 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
1995-12-28 04:08:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (source) {
|
|
|
|
case QUERY_SRPM:
|
|
|
|
case QUERY_RPM:
|
1996-01-06 02:12:17 +08:00
|
|
|
fd = open(arg, O_RDONLY);
|
1996-01-14 06:00:57 +08:00
|
|
|
if (fd < 0) {
|
1996-01-06 02:12:17 +08:00
|
|
|
fprintf(stderr, "open of %s failed: %s\n", arg, strerror(errno));
|
|
|
|
} else {
|
|
|
|
rc = pkgReadHeader(fd, &h, &isSource);
|
|
|
|
close(fd);
|
|
|
|
switch (rc) {
|
|
|
|
case 0:
|
1996-03-30 03:39:41 +08:00
|
|
|
if (!h) {
|
|
|
|
fprintf(stderr, "old format source packages cannot be "
|
|
|
|
"queried\n");
|
|
|
|
} else {
|
1996-04-02 11:36:00 +08:00
|
|
|
printHeader(h, queryFlags, queryFormat);
|
1996-03-30 03:39:41 +08:00
|
|
|
freeHeader(h);
|
|
|
|
}
|
1996-01-06 02:12:17 +08:00
|
|
|
break;
|
|
|
|
case 1:
|
1996-04-06 01:35:45 +08:00
|
|
|
fprintf(stderr, "%s does not appear to be a RPM package\n",
|
|
|
|
arg);
|
|
|
|
/* fallthrough */
|
|
|
|
case 2:
|
|
|
|
fprintf(stderr, "query of %s failed\n", arg);
|
1996-04-03 11:45:27 +08:00
|
|
|
retcode = 1;
|
1996-01-06 02:12:17 +08:00
|
|
|
}
|
1996-03-30 03:39:41 +08:00
|
|
|
|
1996-01-06 02:12:17 +08:00
|
|
|
}
|
|
|
|
|
1995-12-28 04:08:35 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case QUERY_ALL:
|
|
|
|
offset = rpmdbFirstRecNum(db);
|
|
|
|
while (offset) {
|
|
|
|
h = rpmdbGetRecord(db, offset);
|
|
|
|
if (!h) {
|
|
|
|
fprintf(stderr, "could not read database record!\n");
|
1996-04-03 11:45:27 +08:00
|
|
|
return 1;
|
1995-12-28 04:08:35 +08:00
|
|
|
}
|
1996-04-02 11:36:00 +08:00
|
|
|
printHeader(h, queryFlags, queryFormat);
|
1995-12-28 04:08:35 +08:00
|
|
|
freeHeader(h);
|
|
|
|
offset = rpmdbNextRecNum(db, offset);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
1996-01-06 02:12:17 +08:00
|
|
|
case QUERY_SGROUP:
|
|
|
|
case QUERY_GROUP:
|
|
|
|
if (rpmdbFindByGroup(db, arg, &matches)) {
|
1996-05-22 22:37:19 +08:00
|
|
|
fprintf(stderr, "group %s does not contain any packages\n", arg);
|
1996-04-03 11:45:27 +08:00
|
|
|
retcode = 1;
|
1996-01-06 02:12:17 +08:00
|
|
|
} else {
|
1996-04-02 11:36:00 +08:00
|
|
|
showMatches(db, matches, queryFlags, queryFormat);
|
1996-01-06 02:12:17 +08:00
|
|
|
freeDBIndexRecord(matches);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
1996-06-10 05:47:42 +08:00
|
|
|
case QUERY_PROVIDES:
|
|
|
|
if (rpmdbFindByProvides(db, arg, &matches)) {
|
|
|
|
fprintf(stderr, "no package provides %s\n", arg);
|
|
|
|
retcode = 1;
|
|
|
|
} else {
|
|
|
|
showMatches(db, matches, queryFlags, queryFormat);
|
|
|
|
freeDBIndexRecord(matches);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QUERY_REQUIREDBY:
|
|
|
|
if (rpmdbFindByRequiredBy(db, arg, &matches)) {
|
|
|
|
fprintf(stderr, "no package requires %s\n", arg);
|
|
|
|
retcode = 1;
|
|
|
|
} else {
|
|
|
|
showMatches(db, matches, queryFlags, queryFormat);
|
|
|
|
freeDBIndexRecord(matches);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
1995-12-28 04:08:35 +08:00
|
|
|
case QUERY_SPATH:
|
|
|
|
case QUERY_PATH:
|
1996-04-16 05:06:26 +08:00
|
|
|
if (*arg != '/') {
|
|
|
|
char path[255];
|
|
|
|
if (realpath(arg, path) != NULL)
|
|
|
|
arg = path;
|
|
|
|
}
|
1995-12-28 04:08:35 +08:00
|
|
|
if (rpmdbFindByFile(db, arg, &matches)) {
|
1996-01-06 02:12:17 +08:00
|
|
|
fprintf(stderr, "file %s is not owned by any package\n", arg);
|
1996-04-03 11:45:27 +08:00
|
|
|
retcode = 1;
|
1995-12-28 04:08:35 +08:00
|
|
|
} else {
|
1996-04-02 11:36:00 +08:00
|
|
|
showMatches(db, matches, queryFlags, queryFormat);
|
1996-01-06 02:12:17 +08:00
|
|
|
freeDBIndexRecord(matches);
|
1995-12-28 04:08:35 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QUERY_SPACKAGE:
|
|
|
|
case QUERY_PACKAGE:
|
1996-06-03 02:04:36 +08:00
|
|
|
if (queryFlags & QUERY_BY_NUMBER) {
|
1996-05-22 22:37:19 +08:00
|
|
|
char *end = NULL;
|
|
|
|
recNumber = strtoul(arg, &end, 10);
|
|
|
|
if ((*end) || (end == arg) || (recNumber == ULONG_MAX)) {
|
1996-06-03 02:04:36 +08:00
|
|
|
fprintf(stderr, "invalid package number: %s\n", arg);
|
1996-05-22 22:37:19 +08:00
|
|
|
return 1;
|
|
|
|
}
|
1996-03-01 11:29:18 +08:00
|
|
|
message(MESS_DEBUG, "showing package: %d\n", recNumber);
|
|
|
|
h = rpmdbGetRecord(db, recNumber);
|
|
|
|
|
1996-04-03 11:45:27 +08:00
|
|
|
if (!h) {
|
1996-03-01 11:29:18 +08:00
|
|
|
fprintf(stderr, "record %d could not be read\n", recNumber);
|
1996-04-03 11:45:27 +08:00
|
|
|
retcode = 1;
|
|
|
|
} else {
|
1996-04-02 11:36:00 +08:00
|
|
|
printHeader(h, queryFlags, queryFormat);
|
1996-03-01 11:29:18 +08:00
|
|
|
freeHeader(h);
|
|
|
|
}
|
1996-01-06 02:12:17 +08:00
|
|
|
} else {
|
1996-03-01 11:29:18 +08:00
|
|
|
rc = findPackageByLabel(db, arg, &matches);
|
1996-04-03 11:45:27 +08:00
|
|
|
if (rc == 1) {
|
|
|
|
retcode = 1;
|
1996-03-01 11:29:18 +08:00
|
|
|
fprintf(stderr, "package %s is not installed\n", arg);
|
1996-04-03 11:45:27 +08:00
|
|
|
} else if (rc == 2) {
|
|
|
|
retcode = 1;
|
1996-03-01 11:29:18 +08:00
|
|
|
fprintf(stderr, "error looking for package %s\n", arg);
|
|
|
|
} else {
|
1996-04-02 11:36:00 +08:00
|
|
|
showMatches(db, matches, queryFlags, queryFormat);
|
1996-03-01 11:29:18 +08:00
|
|
|
freeDBIndexRecord(matches);
|
|
|
|
}
|
1996-01-06 02:12:17 +08:00
|
|
|
}
|
1995-12-28 04:08:35 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
1996-01-09 03:44:29 +08:00
|
|
|
if (source != QUERY_SRPM && source != QUERY_RPM) {
|
|
|
|
rpmdbClose(db);
|
|
|
|
}
|
1996-04-03 11:45:27 +08:00
|
|
|
|
|
|
|
return retcode;
|
1995-12-28 04:08:35 +08:00
|
|
|
}
|
1996-02-15 04:56:22 +08:00
|
|
|
|
|
|
|
/* 0 found matches */
|
|
|
|
/* 1 no matches */
|
|
|
|
/* 2 error */
|
|
|
|
int findPackageByLabel(rpmdb db, char * arg, dbIndexSet * matches) {
|
|
|
|
char * localarg, * chptr;
|
|
|
|
char * release;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
if (!strlen(arg)) return 1;
|
|
|
|
|
|
|
|
/* did they give us just a name? */
|
|
|
|
rc = findMatches(db, arg, NULL, NULL, matches);
|
|
|
|
if (rc != 1) return rc;
|
|
|
|
|
|
|
|
/* maybe a name and a release */
|
|
|
|
localarg = alloca(strlen(arg) + 1);
|
|
|
|
strcpy(localarg, arg);
|
|
|
|
|
|
|
|
chptr = (localarg + strlen(localarg)) - 1;
|
|
|
|
while (chptr > localarg && *chptr != '-') chptr--;
|
|
|
|
if (chptr == localarg) return 1;
|
|
|
|
|
|
|
|
*chptr = '\0';
|
|
|
|
rc = findMatches(db, localarg, chptr + 1, NULL, matches);
|
|
|
|
if (rc != 1) return rc;
|
|
|
|
|
|
|
|
/* how about name-version-release? */
|
|
|
|
|
|
|
|
release = chptr + 1;
|
|
|
|
while (chptr > localarg && *chptr != '-') chptr--;
|
|
|
|
if (chptr == localarg) return 1;
|
|
|
|
|
|
|
|
*chptr = '\0';
|
|
|
|
return findMatches(db, localarg, chptr + 1, release, matches);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 0 found matches */
|
|
|
|
/* 1 no matches */
|
|
|
|
/* 2 error */
|
|
|
|
int findMatches(rpmdb db, char * name, char * version, char * release,
|
|
|
|
dbIndexSet * matches) {
|
|
|
|
int gotMatches;
|
|
|
|
int rc;
|
|
|
|
int i;
|
|
|
|
char * pkgRelease, * pkgVersion;
|
|
|
|
int count, type;
|
|
|
|
int goodRelease, goodVersion;
|
|
|
|
Header h;
|
|
|
|
|
|
|
|
if ((rc = rpmdbFindPackage(db, name, matches))) {
|
|
|
|
if (rc == -1) return 2; else return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!version && !release) return 0;
|
|
|
|
|
|
|
|
gotMatches = 0;
|
|
|
|
|
|
|
|
/* make sure the version and releases match */
|
|
|
|
for (i = 0; i < matches->count; i++) {
|
|
|
|
if (matches->recs[i].recOffset) {
|
|
|
|
h = rpmdbGetRecord(db, matches->recs[i].recOffset);
|
|
|
|
if (!h) {
|
|
|
|
fprintf(stderr, "error: could not read database record\n");
|
|
|
|
freeDBIndexRecord(*matches);
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
getEntry(h, RPMTAG_VERSION, &type, (void **) &pkgVersion, &count);
|
|
|
|
getEntry(h, RPMTAG_RELEASE, &type, (void **) &pkgRelease, &count);
|
|
|
|
|
|
|
|
goodRelease = goodVersion = 1;
|
|
|
|
|
|
|
|
if (release && strcmp(release, pkgRelease)) goodRelease = 0;
|
|
|
|
if (version && strcmp(version, pkgVersion)) goodVersion = 0;
|
|
|
|
|
|
|
|
if (goodRelease && goodVersion)
|
|
|
|
gotMatches = 1;
|
|
|
|
else
|
|
|
|
matches->recs[i].recOffset = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!gotMatches) {
|
|
|
|
freeDBIndexRecord(*matches);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
1996-04-03 11:45:27 +08:00
|
|
|
|
|
|
|
void queryPrintTags(void) {
|
|
|
|
const struct rpmTagTableEntry * t;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0, t = rpmTagTable; i < rpmTagTableSize; i++, t++) {
|
|
|
|
printf("%s\n", t->name);
|
|
|
|
}
|
|
|
|
}
|