ldif.c revision 1.1.1.9 1 1.1.1.9 christos /* $NetBSD: ldif.c,v 1.1.1.9 2021/08/14 16:05:23 christos Exp $ */
2 1.1.1.2 lukem
3 1.1 lukem /* ldif.c - the ldif backend */
4 1.1.1.4 tron /* $OpenLDAP$ */
5 1.1 lukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6 1.1 lukem *
7 1.1.1.9 christos * Copyright 2005-2021 The OpenLDAP Foundation.
8 1.1 lukem * All rights reserved.
9 1.1 lukem *
10 1.1 lukem * Redistribution and use in source and binary forms, with or without
11 1.1 lukem * modification, are permitted only as authorized by the OpenLDAP
12 1.1 lukem * Public License.
13 1.1 lukem *
14 1.1 lukem * A copy of this license is available in the file LICENSE in the
15 1.1 lukem * top-level directory of the distribution or, alternatively, at
16 1.1 lukem * <http://www.OpenLDAP.org/license.html>.
17 1.1 lukem */
18 1.1 lukem /* ACKNOWLEDGEMENTS:
19 1.1 lukem * This work was originally developed by Eric Stokes for inclusion
20 1.1 lukem * in OpenLDAP Software.
21 1.1 lukem */
22 1.1 lukem
23 1.1.1.5 christos #include <sys/cdefs.h>
24 1.1.1.9 christos __RCSID("$NetBSD: ldif.c,v 1.1.1.9 2021/08/14 16:05:23 christos Exp $");
25 1.1.1.5 christos
26 1.1 lukem #include "portable.h"
27 1.1 lukem #include <stdio.h>
28 1.1 lukem #include <ac/string.h>
29 1.1 lukem #include <sys/types.h>
30 1.1 lukem #include <sys/stat.h>
31 1.1 lukem #include <ac/dirent.h>
32 1.1 lukem #include <fcntl.h>
33 1.1 lukem #include <ac/errno.h>
34 1.1 lukem #include <ac/unistd.h>
35 1.1 lukem #include "slap.h"
36 1.1 lukem #include "lutil.h"
37 1.1.1.9 christos #include "slap-config.h"
38 1.1 lukem
39 1.1.1.2 lukem struct ldif_tool {
40 1.1.1.2 lukem Entry **entries; /* collected by bi_tool_entry_first() */
41 1.1.1.2 lukem ID elen; /* length of entries[] array */
42 1.1.1.2 lukem ID ecount; /* number of entries */
43 1.1.1.2 lukem ID ecurrent; /* bi_tool_entry_next() position */
44 1.1.1.2 lukem # define ENTRY_BUFF_INCREMENT 500 /* initial entries[] length */
45 1.1.1.3 adam struct berval *tl_base;
46 1.1.1.3 adam int tl_scope;
47 1.1.1.3 adam Filter *tl_filter;
48 1.1.1.2 lukem };
49 1.1 lukem
50 1.1.1.2 lukem /* Per-database data */
51 1.1 lukem struct ldif_info {
52 1.1.1.2 lukem struct berval li_base_path; /* database directory */
53 1.1.1.2 lukem struct ldif_tool li_tool; /* for slap tools */
54 1.1.1.2 lukem /*
55 1.1.1.2 lukem * Read-only LDAP requests readlock li_rdwr for filesystem input.
56 1.1.1.2 lukem * Update requests first lock li_modop_mutex for filesystem I/O,
57 1.1.1.2 lukem * and then writelock li_rdwr as well for filesystem output.
58 1.1.1.2 lukem * This allows update requests to do callbacks that acquire
59 1.1.1.2 lukem * read locks, e.g. access controls that inspect entries.
60 1.1.1.2 lukem * (An alternative would be recursive read/write locks.)
61 1.1.1.2 lukem */
62 1.1.1.2 lukem ldap_pvt_thread_mutex_t li_modop_mutex; /* serialize update requests */
63 1.1.1.2 lukem ldap_pvt_thread_rdwr_t li_rdwr; /* no other I/O when writing */
64 1.1 lukem };
65 1.1 lukem
66 1.1.1.4 tron static int write_data( int fd, const char *spew, int len, int *save_errno );
67 1.1.1.4 tron
68 1.1 lukem #ifdef _WIN32
69 1.1 lukem #define mkdir(a,b) mkdir(a)
70 1.1.1.2 lukem #define move_file(from, to) (!MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING))
71 1.1.1.2 lukem #else
72 1.1.1.2 lukem #define move_file(from, to) rename(from, to)
73 1.1 lukem #endif
74 1.1.1.2 lukem #define move_dir(from, to) rename(from, to)
75 1.1 lukem
76 1.1 lukem
77 1.1 lukem #define LDIF ".ldif"
78 1.1 lukem #define LDIF_FILETYPE_SEP '.' /* LDIF[0] */
79 1.1 lukem
80 1.1 lukem /*
81 1.1 lukem * Unsafe/translated characters in the filesystem.
82 1.1 lukem *
83 1.1 lukem * LDIF_UNSAFE_CHAR(c) returns true if the character c is not to be used
84 1.1.1.2 lukem * in relative filenames, except it should accept '\\', '{' and '}' even
85 1.1.1.2 lukem * if unsafe. The value should be a constant expression.
86 1.1 lukem *
87 1.1 lukem * If '\\' is unsafe, #define LDIF_ESCAPE_CHAR as a safe character.
88 1.1 lukem * If '{' and '}' are unsafe, #define IX_FSL/IX_FSR as safe characters.
89 1.1 lukem * (Not digits, '-' or '+'. IX_FSL == IX_FSR is allowed.)
90 1.1 lukem *
91 1.1 lukem * Characters are escaped as LDIF_ESCAPE_CHAR followed by two hex digits,
92 1.1 lukem * except '\\' is replaced with LDIF_ESCAPE_CHAR and {} with IX_FS[LR].
93 1.1 lukem * Also some LDIF special chars are hex-escaped.
94 1.1 lukem *
95 1.1 lukem * Thus an LDIF filename is a valid normalized RDN (or suffix DN)
96 1.1 lukem * followed by ".ldif", except with '\\' replaced with LDIF_ESCAPE_CHAR.
97 1.1 lukem */
98 1.1 lukem
99 1.1 lukem #ifndef _WIN32
100 1.1 lukem
101 1.1 lukem /*
102 1.1 lukem * Unix/MacOSX version. ':' vs '/' can cause confusion on MacOSX so we
103 1.1 lukem * escape both. We escape them on Unix so both OS variants get the same
104 1.1 lukem * filenames.
105 1.1 lukem */
106 1.1 lukem #define LDIF_ESCAPE_CHAR '\\'
107 1.1 lukem #define LDIF_UNSAFE_CHAR(c) ((c) == '/' || (c) == ':')
108 1.1 lukem
109 1.1 lukem #else /* _WIN32 */
110 1.1 lukem
111 1.1 lukem /* Windows version - Microsoft's list of unsafe characters, except '\\' */
112 1.1.1.2 lukem #define LDIF_ESCAPE_CHAR '^' /* Not '\\' (unsafe on Windows) */
113 1.1 lukem #define LDIF_UNSAFE_CHAR(c) \
114 1.1 lukem ((c) == '/' || (c) == ':' || \
115 1.1 lukem (c) == '<' || (c) == '>' || (c) == '"' || \
116 1.1 lukem (c) == '|' || (c) == '?' || (c) == '*')
117 1.1 lukem
118 1.1 lukem #endif /* !_WIN32 */
119 1.1 lukem
120 1.1 lukem /*
121 1.1.1.9 christos * Left and Right "{num}" prefix to ordered RDNs ("olcDatabase={1}mdb").
122 1.1 lukem * IX_DN* are for LDAP RDNs, IX_FS* for their .ldif filenames.
123 1.1 lukem */
124 1.1 lukem #define IX_DNL '{'
125 1.1 lukem #define IX_DNR '}'
126 1.1 lukem #ifndef IX_FSL
127 1.1 lukem #define IX_FSL IX_DNL
128 1.1 lukem #define IX_FSR IX_DNR
129 1.1 lukem #endif
130 1.1 lukem
131 1.1 lukem /*
132 1.1 lukem * Test for unsafe chars, as well as chars handled specially by back-ldif:
133 1.1 lukem * - If the escape char is not '\\', it must itself be escaped. Otherwise
134 1.1 lukem * '\\' and the escape char would map to the same character.
135 1.1 lukem * - Escape the '.' in ".ldif", so the directory for an RDN that actually
136 1.1 lukem * ends with ".ldif" can not conflict with a file of the same name. And
137 1.1 lukem * since some OSes/programs choke on multiple '.'s, escape all of them.
138 1.1 lukem * - If '{' and '}' are translated to some other characters, those
139 1.1 lukem * characters must in turn be escaped when they occur in an RDN.
140 1.1 lukem */
141 1.1 lukem #ifndef LDIF_NEED_ESCAPE
142 1.1 lukem #define LDIF_NEED_ESCAPE(c) \
143 1.1 lukem ((LDIF_UNSAFE_CHAR(c)) || \
144 1.1 lukem LDIF_MAYBE_UNSAFE(c, LDIF_ESCAPE_CHAR) || \
145 1.1 lukem LDIF_MAYBE_UNSAFE(c, LDIF_FILETYPE_SEP) || \
146 1.1 lukem LDIF_MAYBE_UNSAFE(c, IX_FSL) || \
147 1.1 lukem (IX_FSR != IX_FSL && LDIF_MAYBE_UNSAFE(c, IX_FSR)))
148 1.1 lukem #endif
149 1.1 lukem /*
150 1.1 lukem * Helper macro for LDIF_NEED_ESCAPE(): Treat character x as unsafe if
151 1.1 lukem * back-ldif does not already treat is specially.
152 1.1 lukem */
153 1.1 lukem #define LDIF_MAYBE_UNSAFE(c, x) \
154 1.1 lukem (!(LDIF_UNSAFE_CHAR(x) || (x) == '\\' || (x) == IX_DNL || (x) == IX_DNR) \
155 1.1 lukem && (c) == (x))
156 1.1 lukem
157 1.1.1.2 lukem /* Collect other "safe char" tests here, until someone needs a fix. */
158 1.1.1.2 lukem enum {
159 1.1.1.2 lukem eq_unsafe = LDIF_UNSAFE_CHAR('='),
160 1.1.1.2 lukem safe_filenames = STRLENOF("" LDAP_DIRSEP "") == 1 && !(
161 1.1.1.2 lukem LDIF_UNSAFE_CHAR('-') || /* for "{-1}frontend" in bconfig.c */
162 1.1.1.2 lukem LDIF_UNSAFE_CHAR(LDIF_ESCAPE_CHAR) ||
163 1.1.1.2 lukem LDIF_UNSAFE_CHAR(IX_FSL) || LDIF_UNSAFE_CHAR(IX_FSR))
164 1.1.1.2 lukem };
165 1.1.1.2 lukem /* Sanity check: Try to force a compilation error if !safe_filenames */
166 1.1.1.2 lukem typedef struct {
167 1.1.1.2 lukem int assert_safe_filenames : safe_filenames ? 2 : -2;
168 1.1.1.2 lukem } assert_safe_filenames[safe_filenames ? 2 : -2];
169 1.1 lukem
170 1.1 lukem
171 1.1 lukem static ConfigTable ldifcfg[] = {
172 1.1 lukem { "directory", "dir", 2, 2, 0, ARG_BERVAL|ARG_OFFSET,
173 1.1 lukem (void *)offsetof(struct ldif_info, li_base_path),
174 1.1 lukem "( OLcfgDbAt:0.1 NAME 'olcDbDirectory' "
175 1.1 lukem "DESC 'Directory for database content' "
176 1.1 lukem "EQUALITY caseIgnoreMatch "
177 1.1 lukem "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
178 1.1 lukem { NULL, NULL, 0, 0, 0, ARG_IGNORED,
179 1.1 lukem NULL, NULL, NULL, NULL }
180 1.1 lukem };
181 1.1 lukem
182 1.1 lukem static ConfigOCs ldifocs[] = {
183 1.1 lukem { "( OLcfgDbOc:2.1 "
184 1.1 lukem "NAME 'olcLdifConfig' "
185 1.1 lukem "DESC 'LDIF backend configuration' "
186 1.1 lukem "SUP olcDatabaseConfig "
187 1.1 lukem "MUST ( olcDbDirectory ) )", Cft_Database, ldifcfg },
188 1.1 lukem { NULL, 0, NULL }
189 1.1 lukem };
190 1.1 lukem
191 1.1 lukem
192 1.1.1.2 lukem /*
193 1.1.1.2 lukem * Handle file/directory names.
194 1.1.1.2 lukem */
195 1.1.1.2 lukem
196 1.1 lukem /* Set *res = LDIF filename path for the normalized DN */
197 1.1.1.2 lukem static int
198 1.1.1.2 lukem ndn2path( Operation *op, struct berval *dn, struct berval *res, int empty_ok )
199 1.1 lukem {
200 1.1.1.2 lukem BackendDB *be = op->o_bd;
201 1.1 lukem struct ldif_info *li = (struct ldif_info *) be->be_private;
202 1.1 lukem struct berval *suffixdn = &be->be_nsuffix[0];
203 1.1 lukem const char *start, *end, *next, *p;
204 1.1 lukem char ch, *ptr;
205 1.1 lukem ber_len_t len;
206 1.1 lukem static const char hex[] = "0123456789ABCDEF";
207 1.1 lukem
208 1.1 lukem assert( dn != NULL );
209 1.1 lukem assert( !BER_BVISNULL( dn ) );
210 1.1 lukem assert( suffixdn != NULL );
211 1.1 lukem assert( !BER_BVISNULL( suffixdn ) );
212 1.1 lukem assert( dnIsSuffix( dn, suffixdn ) );
213 1.1 lukem
214 1.1.1.2 lukem if ( dn->bv_len == 0 && !empty_ok ) {
215 1.1.1.2 lukem return LDAP_UNWILLING_TO_PERFORM;
216 1.1.1.2 lukem }
217 1.1.1.2 lukem
218 1.1 lukem start = dn->bv_val;
219 1.1 lukem end = start + dn->bv_len;
220 1.1 lukem
221 1.1 lukem /* Room for dir, dirsep, dn, LDIF, "\hexpair"-escaping of unsafe chars */
222 1.1 lukem len = li->li_base_path.bv_len + dn->bv_len + (1 + STRLENOF( LDIF ));
223 1.1 lukem for ( p = start; p < end; ) {
224 1.1 lukem ch = *p++;
225 1.1 lukem if ( LDIF_NEED_ESCAPE( ch ) )
226 1.1 lukem len += 2;
227 1.1 lukem }
228 1.1 lukem res->bv_val = ch_malloc( len + 1 );
229 1.1 lukem
230 1.1 lukem ptr = lutil_strcopy( res->bv_val, li->li_base_path.bv_val );
231 1.1 lukem for ( next = end - suffixdn->bv_len; end > start; end = next ) {
232 1.1 lukem /* Set p = start of DN component, next = &',' or start of DN */
233 1.1 lukem while ( (p = next) > start ) {
234 1.1 lukem --next;
235 1.1 lukem if ( DN_SEPARATOR( *next ) )
236 1.1 lukem break;
237 1.1 lukem }
238 1.1 lukem /* Append <dirsep> <p..end-1: RDN or database-suffix> */
239 1.1 lukem for ( *ptr++ = LDAP_DIRSEP[0]; p < end; *ptr++ = ch ) {
240 1.1 lukem ch = *p++;
241 1.1 lukem if ( LDIF_ESCAPE_CHAR != '\\' && ch == '\\' ) {
242 1.1 lukem ch = LDIF_ESCAPE_CHAR;
243 1.1 lukem } else if ( IX_FSL != IX_DNL && ch == IX_DNL ) {
244 1.1 lukem ch = IX_FSL;
245 1.1 lukem } else if ( IX_FSR != IX_DNR && ch == IX_DNR ) {
246 1.1 lukem ch = IX_FSR;
247 1.1 lukem } else if ( LDIF_NEED_ESCAPE( ch ) ) {
248 1.1 lukem *ptr++ = LDIF_ESCAPE_CHAR;
249 1.1 lukem *ptr++ = hex[(ch & 0xFFU) >> 4];
250 1.1 lukem ch = hex[ch & 0x0FU];
251 1.1 lukem }
252 1.1 lukem }
253 1.1 lukem }
254 1.1 lukem ptr = lutil_strcopy( ptr, LDIF );
255 1.1 lukem res->bv_len = ptr - res->bv_val;
256 1.1 lukem
257 1.1 lukem assert( res->bv_len <= len );
258 1.1.1.2 lukem
259 1.1.1.2 lukem return LDAP_SUCCESS;
260 1.1 lukem }
261 1.1 lukem
262 1.1.1.2 lukem /*
263 1.1.1.2 lukem * *dest = dupbv(<dir + LDAP_DIRSEP>), plus room for <more>-sized filename.
264 1.1.1.2 lukem * Return pointer past the dirname.
265 1.1.1.2 lukem */
266 1.1.1.2 lukem static char *
267 1.1.1.2 lukem fullpath_alloc( struct berval *dest, const struct berval *dir, ber_len_t more )
268 1.1.1.2 lukem {
269 1.1.1.2 lukem char *s = SLAP_MALLOC( dir->bv_len + more + 2 );
270 1.1.1.2 lukem
271 1.1.1.2 lukem dest->bv_val = s;
272 1.1.1.2 lukem if ( s == NULL ) {
273 1.1.1.2 lukem dest->bv_len = 0;
274 1.1.1.9 christos Debug( LDAP_DEBUG_ANY, "back-ldif: out of memory\n" );
275 1.1.1.2 lukem } else {
276 1.1.1.2 lukem s = lutil_strcopy( dest->bv_val, dir->bv_val );
277 1.1.1.2 lukem *s++ = LDAP_DIRSEP[0];
278 1.1.1.2 lukem *s = '\0';
279 1.1.1.2 lukem dest->bv_len = s - dest->bv_val;
280 1.1.1.2 lukem }
281 1.1.1.2 lukem return s;
282 1.1.1.2 lukem }
283 1.1.1.2 lukem
284 1.1.1.2 lukem /*
285 1.1.1.2 lukem * Append filename to fullpath_alloc() dirname or replace previous filename.
286 1.1.1.2 lukem * dir_end = fullpath_alloc() return value.
287 1.1.1.2 lukem */
288 1.1.1.2 lukem #define FILL_PATH(fpath, dir_end, filename) \
289 1.1.1.2 lukem ((fpath)->bv_len = lutil_strcopy(dir_end, filename) - (fpath)->bv_val)
290 1.1.1.2 lukem
291 1.1.1.2 lukem
292 1.1.1.2 lukem /* .ldif entry filename length <-> subtree dirname length. */
293 1.1.1.2 lukem #define ldif2dir_len(bv) ((bv).bv_len -= STRLENOF(LDIF))
294 1.1.1.2 lukem #define dir2ldif_len(bv) ((bv).bv_len += STRLENOF(LDIF))
295 1.1.1.2 lukem /* .ldif entry filename <-> subtree dirname, both with dirname length. */
296 1.1.1.2 lukem #define ldif2dir_name(bv) ((bv).bv_val[(bv).bv_len] = '\0')
297 1.1.1.2 lukem #define dir2ldif_name(bv) ((bv).bv_val[(bv).bv_len] = LDIF_FILETYPE_SEP)
298 1.1.1.2 lukem
299 1.1.1.2 lukem /* Get the parent directory path, plus the LDIF suffix overwritten by a \0. */
300 1.1.1.2 lukem static int
301 1.1.1.2 lukem get_parent_path( struct berval *dnpath, struct berval *res )
302 1.1.1.2 lukem {
303 1.1.1.2 lukem ber_len_t i = dnpath->bv_len;
304 1.1.1.2 lukem
305 1.1.1.2 lukem while ( i > 0 && dnpath->bv_val[ --i ] != LDAP_DIRSEP[0] ) ;
306 1.1.1.2 lukem if ( res == NULL ) {
307 1.1.1.2 lukem res = dnpath;
308 1.1.1.2 lukem } else {
309 1.1.1.2 lukem res->bv_val = SLAP_MALLOC( i + 1 + STRLENOF(LDIF) );
310 1.1.1.2 lukem if ( res->bv_val == NULL )
311 1.1.1.2 lukem return LDAP_OTHER;
312 1.1.1.2 lukem AC_MEMCPY( res->bv_val, dnpath->bv_val, i );
313 1.1.1.2 lukem }
314 1.1.1.2 lukem res->bv_len = i;
315 1.1.1.2 lukem strcpy( res->bv_val + i, LDIF );
316 1.1.1.2 lukem res->bv_val[i] = '\0';
317 1.1.1.2 lukem return LDAP_SUCCESS;
318 1.1.1.2 lukem }
319 1.1.1.2 lukem
320 1.1.1.2 lukem /* Make temporary filename pattern for mkstemp() based on dnpath. */
321 1.1.1.2 lukem static char *
322 1.1.1.2 lukem ldif_tempname( const struct berval *dnpath )
323 1.1.1.2 lukem {
324 1.1.1.2 lukem static const char suffix[] = ".XXXXXX";
325 1.1.1.2 lukem ber_len_t len = dnpath->bv_len - STRLENOF( LDIF );
326 1.1.1.2 lukem char *name = SLAP_MALLOC( len + sizeof( suffix ) );
327 1.1.1.2 lukem
328 1.1.1.2 lukem if ( name != NULL ) {
329 1.1.1.2 lukem AC_MEMCPY( name, dnpath->bv_val, len );
330 1.1.1.2 lukem strcpy( name + len, suffix );
331 1.1.1.2 lukem }
332 1.1.1.2 lukem return name;
333 1.1.1.2 lukem }
334 1.1.1.2 lukem
335 1.1.1.4 tron /* CRC-32 table for the polynomial:
336 1.1.1.4 tron * x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
337 1.1.1.4 tron *
338 1.1.1.4 tron * As used by zlib
339 1.1.1.4 tron */
340 1.1.1.4 tron
341 1.1.1.4 tron static const ber_uint_t crctab[256] = {
342 1.1.1.4 tron 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
343 1.1.1.4 tron 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
344 1.1.1.4 tron 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
345 1.1.1.4 tron 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
346 1.1.1.4 tron 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
347 1.1.1.4 tron 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
348 1.1.1.4 tron 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
349 1.1.1.4 tron 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
350 1.1.1.4 tron 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
351 1.1.1.4 tron 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
352 1.1.1.4 tron 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
353 1.1.1.4 tron 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
354 1.1.1.4 tron 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
355 1.1.1.4 tron 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
356 1.1.1.4 tron 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
357 1.1.1.4 tron 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
358 1.1.1.4 tron 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
359 1.1.1.4 tron 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
360 1.1.1.4 tron 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
361 1.1.1.4 tron 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
362 1.1.1.4 tron 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
363 1.1.1.4 tron 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
364 1.1.1.4 tron 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
365 1.1.1.4 tron 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
366 1.1.1.4 tron 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
367 1.1.1.4 tron 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
368 1.1.1.4 tron 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
369 1.1.1.4 tron 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
370 1.1.1.4 tron 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
371 1.1.1.4 tron 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
372 1.1.1.4 tron 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
373 1.1.1.4 tron 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
374 1.1.1.4 tron 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
375 1.1.1.4 tron 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
376 1.1.1.4 tron 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
377 1.1.1.4 tron 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
378 1.1.1.4 tron 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
379 1.1.1.4 tron 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
380 1.1.1.4 tron 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
381 1.1.1.4 tron 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
382 1.1.1.4 tron 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
383 1.1.1.4 tron 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
384 1.1.1.4 tron 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
385 1.1.1.4 tron 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
386 1.1.1.4 tron 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
387 1.1.1.4 tron 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
388 1.1.1.4 tron 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
389 1.1.1.4 tron 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
390 1.1.1.4 tron 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
391 1.1.1.4 tron 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
392 1.1.1.4 tron 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
393 1.1.1.4 tron 0x2d02ef8dL
394 1.1.1.4 tron };
395 1.1.1.4 tron
396 1.1.1.4 tron #define CRC1 crc = crctab[(crc ^ *buf++) & 0xff] ^ (crc >> 8)
397 1.1.1.4 tron #define CRC8 CRC1; CRC1; CRC1; CRC1; CRC1; CRC1; CRC1; CRC1
398 1.1.1.4 tron unsigned int
399 1.1.1.4 tron crc32(const void *vbuf, int len)
400 1.1.1.4 tron {
401 1.1.1.4 tron const unsigned char *buf = vbuf;
402 1.1.1.4 tron ber_uint_t crc = 0xffffffff;
403 1.1.1.4 tron
404 1.1.1.4 tron while (len > 7) {
405 1.1.1.4 tron CRC8;
406 1.1.1.4 tron len -= 8;
407 1.1.1.4 tron }
408 1.1.1.4 tron while (len) {
409 1.1.1.4 tron CRC1;
410 1.1.1.4 tron len--;
411 1.1.1.4 tron }
412 1.1.1.4 tron
413 1.1.1.4 tron return crc ^ 0xffffffff;
414 1.1.1.4 tron }
415 1.1.1.4 tron
416 1.1.1.2 lukem /*
417 1.1.1.2 lukem * Read a file, or stat() it if datap == NULL. Allocate and fill *datap.
418 1.1.1.2 lukem * Return LDAP_SUCCESS, LDAP_NO_SUCH_OBJECT (no such file), or another error.
419 1.1.1.2 lukem */
420 1.1.1.2 lukem static int
421 1.1.1.2 lukem ldif_read_file( const char *path, char **datap )
422 1.1.1.2 lukem {
423 1.1.1.4 tron int rc = LDAP_SUCCESS, fd, len;
424 1.1.1.2 lukem int res = -1; /* 0:success, <0:error, >0:file too big/growing. */
425 1.1 lukem struct stat st;
426 1.1.1.4 tron char *data = NULL, *ptr = NULL;
427 1.1.1.4 tron const char *msg;
428 1.1 lukem
429 1.1.1.2 lukem if ( datap == NULL ) {
430 1.1.1.2 lukem res = stat( path, &st );
431 1.1.1.2 lukem goto done;
432 1.1.1.2 lukem }
433 1.1.1.2 lukem fd = open( path, O_RDONLY );
434 1.1.1.2 lukem if ( fd >= 0 ) {
435 1.1.1.2 lukem if ( fstat( fd, &st ) == 0 ) {
436 1.1.1.2 lukem if ( st.st_size > INT_MAX - 2 ) {
437 1.1.1.2 lukem res = 1;
438 1.1.1.2 lukem } else {
439 1.1.1.2 lukem len = st.st_size + 1; /* +1 detects file size > st.st_size */
440 1.1.1.2 lukem *datap = data = ptr = SLAP_MALLOC( len + 1 );
441 1.1.1.2 lukem if ( ptr != NULL ) {
442 1.1.1.2 lukem while ( len && (res = read( fd, ptr, len )) ) {
443 1.1.1.2 lukem if ( res > 0 ) {
444 1.1.1.2 lukem len -= res;
445 1.1.1.2 lukem ptr += res;
446 1.1.1.2 lukem } else if ( errno != EINTR ) {
447 1.1.1.2 lukem break;
448 1.1.1.2 lukem }
449 1.1.1.2 lukem }
450 1.1.1.2 lukem *ptr = '\0';
451 1.1.1.2 lukem }
452 1.1.1.2 lukem }
453 1.1 lukem }
454 1.1.1.2 lukem if ( close( fd ) < 0 )
455 1.1.1.2 lukem res = -1;
456 1.1.1.2 lukem }
457 1.1.1.2 lukem
458 1.1.1.2 lukem done:
459 1.1.1.2 lukem if ( res == 0 ) {
460 1.1.1.4 tron #ifdef LDAP_DEBUG
461 1.1.1.4 tron msg = "entry file exists";
462 1.1.1.4 tron if ( datap ) {
463 1.1.1.4 tron msg = "read entry file";
464 1.1.1.4 tron len = ptr - data;
465 1.1.1.4 tron ptr = strstr( data, "\n# CRC32" );
466 1.1.1.4 tron if (!ptr) {
467 1.1.1.4 tron msg = "read entry file without checksum";
468 1.1.1.4 tron } else {
469 1.1.1.4 tron unsigned int crc1 = 0, crc2 = 1;
470 1.1.1.4 tron if ( sscanf( ptr + 9, "%08x", &crc1) == 1) {
471 1.1.1.4 tron ptr = strchr(ptr+1, '\n');
472 1.1.1.4 tron if ( ptr ) {
473 1.1.1.4 tron ptr++;
474 1.1.1.4 tron len -= (ptr - data);
475 1.1.1.4 tron crc2 = crc32( ptr, len );
476 1.1.1.4 tron }
477 1.1.1.4 tron }
478 1.1.1.4 tron if ( crc1 != crc2 ) {
479 1.1.1.4 tron Debug( LDAP_DEBUG_ANY, "ldif_read_file: checksum error on \"%s\"\n",
480 1.1.1.9 christos path );
481 1.1.1.4 tron return rc;
482 1.1.1.4 tron }
483 1.1.1.4 tron }
484 1.1.1.4 tron }
485 1.1.1.9 christos Debug( LDAP_DEBUG_TRACE, "ldif_read_file: %s: \"%s\"\n", msg, path );
486 1.1.1.4 tron #endif /* LDAP_DEBUG */
487 1.1.1.2 lukem } else {
488 1.1.1.9 christos char ebuf[128];
489 1.1.1.2 lukem if ( res < 0 && errno == ENOENT ) {
490 1.1.1.2 lukem Debug( LDAP_DEBUG_TRACE, "ldif_read_file: "
491 1.1.1.9 christos "no entry file \"%s\"\n", path );
492 1.1.1.2 lukem rc = LDAP_NO_SUCH_OBJECT;
493 1.1.1.2 lukem } else {
494 1.1.1.9 christos msg = res < 0 ? AC_STRERROR_R( errno, ebuf, sizeof(ebuf) ) : "bad stat() size";
495 1.1.1.2 lukem Debug( LDAP_DEBUG_ANY, "ldif_read_file: %s for \"%s\"\n",
496 1.1.1.9 christos msg, path );
497 1.1.1.2 lukem rc = LDAP_OTHER;
498 1.1 lukem }
499 1.1.1.2 lukem if ( data != NULL )
500 1.1.1.2 lukem SLAP_FREE( data );
501 1.1 lukem }
502 1.1.1.2 lukem return rc;
503 1.1 lukem }
504 1.1 lukem
505 1.1 lukem /*
506 1.1 lukem * return nonnegative for success or -1 for error
507 1.1 lukem * do not return numbers less than -1
508 1.1 lukem */
509 1.1.1.2 lukem static int
510 1.1.1.2 lukem spew_file( int fd, const char *spew, int len, int *save_errno )
511 1.1.1.2 lukem {
512 1.1.1.4 tron int writeres;
513 1.1.1.4 tron #define HEADER "# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.\n"
514 1.1.1.4 tron char header[sizeof(HEADER "# CRC32 12345678\n")];
515 1.1.1.2 lukem
516 1.1.1.4 tron sprintf(header, HEADER "# CRC32 %08x\n", crc32(spew, len));
517 1.1.1.4 tron writeres = write_data(fd, header, sizeof(header)-1, save_errno);
518 1.1.1.4 tron return writeres < 0 ? writeres : write_data(fd, spew, len, save_errno);
519 1.1.1.4 tron }
520 1.1.1.4 tron
521 1.1.1.4 tron static int
522 1.1.1.4 tron write_data( int fd, const char *spew, int len, int *save_errno )
523 1.1.1.4 tron {
524 1.1.1.4 tron int writeres = 0;
525 1.1 lukem while(len > 0) {
526 1.1 lukem writeres = write(fd, spew, len);
527 1.1 lukem if(writeres == -1) {
528 1.1.1.2 lukem *save_errno = errno;
529 1.1.1.2 lukem if (*save_errno != EINTR)
530 1.1.1.2 lukem break;
531 1.1 lukem }
532 1.1 lukem else {
533 1.1 lukem spew += writeres;
534 1.1 lukem len -= writeres;
535 1.1 lukem }
536 1.1 lukem }
537 1.1 lukem return writeres;
538 1.1 lukem }
539 1.1 lukem
540 1.1.1.2 lukem /* Write an entry LDIF file. Create parentdir first if non-NULL. */
541 1.1 lukem static int
542 1.1.1.2 lukem ldif_write_entry(
543 1.1.1.2 lukem Operation *op,
544 1.1.1.2 lukem Entry *e,
545 1.1.1.2 lukem const struct berval *path,
546 1.1.1.2 lukem const char *parentdir,
547 1.1.1.2 lukem const char **text )
548 1.1 lukem {
549 1.1.1.2 lukem int rc = LDAP_OTHER, res, save_errno = 0;
550 1.1.1.2 lukem int fd, entry_length;
551 1.1.1.2 lukem char *entry_as_string, *tmpfname;
552 1.1.1.9 christos char ebuf[128];
553 1.1.1.2 lukem
554 1.1.1.2 lukem if ( op->o_abandon )
555 1.1.1.2 lukem return SLAPD_ABANDON;
556 1.1 lukem
557 1.1.1.2 lukem if ( parentdir != NULL && mkdir( parentdir, 0750 ) < 0 ) {
558 1.1 lukem save_errno = errno;
559 1.1.1.2 lukem Debug( LDAP_DEBUG_ANY, "ldif_write_entry: %s \"%s\": %s\n",
560 1.1.1.2 lukem "cannot create parent directory",
561 1.1.1.9 christos parentdir, AC_STRERROR_R( save_errno, ebuf, sizeof(ebuf) ) );
562 1.1.1.2 lukem *text = "internal error (cannot create parent directory)";
563 1.1.1.2 lukem return rc;
564 1.1.1.2 lukem }
565 1.1.1.2 lukem
566 1.1.1.2 lukem tmpfname = ldif_tempname( path );
567 1.1.1.2 lukem fd = tmpfname == NULL ? -1 : mkstemp( tmpfname );
568 1.1.1.2 lukem if ( fd < 0 ) {
569 1.1.1.2 lukem save_errno = errno;
570 1.1.1.2 lukem Debug( LDAP_DEBUG_ANY, "ldif_write_entry: %s for \"%s\": %s\n",
571 1.1.1.9 christos "cannot create file", e->e_dn, AC_STRERROR_R( save_errno, ebuf, sizeof(ebuf) ) );
572 1.1.1.2 lukem *text = "internal error (cannot create file)";
573 1.1 lukem
574 1.1 lukem } else {
575 1.1.1.2 lukem ber_len_t dn_len = e->e_name.bv_len;
576 1.1 lukem struct berval rdn;
577 1.1 lukem
578 1.1 lukem /* Only save the RDN onto disk */
579 1.1 lukem dnRdn( &e->e_name, &rdn );
580 1.1.1.2 lukem if ( rdn.bv_len != dn_len ) {
581 1.1 lukem e->e_name.bv_val[rdn.bv_len] = '\0';
582 1.1 lukem e->e_name.bv_len = rdn.bv_len;
583 1.1 lukem }
584 1.1 lukem
585 1.1.1.2 lukem res = -2;
586 1.1.1.2 lukem ldap_pvt_thread_mutex_lock( &entry2str_mutex );
587 1.1.1.2 lukem entry_as_string = entry2str( e, &entry_length );
588 1.1.1.2 lukem if ( entry_as_string != NULL )
589 1.1.1.2 lukem res = spew_file( fd, entry_as_string, entry_length, &save_errno );
590 1.1.1.2 lukem ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
591 1.1 lukem
592 1.1 lukem /* Restore full DN */
593 1.1.1.2 lukem if ( rdn.bv_len != dn_len ) {
594 1.1.1.2 lukem e->e_name.bv_val[rdn.bv_len] = ',';
595 1.1.1.2 lukem e->e_name.bv_len = dn_len;
596 1.1 lukem }
597 1.1 lukem
598 1.1.1.2 lukem if ( close( fd ) < 0 && res >= 0 ) {
599 1.1.1.2 lukem res = -1;
600 1.1.1.2 lukem save_errno = errno;
601 1.1.1.2 lukem }
602 1.1 lukem
603 1.1.1.2 lukem if ( res >= 0 ) {
604 1.1.1.2 lukem if ( move_file( tmpfname, path->bv_val ) == 0 ) {
605 1.1.1.2 lukem Debug( LDAP_DEBUG_TRACE, "ldif_write_entry: "
606 1.1.1.9 christos "wrote entry \"%s\"\n", e->e_name.bv_val );
607 1.1.1.2 lukem rc = LDAP_SUCCESS;
608 1.1 lukem } else {
609 1.1.1.2 lukem save_errno = errno;
610 1.1.1.2 lukem Debug( LDAP_DEBUG_ANY, "ldif_write_entry: "
611 1.1.1.2 lukem "could not put entry file for \"%s\" in place: %s\n",
612 1.1.1.9 christos e->e_name.bv_val, AC_STRERROR_R( save_errno, ebuf, sizeof(ebuf) ) );
613 1.1.1.2 lukem *text = "internal error (could not put entry file in place)";
614 1.1.1.2 lukem }
615 1.1.1.2 lukem } else if ( res == -1 ) {
616 1.1.1.2 lukem Debug( LDAP_DEBUG_ANY, "ldif_write_entry: %s \"%s\": %s\n",
617 1.1.1.9 christos "write error to", tmpfname, AC_STRERROR_R( save_errno, ebuf, sizeof(ebuf) ) );
618 1.1.1.2 lukem *text = "internal error (write error to entry file)";
619 1.1 lukem }
620 1.1 lukem
621 1.1.1.2 lukem if ( rc != LDAP_SUCCESS ) {
622 1.1 lukem unlink( tmpfname );
623 1.1 lukem }
624 1.1 lukem }
625 1.1 lukem
626 1.1.1.2 lukem if ( tmpfname )
627 1.1.1.2 lukem SLAP_FREE( tmpfname );
628 1.1.1.2 lukem return rc;
629 1.1 lukem }
630 1.1 lukem
631 1.1.1.2 lukem /*
632 1.1.1.2 lukem * Read the entry at path, or if entryp==NULL just see if it exists.
633 1.1.1.2 lukem * pdn and pndn are the parent's DN and normalized DN, or both NULL.
634 1.1.1.2 lukem * Return an LDAP result code.
635 1.1.1.2 lukem */
636 1.1.1.2 lukem static int
637 1.1.1.2 lukem ldif_read_entry(
638 1.1.1.2 lukem Operation *op,
639 1.1.1.2 lukem const char *path,
640 1.1 lukem struct berval *pdn,
641 1.1.1.2 lukem struct berval *pndn,
642 1.1.1.2 lukem Entry **entryp,
643 1.1.1.2 lukem const char **text )
644 1.1 lukem {
645 1.1.1.2 lukem int rc;
646 1.1.1.2 lukem Entry *entry;
647 1.1.1.2 lukem char *entry_as_string;
648 1.1.1.2 lukem struct berval rdn;
649 1.1 lukem
650 1.1.1.2 lukem /* TODO: Does slapd prevent Abandon of Bind as per rfc4511?
651 1.1.1.2 lukem * If so we need not check for LDAP_REQ_BIND here.
652 1.1.1.2 lukem */
653 1.1.1.2 lukem if ( op->o_abandon && op->o_tag != LDAP_REQ_BIND )
654 1.1.1.2 lukem return SLAPD_ABANDON;
655 1.1.1.2 lukem
656 1.1.1.2 lukem rc = ldif_read_file( path, entryp ? &entry_as_string : NULL );
657 1.1.1.2 lukem
658 1.1.1.2 lukem switch ( rc ) {
659 1.1.1.2 lukem case LDAP_SUCCESS:
660 1.1.1.2 lukem if ( entryp == NULL )
661 1.1.1.2 lukem break;
662 1.1.1.2 lukem *entryp = entry = str2entry( entry_as_string );
663 1.1.1.2 lukem SLAP_FREE( entry_as_string );
664 1.1.1.2 lukem if ( entry == NULL ) {
665 1.1.1.2 lukem rc = LDAP_OTHER;
666 1.1.1.2 lukem if ( text != NULL )
667 1.1.1.2 lukem *text = "internal error (cannot parse some entry file)";
668 1.1.1.2 lukem break;
669 1.1 lukem }
670 1.1.1.2 lukem if ( pdn == NULL || BER_BVISEMPTY( pdn ) )
671 1.1.1.2 lukem break;
672 1.1.1.2 lukem /* Append parent DN to DN from LDIF file */
673 1.1.1.2 lukem rdn = entry->e_name;
674 1.1.1.2 lukem build_new_dn( &entry->e_name, pdn, &rdn, NULL );
675 1.1.1.2 lukem SLAP_FREE( rdn.bv_val );
676 1.1.1.2 lukem rdn = entry->e_nname;
677 1.1.1.2 lukem build_new_dn( &entry->e_nname, pndn, &rdn, NULL );
678 1.1.1.2 lukem SLAP_FREE( rdn.bv_val );
679 1.1.1.2 lukem break;
680 1.1.1.2 lukem
681 1.1.1.2 lukem case LDAP_OTHER:
682 1.1.1.2 lukem if ( text != NULL )
683 1.1.1.2 lukem *text = entryp
684 1.1.1.2 lukem ? "internal error (cannot read some entry file)"
685 1.1.1.2 lukem : "internal error (cannot stat some entry file)";
686 1.1.1.2 lukem break;
687 1.1 lukem }
688 1.1.1.2 lukem
689 1.1.1.2 lukem return rc;
690 1.1 lukem }
691 1.1 lukem
692 1.1.1.2 lukem /*
693 1.1.1.2 lukem * Read the operation's entry, or if entryp==NULL just see if it exists.
694 1.1.1.2 lukem * Return an LDAP result code. May set *text to a message on failure.
695 1.1.1.2 lukem * If pathp is non-NULL, set it to the entry filename on success.
696 1.1.1.2 lukem */
697 1.1 lukem static int
698 1.1 lukem get_entry(
699 1.1 lukem Operation *op,
700 1.1 lukem Entry **entryp,
701 1.1.1.2 lukem struct berval *pathp,
702 1.1.1.2 lukem const char **text )
703 1.1 lukem {
704 1.1 lukem int rc;
705 1.1 lukem struct berval path, pdn, pndn;
706 1.1 lukem
707 1.1.1.2 lukem dnParent( &op->o_req_dn, &pdn );
708 1.1.1.2 lukem dnParent( &op->o_req_ndn, &pndn );
709 1.1.1.2 lukem rc = ndn2path( op, &op->o_req_ndn, &path, 0 );
710 1.1.1.2 lukem if ( rc != LDAP_SUCCESS ) {
711 1.1.1.2 lukem goto done;
712 1.1 lukem }
713 1.1.1.2 lukem
714 1.1.1.2 lukem rc = ldif_read_entry( op, path.bv_val, &pdn, &pndn, entryp, text );
715 1.1 lukem
716 1.1 lukem if ( rc == LDAP_SUCCESS && pathp != NULL ) {
717 1.1 lukem *pathp = path;
718 1.1 lukem } else {
719 1.1.1.2 lukem SLAP_FREE( path.bv_val );
720 1.1 lukem }
721 1.1.1.2 lukem done:
722 1.1 lukem return rc;
723 1.1 lukem }
724 1.1 lukem
725 1.1 lukem
726 1.1.1.2 lukem /*
727 1.1.1.2 lukem * RDN-named directory entry, with special handling of "attr={num}val" RDNs.
728 1.1.1.2 lukem * For sorting, filename "attr=val.ldif" is truncated to "attr="val\0ldif",
729 1.1.1.2 lukem * and filename "attr={num}val.ldif" to "attr={\0um}val.ldif".
730 1.1.1.2 lukem * Does not sort escaped chars correctly, would need to un-escape them.
731 1.1.1.2 lukem */
732 1.1 lukem typedef struct bvlist {
733 1.1 lukem struct bvlist *next;
734 1.1.1.2 lukem char *trunc; /* filename was truncated here */
735 1.1.1.2 lukem int inum; /* num from "attr={num}" in filename, or INT_MIN */
736 1.1.1.2 lukem char savech; /* original char at *trunc */
737 1.1.1.2 lukem /* BVL_NAME(&bvlist) is the filename, allocated after the struct: */
738 1.1.1.2 lukem # define BVL_NAME(bvl) ((char *) ((bvl) + 1))
739 1.1.1.2 lukem # define BVL_SIZE(namelen) (sizeof(bvlist) + (namelen) + 1)
740 1.1 lukem } bvlist;
741 1.1 lukem
742 1.1.1.2 lukem static int
743 1.1.1.2 lukem ldif_send_entry( Operation *op, SlapReply *rs, Entry *e, int scope )
744 1.1 lukem {
745 1.1.1.2 lukem int rc = LDAP_SUCCESS;
746 1.1 lukem
747 1.1.1.2 lukem if ( scope == LDAP_SCOPE_BASE || scope == LDAP_SCOPE_SUBTREE ) {
748 1.1.1.2 lukem if ( rs == NULL ) {
749 1.1.1.2 lukem /* Save the entry for tool mode */
750 1.1.1.2 lukem struct ldif_tool *tl =
751 1.1.1.2 lukem &((struct ldif_info *) op->o_bd->be_private)->li_tool;
752 1.1.1.2 lukem
753 1.1.1.2 lukem if ( tl->ecount >= tl->elen ) {
754 1.1.1.2 lukem /* Allocate/grow entries */
755 1.1.1.2 lukem ID elen = tl->elen ? tl->elen * 2 : ENTRY_BUFF_INCREMENT;
756 1.1.1.2 lukem Entry **entries = (Entry **) SLAP_REALLOC( tl->entries,
757 1.1.1.2 lukem sizeof(Entry *) * elen );
758 1.1.1.2 lukem if ( entries == NULL ) {
759 1.1.1.2 lukem Debug( LDAP_DEBUG_ANY,
760 1.1.1.9 christos "ldif_send_entry: out of memory\n" );
761 1.1.1.2 lukem rc = LDAP_OTHER;
762 1.1.1.2 lukem goto done;
763 1.1.1.2 lukem }
764 1.1.1.2 lukem tl->elen = elen;
765 1.1.1.2 lukem tl->entries = entries;
766 1.1.1.2 lukem }
767 1.1.1.2 lukem tl->entries[tl->ecount++] = e;
768 1.1.1.9 christos e->e_id = tl->ecount;
769 1.1.1.2 lukem return rc;
770 1.1 lukem }
771 1.1 lukem
772 1.1.1.2 lukem else if ( !get_manageDSAit( op ) && is_entry_referral( e ) ) {
773 1.1.1.2 lukem /* Send a continuation reference.
774 1.1.1.2 lukem * (ldif_back_referrals() handles baseobject referrals.)
775 1.1.1.2 lukem * Don't check the filter since it's only a candidate.
776 1.1.1.2 lukem */
777 1.1.1.2 lukem BerVarray refs = get_entry_referrals( op, e );
778 1.1.1.2 lukem rs->sr_ref = referral_rewrite( refs, &e->e_name, NULL, scope );
779 1.1.1.2 lukem rs->sr_entry = e;
780 1.1.1.2 lukem rc = send_search_reference( op, rs );
781 1.1.1.2 lukem ber_bvarray_free( rs->sr_ref );
782 1.1.1.2 lukem ber_bvarray_free( refs );
783 1.1.1.2 lukem rs->sr_ref = NULL;
784 1.1.1.2 lukem rs->sr_entry = NULL;
785 1.1 lukem }
786 1.1 lukem
787 1.1.1.2 lukem else if ( test_filter( op, e, op->ors_filter ) == LDAP_COMPARE_TRUE ) {
788 1.1.1.2 lukem rs->sr_entry = e;
789 1.1.1.2 lukem rs->sr_attrs = op->ors_attrs;
790 1.1.1.4 tron /* Could set REP_ENTRY_MUSTBEFREED too for efficiency,
791 1.1.1.4 tron * but refraining lets us test unFREEable MODIFIABLE
792 1.1.1.4 tron * entries. Like entries built on the stack.
793 1.1.1.4 tron */
794 1.1.1.2 lukem rs->sr_flags = REP_ENTRY_MODIFIABLE;
795 1.1.1.2 lukem rc = send_search_entry( op, rs );
796 1.1.1.2 lukem rs->sr_entry = NULL;
797 1.1.1.4 tron rs->sr_attrs = NULL;
798 1.1 lukem }
799 1.1 lukem }
800 1.1 lukem
801 1.1.1.2 lukem done:
802 1.1.1.2 lukem entry_free( e );
803 1.1.1.2 lukem return rc;
804 1.1.1.2 lukem }
805 1.1 lukem
806 1.1.1.2 lukem /* Read LDIF directory <path> into <listp>. Set *fname_maxlenp. */
807 1.1.1.2 lukem static int
808 1.1.1.2 lukem ldif_readdir(
809 1.1.1.2 lukem Operation *op,
810 1.1.1.2 lukem SlapReply *rs,
811 1.1.1.2 lukem const struct berval *path,
812 1.1.1.2 lukem bvlist **listp,
813 1.1.1.2 lukem ber_len_t *fname_maxlenp )
814 1.1.1.2 lukem {
815 1.1.1.2 lukem int rc = LDAP_SUCCESS;
816 1.1.1.2 lukem DIR *dir_of_path;
817 1.1.1.9 christos char ebuf[128];
818 1.1 lukem
819 1.1.1.2 lukem *listp = NULL;
820 1.1.1.2 lukem *fname_maxlenp = 0;
821 1.1.1.2 lukem
822 1.1.1.2 lukem dir_of_path = opendir( path->bv_val );
823 1.1.1.2 lukem if ( dir_of_path == NULL ) {
824 1.1.1.2 lukem int save_errno = errno;
825 1.1.1.2 lukem struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
826 1.1.1.2 lukem int is_rootDSE = (path->bv_len == li->li_base_path.bv_len);
827 1.1.1.2 lukem
828 1.1.1.2 lukem /* Absent directory is OK (leaf entry), except the database dir */
829 1.1.1.2 lukem if ( is_rootDSE || save_errno != ENOENT ) {
830 1.1.1.2 lukem Debug( LDAP_DEBUG_ANY,
831 1.1.1.2 lukem "=> ldif_search_entry: failed to opendir \"%s\": %s\n",
832 1.1.1.9 christos path->bv_val, AC_STRERROR_R( save_errno, ebuf, sizeof(ebuf) ) );
833 1.1.1.2 lukem rc = LDAP_OTHER;
834 1.1.1.2 lukem if ( rs != NULL )
835 1.1.1.2 lukem rs->sr_text =
836 1.1.1.2 lukem save_errno != ENOENT ? "internal error (bad directory)"
837 1.1.1.2 lukem : "internal error (database directory does not exist)";
838 1.1 lukem }
839 1.1.1.2 lukem
840 1.1.1.2 lukem } else {
841 1.1.1.2 lukem bvlist *ptr;
842 1.1.1.2 lukem struct dirent *dir;
843 1.1.1.2 lukem int save_errno = 0;
844 1.1.1.2 lukem
845 1.1.1.2 lukem while ( (dir = readdir( dir_of_path )) != NULL ) {
846 1.1.1.2 lukem size_t fname_len;
847 1.1 lukem bvlist *bvl, **prev;
848 1.1.1.2 lukem char *trunc, *idxp, *endp, *endp2;
849 1.1 lukem
850 1.1.1.2 lukem fname_len = strlen( dir->d_name );
851 1.1.1.2 lukem if ( fname_len < STRLENOF( "x=" LDIF )) /* min filename size */
852 1.1 lukem continue;
853 1.1.1.2 lukem if ( strcmp( dir->d_name + fname_len - STRLENOF(LDIF), LDIF ))
854 1.1 lukem continue;
855 1.1 lukem
856 1.1.1.2 lukem if ( *fname_maxlenp < fname_len )
857 1.1.1.2 lukem *fname_maxlenp = fname_len;
858 1.1.1.2 lukem
859 1.1.1.2 lukem bvl = SLAP_MALLOC( BVL_SIZE( fname_len ) );
860 1.1.1.2 lukem if ( bvl == NULL ) {
861 1.1.1.2 lukem rc = LDAP_OTHER;
862 1.1.1.2 lukem save_errno = errno;
863 1.1.1.2 lukem break;
864 1.1 lukem }
865 1.1.1.2 lukem strcpy( BVL_NAME( bvl ), dir->d_name );
866 1.1 lukem
867 1.1.1.2 lukem /* Make it sortable by ("attr=val" or <preceding {num}, num>) */
868 1.1.1.2 lukem trunc = BVL_NAME( bvl ) + fname_len - STRLENOF( LDIF );
869 1.1.1.2 lukem if ( (idxp = strchr( BVL_NAME( bvl ) + 2, IX_FSL )) != NULL &&
870 1.1.1.2 lukem (endp = strchr( ++idxp, IX_FSR )) != NULL && endp > idxp &&
871 1.1.1.2 lukem (eq_unsafe || idxp[-2] == '=' || endp + 1 == trunc) )
872 1.1.1.2 lukem {
873 1.1.1.2 lukem /* attr={n}val or bconfig.c's "pseudo-indexed" attr=val{n} */
874 1.1.1.2 lukem bvl->inum = strtol( idxp, &endp2, 10 );
875 1.1.1.2 lukem if ( endp2 == endp ) {
876 1.1.1.2 lukem trunc = idxp;
877 1.1.1.2 lukem goto truncate;
878 1.1.1.2 lukem }
879 1.1.1.2 lukem }
880 1.1.1.2 lukem bvl->inum = INT_MIN;
881 1.1.1.2 lukem truncate:
882 1.1.1.2 lukem bvl->trunc = trunc;
883 1.1.1.2 lukem bvl->savech = *trunc;
884 1.1.1.2 lukem *trunc = '\0';
885 1.1.1.2 lukem
886 1.1.1.2 lukem /* Insertion sort */
887 1.1.1.2 lukem for ( prev = listp; (ptr = *prev) != NULL; prev = &ptr->next ) {
888 1.1.1.2 lukem int cmp = strcmp( BVL_NAME( bvl ), BVL_NAME( ptr ));
889 1.1.1.2 lukem if ( cmp < 0 || (cmp == 0 && bvl->inum < ptr->inum) )
890 1.1 lukem break;
891 1.1 lukem }
892 1.1 lukem *prev = bvl;
893 1.1 lukem bvl->next = ptr;
894 1.1 lukem }
895 1.1 lukem
896 1.1.1.2 lukem if ( closedir( dir_of_path ) < 0 ) {
897 1.1.1.2 lukem save_errno = errno;
898 1.1.1.2 lukem rc = LDAP_OTHER;
899 1.1.1.2 lukem if ( rs != NULL )
900 1.1.1.2 lukem rs->sr_text = "internal error (bad directory)";
901 1.1.1.2 lukem }
902 1.1.1.2 lukem if ( rc != LDAP_SUCCESS ) {
903 1.1.1.2 lukem Debug( LDAP_DEBUG_ANY, "ldif_search_entry: %s \"%s\": %s\n",
904 1.1.1.2 lukem "error reading directory", path->bv_val,
905 1.1.1.9 christos AC_STRERROR_R( save_errno, ebuf, sizeof(ebuf) ) );
906 1.1 lukem }
907 1.1 lukem }
908 1.1.1.2 lukem
909 1.1 lukem return rc;
910 1.1 lukem }
911 1.1 lukem
912 1.1.1.2 lukem /*
913 1.1.1.2 lukem * Send an entry, recursively search its children, and free or save it.
914 1.1.1.2 lukem * Return an LDAP result code. Parameters:
915 1.1.1.2 lukem * op, rs operation and reply. rs == NULL for slap tools.
916 1.1.1.2 lukem * e entry to search, or NULL for rootDSE.
917 1.1.1.2 lukem * scope scope for the part of the search from this entry.
918 1.1.1.2 lukem * path LDIF filename -- bv_len and non-directory part are overwritten.
919 1.1.1.2 lukem */
920 1.1 lukem static int
921 1.1.1.2 lukem ldif_search_entry(
922 1.1.1.2 lukem Operation *op,
923 1.1.1.2 lukem SlapReply *rs,
924 1.1.1.2 lukem Entry *e,
925 1.1.1.2 lukem int scope,
926 1.1.1.2 lukem struct berval *path )
927 1.1 lukem {
928 1.1.1.2 lukem int rc = LDAP_SUCCESS;
929 1.1.1.2 lukem struct berval dn = BER_BVC( "" ), ndn = BER_BVC( "" );
930 1.1.1.2 lukem
931 1.1.1.2 lukem if ( scope != LDAP_SCOPE_BASE && e != NULL ) {
932 1.1.1.2 lukem /* Copy DN/NDN since we send the entry with REP_ENTRY_MODIFIABLE,
933 1.1.1.2 lukem * which bconfig.c seems to need. (TODO: see config_rename_one.)
934 1.1.1.2 lukem */
935 1.1.1.2 lukem if ( ber_dupbv( &dn, &e->e_name ) == NULL ||
936 1.1.1.2 lukem ber_dupbv( &ndn, &e->e_nname ) == NULL )
937 1.1.1.2 lukem {
938 1.1.1.2 lukem Debug( LDAP_DEBUG_ANY,
939 1.1.1.9 christos "ldif_search_entry: out of memory\n" );
940 1.1.1.2 lukem rc = LDAP_OTHER;
941 1.1.1.2 lukem goto done;
942 1.1.1.2 lukem }
943 1.1.1.2 lukem }
944 1.1.1.2 lukem
945 1.1.1.2 lukem /* Send the entry if appropriate, and free or save it */
946 1.1.1.2 lukem if ( e != NULL )
947 1.1.1.2 lukem rc = ldif_send_entry( op, rs, e, scope );
948 1.1.1.2 lukem
949 1.1.1.2 lukem /* Search the children */
950 1.1.1.2 lukem if ( scope != LDAP_SCOPE_BASE && rc == LDAP_SUCCESS ) {
951 1.1.1.2 lukem bvlist *list, *ptr;
952 1.1.1.2 lukem struct berval fpath; /* becomes child pathname */
953 1.1.1.2 lukem char *dir_end; /* will point past dirname in fpath */
954 1.1.1.2 lukem
955 1.1.1.2 lukem ldif2dir_len( *path );
956 1.1.1.2 lukem ldif2dir_name( *path );
957 1.1.1.2 lukem rc = ldif_readdir( op, rs, path, &list, &fpath.bv_len );
958 1.1.1.2 lukem
959 1.1.1.2 lukem if ( list != NULL ) {
960 1.1.1.2 lukem const char **text = rs == NULL ? NULL : &rs->sr_text;
961 1.1.1.2 lukem
962 1.1.1.2 lukem if ( scope == LDAP_SCOPE_ONELEVEL )
963 1.1.1.2 lukem scope = LDAP_SCOPE_BASE;
964 1.1.1.2 lukem else if ( scope == LDAP_SCOPE_SUBORDINATE )
965 1.1.1.2 lukem scope = LDAP_SCOPE_SUBTREE;
966 1.1.1.2 lukem
967 1.1.1.2 lukem /* Allocate fpath and fill in directory part */
968 1.1.1.2 lukem dir_end = fullpath_alloc( &fpath, path, fpath.bv_len );
969 1.1.1.2 lukem if ( dir_end == NULL )
970 1.1.1.2 lukem rc = LDAP_OTHER;
971 1.1.1.2 lukem
972 1.1.1.2 lukem do {
973 1.1.1.2 lukem ptr = list;
974 1.1.1.2 lukem
975 1.1.1.2 lukem if ( rc == LDAP_SUCCESS ) {
976 1.1.1.2 lukem *ptr->trunc = ptr->savech;
977 1.1.1.2 lukem FILL_PATH( &fpath, dir_end, BVL_NAME( ptr ));
978 1.1.1.2 lukem
979 1.1.1.2 lukem rc = ldif_read_entry( op, fpath.bv_val, &dn, &ndn,
980 1.1.1.2 lukem &e, text );
981 1.1.1.2 lukem switch ( rc ) {
982 1.1.1.2 lukem case LDAP_SUCCESS:
983 1.1.1.2 lukem rc = ldif_search_entry( op, rs, e, scope, &fpath );
984 1.1.1.2 lukem break;
985 1.1.1.2 lukem case LDAP_NO_SUCH_OBJECT:
986 1.1.1.2 lukem /* Only the search baseDN may produce noSuchObject. */
987 1.1.1.2 lukem rc = LDAP_OTHER;
988 1.1.1.2 lukem if ( rs != NULL )
989 1.1.1.2 lukem rs->sr_text = "internal error "
990 1.1.1.2 lukem "(did someone just remove an entry file?)";
991 1.1.1.2 lukem Debug( LDAP_DEBUG_ANY, "ldif_search_entry: "
992 1.1.1.2 lukem "file listed in parent directory does not exist: "
993 1.1.1.9 christos "\"%s\"\n", fpath.bv_val );
994 1.1.1.2 lukem break;
995 1.1.1.2 lukem }
996 1.1.1.2 lukem }
997 1.1.1.2 lukem
998 1.1.1.2 lukem list = ptr->next;
999 1.1.1.2 lukem SLAP_FREE( ptr );
1000 1.1.1.2 lukem } while ( list != NULL );
1001 1.1.1.2 lukem
1002 1.1.1.2 lukem if ( !BER_BVISNULL( &fpath ) )
1003 1.1.1.2 lukem SLAP_FREE( fpath.bv_val );
1004 1.1.1.2 lukem }
1005 1.1.1.2 lukem }
1006 1.1.1.2 lukem
1007 1.1.1.2 lukem done:
1008 1.1.1.2 lukem if ( !BER_BVISEMPTY( &dn ) )
1009 1.1.1.2 lukem ber_memfree( dn.bv_val );
1010 1.1.1.2 lukem if ( !BER_BVISEMPTY( &ndn ) )
1011 1.1.1.2 lukem ber_memfree( ndn.bv_val );
1012 1.1.1.2 lukem return rc;
1013 1.1.1.2 lukem }
1014 1.1.1.2 lukem
1015 1.1.1.2 lukem static int
1016 1.1.1.2 lukem search_tree( Operation *op, SlapReply *rs )
1017 1.1.1.2 lukem {
1018 1.1.1.2 lukem int rc = LDAP_SUCCESS;
1019 1.1.1.2 lukem Entry *e = NULL;
1020 1.1 lukem struct berval path;
1021 1.1 lukem struct berval pdn, pndn;
1022 1.1 lukem
1023 1.1.1.2 lukem (void) ndn2path( op, &op->o_req_ndn, &path, 1 );
1024 1.1.1.2 lukem if ( !BER_BVISEMPTY( &op->o_req_ndn ) ) {
1025 1.1.1.2 lukem /* Read baseObject */
1026 1.1.1.2 lukem dnParent( &op->o_req_dn, &pdn );
1027 1.1.1.2 lukem dnParent( &op->o_req_ndn, &pndn );
1028 1.1.1.2 lukem rc = ldif_read_entry( op, path.bv_val, &pdn, &pndn, &e,
1029 1.1.1.2 lukem rs == NULL ? NULL : &rs->sr_text );
1030 1.1.1.2 lukem }
1031 1.1.1.2 lukem if ( rc == LDAP_SUCCESS )
1032 1.1.1.2 lukem rc = ldif_search_entry( op, rs, e, op->ors_scope, &path );
1033 1.1.1.2 lukem
1034 1.1 lukem ch_free( path.bv_val );
1035 1.1 lukem return rc;
1036 1.1 lukem }
1037 1.1 lukem
1038 1.1 lukem
1039 1.1.1.2 lukem /*
1040 1.1.1.2 lukem * Prepare to create or rename an entry:
1041 1.1.1.2 lukem * Check that the entry does not already exist.
1042 1.1.1.2 lukem * Check that the parent entry exists and can have subordinates,
1043 1.1.1.2 lukem * unless need_dir is NULL or adding the suffix entry.
1044 1.1.1.2 lukem *
1045 1.1.1.2 lukem * Return an LDAP result code. May set *text to a message on failure.
1046 1.1.1.2 lukem * If success, set *dnpath to LDIF entry path and *need_dir to
1047 1.1.1.2 lukem * (directory must be created ? dirname : NULL).
1048 1.1.1.2 lukem */
1049 1.1.1.2 lukem static int
1050 1.1.1.2 lukem ldif_prepare_create(
1051 1.1.1.2 lukem Operation *op,
1052 1.1.1.2 lukem Entry *e,
1053 1.1.1.2 lukem struct berval *dnpath,
1054 1.1.1.2 lukem char **need_dir,
1055 1.1.1.2 lukem const char **text )
1056 1.1 lukem {
1057 1.1.1.2 lukem struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
1058 1.1.1.2 lukem struct berval *ndn = &e->e_nname;
1059 1.1.1.2 lukem struct berval ppath = BER_BVNULL;
1060 1.1.1.2 lukem struct stat st;
1061 1.1.1.2 lukem Entry *parent = NULL;
1062 1.1.1.2 lukem int rc;
1063 1.1.1.9 christos char ebuf[128];
1064 1.1.1.2 lukem
1065 1.1.1.2 lukem if ( op->o_abandon )
1066 1.1.1.2 lukem return SLAPD_ABANDON;
1067 1.1.1.2 lukem
1068 1.1.1.2 lukem rc = ndn2path( op, ndn, dnpath, 0 );
1069 1.1.1.2 lukem if ( rc != LDAP_SUCCESS ) {
1070 1.1.1.2 lukem return rc;
1071 1.1.1.2 lukem }
1072 1.1.1.2 lukem
1073 1.1.1.2 lukem if ( stat( dnpath->bv_val, &st ) == 0 ) { /* entry .ldif file */
1074 1.1.1.2 lukem rc = LDAP_ALREADY_EXISTS;
1075 1.1.1.2 lukem
1076 1.1.1.2 lukem } else if ( errno != ENOENT ) {
1077 1.1.1.2 lukem Debug( LDAP_DEBUG_ANY,
1078 1.1.1.2 lukem "ldif_prepare_create: cannot stat \"%s\": %s\n",
1079 1.1.1.9 christos dnpath->bv_val, AC_STRERROR_R( errno, ebuf, sizeof(ebuf) ) );
1080 1.1.1.2 lukem rc = LDAP_OTHER;
1081 1.1.1.2 lukem *text = "internal error (cannot check entry file)";
1082 1.1.1.2 lukem
1083 1.1.1.2 lukem } else if ( need_dir != NULL ) {
1084 1.1.1.2 lukem *need_dir = NULL;
1085 1.1.1.2 lukem rc = get_parent_path( dnpath, &ppath );
1086 1.1.1.2 lukem /* If parent dir exists, so does parent .ldif:
1087 1.1.1.2 lukem * The directory gets created after and removed before the .ldif.
1088 1.1.1.2 lukem * Except with the database directory, which has no matching entry.
1089 1.1.1.2 lukem */
1090 1.1.1.2 lukem if ( rc == LDAP_SUCCESS && stat( ppath.bv_val, &st ) < 0 ) {
1091 1.1.1.2 lukem rc = errno == ENOENT && ppath.bv_len > li->li_base_path.bv_len
1092 1.1.1.2 lukem ? LDAP_NO_SUCH_OBJECT : LDAP_OTHER;
1093 1.1.1.2 lukem }
1094 1.1.1.2 lukem switch ( rc ) {
1095 1.1.1.2 lukem case LDAP_NO_SUCH_OBJECT:
1096 1.1.1.2 lukem /* No parent dir, check parent .ldif */
1097 1.1.1.2 lukem dir2ldif_name( ppath );
1098 1.1.1.2 lukem rc = ldif_read_entry( op, ppath.bv_val, NULL, NULL,
1099 1.1.1.2 lukem (op->o_tag != LDAP_REQ_ADD || get_manageDSAit( op )
1100 1.1.1.2 lukem ? &parent : NULL),
1101 1.1.1.2 lukem text );
1102 1.1.1.2 lukem switch ( rc ) {
1103 1.1.1.2 lukem case LDAP_SUCCESS:
1104 1.1.1.2 lukem /* Check that parent is not a referral, unless
1105 1.1.1.2 lukem * ldif_back_referrals() already checked.
1106 1.1.1.2 lukem */
1107 1.1.1.2 lukem if ( parent != NULL ) {
1108 1.1.1.2 lukem int is_ref = is_entry_referral( parent );
1109 1.1.1.2 lukem entry_free( parent );
1110 1.1.1.2 lukem if ( is_ref ) {
1111 1.1.1.2 lukem rc = LDAP_AFFECTS_MULTIPLE_DSAS;
1112 1.1.1.2 lukem *text = op->o_tag == LDAP_REQ_MODDN
1113 1.1.1.2 lukem ? "newSuperior is a referral object"
1114 1.1.1.2 lukem : "parent is a referral object";
1115 1.1.1.2 lukem break;
1116 1.1.1.2 lukem }
1117 1.1.1.2 lukem }
1118 1.1.1.2 lukem /* Must create parent directory. */
1119 1.1.1.2 lukem ldif2dir_name( ppath );
1120 1.1.1.2 lukem *need_dir = ppath.bv_val;
1121 1.1.1.2 lukem break;
1122 1.1.1.2 lukem case LDAP_NO_SUCH_OBJECT:
1123 1.1.1.2 lukem *text = op->o_tag == LDAP_REQ_MODDN
1124 1.1.1.2 lukem ? "newSuperior object does not exist"
1125 1.1.1.2 lukem : "parent does not exist";
1126 1.1.1.2 lukem break;
1127 1.1.1.2 lukem }
1128 1.1 lukem break;
1129 1.1.1.2 lukem case LDAP_OTHER:
1130 1.1.1.2 lukem Debug( LDAP_DEBUG_ANY,
1131 1.1.1.2 lukem "ldif_prepare_create: cannot stat \"%s\" parent dir: %s\n",
1132 1.1.1.9 christos ndn->bv_val, AC_STRERROR_R( errno, ebuf, sizeof(ebuf) ) );
1133 1.1.1.2 lukem *text = "internal error (cannot stat parent dir)";
1134 1.1.1.2 lukem break;
1135 1.1.1.2 lukem }
1136 1.1.1.2 lukem if ( *need_dir == NULL && ppath.bv_val != NULL )
1137 1.1.1.2 lukem SLAP_FREE( ppath.bv_val );
1138 1.1.1.2 lukem }
1139 1.1.1.2 lukem
1140 1.1.1.2 lukem if ( rc != LDAP_SUCCESS ) {
1141 1.1.1.2 lukem SLAP_FREE( dnpath->bv_val );
1142 1.1.1.2 lukem BER_BVZERO( dnpath );
1143 1.1.1.2 lukem }
1144 1.1.1.2 lukem return rc;
1145 1.1 lukem }
1146 1.1 lukem
1147 1.1.1.2 lukem static int
1148 1.1.1.2 lukem apply_modify_to_entry(
1149 1.1.1.2 lukem Entry *entry,
1150 1.1.1.2 lukem Modifications *modlist,
1151 1.1.1.2 lukem Operation *op,
1152 1.1.1.4 tron SlapReply *rs,
1153 1.1.1.4 tron char *textbuf )
1154 1.1 lukem {
1155 1.1 lukem int rc = modlist ? LDAP_UNWILLING_TO_PERFORM : LDAP_SUCCESS;
1156 1.1 lukem int is_oc = 0;
1157 1.1 lukem Modification *mods;
1158 1.1 lukem
1159 1.1 lukem if (!acl_check_modlist(op, entry, modlist)) {
1160 1.1 lukem return LDAP_INSUFFICIENT_ACCESS;
1161 1.1 lukem }
1162 1.1 lukem
1163 1.1 lukem for (; modlist != NULL; modlist = modlist->sml_next) {
1164 1.1 lukem mods = &modlist->sml_mod;
1165 1.1 lukem
1166 1.1 lukem if ( mods->sm_desc == slap_schema.si_ad_objectClass ) {
1167 1.1 lukem is_oc = 1;
1168 1.1 lukem }
1169 1.1 lukem switch (mods->sm_op) {
1170 1.1 lukem case LDAP_MOD_ADD:
1171 1.1 lukem rc = modify_add_values(entry, mods,
1172 1.1 lukem get_permissiveModify(op),
1173 1.1 lukem &rs->sr_text, textbuf,
1174 1.1.1.4 tron SLAP_TEXT_BUFLEN );
1175 1.1 lukem break;
1176 1.1.1.2 lukem
1177 1.1 lukem case LDAP_MOD_DELETE:
1178 1.1 lukem rc = modify_delete_values(entry, mods,
1179 1.1 lukem get_permissiveModify(op),
1180 1.1 lukem &rs->sr_text, textbuf,
1181 1.1.1.4 tron SLAP_TEXT_BUFLEN );
1182 1.1 lukem break;
1183 1.1.1.2 lukem
1184 1.1 lukem case LDAP_MOD_REPLACE:
1185 1.1 lukem rc = modify_replace_values(entry, mods,
1186 1.1 lukem get_permissiveModify(op),
1187 1.1 lukem &rs->sr_text, textbuf,
1188 1.1.1.4 tron SLAP_TEXT_BUFLEN );
1189 1.1 lukem break;
1190 1.1 lukem
1191 1.1 lukem case LDAP_MOD_INCREMENT:
1192 1.1 lukem rc = modify_increment_values( entry,
1193 1.1 lukem mods, get_permissiveModify(op),
1194 1.1 lukem &rs->sr_text, textbuf,
1195 1.1.1.4 tron SLAP_TEXT_BUFLEN );
1196 1.1 lukem break;
1197 1.1 lukem
1198 1.1 lukem case SLAP_MOD_SOFTADD:
1199 1.1 lukem mods->sm_op = LDAP_MOD_ADD;
1200 1.1 lukem rc = modify_add_values(entry, mods,
1201 1.1 lukem get_permissiveModify(op),
1202 1.1 lukem &rs->sr_text, textbuf,
1203 1.1.1.4 tron SLAP_TEXT_BUFLEN );
1204 1.1 lukem mods->sm_op = SLAP_MOD_SOFTADD;
1205 1.1 lukem if (rc == LDAP_TYPE_OR_VALUE_EXISTS) {
1206 1.1 lukem rc = LDAP_SUCCESS;
1207 1.1 lukem }
1208 1.1 lukem break;
1209 1.1.1.4 tron
1210 1.1.1.4 tron case SLAP_MOD_SOFTDEL:
1211 1.1.1.4 tron mods->sm_op = LDAP_MOD_DELETE;
1212 1.1.1.4 tron rc = modify_delete_values(entry, mods,
1213 1.1.1.4 tron get_permissiveModify(op),
1214 1.1.1.4 tron &rs->sr_text, textbuf,
1215 1.1.1.4 tron SLAP_TEXT_BUFLEN );
1216 1.1.1.4 tron mods->sm_op = SLAP_MOD_SOFTDEL;
1217 1.1.1.4 tron if (rc == LDAP_NO_SUCH_ATTRIBUTE) {
1218 1.1.1.4 tron rc = LDAP_SUCCESS;
1219 1.1.1.4 tron }
1220 1.1.1.4 tron break;
1221 1.1.1.4 tron
1222 1.1.1.4 tron case SLAP_MOD_ADD_IF_NOT_PRESENT:
1223 1.1.1.4 tron if ( attr_find( entry->e_attrs, mods->sm_desc ) ) {
1224 1.1.1.4 tron rc = LDAP_SUCCESS;
1225 1.1.1.4 tron break;
1226 1.1.1.4 tron }
1227 1.1.1.4 tron mods->sm_op = LDAP_MOD_ADD;
1228 1.1.1.4 tron rc = modify_add_values(entry, mods,
1229 1.1.1.4 tron get_permissiveModify(op),
1230 1.1.1.4 tron &rs->sr_text, textbuf,
1231 1.1.1.4 tron SLAP_TEXT_BUFLEN );
1232 1.1.1.4 tron mods->sm_op = SLAP_MOD_ADD_IF_NOT_PRESENT;
1233 1.1.1.4 tron break;
1234 1.1 lukem }
1235 1.1 lukem if(rc != LDAP_SUCCESS) break;
1236 1.1 lukem }
1237 1.1 lukem
1238 1.1.1.2 lukem if ( rc == LDAP_SUCCESS ) {
1239 1.1.1.2 lukem rs->sr_text = NULL; /* Needed at least with SLAP_MOD_SOFTADD */
1240 1.1 lukem if ( is_oc ) {
1241 1.1 lukem entry->e_ocflags = 0;
1242 1.1 lukem }
1243 1.1 lukem /* check that the entry still obeys the schema */
1244 1.1.1.2 lukem rc = entry_schema_check( op, entry, NULL, 0, 0, NULL,
1245 1.1.1.4 tron &rs->sr_text, textbuf, SLAP_TEXT_BUFLEN );
1246 1.1 lukem }
1247 1.1 lukem
1248 1.1 lukem return rc;
1249 1.1 lukem }
1250 1.1 lukem
1251 1.1.1.2 lukem
1252 1.1.1.2 lukem static int
1253 1.1 lukem ldif_back_referrals( Operation *op, SlapReply *rs )
1254 1.1 lukem {
1255 1.1.1.2 lukem struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
1256 1.1.1.2 lukem struct berval path, dn = op->o_req_dn, ndn = op->o_req_ndn;
1257 1.1.1.2 lukem ber_len_t min_dnlen;
1258 1.1.1.2 lukem Entry *entry = NULL, **entryp;
1259 1.1.1.2 lukem BerVarray ref;
1260 1.1.1.2 lukem int rc;
1261 1.1 lukem
1262 1.1.1.2 lukem min_dnlen = op->o_bd->be_nsuffix[0].bv_len;
1263 1.1.1.2 lukem if ( min_dnlen == 0 ) {
1264 1.1.1.2 lukem /* Catch root DSE (empty DN), it is not a referral */
1265 1.1.1.2 lukem min_dnlen = 1;
1266 1.1 lukem }
1267 1.1.1.2 lukem if ( ndn2path( op, &ndn, &path, 0 ) != LDAP_SUCCESS ) {
1268 1.1.1.2 lukem return LDAP_SUCCESS; /* Root DSE again */
1269 1.1 lukem }
1270 1.1 lukem
1271 1.1.1.2 lukem entryp = get_manageDSAit( op ) ? NULL : &entry;
1272 1.1 lukem ldap_pvt_thread_rdwr_rlock( &li->li_rdwr );
1273 1.1 lukem
1274 1.1.1.2 lukem for (;;) {
1275 1.1.1.2 lukem dnParent( &dn, &dn );
1276 1.1.1.2 lukem dnParent( &ndn, &ndn );
1277 1.1.1.2 lukem rc = ldif_read_entry( op, path.bv_val, &dn, &ndn,
1278 1.1.1.2 lukem entryp, &rs->sr_text );
1279 1.1.1.2 lukem if ( rc != LDAP_NO_SUCH_OBJECT )
1280 1.1.1.2 lukem break;
1281 1.1 lukem
1282 1.1.1.2 lukem rc = LDAP_SUCCESS;
1283 1.1.1.2 lukem if ( ndn.bv_len < min_dnlen )
1284 1.1.1.2 lukem break;
1285 1.1.1.2 lukem (void) get_parent_path( &path, NULL );
1286 1.1.1.2 lukem dir2ldif_name( path );
1287 1.1.1.2 lukem entryp = &entry;
1288 1.1.1.2 lukem }
1289 1.1 lukem
1290 1.1.1.2 lukem ldap_pvt_thread_rdwr_runlock( &li->li_rdwr );
1291 1.1.1.2 lukem SLAP_FREE( path.bv_val );
1292 1.1 lukem
1293 1.1.1.2 lukem if ( entry != NULL ) {
1294 1.1.1.2 lukem if ( is_entry_referral( entry ) ) {
1295 1.1 lukem Debug( LDAP_DEBUG_TRACE,
1296 1.1 lukem "ldif_back_referrals: tag=%lu target=\"%s\" matched=\"%s\"\n",
1297 1.1.1.2 lukem (unsigned long) op->o_tag, op->o_req_dn.bv_val, entry->e_dn );
1298 1.1 lukem
1299 1.1.1.2 lukem ref = get_entry_referrals( op, entry );
1300 1.1.1.2 lukem rs->sr_ref = referral_rewrite( ref, &entry->e_name, &op->o_req_dn,
1301 1.1.1.2 lukem op->o_tag == LDAP_REQ_SEARCH ?
1302 1.1.1.2 lukem op->ors_scope : LDAP_SCOPE_DEFAULT );
1303 1.1.1.2 lukem ber_bvarray_free( ref );
1304 1.1.1.2 lukem
1305 1.1.1.2 lukem if ( rs->sr_ref != NULL ) {
1306 1.1.1.2 lukem /* send referral */
1307 1.1.1.2 lukem rc = rs->sr_err = LDAP_REFERRAL;
1308 1.1.1.2 lukem rs->sr_matched = entry->e_dn;
1309 1.1.1.2 lukem send_ldap_result( op, rs );
1310 1.1.1.2 lukem ber_bvarray_free( rs->sr_ref );
1311 1.1.1.2 lukem rs->sr_ref = NULL;
1312 1.1.1.2 lukem } else {
1313 1.1 lukem rc = LDAP_OTHER;
1314 1.1.1.2 lukem rs->sr_text = "bad referral object";
1315 1.1 lukem }
1316 1.1 lukem rs->sr_matched = NULL;
1317 1.1 lukem }
1318 1.1 lukem
1319 1.1.1.2 lukem entry_free( entry );
1320 1.1 lukem }
1321 1.1 lukem
1322 1.1 lukem return rc;
1323 1.1 lukem }
1324 1.1 lukem
1325 1.1 lukem
1326 1.1 lukem /* LDAP operations */
1327 1.1 lukem
1328 1.1 lukem static int
1329 1.1 lukem ldif_back_bind( Operation *op, SlapReply *rs )
1330 1.1 lukem {
1331 1.1 lukem struct ldif_info *li;
1332 1.1 lukem Attribute *a;
1333 1.1 lukem AttributeDescription *password = slap_schema.si_ad_userPassword;
1334 1.1 lukem int return_val;
1335 1.1.1.2 lukem Entry *entry = NULL;
1336 1.1 lukem
1337 1.1 lukem switch ( be_rootdn_bind( op, rs ) ) {
1338 1.1 lukem case SLAP_CB_CONTINUE:
1339 1.1 lukem break;
1340 1.1 lukem
1341 1.1 lukem default:
1342 1.1 lukem /* in case of success, front end will send result;
1343 1.1 lukem * otherwise, be_rootdn_bind() did */
1344 1.1 lukem return rs->sr_err;
1345 1.1 lukem }
1346 1.1 lukem
1347 1.1 lukem li = (struct ldif_info *) op->o_bd->be_private;
1348 1.1 lukem ldap_pvt_thread_rdwr_rlock(&li->li_rdwr);
1349 1.1.1.2 lukem return_val = get_entry(op, &entry, NULL, NULL);
1350 1.1 lukem
1351 1.1 lukem /* no object is found for them */
1352 1.1 lukem if(return_val != LDAP_SUCCESS) {
1353 1.1 lukem rs->sr_err = return_val = LDAP_INVALID_CREDENTIALS;
1354 1.1 lukem goto return_result;
1355 1.1 lukem }
1356 1.1 lukem
1357 1.1 lukem /* they don't have userpassword */
1358 1.1 lukem if((a = attr_find(entry->e_attrs, password)) == NULL) {
1359 1.1 lukem rs->sr_err = LDAP_INAPPROPRIATE_AUTH;
1360 1.1 lukem return_val = 1;
1361 1.1 lukem goto return_result;
1362 1.1 lukem }
1363 1.1 lukem
1364 1.1 lukem /* authentication actually failed */
1365 1.1 lukem if(slap_passwd_check(op, entry, a, &op->oq_bind.rb_cred,
1366 1.1 lukem &rs->sr_text) != 0) {
1367 1.1 lukem rs->sr_err = LDAP_INVALID_CREDENTIALS;
1368 1.1 lukem return_val = 1;
1369 1.1 lukem goto return_result;
1370 1.1 lukem }
1371 1.1 lukem
1372 1.1 lukem /* let the front-end send success */
1373 1.1.1.2 lukem return_val = LDAP_SUCCESS;
1374 1.1 lukem
1375 1.1 lukem return_result:
1376 1.1 lukem ldap_pvt_thread_rdwr_runlock(&li->li_rdwr);
1377 1.1.1.2 lukem if(return_val != LDAP_SUCCESS)
1378 1.1 lukem send_ldap_result( op, rs );
1379 1.1 lukem if(entry != NULL)
1380 1.1 lukem entry_free(entry);
1381 1.1 lukem return return_val;
1382 1.1 lukem }
1383 1.1 lukem
1384 1.1.1.2 lukem static int
1385 1.1.1.2 lukem ldif_back_search( Operation *op, SlapReply *rs )
1386 1.1 lukem {
1387 1.1 lukem struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
1388 1.1 lukem
1389 1.1 lukem ldap_pvt_thread_rdwr_rlock(&li->li_rdwr);
1390 1.1.1.2 lukem rs->sr_err = search_tree( op, rs );
1391 1.1 lukem ldap_pvt_thread_rdwr_runlock(&li->li_rdwr);
1392 1.1 lukem send_ldap_result(op, rs);
1393 1.1 lukem
1394 1.1 lukem return rs->sr_err;
1395 1.1 lukem }
1396 1.1 lukem
1397 1.1.1.2 lukem static int
1398 1.1.1.2 lukem ldif_back_add( Operation *op, SlapReply *rs )
1399 1.1.1.2 lukem {
1400 1.1 lukem struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
1401 1.1 lukem Entry * e = op->ora_e;
1402 1.1.1.2 lukem struct berval path;
1403 1.1.1.2 lukem char *parentdir;
1404 1.1 lukem char textbuf[SLAP_TEXT_BUFLEN];
1405 1.1.1.2 lukem int rc;
1406 1.1 lukem
1407 1.1.1.9 christos Debug( LDAP_DEBUG_TRACE, "ldif_back_add: \"%s\"\n", e->e_dn );
1408 1.1 lukem
1409 1.1.1.2 lukem rc = entry_schema_check( op, e, NULL, 0, 1, NULL,
1410 1.1 lukem &rs->sr_text, textbuf, sizeof( textbuf ) );
1411 1.1.1.2 lukem if ( rc != LDAP_SUCCESS )
1412 1.1.1.2 lukem goto send_res;
1413 1.1 lukem
1414 1.1.1.2 lukem rc = slap_add_opattrs( op, &rs->sr_text, textbuf, sizeof( textbuf ), 1 );
1415 1.1.1.2 lukem if ( rc != LDAP_SUCCESS )
1416 1.1.1.2 lukem goto send_res;
1417 1.1.1.2 lukem
1418 1.1.1.2 lukem ldap_pvt_thread_mutex_lock( &li->li_modop_mutex );
1419 1.1.1.2 lukem
1420 1.1.1.2 lukem rc = ldif_prepare_create( op, e, &path, &parentdir, &rs->sr_text );
1421 1.1.1.2 lukem if ( rc == LDAP_SUCCESS ) {
1422 1.1.1.2 lukem ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
1423 1.1.1.2 lukem rc = ldif_write_entry( op, e, &path, parentdir, &rs->sr_text );
1424 1.1.1.2 lukem ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
1425 1.1.1.2 lukem
1426 1.1.1.2 lukem SLAP_FREE( path.bv_val );
1427 1.1.1.2 lukem if ( parentdir != NULL )
1428 1.1.1.2 lukem SLAP_FREE( parentdir );
1429 1.1 lukem }
1430 1.1 lukem
1431 1.1.1.2 lukem ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex );
1432 1.1 lukem
1433 1.1.1.2 lukem send_res:
1434 1.1.1.2 lukem rs->sr_err = rc;
1435 1.1.1.2 lukem Debug( LDAP_DEBUG_TRACE, "ldif_back_add: err: %d text: %s\n",
1436 1.1.1.9 christos rc, rs->sr_text ? rs->sr_text : "" );
1437 1.1.1.2 lukem send_ldap_result( op, rs );
1438 1.1 lukem slap_graduate_commit_csn( op );
1439 1.1.1.4 tron rs->sr_text = NULL; /* remove possible pointer to textbuf */
1440 1.1 lukem return rs->sr_err;
1441 1.1 lukem }
1442 1.1 lukem
1443 1.1.1.2 lukem static int
1444 1.1.1.2 lukem ldif_back_modify( Operation *op, SlapReply *rs )
1445 1.1.1.2 lukem {
1446 1.1 lukem struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
1447 1.1 lukem Modifications * modlst = op->orm_modlist;
1448 1.1 lukem struct berval path;
1449 1.1 lukem Entry *entry;
1450 1.1.1.4 tron char textbuf[SLAP_TEXT_BUFLEN];
1451 1.1.1.2 lukem int rc;
1452 1.1 lukem
1453 1.1 lukem slap_mods_opattrs( op, &op->orm_modlist, 1 );
1454 1.1 lukem
1455 1.1.1.2 lukem ldap_pvt_thread_mutex_lock( &li->li_modop_mutex );
1456 1.1 lukem
1457 1.1.1.2 lukem rc = get_entry( op, &entry, &path, &rs->sr_text );
1458 1.1.1.2 lukem if ( rc == LDAP_SUCCESS ) {
1459 1.1.1.4 tron rc = apply_modify_to_entry( entry, modlst, op, rs, textbuf );
1460 1.1.1.2 lukem if ( rc == LDAP_SUCCESS ) {
1461 1.1.1.2 lukem ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
1462 1.1.1.2 lukem rc = ldif_write_entry( op, entry, &path, NULL, &rs->sr_text );
1463 1.1.1.2 lukem ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
1464 1.1 lukem }
1465 1.1 lukem
1466 1.1 lukem entry_free( entry );
1467 1.1 lukem SLAP_FREE( path.bv_val );
1468 1.1 lukem }
1469 1.1 lukem
1470 1.1.1.2 lukem ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex );
1471 1.1.1.2 lukem
1472 1.1.1.2 lukem rs->sr_err = rc;
1473 1.1.1.2 lukem send_ldap_result( op, rs );
1474 1.1 lukem slap_graduate_commit_csn( op );
1475 1.1.1.4 tron rs->sr_text = NULL; /* remove possible pointer to textbuf */
1476 1.1 lukem return rs->sr_err;
1477 1.1 lukem }
1478 1.1 lukem
1479 1.1.1.2 lukem static int
1480 1.1.1.2 lukem ldif_back_delete( Operation *op, SlapReply *rs )
1481 1.1.1.2 lukem {
1482 1.1 lukem struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
1483 1.1 lukem struct berval path;
1484 1.1.1.2 lukem int rc = LDAP_SUCCESS;
1485 1.1.1.9 christos char ebuf[128];
1486 1.1 lukem
1487 1.1 lukem if ( BER_BVISEMPTY( &op->o_csn )) {
1488 1.1 lukem struct berval csn;
1489 1.1.1.3 adam char csnbuf[LDAP_PVT_CSNSTR_BUFSIZE];
1490 1.1 lukem
1491 1.1 lukem csn.bv_val = csnbuf;
1492 1.1 lukem csn.bv_len = sizeof( csnbuf );
1493 1.1 lukem slap_get_csn( op, &csn, 1 );
1494 1.1 lukem }
1495 1.1 lukem
1496 1.1.1.2 lukem ldap_pvt_thread_mutex_lock( &li->li_modop_mutex );
1497 1.1.1.2 lukem ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
1498 1.1.1.2 lukem if ( op->o_abandon ) {
1499 1.1.1.2 lukem rc = SLAPD_ABANDON;
1500 1.1.1.2 lukem goto done;
1501 1.1.1.2 lukem }
1502 1.1.1.2 lukem
1503 1.1.1.2 lukem rc = ndn2path( op, &op->o_req_ndn, &path, 0 );
1504 1.1.1.2 lukem if ( rc != LDAP_SUCCESS ) {
1505 1.1.1.2 lukem goto done;
1506 1.1.1.2 lukem }
1507 1.1 lukem
1508 1.1.1.2 lukem ldif2dir_len( path );
1509 1.1.1.2 lukem ldif2dir_name( path );
1510 1.1.1.2 lukem if ( rmdir( path.bv_val ) < 0 ) {
1511 1.1 lukem switch ( errno ) {
1512 1.1 lukem case ENOTEMPTY:
1513 1.1.1.2 lukem rc = LDAP_NOT_ALLOWED_ON_NONLEAF;
1514 1.1 lukem break;
1515 1.1 lukem case ENOENT:
1516 1.1 lukem /* is leaf, go on */
1517 1.1 lukem break;
1518 1.1 lukem default:
1519 1.1.1.2 lukem rc = LDAP_OTHER;
1520 1.1.1.2 lukem rs->sr_text = "internal error (cannot delete subtree directory)";
1521 1.1 lukem break;
1522 1.1 lukem }
1523 1.1 lukem }
1524 1.1 lukem
1525 1.1.1.2 lukem if ( rc == LDAP_SUCCESS ) {
1526 1.1.1.2 lukem dir2ldif_name( path );
1527 1.1.1.2 lukem if ( unlink( path.bv_val ) < 0 ) {
1528 1.1.1.2 lukem rc = LDAP_NO_SUCH_OBJECT;
1529 1.1.1.2 lukem if ( errno != ENOENT ) {
1530 1.1.1.2 lukem rc = LDAP_OTHER;
1531 1.1.1.2 lukem rs->sr_text = "internal error (cannot delete entry file)";
1532 1.1 lukem }
1533 1.1 lukem }
1534 1.1 lukem }
1535 1.1 lukem
1536 1.1.1.2 lukem if ( rc == LDAP_OTHER ) {
1537 1.1.1.2 lukem Debug( LDAP_DEBUG_ANY, "ldif_back_delete: %s \"%s\": %s\n",
1538 1.1.1.9 christos "cannot delete", path.bv_val, AC_STRERROR_R( errno, ebuf, sizeof(ebuf) ) );
1539 1.1.1.2 lukem }
1540 1.1.1.2 lukem
1541 1.1.1.2 lukem SLAP_FREE( path.bv_val );
1542 1.1.1.2 lukem done:
1543 1.1.1.2 lukem ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
1544 1.1.1.2 lukem ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex );
1545 1.1.1.2 lukem rs->sr_err = rc;
1546 1.1.1.2 lukem send_ldap_result( op, rs );
1547 1.1 lukem slap_graduate_commit_csn( op );
1548 1.1 lukem return rs->sr_err;
1549 1.1 lukem }
1550 1.1 lukem
1551 1.1 lukem
1552 1.1 lukem static int
1553 1.1 lukem ldif_move_entry(
1554 1.1 lukem Operation *op,
1555 1.1 lukem Entry *entry,
1556 1.1.1.2 lukem int same_ndn,
1557 1.1.1.2 lukem struct berval *oldpath,
1558 1.1.1.2 lukem const char **text )
1559 1.1 lukem {
1560 1.1.1.2 lukem struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
1561 1.1 lukem struct berval newpath;
1562 1.1.1.2 lukem char *parentdir = NULL, *trash;
1563 1.1.1.2 lukem int rc, rename_res;
1564 1.1.1.9 christos char ebuf[128];
1565 1.1 lukem
1566 1.1.1.2 lukem if ( same_ndn ) {
1567 1.1.1.2 lukem rc = LDAP_SUCCESS;
1568 1.1.1.2 lukem newpath = *oldpath;
1569 1.1.1.2 lukem } else {
1570 1.1.1.2 lukem rc = ldif_prepare_create( op, entry, &newpath,
1571 1.1.1.2 lukem op->orr_newSup ? &parentdir : NULL, text );
1572 1.1.1.2 lukem }
1573 1.1 lukem
1574 1.1.1.2 lukem if ( rc == LDAP_SUCCESS ) {
1575 1.1.1.2 lukem ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
1576 1.1.1.2 lukem
1577 1.1.1.2 lukem rc = ldif_write_entry( op, entry, &newpath, parentdir, text );
1578 1.1.1.2 lukem if ( rc == LDAP_SUCCESS && !same_ndn ) {
1579 1.1.1.2 lukem trash = oldpath->bv_val; /* will be .ldif file to delete */
1580 1.1.1.2 lukem ldif2dir_len( newpath );
1581 1.1.1.2 lukem ldif2dir_len( *oldpath );
1582 1.1.1.2 lukem /* Move subdir before deleting old entry,
1583 1.1.1.2 lukem * so .ldif always exists if subdir does.
1584 1.1.1.2 lukem */
1585 1.1.1.2 lukem ldif2dir_name( newpath );
1586 1.1.1.2 lukem ldif2dir_name( *oldpath );
1587 1.1.1.2 lukem rename_res = move_dir( oldpath->bv_val, newpath.bv_val );
1588 1.1.1.2 lukem if ( rename_res != 0 && errno != ENOENT ) {
1589 1.1.1.2 lukem rc = LDAP_OTHER;
1590 1.1.1.2 lukem *text = "internal error (cannot move this subtree)";
1591 1.1.1.2 lukem trash = newpath.bv_val;
1592 1.1 lukem }
1593 1.1.1.2 lukem
1594 1.1.1.2 lukem /* Delete old entry, or if error undo change */
1595 1.1.1.2 lukem for (;;) {
1596 1.1.1.2 lukem dir2ldif_name( newpath );
1597 1.1.1.2 lukem dir2ldif_name( *oldpath );
1598 1.1.1.2 lukem if ( unlink( trash ) == 0 )
1599 1.1.1.2 lukem break;
1600 1.1.1.2 lukem if ( rc == LDAP_SUCCESS ) {
1601 1.1.1.2 lukem /* Prepare to undo change and return failure */
1602 1.1.1.2 lukem rc = LDAP_OTHER;
1603 1.1.1.2 lukem *text = "internal error (cannot move this entry)";
1604 1.1.1.2 lukem trash = newpath.bv_val;
1605 1.1.1.2 lukem if ( rename_res != 0 )
1606 1.1.1.2 lukem continue;
1607 1.1.1.2 lukem /* First move subdirectory back */
1608 1.1.1.2 lukem ldif2dir_name( newpath );
1609 1.1.1.2 lukem ldif2dir_name( *oldpath );
1610 1.1.1.2 lukem if ( move_dir( newpath.bv_val, oldpath->bv_val ) == 0 )
1611 1.1.1.2 lukem continue;
1612 1.1.1.2 lukem }
1613 1.1.1.2 lukem *text = "added new but couldn't delete old entry!";
1614 1.1.1.2 lukem break;
1615 1.1 lukem }
1616 1.1.1.2 lukem
1617 1.1.1.2 lukem if ( rc != LDAP_SUCCESS ) {
1618 1.1.1.9 christos Debug(LDAP_DEBUG_ANY,
1619 1.1.1.9 christos "ldif_move_entry: %s (%s): \"%s\" -> \"%s\"\n",
1620 1.1.1.9 christos *text, AC_STRERROR_R(errno, ebuf, sizeof(ebuf)),
1621 1.1.1.9 christos op->o_req_dn.bv_val, entry->e_dn );
1622 1.1 lukem }
1623 1.1 lukem }
1624 1.1.1.2 lukem
1625 1.1.1.2 lukem ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
1626 1.1.1.2 lukem if ( !same_ndn )
1627 1.1.1.2 lukem SLAP_FREE( newpath.bv_val );
1628 1.1.1.2 lukem if ( parentdir != NULL )
1629 1.1.1.2 lukem SLAP_FREE( parentdir );
1630 1.1 lukem }
1631 1.1 lukem
1632 1.1.1.2 lukem return rc;
1633 1.1 lukem }
1634 1.1 lukem
1635 1.1 lukem static int
1636 1.1.1.2 lukem ldif_back_modrdn( Operation *op, SlapReply *rs )
1637 1.1 lukem {
1638 1.1 lukem struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
1639 1.1 lukem struct berval new_dn = BER_BVNULL, new_ndn = BER_BVNULL;
1640 1.1 lukem struct berval p_dn, old_path;
1641 1.1 lukem Entry *entry;
1642 1.1.1.4 tron char textbuf[SLAP_TEXT_BUFLEN];
1643 1.1.1.2 lukem int rc, same_ndn;
1644 1.1 lukem
1645 1.1 lukem slap_mods_opattrs( op, &op->orr_modlist, 1 );
1646 1.1 lukem
1647 1.1.1.2 lukem ldap_pvt_thread_mutex_lock( &li->li_modop_mutex );
1648 1.1 lukem
1649 1.1.1.2 lukem rc = get_entry( op, &entry, &old_path, &rs->sr_text );
1650 1.1 lukem if ( rc == LDAP_SUCCESS ) {
1651 1.1 lukem /* build new dn, and new ndn for the entry */
1652 1.1 lukem if ( op->oq_modrdn.rs_newSup != NULL ) {
1653 1.1 lukem p_dn = *op->oq_modrdn.rs_newSup;
1654 1.1 lukem } else {
1655 1.1 lukem dnParent( &entry->e_name, &p_dn );
1656 1.1 lukem }
1657 1.1.1.2 lukem build_new_dn( &new_dn, &p_dn, &op->oq_modrdn.rs_newrdn, NULL );
1658 1.1 lukem dnNormalize( 0, NULL, NULL, &new_dn, &new_ndn, NULL );
1659 1.1.1.2 lukem same_ndn = !ber_bvcmp( &entry->e_nname, &new_ndn );
1660 1.1 lukem ber_memfree_x( entry->e_name.bv_val, NULL );
1661 1.1 lukem ber_memfree_x( entry->e_nname.bv_val, NULL );
1662 1.1 lukem entry->e_name = new_dn;
1663 1.1 lukem entry->e_nname = new_ndn;
1664 1.1 lukem
1665 1.1 lukem /* perform the modifications */
1666 1.1.1.4 tron rc = apply_modify_to_entry( entry, op->orr_modlist, op, rs, textbuf );
1667 1.1 lukem if ( rc == LDAP_SUCCESS )
1668 1.1.1.2 lukem rc = ldif_move_entry( op, entry, same_ndn, &old_path,
1669 1.1.1.2 lukem &rs->sr_text );
1670 1.1 lukem
1671 1.1 lukem entry_free( entry );
1672 1.1 lukem SLAP_FREE( old_path.bv_val );
1673 1.1 lukem }
1674 1.1 lukem
1675 1.1.1.2 lukem ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex );
1676 1.1 lukem rs->sr_err = rc;
1677 1.1 lukem send_ldap_result( op, rs );
1678 1.1 lukem slap_graduate_commit_csn( op );
1679 1.1.1.4 tron rs->sr_text = NULL; /* remove possible pointer to textbuf */
1680 1.1 lukem return rs->sr_err;
1681 1.1 lukem }
1682 1.1 lukem
1683 1.1 lukem
1684 1.1 lukem /* Return LDAP_SUCCESS IFF we retrieve the specified entry. */
1685 1.1 lukem static int
1686 1.1 lukem ldif_back_entry_get(
1687 1.1 lukem Operation *op,
1688 1.1 lukem struct berval *ndn,
1689 1.1 lukem ObjectClass *oc,
1690 1.1 lukem AttributeDescription *at,
1691 1.1 lukem int rw,
1692 1.1 lukem Entry **e )
1693 1.1 lukem {
1694 1.1 lukem struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
1695 1.1 lukem struct berval op_dn = op->o_req_dn, op_ndn = op->o_req_ndn;
1696 1.1 lukem int rc;
1697 1.1 lukem
1698 1.1 lukem assert( ndn != NULL );
1699 1.1 lukem assert( !BER_BVISNULL( ndn ) );
1700 1.1 lukem
1701 1.1 lukem ldap_pvt_thread_rdwr_rlock( &li->li_rdwr );
1702 1.1 lukem op->o_req_dn = *ndn;
1703 1.1 lukem op->o_req_ndn = *ndn;
1704 1.1.1.2 lukem rc = get_entry( op, e, NULL, NULL );
1705 1.1 lukem op->o_req_dn = op_dn;
1706 1.1 lukem op->o_req_ndn = op_ndn;
1707 1.1 lukem ldap_pvt_thread_rdwr_runlock( &li->li_rdwr );
1708 1.1 lukem
1709 1.1 lukem if ( rc == LDAP_SUCCESS && oc && !is_entry_objectclass_or_sub( *e, oc ) ) {
1710 1.1 lukem rc = LDAP_NO_SUCH_ATTRIBUTE;
1711 1.1 lukem entry_free( *e );
1712 1.1 lukem *e = NULL;
1713 1.1 lukem }
1714 1.1 lukem
1715 1.1 lukem return rc;
1716 1.1 lukem }
1717 1.1 lukem
1718 1.1.1.9 christos static int
1719 1.1.1.9 christos ldif_back_entry_release_rw (
1720 1.1.1.9 christos Operation *op,
1721 1.1.1.9 christos Entry *e,
1722 1.1.1.9 christos int rw )
1723 1.1.1.9 christos {
1724 1.1.1.9 christos ID id = e->e_id;
1725 1.1.1.9 christos
1726 1.1.1.9 christos /* only tool mode assigns valid IDs */
1727 1.1.1.9 christos if ( id != 0 && id != NOID )
1728 1.1.1.9 christos {
1729 1.1.1.9 christos struct ldif_tool *tl = &((struct ldif_info *) op->o_bd->be_private)->li_tool;
1730 1.1.1.9 christos
1731 1.1.1.9 christos id--;
1732 1.1.1.9 christos
1733 1.1.1.9 christos assert( id < tl->ecount );
1734 1.1.1.9 christos assert( e == tl->entries[id] );
1735 1.1.1.9 christos tl->entries[id] = NULL;
1736 1.1.1.9 christos }
1737 1.1.1.9 christos
1738 1.1.1.9 christos entry_free( e );
1739 1.1.1.9 christos return 0;
1740 1.1.1.9 christos }
1741 1.1.1.9 christos
1742 1.1 lukem
1743 1.1 lukem /* Slap tools */
1744 1.1 lukem
1745 1.1.1.2 lukem static int
1746 1.1.1.2 lukem ldif_tool_entry_open( BackendDB *be, int mode )
1747 1.1.1.2 lukem {
1748 1.1.1.2 lukem struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;
1749 1.1 lukem
1750 1.1.1.2 lukem tl->ecurrent = 0;
1751 1.1.1.2 lukem return 0;
1752 1.1.1.2 lukem }
1753 1.1 lukem
1754 1.1.1.2 lukem static int
1755 1.1.1.2 lukem ldif_tool_entry_close( BackendDB *be )
1756 1.1.1.2 lukem {
1757 1.1.1.2 lukem struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;
1758 1.1.1.2 lukem Entry **entries = tl->entries;
1759 1.1.1.2 lukem ID i;
1760 1.1.1.2 lukem
1761 1.1.1.2 lukem for ( i = tl->ecount; i--; )
1762 1.1.1.2 lukem if ( entries[i] )
1763 1.1.1.2 lukem entry_free( entries[i] );
1764 1.1.1.2 lukem SLAP_FREE( entries );
1765 1.1.1.2 lukem tl->entries = NULL;
1766 1.1.1.2 lukem tl->ecount = tl->elen = 0;
1767 1.1 lukem return 0;
1768 1.1 lukem }
1769 1.1 lukem
1770 1.1.1.2 lukem static ID
1771 1.1.1.2 lukem ldif_tool_entry_next( BackendDB *be )
1772 1.1 lukem {
1773 1.1.1.2 lukem struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;
1774 1.1.1.2 lukem
1775 1.1.1.3 adam do {
1776 1.1.1.3 adam Entry *e = tl->entries[ tl->ecurrent ];
1777 1.1.1.3 adam
1778 1.1.1.3 adam if ( tl->ecurrent >= tl->ecount ) {
1779 1.1.1.3 adam return NOID;
1780 1.1.1.3 adam }
1781 1.1.1.3 adam
1782 1.1.1.3 adam ++tl->ecurrent;
1783 1.1.1.3 adam
1784 1.1.1.3 adam if ( tl->tl_base && !dnIsSuffixScope( &e->e_nname, tl->tl_base, tl->tl_scope ) ) {
1785 1.1.1.3 adam continue;
1786 1.1.1.3 adam }
1787 1.1.1.3 adam
1788 1.1.1.3 adam if ( tl->tl_filter && test_filter( NULL, e, tl->tl_filter ) != LDAP_COMPARE_TRUE ) {
1789 1.1.1.3 adam continue;
1790 1.1.1.3 adam }
1791 1.1.1.3 adam
1792 1.1.1.3 adam break;
1793 1.1.1.3 adam } while ( 1 );
1794 1.1.1.3 adam
1795 1.1.1.3 adam return tl->ecurrent;
1796 1.1 lukem }
1797 1.1 lukem
1798 1.1 lukem static ID
1799 1.1.1.3 adam ldif_tool_entry_first_x( BackendDB *be, struct berval *base, int scope, Filter *f )
1800 1.1 lukem {
1801 1.1.1.2 lukem struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;
1802 1.1 lukem
1803 1.1.1.3 adam tl->tl_base = base;
1804 1.1.1.3 adam tl->tl_scope = scope;
1805 1.1.1.3 adam tl->tl_filter = f;
1806 1.1.1.3 adam
1807 1.1.1.2 lukem if ( tl->entries == NULL ) {
1808 1.1 lukem Operation op = {0};
1809 1.1 lukem
1810 1.1 lukem op.o_bd = be;
1811 1.1 lukem op.o_req_dn = *be->be_suffix;
1812 1.1 lukem op.o_req_ndn = *be->be_nsuffix;
1813 1.1 lukem op.ors_scope = LDAP_SCOPE_SUBTREE;
1814 1.1.1.2 lukem if ( search_tree( &op, NULL ) != LDAP_SUCCESS ) {
1815 1.1.1.2 lukem tl->ecurrent = tl->ecount; /* fail ldif_tool_entry_next() */
1816 1.1.1.4 tron return NOID; /* fail ldif_tool_entry_get() */
1817 1.1.1.2 lukem }
1818 1.1 lukem }
1819 1.1 lukem return ldif_tool_entry_next( be );
1820 1.1 lukem }
1821 1.1 lukem
1822 1.1.1.9 christos static ID
1823 1.1.1.9 christos ldif_tool_dn2id_get( BackendDB *be, struct berval *dn )
1824 1.1.1.9 christos {
1825 1.1.1.9 christos struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;
1826 1.1.1.9 christos
1827 1.1.1.9 christos Operation op = {0};
1828 1.1.1.9 christos
1829 1.1.1.9 christos op.o_bd = be;
1830 1.1.1.9 christos op.o_req_dn = *dn;
1831 1.1.1.9 christos op.o_req_ndn = *dn;
1832 1.1.1.9 christos op.ors_scope = LDAP_SCOPE_BASE;
1833 1.1.1.9 christos if ( search_tree( &op, NULL ) != LDAP_SUCCESS ) {
1834 1.1.1.9 christos return NOID;
1835 1.1.1.9 christos }
1836 1.1.1.9 christos return tl->ecount;
1837 1.1.1.9 christos }
1838 1.1.1.9 christos
1839 1.1.1.2 lukem static Entry *
1840 1.1.1.2 lukem ldif_tool_entry_get( BackendDB *be, ID id )
1841 1.1.1.2 lukem {
1842 1.1.1.2 lukem struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;
1843 1.1.1.2 lukem Entry *e = NULL;
1844 1.1 lukem
1845 1.1.1.2 lukem --id;
1846 1.1.1.2 lukem if ( id < tl->ecount ) {
1847 1.1.1.2 lukem e = tl->entries[id];
1848 1.1 lukem }
1849 1.1.1.2 lukem return e;
1850 1.1 lukem }
1851 1.1 lukem
1852 1.1.1.2 lukem static ID
1853 1.1.1.2 lukem ldif_tool_entry_put( BackendDB *be, Entry *e, struct berval *text )
1854 1.1.1.2 lukem {
1855 1.1.1.2 lukem int rc;
1856 1.1.1.2 lukem const char *errmsg = NULL;
1857 1.1.1.2 lukem struct berval path;
1858 1.1.1.2 lukem char *parentdir;
1859 1.1.1.2 lukem Operation op = {0};
1860 1.1 lukem
1861 1.1.1.2 lukem op.o_bd = be;
1862 1.1.1.2 lukem rc = ldif_prepare_create( &op, e, &path, &parentdir, &errmsg );
1863 1.1.1.2 lukem if ( rc == LDAP_SUCCESS ) {
1864 1.1.1.2 lukem rc = ldif_write_entry( &op, e, &path, parentdir, &errmsg );
1865 1.1.1.2 lukem
1866 1.1.1.2 lukem SLAP_FREE( path.bv_val );
1867 1.1.1.2 lukem if ( parentdir != NULL )
1868 1.1.1.2 lukem SLAP_FREE( parentdir );
1869 1.1.1.2 lukem if ( rc == LDAP_SUCCESS )
1870 1.1.1.2 lukem return 1;
1871 1.1 lukem }
1872 1.1.1.2 lukem
1873 1.1.1.2 lukem if ( errmsg == NULL && rc != LDAP_OTHER )
1874 1.1.1.2 lukem errmsg = ldap_err2string( rc );
1875 1.1.1.2 lukem if ( errmsg != NULL )
1876 1.1.1.2 lukem snprintf( text->bv_val, text->bv_len, "%s", errmsg );
1877 1.1.1.2 lukem return NOID;
1878 1.1 lukem }
1879 1.1 lukem
1880 1.1.1.9 christos static ID
1881 1.1.1.9 christos ldif_tool_entry_modify( BackendDB *be, Entry *e, struct berval *text )
1882 1.1.1.9 christos {
1883 1.1.1.9 christos int rc;
1884 1.1.1.9 christos const char *errmsg = NULL;
1885 1.1.1.9 christos struct berval path;
1886 1.1.1.9 christos Operation op = {0};
1887 1.1.1.9 christos
1888 1.1.1.9 christos op.o_bd = be;
1889 1.1.1.9 christos ndn2path( &op, &e->e_nname, &path, 0 );
1890 1.1.1.9 christos rc = ldif_write_entry( &op, e, &path, NULL, &errmsg );
1891 1.1.1.9 christos SLAP_FREE( path.bv_val );
1892 1.1.1.9 christos if ( rc == LDAP_SUCCESS )
1893 1.1.1.9 christos return 1;
1894 1.1.1.9 christos
1895 1.1.1.9 christos if ( errmsg == NULL && rc != LDAP_OTHER )
1896 1.1.1.9 christos errmsg = ldap_err2string( rc );
1897 1.1.1.9 christos if ( errmsg != NULL )
1898 1.1.1.9 christos snprintf( text->bv_val, text->bv_len, "%s", errmsg );
1899 1.1.1.9 christos return NOID;
1900 1.1.1.9 christos }
1901 1.1.1.9 christos
1902 1.1.1.9 christos static int
1903 1.1.1.9 christos ldif_tool_entry_delete( BackendDB *be, struct berval *ndn, struct berval *text )
1904 1.1.1.9 christos {
1905 1.1.1.9 christos int rc = LDAP_SUCCESS;
1906 1.1.1.9 christos const char *errmsg = NULL;
1907 1.1.1.9 christos struct berval path;
1908 1.1.1.9 christos Operation op = {0};
1909 1.1.1.9 christos
1910 1.1.1.9 christos op.o_bd = be;
1911 1.1.1.9 christos ndn2path( &op, ndn, &path, 0 );
1912 1.1.1.9 christos
1913 1.1.1.9 christos ldif2dir_len( path );
1914 1.1.1.9 christos ldif2dir_name( path );
1915 1.1.1.9 christos if ( rmdir( path.bv_val ) < 0 ) {
1916 1.1.1.9 christos switch ( errno ) {
1917 1.1.1.9 christos case ENOTEMPTY:
1918 1.1.1.9 christos rc = LDAP_NOT_ALLOWED_ON_NONLEAF;
1919 1.1.1.9 christos break;
1920 1.1.1.9 christos case ENOENT:
1921 1.1.1.9 christos /* is leaf, go on */
1922 1.1.1.9 christos break;
1923 1.1.1.9 christos default:
1924 1.1.1.9 christos rc = LDAP_OTHER;
1925 1.1.1.9 christos errmsg = "internal error (cannot delete subtree directory)";
1926 1.1.1.9 christos break;
1927 1.1.1.9 christos }
1928 1.1.1.9 christos }
1929 1.1.1.9 christos
1930 1.1.1.9 christos if ( rc == LDAP_SUCCESS ) {
1931 1.1.1.9 christos dir2ldif_name( path );
1932 1.1.1.9 christos if ( unlink( path.bv_val ) < 0 ) {
1933 1.1.1.9 christos rc = LDAP_NO_SUCH_OBJECT;
1934 1.1.1.9 christos if ( errno != ENOENT ) {
1935 1.1.1.9 christos rc = LDAP_OTHER;
1936 1.1.1.9 christos errmsg = "internal error (cannot delete entry file)";
1937 1.1.1.9 christos }
1938 1.1.1.9 christos }
1939 1.1.1.9 christos }
1940 1.1.1.9 christos
1941 1.1.1.9 christos SLAP_FREE( path.bv_val );
1942 1.1.1.9 christos
1943 1.1.1.9 christos if ( errmsg == NULL && rc != LDAP_OTHER )
1944 1.1.1.9 christos errmsg = ldap_err2string( rc );
1945 1.1.1.9 christos if ( errmsg != NULL )
1946 1.1.1.9 christos snprintf( text->bv_val, text->bv_len, "%s", errmsg );
1947 1.1.1.9 christos return rc;
1948 1.1.1.9 christos }
1949 1.1.1.9 christos
1950 1.1 lukem
1951 1.1 lukem /* Setup */
1952 1.1 lukem
1953 1.1 lukem static int
1954 1.1 lukem ldif_back_db_init( BackendDB *be, ConfigReply *cr )
1955 1.1 lukem {
1956 1.1 lukem struct ldif_info *li;
1957 1.1 lukem
1958 1.1 lukem li = ch_calloc( 1, sizeof(struct ldif_info) );
1959 1.1 lukem be->be_private = li;
1960 1.1 lukem be->be_cf_ocs = ldifocs;
1961 1.1.1.2 lukem ldap_pvt_thread_mutex_init( &li->li_modop_mutex );
1962 1.1.1.2 lukem ldap_pvt_thread_rdwr_init( &li->li_rdwr );
1963 1.1 lukem SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_ONE_SUFFIX;
1964 1.1 lukem return 0;
1965 1.1 lukem }
1966 1.1 lukem
1967 1.1 lukem static int
1968 1.1 lukem ldif_back_db_destroy( Backend *be, ConfigReply *cr )
1969 1.1 lukem {
1970 1.1 lukem struct ldif_info *li = be->be_private;
1971 1.1 lukem
1972 1.1.1.2 lukem ch_free( li->li_base_path.bv_val );
1973 1.1.1.2 lukem ldap_pvt_thread_rdwr_destroy( &li->li_rdwr );
1974 1.1.1.2 lukem ldap_pvt_thread_mutex_destroy( &li->li_modop_mutex );
1975 1.1 lukem free( be->be_private );
1976 1.1 lukem return 0;
1977 1.1 lukem }
1978 1.1 lukem
1979 1.1 lukem static int
1980 1.1.1.2 lukem ldif_back_db_open( Backend *be, ConfigReply *cr )
1981 1.1 lukem {
1982 1.1 lukem struct ldif_info *li = (struct ldif_info *) be->be_private;
1983 1.1 lukem if( BER_BVISEMPTY(&li->li_base_path)) {/* missing base path */
1984 1.1.1.9 christos Debug( LDAP_DEBUG_ANY, "missing base path for back-ldif\n" );
1985 1.1 lukem return 1;
1986 1.1 lukem }
1987 1.1 lukem return 0;
1988 1.1 lukem }
1989 1.1 lukem
1990 1.1 lukem int
1991 1.1.1.2 lukem ldif_back_initialize( BackendInfo *bi )
1992 1.1 lukem {
1993 1.1 lukem static char *controls[] = {
1994 1.1 lukem LDAP_CONTROL_MANAGEDSAIT,
1995 1.1 lukem NULL
1996 1.1 lukem };
1997 1.1 lukem int rc;
1998 1.1 lukem
1999 1.1 lukem bi->bi_flags |=
2000 1.1 lukem SLAP_BFLAG_INCREMENT |
2001 1.1 lukem SLAP_BFLAG_REFERRALS;
2002 1.1 lukem
2003 1.1 lukem bi->bi_controls = controls;
2004 1.1 lukem
2005 1.1 lukem bi->bi_open = 0;
2006 1.1 lukem bi->bi_close = 0;
2007 1.1 lukem bi->bi_config = 0;
2008 1.1 lukem bi->bi_destroy = 0;
2009 1.1 lukem
2010 1.1 lukem bi->bi_db_init = ldif_back_db_init;
2011 1.1 lukem bi->bi_db_config = config_generic_wrapper;
2012 1.1 lukem bi->bi_db_open = ldif_back_db_open;
2013 1.1 lukem bi->bi_db_close = 0;
2014 1.1 lukem bi->bi_db_destroy = ldif_back_db_destroy;
2015 1.1 lukem
2016 1.1 lukem bi->bi_op_bind = ldif_back_bind;
2017 1.1 lukem bi->bi_op_unbind = 0;
2018 1.1 lukem bi->bi_op_search = ldif_back_search;
2019 1.1 lukem bi->bi_op_compare = 0;
2020 1.1 lukem bi->bi_op_modify = ldif_back_modify;
2021 1.1 lukem bi->bi_op_modrdn = ldif_back_modrdn;
2022 1.1 lukem bi->bi_op_add = ldif_back_add;
2023 1.1 lukem bi->bi_op_delete = ldif_back_delete;
2024 1.1 lukem bi->bi_op_abandon = 0;
2025 1.1 lukem
2026 1.1 lukem bi->bi_extended = 0;
2027 1.1 lukem
2028 1.1 lukem bi->bi_chk_referrals = ldif_back_referrals;
2029 1.1 lukem
2030 1.1 lukem bi->bi_connection_init = 0;
2031 1.1 lukem bi->bi_connection_destroy = 0;
2032 1.1 lukem
2033 1.1 lukem bi->bi_entry_get_rw = ldif_back_entry_get;
2034 1.1.1.9 christos bi->bi_entry_release_rw = ldif_back_entry_release_rw;
2035 1.1 lukem
2036 1.1 lukem #if 0 /* NOTE: uncomment to completely disable access control */
2037 1.1 lukem bi->bi_access_allowed = slap_access_always_allowed;
2038 1.1 lukem #endif
2039 1.1 lukem
2040 1.1 lukem bi->bi_tool_entry_open = ldif_tool_entry_open;
2041 1.1 lukem bi->bi_tool_entry_close = ldif_tool_entry_close;
2042 1.1.1.3 adam bi->bi_tool_entry_first = backend_tool_entry_first;
2043 1.1.1.3 adam bi->bi_tool_entry_first_x = ldif_tool_entry_first_x;
2044 1.1 lukem bi->bi_tool_entry_next = ldif_tool_entry_next;
2045 1.1.1.9 christos bi->bi_tool_dn2id_get = ldif_tool_dn2id_get;
2046 1.1 lukem bi->bi_tool_entry_get = ldif_tool_entry_get;
2047 1.1 lukem bi->bi_tool_entry_put = ldif_tool_entry_put;
2048 1.1.1.9 christos bi->bi_tool_entry_modify = ldif_tool_entry_modify;
2049 1.1.1.9 christos bi->bi_tool_entry_delete = ldif_tool_entry_delete;
2050 1.1 lukem bi->bi_tool_entry_reindex = 0;
2051 1.1 lukem bi->bi_tool_sync = 0;
2052 1.1.1.2 lukem
2053 1.1 lukem bi->bi_cf_ocs = ldifocs;
2054 1.1 lukem
2055 1.1 lukem rc = config_register_schema( ldifcfg, ldifocs );
2056 1.1 lukem if ( rc ) return rc;
2057 1.1 lukem return 0;
2058 1.1 lukem }
2059