Main Page   Modules   Compound List   File List   Compound Members   File Members   Related Pages  

lib/query.c

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

Generated at Sun Apr 8 18:43:00 2001 for rpm by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000