Annotation of rpm2html/rdf.c, revision 1.11

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

Webmaster