Annotation of rpm2html/rpmopen.c, revision 1.80

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

Webmaster