Annotation of rpm2html/rdf.c, revision 1.32
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.32 ! daniel 6: * $Id: rdf.c,v 1.31 1998/11/11 18:43:34 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 */
1.28 daniel 62: if ((dir->build_tree != 0) && (rpm->extra->filelist != NULL)) {
1.16 veillard 63: char *cur, *filename;
64:
1.28 daniel 65: cur = rpm->extra->filelist;
1.16 veillard 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 */
1.28 daniel 91: rpmFreeExtraData(rpm);
1.16 veillard 92:
93: /* increment the counters */
94: rpm2html_files++;
95: rpm2html_size += rpm->size / 1024;
96: }
97: return(rpm);
98: }
99:
100: /*
1.1 httpng 101: * Open an RDF file call the parser to create a XML tree
102: * Then walk the tree and build an rpmData structure for
103: * the corresponding package.
104: */
1.16 veillard 105: rpmDataPtr rpmOpenRdfFile(char *file) {
1.6 veillard 106: char nameBuffer[200];
1.5 veillard 107: rdfSchema rdf;
108: rdfNamespace rpmNs;
109: rdfNamespace rdfNs;
110: rdfDescription desc;
111: rdfBag bag;
1.7 veillard 112: rdfElement elem;
1.5 veillard 113: char *value;
114: rpmDataPtr rpm;
1.6 veillard 115: struct stat buf;
1.7 veillard 116: int i;
1.5 veillard 117:
118: rdf = rdfRead(file);
119: if (rdf == NULL) return(NULL);
120:
121: /*
122: * Start the analyze, check that's an RDf for RPM packages.
123: */
124: rdfNs = rdfGetNamespace(rdf, "http://www.w3.org/TR/WD-rdf-syntax#");
125: if (rdfNs == NULL) {
126: fprintf(stderr, "%s is not an RDF schema\n", file);
127: rdfDestroySchema(rdf);
128: return(NULL);
129: }
130: rpmNs = rdfGetNamespace(rdf, "http://www.rpm.org/");
131: if (rdfNs == NULL) {
132: fprintf(stderr, "%s is not an RPM specific RDF schema\n", file);
133: rdfDestroySchema(rdf);
134: return(NULL);
135: }
136: desc = rdfFirstDescription(rdf);
137: if (rdfNs == NULL) {
138: fprintf(stderr, "%s RDF schema seems empty\n", file);
139: rdfDestroySchema(rdf);
140: return(NULL);
141: }
142:
143: /*
144: * We are pretty sure that it will be a valid schema,
1.28 daniel 145: * allocate a new rpmData block, and an rpmExtraData block fill them
1.5 veillard 146: */
147: rpm = (rpmDataPtr) malloc(sizeof(rpmData));
148: if (rpm == NULL) {
1.28 daniel 149: fprintf(stderr, "cannot allocate %d bytes: %s\n", sizeof(rpmData),
150: strerror(errno));
151: return(NULL);
1.5 veillard 152: }
1.6 veillard 153: memset(rpm, 0, sizeof(rpmData));
1.28 daniel 154: rpm->extra = (rpmExtraDataPtr) malloc(sizeof(rpmExtraData));
155: if (rpm == NULL) {
156: fprintf(stderr, "cannot allocate %d bytes: %s\n", sizeof(rpmExtraData),
157: strerror(errno));
158: return(NULL);
159: }
160: memset(rpm->extra, 0, sizeof(rpmExtraData));
1.5 veillard 161:
1.6 veillard 162: stat(file, &buf);
1.28 daniel 163: rpm->extra->stamp = buf.st_mtime;
1.6 veillard 164:
165: /*
166: * Now extract all the metadata informations from the RDF tree
167: */
1.5 veillard 168: rdfGetValue(desc, "Name", rpmNs, &value, NULL);
1.30 daniel 169: if (value != NULL) rpm->name = value;
1.5 veillard 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);
1.30 daniel 176: if (value != NULL) rpm->version = value;
1.5 veillard 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);
1.30 daniel 183: if (value != NULL) rpm->release = value;
1.5 veillard 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);
1.30 daniel 190: if (value != NULL) rpm->url = value;
1.7 veillard 191: else rpm->url = NULL;
192:
1.5 veillard 193: rdfGetValue(desc, "Arch", rpmNs, &value, NULL);
1.30 daniel 194: if (value != NULL) rpm->arch = value;
1.24 daniel 195: else rpm->arch = strdup("noarch");
1.7 veillard 196:
1.5 veillard 197: rdfGetValue(desc, "Os", rpmNs, &value, NULL);
1.30 daniel 198: if (value != NULL) rpm->os = value;
1.7 veillard 199: else rpm->os = strdup("linux");
200:
1.5 veillard 201: rdfGetValue(desc, "Distribution", rpmNs, &value, NULL);
1.30 daniel 202: if (value != NULL) rpm->distribution = value;
1.7 veillard 203: else rpm->distribution = strdup(localizedStrings[LANG_UNKNOWN]);
204:
1.5 veillard 205: rdfGetValue(desc, "Vendor", rpmNs, &value, NULL);
1.30 daniel 206: if (value != NULL) rpm->vendor = value;
1.7 veillard 207: else rpm->vendor = strdup(localizedStrings[LANG_UNKNOWN]);
208:
1.5 veillard 209: rdfGetValue(desc, "Packager", rpmNs, &value, NULL);
1.30 daniel 210: if (value != NULL) rpm->extra->packager = value;
1.28 daniel 211: else rpm->extra->packager = NULL;
1.7 veillard 212:
1.5 veillard 213: rdfGetValue(desc, "Group", rpmNs, &value, NULL);
1.30 daniel 214: if (value != NULL) rpm->group = value;
1.7 veillard 215: else rpm->group = strdup(localizedStrings[LANG_NO_GROUP]);
216:
1.5 veillard 217: rdfGetValue(desc, "Summary", rpmNs, &value, NULL);
1.30 daniel 218: if (value != NULL) rpm->summary = value;
1.7 veillard 219: else rpm->summary = strdup(localizedStrings[LANG_NO_SUMMARY]);
220:
1.5 veillard 221: rdfGetValue(desc, "Description", rpmNs, &value, NULL);
1.30 daniel 222: if (value != NULL) rpm->extra->description = value;
1.28 daniel 223: else rpm->extra->description = strdup(localizedStrings[LANG_NO_DESCRIPTION]);
1.7 veillard 224:
1.5 veillard 225: rdfGetValue(desc, "Copyright", rpmNs, &value, NULL);
1.30 daniel 226: if (value != NULL) rpm->extra->copyright = value;
1.28 daniel 227: else rpm->extra->copyright = NULL;
1.7 veillard 228:
1.5 veillard 229: rdfGetValue(desc, "Changelog", rpmNs, &value, NULL);
1.30 daniel 230: if (value != NULL) rpm->extra->changelog = value;
1.28 daniel 231: else rpm->extra->changelog = NULL;
1.7 veillard 232:
233: rdfGetValue(desc, "Sources", rpmNs, &value, NULL);
234: if (value != NULL) {
1.30 daniel 235: rpm->extra->srcrpm = value;
1.28 daniel 236: } else rpm->extra->srcrpm = strdup("");
1.7 veillard 237:
238: rdfGetValue(desc, "Size", rpmNs, &value, NULL);
239: if (value != NULL) {
240: if (sscanf(value, "%d", &(rpm->size)) != 1)
241: rpm->size = 0;
1.32 ! daniel 242: free(value);
1.7 veillard 243: } else rpm->size = 0;
244:
245: rdfGetValue(desc, "Date", rpmNs, &value, NULL);
246: if (value != NULL) {
1.8 veillard 247: if (sscanf(value, "%d", &i) != 1)
1.7 veillard 248: rpm->date = 0;
1.8 veillard 249: else
250: rpm->date = i;
1.32 ! daniel 251: free(value);
1.7 veillard 252: } else rpm->date = 0;
253:
254: rdfGetValue(desc, "BuildHost", rpmNs, &value, NULL);
1.30 daniel 255: if (value != NULL) rpm->extra->host = value;
1.28 daniel 256: else rpm->extra->host = strdup(localizedStrings[LANG_NO_HOST]);
1.7 veillard 257:
258: rdfGetValue(desc, "Files", rpmNs, &value, NULL);
1.30 daniel 259: if (value != NULL) rpm->extra->filelist = value;
1.28 daniel 260: else rpm->extra->filelist = NULL;
1.7 veillard 261:
262: /*
263: * Fetching packages provided is a bit more tricky, one have to
264: * find the RDF Bag, and scan it's values.
265: */
1.28 daniel 266: rpm->extra->nb_resources = 0;
1.7 veillard 267: rdfGetValue(desc, "Provides", rpmNs, NULL, &bag);
268: if (bag != NULL) {
269: elem = rdfFirstChild(bag);
1.28 daniel 270: rpm->extra->max_resources = 5;
271: rpm->extra->resources = (rpmRessPtr *) malloc(rpm->extra->max_resources *
1.11 veillard 272: sizeof(rpmRessPtr));
1.28 daniel 273: if (rpm->extra->resources == NULL) {
1.11 veillard 274: fprintf(stderr, "rpmOpenRdf : ran out of memory\n");
275: exit(1);
276: }
1.7 veillard 277: i = 0;
278: while (elem != NULL) {
1.32 ! daniel 279: char *name;
1.28 daniel 280: if (i >= rpm->extra->max_resources) {
281: rpm->extra->max_resources *= 2;
282: rpm->extra->resources = (rpmRessPtr *) realloc(rpm->extra->resources,
283: rpm->extra->max_resources * sizeof(rpmRessPtr));
284: if (rpm->extra->resources == NULL) {
1.11 veillard 285: fprintf(stderr, "rpmOpenRdf : ran out of memory\n");
286: exit(1);
287: }
1.7 veillard 288: }
289: /*
290: * Check that we are scanning an RPM Resource.
291: */
1.32 ! daniel 292: name = rdfElemGetPropertyName(elem);
! 293: if ((name != NULL) &&
! 294: (!strcmp(name, "Resource")) &&
1.7 veillard 295: (rdfElemGetNamespace(elem) == rpmNs)) {
296: value = rdfElemGetValue(elem);
297: if (value != NULL) {
1.28 daniel 298: rpm->extra->resources[i] = rpmRessAdd(value, rpm, 0);
1.7 veillard 299: i++;
1.28 daniel 300: rpm->extra->nb_resources++;
1.32 ! daniel 301: free(value);
1.20 veillard 302: } else if (rpm2htmlVerbose > 1) {
1.7 veillard 303: fprintf(stderr, "%s : malformed Resource element !\n", file);
304: }
1.20 veillard 305: } else if (rpm2htmlVerbose > 1) {
1.7 veillard 306: fprintf(stderr, "%s : malformed Provides bag !\n", file);
307: }
1.32 ! daniel 308: if (name != NULL) free(name);
1.7 veillard 309: elem = rdfNextElem(elem);
310: }
1.20 veillard 311: } else if (rpm2htmlVerbose > 1) {
1.7 veillard 312: fprintf(stderr, "%s doesn't export any resource\n", file);
313: }
314:
315: /*
316: * idem for the dependencies.
317: */
1.28 daniel 318: rpm->extra->nb_requires = 0;
1.7 veillard 319: rdfGetValue(desc, "Requires", rpmNs, NULL, &bag);
320: if (bag != NULL) {
321: elem = rdfFirstChild(bag);
1.28 daniel 322: rpm->extra->max_requires = 5;
323: rpm->extra->requires = (rpmRessPtr *) malloc(rpm->extra->max_requires *
1.11 veillard 324: sizeof(rpmRessPtr));
1.28 daniel 325: if (rpm->extra->requires == NULL) {
1.11 veillard 326: fprintf(stderr, "rpmOpenRdf : ran out of memory\n");
327: exit(1);
328: }
1.7 veillard 329: i = 0;
330: while (elem != NULL) {
1.32 ! daniel 331: char *name;
1.28 daniel 332: if (i >= rpm->extra->max_requires) {
333: rpm->extra->max_requires *= 2;
334: rpm->extra->requires = (rpmRessPtr *) realloc(rpm->extra->requires,
335: rpm->extra->max_requires * sizeof(rpmRessPtr));
336: if (rpm->extra->requires == NULL) {
1.11 veillard 337: fprintf(stderr, "rpmOpenRdf : ran out of memory\n");
338: exit(1);
339: }
1.7 veillard 340: }
341: /*
342: * Check that we are scanning an RPM Resource.
343: */
1.32 ! daniel 344: name = rdfElemGetPropertyName(elem);
! 345: if ((name != NULL) &&
! 346: (!strcmp(name, "Resource")) &&
1.7 veillard 347: (rdfElemGetNamespace(elem) == rpmNs)) {
348: value = rdfElemGetValue(elem);
349: if (value != NULL) {
1.28 daniel 350: rpm->extra->requires[i] = rpmRequAdd(value, rpm, 0);
1.7 veillard 351: i++;
1.28 daniel 352: rpm->extra->nb_requires++;
1.32 ! daniel 353: free(value);
1.20 veillard 354: } else if (rpm2htmlVerbose > 1) {
1.7 veillard 355: fprintf(stderr, "%s : malformed Resource element !\n", file);
356: }
1.20 veillard 357: } else if (rpm2htmlVerbose > 1) {
1.7 veillard 358: fprintf(stderr, "%s : malformed Provides bag !\n", file);
359: }
1.32 ! daniel 360: if (name != NULL) free(name);
1.7 veillard 361: elem = rdfNextElem(elem);
362: }
363: }
1.5 veillard 364:
1.6 veillard 365: /*
366: * Finish filling the rpmData structure.
367: */
1.31 daniel 368: value = rdfGetDescriptionAbout(rdf, desc);
369: if (value != NULL) {
370: char *filename = &value[strlen(value)];
371:
372: while ((filename > value) && (*filename != '/'))
373: filename --;
374: rpm->filename = strdup(filename);
1.32 ! daniel 375: free(value);
1.31 daniel 376: } else {
1.6 veillard 377: #ifdef HAVE_SNPRINTF
1.31 daniel 378: sprintf(nameBuffer, "%s-%s-%s.%s.rpm",
379: rpm->name, rpm->version, rpm->release, rpm->arch);
1.6 veillard 380: #else
1.31 daniel 381: snprintf(nameBuffer, 200, "%s-%s-%s.%s.rpm",
382: rpm->name, rpm->version, rpm->release, rpm->arch);
1.6 veillard 383: #endif
1.31 daniel 384: rpm->filename = strdup(nameBuffer);
385: }
1.6 veillard 386:
387:
388: /*
389: * Cleanup.
390: */
1.5 veillard 391: rdfDestroySchema(rdf);
392: return(rpm);
1.1 httpng 393: }
394:
395: /*
1.4 veillard 396: * Create and RDF file containing the description for the given RPM data.
1.1 httpng 397: */
398: void dumpRpmRdf(rpmDataPtr rpm, rpmSubdirPtr tree) {
1.12 veillard 399: FILE *output;
400: struct stat stat_buf;
1.1 httpng 401: struct tm * tstruct;
402: rpmDirPtr dir = rpm->dir;
1.3 veillard 403: char *base = dir->dir;
1.1 httpng 404: int i;
1.4 veillard 405: char buf[10000];
406: char file[1000];
1.29 daniel 407: char dotdot[50];
1.12 veillard 408: char *buffer;
409: int size;
1.27 daniel 410: int stat_res = 0;
1.4 veillard 411: rdfSchema rdf;
412: rdfNamespace rpmNs;
413: rdfDescription desc;
1.29 daniel 414: rdfElement elem;
1.4 veillard 415: rdfBag bag;
1.29 daniel 416: int deep;
417: char *ptr;
1.1 httpng 418:
1.7 veillard 419: if (!rpm2html_dump_rdf) return;
420:
1.3 veillard 421: if (rpm2html_rdf_dir != NULL) base = rpm2html_rdf_dir;
422:
1.29 daniel 423: deep = 0;
424: if (rpm->subdir != NULL)
425: for (ptr = rpm->subdir, deep++;*ptr != 0;ptr++)
426: if (*ptr == '/') deep++;
427: if (dir->subdir != NULL)
428: for (ptr = dir->subdir, deep++;*ptr != 0;ptr++)
429: if (*ptr == '/') deep++;
430:
1.1 httpng 431: if ((dir->subdir != NULL) && (dir->subdir[0] != '\0')) {
432: if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0'))
1.4 veillard 433: sprintf(file, "%s/%s/%s/%s.rdf", base, dir->subdir,
1.1 httpng 434: rpm->subdir, rpmName(rpm));
435: else
1.4 veillard 436: sprintf(file, "%s/%s/%s.rdf", base, dir->subdir, rpmName(rpm));
1.1 httpng 437: } else {
438: if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0'))
1.4 veillard 439: sprintf(file, "%s/%s/%s.rdf", base, rpm->subdir, rpmName(rpm));
1.1 httpng 440: else
1.4 veillard 441: sprintf(file, "%s/%s.rdf", base, rpmName(rpm));
1.1 httpng 442: }
1.29 daniel 443: dotdot[0] = '\0';
444: for (;deep > 0;deep --)
445: strcat(dotdot, "../");
1.1 httpng 446:
1.12 veillard 447: /*
448: * Check wether the RPM timestamp is older than the filestamp.
449: if ((stat_res = stat(file, &stat_buf)) == 0) {
450: if (stat_buf.st_mtime > rpm->stamp) return;
451: }
1.27 daniel 452: */
453: stat_res = stat(file, &stat_buf);
1.9 veillard 454:
455: /*
456: * Create the directory if needed
457: */
458: if ((dir->subdir != NULL) && (dir->subdir[0] != '\0')) {
459: if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0'))
460: sprintf(buf, "%s/%s/%s", base, dir->subdir, rpm->subdir);
461: else
462: sprintf(buf, "%s/%s", base, dir->subdir);
463: } else {
464: if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0'))
465: sprintf(buf, "%s/%s", base, rpm->subdir);
466: else
467: sprintf(buf, "%s", base);
468: }
469: createDirectory(buf);
470:
1.4 veillard 471: /*
472: * build the RDF document tree
473: * Note : the order is not important but following the rpmData
474: * structure order is easier to check.
475: */
476: rdf = rdfNewSchema();
477: rpmNs = rdfNewNamespace(rdf, "http://www.rpm.org/", "RPM");
478:
1.2 httpng 479: if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0')) {
480: if (dir->mirrors[0] != NULL)
1.4 veillard 481: sprintf(buf, "%s/%s/%s",
1.2 httpng 482: dir->mirrors[0], rpm->subdir, rpm->filename);
483: else
1.4 veillard 484: sprintf(buf, "%s/%s/%s",
1.2 httpng 485: dir->ftp, rpm->subdir, rpm->filename);
486: } else {
487: if (dir->mirrors[0] != NULL)
1.4 veillard 488: sprintf(buf, "%s/%s",
1.2 httpng 489: dir->mirrors[0], rpm->filename);
490: else
1.4 veillard 491: sprintf(buf, "%s/%s",
1.2 httpng 492: dir->ftp, rpm->filename);
493: }
1.4 veillard 494: desc = rdfAddDescription(rdf, NULL, buf);
495:
496: rdfSetValue(desc, "Name", rpmNs, rpm->name);
497: rdfSetValue(desc, "Version", rpmNs, rpm->version);
498: rdfSetValue(desc, "Release", rpmNs, rpm->release);
499: if (rpm->url)
500: rdfSetValue(desc, "URL", rpmNs, rpm->url);
501: if (rpm->arch)
502: rdfSetValue(desc, "Arch", rpmNs, rpm->arch);
503: if (rpm->os)
504: rdfSetValue(desc, "Os", rpmNs, rpm->os);
1.2 httpng 505: if (rpm->distribution)
1.4 veillard 506: rdfSetValue(desc, "Distribution", rpmNs, rpm->distribution);
1.2 httpng 507: if (rpm->vendor)
1.4 veillard 508: rdfSetValue(desc, "Vendor", rpmNs, rpm->vendor);
1.28 daniel 509: if (rpm->extra->packager)
510: rdfSetValue(desc, "Packager", rpmNs, rpm->extra->packager);
1.4 veillard 511: if (rpm->group)
512: rdfSetValue(desc, "Group", rpmNs, rpm->group);
513: if (rpm->summary)
514: rdfSetValue(desc, "Summary", rpmNs, rpm->summary);
1.28 daniel 515: if (rpm->extra->description)
516: rdfSetValue(desc, "Description", rpmNs, rpm->extra->description);
517: if (rpm->extra->copyright)
518: rdfSetValue(desc, "Copyright", rpmNs, rpm->extra->copyright);
519: if (rpm->extra->changelog)
520: rdfSetValue(desc, "Changelog", rpmNs, rpm->extra->changelog);
521: if (rpm->extra->srcrpm) {
522: rdfSetValue(desc, "Sources", rpmNs, rpm->extra->srcrpm);
1.4 veillard 523: if (dir->ftpsrc) {
1.7 veillard 524: rdfSetValue(desc, "SourcesFtp", rpmNs, dir->ftpsrc);
1.4 veillard 525: }
526: }
1.2 httpng 527: tstruct = localtime(&(rpm->date));
528: #ifdef HAVE_STRFTIME
529: strftime(buf, sizeof(buf) - 1, "%c", tstruct);
530: #else
531: #error "no strftime, please check !"
532: #endif
1.4 veillard 533: rdfSetValue(desc, "BuildDate", rpmNs, buf);
1.12 veillard 534: sprintf(buf, "%d", (int) rpm->date);
1.10 veillard 535: rdfSetValue(desc, "Date", rpmNs, buf);
1.4 veillard 536: sprintf(buf, "%d", rpm->size);
537: rdfSetValue(desc, "Size", rpmNs, buf);
1.28 daniel 538: if (rpm->extra->host)
539: rdfSetValue(desc, "BuildHost", rpmNs, rpm->extra->host);
540: if (rpm->extra->nb_resources > 0) {
1.4 veillard 541: bag = rdfBagCreate(rdf, desc, "Provides", rpmNs);
1.28 daniel 542: for (i = 0;i < rpm->extra->nb_resources;i++) {
1.29 daniel 543: elem = rdfBagAddValue(bag, "Resource", rpmNs,
1.28 daniel 544: rpm->extra->resources[i]->name, NULL);
1.29 daniel 545: if (rpm->extra->resources[i]->name[0] != '/') {
546: snprintf(buf, sizeof(buf) - 1, "%sresources/%s.rdf",
547: dotdot, rpm->extra->resources[i]->name);
548: xmlSetProp(elem, "href", buf);
549: }
1.2 httpng 550: }
551: }
1.28 daniel 552: if (rpm->extra->nb_requires > 0) {
1.4 veillard 553: bag = rdfBagCreate(rdf, desc, "Requires", rpmNs);
1.28 daniel 554: for (i = 0;i < rpm->extra->nb_requires;i++) {
1.29 daniel 555: elem = rdfBagAddValue(bag, "Resource", rpmNs,
1.28 daniel 556: rpm->extra->requires[i]->name, NULL);
1.29 daniel 557: if (rpm->extra->requires[i]->name[0] != '/') {
558: snprintf(buf, sizeof(buf) - 1, "%sresources/%s.rdf",
559: dotdot, rpm->extra->requires[i]->name);
560: xmlSetProp(elem, "href", buf);
561: }
1.2 httpng 562: }
563: }
1.28 daniel 564: if (rpm->extra->filelist)
565: rdfSetValue(desc, "Files", rpmNs, rpm->extra->filelist);
1.4 veillard 566:
567: /*
1.12 veillard 568: * Save the RDF to a buffer, remove the tree.
1.4 veillard 569: */
1.12 veillard 570: rdfWriteMemory(rdf, &buffer, &size);
1.4 veillard 571: rdfDestroySchema(rdf);
1.12 veillard 572:
573: /*
574: * if the file already exists avoid to overwrite it if the content
575: * didn't change.
576: */
577: if ((stat_res == 0) && (stat_buf.st_size == size)) {
578: char *buffer2 = malloc(size * sizeof(char));
579:
580: if (buffer2 == NULL) {
581: fprintf(stderr, " : running out of memory\n");
582: return;
583: }
584: output = fopen(file, "r");
585: if (output == NULL) {
586: fprintf(stderr, "couldn't open %s for reading !\n", file);
587: return;
588: }
589: if (fread(buffer2, size, 1, output) != 1) {
590: fprintf(stderr, "Problem reading from %s !\n", file);
591: }
592: fclose(output);
593:
594: /*
595: * Now compare the content !
596: */
597: if (!memcmp(buffer, buffer2, size)) {
598: free(buffer2);
1.20 veillard 599: if (rpm2htmlVerbose > 1)
1.12 veillard 600: fprintf(stderr, "File %s : Content identical !\n", file);
601: return;
602: }
603: free(buffer2);
604: }
605:
606: /*
607: * Dump the file.
608: */
1.20 veillard 609: if (rpm2htmlVerbose > 1) {
1.12 veillard 610: printf("Dumping %s\n", file);
611: }
612: output = fopen(file, "w");
613: if (output == NULL) {
614: fprintf(stderr, "couldn't open %s for writing !\n", file);
615: return;
616: }
617: if (fwrite(buffer, size, 1, output) != 1) {
618: fprintf(stderr, "Problem writing to %s !\n", file);
619: }
620: fclose(output);
1.1 httpng 621: }
622:
1.13 veillard 623: /*
624: * Create and RDF file containing informations about a resource.
625: */
626:
627: void dumpResRdf(rpmRessPtr res) {
628: FILE *output;
629: struct stat stat_buf;
630: char *base;
631: int i;
632: char buf[10000];
633: char file[1000];
634: char *buffer;
635: int size;
636: int stat_res;
637: rpmDataPtr rpm;
638: rpmDirPtr dir;
639: rdfSchema rdf;
640: rdfNamespace rpmNs;
641: rdfDescription desc;
642: static int initialized = 0;
643:
644: if (!rpm2html_dump_rdf_resources) return;
645:
646: if (rpm2html_rdf_resources_dir != NULL) base = rpm2html_rdf_resources_dir;
647: else return;
648:
649: if (res->nb_provider == 0) return;
650:
1.15 veillard 651: sprintf(file, "%s/%s.rdf", base, res->name);
1.13 veillard 652:
653: /*
654: * Create the directory if needed
655: */
656: if (!initialized) {
657: sprintf(buf, "%s", base);
658: createDirectory(buf);
659: initialized = 1;
660: }
661:
662: /*
663: * build the RDF document tree
664: * Note : the order is not important but following the rpmData
665: * structure order is easier to check.
666: */
667: rdf = rdfNewSchema();
668: rpmNs = rdfNewNamespace(rdf, "http://www.rpm.org/", "RPM");
669: for (i = 0;i < res->nb_provider;i++) {
670: rpm = res->provider[i];
671: dir = rpm->dir;
672: if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0')) {
673: if (dir->mirrors[0] != NULL)
674: sprintf(buf, "%s/%s/%s",
675: dir->mirrors[0], rpm->subdir, rpm->filename);
676: else
677: sprintf(buf, "%s/%s/%s",
678: dir->ftp, rpm->subdir, rpm->filename);
679: } else {
680: if (dir->mirrors[0] != NULL)
681: sprintf(buf, "%s/%s",
682: dir->mirrors[0], rpm->filename);
683: else
684: sprintf(buf, "%s/%s",
685: dir->ftp, rpm->filename);
686: }
687: desc = rdfAddDescription(rdf, NULL, buf);
1.29 daniel 688: if ((dir->subdir != NULL) && (dir->subdir[0] != '\0')) {
689: if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0'))
690: sprintf(buf, "../%s/%s/%s.rdf", dir->subdir,
691: rpm->subdir, rpmName(rpm));
692: else
693: sprintf(buf, "../%s/%s.rdf", dir->subdir, rpmName(rpm));
694: } else {
695: if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0'))
696: sprintf(buf, "../%s/%s.rdf", rpm->subdir, rpmName(rpm));
697: else
698: sprintf(buf, "../%s.rdf", rpmName(rpm));
699: }
700: xmlSetProp(desc, "href", buf);
1.13 veillard 701: rdfSetValue(desc, "Name", rpmNs, rpm->name);
702: rdfSetValue(desc, "Version", rpmNs, rpm->version);
703: rdfSetValue(desc, "Release", rpmNs, rpm->release);
704: if (rpm->arch)
705: rdfSetValue(desc, "Arch", rpmNs, rpm->arch);
706: if (rpm->os)
707: rdfSetValue(desc, "Os", rpmNs, rpm->os);
708: if (rpm->distribution)
709: rdfSetValue(desc, "Distribution", rpmNs, rpm->distribution);
710: if (rpm->vendor)
711: rdfSetValue(desc, "Vendor", rpmNs, rpm->vendor);
712: sprintf(buf, "%d", (int) rpm->date);
713: rdfSetValue(desc, "Date", rpmNs, buf);
1.17 veillard 714: sprintf(buf, "%d", (int) rpm->size);
715: rdfSetValue(desc, "Size", rpmNs, buf);
1.14 httpng 716: if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0')) {
717: if ((dir->subdir != NULL) && (dir->subdir[0] != '\0'))
718: sprintf(buf, "%s/%s",
719: dir->subdir, rpm->subdir);
720: else
721: sprintf(buf, "%s",
722: rpm->subdir);
723: } else {
724: if ((dir->subdir != NULL) && (dir->subdir[0] != '\0'))
725: sprintf(buf, "%s",
726: dir->subdir);
727: else
728: buf[0] = '\0';
729: }
730: if (buf[0] != '\0')
731: rdfSetValue(desc, "Subdir", rpmNs, buf);
1.13 veillard 732: }
733:
734: /*
735: * Save the RDF to a buffer, remove the tree.
736: */
737: rdfWriteMemory(rdf, &buffer, &size);
738: rdfDestroySchema(rdf);
739:
740: /*
741: * if the file already exists avoid to overwrite it if the content
742: * didn't change.
743: */
744: stat_res = stat(file, &stat_buf);
745:
746: if ((stat_res == 0) && (stat_buf.st_size == size)) {
747: char *buffer2 = malloc(size * sizeof(char));
748:
749: if (buffer2 == NULL) {
750: fprintf(stderr, " : running out of memory\n");
751: return;
752: }
753: output = fopen(file, "r");
754: if (output == NULL) {
755: fprintf(stderr, "couldn't open %s for reading !\n", file);
756: return;
757: }
758: if (fread(buffer2, size, 1, output) != 1) {
759: fprintf(stderr, "Problem reading from %s !\n", file);
760: }
761: fclose(output);
762:
763: /*
764: * Now compare the content !
765: */
766: if (!memcmp(buffer, buffer2, size)) {
767: free(buffer2);
1.20 veillard 768: if (rpm2htmlVerbose > 1)
1.13 veillard 769: fprintf(stderr, "File %s : Content identical !\n", file);
770: return;
771: }
772: free(buffer2);
773: }
774:
775: /*
776: * Dump the file.
777: */
1.20 veillard 778: if (rpm2htmlVerbose > 1) {
1.13 veillard 779: printf("Dumping %s\n", file);
780: }
781: output = fopen(file, "w");
782: if (output == NULL) {
783: fprintf(stderr, "couldn't open %s for writing !\n", file);
784: return;
785: }
786: if (fwrite(buffer, size, 1, output) != 1) {
787: fprintf(stderr, "Problem writing to %s !\n", file);
788: }
789: fclose(output);
790: }
791:
792: /*
793: * Dump all the RDf files about known resources.
794: */
795:
796: void dumpAllResRdf(void) {
797: rpmRessPtr cur;
798:
799: if (!rpm2html_dump_rdf_resources) return;
800:
801: cur = ressList;
802:
803: while (cur != NULL) {
804: dumpResRdf(cur);
805: cur = cur->next;
806: }
1.21 daniel 807: }
808:
809: /*
810: * Dump an apropos RDF file for all packages.
1.22 daniel 811: * Since the file is really too big to be kept as-if, it is compressed
1.21 daniel 812: */
813:
814: void dumpAproposRdf(void) {
815: rpmDataPtr rpm;
816: char file[1000];
817: char buf[1000];
818: rdfSchema rdf;
819: rdfNamespace rpmNs;
820: rdfDescription desc;
821: rpmDirPtr dir;
822: char *base;
1.22 daniel 823: char *buffer;
824: int size;
825: gzFile output;
826: int res;
1.21 daniel 827:
828: if (!rpm2html_dump_rdf_resources) return;
829:
830: if (rpm2html_rdf_resources_dir != NULL) base = rpm2html_rdf_resources_dir;
831: else return;
832:
1.22 daniel 833: sprintf(file, "%s/fullIndex.rdf.gz", base);
1.21 daniel 834: if (rpm2htmlVerbose > 1) {
835: printf("Dumping %s\n", file);
836: }
837:
838: /*
839: * build the RDF document tree, one only dump the minimum needed
840: * for searching.
841: */
842: rdf = rdfNewSchema();
843: rpmNs = rdfNewNamespace(rdf, "http://www.rpm.org/", "RPM");
844:
845: rpm = rpmSoftwareList;
846:
847: while (rpm != NULL) {
848: dir = rpm->dir;
849: if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0')) {
850: if (dir->mirrors[0] != NULL)
851: sprintf(buf, "%s/%s/%s",
852: dir->mirrors[0], rpm->subdir, rpm->filename);
853: else
854: sprintf(buf, "%s/%s/%s",
855: dir->ftp, rpm->subdir, rpm->filename);
856: } else {
857: if (dir->mirrors[0] != NULL)
858: sprintf(buf, "%s/%s",
859: dir->mirrors[0], rpm->filename);
860: else
861: sprintf(buf, "%s/%s",
862: dir->ftp, rpm->filename);
863: }
864: desc = rdfAddDescription(rdf, NULL, buf);
865: rdfSetValue(desc, "Name", rpmNs, rpm->name);
1.23 veillard 866: rdfSetValue(desc, "Summary", rpmNs, rpm->summary);
867: rpm = rpm->nextSoft;
1.21 daniel 868: }
869:
870: /*
871: * Dump the RDF tree, and cleanup.
872: */
1.22 daniel 873: rdfWriteMemory(rdf, &buffer, &size);
1.21 daniel 874: rdfDestroySchema(rdf);
1.22 daniel 875:
876: /*
877: * Write the compressed version of the RDF base.
878: */
879: output = gzopen(file, "w9");
880: if (output == NULL) {
881: fprintf(stderr, "Could not write %s : gzopen failed\n", file);
882: return;
883: }
884: res = gzwrite(output, buffer, size);
885: if (res <= 0) {
886: fprintf(stderr, "Could not write %s : gzwrite failed\n", file);
887: return;
888: }
889: gzclose(output);
1.13 veillard 890: }
891:
1.25 veillard 892: /*
893: * Dump the distribs/xxx.rdf file giving information about a
894: * specific distribution
895: */
896:
897: void dumpDistRdf(rpmDirPtr dir) {
898: char buf[100];
899: char file[1000];
900: rdfSchema rdf;
901: rdfNamespace rpmNs;
902: rdfDescription desc;
903: rdfBag mirrors;
904: rdfElement mirror;
905: struct stat stat_buf;
906: int stat_res;
907: char *base, *ptr;
908: char *buffer;
909: int size;
910: FILE *output;
911: int i;
912:
913: if (!rpm2html_dump_rdf_resources) return;
914:
915: if (rpm2html_rdf_resources_dir != NULL) base = rpm2html_rdf_resources_dir;
916: else return;
917:
918: sprintf(buf, "%s", dir->subdir);
919: for (ptr = &buf[0]; *ptr; ptr++) if (*ptr == '/') *ptr = '_';
920: sprintf(file, "%s/distribs", base);
921: createDirectory(file);
922: sprintf(file, "%s/distribs/%s.rdf", base, buf);
923:
924: /*
925: * build the RDF document tree, one only dump the minimum needed
926: * for searching distributions informations.
927: */
928: rdf = rdfNewSchema();
929: rpmNs = rdfNewNamespace(rdf, "http://www.rpm.org/", "RPM");
930:
931: desc = rdfAddDescription(rdf, NULL, dir->ftp);
932: rdfSetValue(desc, "ID", rpmNs, dir->subdir);
933: rdfSetValue(desc, "Name", rpmNs, dir->name);
934: rdfSetValue(desc, "Origin", rpmNs, dir->ftp);
935: rdfSetValue(desc, "Sources", rpmNs, dir->ftpsrc);
936: sprintf(buf, "%d", dir->files);
937: mirrors = rdfBagCreate(rdf, desc, "Mirrors", rpmNs);
938: for (i = 0;i < dir->nb_mirrors;i++) {
939: mirror = rdfBagAddValue(mirrors, "Mirror", rpmNs, NULL, NULL);
940: rdfSetElementResource(rdf, mirror, dir->mirrors[i]);
941: }
942:
943: /*
944: * Dump the RDF tree, and cleanup.
945: */
946: rdfWriteMemory(rdf, &buffer, &size);
947: rdfDestroySchema(rdf);
948:
949: /*
950: * if the file already exists avoid to overwrite it if the content
951: * didn't change.
952: */
953: stat_res = stat(file, &stat_buf);
954:
955: if ((stat_res == 0) && (stat_buf.st_size == size)) {
956: char *buffer2 = malloc(size * sizeof(char));
957:
958: if (buffer2 == NULL) {
959: fprintf(stderr, " : running out of memory\n");
960: return;
961: }
962: output = fopen(file, "r");
963: if (output == NULL) {
964: fprintf(stderr, "couldn't open %s for reading !\n", file);
965: return;
966: }
967: if (fread(buffer2, size, 1, output) != 1) {
968: fprintf(stderr, "Problem reading from %s !\n", file);
969: }
970: fclose(output);
971:
972: /*
973: * Now compare the content !
974: */
975: if (!memcmp(buffer, buffer2, size)) {
976: free(buffer2);
977: if (rpm2htmlVerbose > 1)
978: fprintf(stderr, "File %s : Content identical !\n", file);
979: return;
980: }
981: free(buffer2);
982: }
983:
984: /*
985: * Dump the file.
986: */
987: if (rpm2htmlVerbose > 1) {
988: printf("Dumping %s\n", file);
989: }
990: output = fopen(file, "w");
991: if (output == NULL) {
992: fprintf(stderr, "couldn't open %s for writing !\n", file);
993: return;
994: }
995: if (fwrite(buffer, size, 1, output) != 1) {
996: fprintf(stderr, "Problem writing to %s !\n", file);
997: }
998: fclose(output);
999: }
1.26 daniel 1000:
1001: /*
1002: * Dump the distribs/metadata.rdf file listing all the recognized
1003: * metadata mirrors sites.
1004: */
1005:
1006: void dumpMetadataListRdf(void) {
1007: char file[1000];
1008: rdfSchema rdf;
1009: rdfNamespace rpmNs;
1010: rdfDescription desc;
1011: struct stat stat_buf;
1012: int stat_res;
1013: char *base;
1014: char *buffer;
1015: int size;
1016: FILE *output;
1017: int i;
1018:
1019: if (!rpm2html_dump_rdf_resources) return;
1020:
1021: if (rpm2html_rdf_resources_dir != NULL) base = rpm2html_rdf_resources_dir;
1022: else return;
1023:
1024: sprintf(file, "%s/distribs", base);
1025: createDirectory(file);
1026: sprintf(file, "%s/distribs/metadata.rdf", base);
1027:
1028: /*
1029: * build the RDF document tree, one only dump the minimum needed
1030: * for searching distributions informations.
1031: */
1032: rdf = rdfNewSchema();
1033: rpmNs = rdfNewNamespace(rdf, "http://www.rpm.org/", "RPM");
1034:
1035: for (i = 0;i < nb_metadata_mirrors;i++){
1036: desc = rdfAddDescription(rdf, NULL, metadata_mirrors[i]);
1037: rdfSetValue(desc, "URI", rpmNs, metadata_mirrors[i]);
1038: }
1039:
1040: /*
1041: * Dump the RDF tree, and cleanup.
1042: */
1043: rdfWriteMemory(rdf, &buffer, &size);
1044: rdfDestroySchema(rdf);
1045:
1046: /*
1047: * if the file already exists avoid to overwrite it if the content
1048: * didn't change.
1049: */
1050: stat_res = stat(file, &stat_buf);
1051:
1052: if ((stat_res == 0) && (stat_buf.st_size == size)) {
1053: char *buffer2 = malloc(size * sizeof(char));
1054:
1055: if (buffer2 == NULL) {
1056: fprintf(stderr, " : running out of memory\n");
1057: return;
1058: }
1059: output = fopen(file, "r");
1060: if (output == NULL) {
1061: fprintf(stderr, "couldn't open %s for reading !\n", file);
1062: return;
1063: }
1064: if (fread(buffer2, size, 1, output) != 1) {
1065: fprintf(stderr, "Problem reading from %s !\n", file);
1066: }
1067: fclose(output);
1068:
1069: /*
1070: * Now compare the content !
1071: */
1072: if (!memcmp(buffer, buffer2, size)) {
1073: free(buffer2);
1074: if (rpm2htmlVerbose > 1)
1075: fprintf(stderr, "File %s : Content identical !\n", file);
1076: return;
1077: }
1078: free(buffer2);
1079: }
1080:
1081: /*
1082: * Dump the file.
1083: */
1084: if (rpm2htmlVerbose > 1) {
1085: printf("Dumping %s\n", file);
1086: }
1087: output = fopen(file, "w");
1088: if (output == NULL) {
1089: fprintf(stderr, "couldn't open %s for writing !\n", file);
1090: return;
1091: }
1092: if (fwrite(buffer, size, 1, output) != 1) {
1093: fprintf(stderr, "Problem writing to %s !\n", file);
1094: }
1095: fclose(output);
1096: }
1097:
1.25 veillard 1098: /*
1099: * Dump the distribs/list.rdf file listing all the recognized distributions
1.26 daniel 1100: * as well as the metadata mirrors list.
1.25 veillard 1101: */
1102:
1103: void dumpDistListRdf(void) {
1104: rpmDirPtr dir;
1105: char file[1000];
1106: rdfSchema rdf;
1107: rdfNamespace rpmNs;
1108: rdfDescription desc;
1109: struct stat stat_buf;
1110: int stat_res;
1111: char *base;
1112: char *buffer;
1113: int size;
1114: FILE *output;
1115:
1116: if (!rpm2html_dump_rdf_resources) return;
1117:
1118: if (rpm2html_rdf_resources_dir != NULL) base = rpm2html_rdf_resources_dir;
1119: else return;
1120:
1.26 daniel 1121: dumpMetadataListRdf();
1122:
1.25 veillard 1123: sprintf(file, "%s/distribs", base);
1124: createDirectory(file);
1125: sprintf(file, "%s/distribs/list.rdf", base);
1126:
1127: /*
1128: * build the RDF document tree, one only dump the minimum needed
1129: * for searching distributions informations.
1130: */
1131: rdf = rdfNewSchema();
1132: rpmNs = rdfNewNamespace(rdf, "http://www.rpm.org/", "RPM");
1133:
1134: dir = dirList;
1135: while (dir != NULL) {
1136: desc = rdfAddDescription(rdf, NULL, dir->ftp);
1137: rdfSetValue(desc, "ID", rpmNs, dir->subdir);
1138: dumpDistRdf(dir);
1139: dir = dir->next;
1140: }
1141: /*
1142: * Dump the RDF tree, and cleanup.
1143: */
1144: rdfWriteMemory(rdf, &buffer, &size);
1145: rdfDestroySchema(rdf);
1146:
1147: /*
1148: * if the file already exists avoid to overwrite it if the content
1149: * didn't change.
1150: */
1151: stat_res = stat(file, &stat_buf);
1152:
1153: if ((stat_res == 0) && (stat_buf.st_size == size)) {
1154: char *buffer2 = malloc(size * sizeof(char));
1155:
1156: if (buffer2 == NULL) {
1157: fprintf(stderr, " : running out of memory\n");
1158: return;
1159: }
1160: output = fopen(file, "r");
1161: if (output == NULL) {
1162: fprintf(stderr, "couldn't open %s for reading !\n", file);
1163: return;
1164: }
1165: if (fread(buffer2, size, 1, output) != 1) {
1166: fprintf(stderr, "Problem reading from %s !\n", file);
1167: }
1168: fclose(output);
1169:
1170: /*
1171: * Now compare the content !
1172: */
1173: if (!memcmp(buffer, buffer2, size)) {
1174: free(buffer2);
1175: if (rpm2htmlVerbose > 1)
1176: fprintf(stderr, "File %s : Content identical !\n", file);
1177: return;
1178: }
1179: free(buffer2);
1180: }
1181:
1182: /*
1183: * Dump the file.
1184: */
1185: if (rpm2htmlVerbose > 1) {
1186: printf("Dumping %s\n", file);
1187: }
1188: output = fopen(file, "w");
1189: if (output == NULL) {
1190: fprintf(stderr, "couldn't open %s for writing !\n", file);
1191: return;
1192: }
1193: if (fwrite(buffer, size, 1, output) != 1) {
1194: fprintf(stderr, "Problem writing to %s !\n", file);
1195: }
1196: fclose(output);
1197: }
1.26 daniel 1198:
Webmaster