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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include <sys/types.h>
30 #include <sys/param.h>
31 #ifdef _KERNEL
32 #include <sys/systm.h>
33 #else
34 #include <string.h>
35 #include <strings.h>
36 #endif
37
38 #include <sys/mdesc.h>
39 #include <sys/mdesc_impl.h>
40
41 static int
42 mdl_scan_dag(md_impl_t *mdp,
43 int nodeidx,
44 mde_str_cookie_t node_cookie,
45 mde_str_cookie_t arc_cookie,
46 uint8_t *dseenp,
47 int *idxp,
48 mde_cookie_t *stashp,
49 int level);
50
51
52 int
md_scan_dag(md_t * ptr,mde_cookie_t startnode,mde_str_cookie_t node_name_cookie,mde_str_cookie_t arc_name_cookie,mde_cookie_t * stashp)53 md_scan_dag(md_t *ptr,
54 mde_cookie_t startnode,
55 mde_str_cookie_t node_name_cookie,
56 mde_str_cookie_t arc_name_cookie,
57 mde_cookie_t *stashp)
58 {
59 int res;
60 int idx;
61 uint8_t *seenp;
62 md_impl_t *mdp;
63 int start;
64
65 mdp = (md_impl_t *)ptr;
66
67 /*
68 * Possible the caller was lazy and didn't check the
69 * validitiy of either the node name or the arc name
70 * on calling ... in which case fail to find any
71 * nodes.
72 * This is distinct, from a fail (-1) since we return
73 * that nothing was found.
74 */
75
76 if (node_name_cookie == MDE_INVAL_STR_COOKIE ||
77 arc_name_cookie == MDE_INVAL_STR_COOKIE) return 0;
78
79 /*
80 * if we want to start at the top, start at index 0
81 */
82
83 start = (int)startnode;
84 if (start == MDE_INVAL_ELEM_COOKIE) start = 0;
85
86 /*
87 * Scan from the start point until the first node.
88 */
89 while (MDE_TAG(&mdp->mdep[start]) == MDET_NULL) start++;
90
91 /*
92 * This was a bogus start point if no node found
93 */
94 if (MDE_TAG(&mdp->mdep[start]) != MDET_NODE) {
95 return (-1); /* illegal start node specified */
96 }
97
98 /*
99 * Allocate a recursion mask on the local stack fail
100 * if we can't allocate the recursion detection.
101 */
102 seenp = (uint8_t *)mdp->allocp(mdp->element_count);
103 if (seenp == NULL)
104 return (-1);
105 (void) memset(seenp, 0, mdp->element_count);
106
107 /*
108 * Now build the list of requested nodes.
109 */
110 idx = 0;
111 res = mdl_scan_dag(mdp, start,
112 node_name_cookie, arc_name_cookie,
113 seenp, &idx, stashp, 0);
114
115 mdp->freep(seenp, mdp->element_count);
116
117 return (res >= 0 ? idx : res);
118 }
119
120
121
122
123
124 static int
mdl_scan_dag(md_impl_t * mdp,int nodeidx,mde_str_cookie_t node_name_cookie,mde_str_cookie_t arc_name_cookie,uint8_t * seenp,int * idxp,mde_cookie_t * stashp,int level)125 mdl_scan_dag(md_impl_t *mdp,
126 int nodeidx,
127 mde_str_cookie_t node_name_cookie,
128 mde_str_cookie_t arc_name_cookie,
129 uint8_t *seenp,
130 int *idxp,
131 mde_cookie_t *stashp,
132 int level)
133 {
134 md_element_t *mdep;
135
136 mdep = &(mdp->mdep[nodeidx]);
137
138 /* see if cookie is infact a node */
139 if (MDE_TAG(mdep) != MDET_NODE)
140 return (-1);
141
142 /* have we been here before ? */
143 if (seenp[nodeidx])
144 return (0);
145 seenp[nodeidx] = 1;
146
147 /* is this node of the type we seek ? */
148
149 #ifdef DEBUG_LIBMDESC
150 {
151 int x;
152 for (x = 0; x < level; x++)
153 printf("-");
154 printf("%d (%s)\n", nodeidx, (char *)(mdp->datap + MDE_NAME(mdep)));
155 }
156 #endif
157
158 if (MDE_NAME(mdep) == node_name_cookie) {
159 /* record the node in the list and keep searching */
160 if (stashp != NULL) {
161 stashp[*idxp] = (mde_cookie_t)nodeidx;
162 }
163 (*idxp)++;
164 #ifdef DEBUG_LIBMDESC
165 printf("\t* %d\n", *idxp);
166 #endif
167 }
168
169 /*
170 * Simply walk the elements in the node.
171 * if we find a matching arc, then recursively call
172 * the subordinate looking for a match
173 */
174
175 for (mdep++; MDE_TAG(mdep) != MDET_NODE_END; mdep++) {
176 if (MDE_TAG(mdep) == MDET_PROP_ARC &&
177 MDE_NAME(mdep) == arc_name_cookie) {
178 int res;
179
180 res = mdl_scan_dag(mdp,
181 (int)mdep->d.prop_idx,
182 node_name_cookie,
183 arc_name_cookie,
184 seenp, idxp, stashp, level+1);
185
186 if (res == -1)
187 return (res);
188 }
189 }
190
191 return (0);
192 }
193