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