1 /* 2 * Copyright 2002-2007, Axel Dörfler, axeld@pinc-software.de. 3 * This file may be used under the terms of the MIT License. 4 */ 5 6 /*! \brief Implements the driver settings API 7 This file is used by three different components with different needs: 8 1) the boot loader 9 Buffers a list of settings files to move over to the kernel - the 10 actual buffering is located in the boot loader directly, though. 11 Creates driver_settings structures out of those on demand only. 12 2) the kernel 13 Maintains a list of settings so that no disk access is required 14 for known settings (such as those passed over from the boot 15 loader). 16 3) libroot.so 17 Exports the parser to userland applications, so that they can 18 easily make use of driver_settings styled files. 19 20 The file has to be recompiled for every component separately, so that 21 it properly exports the required functionality (which is specified by 22 _BOOT_MODE for the boot loader, and _KERNEL_MODE for the kernel). 23 */ 24 25 // The boot loader is compiled with kernel rules, but we want to explicitely 26 // differentiate between the two here. 27 #ifdef _BOOT_MODE 28 # undef _KERNEL_MODE 29 #endif 30 31 #include <BeBuild.h> 32 #include <directories.h> 33 #include <driver_settings.h> 34 #include <FindDirectory.h> 35 #include <OS.h> 36 37 #ifdef _KERNEL_MODE 38 # include <KernelExport.h> 39 # include <util/list.h> 40 # include <lock.h> 41 # include <kdriver_settings.h> 42 # include <kernel.h> 43 # include <boot/kernel_args.h> 44 # include <boot_device.h> 45 #endif 46 #ifdef _BOOT_MODE 47 # include <boot/kernel_args.h> 48 # include <boot/stage2.h> 49 #else 50 # include <find_directory_private.h> 51 #endif 52 53 #include <stdlib.h> 54 #include <string.h> 55 #include <strings.h> 56 #include <unistd.h> 57 #include <fcntl.h> 58 #include <ctype.h> 59 60 #ifndef B_BUFFER_OVERFLOW 61 # define B_BUFFER_OVERFLOW B_ERROR 62 #endif 63 64 #define SETTINGS_DIRECTORY "/kernel/drivers/" 65 #define SETTINGS_MAGIC 'DrvS' 66 67 // Those maximum values are independent from the implementation - they 68 // have been chosen to make the code more robust against bad files 69 #define MAX_SETTINGS_SIZE 32768 70 #define MAX_SETTINGS_LEVEL 8 71 72 #define CONTINUE_PARAMETER 1 73 #define NO_PARAMETER 2 74 75 76 typedef struct settings_handle { 77 #ifdef _KERNEL_MODE 78 list_link link; 79 char name[B_OS_NAME_LENGTH]; 80 int32 ref_count; 81 // A negative ref_count means the node is not reference counted and not 82 // stored in the list. 83 #endif 84 int32 magic; 85 struct driver_settings settings; 86 char *text; 87 } settings_handle; 88 89 90 enum assignment_mode { 91 NO_ASSIGNMENT, 92 ALLOW_ASSIGNMENT, 93 IGNORE_ASSIGNMENT 94 }; 95 96 97 #ifdef _KERNEL_MODE 98 static struct list sHandles; 99 static mutex sLock = MUTEX_INITIALIZER("driver settings"); 100 #endif 101 102 103 // #pragma mark - private functions 104 105 106 /*! 107 \brief Returns true for any characters that separate parameters 108 109 Those characters are ignored in the input stream and won't be added 110 to any words. 111 */ 112 static inline bool 113 is_parameter_separator(char c) 114 { 115 return c == '\n' || c == ';'; 116 } 117 118 119 /*! Indicates if "c" begins a new word or not. 120 */ 121 static inline bool 122 is_word_break(char c) 123 { 124 return isspace(c) || is_parameter_separator(c); 125 } 126 127 128 static inline bool 129 check_handle(settings_handle *handle) 130 { 131 if (handle == NULL 132 || handle->magic != SETTINGS_MAGIC) 133 return false; 134 135 return true; 136 } 137 138 139 static driver_parameter * 140 get_parameter(settings_handle *handle, const char *name) 141 { 142 int32 i; 143 for (i = handle->settings.parameter_count; i-- > 0;) { 144 if (!strcmp(handle->settings.parameters[i].name, name)) 145 return &handle->settings.parameters[i]; 146 } 147 return NULL; 148 } 149 150 151 /*! 152 Returns the next word in the input buffer passed in via "_pos" - if 153 this function returns, it will bump the input position after the word. 154 It automatically cares about quoted strings and escaped characters. 155 If "allowNewLine" is true, it reads over comments to get to the next 156 word. 157 Depending on the "assignmentMode" parameter, the '=' sign is either 158 used as a work break, or not. 159 The input buffer will be changed to contain the word without quotes 160 or escaped characters and adds a terminating NULL byte. The "_word" 161 parameter will be set to the beginning of the word. 162 If the word is followed by a newline it will return B_OK, if white 163 spaces follows, it will return CONTINUE_PARAMETER. 164 */ 165 static status_t 166 get_word(char **_pos, char **_word, int32 assignmentMode, bool allowNewLine) 167 { 168 char *pos = *_pos; 169 char quoted = 0; 170 bool newLine = false, end = false; 171 int escaped = 0; 172 bool charEscaped = false; 173 174 // Skip any white space and comments 175 while (pos[0] 176 && ((allowNewLine && (isspace(pos[0]) || is_parameter_separator(pos[0]) 177 || pos[0] == '#')) 178 || (!allowNewLine && (pos[0] == '\t' || pos[0] == ' ')) 179 || (assignmentMode == ALLOW_ASSIGNMENT && pos[0] == '='))) { 180 // skip any comment lines 181 if (pos[0] == '#') { 182 while (pos[0] && pos[0] != '\n') 183 pos++; 184 } 185 pos++; 186 } 187 188 if (pos[0] == '}' || pos[0] == '\0') { 189 // if we just read some white space before an end of a 190 // parameter, this is just no parameter at all 191 *_pos = pos; 192 return NO_PARAMETER; 193 } 194 195 // Read in a word - might contain escaped (\) spaces, or it 196 // might also be quoted (" or '). 197 198 if (pos[0] == '"' || pos[0] == '\'') { 199 quoted = pos[0]; 200 pos++; 201 } 202 *_word = pos; 203 204 while (pos[0]) { 205 if (charEscaped) 206 charEscaped = false; 207 else if (pos[0] == '\\') { 208 charEscaped = true; 209 escaped++; 210 } else if ((!quoted && (is_word_break(pos[0]) 211 || (assignmentMode != IGNORE_ASSIGNMENT && pos[0] == '='))) 212 || (quoted && pos[0] == quoted)) 213 break; 214 215 pos++; 216 } 217 218 // "String exceeds line" - missing end quote 219 if (quoted && pos[0] != quoted) 220 return B_BAD_DATA; 221 222 // last character is a backslash 223 if (charEscaped) 224 return B_BAD_DATA; 225 226 end = pos[0] == '\0'; 227 newLine = is_parameter_separator(pos[0]) || end; 228 pos[0] = '\0'; 229 230 // Correct name if there were any escaped characters 231 if (escaped) { 232 char *word = *_word; 233 int offset = 0; 234 while (word <= pos) { 235 if (word[0] == '\\') { 236 offset--; 237 word++; 238 } 239 word[offset] = word[0]; 240 word++; 241 } 242 } 243 244 if (end) { 245 *_pos = pos; 246 return B_OK; 247 } 248 249 // Scan for next beginning word, open brackets, or comment start 250 251 pos++; 252 while (true) { 253 *_pos = pos; 254 if (!pos[0]) 255 return B_NO_ERROR; 256 257 if (is_parameter_separator(pos[0])) { 258 // an open bracket '{' could follow after the first 259 // newline, but not later 260 if (newLine) 261 return B_NO_ERROR; 262 263 newLine = true; 264 } else if (pos[0] == '{' || pos[0] == '}' || pos[0] == '#') 265 return B_NO_ERROR; 266 else if (!isspace(pos[0])) 267 return newLine ? B_NO_ERROR : CONTINUE_PARAMETER; 268 269 pos++; 270 } 271 } 272 273 274 static status_t 275 parse_parameter(struct driver_parameter *parameter, char **_pos, int32 level) 276 { 277 char *pos = *_pos; 278 status_t status; 279 280 // initialize parameter first 281 memset(parameter, 0, sizeof(struct driver_parameter)); 282 283 status = get_word(&pos, ¶meter->name, NO_ASSIGNMENT, true); 284 if (status == CONTINUE_PARAMETER) { 285 while (status == CONTINUE_PARAMETER) { 286 char **newArray, *value = NULL; 287 status = get_word(&pos, &value, parameter->value_count == 0 288 ? ALLOW_ASSIGNMENT : IGNORE_ASSIGNMENT, false); 289 if (status < B_OK) 290 break; 291 292 // enlarge value array and save the value 293 294 newArray = (char**)realloc(parameter->values, 295 (parameter->value_count + 1) * sizeof(char *)); 296 if (newArray == NULL) 297 return B_NO_MEMORY; 298 299 parameter->values = newArray; 300 parameter->values[parameter->value_count++] = value; 301 } 302 } 303 304 *_pos = pos; 305 return status; 306 } 307 308 309 static status_t 310 parse_parameters(struct driver_parameter **_parameters, int *_count, 311 char **_pos, int32 level) 312 { 313 if (level > MAX_SETTINGS_LEVEL) 314 return B_LINK_LIMIT; 315 316 while (true) { 317 struct driver_parameter parameter; 318 struct driver_parameter *newArray; 319 status_t status; 320 321 status = parse_parameter(¶meter, _pos, level); 322 if (status < B_OK) 323 return status; 324 325 if (status != NO_PARAMETER) { 326 driver_parameter *newParameter; 327 328 newArray = (driver_parameter*)realloc(*_parameters, (*_count + 1) 329 * sizeof(struct driver_parameter)); 330 if (newArray == NULL) 331 return B_NO_MEMORY; 332 333 memcpy(&newArray[*_count], ¶meter, sizeof(struct driver_parameter)); 334 newParameter = &newArray[*_count]; 335 336 *_parameters = newArray; 337 (*_count)++; 338 339 // check for level beginning and end 340 if (**_pos == '{') { 341 // if we go a level deeper, just start all over again... 342 (*_pos)++; 343 status = parse_parameters(&newParameter->parameters, 344 &newParameter->parameter_count, _pos, level + 1); 345 if (status < B_OK) 346 return status; 347 } 348 } 349 350 if ((**_pos == '}' && level > 0) 351 || (**_pos == '\0' && level == 0)) { 352 // take the closing bracket from the stack 353 (*_pos)++; 354 return B_OK; 355 } 356 357 // obviously, something has gone wrong 358 if (**_pos == '}' || **_pos == '\0') 359 return B_ERROR; 360 } 361 } 362 363 364 static status_t 365 parse_settings(settings_handle *handle) 366 { 367 char *text = handle->text; 368 369 memset(&handle->settings, 0, sizeof(struct driver_settings)); 370 371 // empty settings are allowed 372 if (text == NULL) 373 return B_OK; 374 375 return parse_parameters(&handle->settings.parameters, 376 &handle->settings.parameter_count, &text, 0); 377 } 378 379 380 static void 381 free_parameter(struct driver_parameter *parameter) 382 { 383 int32 i; 384 for (i = parameter->parameter_count; i-- > 0;) 385 free_parameter(¶meter->parameters[i]); 386 387 free(parameter->parameters); 388 free(parameter->values); 389 } 390 391 392 static void 393 free_settings(settings_handle *handle) 394 { 395 int32 i; 396 for (i = handle->settings.parameter_count; i-- > 0;) 397 free_parameter(&handle->settings.parameters[i]); 398 399 free(handle->settings.parameters); 400 free(handle->text); 401 free(handle); 402 } 403 404 405 static settings_handle * 406 new_settings(char *buffer, const char *driverName) 407 { 408 settings_handle *handle = (settings_handle*)malloc(sizeof(settings_handle)); 409 if (handle == NULL) 410 return NULL; 411 412 handle->magic = SETTINGS_MAGIC; 413 handle->text = buffer; 414 415 #ifdef _KERNEL_MODE 416 if (driverName != NULL) { 417 handle->ref_count = 1; 418 strlcpy(handle->name, driverName, sizeof(handle->name)); 419 } else { 420 handle->ref_count = -1; 421 handle->name[0] = 0; 422 } 423 #endif 424 425 if (parse_settings(handle) == B_OK) 426 return handle; 427 428 free(handle); 429 return NULL; 430 } 431 432 433 static settings_handle * 434 load_driver_settings_from_file(int file, const char *driverName) 435 { 436 struct stat stat; 437 438 // Allocate a buffer and read the whole file into it. 439 // We will keep this buffer in memory, until the settings 440 // are unloaded. 441 // The driver_parameter::name field will point directly 442 // to this buffer. 443 444 if (fstat(file, &stat) < B_OK) 445 return NULL; 446 447 if (stat.st_size > B_OK && stat.st_size < MAX_SETTINGS_SIZE) { 448 char *text = (char *)malloc(stat.st_size + 1); 449 if (text != NULL && read(file, text, stat.st_size) == stat.st_size) { 450 settings_handle *handle; 451 452 text[stat.st_size] = '\0'; 453 // make sure the string is null terminated 454 // to avoid misbehaviour 455 456 handle = new_settings(text, driverName); 457 if (handle != NULL) { 458 // everything went fine! 459 return handle; 460 } 461 } 462 // "text" might be NULL here, but that's allowed 463 free(text); 464 } 465 466 return NULL; 467 } 468 469 470 static bool 471 put_string(char **_buffer, ssize_t *_bufferSize, char *string) 472 { 473 size_t length, reserved, quotes; 474 char *buffer = *_buffer, c; 475 bool quoted; 476 477 if (string == NULL) 478 return true; 479 480 for (length = reserved = quotes = 0; (c = string[length]) != '\0'; length++) { 481 if (c == '"') 482 quotes++; 483 else if (is_word_break(c)) 484 reserved++; 485 } 486 quoted = reserved || quotes; 487 488 // update _bufferSize in any way, so that we can chain several 489 // of these calls without having to check the return value 490 // everytime 491 *_bufferSize -= length + (quoted ? 2 + quotes : 0); 492 493 if (*_bufferSize <= 0) 494 return false; 495 496 if (quoted) 497 *(buffer++) = '"'; 498 499 for (;(c = string[0]) != '\0'; string++) { 500 if (c == '"') 501 *(buffer++) = '\\'; 502 503 *(buffer++) = c; 504 } 505 506 if (quoted) 507 *(buffer++) = '"'; 508 509 buffer[0] = '\0'; 510 511 // update the buffer position 512 *_buffer = buffer; 513 514 return true; 515 } 516 517 518 static bool 519 put_chars(char **_buffer, ssize_t *_bufferSize, const char *chars) 520 { 521 char *buffer = *_buffer; 522 size_t length; 523 524 if (chars == NULL) 525 return true; 526 527 length = strlen(chars); 528 *_bufferSize -= length; 529 530 if (*_bufferSize <= 0) 531 return false; 532 533 memcpy(buffer, chars, length); 534 buffer += length; 535 buffer[0] = '\0'; 536 537 // update the buffer position 538 *_buffer = buffer; 539 540 return true; 541 } 542 543 544 static bool 545 put_char(char **_buffer, ssize_t *_bufferSize, char c) 546 { 547 char *buffer = *_buffer; 548 549 *_bufferSize -= 1; 550 551 if (*_bufferSize <= 0) 552 return false; 553 554 buffer[0] = c; 555 buffer[1] = '\0'; 556 557 // update the buffer position 558 *_buffer = buffer + 1; 559 560 return true; 561 } 562 563 564 static void 565 put_level_space(char **_buffer, ssize_t *_bufferSize, int32 level) 566 { 567 while (level-- > 0) 568 put_char(_buffer, _bufferSize, '\t'); 569 } 570 571 572 static void 573 put_parameter(char **_buffer, ssize_t *_bufferSize, 574 struct driver_parameter *parameter, int32 level, bool flat) 575 { 576 int32 i; 577 578 if (!flat) 579 put_level_space(_buffer, _bufferSize, level); 580 581 put_string(_buffer, _bufferSize, parameter->name); 582 if (flat && parameter->value_count > 0) 583 put_chars(_buffer, _bufferSize, " ="); 584 585 for (i = 0; i < parameter->value_count; i++) { 586 put_char(_buffer, _bufferSize, ' '); 587 put_string(_buffer, _bufferSize, parameter->values[i]); 588 } 589 590 if (parameter->parameter_count > 0) { 591 put_chars(_buffer, _bufferSize, " {"); 592 if (!flat) 593 put_char(_buffer, _bufferSize, '\n'); 594 595 for (i = 0; i < parameter->parameter_count; i++) { 596 put_parameter(_buffer, _bufferSize, ¶meter->parameters[i], 597 level + 1, flat); 598 599 if (parameter->parameters[i].parameter_count == 0) 600 put_chars(_buffer, _bufferSize, flat ? "; " : "\n"); 601 } 602 603 if (!flat) 604 put_level_space(_buffer, _bufferSize, level); 605 put_chars(_buffer, _bufferSize, flat ? "}" : "}\n"); 606 } 607 } 608 609 610 // #pragma mark - Kernel only functions 611 612 613 #ifdef _KERNEL_MODE 614 static settings_handle * 615 find_driver_settings(const char *name) 616 { 617 settings_handle *handle = NULL; 618 619 ASSERT_LOCKED_MUTEX(&sLock); 620 621 while ((handle = (settings_handle*)list_get_next_item(&sHandles, handle)) 622 != NULL) { 623 if (!strcmp(handle->name, name)) 624 return handle; 625 } 626 627 return NULL; 628 } 629 630 631 status_t 632 driver_settings_init(kernel_args *args) 633 { 634 struct driver_settings_file *settings = args->driver_settings; 635 636 // Move the preloaded driver settings over to the kernel 637 638 list_init(&sHandles); 639 640 while (settings != NULL) { 641 settings_handle *handle 642 = (settings_handle*)malloc(sizeof(settings_handle)); 643 if (handle == NULL) 644 return B_NO_MEMORY; 645 646 if (settings->size != 0) { 647 handle->text = (char*)malloc(settings->size + 1); 648 if (handle->text == NULL) { 649 free(handle); 650 return B_NO_MEMORY; 651 } 652 653 memcpy(handle->text, settings->buffer, settings->size); 654 handle->text[settings->size] = '\0'; 655 // null terminate the buffer 656 } else 657 handle->text = NULL; 658 659 strlcpy(handle->name, settings->name, sizeof(handle->name)); 660 handle->settings.parameters = NULL; 661 handle->settings.parameter_count = 0; 662 handle->magic = 0; 663 // this triggers parsing the settings when they are actually used 664 665 if (!strcmp(handle->name, B_SAFEMODE_DRIVER_SETTINGS)) { 666 // These settings cannot be reloaded, so we better don't throw 667 // them away. 668 handle->ref_count = 1; 669 } else 670 handle->ref_count = 0; 671 672 list_add_item(&sHandles, handle); 673 674 settings = settings->next; 675 } 676 677 return B_OK; 678 } 679 #endif 680 681 682 // #pragma mark - public API 683 684 685 status_t 686 unload_driver_settings(void *_handle) 687 { 688 settings_handle *handle = (settings_handle *)_handle; 689 if (!check_handle(handle)) 690 return B_BAD_VALUE; 691 692 #ifdef _KERNEL_MODE 693 mutex_lock(&sLock); 694 695 if (handle->ref_count > 0) { 696 if (--handle->ref_count == 0 && gBootDevice > 0) { 697 // don't unload an handle when /boot is not available 698 list_remove_link(&handle->link); 699 } else 700 handle = NULL; 701 } 702 mutex_unlock(&sLock); 703 #endif 704 705 if (handle != NULL) 706 free_settings(handle); 707 708 return B_OK; 709 } 710 711 712 void * 713 load_driver_settings(const char *driverName) 714 { 715 settings_handle *handle; 716 int file = -1; 717 718 if (driverName == NULL) 719 return NULL; 720 721 #ifdef _KERNEL_MODE 722 // see if we already have these settings loaded 723 mutex_lock(&sLock); 724 handle = find_driver_settings(driverName); 725 if (handle != NULL && handle->ref_count == 0 && gBootDevice > 0) { 726 // A handle with a zero ref_count should be unloaded if /boot is 727 // available. 728 list_remove_link(&handle->link); 729 free_settings(handle); 730 } else if (handle != NULL) { 731 handle->ref_count++; 732 733 // we got it, now let's see if it already has been parsed 734 if (handle->magic != SETTINGS_MAGIC) { 735 handle->magic = SETTINGS_MAGIC; 736 737 if (parse_settings(handle) != B_OK) { 738 // no valid settings, let's cut down its memory requirements 739 free(handle->text); 740 handle->text = NULL; 741 handle = NULL; 742 } 743 } 744 mutex_unlock(&sLock); 745 return handle; 746 } 747 748 // we are allowed to call the driver settings pretty early in the boot process 749 if (gKernelStartup) { 750 mutex_unlock(&sLock); 751 return NULL; 752 } 753 #endif // _KERNEL_MODE 754 #ifdef _BOOT_MODE 755 // see if we already have these settings loaded 756 { 757 struct driver_settings_file *settings = gKernelArgs.driver_settings; 758 while (settings != NULL) { 759 if (!strcmp(settings->name, driverName)) { 760 // we have it - since the buffer is clobbered, we have to 761 // copy its contents, though 762 char *text = (char*)malloc(settings->size + 1); 763 if (text == NULL) 764 return NULL; 765 766 memcpy(text, settings->buffer, settings->size + 1); 767 return new_settings(text, driverName); 768 } 769 settings = settings->next; 770 } 771 } 772 #endif // _BOOT_MODE 773 774 // open the settings from the standardized location 775 if (driverName[0] != '/') { 776 char path[B_FILE_NAME_LENGTH + 64]; 777 778 #ifdef _BOOT_MODE 779 strcpy(path, kUserSettingsDirectory); 780 #else 781 // TODO: use B_SYSTEM_SETTINGS_DIRECTORY instead! 782 if (__find_directory(B_USER_SETTINGS_DIRECTORY, -1, false, path, 783 sizeof(path)) == B_OK) 784 #endif 785 { 786 strlcat(path, SETTINGS_DIRECTORY, sizeof(path)); 787 strlcat(path, driverName, sizeof(path)); 788 } 789 790 file = open(path, O_RDONLY); 791 } else 792 file = open(driverName, O_RDONLY); 793 794 if (file < B_OK) { 795 #ifdef _KERNEL_MODE 796 mutex_unlock(&sLock); 797 #endif 798 return NULL; 799 } 800 801 handle = load_driver_settings_from_file(file, driverName); 802 803 #ifdef _KERNEL_MODE 804 if (handle != NULL) 805 list_add_item(&sHandles, handle); 806 mutex_unlock(&sLock); 807 #endif 808 809 close(file); 810 return (void *)handle; 811 } 812 813 814 void* 815 load_driver_settings_file(int fd) 816 { 817 return load_driver_settings_from_file(fd, NULL); 818 } 819 820 821 /*! 822 Returns a new driver_settings handle that has the parsed contents 823 of the passed string. 824 You can get an empty driver_settings object when you pass NULL as 825 the "settingsString" parameter. 826 */ 827 void * 828 parse_driver_settings_string(const char *settingsString) 829 { 830 char *text = NULL; 831 if (settingsString != NULL) { 832 // we simply copy the whole string to use it as our internal buffer 833 text = strdup(settingsString); 834 if (text == NULL) 835 return NULL; 836 } 837 838 settings_handle *handle = new_settings(text, NULL); 839 if (handle == NULL) 840 free(text); 841 return handle; 842 } 843 844 845 /*! 846 This function prints out a driver settings structure to a human 847 readable string. 848 It's either in standard style or the single line style speficied 849 by the "flat" parameter. 850 If the buffer is too small to hold the string, B_BUFFER_OVERFLOW 851 is returned, and the needed amount of bytes if placed in the 852 "_bufferSize" parameter. 853 If the "handle" parameter is not a valid driver settings handle, or 854 the "buffer" parameter is NULL, B_BAD_VALUE is returned. 855 */ 856 status_t 857 get_driver_settings_string(void *_handle, char *buffer, ssize_t *_bufferSize, 858 bool flat) 859 { 860 settings_handle *handle = (settings_handle *)_handle; 861 ssize_t bufferSize = *_bufferSize; 862 int32 i; 863 864 if (!check_handle(handle) || !buffer || *_bufferSize == 0) 865 return B_BAD_VALUE; 866 867 for (i = 0; i < handle->settings.parameter_count; i++) { 868 put_parameter(&buffer, &bufferSize, &handle->settings.parameters[i], 869 0, flat); 870 } 871 872 *_bufferSize -= bufferSize; 873 return bufferSize >= 0 ? B_OK : B_BUFFER_OVERFLOW; 874 } 875 876 877 /*! 878 Matches the first value of the parameter matching "keyName" with a set 879 of boolean values like 1/true/yes/on/enabled/... 880 Returns "unknownValue" if the parameter could not be found or doesn't 881 have any valid boolean setting, and "noArgValue" if the parameter 882 doesn't have any values. 883 Also returns "unknownValue" if the handle passed in was not valid. 884 */ 885 bool 886 get_driver_boolean_parameter(void *_handle, const char *keyName, 887 bool unknownValue, bool noArgValue) 888 { 889 settings_handle *handle = (settings_handle*)_handle; 890 driver_parameter *parameter; 891 char *boolean; 892 893 if (!check_handle(handle)) 894 return unknownValue; 895 896 // check for the parameter 897 if ((parameter = get_parameter(handle, keyName)) == NULL) 898 return unknownValue; 899 900 // check for the argument 901 if (parameter->value_count <= 0) 902 return noArgValue; 903 904 boolean = parameter->values[0]; 905 if (!strcmp(boolean, "1") 906 || !strcasecmp(boolean, "true") 907 || !strcasecmp(boolean, "yes") 908 || !strcasecmp(boolean, "on") 909 || !strcasecmp(boolean, "enable") 910 || !strcasecmp(boolean, "enabled")) 911 return true; 912 913 if (!strcmp(boolean, "0") 914 || !strcasecmp(boolean, "false") 915 || !strcasecmp(boolean, "no") 916 || !strcasecmp(boolean, "off") 917 || !strcasecmp(boolean, "disable") 918 || !strcasecmp(boolean, "disabled")) 919 return false; 920 921 // if no known keyword is found, "unknownValue" is returned 922 return unknownValue; 923 } 924 925 926 const char * 927 get_driver_parameter(void *_handle, const char *keyName, 928 const char *unknownValue, const char *noArgValue) 929 { 930 settings_handle* handle = (settings_handle*)_handle; 931 struct driver_parameter *parameter; 932 933 if (!check_handle(handle)) 934 return unknownValue; 935 936 // check for the parameter 937 if ((parameter = get_parameter(handle, keyName)) == NULL) 938 return unknownValue; 939 940 // check for the argument 941 if (parameter->value_count <= 0) 942 return noArgValue; 943 944 return parameter->values[0]; 945 } 946 947 948 const driver_settings * 949 get_driver_settings(void *handle) 950 { 951 if (!check_handle((settings_handle*)handle)) 952 return NULL; 953 954 return &((settings_handle *)handle)->settings; 955 } 956 957 958 #if defined(HAIKU_TARGET_PLATFORM_HAIKU) \ 959 && (defined(__i386__) || defined(__x86_64__)) 960 961 // Obsolete function, use unload_driver_settings instead. Introduced by 962 // accident in hrev3530 (2003) and present in public headers for a long time. 963 B_DEFINE_WEAK_ALIAS(unload_driver_settings, delete_driver_settings); 964 965 #endif 966