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 2005 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 mdl_scan_dag(md_impl_t *mdp, 125 int nodeidx, 126 mde_str_cookie_t node_name_cookie, 127 mde_str_cookie_t arc_name_cookie, 128 uint8_t *seenp, 129 int *idxp, 130 mde_cookie_t *stashp, 131 int level) 132 { 133 md_element_t *mdep; 134 135 mdep = &(mdp->mdep[nodeidx]); 136 137 /* see if cookie is infact a node */ 138 if (MDE_TAG(mdep) != MDET_NODE) 139 return (-1); 140 141 /* have we been here before ? */ 142 if (seenp[nodeidx]) 143 return (0); 144 seenp[nodeidx] = 1; 145 146 /* is this node of the type we seek ? */ 147 148 #ifdef DEBUG_LIBMDESC 149 { 150 int x; 151 for (x = 0; x < level; x++) 152 printf("-"); 153 printf("%d (%s)\n", nodeidx, (char *)(mdp->datap + MDE_NAME(mdep))); 154 } 155 #endif 156 157 if (MDE_NAME(mdep) == node_name_cookie) { 158 /* record the node in the list and keep searching */ 159 if (stashp != NULL) { 160 stashp[*idxp] = (mde_cookie_t)nodeidx; 161 } 162 (*idxp)++; 163 #ifdef DEBUG_LIBMDESC 164 printf("\t* %d\n", *idxp); 165 #endif 166 } 167 168 /* 169 * Simply walk the elements in the node. 170 * if we find a matching arc, then recursively call 171 * the subordinate looking for a match 172 */ 173 174 for (mdep++; MDE_TAG(mdep) != MDET_NODE_END; mdep++) { 175 if (MDE_TAG(mdep) == MDET_PROP_ARC && 176 MDE_NAME(mdep) == arc_name_cookie) { 177 int res; 178 179 res = mdl_scan_dag(mdp, 180 (int)mdep->d.prop_idx, 181 node_name_cookie, 182 arc_name_cookie, 183 seenp, idxp, stashp, level+1); 184 185 if (res == -1) 186 return (res); 187 } 188 } 189 190 return (0); 191 } 192