Annotation of rpm2html/rpmopen.c, revision 1.74

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.74    ! daniel      6:  * $Id: rpmopen.c,v 1.73 2000/06/24 16:44:01 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.1       veillard   27: 
                     28: #include "rpmdata.h"
1.7       veillard   29: #include "html.h"
1.40      httpng     30: #include "rdf.h"
1.8       veillard   31: #include "rpm2html.h"
1.12      veillard   32: #include "language.h"
1.1       veillard   33: 
1.66      daniel     34: #ifndef HAVE_SNPRINTF
                     35: #error You really need snprintf ...
                     36: #endif
1.1       veillard   37: /*
1.69      daniel     38:  * Get the internal number associated with an RPM tag.
1.1       veillard   39:  */
                     40: static int getTagNumber(char *tag) {
                     41:     int i;
                     42:     const struct headerTagTableEntry * t;
                     43: 
                     44:     for (i = 0, t = rpmTagTable; i < rpmTagTableSize; i++, t++) {
                     45:        if (!strcasecmp(tag, t->name)) return(t->val);
                     46:     }
                     47:     fprintf(stderr, "getTagNumber(%s) : unknown tag !\n", tag);
                     48:     return(-1);
                     49: }
                     50: 
                     51: /*
1.58      daniel     52:  * Free up the extra data not needed for the last stage processing.
                     53:  */
                     54: 
                     55: void rpmFreeExtraData(rpmDataPtr rpm) {
                     56:     rpmExtraDataPtr extra;
                     57: 
                     58:     if ((rpm == NULL) || (rpm->extra == NULL)) return;
                     59:     extra = rpm->extra;
1.61      daniel     60:     if (extra->packager != NULL) debugFree(extra->packager);
                     61:     if (extra->description != NULL) debugFree(extra->description);
                     62:     if (extra->copyright != NULL) debugFree(extra->copyright);
                     63:     if (extra->changelog != NULL) debugFree(extra->changelog);
                     64:     if (extra->srcrpm != NULL) debugFree(extra->srcrpm);
                     65:     if (extra->host != NULL) debugFree(extra->host);
                     66:     if (extra->resources != NULL) debugFree(extra->resources);
                     67:     if (extra->requires != NULL) debugFree(extra->requires);
                     68:     if (extra->filelist != NULL) debugFree(extra->filelist);
                     69:     debugFree(extra);
1.58      daniel     70: }
                     71: 
                     72: /*
1.59      daniel     73:  * check a dependancy name to get rid of bad deps due to bad scripts
1.55      daniel     74:  * or spec files.
1.53      veillard   75:  */
                     76: int checkResourceName(const char *res) {
1.59      daniel     77:     int isname = 0;
                     78:     const char *base = res;
1.55      daniel     79: 
1.53      veillard   80:     if (*res == 0) return(0);
1.55      daniel     81: 
                     82:     /*
1.59      daniel     83:      * we only accept absolute pathnames.
1.55      daniel     84:      */
1.59      daniel     85:     if (*res == '/') isname = 1;
1.53      veillard   86:     while (*res != 0) {
1.59      daniel     87:         if (((*res >= 'A') && (*res <= 'Z')) ||
                     88:            ((*res >= 'a') && (*res <= 'z')) ||
1.53      veillard   89:             ((*res >= '0') && (*res <= '9')) ||
1.55      daniel     90:            (*res == '-') || (*res == '.') ||
                     91:            (*res == '@') || (*res == '_') ||
1.59      daniel     92:            (*res == '+') ||
                     93:            ((*res == '/') && (isname == 1)))
1.53      veillard   94:            res++;
                     95:        else
                     96:            return(0);
1.59      daniel     97:        if ((res - base) > 100) return(0);
                     98:     }
                     99:     return(1);
                    100: }
                    101: 
                    102: /*
                    103:  * check a release name
                    104:  */
                    105: int checkReleaseName(const char *res) {
                    106:     const char *base = res;
                    107: 
                    108:     if (*res == 0) return(0);
                    109: 
                    110:     while (*res != 0) {
                    111:         if (((*res >= 'A') && (*res <= 'Z')) ||
                    112:            ((*res >= 'a') && (*res <= 'z')) ||
                    113:             ((*res >= '0') && (*res <= '9')) ||
                    114:            (*res == '-') || (*res == '.') ||
                    115:            (*res == '@') || (*res == '_') ||
                    116:            (*res == '+'))
                    117:            res++;
                    118:        else
                    119:            return(0);
                    120:        if ((res - base) > 20) return(0);
                    121:     }
                    122:     return(1);
                    123: }
                    124: 
                    125: /*
                    126:  * check a group name
                    127:  */
                    128: int checkGroupName(const char *res) {
                    129:     const char *base = res;
                    130: 
                    131:     /* Grrr !!! Suse packages have an empty Group name
                    132:     if (*res == 0) return(0);
                    133:      */
                    134: 
                    135:     while (*res != 0) {
                    136:         if (((*res >= 'A') && (*res <= 'Z')) ||
                    137:            ((*res >= 'a') && (*res <= 'z')) ||
                    138:             ((*res >= '0') && (*res <= '9')) ||
                    139:            (*res == ' ') || (*res == '.') ||
                    140:            (*res == '+') || (*res == '/') ||
                    141:            (*res == '-'))
                    142:            res++;
                    143:        else
                    144:            return(0);
                    145:        if ((res - base) > 60) return(0);
                    146:     }
                    147:     return(1);
                    148: }
                    149: 
                    150: /*
                    151:  * check a version name
                    152:  */
                    153: int checkVersionName(const char *res) {
                    154:     const char *base = res;
                    155: 
                    156:     if (*res == 0) return(0);
                    157: 
                    158:     while (*res != 0) {
                    159:         if (((*res >= 'A') && (*res <= 'Z')) ||
                    160:            ((*res >= 'a') && (*res <= 'z')) ||
                    161:             ((*res >= '0') && (*res <= '9')) ||
                    162:            (*res == '-') || (*res == '.') ||
                    163:            (*res == '@') || (*res == '_') ||
                    164:            (*res == '+'))
                    165:            res++;
                    166:        else
                    167:            return(0);
                    168:        if ((res - base) > 20) return(0);
1.53      veillard  169:     }
                    170:     return(1);
                    171: }
1.60      daniel    172: 
1.53      veillard  173: /*
1.11      veillard  174:  * rpmAnalyze : analyze an RPM record, read and parse the header and 
                    175:  *              fill the informations in the database.
1.1       veillard  176:  */
1.62      daniel    177: #define ENTRY_CLEANUP(p)                                               \
                    178:     if ((type == RPM_STRING_ARRAY_TYPE || type == RPM_I18NSTRING_TYPE)&&\
                    179:         (p != NULL)) { free((p)); p = NULL; }
                    180: 
1.60      daniel    181: static char *buffer = NULL;
                    182: static int buffer_size = 50 * 1024 * sizeof(char);
1.61      daniel    183: 
1.36      veillard  184: rpmDataPtr rpmAnalyze(char *nameRpm, Header h, rpmDirPtr dir,
1.52      daniel    185:                       rpmSubdirPtr tree, time_t stamp, int isSource) {
1.11      veillard  186:     int installed = dir->installbase;
1.2       veillard  187:     char * name = NULL, * version = NULL, * release = NULL;
1.1       veillard  188:     int_32 count, type;
1.2       veillard  189:     void * p = NULL;
1.10      veillard  190:     int val, i, j;
1.1       veillard  191:     rpmDataPtr rpm = NULL;
1.11      veillard  192:     static char nameBuffer[500];
1.1       veillard  193: 
1.41      veillard  194:     if (buffer == NULL) {
1.61      daniel    195:         buffer = (char *) debugMalloc(buffer_size);
1.41      veillard  196:        if (buffer == NULL) {
                    197:            fprintf(stderr, "cannot allocate %d bytes: %s\n", buffer_size,
                    198:                    strerror(errno));
                    199:            exit(1);
                    200:        }
                    201:     }
                    202: 
1.1       veillard  203:     /* extract informations from the header */
                    204:     headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &count);
1.49      veillard  205:     if (name == NULL) {
                    206:         fprintf(stderr, "Invalid package %s : no name\n", nameRpm);
                    207:        return(NULL);
                    208:     }
                    209:     if (!(((name[0] >= 'a') && (name[0] <= 'z')) ||
                    210:           ((name[0] >= 'A') && (name[0] <= 'Z')) ||
                    211:          ((name[0] >= '0') && (name[0] <= '9')))) {
                    212:         fprintf(stderr, "Invalid package %s : garbled name\n", nameRpm);
1.62      daniel    213:        ENTRY_CLEANUP(name)
1.49      veillard  214:        return(NULL);
                    215:     }    
1.59      daniel    216:     if (!checkResourceName(name)) {
                    217:         fprintf(stderr, "Invalid package %s : garbled name\n", nameRpm);
1.62      daniel    218:        ENTRY_CLEANUP(name)
1.59      daniel    219:        return(NULL);
                    220:     }
1.1       veillard  221:     headerGetEntry(h, RPMTAG_VERSION, &type, (void **) &version, &count);
1.49      veillard  222:     if ((version == NULL) || (version[0] == 0)) {
                    223:         fprintf(stderr, "Invalid package %s : version invalid\n", nameRpm);
1.62      daniel    224:        ENTRY_CLEANUP(name)
                    225:        ENTRY_CLEANUP(version)
1.49      veillard  226:        return(NULL);
                    227:     }
1.59      daniel    228:     if (!checkVersionName(version)) {
                    229:         fprintf(stderr, "Invalid package %s : garbled version\n", nameRpm);
1.62      daniel    230:        ENTRY_CLEANUP(name)
                    231:        ENTRY_CLEANUP(version)
1.59      daniel    232:        return(NULL);
                    233:     }
1.1       veillard  234:     headerGetEntry(h, RPMTAG_RELEASE, &type, (void **) &release, &count);
1.49      veillard  235:     if ((release == NULL) || (release[0] == 0)) {
                    236:         fprintf(stderr, "Invalid package %s : release invalid\n", nameRpm);
1.62      daniel    237:        ENTRY_CLEANUP(name)
                    238:        ENTRY_CLEANUP(version)
                    239:        ENTRY_CLEANUP(release)
1.49      veillard  240:        return(NULL);
                    241:     }
1.59      daniel    242:     if (!checkReleaseName(release)) {
                    243:         fprintf(stderr, "Invalid package %s : garbled release\n", nameRpm);
1.62      daniel    244:        ENTRY_CLEANUP(name)
                    245:        ENTRY_CLEANUP(version)
                    246:        ENTRY_CLEANUP(release)
1.59      daniel    247:        return(NULL);
                    248:     }
1.1       veillard  249:         
1.58      daniel    250:     /* allocate a new rpmData block, and an rpmExtraData block fill them */
1.61      daniel    251:     rpm = (rpmDataPtr) debugMalloc(sizeof(rpmData));
1.1       veillard  252:     if (rpm == NULL) {
1.41      veillard  253:         fprintf(stderr, "cannot allocate %d bytes: %s\n", sizeof(rpmData),
                    254:                strerror(errno));
                    255:         return(NULL);
1.1       veillard  256:     }
1.44      veillard  257:     memset(rpm, 0, sizeof(rpmData));
1.61      daniel    258:     rpm->extra = (rpmExtraDataPtr) debugMalloc(sizeof(rpmExtraData));
1.58      daniel    259:     if (rpm == NULL) {
                    260:         fprintf(stderr, "cannot allocate %d bytes: %s\n", sizeof(rpmExtraData),
                    261:                strerror(errno));
                    262:         return(NULL);
                    263:     }
                    264:     memset(rpm->extra, 0, sizeof(rpmExtraData));
1.6       veillard  265:     rpm->dir = dir;
1.36      veillard  266:     if (tree) {
                    267:         if ((tree->rpmpath != NULL) && (tree->rpmpath[0] != '\0'))
1.61      daniel    268:            rpm->subdir = stringAdd(tree->rpmpath);
1.36      veillard  269:        else
                    270:            rpm->subdir = NULL;
                    271:     } else
                    272:        rpm->subdir = NULL;
1.58      daniel    273:     rpm->extra->stamp = stamp;
1.61      daniel    274:     rpm->name = stringAdd(name);
1.62      daniel    275:     ENTRY_CLEANUP(name)
1.61      daniel    276:     rpm->version = stringAdd(version);
1.62      daniel    277:     ENTRY_CLEANUP(version)
1.61      daniel    278:     rpm->release = stringAdd(release);
1.62      daniel    279:     ENTRY_CLEANUP(release)
1.1       veillard  280: 
1.26      veillard  281:     /* get all the resources provided by this RPM */
1.2       veillard  282:     if (!headerGetEntry(h, RPMTAG_SUMMARY, &type, &p, &count) || !p) {
1.61      daniel    283:         rpm->summary = debugStrdup(localizedStrings[LANG_NO_SUMMARY]);
1.2       veillard  284:     } else {
1.61      daniel    285:        rpm->summary = debugStrdup((char *) p);
1.2       veillard  286:     }
1.62      daniel    287:     ENTRY_CLEANUP(p);
1.28      veillard  288:     if (!headerGetEntry(h, RPMTAG_DESCRIPTION, &type, &p, &count) || !p ||
                    289:         (type != RPM_STRING_TYPE)) {
1.61      daniel    290:         rpm->extra->description = debugStrdup(localizedStrings[LANG_NO_DESCRIPTION]);
1.2       veillard  291:     } else {
1.61      daniel    292:        rpm->extra->description = debugStrdup((char *) p);
1.2       veillard  293:     }
1.62      daniel    294:     ENTRY_CLEANUP(p);
1.28      veillard  295:     if (!headerGetEntry(h, RPMTAG_DISTRIBUTION, &type, &p, &count) || !p ||
                    296:         (type != RPM_STRING_TYPE)) {
1.61      daniel    297:         rpm->distribution = stringAdd(localizedStrings[LANG_UNKNOWN]);
1.2       veillard  298:     } else {
1.61      daniel    299:        rpm->distribution = stringAdd((char *) p);
1.2       veillard  300:     }
1.62      daniel    301:     ENTRY_CLEANUP(p);
1.52      daniel    302:     if (isSource) {
1.61      daniel    303:         rpm->arch = stringAdd("src");
1.11      veillard  304:        if (nameRpm == NULL) {
1.66      daniel    305:            snprintf(nameBuffer, sizeof(nameBuffer), "%s-%s-%s.src.rpm",
1.52      daniel    306:                    name, version, release);
1.11      veillard  307:            nameRpm = nameBuffer;
                    308:        }
1.2       veillard  309:     } else {
1.52      daniel    310:        if (!headerGetEntry(h, RPMTAG_ARCH, &type, &p, &count) || !p ||
                    311:            (type != RPM_STRING_TYPE)) {
                    312:            if (type == RPM_INT8_TYPE) {
                    313:                /*
                    314:                 * Old packages.
                    315:                 */
                    316:                switch (*((char *) p)) {
                    317:                    case 1:
1.61      daniel    318:                        rpm->arch = stringAdd("i386");
1.52      daniel    319:                        break;
                    320:                    default:
1.61      daniel    321:                        rpm->arch = stringAdd("src");
1.52      daniel    322:                        break;
                    323:                }
                    324:            } else
1.61      daniel    325:                rpm->arch = stringAdd(localizedStrings[LANG_NONE]);
1.52      daniel    326:            if (nameRpm == NULL) {
1.66      daniel    327:                snprintf(nameBuffer, sizeof(nameBuffer), "%s-%s-%s.rpm", name, version, release);
1.52      daniel    328:                nameRpm = nameBuffer;
                    329:            }
                    330:        } else {
1.61      daniel    331:            rpm->arch = stringAdd((char *) p);
1.52      daniel    332:            if (nameRpm == NULL) {
1.66      daniel    333:                snprintf(nameBuffer, sizeof(nameBuffer), "%s-%s-%s.%s.rpm",
1.52      daniel    334:                        name, version, release, (char *)p);
                    335:                nameRpm = nameBuffer;
                    336:            }
1.11      veillard  337:        }
1.62      daniel    338:        ENTRY_CLEANUP(p);
1.2       veillard  339:     }
1.28      veillard  340:     if (!headerGetEntry(h, RPMTAG_OS, &type, &p, &count) || !p ||
                    341:         (type != RPM_STRING_TYPE)) {
1.29      veillard  342:        if (type == RPM_INT8_TYPE) {
                    343:            /*
1.32      veillard  344:             * Old packages.
1.29      veillard  345:             */
                    346:            switch (*((char *) p)) {
                    347:                case 1:
1.61      daniel    348:                    rpm->os = stringAdd("linux");
1.29      veillard  349:                    break;
                    350:                default:
1.61      daniel    351:                    rpm->os = stringAdd("linux");
1.29      veillard  352:                    break;
                    353:            }
                    354:        } else
1.61      daniel    355:            rpm->os = stringAdd("");
1.7       veillard  356:     } else {
1.61      daniel    357:        rpm->os = stringAdd((char *) p);
1.7       veillard  358:     }
1.62      daniel    359:     ENTRY_CLEANUP(p);
1.28      veillard  360:     if (!headerGetEntry(h, RPMTAG_VENDOR, &type, &p, &count) || !p ||
                    361:         (type != RPM_STRING_TYPE)) {
1.7       veillard  362:         rpm->vendor = NULL;
1.2       veillard  363:     } else {
1.61      daniel    364:        rpm->vendor = stringAdd((char *) p);
1.2       veillard  365:     }
1.62      daniel    366:     ENTRY_CLEANUP(p);
1.28      veillard  367:     if (!headerGetEntry(h, RPMTAG_GROUP, &type, &p, &count) || !p ||
                    368:         (type != RPM_STRING_TYPE)) {
1.61      daniel    369:         rpm->group = stringAdd(localizedStrings[LANG_NO_GROUP]);
1.2       veillard  370:     } else {
1.61      daniel    371:        rpm->group = stringAdd((char *) p);
1.59      daniel    372:     }
1.62      daniel    373:     ENTRY_CLEANUP(p);
1.59      daniel    374:     if (!checkGroupName(rpm->group)) {
                    375:         fprintf(stderr, "Invalid package %s : garbled group\n", nameRpm);
1.74    ! daniel    376:        if (rpm->name)
        !           377:            stringFree(rpm->name);
        !           378:        if (rpm->version)
        !           379:            stringFree(rpm->version);
        !           380:        if (rpm->release)
        !           381:            stringFree(rpm->release);
        !           382:        if (rpm->summary)
        !           383:            debugFree(rpm->summary);
        !           384:        if (rpm->distribution)
        !           385:            stringFree(rpm->distribution);
        !           386:        if (rpm->arch)
        !           387:            stringFree(rpm->arch);
        !           388:        if (rpm->os)
        !           389:            stringFree(rpm->os);
        !           390:        if (rpm->vendor != NULL)
        !           391:            stringFree(rpm->vendor);
        !           392:        if (rpm->group != NULL)
        !           393:            stringFree(rpm->group);
1.61      daniel    394:        debugFree(rpm);
1.59      daniel    395:        return(NULL);
1.2       veillard  396:     }
1.28      veillard  397:     if (!headerGetEntry(h, RPMTAG_BUILDHOST, &type, &p, &count) || !p ||
                    398:         (type != RPM_STRING_TYPE)) {
1.61      daniel    399:         rpm->extra->host = debugStrdup(localizedStrings[LANG_NO_HOST]);
1.2       veillard  400:     } else {
1.61      daniel    401:        rpm->extra->host = debugStrdup((char *) p);
1.2       veillard  402:     }
1.62      daniel    403:     ENTRY_CLEANUP(p);
1.2       veillard  404:     if (!headerGetEntry(h, RPMTAG_SIZE, &type, &p, &count) || !p) {
                    405:         rpm->size = 0;
                    406:     } else {
                    407:        rpm->size = *((int *) p);
                    408:     }
1.62      daniel    409:     ENTRY_CLEANUP(p);
1.11      veillard  410:     if (installed) {
                    411:        if (!headerGetEntry(h, RPMTAG_INSTALLTIME, &type, &p, &count) || !p) {
                    412:            rpm->date = 0;
                    413:        } else {
                    414:            rpm->date = *((int_32 *) p);
                    415:        }
1.62      daniel    416:        ENTRY_CLEANUP(p);
1.2       veillard  417:     } else {
1.11      veillard  418:        if (!headerGetEntry(h, RPMTAG_BUILDTIME, &type, &p, &count) || !p) {
                    419:            rpm->date = 0;
                    420:        } else {
                    421:            rpm->date = *((int_32 *) p);
                    422:        }
1.62      daniel    423:        ENTRY_CLEANUP(p);
1.2       veillard  424:     }
1.28      veillard  425:     if (!headerGetEntry(h, RPMTAG_SOURCERPM, &type, &p, &count) || !p ||
                    426:         (type != RPM_STRING_TYPE)) {
1.61      daniel    427:         rpm->extra->srcrpm = debugStrdup("");
1.2       veillard  428:     } else {
1.61      daniel    429:        rpm->extra->srcrpm = debugStrdup((char *) p);
1.2       veillard  430:     }
1.62      daniel    431:     ENTRY_CLEANUP(p);
1.28      veillard  432:     if (!headerGetEntry(h, RPMTAG_URL, &type, &p, &count) || !p ||
                    433:         (type != RPM_STRING_TYPE)) {
1.7       veillard  434:         rpm->url = NULL;
                    435:     } else {
1.61      daniel    436:        rpm->url = debugStrdup((char *) p);
1.7       veillard  437:     }
1.62      daniel    438:     ENTRY_CLEANUP(p);
1.28      veillard  439:     if (!headerGetEntry(h, RPMTAG_PACKAGER, &type, &p, &count) || !p ||
                    440:         (type != RPM_STRING_TYPE)) {
1.58      daniel    441:         rpm->extra->packager = NULL;
1.7       veillard  442:     } else {
1.61      daniel    443:        rpm->extra->packager = debugStrdup((char *) p);
1.7       veillard  444:     }
1.62      daniel    445:     ENTRY_CLEANUP(p);
1.28      veillard  446:     if (!headerGetEntry(h, RPMTAG_COPYRIGHT, &type, &p, &count) || !p ||
                    447:         (type != RPM_STRING_TYPE)) {
1.58      daniel    448:         rpm->extra->copyright = NULL;
1.7       veillard  449:     } else {
1.61      daniel    450:        rpm->extra->copyright = debugStrdup((char *) p);
1.7       veillard  451:     }
1.62      daniel    452:     ENTRY_CLEANUP(p);
1.31      veillard  453:     /* Pick up changelog entries */
                    454:     if (!headerGetEntry(h, RPMTAG_CHANGELOGTEXT, &type, &p, &count) || !p) {
1.58      daniel    455:         rpm->extra->changelog = NULL;
1.31      veillard  456:     } else {
                    457:       time_t *dates;
                    458:       char **names;
                    459:       char **holdp = (char **)p;
                    460:       char *cp;
                    461:       struct tm *tm_buf;
                    462:       int i, len, pos;
                    463:       char date_string[50];
                    464:       char *res = buffer;
1.42      veillard  465: 
1.31      veillard  466:       *res = '\0';
                    467:       headerGetEntry(h, RPMTAG_CHANGELOGTIME, &type, (void *)&dates, &count);
                    468:       headerGetEntry(h, RPMTAG_CHANGELOGNAME, &type, (void *)&names, &count);
                    469:       for (i = 0;  i < count;  i++) {
1.42      veillard  470:         if ((res - buffer) > (buffer_size - 1024)) {
                    471:            int delta = res - buffer;
                    472: 
1.41      veillard  473:            buffer_size *= 2;
1.61      daniel    474:            buffer = (char *) debugRealloc(buffer, buffer_size);
1.42      veillard  475:            if (buffer == NULL) {
                    476:                fprintf(stderr, "cannot re-allocate %d bytes: %s\n",
                    477:                        buffer_size, strerror(errno));
                    478:                exit(1);
                    479:            }
                    480:            res = &buffer[delta];
1.41      veillard  481:        }
1.31      veillard  482:        tm_buf = localtime(&dates[i]);
                    483:         strftime(date_string, sizeof(date_string) - 1, "%a %b %d %Y", tm_buf);
1.66      daniel    484:        len = snprintf(res, buffer_size, "* %s %s\n", date_string, names[i]);
1.31      veillard  485:        res += len;
                    486:        cp = holdp[i];
                    487:        pos = 0;
                    488:        while (*cp) {
                    489:          if (pos++ == 0) {
                    490:            *res++ = ' ';
                    491:            *res++ = ' ';           
                    492:          }
                    493:          *res++ = *cp;
                    494:          if (*cp++ == '\n') pos = 0;
                    495:        }
                    496:        *res++ = '\n';
                    497:       }
                    498:       *res = '\0';
1.61      daniel    499:       rpm->extra->changelog = debugStrdup(buffer);
1.31      veillard  500:     }
1.62      daniel    501:     ENTRY_CLEANUP(p);
1.7       veillard  502:     if (rpm->vendor == NULL) {
1.61      daniel    503:         if (rpm->extra->packager != NULL) rpm->vendor = debugStrdup(rpm->extra->packager);
                    504:        else rpm->vendor = debugStrdup(localizedStrings[LANG_UNKNOWN]);
1.7       veillard  505:     }
1.2       veillard  506: 
1.61      daniel    507:     rpm->filename = debugStrdup(nameRpm);
1.11      veillard  508: 
1.48      veillard  509:     /* package-xxx.rpm provides at least the resource "package" */
1.1       veillard  510:     val = getTagNumber("RPMTAG_PROVIDES");
                    511:     if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
1.58      daniel    512:         rpm->extra->nb_resources = 1;
                    513:         rpm->extra->max_resources = 1;
1.61      daniel    514:        rpm->extra->resources = (rpmRessPtr *) debugMalloc(sizeof(rpmRessPtr) *
1.58      daniel    515:                                              rpm->extra->max_resources);
                    516:        if (rpm->extra->resources == NULL) {
1.48      veillard  517:            fprintf(stderr, ": ran out of memory\n");
                    518:            exit(1);
                    519:        }
1.58      daniel    520:        rpm->extra->resources[0] = rpmRessAdd(name, rpm, installed);
1.1       veillard  521:     } else {
1.58      daniel    522:         rpm->extra->max_resources = count + 1;
1.61      daniel    523:        rpm->extra->resources = (rpmRessPtr *) debugMalloc(sizeof(rpmRessPtr) *
1.58      daniel    524:                                              rpm->extra->max_resources);
                    525:        if (rpm->extra->resources == NULL) {
1.48      veillard  526:            fprintf(stderr, ": ran out of memory\n");
                    527:            exit(1);
1.1       veillard  528:        }
1.58      daniel    529:        rpm->extra->resources[0] = rpmRessAdd(name, rpm, installed);
                    530:         rpm->extra->nb_resources = 1;
1.1       veillard  531: 
1.58      daniel    532:         for (i = 0, j = rpm->extra->nb_resources; i < count;i++) {
1.53      veillard  533:            if (!checkResourceName(((char **) p)[i])) continue;
1.58      daniel    534:            rpm->extra->resources[j++] = rpmRessAdd(((char **) p)[i], rpm, installed);
1.4       veillard  535:        }
1.58      daniel    536:        rpm->extra->nb_resources = j;
1.4       veillard  537:     }
1.62      daniel    538:     ENTRY_CLEANUP(p);
1.4       veillard  539: 
                    540:     val = getTagNumber("RPMTAG_REQUIRENAME");
                    541:     if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
1.73      daniel    542:        rpm->extra->nb_requires = 0;
1.58      daniel    543:        rpm->extra->requires = NULL;
1.4       veillard  544:     } else {
1.73      daniel    545:        int_32 count2, count3, type2, type3;
                    546:        void * q = NULL;
                    547:        void * r = NULL;
                    548:        int valv, valf;
1.4       veillard  549: 
1.70      daniel    550:        rpm->extra->max_requires = count;
                    551:        rpm->extra->requires = (rpmRessPtr *) debugMalloc(sizeof(rpmRessPtr) *
                    552:                                                   rpm->extra->max_requires);
                    553:        if (rpm->extra->requires == NULL) {
                    554:            fprintf(stderr, ": ran out of memory\n");
                    555:            exit(1);
                    556:        }
1.73      daniel    557:        valv = getTagNumber("RPMTAG_REQUIREVERSION");
                    558:        valf = getTagNumber("RPMTAG_REQUIREFLAGS");
                    559:        headerGetEntry(h, valv, &type2, &q, &count2);
                    560:        headerGetEntry(h, valf, &type3, &r, &count3);
1.70      daniel    561: 
                    562:        rpm->extra->nb_requires = 0;
                    563: 
1.73      daniel    564:         for (i = 0, j = 0; (i < count2) && (i < count3);i++) {
1.70      daniel    565:            char buf[10];
                    566:            long anint = *(((long *)r)+i);
                    567:            buf[0]='\0';
                    568:      
                    569:            if (anint & RPMSENSE_LESS)
                    570:                strcat(buf, "<");
                    571:            if (anint & RPMSENSE_GREATER)
                    572:                strcat(buf, ">");
                    573:            if (anint & RPMSENSE_EQUAL)
1.73      daniel    574:                strcat(buf, "=");
1.53      veillard  575:            if (!checkResourceName(((char **) p)[i])) continue;
1.70      daniel    576:            rpm->extra->requires[j++] = 
                    577:                rpmRequAdd(((char **) p)[i],((char **) q)[i],
                    578:                           ((char *) buf) , rpm, installed);
1.1       veillard  579:        }
1.58      daniel    580:        rpm->extra->nb_requires = j;
1.73      daniel    581:        if ((type2 == RPM_STRING_ARRAY_TYPE || type2 == RPM_I18NSTRING_TYPE)&&
                    582:            (q != NULL)) { free((q)); q = NULL; }
                    583:        if ((type3 == RPM_STRING_ARRAY_TYPE || type3 == RPM_I18NSTRING_TYPE)&&
                    584:            (r != NULL)) { free((r)); r = NULL; }
                    585:        for (;i < count;i++)
                    586:            rpmRequAdd(((char **) p)[i], NULL, NULL, rpm, installed);
1.5       veillard  587:     }
1.62      daniel    588:     ENTRY_CLEANUP(p);
1.69      daniel    589: 
                    590: #if defined(RPMTAG_FILENAMES)
1.5       veillard  591:     val = getTagNumber("RPMTAG_FILENAMES");
1.69      daniel    592:     headerGetEntry(h, val, &type, &p, &count);
                    593: #else
                    594:     rpmBuildFileList(h, (const char ***) &p, &count);
                    595: #endif
                    596: 
                    597:     if (count == 0) {
1.58      daniel    598:         rpm->extra->filelist = NULL; /* No filelist in the package ! */
1.5       veillard  599:     } else {
                    600:         char *ptr = buffer;
1.42      veillard  601: 
1.5       veillard  602:        for (i = 0; i < count;i++) {
1.42      veillard  603:            if ((ptr - buffer) > (buffer_size - 1024)) {
                    604:                int delta = ptr - buffer;
                    605: 
1.41      veillard  606:                buffer_size *= 2;
1.61      daniel    607:                buffer = (char *) debugRealloc(buffer, buffer_size);
1.42      veillard  608:                if (buffer == NULL) {
                    609:                    fprintf(stderr, "cannot re-allocate %d bytes: %s\n",
                    610:                            buffer_size, strerror(errno));
                    611:                    exit(1);
                    612:                }
                    613:                ptr = &buffer[delta];
1.41      veillard  614:            }
1.66      daniel    615:            ptr += snprintf(ptr, buffer_size, "%s\n", ((char **) p)[i]);
1.5       veillard  616:        }
1.61      daniel    617:        rpm->extra->filelist = debugStrdup(buffer);
1.1       veillard  618:     }
1.62      daniel    619:     ENTRY_CLEANUP(p);
1.1       veillard  620: 
1.37      veillard  621:     /* Add the package files to the real filesystem tree if asked for */
1.58      daniel    622:     if ((dir->build_tree != 0) && (rpm->extra->filelist != NULL)) {
1.37      veillard  623:         char *cur, *filename;
                    624:        
1.58      daniel    625:        cur = rpm->extra->filelist;
1.37      veillard  626:        while ((*cur != '\0') && (*cur != '/')) cur++;
                    627:        filename = cur;
                    628:        while (*cur != '\0') {
                    629:            if ((*cur == '\n') || (*cur == '\r')) {
                    630:                if (cur != filename)
                    631:                    rpmAddRealFile(dir->root, filename, rpm);
                    632:                while ((*cur != '\0') && (*cur != '/')) cur++;
                    633:                 filename = cur;
                    634:            } else
                    635:                cur++;
                    636:        }
                    637:        if (cur != filename)
                    638:            rpmAddRealFile(dir->root, filename, rpm);
                    639:     }
1.17      veillard  640: 
                    641:     /* Register this package */
                    642:     rpmAddSoftware(rpm);
1.7       veillard  643: 
                    644:     /* dump the HTML related to this package */
1.56      daniel    645:     if ((rpm2html_dump_html) && (dir->html))
1.40      httpng    646:        dumpRpmHtml(rpm, tree);
                    647:     if (rpm2html_dump_rdf)
                    648:        dumpRpmRdf(rpm, tree);
1.7       veillard  649: 
1.58      daniel    650:     /* free the extra data */
                    651:     rpmFreeExtraData(rpm);
1.8       veillard  652: 
                    653:     /* increment the counters */
1.11      veillard  654:     if (installed) {
                    655:        rpm2html_install_files++;
1.21      veillard  656:        rpm2html_install_size += rpm->size / 1024;
1.11      veillard  657:     } else {
                    658:        rpm2html_files++;
1.21      veillard  659:        rpm2html_size += rpm->size / 1024;
1.11      veillard  660:     }
1.7       veillard  661: 
1.32      veillard  662:     return(rpm);
1.11      veillard  663: }
                    664: 
                    665: /*
                    666:  * rpmOpen : open an RPM file, read and parse the header and 
                    667:  *           fill the informations in the database.
                    668:  */
1.35      veillard  669: rpmDataPtr rpmOpen(char *nameRpm, rpmDirPtr dir, rpmSubdirPtr tree) {
1.32      veillard  670:     rpmDataPtr cur;
1.64      daniel    671: #if defined(HAVE_RPM_RPMIO_H)
                    672:     FD_t fd;
                    673: #else
1.11      veillard  674:     int fd;
1.64      daniel    675: #define        fdOpen(_a, _b, _c)      open((_a), (_b))
                    676: #define        fdClose(_a)             close(_a)
                    677: #endif
1.11      veillard  678:     int rc;
                    679:     Header h = NULL;
                    680:     int isSource;
                    681:     char buffer[500];
1.20      veillard  682:     struct stat buf;
1.11      veillard  683: 
                    684:     /* open the file for reading */
1.35      veillard  685:     if (tree->htmlpath[0] != '\0')
1.66      daniel    686:        snprintf(buffer, sizeof(buffer), "%s/%s/%s", dir->rpmdir, tree->rpmpath, nameRpm);
1.24      veillard  687:     else
1.66      daniel    688:        snprintf(buffer, sizeof(buffer), "%s/%s", dir->rpmdir, nameRpm);
1.72      daniel    689: 
                    690: #if defined(USE_RPMIO)
                    691:     fd = Fopen(buffer, "r.fdio");
                    692:     if (fd == NULL || Ferror(fd)) {
                    693:          fprintf(stderr, "Fopen of %s failed: %s\n", buffer,
                    694:                 Fstrerror(fd));
                    695:         return(NULL);
                    696:     }
                    697: #else
1.64      daniel    698:     if ((fd = fdOpen(buffer, O_RDONLY, 0)) < 0) {
1.11      veillard  699:          fprintf(stderr, "open of %s failed: %s\n", buffer,
                    700:                 strerror(errno));
1.32      veillard  701:         return(NULL);
1.11      veillard  702:     }
1.72      daniel    703: #endif
1.11      veillard  704: 
1.20      veillard  705:     stat(buffer, &buf);
                    706: 
1.11      veillard  707:     /* read the RPM header */
                    708:     rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
                    709:     switch (rc) {
                    710:        case 0:
                    711:            if (!h) {
                    712:                fprintf(stderr,
                    713:                        "old format source packages cannot be queried\n");
1.68      veillard  714:                fdClose(fd);
1.32      veillard  715:                return(NULL);
1.11      veillard  716:            }
                    717:            break;
                    718:        case 1:
                    719:            fprintf(stderr, "%s does not appear to be a RPM package\n",
                    720:                    nameRpm);
1.68      veillard  721:            fdClose(fd);
1.32      veillard  722:            return(NULL);
1.11      veillard  723:        case 2:
                    724:            fprintf(stderr, "query of %s failed\n", nameRpm);
1.68      veillard  725:            fdClose(fd);
1.32      veillard  726:            return(NULL);
1.11      veillard  727:        default:
                    728:            fprintf(stderr, "rpmReadPackageHeader(%s): unknown error %d\n",
                    729:                    nameRpm, rc);
1.68      veillard  730:            fdClose(fd);
1.32      veillard  731:            return(NULL);
1.11      veillard  732:     }
                    733: 
1.52      daniel    734:     cur = rpmAnalyze(nameRpm, h, dir, tree, buf.st_mtime, isSource);
1.11      veillard  735: 
                    736:     /* free the header and close the descriptor */
                    737:     headerFree(h);
1.72      daniel    738: #if defined(USE_RPMIO)
                    739:     Fclose(fd);
                    740: #else
1.64      daniel    741:     fdClose(fd);
1.72      daniel    742: #endif
1.1       veillard  743: 
1.32      veillard  744:     return(cur);
1.6       veillard  745: }
                    746: 
                    747: /*
1.22      veillard  748:  * Scan one directory for RPM files this is where the recursive handling
                    749:  * is done.
1.6       veillard  750:  */
1.35      veillard  751: static rpmDataPtr rpmOneDirScan(rpmDirPtr dir, rpmSubdirPtr tree) {
                    752:     rpmSubdirPtr subtree;
1.32      veillard  753:     rpmDataPtr ret = NULL, cur;
1.7       veillard  754:     char *filename;
1.22      veillard  755:     static char path[2000];
1.23      veillard  756:     struct stat buf;
1.7       veillard  757:     int len;
1.39      veillard  758:     DIR *d;
                    759:     struct dirent *file;
1.6       veillard  760: 
1.24      veillard  761: 
                    762:     /*
                    763:      * Create the directory for the HTML pages
                    764:      */
1.56      daniel    765:     if ((rpm2html_dump_html) && (dir->html)) {
1.45      veillard  766:        if (tree->htmlpath[0] != '\0')
1.66      daniel    767:            snprintf(path, sizeof(path), "%s/%s", dir->dir, tree->htmlpath);
1.45      veillard  768:        else
1.66      daniel    769:            snprintf(path, sizeof(path), "%s", dir->dir);
1.45      veillard  770:        createDirectory(path);
                    771:     }
1.43      veillard  772: 
                    773:     /*
                    774:      * Create the directory for the RDF pages
                    775:     if (rpm2html_rdf_dir != NULL) {
                    776:        if (tree->htmlpath[0] != '\0')
1.66      daniel    777:            snprintf(path, sizeof(path), "%s/%s", rpm2html_rdf_dir, tree->htmlpath);
1.43      veillard  778:        else
1.66      daniel    779:            snprintf(path, sizeof(path), "%s", rpm2html_rdf_dir);
1.43      veillard  780:         createDirectory(path);
                    781:     }
1.47      veillard  782:      */
1.24      veillard  783: 
                    784:     /*
                    785:      * Scan the repository.
                    786:      */
1.35      veillard  787:     if (tree->rpmpath[0] != '\0')
1.66      daniel    788:        snprintf(path, sizeof(path), "%s/%s", dir->rpmdir, tree->rpmpath);
1.24      veillard  789:     else
1.66      daniel    790:        snprintf(path, sizeof(path), "%s", dir->rpmdir);
1.51      veillard  791:     if (rpm2htmlVerbose > 1)
1.66      daniel    792:         printf("Scanning directory %s\n", path);
1.24      veillard  793: 
1.39      veillard  794:     d = opendir(path);
                    795:     if (d == NULL) {
1.24      veillard  796:         fprintf(stderr, "Listing of %s failed: %s\n", path,
1.6       veillard  797:                strerror(errno));
1.35      veillard  798:         rpmRemoveSubdir(tree);
1.36      veillard  799:         rpmFreeSubdir(tree);
1.32      veillard  800:        return(NULL);
1.6       veillard  801:     } else {
1.39      veillard  802:         while ((file = readdir(d)) != NULL) {
1.32      veillard  803:            cur = NULL;
1.39      veillard  804:            filename = file->d_name;
1.7       veillard  805:            len = strlen(filename);
1.24      veillard  806: 
                    807:            /*
                    808:             * Compute the full path
                    809:             */
1.35      veillard  810:            if (tree->rpmpath[0] != '\0')
1.66      daniel    811:                snprintf(path, sizeof(path), "%s/%s/%s", dir->rpmdir, tree->rpmpath,
1.35      veillard  812:                        filename);
1.22      veillard  813:            else
1.66      daniel    814:                snprintf(path, sizeof(path), "%s/%s", dir->rpmdir, filename);
1.22      veillard  815: 
                    816:            /*
1.25      veillard  817:             * Stat() the file to detect directory and symlimks
                    818:             */
1.30      veillard  819:            if (lstat(path, &buf) != 0) {
1.25      veillard  820:                fprintf(stderr, "Couldn't stat(%s)\n", path);
                    821:                continue;
                    822:            }
1.35      veillard  823: 
1.25      veillard  824:            /*
1.23      veillard  825:             * Check for RPM files by looking at the suffix
1.54      veillard  826:             * Note that SuSE source RPMs have a ".spm" suffix
1.63      daniel    827:             * We may or may not follow symlinks to RPM files
1.22      veillard  828:             */
1.63      daniel    829:            if (((len >= 5) &&
1.54      veillard  830:                       (!strcasecmp(&filename[len - 4], ".rpm"))) ||
                    831:                     ((len >= 5) &&
                    832:                       (!strcasecmp(&filename[len - 4], ".spm")))) {
1.63      daniel    833:  
1.65      daniel    834:                if ((S_ISLNK(buf.st_mode)) && (dir->rpm_symlinks == 0)) {
1.66      daniel    835:                    if (rpm2htmlVerbose > 1)
1.63      daniel    836:                        fprintf(stderr, "Dropping symlink %s\n", path);
                    837:                    continue;
                    838:                }
1.35      veillard  839:                cur = rpmOpen(filename, dir, tree);
1.63      daniel    840:            }
                    841: 
                    842:            /*
                    843:             * Don't follow of analyze symlinks,
                    844:             */
1.65      daniel    845:             else if ((S_ISLNK(buf.st_mode)) && (dir->follow_symlinks == 0)) {
1.66      daniel    846:                if (rpm2htmlVerbose > 1)
1.63      daniel    847:                    fprintf(stderr, "Dropping symlink %s\n", path);
                    848:                continue;
1.44      veillard  849:            }
                    850: 
                    851:            /*
                    852:             * Check for RDF files by looking at the suffix
                    853:             */
                    854:            else if ((len >= 5) && (!strcasecmp(&filename[len - 4], ".rdf"))) {
                    855:                cur = rpmOpenRdf(filename, dir, tree);
1.22      veillard  856:            }
1.35      veillard  857: 
1.22      veillard  858:            /*
1.23      veillard  859:             * Else if this is a directory, recurse !
1.22      veillard  860:             */
1.25      veillard  861:            else if (S_ISDIR(buf.st_mode)) {
                    862:                if (filename[0] != '.') {
1.57      daniel    863:                    subtree = rpmNewSubdir(tree, filename, NULL, NULL, NULL, 0);
1.35      veillard  864:                    cur = rpmOneDirScan(dir, subtree);
1.25      veillard  865:                }
1.22      veillard  866:            }
1.32      veillard  867:            if (cur != NULL) ret = rpmAddList(ret, cur);
1.7       veillard  868:        }
1.6       veillard  869:     }
1.39      veillard  870:     closedir(d);
1.33      veillard  871: 
                    872:     /*
                    873:      * Dump the pages related to this directory.
                    874:      */
1.35      veillard  875:     if (ret != NULL) ret = dumpDirIndex(dir, tree, ret);
1.36      veillard  876:     else {
                    877:         rpmRemoveSubdir(tree);
                    878:        rpmFreeSubdir(tree);
                    879:     }
1.35      veillard  880: 
1.32      veillard  881:     return(ret);
1.22      veillard  882: }
                    883: 
                    884: /*
                    885:  * Scan a directory for RPM files.
                    886:  */
1.35      veillard  887: static rpmDataPtr rpmDirScan(rpmDirPtr dir, rpmSubdirPtr tree) {
1.37      veillard  888:     rpmSubdirPtr cur;
                    889:     rpmDataPtr ret;
                    890:     
1.56      daniel    891:     if ((rpm2html_dump_html) && (dir->html) && (dir->build_tree != 0)) {
1.37      veillard  892:        dir->root = rpmCreateRealRoot();
                    893:     }
                    894:     cur = rpmNewSubdir(tree, dir->name,
1.57      daniel    895:               dir->subdir == NULL ? "" : dir->subdir, "", dir->color,
                    896:              dir->html);
1.37      veillard  897:     ret = rpmOneDirScan(dir, cur);
1.38      veillard  898:     rpmDumpHtmlRealRoot(dir);
1.37      veillard  899:     return(ret);
1.6       veillard  900: }
                    901: 
                    902: /*
1.11      veillard  903:  * Scan the local RPM database for RPM files.
                    904:  */
1.32      veillard  905: static rpmDataPtr rpmBaseScan(rpmDirPtr dir) {
1.37      veillard  906:     static char path[2000];
1.32      veillard  907:     rpmDataPtr ret = NULL, cur;
1.11      veillard  908:     rpmdb db;
                    909:     Header h = NULL;
1.72      daniel    910: #ifndef        USE_RPMIO
1.32      veillard  911:     int offset;
1.71      daniel    912: #endif
1.11      veillard  913:     char *prefix = "/";
                    914: 
1.37      veillard  915:     /*
                    916:      * Create the directory for the HTML pages
                    917:      */
1.56      daniel    918:     if ((rpm2html_dump_html) && (dir->html)) {
1.45      veillard  919:        if (dir->subdir)
1.66      daniel    920:            snprintf(path, sizeof(path), "%s/%s", dir->dir, dir->subdir);
1.45      veillard  921:        else
1.66      daniel    922:            snprintf(path, sizeof(path), "%s", dir->dir);
1.45      veillard  923:        createDirectory(path);
                    924:     }
                    925: 
                    926:     /*
                    927:      * Create the directory for the RDF pages
                    928:      */
                    929:     if (rpm2html_rdf_dir != NULL) {
                    930:        if (dir->subdir)
1.66      daniel    931:            snprintf(path, sizeof(path), "%s/%s", rpm2html_rdf_dir, dir->subdir);
1.45      veillard  932:        else
1.66      daniel    933:            snprintf(path, sizeof(path), "%s", rpm2html_rdf_dir);
1.45      veillard  934:         createDirectory(path);
                    935:     }
1.37      veillard  936: 
1.66      daniel    937:     if (rpm2htmlVerbose)
                    938:         printf("Scanning the database of installed RPMs\n");
1.70      daniel    939: 
                    940:     if (dir->dbpath != NULL)
                    941:        addMacro(NULL, "_dbpath", NULL, dir->dbpath, -7); /* Added by A.Gibert */
1.66      daniel    942: 
1.11      veillard  943:     if (rpmdbOpen(prefix, &db, O_RDONLY, 0644)) {
1.32      veillard  944:         return(NULL);
1.11      veillard  945:     }
1.71      daniel    946: 
1.72      daniel    947: #ifdef USE_RPMIO
1.71      daniel    948:     {  rpmdbMatchIterator mi;
                    949:        mi = rpmdbInitIterator(db, RPMDBI_PACKAGES, NULL, 0);
                    950:        while ((h = rpmdbNextIterator(mi)) != NULL) {
                    951:            cur = rpmAnalyze(NULL, h, dir, NULL, 0, 0);
                    952:            if (cur != NULL) ret = rpmAddList(ret, cur);
                    953:        }
                    954:        rpmdbFreeIterator(mi);
                    955:     }
1.72      daniel    956: #else  /* USE_RPMIO */
1.11      veillard  957:     offset = rpmdbFirstRecNum(db);
                    958:     while (offset) {
                    959:         h = rpmdbGetRecord(db, offset);
                    960:        if (!h) {
                    961:            fprintf(stderr, "could not read database record!\n");
1.32      veillard  962:            return(ret);
1.11      veillard  963:        }
1.52      daniel    964:        cur = rpmAnalyze(NULL, h, dir, NULL, 0, 0);
1.32      veillard  965:        if (cur != NULL) ret = rpmAddList(ret, cur);
1.11      veillard  966:        headerFree(h);
                    967:        offset = rpmdbNextRecNum(db, offset);
                    968:     }
1.72      daniel    969: #endif /* USE_RPMIO */
1.71      daniel    970: 
1.11      veillard  971:     rpmdbClose(db);
                    972: 
1.32      veillard  973:     return(ret);
1.11      veillard  974: }
                    975: 
                    976: /*
1.6       veillard  977:  * Scan all registered directories.
                    978:  * One fist check for completeness of the informations in
                    979:  * the rpmDir structure.
                    980:  */
                    981: 
1.32      veillard  982: rpmDataPtr rpmDirScanAll(void) {
1.18      veillard  983:     rpmDirPtr dir, next;
1.32      veillard  984:     rpmDataPtr ret = NULL, cur;
1.46      veillard  985:     int maxLists = 50;
                    986:     rpmDataPtr *rpmLists;
1.35      veillard  987:     int nbLists = 0;
                    988:     int i;
1.18      veillard  989: 
                    990:     /*
                    991:      * first reverse the list ....
                    992:      */
                    993:     dir = dirList;
                    994:     dirList = NULL;
                    995:     while (dir != NULL) {
                    996:         next = dir->next;
                    997:        dir->next = dirList;
                    998:        dirList = dir;
                    999:        dir = next;
                   1000:     }
1.57      daniel   1001:     dir = dirList;
1.18      veillard 1002: 
1.35      veillard 1003:     /*
                   1004:      * Allocate a directory tree.
                   1005:      */
1.57      daniel   1006:     dirTree = rpmNewSubdir(NULL, "", "", "", NULL, 1);
1.6       veillard 1007: 
1.61      daniel   1008:     rpmLists = (rpmDataPtr *) debugMalloc(maxLists * sizeof(rpmDataPtr));
1.46      veillard 1009:     if (rpmLists == NULL) {
                   1010:         fprintf(stderr, "rpmDirScanAll : running out of memory !\n");
                   1011:        exit(1);
                   1012:     }
                   1013: 
1.6       veillard 1014:     while (dir != NULL) {
1.32      veillard 1015:         cur  = NULL;
                   1016: 
1.14      veillard 1017:        /*
                   1018:         * Override default setting.
                   1019:         */
1.15      veillard 1020:        if ((dir->maint == NULL) && (rpm2html_maint != NULL))
1.61      daniel   1021:            dir->maint = debugStrdup(rpm2html_maint);
1.15      veillard 1022:        if ((dir->mail == NULL) && (rpm2html_mail != NULL))
1.61      daniel   1023:            dir->mail = debugStrdup(rpm2html_mail);
1.15      veillard 1024:        if ((dir->ftp == NULL) && (rpm2html_ftp != NULL))
1.61      daniel   1025:            dir->ftp = debugStrdup(rpm2html_ftp);
1.15      veillard 1026:        if ((dir->ftpsrc == NULL) && (rpm2html_ftpsrc != NULL))
1.61      daniel   1027:            dir->ftpsrc = debugStrdup(rpm2html_ftpsrc);
1.15      veillard 1028:        if ((dir->dir == NULL) && (rpm2html_dir != NULL))
1.61      daniel   1029:            dir->dir = debugStrdup(rpm2html_dir);
1.15      veillard 1030:        if ((dir->host == NULL) && (rpm2html_host != NULL))
1.61      daniel   1031:            dir->host = debugStrdup(rpm2html_host);
1.15      veillard 1032:        if ((dir->name == NULL) && (rpm2html_name != NULL))
1.61      daniel   1033:            dir->name = debugStrdup(rpm2html_name);
1.15      veillard 1034:        if ((dir->url == NULL) && (rpm2html_url != NULL))
1.61      daniel   1035:            dir->url = debugStrdup(rpm2html_url);
1.14      veillard 1036: 
                   1037:         if (dir->rpmdir == NULL) {
1.6       veillard 1038:            fprintf(stderr, "?!? rpmDir without directory ?!? disabled !\n");
1.67      daniel   1039:        } else if (!strncmp(dir->rpmdir, "localbase", 9)) {   /* Added by A. Gibert */
1.11      veillard 1040:            /* Scan the local RPM database instead of a directory */
1.32      veillard 1041:             cur = rpmBaseScan(dir);
1.7       veillard 1042:        } else if (dir->ftp == NULL) {
                   1043:            fprintf(stderr, "Directory %s disabled : no ftp field\n",
1.14      veillard 1044:                    dir->rpmdir);
1.6       veillard 1045:        } else {
1.51      veillard 1046:            if (rpm2htmlVerbose)
1.66      daniel   1047:                printf("Scanning directory %s for RPMs\n",dir->rpmdir);
1.35      veillard 1048:            cur = rpmDirScan(dir, dirTree);
1.6       veillard 1049:        }
                   1050: 
1.35      veillard 1051:        if (cur != NULL) {
1.46      veillard 1052:            if (nbLists >= maxLists) {
                   1053:                maxLists *= 2;
1.61      daniel   1054:                rpmLists = (rpmDataPtr *) debugRealloc(rpmLists,
1.46      veillard 1055:                                             maxLists * sizeof(rpmDataPtr));
                   1056:                if (rpmLists == NULL) {
                   1057:                    fprintf(stderr, "rpmDirScanAll : running out of memory!\n");
                   1058:                    exit(1);
1.35      veillard 1059:                }
                   1060:            }
1.46      veillard 1061:            rpmLists[nbLists] = cur;
                   1062:            nbLists++;
1.39      veillard 1063:        }
                   1064:        if (dir->root != NULL) {
1.48      veillard 1065:            /************************************************
1.39      veillard 1066:            if (rpm2html_build_tree)
                   1067:                treeRoot = rpmMergeRealRoots(treeRoot, dir->root);
                   1068:             else
1.48      veillard 1069:             ************************************************/
                   1070:            rpmDestroyRealRoot(dir->root);
                   1071:            dir->root = NULL;
1.35      veillard 1072:        }
1.32      veillard 1073: 
1.6       veillard 1074:         dir = dir->next;
                   1075:     }
1.35      veillard 1076:     for (i = 0;i < nbLists;i++)
                   1077:        ret = rpmAddList(ret, rpmLists[i]);
1.61      daniel   1078:     debugFree(rpmLists);
1.32      veillard 1079:     return(ret);
1.60      daniel   1080: }
                   1081: 
                   1082: /*
                   1083:  * Cleanup the global variables from this module
                   1084:  */
                   1085: void rpmopenCleanup(void) {
                   1086:     if (buffer != NULL)
1.61      daniel   1087:         debugFree(buffer);
1.60      daniel   1088:     buffer = NULL;
                   1089:     buffer_size = 50 * 1024 * sizeof(char);
1.1       veillard 1090: }
                   1091: 

Webmaster