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 #if HAVE_DIRENT_H
00039 #include <dirent.h>
00040 #define NAMLEN(d) strlen((d)->d_name)
00041 #else
00042 #define dirent direct
00043 #define NAMLEN(d) (d)->d_namlen
00044 #if HAVE_SYS_NDIR_H
00045 #include <sys/ndir.h>
00046 #endif
00047 #if HAVE_SYS_DIR_H
00048 #include <sys/dir.h>
00049 #endif
00050 #if HAVE_NDIR_H
00051 #include <ndir.h>
00052 #endif
00053 #endif
00054
00055 #include <assert.h>
00056 #include <string.h>
00057
00058 #include <expat.h>
00059
00060 #include <discover/discover.h>
00061 #include <discover/discover-conf.h>
00062 #include <discover/discover-xml.h>
00063
00064 #include <discover/load-url.h>
00065 #include <discover/url-xml.h>
00066 #include <discover/utils.h>
00067
00068
00069
00070 static discover_bus_map_t bus_map[] = {
00071 { "ata", 0, 0, NULL },
00072 { "pci", 0, 0, NULL },
00073 { "pcmcia", 0, 0, NULL },
00074 { "scsi", 0, 0, NULL },
00075 { "usb", 0, 0, NULL },
00076 { NULL }
00077 };
00078
00079 static char * filetype_map[] = {
00080 "vendor", "busclass", "device"
00081 };
00082
00083 static int conf_loaded = 0;
00084
00085 static discover_xml_url_t *pre_urls = NULL;
00086 static discover_xml_url_t *post_urls = NULL;
00087 static discover_xml_url_t *urls = NULL;
00088
00090 enum state { START, BUSSCAN, DATA_SOURCES };
00091
00093 enum scan_flag { SCAN_NEVER, SCAN_DEFAULT };
00094
00095 struct context {
00096 enum state state;
00097 enum scan_flag scan;
00098 discover_error_t *status;
00099
00100 int unknown_level;
00101 };
00102
00103 static char *known_conf_elements[] = {
00104 "bus",
00105 "data-source",
00106 "busscan",
00107 "data-sources",
00108 "conffile",
00109 NULL
00110 };
00111
00112
00113 static bool
00114 unknown_conf_element(const XML_Char * const tag)
00115 {
00116 int i;
00117 for (i = 0; known_conf_elements[i] != NULL; i++) {
00118 if (strcmp(tag, known_conf_elements[i]) == 0)
00119 return false;
00120 }
00121 return true;
00122 }
00123
00124 static enum scan_flag
00125 get_scan_flag(const XML_Char *attrs[])
00126 {
00127 int i;
00128 char *scan;
00129
00130 assert(attrs != NULL);
00131
00132 scan = NULL;
00133 for (i = 0; attrs[i]; i+= 2) {
00134 if (strcmp(attrs[i], "scan") == 0) {
00135 scan = (char *)attrs[i + 1];
00136 }
00137 }
00138
00139 assert(scan != NULL);
00140
00141 if (strcmp(scan, "default") == 0) {
00142 return SCAN_DEFAULT;
00143 } else {
00144 return SCAN_NEVER;
00145 }
00146 }
00147
00153 discover_bus_map_t *
00154 _real_discover_conf_get_bus_map(discover_bus_t bus, discover_error_t *status)
00155 {
00156 assert(status != NULL);
00157 assert(bus >= 0);
00158
00159 if (bus >= BUS_COUNT) {
00160 status->code = DISCOVER_EBUSNOTFOUND;
00161 }
00162
00163 return (discover_bus_map_t *)(bus_map + bus);
00164 }
00165
00167 discover_bus_map_t *
00168 _real_discover_conf_get_bus_map_by_name(char *name, discover_error_t *status)
00169 {
00170 discover_bus_t bus;
00171
00172 assert(status != NULL);
00173
00174 bus = discover_conf_name_to_bus(name, status);
00175
00176 if (status->code != 0) {
00177 return NULL;
00178 }
00179
00180 return _real_discover_conf_get_bus_map(bus, status);
00181 }
00182
00183 static void
00184 _real_discover_conf_insert_url(char *url, discover_error_t *status)
00185 {
00186 discover_xml_url_t *new;
00187
00188 assert(url != NULL);
00189 assert(status != NULL);
00190
00191 status->code = 0;
00192
00193 new = discover_xml_url_new();
00194 new->url = _discover_xstrdup(url);
00195
00196 new->next = pre_urls;
00197 if (pre_urls) {
00198 if (pre_urls->last) {
00199 new->last = pre_urls->last;
00200 } else {
00201 new->last = pre_urls;
00202 }
00203 } else {
00204 new->last = NULL;
00205 }
00206
00207 pre_urls = new;
00208 }
00209
00210 static void
00211 _real_discover_conf_append_url(char *url, discover_error_t *status)
00212 {
00213 discover_xml_url_t *new;
00214
00215 assert(url != NULL);
00216 assert(status != NULL);
00217
00218 status->code = 0;
00219
00220 new = discover_xml_url_new();
00221 new->url = _discover_xstrdup(url);
00222
00223 if (post_urls) {
00224 if (post_urls->last) {
00225 post_urls->last->next = new;
00226 } else {
00227 post_urls->next = new;
00228 }
00229 post_urls->last = new;
00230 } else {
00231 post_urls = new;
00232 post_urls->next = NULL;
00233 post_urls->last = NULL;
00234 }
00235 }
00236
00237 static void
00238 start_element(void *ctx, const XML_Char *name, const XML_Char *attrs[])
00239 {
00240 struct context *context = ctx;
00241 discover_bus_map_t *busmap;
00242 discover_error_t *status;
00243 char *busname;
00244 char *found_url;
00245 int prepend_url;
00246 int i;
00247
00248 assert(context != NULL);
00249 assert(name != NULL);
00250
00251 if (unknown_conf_element(name)) {
00252 context->unknown_level++;
00253 return;
00254 }
00255
00256 if (context->unknown_level > 0) {
00257 return;
00258 }
00259
00260 status = context->status;
00261
00262 switch (context->state) {
00263 case START:
00264 if (strcmp(name, "busscan") == 0) {
00265 context->state = BUSSCAN;
00266 context->scan = get_scan_flag(attrs);
00267 } else if (strcmp(name, "data-sources") == 0) {
00268 context->state = DATA_SOURCES;
00269 }
00270 break;
00271
00272 case BUSSCAN:
00273 if (strcmp(name, "bus") == 0) {
00274 assert(attrs != NULL);
00275
00276 for (i = 0; attrs[i]; i += 2) {
00277 if (strcmp(attrs[i], "name") == 0) {
00278 busname = (char *)attrs[i + 1];
00279 busmap = _real_discover_conf_get_bus_map_by_name(busname, status);
00280 if (status->code != 0) {
00281 return;
00282 }
00283 if (context->scan == SCAN_DEFAULT) {
00284 busmap->scan_default = 1;
00285 } else {
00286 busmap->scan_never = 1;
00287 }
00288 }
00289 }
00290 }
00291 break;
00292
00293 case DATA_SOURCES:
00294 if (strcmp(name, "data-source") == 0) {
00295 found_url = NULL;
00296 prepend_url = 0;
00297 for (i = 0; attrs[i]; i += 2) {
00298 if (strcmp(attrs[i], "url") == 0) {
00299 found_url = (char *)attrs[i + 1];
00300 }
00301 else if ((strcmp(attrs[i], "place") == 0) &&
00302 (strcmp(attrs[i + 1], "before") == 0)) {
00303 prepend_url = 1;
00304 }
00305 }
00306 if (found_url != NULL) {
00307 if (prepend_url != 0) {
00308 _real_discover_conf_insert_url(found_url, status);
00309 } else {
00310 _real_discover_conf_append_url(found_url, status);
00311 }
00312 if (status->code != 0) {
00313 return;
00314 }
00315 }
00316 }
00317 break;
00318 }
00319 }
00320
00321 static void
00322 end_element(void *ctx, const XML_Char *name)
00323 {
00324 struct context *context = ctx;
00325
00326 assert(context != NULL);
00327 assert(name != NULL);
00328
00329 if (unknown_conf_element(name)) {
00330 context->unknown_level--;
00331 return;
00332 }
00333
00334 if (context->unknown_level > 0) {
00335 return;
00336 }
00337
00338 switch (context->state) {
00339 case START:
00340 break;
00341
00342 case BUSSCAN:
00343 if (strcmp(name, "busscan") == 0) {
00344 context->state = START;
00345 }
00346 break;
00347
00348 case DATA_SOURCES:
00349 if (strcmp(name, "data-sources") == 0) {
00350 context->state = START;
00351 }
00352 break;
00353 }
00354 }
00355
00377 void
00378 discover_conf_load(discover_error_t *status)
00379 {
00380 XML_Parser parser;
00381 struct context context;
00382 int load_url_status;
00383 int conf_load_error = 0;
00384 int conf_parse_error = 0;
00385 DIR *confdir;
00386 struct dirent *confent;
00387 char buf[512];
00388
00389 assert(status != NULL);
00390
00391 status->code = 0;
00392
00393 if (conf_loaded) {
00394 return;
00395 }
00396
00397 confdir = opendir(SYSCONFDIR "/discover.conf.d");
00398 if (confdir != NULL) {
00399 while ((confent = readdir(confdir)) != NULL) {
00400 if (strchr(confent->d_name, '.') != NULL) {
00401 continue;
00402 }
00403
00404 context.state = START;
00405 context.status = status;
00406 context.unknown_level = 0;
00407
00408 parser = XML_ParserCreate(NULL);
00409 XML_SetElementHandler(parser, start_element, end_element);
00410 XML_SetUserData(parser, &context);
00411
00412 strcpy(buf, "file:///" SYSCONFDIR "/discover.conf.d/");
00413 strncat(buf, confent->d_name, sizeof(buf));
00414 buf[sizeof(buf) - 1] = '\0';
00415
00416 load_url_status = _discover_load_url(buf, parser);
00417
00418
00419 if (status->code != 0) {
00420 char *message = _discover_xmalloc(256);
00421 snprintf(message, 256, "Error parsing configuration file %s",
00422 buf);
00423 status->create_message(&status, message);
00424 XML_ParserFree(parser);
00425 conf_parse_error = 1;
00426 break;
00427 }
00428
00429
00430 if (!load_url_status) {
00431 conf_load_error = 1;
00432 XML_ParserFree(parser);
00433 continue;
00434 }
00435
00436 if (!XML_Parse(parser, "", 0, 1)) {
00437 char *message = _discover_xmalloc(256);
00438 snprintf(message, 256, "Error parsing configuration file %s",
00439 buf);
00440 status->create_message(&status, message);
00441 status->code = DISCOVER_EXML;
00442 XML_ParserFree(parser);
00443 conf_parse_error = 1;
00444 break;
00445 }
00446
00447
00448 XML_ParserFree(parser);
00449 }
00450
00451 closedir(confdir);
00452
00453 if (conf_parse_error) {
00454 return;
00455 }
00456 }
00457
00458 if (conf_load_error) {
00459 char *message = _discover_xmalloc(256);
00460 snprintf(message, 256,
00461 "Failed loading one or more configuration files");
00462 status->create_message(&status, message);
00463 }
00464
00465 conf_loaded = 1;
00466
00467 return;
00468 }
00469
00476 int
00477 discover_conf_name_to_bus(char *name, discover_error_t *status)
00478 {
00479 int i;
00480 for (i = 0; bus_map[i].name; i++) {
00481 if (strcmp(bus_map[i].name, name) == 0) {
00482 return i;
00483 }
00484 }
00485
00486 status->code = DISCOVER_EBUSNOTFOUND;
00487 return -1;
00488 }
00489
00495 discover_bus_map_t *
00496 discover_conf_get_full_bus_map(discover_error_t *status)
00497 {
00498 discover_conf_load(status);
00499 return bus_map;
00500 }
00501
00508 discover_bus_map_t *
00509 discover_conf_get_bus_map_by_name(char *name, discover_error_t *status)
00510 {
00511 assert(status != NULL);
00512
00513 discover_conf_load(status);
00514 if (status->code != 0) {
00515 return NULL;
00516 }
00517
00518
00519
00520
00521
00522 return _real_discover_conf_get_bus_map_by_name(name, status);
00523 }
00524
00531 discover_bus_map_t *
00532 discover_conf_get_bus_map(discover_bus_t bus, discover_error_t *status)
00533 {
00534 assert(status != NULL);
00535 assert(bus >= 0);
00536
00537 if (bus >= BUS_COUNT) {
00538 status->code = DISCOVER_EBUSNOTFOUND;
00539 }
00540
00541 discover_conf_load(status);
00542 if (status->code != 0) {
00543 return NULL;
00544 }
00545
00546 return (discover_bus_map_t *)(bus_map + bus);
00547 }
00548
00556 void
00557 discover_conf_insert_url(char *url, discover_error_t *status)
00558 {
00559 assert(status != NULL);
00560
00561 discover_conf_load(status);
00562 if (status->code != 0) {
00563 return;
00564 }
00565
00566 _real_discover_conf_insert_url(url, status);
00567
00568 return;
00569 }
00570
00578 void
00579 discover_conf_append_url(char *url, discover_error_t *status)
00580 {
00581 assert(status != NULL);
00582
00583 discover_conf_load(status);
00584 if (status->code != 0) {
00585 return;
00586 }
00587
00588 _real_discover_conf_append_url(url, status);
00589
00590 return;
00591 }
00592
00598 discover_xml_url_t *
00599 discover_conf_get_urls(discover_error_t *status)
00600 {
00601 discover_xml_url_t *new;
00602
00603 assert(status != NULL);
00604
00605 status->code = 0;
00606
00607 if (!urls) {
00608 discover_conf_load(status);
00609
00610 new = discover_xml_url_new();
00611 new->url = _discover_xstrdup(DISCOVER_DEFAULT_URL);
00612
00613 if (pre_urls) {
00614 urls = pre_urls;
00615 if (urls->last) {
00616 urls->last->next = new;
00617 } else {
00618 urls->next = new;
00619 }
00620 urls->last = new;
00621 } else {
00622 urls = new;
00623 }
00624
00625 if (post_urls) {
00626 if (urls->last) {
00627 urls->last->next = post_urls;
00628 } else {
00629 urls->next = post_urls;
00630 }
00631
00632 if (post_urls->last) {
00633 urls->last = post_urls->last;
00634 } else {
00635 urls->last = post_urls;
00636 }
00637 }
00638
00639 post_urls = pre_urls = NULL;
00640 }
00641
00642 return urls;
00643 }
00644
00649 void
00650 discover_conf_free(void)
00651 {
00652 conf_loaded = 0;
00653
00654 if (urls) {
00655 discover_xml_url_free(urls);
00656 urls = NULL;
00657 }
00658 }
00659
00665 char *
00666 discover_conf_get_bus_name(discover_bus_t bus)
00667 {
00668 assert(bus >= 0);
00669 if (bus >= BUS_COUNT) {
00670 return NULL;
00671 }
00672
00673 return bus_map[bus].name;
00674 }
00675
00681 char *
00682 discover_conf_get_filetype_name(discover_filetype_t filetype)
00683 {
00684 if (filetype >= 3) {
00685 return NULL;
00686 }
00687
00688 return filetype_map[filetype];
00689 }
00690
00693
00694
00695
00696
00697
00698
00699