Annotation of rpm2html/rpmopen.c, revision 1.91

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

Webmaster