Annotation of rpm2html/rdf.c, revision 1.19

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

Webmaster