Annotation of rpm2html/rpmopen.c, revision 1.54

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

Webmaster