1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved. 24 */ 25 26 /* 27 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31 /* 32 * 33 * MODULE: dat_sr_parser.c 34 * 35 * PURPOSE: static registry parser 36 * 37 * $Id: udat_sr_parser.c,v 1.1 2003/07/31 14:04:19 jlentini Exp $ 38 */ 39 40 41 #include "udat_sr_parser.h" 42 #include "dat_sr.h" 43 44 45 /* 46 * 47 * Constants 48 * 49 */ 50 51 #define DAT_SR_CONF_ENV "DAT_OVERRIDE" 52 #define DAT_SR_CONF_DEFAULT "/etc/dat/dat.conf" 53 54 #define DAT_SR_TOKEN_THREADSAFE "threadsafe" 55 #define DAT_SR_TOKEN_NONTHREADSAFE "nonthreadsafe" 56 #define DAT_SR_TOKEN_DEFAULT "default" 57 #define DAT_SR_TOKEN_NONDEFAULT "nondefault" 58 59 #define DAT_SR_CHAR_NEWLINE '\n' 60 #define DAT_SR_CHAR_COMMENT '#' 61 #define DAT_SR_CHAR_QUOTE '"' 62 #define DAT_SR_CHAR_BACKSLASH '\\' 63 64 65 /* 66 * 67 * Enumerations 68 * 69 */ 70 71 typedef enum 72 { 73 DAT_SR_TOKEN_STRING, /* text field (both quoted or unquoted) */ 74 DAT_SR_TOKEN_EOR, /* end of record (newline) */ 75 DAT_SR_TOKEN_EOF /* end of file */ 76 } DAT_SR_TOKEN_TYPE; 77 78 typedef enum 79 { 80 DAT_SR_API_UDAT, 81 DAT_SR_API_KDAT 82 } DAT_SR_API_TYPE; 83 84 85 /* 86 * 87 * Structures 88 * 89 */ 90 91 typedef struct 92 { 93 DAT_SR_TOKEN_TYPE type; 94 char *value; /* valid if type is DAT_SR_TOKEN_STRING */ 95 DAT_OS_SIZE value_len; 96 } DAT_SR_TOKEN; 97 98 typedef struct DAT_SR_STACK_NODE 99 { 100 DAT_SR_TOKEN token; 101 struct DAT_SR_STACK_NODE *next; 102 } DAT_SR_STACK_NODE; 103 104 typedef struct 105 { 106 DAT_UINT32 major; 107 DAT_UINT32 minor; 108 } DAT_SR_VERSION; 109 110 typedef struct 111 { 112 char *id; 113 DAT_SR_VERSION version; 114 } DAT_SR_PROVIDER_VERSION; 115 116 typedef struct 117 { 118 DAT_SR_API_TYPE type; 119 DAT_SR_VERSION version; 120 } DAT_SR_API_VERSION; 121 122 typedef struct 123 { 124 char *ia_name; 125 DAT_SR_API_VERSION api_version; 126 DAT_BOOLEAN is_thread_safe; 127 DAT_BOOLEAN is_default; 128 char *lib_path; 129 DAT_SR_PROVIDER_VERSION provider_version; 130 char *ia_params; 131 char *platform_params; 132 } DAT_SR_CONF_ENTRY; 133 134 135 /* 136 * 137 * Internal Function Declarations 138 * 139 */ 140 141 static DAT_RETURN 142 dat_sr_load_entry( 143 DAT_SR_CONF_ENTRY *entry); 144 145 static DAT_BOOLEAN 146 dat_sr_is_valid_entry( 147 DAT_SR_CONF_ENTRY *entry); 148 149 static char * 150 dat_sr_type_to_str( 151 DAT_SR_TOKEN_TYPE type); 152 153 static DAT_RETURN 154 dat_sr_parse_eof( 155 DAT_OS_FILE *file); 156 157 static DAT_RETURN 158 dat_sr_parse_entry( 159 DAT_OS_FILE *file); 160 161 static DAT_RETURN 162 dat_sr_parse_ia_name( 163 DAT_OS_FILE *file, 164 DAT_SR_CONF_ENTRY *entry); 165 166 static DAT_RETURN 167 dat_sr_parse_api( 168 DAT_OS_FILE *file, 169 DAT_SR_CONF_ENTRY *entry); 170 171 static DAT_RETURN 172 dat_sr_parse_thread_safety( 173 DAT_OS_FILE *file, 174 DAT_SR_CONF_ENTRY *entry); 175 176 static DAT_RETURN 177 dat_sr_parse_default( 178 DAT_OS_FILE *file, 179 DAT_SR_CONF_ENTRY *entry); 180 181 static DAT_RETURN 182 dat_sr_parse_lib_path( 183 DAT_OS_FILE *file, 184 DAT_SR_CONF_ENTRY *entry); 185 186 static DAT_RETURN 187 dat_sr_parse_provider_version( 188 DAT_OS_FILE *file, 189 DAT_SR_CONF_ENTRY *entry); 190 191 static DAT_RETURN 192 dat_sr_parse_ia_params( 193 DAT_OS_FILE *file, 194 DAT_SR_CONF_ENTRY *entry); 195 196 static DAT_RETURN 197 dat_sr_parse_platform_params( 198 DAT_OS_FILE *file, 199 DAT_SR_CONF_ENTRY *entry); 200 201 static DAT_RETURN 202 dat_sr_parse_eoe( 203 DAT_OS_FILE *file, 204 DAT_SR_CONF_ENTRY *entry); 205 206 static DAT_RETURN 207 dat_sr_convert_api( 208 char *str, 209 DAT_SR_API_VERSION *api_version); 210 211 static DAT_RETURN 212 dat_sr_convert_thread_safety( 213 char *str, 214 DAT_BOOLEAN *is_thread_safe); 215 216 static DAT_RETURN 217 dat_sr_convert_default( 218 char *str, 219 DAT_BOOLEAN *is_default); 220 221 static DAT_RETURN 222 dat_sr_convert_provider_version( 223 char *str, 224 DAT_SR_PROVIDER_VERSION *provider_version); 225 226 static DAT_RETURN 227 dat_sr_get_token( 228 DAT_OS_FILE *file, 229 DAT_SR_TOKEN *token); 230 231 static DAT_RETURN 232 dat_sr_put_token( 233 DAT_OS_FILE *file, 234 DAT_SR_TOKEN *token); 235 236 static DAT_RETURN 237 dat_sr_read_token( 238 DAT_OS_FILE *file, 239 DAT_SR_TOKEN *token); 240 241 static DAT_RETURN 242 dat_sr_read_str( 243 DAT_OS_FILE *file, 244 DAT_SR_TOKEN *token, 245 DAT_OS_SIZE token_len); 246 247 static DAT_RETURN 248 dat_sr_read_quoted_str( 249 DAT_OS_FILE *file, 250 DAT_SR_TOKEN *token, 251 DAT_OS_SIZE token_len, 252 DAT_COUNT num_escape_seq); 253 254 static void 255 dat_sr_read_comment( 256 DAT_OS_FILE *file); 257 258 259 /* 260 * 261 * Global Variables 262 * 263 */ 264 265 static DAT_SR_STACK_NODE *g_token_stack = NULL; 266 267 268 /* 269 * 270 * External Function Definitions 271 * 272 */ 273 274 /* 275 * Function: dat_sr_load 276 */ 277 278 DAT_RETURN 279 dat_sr_load(void) 280 { 281 char *sr_path; 282 DAT_OS_FILE *sr_file; 283 284 sr_path = dat_os_getenv(DAT_SR_CONF_ENV); 285 if (sr_path == NULL) { 286 sr_path = DAT_SR_CONF_DEFAULT; 287 } 288 289 dat_os_dbg_print(DAT_OS_DBG_TYPE_SR, 290 "DAT Registry: static registry file <%s> \n", sr_path); 291 292 sr_file = dat_os_fopen(sr_path); 293 if (sr_file == NULL) { 294 return (DAT_INTERNAL_ERROR); 295 } 296 297 for (;;) { 298 if (DAT_SUCCESS == dat_sr_parse_eof(sr_file)) { 299 break; 300 } else if (DAT_SUCCESS == dat_sr_parse_entry(sr_file)) { 301 continue; 302 } else { 303 dat_os_assert(!"unable to parse static registry file"); 304 break; 305 } 306 } 307 308 if (0 != dat_os_fclose(sr_file)) { 309 return (DAT_INTERNAL_ERROR); 310 } 311 312 return (DAT_SUCCESS); 313 } 314 315 316 /* 317 * 318 * Internal Function Definitions 319 * 320 */ 321 322 /* 323 * Function: dat_sr_is_valid_entry 324 */ 325 326 DAT_BOOLEAN 327 dat_sr_is_valid_entry( 328 DAT_SR_CONF_ENTRY *entry) 329 { 330 if ((DAT_SR_API_UDAT == entry->api_version.type) && 331 (entry->is_default)) { 332 return (DAT_TRUE); 333 } else { 334 return (DAT_FALSE); 335 } 336 } 337 338 339 /* 340 * Function: dat_sr_load_entry 341 */ 342 343 DAT_RETURN 344 dat_sr_load_entry( 345 DAT_SR_CONF_ENTRY *conf_entry) 346 { 347 DAT_SR_ENTRY entry; 348 349 if (DAT_NAME_MAX_LENGTH < (strlen(conf_entry->ia_name) + 1)) { 350 dat_os_dbg_print(DAT_OS_DBG_TYPE_SR, 351 "DAT Registry: ia name %s is longer than " 352 "DAT_NAME_MAX_LENGTH (%i)\n", 353 conf_entry->ia_name, DAT_NAME_MAX_LENGTH); 354 355 return (DAT_INSUFFICIENT_RESOURCES); 356 } 357 358 (void) dat_os_strncpy(entry.info.ia_name, conf_entry->ia_name, 359 DAT_NAME_MAX_LENGTH); 360 entry.info.dapl_version_major = conf_entry->api_version.version.major; 361 entry.info.dapl_version_minor = conf_entry->api_version.version.minor; 362 entry.info.is_thread_safe = conf_entry->is_thread_safe; 363 entry.lib_path = conf_entry->lib_path; 364 entry.ia_params = conf_entry->ia_params; 365 entry.lib_handle = NULL; 366 entry.ref_count = 0; 367 368 dat_os_dbg_print(DAT_OS_DBG_TYPE_SR, 369 "DAT Registry: loading provider for %s\n", 370 conf_entry->ia_name); 371 372 return (dat_sr_insert(&entry.info, &entry)); 373 } 374 375 376 /* 377 * Function: dat_sr_type_to_str 378 */ 379 380 char * 381 dat_sr_type_to_str( 382 DAT_SR_TOKEN_TYPE type) 383 { 384 static char *str_array[] = { "string", "eor", "eof" }; 385 386 if ((type < 0) || (2 < type)) { 387 return ("error: invalid token type"); 388 } 389 390 return (str_array[type]); 391 } 392 393 394 /* 395 * Function: dat_sr_parse_eof 396 */ 397 398 DAT_RETURN 399 dat_sr_parse_eof( 400 DAT_OS_FILE *file) 401 { 402 DAT_SR_TOKEN token; 403 404 if (DAT_SUCCESS != dat_sr_get_token(file, &token)) { 405 return (DAT_INTERNAL_ERROR); 406 } 407 408 if (DAT_SR_TOKEN_EOF == token.type) { 409 return (DAT_SUCCESS); 410 } else { 411 (void) dat_sr_put_token(file, &token); 412 return (DAT_INTERNAL_ERROR); 413 } 414 } 415 416 417 /* 418 * Function: dat_sr_parse_ia_name 419 */ 420 421 DAT_RETURN 422 dat_sr_parse_entry( 423 DAT_OS_FILE *file) 424 { 425 DAT_SR_CONF_ENTRY entry; 426 DAT_RETURN status; 427 428 (void) dat_os_memset(&entry, 0, sizeof (DAT_SR_CONF_ENTRY)); 429 430 if ((DAT_SUCCESS == dat_sr_parse_ia_name(file, &entry)) && 431 (DAT_SUCCESS == dat_sr_parse_api(file, &entry)) && 432 (DAT_SUCCESS == dat_sr_parse_thread_safety(file, &entry)) && 433 (DAT_SUCCESS == dat_sr_parse_default(file, &entry)) && 434 (DAT_SUCCESS == dat_sr_parse_lib_path(file, &entry)) && 435 (DAT_SUCCESS == dat_sr_parse_provider_version(file, &entry)) && 436 (DAT_SUCCESS == dat_sr_parse_ia_params(file, &entry)) && 437 (DAT_SUCCESS == dat_sr_parse_platform_params(file, &entry)) && 438 (DAT_SUCCESS == dat_sr_parse_eoe(file, &entry))) { 439 dat_os_dbg_print(DAT_OS_DBG_TYPE_SR, 440 "\n" 441 "DAT Registry: entry \n" 442 " ia_name %s\n" 443 " api_version\n" 444 " type 0x%X\n" 445 " major.minor %d.%d\n" 446 " is_thread_safe %d\n" 447 " is_default %d\n" 448 " lib_path %s\n" 449 " provider_version\n" 450 " id %s\n" 451 " major.minor %d.%d\n" 452 " ia_params %s\n" 453 "\n", 454 entry.ia_name, 455 entry.api_version.type, 456 entry.api_version.version.major, 457 entry.api_version.version.minor, 458 entry.is_thread_safe, 459 entry.is_default, 460 entry.lib_path, 461 entry.provider_version.id, 462 entry.provider_version.version.major, 463 entry.provider_version.version.minor, 464 entry.ia_params); 465 466 if (DAT_TRUE == dat_sr_is_valid_entry(&entry)) { 467 /* 468 * The static registry configuration file may have 469 * multiple entries with the same IA name. The first 470 * entry will be installed in the static registry 471 * causing subsequent attempts to register the same IA 472 * name to fail. Therefore the return code from 473 * dat_sr_load_entry() is ignored. 474 */ 475 (void) dat_sr_load_entry(&entry); 476 } 477 478 status = DAT_SUCCESS; 479 } else { /* resync */ 480 DAT_SR_TOKEN token; 481 482 /* 483 * The static registry format is specified in the DAT 484 * specification. While the registry file's contents may change 485 * between revisions of the specification, there is no way to 486 * determine the specification version to which the 487 * configuration file conforms. If an entry is found that does 488 * not match the expected format, the entry is discarded 489 * and the parsing of the file continues. There is no way to 490 * determine if the entry was an error or an entry confirming 491 * to an alternate version of specification. 492 */ 493 494 for (;;) { 495 if (DAT_SUCCESS != dat_sr_get_token(file, &token)) { 496 status = DAT_INTERNAL_ERROR; 497 break; 498 } 499 500 if (DAT_SR_TOKEN_STRING != token.type) { 501 status = DAT_SUCCESS; 502 break; 503 } else { 504 dat_os_free(token.value, 505 (sizeof (char) * 506 dat_os_strlen(token.value)) + 1); 507 continue; 508 } 509 } 510 } 511 512 /* free resources */ 513 if (NULL != entry.ia_name) { 514 dat_os_free(entry.ia_name, 515 sizeof (char) * (dat_os_strlen(entry.ia_name) + 1)); 516 } 517 if (NULL != entry.lib_path) { 518 dat_os_free(entry.lib_path, 519 sizeof (char) * (dat_os_strlen(entry.lib_path) + 1)); 520 } 521 522 if (NULL != entry.provider_version.id) { 523 dat_os_free(entry.provider_version.id, 524 sizeof (char) * 525 (dat_os_strlen(entry.provider_version.id) + 1)); 526 } 527 528 if (NULL != entry.ia_params) { 529 dat_os_free(entry.ia_params, 530 sizeof (char) * (dat_os_strlen(entry.ia_params) + 1)); 531 } 532 533 return (status); 534 } 535 536 537 /* 538 * Function: dat_sr_parse_ia_name 539 */ 540 541 DAT_RETURN 542 dat_sr_parse_ia_name( 543 DAT_OS_FILE *file, 544 DAT_SR_CONF_ENTRY *entry) 545 { 546 DAT_SR_TOKEN token; 547 DAT_RETURN status; 548 549 if (DAT_SUCCESS != dat_sr_get_token(file, &token)) { 550 return (DAT_INTERNAL_ERROR); 551 } 552 553 if (DAT_SR_TOKEN_STRING != token.type) { 554 status = DAT_INTERNAL_ERROR; 555 } else { 556 entry->ia_name = token.value; 557 558 status = DAT_SUCCESS; 559 } 560 561 if (DAT_SUCCESS != status) { 562 DAT_RETURN status_success; 563 564 status_success = dat_sr_put_token(file, &token); 565 dat_os_assert(DAT_SUCCESS == status_success); 566 } 567 568 return (status); 569 } 570 571 572 /* 573 * Function: dat_sr_parse_ia_name 574 */ 575 576 DAT_RETURN 577 dat_sr_parse_api( 578 DAT_OS_FILE *file, 579 DAT_SR_CONF_ENTRY *entry) 580 { 581 DAT_SR_TOKEN token; 582 DAT_RETURN status; 583 584 if (DAT_SUCCESS != dat_sr_get_token(file, &token)) { 585 return (DAT_INTERNAL_ERROR); 586 } 587 588 if (DAT_SR_TOKEN_STRING != token.type) { 589 status = DAT_INTERNAL_ERROR; 590 } else if (DAT_SUCCESS != dat_sr_convert_api( 591 token.value, &entry->api_version)) { 592 status = DAT_INTERNAL_ERROR; 593 } else { 594 dat_os_free(token.value, 595 (sizeof (char) * dat_os_strlen(token.value)) + 1); 596 597 status = DAT_SUCCESS; 598 } 599 600 if (DAT_SUCCESS != status) { 601 DAT_RETURN status_success; 602 603 status_success = dat_sr_put_token(file, &token); 604 dat_os_assert(DAT_SUCCESS == status_success); 605 } 606 607 return (status); 608 } 609 610 611 /* 612 * Function: dat_sr_parse_thread_safety 613 */ 614 615 static DAT_RETURN 616 dat_sr_parse_thread_safety( 617 DAT_OS_FILE *file, 618 DAT_SR_CONF_ENTRY *entry) 619 { 620 DAT_SR_TOKEN token; 621 DAT_RETURN status; 622 623 if (DAT_SUCCESS != dat_sr_get_token(file, &token)) { 624 return (DAT_INTERNAL_ERROR); 625 } 626 627 if (DAT_SR_TOKEN_STRING != token.type) { 628 status = DAT_INTERNAL_ERROR; 629 } else if (DAT_SUCCESS != dat_sr_convert_thread_safety( 630 token.value, &entry->is_thread_safe)) { 631 status = DAT_INTERNAL_ERROR; 632 } else { 633 dat_os_free(token.value, 634 (sizeof (char) * dat_os_strlen(token.value)) + 1); 635 636 status = DAT_SUCCESS; 637 } 638 639 if (DAT_SUCCESS != status) { 640 DAT_RETURN status_success; 641 642 status_success = dat_sr_put_token(file, &token); 643 dat_os_assert(DAT_SUCCESS == status_success); 644 } 645 646 return (status); 647 } 648 649 650 /* 651 * Function: dat_sr_parse_default 652 */ 653 654 DAT_RETURN 655 dat_sr_parse_default( 656 DAT_OS_FILE *file, 657 DAT_SR_CONF_ENTRY *entry) 658 { 659 DAT_SR_TOKEN token; 660 DAT_RETURN status; 661 662 if (DAT_SUCCESS != dat_sr_get_token(file, &token)) { 663 return (DAT_INTERNAL_ERROR); 664 } 665 666 if (DAT_SR_TOKEN_STRING != token.type) { 667 status = DAT_INTERNAL_ERROR; 668 } else if (DAT_SUCCESS != dat_sr_convert_default( 669 token.value, &entry->is_default)) { 670 status = DAT_INTERNAL_ERROR; 671 } else { 672 dat_os_free(token.value, 673 (sizeof (char) * dat_os_strlen(token.value)) + 1); 674 675 status = DAT_SUCCESS; 676 } 677 678 if (DAT_SUCCESS != status) { 679 DAT_RETURN status_success; 680 681 status_success = dat_sr_put_token(file, &token); 682 dat_os_assert(DAT_SUCCESS == status_success); 683 } 684 685 return (status); 686 } 687 688 689 /* 690 * Function: dat_sr_parse_lib_path 691 */ 692 693 DAT_RETURN 694 dat_sr_parse_lib_path( 695 DAT_OS_FILE *file, 696 DAT_SR_CONF_ENTRY *entry) 697 { 698 DAT_SR_TOKEN token; 699 DAT_RETURN status; 700 701 if (DAT_SUCCESS != dat_sr_get_token(file, &token)) { 702 return (DAT_INTERNAL_ERROR); 703 } 704 705 if (DAT_SR_TOKEN_STRING != token.type) { 706 status = DAT_INTERNAL_ERROR; 707 } else { 708 entry->lib_path = token.value; 709 710 status = DAT_SUCCESS; 711 } 712 713 if (DAT_SUCCESS != status) { 714 DAT_RETURN status_success; 715 716 status_success = dat_sr_put_token(file, &token); 717 dat_os_assert(DAT_SUCCESS == status_success); 718 } 719 720 return (status); 721 } 722 723 /* 724 * Function: dat_sr_parse_provider_version 725 */ 726 727 DAT_RETURN 728 dat_sr_parse_provider_version( 729 DAT_OS_FILE *file, 730 DAT_SR_CONF_ENTRY *entry) 731 { 732 DAT_SR_TOKEN token; 733 DAT_RETURN status; 734 735 if (DAT_SUCCESS != dat_sr_get_token(file, &token)) { 736 return (DAT_INTERNAL_ERROR); 737 } 738 739 if (DAT_SR_TOKEN_STRING != token.type) { 740 status = DAT_INTERNAL_ERROR; 741 } else if (DAT_SUCCESS != dat_sr_convert_provider_version( 742 token.value, &entry->provider_version)) { 743 status = DAT_INTERNAL_ERROR; 744 } else { 745 dat_os_free(token.value, 746 (sizeof (char) * dat_os_strlen(token.value)) + 1); 747 748 status = DAT_SUCCESS; 749 } 750 751 if (DAT_SUCCESS != status) { 752 DAT_RETURN status_success; 753 754 status_success = dat_sr_put_token(file, &token); 755 dat_os_assert(DAT_SUCCESS == status_success); 756 } 757 758 return (status); 759 } 760 761 762 /* 763 * Function: dat_sr_parse_ia_params 764 */ 765 766 DAT_RETURN 767 dat_sr_parse_ia_params( 768 DAT_OS_FILE *file, 769 DAT_SR_CONF_ENTRY *entry) 770 { 771 DAT_SR_TOKEN token; 772 DAT_RETURN status; 773 774 if (DAT_SUCCESS != dat_sr_get_token(file, &token)) { 775 return (DAT_INTERNAL_ERROR); 776 } 777 778 if (DAT_SR_TOKEN_STRING != token.type) { 779 status = DAT_INTERNAL_ERROR; 780 } else { 781 entry->ia_params = token.value; 782 783 status = DAT_SUCCESS; 784 } 785 786 if (DAT_SUCCESS != status) { 787 DAT_RETURN status_success; 788 789 status_success = dat_sr_put_token(file, &token); 790 dat_os_assert(DAT_SUCCESS == status_success); 791 } 792 793 return (status); 794 } 795 796 797 /* 798 * Function: dat_sr_parse_platform_params 799 */ 800 801 DAT_RETURN 802 dat_sr_parse_platform_params( 803 DAT_OS_FILE *file, 804 DAT_SR_CONF_ENTRY *entry) 805 { 806 DAT_SR_TOKEN token; 807 DAT_RETURN status; 808 809 if (DAT_SUCCESS != dat_sr_get_token(file, &token)) { 810 return (DAT_INTERNAL_ERROR); 811 } 812 813 if (DAT_SR_TOKEN_STRING != token.type) { 814 status = DAT_INTERNAL_ERROR; 815 } else { 816 entry->platform_params = token.value; 817 818 status = DAT_SUCCESS; 819 } 820 821 if (DAT_SUCCESS != status) { 822 DAT_RETURN status_success; 823 824 status_success = dat_sr_put_token(file, &token); 825 dat_os_assert(DAT_SUCCESS == status_success); 826 } 827 828 return (status); 829 } 830 831 832 /* 833 * Function: dat_sr_parse_eoe 834 */ 835 836 DAT_RETURN 837 dat_sr_parse_eoe( 838 DAT_OS_FILE *file, 839 DAT_SR_CONF_ENTRY *entry) /*ARGSUSED*/ 840 { 841 DAT_SR_TOKEN token; 842 DAT_RETURN status; 843 844 if (DAT_SUCCESS != dat_sr_get_token(file, &token)) { 845 return (DAT_INTERNAL_ERROR); 846 } 847 848 if ((DAT_SR_TOKEN_EOF != token.type) && 849 (DAT_SR_TOKEN_EOR != token.type)) { 850 status = DAT_INTERNAL_ERROR; 851 } else { 852 status = DAT_SUCCESS; 853 } 854 855 if (DAT_SUCCESS != status) { 856 DAT_RETURN status_success; 857 858 status_success = dat_sr_put_token(file, &token); 859 dat_os_assert(DAT_SUCCESS == status_success); 860 } 861 862 return (status); 863 } 864 865 866 /* 867 * Function: dat_sr_convert_api 868 */ 869 870 DAT_RETURN 871 dat_sr_convert_api( 872 char *str, 873 DAT_SR_API_VERSION *api_version) 874 { 875 int i; 876 int minor_i; 877 878 dat_os_assert(0 < dat_os_strlen(str)); 879 880 if ('u' == str[0]) { 881 api_version->type = DAT_SR_API_UDAT; 882 } else if ('k' == str[0]) { 883 api_version->type = DAT_SR_API_KDAT; 884 } else { 885 return (DAT_INTERNAL_ERROR); 886 } 887 888 for (i = 1 /* move past initial [u|k] */; '\0' != str[i]; i++) { 889 if ('.' == str[i]) { 890 break; 891 } else if (DAT_TRUE != dat_os_isdigit(str[i])) { 892 return (DAT_INTERNAL_ERROR); 893 } 894 } 895 896 api_version->version.major = (DAT_UINT32)dat_os_strtol(str + 1, NULL, 897 10); 898 899 /* move past '.' */ 900 minor_i = ++i; 901 902 for (; '\0' != str[i]; i++) { 903 if (DAT_TRUE != dat_os_isdigit(str[i])) { 904 return (DAT_INTERNAL_ERROR); 905 } 906 } 907 908 api_version->version.minor = (DAT_UINT32)dat_os_strtol(str + minor_i, 909 NULL, 10); 910 911 if ('\0' != str[i]) { 912 return (DAT_INTERNAL_ERROR); 913 } 914 915 return (DAT_SUCCESS); 916 } 917 918 919 /* 920 * Function: dat_sr_convert_thread_safety 921 */ 922 923 static DAT_RETURN 924 dat_sr_convert_thread_safety( 925 char *str, 926 DAT_BOOLEAN *is_thread_safe) 927 { 928 if (!dat_os_strncmp(str, 929 DAT_SR_TOKEN_THREADSAFE, 930 dat_os_strlen(DAT_SR_TOKEN_THREADSAFE))) { 931 *is_thread_safe = DAT_TRUE; 932 return (DAT_SUCCESS); 933 } else if (!dat_os_strncmp(str, 934 DAT_SR_TOKEN_NONTHREADSAFE, 935 dat_os_strlen(DAT_SR_TOKEN_NONTHREADSAFE))) { 936 *is_thread_safe = DAT_FALSE; 937 return (DAT_SUCCESS); 938 } else { 939 return (DAT_INTERNAL_ERROR); 940 } 941 } 942 943 944 /* 945 * Function: dat_sr_convert_default 946 */ 947 948 static DAT_RETURN 949 dat_sr_convert_default( 950 char *str, 951 DAT_BOOLEAN *is_default) 952 { 953 if (!dat_os_strncmp(str, 954 DAT_SR_TOKEN_DEFAULT, 955 dat_os_strlen(DAT_SR_TOKEN_DEFAULT))) { 956 *is_default = DAT_TRUE; 957 return (DAT_SUCCESS); 958 } else if (!dat_os_strncmp(str, 959 DAT_SR_TOKEN_NONDEFAULT, 960 dat_os_strlen(DAT_SR_TOKEN_NONDEFAULT))) { 961 *is_default = DAT_FALSE; 962 return (DAT_SUCCESS); 963 } else { 964 return (DAT_INTERNAL_ERROR); 965 } 966 } 967 968 969 /* 970 * Function: dat_sr_convert_provider_version 971 */ 972 973 DAT_RETURN 974 dat_sr_convert_provider_version( 975 char *str, 976 DAT_SR_PROVIDER_VERSION *provider_version) 977 { 978 DAT_RETURN status; 979 int i; 980 int decimal_i; 981 982 dat_os_assert(0 < dat_os_strlen(str)); 983 dat_os_assert(NULL == provider_version->id); 984 985 status = DAT_SUCCESS; 986 987 for (i = 0; '\0' != str[i]; i++) { 988 if ('.' == str[i]) { 989 break; 990 } 991 } 992 993 /* if no id value was found */ 994 if (0 == i) { 995 status = DAT_INTERNAL_ERROR; 996 goto exit; 997 } 998 999 if (NULL == (provider_version->id = dat_os_alloc(sizeof (char) * 1000 (i + 1)))) { 1001 status = DAT_INSUFFICIENT_RESOURCES | DAT_RESOURCE_MEMORY; 1002 goto exit; 1003 } 1004 1005 (void) dat_os_strncpy(provider_version->id, str, i); 1006 provider_version->id[i] = '\0'; 1007 1008 /* move past '.' */ 1009 decimal_i = ++i; 1010 1011 for (; '\0' != str[i]; i++) { 1012 if ('.' == str[i]) { 1013 break; 1014 } else if (DAT_TRUE != dat_os_isdigit(str[i])) { 1015 status = DAT_INTERNAL_ERROR; 1016 goto exit; 1017 } 1018 } 1019 1020 /* if no version value was found */ 1021 if (decimal_i == i) { 1022 status = DAT_INTERNAL_ERROR; 1023 goto exit; 1024 } 1025 1026 provider_version->version.major = (DAT_UINT32) 1027 dat_os_strtol(str + decimal_i, NULL, 10); 1028 1029 /* move past '.' */ 1030 decimal_i = ++i; 1031 1032 for (; '\0' != str[i]; i++) { 1033 if (DAT_TRUE != dat_os_isdigit(str[i])) { 1034 status = DAT_INTERNAL_ERROR; 1035 goto exit; 1036 } 1037 } 1038 1039 /* if no version value was found */ 1040 if (decimal_i == i) { 1041 status = DAT_INTERNAL_ERROR; 1042 goto exit; 1043 } 1044 1045 provider_version->version.minor = (DAT_UINT32) 1046 dat_os_strtol(str + decimal_i, NULL, 10); 1047 1048 if ('\0' != str[i]) { 1049 status = DAT_INTERNAL_ERROR; 1050 goto exit; 1051 } 1052 1053 exit: 1054 if (DAT_SUCCESS != status) { 1055 if (NULL != provider_version->id) { 1056 dat_os_free(provider_version->id, 1057 sizeof (char) * 1058 (dat_os_strlen(provider_version->id) + 1)); 1059 provider_version->id = NULL; 1060 } 1061 } 1062 1063 return (status); 1064 } 1065 1066 1067 /* 1068 * Function: dat_sr_get_token 1069 */ 1070 1071 DAT_RETURN 1072 dat_sr_get_token( 1073 DAT_OS_FILE *file, 1074 DAT_SR_TOKEN *token) 1075 { 1076 if (NULL == g_token_stack) { 1077 return (dat_sr_read_token(file, token)); 1078 } else { 1079 DAT_SR_STACK_NODE *top; 1080 1081 top = g_token_stack; 1082 1083 *token = top->token; 1084 g_token_stack = top->next; 1085 1086 dat_os_free(top, sizeof (DAT_SR_STACK_NODE)); 1087 1088 return (DAT_SUCCESS); 1089 } 1090 } 1091 1092 1093 /* 1094 * Function: dat_sr_put_token 1095 */ 1096 1097 DAT_RETURN 1098 dat_sr_put_token( 1099 DAT_OS_FILE *file, 1100 DAT_SR_TOKEN *token) /*ARGSUSED*/ 1101 { 1102 DAT_SR_STACK_NODE *top; 1103 1104 if (NULL == (top = dat_os_alloc(sizeof (DAT_SR_STACK_NODE)))) { 1105 return (DAT_INSUFFICIENT_RESOURCES | DAT_RESOURCE_MEMORY); 1106 } 1107 1108 top->token = *token; 1109 top->next = g_token_stack; 1110 g_token_stack = top; 1111 1112 return (DAT_SUCCESS); 1113 } 1114 1115 1116 /* 1117 * Function: dat_sr_read_token 1118 */ 1119 1120 DAT_RETURN 1121 dat_sr_read_token( 1122 DAT_OS_FILE *file, 1123 DAT_SR_TOKEN *token) 1124 { 1125 DAT_OS_FILE_POS pos; 1126 DAT_OS_SIZE token_len; 1127 DAT_COUNT num_escape_seq; 1128 DAT_BOOLEAN is_quoted_str; 1129 DAT_BOOLEAN is_prev_char_backslash; 1130 1131 /* 1132 * The DAT standard does not specify a maximum size for quoted strings. 1133 * Therefore the tokenizer must be able to read in a token of arbitrary 1134 * size. Instead of allocating a fixed length buffer, the tokenizer 1135 * first scans the input a single character at a time looking for the 1136 * begining and end of the token. Once the these positions are found, 1137 * the entire token is read into memory. By using this algorithm, the 1138 * implementation does not place an arbitrary maximum on the token size. 1139 */ 1140 1141 token_len = 0; 1142 num_escape_seq = 0; 1143 is_quoted_str = DAT_FALSE; 1144 is_prev_char_backslash = DAT_FALSE; 1145 1146 for (;;) { 1147 DAT_OS_FILE_POS cur_pos; 1148 int c; 1149 1150 /* if looking for start of the token */ 1151 if (0 == token_len) { 1152 if (DAT_SUCCESS != dat_os_fgetpos(file, &cur_pos)) { 1153 return (DAT_INTERNAL_ERROR); 1154 } 1155 } 1156 1157 c = dat_os_fgetc(file); 1158 1159 /* if looking for start of the token */ 1160 if (0 == token_len) { 1161 if (EOF == c) { 1162 token->type = DAT_SR_TOKEN_EOF; 1163 token->value = NULL; 1164 token->value_len = 0; 1165 goto success; 1166 } else if (DAT_SR_CHAR_NEWLINE == c) { 1167 token->type = DAT_SR_TOKEN_EOR; 1168 token->value = NULL; 1169 token->value_len = 0; 1170 goto success; 1171 } else if (dat_os_isblank(c)) { 1172 continue; 1173 } else if (DAT_SR_CHAR_COMMENT == c) { 1174 dat_sr_read_comment(file); 1175 continue; 1176 } else { 1177 if (DAT_SR_CHAR_QUOTE == c) { 1178 is_quoted_str = DAT_TRUE; 1179 } 1180 1181 pos = cur_pos; 1182 token_len++; 1183 } 1184 } else { /* looking for the end of the token */ 1185 if (EOF == c) { 1186 break; 1187 } else if (DAT_SR_CHAR_NEWLINE == c) { 1188 /* put back the newline */ 1189 (void) dat_os_fungetc(file); 1190 break; 1191 } else if (!is_quoted_str && dat_os_isblank(c)) { 1192 break; 1193 } else { 1194 token_len++; 1195 1196 if ((DAT_SR_CHAR_QUOTE == c) && 1197 !is_prev_char_backslash) { 1198 break; 1199 } else if ((DAT_SR_CHAR_BACKSLASH == c) && 1200 !is_prev_char_backslash) { 1201 is_prev_char_backslash = DAT_TRUE; 1202 num_escape_seq++; 1203 } else { 1204 is_prev_char_backslash = DAT_FALSE; 1205 } 1206 } 1207 } 1208 } 1209 1210 /* the token was a string */ 1211 if (DAT_SUCCESS != dat_os_fsetpos(file, &pos)) { 1212 return (DAT_INTERNAL_ERROR); 1213 } 1214 1215 if (is_quoted_str) { 1216 if (DAT_SUCCESS != dat_sr_read_quoted_str(file, 1217 token, 1218 token_len, 1219 num_escape_seq)) { 1220 return (DAT_INTERNAL_ERROR); 1221 } 1222 } else { 1223 if (DAT_SUCCESS != dat_sr_read_str(file, 1224 token, 1225 token_len)) { 1226 return (DAT_INTERNAL_ERROR); 1227 } 1228 } 1229 1230 success: 1231 dat_os_dbg_print(DAT_OS_DBG_TYPE_SR, 1232 "\n" 1233 "DAT Registry: token\n" 1234 " type %s\n" 1235 " value <%s>\n" 1236 "\n", 1237 dat_sr_type_to_str(token->type), 1238 ((DAT_SR_TOKEN_STRING == token->type) ? token->value : "")); 1239 1240 return (DAT_SUCCESS); 1241 } 1242 1243 1244 /* 1245 * Function: dat_sr_read_str 1246 */ 1247 1248 DAT_RETURN 1249 dat_sr_read_str( 1250 DAT_OS_FILE *file, 1251 DAT_SR_TOKEN *token, 1252 DAT_OS_SIZE token_len) 1253 { 1254 token->type = DAT_SR_TOKEN_STRING; 1255 /* +1 for null termination */ 1256 token->value_len = sizeof (char) * (token_len + 1); 1257 if (NULL == (token->value = dat_os_alloc(token->value_len))) { 1258 return (DAT_INSUFFICIENT_RESOURCES | DAT_RESOURCE_MEMORY); 1259 } 1260 1261 if (token_len != dat_os_fread(file, token->value, token_len)) { 1262 dat_os_free(token->value, token->value_len); 1263 token->value = NULL; 1264 1265 return (DAT_INTERNAL_ERROR); 1266 } 1267 1268 token->value[token->value_len - 1] = '\0'; 1269 1270 return (DAT_SUCCESS); 1271 } 1272 1273 1274 /* 1275 * Function: dat_sr_read_quoted_str 1276 */ 1277 1278 DAT_RETURN 1279 dat_sr_read_quoted_str( 1280 DAT_OS_FILE *file, 1281 DAT_SR_TOKEN *token, 1282 DAT_OS_SIZE token_len, 1283 DAT_COUNT num_escape_seq) 1284 { 1285 DAT_OS_SIZE str_len; 1286 DAT_OS_SIZE i; 1287 DAT_OS_SIZE j; 1288 int c; 1289 DAT_RETURN status; 1290 DAT_BOOLEAN is_prev_char_backslash; 1291 1292 str_len = token_len - 2; /* minus 2 " characters */ 1293 is_prev_char_backslash = DAT_FALSE; 1294 status = DAT_SUCCESS; 1295 1296 token->type = DAT_SR_TOKEN_STRING; 1297 /* +1 for null termination */ 1298 token->value_len = sizeof (char) * (str_len - num_escape_seq + 1); 1299 1300 if (NULL == (token->value = dat_os_alloc(token->value_len))) { 1301 status = DAT_INSUFFICIENT_RESOURCES | DAT_RESOURCE_MEMORY; 1302 goto exit; 1303 } 1304 1305 /* throw away " */ 1306 if (DAT_SR_CHAR_QUOTE != dat_os_fgetc(file)) { 1307 status = DAT_INTERNAL_ERROR; 1308 goto exit; 1309 } 1310 1311 for (i = 0, j = 0; i < str_len; i++) { 1312 c = dat_os_fgetc(file); 1313 1314 if (EOF == c) { 1315 status = DAT_INTERNAL_ERROR; 1316 goto exit; 1317 } else if ((DAT_SR_CHAR_BACKSLASH == c) && 1318 !is_prev_char_backslash) { 1319 is_prev_char_backslash = DAT_TRUE; 1320 } else { 1321 token->value[j] = c; 1322 j++; 1323 1324 is_prev_char_backslash = DAT_FALSE; 1325 } 1326 } 1327 1328 /* throw away " */ 1329 if (DAT_SR_CHAR_QUOTE != dat_os_fgetc(file)) { 1330 status = DAT_INTERNAL_ERROR; 1331 goto exit; 1332 } 1333 1334 token->value[token->value_len - 1] = '\0'; 1335 1336 exit: 1337 if (DAT_SUCCESS != status) { 1338 if (NULL != token->value) { 1339 dat_os_free(token->value, token->value_len); 1340 token->value = NULL; 1341 } 1342 } 1343 1344 return (status); 1345 } 1346 1347 1348 /* 1349 * Function: dat_sr_read_comment 1350 */ 1351 1352 void 1353 dat_sr_read_comment( 1354 DAT_OS_FILE *file) 1355 { 1356 int c; 1357 1358 /* read up to an EOR or EOF to move past the comment */ 1359 do { 1360 c = dat_os_fgetc(file); 1361 } while ((DAT_SR_CHAR_NEWLINE != c) && (EOF != c)); 1362 1363 /* put back the newline */ 1364 (void) dat_os_fungetc(file); 1365 } 1366