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

query.c

Go to the documentation of this file.
00001 
00006 #include "system.h"
00007 
00008 #ifndef PATH_MAX
00009 /*@-incondefs@*/        /* FIX: long int? */
00010 # define PATH_MAX 255
00011 /*@=incondefs@*/
00012 #endif
00013 
00014 #include <rpmcli.h>
00015 #include <rpmbuild.h>
00016 #include "manifest.h"
00017 #include "debug.h"
00018 
00019 /*@access rpmdbMatchIterator@*/         /* XXX compared with NULL */
00020 /*@access Header@*/                     /* XXX compared with NULL */
00021 /*@access rpmdb@*/                      /* XXX compared with NULL */
00022 /*@access FD_t@*/                       /* XXX compared with NULL */
00023 
00026 static void printFileInfo(char * te, const char * name,
00027                           unsigned int size, unsigned short mode,
00028                           unsigned int mtime,
00029                           unsigned short rdev, unsigned int nlink,
00030                           const char * owner, const char * group,
00031                           int uid, int gid, const char * linkto)
00032         /*@modifies *te @*/
00033 {
00034     char sizefield[15];
00035     char ownerfield[9], groupfield[9];
00036     char timefield[100];
00037     time_t when = mtime;  /* important if sizeof(int_32) ! sizeof(time_t) */
00038     struct tm * tm;
00039     static time_t now;
00040     static struct tm nowtm;
00041     const char * namefield = name;
00042     char * perms = rpmPermsString(mode);
00043 
00044     /* On first call, grab snapshot of now */
00045     if (now == 0) {
00046         now = time(NULL);
00047         tm = localtime(&now);
00048         if (tm) nowtm = *tm;    /* structure assignment */
00049     }
00050 
00051     if (owner) 
00052         strncpy(ownerfield, owner, 8);
00053     else
00054         sprintf(ownerfield, "%-8d", uid);
00055     ownerfield[8] = '\0';
00056 
00057     if (group) 
00058         strncpy(groupfield, group, 8);
00059     else 
00060         sprintf(groupfield, "%-8d", gid);
00061     groupfield[8] = '\0';
00062 
00063     /* this is normally right */
00064     sprintf(sizefield, "%12u", size);
00065 
00066     /* this knows too much about dev_t */
00067 
00068     if (S_ISLNK(mode)) {
00069         char *nf = alloca(strlen(name) + sizeof(" -> ") + strlen(linkto));
00070         sprintf(nf, "%s -> %s", name, linkto);
00071         namefield = nf;
00072     } else if (S_ISCHR(mode)) {
00073         perms[0] = 'c';
00074         sprintf(sizefield, "%3u, %3u", ((unsigned)(rdev >> 8) & 0xff),
00075                         ((unsigned)rdev & 0xff));
00076     } else if (S_ISBLK(mode)) {
00077         perms[0] = 'b';
00078         sprintf(sizefield, "%3u, %3u", ((unsigned)(rdev >> 8) & 0xff),
00079                         ((unsigned)rdev & 0xff));
00080     }
00081 
00082     /* Convert file mtime to display format */
00083     tm = localtime(&when);
00084     timefield[0] = '\0';
00085     if (tm != NULL)
00086     {   const char *fmt;
00087         if (now > when + 6L * 30L * 24L * 60L * 60L ||  /* Old. */
00088             now < when - 60L * 60L)                     /* In the future.  */
00089         {
00090         /* The file is fairly old or in the future.
00091          * POSIX says the cutoff is 6 months old;
00092          * approximate this by 6*30 days.
00093          * Allow a 1 hour slop factor for what is considered "the future",
00094          * to allow for NFS server/client clock disagreement.
00095          * Show the year instead of the time of day.
00096          */        
00097             fmt = "%b %e  %Y";
00098         } else {
00099             fmt = "%b %e %H:%M";
00100         }
00101         (void)strftime(timefield, sizeof(timefield) - 1, fmt, tm);
00102     }
00103 
00104     sprintf(te, "%s %4d %-8s%-8s %10s %s %s", perms,
00105         (int)nlink, ownerfield, groupfield, sizefield, timefield, namefield);
00106     perms = _free(perms);
00107 }
00108 
00111 static inline /*@null@*/ const char * queryHeader(Header h, const char * qfmt)
00112         /*@*/
00113 {
00114     const char * errstr;
00115     const char * str;
00116 
00117     str = headerSprintf(h, qfmt, rpmTagTable, rpmHeaderFormats, &errstr);
00118     if (str == NULL)
00119         rpmError(RPMERR_QFMT, _("incorrect format: %s\n"), errstr);
00120     return str;
00121 }
00122 
00125 static int countLinks(int_16 * fileRdevList, int_32 * fileInodeList, int nfiles,
00126                 int xfile)
00127         /*@*/
00128 {
00129     int nlink = 0;
00130 
00131     /* XXX rpm-3.3.12 has not RPMTAG_FILEINODES */
00132     if (!(fileRdevList[xfile] != 0 && fileRdevList &&
00133                 fileInodeList[xfile] != 0 && fileInodeList && nfiles > 0))
00134         return 1;
00135     while (nfiles-- > 0) {
00136         if (fileRdevList[nfiles] == 0)
00137             continue;
00138         if (fileRdevList[nfiles] != fileRdevList[xfile])
00139             continue;
00140         if (fileInodeList[nfiles] == 0)
00141             continue;
00142         if (fileInodeList[nfiles] != fileInodeList[xfile])
00143             continue;
00144         nlink++;
00145     }
00146     if (nlink == 0) nlink = 1;
00147     return nlink;
00148 }
00149 
00150 int showQueryPackage(QVA_t qva, /*@unused@*/rpmdb rpmdb, Header h)
00151 {
00152     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00153     HFD_t hfd = headerFreeData;
00154     char * t, * te;
00155     rpmQueryFlags queryFlags = qva->qva_flags;
00156     const char * queryFormat = qva->qva_queryFormat;
00157     rpmTagType type;
00158     int_32 count;
00159     char * prefix = NULL;
00160     const char ** dirNames = NULL;
00161     const char ** baseNames = NULL;
00162     rpmTagType bnt, dnt;
00163     const char ** fileMD5List = NULL;
00164     const char ** fileOwnerList = NULL;
00165     const char ** fileGroupList = NULL;
00166     const char ** fileLinktoList = NULL;
00167     rpmTagType m5t, fot, fgt, ltt;
00168     const char * fileStatesList;
00169     int_32 * fileFlagsList, * fileMTimeList, * fileSizeList;
00170     int_32 * fileUIDList = NULL;
00171     int_32 * fileGIDList = NULL;
00172     int_32 * fileInodeList = NULL;
00173     uint_16 * fileModeList;
00174     uint_16 * fileRdevList;
00175     int_32 * dirIndexes;
00176     int rc = 0;         /* XXX FIXME: need real return code */
00177     int nonewline = 0;
00178     int i;
00179 
00180     te = t = xmalloc(BUFSIZ);
00181     *te = '\0';
00182 
00183     if (queryFormat == NULL && queryFlags == QUERY_FOR_DEFAULT) {
00184         const char * name, * version, * release;
00185         (void) headerNVR(h, &name, &version, &release);
00186         te = stpcpy(te, name);
00187         te = stpcpy( stpcpy(te, "-"), version);
00188         te = stpcpy( stpcpy(te, "-"), release);
00189         goto exit;
00190     }
00191 
00192     if (queryFormat) {
00193         const char * str = queryHeader(h, queryFormat);
00194         nonewline = 1;
00195         /*@-branchstate@*/
00196         if (str) {
00197             size_t tb = (te - t);
00198             size_t sb = strlen(str);
00199 
00200             if (sb >= (BUFSIZ - tb)) {
00201                 t = xrealloc(t, BUFSIZ+sb);
00202                 te = t + tb;
00203             }
00204             /*@-usereleased@*/
00205             te = stpcpy(te, str);
00206             /*@=usereleased@*/
00207             str = _free(str);
00208         }
00209         /*@=branchstate@*/
00210     }
00211 
00212     if (!(queryFlags & QUERY_FOR_LIST))
00213         goto exit;
00214 
00215     if (!hge(h, RPMTAG_BASENAMES, &bnt, (void **) &baseNames, &count)) {
00216         te = stpcpy(te, _("(contains no files)"));
00217         goto exit;
00218     }
00219     if (!hge(h, RPMTAG_FILESTATES, &type, (void **) &fileStatesList, NULL))
00220         fileStatesList = NULL;
00221     if (!hge(h, RPMTAG_DIRNAMES, &dnt, (void **) &dirNames, NULL))
00222         dirNames = NULL;
00223     if (!hge(h, RPMTAG_DIRINDEXES, NULL, (void **) &dirIndexes, NULL))
00224         dirIndexes = NULL;
00225     if (!hge(h, RPMTAG_FILEFLAGS, &type, (void **) &fileFlagsList, NULL))
00226         fileFlagsList = NULL;
00227     if (!hge(h, RPMTAG_FILESIZES, &type, (void **) &fileSizeList, NULL))
00228         fileSizeList = NULL;
00229     if (!hge(h, RPMTAG_FILEMODES, &type, (void **) &fileModeList, NULL))
00230         fileModeList = NULL;
00231     if (!hge(h, RPMTAG_FILEMTIMES, &type, (void **) &fileMTimeList, NULL))
00232         fileMTimeList = NULL;
00233     if (!hge(h, RPMTAG_FILERDEVS, &type, (void **) &fileRdevList, NULL))
00234         fileRdevList = NULL;
00235     if (!hge(h, RPMTAG_FILEINODES, &type, (void **) &fileInodeList, NULL))
00236         fileInodeList = NULL;
00237     if (!hge(h, RPMTAG_FILELINKTOS, &ltt, (void **) &fileLinktoList, NULL))
00238         fileLinktoList = NULL;
00239     if (!hge(h, RPMTAG_FILEMD5S, &m5t, (void **) &fileMD5List, NULL))
00240         fileMD5List = NULL;
00241     if (!hge(h, RPMTAG_FILEUIDS, &type, (void **) &fileUIDList, NULL))
00242         fileUIDList = NULL;
00243     if (!hge(h, RPMTAG_FILEGIDS, &type, (void **) &fileGIDList, NULL))
00244         fileGIDList = NULL;
00245     if (!hge(h, RPMTAG_FILEUSERNAME, &fot, (void **) &fileOwnerList, NULL))
00246         fileOwnerList = NULL;
00247     if (!hge(h, RPMTAG_FILEGROUPNAME, &fgt, (void **) &fileGroupList, NULL))
00248         fileGroupList = NULL;
00249 
00250     for (i = 0; i < count; i++) {
00251 
00252         /* If querying only docs, skip non-doc files. */
00253         if ((queryFlags & QUERY_FOR_DOCS)
00254           && !(fileFlagsList[i] & RPMFILE_DOC))
00255             continue;
00256 
00257         /* If querying only configs, skip non-config files. */
00258         if ((queryFlags & QUERY_FOR_CONFIG)
00259           && !(fileFlagsList[i] & RPMFILE_CONFIG))
00260             continue;
00261 
00262         /* If not querying %ghost, skip ghost files. */
00263         if (!(qva->qva_fflags & RPMFILE_GHOST)
00264           && (fileFlagsList[i] & RPMFILE_GHOST))
00265             continue;
00266 
00267         /*@-internalglobs@*/ /* FIX: shrug */
00268         if (!rpmIsVerbose() && prefix)
00269             te = stpcpy(te, prefix);
00270         /*@=internalglobs@*/
00271 
00272         if (queryFlags & QUERY_FOR_STATE) {
00273             if (fileStatesList) {
00274                 rpmfileState fstate = fileStatesList[i];
00275                 switch (fstate) {
00276                 case RPMFILE_STATE_NORMAL:
00277                     te = stpcpy(te, _("normal        "));
00278                     /*@switchbreak@*/ break;
00279                 case RPMFILE_STATE_REPLACED:
00280                     te = stpcpy(te, _("replaced      "));
00281                     /*@switchbreak@*/ break;
00282                 case RPMFILE_STATE_NOTINSTALLED:
00283                     te = stpcpy(te, _("not installed "));
00284                     /*@switchbreak@*/ break;
00285                 case RPMFILE_STATE_NETSHARED:
00286                     te = stpcpy(te, _("net shared    "));
00287                     /*@switchbreak@*/ break;
00288                 default:
00289                     sprintf(te, _("(unknown %3d) "), (int)fileStatesList[i]);
00290                     te += strlen(te);
00291                     /*@switchbreak@*/ break;
00292                 }
00293             } else {
00294                 te = stpcpy(te, _("(no state)    "));
00295             }
00296         }
00297 
00298         if (queryFlags & QUERY_FOR_DUMPFILES) {
00299             sprintf(te, "%s%s %d %d %s 0%o ", 
00300                                    dirNames[dirIndexes[i]], baseNames[i],
00301                                    fileSizeList[i], fileMTimeList[i],
00302                                    fileMD5List[i], (unsigned) fileModeList[i]);
00303             te += strlen(te);
00304 
00305             if (fileOwnerList && fileGroupList) {
00306                 sprintf(te, "%s %s", fileOwnerList[i], fileGroupList[i]);
00307                 te += strlen(te);
00308             } else if (fileUIDList && fileGIDList) {
00309                 sprintf(te, "%d %d", fileUIDList[i], fileGIDList[i]);
00310                 te += strlen(te);
00311             } else {
00312                 rpmError(RPMERR_INTERNAL,
00313                         _("package has neither file owner or id lists\n"));
00314             }
00315 
00316             sprintf(te, " %s %s %u ", 
00317                                  fileFlagsList[i] & RPMFILE_CONFIG ? "1" : "0",
00318                                  fileFlagsList[i] & RPMFILE_DOC ? "1" : "0",
00319                                  (unsigned) fileRdevList[i]);
00320             te += strlen(te);
00321 
00322             if (strlen(fileLinktoList[i]))
00323                 sprintf(te, "%s", fileLinktoList[i]);
00324             else
00325                 sprintf(te, "X");
00326             te += strlen(te);
00327         } else
00328         /*@-internalglobs@*/ /* FIX: shrug */
00329         if (!rpmIsVerbose()) {
00330             te = stpcpy(te, dirNames[dirIndexes[i]]);
00331             te = stpcpy(te, baseNames[i]);
00332         }
00333         /*@=internalglobs@*/
00334         else {
00335             char * filespec;
00336             int nlink;
00337             size_t fileSize;
00338 
00339             filespec = xmalloc(strlen(dirNames[dirIndexes[i]])
00340                                               + strlen(baseNames[i]) + 1);
00341             strcpy(filespec, dirNames[dirIndexes[i]]);
00342             strcat(filespec, baseNames[i]);
00343                                         
00344             fileSize = fileSizeList[i];
00345             nlink = countLinks(fileRdevList, fileInodeList, count, i);
00346 
00347 if (S_ISDIR(fileModeList[i])) {
00348     nlink++;
00349     fileSize = 0;
00350 }
00351             if (fileOwnerList && fileGroupList) {
00352                 printFileInfo(te, filespec, fileSize,
00353                                               fileModeList[i], fileMTimeList[i],
00354                                               fileRdevList[i], nlink,
00355                                               fileOwnerList[i], 
00356                                               fileGroupList[i], -1, 
00357                                               -1, fileLinktoList[i]);
00358                 te += strlen(te);
00359             } else if (fileUIDList && fileGIDList) {
00360                 printFileInfo(te, filespec, fileSize,
00361                                               fileModeList[i], fileMTimeList[i],
00362                                               fileRdevList[i], nlink,
00363                                               NULL, NULL, fileUIDList[i], 
00364                                               fileGIDList[i], 
00365                                               fileLinktoList[i]);
00366                 te += strlen(te);
00367             } else {
00368                 rpmError(RPMERR_INTERNAL,
00369                         _("package has neither file owner or id lists\n"));
00370             }
00371 
00372             filespec = _free(filespec);
00373         }
00374         if (te > t) {
00375             *te++ = '\n';
00376             *te = '\0';
00377             rpmMessage(RPMMESS_NORMAL, "%s", t);
00378             te = t;
00379             *t = '\0';
00380         }
00381     }
00382             
00383     rc = 0;
00384 
00385 exit:
00386     if (te > t) {
00387         if (!nonewline) {
00388             *te++ = '\n';
00389             *te = '\0';
00390         }
00391         rpmMessage(RPMMESS_NORMAL, "%s", t);
00392     }
00393     t = _free(t);
00394     dirNames = hfd(dirNames, dnt);
00395     baseNames = hfd(baseNames, bnt);
00396     fileLinktoList = hfd(fileLinktoList, ltt);
00397     fileMD5List = hfd(fileMD5List, m5t);
00398     fileOwnerList = hfd(fileOwnerList, fot);
00399     fileGroupList = hfd(fileGroupList, fgt);
00400     return rc;
00401 }
00402 
00405 static void
00406 printNewSpecfile(Spec spec)
00407         /*@globals fileSystem @*/
00408         /*@modifies spec->sl->sl_lines[], fileSystem @*/
00409 {
00410     Header h;
00411     speclines sl = spec->sl;
00412     spectags st = spec->st;
00413     const char * msgstr = NULL;
00414     int i, j;
00415 
00416     if (sl == NULL || st == NULL)
00417         return;
00418 
00419     /*@-branchstate@*/
00420     for (i = 0; i < st->st_ntags; i++) {
00421         spectag t = st->st_t + i;
00422         const char * tn = tagName(t->t_tag);
00423         const char * errstr;
00424         char fmt[1024];
00425 
00426         fmt[0] = '\0';
00427         if (t->t_msgid == NULL)
00428             h = spec->packages->header;
00429         else {
00430             Package pkg;
00431             char *fe;
00432 
00433             strcpy(fmt, t->t_msgid);
00434             for (fe = fmt; *fe && *fe != '('; fe++)
00435                 {} ;
00436             if (*fe == '(') *fe = '\0';
00437             h = NULL;
00438             for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
00439                 const char *pkgname;
00440                 h = pkg->header;
00441                 (void) headerNVR(h, &pkgname, NULL, NULL);
00442                 if (!strcmp(pkgname, fmt))
00443                     /*@innerbreak@*/ break;
00444             }
00445             if (pkg == NULL || h == NULL)
00446                 h = spec->packages->header;
00447         }
00448 
00449         if (h == NULL)
00450             continue;
00451 
00452         fmt[0] = '\0';
00453         (void) stpcpy( stpcpy( stpcpy( fmt, "%{"), tn), "}");
00454         msgstr = _free(msgstr);
00455 
00456         msgstr = headerSprintf(h, fmt, rpmTagTable, rpmHeaderFormats, &errstr);
00457         if (msgstr == NULL) {
00458             rpmError(RPMERR_QFMT, _("can't query %s: %s\n"), tn, errstr);
00459             return;
00460         }
00461 
00462         switch(t->t_tag) {
00463         case RPMTAG_SUMMARY:
00464         case RPMTAG_GROUP:
00465             /*@-unqualifiedtrans@*/
00466             sl->sl_lines[t->t_startx] = _free(sl->sl_lines[t->t_startx]);
00467             /*@=unqualifiedtrans@*/
00468             if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG))
00469                 continue;
00470             {   char *buf = xmalloc(strlen(tn) + sizeof(": ") + strlen(msgstr));
00471                 (void) stpcpy( stpcpy( stpcpy(buf, tn), ": "), msgstr);
00472                 sl->sl_lines[t->t_startx] = buf;
00473             }
00474             /*@switchbreak@*/ break;
00475         case RPMTAG_DESCRIPTION:
00476             for (j = 1; j < t->t_nlines; j++) {
00477                 if (*sl->sl_lines[t->t_startx + j] == '%')
00478                     /*@innercontinue@*/ continue;
00479                 /*@-unqualifiedtrans@*/
00480                 sl->sl_lines[t->t_startx + j] =
00481                         _free(sl->sl_lines[t->t_startx + j]);
00482                 /*@=unqualifiedtrans@*/
00483             }
00484             if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG)) {
00485                 sl->sl_lines[t->t_startx] = _free(sl->sl_lines[t->t_startx]);
00486                 continue;
00487             }
00488             sl->sl_lines[t->t_startx + 1] = xstrdup(msgstr);
00489             if (t->t_nlines > 2)
00490                 sl->sl_lines[t->t_startx + 2] = xstrdup("\n\n");
00491             /*@switchbreak@*/ break;
00492         }
00493     }
00494     /*@=branchstate@*/
00495     msgstr = _free(msgstr);
00496 
00497     for (i = 0; i < sl->sl_nlines; i++) {
00498         const char * s = sl->sl_lines[i];
00499         if (s == NULL)
00500             continue;
00501         printf("%s", s);
00502         if (strchr(s, '\n') == NULL && s[strlen(s)-1] != '\n')
00503             printf("\n");
00504     }
00505 }
00506 
00507 void rpmDisplayQueryTags(FILE * fp)
00508 {
00509     const struct headerTagTableEntry_s * t;
00510     int i;
00511     const struct headerSprintfExtension_s * ext = rpmHeaderFormats;
00512 
00513     for (i = 0, t = rpmTagTable; i < rpmTagTableSize; i++, t++)
00514         if (t->name) fprintf(fp, "%s\n", t->name + 7);
00515 
00516     while (ext->name != NULL) {
00517         if (ext->type == HEADER_EXT_MORE) {
00518             ext = ext->u.more;
00519             continue;
00520         }
00521         /* XXX don't print query tags twice. */
00522         for (i = 0, t = rpmTagTable; i < rpmTagTableSize; i++, t++) {
00523             if (t->name == NULL)        /* XXX programmer error. */
00524                 /*@innercontinue@*/ continue;
00525             if (!strcmp(t->name, ext->name))
00526                 /*@innerbreak@*/ break;
00527         }
00528         if (i >= rpmTagTableSize && ext->type == HEADER_EXT_TAG)
00529             fprintf(fp, "%s\n", ext->name + 7);
00530         ext++;
00531     }
00532 }
00533 
00534 int showMatches(QVA_t qva, rpmdbMatchIterator mi, QVF_t showPackage)
00535 {
00536     Header h;
00537     int ec = 0;
00538 
00539     while ((h = rpmdbNextIterator(mi)) != NULL) {
00540         int rc;
00541         /*@-nullpass@*/
00542         if ((rc = showPackage(qva, rpmdbGetIteratorRpmDB(mi), h)) != 0)
00543             ec = rc;
00544         /*@=nullpass@*/
00545     }
00546     mi = rpmdbFreeIterator(mi);
00547     return ec;
00548 }
00549 
00555 static inline unsigned char nibble(char c)
00556         /*@*/
00557 {
00558     if (c >= '0' && c <= '9')
00559         return (c - '0');
00560     if (c >= 'A' && c <= 'F')
00561         return (c - 'A') + 10;
00562     if (c >= 'a' && c <= 'f')
00563         return (c - 'a') + 10;
00564     return 0;
00565 }
00566 
00567 /*@-redecl@*/
00571 int     (*parseSpecVec) (Spec *specp, const char *specFile, const char *rootdir,
00572                 const char *buildRoot, int recursing, const char *passPhrase,
00573                 char *cookie, int anyarch, int force) = NULL;
00577 /*@null@*/ Spec (*freeSpecVec) (Spec spec) = NULL;
00578 /*@=redecl@*/
00579 
00580 int rpmQueryVerify(QVA_t qva, rpmQVSources source, const char * arg,
00581         rpmdb rpmdb, QVF_t showPackage)
00582 {
00583     rpmdbMatchIterator mi = NULL;
00584     Header h;
00585     int rc;
00586     int isSource;
00587     int retcode = 0;
00588     const char ** av = NULL;
00589     char * end = NULL;
00590     const char * s;
00591     int i;
00592 
00593     switch (source) {
00594     case RPMQV_RPM:
00595     {   int ac = 0;
00596         const char * fileURL = NULL;
00597         rpmRC rpmrc;
00598 
00599         rc = rpmGlob(arg, &ac, &av);
00600         if (rc) return 1;
00601 
00602 restart:
00603         for (i = 0; i < ac; i++) {
00604             FD_t fd;
00605 
00606             fileURL = _free(fileURL);
00607             fileURL = av[i];
00608             av[i] = NULL;
00609 
00610             /* Try to read the header from a package file. */
00611             fd = Fopen(fileURL, "r.ufdio");
00612             if (fd == NULL || Ferror(fd)) {
00613                 rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), fileURL,
00614                         Fstrerror(fd));
00615                 if (fd) (void) Fclose(fd);
00616                 retcode = 1;
00617                 /*@loopbreak@*/ break;
00618             }
00619 
00620             /*@-mustmod@*/      /* LCL: segfault. */
00621             rpmrc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
00622             /*@=mustmod@*/
00623             (void) Fclose(fd);
00624 
00625             if (!(rpmrc == RPMRC_OK || rpmrc == RPMRC_BADMAGIC)) {
00626                 rpmError(RPMERR_QUERY, _("query of %s failed\n"), fileURL);
00627                 retcode = 1;
00628                 /*@loopbreak@*/ break;
00629             }
00630             if (rpmrc == RPMRC_OK && h == NULL) {
00631                 rpmError(RPMERR_QUERY,
00632                         _("old format source packages cannot be queried\n"));
00633                 retcode = 1;
00634                 /*@loopbreak@*/ break;
00635             }
00636 
00637             /* Query a package file. */
00638             if (rpmrc == RPMRC_OK) {
00639                 retcode = showPackage(qva, rpmdb, h);
00640                 h = headerFree(h);
00641                 continue;
00642             }
00643 
00644             /* Try to read a package manifest. */
00645             fd = Fopen(fileURL, "r.fpio");
00646             if (fd == NULL || Ferror(fd)) {
00647                 rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), fileURL,
00648                         Fstrerror(fd));
00649                 if (fd) (void) Fclose(fd);
00650                 retcode = 1;
00651                 /*@loopbreak@*/ break;
00652             }
00653             
00654             /* Read list of packages from manifest. */
00655             retcode = rpmReadPackageManifest(fd, &ac, &av);
00656             if (retcode) {
00657                 rpmError(RPMERR_MANIFEST, _("%s: read manifest failed: %s\n"),
00658                         fileURL, Fstrerror(fd));
00659                 retcode = 1;
00660             }
00661             (void) Fclose(fd);
00662 
00663             /* If successful, restart the query loop. */
00664             if (retcode == 0)
00665                 goto restart;
00666 
00667             /*@loopbreak@*/ break;
00668         }
00669 
00670         fileURL = _free(fileURL);
00671         if (av) {
00672             for (i = 0; i < ac; i++)
00673                 av[i] = _free(av[i]);
00674             av = _free(av);
00675         }
00676     }   break;
00677 
00678     case RPMQV_SPECFILE:
00679         if (showPackage != showQueryPackage)
00680             return 1;
00681 
00682         /* XXX Eliminate linkage dependency loop */
00683         if (parseSpecVec == NULL || freeSpecVec == NULL)
00684             return 1;
00685 
00686       { Spec spec = NULL;
00687         Package pkg;
00688         char * buildRoot = NULL;
00689         int recursing = 0;
00690         char * passPhrase = "";
00691         char *cookie = NULL;
00692         int anyarch = 1;
00693         int force = 1;
00694 
00695         rc = parseSpecVec(&spec, arg, "/", buildRoot, recursing, passPhrase,
00696                 cookie, anyarch, force);
00697         if (rc || spec == NULL) {
00698             rpmError(RPMERR_QUERY,
00699                         _("query of specfile %s failed, can't parse\n"), arg);
00700             spec = freeSpecVec(spec);
00701             retcode = 1;
00702             break;
00703         }
00704 
00705         if (specedit) {
00706             printNewSpecfile(spec);
00707             spec = freeSpecVec(spec);
00708             retcode = 0;
00709             break;
00710         }
00711 
00712         for (pkg = spec->packages; pkg != NULL; pkg = pkg->next)
00713             (void) showPackage(qva, NULL, pkg->header);
00714         spec = freeSpecVec(spec);
00715       } break;
00716 
00717     case RPMQV_ALL:
00718         /* RPMDBI_PACKAGES */
00719         mi = rpmdbInitIterator(rpmdb, RPMDBI_PACKAGES, NULL, 0);
00720         if (mi == NULL) {
00721             rpmError(RPMERR_QUERYINFO, _("no packages\n"));
00722             retcode = 1;
00723         } else {
00724             for (av = (const char **) arg; av && *av; av++) {
00725                 if (!rpmdbSetIteratorRE(mi, RPMTAG_NAME, RPMMIRE_DEFAULT, *av))
00726                     continue;
00727                 mi = rpmdbFreeIterator(mi);
00728                 retcode = 1;
00729                 /*@loopbreak@*/ break;
00730             }
00731             if (!retcode)
00732                 retcode = showMatches(qva, mi, showPackage);
00733         }
00734         break;
00735 
00736     case RPMQV_GROUP:
00737         mi = rpmdbInitIterator(rpmdb, RPMTAG_GROUP, arg, 0);
00738         if (mi == NULL) {
00739             rpmError(RPMERR_QUERYINFO,
00740                 _("group %s does not contain any packages\n"), arg);
00741             retcode = 1;
00742         } else {
00743             retcode = showMatches(qva, mi, showPackage);
00744         }
00745         break;
00746 
00747     case RPMQV_TRIGGEREDBY:
00748         mi = rpmdbInitIterator(rpmdb, RPMTAG_TRIGGERNAME, arg, 0);
00749         if (mi == NULL) {
00750             rpmError(RPMERR_QUERYINFO, _("no package triggers %s\n"), arg);
00751             retcode = 1;
00752         } else {
00753             retcode = showMatches(qva, mi, showPackage);
00754         }
00755         break;
00756 
00757     case RPMQV_PKGID:
00758     {   unsigned char md5[16];
00759         unsigned char * t;
00760 
00761         for (i = 0, s = arg; *s && isxdigit(*s); s++, i++)
00762             {};
00763         if (i != 32) {
00764             rpmError(RPMERR_QUERYINFO, _("malformed %s: %s\n"), "pkgid", arg);
00765             return 1;
00766         }
00767 
00768         for (i = 0, t = md5, s = arg; i < 16; i++, t++, s += 2)
00769             *t = (nibble(s[0]) << 4) | nibble(s[1]);
00770         
00771         mi = rpmdbInitIterator(rpmdb, RPMTAG_SIGMD5, md5, 16);
00772         if (mi == NULL) {
00773             rpmError(RPMERR_QUERYINFO, _("no package matches %s: %s\n"),
00774                         "pkgid", arg);
00775             retcode = 1;
00776         } else {
00777             retcode = showMatches(qva, mi, showPackage);
00778         }
00779     }   break;
00780 
00781     case RPMQV_HDRID:
00782         for (i = 0, s = arg; *s && isxdigit(*s); s++, i++)
00783             {};
00784         if (i != 40) {
00785             rpmError(RPMERR_QUERYINFO, _("malformed %s: %s\n"), "hdrid", arg);
00786             return 1;
00787         }
00788 
00789         mi = rpmdbInitIterator(rpmdb, RPMTAG_SHA1HEADER, arg, 0);
00790         if (mi == NULL) {
00791             rpmError(RPMERR_QUERYINFO, _("no package matches %s: %s\n"),
00792                         "hdrid", arg);
00793             retcode = 1;
00794         } else {
00795             retcode = showMatches(qva, mi, showPackage);
00796         }
00797         break;
00798 
00799     case RPMQV_FILEID:
00800         for (i = 0, s = arg; *s && isxdigit(*s); s++, i++)
00801             {};
00802         if (i != 32) {
00803             rpmError(RPMERR_QUERY, _("malformed %s: %s\n"), "fileid", arg);
00804             return 1;
00805         }
00806 
00807         mi = rpmdbInitIterator(rpmdb, RPMTAG_FILEMD5S, arg, 0);
00808         if (mi == NULL) {
00809             rpmError(RPMERR_QUERYINFO, _("no package matches %s: %s\n"),
00810                         "fileid", arg);
00811             retcode = 1;
00812         } else {
00813             retcode = showMatches(qva, mi, showPackage);
00814         }
00815         break;
00816 
00817     case RPMQV_TID:
00818     {   int mybase = 10;
00819         const char * myarg = arg;
00820         unsigned iid;
00821 
00822         /* XXX should be in strtoul */
00823         if (*myarg == '0') {
00824             myarg++;
00825             mybase = 8;
00826             if (*myarg == 'x') {
00827                 myarg++;
00828                 mybase = 16;
00829             }
00830         }
00831         iid = strtoul(myarg, &end, mybase);
00832         if ((*end) || (end == arg) || (iid == ULONG_MAX)) {
00833             rpmError(RPMERR_QUERY, _("malformed %s: %s\n"), "tid", arg);
00834             return 1;
00835         }
00836         mi = rpmdbInitIterator(rpmdb, RPMTAG_INSTALLTID, &iid, sizeof(iid));
00837         if (mi == NULL) {
00838             rpmError(RPMERR_QUERYINFO, _("no package matches %s: %s\n"),
00839                         "tid", arg);
00840             retcode = 1;
00841         } else {
00842             retcode = showMatches(qva, mi, showPackage);
00843         }
00844     }   break;
00845 
00846     case RPMQV_WHATREQUIRES:
00847         mi = rpmdbInitIterator(rpmdb, RPMTAG_REQUIRENAME, arg, 0);
00848         if (mi == NULL) {
00849             rpmError(RPMERR_QUERYINFO, _("no package requires %s\n"), arg);
00850             retcode = 1;
00851         } else {
00852             retcode = showMatches(qva, mi, showPackage);
00853         }
00854         break;
00855 
00856     case RPMQV_WHATPROVIDES:
00857         if (arg[0] != '/') {
00858             mi = rpmdbInitIterator(rpmdb, RPMTAG_PROVIDENAME, arg, 0);
00859             if (mi == NULL) {
00860                 rpmError(RPMERR_QUERYINFO, _("no package provides %s\n"), arg);
00861                 retcode = 1;
00862             } else {
00863                 retcode = showMatches(qva, mi, showPackage);
00864             }
00865             break;
00866         }
00867         /*@fallthrough@*/
00868     case RPMQV_PATH:
00869     {   char * fn;
00870 
00871         for (s = arg; *s != '\0'; s++)
00872             if (!(*s == '.' || *s == '/'))
00873                 /*@loopbreak@*/ break;
00874 
00875         if (*s == '\0') {
00876             char fnbuf[PATH_MAX];
00877             fn = /*@-unrecog@*/ realpath(arg, fnbuf) /*@=unrecog@*/;
00878             if (fn)
00879                 fn = xstrdup(fn);
00880             else
00881                 fn = xstrdup(arg);
00882         } else
00883             fn = xstrdup(arg);
00884         (void) rpmCleanPath(fn);
00885 
00886         mi = rpmdbInitIterator(rpmdb, RPMTAG_BASENAMES, fn, 0);
00887         if (mi == NULL) {
00888             int myerrno = 0;
00889             if (access(fn, F_OK) != 0)
00890                 myerrno = errno;
00891             switch (myerrno) {
00892             default:
00893                 rpmError(RPMERR_QUERY,
00894                         _("file %s: %s\n"), fn, strerror(myerrno));
00895                 break;
00896             case 0:
00897                 rpmError(RPMERR_QUERYINFO,
00898                         _("file %s is not owned by any package\n"), fn);
00899                 break;
00900             }
00901             retcode = 1;
00902         } else {
00903             retcode = showMatches(qva, mi, showPackage);
00904         }
00905         fn = _free(fn);
00906     }   break;
00907 
00908     case RPMQV_DBOFFSET:
00909     {   int mybase = 10;
00910         const char * myarg = arg;
00911         unsigned recOffset;
00912 
00913         /* XXX should be in strtoul */
00914         if (*myarg == '0') {
00915             myarg++;
00916             mybase = 8;
00917             if (*myarg == 'x') {
00918                 myarg++;
00919                 mybase = 16;
00920             }
00921         }
00922         recOffset = strtoul(myarg, &end, mybase);
00923         if ((*end) || (end == arg) || (recOffset == ULONG_MAX)) {
00924             rpmError(RPMERR_QUERYINFO, _("invalid package number: %s\n"), arg);
00925             return 1;
00926         }
00927         rpmMessage(RPMMESS_DEBUG, _("package record number: %u\n"), recOffset);
00928         mi = rpmdbInitIterator(rpmdb, RPMDBI_PACKAGES, &recOffset, sizeof(recOffset));
00929         if (mi == NULL) {
00930             rpmError(RPMERR_QUERYINFO,
00931                 _("record %u could not be read\n"), recOffset);
00932             retcode = 1;
00933         } else {
00934             retcode = showMatches(qva, mi, showPackage);
00935         }
00936     }   break;
00937 
00938     case RPMQV_PACKAGE:
00939         /* XXX HACK to get rpmdbFindByLabel out of the API */
00940         mi = rpmdbInitIterator(rpmdb, RPMDBI_LABEL, arg, 0);
00941         if (mi == NULL) {
00942             rpmError(RPMERR_QUERYINFO, _("package %s is not installed\n"), arg);
00943             retcode = 1;
00944         } else {
00945             retcode = showMatches(qva, mi, showPackage);
00946         }
00947         break;
00948     }
00949    
00950     return retcode;
00951 }
00952 
00953 int rpmQuery(QVA_t qva, rpmQVSources source, const char * arg)
00954 {
00955     rpmdb rpmdb = NULL;
00956     int rc;
00957 
00958     switch (source) {
00959     case RPMQV_RPM:
00960     case RPMQV_SPECFILE:
00961         break;
00962     default:
00963         if (rpmdbOpen(qva->qva_prefix, &rpmdb, O_RDONLY, 0644))
00964             return 1;
00965         break;
00966     }
00967 
00968     rc = rpmQueryVerify(qva, source, arg, rpmdb, showQueryPackage);
00969 
00970     if (rpmdb != NULL)
00971         (void) rpmdbClose(rpmdb);
00972 
00973     return rc;
00974 }

Generated on Mon Apr 18 03:27:25 2005 for rpm by  doxygen 1.4.1