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 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 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