Annotation of rpm2html/rdf.c, revision 1.47

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

Webmaster