added a LDB_ATTR_FLAG_FIXED so the schema module can mark attributes
[tprouty/samba.git] / source4 / lib / ldb / common / ldb_attributes.c
1 /* 
2    ldb database library
3
4    Copyright (C) Andrew Tridgell  2005
5
6      ** NOTE! The following LGPL license applies to the ldb
7      ** library. This does NOT imply that all of Samba is released
8      ** under the LGPL
9    
10    This library is free software; you can redistribute it and/or
11    modify it under the terms of the GNU Lesser General Public
12    License as published by the Free Software Foundation; either
13    version 3 of the License, or (at your option) any later version.
14
15    This library is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    Lesser General Public License for more details.
19
20    You should have received a copy of the GNU Lesser General Public
21    License along with this library; if not, see <http://www.gnu.org/licenses/>.
22 */
23 /*
24   register handlers for specific attributes and objectclass relationships
25
26   this allows a backend to store its schema information in any format
27   it likes (or to not have any schema information at all) while keeping the 
28   message matching logic generic
29 */
30
31 #include "ldb_includes.h"
32
33 /*
34   add a attribute to the ldb_schema
35
36   if flags contains LDB_ATTR_FLAG_ALLOCATED
37   the attribute name string will be copied using
38   talloc_strdup(), otherwise it needs to be a static const
39   string at least with a lifetime longer than the ldb struct!
40   
41   the ldb_schema_syntax structure should be a pointer
42   to a static const struct or at least it needs to be
43   a struct with a longer lifetime than the ldb context!
44
45 */
46 int ldb_schema_attribute_add_with_syntax(struct ldb_context *ldb, 
47                                          const char *attribute,
48                                          unsigned flags,
49                                          const struct ldb_schema_syntax *syntax)
50 {
51         int i, n;
52         struct ldb_schema_attribute *a;
53
54         n = ldb->schema.num_attributes + 1;
55
56         a = talloc_realloc(ldb, ldb->schema.attributes,
57                            struct ldb_schema_attribute, n);
58         if (a == NULL) {
59                 ldb_oom(ldb);
60                 return -1;
61         }
62         ldb->schema.attributes = a;
63
64         for (i = 0; i < ldb->schema.num_attributes; i++) {
65                 if (ldb_attr_cmp(attribute, a[i].name) < 0) {
66                         memmove(a+i+1, a+i, sizeof(*a) * (ldb->schema.num_attributes-i));
67                         break;
68                 }
69         }
70
71         a[i].name       = attribute;
72         a[i].flags      = flags;
73         a[i].syntax     = syntax;
74
75         if (a[i].flags & LDB_ATTR_FLAG_ALLOCATED) {
76                 a[i].name = talloc_strdup(a, a[i].name);
77                 if (a[i].name == NULL) {
78                         ldb_oom(ldb);
79                         return -1;
80                 }
81         }
82
83         ldb->schema.num_attributes++;
84         return 0;
85 }
86
87 static const struct ldb_schema_syntax ldb_syntax_default = {
88         .name            = LDB_SYNTAX_OCTET_STRING,
89         .ldif_read_fn    = ldb_handler_copy,
90         .ldif_write_fn   = ldb_handler_copy,
91         .canonicalise_fn = ldb_handler_copy,
92         .comparison_fn   = ldb_comparison_binary
93 };
94
95 static const struct ldb_schema_attribute ldb_attribute_default = {
96         .name   = NULL,
97         .flags  = 0,
98         .syntax = &ldb_syntax_default
99 };
100
101 /*
102   return the attribute handlers for a given attribute
103 */
104 const struct ldb_schema_attribute *ldb_schema_attribute_by_name(struct ldb_context *ldb,
105                                                                 const char *name)
106 {
107         int i, e, b = 0, r;
108         const struct ldb_schema_attribute *def = &ldb_attribute_default;
109
110         /* as handlers are sorted, '*' must be the first if present */
111         if (strcmp(ldb->schema.attributes[0].name, "*") == 0) {
112                 def = &ldb->schema.attributes[0];
113                 b = 1;
114         }
115
116         /* do a binary search on the array */
117         e = ldb->schema.num_attributes - 1;
118
119         while (b <= e) {
120
121                 i = (b + e) / 2;
122
123                 r = ldb_attr_cmp(name, ldb->schema.attributes[i].name);
124                 if (r == 0) {
125                         return &ldb->schema.attributes[i];
126                 }
127                 if (r < 0) {
128                         e = i - 1;
129                 } else {
130                         b = i + 1;
131                 }
132
133         }
134
135         return def;
136 }
137
138
139 /*
140   add to the list of ldif handlers for this ldb context
141 */
142 void ldb_schema_attribute_remove(struct ldb_context *ldb, const char *name)
143 {
144         const struct ldb_schema_attribute *a;
145         int i;
146
147         a = ldb_schema_attribute_by_name(ldb, name);
148         if (a == NULL) {
149                 return;
150         }
151
152         /* FIXED attributes are never removed */
153         if (a->flags & LDB_ATTR_FLAG_FIXED) {
154                 return;
155         }
156
157         if (a->flags & LDB_ATTR_FLAG_ALLOCATED) {
158                 talloc_free(discard_const_p(char, a->name));
159         }
160
161         i = a - ldb->schema.attributes;
162         if (i < ldb->schema.num_attributes - 1) {
163                 memmove(&ldb->schema.attributes[i], 
164                         a+1, sizeof(*a) * (ldb->schema.num_attributes-(i+1)));
165         }
166
167         ldb->schema.num_attributes--;
168 }
169
170 /*
171   setup a attribute handler using a standard syntax
172 */
173 int ldb_schema_attribute_add(struct ldb_context *ldb,
174                              const char *attribute,
175                              unsigned flags,
176                              const char *syntax)
177 {
178         const struct ldb_schema_syntax *s = ldb_standard_syntax_by_name(ldb, syntax);
179         return ldb_schema_attribute_add_with_syntax(ldb, attribute, flags, s);
180 }
181
182 /*
183   setup the attribute handles for well known attributes
184 */
185 int ldb_setup_wellknown_attributes(struct ldb_context *ldb)
186 {
187         const struct {
188                 const char *attr;
189                 const char *syntax;
190         } wellknown[] = {
191                 { "dn", LDB_SYNTAX_DN },
192                 { "distinguishedName", LDB_SYNTAX_DN },
193                 { "cn", LDB_SYNTAX_DIRECTORY_STRING },
194                 { "dc", LDB_SYNTAX_DIRECTORY_STRING },
195                 { "ou", LDB_SYNTAX_DIRECTORY_STRING },
196                 { "objectClass", LDB_SYNTAX_OBJECTCLASS }
197         };
198         int i;
199         int ret;
200
201         for (i=0;i<ARRAY_SIZE(wellknown);i++) {
202                 ret = ldb_schema_attribute_add(ldb, wellknown[i].attr, 0,
203                                                wellknown[i].syntax);
204                 if (ret != LDB_SUCCESS) {
205                         return ret;
206                 }
207         }
208
209         return LDB_SUCCESS;
210 }
211