Annotation of rpm2html/rdf.c, revision 1.8
1.1 httpng 1: /*
2: * rdf.c : implementation for the RDF encoding/decoding of RPM informations.
3: */
4:
1.2 httpng 5: #include "config.h"
1.6 veillard 6: #include <sys/stat.h>
1.2 httpng 7: #ifdef HAVE_FCNTL_H
8: #include <fcntl.h>
9: #endif
10: #include <stdio.h>
11: #include <stdlib.h>
12: #include <string.h>
13: #ifdef HAVE_UNISTD_H
14: #include <unistd.h>
15: #endif
16: #include <time.h>
1.1 httpng 17: #include <errno.h>
1.2 httpng 18: #include <ctype.h>
1.1 httpng 19:
20: #include "rpm2html.h"
21: #include "rpmdata.h"
1.4 veillard 22: #include "html.h"
1.7 veillard 23: #include "language.h"
1.4 veillard 24:
25: #include "rdf_api.h"
1.1 httpng 26: #include "rdf.h"
27:
28: /*
29: * Open an RDF file call the parser to create a XML tree
30: * Then walk the tree and build an rpmData structure for
31: * the corresponding package.
32: */
1.5 veillard 33: rpmDataPtr rpmOpenRdf(char *nameRdf, rpmDirPtr dir, rpmSubdirPtr tree) {
34: char file[1000];
1.6 veillard 35: char nameBuffer[200];
1.5 veillard 36: rdfSchema rdf;
37: rdfNamespace rpmNs;
38: rdfNamespace rdfNs;
39: rdfDescription desc;
40: rdfBag bag;
1.7 veillard 41: rdfElement elem;
1.5 veillard 42: char *value;
43: rpmDataPtr rpm;
1.6 veillard 44: struct stat buf;
1.7 veillard 45: int i;
1.5 veillard 46:
47: /*
48: * open the file for reading
49: */
50: if (tree->htmlpath[0] != '\0')
51: sprintf(file, "%s/%s/%s", dir->rpmdir, tree->rpmpath, nameRdf);
52: else
53: sprintf(file, "%s/%s", dir->rpmdir, nameRdf);
54:
55: rdf = rdfRead(file);
56: if (rdf == NULL) return(NULL);
57:
58: /*
59: * Start the analyze, check that's an RDf for RPM packages.
60: */
61: rdfNs = rdfGetNamespace(rdf, "http://www.w3.org/TR/WD-rdf-syntax#");
62: if (rdfNs == NULL) {
63: fprintf(stderr, "%s is not an RDF schema\n", file);
64: rdfDestroySchema(rdf);
65: return(NULL);
66: }
67: rpmNs = rdfGetNamespace(rdf, "http://www.rpm.org/");
68: if (rdfNs == NULL) {
69: fprintf(stderr, "%s is not an RPM specific RDF schema\n", file);
70: rdfDestroySchema(rdf);
71: return(NULL);
72: }
73: desc = rdfFirstDescription(rdf);
74: if (rdfNs == NULL) {
75: fprintf(stderr, "%s RDF schema seems empty\n", file);
76: rdfDestroySchema(rdf);
77: return(NULL);
78: }
79:
80: /*
81: * We are pretty sure that it will be a valid schema,
1.6 veillard 82: * Allocate the rpmData structure, initialize it.
1.5 veillard 83: */
84: rpm = (rpmDataPtr) malloc(sizeof(rpmData));
85: if (rpm == NULL) {
86: fprintf(stderr, "rpmOpenRdf : out of memory !\n");
87: rdfDestroySchema(rdf);
88: return(NULL);
89: }
1.6 veillard 90: memset(rpm, 0, sizeof(rpmData));
91: rpm->dir = dir;
92: if (tree) {
93: if ((tree->rpmpath != NULL) && (tree->rpmpath[0] != '\0'))
94: rpm->subdir = strdup(tree->rpmpath);
95: else
96: rpm->subdir = NULL;
97: } else
98: rpm->subdir = NULL;
1.5 veillard 99:
1.6 veillard 100: stat(file, &buf);
101: rpm->stamp = buf.st_mtime;
102:
103: /*
104: * Now extract all the metadata informations from the RDF tree
105: */
1.5 veillard 106: rdfGetValue(desc, "Name", rpmNs, &value, NULL);
107: if (value != NULL) rpm->name = strdup(value);
108: else {
109: fprintf(stderr, "%s RDF schema invalid : no Name\n", file);
110: rdfDestroySchema(rdf);
111: return(NULL);
112: }
113: rdfGetValue(desc, "Version", rpmNs, &value, NULL);
114: if (value != NULL) rpm->version = strdup(value);
115: else {
116: fprintf(stderr, "%s RDF schema invalid : no Version\n", file);
117: rdfDestroySchema(rdf);
118: return(NULL);
119: }
120: rdfGetValue(desc, "Release", rpmNs, &value, NULL);
121: if (value != NULL) rpm->release = strdup(value);
122: else {
123: fprintf(stderr, "%s RDF schema invalid : no Release\n", file);
124: rdfDestroySchema(rdf);
125: return(NULL);
126: }
127: rdfGetValue(desc, "URL", rpmNs, &value, NULL);
128: if (value != NULL) rpm->url = strdup(value);
1.7 veillard 129: else rpm->url = NULL;
130:
1.5 veillard 131: rdfGetValue(desc, "Arch", rpmNs, &value, NULL);
132: if (value != NULL) rpm->arch = strdup(value);
1.7 veillard 133: else rpm->arch = strdup(localizedStrings[LANG_NONE]);
134:
1.5 veillard 135: rdfGetValue(desc, "Os", rpmNs, &value, NULL);
136: if (value != NULL) rpm->os = strdup(value);
1.7 veillard 137: else rpm->os = strdup("linux");
138:
1.5 veillard 139: rdfGetValue(desc, "Distribution", rpmNs, &value, NULL);
140: if (value != NULL) rpm->distribution = strdup(value);
1.7 veillard 141: else rpm->distribution = strdup(localizedStrings[LANG_UNKNOWN]);
142:
1.5 veillard 143: rdfGetValue(desc, "Vendor", rpmNs, &value, NULL);
144: if (value != NULL) rpm->vendor = strdup(value);
1.7 veillard 145: else rpm->vendor = strdup(localizedStrings[LANG_UNKNOWN]);
146:
1.5 veillard 147: rdfGetValue(desc, "Packager", rpmNs, &value, NULL);
148: if (value != NULL) rpm->packager = strdup(value);
1.7 veillard 149: else rpm->packager = NULL;
150:
1.5 veillard 151: rdfGetValue(desc, "Group", rpmNs, &value, NULL);
152: if (value != NULL) rpm->group = strdup(value);
1.7 veillard 153: else rpm->group = strdup(localizedStrings[LANG_NO_GROUP]);
154:
1.5 veillard 155: rdfGetValue(desc, "Summary", rpmNs, &value, NULL);
156: if (value != NULL) rpm->summary = strdup(value);
1.7 veillard 157: else rpm->summary = strdup(localizedStrings[LANG_NO_SUMMARY]);
158:
1.5 veillard 159: rdfGetValue(desc, "Description", rpmNs, &value, NULL);
160: if (value != NULL) rpm->description = strdup(value);
1.7 veillard 161: else rpm->description = strdup(localizedStrings[LANG_NO_DESCRIPTION]);
162:
1.5 veillard 163: rdfGetValue(desc, "Copyright", rpmNs, &value, NULL);
164: if (value != NULL) rpm->copyright = strdup(value);
1.7 veillard 165: else rpm->copyright = NULL;
166:
1.5 veillard 167: rdfGetValue(desc, "Changelog", rpmNs, &value, NULL);
168: if (value != NULL) rpm->changelog = strdup(value);
1.7 veillard 169: else rpm->changelog = NULL;
170:
171: rdfGetValue(desc, "Sources", rpmNs, &value, NULL);
172: if (value != NULL) {
173: rpm->srcrpm = strdup(value);
174: } else rpm->srcrpm = strdup("");
175:
176: rdfGetValue(desc, "Size", rpmNs, &value, NULL);
177: if (value != NULL) {
178: if (sscanf(value, "%d", &(rpm->size)) != 1)
179: rpm->size = 0;
180: } else rpm->size = 0;
181:
182: rdfGetValue(desc, "Date", rpmNs, &value, NULL);
183: if (value != NULL) {
1.8 ! veillard 184: if (sscanf(value, "%d", &i) != 1)
1.7 veillard 185: rpm->date = 0;
1.8 ! veillard 186: else
! 187: rpm->date = i;
1.7 veillard 188: } else rpm->date = 0;
189:
190: rdfGetValue(desc, "BuildHost", rpmNs, &value, NULL);
191: if (value != NULL) rpm->host = strdup(value);
192: else rpm->host = strdup(localizedStrings[LANG_NO_HOST]);
193:
194: rdfGetValue(desc, "Files", rpmNs, &value, NULL);
195: if (value != NULL) rpm->filelist = strdup(value);
196: else rpm->filelist = NULL;
197:
198: /*
199: * Fetching packages provided is a bit more tricky, one have to
200: * find the RDF Bag, and scan it's values.
201: */
202: rpm->nb_resources = 0;
203: rdfGetValue(desc, "Provides", rpmNs, NULL, &bag);
204: if (bag != NULL) {
205: elem = rdfFirstChild(bag);
206: i = 0;
207: while (elem != NULL) {
208: if (i >= MAX_RES) {
209: fprintf(stderr, "MAX_RES %d overflow, increase the limit!\n",
210: MAX_RES);
211: break;
212: }
213: /*
214: * Check that we are scanning an RPM Resource.
215: */
216: if ((!strcmp(rdfElemGetPropertyName(elem), "Resource")) &&
217: (rdfElemGetNamespace(elem) == rpmNs)) {
218: value = rdfElemGetValue(elem);
219: if (value != NULL) {
220: rpm->resources[i] = rpmRessAdd(value, rpm, 0);
221: i++;
222: rpm->nb_resources++;
1.8 ! veillard 223: } else if (verbose > 1) {
1.7 veillard 224: fprintf(stderr, "%s : malformed Resource element !\n", file);
225: }
1.8 ! veillard 226: } else if (verbose > 1) {
1.7 veillard 227: fprintf(stderr, "%s : malformed Provides bag !\n", file);
228: }
229: elem = rdfNextElem(elem);
230: }
1.8 ! veillard 231: } else if (verbose > 1) {
1.7 veillard 232: fprintf(stderr, "%s doesn't export any resource\n", file);
233: }
234:
235: /*
236: * idem for the dependencies.
237: */
238: rpm->nb_requires = 0;
239: rdfGetValue(desc, "Requires", rpmNs, NULL, &bag);
240: if (bag != NULL) {
241: elem = rdfFirstChild(bag);
242: i = 0;
243: while (elem != NULL) {
244: if (i >= MAX_REQU) {
245: fprintf(stderr, "MAX_RES %d overflow, increase the limit!\n",
246: MAX_REQU);
247: break;
248: }
249: /*
250: * Check that we are scanning an RPM Resource.
251: */
252: if ((!strcmp(rdfElemGetPropertyName(elem), "Resource")) &&
253: (rdfElemGetNamespace(elem) == rpmNs)) {
254: value = rdfElemGetValue(elem);
255: if (value != NULL) {
256: rpm->requires[i] = rpmRequAdd(value, rpm, 0);
257: i++;
258: rpm->nb_requires++;
1.8 ! veillard 259: } else if (verbose > 1) {
1.7 veillard 260: fprintf(stderr, "%s : malformed Resource element !\n", file);
261: }
1.8 ! veillard 262: } else if (verbose > 1) {
1.7 veillard 263: fprintf(stderr, "%s : malformed Provides bag !\n", file);
264: }
265: elem = rdfNextElem(elem);
266: }
267: }
1.5 veillard 268:
1.6 veillard 269: /*
270: * Finish filling the rpmData structure.
271: */
272: #ifdef HAVE_SNPRINTF
273: sprintf(nameBuffer, "%s-%s-%s.rpm",
274: rpm->name, rpm->version, rpm->release);
275: #else
276: snprintf(nameBuffer, 200, "%s-%s-%s.rpm",
277: rpm->name, rpm->version, rpm->release);
278: #endif
279: rpm->filename = strdup(nameBuffer);
280:
281: /* Add the package files to the real filesystem tree if asked for */
282: if ((dir->build_tree != 0) && (rpm->filelist != NULL)) {
283: char *cur, *filename;
284:
285: cur = rpm->filelist;
286: while ((*cur != '\0') && (*cur != '/')) cur++;
287: filename = cur;
288: while (*cur != '\0') {
289: if ((*cur == '\n') || (*cur == '\r')) {
290: if (cur != filename)
291: rpmAddRealFile(dir->root, filename, rpm);
292: while ((*cur != '\0') && (*cur != '/')) cur++;
293: filename = cur;
294: } else
295: cur++;
296: }
297: if (cur != filename)
298: rpmAddRealFile(dir->root, filename, rpm);
299: }
300:
301: /* Register this package */
302: rpmAddSoftware(rpm);
303:
304: /* dump the HTML related to this package */
305: if (rpm2html_dump_html)
306: dumpRpmHtml(rpm, tree);
307: if (rpm2html_dump_rdf)
308: dumpRpmRdf(rpm, tree);
309:
310: /* free large amount of data not used later */
311: if (rpm->filelist) free(rpm->filelist);
312: rpm->filelist = NULL;
313: if (rpm->copyright) free(rpm->copyright);
314: rpm->copyright = NULL;
315: if (rpm->changelog) free(rpm->changelog);
316: rpm->changelog = NULL;
317: if (rpm->description) free(rpm->description);
318: rpm->description = NULL;
319:
320: /* increment the counters */
321: rpm2html_files++;
322: rpm2html_size += rpm->size / 1024;
323:
324: /*
325: * Cleanup.
326: */
1.5 veillard 327: rdfDestroySchema(rdf);
328: return(rpm);
1.1 httpng 329: }
330:
331: /*
1.4 veillard 332: * Create and RDF file containing the description for the given RPM data.
1.1 httpng 333: */
334: void dumpRpmRdf(rpmDataPtr rpm, rpmSubdirPtr tree) {
335: struct tm * tstruct;
336: rpmDirPtr dir = rpm->dir;
1.3 veillard 337: char *base = dir->dir;
1.1 httpng 338: int i;
1.4 veillard 339: char buf[10000];
340: char file[1000];
341: rdfSchema rdf;
342: rdfNamespace rpmNs;
343: rdfDescription desc;
344: rdfBag bag;
1.1 httpng 345:
1.7 veillard 346: if (!rpm2html_dump_rdf) return;
347:
1.3 veillard 348: if (rpm2html_rdf_dir != NULL) base = rpm2html_rdf_dir;
349:
1.1 httpng 350: if ((dir->subdir != NULL) && (dir->subdir[0] != '\0')) {
351: if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0'))
1.4 veillard 352: sprintf(file, "%s/%s/%s/%s.rdf", base, dir->subdir,
1.1 httpng 353: rpm->subdir, rpmName(rpm));
354: else
1.4 veillard 355: sprintf(file, "%s/%s/%s.rdf", base, dir->subdir, rpmName(rpm));
1.1 httpng 356: } else {
357: if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0'))
1.4 veillard 358: sprintf(file, "%s/%s/%s.rdf", base, rpm->subdir, rpmName(rpm));
1.1 httpng 359: else
1.4 veillard 360: sprintf(file, "%s/%s.rdf", base, rpmName(rpm));
1.1 httpng 361: }
362:
1.4 veillard 363: if (checkDate(file, rpm->stamp)) return;
1.1 httpng 364: if (verbose > 1) {
1.4 veillard 365: printf("Dumping %s\n", file);
1.1 httpng 366: }
1.4 veillard 367:
368: /*
369: * build the RDF document tree
370: * Note : the order is not important but following the rpmData
371: * structure order is easier to check.
372: */
373: rdf = rdfNewSchema();
374: rpmNs = rdfNewNamespace(rdf, "http://www.rpm.org/", "RPM");
375:
1.2 httpng 376: if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0')) {
377: if (dir->mirrors[0] != NULL)
1.4 veillard 378: sprintf(buf, "%s/%s/%s",
1.2 httpng 379: dir->mirrors[0], rpm->subdir, rpm->filename);
380: else
1.4 veillard 381: sprintf(buf, "%s/%s/%s",
1.2 httpng 382: dir->ftp, rpm->subdir, rpm->filename);
383: } else {
384: if (dir->mirrors[0] != NULL)
1.4 veillard 385: sprintf(buf, "%s/%s",
1.2 httpng 386: dir->mirrors[0], rpm->filename);
387: else
1.4 veillard 388: sprintf(buf, "%s/%s",
1.2 httpng 389: dir->ftp, rpm->filename);
390: }
1.4 veillard 391: desc = rdfAddDescription(rdf, NULL, buf);
392:
393: rdfSetValue(desc, "Name", rpmNs, rpm->name);
394: rdfSetValue(desc, "Version", rpmNs, rpm->version);
395: rdfSetValue(desc, "Release", rpmNs, rpm->release);
396: if (rpm->url)
397: rdfSetValue(desc, "URL", rpmNs, rpm->url);
398: if (rpm->arch)
399: rdfSetValue(desc, "Arch", rpmNs, rpm->arch);
400: if (rpm->os)
401: rdfSetValue(desc, "Os", rpmNs, rpm->os);
1.2 httpng 402: if (rpm->distribution)
1.4 veillard 403: rdfSetValue(desc, "Distribution", rpmNs, rpm->distribution);
1.2 httpng 404: if (rpm->vendor)
1.4 veillard 405: rdfSetValue(desc, "Vendor", rpmNs, rpm->vendor);
406: if (rpm->packager)
407: rdfSetValue(desc, "Packager", rpmNs, rpm->packager);
408: if (rpm->group)
409: rdfSetValue(desc, "Group", rpmNs, rpm->group);
410: if (rpm->summary)
411: rdfSetValue(desc, "Summary", rpmNs, rpm->summary);
412: if (rpm->description)
413: rdfSetValue(desc, "Description", rpmNs, rpm->description);
414: if (rpm->copyright)
415: rdfSetValue(desc, "Copyright", rpmNs, rpm->copyright);
416: if (rpm->changelog)
417: rdfSetValue(desc, "Changelog", rpmNs, rpm->changelog);
418: if (rpm->srcrpm) {
1.7 veillard 419: rdfSetValue(desc, "Sources", rpmNs, rpm->srcrpm);
1.4 veillard 420: if (dir->ftpsrc) {
1.7 veillard 421: rdfSetValue(desc, "SourcesFtp", rpmNs, dir->ftpsrc);
1.4 veillard 422: }
423: }
1.2 httpng 424: tstruct = localtime(&(rpm->date));
425: #ifdef HAVE_STRFTIME
426: strftime(buf, sizeof(buf) - 1, "%c", tstruct);
427: #else
428: #error "no strftime, please check !"
429: #endif
1.4 veillard 430: rdfSetValue(desc, "BuildDate", rpmNs, buf);
431: sprintf(buf, "%d", rpm->size);
432: rdfSetValue(desc, "Size", rpmNs, buf);
1.2 httpng 433: if (rpm->host)
1.4 veillard 434: rdfSetValue(desc, "BuildHost", rpmNs, rpm->host);
1.2 httpng 435: if (rpm->nb_resources > 0) {
1.7 veillard 436: /** !!!!!
437: sprintf(buf, "%d", rpm->nb_resources);
438: rdfSetValue(desc, "NbProvides", rpmNs, buf);
439: */
1.4 veillard 440: bag = rdfBagCreate(rdf, desc, "Provides", rpmNs);
1.2 httpng 441: for (i = 0;i < rpm->nb_resources;i++) {
1.4 veillard 442: rdfBagAddValue(bag, "Resource", rpmNs,
443: rpm->resources[i]->name, NULL);
1.2 httpng 444: }
445: }
446: if (rpm->nb_requires > 0) {
1.7 veillard 447: /** !!!!!
448: sprintf(buf, "%d", rpm->nb_requires);
449: rdfSetValue(desc, "NbRequires", rpmNs, buf);
450: */
1.4 veillard 451: bag = rdfBagCreate(rdf, desc, "Requires", rpmNs);
1.2 httpng 452: for (i = 0;i < rpm->nb_requires;i++) {
1.4 veillard 453: rdfBagAddValue(bag, "Resource", rpmNs,
454: rpm->requires[i]->name, NULL);
1.2 httpng 455: }
456: }
457: if (rpm->filelist)
1.4 veillard 458: rdfSetValue(desc, "Files", rpmNs, rpm->filelist);
459:
460: /*
461: * Save the RDF file and cleanup the tree.
462: */
463: rdfWrite(rdf, file);
464: rdfDestroySchema(rdf);
1.1 httpng 465: }
466:
Webmaster