Annotation of rpm2html/rpmopen.c, revision 1.20

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.20    ! veillard    7:  * $Id: rpmopen.c,v 1.19 1998/01/10 03:52:20 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.1       veillard   24: 
                     25: #include <rpm/rpmlib.h>
                     26: 
                     27: #include "rpmdata.h"
1.7       veillard   28: #include "html.h"
1.8       veillard   29: #include "rpm2html.h"
1.12      veillard   30: #include "language.h"
1.1       veillard   31: 
                     32: /*
                     33:  * Get the internal number associated to an RPM tag.
                     34:  */
                     35: static int getTagNumber(char *tag) {
                     36:     int i;
                     37:     const struct headerTagTableEntry * t;
                     38: 
                     39:     for (i = 0, t = rpmTagTable; i < rpmTagTableSize; i++, t++) {
                     40:        if (!strcasecmp(tag, t->name)) return(t->val);
                     41:     }
                     42:     fprintf(stderr, "getTagNumber(%s) : unknown tag !\n", tag);
                     43:     return(-1);
                     44: }
                     45: 
                     46: /*
1.11      veillard   47:  * rpmAnalyze : analyze an RPM record, read and parse the header and 
                     48:  *              fill the informations in the database.
1.1       veillard   49:  */
1.20    ! veillard   50: int rpmAnalyze(char *nameRpm, Header h, rpmDirPtr dir, time_t stamp) {
1.11      veillard   51:     int installed = dir->installbase;
1.2       veillard   52:     char * name = NULL, * version = NULL, * release = NULL;
1.1       veillard   53:     int_32 count, type;
1.2       veillard   54:     void * p = NULL;
1.10      veillard   55:     int val, i, j;
1.1       veillard   56:     rpmDataPtr rpm = NULL;
1.5       veillard   57:     static char buffer[500000];
1.11      veillard   58:     static char nameBuffer[500];
1.1       veillard   59: 
                     60:     /* extract informations from the header */
                     61:     headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &count);
                     62:     headerGetEntry(h, RPMTAG_VERSION, &type, (void **) &version, &count);
                     63:     headerGetEntry(h, RPMTAG_RELEASE, &type, (void **) &release, &count);
                     64:         
                     65:     /* allocate a new rpmData block, fill it */
                     66:     rpm = (rpmDataPtr) malloc(sizeof(rpmData));
1.15      veillard   67:     memset(rpm, 0, sizeof(rpmData));
1.1       veillard   68:     if (rpm == NULL) {
                     69:          fprintf(stderr, "cannot allocate %d bytes: %s\n", sizeof(rpmData),
                     70:                 strerror(errno));
1.11      veillard   71:          return(-1);
1.1       veillard   72:     }
1.6       veillard   73:     rpm->dir = dir;
1.20    ! veillard   74:     rpm->stamp = stamp;
1.1       veillard   75:     rpm->name = strdup(name);
                     76:     rpm->version = strdup(version);
                     77:     rpm->release = strdup(release);
                     78: 
                     79:     /* get all the ressources provided by this RPM */
1.2       veillard   80:     if (!headerGetEntry(h, RPMTAG_SUMMARY, &type, &p, &count) || !p) {
1.12      veillard   81:         rpm->summary = localizedStrings[LANG_NO_SUMMARY];
1.2       veillard   82:     } else {
1.19      veillard   83:        rpm->summary = strdupHTML((char *) p);
1.2       veillard   84:     }
                     85:     if (!headerGetEntry(h, RPMTAG_DESCRIPTION, &type, &p, &count) || !p) {
1.12      veillard   86:         rpm->description = localizedStrings[LANG_NO_DESCRIPTION];
1.2       veillard   87:     } else {
1.19      veillard   88:        rpm->description = strdupHTML((char *) p);
1.2       veillard   89:     }
                     90:     if (!headerGetEntry(h, RPMTAG_DISTRIBUTION, &type, &p, &count) || !p) {
1.12      veillard   91:         rpm->distribution = localizedStrings[LANG_UNKNOWN];
1.2       veillard   92:     } else {
                     93:        rpm->distribution = strdup((char *) p);
                     94:     }
                     95:     if (!headerGetEntry(h, RPMTAG_ARCH, &type, &p, &count) || !p) {
1.12      veillard   96:         rpm->arch = localizedStrings[LANG_NONE];
1.11      veillard   97:        if (nameRpm == NULL) {
1.12      veillard   98:            sprintf(nameBuffer, "%s-%s-%s.rpm", name, version, release);
1.11      veillard   99:            nameRpm = nameBuffer;
                    100:        }
1.2       veillard  101:     } else {
                    102:        rpm->arch = strdup((char *) p);
1.11      veillard  103:        if (nameRpm == NULL) {
1.12      veillard  104:            sprintf(nameBuffer, "%s-%s-%s.%s.rpm",
                    105:                    name, version, release, (char *)p);
1.11      veillard  106:            nameRpm = nameBuffer;
                    107:        }
1.2       veillard  108:     }
1.7       veillard  109:     if (!headerGetEntry(h, RPMTAG_OS, &type, &p, &count) || !p) {
                    110:         rpm->os = "";
                    111:     } else {
                    112:        rpm->os = strdup((char *) p);
                    113:     }
1.2       veillard  114:     if (!headerGetEntry(h, RPMTAG_VENDOR, &type, &p, &count) || !p) {
1.7       veillard  115:         rpm->vendor = NULL;
1.2       veillard  116:     } else {
                    117:        rpm->vendor = strdup((char *) p);
                    118:     }
                    119:     if (!headerGetEntry(h, RPMTAG_GROUP, &type, &p, &count) || !p) {
1.12      veillard  120:         rpm->group = localizedStrings[LANG_NO_GROUP];
1.2       veillard  121:     } else {
                    122:        rpm->group = strdup((char *) p);
                    123:     }
                    124:     if (!headerGetEntry(h, RPMTAG_BUILDHOST, &type, &p, &count) || !p) {
1.12      veillard  125:         rpm->host = localizedStrings[LANG_NO_HOST];
1.2       veillard  126:     } else {
                    127:        rpm->host = strdup((char *) p);
                    128:     }
                    129:     if (!headerGetEntry(h, RPMTAG_SIZE, &type, &p, &count) || !p) {
                    130:         rpm->size = 0;
                    131:     } else {
                    132:        rpm->size = *((int *) p);
                    133:     }
1.11      veillard  134:     if (installed) {
                    135:        if (!headerGetEntry(h, RPMTAG_INSTALLTIME, &type, &p, &count) || !p) {
                    136:            rpm->date = 0;
                    137:        } else {
                    138:            rpm->date = *((int_32 *) p);
                    139:        }
1.2       veillard  140:     } else {
1.11      veillard  141:        if (!headerGetEntry(h, RPMTAG_BUILDTIME, &type, &p, &count) || !p) {
                    142:            rpm->date = 0;
                    143:        } else {
                    144:            rpm->date = *((int_32 *) p);
                    145:        }
1.2       veillard  146:     }
                    147:     if (!headerGetEntry(h, RPMTAG_SOURCERPM, &type, &p, &count) || !p) {
                    148:         rpm->srcrpm = "";
                    149:     } else {
                    150:        rpm->srcrpm = strdup((char *) p);
                    151:     }
1.7       veillard  152:     if (!headerGetEntry(h, RPMTAG_URL, &type, &p, &count) || !p) {
                    153:         rpm->url = NULL;
                    154:     } else {
                    155:        rpm->url = strdup((char *) p);
                    156:     }
                    157:     if (!headerGetEntry(h, RPMTAG_PACKAGER, &type, &p, &count) || !p) {
                    158:         rpm->packager = NULL;
                    159:     } else {
                    160:        rpm->packager = strdup((char *) p);
                    161:     }
                    162:     if (!headerGetEntry(h, RPMTAG_COPYRIGHT, &type, &p, &count) || !p) {
                    163:         rpm->copyright = NULL;
                    164:     } else {
                    165:        rpm->copyright = strdup((char *) p);
                    166:     }
                    167:     if (rpm->vendor == NULL) {
1.15      veillard  168:         if (rpm->packager != NULL) rpm->vendor = strdup(rpm->packager);
                    169:        else rpm->vendor = strdup(localizedStrings[LANG_UNKNOWN]);
1.7       veillard  170:     }
1.2       veillard  171: 
1.11      veillard  172:     rpm->filename = strdup(nameRpm);
                    173: 
1.10      veillard  174:     /* package-xxx.rpm provides the ressource "package" */
                    175:     rpm->nb_ressources = 1;
1.11      veillard  176:     rpm->ressources[0] = rpmRessAdd(name, rpm, installed);
1.10      veillard  177: 
1.1       veillard  178:     val = getTagNumber("RPMTAG_PROVIDES");
                    179:     if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
1.10      veillard  180:         rpm->nb_ressources = 1;
1.1       veillard  181:     } else {
                    182:        if (count >= MAX_RESS) {
                    183:            fprintf(stderr, "MAX_RESS %d overflow, increase the limit!\n",
                    184:                    MAX_RESS);
                    185:            count = MAX_RESS;
                    186:        }
                    187: 
1.10      veillard  188:         for (i = 0, j = rpm->nb_ressources; i < count;j++, i++) {
1.11      veillard  189:            rpm->ressources[j] = rpmRessAdd(((char **) p)[i], rpm, installed);
1.4       veillard  190:        }
1.10      veillard  191:        rpm->nb_ressources += count;
1.4       veillard  192:     }
                    193: 
                    194:     val = getTagNumber("RPMTAG_REQUIRENAME");
                    195:     if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
                    196:         rpm->nb_requires = 0;
                    197:     } else {
                    198:        if (count >= MAX_REQU) {
                    199:            fprintf(stderr, "MAX_REQU %d overflow, increase the limit!\n",
                    200:                    MAX_REQU);
                    201:            count = MAX_REQU;
                    202:        }
                    203: 
                    204:        rpm->nb_requires = count;
                    205:         for (i = 0; i < count;i++) {
1.11      veillard  206:            rpm->requires[i] = rpmRequAdd(((char **) p)[i], rpm, installed);
1.1       veillard  207:        }
1.5       veillard  208:     }
                    209:     val = getTagNumber("RPMTAG_FILENAMES");
                    210:     if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
1.7       veillard  211:         rpm->filelist = NULL; /* No filelist in the package ! */
1.5       veillard  212:     } else {
                    213:         char *ptr = buffer;
                    214:        for (i = 0; i < count;i++) {
                    215:            ptr += sprintf(ptr, "%s\n", ((char **) p)[i]);
                    216:        }
                    217:        rpm->filelist = strdup(buffer);
1.1       veillard  218:     }
                    219: 
                    220:     /* insert the package informations in the database */
1.11      veillard  221:     if (installed) {
                    222:        rpm->next = rpmInstalledList;
                    223:        rpmInstalledList = rpm;
                    224:     } else {
                    225:        rpm->next = rpmList;
                    226:        rpmList = rpm;
                    227:     }
1.17      veillard  228: 
                    229:     /* Register this package */
                    230:     rpmAddSoftware(rpm);
1.7       veillard  231: 
                    232:     /* dump the HTML related to this package */
                    233:     dumpRpmHtml(rpm);
                    234: 
                    235:     /* free large amount of data not used later */
                    236:     if (rpm->filelist) free(rpm->filelist);
1.15      veillard  237:     rpm->filelist = NULL;
1.7       veillard  238:     if (rpm->copyright) free(rpm->copyright);
1.15      veillard  239:     rpm->copyright = NULL;
                    240:     if (rpm->description) free(rpm->description);
                    241:     rpm->description = NULL;
1.8       veillard  242: 
                    243:     /* increment the counters */
1.11      veillard  244:     if (installed) {
                    245:        rpm2html_install_files++;
                    246:        rpm2html_install_size += rpm->size;
                    247:     } else {
                    248:        rpm2html_files++;
                    249:        rpm2html_size += rpm->size;
                    250:     }
1.7       veillard  251: 
1.1       veillard  252:     return(0);
1.11      veillard  253: }
                    254: 
                    255: /*
                    256:  * rpmOpen : open an RPM file, read and parse the header and 
                    257:  *           fill the informations in the database.
                    258:  */
                    259: int rpmOpen(char *nameRpm, rpmDirPtr dir) {
                    260:     int fd;
                    261:     int rc;
                    262:     int n;
                    263:     Header h = NULL;
                    264:     int isSource;
                    265:     char buffer[500];
1.20    ! veillard  266:     struct stat buf;
1.11      veillard  267: 
                    268:     /* open the file for reading */
1.14      veillard  269:     sprintf(buffer, "%s/%s", dir->rpmdir, nameRpm);
1.11      veillard  270:     if ((fd = open(buffer, O_RDONLY)) < 0) {
                    271:          fprintf(stderr, "open of %s failed: %s\n", buffer,
                    272:                 strerror(errno));
                    273:         return(-1);
                    274:     }
                    275: 
1.20    ! veillard  276:     stat(buffer, &buf);
        !           277: 
1.11      veillard  278:     /* read the RPM header */
                    279:     rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
                    280:     switch (rc) {
                    281:        case 0:
                    282:            if (!h) {
                    283:                fprintf(stderr,
                    284:                        "old format source packages cannot be queried\n");
                    285:                return(-1);
                    286:            }
                    287:            break;
                    288:        case 1:
                    289:            fprintf(stderr, "%s does not appear to be a RPM package\n",
                    290:                    nameRpm);
                    291:            return(-1);
                    292:        case 2:
                    293:            fprintf(stderr, "query of %s failed\n", nameRpm);
                    294:            return(-1);
                    295:        default:
                    296:            fprintf(stderr, "rpmReadPackageHeader(%s): unknown error %d\n",
                    297:                    nameRpm, rc);
                    298:            return(-1);
                    299:     }
                    300: 
1.20    ! veillard  301:     n = rpmAnalyze(nameRpm, h, dir, buf.st_mtime);
1.11      veillard  302: 
                    303:     /* free the header and close the descriptor */
                    304:     headerFree(h);
                    305:     close(fd);
1.1       veillard  306: 
1.11      veillard  307:     return(n);
1.6       veillard  308: }
                    309: 
                    310: /*
                    311:  * Scan a directory for RPM files.
                    312:  */
                    313: static int rpmDirScan(rpmDirPtr dir) {
                    314:     struct dirent **namelist;
1.7       veillard  315:     char *filename;
                    316:     int len;
1.6       veillard  317:     int n, i;
                    318: 
1.14      veillard  319:     n = scandir(dir->rpmdir, &namelist, 0, alphasort);
1.6       veillard  320:     if (n < 0) {
1.14      veillard  321:         fprintf(stderr, "Listing of %s failed: %s\n", dir->rpmdir,
1.6       veillard  322:                strerror(errno));
                    323:        return(-1);
                    324:     } else {
1.7       veillard  325:         for (i = 0;i < n;i++) {
                    326:            /* check that this is a RPM file by looking at the suffix */
                    327:            filename = namelist[i]->d_name;
                    328:            len = strlen(filename);
                    329:            if ((len >= 5) && (!strcasecmp(&filename[len - 4], ".rpm")))
                    330:                rpmOpen(filename, dir);
                    331:        }
1.6       veillard  332:     }
                    333:     free(namelist);
                    334:     return(n);
                    335: }
                    336: 
                    337: /*
1.11      veillard  338:  * Scan the local RPM database for RPM files.
                    339:  */
                    340: static int rpmBaseScan(rpmDirPtr dir) {
                    341:     rpmdb db;
                    342:     Header h = NULL;
                    343:     int offset, n = 0;
                    344:     char *prefix = "/";
                    345: 
                    346:     if (rpmdbOpen(prefix, &db, O_RDONLY, 0644)) {
                    347:         return(n);
                    348:     }
                    349:     offset = rpmdbFirstRecNum(db);
                    350:     while (offset) {
                    351:         h = rpmdbGetRecord(db, offset);
                    352:        if (!h) {
                    353:            fprintf(stderr, "could not read database record!\n");
                    354:            return(n);
                    355:        }
1.20    ! veillard  356:        rpmAnalyze(NULL, h, dir, 0);
1.11      veillard  357:        headerFree(h);
                    358:        offset = rpmdbNextRecNum(db, offset);
                    359:     }
                    360:     rpmdbClose(db);
                    361: 
                    362:     return(n);
                    363: }
                    364: 
                    365: /*
1.6       veillard  366:  * Scan all registered directories.
                    367:  * One fist check for completeness of the informations in
                    368:  * the rpmDir structure.
                    369:  */
                    370: 
                    371: int rpmDirScanAll(void) {
1.7       veillard  372:     int n = 0, i;
                    373: 
1.18      veillard  374:     rpmDirPtr dir, next;
                    375: 
                    376:     /*
                    377:      * first reverse the list ....
                    378:      */
                    379:     dir = dirList;
                    380:     dirList = NULL;
                    381:     while (dir != NULL) {
                    382:         next = dir->next;
                    383:        dir->next = dirList;
                    384:        dirList = dir;
                    385:        dir = next;
                    386:     }
                    387: 
                    388:     dir = dirList;
1.6       veillard  389: 
                    390:     while (dir != NULL) {
1.14      veillard  391:        /*
                    392:         * Override default setting.
                    393:         */
1.15      veillard  394:        if ((dir->maint == NULL) && (rpm2html_maint != NULL))
                    395:            dir->maint = strdup(rpm2html_maint);
                    396:        if ((dir->mail == NULL) && (rpm2html_mail != NULL))
                    397:            dir->mail = strdup(rpm2html_mail);
                    398:        if ((dir->ftp == NULL) && (rpm2html_ftp != NULL))
                    399:            dir->ftp = strdup(rpm2html_ftp);
                    400:        if ((dir->ftpsrc == NULL) && (rpm2html_ftpsrc != NULL))
                    401:            dir->ftpsrc = strdup(rpm2html_ftpsrc);
                    402:        if ((dir->dir == NULL) && (rpm2html_dir != NULL))
                    403:            dir->dir = strdup(rpm2html_dir);
                    404:        if ((dir->host == NULL) && (rpm2html_host != NULL))
                    405:            dir->host = strdup(rpm2html_host);
                    406:        if ((dir->name == NULL) && (rpm2html_name != NULL))
                    407:            dir->name = strdup(rpm2html_name);
                    408:        if ((dir->url == NULL) && (rpm2html_url != NULL))
                    409:            dir->url = strdup(rpm2html_url);
1.14      veillard  410: 
                    411:         if (dir->rpmdir == NULL) {
1.6       veillard  412:            fprintf(stderr, "?!? rpmDir without directory ?!? disabled !\n");
1.14      veillard  413:        } else if (!strcmp(dir->rpmdir, "localbase")) {
1.11      veillard  414:            /* Scan the local RPM database instead of a directory */
                    415:             i = rpmBaseScan(dir);
                    416:            if (i > 0) n += i;
1.7       veillard  417:        } else if (dir->ftp == NULL) {
                    418:            fprintf(stderr, "Directory %s disabled : no ftp field\n",
1.14      veillard  419:                    dir->rpmdir);
1.6       veillard  420:        } else {
1.16      veillard  421:            if (verbose)
                    422:                fprintf(stderr, "Scanning directory %s for RPMs\n",dir->rpmdir);
1.7       veillard  423:            i = rpmDirScan(dir);
                    424:            if (i > 0) n += i;
1.6       veillard  425:        }
                    426: 
                    427:         dir = dir->next;
                    428:     }
1.7       veillard  429:     return(n);
1.1       veillard  430: }
                    431: 

Webmaster