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