Annotation of rpm2html/rdf.c, revision 1.22
1.1 httpng 1: /*
2: * rdf.c : implementation for the RDF encoding/decoding of RPM informations.
1.19 veillard 3: *
4: * See Copyright for the status of this software.
5: *
1.22 ! daniel 6: * $Id: rdf.c,v 1.21 1998/07/12 15:58:42 daniel Exp $
1.1 httpng 7: */
8:
1.2 httpng 9: #include "config.h"
1.6 veillard 10: #include <sys/stat.h>
1.2 httpng 11: #ifdef HAVE_FCNTL_H
12: #include <fcntl.h>
13: #endif
14: #include <stdio.h>
15: #include <stdlib.h>
16: #include <string.h>
17: #ifdef HAVE_UNISTD_H
18: #include <unistd.h>
19: #endif
20: #include <time.h>
1.1 httpng 21: #include <errno.h>
1.2 httpng 22: #include <ctype.h>
1.22 ! daniel 23: #include <zlib.h>
1.1 httpng 24:
25: #include "rpm2html.h"
26: #include "rpmdata.h"
1.4 veillard 27: #include "html.h"
1.7 veillard 28: #include "language.h"
1.4 veillard 29:
30: #include "rdf_api.h"
1.1 httpng 31: #include "rdf.h"
32:
33: /*
1.16 veillard 34: * Open and process an RDF file in the incoming tree of an rpm2html mirror.
35: */
36: rpmDataPtr rpmOpenRdf(char *nameRdf, rpmDirPtr dir, rpmSubdirPtr tree) {
37: char file[1000];
38: rpmDataPtr rpm;
39:
40: /*
41: * create path
42: */
43: if (tree->htmlpath[0] != '\0')
44: sprintf(file, "%s/%s/%s", dir->rpmdir, tree->rpmpath, nameRdf);
45: else
46: sprintf(file, "%s/%s", dir->rpmdir, nameRdf);
47:
48: rpm = rpmOpenRdfFile(file);
49:
50: if (rpm != NULL) {
51: /* setup tree and subdir informations */
52: rpm->dir = dir;
53: if (tree) {
54: if ((tree->rpmpath != NULL) && (tree->rpmpath[0] != '\0'))
55: rpm->subdir = strdup(tree->rpmpath);
56: else
57: rpm->subdir = NULL;
58: } else
59: rpm->subdir = NULL;
60:
61: /* Add the package files to the real filesystem tree if asked for */
62: if ((dir->build_tree != 0) && (rpm->filelist != NULL)) {
63: char *cur, *filename;
64:
65: cur = rpm->filelist;
66: while ((*cur != '\0') && (*cur != '/')) cur++;
67: filename = cur;
68: while (*cur != '\0') {
69: if ((*cur == '\n') || (*cur == '\r')) {
70: if (cur != filename)
71: rpmAddRealFile(dir->root, filename, rpm);
72: while ((*cur != '\0') && (*cur != '/')) cur++;
73: filename = cur;
74: } else
75: cur++;
76: }
77: if (cur != filename)
78: rpmAddRealFile(dir->root, filename, rpm);
79: }
80:
81: /* Register this package */
82: rpmAddSoftware(rpm);
83:
84: /* dump the HTML related to this package */
85: if (rpm2html_dump_html)
86: dumpRpmHtml(rpm, tree);
87: if (rpm2html_dump_rdf)
88: dumpRpmRdf(rpm, tree);
89:
90: /* free large amount of data not used later */
91: if (rpm->filelist) free(rpm->filelist);
92: rpm->filelist = NULL;
93: if (rpm->copyright) free(rpm->copyright);
94: rpm->copyright = NULL;
95: if (rpm->changelog) free(rpm->changelog);
96: rpm->changelog = NULL;
97: if (rpm->description) free(rpm->description);
98: rpm->description = NULL;
99:
100: /* increment the counters */
101: rpm2html_files++;
102: rpm2html_size += rpm->size / 1024;
103: }
104: return(rpm);
105: }
106:
107: /*
1.1 httpng 108: * Open an RDF file call the parser to create a XML tree
109: * Then walk the tree and build an rpmData structure for
110: * the corresponding package.
111: */
1.16 veillard 112: rpmDataPtr rpmOpenRdfFile(char *file) {
1.6 veillard 113: char nameBuffer[200];
1.5 veillard 114: rdfSchema rdf;
115: rdfNamespace rpmNs;
116: rdfNamespace rdfNs;
117: rdfDescription desc;
118: rdfBag bag;
1.7 veillard 119: rdfElement elem;
1.5 veillard 120: char *value;
121: rpmDataPtr rpm;
1.6 veillard 122: struct stat buf;
1.7 veillard 123: int i;
1.5 veillard 124:
125: rdf = rdfRead(file);
126: if (rdf == NULL) return(NULL);
127:
128: /*
129: * Start the analyze, check that's an RDf for RPM packages.
130: */
131: rdfNs = rdfGetNamespace(rdf, "http://www.w3.org/TR/WD-rdf-syntax#");
132: if (rdfNs == NULL) {
133: fprintf(stderr, "%s is not an RDF schema\n", file);
134: rdfDestroySchema(rdf);
135: return(NULL);
136: }
137: rpmNs = rdfGetNamespace(rdf, "http://www.rpm.org/");
138: if (rdfNs == NULL) {
139: fprintf(stderr, "%s is not an RPM specific RDF schema\n", file);
140: rdfDestroySchema(rdf);
141: return(NULL);
142: }
143: desc = rdfFirstDescription(rdf);
144: if (rdfNs == NULL) {
145: fprintf(stderr, "%s RDF schema seems empty\n", file);
146: rdfDestroySchema(rdf);
147: return(NULL);
148: }
149:
150: /*
151: * We are pretty sure that it will be a valid schema,
1.6 veillard 152: * Allocate the rpmData structure, initialize it.
1.5 veillard 153: */
154: rpm = (rpmDataPtr) malloc(sizeof(rpmData));
155: if (rpm == NULL) {
156: fprintf(stderr, "rpmOpenRdf : out of memory !\n");
157: rdfDestroySchema(rdf);
158: return(NULL);
159: }
1.6 veillard 160: memset(rpm, 0, sizeof(rpmData));
1.5 veillard 161:
1.6 veillard 162: stat(file, &buf);
163: rpm->stamp = buf.st_mtime;
164:
165: /*
166: * Now extract all the metadata informations from the RDF tree
167: */
1.5 veillard 168: rdfGetValue(desc, "Name", rpmNs, &value, NULL);
169: if (value != NULL) rpm->name = strdup(value);
170: else {
171: fprintf(stderr, "%s RDF schema invalid : no Name\n", file);
172: rdfDestroySchema(rdf);
173: return(NULL);
174: }
175: rdfGetValue(desc, "Version", rpmNs, &value, NULL);
176: if (value != NULL) rpm->version = strdup(value);
177: else {
178: fprintf(stderr, "%s RDF schema invalid : no Version\n", file);
179: rdfDestroySchema(rdf);
180: return(NULL);
181: }
182: rdfGetValue(desc, "Release", rpmNs, &value, NULL);
183: if (value != NULL) rpm->release = strdup(value);
184: else {
185: fprintf(stderr, "%s RDF schema invalid : no Release\n", file);
186: rdfDestroySchema(rdf);
187: return(NULL);
188: }
189: rdfGetValue(desc, "URL", rpmNs, &value, NULL);
190: if (value != NULL) rpm->url = strdup(value);
1.7 veillard 191: else rpm->url = NULL;
192:
1.5 veillard 193: rdfGetValue(desc, "Arch", rpmNs, &value, NULL);
194: if (value != NULL) rpm->arch = strdup(value);
1.7 veillard 195: else rpm->arch = strdup(localizedStrings[LANG_NONE]);
196:
1.5 veillard 197: rdfGetValue(desc, "Os", rpmNs, &value, NULL);
198: if (value != NULL) rpm->os = strdup(value);
1.7 veillard 199: else rpm->os = strdup("linux");
200:
1.5 veillard 201: rdfGetValue(desc, "Distribution", rpmNs, &value, NULL);
202: if (value != NULL) rpm->distribution = strdup(value);
1.7 veillard 203: else rpm->distribution = strdup(localizedStrings[LANG_UNKNOWN]);
204:
1.5 veillard 205: rdfGetValue(desc, "Vendor", rpmNs, &value, NULL);
206: if (value != NULL) rpm->vendor = strdup(value);
1.7 veillard 207: else rpm->vendor = strdup(localizedStrings[LANG_UNKNOWN]);
208:
1.5 veillard 209: rdfGetValue(desc, "Packager", rpmNs, &value, NULL);
210: if (value != NULL) rpm->packager = strdup(value);
1.7 veillard 211: else rpm->packager = NULL;
212:
1.5 veillard 213: rdfGetValue(desc, "Group", rpmNs, &value, NULL);
214: if (value != NULL) rpm->group = strdup(value);
1.7 veillard 215: else rpm->group = strdup(localizedStrings[LANG_NO_GROUP]);
216:
1.5 veillard 217: rdfGetValue(desc, "Summary", rpmNs, &value, NULL);
218: if (value != NULL) rpm->summary = strdup(value);
1.7 veillard 219: else rpm->summary = strdup(localizedStrings[LANG_NO_SUMMARY]);
220:
1.5 veillard 221: rdfGetValue(desc, "Description", rpmNs, &value, NULL);
222: if (value != NULL) rpm->description = strdup(value);
1.7 veillard 223: else rpm->description = strdup(localizedStrings[LANG_NO_DESCRIPTION]);
224:
1.5 veillard 225: rdfGetValue(desc, "Copyright", rpmNs, &value, NULL);
226: if (value != NULL) rpm->copyright = strdup(value);
1.7 veillard 227: else rpm->copyright = NULL;
228:
1.5 veillard 229: rdfGetValue(desc, "Changelog", rpmNs, &value, NULL);
230: if (value != NULL) rpm->changelog = strdup(value);
1.7 veillard 231: else rpm->changelog = NULL;
232:
233: rdfGetValue(desc, "Sources", rpmNs, &value, NULL);
234: if (value != NULL) {
235: rpm->srcrpm = strdup(value);
236: } else rpm->srcrpm = strdup("");
237:
238: rdfGetValue(desc, "Size", rpmNs, &value, NULL);
239: if (value != NULL) {
240: if (sscanf(value, "%d", &(rpm->size)) != 1)
241: rpm->size = 0;
242: } else rpm->size = 0;
243:
244: rdfGetValue(desc, "Date", rpmNs, &value, NULL);
245: if (value != NULL) {
1.8 veillard 246: if (sscanf(value, "%d", &i) != 1)
1.7 veillard 247: rpm->date = 0;
1.8 veillard 248: else
249: rpm->date = i;
1.7 veillard 250: } else rpm->date = 0;
251:
252: rdfGetValue(desc, "BuildHost", rpmNs, &value, NULL);
253: if (value != NULL) rpm->host = strdup(value);
254: else rpm->host = strdup(localizedStrings[LANG_NO_HOST]);
255:
256: rdfGetValue(desc, "Files", rpmNs, &value, NULL);
257: if (value != NULL) rpm->filelist = strdup(value);
258: else rpm->filelist = NULL;
259:
260: /*
261: * Fetching packages provided is a bit more tricky, one have to
262: * find the RDF Bag, and scan it's values.
263: */
264: rpm->nb_resources = 0;
265: rdfGetValue(desc, "Provides", rpmNs, NULL, &bag);
266: if (bag != NULL) {
267: elem = rdfFirstChild(bag);
1.11 veillard 268: rpm->max_resources = 5;
269: rpm->resources = (rpmRessPtr *) malloc(rpm->max_resources *
270: sizeof(rpmRessPtr));
271: if (rpm->resources == NULL) {
272: fprintf(stderr, "rpmOpenRdf : ran out of memory\n");
273: exit(1);
274: }
1.7 veillard 275: i = 0;
276: while (elem != NULL) {
1.11 veillard 277: if (i >= rpm->max_resources) {
278: rpm->max_resources *= 2;
279: rpm->resources = (rpmRessPtr *) realloc(rpm->resources,
280: rpm->max_resources * sizeof(rpmRessPtr));
281: if (rpm->resources == NULL) {
282: fprintf(stderr, "rpmOpenRdf : ran out of memory\n");
283: exit(1);
284: }
1.7 veillard 285: }
286: /*
287: * Check that we are scanning an RPM Resource.
288: */
289: if ((!strcmp(rdfElemGetPropertyName(elem), "Resource")) &&
290: (rdfElemGetNamespace(elem) == rpmNs)) {
291: value = rdfElemGetValue(elem);
292: if (value != NULL) {
293: rpm->resources[i] = rpmRessAdd(value, rpm, 0);
294: i++;
295: rpm->nb_resources++;
1.20 veillard 296: } else if (rpm2htmlVerbose > 1) {
1.7 veillard 297: fprintf(stderr, "%s : malformed Resource element !\n", file);
298: }
1.20 veillard 299: } else if (rpm2htmlVerbose > 1) {
1.7 veillard 300: fprintf(stderr, "%s : malformed Provides bag !\n", file);
301: }
302: elem = rdfNextElem(elem);
303: }
1.20 veillard 304: } else if (rpm2htmlVerbose > 1) {
1.7 veillard 305: fprintf(stderr, "%s doesn't export any resource\n", file);
306: }
307:
308: /*
309: * idem for the dependencies.
310: */
311: rpm->nb_requires = 0;
312: rdfGetValue(desc, "Requires", rpmNs, NULL, &bag);
313: if (bag != NULL) {
314: elem = rdfFirstChild(bag);
1.11 veillard 315: rpm->max_requires = 5;
316: rpm->requires = (rpmRessPtr *) malloc(rpm->max_requires *
317: sizeof(rpmRessPtr));
318: if (rpm->requires == NULL) {
319: fprintf(stderr, "rpmOpenRdf : ran out of memory\n");
320: exit(1);
321: }
1.7 veillard 322: i = 0;
323: while (elem != NULL) {
1.11 veillard 324: if (i >= rpm->max_requires) {
325: rpm->max_requires *= 2;
326: rpm->requires = (rpmRessPtr *) realloc(rpm->requires,
327: rpm->max_requires * sizeof(rpmRessPtr));
328: if (rpm->requires == NULL) {
329: fprintf(stderr, "rpmOpenRdf : ran out of memory\n");
330: exit(1);
331: }
1.7 veillard 332: }
333: /*
334: * Check that we are scanning an RPM Resource.
335: */
336: if ((!strcmp(rdfElemGetPropertyName(elem), "Resource")) &&
337: (rdfElemGetNamespace(elem) == rpmNs)) {
338: value = rdfElemGetValue(elem);
339: if (value != NULL) {
340: rpm->requires[i] = rpmRequAdd(value, rpm, 0);
341: i++;
342: rpm->nb_requires++;
1.20 veillard 343: } else if (rpm2htmlVerbose > 1) {
1.7 veillard 344: fprintf(stderr, "%s : malformed Resource element !\n", file);
345: }
1.20 veillard 346: } else if (rpm2htmlVerbose > 1) {
1.7 veillard 347: fprintf(stderr, "%s : malformed Provides bag !\n", file);
348: }
349: elem = rdfNextElem(elem);
350: }
351: }
1.5 veillard 352:
1.6 veillard 353: /*
354: * Finish filling the rpmData structure.
355: */
356: #ifdef HAVE_SNPRINTF
357: sprintf(nameBuffer, "%s-%s-%s.rpm",
358: rpm->name, rpm->version, rpm->release);
359: #else
360: snprintf(nameBuffer, 200, "%s-%s-%s.rpm",
361: rpm->name, rpm->version, rpm->release);
362: #endif
363: rpm->filename = strdup(nameBuffer);
364:
365:
366: /*
367: * Cleanup.
368: */
1.5 veillard 369: rdfDestroySchema(rdf);
370: return(rpm);
1.1 httpng 371: }
372:
373: /*
1.4 veillard 374: * Create and RDF file containing the description for the given RPM data.
1.1 httpng 375: */
376: void dumpRpmRdf(rpmDataPtr rpm, rpmSubdirPtr tree) {
1.12 veillard 377: FILE *output;
378: struct stat stat_buf;
1.1 httpng 379: struct tm * tstruct;
380: rpmDirPtr dir = rpm->dir;
1.3 veillard 381: char *base = dir->dir;
1.1 httpng 382: int i;
1.4 veillard 383: char buf[10000];
384: char file[1000];
1.12 veillard 385: char *buffer;
386: int size;
387: int stat_res;
1.4 veillard 388: rdfSchema rdf;
389: rdfNamespace rpmNs;
390: rdfDescription desc;
391: rdfBag bag;
1.1 httpng 392:
1.7 veillard 393: if (!rpm2html_dump_rdf) return;
394:
1.3 veillard 395: if (rpm2html_rdf_dir != NULL) base = rpm2html_rdf_dir;
396:
1.1 httpng 397: if ((dir->subdir != NULL) && (dir->subdir[0] != '\0')) {
398: if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0'))
1.4 veillard 399: sprintf(file, "%s/%s/%s/%s.rdf", base, dir->subdir,
1.1 httpng 400: rpm->subdir, rpmName(rpm));
401: else
1.4 veillard 402: sprintf(file, "%s/%s/%s.rdf", base, dir->subdir, rpmName(rpm));
1.1 httpng 403: } else {
404: if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0'))
1.4 veillard 405: sprintf(file, "%s/%s/%s.rdf", base, rpm->subdir, rpmName(rpm));
1.1 httpng 406: else
1.4 veillard 407: sprintf(file, "%s/%s.rdf", base, rpmName(rpm));
1.1 httpng 408: }
409:
1.12 veillard 410: /*
411: * Check wether the RPM timestamp is older than the filestamp.
412: */
413: if ((stat_res = stat(file, &stat_buf)) == 0) {
414: if (stat_buf.st_mtime > rpm->stamp) return;
415: }
1.9 veillard 416:
417: /*
418: * Create the directory if needed
419: */
420: if ((dir->subdir != NULL) && (dir->subdir[0] != '\0')) {
421: if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0'))
422: sprintf(buf, "%s/%s/%s", base, dir->subdir, rpm->subdir);
423: else
424: sprintf(buf, "%s/%s", base, dir->subdir);
425: } else {
426: if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0'))
427: sprintf(buf, "%s/%s", base, rpm->subdir);
428: else
429: sprintf(buf, "%s", base);
430: }
431: createDirectory(buf);
432:
1.4 veillard 433: /*
434: * build the RDF document tree
435: * Note : the order is not important but following the rpmData
436: * structure order is easier to check.
437: */
438: rdf = rdfNewSchema();
439: rpmNs = rdfNewNamespace(rdf, "http://www.rpm.org/", "RPM");
440:
1.2 httpng 441: if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0')) {
442: if (dir->mirrors[0] != NULL)
1.4 veillard 443: sprintf(buf, "%s/%s/%s",
1.2 httpng 444: dir->mirrors[0], rpm->subdir, rpm->filename);
445: else
1.4 veillard 446: sprintf(buf, "%s/%s/%s",
1.2 httpng 447: dir->ftp, rpm->subdir, rpm->filename);
448: } else {
449: if (dir->mirrors[0] != NULL)
1.4 veillard 450: sprintf(buf, "%s/%s",
1.2 httpng 451: dir->mirrors[0], rpm->filename);
452: else
1.4 veillard 453: sprintf(buf, "%s/%s",
1.2 httpng 454: dir->ftp, rpm->filename);
455: }
1.4 veillard 456: desc = rdfAddDescription(rdf, NULL, buf);
457:
458: rdfSetValue(desc, "Name", rpmNs, rpm->name);
459: rdfSetValue(desc, "Version", rpmNs, rpm->version);
460: rdfSetValue(desc, "Release", rpmNs, rpm->release);
461: if (rpm->url)
462: rdfSetValue(desc, "URL", rpmNs, rpm->url);
463: if (rpm->arch)
464: rdfSetValue(desc, "Arch", rpmNs, rpm->arch);
465: if (rpm->os)
466: rdfSetValue(desc, "Os", rpmNs, rpm->os);
1.2 httpng 467: if (rpm->distribution)
1.4 veillard 468: rdfSetValue(desc, "Distribution", rpmNs, rpm->distribution);
1.2 httpng 469: if (rpm->vendor)
1.4 veillard 470: rdfSetValue(desc, "Vendor", rpmNs, rpm->vendor);
471: if (rpm->packager)
472: rdfSetValue(desc, "Packager", rpmNs, rpm->packager);
473: if (rpm->group)
474: rdfSetValue(desc, "Group", rpmNs, rpm->group);
475: if (rpm->summary)
476: rdfSetValue(desc, "Summary", rpmNs, rpm->summary);
477: if (rpm->description)
478: rdfSetValue(desc, "Description", rpmNs, rpm->description);
479: if (rpm->copyright)
480: rdfSetValue(desc, "Copyright", rpmNs, rpm->copyright);
481: if (rpm->changelog)
482: rdfSetValue(desc, "Changelog", rpmNs, rpm->changelog);
483: if (rpm->srcrpm) {
1.7 veillard 484: rdfSetValue(desc, "Sources", rpmNs, rpm->srcrpm);
1.4 veillard 485: if (dir->ftpsrc) {
1.7 veillard 486: rdfSetValue(desc, "SourcesFtp", rpmNs, dir->ftpsrc);
1.4 veillard 487: }
488: }
1.2 httpng 489: tstruct = localtime(&(rpm->date));
490: #ifdef HAVE_STRFTIME
491: strftime(buf, sizeof(buf) - 1, "%c", tstruct);
492: #else
493: #error "no strftime, please check !"
494: #endif
1.4 veillard 495: rdfSetValue(desc, "BuildDate", rpmNs, buf);
1.12 veillard 496: sprintf(buf, "%d", (int) rpm->date);
1.10 veillard 497: rdfSetValue(desc, "Date", rpmNs, buf);
1.4 veillard 498: sprintf(buf, "%d", rpm->size);
499: rdfSetValue(desc, "Size", rpmNs, buf);
1.2 httpng 500: if (rpm->host)
1.4 veillard 501: rdfSetValue(desc, "BuildHost", rpmNs, rpm->host);
1.2 httpng 502: if (rpm->nb_resources > 0) {
1.7 veillard 503: /** !!!!!
504: sprintf(buf, "%d", rpm->nb_resources);
505: rdfSetValue(desc, "NbProvides", rpmNs, buf);
506: */
1.4 veillard 507: bag = rdfBagCreate(rdf, desc, "Provides", rpmNs);
1.2 httpng 508: for (i = 0;i < rpm->nb_resources;i++) {
1.4 veillard 509: rdfBagAddValue(bag, "Resource", rpmNs,
510: rpm->resources[i]->name, NULL);
1.2 httpng 511: }
512: }
513: if (rpm->nb_requires > 0) {
1.7 veillard 514: /** !!!!!
515: sprintf(buf, "%d", rpm->nb_requires);
516: rdfSetValue(desc, "NbRequires", rpmNs, buf);
517: */
1.4 veillard 518: bag = rdfBagCreate(rdf, desc, "Requires", rpmNs);
1.2 httpng 519: for (i = 0;i < rpm->nb_requires;i++) {
1.4 veillard 520: rdfBagAddValue(bag, "Resource", rpmNs,
521: rpm->requires[i]->name, NULL);
1.2 httpng 522: }
523: }
524: if (rpm->filelist)
1.4 veillard 525: rdfSetValue(desc, "Files", rpmNs, rpm->filelist);
526:
527: /*
1.12 veillard 528: * Save the RDF to a buffer, remove the tree.
1.4 veillard 529: */
1.12 veillard 530: rdfWriteMemory(rdf, &buffer, &size);
1.4 veillard 531: rdfDestroySchema(rdf);
1.12 veillard 532:
533: /*
534: * if the file already exists avoid to overwrite it if the content
535: * didn't change.
536: */
537: if ((stat_res == 0) && (stat_buf.st_size == size)) {
538: char *buffer2 = malloc(size * sizeof(char));
539:
540: if (buffer2 == NULL) {
541: fprintf(stderr, " : running out of memory\n");
542: return;
543: }
544: output = fopen(file, "r");
545: if (output == NULL) {
546: fprintf(stderr, "couldn't open %s for reading !\n", file);
547: return;
548: }
549: if (fread(buffer2, size, 1, output) != 1) {
550: fprintf(stderr, "Problem reading from %s !\n", file);
551: }
552: fclose(output);
553:
554: /*
555: * Now compare the content !
556: */
557: if (!memcmp(buffer, buffer2, size)) {
558: free(buffer2);
1.20 veillard 559: if (rpm2htmlVerbose > 1)
1.12 veillard 560: fprintf(stderr, "File %s : Content identical !\n", file);
561: return;
562: }
563: free(buffer2);
564: }
565:
566: /*
567: * Dump the file.
568: */
1.20 veillard 569: if (rpm2htmlVerbose > 1) {
1.12 veillard 570: printf("Dumping %s\n", file);
571: }
572: output = fopen(file, "w");
573: if (output == NULL) {
574: fprintf(stderr, "couldn't open %s for writing !\n", file);
575: return;
576: }
577: if (fwrite(buffer, size, 1, output) != 1) {
578: fprintf(stderr, "Problem writing to %s !\n", file);
579: }
580: fclose(output);
1.1 httpng 581: }
582:
1.13 veillard 583: /*
584: * Create and RDF file containing informations about a resource.
585: */
586:
587: void dumpResRdf(rpmRessPtr res) {
588: FILE *output;
589: struct stat stat_buf;
590: char *base;
591: int i;
592: char buf[10000];
593: char file[1000];
594: char *buffer;
595: int size;
596: int stat_res;
597: rpmDataPtr rpm;
598: rpmDirPtr dir;
599: rdfSchema rdf;
600: rdfNamespace rpmNs;
601: rdfDescription desc;
602: static int initialized = 0;
603:
604: if (!rpm2html_dump_rdf_resources) return;
605:
606: if (rpm2html_rdf_resources_dir != NULL) base = rpm2html_rdf_resources_dir;
607: else return;
608:
609: if (res->nb_provider == 0) return;
610:
1.15 veillard 611: sprintf(file, "%s/%s.rdf", base, res->name);
1.13 veillard 612:
613: /*
614: * Create the directory if needed
615: */
616: if (!initialized) {
617: sprintf(buf, "%s", base);
618: createDirectory(buf);
619: initialized = 1;
620: }
621:
622: /*
623: * build the RDF document tree
624: * Note : the order is not important but following the rpmData
625: * structure order is easier to check.
626: */
627: rdf = rdfNewSchema();
628: rpmNs = rdfNewNamespace(rdf, "http://www.rpm.org/", "RPM");
629:
630: for (i = 0;i < res->nb_provider;i++) {
631: rpm = res->provider[i];
632: dir = rpm->dir;
633: if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0')) {
634: if (dir->mirrors[0] != NULL)
635: sprintf(buf, "%s/%s/%s",
636: dir->mirrors[0], rpm->subdir, rpm->filename);
637: else
638: sprintf(buf, "%s/%s/%s",
639: dir->ftp, rpm->subdir, rpm->filename);
640: } else {
641: if (dir->mirrors[0] != NULL)
642: sprintf(buf, "%s/%s",
643: dir->mirrors[0], rpm->filename);
644: else
645: sprintf(buf, "%s/%s",
646: dir->ftp, rpm->filename);
647: }
648: desc = rdfAddDescription(rdf, NULL, buf);
649: rdfSetValue(desc, "Name", rpmNs, rpm->name);
650: rdfSetValue(desc, "Version", rpmNs, rpm->version);
651: rdfSetValue(desc, "Release", rpmNs, rpm->release);
652: if (rpm->arch)
653: rdfSetValue(desc, "Arch", rpmNs, rpm->arch);
654: if (rpm->os)
655: rdfSetValue(desc, "Os", rpmNs, rpm->os);
656: if (rpm->distribution)
657: rdfSetValue(desc, "Distribution", rpmNs, rpm->distribution);
658: if (rpm->vendor)
659: rdfSetValue(desc, "Vendor", rpmNs, rpm->vendor);
660: sprintf(buf, "%d", (int) rpm->date);
661: rdfSetValue(desc, "Date", rpmNs, buf);
1.17 veillard 662: sprintf(buf, "%d", (int) rpm->size);
663: rdfSetValue(desc, "Size", rpmNs, buf);
1.14 httpng 664: if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0')) {
665: if ((dir->subdir != NULL) && (dir->subdir[0] != '\0'))
666: sprintf(buf, "%s/%s",
667: dir->subdir, rpm->subdir);
668: else
669: sprintf(buf, "%s",
670: rpm->subdir);
671: } else {
672: if ((dir->subdir != NULL) && (dir->subdir[0] != '\0'))
673: sprintf(buf, "%s",
674: dir->subdir);
675: else
676: buf[0] = '\0';
677: }
678: if (buf[0] != '\0')
679: rdfSetValue(desc, "Subdir", rpmNs, buf);
1.13 veillard 680: }
681:
682: /*
683: * Save the RDF to a buffer, remove the tree.
684: */
685: rdfWriteMemory(rdf, &buffer, &size);
686: rdfDestroySchema(rdf);
687:
688: /*
689: * if the file already exists avoid to overwrite it if the content
690: * didn't change.
691: */
692: stat_res = stat(file, &stat_buf);
693:
694: if ((stat_res == 0) && (stat_buf.st_size == size)) {
695: char *buffer2 = malloc(size * sizeof(char));
696:
697: if (buffer2 == NULL) {
698: fprintf(stderr, " : running out of memory\n");
699: return;
700: }
701: output = fopen(file, "r");
702: if (output == NULL) {
703: fprintf(stderr, "couldn't open %s for reading !\n", file);
704: return;
705: }
706: if (fread(buffer2, size, 1, output) != 1) {
707: fprintf(stderr, "Problem reading from %s !\n", file);
708: }
709: fclose(output);
710:
711: /*
712: * Now compare the content !
713: */
714: if (!memcmp(buffer, buffer2, size)) {
715: free(buffer2);
1.20 veillard 716: if (rpm2htmlVerbose > 1)
1.13 veillard 717: fprintf(stderr, "File %s : Content identical !\n", file);
718: return;
719: }
720: free(buffer2);
721: }
722:
723: /*
724: * Dump the file.
725: */
1.20 veillard 726: if (rpm2htmlVerbose > 1) {
1.13 veillard 727: printf("Dumping %s\n", file);
728: }
729: output = fopen(file, "w");
730: if (output == NULL) {
731: fprintf(stderr, "couldn't open %s for writing !\n", file);
732: return;
733: }
734: if (fwrite(buffer, size, 1, output) != 1) {
735: fprintf(stderr, "Problem writing to %s !\n", file);
736: }
737: fclose(output);
738: }
739:
740: /*
741: * Dump all the RDf files about known resources.
742: */
743:
744: void dumpAllResRdf(void) {
745: rpmRessPtr cur;
746:
747: if (!rpm2html_dump_rdf_resources) return;
748:
749: cur = ressList;
750:
751: while (cur != NULL) {
752: dumpResRdf(cur);
753: cur = cur->next;
754: }
1.21 daniel 755: }
756:
757: /*
758: * Dump an apropos RDF file for all packages.
1.22 ! daniel 759: * Since the file is really too big to be kept as-if, it is compressed
1.21 daniel 760: */
761:
762: void dumpAproposRdf(void) {
763: rpmDataPtr rpm;
764: char file[1000];
765: char buf[1000];
766: rdfSchema rdf;
767: rdfNamespace rpmNs;
768: rdfDescription desc;
769: rpmDirPtr dir;
770: char *base;
1.22 ! daniel 771: char *buffer;
! 772: int size;
! 773: gzFile output;
! 774: int res;
1.21 daniel 775:
776: if (!rpm2html_dump_rdf_resources) return;
777:
778: if (rpm2html_rdf_resources_dir != NULL) base = rpm2html_rdf_resources_dir;
779: else return;
780:
1.22 ! daniel 781: sprintf(file, "%s/fullIndex.rdf.gz", base);
1.21 daniel 782: if (rpm2htmlVerbose > 1) {
783: printf("Dumping %s\n", file);
784: }
785:
786: /*
787: * build the RDF document tree, one only dump the minimum needed
788: * for searching.
789: */
790: rdf = rdfNewSchema();
791: rpmNs = rdfNewNamespace(rdf, "http://www.rpm.org/", "RPM");
792:
793: rpm = rpmSoftwareList;
794:
795: while (rpm != NULL) {
796: dir = rpm->dir;
797: if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0')) {
798: if (dir->mirrors[0] != NULL)
799: sprintf(buf, "%s/%s/%s",
800: dir->mirrors[0], rpm->subdir, rpm->filename);
801: else
802: sprintf(buf, "%s/%s/%s",
803: dir->ftp, rpm->subdir, rpm->filename);
804: } else {
805: if (dir->mirrors[0] != NULL)
806: sprintf(buf, "%s/%s",
807: dir->mirrors[0], rpm->filename);
808: else
809: sprintf(buf, "%s/%s",
810: dir->ftp, rpm->filename);
811: }
812: desc = rdfAddDescription(rdf, NULL, buf);
813: rdfSetValue(desc, "Name", rpmNs, rpm->name);
814: rdfSetValue(desc, "Description", rpmNs, rpm->description);
815: rpm = rpm->nextArch;
816: }
817:
818: /*
819: * Dump the RDF tree, and cleanup.
820: */
1.22 ! daniel 821: rdfWriteMemory(rdf, &buffer, &size);
1.21 daniel 822: rdfDestroySchema(rdf);
1.22 ! daniel 823:
! 824: /*
! 825: * Write the compressed version of the RDF base.
! 826: */
! 827: output = gzopen(file, "w9");
! 828: if (output == NULL) {
! 829: fprintf(stderr, "Could not write %s : gzopen failed\n", file);
! 830: return;
! 831: }
! 832: res = gzwrite(output, buffer, size);
! 833: if (res <= 0) {
! 834: fprintf(stderr, "Could not write %s : gzwrite failed\n", file);
! 835: return;
! 836: }
! 837: gzclose(output);
1.13 veillard 838: }
839:
Webmaster