2 Unix SMB/CIFS mplementation.
4 implement possibleInferiors calculation
6 Copyright (C) Andrew Tridgell 2009
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 This module is a C implementation of the logic in the
25 dsdb/samdb/ldb_modules/tests/possibleInferiors.py code
27 To understand the C code, please see the python code first
31 #include "dsdb/samdb/samdb.h"
35 create the SUPCLASSES() list
37 static char **schema_supclasses(struct dsdb_schema
*schema
, struct dsdb_class
*schema_class
)
41 if (schema_class
->supclasses
) {
42 return schema_class
->supclasses
;
45 list
= str_list_make_empty(schema_class
);
47 DEBUG(0,(__location__
" out of memory\n"));
51 /* Cope with 'top SUP top', ie top is subClassOf top */
52 if (schema_class
->subClassOf
&&
53 strcmp(schema_class
->lDAPDisplayName
, schema_class
->subClassOf
) == 0) {
54 schema_class
->supclasses
= list
;
58 if (schema_class
->subClassOf
) {
60 list
= str_list_add_const(list
, schema_class
->subClassOf
);
62 list2
= schema_supclasses(schema
,
63 discard_const_p(struct dsdb_class
,
64 dsdb_class_by_lDAPDisplayName(schema
,
65 schema_class
->subClassOf
)));
66 list
= str_list_append_const(list
, list2
);
69 schema_class
->supclasses
= str_list_unique(list
);
75 this one is used internally
76 matches SUBCLASSES() python function
78 static char **schema_subclasses(struct dsdb_schema
*schema
, TALLOC_CTX
*mem_ctx
, char **oclist
)
80 char **list
= str_list_make_empty(mem_ctx
);
83 for (i
=0; oclist
&& oclist
[i
]; i
++) {
84 struct dsdb_class
*schema_class
= dsdb_class_by_lDAPDisplayName(schema
, oclist
[i
]);
86 DEBUG(0, ("ERROR: Unable to locate subClass: '%s'\n", oclist
[i
]));
89 list
= str_list_append_const(list
, schema_class
->subclasses
);
96 equivalent of the POSSSUPERIORS() python function
98 static char **schema_posssuperiors(struct dsdb_schema
*schema
,
99 struct dsdb_class
*schema_class
)
101 if (schema_class
->posssuperiors
== NULL
) {
102 char **list2
= str_list_make_empty(schema_class
);
106 list2
= str_list_append_const(list2
, schema_class
->systemPossSuperiors
);
107 list2
= str_list_append_const(list2
, schema_class
->possSuperiors
);
108 list3
= schema_supclasses(schema
, schema_class
);
109 for (i
=0; list3
&& list3
[i
]; i
++) {
110 struct dsdb_class
*class2
= dsdb_class_by_lDAPDisplayName(schema
, list3
[i
]);
112 DEBUG(0, ("ERROR: Unable to locate supClass: '%s'\n", list3
[i
]));
115 list2
= str_list_append_const(list2
, schema_posssuperiors(schema
, class2
));
117 list2
= str_list_append_const(list2
, schema_subclasses(schema
, list2
, list2
));
119 schema_class
->posssuperiors
= str_list_unique(list2
);
122 return schema_class
->posssuperiors
;
125 static char **schema_subclasses_recurse(struct dsdb_schema
*schema
, struct dsdb_class
*schema_class
)
127 char **list
= str_list_copy_const(schema_class
, schema_class
->subclasses_direct
);
129 for (i
=0;list
&& list
[i
]; i
++) {
130 struct dsdb_class
*schema_class2
= dsdb_class_by_lDAPDisplayName(schema
, list
[i
]);
131 if (schema_class
!= schema_class2
) {
132 list
= str_list_append_const(list
, schema_subclasses_recurse(schema
, schema_class2
));
138 /* Walk down the subClass tree, setting a higher index as we go down
139 * each level. top is 1, subclasses of top are 2, etc */
140 void schema_subclasses_order_recurse(struct dsdb_schema
*schema
, struct dsdb_class
*schema_class
, int order
)
142 const char **list
= schema_class
->subclasses_direct
;
144 schema_class
->subClass_order
= order
;
145 for (i
=0;list
&& list
[i
]; i
++) {
146 struct dsdb_class
*schema_class2
= dsdb_class_by_lDAPDisplayName(schema
, list
[i
]);
147 schema_subclasses_order_recurse(schema
, schema_class2
, order
+1);
152 static void schema_create_subclasses(struct dsdb_schema
*schema
)
154 struct dsdb_class
*schema_class
;
156 for (schema_class
=schema
->classes
; schema_class
; schema_class
=schema_class
->next
) {
157 struct dsdb_class
*schema_class2
= dsdb_class_by_lDAPDisplayName(schema
, schema_class
->subClassOf
);
158 if (schema_class2
== NULL
) {
159 DEBUG(0,("ERROR: no subClassOf for '%s'\n", schema_class
->lDAPDisplayName
));
162 if (schema_class2
&& schema_class
!= schema_class2
) {
163 if (schema_class2
->subclasses_direct
== NULL
) {
164 schema_class2
->subclasses_direct
= str_list_make_empty(schema_class2
);
166 schema_class2
->subclasses_direct
= str_list_add_const(schema_class2
->subclasses_direct
,
167 schema_class
->lDAPDisplayName
);
171 for (schema_class
=schema
->classes
; schema_class
; schema_class
=schema_class
->next
) {
172 schema_class
->subclasses
= str_list_unique(schema_subclasses_recurse(schema
, schema_class
));
174 /* Initilise the subClass order, to ensure we can't have uninitilised sort on the subClass hirarchy */
175 schema_class
->subClass_order
= 0;
178 schema_subclasses_order_recurse(schema
, dsdb_class_by_lDAPDisplayName(schema
, "top"), 1);
181 static void schema_fill_possible_inferiors(struct dsdb_schema
*schema
, struct dsdb_class
*schema_class
)
183 struct dsdb_class
*c2
;
185 for (c2
=schema
->classes
; c2
; c2
=c2
->next
) {
186 char **superiors
= schema_posssuperiors(schema
, c2
);
187 if (c2
->systemOnly
== false
188 && c2
->objectClassCategory
!= 2
189 && c2
->objectClassCategory
!= 3
190 && str_list_check(superiors
, schema_class
->lDAPDisplayName
)) {
191 if (schema_class
->possibleInferiors
== NULL
) {
192 schema_class
->possibleInferiors
= str_list_make_empty(schema_class
);
194 schema_class
->possibleInferiors
= str_list_add_const(schema_class
->possibleInferiors
,
195 c2
->lDAPDisplayName
);
198 schema_class
->possibleInferiors
= str_list_unique(schema_class
->possibleInferiors
);
201 static void schema_fill_system_possible_inferiors(struct dsdb_schema
*schema
, struct dsdb_class
*schema_class
)
203 struct dsdb_class
*c2
;
205 for (c2
=schema
->classes
; c2
; c2
=c2
->next
) {
206 char **superiors
= schema_posssuperiors(schema
, c2
);
207 if (c2
->objectClassCategory
!= 2
208 && c2
->objectClassCategory
!= 3
209 && str_list_check(superiors
, schema_class
->lDAPDisplayName
)) {
210 if (schema_class
->systemPossibleInferiors
== NULL
) {
211 schema_class
->systemPossibleInferiors
= str_list_make_empty(schema_class
);
213 schema_class
->systemPossibleInferiors
= str_list_add_const(schema_class
->systemPossibleInferiors
,
214 c2
->lDAPDisplayName
);
217 schema_class
->systemPossibleInferiors
= str_list_unique(schema_class
->systemPossibleInferiors
);
221 fill in a string class name from a governs_ID
223 static void schema_fill_from_class_one(struct dsdb_schema
*schema
, struct dsdb_class
*c
,
224 const char **s
, uint32_t id
)
226 if (*s
== NULL
&& id
!= 0) {
227 struct dsdb_class
*c2
= dsdb_class_by_governsID_id(schema
, id
);
229 *s
= c2
->lDAPDisplayName
;
235 fill in a list of string class names from a governs_ID list
237 static void schema_fill_from_class_list(struct dsdb_schema
*schema
, struct dsdb_class
*c
,
238 const char ***s
, uint32_t *ids
)
240 if (*s
== NULL
&& ids
!= NULL
) {
242 for (i
=0;ids
[i
];i
++) ;
243 *s
= talloc_array(c
, const char *, i
+1);
244 for (i
=0;ids
[i
];i
++) {
245 struct dsdb_class
*c2
= dsdb_class_by_governsID_id(schema
, ids
[i
]);
247 (*s
)[i
] = c2
->lDAPDisplayName
;
257 fill in a list of string attribute names from a attributeID list
259 static void schema_fill_from_attribute_list(struct dsdb_schema
*schema
, struct dsdb_class
*c
,
260 const char ***s
, uint32_t *ids
)
262 if (*s
== NULL
&& ids
!= NULL
) {
264 for (i
=0;ids
[i
];i
++) ;
265 *s
= talloc_array(c
, const char *, i
+1);
266 for (i
=0;ids
[i
];i
++) {
267 struct dsdb_attribute
*a
= dsdb_attribute_by_attributeID_id(schema
, ids
[i
]);
269 (*s
)[i
] = a
->lDAPDisplayName
;
279 if the schema came from DRS then some attributes will be setup as IDs
281 static void schema_fill_from_ids(struct dsdb_schema
*schema
)
283 struct dsdb_class
*c
;
284 for (c
=schema
->classes
; c
; c
=c
->next
) {
285 schema_fill_from_class_one(schema
, c
, &c
->subClassOf
, c
->subClassOf_id
);
286 schema_fill_from_attribute_list(schema
, c
, &c
->systemMayContain
, c
->systemMayContain_ids
);
287 schema_fill_from_attribute_list(schema
, c
, &c
->systemMustContain
, c
->systemMustContain_ids
);
288 schema_fill_from_attribute_list(schema
, c
, &c
->mustContain
, c
->mustContain_ids
);
289 schema_fill_from_attribute_list(schema
, c
, &c
->mayContain
, c
->mayContain_ids
);
290 schema_fill_from_class_list(schema
, c
, &c
->possSuperiors
, c
->possSuperiors_ids
);
291 schema_fill_from_class_list(schema
, c
, &c
->systemPossSuperiors
, c
->systemPossSuperiors_ids
);
292 schema_fill_from_class_list(schema
, c
, &c
->systemAuxiliaryClass
, c
->systemAuxiliaryClass_ids
);
293 schema_fill_from_class_list(schema
, c
, &c
->auxiliaryClass
, c
->auxiliaryClass_ids
);
297 void schema_fill_constructed(struct dsdb_schema
*schema
)
299 struct dsdb_class
*schema_class
;
301 schema_fill_from_ids(schema
);
303 schema_create_subclasses(schema
);
305 for (schema_class
=schema
->classes
; schema_class
; schema_class
=schema_class
->next
) {
306 schema_fill_possible_inferiors(schema
, schema_class
);
307 schema_fill_system_possible_inferiors(schema
, schema_class
);
310 /* free up our internal cache elements */
311 for (schema_class
=schema
->classes
; schema_class
; schema_class
=schema_class
->next
) {
312 talloc_free(schema_class
->supclasses
);
313 talloc_free(schema_class
->subclasses_direct
);
314 talloc_free(schema_class
->subclasses
);
315 talloc_free(schema_class
->posssuperiors
);
316 schema_class
->supclasses
= NULL
;
317 schema_class
->subclasses_direct
= NULL
;
318 schema_class
->subclasses
= NULL
;
319 schema_class
->posssuperiors
= NULL
;