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