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

lib/query.c

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

Generated at Thu Sep 6 11:32:30 2001 for rpm by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001