eliminate old rpmrc configuration syntax.
[tools/librpm-tizen.git] / lib / query.c
1 #include "system.h"
2
3 #ifndef PATH_MAX
4 # define PATH_MAX 255
5 #endif
6
7 #include "build/rpmbuild.h"
8 #include "popt/popt.h"
9 #include "url.h"
10
11 static char * permsString(int mode);
12 static void printHeader(Header h, int queryFlags, const char * queryFormat);
13 static void showMatches(rpmdb db, dbiIndexSet matches, int queryFlags, 
14                         const char * queryFormat);
15 static void printFileInfo(char * name, unsigned int size, unsigned short mode,
16                           unsigned int mtime, unsigned short rdev,
17                           char * owner, char * group, int uid, int gid,
18                           char * linkto);
19
20 #define POPT_QUERYFORMAT        1000
21 #define POPT_WHATREQUIRES       1001
22 #define POPT_WHATPROVIDES       1002
23 #define POPT_QUERYBYNUMBER      1003
24 #define POPT_TRIGGEREDBY        1004
25 #define POPT_DUMP               1005
26 #define POPT_SPECFILE           1006
27
28 static void queryArgCallback(poptContext con, enum poptCallbackReason reason,
29                              const struct poptOption * opt, const char * arg, 
30                              struct rpmQueryArguments * data);
31
32 struct poptOption rpmQuerySourcePoptTable[] = {
33         { NULL, '\0', POPT_ARG_CALLBACK | POPT_CBFLAG_INC_DATA, 
34                 queryArgCallback, 0, NULL, NULL },
35         { "file", 'f', 0, 0, 'f',
36                 N_("query package owning file"), "FILE" },
37         { "group", 'g', 0, 0, 'g',
38                 N_("query packages in group"), "GROUP" },
39         { "package", 'p', 0, 0, 'p',
40                 N_("query a package file"), NULL },
41         { "specfile", '\0', 0, 0, POPT_SPECFILE,
42                 N_("query a spec file"), NULL },
43         { "triggeredby", '\0', 0, 0, POPT_TRIGGEREDBY, 
44                 N_("query the pacakges triggered by the package"), "PACKAGE" },
45         { "whatrequires", '\0', 0, 0, POPT_WHATREQUIRES, 
46                 N_("query the packages which require a capability"), "CAPABILITY" },
47         { "whatprovides", '\0', 0, 0, POPT_WHATPROVIDES, 
48                 N_("query the packages which provide a capability"), "CAPABILITY" },
49         { 0, 0, 0, 0, 0,        NULL, NULL }
50 };
51
52 struct poptOption rpmQueryPoptTable[] = {
53         { NULL, '\0', POPT_ARG_CALLBACK | POPT_CBFLAG_INC_DATA, 
54                 queryArgCallback, 0, NULL, NULL },
55         { "configfiles", 'c', 0, 0, 'c',
56                 N_("list all configuration files"), NULL },
57         { "docfiles", 'd', 0, 0, 'd',
58                 N_("list all documetnation files"), NULL },
59         { "dump", '\0', 0, 0, POPT_DUMP,
60                 N_("dump basic file information"), NULL },
61         { "list", 'l', 0, 0, 'l',
62                 N_("list files in package"), NULL },
63         { "qf", '\0', POPT_ARG_STRING | POPT_ARGFLAG_DOC_HIDDEN, 0, 
64                 POPT_QUERYFORMAT, NULL, NULL },
65         { "querybynumber", '\0', POPT_ARGFLAG_DOC_HIDDEN, 0, 
66                 POPT_QUERYBYNUMBER, NULL, NULL },
67         { "queryformat", '\0', POPT_ARG_STRING, 0, POPT_QUERYFORMAT,
68                 N_("use the following query format"), "QUERYFORMAT" },
69         { "state", 's', 0, 0, 's',
70                 N_("display the states of the listed files"), NULL },
71         { "verbose", 'v', 0, 0, 'v',
72                 N_("display a verbose file listing"), NULL },
73         { 0, 0, 0, 0, 0,        NULL, NULL }
74 };
75
76 static void queryArgCallback(poptContext con, enum poptCallbackReason reason,
77                              const struct poptOption * opt, const char * arg, 
78                              struct rpmQueryArguments * data) {
79     int len;
80
81     switch (opt->val) {
82       case 'c': data->flags |= QUERY_FOR_CONFIG | QUERY_FOR_LIST; break;
83       case 'd': data->flags |= QUERY_FOR_DOCS | QUERY_FOR_LIST; break;
84       case 'l': data->flags |= QUERY_FOR_LIST; break;
85       case 's': data->flags |= QUERY_FOR_STATE | QUERY_FOR_LIST; break;
86       case POPT_DUMP: data->flags |= QUERY_FOR_DUMPFILES | QUERY_FOR_LIST; break;
87
88       case 'a': data->source |= QUERY_ALL; data->sourceCount++; break;
89       case 'f': data->source |= QUERY_PATH; data->sourceCount++; break;
90       case 'g': data->source |= QUERY_GROUP; data->sourceCount++; break;
91       case 'p': data->source |= QUERY_RPM; data->sourceCount++; break;
92       case 'v': rpmIncreaseVerbosity();  break;
93       case POPT_SPECFILE: data->source |= QUERY_SPECFILE; data->sourceCount++; break;
94       case POPT_WHATPROVIDES: data->source |= QUERY_WHATPROVIDES; 
95                               data->sourceCount++; break;
96       case POPT_WHATREQUIRES: data->source |= QUERY_WHATREQUIRES; 
97                               data->sourceCount++; break;
98       case POPT_QUERYBYNUMBER: data->source |= QUERY_DBOFFSET; 
99                               data->sourceCount++; break;
100       case POPT_TRIGGEREDBY: data->source |= QUERY_TRIGGEREDBY;
101                               data->sourceCount++; break;
102
103       case POPT_QUERYFORMAT:
104         if (data->queryFormat) {
105             len = strlen(data->queryFormat) + strlen(arg) + 1;
106             data->queryFormat = realloc(data->queryFormat, len);
107             strcat(data->queryFormat, arg);
108         } else {
109             data->queryFormat = malloc(strlen(arg) + 1);
110             strcpy(data->queryFormat, arg);
111         }
112         break;
113     }
114 }
115
116 static int queryHeader(Header h, const char * chptr) {
117     char * str;
118     char * error;
119
120     str = headerSprintf(h, chptr, rpmTagTable, rpmHeaderFormats, &error);
121     if (!str) {
122         fprintf(stderr, _("error in format: %s\n"), error);
123         return 1;
124     }
125
126     fputs(str, stdout);
127
128     return 0;
129 }
130
131 static void printHeader(Header h, int queryFlags, const char * queryFormat) {
132     char * name, * version, * release;
133     int_32 count, type;
134     char * prefix = NULL;
135     char ** fileList, ** fileMD5List;
136     char * fileStatesList;
137     char ** fileOwnerList = NULL;
138     char ** fileGroupList = NULL;
139     char ** fileLinktoList;
140     int_32 * fileFlagsList, * fileMTimeList, * fileSizeList;
141     int_32 * fileUIDList, * fileGIDList;
142     uint_16 * fileModeList;
143     uint_16 * fileRdevList;
144     int i;
145
146     headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &count);
147     headerGetEntry(h, RPMTAG_VERSION, &type, (void **) &version, &count);
148     headerGetEntry(h, RPMTAG_RELEASE, &type, (void **) &release, &count);
149
150     if (!queryFormat && !queryFlags) {
151         fprintf(stdout, "%s-%s-%s\n", name, version, release);
152     } else {
153         if (queryFormat)
154             queryHeader(h, queryFormat);
155
156         if (queryFlags & QUERY_FOR_LIST) {
157             if (!headerGetEntry(h, RPMTAG_FILENAMES, &type, (void **) &fileList, 
158                  &count)) {
159                 fputs(_("(contains no files)"), stdout);
160                 fputs("\n", stdout);
161             } else {
162                 if (!headerGetEntry(h, RPMTAG_FILESTATES, &type, 
163                          (void **) &fileStatesList, &count)) {
164                     fileStatesList = NULL;
165                 }
166                 headerGetEntry(h, RPMTAG_FILEFLAGS, &type, 
167                          (void **) &fileFlagsList, &count);
168                 headerGetEntry(h, RPMTAG_FILESIZES, &type, 
169                          (void **) &fileSizeList, &count);
170                 headerGetEntry(h, RPMTAG_FILEMODES, &type, 
171                          (void **) &fileModeList, &count);
172                 headerGetEntry(h, RPMTAG_FILEMTIMES, &type, 
173                          (void **) &fileMTimeList, &count);
174                 headerGetEntry(h, RPMTAG_FILERDEVS, &type, 
175                          (void **) &fileRdevList, &count);
176                 headerGetEntry(h, RPMTAG_FILELINKTOS, &type, 
177                          (void **) &fileLinktoList, &count);
178                 headerGetEntry(h, RPMTAG_FILEMD5S, &type, 
179                          (void **) &fileMD5List, &count);
180
181                 if (!headerGetEntry(h, RPMTAG_FILEUIDS, &type, 
182                          (void **) &fileUIDList, &count)) {
183                     fileUIDList = NULL;
184                 } else {
185                     headerGetEntry(h, RPMTAG_FILEGIDS, &type, 
186                              (void **) &fileGIDList, &count);
187                 }
188
189                 if (!headerGetEntry(h, RPMTAG_FILEUSERNAME, &type, 
190                          (void **) &fileOwnerList, &count)) {
191                     fileOwnerList = NULL;
192                 } else {
193                     headerGetEntry(h, RPMTAG_FILEGROUPNAME, &type, 
194                              (void **) &fileGroupList, &count);
195                 }
196
197                 for (i = 0; i < count; i++) {
198                     if (!((queryFlags & QUERY_FOR_DOCS) || 
199                           (queryFlags & QUERY_FOR_CONFIG)) 
200                         || ((queryFlags & QUERY_FOR_DOCS) && 
201                             (fileFlagsList[i] & RPMFILE_DOC))
202                         || ((queryFlags & QUERY_FOR_CONFIG) && 
203                             (fileFlagsList[i] & RPMFILE_CONFIG))) {
204
205                         if (!rpmIsVerbose())
206                             prefix ? fputs(prefix, stdout) : 0;
207
208                         if (queryFlags & QUERY_FOR_STATE) {
209                             if (fileStatesList) {
210                                 switch (fileStatesList[i]) {
211                                   case RPMFILE_STATE_NORMAL:
212                                     fputs(_("normal        "), stdout); break;
213                                   case RPMFILE_STATE_REPLACED:
214                                     fputs(_("replaced      "), stdout); break;
215                                   case RPMFILE_STATE_NETSHARED:
216                                     fputs(_("net shared    "), stdout); break;
217                                   case RPMFILE_STATE_NOTINSTALLED:
218                                     fputs(_("not installed "), stdout); break;
219                                   default:
220                                     fprintf(stdout, _("(unknown %3d) "), 
221                                           fileStatesList[i]);
222                                 }
223                             } else {
224                                 fputs(    _("(no state)    "), stdout);
225                             }
226                         }
227                             
228                         if (queryFlags & QUERY_FOR_DUMPFILES) {
229                             fprintf(stdout, "%s %d %d %s 0%o ", fileList[i],
230                                    fileSizeList[i], fileMTimeList[i],
231                                    fileMD5List[i], fileModeList[i]);
232
233                             if (fileOwnerList)
234                                 fprintf(stdout, "%s %s", fileOwnerList[i], 
235                                                 fileGroupList[i]);
236                             else if (fileUIDList)
237                                 fprintf(stdout, "%d %d", fileUIDList[i], 
238                                                 fileGIDList[i]);
239                             else {
240                                 rpmError(RPMERR_INTERNAL, _("package has "
241                                         "neither file owner or id lists"));
242                             }
243
244                             fprintf(stdout, " %s %s %u ", 
245                                  fileFlagsList[i] & RPMFILE_CONFIG ? "1" : "0",
246                                  fileFlagsList[i] & RPMFILE_DOC ? "1" : "0",
247                                  (unsigned)fileRdevList[i]);
248
249                             if (strlen(fileLinktoList[i]))
250                                 fprintf(stdout, "%s\n", fileLinktoList[i]);
251                             else
252                                 fprintf(stdout, "X\n");
253
254                         } else if (!rpmIsVerbose()) {
255                             fputs(fileList[i], stdout);
256                             fputs("\n", stdout);
257                         } else if (fileOwnerList) 
258                             printFileInfo(fileList[i], fileSizeList[i],
259                                           fileModeList[i], fileMTimeList[i],
260                                           fileRdevList[i], fileOwnerList[i], 
261                                           fileGroupList[i], -1, 
262                                           -1, fileLinktoList[i]);
263                         else if (fileUIDList) {
264                             printFileInfo(fileList[i], fileSizeList[i],
265                                           fileModeList[i], fileMTimeList[i],
266                                           fileRdevList[i], NULL, 
267                                           NULL, fileUIDList[i], 
268                                           fileGIDList[i], fileLinktoList[i]);
269                         } else {
270                             rpmError(RPMERR_INTERNAL, _("package has "
271                                     "neither file owner or id lists"));
272                         }
273                     }
274                 }
275             
276                 free(fileList);
277                 free(fileLinktoList);
278                 free(fileMD5List);
279                 if (fileOwnerList) free(fileOwnerList);
280                 if (fileGroupList) free(fileGroupList);
281             }
282         }
283     }
284 }
285
286 static char * permsString(int mode) {
287     static char perms[11];
288
289     strcpy(perms, "----------");
290    
291     if (mode & S_IRUSR) perms[1] = 'r';
292     if (mode & S_IWUSR) perms[2] = 'w';
293     if (mode & S_IXUSR) perms[3] = 'x';
294  
295     if (mode & S_IRGRP) perms[4] = 'r';
296     if (mode & S_IWGRP) perms[5] = 'w';
297     if (mode & S_IXGRP) perms[6] = 'x';
298
299     if (mode & S_IROTH) perms[7] = 'r';
300     if (mode & S_IWOTH) perms[8] = 'w';
301     if (mode & S_IXOTH) perms[9] = 'x';
302
303
304     if (mode & S_ISVTX)
305         perms[9] = ((mode & S_IXOTH) ? 't' : 'T');
306
307     if (mode & S_ISUID) {
308         if (mode & S_IXUSR) 
309             perms[3] = 's'; 
310         else
311             perms[3] = 'S'; 
312     }
313
314     if (mode & S_ISGID) {
315         if (mode & S_IXGRP) 
316             perms[6] = 's'; 
317         else
318             perms[6] = 'S'; 
319     }
320
321     if (S_ISDIR(mode)) 
322         perms[0] = 'd';
323     else if (S_ISLNK(mode)) {
324         perms[0] = 'l';
325     }
326     else if (S_ISFIFO(mode)) 
327         perms[0] = 'p';
328     else if (S_ISSOCK(mode)) 
329         perms[0] = 's';
330     else if (S_ISCHR(mode)) {
331         perms[0] = 'c';
332     } else if (S_ISBLK(mode)) {
333         perms[0] = 'b';
334     }
335
336     return perms;
337 }
338
339 static void printFileInfo(char * name, unsigned int size, unsigned short mode,
340                           unsigned int mtime, unsigned short rdev,
341                           char * owner, char * group, int uid, int gid,
342                           char * linkto) {
343     char sizefield[15];
344     char ownerfield[9], groupfield[9];
345     char timefield[100] = "";
346     time_t themtime;
347     time_t currenttime;
348     static int thisYear = 0;
349     static int thisMonth = 0;
350     struct tm * tstruct;
351     char * namefield = name;
352     char * perms;
353
354     perms = permsString(mode);
355
356     if (!thisYear) {
357         currenttime = time(NULL);
358         tstruct = localtime(&currenttime);
359         thisYear = tstruct->tm_year;
360         thisMonth = tstruct->tm_mon;
361     }
362
363     ownerfield[8] = groupfield[8] = '\0';
364
365     if (owner) 
366         strncpy(ownerfield, owner, 8);
367     else
368         sprintf(ownerfield, "%-8d", uid);
369
370     if (group) 
371         strncpy(groupfield, group, 8);
372     else 
373         sprintf(groupfield, "%-8d", gid);
374
375     /* this is normally right */
376     sprintf(sizefield, "%10u", size);
377
378     /* this knows too much about dev_t */
379
380     if (S_ISLNK(mode)) {
381         namefield = alloca(strlen(name) + strlen(linkto) + 10);
382         sprintf(namefield, "%s -> %s", name, linkto);
383     } else if (S_ISCHR(mode)) {
384         perms[0] = 'c';
385         sprintf(sizefield, "%3u, %3u", (rdev >> 8) & 0xff, rdev & 0xFF);
386     } else if (S_ISBLK(mode)) {
387         perms[0] = 'b';
388         sprintf(sizefield, "%3u, %3u", (rdev >> 8) & 0xff, rdev & 0xFF);
389     }
390
391     /* this is important if sizeof(int_32) ! sizeof(time_t) */
392     themtime = mtime;
393     tstruct = localtime(&themtime);
394
395     if (tstruct->tm_year == thisYear || 
396       ((tstruct->tm_year + 1) == thisYear && tstruct->tm_mon > thisMonth)) 
397         (void)strftime(timefield, sizeof(timefield) - 1, "%b %d %H:%M",tstruct);
398     else
399         (void)strftime(timefield, sizeof(timefield) - 1, "%b %d  %Y", tstruct);
400
401     fprintf(stdout, "%s %8s %8s %10s %s %s\n", perms, ownerfield, groupfield, 
402                 sizefield, timefield, namefield);
403 }
404
405 static void showMatches(rpmdb db, dbiIndexSet matches, int queryFlags, 
406                         const char * queryFormat) {
407     int i;
408     Header h;
409
410     for (i = 0; i < dbiIndexSetCount(matches); i++) {
411         unsigned int recOffset = dbiIndexRecordOffset(matches, i);
412         if (recOffset) {
413             rpmMessage(RPMMESS_DEBUG, _("querying record number %d\n"),
414                         recOffset);
415             
416             h = rpmdbGetRecord(db, recOffset);
417             if (h == NULL) {
418                 fprintf(stderr, _("error: could not read database record\n"));
419             } else {
420                 printHeader(h, queryFlags, queryFormat);
421                 headerFree(h);
422             }
423         }
424     }
425 }
426
427 extern int specedit;
428
429 static void
430 printNewSpecfile(Spec spec)
431 {
432     struct speclines *sl = spec->sl;
433     struct spectags *st = spec->st;
434     char buf[8192];
435     int i, j;
436
437     if (sl == NULL || st == NULL)
438         return;
439
440 #define SPECSPACKAGE    "specs"
441
442     for (i = 0; i < st->st_ntags; i++) {
443         char *msgstr;
444         struct spectag *t;
445         t = st->st_t + i;
446
447         /* XXX Summary tag often precedes name, so build msgid now. */
448         if (t->t_msgid == NULL) {
449             char *n;
450             headerGetEntry(spec->packages->header, RPMTAG_NAME, NULL,
451                 (void *) &n, NULL);
452             sprintf(buf, "%s(%s)", n, tagName(t->t_tag));
453             t->t_msgid = strdup(buf);
454         }
455         msgstr = strdup(dgettext(SPECSPACKAGE, t->t_msgid));
456
457         switch(t->t_tag) {
458         case RPMTAG_SUMMARY:
459         case RPMTAG_GROUP:
460             FREE(sl->sl_lines[t->t_startx]);
461             if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG))
462                 continue;
463             sprintf(buf, "%s: %s\n",
464                 ((t->t_tag == RPMTAG_GROUP) ? "Group" : "Summary"),
465                 msgstr);
466             sl->sl_lines[t->t_startx] = strdup(buf);
467             break;
468         case RPMTAG_DESCRIPTION:
469             for (j = 1; j < t->t_nlines; j++)
470                 FREE(sl->sl_lines[t->t_startx + j]);
471             if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG)) {
472                 FREE(sl->sl_lines[t->t_startx]);
473                 continue;
474             }
475             sl->sl_lines[t->t_startx + 1] = strdup(msgstr);
476             if (t->t_nlines > 2)
477                 sl->sl_lines[t->t_startx + 2] = strdup("\n\n");
478             break;
479         }
480     }
481
482     for (i = 0; i < sl->sl_nlines; i++) {
483         if (sl->sl_lines[i] == NULL)
484             continue;
485         printf("%s", sl->sl_lines[i]);
486     }
487 }
488
489 int rpmQuery(const char * prefix, enum rpmQuerySources source, int queryFlags, 
490              const char * arg, const char * queryFormat) {
491     Header h;
492     int offset;
493     int rc;
494     int isSource;
495     rpmdb db;
496     dbiIndexSet matches;
497     int recNumber;
498     int retcode = 0;
499     char *end = NULL;
500
501     switch (source) {
502     default:
503         if (rpmdbOpen(prefix, &db, O_RDONLY, 0644)) {
504             fprintf(stderr, _("rpmQuery: rpmdbOpen() failed\n"));
505             exit(1);
506         }
507         break;
508     case QUERY_RPM:
509     case QUERY_SPECFILE:
510         break;
511     }
512
513     switch (source) {
514       case QUERY_RPM:
515       { FD_t fd;
516
517         fd = ufdOpen(arg, O_RDONLY, 0);
518         if (fdFileno(fd) < 0) {
519             fprintf(stderr, _("open of %s failed\n"), arg);
520             ufdClose(fd);
521             retcode = 1;
522             break;
523         }
524
525         rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
526
527         ufdClose(fd);
528
529         switch (rc) {
530         case 0:
531             if (h == NULL) {
532                 fprintf(stderr, _("old format source packages cannot "
533                         "be queried\n"));
534             } else {
535                 printHeader(h, queryFlags, queryFormat);
536                 headerFree(h);
537             }
538             break;
539         case 1:
540             fprintf(stderr, _("%s does not appear to be a RPM package\n"), arg);
541             /* fallthrough */
542         case 2:
543             fprintf(stderr, _("query of %s failed\n"), arg);
544             retcode = 1;
545             break;
546         }
547       } break;
548
549       case QUERY_SPECFILE:
550       { Spec spec = NULL;
551         Package pkg;
552         char * buildRoot = NULL;
553         int inBuildArch = 0;
554         char * passPhrase = "";
555         char *cookie = NULL;
556         int anyarch = 1;
557         int force = 1;
558         rc = parseSpec(&spec, arg, buildRoot, inBuildArch, passPhrase, cookie,
559             anyarch, force);
560         if (rc || spec == NULL) {
561             
562             fprintf(stderr, _("query of specfile %s failed, can't parse\n"), arg);
563             if (spec != NULL) freeSpec(spec);
564             retcode = 1;
565             break;
566         }
567
568         if (specedit) {
569             printNewSpecfile(spec);
570             freeSpec(spec);
571             retcode = 0;
572             break;
573         }
574
575         for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
576 #if 0
577             char *binRpm, *errorString;
578             binRpm = headerSprintf(pkg->header,
579                 rpmGetPath("%{_rpmfilename}", NULL),
580                 rpmTagTable, rpmHeaderFormats, &errorString);
581             if (!(pkg == spec->packages && pkg->next == NULL))
582                 fprintf(stdout, "====== %s\n", binRpm);
583             free(binRpm);
584 #endif
585             printHeader(pkg->header, queryFlags, queryFormat);
586         }
587         freeSpec(spec);
588       } break;
589
590       case QUERY_ALL:
591         offset = rpmdbFirstRecNum(db);
592         while (offset) {
593             h = rpmdbGetRecord(db, offset);
594             if (h == NULL) {
595                 fprintf(stderr, _("could not read database record!\n"));
596                 return 1;
597             }
598             printHeader(h, queryFlags, queryFormat);
599             headerFree(h);
600             offset = rpmdbNextRecNum(db, offset);
601         }
602         break;
603
604       case QUERY_GROUP:
605         if (rpmdbFindByGroup(db, arg, &matches)) {
606             fprintf(stderr, _("group %s does not contain any packages\n"), arg);
607             retcode = 1;
608         } else {
609             showMatches(db, matches, queryFlags, queryFormat);
610             dbiFreeIndexRecord(matches);
611         }
612         break;
613
614       case QUERY_WHATPROVIDES:
615         if (rpmdbFindByProvides(db, arg, &matches)) {
616             fprintf(stderr, _("no package provides %s\n"), arg);
617             retcode = 1;
618         } else {
619             showMatches(db, matches, queryFlags, queryFormat);
620             dbiFreeIndexRecord(matches);
621         }
622         break;
623
624       case QUERY_TRIGGEREDBY:
625         if (rpmdbFindByTriggeredBy(db, arg, &matches)) {
626             fprintf(stderr, _("no package triggers %s\n"), arg);
627             retcode = 1;
628         } else {
629             showMatches(db, matches, queryFlags, queryFormat);
630             dbiFreeIndexRecord(matches);
631         }
632         break;
633
634       case QUERY_WHATREQUIRES:
635         if (rpmdbFindByRequiredBy(db, arg, &matches)) {
636             fprintf(stderr, _("no package requires %s\n"), arg);
637             retcode = 1;
638         } else {
639             showMatches(db, matches, queryFlags, queryFormat);
640             dbiFreeIndexRecord(matches);
641         }
642         break;
643
644       case QUERY_PATH:
645         if (rpmdbFindByFile(db, arg, &matches)) {
646             int myerrno = 0;
647             if (access(arg, F_OK) != 0)
648                 myerrno = errno;
649             switch (myerrno) {
650             default:
651                 fprintf(stderr, _("file %s: %s\n"), arg, strerror(myerrno));
652                 break;
653             case 0:
654                 fprintf(stderr, _("file %s is not owned by any package\n"), arg);
655                 break;
656             }
657             retcode = 1;
658         } else {
659             showMatches(db, matches, queryFlags, queryFormat);
660             dbiFreeIndexRecord(matches);
661         }
662         break;
663
664       case QUERY_DBOFFSET:
665         recNumber = strtoul(arg, &end, 10);
666         if ((*end) || (end == arg) || (recNumber == ULONG_MAX)) {
667             fprintf(stderr, _("invalid package number: %s\n"), arg);
668             return 1;
669         }
670         rpmMessage(RPMMESS_DEBUG, _("showing package: %d\n"), recNumber);
671         h = rpmdbGetRecord(db, recNumber);
672         if (h == NULL)  {
673             fprintf(stderr, _("record %d could not be read\n"), recNumber);
674             retcode = 1;
675         } else {
676             printHeader(h, queryFlags, queryFormat);
677             headerFree(h);
678         }
679         break;
680
681       case QUERY_PACKAGE:
682         rc = rpmdbFindByLabel(db, arg, &matches);
683         if (rc == 1) {
684             retcode = 1;
685             fprintf(stderr, _("package %s is not installed\n"), arg);
686         } else if (rc == 2) {
687             retcode = 1;
688             fprintf(stderr, _("error looking for package %s\n"), arg);
689         } else {
690             showMatches(db, matches, queryFlags, queryFormat);
691             dbiFreeIndexRecord(matches);
692         }
693         break;
694     }
695    
696     switch (source) {
697     default:
698         rpmdbClose(db);
699         break;
700     case QUERY_RPM:
701     case QUERY_SPECFILE:
702         break;
703     }
704
705     return retcode;
706 }
707
708 void rpmDisplayQueryTags(FILE * f) {
709     const struct headerTagTableEntry * t;
710     int i;
711     const struct headerSprintfExtension * ext = rpmHeaderFormats;
712
713     for (i = 0, t = rpmTagTable; i < rpmTagTableSize; i++, t++) {
714         fprintf(f, "%s\n", t->name + 7);
715     }
716
717     while (ext->name) {
718         if (ext->type == HEADER_EXT_TAG)
719             fprintf(f, "%s\n", ext->name + 7), ext++;
720         else if (ext->type == HEADER_EXT_MORE)
721             ext = ext->u.more;
722         else
723             ext++;
724     }
725 }