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