~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/lib/ldb/modules/objectclass.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
   ldb database library
 
3
 
 
4
   Copyright (C) Simo Sorce  2006
 
5
   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2006
 
6
 
 
7
     ** NOTE! The following LGPL license applies to the ldb
 
8
     ** library. This does NOT imply that all of Samba is released
 
9
     ** under the LGPL
 
10
   
 
11
   This library is free software; you can redistribute it and/or
 
12
   modify it under the terms of the GNU Lesser General Public
 
13
   License as published by the Free Software Foundation; either
 
14
   version 3 of the License, or (at your option) any later version.
 
15
 
 
16
   This library is distributed in the hope that it will be useful,
 
17
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
19
   Lesser General Public License for more details.
 
20
 
 
21
   You should have received a copy of the GNU Lesser General Public
 
22
   License along with this library; if not, see <http://www.gnu.org/licenses/>.
 
23
*/
 
24
 
 
25
/*
 
26
 *  Name: ldb
 
27
 *
 
28
 *  Component: objectClass sorting module
 
29
 *
 
30
 *  Description: sort the objectClass attribute into the class hierarchy
 
31
 *
 
32
 *  Author: Andrew Bartlett
 
33
 */
 
34
 
 
35
#include "includes.h"
 
36
#include "ldb/include/includes.h"
 
37
 
 
38
struct oc_context {
 
39
 
 
40
        enum oc_step {OC_DO_REQ, OC_SEARCH_SELF, OC_DO_MOD} step;
 
41
 
 
42
        struct ldb_module *module;
 
43
        struct ldb_request *orig_req;
 
44
 
 
45
        struct ldb_request *down_req;
 
46
 
 
47
        struct ldb_request *search_req;
 
48
        struct ldb_reply *search_res;
 
49
 
 
50
        struct ldb_request *mod_req;
 
51
};
 
52
 
 
53
struct class_list {
 
54
        struct class_list *prev, *next;
 
55
        const char *objectclass;
 
56
};
 
57
 
 
58
static struct ldb_handle *oc_init_handle(struct ldb_request *req, struct ldb_module *module)
 
59
{
 
60
        struct oc_context *ac;
 
61
        struct ldb_handle *h;
 
62
 
 
63
        h = talloc_zero(req, struct ldb_handle);
 
64
        if (h == NULL) {
 
65
                ldb_set_errstring(module->ldb, "Out of Memory");
 
66
                return NULL;
 
67
        }
 
68
 
 
69
        h->module = module;
 
70
 
 
71
        ac = talloc_zero(h, struct oc_context);
 
72
        if (ac == NULL) {
 
73
                ldb_set_errstring(module->ldb, "Out of Memory");
 
74
                talloc_free(h);
 
75
                return NULL;
 
76
        }
 
77
 
 
78
        h->private_data = (void *)ac;
 
79
 
 
80
        h->state = LDB_ASYNC_INIT;
 
81
        h->status = LDB_SUCCESS;
 
82
 
 
83
        ac->module = module;
 
84
        ac->orig_req = req;
 
85
 
 
86
        return h;
 
87
}
 
88
 
 
89
static int objectclass_sort(struct ldb_module *module,
 
90
                            TALLOC_CTX *mem_ctx,
 
91
                            struct ldb_message_element *objectclass_element,
 
92
                            struct class_list **sorted_out) 
 
93
{
 
94
        int i;
 
95
        int layer;
 
96
        struct class_list *sorted = NULL, *parent_class = NULL,
 
97
                *subclass = NULL, *unsorted = NULL, *current, *poss_subclass;
 
98
        /* DESIGN:
 
99
         *
 
100
         * We work on 4 different 'bins' (implemented here as linked lists):
 
101
         *
 
102
         * * sorted:       the eventual list, in the order we wish to push
 
103
         *                 into the database.  This is the only ordered list.
 
104
         *
 
105
         * * parent_class: The current parent class 'bin' we are
 
106
         *                 trying to find subclasses for
 
107
         *
 
108
         * * subclass:     The subclasses we have found so far
 
109
         *
 
110
         * * unsorted:     The remaining objectClasses
 
111
         *
 
112
         * The process is a matter of filtering objectClasses up from
 
113
         * unsorted into sorted.  Order is irrelevent in the later 3 'bins'.
 
114
         * 
 
115
         * We start with 'top' (found and promoted to parent_class
 
116
         * initially).  Then we find (in unsorted) all the direct
 
117
         * subclasses of 'top'.  parent_classes is concatenated onto
 
118
         * the end of 'sorted', and subclass becomes the list in
 
119
         * parent_class.
 
120
         *
 
121
         * We then repeat, until we find no more subclasses.  Any left
 
122
         * over classes are added to the end.
 
123
         *
 
124
         */
 
125
 
 
126
        /* Firstly, dump all the objectClass elements into the
 
127
         * unsorted bin, except for 'top', which is special */
 
128
        for (i=0; i < objectclass_element->num_values; i++) {
 
129
                current = talloc(mem_ctx, struct class_list);
 
130
                if (!current) {
 
131
                        ldb_set_errstring(module->ldb, "objectclass: out of memory allocating objectclass list");
 
132
                        talloc_free(mem_ctx);
 
133
                        return LDB_ERR_OPERATIONS_ERROR;
 
134
                }
 
135
                current->objectclass = (const char *)objectclass_element->values[i].data;
 
136
 
 
137
                /* this is the root of the tree.  We will start
 
138
                 * looking for subclasses from here */
 
139
                if (ldb_attr_cmp("top", current->objectclass) == 0) {
 
140
                        DLIST_ADD(parent_class, current);
 
141
                } else {
 
142
                        DLIST_ADD(unsorted, current);
 
143
                }
 
144
        }
 
145
 
 
146
        /* DEBUGGING aid:  how many layers are we down now? */
 
147
        layer = 0;
 
148
        do {
 
149
                layer++;
 
150
                /* Find all the subclasses of classes in the
 
151
                 * parent_classes.  Push them onto the subclass list */
 
152
 
 
153
                /* Ensure we don't bother if there are no unsorted entries left */
 
154
                for (current = parent_class; unsorted && current; current = current->next) {
 
155
                        const char **subclasses = ldb_subclass_list(module->ldb, current->objectclass);
 
156
 
 
157
                        /* Walk the list of possible subclasses in unsorted */
 
158
                        for (poss_subclass = unsorted; poss_subclass; ) {
 
159
                                struct class_list *next;
 
160
                                
 
161
                                /* Save the next pointer, as the DLIST_ macros will change poss_subclass->next */
 
162
                                next = poss_subclass->next;
 
163
 
 
164
                                for (i = 0; subclasses && subclasses[i]; i++) {
 
165
                                        if (ldb_attr_cmp(poss_subclass->objectclass, subclasses[i]) == 0) {
 
166
                                                DLIST_REMOVE(unsorted, poss_subclass);
 
167
                                                DLIST_ADD(subclass, poss_subclass);
 
168
 
 
169
                                                break;
 
170
                                        }
 
171
                                }
 
172
                                poss_subclass = next;
 
173
                        }
 
174
                }
 
175
 
 
176
                /* Now push the parent_classes as sorted, we are done with
 
177
                these.  Add to the END of the list by concatenation */
 
178
                DLIST_CONCATENATE(sorted, parent_class, struct class_list *);
 
179
 
 
180
                /* and now find subclasses of these */
 
181
                parent_class = subclass;
 
182
                subclass = NULL;
 
183
 
 
184
                /* If we didn't find any subclasses we will fall out
 
185
                 * the bottom here */
 
186
        } while (parent_class);
 
187
 
 
188
        /* This shouldn't happen, and would break MMC, but we can't
 
189
         * afford to loose objectClasses.  Perhaps there was no 'top',
 
190
         * or some other schema error? 
 
191
         *
 
192
         * Detecting schema errors is the job of the schema module, so
 
193
         * at this layer we just try not to loose data
 
194
         */
 
195
        DLIST_CONCATENATE(sorted, unsorted, struct class_list *);
 
196
 
 
197
        *sorted_out = sorted;
 
198
        return LDB_SUCCESS;
 
199
}
 
200
 
 
201
static int objectclass_add(struct ldb_module *module, struct ldb_request *req)
 
202
{
 
203
        struct ldb_message_element *objectclass_element;
 
204
        struct class_list *sorted, *current;
 
205
        struct ldb_request *down_req;
 
206
        struct ldb_message *msg;
 
207
        int ret;
 
208
        TALLOC_CTX *mem_ctx;
 
209
 
 
210
        ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectclass_add\n");
 
211
 
 
212
        if (ldb_dn_is_special(req->op.add.message->dn)) { /* do not manipulate our control entries */
 
213
                return ldb_next_request(module, req);
 
214
        }
 
215
        
 
216
        objectclass_element = ldb_msg_find_element(req->op.add.message, "objectClass");
 
217
 
 
218
        /* If no part of this add has an objectClass, then we don't
 
219
         * need to make any changes. cn=rootdse doesn't have an objectClass */
 
220
        if (!objectclass_element) {
 
221
                return ldb_next_request(module, req);
 
222
        }
 
223
 
 
224
        mem_ctx = talloc_new(req);
 
225
        if (mem_ctx == NULL) {
 
226
                return LDB_ERR_OPERATIONS_ERROR;
 
227
        }
 
228
 
 
229
        ret = objectclass_sort(module, mem_ctx, objectclass_element, &sorted);
 
230
        if (ret != LDB_SUCCESS) {
 
231
                return ret;
 
232
        }
 
233
 
 
234
        /* prepare the first operation */
 
235
        down_req = talloc(req, struct ldb_request);
 
236
        if (down_req == NULL) {
 
237
                ldb_set_errstring(module->ldb, "Out of memory!");
 
238
                talloc_free(mem_ctx);
 
239
                return LDB_ERR_OPERATIONS_ERROR;
 
240
        }
 
241
 
 
242
        *down_req = *req; /* copy the request */
 
243
 
 
244
        down_req->op.add.message = msg = ldb_msg_copy_shallow(down_req, req->op.add.message);
 
245
 
 
246
        if (down_req->op.add.message == NULL) {
 
247
                talloc_free(mem_ctx);
 
248
                return LDB_ERR_OPERATIONS_ERROR;
 
249
        }
 
250
 
 
251
        ldb_msg_remove_attr(msg, "objectClass");
 
252
        ret = ldb_msg_add_empty(msg, "objectClass", 0, NULL);
 
253
        
 
254
        if (ret != LDB_SUCCESS) {
 
255
                talloc_free(mem_ctx);
 
256
                return ret;
 
257
        }
 
258
 
 
259
        /* We must completely replace the existing objectClass entry,
 
260
         * because we need it sorted */
 
261
 
 
262
        /* Move from the linked list back into an ldb msg */
 
263
        for (current = sorted; current; current = current->next) {
 
264
                ret = ldb_msg_add_string(msg, "objectClass", current->objectclass);
 
265
                if (ret != LDB_SUCCESS) {
 
266
                        ldb_set_errstring(module->ldb, "objectclass: could not re-add sorted objectclass to modify msg");
 
267
                        talloc_free(mem_ctx);
 
268
                        return ret;
 
269
                }
 
270
        }
 
271
 
 
272
        talloc_free(mem_ctx);
 
273
        ret = ldb_msg_sanity_check(module->ldb, msg);
 
274
 
 
275
        if (ret != LDB_SUCCESS) {
 
276
                return ret;
 
277
        }
 
278
 
 
279
        /* go on with the call chain */
 
280
        ret = ldb_next_request(module, down_req);
 
281
 
 
282
        /* do not free down_req as the call results may be linked to it,
 
283
         * it will be freed when the upper level request get freed */
 
284
        if (ret == LDB_SUCCESS) {
 
285
                req->handle = down_req->handle;
 
286
        }
 
287
        return ret;
 
288
}
 
289
 
 
290
static int objectclass_modify(struct ldb_module *module, struct ldb_request *req)
 
291
{
 
292
        struct ldb_message_element *objectclass_element;
 
293
        struct ldb_message *msg;
 
294
        ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectclass_modify\n");
 
295
 
 
296
        if (ldb_dn_is_special(req->op.mod.message->dn)) { /* do not manipulate our control entries */
 
297
                return ldb_next_request(module, req);
 
298
        }
 
299
        
 
300
        objectclass_element = ldb_msg_find_element(req->op.mod.message, "objectClass");
 
301
 
 
302
        /* If no part of this touches the objectClass, then we don't
 
303
         * need to make any changes.  */
 
304
        /* If the only operation is the deletion of the objectClass then go on */
 
305
        if (!objectclass_element) {
 
306
                return ldb_next_request(module, req);
 
307
        }
 
308
 
 
309
        switch (objectclass_element->flags & LDB_FLAG_MOD_MASK) {
 
310
        case LDB_FLAG_MOD_DELETE:
 
311
                /* Delete everything?  Probably totally illigal, but hey! */
 
312
                if (objectclass_element->num_values == 0) {
 
313
                        return ldb_next_request(module, req);
 
314
                }
 
315
                break;
 
316
        case LDB_FLAG_MOD_REPLACE:
 
317
        {
 
318
                struct ldb_request *down_req;
 
319
                struct class_list *sorted, *current;
 
320
                TALLOC_CTX *mem_ctx;
 
321
                int ret;
 
322
                mem_ctx = talloc_new(req);
 
323
                if (mem_ctx == NULL) {
 
324
                        return LDB_ERR_OPERATIONS_ERROR;
 
325
                }
 
326
 
 
327
                /* prepare the first operation */
 
328
                down_req = talloc(req, struct ldb_request);
 
329
                if (down_req == NULL) {
 
330
                        ldb_set_errstring(module->ldb, "Out of memory!");
 
331
                        talloc_free(mem_ctx);
 
332
                        return LDB_ERR_OPERATIONS_ERROR;
 
333
                }
 
334
                
 
335
                *down_req = *req; /* copy the request */
 
336
                
 
337
                down_req->op.mod.message = msg = ldb_msg_copy_shallow(down_req, req->op.mod.message);
 
338
                
 
339
                if (down_req->op.add.message == NULL) {
 
340
                        talloc_free(mem_ctx);
 
341
                        return LDB_ERR_OPERATIONS_ERROR;
 
342
                }
 
343
                
 
344
                ret = objectclass_sort(module, mem_ctx, objectclass_element, &sorted);
 
345
                if (ret != LDB_SUCCESS) {
 
346
                        return ret;
 
347
                }
 
348
 
 
349
                /* We must completely replace the existing objectClass entry,
 
350
                 * because we need it sorted */
 
351
                
 
352
                ldb_msg_remove_attr(msg, "objectClass");
 
353
                ret = ldb_msg_add_empty(msg, "objectClass", LDB_FLAG_MOD_REPLACE, NULL);
 
354
                
 
355
                if (ret != LDB_SUCCESS) {
 
356
                        talloc_free(mem_ctx);
 
357
                        return ret;
 
358
                }
 
359
 
 
360
                /* Move from the linked list back into an ldb msg */
 
361
                for (current = sorted; current; current = current->next) {
 
362
                        ret = ldb_msg_add_string(msg, "objectClass", current->objectclass);
 
363
                        if (ret != LDB_SUCCESS) {
 
364
                                ldb_set_errstring(module->ldb, "objectclass: could not re-add sorted objectclass to modify msg");
 
365
                                talloc_free(mem_ctx);
 
366
                                return ret;
 
367
                        }
 
368
                }
 
369
                
 
370
                talloc_free(mem_ctx);
 
371
 
 
372
                ret = ldb_msg_sanity_check(module->ldb, msg);
 
373
                if (ret != LDB_SUCCESS) {
 
374
                        talloc_free(mem_ctx);
 
375
                        return ret;
 
376
                }
 
377
                
 
378
                /* go on with the call chain */
 
379
                ret = ldb_next_request(module, down_req);
 
380
                
 
381
                /* do not free down_req as the call results may be linked to it,
 
382
                 * it will be freed when the upper level request get freed */
 
383
                if (ret == LDB_SUCCESS) {
 
384
                        req->handle = down_req->handle;
 
385
                }
 
386
                return ret;
 
387
        }
 
388
        }
 
389
 
 
390
        {
 
391
                struct ldb_handle *h;
 
392
                struct oc_context *ac;
 
393
                
 
394
                h = oc_init_handle(req, module);
 
395
                if (!h) {
 
396
                        return LDB_ERR_OPERATIONS_ERROR;
 
397
                }
 
398
                ac = talloc_get_type(h->private_data, struct oc_context);
 
399
                
 
400
                /* return or own handle to deal with this call */
 
401
                req->handle = h;
 
402
                
 
403
                /* prepare the first operation */
 
404
                ac->down_req = talloc(ac, struct ldb_request);
 
405
                if (ac->down_req == NULL) {
 
406
                        ldb_set_errstring(module->ldb, "Out of memory!");
 
407
                        return LDB_ERR_OPERATIONS_ERROR;
 
408
                }
 
409
                
 
410
                *(ac->down_req) = *req; /* copy the request */
 
411
                
 
412
                ac->down_req->context = NULL;
 
413
                ac->down_req->callback = NULL;
 
414
                ldb_set_timeout_from_prev_req(module->ldb, req, ac->down_req);
 
415
                
 
416
                ac->step = OC_DO_REQ;
 
417
 
 
418
                return ldb_next_request(module, ac->down_req);
 
419
        }
 
420
}
 
421
 
 
422
static int get_self_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
 
423
{
 
424
        struct oc_context *ac;
 
425
 
 
426
        if (!context || !ares) {
 
427
                ldb_set_errstring(ldb, "NULL Context or Result in callback");
 
428
                return LDB_ERR_OPERATIONS_ERROR;
 
429
        }
 
430
 
 
431
        ac = talloc_get_type(context, struct oc_context);
 
432
 
 
433
        /* we are interested only in the single reply (base search) we receive here */
 
434
        if (ares->type == LDB_REPLY_ENTRY) {
 
435
                if (ac->search_res != NULL) {
 
436
                        ldb_set_errstring(ldb, "Too many results");
 
437
                        talloc_free(ares);
 
438
                        return LDB_ERR_OPERATIONS_ERROR;
 
439
                }
 
440
 
 
441
                ac->search_res = talloc_move(ac, &ares);
 
442
        } else {
 
443
                talloc_free(ares);
 
444
        }
 
445
 
 
446
        return LDB_SUCCESS;
 
447
}
 
448
 
 
449
static int objectclass_search_self(struct ldb_handle *h) {
 
450
 
 
451
        struct oc_context *ac;
 
452
        static const char * const attrs[] = { "objectClass", NULL };
 
453
 
 
454
        ac = talloc_get_type(h->private_data, struct oc_context);
 
455
 
 
456
        /* prepare the search operation */
 
457
        ac->search_req = talloc_zero(ac, struct ldb_request);
 
458
        if (ac->search_req == NULL) {
 
459
                ldb_debug(ac->module->ldb, LDB_DEBUG_ERROR, "Out of Memory!\n");
 
460
                return LDB_ERR_OPERATIONS_ERROR;
 
461
        }
 
462
 
 
463
        ac->search_req->operation = LDB_SEARCH;
 
464
        ac->search_req->op.search.base = ac->orig_req->op.mod.message->dn;
 
465
        ac->search_req->op.search.scope = LDB_SCOPE_BASE;
 
466
        ac->search_req->op.search.tree = ldb_parse_tree(ac->search_req, NULL);
 
467
        if (ac->search_req->op.search.tree == NULL) {
 
468
                ldb_set_errstring(ac->module->ldb, "objectclass: Internal error producing null search");
 
469
                return LDB_ERR_OPERATIONS_ERROR;
 
470
        }
 
471
        ac->search_req->op.search.attrs = attrs;
 
472
        ac->search_req->controls = NULL;
 
473
        ac->search_req->context = ac;
 
474
        ac->search_req->callback = get_self_callback;
 
475
        ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->search_req);
 
476
 
 
477
        ac->step = OC_SEARCH_SELF;
 
478
 
 
479
        return ldb_next_request(ac->module, ac->search_req);
 
480
}
 
481
 
 
482
static int objectclass_do_mod(struct ldb_handle *h) {
 
483
 
 
484
        struct oc_context *ac;
 
485
        struct ldb_message_element *objectclass_element;
 
486
        struct ldb_message *msg;
 
487
        TALLOC_CTX *mem_ctx;
 
488
        struct class_list *sorted, *current;
 
489
        int ret;
 
490
      
 
491
        ac = talloc_get_type(h->private_data, struct oc_context);
 
492
 
 
493
        mem_ctx = talloc_new(ac);
 
494
        if (mem_ctx == NULL) {
 
495
                return LDB_ERR_OPERATIONS_ERROR;
 
496
        }
 
497
 
 
498
        ac->mod_req = talloc(ac, struct ldb_request);
 
499
        if (ac->mod_req == NULL) {
 
500
                talloc_free(mem_ctx);
 
501
                return LDB_ERR_OPERATIONS_ERROR;
 
502
        }
 
503
 
 
504
        ac->mod_req->operation = LDB_MODIFY;
 
505
        ac->mod_req->controls = NULL;
 
506
        ac->mod_req->context = ac;
 
507
        ac->mod_req->callback = NULL;
 
508
        ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->mod_req);
 
509
        
 
510
        /* use a new message structure */
 
511
        ac->mod_req->op.mod.message = msg = ldb_msg_new(ac->mod_req);
 
512
        if (msg == NULL) {
 
513
                ldb_set_errstring(ac->module->ldb, "objectclass: could not create new modify msg");
 
514
                talloc_free(mem_ctx);
 
515
                return LDB_ERR_OPERATIONS_ERROR;
 
516
        }
 
517
 
 
518
        /* This is now the objectClass list from the database */
 
519
        objectclass_element = ldb_msg_find_element(ac->search_res->message, 
 
520
                                                   "objectClass");
 
521
        if (!objectclass_element) {
 
522
                /* Where did it go?  Move along now, nothing to see here */
 
523
                talloc_free(mem_ctx);
 
524
                return LDB_SUCCESS;
 
525
        }
 
526
        
 
527
        /* modify dn */
 
528
        msg->dn = ac->orig_req->op.mod.message->dn;
 
529
 
 
530
        ret = objectclass_sort(ac->module, mem_ctx, objectclass_element, &sorted);
 
531
        if (ret != LDB_SUCCESS) {
 
532
                return ret;
 
533
        }
 
534
 
 
535
        /* We must completely replace the existing objectClass entry.
 
536
         * We could do a constrained add/del, but we are meant to be
 
537
         * in a transaction... */
 
538
 
 
539
        ret = ldb_msg_add_empty(msg, "objectClass", LDB_FLAG_MOD_REPLACE, NULL);
 
540
        if (ret != LDB_SUCCESS) {
 
541
                ldb_set_errstring(ac->module->ldb, "objectclass: could not clear objectclass in modify msg");
 
542
                talloc_free(mem_ctx);
 
543
                return ret;
 
544
        }
 
545
        
 
546
        /* Move from the linked list back into an ldb msg */
 
547
        for (current = sorted; current; current = current->next) {
 
548
                ret = ldb_msg_add_string(msg, "objectClass", current->objectclass);
 
549
                if (ret != LDB_SUCCESS) {
 
550
                        ldb_set_errstring(ac->module->ldb, "objectclass: could not re-add sorted objectclass to modify msg");
 
551
                        talloc_free(mem_ctx);
 
552
                        return ret;
 
553
                }
 
554
        }
 
555
 
 
556
        ret = ldb_msg_sanity_check(ac->module->ldb, msg);
 
557
        if (ret != LDB_SUCCESS) {
 
558
                talloc_free(mem_ctx);
 
559
                return ret;
 
560
        }
 
561
 
 
562
 
 
563
        h->state = LDB_ASYNC_INIT;
 
564
        h->status = LDB_SUCCESS;
 
565
 
 
566
        ac->step = OC_DO_MOD;
 
567
 
 
568
        talloc_free(mem_ctx);
 
569
        /* perform the search */
 
570
        return ldb_next_request(ac->module, ac->mod_req);
 
571
}
 
572
 
 
573
static int oc_wait(struct ldb_handle *handle) {
 
574
        struct oc_context *ac;
 
575
        int ret;
 
576
    
 
577
        if (!handle || !handle->private_data) {
 
578
                return LDB_ERR_OPERATIONS_ERROR;
 
579
        }
 
580
 
 
581
        if (handle->state == LDB_ASYNC_DONE) {
 
582
                return handle->status;
 
583
        }
 
584
 
 
585
        handle->state = LDB_ASYNC_PENDING;
 
586
        handle->status = LDB_SUCCESS;
 
587
 
 
588
        ac = talloc_get_type(handle->private_data, struct oc_context);
 
589
 
 
590
        switch (ac->step) {
 
591
        case OC_DO_REQ:
 
592
                ret = ldb_wait(ac->down_req->handle, LDB_WAIT_NONE);
 
593
 
 
594
                if (ret != LDB_SUCCESS) {
 
595
                        handle->status = ret;
 
596
                        goto done;
 
597
                }
 
598
                if (ac->down_req->handle->status != LDB_SUCCESS) {
 
599
                        handle->status = ac->down_req->handle->status;
 
600
                        goto done;
 
601
                }
 
602
 
 
603
                if (ac->down_req->handle->state != LDB_ASYNC_DONE) {
 
604
                        return LDB_SUCCESS;
 
605
                }
 
606
 
 
607
                /* mods done, go on */
 
608
                return objectclass_search_self(handle);
 
609
 
 
610
        case OC_SEARCH_SELF:
 
611
                ret = ldb_wait(ac->search_req->handle, LDB_WAIT_NONE);
 
612
 
 
613
                if (ret != LDB_SUCCESS) {
 
614
                        handle->status = ret;
 
615
                        goto done;
 
616
                }
 
617
                if (ac->search_req->handle->status != LDB_SUCCESS) {
 
618
                        handle->status = ac->search_req->handle->status;
 
619
                        goto done;
 
620
                }
 
621
 
 
622
                if (ac->search_req->handle->state != LDB_ASYNC_DONE) {
 
623
                        return LDB_SUCCESS;
 
624
                }
 
625
 
 
626
                /* self search done, go on */
 
627
                return objectclass_do_mod(handle);
 
628
 
 
629
        case OC_DO_MOD:
 
630
                ret = ldb_wait(ac->mod_req->handle, LDB_WAIT_NONE);
 
631
 
 
632
                if (ret != LDB_SUCCESS) {
 
633
                        handle->status = ret;
 
634
                        goto done;
 
635
                }
 
636
                if (ac->mod_req->handle->status != LDB_SUCCESS) {
 
637
                        handle->status = ac->mod_req->handle->status;
 
638
                        goto done;
 
639
                }
 
640
 
 
641
                if (ac->mod_req->handle->state != LDB_ASYNC_DONE) {
 
642
                        return LDB_SUCCESS;
 
643
                }
 
644
 
 
645
                break;
 
646
                
 
647
        default:
 
648
                ret = LDB_ERR_OPERATIONS_ERROR;
 
649
                goto done;
 
650
        }
 
651
 
 
652
        ret = LDB_SUCCESS;
 
653
 
 
654
done:
 
655
        handle->state = LDB_ASYNC_DONE;
 
656
        return ret;
 
657
}
 
658
 
 
659
static int oc_wait_all(struct ldb_handle *handle) {
 
660
 
 
661
        int ret;
 
662
 
 
663
        while (handle->state != LDB_ASYNC_DONE) {
 
664
                ret = oc_wait(handle);
 
665
                if (ret != LDB_SUCCESS) {
 
666
                        return ret;
 
667
                }
 
668
        }
 
669
 
 
670
        return handle->status;
 
671
}
 
672
 
 
673
static int objectclass_wait(struct ldb_handle *handle, enum ldb_wait_type type)
 
674
{
 
675
        if (type == LDB_WAIT_ALL) {
 
676
                return oc_wait_all(handle);
 
677
        } else {
 
678
                return oc_wait(handle);
 
679
        }
 
680
}
 
681
 
 
682
static const struct ldb_module_ops objectclass_ops = {
 
683
        .name              = "objectclass",
 
684
        .add           = objectclass_add,
 
685
        .modify        = objectclass_modify,
 
686
        .wait          = objectclass_wait
 
687
};
 
688
 
 
689
int ldb_objectclass_init(void)
 
690
{
 
691
        return ldb_register_module(&objectclass_ops);
 
692
}
 
693