Make the schema_inferiors generation code to compile
[ira/wip.git] / source4 / dsdb / schema / schema_inferiors.c
1 /* 
2    Unix SMB/CIFS mplementation.
3
4    implement possibleInferiors calculation
5    
6    Copyright (C) Andrew Tridgell 2009
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
8
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.
13    
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.
18    
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/>.
21    
22 */
23 /*
24   This module is a C implementation of the logic in the
25   dsdb/samdb/ldb_modules/tests/possibleInferiors.py code
26
27   To understand the C code, please see the python code first
28  */
29
30 #include "includes.h"
31 #include "dsdb/samdb/samdb.h"
32
33
34
35 /*
36   create the SUPCLASSES() list
37  */
38 static char * const *schema_supclasses(struct dsdb_schema *schema, 
39                                        TALLOC_CTX *mem_ctx, struct dsdb_class *schema_class)
40 {
41         char * const *list;
42
43         if (schema_class->supclasses) {
44                 return schema_class->supclasses;
45         }
46
47         list = str_list_make(mem_ctx, NULL, NULL);
48         if (list == NULL) {
49                 DEBUG(0,(__location__ " out of memory\n"));
50                 return NULL;
51         }
52
53         /* Cope with 'top SUP top', ie top is subClassOf top */ 
54         if (strcmp(schema_class->lDAPDisplayName, schema_class->subClassOf) == 0) {
55                 schema_class->supclasses = list;
56                 return list;
57         }
58
59         if (schema_class->subClassOf) {
60                 char **list2;
61                 list = str_list_add(list, schema_class->subClassOf);
62
63                 list2 = schema_supclasses(schema, mem_ctx, dsdb_class_by_lDAPDisplayName(schema, schema_class->subClassOf));
64                 list = str_list_append(list, list2);
65         }
66
67         schema_class->supclasses = list;
68         
69         return list;
70 }
71
72 /*
73   this one is used internally
74   matches SUBCLASSES() python function
75  */
76 static char **schema_subclasses(struct dsdb_schema *schema, TALLOC_CTX *mem_ctx,
77                                 const char * const *oclist)
78 {
79         char **list = str_list_make(mem_ctx, NULL, NULL);
80         int i;
81
82         for (i=0; oclist && oclist[i]; i++) {
83                 struct dsdb_class *schema_class = dsdb_class_by_lDAPDisplayName(schema, oclist[i]);
84                 list = str_list_append(list, schema_class->subclasses);
85         }
86         return list;
87 }
88
89
90 /* 
91    equivalent of the POSSSUPERIORS() python function
92  */
93 static char **schema_posssuperiors(struct dsdb_schema *schema, TALLOC_CTX *mem_ctx,
94                                    struct dsdb_class *schema_class)
95 {
96         char **list = str_list_make(mem_ctx, NULL, NULL);
97
98         if (schema_class->posssuperiors) {
99                 return schema_class->posssuperiors;
100         } else {
101                 char * const *list2 = str_list_make(mem_ctx, NULL, NULL);
102                 list2 = str_list_append(list2, schema_class->systemPossSuperiors);
103                 list2 = str_list_append(list2, schema_class->possSuperiors);
104                 list2 = str_list_append(list2, schema_supclasses(schema, list2, schema_class));
105                 list2 = str_list_append(list2, schema_subclasses(schema, list2, list2));
106
107                 schema_class->posssuperiors = list2;
108                 return schema_class->posssuperiors;
109         }
110
111         return list;
112 }
113
114 static char **schema_subclasses_recurse(struct dsdb_schema *schema, struct dsdb_class *schema_class)
115 {
116         char * const *list = str_list_copy(schema_class, schema_class->subclasses_direct);
117         int i;
118         for (i=0;list && list[i]; i++) {
119                 struct dsdb_class *schema_class2 = dsdb_class_by_lDAPDisplayName(schema, list[i]);
120                 if (schema_class != schema_class2) {
121                         list = str_list_append(list, schema_subclasses_recurse(schema, schema_class2));
122                 }
123         }
124         return list;
125 }
126
127 static void schema_create_subclasses(struct dsdb_schema *schema)
128 {
129         struct dsdb_class *schema_class;
130
131         for (schema_class=schema->classes; schema_class; schema_class=schema_class->next) {
132                 struct dsdb_class *schema_class2 = dsdb_class_by_lDAPDisplayName(schema, schema_class->subClassOf);
133                 schema_class->subclasses_direct = str_list_make(schema_class, NULL, NULL);
134                 if (schema_class != schema_class2) {
135                         if (schema_class2->subclasses_direct == NULL) {
136                                 schema_class2->subclasses_direct = str_list_make(schema_class2, NULL, NULL);
137                         }
138                         schema_class2->subclasses_direct = str_list_add(schema_class2->subclasses_direct, 
139                                                                         schema_class->subClassOf);
140                 }
141         }
142
143         for (schema_class=schema->classes; schema_class; schema_class=schema_class->next) {
144                 schema_class->subclasses = schema_subclasses_recurse(schema, schema_class);
145         }       
146 }
147
148 static void schema_fill_possible_inferiors(struct dsdb_schema *schema, struct dsdb_class *schema_class)
149 {
150         struct dsdb_class *c2;
151
152         for (c2=schema->classes; c2; c2=c2->next) {
153                 char **superiors = schema_posssuperiors(schema, c2, c2);
154                 if (c2->systemOnly == false 
155                     && c2->objectClassCategory != 2 
156                     && c2->objectClassCategory != 3
157                     && str_list_check(superiors, schema_class->lDAPDisplayName)) {
158                         if (c2->possible_inferiors == NULL) {
159                                 c2->possible_inferiors = str_list_make(c2, NULL, NULL);
160                         }
161                         c2->possible_inferiors = str_list_add_unique(c2->possible_inferiors,
162                                                                      schema_class->lDAPDisplayName);
163                 }
164                 talloc_free(superiors);
165         }
166 }
167
168 void schema_fill_constructed(struct dsdb_schema *schema) 
169 {
170         struct dsdb_class *schema_class;
171
172         schema_create_subclasses(schema);
173
174         for (schema_class=schema->classes; schema_class; schema_class=schema_class->next) {
175                 schema_fill_possible_inferiors(schema, schema_class);
176         }
177 }