/*
* rdf.c : implementation for the RDF encoding/decoding of RPM informations.
*/
#include "config.h"
#include <sys/stat.h>
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <time.h>
#include <errno.h>
#include <ctype.h>
#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;
/*
* Create the directory if needed
*/
if ((dir->subdir != NULL) && (dir->subdir[0] != '\0')) {
if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0'))
sprintf(buf, "%s/%s/%s", base, dir->subdir, rpm->subdir);
else
sprintf(buf, "%s/%s", base, dir->subdir);
} else {
if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0'))
sprintf(buf, "%s/%s", base, rpm->subdir);
else
sprintf(buf, "%s", base);
}
createDirectory(buf);
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);
}
Webmaster