Annotation of rpm2html/rpmopen.c, revision 1.13

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.13    ! veillard    7:  * $Id: rpmopen.c,v 1.12 1997/11/16 08:25:49 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.11      veillard   50: int rpmAnalyze(char *nameRpm, Header h, rpmDirPtr dir) {
                     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));
                     67:     if (rpm == NULL) {
                     68:          fprintf(stderr, "cannot allocate %d bytes: %s\n", sizeof(rpmData),
                     69:                 strerror(errno));
1.11      veillard   70:          return(-1);
1.1       veillard   71:     }
1.6       veillard   72:     rpm->dir = dir;
1.1       veillard   73:     rpm->name = strdup(name);
                     74:     rpm->version = strdup(version);
                     75:     rpm->release = strdup(release);
                     76: 
                     77:     /* get all the ressources provided by this RPM */
1.2       veillard   78:     if (!headerGetEntry(h, RPMTAG_SUMMARY, &type, &p, &count) || !p) {
1.12      veillard   79:         rpm->summary = localizedStrings[LANG_NO_SUMMARY];
1.2       veillard   80:     } else {
                     81:        rpm->summary = strdup((char *) p);
                     82:     }
                     83:     if (!headerGetEntry(h, RPMTAG_DESCRIPTION, &type, &p, &count) || !p) {
1.12      veillard   84:         rpm->description = localizedStrings[LANG_NO_DESCRIPTION];
1.2       veillard   85:     } else {
                     86:        rpm->description = strdup((char *) p);
                     87:     }
                     88:     if (!headerGetEntry(h, RPMTAG_DISTRIBUTION, &type, &p, &count) || !p) {
1.12      veillard   89:         rpm->distribution = localizedStrings[LANG_UNKNOWN];
1.2       veillard   90:     } else {
                     91:        rpm->distribution = strdup((char *) p);
                     92:     }
                     93:     if (!headerGetEntry(h, RPMTAG_ARCH, &type, &p, &count) || !p) {
1.12      veillard   94:         rpm->arch = localizedStrings[LANG_NONE];
1.11      veillard   95:        if (nameRpm == NULL) {
1.12      veillard   96:            sprintf(nameBuffer, "%s-%s-%s.rpm", name, version, release);
1.11      veillard   97:            nameRpm = nameBuffer;
                     98:        }
1.2       veillard   99:     } else {
                    100:        rpm->arch = strdup((char *) p);
1.11      veillard  101:        if (nameRpm == NULL) {
1.12      veillard  102:            sprintf(nameBuffer, "%s-%s-%s.%s.rpm",
                    103:                    name, version, release, (char *)p);
1.11      veillard  104:            nameRpm = nameBuffer;
                    105:        }
1.2       veillard  106:     }
1.7       veillard  107:     if (!headerGetEntry(h, RPMTAG_OS, &type, &p, &count) || !p) {
                    108:         rpm->os = "";
                    109:     } else {
                    110:        rpm->os = strdup((char *) p);
                    111:     }
1.2       veillard  112:     if (!headerGetEntry(h, RPMTAG_VENDOR, &type, &p, &count) || !p) {
1.7       veillard  113:         rpm->vendor = NULL;
1.2       veillard  114:     } else {
                    115:        rpm->vendor = strdup((char *) p);
                    116:     }
                    117:     if (!headerGetEntry(h, RPMTAG_GROUP, &type, &p, &count) || !p) {
1.12      veillard  118:         rpm->group = localizedStrings[LANG_NO_GROUP];
1.2       veillard  119:     } else {
                    120:        rpm->group = strdup((char *) p);
                    121:     }
                    122:     if (!headerGetEntry(h, RPMTAG_BUILDHOST, &type, &p, &count) || !p) {
1.12      veillard  123:         rpm->host = localizedStrings[LANG_NO_HOST];
1.2       veillard  124:     } else {
                    125:        rpm->host = strdup((char *) p);
                    126:     }
                    127:     if (!headerGetEntry(h, RPMTAG_SIZE, &type, &p, &count) || !p) {
                    128:         rpm->size = 0;
                    129:     } else {
                    130:        rpm->size = *((int *) p);
                    131:     }
1.11      veillard  132:     if (installed) {
                    133:        if (!headerGetEntry(h, RPMTAG_INSTALLTIME, &type, &p, &count) || !p) {
                    134:            rpm->date = 0;
                    135:        } else {
                    136:            rpm->date = *((int_32 *) p);
                    137:        }
1.2       veillard  138:     } else {
1.11      veillard  139:        if (!headerGetEntry(h, RPMTAG_BUILDTIME, &type, &p, &count) || !p) {
                    140:            rpm->date = 0;
                    141:        } else {
                    142:            rpm->date = *((int_32 *) p);
                    143:        }
1.2       veillard  144:     }
                    145:     if (!headerGetEntry(h, RPMTAG_SOURCERPM, &type, &p, &count) || !p) {
                    146:         rpm->srcrpm = "";
                    147:     } else {
                    148:        rpm->srcrpm = strdup((char *) p);
                    149:     }
1.7       veillard  150:     if (!headerGetEntry(h, RPMTAG_URL, &type, &p, &count) || !p) {
                    151:         rpm->url = NULL;
                    152:     } else {
                    153:        rpm->url = strdup((char *) p);
                    154:     }
                    155:     if (!headerGetEntry(h, RPMTAG_PACKAGER, &type, &p, &count) || !p) {
                    156:         rpm->packager = NULL;
                    157:     } else {
                    158:        rpm->packager = strdup((char *) p);
                    159:     }
                    160:     if (!headerGetEntry(h, RPMTAG_COPYRIGHT, &type, &p, &count) || !p) {
                    161:         rpm->copyright = NULL;
                    162:     } else {
                    163:        rpm->copyright = strdup((char *) p);
                    164:     }
                    165:     if (rpm->vendor == NULL) {
                    166:         if (rpm->packager != NULL) rpm->vendor = rpm->packager;
1.12      veillard  167:        else rpm->vendor = localizedStrings[LANG_UNKNOWN];
1.7       veillard  168:     }
1.2       veillard  169: 
1.11      veillard  170:     rpm->filename = strdup(nameRpm);
                    171: 
1.10      veillard  172:     /* package-xxx.rpm provides the ressource "package" */
                    173:     rpm->nb_ressources = 1;
1.11      veillard  174:     rpm->ressources[0] = rpmRessAdd(name, rpm, installed);
1.10      veillard  175: 
1.1       veillard  176:     val = getTagNumber("RPMTAG_PROVIDES");
                    177:     if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
1.10      veillard  178:         rpm->nb_ressources = 1;
1.1       veillard  179:     } else {
                    180:        if (count >= MAX_RESS) {
                    181:            fprintf(stderr, "MAX_RESS %d overflow, increase the limit!\n",
                    182:                    MAX_RESS);
                    183:            count = MAX_RESS;
                    184:        }
                    185: 
1.10      veillard  186:         for (i = 0, j = rpm->nb_ressources; i < count;j++, i++) {
1.11      veillard  187:            rpm->ressources[j] = rpmRessAdd(((char **) p)[i], rpm, installed);
1.4       veillard  188:        }
1.10      veillard  189:        rpm->nb_ressources += count;
1.4       veillard  190:     }
                    191: 
                    192:     val = getTagNumber("RPMTAG_REQUIRENAME");
                    193:     if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
                    194:         rpm->nb_requires = 0;
                    195:     } else {
                    196:        if (count >= MAX_REQU) {
                    197:            fprintf(stderr, "MAX_REQU %d overflow, increase the limit!\n",
                    198:                    MAX_REQU);
                    199:            count = MAX_REQU;
                    200:        }
                    201: 
                    202:        rpm->nb_requires = count;
                    203:         for (i = 0; i < count;i++) {
1.11      veillard  204:            rpm->requires[i] = rpmRequAdd(((char **) p)[i], rpm, installed);
1.1       veillard  205:        }
1.5       veillard  206:     }
                    207:     val = getTagNumber("RPMTAG_FILENAMES");
                    208:     if (!headerGetEntry(h, val, &type, &p, &count) || !p) {
1.7       veillard  209:         rpm->filelist = NULL; /* No filelist in the package ! */
1.5       veillard  210:     } else {
                    211:         char *ptr = buffer;
                    212:        for (i = 0; i < count;i++) {
                    213:            ptr += sprintf(ptr, "%s\n", ((char **) p)[i]);
                    214:        }
                    215:        rpm->filelist = strdup(buffer);
1.1       veillard  216:     }
                    217: 
                    218:     /* insert the package informations in the database */
1.11      veillard  219:     if (installed) {
                    220:        rpm->next = rpmInstalledList;
                    221:        rpmInstalledList = rpm;
                    222:     } else {
                    223:        rpm->next = rpmList;
                    224:        rpmList = rpm;
                    225:     }
1.7       veillard  226: 
                    227:     /* dump the HTML related to this package */
                    228:     dumpRpmHtml(rpm);
                    229: 
                    230:     /* free large amount of data not used later */
                    231:     if (rpm->filelist) free(rpm->filelist);
                    232:     if (rpm->copyright) free(rpm->copyright);
1.8       veillard  233: 
                    234:     /* increment the counters */
1.11      veillard  235:     if (installed) {
                    236:        rpm2html_install_files++;
                    237:        rpm2html_install_size += rpm->size;
                    238:     } else {
                    239:        rpm2html_files++;
                    240:        rpm2html_size += rpm->size;
                    241:     }
1.7       veillard  242: 
1.1       veillard  243:     return(0);
1.11      veillard  244: }
                    245: 
                    246: /*
                    247:  * rpmOpen : open an RPM file, read and parse the header and 
                    248:  *           fill the informations in the database.
                    249:  */
                    250: int rpmOpen(char *nameRpm, rpmDirPtr dir) {
                    251:     int fd;
                    252:     int rc;
                    253:     int n;
                    254:     Header h = NULL;
                    255:     int isSource;
                    256:     char buffer[500];
                    257: 
                    258:     /* open the file for reading */
                    259:     sprintf(buffer, "%s/%s", dir->dir, nameRpm);
                    260:     if ((fd = open(buffer, O_RDONLY)) < 0) {
                    261:          fprintf(stderr, "open of %s failed: %s\n", buffer,
                    262:                 strerror(errno));
                    263:         return(-1);
                    264:     }
                    265: 
                    266:     /* read the RPM header */
                    267:     rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
                    268:     switch (rc) {
                    269:        case 0:
                    270:            if (!h) {
                    271:                fprintf(stderr,
                    272:                        "old format source packages cannot be queried\n");
                    273:                return(-1);
                    274:            }
                    275:            break;
                    276:        case 1:
                    277:            fprintf(stderr, "%s does not appear to be a RPM package\n",
                    278:                    nameRpm);
                    279:            return(-1);
                    280:        case 2:
                    281:            fprintf(stderr, "query of %s failed\n", nameRpm);
                    282:            return(-1);
                    283:        default:
                    284:            fprintf(stderr, "rpmReadPackageHeader(%s): unknown error %d\n",
                    285:                    nameRpm, rc);
                    286:            return(-1);
                    287:     }
                    288: 
                    289:     n = rpmAnalyze(nameRpm, h, dir);
                    290: 
                    291:     /* free the header and close the descriptor */
                    292:     headerFree(h);
                    293:     close(fd);
1.1       veillard  294: 
1.11      veillard  295:     return(n);
1.6       veillard  296: }
                    297: 
                    298: /*
                    299:  * Scan a directory for RPM files.
                    300:  */
                    301: static int rpmDirScan(rpmDirPtr dir) {
                    302:     struct dirent **namelist;
1.7       veillard  303:     char *filename;
                    304:     int len;
1.6       veillard  305:     int n, i;
                    306: 
                    307:     n = scandir(dir->dir, &namelist, 0, alphasort);
                    308:     if (n < 0) {
                    309:         fprintf(stderr, "Listing of %s failed: %s\n", dir->dir,
                    310:                strerror(errno));
                    311:        return(-1);
                    312:     } else {
1.7       veillard  313:         for (i = 0;i < n;i++) {
                    314:            /* check that this is a RPM file by looking at the suffix */
                    315:            filename = namelist[i]->d_name;
                    316:            len = strlen(filename);
                    317:            if ((len >= 5) && (!strcasecmp(&filename[len - 4], ".rpm")))
                    318:                rpmOpen(filename, dir);
                    319:        }
1.6       veillard  320:     }
                    321:     free(namelist);
                    322:     return(n);
                    323: }
                    324: 
                    325: /*
1.11      veillard  326:  * Scan the local RPM database for RPM files.
                    327:  */
                    328: static int rpmBaseScan(rpmDirPtr dir) {
                    329:     rpmdb db;
                    330:     Header h = NULL;
                    331:     int offset, n = 0;
                    332:     char *prefix = "/";
                    333: 
                    334:     if (rpmdbOpen(prefix, &db, O_RDONLY, 0644)) {
                    335:         return(n);
                    336:     }
                    337:     offset = rpmdbFirstRecNum(db);
                    338:     while (offset) {
                    339:         h = rpmdbGetRecord(db, offset);
                    340:        if (!h) {
                    341:            fprintf(stderr, "could not read database record!\n");
                    342:            return(n);
                    343:        }
                    344:        rpmAnalyze(NULL, h, dir);
                    345:        headerFree(h);
                    346:        offset = rpmdbNextRecNum(db, offset);
                    347:     }
                    348:     rpmdbClose(db);
                    349: 
                    350:     return(n);
                    351: }
                    352: 
                    353: /*
1.6       veillard  354:  * Scan all registered directories.
                    355:  * One fist check for completeness of the informations in
                    356:  * the rpmDir structure.
                    357:  */
                    358: 
                    359: int rpmDirScanAll(void) {
1.7       veillard  360:     int n = 0, i;
                    361: 
1.6       veillard  362:     rpmDirPtr dir = dirList;
                    363: 
                    364:     while (dir != NULL) {
                    365:         if (dir->dir == NULL) {
                    366:            fprintf(stderr, "?!? rpmDir without directory ?!? disabled !\n");
1.11      veillard  367:        } 
                    368:        
                    369:        if (!strcmp(dir->dir, "localbase")) {
                    370:            /* Scan the local RPM database instead of a directory */
                    371:             i = rpmBaseScan(dir);
                    372:            if (i > 0) n += i;
1.7       veillard  373:        } else if (dir->ftp == NULL) {
                    374:            fprintf(stderr, "Directory %s disabled : no ftp field\n",
1.6       veillard  375:                    dir->dir);
1.7       veillard  376:        } else if (dir->nb_urls <= 0) {
1.6       veillard  377:            fprintf(stderr, "Directory %s disabled : no url(s) field\n",
                    378:                    dir->dir);
                    379:        } else {
                    380:            fprintf(stderr, "Scanning directory %s for RPMs\n", dir->dir);
1.7       veillard  381:            i = rpmDirScan(dir);
                    382:            if (i > 0) n += i;
1.6       veillard  383:        }
                    384: 
                    385:         dir = dir->next;
                    386:     }
1.7       veillard  387:     return(n);
1.1       veillard  388: }
                    389: 

Webmaster