Annotation of rpm2html/rpmopen.c, revision 1.47

1.1       veillard    1: /*
                      2:  * rpmopen.c : open an extract informations from RPM files.
                      3:  *
1.11      veillard    4:  * Copyright (c) 1997 Daniel Veillard <veillard@apocalypse.org>
1.9       veillard    5:  * See COPYING for the status of this software.
1.1       veillard    6:  *
1.47    ! veillard    7:  * $Id: rpmopen.c,v 1.46 1998/05/11 03:31:29 veillard Exp $
1.1       veillard    8:  */
                      9: 
1.9       veillard   10: #include <config.h>
1.1       veillard   11: #include <sys/types.h>
                     12: #include <sys/stat.h>
1.9       veillard   13: #ifdef HAVE_FCNTL_H
1.1       veillard   14: #include <fcntl.h>
1.9       veillard   15: #endif
1.1       veillard   16: #include <stdio.h>
                     17: #include <stdlib.h>
                     18: #include <string.h>
1.9       veillard   19: #ifdef HAVE_UNISTD_H
1.1       veillard   20: #include <unistd.h>
1.9       veillard   21: #endif
1.6       veillard   22: #include <dirent.h>
1.13      veillard   23: #include <errno.h>
1.31      veillard   24: #include <time.h>
1.1       veillard   25: 
                     26: #include <rpm/rpmlib.h>
                     27: 
                     28: #include "rpmdata.h"
1.7       veillard   29: #include "html.h"
1.40      httpng     30: #include "rdf.h"
1.8       veillard   31: #include "rpm2html.h"
1.12      veillard   32: #include "language.h"
1.1       veillard   33: 
                     34: /*
                     35:  * Get the internal number associated to an RPM tag.
                     36:  */
                     37: static int getTagNumber(char *tag) {
                     38:     int i;
                     39:     const struct headerTagTableEntry * t;
                     40: 
                     41:     for (i = 0, t = rpmTagTable; i < rpmTagTableSize; i++, t++) {
                     42:        if (!strcasecmp(tag, t->name)) return(t->val);
                     43:     }
                     44:     fprintf(stderr, "getTagNumber(%s) : unknown tag !\n", tag);
                     45:     return(-1);
                     46: }
                     47: 
                     48: /*
1.11      veillard   49:  * rpmAnalyze : analyze an RPM record, read and parse the header and 
                     50:  *              fill the informations in the database.
1.1       veillard   51:  */
1.36      veillard   52: rpmDataPtr rpmAnalyze(char *nameRpm, Header h, rpmDirPtr dir,
                     53:                       rpmSubdirPtr tree, time_t stamp) {
1.11      veillard   54:     int installed = dir->installbase;
1.2       veillard   55:     char * name = NULL, * version = NULL, * release = NULL;
1.1       veillard   56:     int_32 count, type;
1.2       veillard   57:     void * p = NULL;
1.10      veillard   58:     int val, i, j;
1.1       veillard   59:     rpmDataPtr rpm = NULL;
1.41      veillard   60:     static char *buffer = NULL;
                     61:     static int buffer_size = 50 * 1024 * sizeof(char);
1.11      veillard   62:     static char nameBuffer[500];
1.1       veillard   63: 
1.41      veillard   64:     if (buffer == NULL) {
                     65:         buffer = (char *) malloc(buffer_size);
                     66:        if (buffer == NULL) {
                     67:            fprintf(stderr, "cannot allocate %d bytes: %s\n", buffer_size,
                     68:                    strerror(errno));
                     69:            exit(1);
                     70:        }
                     71:     }
                     72: 
1.1       veillard   73:     /* extract informations from the header */
                     74:     headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &count);
                     75:     headerGetEntry(h, RPMTAG_VERSION, &type, (void **) &version, &count);
                     76:     headerGetEntry(h, RPMTAG_RELEASE, &type, (void **) &release, &count);
                     77:         
                     78:     /* allocate a new rpmData block, fill it */
                     79:     rpm = (rpmDataPtr) malloc(sizeof(rpmData));
                     80:     if (rpm == NULL) {
1.41      veillard   81:         fprintf(stderr, "cannot allocate %d bytes: %s\n", sizeof(rpmData),
                     82:                strerror(errno));
                     83:         return(NULL);
1.1       veillard   84:     }
1.44      veillard   85:     memset(rpm, 0, sizeof(rpmData));
1.6       veillard   86:     rpm->dir = dir;
1.36      veillard   87:     if (tree) {
                     88:         if ((tree->rpmpath != NULL) && (tree->rpmpath[0] != '\0'))
                     89:            rpm->subdir = strdup(tree->rpmpath);
                     90:        else
                     91:            rpm->subdir = NULL;
                     92:     } else
                     93:        rpm->subdir = NULL;
1.20      veillard   94:     rpm->stamp = stamp;
1.1       veillard   95:     rpm->name = strdup(name);
                     96:     rpm->version = strdup(version);
                     97:     rpm->release = strdup(release);
                     98: 
1.26      veillard   99:     /* get all the resources provided by this RPM */
1.2       veillard  100:     if (!headerGetEntry(h, RPMTAG_SUMMARY, &type, &p, &count) || !p) {
1.27      veillard  101:         rpm->summary = strdup(localizedStrings[LANG_NO_SUMMARY]);
1.2       veillard  102:     } else {
1.40      httpng    103:        rpm->summary = strdup((char *) p);
1.2       veillard  104:     }
1.28      veillard  105:     if (!headerGetEntry(h, RPMTAG_DESCRIPTION, &type, &p, &count) || !p ||
                    106:         (type != RPM_STRING_TYPE)) {
1.27      veillard  107:         rpm->description = strdup(localizedStrings[LANG_NO_DESCRIPTION]);
1.2       veillard  108:     } else {
1.40      httpng    109:        rpm->description = strdup((char *) p);
1.2       veillard  110:     }
1.28      veillard  111:     if (!headerGetEntry(h, RPMTAG_DISTRIBUTION, &type, &p, &count) || !p ||
                    112:         (type != RPM_STRING_TYPE)) {
1.27      veillard  113:         rpm->distribution = strdup(localizedStrings[LANG_UNKNOWN]);
1.2       veillard  114:     } else {
                    115:        rpm->distribution = strdup((char *) p);
                    116:     }
1.28      veillard  117:     if (!headerGetEntry(h, RPMTAG_ARCH, &type, &p, &count) || !p ||
                    118:         (type != RPM_STRING_TYPE)) {
1.29      veillard  119:        if (type == RPM_INT8_TYPE) {
                    120:            /*
1.32      veillard  121:             * Old packages.
1.29      veillard  122:             */
                    123:            switch (*((char *) p)) {
                    124:                case 1:
                    125:                    rpm->arch = strdup("i386");
                    126:                    break;
                    127:                default:
                    128:                    rpm->arch = strdup("i386");
                    129:                    break;
                    130:            }
                    131:        } else
                    132:            rpm->arch = strdup(localizedStrings[LANG_NONE]);
1.11      veillard  133:        if (nameRpm == NULL) {
1.12      veillard  134:            sprintf(nameBuffer, "%s-%s-%s.rpm", name, version, release);
1.11      veillard  135:            nameRpm = nameBuffer;
                    136:        }
1.2       veillard  137:     } else {
                    138:        rpm->arch = strdup((char *) p);
1.11      veillard  139:        if (nameRpm == NULL) {
1.12      veillard  140:            sprintf(nameBuffer, "%s-%s-%s.%s.rpm",
                    141:                    name, version, release, (char *)p);
1.11      veillard  142:            nameRpm = nameBuffer;
                    143:        }
1.2       veillard  144:     }
1.28      veillard  145:     if (!headerGetEntry(h, RPMTAG_OS, &type, &p, &count) || !p ||
                    146:         (type != RPM_STRING_TYPE)) {
1.29      veillard  147:        if (type == RPM_INT8_TYPE) {
                    148:            /*
1.32      veillard  149:             * Old packages.
1.29      veillard  150:             */
                    151:            switch (*((char *) p)) {
                    152:                case 1:
                    153:                    rpm->os = strdup("linux");
                    154:                    break;
                    155:                default:
                    156:                    rpm->os = strdup("linux");
                    157:                    break;
                    158:            }
                    159:        } else
                    160:            rpm->os = strdup("");
1.7       veillard  161:     } else {
                    162:        rpm->os = strdup((char *) p);
                    163:     }
1.28      veillard  164:     if (!headerGetEntry(h, RPMTAG_VENDOR, &type, &p, &count) || !p ||
                    165:         (type != RPM_STRING_TYPE)) {
1.7       veillard  166:         rpm->vendor = NULL;
1.2       veillard  167:     } else {
                    168:        rpm->vendor = strdup((char *) p);
                    169:     }
1.28      veillard  170:     if (!headerGetEntry(h, RPMTAG_GROUP, &type, &p, &count) || !p ||
                    171:         (type != RPM_STRING_TYPE)) {
1.27      veillard  172:         rpm->group = strdup(localizedStrings[LANG_NO_GROUP]);
1.2       veillard  173:     } else {
                    174:        rpm->group = strdup((char *) p);
                    175:     }
1.28      veillard  176:     if (!headerGetEntry(h, RPMTAG_BUILDHOST, &type, &p, &count) || !p ||
                    177:         (type != RPM_STRING_TYPE)) {
1.27      veillard  178:         rpm->host = strdup(localizedStrings[LANG_NO_HOST]);
1.2       veillard  179:     } else {
                    180:        rpm->host = strdup((char *) p);
                    181:     }
                    182:     if (!headerGetEntry(h, RPMTAG_SIZE, &type, &p, &count) || !p) {
                    183:         rpm->size = 0;
                    184:     } else {
                    185:        rpm->size = *((int *) p);
                    186:     }
1.11      veillard  187:     if (installed) {
                    188:        if (!headerGetEntry(h, RPMTAG_INSTALLTIME, &type, &p, &count) || !p) {
                    189:            rpm->date = 0;
                    190:        } else {
                    191:            rpm->date = *((int_32 *) p);
                    192:        }
1.2       veillard  193:     } else {
1.11      veillard  194:        if (!headerGetEntry(h, RPMTAG_BUILDTIME, &type, &p, &count) || !p) {
                    195:            rpm->date = 0;
                    196:        } else {
                    197:            rpm->date = *((int_32 *) p);
                    198:        }
1.2       veillard  199:     }
1.28      veillard  200:     if (!headerGetEntry(h, RPMTAG_SOURCERPM, &type, &p, &count) || !p ||
                    201:         (type != RPM_STRING_TYPE)) {
1.27      veillard  202:         rpm->srcrpm = strdup("");
1.2       veillard  203:     } else {
                    204:        rpm->srcrpm = strdup((char *) p);
                    205:     }
1.28      veillard  206:     if (!headerGetEntry(h, RPMTAG_URL, &type, &p, &count) || !p ||
                    207:         (type != RPM_STRING_TYPE)) {
1.7       veillard  208:         rpm->url = NULL;
                    209:     } else {
                    210:        rpm->url = strdup((char *) p);
                    211:     }
1.28      veillard  212:     if (!headerGetEntry(h, RPMTAG_PACKAGER, &type, &p, &count) || !p ||
                    213:         (type != RPM_STRING_TYPE)) {
1.7       veillard  214:         rpm->packager = NULL;
                    215:     } else {
                    216:        rpm->packager = strdup((char *) p);
                    217:     }
1.28      veillard  218:     if (!headerGetEntry(h, RPMTAG_COPYRIGHT, &type, &p, &count) || !p ||
                    219:         (type != RPM_STRING_TYPE)) {
1.7       veillard  220:         rpm->copyright = NULL;
                    221:     } else {
                    222:        rpm->copyright = strdup((char *) p);
                    223:     }
1.31      veillard  224:     /* Pick up changelog entries */
                    225:     if (!headerGetEntry(h, RPMTAG_CHANGELOGTEXT, &type, &p, &count) || !p) {
                    226:         rpm->changelog = NULL;
                    227:     } else {
                    228:       time_t *dates;
                    229:       char **names;
                    230:       char **holdp = (char **)p;
                    231:       char *cp;
                    232:       struct tm *tm_buf;
                    233:       int i, len, pos;
                    234:       char date_string[50];
                    235:       char *res = buffer;
1.42      veillard  236: 
1.31      veillard  237:       *res = '\0';
                    238:       headerGetEntry(h, RPMTAG_CHANGELOGTIME, &type, (void *)&dates, &count);
                    239:       headerGetEntry(h, RPMTAG_CHANGELOGNAME, &type, (void *)&names, &count);
                    240:       for (i = 0;  i < count;  i++) {
1.42      veillard  241:         if ((res - buffer) > (buffer_size - 1024)) {
                    242:            int delta = res - buffer;
                    243: 
1.41      veillard  244:            buffer_size *= 2;
                    245:            buffer = (char *) realloc(buffer, buffer_size);
1.42      veillard  246:            if (buffer == NULL) {
                    247:                fprintf(stderr, "cannot re-allocate %d bytes: %s\n",
                    248:                        buffer_size, strerror(errno));
                    249:                exit(1);
                    250:            }
                    251:            res = &buffer[delta];
1.41      veillard  252:        }
1.31      veillard  253:        tm_buf = localtime(&dates[i]);
                    254:         strftime(date_string, sizeof(date_string) - 1, "%a %b %d %Y", tm_buf);
                    255:        len = sprintf(res, "* %s %s\n", date_string, names[i]);
                    256:        res += len;
                    257:        cp = holdp[i];
                    258:        pos = 0;
                    259:        while (*cp) {
                    260:          if (pos++ == 0) {
                    261:            *res++ = ' ';
                    262:            *res++ = ' ';           
                    263:          }
                    264:          *res++ = *cp;
                    265:          if (*cp++ == '\n') pos = 0;
                    266:        }
                    267:        *res++ = '\n';
                    268:       }
                    269:       *res = '\0';
                    270:       rpm->changelog = strdup(buffer);
                    271:     }
1.7       veillard  272:     if (rpm->vendor == NULL) {
1.15      veillard  273:         if (rpm->packager != NULL) rpm->vendor = strdup(rpm->packager);
                    274:        else rpm->vendor = strdup(localizedStrings[LANG_UNKNOWN]);
1.7       veillard  275:     }
1.2       veillard  276: 
1.11      veillard  277:     rpm->filename = strdup(nameRpm);
                    278: 
1.26      veillard  279:     /* package-xxx.rpm provides the resource "package" */
                    280:     rpm->nb_resources = 1;
                    281:     rpm->resources[0] = rpmRessAdd(name, rpm, installed);
1.10      veillard  282: 
1.1       veillard  283:     val = getTagNumber("RPMTAG_PROVIDES");
                    284:     if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
1.26      veillard  285:         rpm->nb_resources = 1;
1.1       veillard  286:     } else {
1.26      veillard  287:        if (count >= MAX_RES) {
                    288:            fprintf(stderr, "MAX_RES %d overflow, increase the limit!\n",
                    289:                    MAX_RES);
                    290:            count = MAX_RES;
1.1       veillard  291:        }
                    292: 
1.26      veillard  293:         for (i = 0, j = rpm->nb_resources; i < count;j++, i++) {
                    294:            rpm->resources[j] = rpmRessAdd(((char **) p)[i], rpm, installed);
1.4       veillard  295:        }
1.26      veillard  296:        rpm->nb_resources += count;
1.4       veillard  297:     }
                    298: 
                    299:     val = getTagNumber("RPMTAG_REQUIRENAME");
                    300:     if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
                    301:         rpm->nb_requires = 0;
                    302:     } else {
                    303:        if (count >= MAX_REQU) {
                    304:            fprintf(stderr, "MAX_REQU %d overflow, increase the limit!\n",
                    305:                    MAX_REQU);
                    306:            count = MAX_REQU;
                    307:        }
                    308: 
                    309:        rpm->nb_requires = count;
                    310:         for (i = 0; i < count;i++) {
1.11      veillard  311:            rpm->requires[i] = rpmRequAdd(((char **) p)[i], rpm, installed);
1.1       veillard  312:        }
1.5       veillard  313:     }
                    314:     val = getTagNumber("RPMTAG_FILENAMES");
                    315:     if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
1.7       veillard  316:         rpm->filelist = NULL; /* No filelist in the package ! */
1.5       veillard  317:     } else {
                    318:         char *ptr = buffer;
1.42      veillard  319: 
1.5       veillard  320:        for (i = 0; i < count;i++) {
1.42      veillard  321:            if ((ptr - buffer) > (buffer_size - 1024)) {
                    322:                int delta = ptr - buffer;
                    323: 
1.41      veillard  324:                buffer_size *= 2;
                    325:                buffer = (char *) realloc(buffer, buffer_size);
1.42      veillard  326:                if (buffer == NULL) {
                    327:                    fprintf(stderr, "cannot re-allocate %d bytes: %s\n",
                    328:                            buffer_size, strerror(errno));
                    329:                    exit(1);
                    330:                }
                    331:                ptr = &buffer[delta];
1.41      veillard  332:            }
1.5       veillard  333:            ptr += sprintf(ptr, "%s\n", ((char **) p)[i]);
                    334:        }
                    335:        rpm->filelist = strdup(buffer);
1.1       veillard  336:     }
                    337: 
1.37      veillard  338:     /* Add the package files to the real filesystem tree if asked for */
                    339:     if ((dir->build_tree != 0) && (rpm->filelist != NULL)) {
                    340:         char *cur, *filename;
                    341:        
                    342:        cur = rpm->filelist;
                    343:        while ((*cur != '\0') && (*cur != '/')) cur++;
                    344:        filename = cur;
                    345:        while (*cur != '\0') {
                    346:            if ((*cur == '\n') || (*cur == '\r')) {
                    347:                if (cur != filename)
                    348:                    rpmAddRealFile(dir->root, filename, rpm);
                    349:                while ((*cur != '\0') && (*cur != '/')) cur++;
                    350:                 filename = cur;
                    351:            } else
                    352:                cur++;
                    353:        }
                    354:        if (cur != filename)
                    355:            rpmAddRealFile(dir->root, filename, rpm);
                    356:     }
1.17      veillard  357: 
                    358:     /* Register this package */
                    359:     rpmAddSoftware(rpm);
1.7       veillard  360: 
                    361:     /* dump the HTML related to this package */
1.40      httpng    362:     if (rpm2html_dump_html)
                    363:        dumpRpmHtml(rpm, tree);
                    364:     if (rpm2html_dump_rdf)
                    365:        dumpRpmRdf(rpm, tree);
1.7       veillard  366: 
                    367:     /* free large amount of data not used later */
                    368:     if (rpm->filelist) free(rpm->filelist);
1.15      veillard  369:     rpm->filelist = NULL;
1.7       veillard  370:     if (rpm->copyright) free(rpm->copyright);
1.15      veillard  371:     rpm->copyright = NULL;
1.31      veillard  372:     if (rpm->changelog) free(rpm->changelog);
                    373:     rpm->changelog = NULL;
1.15      veillard  374:     if (rpm->description) free(rpm->description);
                    375:     rpm->description = NULL;
1.8       veillard  376: 
                    377:     /* increment the counters */
1.11      veillard  378:     if (installed) {
                    379:        rpm2html_install_files++;
1.21      veillard  380:        rpm2html_install_size += rpm->size / 1024;
1.11      veillard  381:     } else {
                    382:        rpm2html_files++;
1.21      veillard  383:        rpm2html_size += rpm->size / 1024;
1.11      veillard  384:     }
1.7       veillard  385: 
1.32      veillard  386:     return(rpm);
1.11      veillard  387: }
                    388: 
                    389: /*
                    390:  * rpmOpen : open an RPM file, read and parse the header and 
                    391:  *           fill the informations in the database.
                    392:  */
1.35      veillard  393: rpmDataPtr rpmOpen(char *nameRpm, rpmDirPtr dir, rpmSubdirPtr tree) {
1.32      veillard  394:     rpmDataPtr cur;
1.11      veillard  395:     int fd;
                    396:     int rc;
                    397:     Header h = NULL;
                    398:     int isSource;
                    399:     char buffer[500];
1.20      veillard  400:     struct stat buf;
1.11      veillard  401: 
                    402:     /* open the file for reading */
1.35      veillard  403:     if (tree->htmlpath[0] != '\0')
                    404:        sprintf(buffer, "%s/%s/%s", dir->rpmdir, tree->rpmpath, nameRpm);
1.24      veillard  405:     else
                    406:        sprintf(buffer, "%s/%s", dir->rpmdir, nameRpm);
1.11      veillard  407:     if ((fd = open(buffer, O_RDONLY)) < 0) {
                    408:          fprintf(stderr, "open of %s failed: %s\n", buffer,
                    409:                 strerror(errno));
1.32      veillard  410:         return(NULL);
1.11      veillard  411:     }
                    412: 
1.20      veillard  413:     stat(buffer, &buf);
                    414: 
1.11      veillard  415:     /* read the RPM header */
                    416:     rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
                    417:     switch (rc) {
                    418:        case 0:
                    419:            if (!h) {
                    420:                fprintf(stderr,
                    421:                        "old format source packages cannot be queried\n");
1.32      veillard  422:                return(NULL);
1.11      veillard  423:            }
                    424:            break;
                    425:        case 1:
                    426:            fprintf(stderr, "%s does not appear to be a RPM package\n",
                    427:                    nameRpm);
1.32      veillard  428:            return(NULL);
1.11      veillard  429:        case 2:
                    430:            fprintf(stderr, "query of %s failed\n", nameRpm);
1.32      veillard  431:            return(NULL);
1.11      veillard  432:        default:
                    433:            fprintf(stderr, "rpmReadPackageHeader(%s): unknown error %d\n",
                    434:                    nameRpm, rc);
1.32      veillard  435:            return(NULL);
1.11      veillard  436:     }
                    437: 
1.36      veillard  438:     cur = rpmAnalyze(nameRpm, h, dir, tree, buf.st_mtime);
1.11      veillard  439: 
                    440:     /* free the header and close the descriptor */
                    441:     headerFree(h);
                    442:     close(fd);
1.1       veillard  443: 
1.32      veillard  444:     return(cur);
1.6       veillard  445: }
                    446: 
                    447: /*
1.22      veillard  448:  * Scan one directory for RPM files this is where the recursive handling
                    449:  * is done.
1.6       veillard  450:  */
1.35      veillard  451: static rpmDataPtr rpmOneDirScan(rpmDirPtr dir, rpmSubdirPtr tree) {
                    452:     rpmSubdirPtr subtree;
1.32      veillard  453:     rpmDataPtr ret = NULL, cur;
1.7       veillard  454:     char *filename;
1.22      veillard  455:     static char path[2000];
1.23      veillard  456:     struct stat buf;
1.7       veillard  457:     int len;
1.39      veillard  458:     DIR *d;
                    459:     struct dirent *file;
1.6       veillard  460: 
1.24      veillard  461: 
                    462:     /*
                    463:      * Create the directory for the HTML pages
                    464:      */
1.45      veillard  465:     if (rpm2html_dump_html) {
                    466:        if (tree->htmlpath[0] != '\0')
                    467:            sprintf(path, "%s/%s", dir->dir, tree->htmlpath);
                    468:        else
                    469:            sprintf(path, "%s", dir->dir);
                    470:        createDirectory(path);
                    471:     }
1.43      veillard  472: 
                    473:     /*
                    474:      * Create the directory for the RDF pages
                    475:     if (rpm2html_rdf_dir != NULL) {
                    476:        if (tree->htmlpath[0] != '\0')
                    477:            sprintf(path, "%s/%s", rpm2html_rdf_dir, tree->htmlpath);
                    478:        else
                    479:            sprintf(path, "%s", rpm2html_rdf_dir);
                    480:         createDirectory(path);
                    481:     }
1.47    ! veillard  482:      */
1.24      veillard  483: 
                    484:     /*
                    485:      * Scan the repository.
                    486:      */
1.35      veillard  487:     if (tree->rpmpath[0] != '\0')
                    488:        sprintf(path, "%s/%s", dir->rpmdir, tree->rpmpath);
1.24      veillard  489:     else
                    490:        sprintf(path, "%s", dir->rpmdir);
1.35      veillard  491:     if (verbose > 1)
1.24      veillard  492:         fprintf(stderr, "Scanning directory %s\n", path);
                    493: 
1.39      veillard  494:     d = opendir(path);
                    495:     if (d == NULL) {
1.24      veillard  496:         fprintf(stderr, "Listing of %s failed: %s\n", path,
1.6       veillard  497:                strerror(errno));
1.35      veillard  498:         rpmRemoveSubdir(tree);
1.36      veillard  499:         rpmFreeSubdir(tree);
1.32      veillard  500:        return(NULL);
1.6       veillard  501:     } else {
1.39      veillard  502:         while ((file = readdir(d)) != NULL) {
1.32      veillard  503:            cur = NULL;
1.39      veillard  504:            filename = file->d_name;
1.7       veillard  505:            len = strlen(filename);
1.24      veillard  506: 
                    507:            /*
                    508:             * Compute the full path
                    509:             */
1.35      veillard  510:            if (tree->rpmpath[0] != '\0')
                    511:                sprintf(path, "%s/%s/%s", dir->rpmdir, tree->rpmpath,
                    512:                        filename);
1.22      veillard  513:            else
1.24      veillard  514:                sprintf(path, "%s/%s", dir->rpmdir, filename);
1.22      veillard  515: 
                    516:            /*
1.25      veillard  517:             * Stat() the file to detect directory and symlimks
                    518:             */
1.30      veillard  519:            if (lstat(path, &buf) != 0) {
1.25      veillard  520:                fprintf(stderr, "Couldn't stat(%s)\n", path);
                    521:                continue;
                    522:            }
1.35      veillard  523: 
1.25      veillard  524:            /*
                    525:             * Don't follow of analyze symlinks,
                    526:             */
                    527:             if (S_ISLNK(buf.st_mode)) {
                    528:                if (verbose)
                    529:                    fprintf(stderr, "Dropping symlink %s\n", path);
                    530:                continue;
                    531:            }
1.35      veillard  532: 
1.25      veillard  533:            /*
1.23      veillard  534:             * Check for RPM files by looking at the suffix
1.22      veillard  535:             */
1.25      veillard  536:            else if ((len >= 5) && (!strcasecmp(&filename[len - 4], ".rpm"))) {
1.35      veillard  537:                cur = rpmOpen(filename, dir, tree);
1.44      veillard  538:            }
                    539: 
                    540:            /*
                    541:             * Check for RDF files by looking at the suffix
                    542:             */
                    543:            else if ((len >= 5) && (!strcasecmp(&filename[len - 4], ".rdf"))) {
                    544:                cur = rpmOpenRdf(filename, dir, tree);
1.22      veillard  545:            }
1.35      veillard  546: 
1.22      veillard  547:            /*
1.23      veillard  548:             * Else if this is a directory, recurse !
1.22      veillard  549:             */
1.25      veillard  550:            else if (S_ISDIR(buf.st_mode)) {
                    551:                if (filename[0] != '.') {
1.35      veillard  552:                    subtree = rpmNewSubdir(tree, filename, NULL, NULL, NULL);
                    553:                    cur = rpmOneDirScan(dir, subtree);
1.25      veillard  554:                }
1.22      veillard  555:            }
1.32      veillard  556:            if (cur != NULL) ret = rpmAddList(ret, cur);
1.7       veillard  557:        }
1.6       veillard  558:     }
1.39      veillard  559:     closedir(d);
1.33      veillard  560: 
                    561:     /*
                    562:      * Dump the pages related to this directory.
                    563:      */
1.35      veillard  564:     if (ret != NULL) ret = dumpDirIndex(dir, tree, ret);
1.36      veillard  565:     else {
                    566:         rpmRemoveSubdir(tree);
                    567:        rpmFreeSubdir(tree);
                    568:     }
1.35      veillard  569: 
1.32      veillard  570:     return(ret);
1.22      veillard  571: }
                    572: 
                    573: /*
                    574:  * Scan a directory for RPM files.
                    575:  */
1.35      veillard  576: static rpmDataPtr rpmDirScan(rpmDirPtr dir, rpmSubdirPtr tree) {
1.37      veillard  577:     rpmSubdirPtr cur;
                    578:     rpmDataPtr ret;
                    579:     
1.45      veillard  580:     if ((rpm2html_dump_html) && (dir->build_tree != 0)) {
1.37      veillard  581:        dir->root = rpmCreateRealRoot();
                    582:     }
                    583:     cur = rpmNewSubdir(tree, dir->name,
                    584:               dir->subdir == NULL ? "" : dir->subdir, "", dir->color);
                    585:     ret = rpmOneDirScan(dir, cur);
1.38      veillard  586:     rpmDumpHtmlRealRoot(dir);
1.37      veillard  587:     return(ret);
1.6       veillard  588: }
                    589: 
                    590: /*
1.11      veillard  591:  * Scan the local RPM database for RPM files.
                    592:  */
1.32      veillard  593: static rpmDataPtr rpmBaseScan(rpmDirPtr dir) {
1.37      veillard  594:     static char path[2000];
1.32      veillard  595:     rpmDataPtr ret = NULL, cur;
1.11      veillard  596:     rpmdb db;
                    597:     Header h = NULL;
1.32      veillard  598:     int offset;
1.11      veillard  599:     char *prefix = "/";
                    600: 
1.37      veillard  601:     /*
                    602:      * Create the directory for the HTML pages
                    603:      */
1.45      veillard  604:     if (rpm2html_dump_html) {
                    605:        if (dir->subdir)
                    606:            sprintf(path, "%s/%s", dir->dir, dir->subdir);
                    607:        else
                    608:            sprintf(path, "%s", dir->dir);
                    609:        createDirectory(path);
                    610:     }
                    611: 
                    612:     /*
                    613:      * Create the directory for the RDF pages
                    614:      */
                    615:     if (rpm2html_rdf_dir != NULL) {
                    616:        if (dir->subdir)
                    617:            sprintf(path, "%s/%s", rpm2html_rdf_dir, dir->subdir);
                    618:        else
                    619:            sprintf(path, "%s", rpm2html_rdf_dir);
                    620:         createDirectory(path);
                    621:     }
1.37      veillard  622: 
1.11      veillard  623:     if (rpmdbOpen(prefix, &db, O_RDONLY, 0644)) {
1.32      veillard  624:         return(NULL);
1.11      veillard  625:     }
                    626:     offset = rpmdbFirstRecNum(db);
                    627:     while (offset) {
                    628:         h = rpmdbGetRecord(db, offset);
                    629:        if (!h) {
                    630:            fprintf(stderr, "could not read database record!\n");
1.32      veillard  631:            return(ret);
1.11      veillard  632:        }
1.36      veillard  633:        cur = rpmAnalyze(NULL, h, dir, NULL, 0);
1.32      veillard  634:        if (cur != NULL) ret = rpmAddList(ret, cur);
1.11      veillard  635:        headerFree(h);
                    636:        offset = rpmdbNextRecNum(db, offset);
                    637:     }
                    638:     rpmdbClose(db);
                    639: 
1.32      veillard  640:     return(ret);
1.11      veillard  641: }
                    642: 
                    643: /*
1.6       veillard  644:  * Scan all registered directories.
                    645:  * One fist check for completeness of the informations in
                    646:  * the rpmDir structure.
                    647:  */
                    648: 
1.32      veillard  649: rpmDataPtr rpmDirScanAll(void) {
1.18      veillard  650:     rpmDirPtr dir, next;
1.32      veillard  651:     rpmDataPtr ret = NULL, cur;
1.46      veillard  652:     int maxLists = 50;
                    653:     rpmDataPtr *rpmLists;
1.35      veillard  654:     int nbLists = 0;
                    655:     int i;
1.18      veillard  656: 
                    657:     /*
                    658:      * first reverse the list ....
                    659:      */
                    660:     dir = dirList;
                    661:     dirList = NULL;
                    662:     while (dir != NULL) {
                    663:         next = dir->next;
                    664:        dir->next = dirList;
                    665:        dirList = dir;
                    666:        dir = next;
                    667:     }
                    668: 
1.35      veillard  669:     /*
                    670:      * Allocate a directory tree.
                    671:      */
                    672:     dirTree = rpmNewSubdir(NULL, "", "", "", NULL);
1.37      veillard  673: 
1.18      veillard  674:     dir = dirList;
1.6       veillard  675: 
1.46      veillard  676:     rpmLists = (rpmDataPtr *) malloc(maxLists * sizeof(rpmDataPtr));
                    677:     if (rpmLists == NULL) {
                    678:         fprintf(stderr, "rpmDirScanAll : running out of memory !\n");
                    679:        exit(1);
                    680:     }
                    681: 
1.6       veillard  682:     while (dir != NULL) {
1.32      veillard  683:         cur  = NULL;
                    684: 
1.14      veillard  685:        /*
                    686:         * Override default setting.
                    687:         */
1.15      veillard  688:        if ((dir->maint == NULL) && (rpm2html_maint != NULL))
                    689:            dir->maint = strdup(rpm2html_maint);
                    690:        if ((dir->mail == NULL) && (rpm2html_mail != NULL))
                    691:            dir->mail = strdup(rpm2html_mail);
                    692:        if ((dir->ftp == NULL) && (rpm2html_ftp != NULL))
                    693:            dir->ftp = strdup(rpm2html_ftp);
                    694:        if ((dir->ftpsrc == NULL) && (rpm2html_ftpsrc != NULL))
                    695:            dir->ftpsrc = strdup(rpm2html_ftpsrc);
                    696:        if ((dir->dir == NULL) && (rpm2html_dir != NULL))
                    697:            dir->dir = strdup(rpm2html_dir);
                    698:        if ((dir->host == NULL) && (rpm2html_host != NULL))
                    699:            dir->host = strdup(rpm2html_host);
                    700:        if ((dir->name == NULL) && (rpm2html_name != NULL))
                    701:            dir->name = strdup(rpm2html_name);
                    702:        if ((dir->url == NULL) && (rpm2html_url != NULL))
                    703:            dir->url = strdup(rpm2html_url);
1.14      veillard  704: 
                    705:         if (dir->rpmdir == NULL) {
1.6       veillard  706:            fprintf(stderr, "?!? rpmDir without directory ?!? disabled !\n");
1.14      veillard  707:        } else if (!strcmp(dir->rpmdir, "localbase")) {
1.11      veillard  708:            /* Scan the local RPM database instead of a directory */
1.32      veillard  709:             cur = rpmBaseScan(dir);
1.7       veillard  710:        } else if (dir->ftp == NULL) {
                    711:            fprintf(stderr, "Directory %s disabled : no ftp field\n",
1.14      veillard  712:                    dir->rpmdir);
1.6       veillard  713:        } else {
1.16      veillard  714:            if (verbose)
                    715:                fprintf(stderr, "Scanning directory %s for RPMs\n",dir->rpmdir);
1.35      veillard  716:            cur = rpmDirScan(dir, dirTree);
1.6       veillard  717:        }
                    718: 
1.35      veillard  719:        if (cur != NULL) {
1.46      veillard  720:            if (nbLists >= maxLists) {
                    721:                maxLists *= 2;
                    722:                rpmLists = (rpmDataPtr *) realloc(rpmLists,
                    723:                                             maxLists * sizeof(rpmDataPtr));
                    724:                if (rpmLists == NULL) {
                    725:                    fprintf(stderr, "rpmDirScanAll : running out of memory!\n");
                    726:                    exit(1);
1.35      veillard  727:                }
                    728:            }
1.46      veillard  729:            rpmLists[nbLists] = cur;
                    730:            nbLists++;
1.39      veillard  731:        }
                    732:        if (dir->root != NULL) {
                    733:            if (rpm2html_build_tree)
                    734:                treeRoot = rpmMergeRealRoots(treeRoot, dir->root);
                    735:             else
                    736:                rpmDestroyRealRoot(dir->root);
1.35      veillard  737:        }
1.32      veillard  738: 
1.6       veillard  739:         dir = dir->next;
                    740:     }
1.35      veillard  741:     for (i = 0;i < nbLists;i++)
                    742:        ret = rpmAddList(ret, rpmLists[i]);
1.46      veillard  743:     free(rpmLists);
1.32      veillard  744:     return(ret);
1.1       veillard  745: }
                    746: 

Webmaster