# busclass-xml.c

Go to the documentation of this file.

    00001
    00010 /* $Progeny$
    00011  *
    00012  * AUTHOR: John R. Daily <jdaily@progeny.com>
    00013  *
    00014  * Copyright 2002 Progeny Linux Systems, Inc.
    00015  * Copyright 2002 Hewlett-Packard Company
    00016  *
    00017  * Permission is hereby granted, free of charge, to any person obtaining a
    00018  * copy of this software and associated documentation files (the "Software"),
    00019  * to deal in the Software without restriction, including without limitation
    00020  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
    00021  * and/or sell copies of the Software, and to permit persons to whom the
    00022  * Software is furnished to do so, subject to the following conditions:
    00023  *
    00024  * The above copyright notice and this permission notice shall be included in
    00025  * all copies or substantial portions of the Software.
    00026  *
    00027  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    00028  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    00029  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
    00030  * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    00031  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    00032  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    00033  * DEALINGS IN THE SOFTWARE.
    00034  */
    00035
    00036 #include "config.h"
    00037
    00038 #include <sys/types.h>
    00039
    00040 #include <assert.h>
    00041 #include <limits.h>
    00042 #include <stdio.h>
    00043 #include <string.h>
    00044
    00045 #include <expat.h>
    00046
    00047 #include <discover/discover.h>
    00048 #include <discover/discover-xml.h>
    00049
    00050 #include <discover/load-url.h>
    00051 #include <discover/utils.h>
    00052
    00054 struct discover_xml_busclass {
    00055     char *id;
    00056     char *name;
    00057     discover_xml_busclass_t *next;
    00058 };
    00059
    00060 static discover_xml_busclass_t *busclasses[BUS_COUNT];
    00061
    00062 struct context {
    00063     discover_xml_busclass_t **blist;
    00064
    00065     int unknown_level; /* How deep are we into unknown XML tags? */
    00066 };
    00067
    00068 static char *known_bus_elements[] = {
    00069     "busclass",
    00070     "busclass_list",
    00071     NULL
    00072 };
    00073
    00074 static bool
    00075 unknown_bus_element(const XML_Char * const tag)
    00076 {
    00077     int i;
    00078     for (i = 0; known_bus_elements[i] != NULL; i++) {
    00079         if (strcmp(tag, known_bus_elements[i]) == 0)
    00080             return false;
    00081     }
    00082     return true;
    00083 }
    00084
    00085 static void
    00086 start_element(void *ctx, const XML_Char *name, const XML_Char *attrs[])
    00087 {
    00088     struct context *context = ctx;
    00089     int i;
    00090     char *vid, *vname;
    00091     discover_xml_busclass_t *next, **blist;
    00092
    00093     assert(context != NULL);
    00094     assert(name != NULL);
    00095     assert(attrs != NULL);
    00096
    00097     if (unknown_bus_element(name)) {
    00098         context->unknown_level++;
    00099         return;
    00100     }
    00101
    00102     if (context->unknown_level > 0) {
    00103         return;
    00104     }
    00105
    00106     if (strcmp(name, "busclass") == 0) {
    00107         vid = vname = NULL;
    00108         for (i = 0; attrs[i]; i += 2) {
    00109             if (strcmp(attrs[i], "id") == 0) {
    00110                 vid = (char *) attrs[i + 1];
    00111             } else if (strcmp(attrs[i], "name") == 0) {
    00112                 vname = (char *) attrs[i + 1];
    00113             }
    00114         }
    00115
    00116         assert(vid != NULL);
    00117         assert(vname != NULL);
    00118
    00119         blist = context->blist;
    00120         next = *blist;
    00121         *blist = discover_xml_busclass_new();
    00122         (*blist)->id = _discover_xstrdup(vid);
    00123         (*blist)->name = _discover_xstrdup(vname);
    00124         (*blist)->next = next;
    00125     }
    00126 }
    00127
    00128 static void
    00129 end_element(void *ctx, const XML_Char *name)
    00130 {
    00131     struct context *context = ctx;
    00132
    00133     assert(context != NULL);
    00134     assert(name != NULL);
    00135
    00136     if (unknown_bus_element(name)) {
    00137         context->unknown_level--;
    00138         return;
    00139     }
    00140
    00141     if (context->unknown_level > 0) {
    00142         return;
    00143     }
    00144
    00145     /*
    00146      * We don't have any end tags to worry about, but if we did, they
    00147      * would be handled here.
    00148      */
    00149 }
    00150
    00151
    00164 /* Sshh!  Don't tell, but this doesn't actually do any merging at all.
    00165  * Instead, it simply inserts newer entries at the front of the list,
    00166  * meaning that busclass info found later supersedes info found earlier.
    00167  * This gives the illusion of merging, but potentially wastes memory
    00168  * with duplicates.
    00169  */
    00170 void
    00171 discover_xml_merge_busclass_url(discover_xml_busclass_t **blist,
    00172                                 char *url, discover_error_t *status)
    00173 {
    00174     XML_Parser parser;
    00175     struct context context;
    00176
    00177     assert(url != NULL);
    00178     assert(status != NULL);
    00179
    00180     status->code = 0;
    00181
    00182     context.blist = blist;
    00183     context.unknown_level = 0;
    00184
    00185     parser = XML_ParserCreate(NULL);
    00186     XML_SetElementHandler(parser, start_element, end_element);
    00187     XML_SetUserData(parser, &context);
    00188
    00189     if (!_discover_load_url(url, parser)) {
    00190         XML_ParserFree(parser);
    00191         status->code = DISCOVER_EIO;
    00192         return;
    00193     }
    00194
    00195     if (!XML_Parse(parser, "", 0, 1)) {
    00196         XML_ParserFree(parser);
    00197         status->code = DISCOVER_EXML;
    00198         return;
    00199     }
    00200
    00201     XML_ParserFree(parser);
    00202
    00203     return;
    00204 }
    00205
    00212 discover_xml_busclass_t *
    00213 discover_xml_get_busclasses(discover_bus_t bus, discover_error_t *status)
    00214 {
    00215     discover_xml_url_t *urls, *i;
    00216     char *url;
    00217
    00218     assert(status != NULL);
    00219
    00220     status->code = 0;
    00221
    00222     if (!busclasses[bus]) {
    00223         urls = discover_xml_get_data_urls(bus, BUSCLASS_TYPE, status);
    00224         if (status->code != 0) {
    00225             return NULL;
    00226         }
    00227
    00228         for (i = urls;
    00229              i;
    00230              i = discover_xml_url_get_next(i)) {
    00231             url = discover_xml_url_get_url(i);
    00232             discover_xml_merge_busclass_url(&(busclasses[bus]), url, status);
    00233             if (status->code != 0) {
    00234                 return NULL;
    00235             }
    00236         }
    00237     }
    00238
    00239     return busclasses[bus];
    00240 }
    00241
    00242
    00246 void
    00247 discover_xml_free_busclasses(void)
    00248 {
    00249     int i;
    00250     for (i = 0; i < BUS_COUNT; i++) {
    00251         discover_xml_busclass_free(busclasses[i]);
    00252         busclasses[i] = NULL;
    00253     }
    00254 }
    00255
    00262 char *
    00263 discover_xml_busclass_to_class(char *busclass,
    00264                                discover_xml_busclass_t *busclasses)
    00265 {
    00266     char *result;
    00267
    00268     assert(busclass != NULL);
    00269     assert(busclasses != NULL);
    00270
    00271     result = NULL;
    00272
    00273     for (;
    00274          busclasses;
    00275          busclasses = busclasses->next) {
    00276         if (strcmp(busclass, busclasses->id) == 0) {
    00277             result = busclasses->name;
    00278             break;
    00279         }
    00280     }
    00281
    00282     return result;
    00283 }
    00284
    00294 int
    00295 discover_xml_busclass_cmp(char *busclass, char *discover_class,
    00296                           discover_xml_busclass_t *busclasses)
    00297 {
    00298     char *found_class_name = NULL;
    00299
    00300     assert(busclass != NULL);
    00301     assert(discover_class != NULL);
    00302     assert(busclasses != NULL);
    00303
    00304     if (strcmp(discover_class, "all") == 0) {
    00305         return 0;
    00306     }
    00307
    00308     found_class_name = discover_xml_busclass_to_class(busclass, busclasses);
    00309
    00310     /*
    00311      * If the busclass database doesn't know about this device class, we
    00312      * can't make any valid comparison.
    00313      */
    00314     if (found_class_name == NULL) {
    00315         return -1;
    00316     }
    00317
    00318     return strcmp(found_class_name, discover_class);
    00319 }
    00320
    00326 char *
    00327 discover_xml_busclass_get_id(discover_xml_busclass_t *busclass)
    00328 {
    00329     assert(busclass != NULL);
    00330
    00331     return busclass->id;
    00332 }
    00333
    00339 char *
    00340 discover_xml_busclass_get_name(discover_xml_busclass_t *busclass)
    00341 {
    00342     assert(busclass != NULL);
    00343
    00344     return busclass->name;
    00345 }
    00346
    00351 discover_xml_busclass_t *
    00352 discover_xml_busclass_get_next(discover_xml_busclass_t *busclass)
    00353 {
    00354     assert(busclass != NULL);
    00355
    00356     return busclass->next;
    00357 }
    00358
    00362 discover_xml_busclass_t *
    00363 discover_xml_busclass_new(void)
    00364 {
    00365     discover_xml_busclass_t *new;
    00366
    00367     new = _discover_xmalloc(sizeof(discover_xml_busclass_t));
    00368
    00369     new->id = NULL;
    00370     new->name = NULL;
    00371     new->next = NULL;
    00372
    00373     return new;
    00374 }
    00375
    00381 void
    00382 discover_xml_busclass_free(discover_xml_busclass_t *busclasses)
    00383 {
    00384     discover_xml_busclass_t *busclass, *last;
    00385
    00386     last = NULL;
    00387
    00388     for (busclass = busclasses;
    00389          busclass;
    00390          busclass = busclass->next) {
    00391         if (busclass->id) {
    00392             free(busclass->id);
    00393         }
    00394
    00395         if (busclass->name) {
    00396             free(busclass->name);
    00397         }
    00398
    00399         if (last) {
    00400             free(last);
    00401         }
    00402         last = busclass;
    00403     }
    00404
    00405     if (last) {
    00406         free(last);
    00407     }
    00408 }
    00409
    00412 /*
    00413  * Local variables:
    00414  * c-file-style: "progeny"
    00415  * indent-tabs-mode: nil
    00416  * End:
    00417  */
    00418 /* vim: set cin fo=tcroq sw=4 et sts=4 tw=75: */