Annotation of rpm2html/rpmopen.c, revision 1.97

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.97    ! daniel      6:  * $Id: rpmopen.c,v 1.96 2001/02/07 09:04:42 daniel 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.93      veillard   74:     if (extra->packager != NULL) xmlFree(extra->packager);
                     75:     if (extra->description != NULL) xmlFree(extra->description);
                     76:     if (extra->copyright != NULL) xmlFree(extra->copyright);
                     77:     if (extra->changelog != NULL) xmlFree(extra->changelog);
                     78:     if (extra->srcrpm != NULL) xmlFree(extra->srcrpm);
                     79:     if (extra->host != NULL) xmlFree(extra->host);
                     80:     if (extra->resources != NULL) xmlFree(extra->resources);
                     81:     if (extra->requires != NULL) xmlFree(extra->requires);
                     82:     if (extra->filelist != NULL) xmlFree(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)
1.93      veillard   87:                     xmlFree(extra->sigs[n1]->sig);
1.86      veillard   88: #if defined(WITH_GPG)
                     89:                 if (extra->sigs[n1]->resolve != NULL)
1.93      veillard   90:                     xmlFree(extra->sigs[n1]->resolve);
1.86      veillard   91: #endif
1.93      veillard   92:                xmlFree(extra->sigs[n1]);
1.86      veillard   93:             }
1.93      veillard   94:         xmlFree(extra->sigs);
1.83      veillard   95:     }
1.93      veillard   96:     xmlFree(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");
1.93      veillard  231:     rpm->extra->sigs[sign]->resolve = xmlMalloc(sizeof(char) * rsize);
1.86      veillard  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;
1.93      veillard  237:             rpm->extra->sigs[sign]->resolve = xmlRealloc(rpm->extra->sigs[sign]->resolve,
1.86      veillard  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 */
1.93      veillard  281:         sigfile = xmlMalloc(30);
1.86      veillard  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);
1.93      veillard  303:             xmlFree(sigfile);
1.86      veillard  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.93      veillard  336:         buffer = (char *) xmlMalloc(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.93      veillard  392:     rpm = (rpmDataPtr) xmlMalloc(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.93      veillard  399:     rpm->extra = (rpmExtraDataPtr) xmlMalloc(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.93      veillard  424:         rpm->summary = xmlStrdup(localizedStrings[LANG_NO_SUMMARY]);
1.2       veillard  425:     } else {
1.93      veillard  426:        rpm->summary = xmlStrdup((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.93      veillard  431:         rpm->extra->description = xmlStrdup(localizedStrings[LANG_NO_DESCRIPTION]);
1.2       veillard  432:     } else {
1.93      veillard  433:        rpm->extra->description = xmlStrdup((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)
1.93      veillard  524:            xmlFree(rpm->summary);
1.74      daniel    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.93      veillard  535:        xmlFree(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.93      veillard  540:         rpm->extra->host = xmlStrdup(localizedStrings[LANG_NO_HOST]);
1.2       veillard  541:     } else {
1.93      veillard  542:        rpm->extra->host = xmlStrdup((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.93      veillard  568:         rpm->extra->srcrpm = xmlStrdup("");
1.2       veillard  569:     } else {
1.93      veillard  570:        rpm->extra->srcrpm = xmlStrdup((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.93      veillard  577:        rpm->url = xmlStrdup((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.93      veillard  584:        rpm->extra->packager = xmlStrdup((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.93      veillard  591:        rpm->extra->copyright = xmlStrdup((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.93      veillard  615:            buffer = (char *) xmlRealloc(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.93      veillard  640:       rpm->extra->changelog = xmlStrdup(buffer);
1.31      veillard  641:     }
1.62      daniel    642:     ENTRY_CLEANUP(p);
1.7       veillard  643:     if (rpm->vendor == NULL) {
1.93      veillard  644:         if (rpm->extra->packager != NULL) rpm->vendor = xmlStrdup(rpm->extra->packager);
                    645:        else rpm->vendor = xmlStrdup(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;
1.93      veillard  654:       rpm->extra->sigs = (rpmSigPtr *) xmlMalloc(sizeof(rpmSigPtr) *
1.83      veillard  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;
1.93      veillard  667:          rpm->extra->sigs = (rpmSigPtr *) xmlRealloc(rpm->extra->sigs,
1.83      veillard  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: 
1.93      veillard  676:        rpm->extra->sigs[rpm->extra->nb_sigs] = (rpmSigPtr) xmlMalloc(sizeof(rpmSig));
1.83      veillard  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.93      veillard  680:         rpm->extra->sigs[rpm->extra->nb_sigs]->sig = xmlMalloc(count);
1.86      veillard  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.93      veillard  690:     rpm->filename = xmlStrdup(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.93      veillard  697:        rpm->extra->resources = (rpmRessPtr *) xmlMalloc(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.93      veillard  706:        rpm->extra->resources = (rpmRessPtr *) xmlMalloc(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.92      veillard  717:            if (!strcmp(((char **) p)[i],name)) continue;
1.58      daniel    718:            rpm->extra->resources[j++] = rpmRessAdd(((char **) p)[i], rpm, installed);
1.4       veillard  719:        }
1.58      daniel    720:        rpm->extra->nb_resources = j;
1.4       veillard  721:     }
1.62      daniel    722:     ENTRY_CLEANUP(p);
1.4       veillard  723: 
                    724:     val = getTagNumber("RPMTAG_REQUIRENAME");
                    725:     if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
1.73      daniel    726:        rpm->extra->nb_requires = 0;
1.58      daniel    727:        rpm->extra->requires = NULL;
1.4       veillard  728:     } else {
1.73      daniel    729:        int_32 count2, count3, type2, type3;
                    730:        void * q = NULL;
                    731:        void * r = NULL;
                    732:        int valv, valf;
1.4       veillard  733: 
1.70      daniel    734:        rpm->extra->max_requires = count;
1.93      veillard  735:        rpm->extra->requires = (rpmRessPtr *) xmlMalloc(sizeof(rpmRessPtr) *
1.70      daniel    736:                                                   rpm->extra->max_requires);
                    737:        if (rpm->extra->requires == NULL) {
                    738:            fprintf(stderr, ": ran out of memory\n");
                    739:            exit(1);
                    740:        }
1.73      daniel    741:        valv = getTagNumber("RPMTAG_REQUIREVERSION");
                    742:        valf = getTagNumber("RPMTAG_REQUIREFLAGS");
                    743:        headerGetEntry(h, valv, &type2, &q, &count2);
                    744:        headerGetEntry(h, valf, &type3, &r, &count3);
1.70      daniel    745: 
                    746:        rpm->extra->nb_requires = 0;
                    747: 
1.73      daniel    748:         for (i = 0, j = 0; (i < count2) && (i < count3);i++) {
1.70      daniel    749:            long anint = *(((long *)r)+i);
1.77      veillard  750:            rpm_dep_flag flag = RPM2HTML_REQ_NONE;
1.70      daniel    751:      
1.77      veillard  752:            if ((anint & RPMSENSE_LESS) && (anint & RPMSENSE_EQUAL))
                    753:                flag = RPM2HTML_REQ_LEQ;
                    754:            else if (anint & RPMSENSE_LESS)
                    755:                flag = RPM2HTML_REQ_LT;
                    756:            if ((anint & RPMSENSE_GREATER) && (anint & RPMSENSE_EQUAL))
                    757:                flag = RPM2HTML_REQ_GEQ;
                    758:            else if (anint & RPMSENSE_GREATER)
                    759:                flag = RPM2HTML_REQ_GT;
                    760:            else if (anint & RPMSENSE_EQUAL)
                    761:                flag = RPM2HTML_REQ_EQU;
1.53      veillard  762:            if (!checkResourceName(((char **) p)[i])) continue;
1.70      daniel    763:            rpm->extra->requires[j++] = 
                    764:                rpmRequAdd(((char **) p)[i],((char **) q)[i],
1.77      veillard  765:                           flag , rpm, installed);
1.1       veillard  766:        }
1.58      daniel    767:        rpm->extra->nb_requires = j;
1.73      daniel    768:        if ((type2 == RPM_STRING_ARRAY_TYPE || type2 == RPM_I18NSTRING_TYPE)&&
                    769:            (q != NULL)) { free((q)); q = NULL; }
                    770:        if ((type3 == RPM_STRING_ARRAY_TYPE || type3 == RPM_I18NSTRING_TYPE)&&
                    771:            (r != NULL)) { free((r)); r = NULL; }
                    772:        for (;i < count;i++)
1.77      veillard  773:            rpmRequAdd(((char **) p)[i], NULL, RPM2HTML_REQ_NONE,
                    774:                       rpm, installed);
1.5       veillard  775:     }
1.62      daniel    776:     ENTRY_CLEANUP(p);
1.69      daniel    777: 
                    778: #if defined(RPMTAG_FILENAMES)
1.5       veillard  779:     val = getTagNumber("RPMTAG_FILENAMES");
1.69      daniel    780:     headerGetEntry(h, val, &type, &p, &count);
                    781: #else
                    782:     rpmBuildFileList(h, (const char ***) &p, &count);
                    783: #endif
                    784: 
                    785:     if (count == 0) {
1.58      daniel    786:         rpm->extra->filelist = NULL; /* No filelist in the package ! */
1.5       veillard  787:     } else {
                    788:         char *ptr = buffer;
1.42      veillard  789: 
1.5       veillard  790:        for (i = 0; i < count;i++) {
1.42      veillard  791:            if ((ptr - buffer) > (buffer_size - 1024)) {
                    792:                int delta = ptr - buffer;
                    793: 
1.41      veillard  794:                buffer_size *= 2;
1.93      veillard  795:                buffer = (char *) xmlRealloc(buffer, buffer_size);
1.42      veillard  796:                if (buffer == NULL) {
                    797:                    fprintf(stderr, "cannot re-allocate %d bytes: %s\n",
                    798:                            buffer_size, strerror(errno));
                    799:                    exit(1);
                    800:                }
                    801:                ptr = &buffer[delta];
1.41      veillard  802:            }
1.66      daniel    803:            ptr += snprintf(ptr, buffer_size, "%s\n", ((char **) p)[i]);
1.5       veillard  804:        }
1.93      veillard  805:        rpm->extra->filelist = xmlStrdup(buffer);
1.1       veillard  806:     }
1.62      daniel    807:     ENTRY_CLEANUP(p);
1.1       veillard  808: 
1.86      veillard  809:     #ifdef WITH_GPG
                    810:     rpmResolveSignatures(path, nameRpm, sigtarget, rpm);
                    811:     #endif WITH_GPG
                    812: 
1.75      veillard  813: #ifdef WITH_SQL
                    814:     id = sql_add_package(path, rpm->name, rpm->version, rpm->release,
                    815:                         rpm->arch, dir->no, rpm->url, rpm->extra->srcrpm,
                    816:                         dir->vendor, rpm->extra->packager,
                    817:                         rpm->group, rpm->summary, rpm->extra->description,
1.90      veillard  818:                         rpm->extra->copyright, rpm->date, rpm->size, rpm->os,
1.91      veillard  819:                         rpm->distribution, rpm->vendor);
1.76      veillard  820:     if (id > 0) {
                    821:        for (i = 0;i < rpm->extra->nb_resources;i++)
                    822:            sql_add_provides(id, rpm->extra->resources[i]->name);
                    823:        for (i = 0;i < rpm->extra->nb_requires;i++)
                    824:            sql_add_requires(id, rpm->extra->requires[i]->name,
1.77      veillard  825:                             rpm->extra->requires[i]->flag,
1.76      veillard  826:                             rpm->extra->requires[i]->version);
                    827:     }
1.75      veillard  828: #endif
                    829: 
1.37      veillard  830:     /* Add the package files to the real filesystem tree if asked for */
1.75      veillard  831: #ifdef WITH_SQL
                    832:     if ((rpm->extra->filelist != NULL) &&
                    833:        ((dir->build_tree != 0) || (id > 0))) {
                    834: #else
1.58      daniel    835:     if ((dir->build_tree != 0) && (rpm->extra->filelist != NULL)) {
1.75      veillard  836: #endif
1.37      veillard  837:         char *cur, *filename;
                    838:        
1.58      daniel    839:        cur = rpm->extra->filelist;
1.37      veillard  840:        while ((*cur != '\0') && (*cur != '/')) cur++;
                    841:        filename = cur;
                    842:        while (*cur != '\0') {
                    843:            if ((*cur == '\n') || (*cur == '\r')) {
1.75      veillard  844:                if (cur != filename) {
                    845: #ifdef WITH_SQL
                    846:                    if (dir->build_tree != 0)
                    847:                        rpmAddRealFile(dir->root, filename, rpm);
                    848:                    if (id > 0) {
                    849:                        *cur = 0;
                    850:                        sql_add_file(filename,id);
                    851:                        *cur = '\n';
                    852:                    }
                    853: #else
1.37      veillard  854:                    rpmAddRealFile(dir->root, filename, rpm);
1.75      veillard  855: #endif
                    856:                }
1.37      veillard  857:                while ((*cur != '\0') && (*cur != '/')) cur++;
                    858:                 filename = cur;
                    859:            } else
                    860:                cur++;
                    861:        }
                    862:        if (cur != filename)
                    863:            rpmAddRealFile(dir->root, filename, rpm);
                    864:     }
1.17      veillard  865: 
                    866:     /* Register this package */
                    867:     rpmAddSoftware(rpm);
1.7       veillard  868: 
                    869:     /* dump the HTML related to this package */
1.56      daniel    870:     if ((rpm2html_dump_html) && (dir->html))
1.40      httpng    871:        dumpRpmHtml(rpm, tree);
                    872:     if (rpm2html_dump_rdf)
                    873:        dumpRpmRdf(rpm, tree);
1.7       veillard  874: 
1.58      daniel    875:     /* free the extra data */
                    876:     rpmFreeExtraData(rpm);
1.8       veillard  877: 
                    878:     /* increment the counters */
1.11      veillard  879:     if (installed) {
                    880:        rpm2html_install_files++;
1.21      veillard  881:        rpm2html_install_size += rpm->size / 1024;
1.11      veillard  882:     } else {
                    883:        rpm2html_files++;
1.21      veillard  884:        rpm2html_size += rpm->size / 1024;
1.11      veillard  885:     }
1.7       veillard  886: 
1.32      veillard  887:     return(rpm);
1.11      veillard  888: }
                    889: 
                    890: /*
                    891:  * rpmOpen : open an RPM file, read and parse the header and 
                    892:  *           fill the informations in the database.
                    893:  */
1.35      veillard  894: rpmDataPtr rpmOpen(char *nameRpm, rpmDirPtr dir, rpmSubdirPtr tree) {
1.32      veillard  895:     rpmDataPtr cur;
1.64      daniel    896: #if defined(HAVE_RPM_RPMIO_H)
                    897:     FD_t fd;
                    898: #else
1.11      veillard  899:     int fd;
1.64      daniel    900: #define        fdOpen(_a, _b, _c)      open((_a), (_b))
                    901: #define        fdClose(_a)             close(_a)
                    902: #endif
1.11      veillard  903:     int rc;
                    904:     Header h = NULL;
1.83      veillard  905:     Header s = NULL;
                    906:     struct rpmlead lead;
1.11      veillard  907:     int isSource;
                    908:     char buffer[500];
1.20      veillard  909:     struct stat buf;
1.86      veillard  910: #if defined(WITH_GPG)
                    911:     FD_t ofd = NULL;
                    912:     char *sigtarget = NULL;
                    913:     ssize_t count;
                    914:     unsigned char stbuffer[8192];
                    915: #endif
1.11      veillard  916: 
                    917:     /* open the file for reading */
1.35      veillard  918:     if (tree->htmlpath[0] != '\0')
1.66      daniel    919:        snprintf(buffer, sizeof(buffer), "%s/%s/%s", dir->rpmdir, tree->rpmpath, nameRpm);
1.24      veillard  920:     else
1.66      daniel    921:        snprintf(buffer, sizeof(buffer), "%s/%s", dir->rpmdir, nameRpm);
1.72      daniel    922: 
1.78      daniel    923:     if (access(buffer, R_OK) < 0) {
                    924:          fprintf(stderr, "open of %s failed: %s\n", buffer,
                    925:                 strerror(errno));
                    926:         return(NULL);
                    927:     }
1.72      daniel    928: #if defined(USE_RPMIO)
                    929:     fd = Fopen(buffer, "r.fdio");
                    930:     if (fd == NULL || Ferror(fd)) {
                    931:          fprintf(stderr, "Fopen of %s failed: %s\n", buffer,
                    932:                 Fstrerror(fd));
                    933:         return(NULL);
                    934:     }
                    935: #else
1.64      daniel    936:     if ((fd = fdOpen(buffer, O_RDONLY, 0)) < 0) {
1.11      veillard  937:          fprintf(stderr, "open of %s failed: %s\n", buffer,
                    938:                 strerror(errno));
1.32      veillard  939:         return(NULL);
1.11      veillard  940:     }
1.72      daniel    941: #endif
1.11      veillard  942: 
1.20      veillard  943:     stat(buffer, &buf);
                    944: 
1.11      veillard  945:     /* read the RPM header */
                    946:     rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
                    947:     switch (rc) {
                    948:        case 0:
                    949:            if (!h) {
                    950:                fprintf(stderr,
                    951:                        "old format source packages cannot be queried\n");
1.68      veillard  952:                fdClose(fd);
1.32      veillard  953:                return(NULL);
1.11      veillard  954:            }
                    955:            break;
                    956:        case 1:
                    957:            fprintf(stderr, "%s does not appear to be a RPM package\n",
                    958:                    nameRpm);
1.68      veillard  959:            fdClose(fd);
1.32      veillard  960:            return(NULL);
1.11      veillard  961:        case 2:
                    962:            fprintf(stderr, "query of %s failed\n", nameRpm);
1.68      veillard  963:            fdClose(fd);
1.32      veillard  964:            return(NULL);
1.11      veillard  965:        default:
                    966:            fprintf(stderr, "rpmReadPackageHeader(%s): unknown error %d\n",
                    967:                    nameRpm, rc);
1.68      veillard  968:            fdClose(fd);
1.32      veillard  969:            return(NULL);
1.11      veillard  970:     }
                    971: 
                    972: 
1.83      veillard  973:     /* close the descriptor */
                    974: #if defined(USE_RPMIO)
                    975:     Fclose(fd);
                    976: #else
                    977:     fdClose(fd);
                    978: #endif
                    979: 
                    980:     /* XXX I do not know whether it is necessary to open the file twice */
                    981:     /* open the file for reading */
                    982: #if defined(USE_RPMIO)
                    983:     fd = Fopen(buffer, "r.fdio");
                    984:     if (fd == NULL || Ferror(fd)) {
                    985:          fprintf(stderr, "Fopen of %s failed: %s\n", buffer,
                    986:                 Fstrerror(fd));
                    987:         return(NULL);
                    988:     }
                    989: #else
                    990:     if ((fd = fdOpen(buffer, O_RDONLY, 0)) < 0) {
                    991:          fprintf(stderr, "open of %s failed: %s\n", buffer,
                    992:                 strerror(errno));
                    993:         return(NULL);
                    994:     }
                    995: #endif
                    996: 
                    997:     /* read the RPM signature */
                    998:     if (readLead(fd, &lead)) {
                    999:         fprintf(stderr, "readLead failed\n");
                   1000:         fdClose(fd); 
                   1001:         return(NULL);
                   1002:     }
                   1003:     switch (lead.major) {
                   1004:         case 1:
                   1005:             fprintf(stderr, "no signature available (v1.0 RPM) in %s\n", nameRpm);
                   1006:             break;
                   1007:         default:
                   1008:             if (rpmReadSignature(fd, &s, lead.signature_type)) {
                   1009:                fprintf(stderr, "rpmReadSignature failed\n");
                   1010:                fdClose(fd);
                   1011:                return(NULL);
                   1012:             }
                   1013:             if (!s) {
                   1014:                fprintf(stderr, "no signature available in %s\n", nameRpm);
                   1015:                fdClose(fd);
                   1016:                return(NULL);
                   1017:             }
1.86      veillard 1018: #if defined(WITH_GPG)
                   1019:             /* open temp file for writing */
1.93      veillard 1020:             sigtarget = xmlMalloc(30);
1.86      veillard 1021:             strcpy(sigtarget, "/tmp/rpm2html.date.XXXXXX");
                   1022:             sigtarget = mktemp(sigtarget);
                   1023:             ofd = Fopen(sigtarget, "w.ufdio");
                   1024:             if (ofd == NULL || Ferror(ofd)) {
                   1025:                 fprintf(stderr, "Fopen of %s failed: %s\n", sigtarget,
                   1026:                     Fstrerror(ofd));
1.93      veillard 1027:                 xmlFree(sigtarget);
1.86      veillard 1028:                 sigtarget = NULL;
                   1029:             }
                   1030: 
                   1031:             /* write the header and archive to a temp file */
                   1032:             while ((count = Fread(stbuffer, sizeof(stbuffer[0]), sizeof(stbuffer), fd)) > 0) {
                   1033:                 if (Fwrite(stbuffer, sizeof(stbuffer[0]), count, ofd) < 0) {
                   1034:                     fprintf(stderr, "%s: Fwrite failed: %s\n", sigtarget,
                   1035:                         Fstrerror(ofd));
1.93      veillard 1036:                     xmlFree(sigtarget);
1.86      veillard 1037:                     sigtarget = NULL;
                   1038:                 }
                   1039:             }
                   1040:             if (count < 0) {
                   1041:                 fprintf(stderr, "%s: Fread failed: %s\n", buffer, Fstrerror(fd));
1.93      veillard 1042:                 xmlFree(sigtarget);
1.86      veillard 1043:                 sigtarget = NULL;
                   1044:             }
                   1045: 
                   1046:             Fclose(ofd);
                   1047: #endif
1.83      veillard 1048:             break;
                   1049:     }
                   1050: 
                   1051:     /* close the descriptor */
1.72      daniel   1052: #if defined(USE_RPMIO)
                   1053:     Fclose(fd);
                   1054: #else
1.64      daniel   1055:     fdClose(fd);
1.72      daniel   1056: #endif
1.1       veillard 1057: 
1.86      veillard 1058: #if defined(WITH_GPG)
                   1059:     cur = rpmAnalyze(buffer, nameRpm, sigtarget, h, s, dir, tree, buf.st_mtime, isSource);
                   1060: #else
                   1061:     cur = rpmAnalyze(buffer, nameRpm, NULL, h, s, dir, tree, buf.st_mtime, isSource);
                   1062: #endif
1.83      veillard 1063: 
                   1064:     /* free the header */
                   1065:     headerFree(h);
                   1066:     headerFree(s);
                   1067: 
1.86      veillard 1068: #if defined(WITH_GPG)
                   1069:     if (sigtarget) {
                   1070:         unlink(sigtarget);
1.93      veillard 1071:         xmlFree(sigtarget);
1.86      veillard 1072:     }
                   1073: #endif
                   1074: 
1.32      veillard 1075:     return(cur);
1.6       veillard 1076: }
                   1077: 
                   1078: /*
1.22      veillard 1079:  * Scan one directory for RPM files this is where the recursive handling
                   1080:  * is done.
1.6       veillard 1081:  */
1.35      veillard 1082: static rpmDataPtr rpmOneDirScan(rpmDirPtr dir, rpmSubdirPtr tree) {
                   1083:     rpmSubdirPtr subtree;
1.32      veillard 1084:     rpmDataPtr ret = NULL, cur;
1.7       veillard 1085:     char *filename;
1.22      veillard 1086:     static char path[2000];
1.23      veillard 1087:     struct stat buf;
1.7       veillard 1088:     int len;
1.39      veillard 1089:     DIR *d;
                   1090:     struct dirent *file;
1.6       veillard 1091: 
1.24      veillard 1092: 
                   1093:     /*
                   1094:      * Create the directory for the HTML pages
                   1095:      */
1.56      daniel   1096:     if ((rpm2html_dump_html) && (dir->html)) {
1.45      veillard 1097:        if (tree->htmlpath[0] != '\0')
1.66      daniel   1098:            snprintf(path, sizeof(path), "%s/%s", dir->dir, tree->htmlpath);
1.45      veillard 1099:        else
1.66      daniel   1100:            snprintf(path, sizeof(path), "%s", dir->dir);
1.45      veillard 1101:        createDirectory(path);
                   1102:     }
1.43      veillard 1103: 
                   1104:     /*
                   1105:      * Create the directory for the RDF pages
                   1106:     if (rpm2html_rdf_dir != NULL) {
                   1107:        if (tree->htmlpath[0] != '\0')
1.66      daniel   1108:            snprintf(path, sizeof(path), "%s/%s", rpm2html_rdf_dir, tree->htmlpath);
1.43      veillard 1109:        else
1.66      daniel   1110:            snprintf(path, sizeof(path), "%s", rpm2html_rdf_dir);
1.43      veillard 1111:         createDirectory(path);
                   1112:     }
1.47      veillard 1113:      */
1.24      veillard 1114: 
                   1115:     /*
                   1116:      * Scan the repository.
                   1117:      */
1.35      veillard 1118:     if (tree->rpmpath[0] != '\0')
1.66      daniel   1119:        snprintf(path, sizeof(path), "%s/%s", dir->rpmdir, tree->rpmpath);
1.24      veillard 1120:     else
1.66      daniel   1121:        snprintf(path, sizeof(path), "%s", dir->rpmdir);
1.51      veillard 1122:     if (rpm2htmlVerbose > 1)
1.66      daniel   1123:         printf("Scanning directory %s\n", path);
1.24      veillard 1124: 
1.39      veillard 1125:     d = opendir(path);
                   1126:     if (d == NULL) {
1.24      veillard 1127:         fprintf(stderr, "Listing of %s failed: %s\n", path,
1.6       veillard 1128:                strerror(errno));
1.35      veillard 1129:         rpmRemoveSubdir(tree);
1.36      veillard 1130:         rpmFreeSubdir(tree);
1.94      daniel   1131:        tree = NULL;
1.32      veillard 1132:        return(NULL);
1.6       veillard 1133:     } else {
1.39      veillard 1134:         while ((file = readdir(d)) != NULL) {
1.32      veillard 1135:            cur = NULL;
1.39      veillard 1136:            filename = file->d_name;
1.7       veillard 1137:            len = strlen(filename);
1.24      veillard 1138: 
                   1139:            /*
                   1140:             * Compute the full path
                   1141:             */
1.35      veillard 1142:            if (tree->rpmpath[0] != '\0')
1.66      daniel   1143:                snprintf(path, sizeof(path), "%s/%s/%s", dir->rpmdir, tree->rpmpath,
1.35      veillard 1144:                        filename);
1.22      veillard 1145:            else
1.66      daniel   1146:                snprintf(path, sizeof(path), "%s/%s", dir->rpmdir, filename);
1.22      veillard 1147: 
                   1148:            /*
1.25      veillard 1149:             * Stat() the file to detect directory and symlimks
                   1150:             */
1.30      veillard 1151:            if (lstat(path, &buf) != 0) {
1.25      veillard 1152:                fprintf(stderr, "Couldn't stat(%s)\n", path);
                   1153:                continue;
                   1154:            }
1.35      veillard 1155: 
1.25      veillard 1156:            /*
1.23      veillard 1157:             * Check for RPM files by looking at the suffix
1.54      veillard 1158:             * Note that SuSE source RPMs have a ".spm" suffix
1.63      daniel   1159:             * We may or may not follow symlinks to RPM files
1.22      veillard 1160:             */
1.63      daniel   1161:            if (((len >= 5) &&
1.54      veillard 1162:                       (!strcasecmp(&filename[len - 4], ".rpm"))) ||
                   1163:                     ((len >= 5) &&
                   1164:                       (!strcasecmp(&filename[len - 4], ".spm")))) {
1.63      daniel   1165:  
1.65      daniel   1166:                if ((S_ISLNK(buf.st_mode)) && (dir->rpm_symlinks == 0)) {
1.66      daniel   1167:                    if (rpm2htmlVerbose > 1)
1.63      daniel   1168:                        fprintf(stderr, "Dropping symlink %s\n", path);
                   1169:                    continue;
                   1170:                }
1.35      veillard 1171:                cur = rpmOpen(filename, dir, tree);
1.63      daniel   1172:            }
                   1173: 
                   1174:            /*
                   1175:             * Don't follow of analyze symlinks,
                   1176:             */
1.96      daniel   1177:             else if ((S_ISLNK(buf.st_mode)) && (dir->follow_symlinks == 0) &&
                   1178:                     (strcmp(dir->rpmdir, path))) {
1.66      daniel   1179:                if (rpm2htmlVerbose > 1)
1.63      daniel   1180:                    fprintf(stderr, "Dropping symlink %s\n", path);
                   1181:                continue;
1.44      veillard 1182:            }
                   1183: 
                   1184:            /*
                   1185:             * Check for RDF files by looking at the suffix
                   1186:             */
                   1187:            else if ((len >= 5) && (!strcasecmp(&filename[len - 4], ".rdf"))) {
                   1188:                cur = rpmOpenRdf(filename, dir, tree);
1.22      veillard 1189:            }
1.35      veillard 1190: 
1.22      veillard 1191:            /*
1.23      veillard 1192:             * Else if this is a directory, recurse !
1.22      veillard 1193:             */
1.25      veillard 1194:            else if (S_ISDIR(buf.st_mode)) {
                   1195:                if (filename[0] != '.') {
1.57      daniel   1196:                    subtree = rpmNewSubdir(tree, filename, NULL, NULL, NULL, 0);
1.35      veillard 1197:                    cur = rpmOneDirScan(dir, subtree);
1.25      veillard 1198:                }
1.22      veillard 1199:            }
1.32      veillard 1200:            if (cur != NULL) ret = rpmAddList(ret, cur);
1.7       veillard 1201:        }
1.6       veillard 1202:     }
1.39      veillard 1203:     closedir(d);
1.33      veillard 1204: 
                   1205:     /*
                   1206:      * Dump the pages related to this directory.
                   1207:      */
1.35      veillard 1208:     if (ret != NULL) ret = dumpDirIndex(dir, tree, ret);
1.36      veillard 1209:     else {
                   1210:         rpmRemoveSubdir(tree);
                   1211:        rpmFreeSubdir(tree);
1.94      daniel   1212:        tree = NULL;
1.36      veillard 1213:     }
1.35      veillard 1214: 
1.32      veillard 1215:     return(ret);
1.22      veillard 1216: }
                   1217: 
                   1218: /*
                   1219:  * Scan a directory for RPM files.
                   1220:  */
1.35      veillard 1221: static rpmDataPtr rpmDirScan(rpmDirPtr dir, rpmSubdirPtr tree) {
1.37      veillard 1222:     rpmSubdirPtr cur;
                   1223:     rpmDataPtr ret;
                   1224:     
1.56      daniel   1225:     if ((rpm2html_dump_html) && (dir->html) && (dir->build_tree != 0)) {
1.37      veillard 1226:        dir->root = rpmCreateRealRoot();
                   1227:     }
                   1228:     cur = rpmNewSubdir(tree, dir->name,
1.57      daniel   1229:               dir->subdir == NULL ? "" : dir->subdir, "", dir->color,
                   1230:              dir->html);
1.37      veillard 1231:     ret = rpmOneDirScan(dir, cur);
1.38      veillard 1232:     rpmDumpHtmlRealRoot(dir);
1.37      veillard 1233:     return(ret);
1.6       veillard 1234: }
                   1235: 
                   1236: /*
1.11      veillard 1237:  * Scan the local RPM database for RPM files.
                   1238:  */
1.32      veillard 1239: static rpmDataPtr rpmBaseScan(rpmDirPtr dir) {
1.37      veillard 1240:     static char path[2000];
1.32      veillard 1241:     rpmDataPtr ret = NULL, cur;
1.11      veillard 1242:     rpmdb db;
                   1243:     Header h = NULL;
1.72      daniel   1244: #ifndef        USE_RPMIO
1.32      veillard 1245:     int offset;
1.71      daniel   1246: #endif
1.11      veillard 1247:     char *prefix = "/";
1.88      veillard 1248: 
                   1249: #ifdef WITH_SQL
                   1250:     dir->no = sql_get_distrib_by_directory(dir->rpmdir);
                   1251: #endif
1.11      veillard 1252: 
1.37      veillard 1253:     /*
                   1254:      * Create the directory for the HTML pages
                   1255:      */
1.56      daniel   1256:     if ((rpm2html_dump_html) && (dir->html)) {
1.45      veillard 1257:        if (dir->subdir)
1.66      daniel   1258:            snprintf(path, sizeof(path), "%s/%s", dir->dir, dir->subdir);
1.45      veillard 1259:        else
1.66      daniel   1260:            snprintf(path, sizeof(path), "%s", dir->dir);
1.45      veillard 1261:        createDirectory(path);
                   1262:     }
                   1263: 
                   1264:     /*
                   1265:      * Create the directory for the RDF pages
                   1266:      */
                   1267:     if (rpm2html_rdf_dir != NULL) {
                   1268:        if (dir->subdir)
1.66      daniel   1269:            snprintf(path, sizeof(path), "%s/%s", rpm2html_rdf_dir, dir->subdir);
1.45      veillard 1270:        else
1.66      daniel   1271:            snprintf(path, sizeof(path), "%s", rpm2html_rdf_dir);
1.45      veillard 1272:         createDirectory(path);
                   1273:     }
1.37      veillard 1274: 
1.66      daniel   1275:     if (rpm2htmlVerbose)
                   1276:         printf("Scanning the database of installed RPMs\n");
1.70      daniel   1277: 
                   1278:     if (dir->dbpath != NULL)
                   1279:        addMacro(NULL, "_dbpath", NULL, dir->dbpath, -7); /* Added by A.Gibert */
1.66      daniel   1280: 
1.11      veillard 1281:     if (rpmdbOpen(prefix, &db, O_RDONLY, 0644)) {
1.32      veillard 1282:         return(NULL);
1.11      veillard 1283:     }
1.71      daniel   1284: 
1.72      daniel   1285: #ifdef USE_RPMIO
1.71      daniel   1286:     {  rpmdbMatchIterator mi;
                   1287:        mi = rpmdbInitIterator(db, RPMDBI_PACKAGES, NULL, 0);
                   1288:        while ((h = rpmdbNextIterator(mi)) != NULL) {
1.86      veillard 1289:            cur = rpmAnalyze(NULL, NULL, NULL, h, NULL, dir, NULL, 0, 0);
1.71      daniel   1290:            if (cur != NULL) ret = rpmAddList(ret, cur);
                   1291:        }
                   1292:        rpmdbFreeIterator(mi);
                   1293:     }
1.72      daniel   1294: #else  /* USE_RPMIO */
1.11      veillard 1295:     offset = rpmdbFirstRecNum(db);
                   1296:     while (offset) {
                   1297:         h = rpmdbGetRecord(db, offset);
                   1298:        if (!h) {
                   1299:            fprintf(stderr, "could not read database record!\n");
1.32      veillard 1300:            return(ret);
1.11      veillard 1301:        }
1.86      veillard 1302:        cur = rpmAnalyze(NULL, NULL, NULL, h, NULL, dir, NULL, 0, 0);
1.32      veillard 1303:        if (cur != NULL) ret = rpmAddList(ret, cur);
1.11      veillard 1304:        headerFree(h);
                   1305:        offset = rpmdbNextRecNum(db, offset);
                   1306:     }
1.72      daniel   1307: #endif /* USE_RPMIO */
1.71      daniel   1308: 
1.11      veillard 1309:     rpmdbClose(db);
                   1310: 
1.32      veillard 1311:     return(ret);
1.95      daniel   1312: }
                   1313: 
                   1314: /*
                   1315:  * Scan one directory only
                   1316:  */
                   1317: 
                   1318: void rpmDirScanOneDir(const char *directory) {
                   1319:     rpmDirPtr dir;
                   1320:     rpmDataPtr cur;
                   1321: 
                   1322:     /*
                   1323:      * first try to find the distrib
                   1324:      */
                   1325:     dir = dirList;
                   1326:     while (dir != NULL) {
                   1327:        if (!strcasecmp(dir->rpmdir, directory))
                   1328:            break;
                   1329:        dir = dir->next;
                   1330:     }
                   1331:     if (dir == NULL) {
                   1332:        fprintf(stderr, "rpmDirScanOneDir(%s): distribution not found\n",
                   1333:                directory);
                   1334:        return;
                   1335:     }
                   1336:     if (rpm2htmlVerbose)
                   1337:        printf("indexing %s\n", dir->name);
                   1338: 
                   1339:     /*
                   1340:      * Allocate a directory tree.
                   1341:      */
                   1342:     dirTree = rpmNewSubdir(NULL, "", "", "", NULL, 1);
                   1343: 
                   1344:     cur  = NULL;
                   1345: 
                   1346:     /*
                   1347:      * Override default setting.
                   1348:      */
                   1349:     if ((dir->maint == NULL) && (rpm2html_maint != NULL))
                   1350:        dir->maint = xmlStrdup(rpm2html_maint);
                   1351:     if ((dir->mail == NULL) && (rpm2html_mail != NULL))
                   1352:        dir->mail = xmlStrdup(rpm2html_mail);
                   1353:     if ((dir->ftp == NULL) && (rpm2html_ftp != NULL))
                   1354:        dir->ftp = xmlStrdup(rpm2html_ftp);
                   1355:     if ((dir->ftpsrc == NULL) && (rpm2html_ftpsrc != NULL))
                   1356:        dir->ftpsrc = xmlStrdup(rpm2html_ftpsrc);
                   1357:     if ((dir->dir == NULL) && (rpm2html_dir != NULL))
                   1358:        dir->dir = xmlStrdup(rpm2html_dir);
                   1359:     if ((dir->host == NULL) && (rpm2html_host != NULL))
                   1360:        dir->host = xmlStrdup(rpm2html_host);
                   1361:     if ((dir->name == NULL) && (rpm2html_name != NULL))
                   1362:        dir->name = xmlStrdup(rpm2html_name);
                   1363:     if ((dir->url == NULL) && (rpm2html_url != NULL))
                   1364:        dir->url = xmlStrdup(rpm2html_url);
                   1365: 
                   1366:     if (dir->rpmdir == NULL) {
                   1367:        fprintf(stderr, "?!? rpmDir without directory ?!? disabled !\n");
                   1368:     } else if (!strncmp(dir->rpmdir, "localbase", 9)) {
                   1369:        /* Scan the local RPM database instead of a directory */
                   1370:        cur = rpmBaseScan(dir);
                   1371:     } else if (dir->ftp == NULL) {
                   1372:        fprintf(stderr, "Directory %s disabled : no ftp field\n",
                   1373:                dir->rpmdir);
                   1374:     } else {
                   1375: #ifdef WITH_SQL
                   1376:        dir->no = sql_get_distrib_by_directory(dir->rpmdir);
                   1377: #endif
                   1378:        if (rpm2htmlVerbose)
                   1379:            printf("Scanning directory %s for RPMs\n",dir->rpmdir);
                   1380:        cur = rpmDirScan(dir, dirTree);
                   1381:     }
                   1382: 
1.97    ! daniel   1383: #if 0
1.95      daniel   1384:     if (dir->root != NULL) {
                   1385:        rpmDestroyRealRoot(dir->root);
                   1386:        dir->root = NULL;
                   1387:     }
                   1388:     rpmFreeSubdir(dirTree);
                   1389:     dirTree = NULL;
1.97    ! daniel   1390: #endif
1.80      veillard 1391: }
                   1392: 
                   1393: 
                   1394: /*
                   1395:  * Scan one distribution only
                   1396:  */
                   1397: 
                   1398: void rpmDirScanOneDist(const char *dist) {
                   1399:     rpmDirPtr dir;
                   1400:     rpmDataPtr cur;
                   1401: 
                   1402:     /*
                   1403:      * first try to find the distrib
                   1404:      */
                   1405:     dir = dirList;
                   1406:     while (dir != NULL) {
                   1407:        if (!strcasecmp(dir->name, dist))
                   1408:            break;
                   1409:        if (!strcasecmp(dir->subdir, dist))
                   1410:            break;
                   1411:        if (!strcasecmp(dir->rpmdir, dist))
                   1412:            break;
                   1413:        dir = dir->next;
                   1414:     }
                   1415:     if (dir == NULL) {
                   1416:        dir = dirList;
                   1417:        while (dir != NULL) {
                   1418:            if (!strstr(dir->name, dist))
                   1419:                break;
                   1420:            if (!strstr(dir->subdir, dist))
                   1421:                break;
                   1422:            if (!strstr(dir->rpmdir, dist))
                   1423:                break;
                   1424:            dir = dir->next;
                   1425:        }
                   1426:     }
                   1427:     if (dir == NULL) {
                   1428:        fprintf(stderr, "rpmDirScanOneDist(%s): distribution not found\n",
                   1429:                dist);
                   1430:        return;
                   1431:     }
                   1432:     if (rpm2htmlVerbose)
                   1433:        printf("indexing %s\n", dir->name);
                   1434: 
                   1435:     /*
                   1436:      * Allocate a directory tree.
                   1437:      */
                   1438:     dirTree = rpmNewSubdir(NULL, "", "", "", NULL, 1);
                   1439: 
                   1440:     cur  = NULL;
                   1441: 
                   1442:     /*
                   1443:      * Override default setting.
                   1444:      */
                   1445:     if ((dir->maint == NULL) && (rpm2html_maint != NULL))
1.93      veillard 1446:        dir->maint = xmlStrdup(rpm2html_maint);
1.80      veillard 1447:     if ((dir->mail == NULL) && (rpm2html_mail != NULL))
1.93      veillard 1448:        dir->mail = xmlStrdup(rpm2html_mail);
1.80      veillard 1449:     if ((dir->ftp == NULL) && (rpm2html_ftp != NULL))
1.93      veillard 1450:        dir->ftp = xmlStrdup(rpm2html_ftp);
1.80      veillard 1451:     if ((dir->ftpsrc == NULL) && (rpm2html_ftpsrc != NULL))
1.93      veillard 1452:        dir->ftpsrc = xmlStrdup(rpm2html_ftpsrc);
1.80      veillard 1453:     if ((dir->dir == NULL) && (rpm2html_dir != NULL))
1.93      veillard 1454:        dir->dir = xmlStrdup(rpm2html_dir);
1.80      veillard 1455:     if ((dir->host == NULL) && (rpm2html_host != NULL))
1.93      veillard 1456:        dir->host = xmlStrdup(rpm2html_host);
1.80      veillard 1457:     if ((dir->name == NULL) && (rpm2html_name != NULL))
1.93      veillard 1458:        dir->name = xmlStrdup(rpm2html_name);
1.80      veillard 1459:     if ((dir->url == NULL) && (rpm2html_url != NULL))
1.93      veillard 1460:        dir->url = xmlStrdup(rpm2html_url);
1.80      veillard 1461: 
                   1462:     if (dir->rpmdir == NULL) {
                   1463:        fprintf(stderr, "?!? rpmDir without directory ?!? disabled !\n");
                   1464:     } else if (!strncmp(dir->rpmdir, "localbase", 9)) {
                   1465:        /* Scan the local RPM database instead of a directory */
                   1466:        cur = rpmBaseScan(dir);
                   1467:     } else if (dir->ftp == NULL) {
                   1468:        fprintf(stderr, "Directory %s disabled : no ftp field\n",
                   1469:                dir->rpmdir);
                   1470:     } else {
1.82      veillard 1471: #ifdef WITH_SQL
1.80      veillard 1472:        dir->no = sql_get_distrib_by_directory(dir->rpmdir);
1.82      veillard 1473: #endif
1.80      veillard 1474:        if (rpm2htmlVerbose)
                   1475:            printf("Scanning directory %s for RPMs\n",dir->rpmdir);
                   1476:        cur = rpmDirScan(dir, dirTree);
                   1477:     }
                   1478: 
                   1479:     if (dir->root != NULL) {
                   1480:        rpmDestroyRealRoot(dir->root);
                   1481:        dir->root = NULL;
                   1482:     }
1.93      veillard 1483:     rpmFreeSubdir(dirTree);
1.94      daniel   1484:     dirTree = NULL;
1.11      veillard 1485: }
                   1486: 
                   1487: /*
1.6       veillard 1488:  * Scan all registered directories.
                   1489:  * One fist check for completeness of the informations in
                   1490:  * the rpmDir structure.
                   1491:  */
                   1492: 
1.32      veillard 1493: rpmDataPtr rpmDirScanAll(void) {
1.18      veillard 1494:     rpmDirPtr dir, next;
1.32      veillard 1495:     rpmDataPtr ret = NULL, cur;
1.91      veillard 1496: #ifndef WITH_SQL
1.46      veillard 1497:     int maxLists = 50;
                   1498:     rpmDataPtr *rpmLists;
1.35      veillard 1499:     int nbLists = 0;
                   1500:     int i;
1.91      veillard 1501: #endif
1.18      veillard 1502: 
                   1503:     /*
                   1504:      * first reverse the list ....
                   1505:      */
                   1506:     dir = dirList;
                   1507:     dirList = NULL;
                   1508:     while (dir != NULL) {
                   1509:         next = dir->next;
                   1510:        dir->next = dirList;
                   1511:        dirList = dir;
                   1512:        dir = next;
                   1513:     }
1.57      daniel   1514:     dir = dirList;
1.18      veillard 1515: 
1.35      veillard 1516:     /*
                   1517:      * Allocate a directory tree.
                   1518:      */
1.57      daniel   1519:     dirTree = rpmNewSubdir(NULL, "", "", "", NULL, 1);
1.6       veillard 1520: 
1.91      veillard 1521: #ifndef WITH_SQL
1.93      veillard 1522:     rpmLists = (rpmDataPtr *) xmlMalloc(maxLists * sizeof(rpmDataPtr));
1.46      veillard 1523:     if (rpmLists == NULL) {
                   1524:         fprintf(stderr, "rpmDirScanAll : running out of memory !\n");
                   1525:        exit(1);
                   1526:     }
1.91      veillard 1527: #endif
1.46      veillard 1528: 
1.6       veillard 1529:     while (dir != NULL) {
1.32      veillard 1530:         cur  = NULL;
                   1531: 
1.14      veillard 1532:        /*
1.91      veillard 1533:         * Complete with default setting.
1.14      veillard 1534:         */
1.15      veillard 1535:        if ((dir->maint == NULL) && (rpm2html_maint != NULL))
1.93      veillard 1536:            dir->maint = xmlStrdup(rpm2html_maint);
1.15      veillard 1537:        if ((dir->mail == NULL) && (rpm2html_mail != NULL))
1.93      veillard 1538:            dir->mail = xmlStrdup(rpm2html_mail);
1.15      veillard 1539:        if ((dir->ftp == NULL) && (rpm2html_ftp != NULL))
1.93      veillard 1540:            dir->ftp = xmlStrdup(rpm2html_ftp);
1.15      veillard 1541:        if ((dir->ftpsrc == NULL) && (rpm2html_ftpsrc != NULL))
1.93      veillard 1542:            dir->ftpsrc = xmlStrdup(rpm2html_ftpsrc);
1.15      veillard 1543:        if ((dir->dir == NULL) && (rpm2html_dir != NULL))
1.93      veillard 1544:            dir->dir = xmlStrdup(rpm2html_dir);
1.15      veillard 1545:        if ((dir->host == NULL) && (rpm2html_host != NULL))
1.93      veillard 1546:            dir->host = xmlStrdup(rpm2html_host);
1.15      veillard 1547:        if ((dir->name == NULL) && (rpm2html_name != NULL))
1.93      veillard 1548:            dir->name = xmlStrdup(rpm2html_name);
1.15      veillard 1549:        if ((dir->url == NULL) && (rpm2html_url != NULL))
1.93      veillard 1550:            dir->url = xmlStrdup(rpm2html_url);
1.14      veillard 1551: 
                   1552:         if (dir->rpmdir == NULL) {
1.6       veillard 1553:            fprintf(stderr, "?!? rpmDir without directory ?!? disabled !\n");
1.91      veillard 1554:        } else if (!strncmp(dir->rpmdir, "localbase", 9)) {
1.11      veillard 1555:            /* Scan the local RPM database instead of a directory */
1.32      veillard 1556:             cur = rpmBaseScan(dir);
1.7       veillard 1557:        } else if (dir->ftp == NULL) {
                   1558:            fprintf(stderr, "Directory %s disabled : no ftp field\n",
1.14      veillard 1559:                    dir->rpmdir);
1.6       veillard 1560:        } else {
1.82      veillard 1561: #ifdef WITH_SQL
1.79      veillard 1562:            dir->no = sql_get_distrib_by_directory(dir->rpmdir);
1.82      veillard 1563: #endif
1.51      veillard 1564:            if (rpm2htmlVerbose)
1.66      daniel   1565:                printf("Scanning directory %s for RPMs\n",dir->rpmdir);
1.35      veillard 1566:            cur = rpmDirScan(dir, dirTree);
1.6       veillard 1567:        }
                   1568: 
1.91      veillard 1569: #ifdef WITH_SQL
                   1570:        /*
                   1571:         * The packages list will be reextratced from the
                   1572:         * database at the end, minimize memory consumption
                   1573:         */
                   1574:        rpmlistCleanup();
                   1575: #else
1.35      veillard 1576:        if (cur != NULL) {
1.46      veillard 1577:            if (nbLists >= maxLists) {
                   1578:                maxLists *= 2;
1.93      veillard 1579:                rpmLists = (rpmDataPtr *) xmlRealloc(rpmLists,
1.46      veillard 1580:                                             maxLists * sizeof(rpmDataPtr));
                   1581:                if (rpmLists == NULL) {
                   1582:                    fprintf(stderr, "rpmDirScanAll : running out of memory!\n");
                   1583:                    exit(1);
1.35      veillard 1584:                }
                   1585:            }
1.46      veillard 1586:            rpmLists[nbLists] = cur;
                   1587:            nbLists++;
1.39      veillard 1588:        }
1.91      veillard 1589: #endif
1.39      veillard 1590:        if (dir->root != NULL) {
1.48      veillard 1591:            rpmDestroyRealRoot(dir->root);
                   1592:            dir->root = NULL;
1.35      veillard 1593:        }
1.6       veillard 1594:         dir = dir->next;
                   1595:     }
1.91      veillard 1596: #ifndef WITH_SQL
1.35      veillard 1597:     for (i = 0;i < nbLists;i++)
                   1598:        ret = rpmAddList(ret, rpmLists[i]);
1.93      veillard 1599:     xmlFree(rpmLists);
1.91      veillard 1600: #endif
1.32      veillard 1601:     return(ret);
1.60      daniel   1602: }
                   1603: 
                   1604: /*
                   1605:  * Cleanup the global variables from this module
                   1606:  */
                   1607: void rpmopenCleanup(void) {
                   1608:     if (buffer != NULL)
1.93      veillard 1609:         xmlFree(buffer);
1.60      daniel   1610:     buffer = NULL;
                   1611:     buffer_size = 50 * 1024 * sizeof(char);
1.1       veillard 1612: }
                   1613: 

Webmaster