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
dat_sr_load(void)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
dat_sr_is_valid_entry(DAT_SR_CONF_ENTRY * entry)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
dat_sr_load_entry(DAT_SR_CONF_ENTRY * conf_entry)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 *
dat_sr_type_to_str(DAT_SR_TOKEN_TYPE type)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
dat_sr_parse_eof(DAT_OS_FILE * file)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
dat_sr_parse_entry(DAT_OS_FILE * file)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
dat_sr_parse_ia_name(DAT_OS_FILE * file,DAT_SR_CONF_ENTRY * entry)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
dat_sr_parse_api(DAT_OS_FILE * file,DAT_SR_CONF_ENTRY * entry)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
dat_sr_parse_thread_safety(DAT_OS_FILE * file,DAT_SR_CONF_ENTRY * entry)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
dat_sr_parse_default(DAT_OS_FILE * file,DAT_SR_CONF_ENTRY * entry)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
dat_sr_parse_lib_path(DAT_OS_FILE * file,DAT_SR_CONF_ENTRY * entry)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
dat_sr_parse_provider_version(DAT_OS_FILE * file,DAT_SR_CONF_ENTRY * entry)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
dat_sr_parse_ia_params(DAT_OS_FILE * file,DAT_SR_CONF_ENTRY * entry)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
dat_sr_parse_platform_params(DAT_OS_FILE * file,DAT_SR_CONF_ENTRY * entry)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
dat_sr_parse_eoe(DAT_OS_FILE * file,DAT_SR_CONF_ENTRY * entry)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
dat_sr_convert_api(char * str,DAT_SR_API_VERSION * api_version)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
dat_sr_convert_thread_safety(char * str,DAT_BOOLEAN * is_thread_safe)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
dat_sr_convert_default(char * str,DAT_BOOLEAN * is_default)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
dat_sr_convert_provider_version(char * str,DAT_SR_PROVIDER_VERSION * provider_version)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
dat_sr_get_token(DAT_OS_FILE * file,DAT_SR_TOKEN * token)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
dat_sr_put_token(DAT_OS_FILE * file,DAT_SR_TOKEN * token)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
dat_sr_read_token(DAT_OS_FILE * file,DAT_SR_TOKEN * token)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
dat_sr_read_str(DAT_OS_FILE * file,DAT_SR_TOKEN * token,DAT_OS_SIZE token_len)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
dat_sr_read_quoted_str(DAT_OS_FILE * file,DAT_SR_TOKEN * token,DAT_OS_SIZE token_len,DAT_COUNT num_escape_seq)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
dat_sr_read_comment(DAT_OS_FILE * file)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