00001
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <config.h>
00037
00038 #include <assert.h>
00039
00040 #include <expat.h>
00041
00042 #include <discover.h>
00043 #include <discover-conf.h>
00044 #include <discover-xml.h>
00045
00046 #include "load-url.h"
00047 #include "url-xml.h"
00048 #include "utils.h"
00049
00050
00051
00052 static discover_bus_map_t bus_map[] = {
00053 { "ata", 0, 0, NULL },
00054 { "pci", 0, 0, NULL },
00055 { "pcmcia", 0, 0, NULL },
00056 { "scsi", 0, 0, NULL },
00057 { "usb", 0, 0, NULL },
00058 { NULL }
00059 };
00060
00061 static char * filetype_map[] = {
00062 "vendor", "busclass", "device"
00063 };
00064
00065 static int conf_loaded = 0;
00066
00067 static discover_xml_url_t *pre_urls = NULL;
00068 static discover_xml_url_t *post_urls = NULL;
00069 static discover_xml_url_t *urls = NULL;
00070
00072 enum state { START, BUSSCAN, DATA_SOURCES };
00073
00075 enum scan_flag { SCAN_NEVER, SCAN_DEFAULT };
00076
00077 struct context {
00078 enum state state;
00079 enum scan_flag scan;
00080 discover_error_t *status;
00081
00082 int unknown_level;
00083 };
00084
00085 static char *known_conf_elements[] = {
00086 "bus",
00087 "data-source",
00088 "busscan",
00089 "data-sources",
00090 "conffile",
00091 NULL
00092 };
00093
00094
00095 static bool
00096 unknown_conf_element(const XML_Char * const tag)
00097 {
00098 int i;
00099 for (i = 0; known_conf_elements[i] != NULL; i++) {
00100 if (strcmp(tag, known_conf_elements[i]) == 0)
00101 return false;
00102 }
00103 return true;
00104 }
00105
00106 static enum scan_flag
00107 get_scan_flag(const XML_Char *attrs[])
00108 {
00109 int i;
00110 char *scan;
00111
00112 assert(attrs != NULL);
00113
00114 scan = NULL;
00115 for (i = 0; attrs[i]; i+= 2) {
00116 if (strcmp(attrs[i], "scan") == 0) {
00117 scan = (char *)attrs[i + 1];
00118 }
00119 }
00120
00121 assert(scan != NULL);
00122
00123 if (strcmp(scan, "default") == 0) {
00124 return SCAN_DEFAULT;
00125 } else {
00126 return SCAN_NEVER;
00127 }
00128 }
00129
00135 discover_bus_map_t *
00136 _real_discover_conf_get_bus_map(discover_bus_t bus, discover_error_t *status)
00137 {
00138 assert(status != NULL);
00139 assert(bus >= 0);
00140
00141 if (bus >= BUS_COUNT) {
00142 status->code = DISCOVER_EBUSNOTFOUND;
00143 }
00144
00145 return (discover_bus_map_t *)(bus_map + bus);
00146 }
00147
00149 discover_bus_map_t *
00150 _real_discover_conf_get_bus_map_by_name(char *name, discover_error_t *status)
00151 {
00152 discover_bus_t bus;
00153
00154 assert(status != NULL);
00155
00156 bus = discover_conf_name_to_bus(name, status);
00157
00158 if (status->code != 0) {
00159 return NULL;
00160 }
00161
00162 return _real_discover_conf_get_bus_map(bus, status);
00163 }
00164
00165 static void
00166 _real_discover_conf_append_url(char *url, discover_error_t *status)
00167 {
00168 discover_xml_url_t *new;
00169
00170 assert(url != NULL);
00171 assert(status != NULL);
00172
00173 status->code = 0;
00174
00175 new = discover_xml_url_new();
00176 new->url = _discover_xstrdup(url);
00177
00178 if (post_urls) {
00179 if (post_urls->last) {
00180 post_urls->last->next = new;
00181 } else {
00182 post_urls->next = new;
00183 }
00184 post_urls->last = new;
00185 } else {
00186 post_urls = new;
00187 post_urls->next = NULL;
00188 post_urls->last = NULL;
00189 }
00190 }
00191
00192 static void
00193 start_element(void *ctx, const XML_Char *name, const XML_Char *attrs[])
00194 {
00195 struct context *context = ctx;
00196 discover_bus_map_t *busmap;
00197 discover_error_t *status;
00198 char *busname;
00199 int i;
00200
00201 assert(context != NULL);
00202 assert(name != NULL);
00203
00204 if (unknown_conf_element(name)) {
00205 context->unknown_level++;
00206 return;
00207 }
00208
00209 if (context->unknown_level > 0) {
00210 return;
00211 }
00212
00213 status = context->status;
00214
00215 switch (context->state) {
00216 case START:
00217 if (strcmp(name, "busscan") == 0) {
00218 context->state = BUSSCAN;
00219 context->scan = get_scan_flag(attrs);
00220 } else if (strcmp(name, "data-sources") == 0) {
00221 context->state = DATA_SOURCES;
00222 }
00223 break;
00224
00225 case BUSSCAN:
00226 if (strcmp(name, "bus") == 0) {
00227 assert(attrs != NULL);
00228
00229 for (i = 0; attrs[i]; i += 2) {
00230 if (strcmp(attrs[i], "name") == 0) {
00231 busname = (char *)attrs[i + 1];
00232 busmap = _real_discover_conf_get_bus_map_by_name(busname, status);
00233 if (status->code != 0) {
00234 return;
00235 }
00236 if (context->scan == SCAN_DEFAULT) {
00237 busmap->scan_default = 1;
00238 } else {
00239 busmap->scan_never = 1;
00240 }
00241 }
00242 }
00243 }
00244 break;
00245
00246 case DATA_SOURCES:
00247 if (strcmp(name, "data-source") == 0) {
00248 for (i = 0; attrs[i]; i += 2) {
00249 if (strcmp(attrs[i], "url") == 0) {
00250 _real_discover_conf_append_url((char *)attrs[i + 1],
00251 status);
00252 if (status->code != 0) {
00253 return;
00254 }
00255 }
00256 }
00257 }
00258 break;
00259 }
00260 }
00261
00262 static void
00263 end_element(void *ctx, const XML_Char *name)
00264 {
00265 struct context *context = ctx;
00266
00267 assert(context != NULL);
00268 assert(name != NULL);
00269
00270 if (unknown_conf_element(name)) {
00271 context->unknown_level--;
00272 return;
00273 }
00274
00275 if (context->unknown_level > 0) {
00276 return;
00277 }
00278
00279 switch (context->state) {
00280 case START:
00281 break;
00282
00283 case BUSSCAN:
00284 if (strcmp(name, "busscan") == 0) {
00285 context->state = START;
00286 }
00287 break;
00288
00289 case DATA_SOURCES:
00290 if (strcmp(name, "data-sources") == 0) {
00291 context->state = START;
00292 }
00293 break;
00294 }
00295 }
00296
00318 void
00319 discover_conf_load(discover_error_t *status)
00320 {
00321 XML_Parser parser;
00322 struct context context;
00323 int load_url_status;
00324
00325 assert(status != NULL);
00326
00327 status->code = 0;
00328
00329 if (conf_loaded) {
00330 return;
00331 }
00332
00333 context.state = START;
00334 context.status = status;
00335 context.unknown_level = 0;
00336
00337 parser = XML_ParserCreate(NULL);
00338 XML_SetElementHandler(parser, start_element, end_element);
00339 XML_SetUserData(parser, &context);
00340
00341 load_url_status = _discover_load_url("file:///" SYSCONFDIR "/discover.conf",
00342 parser);
00343
00344
00345 if (status->code != 0) {
00346 char *message = _discover_xmalloc(256);
00347 snprintf(message, 256, "Error parsing configuration file %s",
00348 "file:///" SYSCONFDIR "/discover.conf");
00349 status->create_message(&status, message);
00350 XML_ParserFree(parser);
00351 return;
00352 }
00353
00354
00355 if (!load_url_status) {
00356 char *message = _discover_xmalloc(256);
00357 snprintf(message, 256, "Failed loading configuration file %s",
00358 "file:///" SYSCONFDIR "/discover.conf");
00359 status->create_message(&status, message);
00360 XML_ParserFree(parser);
00361 conf_loaded = 1;
00362
00363 return;
00364 }
00365
00366 if (!XML_Parse(parser, "", 0, 1)) {
00367 char *message = _discover_xmalloc(256);
00368 snprintf(message, 256, "Error parsing configuration file %s",
00369 "file:///" SYSCONFDIR "/discover.conf");
00370 status->create_message(&status, message);
00371 status->code = DISCOVER_EXML;
00372 XML_ParserFree(parser);
00373 return;
00374 }
00375
00376 XML_ParserFree(parser);
00377
00378 conf_loaded = 1;
00379
00380 return;
00381 }
00382
00389 int
00390 discover_conf_name_to_bus(char *name, discover_error_t *status)
00391 {
00392 int i;
00393 for (i = 0; bus_map[i].name; i++) {
00394 if (strcmp(bus_map[i].name, name) == 0) {
00395 return i;
00396 }
00397 }
00398
00399 status->code = DISCOVER_EBUSNOTFOUND;
00400 return -1;
00401 }
00402
00408 discover_bus_map_t *
00409 discover_conf_get_full_bus_map(discover_error_t *status)
00410 {
00411 discover_conf_load(status);
00412 return bus_map;
00413 }
00414
00421 discover_bus_map_t *
00422 discover_conf_get_bus_map_by_name(char *name, discover_error_t *status)
00423 {
00424 assert(status != NULL);
00425
00426 discover_conf_load(status);
00427 if (status->code != 0) {
00428 return NULL;
00429 }
00430
00431
00432
00433
00434
00435 return _real_discover_conf_get_bus_map_by_name(name, status);
00436 }
00437
00444 discover_bus_map_t *
00445 discover_conf_get_bus_map(discover_bus_t bus, discover_error_t *status)
00446 {
00447 assert(status != NULL);
00448 assert(bus >= 0);
00449
00450 if (bus >= BUS_COUNT) {
00451 status->code = DISCOVER_EBUSNOTFOUND;
00452 }
00453
00454 discover_conf_load(status);
00455 if (status->code != 0) {
00456 return NULL;
00457 }
00458
00459 return (discover_bus_map_t *)(bus_map + bus);
00460 }
00461
00469 void
00470 discover_conf_insert_url(char *url, discover_error_t *status)
00471 {
00472 discover_xml_url_t *new;
00473
00474 assert(url != NULL);
00475 assert(status != NULL);
00476
00477 status->code = 0;
00478
00479 discover_conf_load(status);
00480 if (status->code != 0) {
00481 return;
00482 }
00483
00484 new = discover_xml_url_new();
00485 new->url = _discover_xstrdup(url);
00486
00487 new->next = pre_urls;
00488 if (pre_urls) {
00489 if (pre_urls->last) {
00490 new->last = pre_urls->last;
00491 } else {
00492 new->last = pre_urls;
00493 }
00494 } else {
00495 new->last = NULL;
00496 }
00497
00498 pre_urls = new;
00499 }
00500
00508 void
00509 discover_conf_append_url(char *url, discover_error_t *status)
00510 {
00511 assert(status != NULL);
00512
00513 discover_conf_load(status);
00514 if (status->code != 0) {
00515 return;
00516 }
00517
00518 _real_discover_conf_append_url(url, status);
00519
00520 return;
00521 }
00522
00528 discover_xml_url_t *
00529 discover_conf_get_urls(discover_error_t *status)
00530 {
00531 discover_xml_url_t *new;
00532
00533 assert(status != NULL);
00534
00535 status->code = 0;
00536
00537 if (!urls) {
00538 discover_conf_load(status);
00539
00540 new = discover_xml_url_new();
00541 new->url = _discover_xstrdup(DISCOVER_DEFAULT_URL);
00542
00543 if (pre_urls) {
00544 urls = pre_urls;
00545 if (urls->last) {
00546 urls->last->next = new;
00547 } else {
00548 urls->next = new;
00549 }
00550 urls->last = new;
00551 } else {
00552 urls = new;
00553 }
00554
00555 if (post_urls) {
00556 if (urls->last) {
00557 urls->last->next = post_urls;
00558 } else {
00559 urls->next = post_urls;
00560 }
00561
00562 if (post_urls->last) {
00563 urls->last = post_urls->last;
00564 } else {
00565 urls->last = post_urls;
00566 }
00567 }
00568
00569 post_urls = pre_urls = NULL;
00570 }
00571
00572 return urls;
00573 }
00574
00579 void
00580 discover_conf_free(void)
00581 {
00582 conf_loaded = 0;
00583
00584 if (urls) {
00585 discover_xml_url_free(urls);
00586 urls = NULL;
00587 }
00588 }
00589
00595 char *
00596 discover_conf_get_bus_name(discover_bus_t bus)
00597 {
00598 assert(bus >= 0);
00599 if (bus >= BUS_COUNT) {
00600 return NULL;
00601 }
00602
00603 return bus_map[bus].name;
00604 }
00605
00611 char *
00612 discover_conf_get_filetype_name(discover_filetype_t filetype)
00613 {
00614 if (filetype >= 3) {
00615 return NULL;
00616 }
00617
00618 return filetype_map[filetype];
00619 }
00620
00623
00624
00625
00626
00627
00628
00629