Annotation of rpm2html/rpmopen.c, revision 1.65

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

Webmaster