"Fossies" - the Fresh Open Source Software Archive

Member "rpm2html-1.11.2/rpmopen.c" (9 Nov 2010, 52643 Bytes) of package /linux/privat/rpm2html-1.11.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "rpmopen.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * rpmopen.c : open an extract information from RPM files.
    3  *
    4  * See Copyright for the status of this software.
    5  *
    6  * $Id: rpmopen.c,v 1.124 2010/11/09 21:57:42 hany Exp $
    7  */
    8 
    9 #include <config.h>
   10 #include <sys/types.h>
   11 #include <sys/stat.h>
   12 #ifdef HAVE_FCNTL_H
   13 #include <fcntl.h>
   14 #endif
   15 #include <stdio.h>
   16 #include <stdlib.h>
   17 #include <string.h>
   18 #ifdef HAVE_UNISTD_H
   19 #include <unistd.h>
   20 #endif
   21 #include <dirent.h>
   22 #include <errno.h>
   23 #include <time.h>
   24 
   25 #include <rpm/rpmlib.h>
   26 #include <rpm/rpmmacro.h>
   27 #include <rpm/rpmdb.h>
   28 #include <rpm/rpmts.h>
   29 #ifdef HAVE_RPM42
   30 #include <rpm/rpmfi.h>
   31 #endif
   32 
   33 #ifndef HAVE_RPM_RPMLEGACY_H
   34 int readLead(FD_t fd, /*@out@*/struct rpmlead *lead);
   35 #endif
   36 #ifdef HAVE_RPM42
   37 typedef enum sigType_e {
   38     RPMSIGTYPE_HEADERSIG= 5     /*!< Header style signature */
   39 } sigType;
   40 
   41 int rpmReadSignature(FD_t fd, Header *sighp, sigType sig_type, const char ** msg);
   42 #else
   43 int rpmReadSignature(FD_t fd, /*@out@*/ Header *header, short sig_type);
   44 #endif
   45 
   46 #if defined(WITH_GPG)
   47 #include <sys/wait.h>
   48 #endif
   49 
   50 #include "rpm2html.h"
   51 #include "rpmdata.h"
   52 #include "html.h"
   53 #include "rdf.h"
   54 #include "language.h"
   55 #ifdef WITH_SQL
   56 #include "sql.h"
   57 #endif
   58 
   59 #ifdef USE_RPMIO
   60 #ifndef rpmdbNextIterator
   61 typedef struct headerTagTableEntry_s *headerTagTableEntryPtr;
   62 #else
   63 typedef struct headerTagTableEntry *headerTagTableEntryPtr;
   64 #endif
   65 #else
   66 typedef struct headerTagTableEntry *headerTagTableEntryPtr;
   67 #endif
   68 #ifndef HAVE_SNPRINTF
   69 #error You really need snprintf ...
   70 #endif
   71 
   72 /*
   73  * Get the internal number associated with an RPM tag.
   74  */
   75 // removal of this possibly breaks compatibility with some ancient RPM but while
   76 // some tags are alredy used as macros directly, without 'getTagNumber()', removal
   77 // of this methond hopefully wont make in worser BUT it will help us compile this
   78 // against rpm.org's rpm-4.6
   79 // XXX TODO: clean-up
   80 //static int
   81 //getTagNumber(char *tag)
   82 //{
   83 //    int i;
   84 //    headerTagTableEntryPtr t;
   85 //
   86 //    t = (headerTagTableEntryPtr) rpmTagTable;
   87 //    for (i = 0; i < rpmTagTableSize; i++, t++) {
   88 //        if (!strcasecmp(tag, t->name))
   89 //            return (t->val);
   90 //    }
   91 //    fprintf(stderr, "getTagNumber(%s) : unknown tag !\n", tag);
   92 //    return (-1);
   93 //}
   94 
   95 /*
   96  * Free up the extra data not needed for the last stage processing.
   97  */
   98 
   99 void
  100 rpmFreeExtraData(rpmDataPtr rpm)
  101 {
  102     rpmExtraDataPtr extra;
  103     int n1;
  104 
  105     if ((rpm == NULL) || (rpm->extra == NULL))
  106         return;
  107     extra = rpm->extra;
  108     if (extra->packager != NULL)
  109         xmlFree(extra->packager);
  110     if (extra->description != NULL)
  111         xmlFree(extra->description);
  112     if (extra->copyright != NULL)
  113         xmlFree(extra->copyright);
  114     if (extra->changelog != NULL)
  115         xmlFree(extra->changelog);
  116     if (extra->srcrpm != NULL)
  117         xmlFree(extra->srcrpm);
  118     if (extra->host != NULL)
  119         xmlFree(extra->host);
  120     if (extra->resources != NULL)
  121         xmlFree(extra->resources);
  122     if (extra->requires != NULL)
  123         xmlFree(extra->requires);
  124     if (extra->filelist != NULL)
  125         xmlFree(extra->filelist);
  126     if (extra->sigs != NULL) {
  127         for (n1 = 0; n1 < extra->nb_sigs; n1++)
  128             if (extra->sigs[n1] != NULL) {
  129                 if (extra->sigs[n1]->sig != NULL)
  130                     xmlFree(extra->sigs[n1]->sig);
  131 #if defined(WITH_GPG)
  132                 if (extra->sigs[n1]->resolve != NULL)
  133                     xmlFree(extra->sigs[n1]->resolve);
  134 #endif
  135                 xmlFree(extra->sigs[n1]);
  136             }
  137         xmlFree(extra->sigs);
  138     }
  139     xmlFree(extra);
  140 }
  141 
  142 /*
  143  * check a dependancy name to get rid of bad deps due to bad scripts
  144  * or spec files.
  145  */
  146 int
  147 checkResourceName(const char *res)
  148 {
  149     int isname = 0;
  150     const char *base = res;
  151 
  152     if (*res == 0)
  153         return (0);
  154 
  155     /*
  156      * we only accept absolute pathnames.
  157      */
  158     if (*res == '/')
  159         isname = 1;
  160     while (*res != 0) {
  161         if (((*res >= 'A') && (*res <= 'Z')) ||
  162             ((*res >= 'a') && (*res <= 'z')) ||
  163             ((*res >= '0') && (*res <= '9')) ||
  164             (*res == '-') || (*res == '.') ||
  165             (*res == '@') || (*res == '_') ||
  166             (*res == '(') || (*res == ')') ||
  167             (*res == '+') || ((*res == '/') && (isname == 1)))
  168             res++;
  169         else
  170             return (0);
  171         //if ((res - base) > 100)
  172         //    return (0);
  173     }
  174     return (1);
  175 }
  176 
  177 /*
  178  * check a release name
  179  */
  180 int
  181 checkReleaseName(const char *res)
  182 {
  183     const char *base = res;
  184 
  185     if (*res == 0)
  186         return (0);
  187 
  188     while (*res != 0) {
  189         if (((*res >= 'A') && (*res <= 'Z')) ||
  190             ((*res >= 'a') && (*res <= 'z')) ||
  191             ((*res >= '0') && (*res <= '9')) ||
  192             (*res == '-') || (*res == '.') ||
  193             (*res == '@') || (*res == '_') || (*res == '+'))
  194             res++;
  195         else
  196             return (0);
  197         if ((res - base) > 65)
  198             return (0);
  199     }
  200     return (1);
  201 }
  202 
  203 /*
  204  * check a group name
  205  */
  206 int
  207 checkGroupName(const char *res)
  208 {
  209     const char *base = res;
  210 
  211     while (*res != 0) {
  212         if (((*res >= 'A') && (*res <= 'Z')) ||
  213             ((*res >= 'a') && (*res <= 'z')) ||
  214             ((*res >= '0') && (*res <= '9')) ||
  215             (*res == ' ') || (*res == '.') ||
  216             (*res == '(') || (*res == ')') ||
  217             (*res == '+') || (*res == '/') || (*res == '-'))
  218             res++;
  219         else
  220             return (0);
  221         //if ((res - base) > 60)
  222         //    return (0);
  223     }
  224     return (1);
  225 }
  226 
  227 /*
  228  * check a version name
  229  */
  230 int
  231 checkVersionName(const char *res)
  232 {
  233     const char *base = res;
  234 
  235     if (*res == 0)
  236         return (0);
  237 
  238     while (*res != 0) {
  239         if (((*res >= 'A') && (*res <= 'Z')) ||
  240             ((*res >= 'a') && (*res <= 'z')) ||
  241             ((*res >= '0') && (*res <= '9')) ||
  242             (*res == '-') || (*res == '.') ||
  243             (*res == '@') || (*res == '_') || (*res == '+'))
  244             res++;
  245         else
  246             return (0);
  247         //if ((res - base) > 20)
  248         //    return (0);
  249     }
  250     return (1);
  251 }
  252 
  253 #if defined(WITH_GPG)
  254 /*
  255  * rpmResolveGPGPSignatures : resolve GPG and PGP signatures found in package
  256  * code based on rpm-4.0-0.45
  257  */
  258 void
  259 rpmResolveGPGPSignature(const char *nameRpm, const char *sigtarget,
  260                         const char *sigfile, rpmDataPtr rpm, int sign)
  261 {
  262     int pid, status, outpipe[2];
  263     FILE *file;
  264     int rsize = 128, crsize;
  265     unsigned char buf[8192];
  266     char *temp;
  267 
  268     /* Now run GPG */
  269     outpipe[0] = outpipe[1] = 0;
  270     pipe(outpipe);
  271 
  272     if (!(pid = fork())) {
  273         close(outpipe[0]);
  274         /* gpg version 0.9 sends its output to stderr. */
  275         dup2(outpipe[1], STDERR_FILENO);
  276 
  277         execlp(GPG_PROG, GPG_PROG,
  278                "--batch", "--no-verbose",
  279                "--verify", sigfile, sigtarget, NULL);
  280         fprintf(stderr, "%s exec failed!\n", GPG_PROG);
  281         exit(1);
  282     }
  283 
  284     close(outpipe[1]);
  285     file = fdopen(outpipe[0], "r");
  286     rpm->extra->sigs[sign]->resolve = xmlMalloc(sizeof(char) * rsize);
  287     rpm->extra->sigs[sign]->resolve[0] = '\0';
  288     while (fgets(buf, 1024, file)) {
  289         crsize = strlen(buf) + strlen(rpm->extra->sigs[sign]->resolve);
  290         if (crsize >= rsize) {
  291             rsize = crsize * 2;
  292             rpm->extra->sigs[sign]->resolve =
  293                 xmlRealloc(rpm->extra->sigs[sign]->resolve,
  294                            sizeof(char) * rsize);
  295             if (rpm->extra->sigs[sign]->resolve == NULL) {
  296                 fprintf(stderr, "cannot re-allocate %d bytes: %s\n",
  297                         rsize, strerror(errno));
  298                 exit(1);
  299             }
  300         }
  301 
  302         strcat(rpm->extra->sigs[sign]->resolve, buf);
  303     }
  304     fclose(file);
  305     
  306     temp = xmlStrdup(protectEmail(rpm->extra->sigs[sign]->resolve));
  307     xmlFree(rpm->extra->sigs[sign]->resolve);
  308     rpm->extra->sigs[sign]->resolve = temp;
  309 
  310     (void) waitpid(pid, &status, 0);
  311 }
  312 
  313 /*
  314  * rpmResolveMD5Signatures : resolve MD5 signatures found in package
  315  * code based on rpm-4.0-0.45
  316  * for now, we are not checking whether MD5 sums are OK
  317  */
  318 /*void rpmResolveMD5Signature(const char *nameRpm, const char *sigtarget,
  319                             const char *sigfile, rpmDataPtr rpm, int sign) {
  320 }*/
  321 
  322 /*
  323  * rpmResolveSignatures : resolve signatures found in package
  324  * code based on rpm-4.0-0.45
  325  */
  326 void
  327 rpmResolveSignatures(const char *path, const char *nameRpm,
  328                      const char *sigtarget, rpmDataPtr rpm)
  329 {
  330     int sign = 0;
  331 
  332     if (rpm == NULL || rpm->extra->nb_sigs == 0 || sigtarget == NULL)
  333         return;
  334 
  335     for (sign = 0; sign < rpm->extra->nb_sigs; sign++) {
  336         FD_t sfd;
  337         char *sigfile = NULL;
  338 
  339         if (rpm->extra->sigs[sign]->tag != RPMSIGTAG_PGP
  340             && rpm->extra->sigs[sign]->tag != RPMSIGTAG_GPG)
  341             continue;
  342 
  343         /* Write out the signature */
  344         sigfile = xmlMalloc(30);
  345         strcpy(sigfile, "/tmp/rpm2html.sig.XXXXXX");
  346         sigfile = mktemp(sigfile);
  347         sfd = Fopen(sigfile, "w.fdio");
  348         (void) Fwrite(rpm->extra->sigs[sign]->sig, sizeof(char),
  349                       rpm->extra->sigs[sign]->size, sfd);
  350         Fclose(sfd);
  351 
  352         switch (rpm->extra->sigs[sign]->tag) {
  353             case RPMSIGTAG_PGP:
  354             case RPMSIGTAG_GPG:
  355                 rpmResolveGPGPSignature(nameRpm, sigtarget, sigfile, rpm,
  356                                         sign);
  357                 break;
  358                 /*case RPMSIGTAG_MD5:
  359                  * rpmResolveMD5Signature(nameRpm, sigtarget, sigfile, rpm, sign);
  360                  * break; */
  361             default:
  362                 break;
  363         }
  364 
  365         if (sigfile != NULL) {
  366             unlink(sigfile);
  367             xmlFree(sigfile);
  368         }
  369     }
  370 }
  371 #endif
  372 
  373 /*
  374  * rpmAnalyze : analyze an RPM record, read and parse the header and 
  375  *              fill the information in the database.
  376  */
  377 #define ENTRY_CLEANUP(p)                        \
  378     if ((type == RPM_STRING_ARRAY_TYPE || type == RPM_I18NSTRING_TYPE)&&\
  379         (p != NULL)) { free((p)); p = NULL; }
  380 
  381 static char *buffer = NULL;
  382 static int buffer_size = 50 * 1024 * sizeof(char);
  383 
  384 rpmDataPtr
  385 rpmAnalyze(char *path, char *nameRpm, const char *sigtarget,
  386            Header h, Header s, rpmDirPtr dir, rpmSubdirPtr tree,
  387            time_t stamp, int isSource)
  388 {
  389     int installed = dir->installbase;
  390     char *name = NULL, *version = NULL, *release = NULL;
  391     int_32 count, type;
  392     void *p = NULL;
  393     int val, i, j;
  394     rpmDataPtr rpm = NULL;
  395     static char nameBuffer[500];
  396 
  397 #ifdef WITH_SQL
  398     int id;
  399 #endif
  400     HeaderIterator sIter;
  401 
  402     if (buffer == NULL) {
  403         buffer = (char *) xmlMalloc(buffer_size);
  404         if (buffer == NULL) {
  405             fprintf(stderr, "cannot allocate %d bytes: %s\n", buffer_size,
  406                     strerror(errno));
  407             exit(1);
  408         }
  409     }
  410 
  411     /* extract information from the header */
  412     headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &count);
  413     if (name == NULL) {
  414         fprintf(stderr, "Invalid package %s : no name\n", nameRpm);
  415         return (NULL);
  416     }
  417     if (!(((name[0] >= 'a') && (name[0] <= 'z')) ||
  418           ((name[0] >= 'A') && (name[0] <= 'Z')) ||
  419           ((name[0] >= '0') && (name[0] <= '9')))) {
  420         fprintf(stderr, "Invalid package %s : garbled name\n", nameRpm);
  421         ENTRY_CLEANUP(name)
  422             return (NULL);
  423     }
  424     if (!checkResourceName(name)) {
  425         fprintf(stderr, "Invalid package %s : garbled name\n", nameRpm);
  426         ENTRY_CLEANUP(name)
  427             return (NULL);
  428     }
  429     headerGetEntry(h, RPMTAG_VERSION, &type, (void **) &version, &count);
  430     if ((version == NULL) || (version[0] == 0)) {
  431         fprintf(stderr, "Invalid package %s : version invalid\n", nameRpm);
  432         ENTRY_CLEANUP(name)
  433             ENTRY_CLEANUP(version)
  434             return (NULL);
  435     }
  436     if (!checkVersionName(version)) {
  437         fprintf(stderr, "Invalid package %s : garbled version\n", nameRpm);
  438         ENTRY_CLEANUP(name)
  439             ENTRY_CLEANUP(version)
  440             return (NULL);
  441     }
  442     headerGetEntry(h, RPMTAG_RELEASE, &type, (void **) &release, &count);
  443     if ((release == NULL) || (release[0] == 0)) {
  444         fprintf(stderr, "Invalid package %s : release invalid\n", nameRpm);
  445         ENTRY_CLEANUP(name)
  446             ENTRY_CLEANUP(version)
  447             ENTRY_CLEANUP(release)
  448             return (NULL);
  449     }
  450     if (!checkReleaseName(release)) {
  451         fprintf(stderr, "Invalid package %s : garbled release\n", nameRpm);
  452         ENTRY_CLEANUP(name)
  453             ENTRY_CLEANUP(version)
  454             ENTRY_CLEANUP(release)
  455             return (NULL);
  456     }
  457 
  458     /* allocate a new rpmData block, and an rpmExtraData block fill them */
  459     rpm = (rpmDataPtr) xmlMalloc(sizeof(rpmData));
  460     if (rpm == NULL) {
  461         fprintf(stderr, "cannot allocate %d bytes: %s\n", sizeof(rpmData),
  462                 strerror(errno));
  463         return (NULL);
  464     }
  465     memset(rpm, 0, sizeof(rpmData));
  466     rpm->extra = (rpmExtraDataPtr) xmlMalloc(sizeof(rpmExtraData));
  467     if (rpm == NULL) {
  468         fprintf(stderr, "cannot allocate %d bytes: %s\n",
  469                 sizeof(rpmExtraData), strerror(errno));
  470         return (NULL);
  471     }
  472     memset(rpm->extra, 0, sizeof(rpmExtraData));
  473     rpm->dir = dir;
  474     if (tree) {
  475         if ((tree->rpmpath != NULL) && (tree->rpmpath[0] != '\0'))
  476             rpm->subdir = stringAdd(tree->rpmpath);
  477         else
  478             rpm->subdir = NULL;
  479     } else
  480         rpm->subdir = NULL;
  481     rpm->extra->stamp = stamp;
  482     rpm->name = stringAdd(name);
  483     ENTRY_CLEANUP(name);
  484         rpm->version = stringAdd(version);
  485     ENTRY_CLEANUP(version);
  486         rpm->release = stringAdd(release);
  487     ENTRY_CLEANUP(release);
  488 
  489         /* get all the resources provided by this RPM */
  490     if (!headerGetEntry(h, RPMTAG_SUMMARY, &type, &p, &count) || !p) {
  491         rpm->summary = xmlStrdup(localizedStrings[LANG_NO_SUMMARY]);
  492     } else {
  493         rpm->summary = xmlStrdup((char *) p);
  494     }
  495     ENTRY_CLEANUP(p);
  496     if (!headerGetEntry(h, RPMTAG_DESCRIPTION, &type, &p, &count) || !p ||
  497         (type != RPM_STRING_TYPE)) {
  498         rpm->extra->description =
  499             xmlStrdup(localizedStrings[LANG_NO_DESCRIPTION]);
  500     } else {
  501         rpm->extra->description = xmlStrdup((char *) p);
  502     }
  503     ENTRY_CLEANUP(p);
  504     if (!headerGetEntry(h, RPMTAG_DISTRIBUTION, &type, &p, &count) || !p ||
  505         (type != RPM_STRING_TYPE)) {
  506         rpm->distribution = stringAdd(localizedStrings[LANG_UNKNOWN]);
  507     } else {
  508         rpm->distribution = stringAdd((char *) p);
  509     }
  510     ENTRY_CLEANUP(p);
  511     if (isSource) {
  512         rpm->arch = stringAdd("src");
  513         if (nameRpm == NULL) {
  514             snprintf(nameBuffer, sizeof(nameBuffer), "%s-%s-%s.src.rpm",
  515                      name, version, release);
  516             nameRpm = nameBuffer;
  517         }
  518     } else {
  519         if (!headerGetEntry(h, RPMTAG_ARCH, &type, &p, &count) || !p ||
  520             (type != RPM_STRING_TYPE)) {
  521             if (type == RPM_INT8_TYPE) {
  522                 /*
  523                  * Old packages.
  524                  */
  525                 switch (*((char *) p)) {
  526                     case 1:
  527                         rpm->arch = stringAdd("i386");
  528                         break;
  529                     default:
  530                         rpm->arch = stringAdd("src");
  531                         break;
  532                 }
  533             } else
  534                 rpm->arch = stringAdd(localizedStrings[LANG_NONE]);
  535             if (nameRpm == NULL) {
  536                 snprintf(nameBuffer, sizeof(nameBuffer), "%s-%s-%s.rpm",
  537                          name, version, release);
  538                 nameRpm = nameBuffer;
  539             }
  540         } else {
  541             rpm->arch = stringAdd((char *) p);
  542             if (nameRpm == NULL) {
  543                 snprintf(nameBuffer, sizeof(nameBuffer), "%s-%s-%s.%s.rpm",
  544                          name, version, release, (char *) p);
  545                 nameRpm = nameBuffer;
  546             }
  547         }
  548         ENTRY_CLEANUP(p);
  549     }
  550     if (!headerGetEntry(h, RPMTAG_OS, &type, &p, &count) || !p ||
  551         (type != RPM_STRING_TYPE)) {
  552         if (type == RPM_INT8_TYPE) {
  553             /*
  554              * Old packages.
  555              */
  556             switch (*((char *) p)) {
  557                 case 1:
  558                     rpm->os = stringAdd("linux");
  559                     break;
  560                 default:
  561                     rpm->os = stringAdd("linux");
  562                     break;
  563             }
  564         } else
  565             rpm->os = stringAdd("");
  566     } else {
  567         rpm->os = stringAdd((char *) p);
  568     }
  569     ENTRY_CLEANUP(p);
  570     if (!headerGetEntry(h, RPMTAG_VENDOR, &type, &p, &count) || !p ||
  571         (type != RPM_STRING_TYPE)) {
  572         rpm->vendor = NULL;
  573     } else {
  574         rpm->vendor = stringAdd(protectEmail((char *) p));
  575     }
  576     ENTRY_CLEANUP(p);
  577     if (!headerGetEntry(h, RPMTAG_GROUP, &type, &p, &count) || !p ||
  578         (type != RPM_STRING_TYPE)) {
  579         rpm->group = stringAdd(localizedStrings[LANG_NO_GROUP]);
  580     } else {
  581         rpm->group = stringAdd((char *) p);
  582     }
  583     ENTRY_CLEANUP(p);
  584     if (!checkGroupName(rpm->group)) {
  585         fprintf(stderr, "Invalid package %s : garbled group\n", nameRpm);
  586         if (rpm->name)
  587             stringFree(rpm->name);
  588         if (rpm->version)
  589             stringFree(rpm->version);
  590         if (rpm->release)
  591             stringFree(rpm->release);
  592         if (rpm->summary)
  593             xmlFree(rpm->summary);
  594         if (rpm->distribution)
  595             stringFree(rpm->distribution);
  596         if (rpm->arch)
  597             stringFree(rpm->arch);
  598         if (rpm->os)
  599             stringFree(rpm->os);
  600         if (rpm->vendor != NULL)
  601             stringFree(rpm->vendor);
  602         if (rpm->group != NULL)
  603             stringFree(rpm->group);
  604         xmlFree(rpm);
  605         return (NULL);
  606     }
  607     if (!headerGetEntry(h, RPMTAG_BUILDHOST, &type, &p, &count) || !p ||
  608         (type != RPM_STRING_TYPE)) {
  609         rpm->extra->host = xmlStrdup(localizedStrings[LANG_NO_HOST]);
  610     } else {
  611         rpm->extra->host = xmlStrdup((char *) p);
  612     }
  613     ENTRY_CLEANUP(p);
  614     if (!headerGetEntry(h, RPMTAG_SIZE, &type, &p, &count) || !p) {
  615         rpm->size = 0;
  616     } else {
  617         rpm->size = *((int *) p);
  618     }
  619     ENTRY_CLEANUP(p);
  620     if (installed) {
  621         if (!headerGetEntry(h, RPMTAG_INSTALLTIME, &type, &p, &count)
  622             || !p) {
  623             rpm->date = 0;
  624         } else {
  625             rpm->date = *((int_32 *) p);
  626         }
  627         ENTRY_CLEANUP(p);
  628     } else {
  629         if (!headerGetEntry(h, RPMTAG_BUILDTIME, &type, &p, &count) || !p) {
  630             rpm->date = 0;
  631         } else {
  632             rpm->date = *((int_32 *) p);
  633         }
  634         ENTRY_CLEANUP(p);
  635     }
  636     if (!headerGetEntry(h, RPMTAG_SOURCERPM, &type, &p, &count) || !p ||
  637         (type != RPM_STRING_TYPE)) {
  638         rpm->extra->srcrpm = xmlStrdup("");
  639     } else {
  640         rpm->extra->srcrpm = xmlStrdup((char *) p);
  641     }
  642     ENTRY_CLEANUP(p);
  643     if (!headerGetEntry(h, RPMTAG_URL, &type, &p, &count) || !p ||
  644         (type != RPM_STRING_TYPE)) {
  645         rpm->url = NULL;
  646     } else {
  647         rpm->url = xmlStrdup((char *) p);
  648     }
  649     ENTRY_CLEANUP(p);
  650     if (!headerGetEntry(h, RPMTAG_PACKAGER, &type, &p, &count) || !p ||
  651         (type != RPM_STRING_TYPE)) {
  652         rpm->extra->packager = NULL;
  653     } else {
  654         rpm->extra->packager = xmlStrdup(protectEmail((char *) p));
  655     }
  656     ENTRY_CLEANUP(p);
  657     if (!headerGetEntry(h, RPMTAG_LICENSE, &type, &p, &count) || !p ||
  658         (type != RPM_STRING_TYPE)) {
  659         rpm->extra->copyright = NULL;
  660     } else {
  661         rpm->extra->copyright = xmlStrdup((char *) p);
  662     }
  663     ENTRY_CLEANUP(p);
  664     /* Pick up changelog entries */
  665     if (!headerGetEntry(h, RPMTAG_CHANGELOGTEXT, &type, &p, &count) || !p) {
  666         rpm->extra->changelog = NULL;
  667     } else {
  668         int_32 *dates;  /* necessary when sizeof(time_t) != sizeof(int_32) */
  669         time_t date;
  670         char **names;
  671         char **holdp = (char **) p;
  672         char *cp;
  673         struct tm *tm_buf;
  674         int i,
  675           len,
  676           pos;
  677         char date_string[50];
  678         char *res = buffer;
  679 
  680         *res = '\0';
  681         headerGetEntry(h, RPMTAG_CHANGELOGTIME, &type, (void *) &dates,
  682                        &count);
  683         headerGetEntry(h, RPMTAG_CHANGELOGNAME, &type, (void *) &names,
  684                        &count);
  685         for (i = 0; i < count; i++) {
  686             if ((res - buffer) > (buffer_size - 1024)) {
  687                 int delta = res - buffer;
  688 
  689                 buffer_size *= 2;
  690                 buffer = (char *) xmlRealloc(buffer, buffer_size);
  691                 if (buffer == NULL) {
  692                     fprintf(stderr, "cannot re-allocate %d bytes: %s\n",
  693                             buffer_size, strerror(errno));
  694                     exit(1);
  695                 }
  696                 res = &buffer[delta];
  697             }
  698             date = dates[i];
  699             tm_buf = localtime(&date);
  700             strftime(date_string, sizeof(date_string) - 1, "%a %b %d %Y",
  701                      tm_buf);
  702             len =
  703                 snprintf(res, buffer_size, "* %s %s\n", date_string,
  704                          names[i]);
  705             res += len;
  706             cp = holdp[i];
  707             pos = 0;
  708 
  709             if ((res - buffer + strlen(holdp[i])) > buffer_size) {
  710                 int delta = res - buffer;
  711 
  712                 buffer_size *= 2;
  713                 buffer = (char *) xmlRealloc(buffer, buffer_size);
  714                 if (buffer == NULL) {
  715                     fprintf(stderr, "cannot re-allocate %d bytes: %s\n",
  716                             buffer_size, strerror(errno));
  717                     exit(1);
  718                 }
  719                 res = &buffer[delta];
  720             }
  721 
  722             while (*cp) {
  723                 if (pos++ == 0) {
  724                     *res++ = ' ';
  725                     *res++ = ' ';
  726                 }
  727                 *res++ = *cp;
  728                 if (*cp++ == '\n')
  729                     pos = 0;
  730             }
  731             *res++ = '\n';
  732         }
  733         *res = '\0';
  734         rpm->extra->changelog = xmlStrdup(protectEmail(buffer));
  735         ENTRY_CLEANUP(names);
  736     }
  737     ENTRY_CLEANUP(p);
  738     if (rpm->vendor == NULL) {
  739         if (rpm->extra->packager != NULL)
  740             rpm->vendor = xmlStrdup(rpm->extra->packager);
  741         else
  742             rpm->vendor = xmlStrdup(localizedStrings[LANG_UNKNOWN]);
  743     }
  744 
  745     if (s == NULL)
  746         rpm->extra->sigs = NULL;
  747     else {
  748         int tag,
  749           type;
  750 
  751         rpm->extra->max_sigs = 1;
  752         rpm->extra->sigs = (rpmSigPtr *) xmlMalloc(sizeof(rpmSigPtr) *
  753                                                    rpm->extra->max_sigs);
  754         rpm->extra->sigs[0] = NULL;
  755         rpm->extra->nb_sigs = 0;
  756 
  757         for (sIter = headerInitIterator(s);
  758              headerNextIterator(sIter, &tag, &type, (void *) &p, &count);) {
  759             if ((tag != RPMSIGTAG_MD5) && (tag != RPMSIGTAG_PGP)
  760                 && (tag != RPMSIGTAG_GPG))
  761                 continue;
  762             if (rpm->extra->nb_sigs >= rpm->extra->max_sigs) {
  763                 rpm->extra->max_sigs *= 2;
  764                 rpm->extra->sigs =
  765                     (rpmSigPtr *) xmlRealloc(rpm->extra->sigs,
  766                                              sizeof(rpmSigPtr) *
  767                                              rpm->extra->max_sigs);
  768                 if (rpm->extra->sigs == NULL) {
  769                     fprintf(stderr, "cannot re-allocate %d bytes: %s\n",
  770                             rpm->extra->max_sigs, strerror(errno));
  771                     exit(1);
  772                 }
  773             }
  774 
  775             rpm->extra->sigs[rpm->extra->nb_sigs] =
  776                 (rpmSigPtr) xmlMalloc(sizeof(rpmSig));
  777             rpm->extra->sigs[rpm->extra->nb_sigs]->tag = tag;
  778             rpm->extra->sigs[rpm->extra->nb_sigs]->type = type;
  779             rpm->extra->sigs[rpm->extra->nb_sigs]->size = count;
  780             rpm->extra->sigs[rpm->extra->nb_sigs]->sig = xmlMalloc(count);
  781             memcpy(rpm->extra->sigs[rpm->extra->nb_sigs]->sig, p, count);
  782 #if defined(WITH_GPG)
  783             rpm->extra->sigs[rpm->extra->nb_sigs]->resolve = NULL;
  784 #endif
  785             rpm->extra->nb_sigs++;
  786             ENTRY_CLEANUP(p);
  787         }
  788     }
  789 
  790     rpm->filename = xmlStrdup(nameRpm);
  791 
  792     /* package-xxx.rpm provides at least the resource "package" */
  793     val = RPMTAG_PROVIDES;
  794     if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
  795         rpm->extra->nb_resources = 1;
  796         rpm->extra->max_resources = 1;
  797         rpm->extra->resources =
  798             (rpmRessPtr *) xmlMalloc(sizeof(rpmRessPtr) *
  799                                      rpm->extra->max_resources);
  800         if (rpm->extra->resources == NULL) {
  801             fprintf(stderr, ": ran out of memory\n");
  802             exit(1);
  803         }
  804         rpm->extra->resources[0] = rpmRessAdd(name, rpm, installed);
  805     } else {
  806         rpm->extra->max_resources = count + 1;
  807         rpm->extra->resources =
  808             (rpmRessPtr *) xmlMalloc(sizeof(rpmRessPtr) *
  809                                      rpm->extra->max_resources);
  810         if (rpm->extra->resources == NULL) {
  811             fprintf(stderr, ": ran out of memory\n");
  812             exit(1);
  813         }
  814         rpm->extra->resources[0] = rpmRessAdd(name, rpm, installed);
  815         rpm->extra->nb_resources = 1;
  816 
  817         for (i = 0, j = rpm->extra->nb_resources; i < count; i++) {
  818             if (!checkResourceName(((char **) p)[i]))
  819                 continue;
  820             if (!strcmp(((char **) p)[i], name))
  821                 continue;
  822             rpm->extra->resources[j++] =
  823                 rpmRessAdd(((char **) p)[i], rpm, installed);
  824         }
  825         rpm->extra->nb_resources = j;
  826     }
  827     ENTRY_CLEANUP(p);
  828 
  829     val = RPMTAG_REQUIRENAME;
  830     if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
  831         rpm->extra->nb_requires = 0;
  832         rpm->extra->requires = NULL;
  833     } else {
  834         int_32 count2,
  835           count3,
  836           type2,
  837           type3;
  838         void *q = NULL;
  839         void *r = NULL;
  840         int valv,
  841           valf;
  842 
  843         rpm->extra->max_requires = count;
  844         rpm->extra->requires =
  845             (rpmRessPtr *) xmlMalloc(sizeof(rpmRessPtr) *
  846                                      rpm->extra->max_requires);
  847         if (rpm->extra->requires == NULL) {
  848             fprintf(stderr, ": ran out of memory\n");
  849             exit(1);
  850         }
  851         valv = RPMTAG_REQUIREVERSION;
  852         valf = RPMTAG_REQUIREFLAGS;
  853         headerGetEntry(h, valv, &type2, &q, &count2);
  854         headerGetEntry(h, valf, &type3, &r, &count3);
  855 
  856         rpm->extra->nb_requires = 0;
  857 
  858         for (i = 0, j = 0; (i < count2) && (i < count3); i++) {
  859             long anint = *(((long *) r) + i);
  860             rpm_dep_flag flag = RPM2HTML_REQ_NONE;
  861 
  862             if ((anint & RPMSENSE_LESS) && (anint & RPMSENSE_EQUAL))
  863                 flag = RPM2HTML_REQ_LEQ;
  864             else if (anint & RPMSENSE_LESS)
  865                 flag = RPM2HTML_REQ_LT;
  866             if ((anint & RPMSENSE_GREATER) && (anint & RPMSENSE_EQUAL))
  867                 flag = RPM2HTML_REQ_GEQ;
  868             else if (anint & RPMSENSE_GREATER)
  869                 flag = RPM2HTML_REQ_GT;
  870             else if (anint & RPMSENSE_EQUAL)
  871                 flag = RPM2HTML_REQ_EQU;
  872             if (!checkResourceName(((char **) p)[i]))
  873                 continue;
  874             rpm->extra->requires[j++] =
  875                 rpmRequAdd(((char **) p)[i], ((char **) q)[i],
  876                            flag, rpm, installed);
  877         }
  878         rpm->extra->nb_requires = j;
  879         if ((type2 == RPM_STRING_ARRAY_TYPE
  880              || type2 == RPM_I18NSTRING_TYPE) && (q != NULL)) {
  881             free((q));
  882             q = NULL;
  883         }
  884         if ((type3 == RPM_STRING_ARRAY_TYPE
  885              || type3 == RPM_I18NSTRING_TYPE) && (r != NULL)) {
  886             free((r));
  887             r = NULL;
  888         }
  889         for (; i < count; i++)
  890             rpmRequAdd(((char **) p)[i], NULL, RPM2HTML_REQ_NONE,
  891                        rpm, installed);
  892     }
  893     ENTRY_CLEANUP(p);
  894 
  895 #ifdef HAVE_RPM42
  896     const char *fname;
  897     rpmfi fi;
  898     fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, 0);
  899 
  900     if (rpmfiFC(fi) <= 0)
  901     rpm->extra->filelist = NULL;    /* No filelist in the package ! */
  902     else {
  903         fi = rpmfiInit(fi, 0);
  904         char *ptr = buffer;
  905 
  906         while (rpmfiNext(fi) >= 0) {
  907             fname = rpmfiFN(fi);
  908 #else
  909   #if defined(RPMTAG_FILENAMES)
  910     val = RPMTAG_FILENAMES;
  911     headerGetEntry(h, val, &type, &p, &count);
  912   #else
  913     rpmBuildFileList(h, (const char ***) &p, &count);
  914   #endif
  915 
  916     if (count == 0) {
  917         rpm->extra->filelist = NULL;    /* No filelist in the package ! */
  918     } else {
  919         char *ptr = buffer;
  920 
  921         for (i = 0; i < count; i++) {
  922 #endif
  923             if ((ptr - buffer) > (buffer_size - 1024)) {
  924                 int delta = ptr - buffer;
  925 
  926                 buffer_size *= 2;
  927                 buffer = (char *) xmlRealloc(buffer, buffer_size);
  928                 if (buffer == NULL) {
  929                     fprintf(stderr, "cannot re-allocate %d bytes: %s\n",
  930                             buffer_size, strerror(errno));
  931                     exit(1);
  932                 }
  933                 ptr = &buffer[delta];
  934             }
  935 #ifdef HAVE_RPM42
  936             ptr += snprintf(ptr, buffer_size, "%s\n", fname);
  937 #else
  938             ptr += snprintf(ptr, buffer_size, "%s\n", ((char **) p)[i]);
  939 #endif
  940         }
  941 #ifdef HAVE_RPM42
  942         fi = rpmfiFree(fi);
  943 #endif
  944         rpm->extra->filelist = xmlStrdup(buffer);
  945     }
  946 #ifndef HAVE_RPM42
  947     ENTRY_CLEANUP(p);
  948 #endif
  949 
  950 #ifdef WITH_GPG
  951     rpmResolveSignatures(path, nameRpm, sigtarget, rpm);
  952 #endif
  953 
  954 #ifdef WITH_SQL
  955     if ((path == NULL) || (!sql_get_package_id(path))) {
  956         id = sql_add_package(path, rpm->name, rpm->version, rpm->release,
  957                              rpm->arch, dir->no, rpm->url,
  958                              rpm->extra->srcrpm, dir->vendor,
  959                              rpm->extra->packager, rpm->group,
  960                              rpm->summary, rpm->extra->description,
  961                              rpm->extra->copyright, rpm->date, rpm->size,
  962                              rpm->os, rpm->distribution, rpm->vendor);
  963         if (id > 0) {
  964             for (i = 0; i < rpm->extra->nb_resources; i++)
  965                 sql_add_provides(id, rpm->extra->resources[i]->name);
  966             for (i = 0; i < rpm->extra->nb_requires; i++)
  967                 sql_add_requires(id, rpm->extra->requires[i]->name,
  968                                  rpm->extra->requires[i]->flag,
  969                                  rpm->extra->requires[i]->version);
  970         }
  971     } else
  972         id = 0;
  973 #endif
  974 
  975     /* Add the package files to the real filesystem tree if asked for */
  976 #ifdef WITH_SQL
  977     if ((rpm->extra->filelist != NULL) &&
  978         ((dir->build_tree != 0) || (id > 0))) {
  979 #else
  980     if ((dir->build_tree != 0) && (rpm->extra->filelist != NULL)) {
  981 #endif
  982         char *cur,
  983          *filename;
  984 
  985         cur = rpm->extra->filelist;
  986         while ((*cur != '\0') && (*cur != '/'))
  987             cur++;
  988         filename = cur;
  989         while (*cur != '\0') {
  990             if ((*cur == '\n') || (*cur == '\r')) {
  991                 if (cur != filename) {
  992 #ifdef WITH_SQL
  993                     if (dir->build_tree != 0)
  994                         rpmAddRealFile(dir->root, filename, rpm);
  995                     if (id > 0) {
  996                         *cur = 0;
  997                         sql_add_file(filename, id);
  998                         *cur = '\n';
  999                     }
 1000 #else
 1001                     rpmAddRealFile(dir->root, filename, rpm);
 1002 #endif
 1003                 }
 1004                 while ((*cur != '\0') && (*cur != '/'))
 1005                     cur++;
 1006                 filename = cur;
 1007             } else
 1008                 cur++;
 1009         }
 1010         if (cur != filename)
 1011             rpmAddRealFile(dir->root, filename, rpm);
 1012     }
 1013 
 1014     /* Register this package */
 1015     rpmAddSoftware(rpm);
 1016 
 1017     /* dump the HTML related to this package */
 1018     if ((rpm2html_dump_html) && (dir->html))
 1019         dumpRpmHtml(rpm, tree);
 1020     if (rpm2html_dump_rdf)
 1021         // TODO compare also last-modification-time of package on RDF (if existing) and dump RDF only if package is newer or RDF does not exists
 1022         dumpRpmRdf(rpm, tree);
 1023 
 1024     /* free the extra data */
 1025     rpmFreeExtraData(rpm);
 1026 
 1027     /* increment the counters */
 1028     if (installed) {
 1029         rpm2html_install_files++;
 1030         rpm2html_install_size += rpm->size / 1024;
 1031     } else {
 1032         rpm2html_files++;
 1033         rpm2html_size += rpm->size / 1024;
 1034     }
 1035 
 1036     return (rpm);
 1037 }
 1038 
 1039 /*
 1040  * rpmOpen : open an RPM file, read and parse the header and 
 1041  *           fill the information in the database.
 1042  */
 1043 rpmDataPtr
 1044 rpmOpen(char *nameRpm, rpmDirPtr dir, rpmSubdirPtr tree)
 1045 {
 1046     rpmDataPtr cur;
 1047     FD_t fd;
 1048     int rc;
 1049     Header h = NULL;
 1050     Header s = NULL;
 1051 #ifndef HAVE_RPM_RPMLEGACY_H
 1052     struct rpmlead lead;
 1053 #endif
 1054     int isSource;
 1055     char buffer[500];
 1056     struct stat buf;
 1057 
 1058 #if defined(WITH_GPG)
 1059     FD_t ofd = NULL;
 1060     char *sigtarget = NULL;
 1061     ssize_t count;
 1062     unsigned char stbuffer[8192];
 1063 #endif
 1064 
 1065     /* open the file for reading */
 1066     if (tree->htmlpath[0] != '\0')
 1067         snprintf(buffer, sizeof(buffer), "%s/%s/%s", dir->rpmdir,
 1068                  tree->rpmpath, nameRpm);
 1069     else
 1070         snprintf(buffer, sizeof(buffer), "%s/%s", dir->rpmdir, nameRpm);
 1071 
 1072     if (access(buffer, R_OK) < 0) {
 1073         fprintf(stderr, "open of %s failed: %s\n", buffer,
 1074                 strerror(errno));
 1075         return (NULL);
 1076     }
 1077     fd = Fopen(buffer, "r.fdio");
 1078     if (fd == NULL || Ferror(fd)) {
 1079         fprintf(stderr, "Fopen of %s failed: %s\n", buffer, Fstrerror(fd));
 1080         return (NULL);
 1081     }
 1082 
 1083     stat(buffer, &buf);
 1084 
 1085     /* read the RPM header */
 1086 #if defined(_RPMVSF_NODIGESTS)
 1087     {   rpmts ts = rpmtsCreate();
 1088     /* do no verifications except the SHA1 header */
 1089     /* for performance reasons (see redhat bugzilla #83320) */
 1090     rpmtsSetVSFlags(ts, ~RPMVSF_NOSHA1HEADER);
 1091     rc = rpmReadPackageFile(ts, fd, buffer, &h);
 1092     ts = rpmtsFree(ts);
 1093     }
 1094 #else
 1095     rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
 1096 #endif
 1097     switch (rc) {
 1098         case 0:
 1099             if (!h) {
 1100                 fprintf(stderr,
 1101                         "old format source packages cannot be queried\n");
 1102                 Fclose(fd);
 1103                 return (NULL);
 1104             }
 1105         isSource = (headerIsEntry(h, RPMTAG_SOURCEPACKAGE) ? 1 : 0);
 1106             break;
 1107         case 1:
 1108             fprintf(stderr, "%s does not appear to be a RPM package\n",
 1109                     nameRpm);
 1110             Fclose(fd);
 1111             return (NULL);
 1112         case 2:
 1113             fprintf(stderr, "query of %s failed\n", nameRpm);
 1114             Fclose(fd);
 1115             return (NULL);
 1116         case 4:
 1117         fprintf(stderr, "%s: Error %d Found and Ignored\n", nameRpm, rc);
 1118         if (!h) {
 1119         fprintf(stderr,
 1120             "packages cannot be queried\n");
 1121         Fclose(fd);
 1122         return (NULL);
 1123         }
 1124         isSource = (headerIsEntry(h, RPMTAG_SOURCEPACKAGE) ? 1 : 0);
 1125         break;
 1126         default:
 1127             fprintf(stderr, "rpmReadPackageHeader(%s): unknown error %d\n",
 1128                     nameRpm, rc);
 1129             Fclose(fd);
 1130             return (NULL);
 1131      }
 1132 
 1133 
 1134 #ifdef HAVE_RPM_RPMLEGACY_H
 1135     // XXX  phanecak: for now I do not know how to read signatures with rpm.org 4.6 or later
 1136 #else   // ifdef HAVE_RPM_RPMLEGACY_H
 1137     /* read the RPM signature */
 1138     if (readLead(fd, &lead)) {
 1139         fprintf(stderr, "readLead failed\n");
 1140         fdClose(fd);
 1141         return (NULL);
 1142     }
 1143     switch (lead.major) {
 1144         case 1:
 1145             fprintf(stderr, "no signature available (v1.0 RPM) in %s\n",
 1146                     nameRpm);
 1147             break;
 1148         default:
 1149 #ifdef HAVE_RPM42
 1150             if (rpmReadSignature(fd, &s, lead.signature_type, NULL)) {
 1151 #else
 1152             if (rpmReadSignature(fd, &s, lead.signature_type)) {
 1153 #endif
 1154                 fprintf(stderr, "rpmReadSignature failed\n");
 1155                 fdClose(fd);
 1156                 return (NULL);
 1157             }
 1158             if (!s) {
 1159                 fprintf(stderr, "no signature available in %s\n", nameRpm);
 1160                 fdClose(fd);
 1161                 return (NULL);
 1162             }
 1163 #if defined(WITH_GPG)
 1164             /* open temp file for writing */
 1165             sigtarget = xmlMalloc(30);
 1166             strcpy(sigtarget, "/tmp/rpm2html.date.XXXXXX");
 1167             sigtarget = mktemp(sigtarget);
 1168             ofd = Fopen(sigtarget, "w.ufdio");
 1169             if (ofd == NULL || Ferror(ofd)) {
 1170                 fprintf(stderr, "Fopen of %s failed: %s\n", sigtarget,
 1171                         Fstrerror(ofd));
 1172                 xmlFree(sigtarget);
 1173                 sigtarget = NULL;
 1174             }
 1175 
 1176             /* write the header and archive to a temp file */
 1177             while ((count =
 1178                     Fread(stbuffer, sizeof(stbuffer[0]), sizeof(stbuffer),
 1179                           fd)) > 0) {
 1180                 if (Fwrite(stbuffer, sizeof(stbuffer[0]), count, ofd) < 0) {
 1181                     fprintf(stderr, "%s: Fwrite failed: %s\n", sigtarget,
 1182                             Fstrerror(ofd));
 1183                     xmlFree(sigtarget);
 1184                     sigtarget = NULL;
 1185                 }
 1186             }
 1187             if (count < 0) {
 1188                 fprintf(stderr, "%s: Fread failed: %s\n", buffer,
 1189                         Fstrerror(fd));
 1190                 xmlFree(sigtarget);
 1191                 sigtarget = NULL;
 1192             }
 1193 
 1194             Fclose(ofd);
 1195 #endif
 1196             break;
 1197     }
 1198 #endif  // ifdef HAVE_RPM_RPMLEGACY_H
 1199 
 1200     /* close the descriptor */
 1201     Fclose(fd);
 1202 
 1203 #if defined(WITH_GPG)
 1204     cur =
 1205         rpmAnalyze(buffer, nameRpm, sigtarget, h, s, dir, tree,
 1206                    buf.st_mtime, isSource);
 1207 #else
 1208     cur =
 1209         rpmAnalyze(buffer, nameRpm, NULL, h, s, dir, tree, buf.st_mtime,
 1210                    isSource);
 1211 #endif
 1212 
 1213     /* free the header */
 1214     headerFree(h);
 1215     headerFree(s);
 1216 
 1217 #if defined(WITH_GPG)
 1218     if (sigtarget) {
 1219         unlink(sigtarget);
 1220         xmlFree(sigtarget);
 1221     }
 1222 #endif
 1223 
 1224     return (cur);
 1225 }
 1226 
 1227 /*
 1228  * Scan one directory for RPM files this is where the recursive handling
 1229  * is done.
 1230  */
 1231 static rpmDataPtr
 1232 rpmOneDirScan(rpmDirPtr dir, rpmSubdirPtr tree)
 1233 {
 1234     rpmSubdirPtr subtree;
 1235     rpmDataPtr ret = NULL,
 1236       cur;
 1237     char *filename;
 1238     static char path[2000];
 1239     struct stat buf;
 1240     int len;
 1241     DIR *d;
 1242     struct dirent *file;
 1243 
 1244 
 1245     /*
 1246      * Create the directory for the HTML pages
 1247      */
 1248     if ((rpm2html_dump_html) && (dir->html)) {
 1249         if (tree->htmlpath[0] != '\0')
 1250             snprintf(path, sizeof(path), "%s/%s", dir->dir,
 1251                      tree->htmlpath);
 1252         else
 1253             snprintf(path, sizeof(path), "%s", dir->dir);
 1254         createDirectory(path);
 1255     }
 1256 
 1257     /*
 1258      * Scan the repository.
 1259      */
 1260     if (tree->rpmpath[0] != '\0')
 1261         snprintf(path, sizeof(path), "%s/%s", dir->rpmdir, tree->rpmpath);
 1262     else
 1263         snprintf(path, sizeof(path), "%s", dir->rpmdir);
 1264     if (rpm2htmlVerbose > 1)
 1265         printf("Scanning directory %s\n", path);
 1266 
 1267     d = opendir(path);
 1268     if (d == NULL) {
 1269         fprintf(stderr, "Listing of %s failed: %s\n", path,
 1270                 strerror(errno));
 1271         rpmRemoveSubdir(tree);
 1272         rpmFreeSubdir(tree);
 1273         tree = NULL;
 1274         return (NULL);
 1275     } else {
 1276         while ((file = readdir(d)) != NULL) {
 1277             cur = NULL;
 1278             filename = file->d_name;
 1279             len = strlen(filename);
 1280 
 1281             /*
 1282              * Compute the full path
 1283              */
 1284             if (tree->rpmpath[0] != '\0')
 1285                 snprintf(path, sizeof(path), "%s/%s/%s", dir->rpmdir,
 1286                          tree->rpmpath, filename);
 1287             else
 1288                 snprintf(path, sizeof(path), "%s/%s", dir->rpmdir,
 1289                          filename);
 1290 
 1291             /*
 1292              * Stat() the file to detect directory and symlimks
 1293              */
 1294             if (lstat(path, &buf) != 0) {
 1295                 fprintf(stderr, "Couldn't stat(%s)\n", path);
 1296                 continue;
 1297             }
 1298 
 1299             /*
 1300              * Check for RPM files by looking at the suffix
 1301              * Note that SuSE source RPMs have a ".spm" suffix
 1302              * We may or may not follow symlinks to RPM files
 1303              */
 1304             if (((len >= 5) &&
 1305                  (!strcasecmp(&filename[len - 4], ".rpm"))) ||
 1306                 ((len >= 5) &&
 1307                  (!strcasecmp(&filename[len - 4], ".spm")))) {
 1308 
 1309                 if ((S_ISLNK(buf.st_mode)) && (dir->rpm_symlinks == 0)) {
 1310                     if (rpm2htmlVerbose > 1)
 1311                         fprintf(stderr, "Dropping symlink %s\n", path);
 1312                     continue;
 1313                 }
 1314                 cur = rpmOpen(filename, dir, tree);
 1315             }
 1316 
 1317             /*
 1318              * Don't follow of analyze symlinks,
 1319              */
 1320             else if ((S_ISLNK(buf.st_mode)) && (dir->follow_symlinks == 0)) {
 1321                 if (rpm2htmlVerbose > 1)
 1322                     fprintf(stderr, "Dropping symlink %s\n", path);
 1323                 continue;
 1324             }
 1325 
 1326             /*
 1327              * Check for RDF files by looking at the suffix
 1328              */
 1329             else if ((len >= 5)
 1330                      && (!strcasecmp(&filename[len - 4], ".rdf"))) {
 1331                 cur = rpmOpenRdf(filename, dir, tree);
 1332             }
 1333 
 1334             /*
 1335              * Else if this is a directory, recurse !
 1336              */
 1337             else if (S_ISDIR(buf.st_mode)) {
 1338                 if (filename[0] != '.') {
 1339                     subtree =
 1340                         rpmNewSubdir(tree, filename, NULL, NULL, NULL, 0);
 1341                     cur = rpmOneDirScan(dir, subtree);
 1342                 }
 1343             }
 1344             if (cur != NULL)
 1345                 ret = rpmAddList(ret, cur);
 1346         }
 1347     }
 1348     closedir(d);
 1349 
 1350     /*
 1351      * Dump the pages related to this directory.
 1352      */
 1353     if (ret != NULL)
 1354         ret = dumpDirIndex(dir, tree, ret);
 1355     else {
 1356         rpmRemoveSubdir(tree);
 1357         rpmFreeSubdir(tree);
 1358         tree = NULL;
 1359     }
 1360 
 1361     return (ret);
 1362 }
 1363 
 1364 /*
 1365  * Scan a directory for RPM files.
 1366  */
 1367 static rpmDataPtr
 1368 rpmDirScan(rpmDirPtr dir, rpmSubdirPtr tree)
 1369 {
 1370     rpmSubdirPtr cur;
 1371     rpmDataPtr ret;
 1372 
 1373     if ((rpm2html_dump_html) && (dir->html) && (dir->build_tree != 0)) {
 1374         dir->root = rpmCreateRealRoot();
 1375     }
 1376     cur = rpmNewSubdir(tree, dir->name,
 1377                        dir->subdir == NULL ? "" : dir->subdir, "",
 1378                        dir->color, dir->html);
 1379     ret = rpmOneDirScan(dir, cur);
 1380     rpmDumpHtmlRealRoot(dir);
 1381     return (ret);
 1382 }
 1383 
 1384 /*
 1385  * Scan the local RPM database for RPM files.
 1386  */
 1387 static rpmDataPtr
 1388 rpmBaseScan(rpmDirPtr dir)
 1389 {
 1390     static char path[2000];
 1391     rpmDataPtr ret = NULL,
 1392       cur;
 1393     rpmdb db;
 1394     Header h = NULL;
 1395     char *prefix = "/";
 1396     rpmdbMatchIterator mi;
 1397 
 1398 #ifdef WITH_SQL
 1399     dir->no = sql_get_distrib_by_directory(dir->rpmdir);
 1400 #endif
 1401 
 1402     /*
 1403      * Create the directory for the HTML pages
 1404      */
 1405     if ((rpm2html_dump_html) && (dir->html)) {
 1406         if (dir->subdir)
 1407             snprintf(path, sizeof(path), "%s/%s", dir->dir, dir->subdir);
 1408         else
 1409             snprintf(path, sizeof(path), "%s", dir->dir);
 1410         createDirectory(path);
 1411     }
 1412 
 1413     /*
 1414      * Create the directory for the RDF pages
 1415      */
 1416     if (rpm2html_rdf_dir != NULL) {
 1417         if (dir->subdir)
 1418             snprintf(path, sizeof(path), "%s/%s", rpm2html_rdf_dir,
 1419                      dir->subdir);
 1420         else
 1421             snprintf(path, sizeof(path), "%s", rpm2html_rdf_dir);
 1422         createDirectory(path);
 1423     }
 1424 
 1425     if (rpm2htmlVerbose)
 1426         printf("Scanning the database of installed RPMs\n");
 1427 
 1428     if (dir->dbpath != NULL)
 1429         addMacro(NULL, "_dbpath", NULL, dir->dbpath, -7);       /* Added by A.Gibert */
 1430 
 1431     if (rpmdbOpen(prefix, &db, O_RDONLY, 0644)) {
 1432         return (NULL);
 1433     }
 1434 
 1435     mi = rpmdbInitIterator(db, RPMDBI_PACKAGES, NULL, 0);
 1436     while ((h = rpmdbNextIterator(mi)) != NULL) {
 1437         cur = rpmAnalyze(NULL, NULL, NULL, h, NULL, dir, NULL, 0, 0);
 1438         if (cur != NULL)
 1439             ret = rpmAddList(ret, cur);
 1440     }
 1441     rpmdbFreeIterator(mi);
 1442 
 1443     rpmdbClose(db);
 1444 
 1445     return (ret);
 1446 }
 1447 
 1448 /*
 1449  * Scan one directory only
 1450  */
 1451 
 1452 void
 1453 rpmDirScanOneDir(const char *directory)
 1454 {
 1455     rpmDirPtr dir;
 1456     rpmDataPtr cur;
 1457 
 1458     /*
 1459      * first try to find the distrib
 1460      */
 1461     dir = dirList;
 1462     while (dir != NULL) {
 1463         if (!strcasecmp(dir->rpmdir, directory))
 1464             break;
 1465         dir = dir->next;
 1466     }
 1467     if (dir == NULL) {
 1468         fprintf(stderr, "rpmDirScanOneDir(%s): distribution not found\n",
 1469                 directory);
 1470         return;
 1471     }
 1472     if (rpm2htmlVerbose)
 1473         printf("indexing %s\n", dir->name);
 1474 
 1475     /*
 1476      * Allocate a directory tree.
 1477      */
 1478     dirTree = rpmNewSubdir(NULL, "", "", "", NULL, 1);
 1479 
 1480     cur = NULL;
 1481 
 1482     /*
 1483      * Override default setting.
 1484      */
 1485     if ((dir->maint == NULL) && (rpm2html_maint != NULL))
 1486         dir->maint = xmlStrdup(rpm2html_maint);
 1487     if ((dir->mail == NULL) && (rpm2html_mail != NULL))
 1488         dir->mail = xmlStrdup(rpm2html_mail);
 1489     if ((dir->ftp == NULL) && (rpm2html_ftp != NULL))
 1490         dir->ftp = xmlStrdup(rpm2html_ftp);
 1491     if ((dir->ftpsrc == NULL) && (rpm2html_ftpsrc != NULL))
 1492         dir->ftpsrc = xmlStrdup(rpm2html_ftpsrc);
 1493     if ((dir->dir == NULL) && (rpm2html_dir != NULL))
 1494         dir->dir = xmlStrdup(rpm2html_dir);
 1495     if ((dir->host == NULL) && (rpm2html_host != NULL))
 1496         dir->host = xmlStrdup(rpm2html_host);
 1497     if ((dir->name == NULL) && (rpm2html_name != NULL))
 1498         dir->name = xmlStrdup(rpm2html_name);
 1499     if ((dir->url == NULL) && (rpm2html_url != NULL))
 1500         dir->url = xmlStrdup(rpm2html_url);
 1501 
 1502     if (dir->rpmdir == NULL) {
 1503         fprintf(stderr, "?!? rpmDir without directory ?!? disabled !\n");
 1504     } else if (!strncmp(dir->rpmdir, "localbase", 9)) {
 1505         /* Scan the local RPM database instead of a directory */
 1506         cur = rpmBaseScan(dir);
 1507     } else if (dir->ftp == NULL) {
 1508         fprintf(stderr, "Directory %s disabled : no ftp field\n",
 1509                 dir->rpmdir);
 1510     } else {
 1511 #ifdef WITH_SQL
 1512         dir->no = sql_get_distrib_by_directory(dir->rpmdir);
 1513 #endif
 1514         if (rpm2htmlVerbose)
 1515             printf("Scanning directory %s for RPMs\n", dir->rpmdir);
 1516         cur = rpmDirScan(dir, dirTree);
 1517     }
 1518 }
 1519 
 1520 
 1521 /*
 1522  * Scan one distribution only
 1523  */
 1524 
 1525 void
 1526 rpmDirScanOneDist(const char *dist)
 1527 {
 1528     rpmDirPtr dir;
 1529     rpmDataPtr cur;
 1530 
 1531     /*
 1532      * first try to find the distrib
 1533      */
 1534     dir = dirList;
 1535     while (dir != NULL) {
 1536         if (!strcasecmp(dir->name, dist))
 1537             break;
 1538         if (!strcasecmp(dir->subdir, dist))
 1539             break;
 1540         if (!strcasecmp(dir->rpmdir, dist))
 1541             break;
 1542         dir = dir->next;
 1543     }
 1544     if (dir == NULL) {
 1545         dir = dirList;
 1546         while (dir != NULL) {
 1547             if (!strstr(dir->name, dist))
 1548                 break;
 1549             if (!strstr(dir->subdir, dist))
 1550                 break;
 1551             if (!strstr(dir->rpmdir, dist))
 1552                 break;
 1553             dir = dir->next;
 1554         }
 1555     }
 1556     if (dir == NULL) {
 1557         fprintf(stderr, "rpmDirScanOneDist(%s): distribution not found\n",
 1558                 dist);
 1559         return;
 1560     }
 1561     if (rpm2htmlVerbose)
 1562         printf("indexing %s\n", dir->name);
 1563 
 1564     /*
 1565      * Allocate a directory tree.
 1566      */
 1567     dirTree = rpmNewSubdir(NULL, "", "", "", NULL, 1);
 1568 
 1569     cur = NULL;
 1570 
 1571     /*
 1572      * Override default setting.
 1573      */
 1574     if ((dir->maint == NULL) && (rpm2html_maint != NULL))
 1575         dir->maint = xmlStrdup(rpm2html_maint);
 1576     if ((dir->mail == NULL) && (rpm2html_mail != NULL))
 1577         dir->mail = xmlStrdup(rpm2html_mail);
 1578     if ((dir->ftp == NULL) && (rpm2html_ftp != NULL))
 1579         dir->ftp = xmlStrdup(rpm2html_ftp);
 1580     if ((dir->ftpsrc == NULL) && (rpm2html_ftpsrc != NULL))
 1581         dir->ftpsrc = xmlStrdup(rpm2html_ftpsrc);
 1582     if ((dir->dir == NULL) && (rpm2html_dir != NULL))
 1583         dir->dir = xmlStrdup(rpm2html_dir);
 1584     if ((dir->host == NULL) && (rpm2html_host != NULL))
 1585         dir->host = xmlStrdup(rpm2html_host);
 1586     if ((dir->name == NULL) && (rpm2html_name != NULL))
 1587         dir->name = xmlStrdup(rpm2html_name);
 1588     if ((dir->url == NULL) && (rpm2html_url != NULL))
 1589         dir->url = xmlStrdup(rpm2html_url);
 1590 
 1591     if (dir->rpmdir == NULL) {
 1592         fprintf(stderr, "?!? rpmDir without directory ?!? disabled !\n");
 1593     } else if (!strncmp(dir->rpmdir, "localbase", 9)) {
 1594         /* Scan the local RPM database instead of a directory */
 1595         cur = rpmBaseScan(dir);
 1596     } else if (dir->ftp == NULL) {
 1597         fprintf(stderr, "Directory %s disabled : no ftp field\n",
 1598                 dir->rpmdir);
 1599     } else {
 1600 #ifdef WITH_SQL
 1601         dir->no = sql_get_distrib_by_directory(dir->rpmdir);
 1602 #endif
 1603         if (rpm2htmlVerbose)
 1604             printf("Scanning directory %s for RPMs\n", dir->rpmdir);
 1605         cur = rpmDirScan(dir, dirTree);
 1606     }
 1607 
 1608     if (dir->root != NULL) {
 1609         rpmDestroyRealRoot(dir->root);
 1610         dir->root = NULL;
 1611     }
 1612     rpmFreeSubdir(dirTree);
 1613     dirTree = NULL;
 1614 }
 1615 
 1616 /*
 1617  * Scan all registered directories.
 1618  * One fist check for completeness of the information in
 1619  * the rpmDir structure.
 1620  */
 1621 
 1622 rpmDataPtr
 1623 rpmDirScanAll(void)
 1624 {
 1625     rpmDirPtr dir,
 1626       next;
 1627     rpmDataPtr ret = NULL,
 1628       cur;
 1629 
 1630 #ifndef WITH_SQL
 1631     int maxLists = 50;
 1632     rpmDataPtr *rpmLists;
 1633     int nbLists = 0;
 1634     int i;
 1635 #endif
 1636 
 1637     /*
 1638      * first reverse the list ....
 1639      */
 1640     dir = dirList;
 1641     dirList = NULL;
 1642     while (dir != NULL) {
 1643         next = dir->next;
 1644         dir->next = dirList;
 1645         dirList = dir;
 1646         dir = next;
 1647     }
 1648     dir = dirList;
 1649 
 1650     /*
 1651      * Allocate a directory tree.
 1652      */
 1653     dirTree = rpmNewSubdir(NULL, "", "", "", NULL, 1);
 1654 
 1655 #ifndef WITH_SQL
 1656     rpmLists = (rpmDataPtr *) xmlMalloc(maxLists * sizeof(rpmDataPtr));
 1657     if (rpmLists == NULL) {
 1658         fprintf(stderr, "rpmDirScanAll : running out of memory !\n");
 1659         exit(1);
 1660     }
 1661 #endif
 1662 
 1663     while (dir != NULL) {
 1664         cur = NULL;
 1665 
 1666         /*
 1667          * Complete with default setting.
 1668          */
 1669         if ((dir->maint == NULL) && (rpm2html_maint != NULL))
 1670             dir->maint = xmlStrdup(rpm2html_maint);
 1671         if ((dir->mail == NULL) && (rpm2html_mail != NULL))
 1672             dir->mail = xmlStrdup(rpm2html_mail);
 1673         if ((dir->ftp == NULL) && (rpm2html_ftp != NULL))
 1674             dir->ftp = xmlStrdup(rpm2html_ftp);
 1675         if ((dir->ftpsrc == NULL) && (rpm2html_ftpsrc != NULL))
 1676             dir->ftpsrc = xmlStrdup(rpm2html_ftpsrc);
 1677         if ((dir->dir == NULL) && (rpm2html_dir != NULL))
 1678             dir->dir = xmlStrdup(rpm2html_dir);
 1679         if ((dir->host == NULL) && (rpm2html_host != NULL))
 1680             dir->host = xmlStrdup(rpm2html_host);
 1681         if ((dir->name == NULL) && (rpm2html_name != NULL))
 1682             dir->name = xmlStrdup(rpm2html_name);
 1683         if ((dir->url == NULL) && (rpm2html_url != NULL))
 1684             dir->url = xmlStrdup(rpm2html_url);
 1685 
 1686         if (dir->rpmdir == NULL) {
 1687             fprintf(stderr,
 1688                     "?!? rpmDir without directory ?!? disabled !\n");
 1689         } else if (!strncmp(dir->rpmdir, "localbase", 9)) {
 1690             /* Scan the local RPM database instead of a directory */
 1691             cur = rpmBaseScan(dir);
 1692         } else if (dir->ftp == NULL) {
 1693             fprintf(stderr, "Directory %s disabled : no ftp field\n",
 1694                     dir->rpmdir);
 1695         } else {
 1696 #ifdef WITH_SQL
 1697             dir->no = sql_get_distrib_by_directory(dir->rpmdir);
 1698 #endif
 1699             if (rpm2htmlVerbose)
 1700                 printf("Scanning directory %s for RPMs\n", dir->rpmdir);
 1701             cur = rpmDirScan(dir, dirTree);
 1702         }
 1703 
 1704 #ifdef WITH_SQL
 1705         /*
 1706          * The packages list will be reextratced from the
 1707          * database at the end, minimize memory consumption
 1708          */
 1709         rpmlistCleanup();
 1710 #else
 1711         if (cur != NULL) {
 1712             if (nbLists >= maxLists) {
 1713                 maxLists *= 2;
 1714                 rpmLists = (rpmDataPtr *) xmlRealloc(rpmLists,
 1715                                                      maxLists *
 1716                                                      sizeof(rpmDataPtr));
 1717                 if (rpmLists == NULL) {
 1718                     fprintf(stderr,
 1719                             "rpmDirScanAll : running out of memory!\n");
 1720                     exit(1);
 1721                 }
 1722             }
 1723             rpmLists[nbLists] = cur;
 1724             nbLists++;
 1725         }
 1726 #endif
 1727         if (dir->root != NULL) {
 1728             rpmDestroyRealRoot(dir->root);
 1729             dir->root = NULL;
 1730         }
 1731         dir = dir->next;
 1732     }
 1733 #ifndef WITH_SQL
 1734     for (i = 0; i < nbLists; i++)
 1735         ret = rpmAddList(ret, rpmLists[i]);
 1736     xmlFree(rpmLists);
 1737 #endif
 1738     return (ret);
 1739 }
 1740 
 1741 /*
 1742  * Cleanup the global variables from this module
 1743  */
 1744 void
 1745 rpmopenCleanup(void)
 1746 {
 1747     if (buffer != NULL)
 1748         xmlFree(buffer);
 1749     buffer = NULL;
 1750     buffer_size = 50 * 1024 * sizeof(char);
 1751 }
 1752