Annotation of rpm2html/rdf.c, revision 1.8

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);
                    206:        i = 0;
                    207:        while (elem != NULL) {
                    208:            if (i >= MAX_RES) {
                    209:                fprintf(stderr, "MAX_RES %d overflow, increase the limit!\n",
                    210:                        MAX_RES);
                    211:                break;
                    212:            }
                    213:            /*
                    214:             * Check that we are scanning an RPM Resource.
                    215:             */
                    216:            if ((!strcmp(rdfElemGetPropertyName(elem), "Resource")) &&
                    217:                (rdfElemGetNamespace(elem) == rpmNs)) {
                    218:                value = rdfElemGetValue(elem);
                    219:                if (value != NULL) {
                    220:                    rpm->resources[i] = rpmRessAdd(value, rpm, 0);
                    221:                    i++;
                    222:                    rpm->nb_resources++;
1.8     ! veillard  223:                } else if (verbose > 1) {
1.7       veillard  224:                    fprintf(stderr, "%s : malformed Resource element !\n", file);
                    225:                }
1.8     ! veillard  226:            } else if (verbose > 1) {
1.7       veillard  227:                fprintf(stderr, "%s : malformed Provides bag !\n", file);
                    228:            }
                    229:            elem = rdfNextElem(elem);
                    230:        }
1.8     ! veillard  231:     } else if (verbose > 1) {
1.7       veillard  232:         fprintf(stderr, "%s doesn't export any resource\n", file);
                    233:     }
                    234: 
                    235:     /*
                    236:      * idem for the dependencies.
                    237:      */
                    238:     rpm->nb_requires = 0;
                    239:     rdfGetValue(desc, "Requires", rpmNs, NULL, &bag);
                    240:     if (bag != NULL) {
                    241:         elem = rdfFirstChild(bag);
                    242:        i = 0;
                    243:        while (elem != NULL) {
                    244:            if (i >= MAX_REQU) {
                    245:                fprintf(stderr, "MAX_RES %d overflow, increase the limit!\n",
                    246:                        MAX_REQU);
                    247:                break;
                    248:            }
                    249:            /*
                    250:             * Check that we are scanning an RPM Resource.
                    251:             */
                    252:            if ((!strcmp(rdfElemGetPropertyName(elem), "Resource")) &&
                    253:                (rdfElemGetNamespace(elem) == rpmNs)) {
                    254:                value = rdfElemGetValue(elem);
                    255:                if (value != NULL) {
                    256:                    rpm->requires[i] = rpmRequAdd(value, rpm, 0);
                    257:                    i++;
                    258:                    rpm->nb_requires++;
1.8     ! veillard  259:                } else if (verbose > 1) {
1.7       veillard  260:                    fprintf(stderr, "%s : malformed Resource element !\n", file);
                    261:                }
1.8     ! veillard  262:            } else if (verbose > 1) {
1.7       veillard  263:                fprintf(stderr, "%s : malformed Provides bag !\n", file);
                    264:            }
                    265:            elem = rdfNextElem(elem);
                    266:        }
                    267:     }
1.5       veillard  268: 
1.6       veillard  269:     /*
                    270:      * Finish filling the rpmData structure.
                    271:      */
                    272: #ifdef HAVE_SNPRINTF
                    273:     sprintf(nameBuffer, "%s-%s-%s.rpm",
                    274:             rpm->name, rpm->version, rpm->release);
                    275: #else
                    276:     snprintf(nameBuffer, 200, "%s-%s-%s.rpm",
                    277:              rpm->name, rpm->version, rpm->release);
                    278: #endif
                    279:     rpm->filename = strdup(nameBuffer);
                    280: 
                    281:     /* Add the package files to the real filesystem tree if asked for */
                    282:     if ((dir->build_tree != 0) && (rpm->filelist != NULL)) {
                    283:         char *cur, *filename;
                    284:        
                    285:        cur = rpm->filelist;
                    286:        while ((*cur != '\0') && (*cur != '/')) cur++;
                    287:        filename = cur;
                    288:        while (*cur != '\0') {
                    289:            if ((*cur == '\n') || (*cur == '\r')) {
                    290:                if (cur != filename)
                    291:                    rpmAddRealFile(dir->root, filename, rpm);
                    292:                while ((*cur != '\0') && (*cur != '/')) cur++;
                    293:                 filename = cur;
                    294:            } else
                    295:                cur++;
                    296:        }
                    297:        if (cur != filename)
                    298:            rpmAddRealFile(dir->root, filename, rpm);
                    299:     }
                    300: 
                    301:     /* Register this package */
                    302:     rpmAddSoftware(rpm);
                    303: 
                    304:     /* dump the HTML related to this package */
                    305:     if (rpm2html_dump_html)
                    306:        dumpRpmHtml(rpm, tree);
                    307:     if (rpm2html_dump_rdf)
                    308:        dumpRpmRdf(rpm, tree);
                    309: 
                    310:     /* free large amount of data not used later */
                    311:     if (rpm->filelist) free(rpm->filelist);
                    312:     rpm->filelist = NULL;
                    313:     if (rpm->copyright) free(rpm->copyright);
                    314:     rpm->copyright = NULL;
                    315:     if (rpm->changelog) free(rpm->changelog);
                    316:     rpm->changelog = NULL;
                    317:     if (rpm->description) free(rpm->description);
                    318:     rpm->description = NULL;
                    319: 
                    320:     /* increment the counters */
                    321:     rpm2html_files++;
                    322:     rpm2html_size += rpm->size / 1024;
                    323: 
                    324:     /*
                    325:      * Cleanup.
                    326:      */
1.5       veillard  327:     rdfDestroySchema(rdf);
                    328:     return(rpm);
1.1       httpng    329: }
                    330: 
                    331: /*
1.4       veillard  332:  * Create and RDF file containing the description for the given RPM data.
1.1       httpng    333:  */
                    334: void dumpRpmRdf(rpmDataPtr rpm, rpmSubdirPtr tree) {
                    335:     struct tm * tstruct;
                    336:     rpmDirPtr dir = rpm->dir;
1.3       veillard  337:     char *base = dir->dir;
1.1       httpng    338:     int i;
1.4       veillard  339:     char buf[10000];
                    340:     char file[1000];
                    341:     rdfSchema rdf;
                    342:     rdfNamespace rpmNs;
                    343:     rdfDescription desc;
                    344:     rdfBag bag;
1.1       httpng    345: 
1.7       veillard  346:     if (!rpm2html_dump_rdf) return;
                    347: 
1.3       veillard  348:     if (rpm2html_rdf_dir != NULL) base = rpm2html_rdf_dir;
                    349: 
1.1       httpng    350:     if ((dir->subdir != NULL) && (dir->subdir[0] != '\0')) {
                    351:        if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0'))
1.4       veillard  352:            sprintf(file, "%s/%s/%s/%s.rdf", base, dir->subdir,
1.1       httpng    353:                    rpm->subdir, rpmName(rpm));
                    354:        else
1.4       veillard  355:            sprintf(file, "%s/%s/%s.rdf", base, dir->subdir, rpmName(rpm));
1.1       httpng    356:     } else {
                    357:        if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0'))
1.4       veillard  358:            sprintf(file, "%s/%s/%s.rdf", base, rpm->subdir, rpmName(rpm));
1.1       httpng    359:        else
1.4       veillard  360:            sprintf(file, "%s/%s.rdf", base, rpmName(rpm));
1.1       httpng    361:     }
                    362: 
1.4       veillard  363:     if (checkDate(file, rpm->stamp)) return;
1.1       httpng    364:     if (verbose > 1) {
1.4       veillard  365:         printf("Dumping %s\n", file);
1.1       httpng    366:     }
1.4       veillard  367: 
                    368:     /*
                    369:      * build the RDF document tree
                    370:      * Note : the order is not important but following the rpmData
                    371:      *        structure order is easier to check.
                    372:      */
                    373:     rdf = rdfNewSchema();
                    374:     rpmNs = rdfNewNamespace(rdf, "http://www.rpm.org/", "RPM");
                    375: 
1.2       httpng    376:     if ((rpm->subdir != NULL) && (rpm->subdir[0] != '\0')) {
                    377:        if (dir->mirrors[0] != NULL)
1.4       veillard  378:            sprintf(buf, "%s/%s/%s",
1.2       httpng    379:                dir->mirrors[0], rpm->subdir, rpm->filename);
                    380:        else
1.4       veillard  381:            sprintf(buf, "%s/%s/%s",
1.2       httpng    382:                dir->ftp, rpm->subdir, rpm->filename);
                    383:     } else {
                    384:        if (dir->mirrors[0] != NULL)
1.4       veillard  385:            sprintf(buf, "%s/%s",
1.2       httpng    386:                dir->mirrors[0], rpm->filename);
                    387:        else
1.4       veillard  388:            sprintf(buf, "%s/%s",
1.2       httpng    389:                dir->ftp, rpm->filename);
                    390:     }
1.4       veillard  391:     desc = rdfAddDescription(rdf, NULL, buf);
                    392: 
                    393:     rdfSetValue(desc, "Name", rpmNs, rpm->name);
                    394:     rdfSetValue(desc, "Version", rpmNs, rpm->version);
                    395:     rdfSetValue(desc, "Release", rpmNs, rpm->release);
                    396:     if (rpm->url)
                    397:         rdfSetValue(desc, "URL", rpmNs, rpm->url);
                    398:     if (rpm->arch)
                    399:         rdfSetValue(desc, "Arch", rpmNs, rpm->arch);
                    400:     if (rpm->os)
                    401:         rdfSetValue(desc, "Os", rpmNs, rpm->os);
1.2       httpng    402:     if (rpm->distribution)
1.4       veillard  403:         rdfSetValue(desc, "Distribution", rpmNs, rpm->distribution);
1.2       httpng    404:     if (rpm->vendor)
1.4       veillard  405:         rdfSetValue(desc, "Vendor", rpmNs, rpm->vendor);
                    406:     if (rpm->packager)
                    407:         rdfSetValue(desc, "Packager", rpmNs, rpm->packager);
                    408:     if (rpm->group)
                    409:         rdfSetValue(desc, "Group", rpmNs, rpm->group);
                    410:     if (rpm->summary)
                    411:        rdfSetValue(desc, "Summary", rpmNs, rpm->summary);
                    412:     if (rpm->description)
                    413:        rdfSetValue(desc, "Description", rpmNs, rpm->description);
                    414:     if (rpm->copyright)
                    415:        rdfSetValue(desc, "Copyright", rpmNs, rpm->copyright);
                    416:     if (rpm->changelog)
                    417:         rdfSetValue(desc, "Changelog", rpmNs, rpm->changelog);
                    418:     if (rpm->srcrpm) {
1.7       veillard  419:        rdfSetValue(desc, "Sources", rpmNs, rpm->srcrpm);
1.4       veillard  420:        if (dir->ftpsrc) {
1.7       veillard  421:            rdfSetValue(desc, "SourcesFtp", rpmNs, dir->ftpsrc);
1.4       veillard  422:        }
                    423:     }
1.2       httpng    424:     tstruct = localtime(&(rpm->date));
                    425: #ifdef HAVE_STRFTIME
                    426:     strftime(buf, sizeof(buf) - 1, "%c", tstruct);
                    427: #else
                    428: #error "no strftime, please check !"
                    429: #endif
1.4       veillard  430:     rdfSetValue(desc, "BuildDate", rpmNs, buf);
                    431:     sprintf(buf, "%d", rpm->size);
                    432:     rdfSetValue(desc, "Size", rpmNs, buf);
1.2       httpng    433:     if (rpm->host)
1.4       veillard  434:         rdfSetValue(desc, "BuildHost", rpmNs, rpm->host);
1.2       httpng    435:     if (rpm->nb_resources > 0) {
1.7       veillard  436:        /** !!!!!
                    437:        sprintf(buf, "%d", rpm->nb_resources);
                    438:        rdfSetValue(desc, "NbProvides", rpmNs, buf);
                    439:         */
1.4       veillard  440:        bag = rdfBagCreate(rdf, desc, "Provides", rpmNs);
1.2       httpng    441:         for (i = 0;i < rpm->nb_resources;i++) {
1.4       veillard  442:            rdfBagAddValue(bag, "Resource", rpmNs,
                    443:                           rpm->resources[i]->name, NULL);
1.2       httpng    444:         }
                    445:     }
                    446:     if (rpm->nb_requires > 0) {
1.7       veillard  447:        /** !!!!!
                    448:         sprintf(buf, "%d", rpm->nb_requires);
                    449:        rdfSetValue(desc, "NbRequires", rpmNs, buf);
                    450:         */
1.4       veillard  451:        bag = rdfBagCreate(rdf, desc, "Requires", rpmNs);
1.2       httpng    452:         for (i = 0;i < rpm->nb_requires;i++) {
1.4       veillard  453:            rdfBagAddValue(bag, "Resource", rpmNs,
                    454:                           rpm->requires[i]->name, NULL);
1.2       httpng    455:         }
                    456:     }
                    457:     if (rpm->filelist)
1.4       veillard  458:         rdfSetValue(desc, "Files", rpmNs, rpm->filelist);
                    459: 
                    460:     /*
                    461:      * Save the RDF file and cleanup the tree.
                    462:      */
                    463:     rdfWrite(rdf, file);
                    464:     rdfDestroySchema(rdf);
1.1       httpng    465: }
                    466: 

Webmaster