Annotation of rpm2html/rpmopen.c, revision 1.88

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.88    ! veillard    6:  * $Id: rpmopen.c,v 1.87 2000/11/17 17:30:51 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.87      veillard  817:                         rpm->extra->copyright, rpm->date, rpm->os);
1.76      veillard  818:     if (id > 0) {
                    819:        for (i = 0;i < rpm->extra->nb_resources;i++)
                    820:            sql_add_provides(id, rpm->extra->resources[i]->name);
                    821:        for (i = 0;i < rpm->extra->nb_requires;i++)
                    822:            sql_add_requires(id, rpm->extra->requires[i]->name,
1.77      veillard  823:                             rpm->extra->requires[i]->flag,
1.76      veillard  824:                             rpm->extra->requires[i]->version);
                    825:     }
1.75      veillard  826: #endif
                    827: 
1.37      veillard  828:     /* Add the package files to the real filesystem tree if asked for */
1.75      veillard  829: #ifdef WITH_SQL
                    830:     if ((rpm->extra->filelist != NULL) &&
                    831:        ((dir->build_tree != 0) || (id > 0))) {
                    832: #else
1.58      daniel    833:     if ((dir->build_tree != 0) && (rpm->extra->filelist != NULL)) {
1.75      veillard  834: #endif
1.37      veillard  835:         char *cur, *filename;
                    836:        
1.58      daniel    837:        cur = rpm->extra->filelist;
1.37      veillard  838:        while ((*cur != '\0') && (*cur != '/')) cur++;
                    839:        filename = cur;
                    840:        while (*cur != '\0') {
                    841:            if ((*cur == '\n') || (*cur == '\r')) {
1.75      veillard  842:                if (cur != filename) {
                    843: #ifdef WITH_SQL
                    844:                    if (dir->build_tree != 0)
                    845:                        rpmAddRealFile(dir->root, filename, rpm);
                    846:                    if (id > 0) {
                    847:                        *cur = 0;
                    848:                        sql_add_file(filename,id);
                    849:                        *cur = '\n';
                    850:                    }
                    851: #else
1.37      veillard  852:                    rpmAddRealFile(dir->root, filename, rpm);
1.75      veillard  853: #endif
                    854:                }
1.37      veillard  855:                while ((*cur != '\0') && (*cur != '/')) cur++;
                    856:                 filename = cur;
                    857:            } else
                    858:                cur++;
                    859:        }
                    860:        if (cur != filename)
                    861:            rpmAddRealFile(dir->root, filename, rpm);
                    862:     }
1.17      veillard  863: 
                    864:     /* Register this package */
                    865:     rpmAddSoftware(rpm);
1.7       veillard  866: 
                    867:     /* dump the HTML related to this package */
1.56      daniel    868:     if ((rpm2html_dump_html) && (dir->html))
1.40      httpng    869:        dumpRpmHtml(rpm, tree);
                    870:     if (rpm2html_dump_rdf)
                    871:        dumpRpmRdf(rpm, tree);
1.7       veillard  872: 
1.58      daniel    873:     /* free the extra data */
                    874:     rpmFreeExtraData(rpm);
1.8       veillard  875: 
                    876:     /* increment the counters */
1.11      veillard  877:     if (installed) {
                    878:        rpm2html_install_files++;
1.21      veillard  879:        rpm2html_install_size += rpm->size / 1024;
1.11      veillard  880:     } else {
                    881:        rpm2html_files++;
1.21      veillard  882:        rpm2html_size += rpm->size / 1024;
1.11      veillard  883:     }
1.7       veillard  884: 
1.32      veillard  885:     return(rpm);
1.11      veillard  886: }
                    887: 
                    888: /*
                    889:  * rpmOpen : open an RPM file, read and parse the header and 
                    890:  *           fill the informations in the database.
                    891:  */
1.35      veillard  892: rpmDataPtr rpmOpen(char *nameRpm, rpmDirPtr dir, rpmSubdirPtr tree) {
1.32      veillard  893:     rpmDataPtr cur;
1.64      daniel    894: #if defined(HAVE_RPM_RPMIO_H)
                    895:     FD_t fd;
                    896: #else
1.11      veillard  897:     int fd;
1.64      daniel    898: #define        fdOpen(_a, _b, _c)      open((_a), (_b))
                    899: #define        fdClose(_a)             close(_a)
                    900: #endif
1.11      veillard  901:     int rc;
                    902:     Header h = NULL;
1.83      veillard  903:     Header s = NULL;
                    904:     struct rpmlead lead;
1.11      veillard  905:     int isSource;
                    906:     char buffer[500];
1.20      veillard  907:     struct stat buf;
1.86      veillard  908: #if defined(WITH_GPG)
                    909:     FD_t ofd = NULL;
                    910:     char *sigtarget = NULL;
                    911:     ssize_t count;
                    912:     unsigned char stbuffer[8192];
                    913: #endif
1.11      veillard  914: 
                    915:     /* open the file for reading */
1.35      veillard  916:     if (tree->htmlpath[0] != '\0')
1.66      daniel    917:        snprintf(buffer, sizeof(buffer), "%s/%s/%s", dir->rpmdir, tree->rpmpath, nameRpm);
1.24      veillard  918:     else
1.66      daniel    919:        snprintf(buffer, sizeof(buffer), "%s/%s", dir->rpmdir, nameRpm);
1.72      daniel    920: 
1.78      daniel    921:     if (access(buffer, R_OK) < 0) {
                    922:          fprintf(stderr, "open of %s failed: %s\n", buffer,
                    923:                 strerror(errno));
                    924:         return(NULL);
                    925:     }
1.72      daniel    926: #if defined(USE_RPMIO)
                    927:     fd = Fopen(buffer, "r.fdio");
                    928:     if (fd == NULL || Ferror(fd)) {
                    929:          fprintf(stderr, "Fopen of %s failed: %s\n", buffer,
                    930:                 Fstrerror(fd));
                    931:         return(NULL);
                    932:     }
                    933: #else
1.64      daniel    934:     if ((fd = fdOpen(buffer, O_RDONLY, 0)) < 0) {
1.11      veillard  935:          fprintf(stderr, "open of %s failed: %s\n", buffer,
                    936:                 strerror(errno));
1.32      veillard  937:         return(NULL);
1.11      veillard  938:     }
1.72      daniel    939: #endif
1.11      veillard  940: 
1.20      veillard  941:     stat(buffer, &buf);
                    942: 
1.11      veillard  943:     /* read the RPM header */
                    944:     rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
                    945:     switch (rc) {
                    946:        case 0:
                    947:            if (!h) {
                    948:                fprintf(stderr,
                    949:                        "old format source packages cannot be queried\n");
1.68      veillard  950:                fdClose(fd);
1.32      veillard  951:                return(NULL);
1.11      veillard  952:            }
                    953:            break;
                    954:        case 1:
                    955:            fprintf(stderr, "%s does not appear to be a RPM package\n",
                    956:                    nameRpm);
1.68      veillard  957:            fdClose(fd);
1.32      veillard  958:            return(NULL);
1.11      veillard  959:        case 2:
                    960:            fprintf(stderr, "query of %s failed\n", nameRpm);
1.68      veillard  961:            fdClose(fd);
1.32      veillard  962:            return(NULL);
1.11      veillard  963:        default:
                    964:            fprintf(stderr, "rpmReadPackageHeader(%s): unknown error %d\n",
                    965:                    nameRpm, rc);
1.68      veillard  966:            fdClose(fd);
1.32      veillard  967:            return(NULL);
1.11      veillard  968:     }
                    969: 
                    970: 
1.83      veillard  971:     /* close the descriptor */
                    972: #if defined(USE_RPMIO)
                    973:     Fclose(fd);
                    974: #else
                    975:     fdClose(fd);
                    976: #endif
                    977: 
                    978:     /* XXX I do not know whether it is necessary to open the file twice */
                    979:     /* open the file for reading */
                    980: #if defined(USE_RPMIO)
                    981:     fd = Fopen(buffer, "r.fdio");
                    982:     if (fd == NULL || Ferror(fd)) {
                    983:          fprintf(stderr, "Fopen of %s failed: %s\n", buffer,
                    984:                 Fstrerror(fd));
                    985:         return(NULL);
                    986:     }
                    987: #else
                    988:     if ((fd = fdOpen(buffer, O_RDONLY, 0)) < 0) {
                    989:          fprintf(stderr, "open of %s failed: %s\n", buffer,
                    990:                 strerror(errno));
                    991:         return(NULL);
                    992:     }
                    993: #endif
                    994: 
                    995:     /* read the RPM signature */
                    996:     if (readLead(fd, &lead)) {
                    997:         fprintf(stderr, "readLead failed\n");
                    998:         fdClose(fd); 
                    999:         return(NULL);
                   1000:     }
                   1001:     switch (lead.major) {
                   1002:         case 1:
                   1003:             fprintf(stderr, "no signature available (v1.0 RPM) in %s\n", nameRpm);
                   1004:             break;
                   1005:         default:
                   1006:             if (rpmReadSignature(fd, &s, lead.signature_type)) {
                   1007:                fprintf(stderr, "rpmReadSignature failed\n");
                   1008:                fdClose(fd);
                   1009:                return(NULL);
                   1010:             }
                   1011:             if (!s) {
                   1012:                fprintf(stderr, "no signature available in %s\n", nameRpm);
                   1013:                fdClose(fd);
                   1014:                return(NULL);
                   1015:             }
1.86      veillard 1016: #if defined(WITH_GPG)
                   1017:             /* open temp file for writing */
                   1018:             sigtarget = debugMalloc(30);
                   1019:             strcpy(sigtarget, "/tmp/rpm2html.date.XXXXXX");
                   1020:             sigtarget = mktemp(sigtarget);
                   1021:             ofd = Fopen(sigtarget, "w.ufdio");
                   1022:             if (ofd == NULL || Ferror(ofd)) {
                   1023:                 fprintf(stderr, "Fopen of %s failed: %s\n", sigtarget,
                   1024:                     Fstrerror(ofd));
                   1025:                 debugFree(sigtarget);
                   1026:                 sigtarget = NULL;
                   1027:             }
                   1028: 
                   1029:             /* write the header and archive to a temp file */
                   1030:             while ((count = Fread(stbuffer, sizeof(stbuffer[0]), sizeof(stbuffer), fd)) > 0) {
                   1031:                 if (Fwrite(stbuffer, sizeof(stbuffer[0]), count, ofd) < 0) {
                   1032:                     fprintf(stderr, "%s: Fwrite failed: %s\n", sigtarget,
                   1033:                         Fstrerror(ofd));
                   1034:                     debugFree(sigtarget);
                   1035:                     sigtarget = NULL;
                   1036:                 }
                   1037:             }
                   1038:             if (count < 0) {
                   1039:                 fprintf(stderr, "%s: Fread failed: %s\n", buffer, Fstrerror(fd));
                   1040:                 debugFree(sigtarget);
                   1041:                 sigtarget = NULL;
                   1042:             }
                   1043: 
                   1044:             Fclose(ofd);
                   1045: #endif
1.83      veillard 1046:             break;
                   1047:     }
                   1048: 
                   1049:     /* close the descriptor */
1.72      daniel   1050: #if defined(USE_RPMIO)
                   1051:     Fclose(fd);
                   1052: #else
1.64      daniel   1053:     fdClose(fd);
1.72      daniel   1054: #endif
1.1       veillard 1055: 
1.86      veillard 1056: #if defined(WITH_GPG)
                   1057:     cur = rpmAnalyze(buffer, nameRpm, sigtarget, h, s, dir, tree, buf.st_mtime, isSource);
                   1058: #else
                   1059:     cur = rpmAnalyze(buffer, nameRpm, NULL, h, s, dir, tree, buf.st_mtime, isSource);
                   1060: #endif
1.83      veillard 1061: 
                   1062:     /* free the header */
                   1063:     headerFree(h);
                   1064:     headerFree(s);
                   1065: 
1.86      veillard 1066: #if defined(WITH_GPG)
                   1067:     if (sigtarget) {
                   1068:         unlink(sigtarget);
                   1069:         debugFree(sigtarget);
                   1070:     }
                   1071: #endif
                   1072: 
1.32      veillard 1073:     return(cur);
1.6       veillard 1074: }
                   1075: 
                   1076: /*
1.22      veillard 1077:  * Scan one directory for RPM files this is where the recursive handling
                   1078:  * is done.
1.6       veillard 1079:  */
1.35      veillard 1080: static rpmDataPtr rpmOneDirScan(rpmDirPtr dir, rpmSubdirPtr tree) {
                   1081:     rpmSubdirPtr subtree;
1.32      veillard 1082:     rpmDataPtr ret = NULL, cur;
1.7       veillard 1083:     char *filename;
1.22      veillard 1084:     static char path[2000];
1.23      veillard 1085:     struct stat buf;
1.7       veillard 1086:     int len;
1.39      veillard 1087:     DIR *d;
                   1088:     struct dirent *file;
1.6       veillard 1089: 
1.24      veillard 1090: 
                   1091:     /*
                   1092:      * Create the directory for the HTML pages
                   1093:      */
1.56      daniel   1094:     if ((rpm2html_dump_html) && (dir->html)) {
1.45      veillard 1095:        if (tree->htmlpath[0] != '\0')
1.66      daniel   1096:            snprintf(path, sizeof(path), "%s/%s", dir->dir, tree->htmlpath);
1.45      veillard 1097:        else
1.66      daniel   1098:            snprintf(path, sizeof(path), "%s", dir->dir);
1.45      veillard 1099:        createDirectory(path);
                   1100:     }
1.43      veillard 1101: 
                   1102:     /*
                   1103:      * Create the directory for the RDF pages
                   1104:     if (rpm2html_rdf_dir != NULL) {
                   1105:        if (tree->htmlpath[0] != '\0')
1.66      daniel   1106:            snprintf(path, sizeof(path), "%s/%s", rpm2html_rdf_dir, tree->htmlpath);
1.43      veillard 1107:        else
1.66      daniel   1108:            snprintf(path, sizeof(path), "%s", rpm2html_rdf_dir);
1.43      veillard 1109:         createDirectory(path);
                   1110:     }
1.47      veillard 1111:      */
1.24      veillard 1112: 
                   1113:     /*
                   1114:      * Scan the repository.
                   1115:      */
1.35      veillard 1116:     if (tree->rpmpath[0] != '\0')
1.66      daniel   1117:        snprintf(path, sizeof(path), "%s/%s", dir->rpmdir, tree->rpmpath);
1.24      veillard 1118:     else
1.66      daniel   1119:        snprintf(path, sizeof(path), "%s", dir->rpmdir);
1.51      veillard 1120:     if (rpm2htmlVerbose > 1)
1.66      daniel   1121:         printf("Scanning directory %s\n", path);
1.24      veillard 1122: 
1.39      veillard 1123:     d = opendir(path);
                   1124:     if (d == NULL) {
1.24      veillard 1125:         fprintf(stderr, "Listing of %s failed: %s\n", path,
1.6       veillard 1126:                strerror(errno));
1.35      veillard 1127:         rpmRemoveSubdir(tree);
1.36      veillard 1128:         rpmFreeSubdir(tree);
1.32      veillard 1129:        return(NULL);
1.6       veillard 1130:     } else {
1.39      veillard 1131:         while ((file = readdir(d)) != NULL) {
1.32      veillard 1132:            cur = NULL;
1.39      veillard 1133:            filename = file->d_name;
1.7       veillard 1134:            len = strlen(filename);
1.24      veillard 1135: 
                   1136:            /*
                   1137:             * Compute the full path
                   1138:             */
1.35      veillard 1139:            if (tree->rpmpath[0] != '\0')
1.66      daniel   1140:                snprintf(path, sizeof(path), "%s/%s/%s", dir->rpmdir, tree->rpmpath,
1.35      veillard 1141:                        filename);
1.22      veillard 1142:            else
1.66      daniel   1143:                snprintf(path, sizeof(path), "%s/%s", dir->rpmdir, filename);
1.22      veillard 1144: 
                   1145:            /*
1.25      veillard 1146:             * Stat() the file to detect directory and symlimks
                   1147:             */
1.30      veillard 1148:            if (lstat(path, &buf) != 0) {
1.25      veillard 1149:                fprintf(stderr, "Couldn't stat(%s)\n", path);
                   1150:                continue;
                   1151:            }
1.35      veillard 1152: 
1.25      veillard 1153:            /*
1.23      veillard 1154:             * Check for RPM files by looking at the suffix
1.54      veillard 1155:             * Note that SuSE source RPMs have a ".spm" suffix
1.63      daniel   1156:             * We may or may not follow symlinks to RPM files
1.22      veillard 1157:             */
1.63      daniel   1158:            if (((len >= 5) &&
1.54      veillard 1159:                       (!strcasecmp(&filename[len - 4], ".rpm"))) ||
                   1160:                     ((len >= 5) &&
                   1161:                       (!strcasecmp(&filename[len - 4], ".spm")))) {
1.63      daniel   1162:  
1.65      daniel   1163:                if ((S_ISLNK(buf.st_mode)) && (dir->rpm_symlinks == 0)) {
1.66      daniel   1164:                    if (rpm2htmlVerbose > 1)
1.63      daniel   1165:                        fprintf(stderr, "Dropping symlink %s\n", path);
                   1166:                    continue;
                   1167:                }
1.35      veillard 1168:                cur = rpmOpen(filename, dir, tree);
1.63      daniel   1169:            }
                   1170: 
                   1171:            /*
                   1172:             * Don't follow of analyze symlinks,
                   1173:             */
1.65      daniel   1174:             else if ((S_ISLNK(buf.st_mode)) && (dir->follow_symlinks == 0)) {
1.66      daniel   1175:                if (rpm2htmlVerbose > 1)
1.63      daniel   1176:                    fprintf(stderr, "Dropping symlink %s\n", path);
                   1177:                continue;
1.44      veillard 1178:            }
                   1179: 
                   1180:            /*
                   1181:             * Check for RDF files by looking at the suffix
                   1182:             */
                   1183:            else if ((len >= 5) && (!strcasecmp(&filename[len - 4], ".rdf"))) {
                   1184:                cur = rpmOpenRdf(filename, dir, tree);
1.22      veillard 1185:            }
1.35      veillard 1186: 
1.22      veillard 1187:            /*
1.23      veillard 1188:             * Else if this is a directory, recurse !
1.22      veillard 1189:             */
1.25      veillard 1190:            else if (S_ISDIR(buf.st_mode)) {
                   1191:                if (filename[0] != '.') {
1.57      daniel   1192:                    subtree = rpmNewSubdir(tree, filename, NULL, NULL, NULL, 0);
1.35      veillard 1193:                    cur = rpmOneDirScan(dir, subtree);
1.25      veillard 1194:                }
1.22      veillard 1195:            }
1.32      veillard 1196:            if (cur != NULL) ret = rpmAddList(ret, cur);
1.7       veillard 1197:        }
1.6       veillard 1198:     }
1.39      veillard 1199:     closedir(d);
1.33      veillard 1200: 
                   1201:     /*
                   1202:      * Dump the pages related to this directory.
                   1203:      */
1.35      veillard 1204:     if (ret != NULL) ret = dumpDirIndex(dir, tree, ret);
1.36      veillard 1205:     else {
                   1206:         rpmRemoveSubdir(tree);
                   1207:        rpmFreeSubdir(tree);
                   1208:     }
1.35      veillard 1209: 
1.32      veillard 1210:     return(ret);
1.22      veillard 1211: }
                   1212: 
                   1213: /*
                   1214:  * Scan a directory for RPM files.
                   1215:  */
1.35      veillard 1216: static rpmDataPtr rpmDirScan(rpmDirPtr dir, rpmSubdirPtr tree) {
1.37      veillard 1217:     rpmSubdirPtr cur;
                   1218:     rpmDataPtr ret;
                   1219:     
1.56      daniel   1220:     if ((rpm2html_dump_html) && (dir->html) && (dir->build_tree != 0)) {
1.37      veillard 1221:        dir->root = rpmCreateRealRoot();
                   1222:     }
                   1223:     cur = rpmNewSubdir(tree, dir->name,
1.57      daniel   1224:               dir->subdir == NULL ? "" : dir->subdir, "", dir->color,
                   1225:              dir->html);
1.37      veillard 1226:     ret = rpmOneDirScan(dir, cur);
1.38      veillard 1227:     rpmDumpHtmlRealRoot(dir);
1.37      veillard 1228:     return(ret);
1.6       veillard 1229: }
                   1230: 
                   1231: /*
1.11      veillard 1232:  * Scan the local RPM database for RPM files.
                   1233:  */
1.32      veillard 1234: static rpmDataPtr rpmBaseScan(rpmDirPtr dir) {
1.37      veillard 1235:     static char path[2000];
1.32      veillard 1236:     rpmDataPtr ret = NULL, cur;
1.11      veillard 1237:     rpmdb db;
                   1238:     Header h = NULL;
1.72      daniel   1239: #ifndef        USE_RPMIO
1.32      veillard 1240:     int offset;
1.71      daniel   1241: #endif
1.11      veillard 1242:     char *prefix = "/";
1.88    ! veillard 1243: 
        !          1244: #ifdef WITH_SQL
        !          1245:     dir->no = sql_get_distrib_by_directory(dir->rpmdir);
        !          1246: #endif
1.11      veillard 1247: 
1.37      veillard 1248:     /*
                   1249:      * Create the directory for the HTML pages
                   1250:      */
1.56      daniel   1251:     if ((rpm2html_dump_html) && (dir->html)) {
1.45      veillard 1252:        if (dir->subdir)
1.66      daniel   1253:            snprintf(path, sizeof(path), "%s/%s", dir->dir, dir->subdir);
1.45      veillard 1254:        else
1.66      daniel   1255:            snprintf(path, sizeof(path), "%s", dir->dir);
1.45      veillard 1256:        createDirectory(path);
                   1257:     }
                   1258: 
                   1259:     /*
                   1260:      * Create the directory for the RDF pages
                   1261:      */
                   1262:     if (rpm2html_rdf_dir != NULL) {
                   1263:        if (dir->subdir)
1.66      daniel   1264:            snprintf(path, sizeof(path), "%s/%s", rpm2html_rdf_dir, dir->subdir);
1.45      veillard 1265:        else
1.66      daniel   1266:            snprintf(path, sizeof(path), "%s", rpm2html_rdf_dir);
1.45      veillard 1267:         createDirectory(path);
                   1268:     }
1.37      veillard 1269: 
1.66      daniel   1270:     if (rpm2htmlVerbose)
                   1271:         printf("Scanning the database of installed RPMs\n");
1.70      daniel   1272: 
                   1273:     if (dir->dbpath != NULL)
                   1274:        addMacro(NULL, "_dbpath", NULL, dir->dbpath, -7); /* Added by A.Gibert */
1.66      daniel   1275: 
1.11      veillard 1276:     if (rpmdbOpen(prefix, &db, O_RDONLY, 0644)) {
1.32      veillard 1277:         return(NULL);
1.11      veillard 1278:     }
1.71      daniel   1279: 
1.72      daniel   1280: #ifdef USE_RPMIO
1.71      daniel   1281:     {  rpmdbMatchIterator mi;
                   1282:        mi = rpmdbInitIterator(db, RPMDBI_PACKAGES, NULL, 0);
                   1283:        while ((h = rpmdbNextIterator(mi)) != NULL) {
1.86      veillard 1284:            cur = rpmAnalyze(NULL, NULL, NULL, h, NULL, dir, NULL, 0, 0);
1.71      daniel   1285:            if (cur != NULL) ret = rpmAddList(ret, cur);
                   1286:        }
                   1287:        rpmdbFreeIterator(mi);
                   1288:     }
1.72      daniel   1289: #else  /* USE_RPMIO */
1.11      veillard 1290:     offset = rpmdbFirstRecNum(db);
                   1291:     while (offset) {
                   1292:         h = rpmdbGetRecord(db, offset);
                   1293:        if (!h) {
                   1294:            fprintf(stderr, "could not read database record!\n");
1.32      veillard 1295:            return(ret);
1.11      veillard 1296:        }
1.86      veillard 1297:        cur = rpmAnalyze(NULL, NULL, NULL, h, NULL, dir, NULL, 0, 0);
1.32      veillard 1298:        if (cur != NULL) ret = rpmAddList(ret, cur);
1.11      veillard 1299:        headerFree(h);
                   1300:        offset = rpmdbNextRecNum(db, offset);
                   1301:     }
1.72      daniel   1302: #endif /* USE_RPMIO */
1.71      daniel   1303: 
1.11      veillard 1304:     rpmdbClose(db);
                   1305: 
1.32      veillard 1306:     return(ret);
1.80      veillard 1307: }
                   1308: 
                   1309: 
                   1310: /*
                   1311:  * Scan one distribution only
                   1312:  */
                   1313: 
                   1314: void rpmDirScanOneDist(const char *dist) {
                   1315:     rpmDirPtr dir;
                   1316:     rpmDataPtr cur;
                   1317: 
                   1318:     /*
                   1319:      * first try to find the distrib
                   1320:      */
                   1321:     dir = dirList;
                   1322:     while (dir != NULL) {
                   1323:        if (!strcasecmp(dir->name, dist))
                   1324:            break;
                   1325:        if (!strcasecmp(dir->subdir, dist))
                   1326:            break;
                   1327:        if (!strcasecmp(dir->rpmdir, dist))
                   1328:            break;
                   1329:        dir = dir->next;
                   1330:     }
                   1331:     if (dir == NULL) {
                   1332:        dir = dirList;
                   1333:        while (dir != NULL) {
                   1334:            if (!strstr(dir->name, dist))
                   1335:                break;
                   1336:            if (!strstr(dir->subdir, dist))
                   1337:                break;
                   1338:            if (!strstr(dir->rpmdir, dist))
                   1339:                break;
                   1340:            dir = dir->next;
                   1341:        }
                   1342:     }
                   1343:     if (dir == NULL) {
                   1344:        fprintf(stderr, "rpmDirScanOneDist(%s): distribution not found\n",
                   1345:                dist);
                   1346:        return;
                   1347:     }
                   1348:     if (rpm2htmlVerbose)
                   1349:        printf("indexing %s\n", dir->name);
                   1350: 
                   1351:     /*
                   1352:      * Allocate a directory tree.
                   1353:      */
                   1354:     dirTree = rpmNewSubdir(NULL, "", "", "", NULL, 1);
                   1355: 
                   1356:     cur  = NULL;
                   1357: 
                   1358:     /*
                   1359:      * Override default setting.
                   1360:      */
                   1361:     if ((dir->maint == NULL) && (rpm2html_maint != NULL))
                   1362:        dir->maint = debugStrdup(rpm2html_maint);
                   1363:     if ((dir->mail == NULL) && (rpm2html_mail != NULL))
                   1364:        dir->mail = debugStrdup(rpm2html_mail);
                   1365:     if ((dir->ftp == NULL) && (rpm2html_ftp != NULL))
                   1366:        dir->ftp = debugStrdup(rpm2html_ftp);
                   1367:     if ((dir->ftpsrc == NULL) && (rpm2html_ftpsrc != NULL))
                   1368:        dir->ftpsrc = debugStrdup(rpm2html_ftpsrc);
                   1369:     if ((dir->dir == NULL) && (rpm2html_dir != NULL))
                   1370:        dir->dir = debugStrdup(rpm2html_dir);
                   1371:     if ((dir->host == NULL) && (rpm2html_host != NULL))
                   1372:        dir->host = debugStrdup(rpm2html_host);
                   1373:     if ((dir->name == NULL) && (rpm2html_name != NULL))
                   1374:        dir->name = debugStrdup(rpm2html_name);
                   1375:     if ((dir->url == NULL) && (rpm2html_url != NULL))
                   1376:        dir->url = debugStrdup(rpm2html_url);
                   1377: 
                   1378:     if (dir->rpmdir == NULL) {
                   1379:        fprintf(stderr, "?!? rpmDir without directory ?!? disabled !\n");
                   1380:     } else if (!strncmp(dir->rpmdir, "localbase", 9)) {
                   1381:        /* Scan the local RPM database instead of a directory */
                   1382:        cur = rpmBaseScan(dir);
                   1383:     } else if (dir->ftp == NULL) {
                   1384:        fprintf(stderr, "Directory %s disabled : no ftp field\n",
                   1385:                dir->rpmdir);
                   1386:     } else {
1.82      veillard 1387: #ifdef WITH_SQL
1.80      veillard 1388:        dir->no = sql_get_distrib_by_directory(dir->rpmdir);
1.82      veillard 1389: #endif
1.80      veillard 1390:        if (rpm2htmlVerbose)
                   1391:            printf("Scanning directory %s for RPMs\n",dir->rpmdir);
                   1392:        cur = rpmDirScan(dir, dirTree);
                   1393:     }
                   1394: 
                   1395:     if (dir->root != NULL) {
                   1396:        rpmDestroyRealRoot(dir->root);
                   1397:        dir->root = NULL;
                   1398:     }
1.11      veillard 1399: }
                   1400: 
                   1401: /*
1.6       veillard 1402:  * Scan all registered directories.
                   1403:  * One fist check for completeness of the informations in
                   1404:  * the rpmDir structure.
                   1405:  */
                   1406: 
1.32      veillard 1407: rpmDataPtr rpmDirScanAll(void) {
1.18      veillard 1408:     rpmDirPtr dir, next;
1.32      veillard 1409:     rpmDataPtr ret = NULL, cur;
1.46      veillard 1410:     int maxLists = 50;
                   1411:     rpmDataPtr *rpmLists;
1.35      veillard 1412:     int nbLists = 0;
                   1413:     int i;
1.18      veillard 1414: 
                   1415:     /*
                   1416:      * first reverse the list ....
                   1417:      */
                   1418:     dir = dirList;
                   1419:     dirList = NULL;
                   1420:     while (dir != NULL) {
                   1421:         next = dir->next;
                   1422:        dir->next = dirList;
                   1423:        dirList = dir;
                   1424:        dir = next;
                   1425:     }
1.57      daniel   1426:     dir = dirList;
1.18      veillard 1427: 
1.35      veillard 1428:     /*
                   1429:      * Allocate a directory tree.
                   1430:      */
1.57      daniel   1431:     dirTree = rpmNewSubdir(NULL, "", "", "", NULL, 1);
1.6       veillard 1432: 
1.61      daniel   1433:     rpmLists = (rpmDataPtr *) debugMalloc(maxLists * sizeof(rpmDataPtr));
1.46      veillard 1434:     if (rpmLists == NULL) {
                   1435:         fprintf(stderr, "rpmDirScanAll : running out of memory !\n");
                   1436:        exit(1);
                   1437:     }
                   1438: 
1.6       veillard 1439:     while (dir != NULL) {
1.32      veillard 1440:         cur  = NULL;
                   1441: 
1.14      veillard 1442:        /*
                   1443:         * Override default setting.
                   1444:         */
1.15      veillard 1445:        if ((dir->maint == NULL) && (rpm2html_maint != NULL))
1.61      daniel   1446:            dir->maint = debugStrdup(rpm2html_maint);
1.15      veillard 1447:        if ((dir->mail == NULL) && (rpm2html_mail != NULL))
1.61      daniel   1448:            dir->mail = debugStrdup(rpm2html_mail);
1.15      veillard 1449:        if ((dir->ftp == NULL) && (rpm2html_ftp != NULL))
1.61      daniel   1450:            dir->ftp = debugStrdup(rpm2html_ftp);
1.15      veillard 1451:        if ((dir->ftpsrc == NULL) && (rpm2html_ftpsrc != NULL))
1.61      daniel   1452:            dir->ftpsrc = debugStrdup(rpm2html_ftpsrc);
1.15      veillard 1453:        if ((dir->dir == NULL) && (rpm2html_dir != NULL))
1.61      daniel   1454:            dir->dir = debugStrdup(rpm2html_dir);
1.15      veillard 1455:        if ((dir->host == NULL) && (rpm2html_host != NULL))
1.61      daniel   1456:            dir->host = debugStrdup(rpm2html_host);
1.15      veillard 1457:        if ((dir->name == NULL) && (rpm2html_name != NULL))
1.61      daniel   1458:            dir->name = debugStrdup(rpm2html_name);
1.15      veillard 1459:        if ((dir->url == NULL) && (rpm2html_url != NULL))
1.61      daniel   1460:            dir->url = debugStrdup(rpm2html_url);
1.14      veillard 1461: 
                   1462:         if (dir->rpmdir == NULL) {
1.6       veillard 1463:            fprintf(stderr, "?!? rpmDir without directory ?!? disabled !\n");
1.67      daniel   1464:        } else if (!strncmp(dir->rpmdir, "localbase", 9)) {   /* Added by A. Gibert */
1.11      veillard 1465:            /* Scan the local RPM database instead of a directory */
1.32      veillard 1466:             cur = rpmBaseScan(dir);
1.7       veillard 1467:        } else if (dir->ftp == NULL) {
                   1468:            fprintf(stderr, "Directory %s disabled : no ftp field\n",
1.14      veillard 1469:                    dir->rpmdir);
1.6       veillard 1470:        } else {
1.82      veillard 1471: #ifdef WITH_SQL
1.79      veillard 1472:            dir->no = sql_get_distrib_by_directory(dir->rpmdir);
1.82      veillard 1473: #endif
1.51      veillard 1474:            if (rpm2htmlVerbose)
1.66      daniel   1475:                printf("Scanning directory %s for RPMs\n",dir->rpmdir);
1.35      veillard 1476:            cur = rpmDirScan(dir, dirTree);
1.6       veillard 1477:        }
                   1478: 
1.35      veillard 1479:        if (cur != NULL) {
1.46      veillard 1480:            if (nbLists >= maxLists) {
                   1481:                maxLists *= 2;
1.61      daniel   1482:                rpmLists = (rpmDataPtr *) debugRealloc(rpmLists,
1.46      veillard 1483:                                             maxLists * sizeof(rpmDataPtr));
                   1484:                if (rpmLists == NULL) {
                   1485:                    fprintf(stderr, "rpmDirScanAll : running out of memory!\n");
                   1486:                    exit(1);
1.35      veillard 1487:                }
                   1488:            }
1.46      veillard 1489:            rpmLists[nbLists] = cur;
                   1490:            nbLists++;
1.39      veillard 1491:        }
                   1492:        if (dir->root != NULL) {
1.48      veillard 1493:            /************************************************
1.39      veillard 1494:            if (rpm2html_build_tree)
                   1495:                treeRoot = rpmMergeRealRoots(treeRoot, dir->root);
                   1496:             else
1.48      veillard 1497:             ************************************************/
                   1498:            rpmDestroyRealRoot(dir->root);
                   1499:            dir->root = NULL;
1.35      veillard 1500:        }
1.32      veillard 1501: 
1.6       veillard 1502:         dir = dir->next;
                   1503:     }
1.35      veillard 1504:     for (i = 0;i < nbLists;i++)
                   1505:        ret = rpmAddList(ret, rpmLists[i]);
1.61      daniel   1506:     debugFree(rpmLists);
1.32      veillard 1507:     return(ret);
1.60      daniel   1508: }
                   1509: 
                   1510: /*
                   1511:  * Cleanup the global variables from this module
                   1512:  */
                   1513: void rpmopenCleanup(void) {
                   1514:     if (buffer != NULL)
1.61      daniel   1515:         debugFree(buffer);
1.60      daniel   1516:     buffer = NULL;
                   1517:     buffer_size = 50 * 1024 * sizeof(char);
1.1       veillard 1518: }
                   1519: 

Webmaster