ldbm_modrdn.c 92 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
  5. * All rights reserved.
  6. *
  7. * License: GPL (version 3 or any later version).
  8. * See LICENSE for details.
  9. * END COPYRIGHT BLOCK **/
  10. #ifdef HAVE_CONFIG_H
  11. # include <config.h>
  12. #endif
  13. /* modrdn.c - ldbm backend modrdn routine */
  14. #include "back-ldbm.h"
  15. static const char *moddn_get_newdn(Slapi_PBlock *pb, Slapi_DN *dn_olddn, Slapi_DN *dn_newrdn, Slapi_DN *dn_newsuperiordn, int is_tombstone);
  16. static void moddn_unlock_and_return_entry(backend *be,struct backentry **targetentry);
  17. static int moddn_newrdn_mods(Slapi_PBlock *pb, const char *olddn, struct backentry *ec, Slapi_Mods *smods_wsi, int is_repl_op);
  18. static IDList *moddn_get_children(back_txn *ptxn, Slapi_PBlock *pb, backend *be, struct backentry *parententry, Slapi_DN *parentdn, struct backentry ***child_entries, struct backdn ***child_dns, int is_resurect_operation);
  19. static int moddn_rename_children(back_txn *ptxn, Slapi_PBlock *pb, backend *be, IDList *children, Slapi_DN *dn_parentdn, Slapi_DN *dn_newsuperiordn, struct backentry *child_entries[]);
  20. static int modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbminfo *li, struct backentry *e, struct backentry **ec, Slapi_Mods *smods1, Slapi_Mods *smods2, Slapi_Mods *smods3);
  21. static void mods_remove_nsuniqueid(Slapi_Mods *smods);
  22. #define MOD_SET_ERROR(rc, error, count) \
  23. { \
  24. (rc) = (error); \
  25. (count) = RETRY_TIMES; /* otherwise, the transaction may not be aborted */ \
  26. }
  27. int
  28. ldbm_back_modrdn( Slapi_PBlock *pb )
  29. {
  30. backend *be;
  31. ldbm_instance *inst = NULL;
  32. struct ldbminfo *li;
  33. struct backentry *e= NULL;
  34. struct backentry *ec= NULL;
  35. back_txn txn;
  36. back_txnid parent_txn;
  37. int retval = -1;
  38. char *msg;
  39. Slapi_Entry *postentry = NULL;
  40. char *errbuf = NULL;
  41. int disk_full = 0;
  42. int retry_count = 0;
  43. int ldap_result_code= LDAP_SUCCESS;
  44. char *ldap_result_message= NULL;
  45. char *ldap_result_matcheddn= NULL;
  46. struct backentry *parententry= NULL;
  47. struct backentry *newparententry= NULL;
  48. struct backentry *original_entry = NULL;
  49. struct backentry *tmpentry = NULL;
  50. modify_context parent_modify_context = {0};
  51. modify_context newparent_modify_context = {0};
  52. modify_context ruv_c = {0};
  53. int ruv_c_init = 0;
  54. int is_ruv = 0;
  55. IDList *children= NULL;
  56. struct backentry **child_entries = NULL;
  57. struct backdn **child_dns = NULL;
  58. Slapi_DN *sdn = NULL;
  59. Slapi_DN dn_newdn;
  60. Slapi_DN dn_newrdn;
  61. Slapi_DN *dn_newsuperiordn = NULL;
  62. Slapi_DN dn_parentdn;
  63. Slapi_DN *orig_dn_newsuperiordn = NULL;
  64. Slapi_Entry *target_entry = NULL;
  65. Slapi_Entry *original_targetentry = NULL;
  66. int rc;
  67. int isroot;
  68. LDAPMod **mods;
  69. Slapi_Mods smods_operation_wsi = {0};
  70. Slapi_Mods smods_generated = {0};
  71. Slapi_Mods smods_generated_wsi = {0};
  72. Slapi_Operation *operation;
  73. int is_replicated_operation= 0;
  74. int is_fixup_operation = 0;
  75. int is_resurect_operation = 0;
  76. int is_tombstone = 0;
  77. entry_address new_addr;
  78. entry_address *old_addr;
  79. entry_address oldparent_addr;
  80. entry_address *newsuperior_addr;
  81. char *original_newrdn = NULL;
  82. CSN *opcsn = NULL;
  83. const char *newdn = NULL;
  84. char *newrdn = NULL;
  85. int opreturn = 0;
  86. int free_modrdn_existing_entry = 0;
  87. int not_an_error = 0;
  88. int support_moddn_aci;
  89. int myrc = 0;
  90. PRUint64 conn_id;
  91. int op_id;
  92. if (slapi_pblock_get(pb, SLAPI_CONN_ID, &conn_id) < 0) {
  93. conn_id = 0; /* connection is NULL */
  94. }
  95. slapi_pblock_get(pb, SLAPI_OPERATION_ID, &op_id);
  96. /* sdn & parentsdn need to be initialized before "goto *_return" */
  97. slapi_sdn_init(&dn_newdn);
  98. slapi_sdn_init(&dn_newrdn);
  99. slapi_sdn_init(&dn_parentdn);
  100. slapi_pblock_get( pb, SLAPI_MODRDN_TARGET_SDN, &sdn );
  101. slapi_pblock_get( pb, SLAPI_BACKEND, &be);
  102. slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
  103. slapi_pblock_get( pb, SLAPI_TXN, (void**)&parent_txn );
  104. slapi_pblock_get( pb, SLAPI_REQUESTOR_ISROOT, &isroot );
  105. slapi_pblock_get( pb, SLAPI_OPERATION, &operation );
  106. slapi_pblock_get( pb, SLAPI_IS_REPLICATED_OPERATION, &is_replicated_operation );
  107. is_ruv = operation_is_flag_set(operation, OP_FLAG_REPL_RUV);
  108. is_fixup_operation = operation_is_flag_set(operation, OP_FLAG_REPL_FIXUP);
  109. is_resurect_operation = operation_is_flag_set(operation,OP_FLAG_RESURECT_ENTRY);
  110. is_tombstone = operation_is_flag_set(operation,OP_FLAG_TOMBSTONE_ENTRY); /* tombstone_to_glue on parent entry*/
  111. if (NULL == sdn) {
  112. slapi_send_ldap_result( pb, LDAP_INVALID_DN_SYNTAX, NULL,
  113. "Null target DN", 0, NULL );
  114. return( -1 );
  115. }
  116. /* In case of support of 'moddn' permission in aci, this permission will
  117. * be tested rather than the SLAPI_ACL_ADD
  118. */
  119. support_moddn_aci = config_get_moddn_aci();
  120. /* dblayer_txn_init needs to be called before "goto error_return" */
  121. dblayer_txn_init(li,&txn);
  122. /* the calls to perform searches require the parent txn if any
  123. so set txn to the parent_txn until we begin the child transaction */
  124. if (parent_txn) {
  125. txn.back_txn_txn = parent_txn;
  126. } else {
  127. parent_txn = txn.back_txn_txn;
  128. slapi_pblock_set( pb, SLAPI_TXN, parent_txn );
  129. }
  130. if (pb->pb_conn)
  131. {
  132. slapi_log_error (SLAPI_LOG_TRACE, "ldbm_back_modrdn", "enter conn=%" NSPRIu64 " op=%d\n",
  133. pb->pb_conn->c_connid, operation->o_opid);
  134. }
  135. inst = (ldbm_instance *) be->be_instance_info;
  136. {
  137. char *newrdn/* , *newsuperiordn */;
  138. /* newrdn is normalized, bu tno need to be case-ignored as
  139. * it's passed to slapi_sdn_init_normdn_byref */
  140. slapi_pblock_get( pb, SLAPI_MODRDN_NEWRDN, &newrdn );
  141. slapi_pblock_get( pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &dn_newsuperiordn );
  142. slapi_sdn_init_dn_byref(&dn_newrdn, newrdn);
  143. /* slapi_sdn_init_normdn_byref(&dn_newsuperiordn, newsuperiordn); */
  144. if (is_resurect_operation) {
  145. /* no need to free this pdn. */
  146. const char *pdn = slapi_dn_find_parent_ext(slapi_sdn_get_dn(sdn), is_resurect_operation);
  147. slapi_sdn_set_dn_byval(&dn_parentdn, pdn);
  148. } else {
  149. slapi_sdn_get_parent(sdn, &dn_parentdn);
  150. }
  151. }
  152. /* if old and new superior are equals, newsuperior should not be set
  153. * Here we have to reset newsuperiordn in order to save processing and
  154. * avoid later deadlock when trying to fetch twice the same entry
  155. */
  156. if (slapi_sdn_compare(dn_newsuperiordn, &dn_parentdn) == 0)
  157. {
  158. slapi_sdn_done(dn_newsuperiordn);
  159. }
  160. /*
  161. * Even if subtree rename is off,
  162. * Replicated Operations are allowed to change the superior
  163. */
  164. if ( !entryrdn_get_switch() &&
  165. (!is_replicated_operation && !slapi_sdn_isempty(dn_newsuperiordn)))
  166. {
  167. slapi_send_ldap_result( pb, LDAP_UNWILLING_TO_PERFORM, NULL,
  168. "server does not support moving of entries", 0, NULL );
  169. return( -1 );
  170. }
  171. if (inst && inst->inst_ref_count) {
  172. slapi_counter_increment(inst->inst_ref_count);
  173. } else {
  174. LDAPDebug1Arg(LDAP_DEBUG_ANY,
  175. "ldbm_modrdn: instance \"%s\" does not exist.\n",
  176. inst ? inst->inst_name : "null instance");
  177. return( -1 );
  178. }
  179. /* The dblock serializes writes to the database,
  180. * which reduces deadlocking in the db code,
  181. * which means that we run faster.
  182. *
  183. * But, this lock is re-enterant for the fixup
  184. * operations that the URP code in the Replication
  185. * plugin generates.
  186. *
  187. * Also some URP post-op operations are called after
  188. * the backend has committed the change and released
  189. * the dblock. Acquire the dblock again for them
  190. * if OP_FLAG_ACTION_INVOKE_FOR_REPLOP is set.
  191. *
  192. * SERIALLOCK is moved to dblayer_txn_begin along with exposing be
  193. * transaction to plugins (see slapi_back_transaction_* APIs).
  194. *
  195. if(SERIALLOCK(li) &&
  196. (!operation_is_flag_set(operation,OP_FLAG_REPL_FIXUP) ||
  197. operation_is_flag_set(operation,OP_FLAG_ACTION_INVOKE_FOR_REPLOP)))
  198. {
  199. dblayer_lock_backend(be);
  200. dblock_acquired= 1;
  201. }
  202. */
  203. /*
  204. * So, we believe that no code up till here actually added anything
  205. * to persistent store. From now on, we're transacted
  206. */
  207. txn.back_txn_txn = NULL; /* ready to create the child transaction */
  208. for (retry_count = 0; retry_count < RETRY_TIMES; retry_count++)
  209. {
  210. if (txn.back_txn_txn && (txn.back_txn_txn != parent_txn))
  211. {
  212. Slapi_Entry *ent = NULL;
  213. /* don't release SERIAL LOCK */
  214. dblayer_txn_abort_ext(li, &txn, PR_FALSE);
  215. /* txn is no longer valid - reset slapi_txn to the parent */
  216. slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
  217. slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &newrdn);
  218. slapi_ch_free_string(&newrdn);
  219. slapi_pblock_set(pb, SLAPI_MODRDN_NEWRDN, original_newrdn);
  220. slapi_sdn_set_dn_byref(&dn_newrdn, original_newrdn);
  221. original_newrdn = slapi_ch_strdup(original_newrdn);
  222. slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &dn_newsuperiordn);
  223. slapi_sdn_free(&dn_newsuperiordn);
  224. slapi_pblock_set(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, orig_dn_newsuperiordn);
  225. orig_dn_newsuperiordn = slapi_sdn_dup(orig_dn_newsuperiordn);
  226. /* must duplicate ec before returning it to cache,
  227. * which could free the entry. */
  228. if ((tmpentry = backentry_dup(original_entry?original_entry:ec)) == NULL) {
  229. ldap_result_code= LDAP_OPERATIONS_ERROR;
  230. goto error_return;
  231. }
  232. slapi_pblock_get( pb, SLAPI_MODRDN_EXISTING_ENTRY, &ent );
  233. if (cache_is_in_cache(&inst->inst_cache, ec)) {
  234. CACHE_REMOVE(&inst->inst_cache, ec);
  235. if (ent && (ent == ec->ep_entry)){
  236. /*
  237. * On a retry, it's possible that ec is now stored in the
  238. * pblock as SLAPI_MODRDN_EXISTING_ENTRY. "ec" will be freed
  239. * by CACHE_RETURN below, so set ent to NULL so don't free
  240. * it again.
  241. */
  242. ent = NULL;
  243. }
  244. }
  245. CACHE_RETURN(&inst->inst_cache, &ec);
  246. if (!cache_is_in_cache(&inst->inst_cache, e)) {
  247. if (CACHE_ADD(&inst->inst_cache, e, NULL) < 0) {
  248. LDAPDebug1Arg(LDAP_DEBUG_CACHE,
  249. "ldbm_back_modrdn: CACHE_ADD %s to cache failed\n",
  250. slapi_entry_get_dn_const(e->ep_entry));
  251. }
  252. }
  253. if (ent && (ent != original_entry->ep_entry)) {
  254. slapi_entry_free(ent);
  255. slapi_pblock_set( pb, SLAPI_MODRDN_EXISTING_ENTRY, NULL );
  256. }
  257. slapi_pblock_set( pb, SLAPI_MODRDN_EXISTING_ENTRY, original_entry->ep_entry );
  258. ec = original_entry;
  259. original_entry = tmpentry;
  260. tmpentry = NULL;
  261. free_modrdn_existing_entry = 0; /* owned by original_entry now */
  262. if (!cache_is_in_cache(&inst->inst_cache, ec)) {
  263. /* Put the resetted entry 'ec' into the cache again. */
  264. if (cache_add_tentative( &inst->inst_cache, ec, NULL ) < 0) {
  265. /* allow modrdn even if the src dn and dest dn are identical */
  266. if ( 0 != slapi_sdn_compare((const Slapi_DN *)&dn_newdn,
  267. (const Slapi_DN *)sdn) ) {
  268. LDAPDebug1Arg(LDAP_DEBUG_ANY,
  269. "ldbm_back_modrdn: adding %s to cache failed\n",
  270. slapi_entry_get_dn_const(ec->ep_entry));
  271. ldap_result_code = LDAP_OPERATIONS_ERROR;
  272. goto error_return;
  273. }
  274. /* so if the old dn is the same as the new dn, the entry will not be cached
  275. until it is replaced with cache_replace */
  276. }
  277. }
  278. slapi_pblock_get(pb, SLAPI_MODRDN_TARGET_ENTRY, &target_entry );
  279. slapi_entry_free(target_entry);
  280. slapi_pblock_set( pb, SLAPI_MODRDN_TARGET_ENTRY, original_targetentry );
  281. if ( (original_targetentry = slapi_entry_dup( original_targetentry )) == NULL ) {
  282. ldap_result_code= LDAP_OPERATIONS_ERROR;
  283. goto error_return;
  284. }
  285. if (ruv_c_init) {
  286. /* reset the ruv txn stuff */
  287. modify_term(&ruv_c, be);
  288. ruv_c_init = 0;
  289. }
  290. /* We're re-trying */
  291. LDAPDebug0Args(LDAP_DEBUG_BACKLDBM,
  292. "Modrdn Retrying Transaction\n");
  293. #ifndef LDBM_NO_BACKOFF_DELAY
  294. {
  295. PRIntervalTime interval;
  296. interval = PR_MillisecondsToInterval(slapi_rand() % 100);
  297. DS_Sleep(interval);
  298. }
  299. #endif
  300. }
  301. if (0 == retry_count) {
  302. /* First time, hold SERIAL LOCK */
  303. retval = dblayer_txn_begin(be, parent_txn, &txn);
  304. } else {
  305. /* Otherwise, no SERIAL LOCK */
  306. retval = dblayer_txn_begin_ext(li, parent_txn, &txn, PR_FALSE);
  307. }
  308. if (0 != retval) {
  309. ldap_result_code= LDAP_OPERATIONS_ERROR;
  310. if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
  311. goto error_return;
  312. }
  313. /* stash the transaction */
  314. slapi_pblock_set(pb, SLAPI_TXN, (void *)txn.back_txn_txn);
  315. if (0 == retry_count) { /* just once */
  316. rc = 0;
  317. rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY);
  318. rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_PARENT_ENTRY);
  319. rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_NEWPARENT_ENTRY);
  320. rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_TARGET_ENTRY);
  321. while(rc!=0)
  322. {
  323. /* JCM - copying entries can be expensive... should optimize */
  324. /*
  325. * Some present state information is passed through the PBlock to the
  326. * backend pre-op plugin. To ensure a consistent snapshot of this state
  327. * we wrap the reading of the entry with the dblock.
  328. */
  329. /* <new rdn>,<new superior> */
  330. if(slapi_isbitset_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY))
  331. {
  332. /* see if an entry with the new name already exists */
  333. done_with_pblock_entry(pb,SLAPI_MODRDN_EXISTING_ENTRY); /* Could be through this multiple times */
  334. /* newrdn is normalized, bu tno need to be case-ignored as
  335. * it's passed to slapi_sdn_init_normdn_byref */
  336. slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &newrdn);
  337. slapi_sdn_init_dn_byref(&dn_newrdn, newrdn);
  338. newdn = moddn_get_newdn(pb,sdn, &dn_newrdn, dn_newsuperiordn, is_tombstone);
  339. slapi_sdn_set_dn_passin(&dn_newdn,newdn);
  340. new_addr.sdn = &dn_newdn;
  341. new_addr.udn = NULL;
  342. /* check dn syntax on newdn */
  343. ldap_result_code = slapi_dn_syntax_check(pb,
  344. (char *)slapi_sdn_get_ndn(&dn_newdn), 1);
  345. if (ldap_result_code)
  346. {
  347. ldap_result_code = LDAP_INVALID_DN_SYNTAX;
  348. slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
  349. goto error_return;
  350. }
  351. new_addr.uniqueid = NULL;
  352. ldap_result_code= get_copy_of_entry(pb, &new_addr, &txn, SLAPI_MODRDN_EXISTING_ENTRY, 0);
  353. if(ldap_result_code==LDAP_OPERATIONS_ERROR ||
  354. ldap_result_code==LDAP_INVALID_DN_SYNTAX)
  355. {
  356. goto error_return;
  357. }
  358. free_modrdn_existing_entry = 1; /* need to free it */
  359. }
  360. /* <old superior> */
  361. if(slapi_isbitset_int(rc,SLAPI_RTN_BIT_FETCH_PARENT_ENTRY))
  362. {
  363. /* find and lock the old parent entry */
  364. done_with_pblock_entry(pb,SLAPI_MODRDN_PARENT_ENTRY); /* Could be through this multiple times */
  365. oldparent_addr.sdn = &dn_parentdn;
  366. oldparent_addr.uniqueid = NULL;
  367. ldap_result_code= get_copy_of_entry(pb, &oldparent_addr, &txn, SLAPI_MODRDN_PARENT_ENTRY, !is_replicated_operation);
  368. }
  369. /* <new superior> */
  370. if(slapi_sdn_get_ndn(dn_newsuperiordn)!=NULL &&
  371. slapi_isbitset_int(rc,SLAPI_RTN_BIT_FETCH_NEWPARENT_ENTRY))
  372. {
  373. /* find and lock the new parent entry */
  374. done_with_pblock_entry(pb,SLAPI_MODRDN_NEWPARENT_ENTRY); /* Could be through this multiple times */
  375. /* Check that this really is a new superior,
  376. * and not the same old one. Compare parentdn & newsuperior */
  377. if (slapi_sdn_compare(dn_newsuperiordn, &dn_parentdn) == 0)
  378. {
  379. slapi_sdn_done(dn_newsuperiordn);
  380. }
  381. else
  382. {
  383. entry_address my_addr;
  384. if (is_replicated_operation)
  385. {
  386. /* If this is a replicated operation,
  387. * then should fetch new superior with uniqueid */
  388. slapi_pblock_get (pb, SLAPI_MODRDN_NEWSUPERIOR_ADDRESS,
  389. &newsuperior_addr);
  390. }
  391. else
  392. {
  393. my_addr.sdn = dn_newsuperiordn;
  394. my_addr.uniqueid = NULL;
  395. newsuperior_addr = &my_addr;
  396. }
  397. ldap_result_code= get_copy_of_entry(pb, newsuperior_addr, &txn, SLAPI_MODRDN_NEWPARENT_ENTRY, !is_replicated_operation);
  398. }
  399. }
  400. /* <old rdn>,<old superior> */
  401. if(slapi_isbitset_int(rc,SLAPI_RTN_BIT_FETCH_TARGET_ENTRY))
  402. {
  403. /* find and lock the entry we are about to modify */
  404. done_with_pblock_entry(pb,SLAPI_MODRDN_TARGET_ENTRY); /* Could be through this multiple times */
  405. slapi_pblock_get (pb, SLAPI_TARGET_ADDRESS, &old_addr);
  406. ldap_result_code= get_copy_of_entry(pb, old_addr, &txn, SLAPI_MODRDN_TARGET_ENTRY, !is_replicated_operation);
  407. if(ldap_result_code==LDAP_OPERATIONS_ERROR ||
  408. ldap_result_code==LDAP_INVALID_DN_SYNTAX)
  409. {
  410. /* JCM - Usually the call to find_entry2modify would generate the result code. */
  411. /* JCM !!! */
  412. goto error_return;
  413. }
  414. }
  415. /* Call the Backend Pre ModRDN plugins */
  416. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
  417. rc= plugin_call_plugins(pb, SLAPI_PLUGIN_BE_PRE_MODRDN_FN);
  418. if (rc < 0) {
  419. if (SLAPI_PLUGIN_NOOP == rc) {
  420. not_an_error = 1;
  421. rc = LDAP_SUCCESS;
  422. }
  423. /*
  424. * Plugin indicated some kind of failure,
  425. * or that this Operation became a No-Op.
  426. */
  427. if (!ldap_result_code) {
  428. slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
  429. }
  430. if (!opreturn) {
  431. slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &opreturn);
  432. }
  433. if (!opreturn) {
  434. slapi_pblock_set( pb, SLAPI_PLUGIN_OPRETURN, ldap_result_code ? &ldap_result_code : &rc );
  435. }
  436. slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
  437. goto error_return;
  438. }
  439. /*
  440. * (rc!=-1) means that the plugin changed things, so we go around
  441. * the loop once again to get the new present state.
  442. */
  443. /* JCMREPL - Warning: A Plugin could cause an infinite loop by always returning a result code that requires some action. */
  444. }
  445. /* find and lock the entry we are about to modify */
  446. /* JCMREPL - Argh, what happens about the stinking referrals? */
  447. slapi_pblock_get (pb, SLAPI_TARGET_ADDRESS, &old_addr);
  448. e = find_entry2modify( pb, be, old_addr, &txn );
  449. if ( e == NULL )
  450. {
  451. ldap_result_code= -1;
  452. goto error_return; /* error result sent by find_entry2modify() */
  453. }
  454. if (slapi_entry_flag_is_set(e->ep_entry, SLAPI_ENTRY_FLAG_TOMBSTONE) &&
  455. !is_resurect_operation) {
  456. ldap_result_code = LDAP_UNWILLING_TO_PERFORM;
  457. ldap_result_message = "Operation not allowed on tombstone entry.";
  458. slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_modrdn",
  459. "Attempt to rename a tombstone entry %s\n",
  460. slapi_sdn_get_dn(slapi_entry_get_sdn_const( e->ep_entry )));
  461. goto error_return;
  462. }
  463. /* Check that an entry with the same DN doesn't already exist. */
  464. {
  465. Slapi_Entry *entry;
  466. slapi_pblock_get( pb, SLAPI_MODRDN_EXISTING_ENTRY, &entry);
  467. if((entry != NULL) &&
  468. /* allow modrdn even if the src dn and dest dn are identical */
  469. (0 != slapi_sdn_compare((const Slapi_DN *)&dn_newdn,
  470. (const Slapi_DN *)sdn)))
  471. {
  472. ldap_result_code= LDAP_ALREADY_EXISTS;
  473. goto error_return;
  474. }
  475. }
  476. /* Fetch and lock the parent of the entry that is moving */
  477. oldparent_addr.sdn = &dn_parentdn;
  478. if (is_resurect_operation) {
  479. oldparent_addr.uniqueid = operation->o_params.p.p_modrdn.modrdn_newsuperior_address.uniqueid;
  480. } else {
  481. oldparent_addr.uniqueid = NULL;
  482. }
  483. parententry = find_entry2modify_only( pb, be, &oldparent_addr, &txn );
  484. modify_init(&parent_modify_context,parententry);
  485. /* Fetch and lock the new parent of the entry that is moving */
  486. if(slapi_sdn_get_ndn(dn_newsuperiordn) != NULL)
  487. {
  488. slapi_pblock_get (pb, SLAPI_MODRDN_NEWSUPERIOR_ADDRESS, &newsuperior_addr);
  489. if (is_resurect_operation) {
  490. newsuperior_addr->uniqueid = slapi_entry_attr_get_charptr(e->ep_entry, SLAPI_ATTR_VALUE_PARENT_UNIQUEID);
  491. }
  492. newparententry = find_entry2modify_only( pb, be, newsuperior_addr, &txn );
  493. slapi_ch_free_string(&newsuperior_addr->uniqueid);
  494. modify_init(&newparent_modify_context,newparententry);
  495. }
  496. opcsn = operation_get_csn (operation);
  497. if (!is_fixup_operation)
  498. {
  499. if ( opcsn == NULL && operation->o_csngen_handler)
  500. {
  501. /*
  502. * Current op is a user request. Opcsn will be assigned
  503. * if the dn is in an updatable replica.
  504. */
  505. opcsn = entry_assign_operation_csn ( pb, e->ep_entry, parententry ? parententry->ep_entry : NULL );
  506. }
  507. if ( opcsn != NULL )
  508. {
  509. entry_set_maxcsn (e->ep_entry, opcsn);
  510. }
  511. }
  512. /*
  513. * Now that we have the old entry, we reset the old DN and recompute
  514. * the new DN. Why? Because earlier when we computed the new DN, we did
  515. * not have the old entry, so we used the DN that was presented as the
  516. * target DN in the ModRDN operation itself, and we would prefer to
  517. * preserve the case and spacing that are in the actual entry's DN
  518. * instead. Otherwise, a ModRDN operation will potentially change an
  519. * entry's entire DN (at least with respect to case and spacing).
  520. */
  521. slapi_sdn_copy( slapi_entry_get_sdn_const( e->ep_entry ), sdn );
  522. slapi_pblock_set( pb, SLAPI_MODRDN_TARGET_SDN, sdn );
  523. if (newparententry != NULL) {
  524. /* don't forget we also want to preserve case of new superior */
  525. if (NULL == dn_newsuperiordn) {
  526. dn_newsuperiordn = slapi_sdn_dup(
  527. slapi_entry_get_sdn_const(newparententry->ep_entry));
  528. } else {
  529. slapi_sdn_copy(slapi_entry_get_sdn_const(newparententry->ep_entry),
  530. dn_newsuperiordn);
  531. }
  532. slapi_pblock_set( pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, dn_newsuperiordn );
  533. }
  534. slapi_sdn_set_dn_passin(&dn_newdn, moddn_get_newdn(pb, sdn, &dn_newrdn, dn_newsuperiordn, is_tombstone));
  535. /* Check that we're allowed to add an entry below the new superior */
  536. if ( newparententry == NULL )
  537. {
  538. /* There may not be a new parent because we don't intend there to be one. */
  539. if (slapi_sdn_get_dn(dn_newsuperiordn))
  540. {
  541. /* If the new entry is not to be a suffix,
  542. * return an error no matter who requested this modrdn */
  543. if (!slapi_be_issuffix(pb->pb_backend, &dn_newdn))
  544. {
  545. /* Here means that we didn't find the parent */
  546. int err = 0;
  547. Slapi_DN ancestorsdn;
  548. struct backentry *ancestorentry;
  549. slapi_sdn_init(&ancestorsdn);
  550. ancestorentry= dn2ancestor(be,&dn_newdn,&ancestorsdn,&txn,&err);
  551. CACHE_RETURN( &inst->inst_cache, &ancestorentry );
  552. ldap_result_matcheddn= slapi_ch_strdup((char *) slapi_sdn_get_dn(&ancestorsdn));
  553. ldap_result_code= LDAP_NO_SUCH_OBJECT;
  554. LDAPDebug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: New superior "
  555. "does not exist matched %s, newsuperior = %s\n",
  556. ldap_result_matcheddn == NULL ? "NULL" :
  557. ldap_result_matcheddn,
  558. slapi_sdn_get_ndn(dn_newsuperiordn), 0 );
  559. slapi_sdn_done(&ancestorsdn);
  560. goto error_return;
  561. }
  562. }
  563. }
  564. else
  565. {
  566. if (support_moddn_aci) {
  567. /* aci permission requires 'moddn' right to allow a MODDN */
  568. ldap_result_code = plugin_call_acl_plugin(pb, newparententry->ep_entry, NULL, NULL, SLAPI_ACL_MODDN, ACLPLUGIN_ACCESS_DEFAULT, &errbuf);
  569. if (ldap_result_code != LDAP_SUCCESS) {
  570. ldap_result_message = errbuf;
  571. LDAPDebug(LDAP_DEBUG_TRACE, "No 'moddn' access to new superior.\n", 0, 0, 0);
  572. goto error_return;
  573. }
  574. } else {
  575. /* aci permission requires 'add' right to allow a MODDN (old style) */
  576. ldap_result_code = plugin_call_acl_plugin (pb, newparententry->ep_entry, NULL, NULL, SLAPI_ACL_ADD, ACLPLUGIN_ACCESS_DEFAULT, &errbuf );
  577. if (ldap_result_code != LDAP_SUCCESS) {
  578. ldap_result_message = errbuf;
  579. LDAPDebug(LDAP_DEBUG_TRACE, "No 'add' access to new superior.\n", 0, 0, 0);
  580. goto error_return;
  581. }
  582. }
  583. }
  584. /* Check that the target entry has a parent */
  585. if ( parententry == NULL )
  586. {
  587. /* If the entry a suffix, and we're root, then it's OK that the parent doesn't exist */
  588. if (!(slapi_be_issuffix(pb->pb_backend, sdn)) && !isroot)
  589. {
  590. /* Here means that we didn't find the parent */
  591. ldap_result_matcheddn = "NULL";
  592. ldap_result_code= LDAP_NO_SUCH_OBJECT;
  593. LDAPDebug( LDAP_DEBUG_TRACE, "Parent does not exist matched %s, parentdn = %s\n",
  594. ldap_result_matcheddn, slapi_sdn_get_ndn(&dn_parentdn), 0 );
  595. goto error_return;
  596. }
  597. }
  598. /* If it is a replicated Operation or "subtree-rename" is on,
  599. * it's allowed to rename entries with children */
  600. if ( !is_replicated_operation && !entryrdn_get_switch() &&
  601. slapi_entry_has_children( e->ep_entry ))
  602. {
  603. ldap_result_code = LDAP_NOT_ALLOWED_ON_NONLEAF;
  604. goto error_return;
  605. }
  606. /*
  607. * JCM - All the child entries must be locked in the cache, so the size of
  608. * subtree that can be renamed is limited by the cache size.
  609. */
  610. /* Save away a copy of the entry, before modifications */
  611. slapi_pblock_set( pb, SLAPI_ENTRY_PRE_OP, slapi_entry_dup( e->ep_entry ));
  612. /* create a copy of the entry and apply the changes to it */
  613. if ( (ec = backentry_dup( e )) == NULL )
  614. {
  615. ldap_result_code= LDAP_OPERATIONS_ERROR;
  616. goto error_return;
  617. }
  618. /* JCMACL - Should be performed before the child check. */
  619. /* JCMACL - Why is the check performed against the copy, rather than the existing entry? */
  620. /* This check must be performed even if the entry is renamed with its own name
  621. * No optimization here we need to check we have the write access to the target entry
  622. */
  623. ldap_result_code = plugin_call_acl_plugin(pb, ec->ep_entry,
  624. NULL /*attr*/, NULL /*value*/, SLAPI_ACL_WRITE,
  625. ACLPLUGIN_ACCESS_MODRDN, &errbuf);
  626. if (ldap_result_code != LDAP_SUCCESS)
  627. {
  628. goto error_return;
  629. }
  630. /* Set the new dn to the copy of the entry */
  631. slapi_entry_set_sdn( ec->ep_entry, &dn_newdn );
  632. if (entryrdn_get_switch()) { /* subtree-rename: on */
  633. Slapi_RDN srdn;
  634. /* Set the new rdn to the copy of the entry; store full dn in e_srdn */
  635. slapi_rdn_init_all_sdn(&srdn, &dn_newdn);
  636. slapi_entry_set_srdn(ec->ep_entry, &srdn);
  637. slapi_rdn_done(&srdn);
  638. }
  639. if(is_resurect_operation) {
  640. slapi_log_error(SLAPI_LOG_REPL, "ldbm_back_modrdn",
  641. "Resurrecting an entry %s\n", slapi_entry_get_dn(ec->ep_entry));
  642. slapi_entry_attr_delete(ec->ep_entry, SLAPI_ATTR_VALUE_PARENT_UNIQUEID);
  643. slapi_entry_attr_delete(ec->ep_entry, SLAPI_ATTR_TOMBSTONE_CSN);
  644. slapi_entry_delete_string(ec->ep_entry, SLAPI_ATTR_OBJECTCLASS, SLAPI_ATTR_VALUE_TOMBSTONE);
  645. /* Now also remove the nscpEntryDN */
  646. if (slapi_entry_attr_delete(ec->ep_entry, SLAPI_ATTR_NSCP_ENTRYDN) != 0){
  647. LDAPDebug(LDAP_DEBUG_REPL, "Resurrection of %s - Couldn't remove %s\n",
  648. slapi_entry_get_dn(ec->ep_entry), SLAPI_ATTR_NSCP_ENTRYDN, 0);
  649. }
  650. /* Set the reason (this is only a reason why modrdn is needed for resurrection) */
  651. slapi_entry_add_string(ec->ep_entry, "nsds5ReplConflict", "deletedEntryHasChildren");
  652. /* Clear the Tombstone Flag in the entry */
  653. slapi_entry_clear_flag(ec->ep_entry, SLAPI_ENTRY_FLAG_TOMBSTONE);
  654. /* make sure the objectclass
  655. - does not contain any duplicate values
  656. - has CSNs for the new values we added
  657. */
  658. {
  659. Slapi_Attr *sa = NULL;
  660. Slapi_Value sv;
  661. const struct berval *svbv = NULL;
  662. /* add the extensibleobject objectclass with csn if not present */
  663. slapi_entry_attr_find(ec->ep_entry, SLAPI_ATTR_OBJECTCLASS, &sa);
  664. slapi_value_init_string(&sv, "extensibleobject");
  665. svbv = slapi_value_get_berval(&sv);
  666. if (slapi_attr_value_find(sa, svbv)) { /* not found, so add it */
  667. if (opcsn) {
  668. value_update_csn(&sv, CSN_TYPE_VALUE_UPDATED, opcsn);
  669. }
  670. slapi_attr_add_value(sa, &sv);
  671. }
  672. value_done(&sv);
  673. /* add the glue objectclass with csn if not present */
  674. slapi_value_init_string(&sv, "glue");
  675. svbv = slapi_value_get_berval(&sv);
  676. if (slapi_attr_value_find(sa, svbv)) { /* not found, so add it */
  677. if (opcsn) {
  678. value_update_csn(&sv, CSN_TYPE_VALUE_UPDATED, opcsn);
  679. }
  680. slapi_attr_add_value(sa, &sv);
  681. }
  682. value_done(&sv);
  683. }
  684. }
  685. /* create it in the cache - prevents others from creating it */
  686. if (( cache_add_tentative( &inst->inst_cache, ec, NULL ) < 0 ) ) {
  687. /* allow modrdn even if the src dn and dest dn are identical */
  688. if ( 0 != slapi_sdn_compare((const Slapi_DN *)&dn_newdn,
  689. (const Slapi_DN *)sdn) ) {
  690. /* somebody must've created it between dn2entry() and here */
  691. /* JCMREPL - Hmm... we can't permit this to happen...? */
  692. ldap_result_code= LDAP_ALREADY_EXISTS;
  693. if (is_resurect_operation) {
  694. slapi_log_error(SLAPI_LOG_CACHE, "ldbm_back_modrdn",
  695. "conn=%lu op=%d cache_add_tentative failed: %s\n",
  696. conn_id, op_id, slapi_entry_get_dn(ec->ep_entry));
  697. }
  698. goto error_return;
  699. }
  700. /* so if the old dn is the same as the new dn, the entry will not be cached
  701. until it is replaced with cache_replace */
  702. }
  703. /* Build the list of modifications required to the existing entry */
  704. slapi_mods_init(&smods_generated,4);
  705. slapi_mods_init(&smods_generated_wsi,4);
  706. ldap_result_code = moddn_newrdn_mods(pb, slapi_sdn_get_dn(sdn),
  707. ec, &smods_generated_wsi, is_replicated_operation);
  708. if (ldap_result_code != LDAP_SUCCESS) {
  709. if (ldap_result_code == LDAP_UNWILLING_TO_PERFORM)
  710. ldap_result_message = "Modification of old rdn attribute type not allowed.";
  711. goto error_return;
  712. }
  713. if (!entryrdn_get_switch()) /* subtree-rename: off */
  714. {
  715. /*
  716. * Remove the old entrydn index entry, and add the new one.
  717. */
  718. slapi_mods_add( &smods_generated, LDAP_MOD_DELETE, LDBM_ENTRYDN_STR,
  719. strlen(backentry_get_ndn(e)), backentry_get_ndn(e));
  720. slapi_mods_add( &smods_generated, LDAP_MOD_REPLACE, LDBM_ENTRYDN_STR,
  721. strlen(backentry_get_ndn(ec)), backentry_get_ndn(ec));
  722. }
  723. /*
  724. * Update parentid if we have a new superior.
  725. */
  726. if(slapi_sdn_get_dn(dn_newsuperiordn)!=NULL) {
  727. char buf[40]; /* Enough for an ID */
  728. if (parententry != NULL) {
  729. sprintf( buf, "%lu", (u_long)parententry->ep_id );
  730. slapi_mods_add_string(&smods_generated, LDAP_MOD_DELETE, LDBM_PARENTID_STR, buf);
  731. }
  732. if (newparententry != NULL) {
  733. sprintf( buf, "%lu", (u_long)newparententry->ep_id );
  734. slapi_mods_add_string(&smods_generated, LDAP_MOD_REPLACE, LDBM_PARENTID_STR, buf);
  735. }
  736. }
  737. slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods );
  738. slapi_mods_init_byref(&smods_operation_wsi,mods);
  739. /*
  740. * We are about to pass the last abandon test, so from now on we are
  741. * committed to finish this operation. Set status to "will complete"
  742. * before we make our last abandon check to avoid race conditions in
  743. * the code that processes abandon operations.
  744. */
  745. if (operation) {
  746. operation->o_status = SLAPI_OP_STATUS_WILL_COMPLETE;
  747. }
  748. if ( slapi_op_abandoned( pb ) ) {
  749. goto error_return;
  750. }
  751. /*
  752. * First, we apply the generated mods that do not involve any state information.
  753. */
  754. if ( entry_apply_mods( ec->ep_entry, slapi_mods_get_ldapmods_byref(&smods_generated) ) != 0 )
  755. {
  756. ldap_result_code= LDAP_OPERATIONS_ERROR;
  757. LDAPDebug( LDAP_DEBUG_TRACE, "ldbm_modrdn: entry_apply_mods failed for entry %s\n",
  758. slapi_entry_get_dn_const(ec->ep_entry), 0, 0);
  759. goto error_return;
  760. }
  761. /*
  762. * Now we apply the generated mods that do involve state information.
  763. */
  764. if (slapi_mods_get_num_mods(&smods_generated_wsi)>0)
  765. {
  766. if (entry_apply_mods_wsi(ec->ep_entry, &smods_generated_wsi, operation_get_csn(operation), is_replicated_operation)!=0)
  767. {
  768. ldap_result_code= LDAP_OPERATIONS_ERROR;
  769. LDAPDebug( LDAP_DEBUG_TRACE, "ldbm_modrdn: entry_apply_mods_wsi failed for entry %s\n",
  770. slapi_entry_get_dn_const(ec->ep_entry), 0, 0);
  771. goto error_return;
  772. }
  773. }
  774. /*
  775. * Now we apply the operation mods that do involve state information.
  776. * (Operational attributes).
  777. * The following block looks redundent to the one above. But it may
  778. * be necessary - check the comment for version 1.3.16.22.2.76 of
  779. * this file and compare that version with its previous one.
  780. */
  781. if (slapi_mods_get_num_mods(&smods_operation_wsi)>0)
  782. {
  783. if (entry_apply_mods_wsi(ec->ep_entry, &smods_operation_wsi, operation_get_csn(operation), is_replicated_operation)!=0)
  784. {
  785. ldap_result_code= LDAP_OPERATIONS_ERROR;
  786. LDAPDebug( LDAP_DEBUG_TRACE, "ldbm_modrdn: entry_apply_mods_wsi (operational attributes) failed for entry %s\n",
  787. slapi_entry_get_dn_const(ec->ep_entry), 0, 0);
  788. goto error_return;
  789. }
  790. }
  791. /* check that the entry still obeys the schema */
  792. if ( slapi_entry_schema_check( pb, ec->ep_entry ) != 0 ) {
  793. ldap_result_code = LDAP_OBJECT_CLASS_VIOLATION;
  794. slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
  795. goto error_return;
  796. }
  797. /* Check attribute syntax if any new values are being added for the new RDN */
  798. if (slapi_mods_get_num_mods(&smods_operation_wsi)>0)
  799. {
  800. if (slapi_mods_syntax_check(pb, smods_generated_wsi.mods, 0) != 0)
  801. {
  802. ldap_result_code = LDAP_INVALID_SYNTAX;
  803. slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
  804. goto error_return;
  805. }
  806. }
  807. /*
  808. * Update the DN CSN of the entry.
  809. */
  810. entry_add_dncsn(ec->ep_entry,operation_get_csn(operation));
  811. entry_add_rdn_csn(ec->ep_entry,operation_get_csn(operation));
  812. /*
  813. * If the entry has a new superior then the subordinate count
  814. * of the parents must be updated.
  815. */
  816. if(slapi_sdn_get_dn(dn_newsuperiordn)!=NULL)
  817. {
  818. /*
  819. * Update the subordinate count of the parents to reflect the moved child.
  820. */
  821. if (parententry) {
  822. retval = parent_update_on_childchange(&parent_modify_context,
  823. PARENTUPDATE_DEL, NULL);
  824. slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_modrdn",
  825. "conn=%lu op=%d parent_update_on_childchange: old_entry=0x%p, new_entry=0x%p, rc=%d\n",
  826. conn_id, op_id, parent_modify_context.old_entry, parent_modify_context.new_entry, retval);
  827. /* The parent modify context now contains info needed later */
  828. if (retval) {
  829. goto error_return;
  830. }
  831. }
  832. if (newparententry) {
  833. retval = parent_update_on_childchange(&newparent_modify_context,
  834. PARENTUPDATE_ADD, NULL);
  835. slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_modrdn",
  836. "conn=%lu op=%d parent_update_on_childchange: old_entry=0x%p, new_entry=0x%p, rc=%d\n",
  837. conn_id, op_id, parent_modify_context.old_entry, parent_modify_context.new_entry, retval);
  838. /* The newparent modify context now contains info needed later */
  839. if (retval) {
  840. goto error_return;
  841. }
  842. }
  843. }
  844. /* is_resurect_operation case, there's no new superior. Just rename. */
  845. if (is_resurect_operation && parententry) {
  846. retval = parent_update_on_childchange(&parent_modify_context, PARENTUPDATE_RESURECT, NULL);
  847. if (retval) {
  848. slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_modrdn",
  849. "conn=%lu op=%d parent_update_on_childchange parent %s of %s failed, rc=%d\n",
  850. conn_id, op_id,
  851. slapi_entry_get_dn_const(parent_modify_context.old_entry->ep_entry),
  852. slapi_entry_get_dn_const(ec->ep_entry), retval);
  853. goto error_return;
  854. }
  855. }
  856. /*
  857. * If the entry has children including tombstones,
  858. * then we're going to have to rename them all.
  859. */
  860. if (slapi_entry_has_children_ext(e->ep_entry, 1)) {
  861. /* JCM - This is where the subtree lock will appear */
  862. if (entryrdn_get_switch()) /* subtree-rename: on */
  863. {
  864. if (is_resurect_operation) {
  865. #if defined(DEBUG)
  866. /* Get the present value of the subcount attr, or 0 if not present */
  867. Slapi_Attr *read_attr = NULL;
  868. int sub_count = -1;
  869. if (0 == slapi_entry_attr_find(parent_modify_context.old_entry->ep_entry,
  870. "numsubordinates", &read_attr)) {
  871. /* decode the value */
  872. Slapi_Value *sval;
  873. slapi_attr_first_value(read_attr, &sval);
  874. if (sval) {
  875. const struct berval *bval = slapi_value_get_berval(sval);
  876. if(bval) {
  877. sub_count = atol(bval->bv_val);
  878. }
  879. }
  880. }
  881. LDAPDebug(LDAP_DEBUG_ANY, "parent_update_on_childchange parent %s of %s numsub=%d\n",
  882. slapi_entry_get_dn_const(parent_modify_context.old_entry->ep_entry),
  883. slapi_entry_get_dn_const(e->ep_entry), sub_count);
  884. #endif
  885. slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_modrdn",
  886. "%s has children\n", slapi_entry_get_dn(e->ep_entry));
  887. }
  888. children = moddn_get_children(&txn, pb, be, e, sdn,
  889. &child_entries, &child_dns, is_resurect_operation);
  890. }
  891. else
  892. {
  893. children = moddn_get_children(&txn, pb, be, e, sdn,
  894. &child_entries, NULL, 0);
  895. }
  896. /* JCM - Shouldn't we perform an access control check on all the children. */
  897. /* JCMREPL - But, the replication client has total rights over its subtree, so no access check needed. */
  898. /* JCM - A subtree move could break ACIs, static groups, and dynamic groups. */
  899. } else if (is_resurect_operation) {
  900. slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_modrdn",
  901. "%s has NO children\n", slapi_entry_get_dn(e->ep_entry));
  902. }
  903. /*
  904. * make copies of the originals, no need to copy the mods because
  905. * we have already copied them
  906. */
  907. if ( (original_entry = backentry_dup( ec )) == NULL ) {
  908. ldap_result_code= LDAP_OPERATIONS_ERROR;
  909. goto error_return;
  910. }
  911. slapi_pblock_get(pb, SLAPI_MODRDN_TARGET_ENTRY, &target_entry);
  912. if ( (original_targetentry = slapi_entry_dup(target_entry)) == NULL ) {
  913. ldap_result_code= LDAP_OPERATIONS_ERROR;
  914. goto error_return;
  915. }
  916. slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &newrdn);
  917. original_newrdn = slapi_ch_strdup(newrdn);
  918. slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &dn_newsuperiordn);
  919. orig_dn_newsuperiordn = slapi_sdn_dup(dn_newsuperiordn);
  920. } /* if (0 == retry_count) just once */
  921. /* call the transaction pre modrdn plugins just after creating the transaction */
  922. retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_PRE_MODRDN_FN);
  923. if (retval) {
  924. LDAPDebug1Arg( LDAP_DEBUG_TRACE, "SLAPI_PLUGIN_BE_TXN_PRE_MODRDN_FN plugin "
  925. "returned error code %d\n", retval );
  926. if (SLAPI_PLUGIN_NOOP == retval) {
  927. not_an_error = 1;
  928. rc = retval = LDAP_SUCCESS;
  929. }
  930. if (!ldap_result_code) {
  931. slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
  932. }
  933. if (!opreturn) {
  934. slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &opreturn);
  935. }
  936. if (!opreturn) {
  937. slapi_pblock_set( pb, SLAPI_PLUGIN_OPRETURN, ldap_result_code ? &ldap_result_code : &retval );
  938. }
  939. slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
  940. goto error_return;
  941. }
  942. /*
  943. * Update the indexes for the entry.
  944. */
  945. retval = modrdn_rename_entry_update_indexes(&txn, pb, li, e, &ec, &smods_generated, &smods_generated_wsi, &smods_operation_wsi);
  946. if (DB_LOCK_DEADLOCK == retval)
  947. {
  948. /* Retry txn */
  949. continue;
  950. }
  951. if (retval)
  952. {
  953. LDAPDebug(LDAP_DEBUG_ANY, "modrdn_rename_entry_update_indexes %s --> %s failed, err=%d\n",
  954. slapi_entry_get_dn(e->ep_entry), slapi_entry_get_dn(ec->ep_entry), retval);
  955. if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
  956. MOD_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
  957. goto error_return;
  958. }
  959. /*
  960. * add new name to index
  961. */
  962. {
  963. char **rdns;
  964. int i;
  965. if ( (rdns = slapi_ldap_explode_rdn( slapi_sdn_get_dn(&dn_newrdn), 0 )) != NULL )
  966. {
  967. for ( i = 0; rdns[i] != NULL; i++ )
  968. {
  969. char *type;
  970. Slapi_Value *svp[2];
  971. Slapi_Value sv;
  972. memset(&sv,0,sizeof(Slapi_Value));
  973. if ( slapi_rdn2typeval( rdns[i], &type, &sv.bv ) != 0 )
  974. {
  975. LDAPDebug( LDAP_DEBUG_ANY, "modrdn: rdn2typeval (%s) failed\n",
  976. rdns[i], 0, 0 );
  977. if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
  978. MOD_SET_ERROR(ldap_result_code,
  979. LDAP_OPERATIONS_ERROR, retry_count);
  980. goto error_return;
  981. }
  982. svp[0] = &sv;
  983. svp[1] = NULL;
  984. retval = index_addordel_values_sv( be, type, svp, NULL, ec->ep_id, BE_INDEX_ADD, &txn );
  985. if (DB_LOCK_DEADLOCK == retval)
  986. {
  987. /* To retry txn, once break "for loop" */
  988. break;
  989. }
  990. else if (retval != 0 )
  991. {
  992. LDAPDebug( LDAP_DEBUG_ANY, "modrdn: could not add new value to index, err=%d %s\n",
  993. retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
  994. if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
  995. MOD_SET_ERROR(ldap_result_code,
  996. LDAP_OPERATIONS_ERROR, retry_count);
  997. goto error_return;
  998. }
  999. }
  1000. slapi_ldap_value_free( rdns );
  1001. if (DB_LOCK_DEADLOCK == retval)
  1002. {
  1003. /* Retry txn */
  1004. continue;
  1005. }
  1006. }
  1007. }
  1008. if (slapi_sdn_get_dn(dn_newsuperiordn)!=NULL)
  1009. {
  1010. /* Push out the db modifications from the parent entry */
  1011. retval = modify_update_all(be, pb, &parent_modify_context, &txn);
  1012. if (DB_LOCK_DEADLOCK == retval)
  1013. {
  1014. /* Retry txn */
  1015. continue;
  1016. }
  1017. else if (0 != retval)
  1018. {
  1019. LDAPDebug( LDAP_DEBUG_ANY, "modrdn: "
  1020. "could not update parent, err=%d %s\n", retval,
  1021. (msg = dblayer_strerror( retval )) ? msg : "", 0 );
  1022. if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
  1023. MOD_SET_ERROR(ldap_result_code,
  1024. LDAP_OPERATIONS_ERROR, retry_count);
  1025. goto error_return;
  1026. }
  1027. /* Push out the db modifications from the new parent entry */
  1028. else /* retval == 0 */
  1029. {
  1030. retval = modify_update_all(be, pb, &newparent_modify_context, &txn);
  1031. slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_modrdn",
  1032. "conn=%lu op=%d modify_update_all: old_entry=0x%p, new_entry=0x%p, rc=%d\n",
  1033. conn_id, op_id, parent_modify_context.old_entry, parent_modify_context.new_entry, retval);
  1034. if (DB_LOCK_DEADLOCK == retval)
  1035. {
  1036. /* Retry txn */
  1037. continue;
  1038. }
  1039. if (0 != retval)
  1040. {
  1041. LDAPDebug( LDAP_DEBUG_ANY, "modrdn: "
  1042. "could not update parent, err=%d %s\n", retval,
  1043. (msg = dblayer_strerror( retval )) ? msg : "",
  1044. 0 );
  1045. if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
  1046. MOD_SET_ERROR(ldap_result_code,
  1047. LDAP_OPERATIONS_ERROR, retry_count);
  1048. goto error_return;
  1049. }
  1050. }
  1051. }
  1052. /*
  1053. * Update ancestorid index.
  1054. */
  1055. if (slapi_sdn_get_dn(dn_newsuperiordn)!=NULL) {
  1056. retval = ldbm_ancestorid_move_subtree(be, sdn, &dn_newdn, e->ep_id, children, &txn);
  1057. if (retval != 0) {
  1058. if (retval == DB_LOCK_DEADLOCK) continue;
  1059. if (retval == DB_RUNRECOVERY || LDBM_OS_ERR_IS_DISKFULL(retval))
  1060. disk_full = 1;
  1061. MOD_SET_ERROR(ldap_result_code,
  1062. LDAP_OPERATIONS_ERROR, retry_count);
  1063. goto error_return;
  1064. }
  1065. }
  1066. /*
  1067. * Update entryrdn index
  1068. */
  1069. if (entryrdn_get_switch()) /* subtree-rename: on */
  1070. {
  1071. Slapi_RDN newsrdn;
  1072. slapi_rdn_init_sdn(&newsrdn, (const Slapi_DN *)&dn_newdn);
  1073. retval = entryrdn_rename_subtree(be, (const Slapi_DN *)sdn, &newsrdn,
  1074. (const Slapi_DN *)dn_newsuperiordn,
  1075. e->ep_id, &txn, is_tombstone);
  1076. slapi_rdn_done(&newsrdn);
  1077. if (retval != 0) {
  1078. if (retval == DB_LOCK_DEADLOCK) continue;
  1079. if (retval == DB_RUNRECOVERY || LDBM_OS_ERR_IS_DISKFULL(retval))
  1080. disk_full = 1;
  1081. MOD_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
  1082. slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_modrdn",
  1083. "entryrdn_rename_subtree failed (%d); dn: %s, newsrdn: %s, dn_newsuperiordn: %s\n",
  1084. retval, slapi_sdn_get_dn(sdn), slapi_rdn_get_rdn(&newsrdn),
  1085. slapi_sdn_get_dn(dn_newsuperiordn));
  1086. goto error_return;
  1087. }
  1088. }
  1089. /*
  1090. * If the entry has children, then rename them all.
  1091. */
  1092. if (!entryrdn_get_switch() && children) /* subtree-rename: off */
  1093. {
  1094. retval= moddn_rename_children(&txn, pb, be, children, sdn,
  1095. &dn_newdn, child_entries);
  1096. }
  1097. if (DB_LOCK_DEADLOCK == retval)
  1098. {
  1099. /* Retry txn */
  1100. continue;
  1101. }
  1102. if (retval != 0)
  1103. {
  1104. if (retval == DB_RUNRECOVERY || LDBM_OS_ERR_IS_DISKFULL(retval))
  1105. disk_full = 1;
  1106. MOD_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
  1107. goto error_return;
  1108. }
  1109. if (!is_ruv && !is_fixup_operation && !NO_RUV_UPDATE(li)) {
  1110. ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
  1111. if (-1 == ruv_c_init) {
  1112. LDAPDebug( LDAP_DEBUG_ANY,
  1113. "ldbm_back_modrdn: ldbm_txn_ruv_modify_context "
  1114. "failed to construct RUV modify context\n",
  1115. 0, 0, 0);
  1116. ldap_result_code = LDAP_OPERATIONS_ERROR;
  1117. retval = 0;
  1118. goto error_return;
  1119. }
  1120. }
  1121. if (ruv_c_init) {
  1122. retval = modify_update_all( be, pb, &ruv_c, &txn );
  1123. if (DB_LOCK_DEADLOCK == retval) {
  1124. /* Abort and re-try */
  1125. continue;
  1126. }
  1127. if (0 != retval) {
  1128. LDAPDebug( LDAP_DEBUG_ANY,
  1129. "modify_update_all failed, err=%d %s\n", retval,
  1130. (msg = dblayer_strerror( retval )) ? msg : "", 0 );
  1131. if (LDBM_OS_ERR_IS_DISKFULL(retval)) {
  1132. disk_full = 1;
  1133. }
  1134. ldap_result_code= LDAP_OPERATIONS_ERROR;
  1135. goto error_return;
  1136. }
  1137. }
  1138. break; /* retval==0, Done, Terminate the loop */
  1139. }
  1140. if (retry_count == RETRY_TIMES)
  1141. {
  1142. /* Failed */
  1143. LDAPDebug( LDAP_DEBUG_ANY, "Retry count exceeded in modrdn\n", 0, 0, 0 );
  1144. ldap_result_code= LDAP_BUSY;
  1145. goto error_return;
  1146. }
  1147. postentry = slapi_entry_dup( ec->ep_entry );
  1148. if(parententry!=NULL)
  1149. {
  1150. modify_switch_entries( &parent_modify_context,be);
  1151. }
  1152. if(newparententry!=NULL)
  1153. {
  1154. myrc = modify_switch_entries( &newparent_modify_context,be);
  1155. slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_modrdn",
  1156. "conn=%lu op=%d modify_switch_entries: old_entry=0x%p, new_entry=0x%p, rc=%d\n",
  1157. conn_id, op_id, parent_modify_context.old_entry, parent_modify_context.new_entry, myrc);
  1158. }
  1159. slapi_pblock_set( pb, SLAPI_ENTRY_POST_OP, postentry );
  1160. /* call the transaction post modrdn plugins just before the commit */
  1161. if ((retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_POST_MODRDN_FN))) {
  1162. LDAPDebug1Arg( LDAP_DEBUG_TRACE, "SLAPI_PLUGIN_BE_TXN_POST_MODRDN_FN plugin "
  1163. "returned error code %d\n", retval );
  1164. if (!ldap_result_code) {
  1165. slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
  1166. }
  1167. if (!ldap_result_code) {
  1168. LDAPDebug0Args( LDAP_DEBUG_ANY, "SLAPI_PLUGIN_BE_TXN_POST_MODRDN_FN plugin "
  1169. "returned error but did not set SLAPI_RESULT_CODE\n" );
  1170. ldap_result_code = LDAP_OPERATIONS_ERROR;
  1171. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
  1172. }
  1173. if (!opreturn) {
  1174. slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &opreturn);
  1175. }
  1176. if (!opreturn) {
  1177. slapi_pblock_set( pb, SLAPI_PLUGIN_OPRETURN, ldap_result_code ? &ldap_result_code : &retval );
  1178. }
  1179. slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
  1180. goto error_return;
  1181. }
  1182. /* Release SERIAL LOCK */
  1183. retval = dblayer_txn_commit(be, &txn);
  1184. /* after commit - txn is no longer valid - replace SLAPI_TXN with parent */
  1185. slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
  1186. if (0 != retval)
  1187. {
  1188. if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
  1189. MOD_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
  1190. goto error_return;
  1191. }
  1192. if(children)
  1193. {
  1194. int i = 0;
  1195. if (child_entries && *child_entries)
  1196. {
  1197. if (entryrdn_get_switch()) /* subtree-rename: on */
  1198. {
  1199. /*
  1200. * If subtree-rename is on, delete subordinate entries from the
  1201. * entry cache. Next time the entries are read from the db,
  1202. * "renamed" dn is generated based upon the moved subtree.
  1203. */
  1204. for (i = 0; child_entries[i] != NULL; i++) {
  1205. if (is_resurect_operation) {
  1206. slapi_log_error(SLAPI_LOG_CACHE, "ldbm_back_modrdn",
  1207. "Calling cache remove & return %s (refcnt: %d)\n",
  1208. slapi_entry_get_dn(child_entries[i]->ep_entry),
  1209. child_entries[i]->ep_refcnt);
  1210. }
  1211. CACHE_REMOVE( &inst->inst_cache, child_entries[i] );
  1212. cache_unlock_entry( &inst->inst_cache, child_entries[i] );
  1213. CACHE_RETURN( &inst->inst_cache, &child_entries[i] );
  1214. }
  1215. }
  1216. else
  1217. {
  1218. for (; child_entries[i]!=NULL; i++) {
  1219. cache_unlock_entry( &inst->inst_cache, child_entries[i] );
  1220. CACHE_RETURN( &inst->inst_cache, &(child_entries[i]) );
  1221. }
  1222. }
  1223. }
  1224. if (entryrdn_get_switch() && child_dns && *child_dns)
  1225. {
  1226. for (i = 0; child_dns[i] != NULL; i++) {
  1227. CACHE_REMOVE( &inst->inst_dncache, child_dns[i] );
  1228. CACHE_RETURN( &inst->inst_dncache, &child_dns[i] );
  1229. }
  1230. }
  1231. }
  1232. if (ruv_c_init) {
  1233. if (modify_switch_entries(&ruv_c, be) != 0 ) {
  1234. ldap_result_code= LDAP_OPERATIONS_ERROR;
  1235. LDAPDebug( LDAP_DEBUG_ANY,
  1236. "ldbm_back_modrdn: modify_switch_entries failed\n", 0, 0, 0);
  1237. goto error_return;
  1238. }
  1239. }
  1240. retval= 0;
  1241. goto common_return;
  1242. error_return:
  1243. /* result already sent above - just free stuff */
  1244. if (postentry) {
  1245. slapi_entry_free( postentry );
  1246. postentry= NULL;
  1247. /* make sure caller doesn't attempt to free this */
  1248. slapi_pblock_set( pb, SLAPI_ENTRY_POST_OP, postentry );
  1249. }
  1250. if(children) {
  1251. int i = 0;
  1252. if (child_entries && *child_entries && inst)
  1253. {
  1254. if (entryrdn_get_switch()) /* subtree-rename: on */
  1255. {
  1256. /*
  1257. * If subtree-rename is on, delete subordinate entries from the
  1258. * entry cache even if the procedure was not successful.
  1259. */
  1260. for (i = 0; child_entries[i] != NULL; i++) {
  1261. CACHE_REMOVE( &inst->inst_cache, child_entries[i] );
  1262. cache_unlock_entry( &inst->inst_cache, child_entries[i] );
  1263. CACHE_RETURN( &inst->inst_cache, &child_entries[i] );
  1264. }
  1265. }
  1266. else
  1267. {
  1268. for(;child_entries[i]!=NULL;i++) {
  1269. cache_unlock_entry( &inst->inst_cache, child_entries[i] );
  1270. CACHE_RETURN( &inst->inst_cache, &(child_entries[i]) );
  1271. }
  1272. }
  1273. }
  1274. if (entryrdn_get_switch() && child_dns && *child_dns && inst)
  1275. {
  1276. for (i = 0; child_dns[i] != NULL; i++) {
  1277. CACHE_REMOVE( &inst->inst_dncache, child_dns[i] );
  1278. CACHE_RETURN( &inst->inst_dncache, &child_dns[i] );
  1279. }
  1280. }
  1281. }
  1282. if (retval == DB_RUNRECOVERY) {
  1283. dblayer_remember_disk_filled(li);
  1284. ldbm_nasty("ModifyDN",82,retval);
  1285. disk_full = 1;
  1286. }
  1287. if (disk_full)
  1288. {
  1289. retval = return_on_disk_full(li);
  1290. }
  1291. else
  1292. {
  1293. /* It is safer not to abort when the transaction is not started. */
  1294. if (txn.back_txn_txn && (txn.back_txn_txn != parent_txn))
  1295. {
  1296. /* make sure SLAPI_RESULT_CODE and SLAPI_PLUGIN_OPRETURN are set */
  1297. int val = 0;
  1298. slapi_pblock_get(pb, SLAPI_RESULT_CODE, &val);
  1299. if (!val) {
  1300. if (!ldap_result_code) {
  1301. ldap_result_code = LDAP_OPERATIONS_ERROR;
  1302. }
  1303. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
  1304. }
  1305. slapi_pblock_get( pb, SLAPI_PLUGIN_OPRETURN, &val );
  1306. if (!val) {
  1307. opreturn = -1;
  1308. slapi_pblock_set( pb, SLAPI_PLUGIN_OPRETURN, &opreturn );
  1309. }
  1310. /* call the transaction post modrdn plugins just before the abort */
  1311. if ((retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_POST_MODRDN_FN))) {
  1312. LDAPDebug1Arg( LDAP_DEBUG_TRACE, "SLAPI_PLUGIN_BE_TXN_POST_MODRDN_FN plugin "
  1313. "returned error code %d\n", retval );
  1314. if (!ldap_result_code) {
  1315. slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
  1316. }
  1317. if (!opreturn) {
  1318. slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &opreturn);
  1319. }
  1320. if (!opreturn) {
  1321. slapi_pblock_set( pb, SLAPI_PLUGIN_OPRETURN, ldap_result_code ? &ldap_result_code : &retval );
  1322. }
  1323. slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
  1324. }
  1325. /* Release SERIAL LOCK */
  1326. dblayer_txn_abort(be, &txn); /* abort crashes in case disk full */
  1327. /* txn is no longer valid - reset the txn pointer to the parent */
  1328. slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
  1329. }
  1330. if (!not_an_error) {
  1331. retval = SLAPI_FAIL_GENERAL;
  1332. }
  1333. }
  1334. common_return:
  1335. /* result code could be used in the bepost plugin functions. */
  1336. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
  1337. /*
  1338. * The bepostop is called even if the operation fails.
  1339. */
  1340. plugin_call_plugins (pb, SLAPI_PLUGIN_BE_POST_MODRDN_FN);
  1341. /* Free up the resource we don't need any more */
  1342. if (ec) {
  1343. if (is_resurect_operation) {
  1344. slapi_log_error(SLAPI_LOG_REPL, "ldbm_back_modrdn",
  1345. "Resurrecting an entry %s: result: %d, %d\n",
  1346. slapi_entry_get_dn(ec->ep_entry), ldap_result_code, retval);
  1347. }
  1348. if (inst && (0 == retval) && entryrdn_get_switch()) { /* subtree-rename: on */
  1349. /* since the op was successful, add the addingentry's dn to the dn cache */
  1350. struct backdn *bdn = dncache_find_id(&inst->inst_dncache, ec->ep_id);
  1351. if (bdn) { /* already in the dncache */
  1352. CACHE_RETURN(&inst->inst_dncache, &bdn);
  1353. } else { /* not in the dncache yet */
  1354. Slapi_DN *ecsdn = slapi_sdn_dup(slapi_entry_get_sdn(ec->ep_entry));
  1355. if (ecsdn) {
  1356. bdn = backdn_init(ecsdn, ec->ep_id, 0);
  1357. if (bdn) {
  1358. CACHE_ADD( &inst->inst_dncache, bdn, NULL );
  1359. CACHE_RETURN(&inst->inst_dncache, &bdn);
  1360. slapi_log_error(SLAPI_LOG_CACHE, "ldbm_back_modrdn",
  1361. "set %s to dn cache\n", slapi_sdn_get_dn(sdn));
  1362. }
  1363. }
  1364. }
  1365. }
  1366. /* remove the new entry from the cache if the op failed -
  1367. otherwise, leave it in */
  1368. if (ec && inst) {
  1369. if (retval && cache_is_in_cache(&inst->inst_cache, ec)) {
  1370. CACHE_REMOVE( &inst->inst_cache, ec );
  1371. }
  1372. CACHE_RETURN( &inst->inst_cache, &ec );
  1373. }
  1374. ec = NULL;
  1375. }
  1376. if (inst) {
  1377. if (e && entryrdn_get_switch() && (0 == retval)) {
  1378. struct backdn *bdn = dncache_find_id(&inst->inst_dncache, e->ep_id);
  1379. CACHE_REMOVE(&inst->inst_dncache, bdn);
  1380. CACHE_RETURN(&inst->inst_dncache, &bdn);
  1381. }
  1382. if (inst->inst_ref_count) {
  1383. slapi_counter_decrement(inst->inst_ref_count);
  1384. }
  1385. }
  1386. moddn_unlock_and_return_entry(be,&e);
  1387. if (ruv_c_init) {
  1388. modify_term(&ruv_c, be);
  1389. }
  1390. if (ldap_result_code!=-1)
  1391. {
  1392. if (not_an_error) {
  1393. /* This is mainly used by urp. Solved conflict is not an error.
  1394. * And we don't want the supplier to halt sending the updates. */
  1395. ldap_result_code = LDAP_SUCCESS;
  1396. }
  1397. slapi_send_ldap_result( pb, ldap_result_code, ldap_result_matcheddn,
  1398. ldap_result_message, 0,NULL );
  1399. }
  1400. slapi_mods_done(&smods_operation_wsi);
  1401. slapi_mods_done(&smods_generated);
  1402. slapi_mods_done(&smods_generated_wsi);
  1403. slapi_ch_free((void**)&child_entries);
  1404. slapi_ch_free((void**)&child_dns);
  1405. if (ldap_result_matcheddn && 0 != strcmp(ldap_result_matcheddn, "NULL"))
  1406. slapi_ch_free((void**)&ldap_result_matcheddn);
  1407. idl_free(&children);
  1408. slapi_sdn_done(&dn_newdn);
  1409. slapi_sdn_done(&dn_newrdn);
  1410. slapi_sdn_done(&dn_parentdn);
  1411. slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_modrdn",
  1412. "conn=%lu op=%d modify_term: old_entry=0x%p, new_entry=0x%p\n",
  1413. conn_id, op_id, parent_modify_context.old_entry, parent_modify_context.new_entry);
  1414. myrc = modify_term(&parent_modify_context,be);
  1415. slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_modrdn",
  1416. "conn=%lu op=%d modify_term: rc=%d\n", conn_id, op_id, myrc);
  1417. slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_modrdn",
  1418. "conn=%lu op=%d modify_term: old_entry=0x%p, new_entry=0x%p\n",
  1419. conn_id, op_id, newparent_modify_context.old_entry, newparent_modify_context.new_entry);
  1420. myrc = modify_term(&newparent_modify_context,be);
  1421. if (free_modrdn_existing_entry) {
  1422. done_with_pblock_entry(pb,SLAPI_MODRDN_EXISTING_ENTRY);
  1423. } else { /* owned by original_entry */
  1424. slapi_pblock_set(pb, SLAPI_MODRDN_EXISTING_ENTRY, NULL);
  1425. }
  1426. done_with_pblock_entry(pb,SLAPI_MODRDN_PARENT_ENTRY);
  1427. done_with_pblock_entry(pb,SLAPI_MODRDN_NEWPARENT_ENTRY);
  1428. done_with_pblock_entry(pb,SLAPI_MODRDN_TARGET_ENTRY);
  1429. slapi_ch_free_string(&original_newrdn);
  1430. slapi_sdn_free(&orig_dn_newsuperiordn);
  1431. backentry_free(&original_entry);
  1432. backentry_free(&tmpentry);
  1433. slapi_entry_free(original_targetentry);
  1434. slapi_ch_free((void**)&errbuf);
  1435. if (retval == 0 && opcsn != NULL && !is_fixup_operation)
  1436. {
  1437. slapi_pblock_set(pb, SLAPI_URP_NAMING_COLLISION_DN,
  1438. slapi_ch_strdup(slapi_sdn_get_dn(sdn)));
  1439. }
  1440. if (pb->pb_conn)
  1441. {
  1442. slapi_log_error (SLAPI_LOG_TRACE, "ldbm_back_modrdn", "leave conn=%" NSPRIu64 " op=%d\n",
  1443. pb->pb_conn->c_connid, operation->o_opid);
  1444. }
  1445. return retval;
  1446. }
  1447. /*
  1448. * Work out what the new DN of the entry will be.
  1449. */
  1450. static const char *
  1451. moddn_get_newdn(Slapi_PBlock *pb, Slapi_DN *dn_olddn, Slapi_DN *dn_newrdn, Slapi_DN *dn_newsuperiordn, int is_tombstone)
  1452. {
  1453. char *newdn;
  1454. const char *newrdn= slapi_sdn_get_dn(dn_newrdn);
  1455. const char *newsuperiordn= slapi_sdn_get_dn(dn_newsuperiordn);
  1456. if( newsuperiordn!=NULL)
  1457. {
  1458. /* construct the new dn */
  1459. if(slapi_dn_isroot(newsuperiordn))
  1460. {
  1461. newdn= slapi_ch_strdup(newrdn);
  1462. }
  1463. else
  1464. {
  1465. newdn= slapi_dn_plus_rdn(newsuperiordn, newrdn); /* JCM - Use Slapi_RDN */
  1466. }
  1467. }
  1468. else
  1469. {
  1470. /* construct the new dn */
  1471. const char *dn = slapi_sdn_get_dn((const Slapi_DN *)dn_olddn);
  1472. if (slapi_dn_isbesuffix(pb, dn)) {
  1473. newdn = slapi_ch_strdup(newrdn);
  1474. } else {
  1475. /* no need to free this pdn. */
  1476. const char *pdn = slapi_dn_find_parent_ext(dn, is_tombstone);
  1477. if (pdn) {
  1478. newdn = slapi_dn_plus_rdn(pdn, newrdn);
  1479. } else {
  1480. newdn = slapi_ch_strdup(newrdn);
  1481. }
  1482. }
  1483. }
  1484. return newdn;
  1485. }
  1486. /*
  1487. * Return the entries to the cache.
  1488. */
  1489. static void
  1490. moddn_unlock_and_return_entry(
  1491. backend *be,
  1492. struct backentry **targetentry)
  1493. {
  1494. ldbm_instance *inst = (ldbm_instance *) be->be_instance_info;
  1495. /* Something bad happened so we should give back all the entries */
  1496. if ( *targetentry!=NULL ) {
  1497. cache_unlock_entry(&inst->inst_cache, *targetentry);
  1498. CACHE_RETURN( &inst->inst_cache, targetentry );
  1499. *targetentry= NULL;
  1500. }
  1501. }
  1502. /*
  1503. * JCM - There was a problem with multi-valued RDNs where
  1504. * JCM - there was an intersection of the two sets RDN Components
  1505. * JCM - and the deleteoldrdn flag was set. A value was deleted
  1506. * JCM - but not re-added because the value is found to already
  1507. * JCM - exist.
  1508. *
  1509. * This function returns 1 if it is necessary to add an RDN value
  1510. * to the entry. This is necessary if either:
  1511. * 1 the attribute or the value is not present in the entry, or
  1512. * 2 the attribute is present, deleteoldrdn is set, and the RDN value
  1513. * is in the deleted list.
  1514. *
  1515. * For example, suppose you rename cn=a to cn=a+sn=b. The cn=a value
  1516. * is removed from the entry and then readded.
  1517. */
  1518. static int
  1519. moddn_rdn_add_needed (
  1520. struct backentry *ec,
  1521. char *type,
  1522. struct berval *bvp,
  1523. int deleteoldrdn,
  1524. Slapi_Mods *smods_wsi
  1525. )
  1526. {
  1527. Slapi_Attr *attr;
  1528. LDAPMod *mod;
  1529. if (slapi_entry_attr_find(ec->ep_entry, type, &attr) != 0 ||
  1530. slapi_attr_value_find( attr, bvp ) != 0 )
  1531. {
  1532. return 1;
  1533. }
  1534. if (deleteoldrdn == 0) return 0;
  1535. /* in a multi-valued RDN, the RDN value might have been already
  1536. * put on the smods_wsi list to be deleted, yet might still be
  1537. * in the target RDN.
  1538. */
  1539. for (mod = slapi_mods_get_first_mod(smods_wsi);
  1540. mod != NULL;
  1541. mod = slapi_mods_get_next_mod(smods_wsi)) {
  1542. if (SLAPI_IS_MOD_DELETE(mod->mod_op) &&
  1543. (strcasecmp(mod->mod_type, type) == 0) &&
  1544. (mod->mod_bvalues != NULL) &&
  1545. (slapi_attr_value_cmp(attr, *mod->mod_bvalues, bvp) == 0)) {
  1546. return 1;
  1547. }
  1548. }
  1549. return 0;
  1550. }
  1551. /*
  1552. * Build the list of modifications to apply to the Existing Entry
  1553. * With State Information:
  1554. * - delete old rdn values from the entry if deleteoldrdn is set
  1555. * - add new rdn values to the entry
  1556. * Without State Information
  1557. * - No changes
  1558. */
  1559. static int
  1560. moddn_newrdn_mods(Slapi_PBlock *pb, const char *olddn, struct backentry *ec, Slapi_Mods *smods_wsi, int is_repl_op)
  1561. {
  1562. char **rdns = NULL;
  1563. char **dns = NULL;
  1564. int deleteoldrdn;
  1565. char *type = NULL;
  1566. char *dn = NULL;
  1567. char *newrdn = NULL;
  1568. int i;
  1569. struct berval *bvps[2];
  1570. struct berval bv;
  1571. bvps[0] = &bv;
  1572. bvps[1] = NULL;
  1573. /* slapi_pblock_get( pb, SLAPI_MODRDN_TARGET, &dn ); */
  1574. slapi_pblock_get( pb, SLAPI_MODRDN_NEWRDN, &newrdn );
  1575. slapi_pblock_get( pb, SLAPI_MODRDN_DELOLDRDN, &deleteoldrdn );
  1576. /*
  1577. * This loop removes the old RDN of the existing entry.
  1578. */
  1579. if (deleteoldrdn) {
  1580. int baddn = 0; /* set to true if could not parse dn */
  1581. int badrdn = 0; /* set to true if could not parse rdn */
  1582. dn = slapi_ch_strdup(olddn);
  1583. dns = slapi_ldap_explode_dn( dn, 0 );
  1584. if ( dns != NULL )
  1585. {
  1586. rdns = slapi_ldap_explode_rdn( dns[0], 0 );
  1587. if ( rdns != NULL )
  1588. {
  1589. for ( i = 0; rdns[i] != NULL; i++ )
  1590. {
  1591. /* delete from entry attributes */
  1592. if ( deleteoldrdn && slapi_rdn2typeval( rdns[i], &type, &bv ) == 0 )
  1593. {
  1594. /* check if user is allowed to modify the specified attribute */
  1595. /*
  1596. * It would be better to do this check in the front end
  1597. * end inside op_shared_rename(), but unfortunately we
  1598. * don't have access to the target entry there.
  1599. */
  1600. if (!op_shared_is_allowed_attr (type, is_repl_op))
  1601. {
  1602. slapi_ldap_value_free( rdns );
  1603. slapi_ldap_value_free( dns );
  1604. slapi_ch_free_string(&dn);
  1605. return LDAP_UNWILLING_TO_PERFORM;
  1606. }
  1607. if (strcasecmp (type, SLAPI_ATTR_UNIQUEID) != 0)
  1608. slapi_mods_add_modbvps( smods_wsi, LDAP_MOD_DELETE, type, bvps );
  1609. }
  1610. }
  1611. slapi_ldap_value_free( rdns );
  1612. }
  1613. else
  1614. {
  1615. badrdn = 1;
  1616. }
  1617. slapi_ldap_value_free( dns );
  1618. }
  1619. else
  1620. {
  1621. baddn = 1;
  1622. }
  1623. slapi_ch_free_string(&dn);
  1624. if ( baddn || badrdn )
  1625. {
  1626. LDAPDebug( LDAP_DEBUG_TRACE, "moddn_newrdn_mods failed: olddn=%s baddn=%d badrdn=%d\n",
  1627. olddn, baddn, badrdn);
  1628. return LDAP_OPERATIONS_ERROR;
  1629. }
  1630. }
  1631. /*
  1632. * add new RDN values to the entry (non-normalized)
  1633. */
  1634. rdns = slapi_ldap_explode_rdn( newrdn, 0 );
  1635. if ( rdns != NULL )
  1636. {
  1637. for ( i = 0; rdns[i] != NULL; i++ )
  1638. {
  1639. if ( slapi_rdn2typeval( rdns[i], &type, &bv ) != 0) {
  1640. continue;
  1641. }
  1642. /* add to entry if it's not already there or if was
  1643. * already deleted
  1644. */
  1645. if (moddn_rdn_add_needed(ec, type, &bv,
  1646. deleteoldrdn,
  1647. smods_wsi) == 1) {
  1648. slapi_mods_add_modbvps( smods_wsi, LDAP_MOD_ADD, type, bvps );
  1649. }
  1650. }
  1651. slapi_ldap_value_free( rdns );
  1652. }
  1653. else
  1654. {
  1655. LDAPDebug( LDAP_DEBUG_TRACE, "moddn_newrdn_mods failed: could not parse new rdn %s\n",
  1656. newrdn, 0, 0);
  1657. return LDAP_OPERATIONS_ERROR;
  1658. }
  1659. return LDAP_SUCCESS;
  1660. }
  1661. static void
  1662. mods_remove_nsuniqueid(Slapi_Mods *smods)
  1663. {
  1664. int i;
  1665. LDAPMod **mods = slapi_mods_get_ldapmods_byref(smods);
  1666. for ( i = 0; mods[i] != NULL; i++ ) {
  1667. if (!strcasecmp(mods[i]->mod_type, SLAPI_ATTR_UNIQUEID)) {
  1668. mods[i]->mod_op = LDAP_MOD_IGNORE;
  1669. }
  1670. }
  1671. }
  1672. /*
  1673. * Update the indexes to reflect the DN change made.
  1674. * e is the entry before, ec the entry after.
  1675. * mods contains the list of attribute change made.
  1676. */
  1677. static int
  1678. modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbminfo *li,
  1679. struct backentry *e, struct backentry **ec,
  1680. Slapi_Mods *smods1, Slapi_Mods *smods2, Slapi_Mods *smods3)
  1681. {
  1682. backend *be;
  1683. ldbm_instance *inst;
  1684. int retval= 0;
  1685. char *msg;
  1686. Slapi_Operation *operation;
  1687. int is_ruv = 0; /* True if the current entry is RUV */
  1688. int cache_rc = 0;
  1689. slapi_pblock_get( pb, SLAPI_BACKEND, &be );
  1690. slapi_pblock_get( pb, SLAPI_OPERATION, &operation );
  1691. is_ruv = operation_is_flag_set(operation, OP_FLAG_REPL_RUV);
  1692. inst = (ldbm_instance *) be->be_instance_info;
  1693. /*
  1694. * Update the ID to Entry index.
  1695. * Note that id2entry_add replaces the entry, so the Entry ID stays the same.
  1696. */
  1697. retval = id2entry_add_ext(be, *ec, ptxn, 1, &cache_rc);
  1698. if (cache_rc) {
  1699. LDAPDebug(LDAP_DEBUG_CACHE,
  1700. "modrdn_rename_entry_update_indexes: adding %s failed to add to the cache (rc: %d, cache_rc: %d)\n",
  1701. slapi_entry_get_dn(e->ep_entry), retval, cache_rc);
  1702. }
  1703. if (DB_LOCK_DEADLOCK == retval)
  1704. {
  1705. /* Retry txn */
  1706. LDAPDebug0Args( LDAP_DEBUG_BACKLDBM, "modrdn_rename_entry_update_indexes: id2entry_add deadlock\n" );
  1707. goto error_return;
  1708. }
  1709. if (retval != 0)
  1710. {
  1711. LDAPDebug( LDAP_DEBUG_ANY, "modrdn_rename_entry_update_indexes: id2entry_add failed, err=%d %s\n", retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
  1712. goto error_return;
  1713. }
  1714. if(smods1!=NULL && slapi_mods_get_num_mods(smods1)>0)
  1715. {
  1716. /*
  1717. * update the indexes: lastmod, rdn, etc.
  1718. */
  1719. retval = index_add_mods( be, slapi_mods_get_ldapmods_byref(smods1), e, *ec, ptxn );
  1720. if (DB_LOCK_DEADLOCK == retval)
  1721. {
  1722. /* Retry txn */
  1723. LDAPDebug0Args( LDAP_DEBUG_BACKLDBM, "modrdn_rename_entry_update_indexes: index_add_mods1 deadlock\n" );
  1724. goto error_return;
  1725. }
  1726. if (retval != 0)
  1727. {
  1728. LDAPDebug( LDAP_DEBUG_TRACE, "index_add_mods 1 failed, err=%d %s\n", retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
  1729. goto error_return;
  1730. }
  1731. }
  1732. if(smods2!=NULL && slapi_mods_get_num_mods(smods2)>0)
  1733. {
  1734. /*
  1735. * smods2 contains the state generated mods. One of them might be the removal of a "nsuniqueid" rdn component
  1736. * previously gnerated through a conflict resolution. We need to make sure we don't remove the index for "nsuniqueid"
  1737. * so let's get it out from the mods before calling index_add_mods...
  1738. */
  1739. mods_remove_nsuniqueid(smods2);
  1740. /*
  1741. * update the indexes: lastmod, rdn, etc.
  1742. */
  1743. retval = index_add_mods( be, slapi_mods_get_ldapmods_byref(smods2), e, *ec, ptxn );
  1744. if (DB_LOCK_DEADLOCK == retval)
  1745. {
  1746. /* Retry txn */
  1747. LDAPDebug0Args( LDAP_DEBUG_BACKLDBM, "modrdn_rename_entry_update_indexes: index_add_mods2 deadlock\n" );
  1748. goto error_return;
  1749. }
  1750. if (retval != 0)
  1751. {
  1752. LDAPDebug( LDAP_DEBUG_TRACE, "index_add_mods 2 failed, err=%d %s\n", retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
  1753. goto error_return;
  1754. }
  1755. }
  1756. if(smods3!=NULL && slapi_mods_get_num_mods(smods3)>0)
  1757. {
  1758. /*
  1759. * update the indexes: lastmod, rdn, etc.
  1760. */
  1761. retval = index_add_mods( be, slapi_mods_get_ldapmods_byref(smods3), e, *ec, ptxn );
  1762. if (DB_LOCK_DEADLOCK == retval)
  1763. {
  1764. /* Retry txn */
  1765. LDAPDebug0Args( LDAP_DEBUG_BACKLDBM, "modrdn_rename_entry_update_indexes: index_add_mods3 deadlock\n" );
  1766. goto error_return;
  1767. }
  1768. if (retval != 0)
  1769. {
  1770. LDAPDebug( LDAP_DEBUG_TRACE, "index_add_mods 3 failed, err=%d %s\n", retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
  1771. goto error_return;
  1772. }
  1773. }
  1774. /*
  1775. * Remove the old entry from the Virtual List View indexes.
  1776. * Add the new entry to the Virtual List View indexes.
  1777. * If ruv, we don't have to update vlv.
  1778. */
  1779. if (!is_ruv)
  1780. {
  1781. retval= vlv_update_all_indexes(ptxn, be, pb, e, *ec);
  1782. if (DB_LOCK_DEADLOCK == retval)
  1783. {
  1784. /* Abort and re-try */
  1785. LDAPDebug0Args( LDAP_DEBUG_BACKLDBM, "modrdn_rename_entry_update_indexes: vlv_update_all_indexes deadlock\n" );
  1786. goto error_return;
  1787. }
  1788. if (retval != 0)
  1789. {
  1790. LDAPDebug( LDAP_DEBUG_TRACE, "vlv_update_all_indexes failed, err=%d %s\n", retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
  1791. goto error_return;
  1792. }
  1793. }
  1794. if (cache_replace( &inst->inst_cache, e, *ec ) != 0 ) {
  1795. LDAPDebug2Args(LDAP_DEBUG_CACHE,
  1796. "modrdn_rename_entry_update_indexes cache_replace %s -> %s failed\n",
  1797. slapi_entry_get_dn(e->ep_entry), slapi_entry_get_dn((*ec)->ep_entry));
  1798. retval= -1;
  1799. goto error_return;
  1800. }
  1801. error_return:
  1802. return retval;
  1803. }
  1804. static int
  1805. moddn_rename_child_entry(
  1806. back_txn *ptxn,
  1807. Slapi_PBlock *pb,
  1808. struct ldbminfo *li,
  1809. struct backentry *e,
  1810. struct backentry **ec,
  1811. int parentdncomps,
  1812. char **newsuperiordns,
  1813. int newsuperiordncomps,
  1814. CSN *opcsn)
  1815. {
  1816. /*
  1817. * Construct the new DN for the entry by taking the old DN
  1818. * excluding the old parent entry DN, and adding the new
  1819. * superior entry DN.
  1820. *
  1821. * slapi_ldap_explode_dn is probably a bit slow, but it knows about
  1822. * DN escaping which is pretty complicated, and we wouldn't
  1823. * want to reimplement that here.
  1824. *
  1825. * JCM - This was written before Slapi_RDN... so this could be made much neater.
  1826. */
  1827. int retval = 0;
  1828. char *olddn;
  1829. char *newdn;
  1830. char **olddns;
  1831. int olddncomps= 0;
  1832. int need= 1; /* For the '\0' */
  1833. int i;
  1834. olddn = slapi_entry_get_dn((*ec)->ep_entry);
  1835. if (NULL == olddn) {
  1836. return retval;
  1837. }
  1838. olddns = slapi_ldap_explode_dn( olddn, 0 );
  1839. if (NULL == olddns) {
  1840. return retval;
  1841. }
  1842. for(;olddns[olddncomps]!=NULL;olddncomps++);
  1843. for(i=0;i<olddncomps-parentdncomps;i++)
  1844. {
  1845. need+= strlen(olddns[i]) + 2; /* For the ", " */
  1846. }
  1847. for(i=0;i<newsuperiordncomps;i++)
  1848. {
  1849. need+= strlen(newsuperiordns[i]) + 2; /* For the ", " */
  1850. }
  1851. need--; /* We don't have a comma on the end of the last component */
  1852. newdn= slapi_ch_malloc(need);
  1853. newdn[0]= '\0';
  1854. for(i=0;i<olddncomps-parentdncomps;i++)
  1855. {
  1856. strcat(newdn,olddns[i]);
  1857. strcat(newdn,", ");
  1858. }
  1859. for(i=0;i<newsuperiordncomps;i++)
  1860. {
  1861. strcat(newdn,newsuperiordns[i]);
  1862. if(i<newsuperiordncomps-1)
  1863. {
  1864. /* We don't have a comma on the end of the last component */
  1865. strcat(newdn,", ");
  1866. }
  1867. }
  1868. slapi_ldap_value_free( olddns );
  1869. slapi_entry_set_dn( (*ec)->ep_entry, newdn );
  1870. /* add the entrydn operational attributes */
  1871. add_update_entrydn_operational_attributes (*ec);
  1872. /*
  1873. * Update the DN CSN of the entry.
  1874. */
  1875. {
  1876. entry_add_dncsn(e->ep_entry, opcsn);
  1877. entry_add_rdn_csn(e->ep_entry, opcsn);
  1878. entry_set_maxcsn(e->ep_entry, opcsn);
  1879. }
  1880. {
  1881. Slapi_Mods smods;
  1882. Slapi_Mods *smodsp = NULL;
  1883. memset(&smods, 0, sizeof(smods));
  1884. slapi_mods_init(&smods, 2);
  1885. slapi_mods_add( &smods, LDAP_MOD_DELETE, LDBM_ENTRYDN_STR,
  1886. strlen( backentry_get_ndn(e) ), backentry_get_ndn(e) );
  1887. slapi_mods_add( &smods, LDAP_MOD_REPLACE, LDBM_ENTRYDN_STR,
  1888. strlen( backentry_get_ndn(*ec) ), backentry_get_ndn(*ec) );
  1889. smodsp = &smods;
  1890. /*
  1891. * Update all the indexes.
  1892. */
  1893. retval = modrdn_rename_entry_update_indexes(ptxn, pb, li, e, ec,
  1894. smodsp, NULL, NULL);
  1895. /* JCMREPL - Should the children get updated modifiersname and lastmodifiedtime? */
  1896. slapi_mods_done(&smods);
  1897. }
  1898. return retval;
  1899. }
  1900. /*
  1901. * Rename all the children of an entry who's name has changed.
  1902. * Called if "subtree-rename: off"
  1903. */
  1904. static int
  1905. moddn_rename_children(
  1906. back_txn *ptxn,
  1907. Slapi_PBlock *pb,
  1908. backend *be,
  1909. IDList *children,
  1910. Slapi_DN *dn_parentdn,
  1911. Slapi_DN *dn_newsuperiordn,
  1912. struct backentry *child_entries[])
  1913. {
  1914. /* Iterate over the children list renaming every child */
  1915. struct ldbminfo *li = (struct ldbminfo *) be->be_database->plg_private;
  1916. Slapi_Operation *operation;
  1917. CSN *opcsn;
  1918. int retval= -1, i;
  1919. char **newsuperiordns = NULL;
  1920. int newsuperiordncomps= 0;
  1921. int parentdncomps= 0;
  1922. NIDS nids = children ? children->b_nids : 0;
  1923. struct backentry **child_entry_copies = NULL;
  1924. ldbm_instance *inst = (ldbm_instance *)be->be_instance_info;
  1925. /*
  1926. * Break down the parent entry dn into its components.
  1927. */
  1928. {
  1929. char **parentdns = slapi_ldap_explode_dn( slapi_sdn_get_dn(dn_parentdn), 0 );
  1930. if (parentdns)
  1931. {
  1932. for(;parentdns[parentdncomps]!=NULL;parentdncomps++);
  1933. slapi_ldap_value_free( parentdns );
  1934. }
  1935. else
  1936. {
  1937. return retval;
  1938. }
  1939. }
  1940. /*
  1941. * Break down the new superior entry dn into its components.
  1942. */
  1943. newsuperiordns = slapi_ldap_explode_dn( slapi_sdn_get_dn(dn_newsuperiordn), 0 );
  1944. if (newsuperiordns)
  1945. {
  1946. for(;newsuperiordns[newsuperiordncomps]!=NULL;newsuperiordncomps++);
  1947. }
  1948. else
  1949. {
  1950. return retval;
  1951. }
  1952. /* probably, only if "subtree-rename is off */
  1953. child_entry_copies =
  1954. (struct backentry**)slapi_ch_calloc(sizeof(struct backentry*), nids+1);
  1955. for (i = 0; i <= nids; i++)
  1956. {
  1957. child_entry_copies[i] = backentry_dup(child_entries[i]);
  1958. }
  1959. /*
  1960. * Iterate over the child entries renaming them.
  1961. */
  1962. slapi_pblock_get( pb, SLAPI_OPERATION, &operation );
  1963. opcsn = operation_get_csn (operation);
  1964. for (i=0,retval=0; retval == 0 && child_entries[i] && child_entry_copies[i]; i++) {
  1965. retval = moddn_rename_child_entry(ptxn, pb, li, child_entries[i],
  1966. &child_entry_copies[i], parentdncomps,
  1967. newsuperiordns, newsuperiordncomps,
  1968. opcsn );
  1969. }
  1970. if (0 == retval) /* success */
  1971. {
  1972. CACHE_REMOVE( &inst->inst_cache, child_entry_copies[i] );
  1973. CACHE_RETURN( &inst->inst_cache, &(child_entry_copies[i]) );
  1974. }
  1975. else /* failure */
  1976. {
  1977. while (child_entries[i] != NULL)
  1978. {
  1979. backentry_free(&(child_entry_copies[i]));
  1980. i++;
  1981. }
  1982. }
  1983. slapi_ldap_value_free( newsuperiordns );
  1984. slapi_ch_free((void**)&child_entry_copies);
  1985. return retval;
  1986. }
  1987. /*
  1988. * Get an IDList of all the children of an entry.
  1989. */
  1990. static IDList *
  1991. moddn_get_children(back_txn *ptxn,
  1992. Slapi_PBlock *pb,
  1993. backend *be,
  1994. struct backentry *parententry,
  1995. Slapi_DN *dn_parentdn,
  1996. struct backentry ***child_entries,
  1997. struct backdn ***child_dns,
  1998. int is_resurect_operation)
  1999. {
  2000. ldbm_instance *inst = (ldbm_instance *) be->be_instance_info;
  2001. int err= 0;
  2002. IDList *candidates;
  2003. IDList *result_idl = NULL;
  2004. char filterstr[20];
  2005. Slapi_Filter *filter;
  2006. NIDS nids;
  2007. int entrynum = 0;
  2008. int dnnum = 0;
  2009. ID id;
  2010. idl_iterator sr_current; /* the current position in the search results */
  2011. struct backentry *e= NULL;
  2012. struct backdn *dn = NULL;
  2013. if (child_entries)
  2014. {
  2015. *child_entries = NULL;
  2016. }
  2017. if (child_dns)
  2018. {
  2019. *child_dns = NULL;
  2020. }
  2021. if (entryrdn_get_switch())
  2022. {
  2023. err = entryrdn_get_subordinates(be,
  2024. slapi_entry_get_sdn_const(parententry->ep_entry),
  2025. parententry->ep_id, &candidates, ptxn, is_resurect_operation);
  2026. if (err) {
  2027. LDAPDebug1Arg( LDAP_DEBUG_ANY, "moddn_get_children: "
  2028. "entryrdn_get_subordinates returned %d\n", err);
  2029. goto bail;
  2030. }
  2031. }
  2032. else
  2033. {
  2034. /* Fetch a candidate list of all the entries below the entry
  2035. * being moved */
  2036. strcpy( filterstr, "objectclass=*" );
  2037. filter = slapi_str2filter( filterstr );
  2038. candidates= subtree_candidates(pb, be, slapi_sdn_get_ndn(dn_parentdn),
  2039. parententry, filter, 1 /* ManageDSAIT */,
  2040. NULL /* allids_before_scopingp */, &err);
  2041. slapi_filter_free(filter,1);
  2042. }
  2043. if (candidates) {
  2044. Slapi_DN parentsdn = {0};
  2045. if (is_resurect_operation) {
  2046. slapi_sdn_get_parent(dn_parentdn, &parentsdn);
  2047. dn_parentdn = &parentsdn;
  2048. }
  2049. sr_current = idl_iterator_init(candidates);
  2050. result_idl= idl_alloc(candidates->b_nids);
  2051. do
  2052. {
  2053. id = idl_iterator_dereference_increment(&sr_current, candidates);
  2054. if ( id!=NOID )
  2055. {
  2056. int err= 0;
  2057. e = id2entry( be, id, ptxn, &err );
  2058. if (e!=NULL)
  2059. {
  2060. /* The subtree search will have included the parent
  2061. * entry in the result set */
  2062. if (e!=parententry)
  2063. {
  2064. /* Check that the candidate entry is really
  2065. * below the base. */
  2066. if(slapi_dn_issuffix( backentry_get_ndn(e),
  2067. slapi_sdn_get_ndn(dn_parentdn)))
  2068. {
  2069. /*
  2070. * The given ID list is not sorted.
  2071. * We have to call idl_insert instead of idl_append.
  2072. */
  2073. idl_insert(&result_idl,id);
  2074. }
  2075. }
  2076. CACHE_RETURN(&inst->inst_cache, &e);
  2077. }
  2078. }
  2079. } while (id!=NOID);
  2080. idl_free(&candidates);
  2081. slapi_sdn_done(&parentsdn);
  2082. }
  2083. nids = result_idl ? result_idl->b_nids : 0;
  2084. if (child_entries) {
  2085. *child_entries= (struct backentry**)slapi_ch_calloc(sizeof(struct backentry*),nids+1);
  2086. }
  2087. if (child_dns)
  2088. {
  2089. *child_dns = (struct backdn **)slapi_ch_calloc(sizeof(struct backdn *),nids+1);
  2090. }
  2091. sr_current = idl_iterator_init(result_idl);
  2092. do {
  2093. id = idl_iterator_dereference_increment(&sr_current, result_idl);
  2094. if ( id!=NOID ) {
  2095. if (child_entries) {
  2096. e = cache_find_id( &inst->inst_cache, id );
  2097. if ( e != NULL ) {
  2098. cache_lock_entry(&inst->inst_cache, e);
  2099. (*child_entries)[entrynum] = e;
  2100. entrynum++;
  2101. }
  2102. }
  2103. if (entryrdn_get_switch() && child_dns)
  2104. {
  2105. dn = dncache_find_id( &inst->inst_dncache, id );
  2106. if ( dn != NULL ) {
  2107. (*child_dns)[dnnum] = dn;
  2108. dnnum++;
  2109. }
  2110. }
  2111. }
  2112. } while (id!=NOID);
  2113. bail:
  2114. return result_idl;
  2115. }