dse.c 68 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. /*
  39. * dse.c - DSE (DSA-Specific Entry) persistent storage.
  40. *
  41. * The DSE store is an LDIF file contained in the file
  42. * INSTANCEDIR/config/XXX.ldif, where INSTANCEDIR is
  43. * the directory of the server instance, and XXX is
  44. * dfined by the caller of dse_new.
  45. *
  46. * In core, the DSEs are stored in an AVL tree, keyed on
  47. * DN. Whenever a modification is made to a DSE, the
  48. * in-core entry is updated, then dse_write_file() is
  49. * called to commit the changes to disk.
  50. *
  51. * This is designed for a small number of DSEs, say
  52. * a maximum of 10 or 20. If large numbers of DSEs
  53. * need to be stored, this approach of writing out
  54. * the entire contents on every modification will
  55. * be insufficient.
  56. *
  57. */
  58. #include <sys/types.h>
  59. #include <sys/stat.h>
  60. #include <fcntl.h>
  61. #include <errno.h>
  62. #include <prio.h>
  63. #include <prcountr.h>
  64. #include "slap.h"
  65. #if !defined (_WIN32)
  66. #include <pwd.h>
  67. #endif /* _WIN32 */
  68. /* #define SLAPI_DSE_DEBUG */ /* define this to force trace log */
  69. /* messages to always be logged */
  70. #ifdef SLAPI_DSE_DEBUG
  71. #define SLAPI_DSE_TRACELEVEL LDAP_DEBUG_ANY
  72. #else /* SLAPI_DSE_DEBUG */
  73. #define SLAPI_DSE_TRACELEVEL LDAP_DEBUG_TRACE
  74. #endif /* SLAPI_DSE_DEBUG */
  75. #define STOP_TRAVERSAL -2
  76. /* This is returned by dupentry_replace if the duplicate entry was found and
  77. replaced. This is returned up through the avl_insert() in
  78. dse_replace_entry(). Otherwise, if avl_insert() returns 0, the
  79. entry was added i.e. a duplicate was not found.
  80. */
  81. #define DSE_ENTRY_WAS_REPLACED -3
  82. /* This is returned by dupentry_merge if the duplicate entry was found and
  83. merged. This is returned up through the avl_insert() in dse_add_entry_pb().
  84. Otherwise, if avl_insert() returns 0, the
  85. entry was added i.e. a duplicate was not found.
  86. */
  87. #define DSE_ENTRY_WAS_MERGED -4
  88. /* some functions can be used either from within a lock or "standalone" */
  89. #define DSE_USE_LOCK 1
  90. #define DSE_NO_LOCK 0
  91. struct dse_callback
  92. {
  93. int operation;
  94. int flags;
  95. Slapi_DN *base;
  96. int scope;
  97. char *filter; /* NULL means match all entries */
  98. Slapi_Filter *slapifilter; /* NULL means match all entries */
  99. int (*fn)(Slapi_PBlock *,Slapi_Entry *,Slapi_Entry *,int*,char*,void *);
  100. void *fn_arg;
  101. struct dse_callback *next;
  102. };
  103. struct dse
  104. {
  105. char *dse_filename; /* these are the primary files which get read from */
  106. char *dse_tmpfile; /* and written to when changes are made via LDAP */
  107. char *dse_fileback; /* contain the latest info, just before a new change */
  108. char *dse_filestartOK; /* contain the latest info with which the server has successfully started */
  109. Avlnode *dse_tree;
  110. struct dse_callback *dse_callback;
  111. PRRWLock *dse_rwlock; /* a read-write lock to protect the whole dse backend */
  112. char **dse_filelist; /* these are additional read only files used to */
  113. /* initialize the dse */
  114. int dse_is_updateable; /* if non-zero, this DSE can be written to */
  115. int dse_readonly_error_reported; /* used to ensure that read-only errors are logged only once */
  116. };
  117. struct dse_node
  118. {
  119. Slapi_Entry *entry;
  120. };
  121. /* search set stuff - used to pass search results to the frontend */
  122. typedef struct dse_search_set
  123. {
  124. DataList dl;
  125. int current_entry;
  126. } dse_search_set;
  127. static int dse_permission_to_write(struct dse* pdse, int loglevel);
  128. static int dse_write_file_nolock(struct dse* pdse);
  129. static int dse_apply_nolock(struct dse* pdse, IFP fp, caddr_t arg);
  130. static int dse_replace_entry( struct dse* pdse, Slapi_Entry *e, int write_file, int use_lock );
  131. static dse_search_set* dse_search_set_new ();
  132. static void dse_search_set_delete (dse_search_set *ss);
  133. static void dse_search_set_clean (dse_search_set *ss);
  134. static void dse_free_entry (void **data);
  135. static void dse_search_set_add_entry (dse_search_set *ss, Slapi_Entry *e);
  136. static Slapi_Entry* dse_search_set_get_next_entry (dse_search_set *ss);
  137. static int dse_add_entry_pb(struct dse* pdse, Slapi_Entry *e, Slapi_PBlock *pb);
  138. static struct dse_node *dse_find_node( struct dse* pdse, const Slapi_DN *dn );
  139. /*
  140. richm: In almost all modes e.g. db2ldif, ldif2db, etc. we do not need/want
  141. to write out the dse.ldif and ldbm.ldif files. The only mode which really
  142. needs to write out the file is the regular server mode. The variable
  143. dont_ever_write_dse_files tells dse_write_file_nolock whether or not to write
  144. the .ldif file for the entry. The default is 1, which means never write the
  145. file. The server, when it starts up in regular mode, must call
  146. dse_unset_dont_ever_write_dse_files() to enable this file to be written
  147. */
  148. static int dont_ever_write_dse_files = 1;
  149. /* Forward declarations */
  150. static int entry_dn_cmp( caddr_t d1, caddr_t d2 );
  151. static int dupentry_disallow( caddr_t d1, caddr_t d2 );
  152. static int dupentry_merge( caddr_t d1, caddr_t d2 );
  153. static int dse_write_entry( caddr_t data, caddr_t arg );
  154. static int ldif_record_end( char *p );
  155. static int dse_call_callback(struct dse* pdse, Slapi_PBlock *pb, int operation, int flags, Slapi_Entry *entryBefore, Slapi_Entry *entryAfter, int *returncode, char* returntext);
  156. /*
  157. * Map a DN onto a dse_node.
  158. * Returns NULL if not found.
  159. * You must have a read or write lock on the dse_rwlock while
  160. * using the returned node.
  161. */
  162. static struct dse_node *
  163. dse_find_node( struct dse* pdse, const Slapi_DN *dn )
  164. {
  165. struct dse_node *n = NULL;
  166. if ( NULL != dn )
  167. {
  168. struct dse_node searchNode;
  169. Slapi_Entry *fe= slapi_entry_alloc();
  170. slapi_entry_init(fe, NULL, NULL);
  171. slapi_entry_set_sdn(fe,dn);
  172. searchNode.entry= fe;
  173. n = (struct dse_node *)avl_find( pdse->dse_tree, &searchNode, entry_dn_cmp );
  174. slapi_entry_free(fe);
  175. }
  176. return n;
  177. }
  178. static int counters_created= 0;
  179. PR_DEFINE_COUNTER(dse_entries_exist);
  180. /*
  181. * Map a DN onto a real Entry.
  182. * Returns NULL if not found.
  183. */
  184. static Slapi_Entry *
  185. dse_get_entry_copy( struct dse* pdse, const Slapi_DN *dn, int use_lock )
  186. {
  187. Slapi_Entry *e= NULL;
  188. struct dse_node *n;
  189. if (use_lock == DSE_USE_LOCK)
  190. PR_RWLock_Rlock(pdse->dse_rwlock);
  191. n = dse_find_node( pdse, dn );
  192. if(n!=NULL)
  193. {
  194. e = slapi_entry_dup(n->entry);
  195. }
  196. if (use_lock == DSE_USE_LOCK)
  197. PR_RWLock_Unlock(pdse->dse_rwlock);
  198. return e;
  199. }
  200. static struct dse_callback *
  201. dse_callback_new(int operation, int flags, const Slapi_DN *base, int scope, const char *filter, dseCallbackFn fn, void *fn_arg)
  202. {
  203. struct dse_callback *p= NULL;
  204. p = (struct dse_callback *)slapi_ch_malloc(sizeof(struct dse_callback));
  205. if (p!=NULL) {
  206. p->operation= operation;
  207. p->flags = flags;
  208. p->base= slapi_sdn_dup(base);
  209. p->scope= scope;
  210. if ( NULL == filter ) {
  211. p->filter= NULL;
  212. p->slapifilter= NULL;
  213. } else {
  214. p->filter= slapi_ch_strdup(filter);
  215. p->slapifilter= slapi_str2filter( p->filter );
  216. filter_normalize(p->slapifilter);
  217. }
  218. p->fn= fn;
  219. p->fn_arg= fn_arg;
  220. p->next= NULL;
  221. }
  222. return p;
  223. }
  224. static void
  225. dse_callback_delete(struct dse_callback **pp)
  226. {
  227. if (pp!=NULL) {
  228. slapi_sdn_free(&((*pp)->base));
  229. slapi_ch_free((void**)&((*pp)->filter));
  230. slapi_filter_free((*pp)->slapifilter,1);
  231. slapi_ch_free((void**)pp);
  232. }
  233. }
  234. static void
  235. dse_callback_deletelist(struct dse_callback **pp)
  236. {
  237. if(pp!=NULL)
  238. {
  239. struct dse_callback *p, *n;
  240. for(p= *pp;p!=NULL;)
  241. {
  242. n= p->next;
  243. dse_callback_delete(&p);
  244. p= n;
  245. }
  246. }
  247. }
  248. /*
  249. Makes a copy of the entry passed in, so it's const
  250. */
  251. static struct dse_node *
  252. dse_node_new(const Slapi_Entry *entry)
  253. {
  254. struct dse_node *p= NULL;
  255. p= (struct dse_node *)slapi_ch_malloc(sizeof(struct dse_node));
  256. if(p!=NULL)
  257. {
  258. p->entry= slapi_entry_dup(entry);
  259. }
  260. if(!counters_created)
  261. {
  262. PR_CREATE_COUNTER(dse_entries_exist,"DSE","entries","");
  263. counters_created= 1;
  264. }
  265. PR_INCREMENT_COUNTER(dse_entries_exist);
  266. return p;
  267. }
  268. static void
  269. dse_node_delete(struct dse_node **pp)
  270. {
  271. slapi_entry_free((*pp)->entry);
  272. slapi_ch_free((void **)&(*pp));
  273. PR_DECREMENT_COUNTER(dse_entries_exist);
  274. }
  275. static void
  276. dse_callback_addtolist(struct dse_callback **pplist, struct dse_callback *p)
  277. {
  278. if(pplist!=NULL)
  279. {
  280. p->next= NULL;
  281. if(*pplist==NULL)
  282. {
  283. *pplist= p;
  284. }
  285. else
  286. {
  287. struct dse_callback *t= *pplist;
  288. for(;t->next!=NULL;t= t->next);
  289. t->next= p;
  290. }
  291. }
  292. }
  293. static void
  294. dse_callback_removefromlist(struct dse_callback **pplist, int operation, int flags, const Slapi_DN *base, int scope, const char *filter, dseCallbackFn fn)
  295. {
  296. if (pplist != NULL) {
  297. struct dse_callback *t= *pplist;
  298. struct dse_callback *prev= NULL;
  299. for(; t!=NULL; ) {
  300. if ((t->operation == operation) && (t->flags == flags) &&
  301. (t->fn == fn) && (scope == t->scope) &&
  302. (slapi_sdn_compare(base,t->base) == 0) &&
  303. (( NULL == filter && NULL == t->filter ) ||
  304. (strcasecmp(filter, t->filter) == 0))) {
  305. if (prev == NULL) {
  306. *pplist= t->next;
  307. } else {
  308. prev->next= t->next;
  309. }
  310. dse_callback_delete(&t);
  311. t= NULL;
  312. } else {
  313. prev= t;
  314. t= t->next;
  315. }
  316. }
  317. }
  318. }
  319. /*
  320. * Create a new dse structure.
  321. */
  322. struct dse *
  323. dse_new( char *filename, char *tmpfilename, char *backfilename, char *startokfilename, const char *configdir)
  324. {
  325. struct dse *pdse= NULL;
  326. const char *config_sub_dir = "config";
  327. char *id = config_get_instancedir();
  328. char *realconfigdir = NULL;
  329. if (configdir!=NULL) {
  330. realconfigdir = slapi_ch_strdup(configdir);
  331. } else if (id!=NULL) {
  332. realconfigdir = slapi_ch_smprintf("%s/%s", id, config_sub_dir);
  333. }
  334. if(realconfigdir!=NULL)
  335. {
  336. pdse= (struct dse *)slapi_ch_calloc(1, sizeof(struct dse));
  337. if(pdse!=NULL)
  338. {
  339. pdse->dse_rwlock = PR_NewRWLock(PR_RWLOCK_RANK_NONE,"dse lock");
  340. /* Set the full path name for the config DSE entry */
  341. if (!strstr(filename, realconfigdir))
  342. {
  343. pdse->dse_filename = slapi_ch_smprintf("%s/%s", realconfigdir, filename );
  344. }
  345. else
  346. pdse->dse_filename = slapi_ch_strdup(filename);
  347. if (!strstr(tmpfilename, realconfigdir)) {
  348. pdse->dse_tmpfile = slapi_ch_smprintf("%s/%s", realconfigdir, tmpfilename );
  349. }
  350. else
  351. pdse->dse_tmpfile = slapi_ch_strdup(tmpfilename);
  352. if ( backfilename != NULL )
  353. {
  354. if (!strstr(backfilename, realconfigdir)) {
  355. pdse->dse_fileback = slapi_ch_smprintf("%s/%s", realconfigdir, backfilename );
  356. }
  357. else
  358. pdse->dse_fileback = slapi_ch_strdup(backfilename);
  359. }
  360. else
  361. pdse->dse_fileback = NULL;
  362. if ( startokfilename != NULL )
  363. {
  364. if (!strstr(startokfilename, realconfigdir)) {
  365. pdse->dse_filestartOK = slapi_ch_smprintf("%s/%s", realconfigdir, startokfilename );
  366. }
  367. else
  368. pdse->dse_filestartOK = slapi_ch_strdup(startokfilename);
  369. }
  370. else
  371. pdse->dse_filestartOK = NULL;
  372. pdse->dse_tree= NULL;
  373. pdse->dse_callback= NULL;
  374. pdse->dse_is_updateable = dse_permission_to_write(pdse,
  375. SLAPI_LOG_TRACE);
  376. }
  377. slapi_ch_free( (void **) &realconfigdir );
  378. }
  379. slapi_ch_free( (void **) &id );
  380. return pdse;
  381. }
  382. /*
  383. * Create a new dse structure with a file list
  384. */
  385. struct dse *
  386. dse_new_with_filelist(char *filename, char *tmpfilename, char *backfilename, char *startokfilename, const char *configdir,
  387. char **filelist)
  388. {
  389. struct dse *newdse = dse_new(filename, tmpfilename, backfilename, startokfilename, configdir);
  390. newdse->dse_filelist = filelist;
  391. return newdse;
  392. }
  393. static int
  394. dse_internal_delete_entry( caddr_t data, caddr_t arg )
  395. {
  396. struct dse_node *n = (struct dse_node *)data;
  397. dse_node_delete(&n);
  398. return 0;
  399. }
  400. /*
  401. * Get rid of a dse structure.
  402. */
  403. int
  404. dse_deletedse(Slapi_PBlock *pb)
  405. {
  406. struct dse *pdse = NULL;
  407. slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &pdse);
  408. if (pdse)
  409. {
  410. int nentries = 0;
  411. PR_RWLock_Wlock(pdse->dse_rwlock);
  412. slapi_ch_free((void **)&(pdse->dse_filename));
  413. slapi_ch_free((void **)&(pdse->dse_tmpfile));
  414. slapi_ch_free((void **)&(pdse->dse_fileback));
  415. slapi_ch_free((void **)&(pdse->dse_filestartOK));
  416. dse_callback_deletelist(&pdse->dse_callback);
  417. nentries = avl_free(pdse->dse_tree, dse_internal_delete_entry);
  418. PR_RWLock_Unlock(pdse->dse_rwlock);
  419. PR_DestroyRWLock(pdse->dse_rwlock);
  420. slapi_ch_free((void **)&pdse);
  421. LDAPDebug( SLAPI_DSE_TRACELEVEL, "Removed [%d] entries from the dse tree.\n",
  422. nentries,0,0 );
  423. }
  424. /* data is freed, so make sure no one tries to use it */
  425. slapi_pblock_set(pb, SLAPI_PLUGIN_PRIVATE, NULL);
  426. return 0;
  427. }
  428. static char* subordinatecount = "numsubordinates";
  429. /*
  430. * Get the number of subordinates for this entry.
  431. */
  432. static size_t
  433. dse_numsubordinates(Slapi_Entry *entry)
  434. {
  435. int ret= 0;
  436. Slapi_Attr *read_attr = NULL;
  437. size_t current_sub_count = 0;
  438. /* Get the present value of the subcount attr, or 0 if not present */
  439. ret = slapi_entry_attr_find(entry,subordinatecount,&read_attr);
  440. if (0 == ret)
  441. {
  442. /* decode the value */
  443. Slapi_Value *sval;
  444. slapi_attr_first_value( read_attr,&sval );
  445. if (sval!=NULL)
  446. {
  447. const struct berval *bval = slapi_value_get_berval( sval );
  448. if( NULL != bval )
  449. current_sub_count = atol(bval->bv_val);
  450. }
  451. }
  452. return current_sub_count;
  453. }
  454. /*
  455. * Update the numsubordinates count.
  456. * mod_op is either an Add or Delete.
  457. */
  458. static void
  459. dse_updateNumSubordinates(Slapi_Entry *entry, int op)
  460. {
  461. int ret= 0;
  462. int mod_op = 0;
  463. Slapi_Attr *read_attr = NULL;
  464. size_t current_sub_count = 0;
  465. int already_present = 0;
  466. /* For now, we're only interested in subordinatecount.
  467. We first examine the present value for the attribute.
  468. If it isn't present and we're adding, we assign value 1 to the attribute and add it.
  469. If it is present, we increment or decrement depending upon whether we're adding or deleting.
  470. If the value after decrementing is zero, we remove it.
  471. */
  472. /* Get the present value of the subcount attr, or 0 if not present */
  473. ret = slapi_entry_attr_find(entry,subordinatecount,&read_attr);
  474. if (0 == ret)
  475. {
  476. /* decode the value */
  477. Slapi_Value *sval;
  478. slapi_attr_first_value( read_attr,&sval );
  479. if (sval!=NULL)
  480. {
  481. const struct berval *bval = slapi_value_get_berval( sval );
  482. if (bval!=NULL)
  483. {
  484. already_present = 1;
  485. current_sub_count = atol(bval->bv_val);
  486. }
  487. }
  488. }
  489. /* are we adding ? */
  490. if ( (SLAPI_OPERATION_ADD == op) && !already_present)
  491. {
  492. /* If so, and the parent entry does not already have a subcount attribute, we need to add it */
  493. mod_op = LDAP_MOD_ADD;
  494. }
  495. else
  496. {
  497. if (SLAPI_OPERATION_DELETE == op)
  498. {
  499. if (!already_present)
  500. {
  501. /* This means that something is wrong---deleting a child but no subcount present on parent */
  502. slapi_log_error( SLAPI_LOG_FATAL, "dse",
  503. "numsubordinates assertion failure\n" );
  504. return;
  505. }
  506. else
  507. {
  508. if (current_sub_count == 1)
  509. {
  510. mod_op = LDAP_MOD_DELETE;
  511. }
  512. else
  513. {
  514. mod_op = LDAP_MOD_REPLACE;
  515. }
  516. }
  517. }
  518. else
  519. {
  520. mod_op = LDAP_MOD_REPLACE;
  521. }
  522. }
  523. /* Now compute the new value */
  524. if (SLAPI_OPERATION_ADD == op)
  525. {
  526. current_sub_count++;
  527. }
  528. else
  529. {
  530. current_sub_count--;
  531. }
  532. {
  533. char value_buffer[20]; /* enough digits for 2^64 children */
  534. struct berval *vals[2];
  535. struct berval val;
  536. vals[0] = &val;
  537. vals[1] = NULL;
  538. sprintf(value_buffer,"%u",current_sub_count);
  539. val.bv_val = value_buffer;
  540. val.bv_len = strlen (val.bv_val);
  541. switch(mod_op)
  542. {
  543. case LDAP_MOD_ADD:
  544. attrlist_merge( &entry->e_attrs, subordinatecount, vals);
  545. break;
  546. case LDAP_MOD_REPLACE:
  547. attrlist_replace( &entry->e_attrs, subordinatecount, vals);
  548. break;
  549. case LDAP_MOD_DELETE:
  550. attrlist_delete( &entry->e_attrs, subordinatecount);
  551. break;
  552. }
  553. }
  554. }
  555. /* the write lock should always be acquired before calling this function */
  556. static void
  557. dse_updateNumSubOfParent(struct dse *pdse, const Slapi_DN *child, int op)
  558. {
  559. Slapi_DN parent;
  560. slapi_sdn_init(&parent);
  561. slapi_sdn_get_parent(child, &parent);
  562. if ( !slapi_sdn_isempty(&parent) )
  563. {
  564. /* no lock because caller should already have the write lock */
  565. Slapi_Entry *parententry= dse_get_entry_copy( pdse, &parent, DSE_NO_LOCK );
  566. if( parententry!=NULL )
  567. {
  568. /* Decrement the numsubordinate count of the parent entry */
  569. dse_updateNumSubordinates(parententry, op);
  570. /* no lock because caller should always have the write lock */
  571. dse_replace_entry( pdse, parententry, 0, DSE_NO_LOCK );
  572. slapi_entry_free(parententry);
  573. }
  574. }
  575. slapi_sdn_done(&parent);
  576. }
  577. static int
  578. dse_read_one_file(struct dse *pdse, const char *filename, Slapi_PBlock *pb,
  579. int primary_file )
  580. {
  581. Slapi_Entry *e= NULL;
  582. char *entrystr= NULL;
  583. char *buf = NULL;
  584. char *lastp = NULL;
  585. int rc= 0; /* Fail */
  586. PRInt32 remaining;
  587. PRInt32 nr = 0;
  588. PRFileInfo prfinfo;
  589. PRFileDesc *prfd = 0;
  590. if ( (NULL != pdse) && (NULL != filename) )
  591. {
  592. if ( (rc = PR_GetFileInfo( filename, &prfinfo )) != PR_SUCCESS )
  593. {
  594. /* the "real" file does not exist; see if there is a tmpfile */
  595. if ( pdse->dse_tmpfile &&
  596. PR_GetFileInfo( pdse->dse_tmpfile, &prfinfo ) == PR_SUCCESS ) {
  597. rc = PR_Rename(pdse->dse_tmpfile, filename);
  598. if (rc == PR_SUCCESS) {
  599. slapi_log_error(SLAPI_LOG_FATAL, "dse",
  600. "The configuration file %s was restored from backup %s\n",
  601. filename, pdse->dse_tmpfile);
  602. rc = 1;
  603. } else {
  604. slapi_log_error(SLAPI_LOG_FATAL, "dse",
  605. "The configuration file %s was not restored from backup %s, error %d\n",
  606. filename, pdse->dse_tmpfile, rc);
  607. rc = 0;
  608. }
  609. } else {
  610. rc = 0; /* fail */
  611. }
  612. }
  613. if ( (rc = PR_GetFileInfo( filename, &prfinfo )) != PR_SUCCESS )
  614. {
  615. slapi_log_error(SLAPI_LOG_FATAL, "dse",
  616. "The configuration file %s could not be accessed, error %d\n",
  617. filename, rc);
  618. rc = 0; /* Fail */
  619. }
  620. else if (( prfd = PR_Open( filename, PR_RDONLY, SLAPD_DEFAULT_FILE_MODE )) == NULL )
  621. {
  622. slapi_log_error(SLAPI_LOG_FATAL, "dse",
  623. "The configuration file %s could not be read. "
  624. SLAPI_COMPONENT_NAME_NSPR " %d (%s)\n",
  625. filename,
  626. PR_GetError(), slapd_pr_strerror(PR_GetError()));
  627. rc = 0; /* Fail */
  628. }
  629. else
  630. {
  631. int done= 0;
  632. /* read the entire file into core */
  633. buf = slapi_ch_malloc( prfinfo.size + 1 );
  634. remaining = prfinfo.size;
  635. if (( nr = slapi_read_buffer( prfd, buf, prfinfo.size )) < 0 )
  636. {
  637. slapi_log_error(SLAPI_LOG_FATAL, "dse",
  638. "Could only read %d of %d bytes from config file %s\n",
  639. nr, prfinfo.size, filename);
  640. rc = 0; /* Fail */
  641. done= 1;
  642. }
  643. (void)PR_Close( prfd );
  644. buf[ nr ] = '\0';
  645. if(!done)
  646. {
  647. int dont_check_dups = 0;
  648. int str2entry_flags = SLAPI_STR2ENTRY_EXPAND_OBJECTCLASSES |
  649. SLAPI_STR2ENTRY_NOT_WELL_FORMED_LDIF ;
  650. PR_ASSERT(pb);
  651. slapi_pblock_get(pb, SLAPI_DSE_DONT_CHECK_DUPS, &dont_check_dups);
  652. if ( !dont_check_dups ) {
  653. str2entry_flags |= SLAPI_STR2ENTRY_REMOVEDUPVALS;
  654. }
  655. /* Convert LDIF to entry structures */
  656. rc= 1; /* assume we will succeed */
  657. while (( entrystr = dse_read_next_entry( buf, &lastp )) != NULL )
  658. {
  659. e = slapi_str2entry( entrystr, str2entry_flags );
  660. if ( e != NULL )
  661. {
  662. int returncode = 0;
  663. char returntext[SLAPI_DSE_RETURNTEXT_SIZE]= {0};
  664. LDAPDebug(SLAPI_DSE_TRACELEVEL, "dse_read_one_file"
  665. " processing entry \"%s\" in file %s%s\n",
  666. slapi_entry_get_dn_const(e), filename,
  667. primary_file ? " (primary file)" : "" );
  668. /* remove the numsubordinates attr, which may be bogus */
  669. slapi_entry_attr_delete(e, subordinatecount);
  670. /* set the "primary file" flag if appropriate */
  671. slapi_pblock_set( pb, SLAPI_DSE_IS_PRIMARY_FILE, &primary_file );
  672. if(dse_call_callback(pdse, pb, DSE_OPERATION_READ,
  673. DSE_FLAG_PREOP, e, NULL, &returncode,
  674. returntext) == SLAPI_DSE_CALLBACK_OK)
  675. {
  676. /* this will free the entry if not added, so it is
  677. definitely consumed by this call */
  678. dse_add_entry_pb(pdse, e, pb);
  679. }
  680. else /* free entry if not used */
  681. {
  682. slapi_log_error(SLAPI_LOG_FATAL, "dse",
  683. "The entry %s in file %s is invalid, error code %d (%s) - %s\n",
  684. slapi_entry_get_dn_const(e),
  685. filename, returncode,
  686. ldap_err2string(returncode),
  687. returntext);
  688. slapi_entry_free(e);
  689. rc = 0; /* failure */
  690. }
  691. } else {
  692. slapi_log_error( SLAPI_LOG_FATAL, "dse",
  693. "parsing dse entry [%s]\n", entrystr );
  694. rc = 0; /* failure */
  695. }
  696. }
  697. }
  698. slapi_ch_free((void **)&buf);
  699. }
  700. }
  701. return rc;
  702. }
  703. /*
  704. * Read the file we were initialised with into memory.
  705. * If not NULL call entry_filter_fn on each entry as it's read.
  706. * The function is free to modify the entry before it's places
  707. * into the AVL tree. True means add the entry. False means don't.
  708. *
  709. * Return 1 for OK, 0 for Fail.
  710. */
  711. int
  712. dse_read_file(struct dse *pdse, Slapi_PBlock *pb)
  713. {
  714. int rc= 1; /* Good */
  715. int ii;
  716. char **filelist = 0;
  717. char *filename = 0;
  718. filelist = charray_dup(pdse->dse_filelist);
  719. filename = slapi_ch_strdup(pdse->dse_filename);
  720. for (ii = 0; rc && filelist && filelist[ii]; ++ii)
  721. {
  722. if (strcasecmp(filename, filelist[ii])!=0)
  723. {
  724. rc = dse_read_one_file(pdse, filelist[ii], pb, 0 /* not primary */);
  725. }
  726. }
  727. if (rc)
  728. {
  729. rc = dse_read_one_file(pdse, filename, pb, 1 /* primary file */);
  730. }
  731. charray_free(filelist);
  732. slapi_ch_free((void **)&filename);
  733. return rc;
  734. }
  735. /*
  736. * Structure to carry context information whilst
  737. * traversing the tree writing the entries to disk.
  738. */
  739. typedef struct _fpw
  740. {
  741. PRFileDesc *fpw_prfd;
  742. int fpw_rc;
  743. struct dse *fpw_pdse;
  744. } FPWrapper;
  745. static int
  746. dse_rw_permission_to_one_file(const char *name, int loglevel)
  747. {
  748. PRErrorCode prerr = 0;
  749. const char *accesstype = "";
  750. if ( NULL == name ) {
  751. return 1; /* file won't be used -- return "sufficient permission" */
  752. }
  753. if ( PR_Access( name, PR_ACCESS_EXISTS ) == PR_SUCCESS ) {
  754. /* file exists: check for read and write permission */
  755. if ( PR_Access( name, PR_ACCESS_WRITE_OK ) != PR_SUCCESS ) {
  756. prerr = PR_GetError();
  757. accesstype = "write";
  758. } else if ( PR_Access( name, PR_ACCESS_READ_OK ) != PR_SUCCESS ) {
  759. prerr = PR_GetError();
  760. accesstype = "read";
  761. }
  762. } else {
  763. /* file does not exist: make sure we can create it */
  764. PRFileDesc *prfd;
  765. prfd = PR_Open( name, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE,
  766. SLAPD_DEFAULT_FILE_MODE );
  767. if ( NULL == prfd ) {
  768. prerr = PR_GetError();
  769. accesstype = "create";
  770. } else {
  771. PR_Close( prfd );
  772. PR_Delete( name );
  773. }
  774. }
  775. if ( prerr != 0 ) {
  776. slapi_log_error( loglevel, "dse", "Unable to %s \"%s\": "
  777. SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
  778. accesstype, name, prerr, slapd_pr_strerror(prerr));
  779. return 0; /* insufficient permission */
  780. } else {
  781. return 1; /* sufficient permission */
  782. }
  783. }
  784. /*
  785. * Check that we have permission to write to all the files that
  786. * dse_write_file_nolock() uses.
  787. * Returns a non-zero value if sufficient permission and 0 if not.
  788. */
  789. static int
  790. dse_permission_to_write(struct dse* pdse, int loglevel)
  791. {
  792. int rc = 1; /* sufficient permission */
  793. if ( NULL != pdse->dse_filename ) {
  794. if ( !dse_rw_permission_to_one_file( pdse->dse_filename, loglevel ) ||
  795. !dse_rw_permission_to_one_file( pdse->dse_fileback, loglevel ) ||
  796. !dse_rw_permission_to_one_file( pdse->dse_tmpfile, loglevel )) {
  797. rc = 0; /* insufficient permission */
  798. }
  799. }
  800. return rc;
  801. }
  802. /*
  803. * Check for read-only status and return an appropriate error to the
  804. * LDAP client.
  805. * Returns 0 if no error was returned and non-zero if one was.
  806. */
  807. static int
  808. dse_check_for_readonly_error(Slapi_PBlock *pb, struct dse* pdse)
  809. {
  810. int rc = 0; /* default: no error */
  811. PR_RWLock_Rlock(pdse->dse_rwlock);
  812. if ( !pdse->dse_is_updateable ) {
  813. if ( !pdse->dse_readonly_error_reported ) {
  814. if ( NULL != pdse->dse_filename ) {
  815. slapi_log_error( SLAPI_LOG_FATAL, "dse",
  816. "The DSE database stored in \"%s\" is not writeable\n",
  817. pdse->dse_filename );
  818. /* log the details too */
  819. (void)dse_permission_to_write(pdse, SLAPI_LOG_FATAL);
  820. }
  821. pdse->dse_readonly_error_reported = 1;
  822. }
  823. rc = 1; /* return an error to the client */
  824. }
  825. PR_RWLock_Unlock(pdse->dse_rwlock);
  826. if ( rc != 0 ) {
  827. slapi_send_ldap_result( pb, LDAP_UNWILLING_TO_PERFORM, NULL,
  828. "DSE database is read-only", 0, NULL );
  829. }
  830. return rc; /* no error */
  831. }
  832. /*
  833. * Write the AVL tree of entries back to the LDIF file.
  834. */
  835. static int
  836. dse_write_file_nolock(struct dse* pdse)
  837. {
  838. FPWrapper fpw;
  839. int rc = 0;
  840. if (dont_ever_write_dse_files)
  841. return rc;
  842. fpw.fpw_rc = 0;
  843. fpw.fpw_prfd = NULL;
  844. if ( NULL != pdse->dse_filename )
  845. {
  846. if (( fpw.fpw_prfd = PR_Open( pdse->dse_tmpfile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE, SLAPD_DEFAULT_FILE_MODE )) == NULL )
  847. {
  848. rc = PR_GetOSError();
  849. slapi_log_error( SLAPI_LOG_FATAL, "dse", "Cannot open "
  850. "temporary DSE file \"%s\" for update: OS error %d (%s)\n",
  851. pdse->dse_tmpfile, rc, slapd_system_strerror( rc ));
  852. }
  853. else
  854. {
  855. fpw.fpw_pdse = pdse;
  856. if ( avl_apply( pdse->dse_tree, dse_write_entry, &fpw, STOP_TRAVERSAL, AVL_INORDER ) == STOP_TRAVERSAL )
  857. {
  858. rc = fpw.fpw_rc;
  859. slapi_log_error( SLAPI_LOG_FATAL, "dse", "Cannot write "
  860. " temporary DSE file \"%s\": OS error %d (%s)\n",
  861. pdse->dse_tmpfile, rc, slapd_system_strerror( rc ));
  862. (void)PR_Close( fpw.fpw_prfd );
  863. fpw.fpw_prfd = NULL;
  864. }
  865. else
  866. {
  867. (void)PR_Close( fpw.fpw_prfd );
  868. fpw.fpw_prfd = NULL;
  869. if ( pdse->dse_fileback != NULL )
  870. {
  871. rc = slapi_destructive_rename( pdse->dse_filename, pdse->dse_fileback );
  872. if ( rc != 0 )
  873. {
  874. slapi_log_error( SLAPI_LOG_FATAL, "dse", "Cannot backup"
  875. " DSE file \"%s\" to \"%s\": OS error %d (%s)\n",
  876. pdse->dse_filename, pdse->dse_fileback,
  877. rc, slapd_system_strerror( rc ));
  878. }
  879. }
  880. rc = slapi_destructive_rename( pdse->dse_tmpfile, pdse->dse_filename );
  881. if ( rc != 0 )
  882. {
  883. slapi_log_error( SLAPI_LOG_FATAL, "dse", "Cannot rename"
  884. " temporary DSE file \"%s\" to \"%s\":"
  885. " OS error %d (%s)\n",
  886. pdse->dse_tmpfile, pdse->dse_filename,
  887. rc, slapd_system_strerror( rc ));
  888. }
  889. }
  890. }
  891. if (fpw.fpw_prfd)
  892. (void)PR_Close(fpw.fpw_prfd);
  893. }
  894. return rc;
  895. }
  896. /*
  897. * Local function for writing an entry to a file.
  898. * Called by the AVL code during traversal.
  899. */
  900. static int
  901. dse_write_entry( caddr_t data, caddr_t arg )
  902. {
  903. struct dse_node *n = (struct dse_node *)data;
  904. FPWrapper *fpw = (FPWrapper *)arg;
  905. char *s;
  906. PRInt32 len;
  907. if ( NULL != n && NULL != n->entry )
  908. {
  909. int returncode;
  910. char returntext[SLAPI_DSE_RETURNTEXT_SIZE]= "";
  911. /* need to make a duplicate here for two reasons:
  912. 1) we don't want to hold on to the raw data in the node for any longer
  913. than we have to; we will usually be inside the dse write lock, but . . .
  914. 2) the write callback may modify the entry, so we want to pass it a
  915. writeable copy rather than the raw avl tree data pointer
  916. */
  917. Slapi_Entry *ec = slapi_entry_dup(n->entry);
  918. if(dse_call_callback(fpw->fpw_pdse, NULL, DSE_OPERATION_WRITE,
  919. DSE_FLAG_PREOP, ec, NULL, &returncode, returntext)
  920. == SLAPI_DSE_CALLBACK_OK)
  921. {
  922. /*
  923. * 3-August-2000 mcs: We used to pass the SLAPI_DUMP_NOOPATTRS
  924. * option to slapi_entry2str_with_options() so that operational
  925. * attributes were NOT stored in the DSE LDIF files. But now
  926. * we store all attribute types.
  927. */
  928. if (( s = slapi_entry2str_with_options( ec, &len, 0 )) != NULL )
  929. {
  930. if ( slapi_write_buffer( fpw->fpw_prfd, s, len ) != len )
  931. {
  932. fpw->fpw_rc = PR_GetOSError();;
  933. slapi_ch_free((void **) &s);
  934. return STOP_TRAVERSAL;
  935. }
  936. if ( slapi_write_buffer( fpw->fpw_prfd, "\n", 1 ) != 1 )
  937. {
  938. fpw->fpw_rc = PR_GetOSError();;
  939. slapi_ch_free((void **) &s);
  940. return STOP_TRAVERSAL;
  941. }
  942. slapi_ch_free((void **) &s);
  943. }
  944. }
  945. slapi_entry_free(ec);
  946. }
  947. return 0;
  948. }
  949. static int
  950. dse_add_entry_pb(struct dse* pdse, Slapi_Entry *e, Slapi_PBlock *pb)
  951. {
  952. int dont_write_file = 0, merge = 0; /* defaults */
  953. int rc= 0;
  954. struct dse_node *n = dse_node_new(e); /* copies e */
  955. Slapi_Entry *schemacheckentry= NULL; /* to use for schema checking */
  956. PR_ASSERT(pb);
  957. slapi_pblock_get(pb, SLAPI_DSE_DONT_WRITE_WHEN_ADDING, &dont_write_file);
  958. slapi_pblock_get(pb, SLAPI_DSE_MERGE_WHEN_ADDING, &merge);
  959. /* keep write lock during both tree update and file write operations */
  960. PR_RWLock_Wlock(pdse->dse_rwlock);
  961. if (merge)
  962. {
  963. rc= avl_insert( &(pdse->dse_tree), n, entry_dn_cmp, dupentry_merge );
  964. }
  965. else
  966. {
  967. rc= avl_insert( &(pdse->dse_tree), n, entry_dn_cmp, dupentry_disallow );
  968. }
  969. if (-1 != rc) {
  970. /* update num sub of parent with no lock; we already hold the write lock */
  971. if (0 == rc) { /* entry was added, not merged; update numsub */
  972. dse_updateNumSubOfParent(pdse, slapi_entry_get_sdn_const(e),
  973. SLAPI_OPERATION_ADD);
  974. } else { /* entry was merged, free temp unused data */
  975. dse_node_delete(&n);
  976. }
  977. if (!dont_write_file) {
  978. dse_write_file_nolock(pdse);
  979. }
  980. } else { /* duplicate entry ignored */
  981. dse_node_delete(&n); /* This also deletes the contained entry */
  982. }
  983. PR_RWLock_Unlock(pdse->dse_rwlock);
  984. if (rc == -1)
  985. {
  986. /* duplicate entry ignored */
  987. schemacheckentry = dse_get_entry_copy( pdse,
  988. slapi_entry_get_sdn_const(e),
  989. DSE_USE_LOCK );
  990. }
  991. else /* entry added or merged */
  992. {
  993. /* entry was added or merged */
  994. if (0 == rc) /* 0 return means entry was added, not merged */
  995. {
  996. /* save a search of the tree, since we added the entry, the
  997. contents of e should be the same as what is in the tree */
  998. schemacheckentry = slapi_entry_dup(e);
  999. }
  1000. else /* merged */
  1001. {
  1002. /* schema check the new merged entry, so get it from the tree */
  1003. schemacheckentry = dse_get_entry_copy( pdse,
  1004. slapi_entry_get_sdn_const(e),
  1005. DSE_USE_LOCK );
  1006. }
  1007. }
  1008. if ( NULL != schemacheckentry )
  1009. {
  1010. /*
  1011. * Verify that the new or merged entry conforms to the schema.
  1012. * Errors are logged by slapi_entry_schema_check().
  1013. */
  1014. (void)slapi_entry_schema_check( pb, schemacheckentry );
  1015. slapi_entry_free(schemacheckentry);
  1016. }
  1017. /* callers expect e (SLAPI_ADD_ENTRY) to be freed or otherwise consumed */
  1018. slapi_entry_free(e);
  1019. return rc;
  1020. }
  1021. /*
  1022. * Local function for comparing two entries by DN. Store the entries
  1023. * so that when they are printed out, the child entries are below their
  1024. * ancestor entries
  1025. */
  1026. static int
  1027. entry_dn_cmp( caddr_t d1, caddr_t d2 )
  1028. {
  1029. struct dse_node *n1 = (struct dse_node *)d1;
  1030. struct dse_node *n2 = (struct dse_node *)d2;
  1031. const Slapi_DN *dn1 = slapi_entry_get_sdn_const(n1->entry);
  1032. const Slapi_DN *dn2 = slapi_entry_get_sdn_const(n2->entry);
  1033. int retval = slapi_sdn_compare(dn1, dn2);
  1034. if (retval != 0)
  1035. {
  1036. if (slapi_sdn_issuffix(dn1, dn2))
  1037. {
  1038. retval = 1;
  1039. }
  1040. else if (slapi_sdn_issuffix(dn2, dn1))
  1041. {
  1042. retval = -1;
  1043. }
  1044. else
  1045. {
  1046. /* put fewer rdns before more rdns */
  1047. int rc = 0;
  1048. char **dnlist1 = ldap_explode_dn(slapi_sdn_get_ndn(dn1), 0);
  1049. char **dnlist2 = ldap_explode_dn(slapi_sdn_get_ndn(dn2), 0);
  1050. int len1 = 0;
  1051. int len2 = 0;
  1052. if (dnlist1)
  1053. for (len1 = 0; dnlist1[len1]; ++len1);
  1054. if (dnlist2)
  1055. for (len2 = 0; dnlist2[len2]; ++len2);
  1056. if (len1 == len2)
  1057. {
  1058. len1--;
  1059. for (; (rc == 0) && (len1 >= 0); --len1)
  1060. {
  1061. rc = strcmp(dnlist1[len1], dnlist2[len1]);
  1062. }
  1063. if (rc)
  1064. retval = rc;
  1065. }
  1066. else
  1067. retval = len1 - len2;
  1068. if (dnlist1)
  1069. ldap_value_free(dnlist1);
  1070. if (dnlist2)
  1071. ldap_value_free(dnlist2);
  1072. }
  1073. }
  1074. /* else entries are equal if dns are equal */
  1075. return retval;
  1076. }
  1077. static int
  1078. dupentry_disallow( caddr_t d1, caddr_t d2 )
  1079. {
  1080. return -1;
  1081. }
  1082. static int
  1083. dupentry_replace( caddr_t d1, caddr_t d2 )
  1084. {
  1085. /*
  1086. * Hack attack: since we don't have the address of the pointer
  1087. * in the avl node, we have to replace the e_dn and e_attrs
  1088. * members of the entry which is in the AVL tree with our
  1089. * new entry DN and attrs. We then point the "new" entry's
  1090. * e_dn and e_attrs pointers to point to the values we just
  1091. * replaced, on the assumption that the caller will be freeing
  1092. * these.
  1093. */
  1094. struct dse_node *n1 = (struct dse_node *)d1; /* OLD */
  1095. struct dse_node *n2 = (struct dse_node *)d2; /* NEW */
  1096. Slapi_Entry *e= n1->entry;
  1097. n1->entry= n2->entry;
  1098. n2->entry= e;
  1099. return DSE_ENTRY_WAS_REPLACED;
  1100. }
  1101. static int
  1102. dupentry_merge( caddr_t d1, caddr_t d2 )
  1103. {
  1104. struct dse_node *n1 = (struct dse_node *)d1; /* OLD */
  1105. struct dse_node *n2 = (struct dse_node *)d2; /* NEW */
  1106. Slapi_Entry *e1= n1->entry;
  1107. Slapi_Entry *e2= n2->entry;
  1108. int rc = 0;
  1109. Slapi_Attr *newattr = 0;
  1110. for (rc = slapi_entry_first_attr(e2, &newattr);
  1111. !rc && newattr;
  1112. rc = slapi_entry_next_attr(e2, newattr, &newattr)) {
  1113. char *type = 0;
  1114. slapi_attr_get_type(newattr, &type);
  1115. if (type) {
  1116. /* insure there are no duplicate values in e1 */
  1117. rc = slapi_entry_merge_values_sv(e1, type,
  1118. attr_get_present_values(newattr));
  1119. }
  1120. }
  1121. return DSE_ENTRY_WAS_MERGED;
  1122. }
  1123. /*
  1124. * Add an entry to the DSE without locking the DSE avl tree.
  1125. * Replaces the entry if it already exists.
  1126. *
  1127. * The given entry e is never consumed. It is the responsibility of the
  1128. * caller to free it when it is no longer needed.
  1129. *
  1130. * The write_file flag is used if we want to update the entry in memory
  1131. * but we do not want to write out the file. For example, if we update
  1132. * the numsubordinates in the entry, this is an operational attribute that
  1133. * we do not want saved to disk.
  1134. */
  1135. static int
  1136. dse_replace_entry( struct dse* pdse, Slapi_Entry *e, int write_file, int use_lock )
  1137. {
  1138. int rc= -1;
  1139. if ( NULL != e )
  1140. {
  1141. struct dse_node *n= dse_node_new(e);
  1142. if (use_lock)
  1143. PR_RWLock_Wlock(pdse->dse_rwlock);
  1144. rc = avl_insert( &(pdse->dse_tree), n, entry_dn_cmp, dupentry_replace );
  1145. if (write_file)
  1146. dse_write_file_nolock(pdse);
  1147. /* If the entry was replaced i.e. not added as a new entry, we need to
  1148. free the old data, which is set in dupentry_replace */
  1149. if (DSE_ENTRY_WAS_REPLACED == rc) {
  1150. dse_node_delete(&n);
  1151. rc = 0; /* for return to caller */
  1152. }
  1153. if (use_lock)
  1154. PR_RWLock_Unlock(pdse->dse_rwlock);
  1155. }
  1156. return rc;
  1157. }
  1158. /*
  1159. * Return -1 if p does not point to a valid LDIF
  1160. * end-of-record delimiter (a NULL, two newlines, or two
  1161. * pairs of CRLF). Otherwise, return the length of
  1162. * the delimiter found.
  1163. */
  1164. static int
  1165. ldif_record_end( char *p )
  1166. {
  1167. if ( NULL != p )
  1168. {
  1169. if ( '\0' == *p )
  1170. {
  1171. return 0;
  1172. }
  1173. else if ( '\n' == *p && '\n' == *( p + 1 ))
  1174. {
  1175. return 2;
  1176. }
  1177. else if ( '\r' == *p && '\n' == *( p + 1 ) && '\r' == *( p + 2 ) && '\n' == *( p + 3 ))
  1178. {
  1179. return 4;
  1180. }
  1181. }
  1182. return -1;
  1183. }
  1184. char *
  1185. dse_read_next_entry( char *buf, char **lastp )
  1186. {
  1187. char *p, *start;
  1188. if ( NULL == buf )
  1189. {
  1190. *lastp = NULL;
  1191. return NULL;
  1192. }
  1193. p = start = ( NULL == *lastp ) ? buf : *lastp;
  1194. /* Skip over any leading record delimiters */
  1195. while ( '\n' == *p || '\r' == *p )
  1196. {
  1197. p++;
  1198. }
  1199. if ( '\0' == *p )
  1200. {
  1201. *lastp = NULL;
  1202. return NULL;
  1203. }
  1204. while ( '\0' != *p )
  1205. {
  1206. int rc;
  1207. if (( rc = ldif_record_end( p )) >= 0 )
  1208. {
  1209. /* Found end of LDIF record */
  1210. *p = '\0';
  1211. p += rc;
  1212. break;
  1213. }
  1214. else
  1215. {
  1216. p++;
  1217. }
  1218. }
  1219. *lastp = p;
  1220. return start;
  1221. }
  1222. /*
  1223. * Apply the function to each entry. The caller is responsible for locking
  1224. * the rwlock in the dse for the appropriate type of operation e.g. for
  1225. * searching, a read lock, for modifying in place, a write lock
  1226. */
  1227. static int
  1228. dse_apply_nolock(struct dse* pdse,IFP fp,caddr_t arg)
  1229. {
  1230. avl_apply( pdse->dse_tree, fp, arg, STOP_TRAVERSAL, AVL_INORDER );
  1231. return 1;
  1232. }
  1233. /*
  1234. * Remove the entry from the tree.
  1235. * Returns 1 if entry is removed and 0 if not.
  1236. */
  1237. static int
  1238. dse_delete_entry(struct dse* pdse, Slapi_PBlock *pb, const Slapi_Entry *e)
  1239. {
  1240. int dont_write_file = 0;
  1241. struct dse_node *n= dse_node_new(e);
  1242. struct dse_node *deleted_node = NULL;
  1243. slapi_pblock_get(pb, SLAPI_DSE_DONT_WRITE_WHEN_ADDING, &dont_write_file);
  1244. /* keep write lock for both tree deleting and file writing */
  1245. PR_RWLock_Wlock(pdse->dse_rwlock);
  1246. if ((deleted_node = (struct dse_node *)avl_delete(&pdse->dse_tree,
  1247. n, entry_dn_cmp)))
  1248. dse_node_delete(&deleted_node);
  1249. dse_node_delete(&n);
  1250. if (!dont_write_file)
  1251. {
  1252. /* Decrement the numsubordinate count of the parent entry */
  1253. dse_updateNumSubOfParent(pdse, slapi_entry_get_sdn_const(e),
  1254. SLAPI_OPERATION_DELETE);
  1255. dse_write_file_nolock(pdse);
  1256. }
  1257. PR_RWLock_Unlock(pdse->dse_rwlock);
  1258. return 1;
  1259. }
  1260. /*
  1261. * Returns a SLAPI_BIND_xxx retun code.
  1262. */
  1263. int
  1264. dse_bind( Slapi_PBlock *pb ) /* JCM There should only be one exit point from this function! */
  1265. {
  1266. char *dn; /* The bind DN */
  1267. int method; /* The bind method */
  1268. struct berval *cred; /* The bind credentials */
  1269. Slapi_Value **bvals;
  1270. struct dse* pdse;
  1271. Slapi_Attr *attr;
  1272. Slapi_DN sdn;
  1273. Slapi_Entry *ec= NULL;
  1274. /*Get the parameters*/
  1275. if (slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &pdse ) < 0 ||
  1276. slapi_pblock_get( pb, SLAPI_BIND_TARGET, &dn ) < 0 ||
  1277. slapi_pblock_get( pb, SLAPI_BIND_METHOD, &method ) < 0 ||
  1278. slapi_pblock_get( pb, SLAPI_BIND_CREDENTIALS, &cred ) < 0){
  1279. slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
  1280. return SLAPI_BIND_FAIL;
  1281. }
  1282. /* always allow noauth simple binds */
  1283. if ( method == LDAP_AUTH_SIMPLE && cred->bv_len == 0 )
  1284. {
  1285. /*
  1286. * report success to client, but return
  1287. * SLAPI_BIND_FAIL so we don't
  1288. * authorize based on noauth credentials
  1289. */
  1290. slapi_send_ldap_result( pb, LDAP_SUCCESS, NULL, NULL, 0, NULL );
  1291. return( SLAPI_BIND_FAIL );
  1292. }
  1293. /* Find the entry that the person is attempting to bind as */
  1294. slapi_sdn_init_dn_byref(&sdn,dn);
  1295. ec = dse_get_entry_copy(pdse,&sdn,DSE_USE_LOCK);
  1296. if ( ec == NULL )
  1297. {
  1298. slapi_send_ldap_result( pb, LDAP_NO_SUCH_OBJECT, NULL, NULL, 0, NULL );
  1299. slapi_sdn_done(&sdn);
  1300. return( SLAPI_BIND_FAIL );
  1301. }
  1302. switch ( method )
  1303. {
  1304. case LDAP_AUTH_SIMPLE:
  1305. {
  1306. Slapi_Value cv;
  1307. if ( slapi_entry_attr_find( ec, "userpassword", &attr ) != 0 )
  1308. {
  1309. slapi_send_ldap_result( pb, LDAP_INAPPROPRIATE_AUTH, NULL, NULL, 0, NULL );
  1310. slapi_entry_free(ec);
  1311. slapi_sdn_done(&sdn);
  1312. return SLAPI_BIND_FAIL;
  1313. }
  1314. bvals= attr_get_present_values( attr );
  1315. slapi_value_init_berval(&cv,cred);
  1316. if ( slapi_pw_find_sv( bvals, &cv ) != 0 )
  1317. {
  1318. slapi_send_ldap_result( pb, LDAP_INVALID_CREDENTIALS, NULL, NULL, 0, NULL );
  1319. slapi_entry_free(ec);
  1320. slapi_sdn_done(&sdn);
  1321. value_done(&cv);
  1322. return SLAPI_BIND_FAIL;
  1323. }
  1324. value_done(&cv);
  1325. }
  1326. break;
  1327. default:
  1328. slapi_send_ldap_result( pb, LDAP_STRONG_AUTH_NOT_SUPPORTED, NULL, "auth method not supported", 0, NULL );
  1329. slapi_entry_free(ec);
  1330. slapi_sdn_done(&sdn);
  1331. return SLAPI_BIND_FAIL;
  1332. }
  1333. slapi_entry_free(ec);
  1334. slapi_sdn_done(&sdn);
  1335. /* success: front end will send result */
  1336. return SLAPI_BIND_SUCCESS;
  1337. }
  1338. int
  1339. dse_unbind( Slapi_PBlock *pb )
  1340. {
  1341. return 0;
  1342. }
  1343. /*
  1344. * This structure is simply to pass parameters to dse_search_filter_entry.
  1345. */
  1346. struct magicSearchStuff
  1347. {
  1348. Slapi_PBlock *pb;
  1349. struct dse *pdse;
  1350. int scope;
  1351. const Slapi_DN *basedn;
  1352. Slapi_Filter *filter;
  1353. int nentries;
  1354. char **attrs; /*Attributes*/
  1355. int attrsonly; /*Should we just return the attributes found?*/
  1356. dse_search_set *ss; /* for the temporary results - to pass to the dse search callbacks */
  1357. };
  1358. /*
  1359. * The function which is called on each node of the AVL tree.
  1360. */
  1361. static int
  1362. dse_search_filter_entry(caddr_t data, caddr_t arg)
  1363. {
  1364. struct dse_node *n = (struct dse_node *)data;
  1365. struct magicSearchStuff *p= (struct magicSearchStuff *)arg;
  1366. if(slapi_sdn_scope_test( slapi_entry_get_sdn_const(n->entry), p->basedn, p->scope))
  1367. {
  1368. if(slapi_vattr_filter_test( p->pb, n->entry, p->filter, 1 /* verify access */ )==0)
  1369. {
  1370. Slapi_Entry *ec = slapi_entry_dup( n->entry );
  1371. p->nentries++;
  1372. if (!p->ss)
  1373. {
  1374. p->ss = dse_search_set_new();
  1375. }
  1376. dse_search_set_add_entry(p->ss, ec); /* consumes the entry */
  1377. } else {
  1378. /*
  1379. slapd_log_error_proc("dse_search_filter_entry",
  1380. "filter test failed: dn %s did not match filter %d\n",
  1381. slapi_entry_get_dn_const(n->entry), p->filter->f_choice);
  1382. */
  1383. }
  1384. } else {
  1385. /*
  1386. slapd_log_error_proc("dse_search_filter_entry",
  1387. "scope test failed: dn %s is not in scope %d of dn [%s]\n",
  1388. slapi_entry_get_dn_const(n->entry), p->scope,
  1389. slapi_sdn_get_dn(p->basedn));
  1390. */
  1391. }
  1392. return 0;
  1393. }
  1394. /*
  1395. * The function which kicks off the traversal of the AVL tree.
  1396. * Returns the number of entries returned.
  1397. */
  1398. /* jcm: Not very efficient if there are many DSE entries. */
  1399. /* jcm: It applies the filter to every node in the tree regardless */
  1400. static int
  1401. do_dse_search(struct dse* pdse, Slapi_PBlock *pb, int scope, const Slapi_DN *basedn, Slapi_Filter *filter, char **attrs, int attrsonly)
  1402. {
  1403. struct magicSearchStuff stuff;
  1404. stuff.pb= pb;
  1405. stuff.pdse= pdse;
  1406. stuff.scope= scope;
  1407. stuff.basedn= basedn;
  1408. stuff.filter= filter;
  1409. stuff.nentries= 0;
  1410. stuff.attrs= attrs;
  1411. stuff.attrsonly= attrsonly;
  1412. stuff.ss = NULL;
  1413. /*
  1414. * If this is a persistent search and the client is only interested in
  1415. * entries that change, we skip looking through the DSE entries.
  1416. */
  1417. if ( pb->pb_op == NULL
  1418. || !operation_is_flag_set( pb->pb_op, OP_FLAG_PS_CHANGESONLY )) {
  1419. PR_RWLock_Rlock(pdse->dse_rwlock);
  1420. dse_apply_nolock(pdse,dse_search_filter_entry,(caddr_t)&stuff);
  1421. PR_RWLock_Unlock(pdse->dse_rwlock);
  1422. }
  1423. if (stuff.ss) /* something was found which matched our criteria */
  1424. {
  1425. Slapi_Entry *e = NULL;
  1426. for (e = dse_search_set_get_next_entry(stuff.ss);
  1427. e;
  1428. e = dse_search_set_get_next_entry(stuff.ss))
  1429. {
  1430. int returncode = 0;
  1431. char returntext[SLAPI_DSE_RETURNTEXT_SIZE]= "";
  1432. if(dse_call_callback(pdse, pb, SLAPI_OPERATION_SEARCH,
  1433. DSE_FLAG_PREOP, e, NULL, &returncode, returntext)
  1434. == SLAPI_DSE_CALLBACK_OK)
  1435. {
  1436. dse_search_set *ss = NULL;
  1437. slapi_pblock_get (pb, SLAPI_SEARCH_RESULT_SET, &ss);
  1438. /* if this is the first entry - allocate dse_search_set structure */
  1439. if (ss == NULL)
  1440. {
  1441. ss = dse_search_set_new ();
  1442. slapi_pblock_set (pb, SLAPI_SEARCH_RESULT_SET, ss);
  1443. }
  1444. /* make another reference to e (stuff.ss references it too)
  1445. the stuff.ss reference is removed by dse_search_set_clean()
  1446. below, leaving ss as the sole owner of the memory */
  1447. dse_search_set_add_entry(ss, e);
  1448. } else {
  1449. stuff.nentries--; /* rejected entry */
  1450. /* this leaves a freed pointer in stuff.ss, but that's ok because
  1451. it should never be referenced, and the reference is removed by
  1452. the call to dse_search_set_clean() below */
  1453. slapi_entry_free(e);
  1454. }
  1455. }
  1456. dse_search_set_clean(stuff.ss);
  1457. }
  1458. /* the pblock ss now contains the "real" search result set and the copies of
  1459. the entries allocated in dse_search_filter_entry; any entries rejected by
  1460. the search callback were freed above by the call to slapi_entry_free() */
  1461. return stuff.nentries;
  1462. }
  1463. /*
  1464. * -1 means something went wrong.
  1465. * 0 means everything went ok.
  1466. */
  1467. int
  1468. dse_search(Slapi_PBlock *pb) /* JCM There should only be one exit point from this function! */
  1469. {
  1470. char *base; /*Base of the search*/
  1471. int scope; /*Scope of the search*/
  1472. Slapi_Filter *filter; /*The filter*/
  1473. char **attrs; /*Attributes*/
  1474. int attrsonly; /*Should we just return the attributes found?*/
  1475. /*int nentries= 0; Number of entries found thus far*/
  1476. struct dse* pdse;
  1477. int returncode= LDAP_SUCCESS;
  1478. int isrootdse= 0;
  1479. char returntext[SLAPI_DSE_RETURNTEXT_SIZE]= "";
  1480. Slapi_DN basesdn;
  1481. /*
  1482. * Get private information created in the init routine.
  1483. * Also get the parameters of the search operation. These come
  1484. * more or less directly from the client.
  1485. */
  1486. if (slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &pdse ) < 0 ||
  1487. slapi_pblock_get( pb, SLAPI_SEARCH_TARGET, &base ) < 0 ||
  1488. slapi_pblock_get( pb, SLAPI_SEARCH_SCOPE, &scope ) < 0 ||
  1489. slapi_pblock_get( pb, SLAPI_SEARCH_FILTER, &filter ) < 0 ||
  1490. slapi_pblock_get( pb, SLAPI_SEARCH_ATTRS, &attrs ) < 0 ||
  1491. slapi_pblock_get( pb, SLAPI_SEARCH_ATTRSONLY, &attrsonly ) <0)
  1492. {
  1493. slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
  1494. return(-1);
  1495. }
  1496. slapi_sdn_init_dn_byref(&basesdn,base);
  1497. /*
  1498. * Sadly the root dse is still a special case. We must not allow
  1499. * acl checks on it, or allow onelevel or subtree searches on it.
  1500. */
  1501. isrootdse= slapi_sdn_isempty(&basesdn);
  1502. switch(scope)
  1503. {
  1504. case LDAP_SCOPE_BASE:
  1505. {
  1506. Slapi_Entry *baseentry= NULL;
  1507. baseentry = dse_get_entry_copy(pdse,&basesdn,DSE_USE_LOCK);
  1508. if ( baseentry == NULL )
  1509. {
  1510. slapi_send_ldap_result( pb, LDAP_NO_SUCH_OBJECT, NULL, NULL, 0, NULL );
  1511. slapi_log_error(SLAPI_LOG_PLUGIN,"dse_search", "node %s was not found\n",
  1512. slapi_sdn_get_dn(&basesdn));
  1513. slapi_sdn_done(&basesdn);
  1514. return -1;
  1515. }
  1516. /*
  1517. * We don't want to do an acl check for the root dse... because the acl
  1518. * code thinks it's a suffix of every target... so every acl applies to
  1519. * the root dse... which is wrong.
  1520. */
  1521. if(slapi_vattr_filter_test( pb, baseentry, filter, !isrootdse /* verify access */ )==0)
  1522. {
  1523. /* Callbacks modify a copy of the entry */
  1524. if(dse_call_callback(pdse, pb, SLAPI_OPERATION_SEARCH,
  1525. DSE_FLAG_PREOP, baseentry, NULL, &returncode, returntext)
  1526. == SLAPI_DSE_CALLBACK_OK)
  1527. {
  1528. dse_search_set *ss;
  1529. ss = dse_search_set_new ();
  1530. slapi_pblock_set (pb, SLAPI_SEARCH_RESULT_SET, ss);
  1531. dse_search_set_add_entry (ss, baseentry); /* consumes the entry */
  1532. baseentry= NULL;
  1533. }
  1534. }
  1535. slapi_entry_free(baseentry);
  1536. }
  1537. break;
  1538. case LDAP_SCOPE_ONELEVEL:
  1539. /* FALL THROUGH */
  1540. case LDAP_SCOPE_SUBTREE:
  1541. if(!isrootdse)
  1542. {
  1543. do_dse_search(pdse, pb, scope, &basesdn, filter, attrs, attrsonly);
  1544. }
  1545. break;
  1546. }
  1547. /* Search is done, send LDAP_SUCCESS */
  1548. slapi_sdn_done(&basesdn);
  1549. return 0;
  1550. }
  1551. /*
  1552. * -1 means something went wrong.
  1553. * 0 means everything went ok.
  1554. */
  1555. static int
  1556. dse_modify_return( int rv, Slapi_Entry *ec, Slapi_Entry *ecc )
  1557. {
  1558. slapi_entry_free(ec);
  1559. slapi_entry_free(ecc);
  1560. return rv;
  1561. }
  1562. int
  1563. dse_modify(Slapi_PBlock *pb) /* JCM There should only be one exit point from this function! */
  1564. {
  1565. int err; /*House keeping stuff*/
  1566. LDAPMod **mods; /*Used to apply the modifications*/
  1567. char *dn; /*Storage for the dn*/
  1568. char *errbuf = NULL; /* To get error back */
  1569. struct dse* pdse;
  1570. Slapi_Entry *ec= NULL;
  1571. Slapi_Entry *ecc= NULL;
  1572. int returncode= LDAP_SUCCESS;
  1573. char returntext[SLAPI_DSE_RETURNTEXT_SIZE]= "";
  1574. Slapi_DN sdn;
  1575. int dont_write_file = 0; /* default */
  1576. PR_ASSERT(pb);
  1577. if (slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &pdse ) < 0 ||
  1578. slapi_pblock_get( pb, SLAPI_MODIFY_TARGET, &dn ) < 0 ||
  1579. slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods ) < 0 || (NULL == pdse))
  1580. {
  1581. slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
  1582. return( -1 );
  1583. }
  1584. slapi_pblock_get(pb, SLAPI_DSE_DONT_WRITE_WHEN_ADDING, &dont_write_file);
  1585. if ( !dont_write_file && dse_check_for_readonly_error(pb,pdse)) {
  1586. return( -1 );
  1587. }
  1588. slapi_sdn_init_dn_byref(&sdn,dn);
  1589. /* Find the entry we are about to modify. */
  1590. ec = dse_get_entry_copy(pdse,&sdn,DSE_USE_LOCK);
  1591. if ( ec == NULL )
  1592. {
  1593. slapi_send_ldap_result( pb, LDAP_NO_SUCH_OBJECT, NULL, NULL, 0, NULL );
  1594. slapi_sdn_done(&sdn);
  1595. return dse_modify_return( -1, ec, ecc );
  1596. }
  1597. /* Check acl */
  1598. err = plugin_call_acl_mods_access ( pb, ec, mods, &errbuf );
  1599. if ( err != LDAP_SUCCESS )
  1600. {
  1601. slapi_send_ldap_result( pb, err, NULL, errbuf, 0, NULL );
  1602. if (errbuf) slapi_ch_free ((void**)&errbuf);
  1603. slapi_sdn_done(&sdn);
  1604. return dse_modify_return( -1, ec, ecc );
  1605. }
  1606. /* Save away a copy of the entry, before modifications */
  1607. slapi_pblock_set( pb, SLAPI_ENTRY_PRE_OP, slapi_entry_dup( ec )); /* JCM - When does this get free'd? */
  1608. /* richm - it is freed in modify.c */
  1609. /* Modify a copy of the entry*/
  1610. ecc = slapi_entry_dup( ec );
  1611. err = entry_apply_mods( ecc, mods );
  1612. /* XXXmcs: should we expand objectclass values here?? */
  1613. switch(dse_call_callback(pdse, pb, SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, ec, ecc, &returncode, returntext))
  1614. {
  1615. case SLAPI_DSE_CALLBACK_ERROR:
  1616. {
  1617. /* Error occured in the callback -- return error code from callback */
  1618. slapi_send_ldap_result( pb, returncode, NULL, returntext, 0, NULL );
  1619. slapi_sdn_done(&sdn);
  1620. return dse_modify_return( -1, ec, ecc );
  1621. }
  1622. case SLAPI_DSE_CALLBACK_DO_NOT_APPLY:
  1623. {
  1624. /* Callback says don't apply the changes -- return Success */
  1625. slapi_send_ldap_result( pb, LDAP_SUCCESS, NULL, NULL, 0, NULL );
  1626. slapi_sdn_done(&sdn);
  1627. return dse_modify_return( 0, ec, ecc );
  1628. }
  1629. case SLAPI_DSE_CALLBACK_OK:
  1630. {
  1631. /* The callback may alter the mods in the pblock. This happens
  1632. for example in the schema code. Since the schema attributes
  1633. are managed exclusively by the schema code, we should not
  1634. apply those mods. However, for reasons unknown to me, we
  1635. must in the general case call entry_apply_mods before calling
  1636. the modify callback above. In the case of schema, the schema
  1637. code will remove the schema attributes from the mods. So, we
  1638. reapply the mods to the entry for the attributes we manage in
  1639. the dse code (e.g. aci)
  1640. */
  1641. int reapply_mods = 0; /* default is to not reapply entry_apply_mods */
  1642. slapi_pblock_get(pb, SLAPI_DSE_REAPPLY_MODS, &reapply_mods);
  1643. /* Callback says apply the changes */
  1644. if ( reapply_mods )
  1645. {
  1646. LDAPMod **modsagain = NULL; /*Used to apply the modifications*/
  1647. slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &modsagain );
  1648. if (NULL != modsagain)
  1649. {
  1650. /* the dse modify callback must have modified ecc back to it's
  1651. original state, before the earlier apply_mods, but without the
  1652. attributes it did not want us to apply mods to */
  1653. err = entry_apply_mods( ecc, modsagain );
  1654. }
  1655. }
  1656. if (err != 0)
  1657. {
  1658. /* entry_apply_mods() failed above, so return an error now */
  1659. slapi_send_ldap_result( pb, err, NULL, NULL, 0, NULL );
  1660. slapi_sdn_done(&sdn);
  1661. return dse_modify_return( -1, ec, ecc );
  1662. }
  1663. break;
  1664. }
  1665. }
  1666. /* We're applying the mods... check that the entry still obeys the schema */
  1667. if ( slapi_entry_schema_check( pb, ecc ) != 0 )
  1668. {
  1669. char *errtext;
  1670. slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &errtext);
  1671. slapi_send_ldap_result( pb, LDAP_OBJECT_CLASS_VIOLATION, NULL, errtext, 0, NULL );
  1672. slapi_sdn_done(&sdn);
  1673. return dse_modify_return( -1, ec, ecc );
  1674. }
  1675. /* Change the entry itself both on disk and in the AVL tree */
  1676. /* dse_replace_entry free's the existing entry. */
  1677. if (dse_replace_entry( pdse, ecc, !dont_write_file, DSE_USE_LOCK )!=0 )
  1678. {
  1679. slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
  1680. slapi_sdn_done(&sdn);
  1681. return dse_modify_return( -1, ec, ecc );
  1682. }
  1683. slapi_pblock_set( pb, SLAPI_ENTRY_POST_OP, slapi_entry_dup(ecc) ); /* JCM - When does this get free'd? */
  1684. /* richm - it is freed in modify.c */
  1685. dse_call_callback(pdse, pb, SLAPI_OPERATION_MODIFY, DSE_FLAG_POSTOP, ec, ecc, &returncode, returntext);
  1686. slapi_send_ldap_result( pb, returncode, NULL, returntext, 0, NULL );
  1687. slapi_sdn_done(&sdn);
  1688. return dse_modify_return(0, ec, ecc);
  1689. }
  1690. static int
  1691. dse_add_return( int rv, Slapi_Entry *e)
  1692. {
  1693. slapi_entry_free(e);
  1694. return rv;
  1695. }
  1696. /*
  1697. * -1 means something went wrong.
  1698. * 0 means everything went ok.
  1699. */
  1700. int
  1701. dse_add(Slapi_PBlock *pb) /* JCM There should only be one exit point from this function! */
  1702. {
  1703. char *dn = NULL;
  1704. Slapi_Entry *e; /*The new entry to add*/
  1705. Slapi_Entry *e_copy = NULL; /* copy of added entry */
  1706. char *errbuf = NULL;
  1707. int rc = LDAP_SUCCESS;
  1708. int error = -1;
  1709. int dont_write_file = 0; /* default */
  1710. struct dse* pdse;
  1711. int returncode= LDAP_SUCCESS;
  1712. char returntext[SLAPI_DSE_RETURNTEXT_SIZE]= "";
  1713. Slapi_DN sdn;
  1714. Slapi_DN parent;
  1715. /*
  1716. * Get the database, the dn and the entry to add
  1717. */
  1718. if (slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &pdse ) < 0 ||
  1719. slapi_pblock_get( pb, SLAPI_ADD_TARGET, &dn ) < 0 ||
  1720. slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &e ) < 0 || (NULL == pdse))
  1721. {
  1722. slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
  1723. return error;
  1724. }
  1725. slapi_pblock_get(pb, SLAPI_DSE_DONT_WRITE_WHEN_ADDING, &dont_write_file);
  1726. if ( !dont_write_file && dse_check_for_readonly_error(pb,pdse)) {
  1727. return( error );
  1728. }
  1729. slapi_sdn_init_dn_byref(&sdn,dn);
  1730. /*
  1731. * Check to make sure the entry passes the schema check
  1732. */
  1733. if ( slapi_entry_schema_check( pb, e ) != 0 )
  1734. {
  1735. char *errtext;
  1736. LDAPDebug( SLAPI_DSE_TRACELEVEL,
  1737. "dse_add: entry failed schema check\n", 0, 0, 0 );
  1738. slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &errtext);
  1739. slapi_send_ldap_result( pb, LDAP_OBJECT_CLASS_VIOLATION, NULL, errtext, 0, NULL );
  1740. slapi_sdn_done(&sdn);
  1741. return error;
  1742. }
  1743. /*
  1744. * Attempt to find this dn.
  1745. */
  1746. {
  1747. Slapi_Entry *existingentry= dse_get_entry_copy( pdse, &sdn, DSE_USE_LOCK );
  1748. if(existingentry!=NULL)
  1749. {
  1750. /*
  1751. * If we've reached this code, there is an entry
  1752. * whose dn matches dn, so tell the user and return
  1753. */
  1754. slapi_send_ldap_result( pb, LDAP_ALREADY_EXISTS, NULL, NULL, 0, NULL );
  1755. slapi_sdn_done(&sdn);
  1756. slapi_entry_free(existingentry);
  1757. return dse_add_return(error, NULL);
  1758. }
  1759. }
  1760. /*
  1761. * Get the parent dn and see if the corresponding entry exists.
  1762. * If the parent does not exist, only allow the "root" user to
  1763. * add the entry.
  1764. */
  1765. slapi_sdn_init(&parent);
  1766. slapi_sdn_get_parent(&sdn,&parent);
  1767. if ( !slapi_sdn_isempty(&parent) )
  1768. {
  1769. Slapi_Entry *parententry= NULL;
  1770. parententry= dse_get_entry_copy( pdse, &parent, DSE_USE_LOCK );
  1771. if( parententry==NULL )
  1772. {
  1773. slapi_send_ldap_result( pb, LDAP_NO_SUCH_OBJECT, NULL, NULL, 0, NULL );
  1774. LDAPDebug( SLAPI_DSE_TRACELEVEL, "dse_add: parent does not exist\n", 0, 0, 0 );
  1775. slapi_sdn_done(&sdn);
  1776. slapi_sdn_done(&parent);
  1777. return dse_add_return(error, NULL);
  1778. }
  1779. rc= plugin_call_acl_plugin ( pb, parententry, NULL, NULL, SLAPI_ACL_ADD, ACLPLUGIN_ACCESS_DEFAULT, &errbuf );
  1780. slapi_entry_free(parententry);
  1781. if ( rc!=LDAP_SUCCESS )
  1782. {
  1783. LDAPDebug( SLAPI_DSE_TRACELEVEL, "dse_add: no access to parent\n", 0, 0, 0 );
  1784. slapi_send_ldap_result( pb, rc, NULL, NULL, 0, NULL );
  1785. slapi_ch_free((void**)&errbuf);
  1786. slapi_sdn_done(&sdn);
  1787. slapi_sdn_done(&parent);
  1788. return dse_add_return(rc, NULL);
  1789. }
  1790. }
  1791. else
  1792. {
  1793. /* no parent */
  1794. int isroot;
  1795. slapi_pblock_get( pb, SLAPI_REQUESTOR_ISROOT, &isroot );
  1796. if ( !isroot )
  1797. {
  1798. LDAPDebug( SLAPI_DSE_TRACELEVEL, "dse_add: no parent and not root\n", 0, 0, 0 );
  1799. slapi_send_ldap_result( pb, LDAP_INSUFFICIENT_ACCESS, NULL, NULL, 0, NULL );
  1800. slapi_sdn_done(&sdn);
  1801. slapi_sdn_done(&parent);
  1802. return dse_add_return(error, NULL);
  1803. }
  1804. }
  1805. slapi_sdn_done(&parent);
  1806. /*
  1807. * Before we add the entry, find out if the syntax of the aci
  1808. * aci attribute values are correct or not. We don't want to add
  1809. * the entry if the syntax is incorrect.
  1810. */
  1811. if ( plugin_call_acl_verify_syntax (pb, e, &errbuf) != 0 )
  1812. {
  1813. slapi_send_ldap_result( pb, LDAP_INVALID_SYNTAX, NULL, errbuf, 0, NULL );
  1814. slapi_ch_free((void**)&errbuf);
  1815. return dse_add_return(error, NULL);
  1816. }
  1817. if(dse_call_callback(pdse, pb, SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, e,
  1818. NULL, &returncode, returntext)!=SLAPI_DSE_CALLBACK_OK)
  1819. {
  1820. slapi_send_ldap_result( pb, returncode, NULL, returntext, 0, NULL );
  1821. slapi_sdn_done(&sdn);
  1822. return dse_add_return(error, NULL);
  1823. }
  1824. /* make copy for postop fns because add_entry_pb consumes e */
  1825. e_copy = slapi_entry_dup(e);
  1826. if ( dse_add_entry_pb(pdse, e, pb) != 0)
  1827. {
  1828. slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
  1829. slapi_sdn_done(&sdn);
  1830. return dse_add_return(error, e_copy);
  1831. }
  1832. /* e has been consumed, so use the copy for the post ops */
  1833. slapi_pblock_set(pb, SLAPI_ADD_ENTRY, e_copy);
  1834. /* The postop must be called after the write lock is released. */
  1835. dse_call_callback(pdse, pb, SLAPI_OPERATION_ADD, DSE_FLAG_POSTOP, e_copy, NULL, &returncode, returntext);
  1836. /* We have been successful. Tell the user */
  1837. slapi_send_ldap_result( pb, returncode, NULL, NULL, 0, NULL );
  1838. slapi_pblock_set( pb, SLAPI_ENTRY_POST_OP, slapi_entry_dup( e_copy ));
  1839. /* entry has been freed, so make sure no one tries to use it later */
  1840. slapi_pblock_set(pb, SLAPI_ADD_ENTRY, NULL);
  1841. /* Free the dn, and return */
  1842. slapi_sdn_done(&sdn);
  1843. return dse_add_return(rc, e_copy);
  1844. }
  1845. /*
  1846. * -1 means something went wrong.
  1847. * 0 means everything went ok.
  1848. */
  1849. static int
  1850. dse_delete_return( int rv, Slapi_Entry *ec)
  1851. {
  1852. slapi_entry_free(ec);
  1853. return rv;
  1854. }
  1855. int
  1856. dse_delete(Slapi_PBlock *pb) /* JCM There should only be one exit point from this function! */
  1857. {
  1858. char *dn = NULL;
  1859. int rc= -1;
  1860. int dont_write_file = 0; /* default */
  1861. struct dse* pdse = NULL;
  1862. int returncode= LDAP_SUCCESS;
  1863. char returntext[SLAPI_DSE_RETURNTEXT_SIZE]= "";
  1864. char *entry_str = "entry";
  1865. char *errbuf = NULL;
  1866. char *attrs[2] = { NULL, NULL };
  1867. Slapi_DN sdn;
  1868. Slapi_Entry *ec = NULL; /* copy of entry to delete */
  1869. /*
  1870. * Get the database and the dn
  1871. */
  1872. if (slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &pdse ) < 0 ||
  1873. slapi_pblock_get( pb, SLAPI_DELETE_TARGET, &dn ) < 0 || (pdse == NULL))
  1874. {
  1875. slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
  1876. return rc;
  1877. }
  1878. slapi_pblock_get(pb, SLAPI_DSE_DONT_WRITE_WHEN_ADDING, &dont_write_file);
  1879. if ( !dont_write_file && dse_check_for_readonly_error(pb,pdse)) {
  1880. return( rc );
  1881. }
  1882. slapi_sdn_init_dn_byref(&sdn,dn);
  1883. ec= dse_get_entry_copy( pdse, &sdn, DSE_USE_LOCK );
  1884. if (ec == NULL)
  1885. {
  1886. slapi_send_ldap_result( pb, LDAP_NO_SUCH_OBJECT, NULL, NULL, 0, NULL );
  1887. slapi_sdn_done(&sdn);
  1888. return dse_delete_return( rc, ec );
  1889. }
  1890. /*
  1891. * Check if this node has any children.
  1892. */
  1893. if(dse_numsubordinates(ec)>0)
  1894. {
  1895. slapi_send_ldap_result( pb, LDAP_NOT_ALLOWED_ON_NONLEAF, NULL, NULL, 0, NULL );
  1896. slapi_sdn_done(&sdn);
  1897. return dse_delete_return( rc, ec );
  1898. }
  1899. /*
  1900. * Check the access
  1901. */
  1902. attrs[0] = entry_str;
  1903. attrs[1] = NULL;
  1904. returncode= plugin_call_acl_plugin ( pb, ec, attrs, NULL, SLAPI_ACL_DELETE, ACLPLUGIN_ACCESS_DEFAULT, &errbuf );
  1905. if ( returncode!=LDAP_SUCCESS)
  1906. {
  1907. slapi_send_ldap_result( pb, returncode, NULL, NULL, 0, NULL );
  1908. slapi_ch_free ( (void**)&errbuf );
  1909. slapi_sdn_done(&sdn);
  1910. return dse_delete_return( rc, ec );
  1911. }
  1912. if(dse_call_callback(pdse, pb, SLAPI_OPERATION_DELETE, DSE_FLAG_PREOP, ec, NULL, &returncode,returntext)==SLAPI_DSE_CALLBACK_OK)
  1913. {
  1914. if(dse_delete_entry(pdse, pb, ec)==0)
  1915. {
  1916. returncode= LDAP_OPERATIONS_ERROR;
  1917. }
  1918. }
  1919. else
  1920. {
  1921. slapi_send_ldap_result( pb, returncode, NULL, NULL, 0, NULL );
  1922. slapi_sdn_done(&sdn);
  1923. return dse_delete_return( rc, ec );
  1924. }
  1925. dse_call_callback(pdse, pb, SLAPI_OPERATION_DELETE, DSE_FLAG_POSTOP, ec, NULL, &returncode, returntext);
  1926. slapi_send_ldap_result( pb, returncode, NULL, returntext, 0, NULL );
  1927. slapi_pblock_set( pb, SLAPI_ENTRY_PRE_OP, slapi_entry_dup( ec ));
  1928. slapi_sdn_done(&sdn);
  1929. return dse_delete_return(0, ec);
  1930. }
  1931. struct dse_callback *
  1932. dse_register_callback(struct dse* pdse, int operation, int flags, const Slapi_DN *base, int scope, const char *filter, dseCallbackFn fn, void *fn_arg)
  1933. {
  1934. struct dse_callback *callback = dse_callback_new(operation, flags, base, scope, filter, fn, fn_arg);
  1935. dse_callback_addtolist(&pdse->dse_callback, callback);
  1936. return callback;
  1937. }
  1938. void
  1939. dse_remove_callback(struct dse* pdse, int operation, int flags, const Slapi_DN *base, int scope, const char *filter, dseCallbackFn fn)
  1940. {
  1941. dse_callback_removefromlist(&pdse->dse_callback, operation, flags, base, scope, filter, fn);
  1942. }
  1943. /*
  1944. * Return values:
  1945. * SLAPI_DSE_CALLBACK_ERROR -- Callback failed.
  1946. * SLAPI_DSE_CALLBACK_OK -- OK, do it.
  1947. * SLAPI_DSE_CALLBACK_DO_NOT_APPLY -- No error, but don't apply changes.
  1948. */
  1949. static int
  1950. dse_call_callback(struct dse* pdse, Slapi_PBlock *pb, int operation, int flags, Slapi_Entry *entryBefore, Slapi_Entry *entryAfter, int *returncode, char *returntext)
  1951. {
  1952. /* ONREPL callbacks can potentially modify pblock parameters like backend
  1953. * which would cause problems during request processing. We need to save
  1954. * "important" fields before calls and restoring them afterwards */
  1955. int r = SLAPI_DSE_CALLBACK_OK;
  1956. if (pdse->dse_callback != NULL) {
  1957. struct dse_callback *p;
  1958. p=pdse->dse_callback;
  1959. while (p!=NULL) {
  1960. struct dse_callback *p_next = p->next;
  1961. if ((p->operation & operation) && (p->flags & flags)) {
  1962. if(slapi_sdn_scope_test(slapi_entry_get_sdn_const(entryBefore), p->base, p->scope))
  1963. {
  1964. if(NULL == p->slapifilter ||
  1965. slapi_vattr_filter_test(pb, entryBefore, p->slapifilter,
  1966. 0 /* !verify access */ )==0)
  1967. {
  1968. int result= (*p->fn)(pb, entryBefore,entryAfter,returncode,returntext,p->fn_arg);
  1969. if(result<r)
  1970. {
  1971. r= result;
  1972. }
  1973. }
  1974. }
  1975. }
  1976. p = p_next;
  1977. }
  1978. }
  1979. return r;
  1980. }
  1981. int
  1982. slapi_config_register_callback(int operation, int flags, const char *base, int scope, const char *filter, dseCallbackFn fn, void *fn_arg)
  1983. {
  1984. int rc= 0;
  1985. Slapi_Backend *be= slapi_be_select_by_instance_name(DSE_BACKEND);
  1986. if (be != NULL) {
  1987. struct dse* pdse= (struct dse*)be->be_database->plg_private;
  1988. if (pdse!=NULL) {
  1989. Slapi_DN dn;
  1990. slapi_sdn_init_dn_byref(&dn,base);
  1991. rc = (NULL != dse_register_callback(pdse, operation, flags, &dn, scope, filter, fn, fn_arg));
  1992. slapi_sdn_done(&dn);
  1993. }
  1994. }
  1995. return rc;
  1996. }
  1997. int
  1998. slapi_config_remove_callback(int operation, int flags, const char *base, int scope, const char *filter, dseCallbackFn fn)
  1999. {
  2000. int rc= 0;
  2001. Slapi_Backend *be= slapi_be_select_by_instance_name(DSE_BACKEND);
  2002. if(be != NULL) {
  2003. struct dse* pdse = (struct dse*)be->be_database->plg_private;
  2004. if (pdse != NULL) {
  2005. Slapi_DN dn;
  2006. slapi_sdn_init_dn_byref(&dn,base);
  2007. dse_remove_callback(pdse, operation, flags, &dn, scope, filter, fn);
  2008. slapi_sdn_done(&dn);
  2009. rc= 1;
  2010. }
  2011. }
  2012. return rc;
  2013. }
  2014. void
  2015. dse_set_dont_ever_write_dse_files()
  2016. {
  2017. dont_ever_write_dse_files = 1;
  2018. }
  2019. void
  2020. dse_unset_dont_ever_write_dse_files()
  2021. {
  2022. dont_ever_write_dse_files = 0;
  2023. }
  2024. static dse_search_set*
  2025. dse_search_set_new ()
  2026. {
  2027. dse_search_set *ss;
  2028. ss = (dse_search_set *)slapi_ch_malloc (sizeof (*ss));
  2029. if (ss)
  2030. {
  2031. dl_init (&ss->dl, 0);
  2032. ss->current_entry = -1;
  2033. }
  2034. return ss;
  2035. }
  2036. /* This is similar to delete, but it does not free the entries contained in the
  2037. search set. This is useful in do_dse_search when we copy the entries from
  2038. 1 search set to the other. */
  2039. static void
  2040. dse_search_set_clean(dse_search_set *ss)
  2041. {
  2042. if (ss)
  2043. {
  2044. dl_cleanup(&ss->dl, NULL);
  2045. slapi_ch_free((void **)&ss);
  2046. }
  2047. }
  2048. static void
  2049. dse_search_set_delete (dse_search_set *ss)
  2050. {
  2051. if (ss)
  2052. {
  2053. dl_cleanup (&ss->dl, dse_free_entry);
  2054. slapi_ch_free ((void**)&ss);
  2055. }
  2056. }
  2057. static void
  2058. dse_free_entry (void **data)
  2059. {
  2060. Slapi_Entry **e;
  2061. if (data)
  2062. {
  2063. e = (Slapi_Entry **)data;
  2064. if (*e)
  2065. slapi_entry_free (*e);
  2066. }
  2067. }
  2068. static void
  2069. dse_search_set_add_entry (dse_search_set *ss, Slapi_Entry *e)
  2070. {
  2071. PR_ASSERT (ss && e);
  2072. dl_add (&ss->dl, e);
  2073. }
  2074. static Slapi_Entry*
  2075. dse_search_set_get_next_entry (dse_search_set *ss)
  2076. {
  2077. PR_ASSERT (ss);
  2078. if (ss->current_entry == -1)
  2079. return (dl_get_first (&ss->dl, &ss->current_entry));
  2080. else
  2081. return (dl_get_next (&ss->dl, &ss->current_entry));
  2082. }
  2083. int
  2084. dse_next_search_entry (Slapi_PBlock *pb)
  2085. {
  2086. dse_search_set *ss;
  2087. Slapi_Entry *e;
  2088. slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &ss);
  2089. /* no entries to return */
  2090. if (ss == NULL)
  2091. {
  2092. slapi_pblock_set (pb, SLAPI_SEARCH_RESULT_ENTRY, NULL);
  2093. return 0;
  2094. }
  2095. e = dse_search_set_get_next_entry (ss);
  2096. slapi_pblock_set (pb, SLAPI_SEARCH_RESULT_ENTRY, e);
  2097. /* we reached the end of the list */
  2098. if (e == NULL)
  2099. {
  2100. dse_search_set_delete (ss);
  2101. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET, NULL);
  2102. }
  2103. return 0;
  2104. }