root/source4/dsdb/samdb/ldb_modules/subtree_rename.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. subren_ctx_init
  2. subtree_rename_callback
  3. subtree_rename_next_request
  4. subtree_rename_search_callback
  5. subtree_rename

   1 /* 
   2    ldb database library
   3 
   4    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2007
   5    Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
   6 
   7    This program is free software; you can redistribute it and/or modify
   8    it under the terms of the GNU General Public License as published by
   9    the Free Software Foundation; either version 3 of the License, or
  10    (at your option) any later version.
  11    
  12    This program is distributed in the hope that it will be useful,
  13    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15    GNU General Public License for more details.
  16    
  17    You should have received a copy of the GNU General Public License
  18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19 */
  20 
  21 /*
  22  *  Name: ldb
  23  *
  24  *  Component: ldb subtree rename module
  25  *
  26  *  Description: Rename a subtree in LDB
  27  *
  28  *  Author: Andrew Bartlett
  29  */
  30 
  31 #include "ldb_module.h"
  32 
  33 struct subren_msg_store {
  34         struct subren_msg_store *next;
  35         struct ldb_dn *olddn;
  36         struct ldb_dn *newdn;
  37 };
  38 
  39 struct subtree_rename_context {
  40         struct ldb_module *module;
  41         struct ldb_request *req;
  42 
  43         struct subren_msg_store *list;
  44         struct subren_msg_store *current;
  45 };
  46 
  47 static struct subtree_rename_context *subren_ctx_init(struct ldb_module *module,
     /* [<][>][^][v][top][bottom][index][help] */
  48                                          struct ldb_request *req)
  49 {
  50         struct ldb_context *ldb;
  51         struct subtree_rename_context *ac;
  52 
  53         ldb = ldb_module_get_ctx(module);
  54 
  55         ac = talloc_zero(req, struct subtree_rename_context);
  56         if (ac == NULL) {
  57                 ldb_oom(ldb);
  58                 return NULL;
  59         }
  60 
  61         ac->module = module;
  62         ac->req = req;
  63 
  64         return ac;
  65 }
  66 
  67 static int subtree_rename_next_request(struct subtree_rename_context *ac);
  68 
  69 static int subtree_rename_callback(struct ldb_request *req,
     /* [<][>][^][v][top][bottom][index][help] */
  70                                    struct ldb_reply *ares)
  71 {
  72         struct ldb_context *ldb;
  73         struct subtree_rename_context *ac;
  74         int ret;
  75 
  76         ac = talloc_get_type(req->context, struct subtree_rename_context);
  77         ldb = ldb_module_get_ctx(ac->module);
  78 
  79         if (!ares) {
  80                 return ldb_module_done(ac->req, NULL, NULL,
  81                                         LDB_ERR_OPERATIONS_ERROR);
  82         }
  83 
  84         if (ares->error != LDB_SUCCESS) {
  85                 return ldb_module_done(ac->req, ares->controls,
  86                                         ares->response, ares->error);
  87         }
  88 
  89         if (ares->type != LDB_REPLY_DONE) {
  90                 ldb_set_errstring(ldb, "Invalid reply type!\n");
  91                 return ldb_module_done(ac->req, NULL, NULL,
  92                                         LDB_ERR_OPERATIONS_ERROR);
  93         }
  94 
  95         if (ac->current == NULL) {
  96                 /* this was the last one */
  97                 return ldb_module_done(ac->req, ares->controls,
  98                                         ares->response, LDB_SUCCESS);
  99         }
 100 
 101         ret = subtree_rename_next_request(ac);
 102         if (ret != LDB_SUCCESS) {
 103                 return ldb_module_done(ac->req, NULL, NULL, ret);
 104         }
 105 
 106         talloc_free(ares);
 107         return LDB_SUCCESS;
 108 }
 109 
 110 static int subtree_rename_next_request(struct subtree_rename_context *ac)
     /* [<][>][^][v][top][bottom][index][help] */
 111 {
 112         struct ldb_context *ldb;
 113         struct ldb_request *req;
 114         int ret;
 115 
 116         ldb = ldb_module_get_ctx(ac->module);
 117 
 118         if (ac->current == NULL) {
 119                 return LDB_ERR_OPERATIONS_ERROR;
 120         }
 121 
 122         ret = ldb_build_rename_req(&req, ldb, ac->current,
 123                                    ac->current->olddn,
 124                                    ac->current->newdn,
 125                                    ac->req->controls,
 126                                    ac, subtree_rename_callback,
 127                                    ac->req);
 128         if (ret != LDB_SUCCESS) {
 129                 return ret;
 130         }
 131 
 132         ac->current = ac->current->next;
 133 
 134         return ldb_next_request(ac->module, req);
 135 }
 136 
 137 static int subtree_rename_search_callback(struct ldb_request *req,
     /* [<][>][^][v][top][bottom][index][help] */
 138                                           struct ldb_reply *ares)
 139 {
 140         struct subren_msg_store *store;
 141         struct subtree_rename_context *ac;
 142         int ret;
 143 
 144         ac = talloc_get_type(req->context, struct subtree_rename_context);
 145 
 146         if (!ares || !ac->current) {
 147                 return ldb_module_done(ac->req, NULL, NULL,
 148                                         LDB_ERR_OPERATIONS_ERROR);
 149         }
 150         if (ares->error != LDB_SUCCESS) {
 151                 return ldb_module_done(ac->req, ares->controls,
 152                                         ares->response, ares->error);
 153         }
 154 
 155         switch (ares->type) {
 156         case LDB_REPLY_ENTRY:
 157 
 158                 if (ldb_dn_compare(ares->message->dn, ac->list->olddn) == 0) {
 159                         /* this was already stored by the
 160                          * subtree_rename_search() */
 161                         talloc_free(ares);
 162                         return LDB_SUCCESS;
 163                 }
 164 
 165                 store = talloc_zero(ac, struct subren_msg_store);
 166                 if (store == NULL) {
 167                         return ldb_module_done(ac->req, NULL, NULL,
 168                                                 LDB_ERR_OPERATIONS_ERROR);
 169                 }
 170                 ac->current->next = store;
 171                 ac->current = store;
 172 
 173                 /* the first list element contains the base for the rename */
 174                 store->olddn = talloc_steal(store, ares->message->dn);
 175                 store->newdn = ldb_dn_copy(store, store->olddn);
 176 
 177                 if ( ! ldb_dn_remove_base_components(store->newdn,
 178                                 ldb_dn_get_comp_num(ac->list->olddn))) {
 179                         return ldb_module_done(ac->req, NULL, NULL,
 180                                                 LDB_ERR_OPERATIONS_ERROR);
 181                 }
 182 
 183                 if ( ! ldb_dn_add_base(store->newdn, ac->list->newdn)) {
 184                         return ldb_module_done(ac->req, NULL, NULL,
 185                                                 LDB_ERR_OPERATIONS_ERROR);
 186                 }
 187 
 188                 break;
 189 
 190         case LDB_REPLY_REFERRAL:
 191                 /* ignore */
 192                 break;
 193 
 194         case LDB_REPLY_DONE:
 195 
 196                 /* rewind ac->current */
 197                 ac->current = ac->list;
 198 
 199                 /* All dns set up, start with the first one */
 200                 ret = subtree_rename_next_request(ac);
 201 
 202                 if (ret != LDB_SUCCESS) {
 203                         return ldb_module_done(ac->req, NULL, NULL, ret);
 204                 }
 205                 break;
 206         }
 207 
 208         talloc_free(ares);
 209         return LDB_SUCCESS;
 210 }
 211 
 212 /* rename */
 213 static int subtree_rename(struct ldb_module *module, struct ldb_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 214 {
 215         struct ldb_context *ldb;
 216         static const char *attrs[2] = { "distinguishedName", NULL };
 217         struct ldb_request *search_req;
 218         struct subtree_rename_context *ac;
 219         int ret;
 220         if (ldb_dn_is_special(req->op.rename.olddn)) { /* do not manipulate our control entries */
 221                 return ldb_next_request(module, req);
 222         }
 223 
 224         ldb = ldb_module_get_ctx(module);
 225 
 226         /* This gets complex:  We need to:
 227            - Do a search for all entires under this entry 
 228            - Wait for these results to appear
 229            - In the callback for each result, issue a modify request
 230             - That will include this rename, we hope
 231            - Wait for each modify result
 232            - Regain our sainity 
 233         */
 234 
 235         ac = subren_ctx_init(module, req);
 236         if (!ac) {
 237                 return LDB_ERR_OPERATIONS_ERROR;
 238         }
 239 
 240         /* add this entry as the first to do */
 241         ac->current = talloc_zero(ac, struct subren_msg_store);
 242         if (ac->current == NULL) {
 243                 return LDB_ERR_OPERATIONS_ERROR;
 244         }
 245         ac->current->olddn = req->op.rename.olddn;
 246         ac->current->newdn = req->op.rename.newdn;
 247         ac->list = ac->current;
 248 
 249         ret = ldb_build_search_req(&search_req, ldb, ac,
 250                                    req->op.rename.olddn, 
 251                                    LDB_SCOPE_SUBTREE,
 252                                    "(objectClass=*)",
 253                                    attrs,
 254                                    NULL,
 255                                    ac, 
 256                                    subtree_rename_search_callback,
 257                                    req);
 258         if (ret != LDB_SUCCESS) {
 259                 return ret;
 260         }
 261 
 262         return ldb_next_request(module, search_req);
 263 }
 264 
 265 const struct ldb_module_ops ldb_subtree_rename_module_ops = {
 266         .name              = "subtree_rename",
 267         .rename            = subtree_rename,
 268 };

/* [<][>][^][v][top][bottom][index][help] */