/* * rpmopen.c : open an extract informations from RPM files. * * See Copyright for the status of this software. * * $Id: rpmopen.c,v 1.76 2000/07/24 18:46:31 veillard Exp $ */ #include #include #include #ifdef HAVE_FCNTL_H #include #endif #include #include #include #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include #include /* Added by A. Gibert */ #include "rpmdata.h" #include "html.h" #include "rdf.h" #include "rpm2html.h" #include "language.h" #ifdef WITH_SQL #include "sql.h" #endif #ifndef HAVE_SNPRINTF #error You really need snprintf ... #endif /* * Get the internal number associated with 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); } /* * Free up the extra data not needed for the last stage processing. */ void rpmFreeExtraData(rpmDataPtr rpm) { rpmExtraDataPtr extra; if ((rpm == NULL) || (rpm->extra == NULL)) return; extra = rpm->extra; if (extra->packager != NULL) debugFree(extra->packager); if (extra->description != NULL) debugFree(extra->description); if (extra->copyright != NULL) debugFree(extra->copyright); if (extra->changelog != NULL) debugFree(extra->changelog); if (extra->srcrpm != NULL) debugFree(extra->srcrpm); if (extra->host != NULL) debugFree(extra->host); if (extra->resources != NULL) debugFree(extra->resources); if (extra->requires != NULL) debugFree(extra->requires); if (extra->filelist != NULL) debugFree(extra->filelist); debugFree(extra); } /* * check a dependancy name to get rid of bad deps due to bad scripts * or spec files. */ int checkResourceName(const char *res) { int isname = 0; const char *base = res; if (*res == 0) return(0); /* * we only accept absolute pathnames. */ if (*res == '/') isname = 1; while (*res != 0) { if (((*res >= 'A') && (*res <= 'Z')) || ((*res >= 'a') && (*res <= 'z')) || ((*res >= '0') && (*res <= '9')) || (*res == '-') || (*res == '.') || (*res == '@') || (*res == '_') || (*res == '+') || ((*res == '/') && (isname == 1))) res++; else return(0); if ((res - base) > 100) return(0); } return(1); } /* * check a release name */ int checkReleaseName(const char *res) { const char *base = res; if (*res == 0) return(0); while (*res != 0) { if (((*res >= 'A') && (*res <= 'Z')) || ((*res >= 'a') && (*res <= 'z')) || ((*res >= '0') && (*res <= '9')) || (*res == '-') || (*res == '.') || (*res == '@') || (*res == '_') || (*res == '+')) res++; else return(0); if ((res - base) > 20) return(0); } return(1); } /* * check a group name */ int checkGroupName(const char *res) { const char *base = res; /* Grrr !!! Suse packages have an empty Group name if (*res == 0) return(0); */ while (*res != 0) { if (((*res >= 'A') && (*res <= 'Z')) || ((*res >= 'a') && (*res <= 'z')) || ((*res >= '0') && (*res <= '9')) || (*res == ' ') || (*res == '.') || (*res == '+') || (*res == '/') || (*res == '-')) res++; else return(0); if ((res - base) > 60) return(0); } return(1); } /* * check a version name */ int checkVersionName(const char *res) { const char *base = res; if (*res == 0) return(0); while (*res != 0) { if (((*res >= 'A') && (*res <= 'Z')) || ((*res >= 'a') && (*res <= 'z')) || ((*res >= '0') && (*res <= '9')) || (*res == '-') || (*res == '.') || (*res == '@') || (*res == '_') || (*res == '+')) res++; else return(0); if ((res - base) > 20) return(0); } return(1); } /* * rpmAnalyze : analyze an RPM record, read and parse the header and * fill the informations in the database. */ #define ENTRY_CLEANUP(p) \ if ((type == RPM_STRING_ARRAY_TYPE || type == RPM_I18NSTRING_TYPE)&&\ (p != NULL)) { free((p)); p = NULL; } static char *buffer = NULL; static int buffer_size = 50 * 1024 * sizeof(char); rpmDataPtr rpmAnalyze(char *path, char *nameRpm, Header h, rpmDirPtr dir, rpmSubdirPtr tree, time_t stamp, int isSource) { 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 nameBuffer[500]; #ifdef WITH_SQL int id; #endif if (buffer == NULL) { buffer = (char *) debugMalloc(buffer_size); if (buffer == NULL) { fprintf(stderr, "cannot allocate %d bytes: %s\n", buffer_size, strerror(errno)); exit(1); } } /* extract informations from the header */ headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &count); if (name == NULL) { fprintf(stderr, "Invalid package %s : no name\n", nameRpm); return(NULL); } if (!(((name[0] >= 'a') && (name[0] <= 'z')) || ((name[0] >= 'A') && (name[0] <= 'Z')) || ((name[0] >= '0') && (name[0] <= '9')))) { fprintf(stderr, "Invalid package %s : garbled name\n", nameRpm); ENTRY_CLEANUP(name) return(NULL); } if (!checkResourceName(name)) { fprintf(stderr, "Invalid package %s : garbled name\n", nameRpm); ENTRY_CLEANUP(name) return(NULL); } headerGetEntry(h, RPMTAG_VERSION, &type, (void **) &version, &count); if ((version == NULL) || (version[0] == 0)) { fprintf(stderr, "Invalid package %s : version invalid\n", nameRpm); ENTRY_CLEANUP(name) ENTRY_CLEANUP(version) return(NULL); } if (!checkVersionName(version)) { fprintf(stderr, "Invalid package %s : garbled version\n", nameRpm); ENTRY_CLEANUP(name) ENTRY_CLEANUP(version) return(NULL); } headerGetEntry(h, RPMTAG_RELEASE, &type, (void **) &release, &count); if ((release == NULL) || (release[0] == 0)) { fprintf(stderr, "Invalid package %s : release invalid\n", nameRpm); ENTRY_CLEANUP(name) ENTRY_CLEANUP(version) ENTRY_CLEANUP(release) return(NULL); } if (!checkReleaseName(release)) { fprintf(stderr, "Invalid package %s : garbled release\n", nameRpm); ENTRY_CLEANUP(name) ENTRY_CLEANUP(version) ENTRY_CLEANUP(release) return(NULL); } /* allocate a new rpmData block, and an rpmExtraData block fill them */ rpm = (rpmDataPtr) debugMalloc(sizeof(rpmData)); if (rpm == NULL) { fprintf(stderr, "cannot allocate %d bytes: %s\n", sizeof(rpmData), strerror(errno)); return(NULL); } memset(rpm, 0, sizeof(rpmData)); rpm->extra = (rpmExtraDataPtr) debugMalloc(sizeof(rpmExtraData)); if (rpm == NULL) { fprintf(stderr, "cannot allocate %d bytes: %s\n", sizeof(rpmExtraData), strerror(errno)); return(NULL); } memset(rpm->extra, 0, sizeof(rpmExtraData)); rpm->dir = dir; if (tree) { if ((tree->rpmpath != NULL) && (tree->rpmpath[0] != '\0')) rpm->subdir = stringAdd(tree->rpmpath); else rpm->subdir = NULL; } else rpm->subdir = NULL; rpm->extra->stamp = stamp; rpm->name = stringAdd(name); ENTRY_CLEANUP(name) rpm->version = stringAdd(version); ENTRY_CLEANUP(version) rpm->release = stringAdd(release); ENTRY_CLEANUP(release) /* get all the resources provided by this RPM */ if (!headerGetEntry(h, RPMTAG_SUMMARY, &type, &p, &count) || !p) { rpm->summary = debugStrdup(localizedStrings[LANG_NO_SUMMARY]); } else { rpm->summary = debugStrdup((char *) p); } ENTRY_CLEANUP(p); if (!headerGetEntry(h, RPMTAG_DESCRIPTION, &type, &p, &count) || !p || (type != RPM_STRING_TYPE)) { rpm->extra->description = debugStrdup(localizedStrings[LANG_NO_DESCRIPTION]); } else { rpm->extra->description = debugStrdup((char *) p); } ENTRY_CLEANUP(p); if (!headerGetEntry(h, RPMTAG_DISTRIBUTION, &type, &p, &count) || !p || (type != RPM_STRING_TYPE)) { rpm->distribution = stringAdd(localizedStrings[LANG_UNKNOWN]); } else { rpm->distribution = stringAdd((char *) p); } ENTRY_CLEANUP(p); if (isSource) { rpm->arch = stringAdd("src"); if (nameRpm == NULL) { snprintf(nameBuffer, sizeof(nameBuffer), "%s-%s-%s.src.rpm", name, version, release); nameRpm = nameBuffer; } } else { if (!headerGetEntry(h, RPMTAG_ARCH, &type, &p, &count) || !p || (type != RPM_STRING_TYPE)) { if (type == RPM_INT8_TYPE) { /* * Old packages. */ switch (*((char *) p)) { case 1: rpm->arch = stringAdd("i386"); break; default: rpm->arch = stringAdd("src"); break; } } else rpm->arch = stringAdd(localizedStrings[LANG_NONE]); if (nameRpm == NULL) { snprintf(nameBuffer, sizeof(nameBuffer), "%s-%s-%s.rpm", name, version, release); nameRpm = nameBuffer; } } else { rpm->arch = stringAdd((char *) p); if (nameRpm == NULL) { snprintf(nameBuffer, sizeof(nameBuffer), "%s-%s-%s.%s.rpm", name, version, release, (char *)p); nameRpm = nameBuffer; } } ENTRY_CLEANUP(p); } if (!headerGetEntry(h, RPMTAG_OS, &type, &p, &count) || !p || (type != RPM_STRING_TYPE)) { if (type == RPM_INT8_TYPE) { /* * Old packages. */ switch (*((char *) p)) { case 1: rpm->os = stringAdd("linux"); break; default: rpm->os = stringAdd("linux"); break; } } else rpm->os = stringAdd(""); } else { rpm->os = stringAdd((char *) p); } ENTRY_CLEANUP(p); if (!headerGetEntry(h, RPMTAG_VENDOR, &type, &p, &count) || !p || (type != RPM_STRING_TYPE)) { rpm->vendor = NULL; } else { rpm->vendor = stringAdd((char *) p); } ENTRY_CLEANUP(p); if (!headerGetEntry(h, RPMTAG_GROUP, &type, &p, &count) || !p || (type != RPM_STRING_TYPE)) { rpm->group = stringAdd(localizedStrings[LANG_NO_GROUP]); } else { rpm->group = stringAdd((char *) p); } ENTRY_CLEANUP(p); if (!checkGroupName(rpm->group)) { fprintf(stderr, "Invalid package %s : garbled group\n", nameRpm); if (rpm->name) stringFree(rpm->name); if (rpm->version) stringFree(rpm->version); if (rpm->release) stringFree(rpm->release); if (rpm->summary) debugFree(rpm->summary); if (rpm->distribution) stringFree(rpm->distribution); if (rpm->arch) stringFree(rpm->arch); if (rpm->os) stringFree(rpm->os); if (rpm->vendor != NULL) stringFree(rpm->vendor); if (rpm->group != NULL) stringFree(rpm->group); debugFree(rpm); return(NULL); } if (!headerGetEntry(h, RPMTAG_BUILDHOST, &type, &p, &count) || !p || (type != RPM_STRING_TYPE)) { rpm->extra->host = debugStrdup(localizedStrings[LANG_NO_HOST]); } else { rpm->extra->host = debugStrdup((char *) p); } ENTRY_CLEANUP(p); if (!headerGetEntry(h, RPMTAG_SIZE, &type, &p, &count) || !p) { rpm->size = 0; } else { rpm->size = *((int *) p); } ENTRY_CLEANUP(p); if (installed) { if (!headerGetEntry(h, RPMTAG_INSTALLTIME, &type, &p, &count) || !p) { rpm->date = 0; } else { rpm->date = *((int_32 *) p); } ENTRY_CLEANUP(p); } else { if (!headerGetEntry(h, RPMTAG_BUILDTIME, &type, &p, &count) || !p) { rpm->date = 0; } else { rpm->date = *((int_32 *) p); } ENTRY_CLEANUP(p); } if (!headerGetEntry(h, RPMTAG_SOURCERPM, &type, &p, &count) || !p || (type != RPM_STRING_TYPE)) { rpm->extra->srcrpm = debugStrdup(""); } else { rpm->extra->srcrpm = debugStrdup((char *) p); } ENTRY_CLEANUP(p); if (!headerGetEntry(h, RPMTAG_URL, &type, &p, &count) || !p || (type != RPM_STRING_TYPE)) { rpm->url = NULL; } else { rpm->url = debugStrdup((char *) p); } ENTRY_CLEANUP(p); if (!headerGetEntry(h, RPMTAG_PACKAGER, &type, &p, &count) || !p || (type != RPM_STRING_TYPE)) { rpm->extra->packager = NULL; } else { rpm->extra->packager = debugStrdup((char *) p); } ENTRY_CLEANUP(p); if (!headerGetEntry(h, RPMTAG_COPYRIGHT, &type, &p, &count) || !p || (type != RPM_STRING_TYPE)) { rpm->extra->copyright = NULL; } else { rpm->extra->copyright = debugStrdup((char *) p); } ENTRY_CLEANUP(p); /* Pick up changelog entries */ if (!headerGetEntry(h, RPMTAG_CHANGELOGTEXT, &type, &p, &count) || !p) { rpm->extra->changelog = NULL; } else { time_t *dates; char **names; char **holdp = (char **)p; char *cp; struct tm *tm_buf; int i, len, pos; char date_string[50]; char *res = buffer; *res = '\0'; headerGetEntry(h, RPMTAG_CHANGELOGTIME, &type, (void *)&dates, &count); headerGetEntry(h, RPMTAG_CHANGELOGNAME, &type, (void *)&names, &count); for (i = 0; i < count; i++) { if ((res - buffer) > (buffer_size - 1024)) { int delta = res - buffer; buffer_size *= 2; buffer = (char *) debugRealloc(buffer, buffer_size); if (buffer == NULL) { fprintf(stderr, "cannot re-allocate %d bytes: %s\n", buffer_size, strerror(errno)); exit(1); } res = &buffer[delta]; } tm_buf = localtime(&dates[i]); strftime(date_string, sizeof(date_string) - 1, "%a %b %d %Y", tm_buf); len = snprintf(res, buffer_size, "* %s %s\n", date_string, names[i]); res += len; cp = holdp[i]; pos = 0; while (*cp) { if (pos++ == 0) { *res++ = ' '; *res++ = ' '; } *res++ = *cp; if (*cp++ == '\n') pos = 0; } *res++ = '\n'; } *res = '\0'; rpm->extra->changelog = debugStrdup(buffer); } ENTRY_CLEANUP(p); if (rpm->vendor == NULL) { if (rpm->extra->packager != NULL) rpm->vendor = debugStrdup(rpm->extra->packager); else rpm->vendor = debugStrdup(localizedStrings[LANG_UNKNOWN]); } rpm->filename = debugStrdup(nameRpm); /* package-xxx.rpm provides at least the resource "package" */ val = getTagNumber("RPMTAG_PROVIDES"); if (!headerGetEntry(h, val, &type, &p, &count) || !p) { rpm->extra->nb_resources = 1; rpm->extra->max_resources = 1; rpm->extra->resources = (rpmRessPtr *) debugMalloc(sizeof(rpmRessPtr) * rpm->extra->max_resources); if (rpm->extra->resources == NULL) { fprintf(stderr, ": ran out of memory\n"); exit(1); } rpm->extra->resources[0] = rpmRessAdd(name, rpm, installed); } else { rpm->extra->max_resources = count + 1; rpm->extra->resources = (rpmRessPtr *) debugMalloc(sizeof(rpmRessPtr) * rpm->extra->max_resources); if (rpm->extra->resources == NULL) { fprintf(stderr, ": ran out of memory\n"); exit(1); } rpm->extra->resources[0] = rpmRessAdd(name, rpm, installed); rpm->extra->nb_resources = 1; for (i = 0, j = rpm->extra->nb_resources; i < count;i++) { if (!checkResourceName(((char **) p)[i])) continue; rpm->extra->resources[j++] = rpmRessAdd(((char **) p)[i], rpm, installed); } rpm->extra->nb_resources = j; } ENTRY_CLEANUP(p); val = getTagNumber("RPMTAG_REQUIRENAME"); if (!headerGetEntry(h, val, &type, &p, &count) || !p) { rpm->extra->nb_requires = 0; rpm->extra->requires = NULL; } else { int_32 count2, count3, type2, type3; void * q = NULL; void * r = NULL; int valv, valf; rpm->extra->max_requires = count; rpm->extra->requires = (rpmRessPtr *) debugMalloc(sizeof(rpmRessPtr) * rpm->extra->max_requires); if (rpm->extra->requires == NULL) { fprintf(stderr, ": ran out of memory\n"); exit(1); } valv = getTagNumber("RPMTAG_REQUIREVERSION"); valf = getTagNumber("RPMTAG_REQUIREFLAGS"); headerGetEntry(h, valv, &type2, &q, &count2); headerGetEntry(h, valf, &type3, &r, &count3); rpm->extra->nb_requires = 0; for (i = 0, j = 0; (i < count2) && (i < count3);i++) { char buf[10]; long anint = *(((long *)r)+i); buf[0]='\0'; if (anint & RPMSENSE_LESS) strcat(buf, "<"); if (anint & RPMSENSE_GREATER) strcat(buf, ">"); if (anint & RPMSENSE_EQUAL) strcat(buf, "="); if (!checkResourceName(((char **) p)[i])) continue; rpm->extra->requires[j++] = rpmRequAdd(((char **) p)[i],((char **) q)[i], ((char *) buf) , rpm, installed); } rpm->extra->nb_requires = j; if ((type2 == RPM_STRING_ARRAY_TYPE || type2 == RPM_I18NSTRING_TYPE)&& (q != NULL)) { free((q)); q = NULL; } if ((type3 == RPM_STRING_ARRAY_TYPE || type3 == RPM_I18NSTRING_TYPE)&& (r != NULL)) { free((r)); r = NULL; } for (;i < count;i++) rpmRequAdd(((char **) p)[i], NULL, NULL, rpm, installed); } ENTRY_CLEANUP(p); #if defined(RPMTAG_FILENAMES) val = getTagNumber("RPMTAG_FILENAMES"); headerGetEntry(h, val, &type, &p, &count); #else rpmBuildFileList(h, (const char ***) &p, &count); #endif if (count == 0) { rpm->extra->filelist = NULL; /* No filelist in the package ! */ } else { char *ptr = buffer; for (i = 0; i < count;i++) { if ((ptr - buffer) > (buffer_size - 1024)) { int delta = ptr - buffer; buffer_size *= 2; buffer = (char *) debugRealloc(buffer, buffer_size); if (buffer == NULL) { fprintf(stderr, "cannot re-allocate %d bytes: %s\n", buffer_size, strerror(errno)); exit(1); } ptr = &buffer[delta]; } ptr += snprintf(ptr, buffer_size, "%s\n", ((char **) p)[i]); } rpm->extra->filelist = debugStrdup(buffer); } ENTRY_CLEANUP(p); #ifdef WITH_SQL id = sql_add_package(path, rpm->name, rpm->version, rpm->release, rpm->arch, dir->no, rpm->url, rpm->extra->srcrpm, dir->vendor, rpm->extra->packager, rpm->group, rpm->summary, rpm->extra->description, rpm->extra->copyright); if (id > 0) { for (i = 0;i < rpm->extra->nb_resources;i++) sql_add_provides(id, rpm->extra->resources[i]->name); for (i = 0;i < rpm->extra->nb_requires;i++) sql_add_requires(id, rpm->extra->requires[i]->name, rpm->extra->requires[i]->flags, rpm->extra->requires[i]->version); } #endif /* Add the package files to the real filesystem tree if asked for */ #ifdef WITH_SQL if ((rpm->extra->filelist != NULL) && ((dir->build_tree != 0) || (id > 0))) { #else if ((dir->build_tree != 0) && (rpm->extra->filelist != NULL)) { #endif char *cur, *filename; cur = rpm->extra->filelist; while ((*cur != '\0') && (*cur != '/')) cur++; filename = cur; while (*cur != '\0') { if ((*cur == '\n') || (*cur == '\r')) { if (cur != filename) { #ifdef WITH_SQL if (dir->build_tree != 0) rpmAddRealFile(dir->root, filename, rpm); if (id > 0) { *cur = 0; sql_add_file(filename,id); *cur = '\n'; } #else rpmAddRealFile(dir->root, filename, rpm); #endif } while ((*cur != '\0') && (*cur != '/')) cur++; filename = cur; } else cur++; } if (cur != filename) rpmAddRealFile(dir->root, filename, rpm); } /* Register this package */ rpmAddSoftware(rpm); /* dump the HTML related to this package */ if ((rpm2html_dump_html) && (dir->html)) dumpRpmHtml(rpm, tree); if (rpm2html_dump_rdf) dumpRpmRdf(rpm, tree); /* free the extra data */ rpmFreeExtraData(rpm); /* increment the counters */ if (installed) { rpm2html_install_files++; rpm2html_install_size += rpm->size / 1024; } else { rpm2html_files++; rpm2html_size += rpm->size / 1024; } return(rpm); } /* * rpmOpen : open an RPM file, read and parse the header and * fill the informations in the database. */ rpmDataPtr rpmOpen(char *nameRpm, rpmDirPtr dir, rpmSubdirPtr tree) { rpmDataPtr cur; #if defined(HAVE_RPM_RPMIO_H) FD_t fd; #else int fd; #define fdOpen(_a, _b, _c) open((_a), (_b)) #define fdClose(_a) close(_a) #endif int rc; Header h = NULL; int isSource; char buffer[500]; struct stat buf; /* open the file for reading */ if (tree->htmlpath[0] != '\0') snprintf(buffer, sizeof(buffer), "%s/%s/%s", dir->rpmdir, tree->rpmpath, nameRpm); else snprintf(buffer, sizeof(buffer), "%s/%s", dir->rpmdir, nameRpm); #if defined(USE_RPMIO) fd = Fopen(buffer, "r.fdio"); if (fd == NULL || Ferror(fd)) { fprintf(stderr, "Fopen of %s failed: %s\n", buffer, Fstrerror(fd)); return(NULL); } #else if ((fd = fdOpen(buffer, O_RDONLY, 0)) < 0) { fprintf(stderr, "open of %s failed: %s\n", buffer, strerror(errno)); return(NULL); } #endif 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"); fdClose(fd); return(NULL); } break; case 1: fprintf(stderr, "%s does not appear to be a RPM package\n", nameRpm); fdClose(fd); return(NULL); case 2: fprintf(stderr, "query of %s failed\n", nameRpm); fdClose(fd); return(NULL); default: fprintf(stderr, "rpmReadPackageHeader(%s): unknown error %d\n", nameRpm, rc); fdClose(fd); return(NULL); } cur = rpmAnalyze(buffer, nameRpm, h, dir, tree, buf.st_mtime, isSource); /* free the header and close the descriptor */ headerFree(h); #if defined(USE_RPMIO) Fclose(fd); #else fdClose(fd); #endif return(cur); } /* * Scan one directory for RPM files this is where the recursive handling * is done. */ static rpmDataPtr rpmOneDirScan(rpmDirPtr dir, rpmSubdirPtr tree) { rpmSubdirPtr subtree; rpmDataPtr ret = NULL, cur; char *filename; static char path[2000]; struct stat buf; int len; DIR *d; struct dirent *file; /* * Create the directory for the HTML pages */ if ((rpm2html_dump_html) && (dir->html)) { if (tree->htmlpath[0] != '\0') snprintf(path, sizeof(path), "%s/%s", dir->dir, tree->htmlpath); else snprintf(path, sizeof(path), "%s", dir->dir); createDirectory(path); } /* * Create the directory for the RDF pages if (rpm2html_rdf_dir != NULL) { if (tree->htmlpath[0] != '\0') snprintf(path, sizeof(path), "%s/%s", rpm2html_rdf_dir, tree->htmlpath); else snprintf(path, sizeof(path), "%s", rpm2html_rdf_dir); createDirectory(path); } */ /* * Scan the repository. */ if (tree->rpmpath[0] != '\0') snprintf(path, sizeof(path), "%s/%s", dir->rpmdir, tree->rpmpath); else snprintf(path, sizeof(path), "%s", dir->rpmdir); if (rpm2htmlVerbose > 1) printf("Scanning directory %s\n", path); d = opendir(path); if (d == NULL) { fprintf(stderr, "Listing of %s failed: %s\n", path, strerror(errno)); rpmRemoveSubdir(tree); rpmFreeSubdir(tree); return(NULL); } else { while ((file = readdir(d)) != NULL) { cur = NULL; filename = file->d_name; len = strlen(filename); /* * Compute the full path */ if (tree->rpmpath[0] != '\0') snprintf(path, sizeof(path), "%s/%s/%s", dir->rpmdir, tree->rpmpath, filename); else snprintf(path, sizeof(path), "%s/%s", dir->rpmdir, filename); /* * Stat() the file to detect directory and symlimks */ if (lstat(path, &buf) != 0) { fprintf(stderr, "Couldn't stat(%s)\n", path); continue; } /* * Check for RPM files by looking at the suffix * Note that SuSE source RPMs have a ".spm" suffix * We may or may not follow symlinks to RPM files */ if (((len >= 5) && (!strcasecmp(&filename[len - 4], ".rpm"))) || ((len >= 5) && (!strcasecmp(&filename[len - 4], ".spm")))) { if ((S_ISLNK(buf.st_mode)) && (dir->rpm_symlinks == 0)) { if (rpm2htmlVerbose > 1) fprintf(stderr, "Dropping symlink %s\n", path); continue; } cur = rpmOpen(filename, dir, tree); } /* * Don't follow of analyze symlinks, */ else if ((S_ISLNK(buf.st_mode)) && (dir->follow_symlinks == 0)) { if (rpm2htmlVerbose > 1) fprintf(stderr, "Dropping symlink %s\n", path); continue; } /* * Check for RDF files by looking at the suffix */ else if ((len >= 5) && (!strcasecmp(&filename[len - 4], ".rdf"))) { cur = rpmOpenRdf(filename, dir, tree); } /* * Else if this is a directory, recurse ! */ else if (S_ISDIR(buf.st_mode)) { if (filename[0] != '.') { subtree = rpmNewSubdir(tree, filename, NULL, NULL, NULL, 0); cur = rpmOneDirScan(dir, subtree); } } if (cur != NULL) ret = rpmAddList(ret, cur); } } closedir(d); /* * Dump the pages related to this directory. */ if (ret != NULL) ret = dumpDirIndex(dir, tree, ret); else { rpmRemoveSubdir(tree); rpmFreeSubdir(tree); } return(ret); } /* * Scan a directory for RPM files. */ static rpmDataPtr rpmDirScan(rpmDirPtr dir, rpmSubdirPtr tree) { rpmSubdirPtr cur; rpmDataPtr ret; if ((rpm2html_dump_html) && (dir->html) && (dir->build_tree != 0)) { dir->root = rpmCreateRealRoot(); } cur = rpmNewSubdir(tree, dir->name, dir->subdir == NULL ? "" : dir->subdir, "", dir->color, dir->html); ret = rpmOneDirScan(dir, cur); rpmDumpHtmlRealRoot(dir); return(ret); } /* * Scan the local RPM database for RPM files. */ static rpmDataPtr rpmBaseScan(rpmDirPtr dir) { static char path[2000]; rpmDataPtr ret = NULL, cur; rpmdb db; Header h = NULL; #ifndef USE_RPMIO int offset; #endif char *prefix = "/"; /* * Create the directory for the HTML pages */ if ((rpm2html_dump_html) && (dir->html)) { if (dir->subdir) snprintf(path, sizeof(path), "%s/%s", dir->dir, dir->subdir); else snprintf(path, sizeof(path), "%s", dir->dir); createDirectory(path); } /* * Create the directory for the RDF pages */ if (rpm2html_rdf_dir != NULL) { if (dir->subdir) snprintf(path, sizeof(path), "%s/%s", rpm2html_rdf_dir, dir->subdir); else snprintf(path, sizeof(path), "%s", rpm2html_rdf_dir); createDirectory(path); } if (rpm2htmlVerbose) printf("Scanning the database of installed RPMs\n"); if (dir->dbpath != NULL) addMacro(NULL, "_dbpath", NULL, dir->dbpath, -7); /* Added by A.Gibert */ if (rpmdbOpen(prefix, &db, O_RDONLY, 0644)) { return(NULL); } #ifdef USE_RPMIO { rpmdbMatchIterator mi; mi = rpmdbInitIterator(db, RPMDBI_PACKAGES, NULL, 0); while ((h = rpmdbNextIterator(mi)) != NULL) { cur = rpmAnalyze(NULL, NULL, h, dir, NULL, 0, 0); if (cur != NULL) ret = rpmAddList(ret, cur); } rpmdbFreeIterator(mi); } #else /* USE_RPMIO */ offset = rpmdbFirstRecNum(db); while (offset) { h = rpmdbGetRecord(db, offset); if (!h) { fprintf(stderr, "could not read database record!\n"); return(ret); } cur = rpmAnalyze(NULL, NULL, h, dir, NULL, 0, 0); if (cur != NULL) ret = rpmAddList(ret, cur); headerFree(h); offset = rpmdbNextRecNum(db, offset); } #endif /* USE_RPMIO */ rpmdbClose(db); return(ret); } /* * Scan all registered directories. * One fist check for completeness of the informations in * the rpmDir structure. */ rpmDataPtr rpmDirScanAll(void) { rpmDirPtr dir, next; rpmDataPtr ret = NULL, cur; int maxLists = 50; rpmDataPtr *rpmLists; int nbLists = 0; int i; /* * first reverse the list .... */ dir = dirList; dirList = NULL; while (dir != NULL) { next = dir->next; dir->next = dirList; dirList = dir; dir = next; } dir = dirList; /* * Allocate a directory tree. */ dirTree = rpmNewSubdir(NULL, "", "", "", NULL, 1); rpmLists = (rpmDataPtr *) debugMalloc(maxLists * sizeof(rpmDataPtr)); if (rpmLists == NULL) { fprintf(stderr, "rpmDirScanAll : running out of memory !\n"); exit(1); } while (dir != NULL) { cur = NULL; /* * Override default setting. */ if ((dir->maint == NULL) && (rpm2html_maint != NULL)) dir->maint = debugStrdup(rpm2html_maint); if ((dir->mail == NULL) && (rpm2html_mail != NULL)) dir->mail = debugStrdup(rpm2html_mail); if ((dir->ftp == NULL) && (rpm2html_ftp != NULL)) dir->ftp = debugStrdup(rpm2html_ftp); if ((dir->ftpsrc == NULL) && (rpm2html_ftpsrc != NULL)) dir->ftpsrc = debugStrdup(rpm2html_ftpsrc); if ((dir->dir == NULL) && (rpm2html_dir != NULL)) dir->dir = debugStrdup(rpm2html_dir); if ((dir->host == NULL) && (rpm2html_host != NULL)) dir->host = debugStrdup(rpm2html_host); if ((dir->name == NULL) && (rpm2html_name != NULL)) dir->name = debugStrdup(rpm2html_name); if ((dir->url == NULL) && (rpm2html_url != NULL)) dir->url = debugStrdup(rpm2html_url); if (dir->rpmdir == NULL) { fprintf(stderr, "?!? rpmDir without directory ?!? disabled !\n"); } else if (!strncmp(dir->rpmdir, "localbase", 9)) { /* Added by A. Gibert */ /* Scan the local RPM database instead of a directory */ cur = rpmBaseScan(dir); } else if (dir->ftp == NULL) { fprintf(stderr, "Directory %s disabled : no ftp field\n", dir->rpmdir); } else { if (rpm2htmlVerbose) printf("Scanning directory %s for RPMs\n",dir->rpmdir); cur = rpmDirScan(dir, dirTree); } if (cur != NULL) { if (nbLists >= maxLists) { maxLists *= 2; rpmLists = (rpmDataPtr *) debugRealloc(rpmLists, maxLists * sizeof(rpmDataPtr)); if (rpmLists == NULL) { fprintf(stderr, "rpmDirScanAll : running out of memory!\n"); exit(1); } } rpmLists[nbLists] = cur; nbLists++; } if (dir->root != NULL) { /************************************************ if (rpm2html_build_tree) treeRoot = rpmMergeRealRoots(treeRoot, dir->root); else ************************************************/ rpmDestroyRealRoot(dir->root); dir->root = NULL; } dir = dir->next; } for (i = 0;i < nbLists;i++) ret = rpmAddList(ret, rpmLists[i]); debugFree(rpmLists); return(ret); } /* * Cleanup the global variables from this module */ void rpmopenCleanup(void) { if (buffer != NULL) debugFree(buffer); buffer = NULL; buffer_size = 50 * 1024 * sizeof(char); }