Annotation of rpm2html/rpmopen.c, revision 1.50

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

Webmaster