/* * rdf.c : implementation for the RDF encoding/decoding of RPM informations. */ #include "config.h" #include #ifdef HAVE_FCNTL_H #include #endif #include #include #include #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include "rpm2html.h" #include "rpmdata.h" #include "html.h" #include "language.h" #include "rdf_api.h" #include "rdf.h" /* * 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 rpmOpenRdf(char *nameRdf, rpmDirPtr dir, rpmSubdirPtr tree) { char file[1000]; char nameBuffer[200]; rdfSchema rdf; rdfNamespace rpmNs; rdfNamespace rdfNs; rdfDescription desc; rdfBag bag; rdfElement elem; char *value; rpmDataPtr rpm; struct stat buf; int i; /* * open the file for reading */ if (tree->htmlpath[0] != '\0') sprintf(file, "%s/%s/%s", dir->rpmdir, tree->rpmpath, nameRdf); else sprintf(file, "%s/%s", dir->rpmdir, nameRdf); 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 the rpmData structure, initialize it. */ rpm = (rpmDataPtr) malloc(sizeof(rpmData)); if (rpm == NULL) { fprintf(stderr, "rpmOpenRdf : out of memory !\n"); rdfDestroySchema(rdf); return(NULL); } memset(rpm, 0, sizeof(rpmData)); rpm->dir = dir; if (tree) { if ((tree->rpmpath != NULL) && (tree->rpmpath[0] != '\0')) rpm->subdir = strdup(tree->rpmpath); else rpm->subdir = NULL; } else rpm->subdir = NULL; stat(file, &buf); rpm->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 = strdup(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 = strdup(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 = strdup(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 = strdup(value); else rpm->url = NULL; rdfGetValue(desc, "Arch", rpmNs, &value, NULL); if (value != NULL) rpm->arch = strdup(value); else rpm->arch = strdup(localizedStrings[LANG_NONE]); rdfGetValue(desc, "Os", rpmNs, &value, NULL); if (value != NULL) rpm->os = strdup(value); else rpm->os = strdup("linux"); rdfGetValue(desc, "Distribution", rpmNs, &value, NULL); if (value != NULL) rpm->distribution = strdup(value); else rpm->distribution = strdup(localizedStrings[LANG_UNKNOWN]); rdfGetValue(desc, "Vendor", rpmNs, &value, NULL); if (value != NULL) rpm->vendor = strdup(value); else rpm->vendor = strdup(localizedStrings[LANG_UNKNOWN]); rdfGetValue(desc, "Packager", rpmNs, &value, NULL); if (value != NULL) rpm->packager = strdup(value); else rpm->packager = NULL; rdfGetValue(desc, "Group", rpmNs, &value, NULL); if (value != NULL) rpm->group = strdup(value); else rpm->group = strdup(localizedStrings[LANG_NO_GROUP]); rdfGetValue(desc, "Summary", rpmNs, &value, NULL); if (value != NULL) rpm->summary = strdup(value); else rpm->summary = strdup(localizedStrings[LANG_NO_SUMMARY]); rdfGetValue(desc, "Description", rpmNs, &value, NULL); if (value != NULL) rpm->description = strdup(value); else rpm->description = strdup(localizedStrings[LANG_NO_DESCRIPTION]); rdfGetValue(desc, "Copyright", rpmNs, &value, NULL); if (value != NULL) rpm->copyright = strdup(value); else rpm->copyright = NULL; rdfGetValue(desc, "Changelog", rpmNs, &value, NULL); if (value != NULL) rpm->changelog = strdup(value); else rpm->changelog = NULL; rdfGetValue(desc, "Sources", rpmNs, &value, NULL); if (value != NULL) { rpm->srcrpm = strdup(value); } else rpm->srcrpm = strdup(""); rdfGetValue(desc, "Size", rpmNs, &value, NULL); if (value != NULL) { if (sscanf(value, "%d", &(rpm->size)) != 1) rpm->size = 0; } 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; } else rpm->date = 0; rdfGetValue(desc, "BuildHost", rpmNs, &value, NULL); if (value != NULL) rpm->host = strdup(value); else rpm->host = strdup(localizedStrings[LANG_NO_HOST]); rdfGetValue(desc, "Files", rpmNs, &value, NULL); if (value != NULL) rpm->filelist = strdup(value); else rpm->filelist = NULL; /* * Fetching packages provided is a bit more tricky, one have to * find the RDF Bag, and scan it's values. */ rpm->nb_resources = 0; rdfGetValue(desc, "Provides", rpmNs, NULL, &bag); if (bag != NULL) { elem = rdfFirstChild(bag); i = 0; while (elem != NULL) { if (i >= MAX_RES) { fprintf(stderr, "MAX_RES %d overflow, increase the limit!\n", MAX_RES); break; } /* * Check that we are scanning an RPM Resource. */ if ((!strcmp(rdfElemGetPropertyName(elem), "Resource")) && (rdfElemGetNamespace(elem) == rpmNs)) { value = rdfElemGetValue(elem); if (value != NULL) { rpm->resources[i] = rpmRessAdd(value, rpm, 0); i++; rpm->nb_resources++; } else if (verbose > 1) { fprintf(stderr, "%s : malformed Resource element !\n", file); } } else if (verbose > 1) { fprintf(stderr, "%s : malformed Provides bag !\n", file); } elem = rdfNextElem(elem); } } else if (verbose > 1) { fprintf(stderr, "%s doesn't export any resource\n", file); } /* * idem for the dependencies. */ rpm->nb_requires = 0; rdfGetValue(desc, "Requires", rpmNs, NULL, &bag); if (bag != NULL) { elem = rdfFirstChild(bag); i = 0; while (elem != NULL) { if (i >= MAX_REQU) { fprintf(stderr, "MAX_RES %d overflow, increase the limit!\n", MAX_REQU); break; } /* * Check that we are scanning an RPM Resource. */ if ((!strcmp(rdfElemGetPropertyName(elem), "Resource")) && (rdfElemGetNamespace(elem) == rpmNs)) { value = rdfElemGetValue(elem); if (value != NULL) { rpm->requires[i] = rpmRequAdd(value, rpm, 0); i++; rpm->nb_requires++; } else if (verbose > 1) { fprintf(stderr, "%s : malformed Resource element !\n", file); } } else if (verbose > 1) { fprintf(stderr, "%s : malformed Provides bag !\n", file); } elem = rdfNextElem(elem); } } /* * Finish filling the rpmData structure. */ #ifdef HAVE_SNPRINTF sprintf(nameBuffer, "%s-%s-%s.rpm", rpm->name, rpm->version, rpm->release); #else snprintf(nameBuffer, 200, "%s-%s-%s.rpm", rpm->name, rpm->version, rpm->release); #endif rpm->filename = strdup(nameBuffer); /* Add the package files to the real filesystem tree if asked for */ if ((dir->build_tree != 0) && (rpm->filelist != NULL)) { char *cur, *filename; cur = rpm->filelist; while ((*cur != '\0') && (*cur != '/')) cur++; filename = cur; while (*cur != '\0') { if ((*cur == '\n') || (*cur == '\r')) { if (cur != filename) rpmAddRealFile(dir->root, filename, rpm); 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 */ if (rpm->filelist) free(rpm->filelist); rpm->filelist = NULL; if (rpm->copyright) free(rpm->copyright); rpm->copyright = NULL; if (rpm->changelog) free(rpm->changelog); rpm->changelog = NULL; if (rpm->description) free(rpm->description); rpm->description = NULL; /* increment the counters */ rpm2html_files++; rpm2html_size += rpm->size / 1024; /* * Cleanup. */ rdfDestroySchema(rdf); return(rpm); } /* * Create and RDF file containing the description for the given RPM data. */ void dumpRpmRdf(rpmDataPtr rpm, rpmSubdirPtr tree) { struct tm * tstruct; rpmDirPtr dir = rpm->dir; char *base = dir->dir; int i; char buf[10000]; char file[1000]; rdfSchema rdf; rdfNamespace rpmNs; rdfDescription desc; rdfBag bag; if (!rpm2html_dump_rdf) return; if (rpm2html_rdf_dir != NULL) base = rpm2html_rdf_dir; if ((dir->subdir != NULL) && (dir->subdir[0] != '\0')) { if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0')) sprintf(file, "%s/%s/%s/%s.rdf", base, dir->subdir, rpm->subdir, rpmName(rpm)); else sprintf(file, "%s/%s/%s.rdf", base, dir->subdir, rpmName(rpm)); } else { if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0')) sprintf(file, "%s/%s/%s.rdf", base, rpm->subdir, rpmName(rpm)); else sprintf(file, "%s/%s.rdf", base, rpmName(rpm)); } if (checkDate(file, rpm->stamp)) return; if (verbose > 1) { printf("Dumping %s\n", file); } /* * 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) sprintf(buf, "%s/%s/%s", dir->mirrors[0], rpm->subdir, rpm->filename); else sprintf(buf, "%s/%s/%s", dir->ftp, rpm->subdir, rpm->filename); } else { if (dir->mirrors[0] != NULL) sprintf(buf, "%s/%s", dir->mirrors[0], rpm->filename); else sprintf(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->packager) rdfSetValue(desc, "Packager", rpmNs, rpm->packager); if (rpm->group) rdfSetValue(desc, "Group", rpmNs, rpm->group); if (rpm->summary) rdfSetValue(desc, "Summary", rpmNs, rpm->summary); if (rpm->description) rdfSetValue(desc, "Description", rpmNs, rpm->description); if (rpm->copyright) rdfSetValue(desc, "Copyright", rpmNs, rpm->copyright); if (rpm->changelog) rdfSetValue(desc, "Changelog", rpmNs, rpm->changelog); if (rpm->srcrpm) { rdfSetValue(desc, "Sources", rpmNs, rpm->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); sprintf(buf, "%d", rpm->size); rdfSetValue(desc, "Size", rpmNs, buf); if (rpm->host) rdfSetValue(desc, "BuildHost", rpmNs, rpm->host); if (rpm->nb_resources > 0) { /** !!!!! sprintf(buf, "%d", rpm->nb_resources); rdfSetValue(desc, "NbProvides", rpmNs, buf); */ bag = rdfBagCreate(rdf, desc, "Provides", rpmNs); for (i = 0;i < rpm->nb_resources;i++) { rdfBagAddValue(bag, "Resource", rpmNs, rpm->resources[i]->name, NULL); } } if (rpm->nb_requires > 0) { /** !!!!! sprintf(buf, "%d", rpm->nb_requires); rdfSetValue(desc, "NbRequires", rpmNs, buf); */ bag = rdfBagCreate(rdf, desc, "Requires", rpmNs); for (i = 0;i < rpm->nb_requires;i++) { rdfBagAddValue(bag, "Resource", rpmNs, rpm->requires[i]->name, NULL); } } if (rpm->filelist) rdfSetValue(desc, "Files", rpmNs, rpm->filelist); /* * Save the RDF file and cleanup the tree. */ rdfWrite(rdf, file); rdfDestroySchema(rdf); }