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 = "(unkown 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) = 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     {   int ac = 0;
00597         const char * fileURL = NULL;
00598         rpmRC rpmrc;
00599 
00600         rc = rpmGlob(arg, &ac, &av);
00601         if (rc) return 1;
00602 
00603 restart:
00604         for (i = 0; i < ac; i++) {
00605             FD_t fd;
00606 
00607             fileURL = _free(fileURL);
00608             fileURL = av[i];
00609             av[i] = NULL;
00610 
00611             /* Try to read the header from a package file. */
00612             fd = Fopen(fileURL, "r.ufdio");
00613             if (fd == NULL || Ferror(fd)) {
00614                 rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), fileURL,
00615                         Fstrerror(fd));
00616                 if (fd) (void) Fclose(fd);
00617                 retcode = 1;
00618                 /*@loopbreak@*/ break;
00619             }
00620 
00621             /*@-mustmod@*/      /* LCL: segfault. */
00622             rpmrc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
00623             /*@=mustmod@*/
00624             (void) Fclose(fd);
00625 
00626             if (!(rpmrc == RPMRC_OK || rpmrc == RPMRC_BADMAGIC)) {
00627                 rpmError(RPMERR_QUERY, _("query of %s failed\n"), fileURL);
00628                 retcode = 1;
00629                 /*@loopbreak@*/ break;
00630             }
00631             if (rpmrc == RPMRC_OK && h == NULL) {
00632                 rpmError(RPMERR_QUERY,
00633                         _("old format source packages cannot be queried\n"));
00634                 retcode = 1;
00635                 /*@loopbreak@*/ break;
00636             }
00637 
00638             /* Query a package file. */
00639             if (rpmrc == RPMRC_OK) {
00640                 retcode = showPackage(qva, rpmdb, h);
00641                 h = headerFree(h);
00642                 continue;
00643             }
00644 
00645             /* Try to read a package manifest. */
00646             fd = Fopen(fileURL, "r.fpio");
00647             if (fd == NULL || Ferror(fd)) {
00648                 rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), fileURL,
00649                         Fstrerror(fd));
00650                 if (fd) (void) Fclose(fd);
00651                 retcode = 1;
00652                 /*@loopbreak@*/ break;
00653             }
00654             
00655             /* Read list of packages from manifest. */
00656             retcode = rpmReadPackageManifest(fd, &ac, &av);
00657             if (retcode) {
00658                 rpmError(RPMERR_MANIFEST, _("%s: read manifest failed: %s\n"),
00659                         fileURL, Fstrerror(fd));
00660                 retcode = 1;
00661             }
00662             (void) Fclose(fd);
00663 
00664             /* If successful, restart the query loop. */
00665             if (retcode == 0)
00666                 goto restart;
00667 
00668             /*@loopbreak@*/ break;
00669         }
00670 
00671         fileURL = _free(fileURL);
00672         if (av) {
00673             for (i = 0; i < ac; i++)
00674                 av[i] = _free(av[i]);
00675             av = _free(av);
00676         }
00677     }   break;
00678 
00679     case RPMQV_SPECFILE:
00680         if (showPackage != showQueryPackage)
00681             return 1;
00682 
00683         /* XXX Eliminate linkage dependency loop */
00684         if (parseSpecVec == NULL || freeSpecVec == NULL)
00685             return 1;
00686 
00687       { Spec spec = NULL;
00688         Package pkg;
00689         char * buildRoot = NULL;
00690         int recursing = 0;
00691         char * passPhrase = "";
00692         char *cookie = NULL;
00693         int anyarch = 1;
00694         int force = 1;
00695 
00696         rc = parseSpecVec(&spec, arg, "/", buildRoot, recursing, passPhrase,
00697                 cookie, anyarch, force);
00698         if (rc || spec == NULL) {
00699             rpmError(RPMERR_QUERY,
00700                         _("query of specfile %s failed, can't parse\n"), arg);
00701             spec = freeSpecVec(spec);
00702             retcode = 1;
00703             break;
00704         }
00705 
00706         if (specedit) {
00707             printNewSpecfile(spec);
00708             spec = freeSpecVec(spec);
00709             retcode = 0;
00710             break;
00711         }
00712 
00713         for (pkg = spec->packages; pkg != NULL; pkg = pkg->next)
00714             (void) showPackage(qva, NULL, pkg->header);
00715         spec = freeSpecVec(spec);
00716       } break;
00717 
00718     case RPMQV_ALL:
00719         /* RPMDBI_PACKAGES */
00720         mi = rpmdbInitIterator(rpmdb, RPMDBI_PACKAGES, NULL, 0);
00721         if (mi == NULL) {
00722             rpmError(RPMERR_QUERYINFO, _("no packages\n"));
00723             retcode = 1;
00724         } else {
00725             for (av = (const char **) arg; av && *av; av++) {
00726                 if (!rpmdbSetIteratorRE(mi, RPMTAG_NAME, RPMMIRE_DEFAULT, *av))
00727                     continue;
00728                 mi = rpmdbFreeIterator(mi);
00729                 retcode = 1;
00730                 /*@loopbreak@*/ break;
00731             }
00732             if (!retcode)
00733                 retcode = showMatches(qva, mi, showPackage);
00734         }
00735         break;
00736 
00737     case RPMQV_GROUP:
00738         mi = rpmdbInitIterator(rpmdb, RPMTAG_GROUP, arg, 0);
00739         if (mi == NULL) {
00740             rpmError(RPMERR_QUERYINFO,
00741                 _("group %s does not contain any packages\n"), arg);
00742             retcode = 1;
00743         } else {
00744             retcode = showMatches(qva, mi, showPackage);
00745         }
00746         break;
00747 
00748     case RPMQV_TRIGGEREDBY:
00749         mi = rpmdbInitIterator(rpmdb, RPMTAG_TRIGGERNAME, arg, 0);
00750         if (mi == NULL) {
00751             rpmError(RPMERR_QUERYINFO, _("no package triggers %s\n"), arg);
00752             retcode = 1;
00753         } else {
00754             retcode = showMatches(qva, mi, showPackage);
00755         }
00756         break;
00757 
00758     case RPMQV_PKGID:
00759     {   unsigned char md5[16];
00760         unsigned char * t;
00761 
00762         for (i = 0, s = arg; *s && isxdigit(*s); s++, i++)
00763             {};
00764         if (i != 32) {
00765             rpmError(RPMERR_QUERYINFO, _("malformed %s: %s\n"), "pkgid", arg);
00766             return 1;
00767         }
00768 
00769         md5[0] = '\0';
00770         for (i = 0, t = md5, s = arg; i < 16; i++, t++, s += 2)
00771             *t = (nibble(s[0]) << 4) | nibble(s[1]);
00772         
00773         mi = rpmdbInitIterator(rpmdb, RPMTAG_SIGMD5, md5, sizeof(md5));
00774         if (mi == NULL) {
00775             rpmError(RPMERR_QUERYINFO, _("no package matches %s: %s\n"),
00776                         "pkgid", arg);
00777             retcode = 1;
00778         } else {
00779             retcode = showMatches(qva, mi, showPackage);
00780         }
00781     }   break;
00782 
00783     case RPMQV_HDRID:
00784         for (i = 0, s = arg; *s && isxdigit(*s); s++, i++)
00785             {};
00786         if (i != 40) {
00787             rpmError(RPMERR_QUERYINFO, _("malformed %s: %s\n"), "hdrid", arg);
00788             return 1;
00789         }
00790 
00791         mi = rpmdbInitIterator(rpmdb, RPMTAG_SHA1HEADER, arg, 0);
00792         if (mi == NULL) {
00793             rpmError(RPMERR_QUERYINFO, _("no package matches %s: %s\n"),
00794                         "hdrid", arg);
00795             retcode = 1;
00796         } else {
00797             retcode = showMatches(qva, mi, showPackage);
00798         }
00799         break;
00800 
00801     case RPMQV_FILEID:
00802     {   unsigned char md5[16];
00803         unsigned char * t;
00804 
00805         for (i = 0, s = arg; *s && isxdigit(*s); s++, i++)
00806             {};
00807         if (i != 32) {
00808             rpmError(RPMERR_QUERY, _("malformed %s: %s\n"), "fileid", arg);
00809             return 1;
00810         }
00811 
00812         md5[0] = '\0';
00813         for (i = 0, t = md5, s = arg; i < 16; i++, t++, s += 2)
00814             *t = (nibble(s[0]) << 4) | nibble(s[1]);
00815         
00816         mi = rpmdbInitIterator(rpmdb, RPMTAG_FILEMD5S, md5, sizeof(md5));
00817         if (mi == NULL) {
00818             rpmError(RPMERR_QUERYINFO, _("no package matches %s: %s\n"),
00819                         "fileid", arg);
00820             retcode = 1;
00821         } else {
00822             retcode = showMatches(qva, mi, showPackage);
00823         }
00824     }   break;
00825 
00826     case RPMQV_TID:
00827     {   int mybase = 10;
00828         const char * myarg = arg;
00829         unsigned iid;
00830 
00831         /* XXX should be in strtoul */
00832         if (*myarg == '0') {
00833             myarg++;
00834             mybase = 8;
00835             if (*myarg == 'x') {
00836                 myarg++;
00837                 mybase = 16;
00838             }
00839         }
00840         iid = strtoul(myarg, &end, mybase);
00841         if ((*end) || (end == arg) || (iid == ULONG_MAX)) {
00842             rpmError(RPMERR_QUERY, _("malformed %s: %s\n"), "tid", arg);
00843             return 1;
00844         }
00845         mi = rpmdbInitIterator(rpmdb, RPMTAG_INSTALLTID, &iid, sizeof(iid));
00846         if (mi == NULL) {
00847             rpmError(RPMERR_QUERYINFO, _("no package matches %s: %s\n"),
00848                         "tid", arg);
00849             retcode = 1;
00850         } else {
00851             retcode = showMatches(qva, mi, showPackage);
00852         }
00853     }   break;
00854 
00855     case RPMQV_WHATREQUIRES:
00856         mi = rpmdbInitIterator(rpmdb, RPMTAG_REQUIRENAME, arg, 0);
00857         if (mi == NULL) {
00858             rpmError(RPMERR_QUERYINFO, _("no package requires %s\n"), arg);
00859             retcode = 1;
00860         } else {
00861             retcode = showMatches(qva, mi, showPackage);
00862         }
00863         break;
00864 
00865     case RPMQV_WHATPROVIDES:
00866         mi = rpmdbInitIterator(rpmdb, RPMTAG_PROVIDENAME, arg, 0);
00867         if (mi == NULL) {
00868             if (arg[0] != '/')
00869                 rpmError(RPMERR_QUERYINFO, _("no package provides %s\n"), arg);
00870             retcode = 1;
00871         } else {
00872             retcode = showMatches(qva, mi, showPackage);
00873         }
00874         if (arg[0] != '/')
00875             break;
00876         retcode = 0;
00877         /*@fallthrough@*/
00878     case RPMQV_PATH:
00879     {   char * fn;
00880 
00881         for (s = arg; *s != '\0'; s++)
00882             if (!(*s == '.' || *s == '/'))
00883                 /*@loopbreak@*/ break;
00884 
00885         if (*s == '\0') {
00886             char fnbuf[PATH_MAX];
00887             fn = /*@-unrecog@*/ realpath(arg, fnbuf) /*@=unrecog@*/;
00888             if (fn)
00889                 fn = xstrdup(fn);
00890             else
00891                 fn = xstrdup(arg);
00892         } else
00893             fn = xstrdup(arg);
00894         (void) rpmCleanPath(fn);
00895 
00896         mi = rpmdbInitIterator(rpmdb, RPMTAG_BASENAMES, fn, 0);
00897         if (mi == NULL) {
00898             int myerrno = 0;
00899             if (access(fn, F_OK) != 0)
00900                 myerrno = errno;
00901             switch (myerrno) {
00902             default:
00903                 rpmError(RPMERR_QUERY,
00904                         _("file %s: %s\n"), fn, strerror(myerrno));
00905                 break;
00906             case 0:
00907                 rpmError(RPMERR_QUERYINFO,
00908                         _("file %s is not owned by any package\n"), fn);
00909                 break;
00910             }
00911             retcode = 1;
00912         } else {
00913             retcode = showMatches(qva, mi, showPackage);
00914         }
00915         fn = _free(fn);
00916     }   break;
00917 
00918     case RPMQV_DBOFFSET:
00919     {   int mybase = 10;
00920         const char * myarg = arg;
00921         unsigned recOffset;
00922 
00923         /* XXX should be in strtoul */
00924         if (*myarg == '0') {
00925             myarg++;
00926             mybase = 8;
00927             if (*myarg == 'x') {
00928                 myarg++;
00929                 mybase = 16;
00930             }
00931         }
00932         recOffset = strtoul(myarg, &end, mybase);
00933         if ((*end) || (end == arg) || (recOffset == ULONG_MAX)) {
00934             rpmError(RPMERR_QUERYINFO, _("invalid package number: %s\n"), arg);
00935             return 1;
00936         }
00937         rpmMessage(RPMMESS_DEBUG, _("package record number: %u\n"), recOffset);
00938         mi = rpmdbInitIterator(rpmdb, RPMDBI_PACKAGES, &recOffset, sizeof(recOffset));
00939         if (mi == NULL) {
00940             rpmError(RPMERR_QUERYINFO,
00941                 _("record %u could not be read\n"), recOffset);
00942             retcode = 1;
00943         } else {
00944             retcode = showMatches(qva, mi, showPackage);
00945         }
00946     }   break;
00947 
00948     case RPMQV_PACKAGE:
00949         /* XXX HACK to get rpmdbFindByLabel out of the API */
00950         mi = rpmdbInitIterator(rpmdb, RPMDBI_LABEL, arg, 0);
00951         if (mi == NULL) {
00952             rpmError(RPMERR_QUERYINFO, _("package %s is not installed\n"), arg);
00953             retcode = 1;
00954         } else {
00955             retcode = showMatches(qva, mi, showPackage);
00956         }
00957         break;
00958     }
00959    
00960     return retcode;
00961 }
00962 
00963 int rpmQuery(QVA_t qva, rpmQVSources source, const char * arg)
00964 {
00965     rpmdb rpmdb = NULL;
00966     int rc;
00967 
00968     switch (source) {
00969     case RPMQV_RPM:
00970     case RPMQV_SPECFILE:
00971         break;
00972     default:
00973         if (rpmdbOpen(qva->qva_prefix, &rpmdb, O_RDONLY, 0644))
00974             return 1;
00975         break;
00976     }
00977 
00978     rc = rpmQueryVerify(qva, source, arg, rpmdb, showQueryPackage);
00979 
00980     if (rpmdb != NULL)
00981         (void) rpmdbClose(rpmdb);
00982 
00983     return rc;
00984 }

Generated on Thu Apr 18 17:34:42 2002 for rpm by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002