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 /*@-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 = "(unknown error)";
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         /* XXX this should use queryHeader(), but prints out tn as well. */
00457         msgstr = headerSprintf(h, fmt, rpmTagTable, rpmHeaderFormats, &errstr);
00458         if (msgstr == NULL) {
00459             rpmError(RPMERR_QFMT, _("can't query %s: %s\n"), tn, errstr);
00460             return;
00461         }
00462 
00463         switch(t->t_tag) {
00464         case RPMTAG_SUMMARY:
00465         case RPMTAG_GROUP:
00466             /*@-unqualifiedtrans@*/
00467             sl->sl_lines[t->t_startx] = _free(sl->sl_lines[t->t_startx]);
00468             /*@=unqualifiedtrans@*/
00469             if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG))
00470                 continue;
00471             {   char *buf = xmalloc(strlen(tn) + sizeof(": ") + strlen(msgstr));
00472                 (void) stpcpy( stpcpy( stpcpy(buf, tn), ": "), msgstr);
00473                 sl->sl_lines[t->t_startx] = buf;
00474             }
00475             /*@switchbreak@*/ break;
00476         case RPMTAG_DESCRIPTION:
00477             for (j = 1; j < t->t_nlines; j++) {
00478                 if (*sl->sl_lines[t->t_startx + j] == '%')
00479                     /*@innercontinue@*/ continue;
00480                 /*@-unqualifiedtrans@*/
00481                 sl->sl_lines[t->t_startx + j] =
00482                         _free(sl->sl_lines[t->t_startx + j]);
00483                 /*@=unqualifiedtrans@*/
00484             }
00485             if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG)) {
00486                 sl->sl_lines[t->t_startx] = _free(sl->sl_lines[t->t_startx]);
00487                 continue;
00488             }
00489             sl->sl_lines[t->t_startx + 1] = xstrdup(msgstr);
00490             if (t->t_nlines > 2)
00491                 sl->sl_lines[t->t_startx + 2] = xstrdup("\n\n");
00492             /*@switchbreak@*/ break;
00493         }
00494     }
00495     /*@=branchstate@*/
00496     msgstr = _free(msgstr);
00497 
00498     for (i = 0; i < sl->sl_nlines; i++) {
00499         const char * s = sl->sl_lines[i];
00500         if (s == NULL)
00501             continue;
00502         printf("%s", s);
00503         if (strchr(s, '\n') == NULL && s[strlen(s)-1] != '\n')
00504             printf("\n");
00505     }
00506 }
00507 
00508 void rpmDisplayQueryTags(FILE * fp)
00509 {
00510     const struct headerTagTableEntry_s * t;
00511     int i;
00512     const struct headerSprintfExtension_s * ext = rpmHeaderFormats;
00513 
00514     for (i = 0, t = rpmTagTable; i < rpmTagTableSize; i++, t++)
00515         if (t->name) fprintf(fp, "%s\n", t->name + 7);
00516 
00517     while (ext->name != NULL) {
00518         if (ext->type == HEADER_EXT_MORE) {
00519             ext = ext->u.more;
00520             continue;
00521         }
00522         /* XXX don't print query tags twice. */
00523         for (i = 0, t = rpmTagTable; i < rpmTagTableSize; i++, t++) {
00524             if (t->name == NULL)        /* XXX programmer error. */
00525                 /*@innercontinue@*/ continue;
00526             if (!strcmp(t->name, ext->name))
00527                 /*@innerbreak@*/ break;
00528         }
00529         if (i >= rpmTagTableSize && ext->type == HEADER_EXT_TAG)
00530             fprintf(fp, "%s\n", ext->name + 7);
00531         ext++;
00532     }
00533 }
00534 
00535 int showMatches(QVA_t qva, rpmdbMatchIterator mi, QVF_t showPackage)
00536 {
00537     Header h;
00538     int ec = 0;
00539 
00540     while ((h = rpmdbNextIterator(mi)) != NULL) {
00541         int rc;
00542         /*@-nullpass@*/
00543         if ((rc = showPackage(qva, rpmdbGetIteratorRpmDB(mi), h)) != 0)
00544             ec = rc;
00545         /*@=nullpass@*/
00546     }
00547     mi = rpmdbFreeIterator(mi);
00548     return ec;
00549 }
00550 
00556 static inline unsigned char nibble(char c)
00557         /*@*/
00558 {
00559     if (c >= '0' && c <= '9')
00560         return (c - '0');
00561     if (c >= 'A' && c <= 'F')
00562         return (c - 'A') + 10;
00563     if (c >= 'a' && c <= 'f')
00564         return (c - 'a') + 10;
00565     return 0;
00566 }
00567 
00568 /*@-redecl@*/
00572 int     (*parseSpecVec) (Spec *specp, const char *specFile, const char *rootdir,
00573                 const char *buildRoot, int recursing, const char *passPhrase,
00574                 char *cookie, int anyarch, int force, int preprocess) = NULL;
00578 /*@null@*/ Spec (*freeSpecVec) (Spec spec) = NULL;
00579 /*@=redecl@*/
00580 
00581 int rpmQueryVerify(QVA_t qva, rpmQVSources source, const char * arg,
00582         rpmdb rpmdb, QVF_t showPackage)
00583 {
00584     rpmdbMatchIterator mi = NULL;
00585     Header h;
00586     int rc;
00587     int isSource;
00588     int retcode = 0;
00589     const char ** av = NULL;
00590     char * end = NULL;
00591     const char * s;
00592     int i;
00593 
00594     switch (source) {
00595     case RPMQV_RPM:
00596     if (rpmExpandNumeric("%{!?_disable_glob_query:%{?_enable_glob_query:1}}"))
00597     {
00598         int ac = 0;
00599         const char * fileURL = NULL;
00600         rpmRC rpmrc;
00601 
00602         rc = rpmGlob(arg, &ac, &av);
00603         if (rc) return 1;
00604 
00605 restart:
00606         for (i = 0; i < ac; i++) {
00607             FD_t fd;
00608 
00609             fileURL = _free(fileURL);
00610             fileURL = av[i];
00611             av[i] = NULL;
00612 
00613             /* Try to read the header from a package file. */
00614             fd = Fopen(fileURL, "r.ufdio");
00615             if (fd == NULL || Ferror(fd)) {
00616                 rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), fileURL,
00617                         Fstrerror(fd));
00618                 if (fd) (void) Fclose(fd);
00619                 retcode = 1;
00620                 /*@loopbreak@*/ break;
00621             }
00622 
00623             /*@-mustmod@*/      /* LCL: segfault. */
00624             rpmrc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
00625             /*@=mustmod@*/
00626             (void) Fclose(fd);
00627 
00628             if (!(rpmrc == RPMRC_OK || rpmrc == RPMRC_BADMAGIC)) {
00629                 rpmError(RPMERR_QUERY, _("query of %s failed\n"), fileURL);
00630                 retcode = 1;
00631                 /*@loopbreak@*/ break;
00632             }
00633             if (rpmrc == RPMRC_OK && h == NULL) {
00634                 rpmError(RPMERR_QUERY,
00635                         _("old format source packages cannot be queried\n"));
00636                 retcode = 1;
00637                 /*@loopbreak@*/ break;
00638             }
00639 
00640             /* Query a package file. */
00641             if (rpmrc == RPMRC_OK) {
00642                 retcode = showPackage(qva, rpmdb, h);
00643                 h = headerFree(h);
00644                 continue;
00645             }
00646 
00647             /* Try to read a package manifest. */
00648             fd = Fopen(fileURL, "r.fpio");
00649             if (fd == NULL || Ferror(fd)) {
00650                 rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), fileURL,
00651                         Fstrerror(fd));
00652                 if (fd) (void) Fclose(fd);
00653                 retcode = 1;
00654                 /*@loopbreak@*/ break;
00655             }
00656             
00657             /* Read list of packages from manifest. */
00658             retcode = rpmReadPackageManifest(fd, &ac, &av);
00659             if (retcode) {
00660                 rpmError(RPMERR_MANIFEST, _("%s: read manifest failed: %s\n"),
00661                         fileURL, Fstrerror(fd));
00662                 retcode = 1;
00663             }
00664             (void) Fclose(fd);
00665 
00666             /* If successful, restart the query loop. */
00667             if (retcode == 0)
00668                 goto restart;
00669 
00670             /*@loopbreak@*/ break;
00671         }
00672 
00673         fileURL = _free(fileURL);
00674         if (av) {
00675             for (i = 0; i < ac; i++)
00676                 av[i] = _free(av[i]);
00677             av = _free(av);
00678         }
00679     } else {
00680         const char * fileURL = arg;
00681         rpmRC rpmrc;
00682 
00683             /* Try to read the header from a package file. */
00684             FD_t fd = Fopen(fileURL, "r.ufdio");
00685             if (fd == NULL || Ferror(fd)) {
00686                 rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), fileURL,
00687                         Fstrerror(fd));
00688                 if (fd) (void) Fclose(fd);
00689                 retcode = 1;
00690                 break;
00691             }
00692 
00693             /*@-mustmod@*/      /* LCL: segfault. */
00694             rpmrc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
00695             /*@=mustmod@*/
00696             (void) Fclose(fd);
00697 
00698             if (!(rpmrc == RPMRC_OK || rpmrc == RPMRC_BADMAGIC)) {
00699                 rpmError(RPMERR_QUERY, _("query of %s failed\n"), fileURL);
00700                 retcode = 1;
00701                 break;
00702             }
00703             if (rpmrc == RPMRC_OK && h == NULL) {
00704                 rpmError(RPMERR_QUERY,
00705                         _("old format source packages cannot be queried\n"));
00706                 retcode = 1;
00707                 break;
00708             }
00709 
00710             /* Query a package file. */
00711             if (rpmrc == RPMRC_OK) {
00712                 retcode = showPackage(qva, rpmdb, h);
00713                 h = headerFree(h);
00714                 break;
00715             }
00716     }   break;
00717 
00718     case RPMQV_SPECFILE:
00719         if (showPackage != showQueryPackage)
00720             return 1;
00721 
00722         /* XXX Eliminate linkage dependency loop */
00723         if (parseSpecVec == NULL || freeSpecVec == NULL)
00724             return 1;
00725 
00726       { Spec spec = NULL;
00727         Package pkg;
00728         char * buildRoot = NULL;
00729         int recursing = 0;
00730         char * passPhrase = "";
00731         char *cookie = NULL;
00732         int anyarch = 1;
00733         int force = 1;
00734         int preprocess = 0;
00735 
00736         rc = parseSpecVec(&spec, arg, "/", buildRoot, recursing, passPhrase,
00737                 cookie, anyarch, force, preprocess);
00738         if (rc || spec == NULL) {
00739             rpmError(RPMERR_QUERY,
00740                         _("query of specfile %s failed, can't parse\n"), arg);
00741             spec = freeSpecVec(spec);
00742             retcode = 1;
00743             break;
00744         }
00745 
00746         if (specedit) {
00747             printNewSpecfile(spec);
00748             spec = freeSpecVec(spec);
00749             retcode = 0;
00750             break;
00751         }
00752 
00753         for (pkg = spec->packages; pkg != NULL; pkg = pkg->next)
00754             (void) showPackage(qva, NULL, pkg->header);
00755         spec = freeSpecVec(spec);
00756       } break;
00757 
00758     case RPMQV_ALL:
00759         /* RPMDBI_PACKAGES */
00760         mi = rpmdbInitIterator(rpmdb, RPMDBI_PACKAGES, NULL, 0);
00761         if (mi == NULL) {
00762             rpmError(RPMERR_QUERYINFO, _("no packages\n"));
00763             retcode = 1;
00764         } else {
00765             for (av = (const char **) arg; av && *av; av++) {
00766                 if (!rpmdbSetIteratorRE(mi, RPMTAG_NAME, RPMMIRE_DEFAULT, *av))
00767                     continue;
00768                 mi = rpmdbFreeIterator(mi);
00769                 retcode = 1;
00770                 /*@loopbreak@*/ break;
00771             }
00772             if (!retcode)
00773                 retcode = showMatches(qva, mi, showPackage);
00774         }
00775         break;
00776 
00777     case RPMQV_GROUP:
00778         mi = rpmdbInitIterator(rpmdb, RPMTAG_GROUP, arg, 0);
00779         if (mi == NULL) {
00780             rpmError(RPMERR_QUERYINFO,
00781                 _("group %s does not contain any packages\n"), arg);
00782             retcode = 1;
00783         } else {
00784             retcode = showMatches(qva, mi, showPackage);
00785         }
00786         break;
00787 
00788     case RPMQV_TRIGGEREDBY:
00789         mi = rpmdbInitIterator(rpmdb, RPMTAG_TRIGGERNAME, arg, 0);
00790         if (mi == NULL) {
00791             rpmError(RPMERR_QUERYINFO, _("no package triggers %s\n"), arg);
00792             retcode = 1;
00793         } else {
00794             retcode = showMatches(qva, mi, showPackage);
00795         }
00796         break;
00797 
00798     case RPMQV_PKGID:
00799     {   unsigned char md5[16];
00800         unsigned char * t;
00801 
00802         for (i = 0, s = arg; *s && isxdigit(*s); s++, i++)
00803             {};
00804         if (i != 32) {
00805             rpmError(RPMERR_QUERYINFO, _("malformed %s: %s\n"), "pkgid", arg);
00806             return 1;
00807         }
00808 
00809         md5[0] = '\0';
00810         for (i = 0, t = md5, s = arg; i < 16; i++, t++, s += 2)
00811             *t = (nibble(s[0]) << 4) | nibble(s[1]);
00812         
00813         mi = rpmdbInitIterator(rpmdb, RPMTAG_SIGMD5, md5, sizeof(md5));
00814         if (mi == NULL) {
00815             rpmError(RPMERR_QUERYINFO, _("no package matches %s: %s\n"),
00816                         "pkgid", arg);
00817             retcode = 1;
00818         } else {
00819             retcode = showMatches(qva, mi, showPackage);
00820         }
00821     }   break;
00822 
00823     case RPMQV_HDRID:
00824         for (i = 0, s = arg; *s && isxdigit(*s); s++, i++)
00825             {};
00826         if (i != 40) {
00827             rpmError(RPMERR_QUERYINFO, _("malformed %s: %s\n"), "hdrid", arg);
00828             return 1;
00829         }
00830 
00831         mi = rpmdbInitIterator(rpmdb, RPMTAG_SHA1HEADER, arg, 0);
00832         if (mi == NULL) {
00833             rpmError(RPMERR_QUERYINFO, _("no package matches %s: %s\n"),
00834                         "hdrid", arg);
00835             retcode = 1;
00836         } else {
00837             retcode = showMatches(qva, mi, showPackage);
00838         }
00839         break;
00840 
00841     case RPMQV_FILEID:
00842     {   unsigned char md5[16];
00843         unsigned char * t;
00844 
00845         for (i = 0, s = arg; *s && isxdigit(*s); s++, i++)
00846             {};
00847         if (i != 32) {
00848             rpmError(RPMERR_QUERY, _("malformed %s: %s\n"), "fileid", arg);
00849             return 1;
00850         }
00851 
00852         md5[0] = '\0';
00853         for (i = 0, t = md5, s = arg; i < 16; i++, t++, s += 2)
00854             *t = (nibble(s[0]) << 4) | nibble(s[1]);
00855         
00856         mi = rpmdbInitIterator(rpmdb, RPMTAG_FILEMD5S, md5, sizeof(md5));
00857         if (mi == NULL) {
00858             rpmError(RPMERR_QUERYINFO, _("no package matches %s: %s\n"),
00859                         "fileid", arg);
00860             retcode = 1;
00861         } else {
00862             retcode = showMatches(qva, mi, showPackage);
00863         }
00864     }   break;
00865 
00866     case RPMQV_TID:
00867     {   int mybase = 10;
00868         const char * myarg = arg;
00869         unsigned iid;
00870 
00871         /* XXX should be in strtoul */
00872         if (*myarg == '0') {
00873             myarg++;
00874             mybase = 8;
00875             if (*myarg == 'x') {
00876                 myarg++;
00877                 mybase = 16;
00878             }
00879         }
00880         iid = strtoul(myarg, &end, mybase);
00881         if ((*end) || (end == arg) || (iid == ULONG_MAX)) {
00882             rpmError(RPMERR_QUERY, _("malformed %s: %s\n"), "tid", arg);
00883             return 1;
00884         }
00885         mi = rpmdbInitIterator(rpmdb, RPMTAG_INSTALLTID, &iid, sizeof(iid));
00886         if (mi == NULL) {
00887             rpmError(RPMERR_QUERYINFO, _("no package matches %s: %s\n"),
00888                         "tid", arg);
00889             retcode = 1;
00890         } else {
00891             retcode = showMatches(qva, mi, showPackage);
00892         }
00893     }   break;
00894 
00895     case RPMQV_WHATREQUIRES:
00896         mi = rpmdbInitIterator(rpmdb, RPMTAG_REQUIRENAME, arg, 0);
00897         if (mi == NULL) {
00898             rpmError(RPMERR_QUERYINFO, _("no package requires %s\n"), arg);
00899             retcode = 1;
00900         } else {
00901             retcode = showMatches(qva, mi, showPackage);
00902         }
00903         break;
00904 
00905     case RPMQV_WHATPROVIDES:
00906         mi = rpmdbInitIterator(rpmdb, RPMTAG_PROVIDENAME, arg, 0);
00907         if (mi == NULL) {
00908             if (arg[0] != '/')
00909                 rpmError(RPMERR_QUERYINFO, _("no package provides %s\n"), arg);
00910             retcode = 1;
00911         } else {
00912             retcode = showMatches(qva, mi, showPackage);
00913         }
00914         if (arg[0] != '/')
00915             break;
00916         /*@fallthrough@*/
00917     case RPMQV_PATH:
00918     {   char * fn;
00919 
00920         for (s = arg; *s != '\0'; s++)
00921             if (!(*s == '.' || *s == '/'))
00922                 /*@loopbreak@*/ break;
00923 
00924         if (*s == '\0') {
00925             char fnbuf[PATH_MAX];
00926             fn = /*@-unrecog@*/ realpath(arg, fnbuf) /*@=unrecog@*/;
00927             if (fn)
00928                 fn = xstrdup(fn);
00929             else
00930                 fn = xstrdup(arg);
00931         } else
00932             fn = xstrdup(arg);
00933         (void) rpmCleanPath(fn);
00934 
00935         mi = rpmdbInitIterator(rpmdb, RPMTAG_BASENAMES, fn, 0);
00936         if (mi == NULL) {
00937             int myerrno = 0;
00938             if (access(fn, F_OK) != 0)
00939                 myerrno = errno;
00940             switch (myerrno) {
00941             default:
00942                 rpmError(RPMERR_QUERY,
00943                         _("file %s: %s\n"), fn, strerror(myerrno));
00944                 break;
00945             case 0:
00946                 switch (source)
00947                 {
00948                     case RPMQV_PATH:
00949                         rpmError(RPMERR_QUERYINFO,
00950                                 _("file %s is not owned by any package\n"), fn);
00951                         break;
00952                     default:
00953                         if (retcode) rpmError(RPMERR_QUERYINFO,
00954                                 _("no package provides %s\n"), fn);
00955                         break;
00956                 }
00957                 break;
00958             }
00959             if (RPMQV_PATH == source)
00960             retcode = 1;
00961         } else {
00962             retcode = showMatches(qva, mi, showPackage);
00963         }
00964         fn = _free(fn);
00965     }   break;
00966 
00967     case RPMQV_DBOFFSET:
00968     {   int mybase = 10;
00969         const char * myarg = arg;
00970         unsigned recOffset;
00971 
00972         /* XXX should be in strtoul */
00973         if (*myarg == '0') {
00974             myarg++;
00975             mybase = 8;
00976             if (*myarg == 'x') {
00977                 myarg++;
00978                 mybase = 16;
00979             }
00980         }
00981         recOffset = strtoul(myarg, &end, mybase);
00982         if ((*end) || (end == arg) || (recOffset == ULONG_MAX)) {
00983             rpmError(RPMERR_QUERYINFO, _("invalid package number: %s\n"), arg);
00984             return 1;
00985         }
00986         rpmMessage(RPMMESS_DEBUG, _("package record number: %u\n"), recOffset);
00987         mi = rpmdbInitIterator(rpmdb, RPMDBI_PACKAGES, &recOffset, sizeof(recOffset));
00988         if (mi == NULL) {
00989             rpmError(RPMERR_QUERYINFO,
00990                 _("record %u could not be read\n"), recOffset);
00991             retcode = 1;
00992         } else {
00993             retcode = showMatches(qva, mi, showPackage);
00994         }
00995     }   break;
00996 
00997     case RPMQV_PACKAGE:
00998         /* XXX HACK to get rpmdbFindByLabel out of the API */
00999         mi = rpmdbInitIterator(rpmdb, RPMDBI_LABEL, arg, 0);
01000         if (mi == NULL) {
01001             rpmError(RPMERR_QUERYINFO, _("package %s is not installed\n"), arg);
01002             retcode = 1;
01003         } else {
01004             retcode = showMatches(qva, mi, showPackage);
01005         }
01006         break;
01007     }
01008    
01009     return retcode;
01010 }
01011 
01012 int rpmQuery(QVA_t qva, rpmQVSources source, const char * arg)
01013 {
01014     rpmdb rpmdb = NULL;
01015     int rc;
01016 
01017     switch (source) {
01018     case RPMQV_RPM:
01019     case RPMQV_SPECFILE:
01020         break;
01021     default:
01022         if (rpmdbOpen(qva->qva_prefix, &rpmdb, O_RDONLY, 0644))
01023             return 1;
01024         break;
01025     }
01026 
01027     rc = rpmQueryVerify(qva, source, arg, rpmdb, showQueryPackage);
01028 
01029     if (rpmdb != NULL)
01030         (void) rpmdbClose(rpmdb);
01031 
01032     return rc;
01033 }

Generated on Sun Feb 2 23:32:02 2003 for rpm by doxygen1.2.18