/* * rdf.c : implementation for the RDF encoding/decoding of RPM informations. * * See Copyright for the status of this software. * * $Id: rdf.c,v 1.47 2000/12/10 17:10:38 veillard Exp $ */ #include "config.h" #include #ifdef HAVE_FCNTL_H #include #endif #include #include #include #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include #include "rpm2html.h" #include "rpmdata.h" #include "html.h" #include "language.h" #include "rdf_api.h" #include "rdf.h" #ifdef WITH_SQL #include "sql.h" #endif #ifndef HAVE_SNPRINTF #error Sorry you really need snprintf for basic security reasons #endif /* * Open and process an RDF file in the incoming tree of an rpm2html mirror. */ rpmDataPtr rpmOpenRdf(char *nameRdf, rpmDirPtr dir, rpmSubdirPtr tree) { char file[1000]; rpmDataPtr rpm; #ifdef WITH_SQL int id; int i; #endif /* * create path */ if (tree->htmlpath[0] != '\0') snprintf(file, sizeof(file), "%s/%s/%s", dir->rpmdir, tree->rpmpath, nameRdf); else snprintf(file, sizeof(file), "%s/%s", dir->rpmdir, nameRdf); rpm = rpmOpenRdfFile(file); if (rpm != NULL) { /* setup tree and subdir informations */ 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; #ifdef WITH_SQL id = sql_add_package(file, 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, rpm->date, rpm->size, rpm->os, rpm->distribution, rpm->vendor); 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]->flag, 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) dumpRpmHtml(rpm, tree); if (rpm2html_dump_rdf) dumpRpmRdf(rpm, tree); /* free large amount of data not used later */ rpmFreeExtraData(rpm); /* increment the counters */ rpm2html_files++; rpm2html_size += rpm->size / 1024; } return(rpm); } /* * Open an RDF file call the parser to create a XML tree * Then walk the tree and build an rpmData structure for * the corresponding package. */ rpmDataPtr rpmOpenRdfFile(char *file) { char nameBuffer[200]; rdfSchema rdf; rdfNamespace rpmNs; rdfNamespace rdfNs; rdfDescription desc; rdfBag bag; rdfElement elem; char *value; rpmDataPtr rpm; struct stat buf; int i; rdf = rdfRead(file); if (rdf == NULL) return(NULL); /* * Start the analyze, check that's an RDf for RPM packages. */ rdfNs = rdfGetNamespace(rdf, "http://www.w3.org/TR/WD-rdf-syntax#"); if (rdfNs == NULL) { fprintf(stderr, "%s is not an RDF schema\n", file); rdfDestroySchema(rdf); return(NULL); } rpmNs = rdfGetNamespace(rdf, "http://www.rpm.org/"); if (rdfNs == NULL) { fprintf(stderr, "%s is not an RPM specific RDF schema\n", file); rdfDestroySchema(rdf); return(NULL); } desc = rdfFirstDescription(rdf); if (rdfNs == NULL) { fprintf(stderr, "%s RDF schema seems empty\n", file); rdfDestroySchema(rdf); return(NULL); } /* * We are pretty sure that it will be a valid schema, * allocate a new rpmData block, and an rpmExtraData block fill them */ rpm = (rpmDataPtr) xmlMalloc(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) xmlMalloc(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)); stat(file, &buf); rpm->extra->stamp = buf.st_mtime; /* * Now extract all the metadata informations from the RDF tree */ rdfGetValue(desc, "Name", rpmNs, &value, NULL); if (value != NULL) { rpm->name = stringAdd(value); xmlFree(value); } else { fprintf(stderr, "%s RDF schema invalid : no Name\n", file); rdfDestroySchema(rdf); return(NULL); } rdfGetValue(desc, "Version", rpmNs, &value, NULL); if (value != NULL) { rpm->version = stringAdd(value); xmlFree(value); } else { fprintf(stderr, "%s RDF schema invalid : no Version\n", file); rdfDestroySchema(rdf); return(NULL); } rdfGetValue(desc, "Release", rpmNs, &value, NULL); if (value != NULL) { rpm->release = stringAdd(value); xmlFree(value); } else { fprintf(stderr, "%s RDF schema invalid : no Release\n", file); rdfDestroySchema(rdf); return(NULL); } rdfGetValue(desc, "URL", rpmNs, &value, NULL); if (value != NULL) rpm->url = value; else rpm->url = NULL; rdfGetValue(desc, "Arch", rpmNs, &value, NULL); if (value != NULL) { rpm->arch = stringAdd(value); xmlFree(value); } else rpm->arch = xmlStrdup("noarch"); rdfGetValue(desc, "Os", rpmNs, &value, NULL); if (value != NULL) { rpm->os = stringAdd(value); xmlFree(value); } else rpm->os = xmlStrdup("linux"); rdfGetValue(desc, "Distribution", rpmNs, &value, NULL); if (value != NULL) { rpm->distribution = stringAdd(value); xmlFree(value); } else rpm->distribution = stringAdd(localizedStrings[LANG_UNKNOWN]); rdfGetValue(desc, "Vendor", rpmNs, &value, NULL); if (value != NULL) { rpm->vendor = stringAdd(value); xmlFree(value); } else rpm->vendor = xmlStrdup(localizedStrings[LANG_UNKNOWN]); rdfGetValue(desc, "Packager", rpmNs, &value, NULL); if (value != NULL) rpm->extra->packager = value; else rpm->extra->packager = NULL; rdfGetValue(desc, "Group", rpmNs, &value, NULL); if (value != NULL) { rpm->group = stringAdd(value); xmlFree(value); } else rpm->group = xmlStrdup(localizedStrings[LANG_NO_GROUP]); rdfGetValue(desc, "Summary", rpmNs, &value, NULL); if (value != NULL) rpm->summary = value; else rpm->summary = xmlStrdup(localizedStrings[LANG_NO_SUMMARY]); rdfGetValue(desc, "Description", rpmNs, &value, NULL); if (value != NULL) rpm->extra->description = value; else rpm->extra->description = xmlStrdup(localizedStrings[LANG_NO_DESCRIPTION]); rdfGetValue(desc, "Copyright", rpmNs, &value, NULL); if (value != NULL) rpm->extra->copyright = value; else rpm->extra->copyright = NULL; rdfGetValue(desc, "Changelog", rpmNs, &value, NULL); if (value != NULL) rpm->extra->changelog = value; else rpm->extra->changelog = NULL; rdfGetValue(desc, "Sources", rpmNs, &value, NULL); if (value != NULL) { rpm->extra->srcrpm = value; } else rpm->extra->srcrpm = xmlStrdup(""); rdfGetValue(desc, "Size", rpmNs, &value, NULL); if (value != NULL) { if (sscanf(value, "%d", &(rpm->size)) != 1) rpm->size = 0; xmlFree(value); } else rpm->size = 0; rdfGetValue(desc, "Date", rpmNs, &value, NULL); if (value != NULL) { if (sscanf(value, "%d", &i) != 1) rpm->date = 0; else rpm->date = i; xmlFree(value); } else rpm->date = 0; rdfGetValue(desc, "BuildHost", rpmNs, &value, NULL); if (value != NULL) rpm->extra->host = value; else rpm->extra->host = xmlStrdup(localizedStrings[LANG_NO_HOST]); rdfGetValue(desc, "Files", rpmNs, &value, NULL); if (value != NULL) rpm->extra->filelist = value; else rpm->extra->filelist = NULL; /* * Fetching packages provided is a bit more tricky, one have to * find the RDF Bag, and scan it's values. */ rpm->extra->nb_resources = 0; rdfGetValue(desc, "Provides", rpmNs, NULL, &bag); if (bag != NULL) { elem = rdfFirstChild(bag); rpm->extra->max_resources = 5; rpm->extra->resources = (rpmRessPtr *) xmlMalloc(rpm->extra->max_resources * sizeof(rpmRessPtr)); if (rpm->extra->resources == NULL) { fprintf(stderr, "rpmOpenRdf : ran out of memory\n"); exit(1); } i = 0; while (elem != NULL) { char *name; if (i >= rpm->extra->max_resources) { rpm->extra->max_resources *= 2; rpm->extra->resources = (rpmRessPtr *) xmlRealloc(rpm->extra->resources, rpm->extra->max_resources * sizeof(rpmRessPtr)); if (rpm->extra->resources == NULL) { fprintf(stderr, "rpmOpenRdf : ran out of memory\n"); exit(1); } } /* * Check that we are scanning an RPM Resource. */ name = rdfElemGetPropertyName(elem); if ((name != NULL) && (!strcmp(name, "Resource")) && (rdfElemGetNamespace(elem) == rpmNs)) { value = rdfElemGetValue(elem); if (value != NULL) { rpm->extra->resources[i] = rpmRessAdd(value, rpm, 0); i++; rpm->extra->nb_resources++; xmlFree(value); } else if (rpm2htmlVerbose > 1) { fprintf(stderr, "%s : malformed Resource element !\n", file); } } else if (rpm2htmlVerbose > 1) { fprintf(stderr, "%s : malformed Provides bag !\n", file); } if (name != NULL) xmlFree(name); elem = rdfNextElem(elem); } } else if (rpm2htmlVerbose > 1) { fprintf(stderr, "%s doesn't export any resource\n", file); } /* * idem for the dependencies. */ rpm->extra->nb_requires = 0; rdfGetValue(desc, "Requires", rpmNs, NULL, &bag); if (bag != NULL) { elem = rdfFirstChild(bag); rpm->extra->max_requires = 5; rpm->extra->requires = (rpmRessPtr *) xmlMalloc(rpm->extra->max_requires * sizeof(rpmRessPtr)); if (rpm->extra->requires == NULL) { fprintf(stderr, "rpmOpenRdf : ran out of memory\n"); exit(1); } i = 0; while (elem != NULL) { char *name; if (i >= rpm->extra->max_requires) { rpm->extra->max_requires *= 2; rpm->extra->requires = (rpmRessPtr *) xmlRealloc(rpm->extra->requires, rpm->extra->max_requires * sizeof(rpmRessPtr)); if (rpm->extra->requires == NULL) { fprintf(stderr, "rpmOpenRdf : ran out of memory\n"); exit(1); } } /* * Check that we are scanning an RPM Resource. */ name = rdfElemGetPropertyName(elem); if ((name != NULL) && (!strcmp(name, "Resource")) && (rdfElemGetNamespace(elem) == rpmNs)) { value = rdfElemGetValue(elem); if (value != NULL) { rpm_dep_flag dep = RPM2HTML_REQ_NONE; xmlChar *reqval = NULL; if ((reqval = xmlGetProp(elem, "gt")) != NULL) { dep = RPM2HTML_REQ_GT; } else if ((reqval = xmlGetProp(elem, "geq")) != NULL) { dep = RPM2HTML_REQ_GEQ; } else if ((reqval = xmlGetProp(elem, "lt")) != NULL) { dep = RPM2HTML_REQ_LT; } else if ((reqval = xmlGetProp(elem, "leq")) != NULL) { dep = RPM2HTML_REQ_LEQ; } else if ((reqval = xmlGetProp(elem, "equ")) != NULL) { dep = RPM2HTML_REQ_EQU; } /* * TODO: fix to import RDF dept to a specific version */ rpm->extra->requires[i] = rpmRequAdd(value, reqval, dep, rpm, 0); i++; rpm->extra->nb_requires++; xmlFree(value); if (reqval != NULL) xmlFree(reqval); } else if (rpm2htmlVerbose > 1) { fprintf(stderr, "%s : malformed Resource element !\n", file); } } else if (rpm2htmlVerbose > 1) { fprintf(stderr, "%s : malformed Provides bag !\n", file); } if (name != NULL) xmlFree(name); elem = rdfNextElem(elem); } } /* * Finish filling the rpmData structure. */ value = rdfGetDescriptionAbout(rdf, desc); if (value != NULL) { char *filename = &value[strlen(value)]; while ((filename > value) && (*filename != '/')) filename --; rpm->filename = xmlStrdup(filename); xmlFree(value); } else { snprintf(nameBuffer, 200, "%s-%s-%s.%s.rpm", rpm->name, rpm->version, rpm->release, rpm->arch); rpm->filename = xmlStrdup(nameBuffer); } /* * Cleanup. */ rdfDestroySchema(rdf); return(rpm); } /* * Create and RDF file containing the description for the given RPM data. */ void dumpRpmRdf(rpmDataPtr rpm, rpmSubdirPtr tree) { FILE *output; struct stat stat_buf; struct tm * tstruct; rpmDirPtr dir = rpm->dir; char *base = dir->dir; int i; char buf[10000]; char file[1000]; char dotdot[50]; char *buffer; int size; int stat_res = 0; rdfSchema rdf; rdfNamespace rpmNs; rdfDescription desc; rdfElement elem; rdfBag bag; int deep; const char *ptr; if (!rpm2html_dump_rdf) return; if (rpm2html_rdf_dir != NULL) base = rpm2html_rdf_dir; deep = 0; if (rpm->subdir != NULL) for (ptr = rpm->subdir, deep++;*ptr != 0;ptr++) if (*ptr == '/') deep++; if (dir->subdir != NULL) for (ptr = dir->subdir, deep++;*ptr != 0;ptr++) if (*ptr == '/') deep++; if ((dir->subdir != NULL) && (dir->subdir[0] != '\0')) { if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0')) snprintf(file, sizeof(file), "%s/%s/%s/%s.rdf", base, dir->subdir, rpm->subdir, rpmName(rpm)); else snprintf(file, sizeof(file), "%s/%s/%s.rdf", base, dir->subdir, rpmName(rpm)); } else { if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0')) snprintf(file, sizeof(file), "%s/%s/%s.rdf", base, rpm->subdir, rpmName(rpm)); else snprintf(file, sizeof(file), "%s/%s.rdf", base, rpmName(rpm)); } dotdot[0] = '\0'; for (;deep > 0;deep --) strcat(dotdot, "../"); /* * Check wether the RPM timestamp is older than the filestamp. if ((stat_res = stat(file, &stat_buf)) == 0) { if (stat_buf.st_mtime > rpm->stamp) return; } */ stat_res = stat(file, &stat_buf); /* * Create the directory if needed */ if ((dir->subdir != NULL) && (dir->subdir[0] != '\0')) { if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0')) snprintf(buf, sizeof(buf), "%s/%s/%s", base, dir->subdir, rpm->subdir); else snprintf(buf, sizeof(buf), "%s/%s", base, dir->subdir); } else { if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0')) snprintf(buf, sizeof(buf), "%s/%s", base, rpm->subdir); else snprintf(buf, sizeof(buf), "%s", base); } createDirectory(buf); /* * build the RDF document tree * Note : the order is not important but following the rpmData * structure order is easier to check. */ rdf = rdfNewSchema(); rpmNs = rdfNewNamespace(rdf, "http://www.rpm.org/", "RPM"); if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0')) { if (dir->mirrors[0] != NULL) snprintf(buf, sizeof(buf), "%s/%s/%s", dir->mirrors[0], rpm->subdir, rpm->filename); else snprintf(buf, sizeof(buf), "%s/%s/%s", dir->ftp, rpm->subdir, rpm->filename); } else { if (dir->mirrors[0] != NULL) snprintf(buf, sizeof(buf), "%s/%s", dir->mirrors[0], rpm->filename); else snprintf(buf, sizeof(buf), "%s/%s", dir->ftp, rpm->filename); } desc = rdfAddDescription(rdf, NULL, buf); rdfSetValue(desc, "Name", rpmNs, rpm->name); rdfSetValue(desc, "Version", rpmNs, rpm->version); rdfSetValue(desc, "Release", rpmNs, rpm->release); if (rpm->url) rdfSetValue(desc, "URL", rpmNs, rpm->url); if (rpm->arch) rdfSetValue(desc, "Arch", rpmNs, rpm->arch); if (rpm->os) rdfSetValue(desc, "Os", rpmNs, rpm->os); if (rpm->distribution) rdfSetValue(desc, "Distribution", rpmNs, rpm->distribution); if (rpm->vendor) rdfSetValue(desc, "Vendor", rpmNs, rpm->vendor); if (rpm->extra->packager) rdfSetValue(desc, "Packager", rpmNs, rpm->extra->packager); if (rpm->group) rdfSetValue(desc, "Group", rpmNs, rpm->group); if (rpm->summary) rdfSetValue(desc, "Summary", rpmNs, rpm->summary); if (rpm->extra->description) rdfSetValue(desc, "Description", rpmNs, rpm->extra->description); if (rpm->extra->copyright) rdfSetValue(desc, "Copyright", rpmNs, rpm->extra->copyright); if (rpm->extra->changelog) rdfSetValue(desc, "Changelog", rpmNs, rpm->extra->changelog); if (rpm->extra->srcrpm) { rdfSetValue(desc, "Sources", rpmNs, rpm->extra->srcrpm); if (dir->ftpsrc) { rdfSetValue(desc, "SourcesFtp", rpmNs, dir->ftpsrc); } } tstruct = localtime(&(rpm->date)); #ifdef HAVE_STRFTIME strftime(buf, sizeof(buf) - 1, "%c", tstruct); #else #error "no strftime, please check !" #endif rdfSetValue(desc, "BuildDate", rpmNs, buf); snprintf(buf, sizeof(buf), "%d", (int) rpm->date); rdfSetValue(desc, "Date", rpmNs, buf); snprintf(buf, sizeof(buf), "%d", rpm->size); rdfSetValue(desc, "Size", rpmNs, buf); if (rpm->extra->host) rdfSetValue(desc, "BuildHost", rpmNs, rpm->extra->host); if (rpm->extra->nb_resources > 0) { bag = rdfBagCreate(rdf, desc, "Provides", rpmNs); for (i = 0;i < rpm->extra->nb_resources;i++) { elem = rdfBagAddValue(bag, "Resource", rpmNs, rpm->extra->resources[i]->name, NULL); if (rpm->extra->resources[i]->name[0] != '/') { snprintf(buf, sizeof(buf) - 1, "%sresources/%s.rdf", dotdot, rpm->extra->resources[i]->name); xmlSetProp(elem, "href", buf); } } } if (rpm->extra->nb_requires > 0) { bag = rdfBagCreate(rdf, desc, "Requires", rpmNs); for (i = 0;i < rpm->extra->nb_requires;i++) { elem = rdfBagAddValue(bag, "Resource", rpmNs, rpm->extra->requires[i]->name, NULL); if (rpm->extra->requires[i]->name[0] != '/') { snprintf(buf, sizeof(buf) - 1, "%sresources/%s.rdf", dotdot, rpm->extra->requires[i]->name); xmlSetProp(elem, "href", buf); } if (rpm->extra->requires[i]->version != NULL) { switch (rpm->extra->requires[i]->flag) { case RPM2HTML_REQ_LT: xmlSetProp(elem, "lt", rpm->extra->requires[i]->version); break; case RPM2HTML_REQ_LEQ: xmlSetProp(elem, "leq", rpm->extra->requires[i]->version); break; case RPM2HTML_REQ_GT: xmlSetProp(elem, "gt", rpm->extra->requires[i]->version); break; case RPM2HTML_REQ_GEQ: xmlSetProp(elem, "geq", rpm->extra->requires[i]->version); break; case RPM2HTML_REQ_EQU: xmlSetProp(elem, "equ", rpm->extra->requires[i]->version); break; case RPM2HTML_REQ_NONE: break; } } } } if (rpm->extra->filelist) rdfSetValue(desc, "Files", rpmNs, rpm->extra->filelist); /* * Save the RDF to a buffer, remove the tree. */ rdfWriteMemory(rdf, &buffer, &size); rdfDestroySchema(rdf); if (buffer == NULL) return; /* * if the file already exists avoid to overwrite it if the content * didn't change. */ if ((stat_res == 0) && (stat_buf.st_size == size)) { char *buffer2 = xmlMalloc(size * sizeof(char)); if (buffer2 == NULL) { fprintf(stderr, " : running out of memory\n"); xmlFree(buffer); return; } output = fopen(file, "r"); if (output == NULL) { fprintf(stderr, "couldn't open %s for reading !\n", file); xmlFree(buffer2); xmlFree(buffer); return; } if (fread(buffer2, size, 1, output) != 1) { fprintf(stderr, "Problem reading from %s !\n", file); xmlFree(buffer); xmlFree(buffer2); } fclose(output); /* * Now compare the content ! */ if (!memcmp(buffer, buffer2, size)) { xmlFree(buffer2); xmlFree(buffer); if (rpm2htmlVerbose > 1) fprintf(stderr, "File %s : Content identical !\n", file); return; } xmlFree(buffer2); } /* * Dump the file. */ if (rpm2htmlVerbose > 1) { printf("Dumping %s\n", file); } output = fopen(file, "w"); if (output == NULL) { fprintf(stderr, "couldn't open %s for writing !\n", file); return; } if (fwrite(buffer, size, 1, output) != 1) { fprintf(stderr, "Problem writing to %s !\n", file); } xmlFree(buffer); fclose(output); } /* * Create and RDF file containing informations about a resource. */ void dumpResRdf(rpmRessPtr res) { FILE *output; struct stat stat_buf; char *base; int i; char buf[10000]; char file[1000]; char *buffer; int size; int stat_res; rpmDataPtr rpm; rpmDirPtr dir; rdfSchema rdf; rdfNamespace rpmNs; rdfDescription desc; static int initialized = 0; if (!rpm2html_dump_rdf_resources) return; if (rpm2html_rdf_resources_dir != NULL) base = rpm2html_rdf_resources_dir; else return; if (res->nb_provider == 0) return; snprintf(file, sizeof(file), "%s/%s.rdf", base, res->name); /* * Create the directory if needed */ if (!initialized) { snprintf(buf, sizeof(buf), "%s", base); createDirectory(buf); initialized = 1; } /* * build the RDF document tree * Note : the order is not important but following the rpmData * structure order is easier to check. */ rdf = rdfNewSchema(); rpmNs = rdfNewNamespace(rdf, "http://www.rpm.org/", "RPM"); for (i = 0;i < res->nb_provider;i++) { rpm = res->provider[i]; dir = rpm->dir; if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0')) { if (dir->mirrors[0] != NULL) snprintf(buf, sizeof(buf), "%s/%s/%s", dir->mirrors[0], rpm->subdir, rpm->filename); else snprintf(buf, sizeof(buf), "%s/%s/%s", dir->ftp, rpm->subdir, rpm->filename); } else { if (dir->mirrors[0] != NULL) snprintf(buf, sizeof(buf), "%s/%s", dir->mirrors[0], rpm->filename); else snprintf(buf, sizeof(buf), "%s/%s", dir->ftp, rpm->filename); } desc = rdfAddDescription(rdf, NULL, buf); if ((dir->subdir != NULL) && (dir->subdir[0] != '\0')) { if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0')) snprintf(buf, sizeof(buf), "../%s/%s/%s.rdf", dir->subdir, rpm->subdir, rpmName(rpm)); else snprintf(buf, sizeof(buf), "../%s/%s.rdf", dir->subdir, rpmName(rpm)); } else { if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0')) snprintf(buf, sizeof(buf), "../%s/%s.rdf", rpm->subdir, rpmName(rpm)); else snprintf(buf, sizeof(buf), "../%s.rdf", rpmName(rpm)); } xmlSetProp(desc, "href", buf); rdfSetValue(desc, "Name", rpmNs, rpm->name); rdfSetValue(desc, "Version", rpmNs, rpm->version); rdfSetValue(desc, "Release", rpmNs, rpm->release); if (rpm->arch) rdfSetValue(desc, "Arch", rpmNs, rpm->arch); if (rpm->os) rdfSetValue(desc, "Os", rpmNs, rpm->os); if (rpm->distribution) rdfSetValue(desc, "Distribution", rpmNs, rpm->distribution); if (rpm->vendor) rdfSetValue(desc, "Vendor", rpmNs, rpm->vendor); snprintf(buf, sizeof(buf), "%d", (int) rpm->date); rdfSetValue(desc, "Date", rpmNs, buf); snprintf(buf, sizeof(buf), "%d", (int) rpm->size); rdfSetValue(desc, "Size", rpmNs, buf); if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0')) { if ((dir->subdir != NULL) && (dir->subdir[0] != '\0')) snprintf(buf, sizeof(buf), "%s/%s", dir->subdir, rpm->subdir); else snprintf(buf, sizeof(buf), "%s", rpm->subdir); } else { if ((dir->subdir != NULL) && (dir->subdir[0] != '\0')) snprintf(buf, sizeof(buf), "%s", dir->subdir); else buf[0] = '\0'; } if (buf[0] != '\0') rdfSetValue(desc, "Subdir", rpmNs, buf); } /* * Save the RDF to a buffer, remove the tree. */ rdfWriteMemory(rdf, &buffer, &size); rdfDestroySchema(rdf); if (buffer == NULL) return; /* * if the file already exists avoid to overwrite it if the content * didn't change. */ stat_res = stat(file, &stat_buf); if ((stat_res == 0) && (stat_buf.st_size == size)) { char *buffer2 = xmlMalloc(size * sizeof(char)); if (buffer2 == NULL) { fprintf(stderr, " : running out of memory\n"); xmlFree(buffer); return; } output = fopen(file, "r"); if (output == NULL) { fprintf(stderr, "couldn't open %s for reading !\n", file); xmlFree(buffer); xmlFree(buffer2); return; } if (fread(buffer2, size, 1, output) != 1) { fprintf(stderr, "Problem reading from %s !\n", file); } fclose(output); /* * Now compare the content ! */ if (!memcmp(buffer, buffer2, size)) { xmlFree(buffer2); xmlFree(buffer); if (rpm2htmlVerbose > 1) fprintf(stderr, "File %s : Content identical !\n", file); return; } xmlFree(buffer2); } /* * Dump the file. */ if (rpm2htmlVerbose > 1) { printf("Dumping %s\n", file); } output = fopen(file, "w"); if (output == NULL) { fprintf(stderr, "couldn't open %s for writing !\n", file); xmlFree(buffer); return; } if (fwrite(buffer, size, 1, output) != 1) { fprintf(stderr, "Problem writing to %s !\n", file); xmlFree(buffer); } fclose(output); xmlFree(buffer); } /* * Dump all the RDf files about known resources. */ void dumpAllResRdf(void) { rpmRessPtr cur; if (!rpm2html_dump_rdf_resources) return; cur = ressList; while (cur != NULL) { dumpResRdf(cur); cur = cur->next; } } /* * Dump an apropos RDF file for all packages. * Since the file is really too big to be kept as-if, it is compressed */ void dumpAproposRdf(void) { rpmDataPtr rpm; char file[1000]; char buf[1000]; rdfSchema rdf; rdfNamespace rpmNs; rdfDescription desc; rpmDirPtr dir; char *base; char *buffer; int size; gzFile output; int res; if (!rpm2html_dump_rdf_resources) return; if (rpm2html_rdf_resources_dir != NULL) base = rpm2html_rdf_resources_dir; else return; snprintf(file, sizeof(file), "%s/fullIndex.rdf.gz", base); if (rpm2htmlVerbose > 1) { printf("Dumping %s\n", file); } /* * build the RDF document tree, one only dump the minimum needed * for searching. */ rdf = rdfNewSchema(); rpmNs = rdfNewNamespace(rdf, "http://www.rpm.org/", "RPM"); rpm = rpmSoftwareList; while (rpm != NULL) { dir = rpm->dir; if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0')) { if (dir->mirrors[0] != NULL) snprintf(buf, sizeof(buf), "%s/%s/%s", dir->mirrors[0], rpm->subdir, rpm->filename); else snprintf(buf, sizeof(buf), "%s/%s/%s", dir->ftp, rpm->subdir, rpm->filename); } else { if (dir->mirrors[0] != NULL) snprintf(buf, sizeof(buf), "%s/%s", dir->mirrors[0], rpm->filename); else snprintf(buf, sizeof(buf), "%s/%s", dir->ftp, rpm->filename); } desc = rdfAddDescription(rdf, NULL, buf); rdfSetValue(desc, "Name", rpmNs, rpm->name); rdfSetValue(desc, "Summary", rpmNs, rpm->summary); rpm = rpm->nextSoft; } /* * Dump the RDF tree, and cleanup. */ rdfWriteMemory(rdf, &buffer, &size); rdfDestroySchema(rdf); if (buffer == NULL) return; /* * Write the compressed version of the RDF base. */ output = gzopen(file, "w9"); if (output == NULL) { fprintf(stderr, "Could not write %s : gzopen failed\n", file); xmlFree(buffer); return; } res = gzwrite(output, buffer, size); if (res <= 0) { fprintf(stderr, "Could not write %s : gzwrite failed\n", file); xmlFree(buffer); return; } gzclose(output); xmlFree(buffer); } /* * Dump the distribs/xxx.rdf file giving information about a * specific distribution */ void dumpDistRdf(rpmDirPtr dir) { char buf[101] = ""; char file[1000]; rdfSchema rdf; rdfNamespace rpmNs; rdfDescription desc; rdfBag mirrors; rdfElement mirror; struct stat stat_buf; int stat_res; char *base, *ptr; char *buffer; int size; FILE *output; int i; if (!rpm2html_dump_rdf_resources) return; if (rpm2html_rdf_resources_dir != NULL) base = rpm2html_rdf_resources_dir; else return; if (dir->subdir) snprintf(buf, sizeof(buf), "%s", dir->subdir); for (ptr = &buf[0]; *ptr; ptr++) if (*ptr == '/') *ptr = '_'; snprintf(file, sizeof(file), "%s/distribs", base); createDirectory(file); snprintf(file, sizeof(file), "%s/distribs/%s.rdf", base, buf); /* * build the RDF document tree, one only dump the minimum needed * for searching distributions informations. */ rdf = rdfNewSchema(); rpmNs = rdfNewNamespace(rdf, "http://www.rpm.org/", "RPM"); desc = rdfAddDescription(rdf, NULL, dir->ftp); rdfSetValue(desc, "ID", rpmNs, dir->subdir); rdfSetValue(desc, "Name", rpmNs, dir->name); rdfSetValue(desc, "Origin", rpmNs, dir->ftp); rdfSetValue(desc, "Sources", rpmNs, dir->ftpsrc); snprintf(buf, sizeof(buf), "%d", dir->files); mirrors = rdfBagCreate(rdf, desc, "Mirrors", rpmNs); for (i = 0;i < dir->nb_mirrors;i++) { mirror = rdfBagAddValue(mirrors, "Mirror", rpmNs, NULL, NULL); rdfSetElementResource(rdf, mirror, dir->mirrors[i]); } /* * Dump the RDF tree, and cleanup. */ rdfWriteMemory(rdf, &buffer, &size); rdfDestroySchema(rdf); if (buffer == NULL) return; /* * if the file already exists avoid to overwrite it if the content * didn't change. */ stat_res = stat(file, &stat_buf); if ((stat_res == 0) && (stat_buf.st_size == size)) { char *buffer2 = xmlMalloc(size * sizeof(char)); if (buffer2 == NULL) { fprintf(stderr, " : running out of memory\n"); xmlFree(buffer); return; } output = fopen(file, "r"); if (output == NULL) { fprintf(stderr, "couldn't open %s for reading !\n", file); xmlFree(buffer2); xmlFree(buffer); return; } if (fread(buffer2, size, 1, output) != 1) { fprintf(stderr, "Problem reading from %s !\n", file); } fclose(output); /* * Now compare the content ! */ if (!memcmp(buffer, buffer2, size)) { xmlFree(buffer2); xmlFree(buffer); if (rpm2htmlVerbose > 1) fprintf(stderr, "File %s : Content identical !\n", file); return; } xmlFree(buffer2); } /* * Dump the file. */ if (rpm2htmlVerbose > 1) { printf("Dumping %s\n", file); } output = fopen(file, "w"); if (output == NULL) { fprintf(stderr, "couldn't open %s for writing !\n", file); xmlFree(buffer); return; } if (fwrite(buffer, size, 1, output) != 1) { fprintf(stderr, "Problem writing to %s !\n", file); xmlFree(buffer); } fclose(output); xmlFree(buffer); } /* * Dump the distribs/metadata.rdf file listing all the recognized * metadata mirrors sites. */ void dumpMetadataListRdf(void) { char file[1000]; rdfSchema rdf; rdfNamespace rpmNs; rdfDescription desc; struct stat stat_buf; int stat_res; char *base; char *buffer; int size; FILE *output; int i; if (!rpm2html_dump_rdf_resources) return; if (rpm2html_rdf_resources_dir != NULL) base = rpm2html_rdf_resources_dir; else return; snprintf(file, sizeof(file), "%s/distribs", base); createDirectory(file); snprintf(file, sizeof(file), "%s/distribs/metadata.rdf", base); /* * build the RDF document tree, one only dump the minimum needed * for searching distributions informations. */ rdf = rdfNewSchema(); rpmNs = rdfNewNamespace(rdf, "http://www.rpm.org/", "RPM"); for (i = 0;i < nb_metadata_mirrors;i++){ desc = rdfAddDescription(rdf, NULL, metadata_mirrors[i]); rdfSetValue(desc, "URI", rpmNs, metadata_mirrors[i]); } /* * Dump the RDF tree, and cleanup. */ rdfWriteMemory(rdf, &buffer, &size); rdfDestroySchema(rdf); if (buffer == NULL) return; /* * if the file already exists avoid to overwrite it if the content * didn't change. */ stat_res = stat(file, &stat_buf); if ((stat_res == 0) && (stat_buf.st_size == size)) { char *buffer2 = xmlMalloc(size * sizeof(char)); if (buffer2 == NULL) { fprintf(stderr, " : running out of memory\n"); xmlFree(buffer); return; } output = fopen(file, "r"); if (output == NULL) { fprintf(stderr, "couldn't open %s for reading !\n", file); xmlFree(buffer); xmlFree(buffer2); return; } if (fread(buffer2, size, 1, output) != 1) { fprintf(stderr, "Problem reading from %s !\n", file); } fclose(output); /* * Now compare the content ! */ if (!memcmp(buffer, buffer2, size)) { xmlFree(buffer2); xmlFree(buffer); if (rpm2htmlVerbose > 1) fprintf(stderr, "File %s : Content identical !\n", file); return; } xmlFree(buffer2); } /* * Dump the file. */ if (rpm2htmlVerbose > 1) { printf("Dumping %s\n", file); } output = fopen(file, "w"); if (output == NULL) { fprintf(stderr, "couldn't open %s for writing !\n", file); return; } if (fwrite(buffer, size, 1, output) != 1) { fprintf(stderr, "Problem writing to %s !\n", file); } fclose(output); xmlFree(buffer); } /* * Dump the distribs/list.rdf file listing all the recognized distributions * as well as the metadata mirrors list. */ void dumpDistListRdf(void) { rpmDirPtr dir; char file[1000]; rdfSchema rdf; rdfNamespace rpmNs; rdfDescription desc; struct stat stat_buf; int stat_res; char *base; char *buffer; int size; FILE *output; if (!rpm2html_dump_rdf_resources) return; if (rpm2html_rdf_resources_dir != NULL) base = rpm2html_rdf_resources_dir; else return; dumpMetadataListRdf(); snprintf(file, sizeof(file), "%s/distribs", base); createDirectory(file); snprintf(file, sizeof(file), "%s/distribs/list.rdf", base); /* * build the RDF document tree, one only dump the minimum needed * for searching distributions informations. */ rdf = rdfNewSchema(); rpmNs = rdfNewNamespace(rdf, "http://www.rpm.org/", "RPM"); dir = dirList; while (dir != NULL) { desc = rdfAddDescription(rdf, NULL, dir->ftp); rdfSetValue(desc, "ID", rpmNs, dir->subdir); dumpDistRdf(dir); dir = dir->next; } /* * Dump the RDF tree, and cleanup. */ rdfWriteMemory(rdf, &buffer, &size); rdfDestroySchema(rdf); if (buffer == NULL) return; /* * if the file already exists avoid to overwrite it if the content * didn't change. */ stat_res = stat(file, &stat_buf); if ((stat_res == 0) && (stat_buf.st_size == size)) { char *buffer2 = xmlMalloc(size * sizeof(char)); if (buffer2 == NULL) { fprintf(stderr, " : running out of memory\n"); xmlFree(buffer); return; } output = fopen(file, "r"); if (output == NULL) { fprintf(stderr, "couldn't open %s for reading !\n", file); xmlFree(buffer); xmlFree(buffer2); return; } if (fread(buffer2, size, 1, output) != 1) { fprintf(stderr, "Problem reading from %s !\n", file); } fclose(output); /* * Now compare the content ! */ if (!memcmp(buffer, buffer2, size)) { xmlFree(buffer2); xmlFree(buffer); if (rpm2htmlVerbose > 1) fprintf(stderr, "File %s : Content identical !\n", file); return; } xmlFree(buffer2); } /* * Dump the file. */ if (rpm2htmlVerbose > 1) { printf("Dumping %s\n", file); } output = fopen(file, "w"); if (output == NULL) { fprintf(stderr, "couldn't open %s for writing !\n", file); return; } if (fwrite(buffer, size, 1, output) != 1) { fprintf(stderr, "Problem writing to %s !\n", file); } fclose(output); xmlFree(buffer); }