Main Page   Modules   Data Structures   File List   Data Fields   Globals   Related Pages  

lib/query.c

Go to the documentation of this file.
00001 
00006 #include "system.h"
00007 
00008 #ifndef PATH_MAX
00009 # define PATH_MAX 255
00010 #endif
00011 
00012 #include <rpmbuild.h>
00013 #include <rpmurl.h>
00014 #include "manifest.h"
00015 #include "debug.h"
00016 
00017 /*@access Header@*/                     /* XXX compared with NULL */
00018 /*@access rpmdbMatchIterator@*/         /* XXX compared with NULL */
00019 
00025 static /*@null@*/ void * _free(/*@only@*/ /*@null@*/ const void * this) {
00026     if (this)   free((void *)this);
00027     return NULL;
00028 }
00029 
00032 static void printFileInfo(char * te, const char * name,
00033                           unsigned int size, unsigned short mode,
00034                           unsigned int mtime,
00035                           unsigned short rdev, unsigned int nlink,
00036                           const char * owner, const char * group,
00037                           int uid, int gid, const char * linkto)
00038 {
00039     char sizefield[15];
00040     char ownerfield[9], groupfield[9];
00041     char timefield[100] = "";
00042     time_t when = mtime;  /* important if sizeof(int_32) ! sizeof(time_t) */
00043     struct tm * tm;
00044     static time_t now;
00045     static struct tm nowtm;
00046     const char * namefield = name;
00047     char * perms = rpmPermsString(mode);
00048 
00049     /* On first call, grab snapshot of now */
00050     if (now == 0) {
00051         now = time(NULL);
00052         tm = localtime(&now);
00053         nowtm = *tm;    /* structure assignment */
00054     }
00055 
00056     if (owner) 
00057         strncpy(ownerfield, owner, 8);
00058     else
00059         sprintf(ownerfield, "%-8d", uid);
00060     ownerfield[8] = '\0';
00061 
00062     if (group) 
00063         strncpy(groupfield, group, 8);
00064     else 
00065         sprintf(groupfield, "%-8d", gid);
00066     groupfield[8] = '\0';
00067 
00068     /* this is normally right */
00069     sprintf(sizefield, "%12u", size);
00070 
00071     /* this knows too much about dev_t */
00072 
00073     if (S_ISLNK(mode)) {
00074         char *nf = alloca(strlen(name) + sizeof(" -> ") + strlen(linkto));
00075         sprintf(nf, "%s -> %s", name, linkto);
00076         namefield = nf;
00077     } else if (S_ISCHR(mode)) {
00078         perms[0] = 'c';
00079         sprintf(sizefield, "%3u, %3u", ((unsigned)(rdev >> 8) & 0xff),
00080                         ((unsigned)rdev & 0xff));
00081     } else if (S_ISBLK(mode)) {
00082         perms[0] = 'b';
00083         sprintf(sizefield, "%3u, %3u", ((unsigned)(rdev >> 8) & 0xff),
00084                         ((unsigned)rdev & 0xff));
00085     }
00086 
00087     /* Convert file mtime to display format */
00088     tm = localtime(&when);
00089     {   const char *fmt;
00090         if (now > when + 6L * 30L * 24L * 60L * 60L ||  /* Old. */
00091             now < when - 60L * 60L)                     /* In the future.  */
00092         {
00093         /* The file is fairly old or in the future.
00094          * POSIX says the cutoff is 6 months old;
00095          * approximate this by 6*30 days.
00096          * Allow a 1 hour slop factor for what is considered "the future",
00097          * to allow for NFS server/client clock disagreement.
00098          * Show the year instead of the time of day.
00099          */        
00100             fmt = "%b %e  %Y";
00101         } else {
00102             fmt = "%b %e %H:%M";
00103         }
00104         (void)strftime(timefield, sizeof(timefield) - 1, fmt, tm);
00105     }
00106 
00107     sprintf(te, "%s %4d %-8s%-8s %10s %s %s", perms,
00108         (int)nlink, ownerfield, groupfield, sizefield, timefield, namefield);
00109     perms = _free(perms);
00110 }
00111 
00114 static inline const char * queryHeader(Header h, const char * qfmt)
00115 {
00116     const char * errstr;
00117     const char * str;
00118 
00119     str = headerSprintf(h, qfmt, rpmTagTable, rpmHeaderFormats, &errstr);
00120     if (str == NULL)
00121         rpmError(RPMERR_QFMT, _("incorrect format: %s\n"), errstr);
00122     return str;
00123 }
00124 
00127 static int countLinks(int_16 * fileRdevList, int_32 * fileInodeList, int nfiles,
00128                 int xfile)
00129 {
00130     int nlink = 0;
00131 
00132     /* XXX rpm-3.3.12 has not RPMTAG_FILEINODES */
00133     if (!(fileRdevList && fileInodeList && nfiles > 0))
00134         return 1;
00135     while (nfiles-- > 0) {
00136         if (fileRdevList[nfiles] != fileRdevList[xfile])
00137             continue;
00138         if (fileInodeList[nfiles] != fileInodeList[xfile])
00139             continue;
00140         nlink++;
00141     }
00142     return nlink;
00143 }
00144 
00145 int showQueryPackage(QVA_t *qva, /*@unused@*/rpmdb rpmdb, Header h)
00146 {
00147     char * t, * te;
00148     
00149     int queryFlags = qva->qva_flags;
00150     const char *queryFormat = qva->qva_queryFormat;
00151 
00152     int_32 count, type;
00153     char * prefix = NULL;
00154     const char ** dirNames = NULL;
00155     const char ** baseNames = NULL;
00156     const char ** fileMD5List = NULL;
00157     const char ** fileOwnerList = NULL;
00158     const char ** fileGroupList = NULL;
00159     const char ** fileLinktoList = NULL;
00160     const char * fileStatesList;
00161     int_32 * fileFlagsList, * fileMTimeList, * fileSizeList;
00162     int_32 * fileUIDList = NULL;
00163     int_32 * fileGIDList = NULL;
00164     int_32 * fileInodeList = NULL;
00165     uint_16 * fileModeList;
00166     uint_16 * fileRdevList;
00167     int_32 * dirIndexes;
00168     int rc = 0;         /* XXX FIXME: need real return code */
00169     int nonewline = 0;
00170     int i;
00171 
00172     te = t = xmalloc(BUFSIZ);
00173     *te = '\0';
00174 
00175     if (!queryFormat && !queryFlags) {
00176         const char * name, * version, * release;
00177         headerNVR(h, &name, &version, &release);
00178         te = stpcpy(te, name);
00179         te = stpcpy( stpcpy(te, "-"), version);
00180         te = stpcpy( stpcpy(te, "-"), release);
00181         goto exit;
00182     }
00183 
00184     if (queryFormat) {
00185         const char * str = queryHeader(h, queryFormat);
00186         nonewline = 1;
00187         if (str) {
00188             size_t tb = (te - t);
00189             size_t sb = strlen(str);
00190 
00191             if (sb >= (BUFSIZ - tb)) {
00192                 t = xrealloc(t, BUFSIZ+sb);
00193                 te = t + tb;
00194             }
00195             te = stpcpy(te, str);
00196             str = _free(str);
00197         }
00198     }
00199 
00200     if (!(queryFlags & QUERY_FOR_LIST))
00201         goto exit;
00202 
00203     if (!headerGetEntry(h, RPMTAG_BASENAMES, &type, 
00204                                 (void **) &baseNames, &count)) {
00205         te = stpcpy(te, _("(contains no files)"));
00206         goto exit;
00207     }
00208     if (!headerGetEntry(h, RPMTAG_FILESTATES, &type, 
00209                          (void **) &fileStatesList, &count)) {
00210         fileStatesList = NULL;
00211     }
00212     headerGetEntry(h, RPMTAG_DIRNAMES, NULL, (void **) &dirNames, NULL);
00213     headerGetEntry(h, RPMTAG_DIRINDEXES, NULL, (void **) &dirIndexes, NULL);
00214     headerGetEntry(h, RPMTAG_FILEFLAGS, &type, (void **)&fileFlagsList, &count);
00215     headerGetEntry(h, RPMTAG_FILESIZES, &type, (void **) &fileSizeList, &count);
00216     headerGetEntry(h, RPMTAG_FILEMODES, &type, (void **) &fileModeList, &count);
00217     headerGetEntry(h, RPMTAG_FILEMTIMES, &type, (void **)&fileMTimeList,&count);
00218     headerGetEntry(h, RPMTAG_FILERDEVS, &type, (void **) &fileRdevList, &count);
00219     headerGetEntry(h, RPMTAG_FILEINODES, &type, (void **)&fileInodeList,&count);
00220     headerGetEntry(h, RPMTAG_FILELINKTOS,&type,(void **)&fileLinktoList,&count);
00221     headerGetEntry(h, RPMTAG_FILEMD5S, &type, (void **) &fileMD5List, &count);
00222 
00223     if (!headerGetEntry(h, RPMTAG_FILEUIDS, &type, 
00224                          (void **) &fileUIDList, &count)) {
00225         fileUIDList = NULL;
00226     } else if (!headerGetEntry(h, RPMTAG_FILEGIDS, &type, 
00227                              (void **) &fileGIDList, &count)) {
00228         fileGIDList = NULL;
00229     }
00230 
00231     if (!headerGetEntry(h, RPMTAG_FILEUSERNAME, &type, 
00232                          (void **) &fileOwnerList, &count)) {
00233         fileOwnerList = NULL;
00234     } else if (!headerGetEntry(h, RPMTAG_FILEGROUPNAME, &type, 
00235                              (void **) &fileGroupList, &count)) {
00236         fileGroupList = NULL;
00237     }
00238 
00239     for (i = 0; i < count; i++) {
00240         /* If querying only docs, skip non-doc files. */
00241         if ((queryFlags & QUERY_FOR_DOCS)
00242           && !(fileFlagsList[i] & RPMFILE_DOC))
00243             continue;
00244         /* If querying only configs, skip non-config files. */
00245         if ((queryFlags & QUERY_FOR_CONFIG)
00246           && !(fileFlagsList[i] & RPMFILE_CONFIG))
00247             continue;
00248 
00249         if (!rpmIsVerbose() && prefix)
00250             te = stpcpy(te, prefix);
00251 
00252         if (queryFlags & QUERY_FOR_STATE) {
00253             if (fileStatesList) {
00254                 switch (fileStatesList[i]) {
00255                 case RPMFILE_STATE_NORMAL:
00256                     te = stpcpy(te, _("normal        ")); break;
00257                 case RPMFILE_STATE_REPLACED:
00258                     te = stpcpy(te, _("replaced      ")); break;
00259                 case RPMFILE_STATE_NOTINSTALLED:
00260                     te = stpcpy(te, _("not installed ")); break;
00261                 case RPMFILE_STATE_NETSHARED:
00262                     te = stpcpy(te, _("net shared    ")); break;
00263                 default:
00264                     sprintf(te, _("(unknown %3d) "), (int)fileStatesList[i]);
00265                     te += strlen(te);
00266                     break;
00267                 }
00268             } else {
00269                 te = stpcpy(te, _("(no state)    "));
00270             }
00271         }
00272 
00273         if (queryFlags & QUERY_FOR_DUMPFILES) {
00274             sprintf(te, "%s%s %d %d %s 0%o ", 
00275                                    dirNames[dirIndexes[i]], baseNames[i],
00276                                    fileSizeList[i], fileMTimeList[i],
00277                                    fileMD5List[i], fileModeList[i]);
00278             te += strlen(te);
00279 
00280             if (fileOwnerList && fileGroupList) {
00281                 sprintf(te, "%s %s", fileOwnerList[i], fileGroupList[i]);
00282                 te += strlen(te);
00283             } else if (fileUIDList && fileGIDList) {
00284                 sprintf(te, "%d %d", fileUIDList[i], fileGIDList[i]);
00285                 te += strlen(te);
00286             } else {
00287                 rpmError(RPMERR_INTERNAL,
00288                         _("package has neither file owner or id lists\n"));
00289             }
00290 
00291             sprintf(te, " %s %s %u ", 
00292                                  fileFlagsList[i] & RPMFILE_CONFIG ? "1" : "0",
00293                                  fileFlagsList[i] & RPMFILE_DOC ? "1" : "0",
00294                                  (unsigned)fileRdevList[i]);
00295             te += strlen(te);
00296 
00297             if (strlen(fileLinktoList[i]))
00298                 sprintf(te, "%s", fileLinktoList[i]);
00299             else
00300                 sprintf(te, "X");
00301             te += strlen(te);
00302         } else if (!rpmIsVerbose()) {
00303             te = stpcpy(te, dirNames[dirIndexes[i]]);
00304             te = stpcpy(te, baseNames[i]);
00305         } else {
00306             char * filespec;
00307             int nlink;
00308 
00309             filespec = xmalloc(strlen(dirNames[dirIndexes[i]])
00310                                               + strlen(baseNames[i]) + 1);
00311             strcpy(filespec, dirNames[dirIndexes[i]]);
00312             strcat(filespec, baseNames[i]);
00313                                         
00314             nlink = countLinks(fileRdevList, fileInodeList, count, i);
00315             if (fileOwnerList && fileGroupList) {
00316                 printFileInfo(te, filespec, fileSizeList[i],
00317                                               fileModeList[i], fileMTimeList[i],
00318                                               fileRdevList[i], nlink,
00319                                               fileOwnerList[i], 
00320                                               fileGroupList[i], -1, 
00321                                               -1, fileLinktoList[i]);
00322                 te += strlen(te);
00323             } else if (fileUIDList && fileGIDList) {
00324                 printFileInfo(te, filespec, fileSizeList[i],
00325                                               fileModeList[i], fileMTimeList[i],
00326                                               fileRdevList[i], nlink,
00327                                               NULL, NULL, fileUIDList[i], 
00328                                               fileGIDList[i], 
00329                                               fileLinktoList[i]);
00330                 te += strlen(te);
00331             } else {
00332                 rpmError(RPMERR_INTERNAL,
00333                         _("package has neither file owner or id lists\n"));
00334             }
00335 
00336             filespec = _free(filespec);
00337         }
00338         if (te > t) {
00339             *te++ = '\n';
00340             *te = '\0';
00341             rpmMessage(RPMMESS_NORMAL, "%s", t);
00342             te = t;
00343             *t = '\0';
00344         }
00345     }
00346             
00347     rc = 0;
00348 
00349 exit:
00350     if (te > t) {
00351         if (!nonewline) {
00352             *te++ = '\n';
00353             *te = '\0';
00354         }
00355         rpmMessage(RPMMESS_NORMAL, "%s", t);
00356     }
00357     t = _free(t);
00358     dirNames = headerFreeData(dirNames, -1);
00359     baseNames = headerFreeData(baseNames, -1);
00360     fileLinktoList = headerFreeData(fileLinktoList, -1);
00361     fileMD5List = headerFreeData(fileMD5List, -1);
00362     fileOwnerList = headerFreeData(fileOwnerList, -1);
00363     fileGroupList = headerFreeData(fileGroupList, -1);
00364     return rc;
00365 }
00366 
00369 static void
00370 printNewSpecfile(Spec spec)
00371 {
00372     Header h = spec->packages->header;
00373     struct speclines *sl = spec->sl;
00374     struct spectags *st = spec->st;
00375     const char * msgstr = NULL;
00376     int i, j;
00377 
00378     if (sl == NULL || st == NULL)
00379         return;
00380 
00381     for (i = 0; i < st->st_ntags; i++) {
00382         struct spectag * t = st->st_t + i;
00383         const char * tn = tagName(t->t_tag);
00384         const char * errstr;
00385         char fmt[128];
00386 
00387         fmt[0] = '\0';
00388         (void) stpcpy( stpcpy( stpcpy( fmt, "%{"), tn), "}\n");
00389         msgstr = _free(msgstr);
00390         msgstr = headerSprintf(h, fmt, rpmTagTable, rpmHeaderFormats, &errstr);
00391         if (msgstr == NULL) {
00392             rpmError(RPMERR_QFMT, _("can't query %s: %s\n"), tn, errstr);
00393             return;
00394         }
00395 
00396         switch(t->t_tag) {
00397         case RPMTAG_SUMMARY:
00398         case RPMTAG_GROUP:
00399             sl->sl_lines[t->t_startx] = _free(sl->sl_lines[t->t_startx]);
00400             if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG))
00401                 continue;
00402             {   char *buf = xmalloc(strlen(tn) + sizeof(": ") + strlen(msgstr));
00403                 (void) stpcpy( stpcpy( stpcpy(buf, tn), ": "), msgstr);
00404                 sl->sl_lines[t->t_startx] = buf;
00405             }
00406             break;
00407         case RPMTAG_DESCRIPTION:
00408             for (j = 1; j < t->t_nlines; j++) {
00409                 sl->sl_lines[t->t_startx + j] =
00410                         _free(sl->sl_lines[t->t_startx + j]);
00411             }
00412             if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG)) {
00413                 sl->sl_lines[t->t_startx] = _free(sl->sl_lines[t->t_startx]);
00414                 continue;
00415             }
00416             sl->sl_lines[t->t_startx + 1] = xstrdup(msgstr);
00417             if (t->t_nlines > 2)
00418                 sl->sl_lines[t->t_startx + 2] = xstrdup("\n\n");
00419             break;
00420         }
00421     }
00422     msgstr = _free(msgstr);
00423 
00424     for (i = 0; i < sl->sl_nlines; i++) {
00425         if (sl->sl_lines[i] == NULL)
00426             continue;
00427         printf("%s", sl->sl_lines[i]);
00428     }
00429 }
00430 
00431 void rpmDisplayQueryTags(FILE * f)
00432 {
00433     const struct headerTagTableEntry * t;
00434     int i;
00435     const struct headerSprintfExtension * ext = rpmHeaderFormats;
00436 
00437     for (i = 0, t = rpmTagTable; i < rpmTagTableSize; i++, t++) {
00438         fprintf(f, "%s\n", t->name + 7);
00439     }
00440 
00441     while (ext->name) {
00442         if (ext->type == HEADER_EXT_MORE) {
00443             ext = ext->u.more;
00444             continue;
00445         }
00446         /* XXX don't print query tags twice. */
00447         for (i = 0, t = rpmTagTable; i < rpmTagTableSize; i++, t++) {
00448             if (!strcmp(t->name, ext->name))
00449                 break;
00450         }
00451         if (i >= rpmTagTableSize && ext->type == HEADER_EXT_TAG)
00452             fprintf(f, "%s\n", ext->name + 7);
00453         ext++;
00454     }
00455 }
00456 
00457 int showMatches(QVA_t *qva, rpmdbMatchIterator mi, QVF_t showPackage)
00458 {
00459     Header h;
00460     int ec = 0;
00461 
00462     while ((h = rpmdbNextIterator(mi)) != NULL) {
00463         int rc;
00464         if ((rc = showPackage(qva, rpmdbGetIteratorRpmDB(mi), h)) != 0)
00465             ec = rc;
00466     }
00467     rpmdbFreeIterator(mi);
00468     return ec;
00469 }
00470 
00474 int     (*parseSpecVec) (Spec *specp, const char *specFile, const char *rootdir,
00475                 const char *buildRoot, int inBuildArch, const char *passPhrase,
00476                 char *cookie, int anyarch, int force) = NULL;
00480 void    (*freeSpecVec) (Spec spec) = NULL;
00481 
00482 int rpmQueryVerify(QVA_t *qva, rpmQVSources source, const char * arg,
00483         rpmdb rpmdb, QVF_t showPackage)
00484 {
00485     rpmdbMatchIterator mi = NULL;
00486     Header h;
00487     int rc;
00488     int isSource;
00489     int retcode = 0;
00490     char *end = NULL;
00491 
00492     switch (source) {
00493     case RPMQV_RPM:
00494     {   int ac = 0;
00495         const char ** av = NULL;
00496         const char * fileURL = NULL;
00497         rpmRC rpmrc;
00498         int i;
00499 
00500         rc = rpmGlob(arg, &ac, &av);
00501         if (rc) return 1;
00502 
00503 restart:
00504         for (i = 0; i < ac; i++) {
00505             FD_t fd;
00506 
00507             fileURL = _free(fileURL);
00508             fileURL = av[i];
00509             av[i] = NULL;
00510 
00511             /* Try to read the header from a package file. */
00512             fd = Fopen(fileURL, "r.ufdio");
00513             if (fd == NULL || Ferror(fd)) {
00514                 rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), fileURL,
00515                         Fstrerror(fd));
00516                 if (fd) Fclose(fd);
00517                 retcode = 1;
00518                 break;
00519             }
00520 
00521             rpmrc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
00522             Fclose(fd);
00523 
00524             if (!(rpmrc == RPMRC_OK || rpmrc == RPMRC_BADMAGIC)) {
00525                 rpmError(RPMERR_QUERY, _("query of %s failed\n"), fileURL);
00526                 retcode = 1;
00527                 break;
00528             }
00529             if (rpmrc == RPMRC_OK && h == NULL) {
00530                 rpmError(RPMERR_QUERY,
00531                         _("old format source packages cannot be queried\n"));
00532                 retcode = 1;
00533                 break;
00534             }
00535 
00536             /* Query a package file. */
00537             if (rpmrc == RPMRC_OK) {
00538                 retcode = showPackage(qva, rpmdb, h);
00539                 headerFree(h);
00540                 continue;
00541             }
00542 
00543             /* Try to read a package manifest. */
00544             fd = Fopen(fileURL, "r.fpio");
00545             if (fd == NULL || Ferror(fd)) {
00546                 rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), fileURL,
00547                         Fstrerror(fd));
00548                 if (fd) Fclose(fd);
00549                 retcode = 1;
00550                 break;
00551             }
00552             
00553             /* Read list of packages from manifest. */
00554             retcode = rpmReadPackageManifest(fd, &ac, &av);
00555             if (retcode) {
00556                 rpmError(RPMERR_MANIFEST, _("%s: read manifest failed: %s\n"),
00557                         fileURL, Fstrerror(fd));
00558                 retcode = 1;
00559             }
00560             Fclose(fd);
00561 
00562             /* If successful, restart the query loop. */
00563             if (retcode == 0)
00564                 goto restart;
00565 
00566             break;
00567         }
00568 
00569         fileURL = _free(fileURL);
00570         if (av) {
00571             for (i = 0; i < ac; i++)
00572                 av[i] = _free(av[i]);
00573             av = _free(av);
00574         }
00575     }   break;
00576 
00577     case RPMQV_SPECFILE:
00578         if (showPackage != showQueryPackage)
00579             return 1;
00580 
00581         /* XXX Eliminate linkage dependency loop */
00582         if (parseSpecVec == NULL || freeSpecVec == NULL)
00583             return 1;
00584 
00585       { Spec spec = NULL;
00586         Package pkg;
00587         char * buildRoot = NULL;
00588         int inBuildArch = 0;
00589         char * passPhrase = "";
00590         char *cookie = NULL;
00591         int anyarch = 1;
00592         int force = 1;
00593 
00594         rc = parseSpecVec(&spec, arg, "/", buildRoot, inBuildArch, passPhrase,
00595                 cookie, anyarch, force);
00596         if (rc || spec == NULL) {
00597             
00598             rpmError(RPMERR_QUERY,
00599                         _("query of specfile %s failed, can't parse\n"), arg);
00600             if (spec != NULL) freeSpecVec(spec);
00601             retcode = 1;
00602             break;
00603         }
00604 
00605         if (specedit) {
00606             printNewSpecfile(spec);
00607             freeSpecVec(spec);
00608             retcode = 0;
00609             break;
00610         }
00611 
00612         for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
00613             showPackage(qva, NULL, pkg->header);
00614         }
00615         freeSpecVec(spec);
00616       } break;
00617 
00618     case RPMQV_ALL:
00619         /* RPMDBI_PACKAGES */
00620         mi = rpmdbInitIterator(rpmdb, RPMDBI_PACKAGES, NULL, 0);
00621         if (mi == NULL) {
00622             rpmError(RPMERR_QUERYINFO, _("no packages\n"));
00623             retcode = 1;
00624         } else {
00625             retcode = showMatches(qva, mi, showPackage);
00626         }
00627         break;
00628 
00629     case RPMQV_GROUP:
00630         mi = rpmdbInitIterator(rpmdb, RPMTAG_GROUP, arg, 0);
00631         if (mi == NULL) {
00632             rpmError(RPMERR_QUERYINFO,
00633                 _("group %s does not contain any packages\n"), arg);
00634             retcode = 1;
00635         } else {
00636             retcode = showMatches(qva, mi, showPackage);
00637         }
00638         break;
00639 
00640     case RPMQV_TRIGGEREDBY:
00641         mi = rpmdbInitIterator(rpmdb, RPMTAG_TRIGGERNAME, arg, 0);
00642         if (mi == NULL) {
00643             rpmError(RPMERR_QUERYINFO, _("no package triggers %s\n"), arg);
00644             retcode = 1;
00645         } else {
00646             retcode = showMatches(qva, mi, showPackage);
00647         }
00648         break;
00649 
00650     case RPMQV_WHATREQUIRES:
00651         mi = rpmdbInitIterator(rpmdb, RPMTAG_REQUIRENAME, arg, 0);
00652         if (mi == NULL) {
00653             rpmError(RPMERR_QUERYINFO, _("no package requires %s\n"), arg);
00654             retcode = 1;
00655         } else {
00656             retcode = showMatches(qva, mi, showPackage);
00657         }
00658         break;
00659 
00660     case RPMQV_WHATPROVIDES:
00661         if (arg[0] != '/') {
00662             mi = rpmdbInitIterator(rpmdb, RPMTAG_PROVIDENAME, arg, 0);
00663             if (mi == NULL) {
00664                 rpmError(RPMERR_QUERYINFO, _("no package provides %s\n"), arg);
00665                 retcode = 1;
00666             } else {
00667                 retcode = showMatches(qva, mi, showPackage);
00668             }
00669             break;
00670         }
00671         /*@fallthrough@*/
00672     case RPMQV_PATH:
00673     {   const char * s;
00674         char * fn;
00675 
00676         for (s = arg; *s; s++)
00677             if (!(*s == '.' || *s == '/')) break;
00678 
00679         if (*s == '\0') {
00680             char fnbuf[PATH_MAX];
00681             fn = /*@-unrecog@*/ realpath(arg, fnbuf) /*@=unrecog@*/;
00682             fn = xstrdup( (fn ? fn : arg) );
00683         } else
00684             fn = xstrdup(arg);
00685         (void) rpmCleanPath(fn);
00686 
00687         mi = rpmdbInitIterator(rpmdb, RPMTAG_BASENAMES, fn, 0);
00688         if (mi == NULL) {
00689             int myerrno = 0;
00690             if (access(fn, F_OK) != 0)
00691                 myerrno = errno;
00692             switch (myerrno) {
00693             default:
00694                 rpmError(RPMERR_QUERY,
00695                         _("file %s: %s\n"), fn, strerror(myerrno));
00696                 break;
00697             case 0:
00698                 rpmError(RPMERR_QUERYINFO,
00699                         _("file %s is not owned by any package\n"), fn);
00700                 break;
00701             }
00702             retcode = 1;
00703         } else {
00704             retcode = showMatches(qva, mi, showPackage);
00705         }
00706         fn = _free(fn);
00707     }   break;
00708 
00709     case RPMQV_DBOFFSET:
00710     {   int mybase = 10;
00711         const char * myarg = arg;
00712         int recOffset;
00713 
00714         /* XXX should be in strtoul */
00715         if (*myarg == '0') {
00716             myarg++;
00717             mybase = 8;
00718             if (*myarg == 'x') {
00719                 myarg++;
00720                 mybase = 16;
00721             }
00722         }
00723         recOffset = strtoul(myarg, &end, mybase);
00724         if ((*end) || (end == arg) || (recOffset == ULONG_MAX)) {
00725             rpmError(RPMERR_QUERY, _("invalid package number: %s\n"), arg);
00726             return 1;
00727         }
00728         rpmMessage(RPMMESS_DEBUG, _("package record number: %u\n"), recOffset);
00729         /* RPMDBI_PACKAGES */
00730         mi = rpmdbInitIterator(rpmdb, RPMDBI_PACKAGES, &recOffset, sizeof(recOffset));
00731         if (mi == NULL) {
00732             rpmError(RPMERR_QUERY,
00733                 _("record %d could not be read\n"), recOffset);
00734             retcode = 1;
00735         } else {
00736             retcode = showMatches(qva, mi, showPackage);
00737         }
00738     }   break;
00739 
00740     case RPMQV_PACKAGE:
00741         /* XXX HACK to get rpmdbFindByLabel out of the API */
00742         mi = rpmdbInitIterator(rpmdb, RPMDBI_LABEL, arg, 0);
00743         if (mi == NULL) {
00744             rpmError(RPMERR_QUERYINFO, _("package %s is not installed\n"), arg);
00745             retcode = 1;
00746         } else {
00747             retcode = showMatches(qva, mi, showPackage);
00748         }
00749         break;
00750     }
00751    
00752     return retcode;
00753 }
00754 
00755 int rpmQuery(QVA_t *qva, rpmQVSources source, const char * arg)
00756 {
00757     rpmdb rpmdb = NULL;
00758     int rc;
00759 
00760     switch (source) {
00761     case RPMQV_RPM:
00762     case RPMQV_SPECFILE:
00763         break;
00764     default:
00765         if (rpmdbOpen(qva->qva_prefix, &rpmdb, O_RDONLY, 0644))
00766             return 1;
00767         break;
00768     }
00769 
00770     rc = rpmQueryVerify(qva, source, arg, rpmdb, showQueryPackage);
00771 
00772     if (rpmdb)
00773         rpmdbClose(rpmdb);
00774 
00775     return rc;
00776 }

Generated at Thu Apr 19 15:29:43 2001 for rpm by doxygen1.2.6-20010408 written by Dimitri van Heesch, © 1997-2001