/* * rpmopen.c : open an extract informations from RPM files. * * Copyright (c) 1997 Daniel Veillard * See COPYING for the status of this software. * * $Id: rpmopen.c,v 1.20 1998/01/30 05:19:53 veillard Exp $ */ #include #include #include #ifdef HAVE_FCNTL_H #include #endif #include #include #include #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include "rpmdata.h" #include "html.h" #include "rpm2html.h" #include "language.h" /* * Get the internal number associated to an RPM tag. */ static int getTagNumber(char *tag) { int i; const struct headerTagTableEntry * t; for (i = 0, t = rpmTagTable; i < rpmTagTableSize; i++, t++) { if (!strcasecmp(tag, t->name)) return(t->val); } fprintf(stderr, "getTagNumber(%s) : unknown tag !\n", tag); return(-1); } /* * rpmAnalyze : analyze an RPM record, read and parse the header and * fill the informations in the database. */ int rpmAnalyze(char *nameRpm, Header h, rpmDirPtr dir, time_t stamp) { int installed = dir->installbase; char * name = NULL, * version = NULL, * release = NULL; int_32 count, type; void * p = NULL; int val, i, j; rpmDataPtr rpm = NULL; static char buffer[500000]; static char nameBuffer[500]; /* extract informations from the header */ headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &count); headerGetEntry(h, RPMTAG_VERSION, &type, (void **) &version, &count); headerGetEntry(h, RPMTAG_RELEASE, &type, (void **) &release, &count); /* allocate a new rpmData block, fill it */ rpm = (rpmDataPtr) malloc(sizeof(rpmData)); memset(rpm, 0, sizeof(rpmData)); if (rpm == NULL) { fprintf(stderr, "cannot allocate %d bytes: %s\n", sizeof(rpmData), strerror(errno)); return(-1); } rpm->dir = dir; rpm->stamp = stamp; rpm->name = strdup(name); rpm->version = strdup(version); rpm->release = strdup(release); /* get all the ressources provided by this RPM */ if (!headerGetEntry(h, RPMTAG_SUMMARY, &type, &p, &count) || !p) { rpm->summary = localizedStrings[LANG_NO_SUMMARY]; } else { rpm->summary = strdupHTML((char *) p); } if (!headerGetEntry(h, RPMTAG_DESCRIPTION, &type, &p, &count) || !p) { rpm->description = localizedStrings[LANG_NO_DESCRIPTION]; } else { rpm->description = strdupHTML((char *) p); } if (!headerGetEntry(h, RPMTAG_DISTRIBUTION, &type, &p, &count) || !p) { rpm->distribution = localizedStrings[LANG_UNKNOWN]; } else { rpm->distribution = strdup((char *) p); } if (!headerGetEntry(h, RPMTAG_ARCH, &type, &p, &count) || !p) { rpm->arch = localizedStrings[LANG_NONE]; if (nameRpm == NULL) { sprintf(nameBuffer, "%s-%s-%s.rpm", name, version, release); nameRpm = nameBuffer; } } else { rpm->arch = strdup((char *) p); if (nameRpm == NULL) { sprintf(nameBuffer, "%s-%s-%s.%s.rpm", name, version, release, (char *)p); nameRpm = nameBuffer; } } if (!headerGetEntry(h, RPMTAG_OS, &type, &p, &count) || !p) { rpm->os = ""; } else { rpm->os = strdup((char *) p); } if (!headerGetEntry(h, RPMTAG_VENDOR, &type, &p, &count) || !p) { rpm->vendor = NULL; } else { rpm->vendor = strdup((char *) p); } if (!headerGetEntry(h, RPMTAG_GROUP, &type, &p, &count) || !p) { rpm->group = localizedStrings[LANG_NO_GROUP]; } else { rpm->group = strdup((char *) p); } if (!headerGetEntry(h, RPMTAG_BUILDHOST, &type, &p, &count) || !p) { rpm->host = localizedStrings[LANG_NO_HOST]; } else { rpm->host = strdup((char *) p); } if (!headerGetEntry(h, RPMTAG_SIZE, &type, &p, &count) || !p) { rpm->size = 0; } else { rpm->size = *((int *) p); } if (installed) { if (!headerGetEntry(h, RPMTAG_INSTALLTIME, &type, &p, &count) || !p) { rpm->date = 0; } else { rpm->date = *((int_32 *) p); } } else { if (!headerGetEntry(h, RPMTAG_BUILDTIME, &type, &p, &count) || !p) { rpm->date = 0; } else { rpm->date = *((int_32 *) p); } } if (!headerGetEntry(h, RPMTAG_SOURCERPM, &type, &p, &count) || !p) { rpm->srcrpm = ""; } else { rpm->srcrpm = strdup((char *) p); } if (!headerGetEntry(h, RPMTAG_URL, &type, &p, &count) || !p) { rpm->url = NULL; } else { rpm->url = strdup((char *) p); } if (!headerGetEntry(h, RPMTAG_PACKAGER, &type, &p, &count) || !p) { rpm->packager = NULL; } else { rpm->packager = strdup((char *) p); } if (!headerGetEntry(h, RPMTAG_COPYRIGHT, &type, &p, &count) || !p) { rpm->copyright = NULL; } else { rpm->copyright = strdup((char *) p); } if (rpm->vendor == NULL) { if (rpm->packager != NULL) rpm->vendor = strdup(rpm->packager); else rpm->vendor = strdup(localizedStrings[LANG_UNKNOWN]); } rpm->filename = strdup(nameRpm); /* package-xxx.rpm provides the ressource "package" */ rpm->nb_ressources = 1; rpm->ressources[0] = rpmRessAdd(name, rpm, installed); val = getTagNumber("RPMTAG_PROVIDES"); if (!headerGetEntry(h, val, &type, &p, &count) || !p) { rpm->nb_ressources = 1; } else { if (count >= MAX_RESS) { fprintf(stderr, "MAX_RESS %d overflow, increase the limit!\n", MAX_RESS); count = MAX_RESS; } for (i = 0, j = rpm->nb_ressources; i < count;j++, i++) { rpm->ressources[j] = rpmRessAdd(((char **) p)[i], rpm, installed); } rpm->nb_ressources += count; } val = getTagNumber("RPMTAG_REQUIRENAME"); if (!headerGetEntry(h, val, &type, &p, &count) || !p) { rpm->nb_requires = 0; } else { if (count >= MAX_REQU) { fprintf(stderr, "MAX_REQU %d overflow, increase the limit!\n", MAX_REQU); count = MAX_REQU; } rpm->nb_requires = count; for (i = 0; i < count;i++) { rpm->requires[i] = rpmRequAdd(((char **) p)[i], rpm, installed); } } val = getTagNumber("RPMTAG_FILENAMES"); if (!headerGetEntry(h, val, &type, &p, &count) || !p) { rpm->filelist = NULL; /* No filelist in the package ! */ } else { char *ptr = buffer; for (i = 0; i < count;i++) { ptr += sprintf(ptr, "%s\n", ((char **) p)[i]); } rpm->filelist = strdup(buffer); } /* insert the package informations in the database */ if (installed) { rpm->next = rpmInstalledList; rpmInstalledList = rpm; } else { rpm->next = rpmList; rpmList = rpm; } /* Register this package */ rpmAddSoftware(rpm); /* dump the HTML related to this package */ dumpRpmHtml(rpm); /* free large amount of data not used later */ if (rpm->filelist) free(rpm->filelist); rpm->filelist = NULL; if (rpm->copyright) free(rpm->copyright); rpm->copyright = NULL; if (rpm->description) free(rpm->description); rpm->description = NULL; /* increment the counters */ if (installed) { rpm2html_install_files++; rpm2html_install_size += rpm->size; } else { rpm2html_files++; rpm2html_size += rpm->size; } return(0); } /* * rpmOpen : open an RPM file, read and parse the header and * fill the informations in the database. */ int rpmOpen(char *nameRpm, rpmDirPtr dir) { int fd; int rc; int n; Header h = NULL; int isSource; char buffer[500]; struct stat buf; /* open the file for reading */ sprintf(buffer, "%s/%s", dir->rpmdir, nameRpm); if ((fd = open(buffer, O_RDONLY)) < 0) { fprintf(stderr, "open of %s failed: %s\n", buffer, strerror(errno)); return(-1); } stat(buffer, &buf); /* read the RPM header */ rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL); switch (rc) { case 0: if (!h) { fprintf(stderr, "old format source packages cannot be queried\n"); return(-1); } break; case 1: fprintf(stderr, "%s does not appear to be a RPM package\n", nameRpm); return(-1); case 2: fprintf(stderr, "query of %s failed\n", nameRpm); return(-1); default: fprintf(stderr, "rpmReadPackageHeader(%s): unknown error %d\n", nameRpm, rc); return(-1); } n = rpmAnalyze(nameRpm, h, dir, buf.st_mtime); /* free the header and close the descriptor */ headerFree(h); close(fd); return(n); } /* * Scan a directory for RPM files. */ static int rpmDirScan(rpmDirPtr dir) { struct dirent **namelist; char *filename; int len; int n, i; n = scandir(dir->rpmdir, &namelist, 0, alphasort); if (n < 0) { fprintf(stderr, "Listing of %s failed: %s\n", dir->rpmdir, strerror(errno)); return(-1); } else { for (i = 0;i < n;i++) { /* check that this is a RPM file by looking at the suffix */ filename = namelist[i]->d_name; len = strlen(filename); if ((len >= 5) && (!strcasecmp(&filename[len - 4], ".rpm"))) rpmOpen(filename, dir); } } free(namelist); return(n); } /* * Scan the local RPM database for RPM files. */ static int rpmBaseScan(rpmDirPtr dir) { rpmdb db; Header h = NULL; int offset, n = 0; char *prefix = "/"; if (rpmdbOpen(prefix, &db, O_RDONLY, 0644)) { return(n); } offset = rpmdbFirstRecNum(db); while (offset) { h = rpmdbGetRecord(db, offset); if (!h) { fprintf(stderr, "could not read database record!\n"); return(n); } rpmAnalyze(NULL, h, dir, 0); headerFree(h); offset = rpmdbNextRecNum(db, offset); } rpmdbClose(db); return(n); } /* * Scan all registered directories. * One fist check for completeness of the informations in * the rpmDir structure. */ int rpmDirScanAll(void) { int n = 0, i; rpmDirPtr dir, next; /* * first reverse the list .... */ dir = dirList; dirList = NULL; while (dir != NULL) { next = dir->next; dir->next = dirList; dirList = dir; dir = next; } dir = dirList; while (dir != NULL) { /* * Override default setting. */ if ((dir->maint == NULL) && (rpm2html_maint != NULL)) dir->maint = strdup(rpm2html_maint); if ((dir->mail == NULL) && (rpm2html_mail != NULL)) dir->mail = strdup(rpm2html_mail); if ((dir->ftp == NULL) && (rpm2html_ftp != NULL)) dir->ftp = strdup(rpm2html_ftp); if ((dir->ftpsrc == NULL) && (rpm2html_ftpsrc != NULL)) dir->ftpsrc = strdup(rpm2html_ftpsrc); if ((dir->dir == NULL) && (rpm2html_dir != NULL)) dir->dir = strdup(rpm2html_dir); if ((dir->host == NULL) && (rpm2html_host != NULL)) dir->host = strdup(rpm2html_host); if ((dir->name == NULL) && (rpm2html_name != NULL)) dir->name = strdup(rpm2html_name); if ((dir->url == NULL) && (rpm2html_url != NULL)) dir->url = strdup(rpm2html_url); if (dir->rpmdir == NULL) { fprintf(stderr, "?!? rpmDir without directory ?!? disabled !\n"); } else if (!strcmp(dir->rpmdir, "localbase")) { /* Scan the local RPM database instead of a directory */ i = rpmBaseScan(dir); if (i > 0) n += i; } else if (dir->ftp == NULL) { fprintf(stderr, "Directory %s disabled : no ftp field\n", dir->rpmdir); } else { if (verbose) fprintf(stderr, "Scanning directory %s for RPMs\n",dir->rpmdir); i = rpmDirScan(dir); if (i > 0) n += i; } dir = dir->next; } return(n); }