File:  [Public] / rpm2html / rdf.c
Revision 1.21: download - view: text, annotated - select for diffs
Sun Jul 12 15:58:42 1998 UTC (25 years, 10 months ago) by daniel
Branches: MAIN
CVS tags: HEAD
Added dumpAproposRdf dumping the RDF catalog, Daniel.

/*
 * rdf.c : implementation for the RDF encoding/decoding of RPM informations.
 *
 * See Copyright for the status of this software.
 *
 * $Id: rdf.c,v 1.21 1998/07/12 15:58:42 daniel Exp $
 */

#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 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;

    /*
     * create path
     */
    if (tree->htmlpath[0] != '\0')
	sprintf(file, "%s/%s/%s", dir->rpmdir, tree->rpmpath, nameRdf);
    else
	sprintf(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 = strdup(tree->rpmpath);
	    else
		rpm->subdir = NULL;
	} else
	    rpm->subdir = NULL;

	/* 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;
    }
    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 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));

    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);
	rpm->max_resources = 5;
	rpm->resources = (rpmRessPtr *) malloc(rpm->max_resources *
	                                       sizeof(rpmRessPtr));
	if (rpm->resources == NULL) {
	    fprintf(stderr, "rpmOpenRdf : ran out of memory\n");
	    exit(1);
	}
	i = 0;
	while (elem != NULL) {
	    if (i >= rpm->max_resources) {
	        rpm->max_resources *= 2;
		rpm->resources = (rpmRessPtr *) realloc(rpm->resources,
		                   rpm->max_resources * sizeof(rpmRessPtr));
		if (rpm->resources == NULL) {
		    fprintf(stderr, "rpmOpenRdf : ran out of memory\n");
		    exit(1);
		}
	    }
	    /*
	     * 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 (rpm2htmlVerbose > 1) {
		    fprintf(stderr, "%s : malformed Resource element !\n", file);
		}
	    } else if (rpm2htmlVerbose > 1) {
	        fprintf(stderr, "%s : malformed Provides bag !\n", file);
	    }
	    elem = rdfNextElem(elem);
	}
    } else if (rpm2htmlVerbose > 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);
	rpm->max_requires = 5;
	rpm->requires = (rpmRessPtr *) malloc(rpm->max_requires *
	                                       sizeof(rpmRessPtr));
	if (rpm->requires == NULL) {
	    fprintf(stderr, "rpmOpenRdf : ran out of memory\n");
	    exit(1);
	}
	i = 0;
	while (elem != NULL) {
	    if (i >= rpm->max_requires) {
	        rpm->max_requires *= 2;
		rpm->requires = (rpmRessPtr *) realloc(rpm->requires,
		                   rpm->max_requires * sizeof(rpmRessPtr));
		if (rpm->requires == NULL) {
		    fprintf(stderr, "rpmOpenRdf : ran out of memory\n");
		    exit(1);
		}
	    }
	    /*
	     * 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 (rpm2htmlVerbose > 1) {
		    fprintf(stderr, "%s : malformed Resource element !\n", file);
		}
	    } else if (rpm2htmlVerbose > 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);


    /*
     * 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 *buffer;
    int size;
    int stat_res;
    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));
    }

    /*
     * 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;
    }

    /*
     * 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);

    /*
     * 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", (int) rpm->date);
    rdfSetValue(desc, "Date", 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 to a buffer, remove the tree.
     */
    rdfWriteMemory(rdf, &buffer, &size);
    rdfDestroySchema(rdf);

    /*
     * 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 = malloc(size * sizeof(char));

        if (buffer2 == NULL) {
	    fprintf(stderr, " : running out of memory\n");
	    return;
	}
	output = fopen(file, "r");
	if (output == NULL) {
	    fprintf(stderr, "couldn't open %s for reading !\n", file);
	    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)) {
	    free(buffer2);
	    if (rpm2htmlVerbose > 1)
		fprintf(stderr, "File %s : Content identical !\n", file);
	    return;
	}
	free(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);
}

/*
 * 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;

    sprintf(file, "%s/%s.rdf", base, res->name);

    /*
     * Create the directory if needed
     */
    if (!initialized) {
	sprintf(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)
		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->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);
	sprintf(buf, "%d", (int) rpm->date);
	rdfSetValue(desc, "Date", rpmNs, buf);
	sprintf(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'))
		sprintf(buf, "%s/%s",
		    dir->subdir, rpm->subdir);
	    else
		sprintf(buf, "%s",
		    rpm->subdir);
	} else {
	    if ((dir->subdir != NULL) && (dir->subdir[0] != '\0'))
		sprintf(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 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 = malloc(size * sizeof(char));

        if (buffer2 == NULL) {
	    fprintf(stderr, " : running out of memory\n");
	    return;
	}
	output = fopen(file, "r");
	if (output == NULL) {
	    fprintf(stderr, "couldn't open %s for reading !\n", file);
	    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)) {
	    free(buffer2);
	    if (rpm2htmlVerbose > 1)
		fprintf(stderr, "File %s : Content identical !\n", file);
	    return;
	}
	free(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);
}

/*
 * 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.
 */

void dumpAproposRdf(void) {
    rpmDataPtr rpm;
    char file[1000];
    char buf[1000];
    rdfSchema rdf;
    rdfNamespace rpmNs;
    rdfDescription desc;
    rpmDirPtr dir;
    char *base;

    if (!rpm2html_dump_rdf_resources) return;

    if (rpm2html_rdf_resources_dir != NULL) base = rpm2html_rdf_resources_dir;
    else return;

    sprintf(file, "%s/fullIndex.rdf", 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)
		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, "Description", rpmNs, rpm->description);
	rpm = rpm->nextArch;
    }

    /*
     * Dump the RDF tree, and cleanup.
     */
    rdfWrite(rdf, file);
    rdfDestroySchema(rdf);
}


Webmaster