15 /*@access Header@*/ /* XXX compared with NULL */
16 /*@access rpmdbMatchIterator@*/ /* XXX compared with NULL */
18 /* ======================================================================== */
19 static char * permsString(int mode)
21 char *perms = xstrdup("----------");
25 else if (S_ISLNK(mode))
27 else if (S_ISFIFO(mode))
29 else if (S_ISSOCK(mode))
31 else if (S_ISCHR(mode))
33 else if (S_ISBLK(mode))
37 if (mode & S_IRUSR) perms[1] = 'r';
38 if (mode & S_IWUSR) perms[2] = 'w';
39 if (mode & S_IXUSR) perms[3] = 'x';
41 if (mode & S_IRGRP) perms[4] = 'r';
42 if (mode & S_IWGRP) perms[5] = 'w';
43 if (mode & S_IXGRP) perms[6] = 'x';
45 if (mode & S_IROTH) perms[7] = 'r';
46 if (mode & S_IWOTH) perms[8] = 'w';
47 if (mode & S_IXOTH) perms[9] = 'x';
50 perms[3] = ((mode & S_IXUSR) ? 's' : 'S');
53 perms[6] = ((mode & S_IXGRP) ? 's' : 'S');
56 perms[9] = ((mode & S_IXOTH) ? 't' : 'T');
62 static void printFileInfo(FILE *fp, const char * name,
63 unsigned int size, unsigned short mode,
65 unsigned short rdev, unsigned int nlink,
66 const char * owner, const char * group,
67 int uid, int gid, const char * linkto)
70 char ownerfield[9], groupfield[9];
71 char timefield[100] = "";
72 time_t when = mtime; /* important if sizeof(int_32) ! sizeof(time_t) */
75 static struct tm nowtm;
76 const char * namefield = name;
79 /* On first call, grab snapshot of now */
83 nowtm = *tm; /* structure assignment */
86 perms = permsString(mode);
89 strncpy(ownerfield, owner, 8);
91 sprintf(ownerfield, "%-8d", uid);
95 strncpy(groupfield, group, 8);
97 sprintf(groupfield, "%-8d", gid);
100 /* this is normally right */
101 sprintf(sizefield, "%12u", size);
103 /* this knows too much about dev_t */
106 char *nf = alloca(strlen(name) + sizeof(" -> ") + strlen(linkto));
107 sprintf(nf, "%s -> %s", name, linkto);
109 } else if (S_ISCHR(mode)) {
111 sprintf(sizefield, "%3u, %3u", ((unsigned)(rdev >> 8) & 0xff),
112 ((unsigned)rdev & 0xff));
113 } else if (S_ISBLK(mode)) {
115 sprintf(sizefield, "%3u, %3u", ((unsigned)(rdev >> 8) & 0xff),
116 ((unsigned)rdev & 0xff));
119 /* Convert file mtime to display format */
120 tm = localtime(&when);
122 if (now > when + 6L * 30L * 24L * 60L * 60L || /* Old. */
123 now < when - 60L * 60L) /* In the future. */
125 /* The file is fairly old or in the future.
126 * POSIX says the cutoff is 6 months old;
127 * approximate this by 6*30 days.
128 * Allow a 1 hour slop factor for what is considered "the future",
129 * to allow for NFS server/client clock disagreement.
130 * Show the year instead of the time of day.
136 (void)strftime(timefield, sizeof(timefield) - 1, fmt, tm);
139 fprintf(fp, "%s %4d %-8s%-8s %10s %s %s\n", perms, (int)nlink,
140 ownerfield, groupfield, sizefield, timefield, namefield);
141 if (perms) free(perms);
144 static int queryHeader(FILE *fp, Header h, const char * chptr)
149 str = headerSprintf(h, chptr, rpmTagTable, rpmHeaderFormats, &errstr);
151 fprintf(stderr, _("error in format: %s\n"), errstr);
160 static int countLinks(int_16 * fileRdevList, int_32 * fileInodeList, int nfiles,
165 /* XXX rpm-3.3.12 has not RPMTAG_FILEINODES */
166 if (!(fileRdevList && fileInodeList && nfiles > 0))
168 while (nfiles-- > 0) {
169 if (fileRdevList[nfiles] != fileRdevList[xfile])
171 if (fileInodeList[nfiles] != fileInodeList[xfile])
178 int showQueryPackage(QVA_t *qva, /*@unused@*/rpmdb rpmdb, Header h)
180 FILE *fp = stdout; /* XXX FIXME: pass as arg */
181 int queryFlags = qva->qva_flags;
182 const char *queryFormat = qva->qva_queryFormat;
184 const char * name, * version, * release;
186 char * prefix = NULL;
187 const char ** dirNames, ** baseNames;
188 const char ** fileMD5List;
189 const char * fileStatesList;
190 const char ** fileOwnerList = NULL;
191 const char ** fileGroupList = NULL;
192 const char ** fileLinktoList;
193 int_32 * fileFlagsList, * fileMTimeList, * fileSizeList;
194 int_32 * fileUIDList = NULL;
195 int_32 * fileGIDList = NULL;
196 int_32 * fileInodeList = NULL;
197 uint_16 * fileModeList;
198 uint_16 * fileRdevList;
202 headerNVR(h, &name, &version, &release);
204 if (!queryFormat && !queryFlags) {
205 fprintf(fp, "%s-%s-%s\n", name, version, release);
208 queryHeader(fp, h, queryFormat);
210 if (queryFlags & QUERY_FOR_LIST) {
211 if (!headerGetEntry(h, RPMTAG_BASENAMES, &type,
212 (void **) &baseNames, &count)) {
213 fputs(_("(contains no files)"), fp);
216 if (!headerGetEntry(h, RPMTAG_FILESTATES, &type,
217 (void **) &fileStatesList, &count)) {
218 fileStatesList = NULL;
220 headerGetEntry(h, RPMTAG_DIRNAMES, NULL,
221 (void **) &dirNames, NULL);
222 headerGetEntry(h, RPMTAG_DIRINDEXES, NULL,
223 (void **) &dirIndexes, NULL);
224 headerGetEntry(h, RPMTAG_FILEFLAGS, &type,
225 (void **) &fileFlagsList, &count);
226 headerGetEntry(h, RPMTAG_FILESIZES, &type,
227 (void **) &fileSizeList, &count);
228 headerGetEntry(h, RPMTAG_FILEMODES, &type,
229 (void **) &fileModeList, &count);
230 headerGetEntry(h, RPMTAG_FILEMTIMES, &type,
231 (void **) &fileMTimeList, &count);
232 headerGetEntry(h, RPMTAG_FILERDEVS, &type,
233 (void **) &fileRdevList, &count);
234 headerGetEntry(h, RPMTAG_FILEINODES, &type,
235 (void **) &fileInodeList, &count);
236 headerGetEntry(h, RPMTAG_FILELINKTOS, &type,
237 (void **) &fileLinktoList, &count);
238 headerGetEntry(h, RPMTAG_FILEMD5S, &type,
239 (void **) &fileMD5List, &count);
241 if (!headerGetEntry(h, RPMTAG_FILEUIDS, &type,
242 (void **) &fileUIDList, &count)) {
244 } else if (!headerGetEntry(h, RPMTAG_FILEGIDS, &type,
245 (void **) &fileGIDList, &count)) {
249 if (!headerGetEntry(h, RPMTAG_FILEUSERNAME, &type,
250 (void **) &fileOwnerList, &count)) {
251 fileOwnerList = NULL;
252 } else if (!headerGetEntry(h, RPMTAG_FILEGROUPNAME, &type,
253 (void **) &fileGroupList, &count)) {
254 fileGroupList = NULL;
257 for (i = 0; i < count; i++) {
258 if (!((queryFlags & QUERY_FOR_DOCS) ||
259 (queryFlags & QUERY_FOR_CONFIG))
260 || ((queryFlags & QUERY_FOR_DOCS) &&
261 (fileFlagsList[i] & RPMFILE_DOC))
262 || ((queryFlags & QUERY_FOR_CONFIG) &&
263 (fileFlagsList[i] & RPMFILE_CONFIG))) {
266 prefix ? fputs(prefix, fp) : 0;
268 if (queryFlags & QUERY_FOR_STATE) {
269 if (fileStatesList) {
270 switch (fileStatesList[i]) {
271 case RPMFILE_STATE_NORMAL:
272 fputs(_("normal "), fp); break;
273 case RPMFILE_STATE_REPLACED:
274 fputs(_("replaced "), fp); break;
275 case RPMFILE_STATE_NOTINSTALLED:
276 fputs(_("not installed "), fp); break;
277 case RPMFILE_STATE_NETSHARED:
278 fputs(_("net shared "), fp); break;
280 fprintf(fp, _("(unknown %3d) "),
281 (int)fileStatesList[i]);
284 fputs( _("(no state) "), fp);
288 if (queryFlags & QUERY_FOR_DUMPFILES) {
289 fprintf(fp, "%s%s %d %d %s 0%o ",
290 dirNames[dirIndexes[i]], baseNames[i],
291 fileSizeList[i], fileMTimeList[i],
292 fileMD5List[i], fileModeList[i]);
294 if (fileOwnerList && fileGroupList)
295 fprintf(fp, "%s %s", fileOwnerList[i],
297 else if (fileUIDList && fileGIDList)
298 fprintf(fp, "%d %d", fileUIDList[i],
301 rpmError(RPMERR_INTERNAL, _("package has "
302 "neither file owner or id lists"));
305 fprintf(fp, " %s %s %u ",
306 fileFlagsList[i] & RPMFILE_CONFIG ? "1" : "0",
307 fileFlagsList[i] & RPMFILE_DOC ? "1" : "0",
308 (unsigned)fileRdevList[i]);
310 if (strlen(fileLinktoList[i]))
311 fprintf(fp, "%s\n", fileLinktoList[i]);
315 } else if (!rpmIsVerbose()) {
316 fputs(dirNames[dirIndexes[i]], fp);
317 fputs(baseNames[i], fp);
323 filespec = xmalloc(strlen(dirNames[dirIndexes[i]])
324 + strlen(baseNames[i]) + 1);
325 strcpy(filespec, dirNames[dirIndexes[i]]);
326 strcat(filespec, baseNames[i]);
328 nlink = countLinks(fileRdevList, fileInodeList, count, i);
329 if (fileOwnerList && fileGroupList) {
330 printFileInfo(fp, filespec, fileSizeList[i],
331 fileModeList[i], fileMTimeList[i],
332 fileRdevList[i], nlink,
334 fileGroupList[i], -1,
335 -1, fileLinktoList[i]);
336 } else if (fileUIDList && fileGIDList) {
337 printFileInfo(fp, filespec, fileSizeList[i],
338 fileModeList[i], fileMTimeList[i],
339 fileRdevList[i], nlink,
340 NULL, NULL, fileUIDList[i],
344 rpmError(RPMERR_INTERNAL, _("package has "
345 "neither file owner or id lists"));
355 free(fileLinktoList);
357 if (fileOwnerList) free(fileOwnerList);
358 if (fileGroupList) free(fileGroupList);
362 return 0; /* XXX FIXME: need real return code */
366 printNewSpecfile(Spec spec)
368 Header h = spec->packages->header;
369 struct speclines *sl = spec->sl;
370 struct spectags *st = spec->st;
371 const char * msgstr = NULL;
374 if (sl == NULL || st == NULL)
377 for (i = 0; i < st->st_ntags; i++) {
378 struct spectag * t = st->st_t + i;
379 const char * tn = tagName(t->t_tag);
384 (void) stpcpy( stpcpy( stpcpy( fmt, "%{"), tn), "}\n");
385 if (msgstr) free((void *)msgstr);
386 msgstr = headerSprintf(h, fmt, rpmTagTable, rpmHeaderFormats, &errstr);
387 if (msgstr == NULL) {
388 fprintf(stderr, _("can't query %s: %s\n"), tn, errstr);
395 free(sl->sl_lines[t->t_startx]);
396 sl->sl_lines[t->t_startx] = NULL;
397 if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG))
399 { char *buf = xmalloc(strlen(tn) + sizeof(": ") + strlen(msgstr));
400 (void) stpcpy( stpcpy( stpcpy(buf, tn), ": "), msgstr);
401 sl->sl_lines[t->t_startx] = buf;
404 case RPMTAG_DESCRIPTION:
405 for (j = 1; j < t->t_nlines; j++) {
406 free(sl->sl_lines[t->t_startx + j]);
407 sl->sl_lines[t->t_startx + j] = NULL;
409 if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG)) {
410 free(sl->sl_lines[t->t_startx]);
411 sl->sl_lines[t->t_startx] = NULL;
414 sl->sl_lines[t->t_startx + 1] = xstrdup(msgstr);
416 sl->sl_lines[t->t_startx + 2] = xstrdup("\n\n");
420 if (msgstr) free((void *)msgstr);
422 for (i = 0; i < sl->sl_nlines; i++) {
423 if (sl->sl_lines[i] == NULL)
425 printf("%s", sl->sl_lines[i]);
429 void rpmDisplayQueryTags(FILE * f)
431 const struct headerTagTableEntry * t;
433 const struct headerSprintfExtension * ext = rpmHeaderFormats;
435 for (i = 0, t = rpmTagTable; i < rpmTagTableSize; i++, t++) {
436 fprintf(f, "%s\n", t->name + 7);
440 if (ext->type == HEADER_EXT_MORE) {
444 /* XXX don't print query tags twice. */
445 for (i = 0, t = rpmTagTable; i < rpmTagTableSize; i++, t++) {
446 if (!strcmp(t->name, ext->name))
449 if (i >= rpmTagTableSize && ext->type == HEADER_EXT_TAG)
450 fprintf(f, "%s\n", ext->name + 7);
455 int showMatches(QVA_t *qva, rpmdbMatchIterator mi, QVF_t showPackage)
460 while ((h = rpmdbNextIterator(mi)) != NULL) {
462 if ((rc = showPackage(qva, rpmdbGetIteratorRpmDB(mi), h)) != 0)
465 rpmdbFreeIterator(mi);
470 * @todo Eliminate linkage loop into librpmbuild.a
472 int (*parseSpecVec) (Spec *specp, const char *specFile, const char *rootdir,
473 const char *buildRoot, int inBuildArch, const char *passPhrase,
474 char *cookie, int anyarch, int force) = NULL;
476 * @todo Eliminate linkage loop into librpmbuild.a
478 void (*freeSpecVec) (Spec spec) = NULL;
480 int rpmQueryVerify(QVA_t *qva, rpmQVSources source, const char * arg,
481 rpmdb rpmdb, QVF_t showPackage)
483 rpmdbMatchIterator mi = NULL;
493 const char ** argv = NULL;
496 rc = rpmGlob(arg, &argc, &argv);
499 for (i = 0; i < argc; i++) {
501 fd = Fopen(argv[i], "r.ufdio");
504 fprintf(stderr, _("open of %s failed: %s\n"), argv[i],
506 urlStrerror(argv[i]));
515 retcode = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
522 fprintf(stderr, _("old format source packages cannot "
527 retcode = showPackage(qva, rpmdb, h);
531 fprintf(stderr, _("%s does not appear to be a RPM package\n"),
535 fprintf(stderr, _("query of %s failed\n"), argv[i]);
541 for (i = 0; i < argc; i++)
542 free((void *)argv[i]);
548 if (showPackage != showQueryPackage)
551 /* XXX Eliminate linkage dependency loop */
552 if (parseSpecVec == NULL || freeSpecVec == NULL)
557 char * buildRoot = NULL;
559 char * passPhrase = "";
564 rc = parseSpecVec(&spec, arg, "/", buildRoot, inBuildArch, passPhrase,
565 cookie, anyarch, force);
566 if (rc || spec == NULL) {
568 fprintf(stderr, _("query of specfile %s failed, can't parse\n"), arg);
569 if (spec != NULL) freeSpecVec(spec);
575 printNewSpecfile(spec);
581 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
582 showPackage(qva, NULL, pkg->header);
588 /* RPMDBI_PACKAGES */
589 mi = rpmdbInitIterator(rpmdb, RPMDBI_PACKAGES, NULL, 0);
591 fprintf(stderr, _("no packages\n"));
594 retcode = showMatches(qva, mi, showPackage);
599 mi = rpmdbInitIterator(rpmdb, RPMTAG_GROUP, arg, 0);
601 fprintf(stderr, _("group %s does not contain any packages\n"), arg);
604 retcode = showMatches(qva, mi, showPackage);
608 case RPMQV_TRIGGEREDBY:
609 mi = rpmdbInitIterator(rpmdb, RPMTAG_TRIGGERNAME, arg, 0);
611 fprintf(stderr, _("no package triggers %s\n"), arg);
614 retcode = showMatches(qva, mi, showPackage);
618 case RPMQV_WHATREQUIRES:
619 mi = rpmdbInitIterator(rpmdb, RPMTAG_REQUIRENAME, arg, 0);
621 fprintf(stderr, _("no package requires %s\n"), arg);
624 retcode = showMatches(qva, mi, showPackage);
628 case RPMQV_WHATPROVIDES:
630 mi = rpmdbInitIterator(rpmdb, RPMTAG_PROVIDENAME, arg, 0);
632 fprintf(stderr, _("no package provides %s\n"), arg);
635 retcode = showMatches(qva, mi, showPackage);
644 for (s = arg; *s; s++)
645 if (!(*s == '.' || *s == '/')) break;
648 char fnbuf[PATH_MAX];
649 fn = /*@-unrecog@*/ realpath(arg, fnbuf) /*@=unrecog@*/;
650 fn = xstrdup( (fn ? fn : arg) );
653 (void) rpmCleanPath(fn);
655 mi = rpmdbInitIterator(rpmdb, RPMTAG_BASENAMES, fn, 0);
658 if (access(fn, F_OK) != 0)
662 fprintf(stderr, _("file %s: %s\n"), fn, strerror(myerrno));
665 fprintf(stderr, _("file %s is not owned by any package\n"), fn);
670 retcode = showMatches(qva, mi, showPackage);
677 const char * myarg = arg;
680 /* XXX should be in strtoul */
689 recOffset = strtoul(myarg, &end, mybase);
690 if ((*end) || (end == arg) || (recOffset == ULONG_MAX)) {
691 fprintf(stderr, _("invalid package number: %s\n"), arg);
694 rpmMessage(RPMMESS_DEBUG, _("package record number: %u\n"), recOffset);
695 /* RPMDBI_PACKAGES */
696 mi = rpmdbInitIterator(rpmdb, RPMDBI_PACKAGES, &recOffset, sizeof(recOffset));
698 fprintf(stderr, _("record %d could not be read\n"), recOffset);
701 retcode = showMatches(qva, mi, showPackage);
706 /* XXX HACK to get rpmdbFindByLabel out of the API */
707 mi = rpmdbInitIterator(rpmdb, RPMDBI_LABEL, arg, 0);
709 fprintf(stderr, _("package %s is not installed\n"), arg);
712 retcode = showMatches(qva, mi, showPackage);
720 int rpmQuery(QVA_t *qva, rpmQVSources source, const char * arg)
730 if (rpmdbOpen(qva->qva_prefix, &rpmdb, O_RDONLY, 0644))
735 rc = rpmQueryVerify(qva, source, arg, rpmdb, showQueryPackage);