~ubuntu-branches/ubuntu/maverick/openldap/maverick-proposed

« back to all changes in this revision

Viewing changes to servers/slapd/back-ldif/ldif.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathias Gug, Steve Langasek, Mathias Gug
  • Date: 2009-02-18 18:44:00 UTC
  • mfrom: (1.1.2 upstream) (0.1.2 lenny)
  • Revision ID: james.westby@ubuntu.com-20090218184400-zw4mjse9eywt5566
Tags: 2.4.14-0ubuntu1
[ Steve Langasek ]
* New upstream version
  - Fixes a bug with the pcache overlay not returning cached entries
    (closes: #497697)
  - Update evolution-ntlm patch to apply to current Makefiles.
  - (tentatively) drop gnutls-ciphers, since this bug was reported to be
    fixed upstream in 2.4.8.  The fix applied in 2.4.8 didn't match the
    patch from the bug report, so this should be watched for regressions.
* Build against db4.7 instead of db4.2 at last!  Closes: #421946.
* Build with --disable-ndb, to avoid a misbuild when libmysqlclient is
  installed in the build environment.
* New patch, no-crlcheck-for-gnutls, to fix a build failure when using
  --with-tls=gnutls.

[ Mathias Gug ]
* Merge from debian unstable, remaining changes:
  - debian/apparmor-profile: add AppArmor profile
  - debian/slapd.postinst: Reload AA profile on configuration
  - updated debian/slapd.README.Debian for note on AppArmor
  - debian/control: Recommends apparmor >= 2.1+1075-0ubuntu6
  - debian/control: Conflicts with apparmor-profiles << 2.1+1075-0ubuntu4
    to make sure that if earlier version of apparmour-profiles gets
    installed it won't overwrite our profile.
  - Modify Maintainer value to match the DebianMaintainerField
    speficication.
  - follow ApparmorProfileMigration and force apparmor compalin mode on 
    some upgrades (LP: #203529)
  - debian/slapd.dirs: add etc/apparmor.d/force-complain
  - debian/slapd.preinst: create symlink for force-complain on pre-feisty
    upgrades, upgrades where apparmor-profiles profile is unchanged (ie
    non-enforcing) and upgrades where apparmor profile does not exist.
  - debian/slapd.postrm: remove symlink in force-complain/ on purge
  - debian/patches/fix-ucred-libc due to changes how newer glibc handle
    the ucred struct now.
  - debian/control:
    - Build-depend on libltdl7-dev rather then libltdl3-dev.
  - debian/patches/autogen.sh:
    - Call libtoolize with the --install option to install config.{guess,sub}
      files.
  - Don't use local statement in config script as it fails if /bin/sh
    points to bash (LP: #286063).
  - Disable the testsuite on hppa. Allows building of packages on this
    architecture again, once this package is in the archive.
    LP: #288908.
  - debian/slapd.postinst, debian/slapd.script-common: set correct ownership
    and permissions on /var/lib/ldap, /etc/ldap/slapd.d (group readable) and
    /var/run/slapd (world readable). (LP: #257667).
  - debian/patches/nssov-build, debian/rules: 
    Build and package the nss overlay.
    debian/schema/misc.ldif: add ldif file for the misc schema, which defines
    rfc822MailMember (required by the nss overlay).
  - debian/{control,rules}: enable PIE hardening
  - Use cn=config as the default configuration backend instead of 
    slapd.conf. Migrate slapd.conf  file to /etc/ldap/slapd.d/ on upgrade
    asking the end user to enter a new password to control the access to the
    cn=config tree.
* debian/patches/corrupt-contextCSN: The contextCSN can get corrupted at
  times. (ITS: #5947)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* ldif.c - the ldif backend */
2
 
/* $OpenLDAP: pkg/ldap/servers/slapd/back-ldif/ldif.c,v 1.48.2.14 2008/04/21 18:53:52 quanah Exp $ */
 
2
/* $OpenLDAP: pkg/ldap/servers/slapd/back-ldif/ldif.c,v 1.48.2.19 2009/02/05 19:35:54 quanah Exp $ */
3
3
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4
4
 *
5
 
 * Copyright 2005-2008 The OpenLDAP Foundation.
 
5
 * Copyright 2005-2009 The OpenLDAP Foundation.
6
6
 * All rights reserved.
7
7
 *
8
8
 * Redistribution and use in source and binary forms, with or without
31
31
#include "lutil.h"
32
32
#include "config.h"
33
33
 
34
 
typedef struct enumCookie {
35
 
        Operation *op;
36
 
        SlapReply *rs;
37
 
        Entry **entries;
38
 
        int elen;
39
 
        int eind;
40
 
} enumCookie;
 
34
struct ldif_tool {
 
35
        Entry   **entries;                      /* collected by bi_tool_entry_first() */
 
36
        ID              elen;                           /* length of entries[] array */
 
37
        ID              ecount;                         /* number of entries */
 
38
        ID              ecurrent;                       /* bi_tool_entry_next() position */
 
39
#       define  ENTRY_BUFF_INCREMENT 500 /* initial entries[] length */
 
40
};
41
41
 
 
42
/* Per-database data */
42
43
struct ldif_info {
43
 
        struct berval li_base_path;
44
 
        enumCookie li_tool_cookie;
45
 
        ID li_tool_current;
46
 
        ldap_pvt_thread_rdwr_t  li_rdwr;
 
44
        struct berval li_base_path;                     /* database directory */
 
45
        struct ldif_tool li_tool;                       /* for slap tools */
 
46
        /*
 
47
         * Read-only LDAP requests readlock li_rdwr for filesystem input.
 
48
         * Update requests first lock li_modop_mutex for filesystem I/O,
 
49
         * and then writelock li_rdwr as well for filesystem output.
 
50
         * This allows update requests to do callbacks that acquire
 
51
         * read locks, e.g. access controls that inspect entries.
 
52
         * (An alternative would be recursive read/write locks.)
 
53
         */
 
54
        ldap_pvt_thread_mutex_t li_modop_mutex; /* serialize update requests */
 
55
        ldap_pvt_thread_rdwr_t  li_rdwr;        /* no other I/O when writing */
47
56
};
48
57
 
49
58
#ifdef _WIN32
50
59
#define mkdir(a,b)      mkdir(a)
 
60
#define move_file(from, to) (!MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING))
 
61
#else
 
62
#define move_file(from, to) rename(from, to)
51
63
#endif
 
64
#define move_dir(from, to) rename(from, to)
52
65
 
53
66
 
54
67
#define LDIF    ".ldif"
58
71
 * Unsafe/translated characters in the filesystem.
59
72
 *
60
73
 * LDIF_UNSAFE_CHAR(c) returns true if the character c is not to be used
61
 
 * in relative filenames, except it should accept '\\' even if unsafe and
62
 
 * need not reject '{' and '}'.  The value should be a constant expression.
 
74
 * in relative filenames, except it should accept '\\', '{' and '}' even
 
75
 * if unsafe.  The value should be a constant expression.
63
76
 *
64
77
 * If '\\' is unsafe, #define LDIF_ESCAPE_CHAR as a safe character.
65
 
 *
66
78
 * If '{' and '}' are unsafe, #define IX_FSL/IX_FSR as safe characters.
67
79
 * (Not digits, '-' or '+'.  IX_FSL == IX_FSR is allowed.)
68
80
 *
87
99
#else /* _WIN32 */
88
100
 
89
101
/* Windows version - Microsoft's list of unsafe characters, except '\\' */
90
 
#define LDIF_ESCAPE_CHAR        '^'
 
102
#define LDIF_ESCAPE_CHAR        '^'                     /* Not '\\' (unsafe on Windows) */
91
103
#define LDIF_UNSAFE_CHAR(c)     \
92
104
        ((c) == '/' || (c) == ':' || \
93
105
         (c) == '<' || (c) == '>' || (c) == '"' || \
132
144
        (!(LDIF_UNSAFE_CHAR(x) || (x) == '\\' || (x) == IX_DNL || (x) == IX_DNR) \
133
145
         && (c) == (x))
134
146
 
 
147
/* Collect other "safe char" tests here, until someone needs a fix. */
 
148
enum {
 
149
        eq_unsafe = LDIF_UNSAFE_CHAR('='),
 
150
        safe_filenames = STRLENOF("" LDAP_DIRSEP "") == 1 && !(
 
151
                LDIF_UNSAFE_CHAR('-') || /* for "{-1}frontend" in bconfig.c */
 
152
                LDIF_UNSAFE_CHAR(LDIF_ESCAPE_CHAR) ||
 
153
                LDIF_UNSAFE_CHAR(IX_FSL) || LDIF_UNSAFE_CHAR(IX_FSR))
 
154
};
 
155
/* Sanity check: Try to force a compilation error if !safe_filenames */
 
156
typedef struct {
 
157
        int assert_safe_filenames : safe_filenames ? 2 : -2;
 
158
} assert_safe_filenames[safe_filenames ? 2 : -2];
135
159
 
136
 
#define ENTRY_BUFF_INCREMENT 500
137
160
 
138
161
static ConfigTable ldifcfg[] = {
139
162
        { "directory", "dir", 2, 2, 0, ARG_BERVAL|ARG_OFFSET,
156
179
};
157
180
 
158
181
 
 
182
/*
 
183
 * Handle file/directory names.
 
184
 */
 
185
 
159
186
/* Set *res = LDIF filename path for the normalized DN */
160
187
static void
161
188
dn2path( BackendDB *be, struct berval *dn, struct berval *res )
215
242
        assert( res->bv_len <= len );
216
243
}
217
244
 
218
 
static char * slurp_file(int fd) {
219
 
        int read_chars_total = 0;
220
 
        int read_chars = 0;
221
 
        int entry_size;
222
 
        char * entry;
223
 
        char * entry_pos;
 
245
/*
 
246
 * *dest = dupbv(<dir + LDAP_DIRSEP>), plus room for <more>-sized filename.
 
247
 * Return pointer past the dirname.
 
248
 */
 
249
static char *
 
250
fullpath_alloc( struct berval *dest, const struct berval *dir, ber_len_t more )
 
251
{
 
252
        char *s = SLAP_MALLOC( dir->bv_len + more + 2 );
 
253
 
 
254
        dest->bv_val = s;
 
255
        if ( s == NULL ) {
 
256
                dest->bv_len = 0;
 
257
                Debug( LDAP_DEBUG_ANY, "back-ldif: out of memory\n", 0, 0, 0 );
 
258
        } else {
 
259
                s = lutil_strcopy( dest->bv_val, dir->bv_val );
 
260
                *s++ = LDAP_DIRSEP[0];
 
261
                *s = '\0';
 
262
                dest->bv_len = s - dest->bv_val;
 
263
        }
 
264
        return s;
 
265
}
 
266
 
 
267
/*
 
268
 * Append filename to fullpath_alloc() dirname or replace previous filename.
 
269
 * dir_end = fullpath_alloc() return value.
 
270
 */
 
271
#define FILL_PATH(fpath, dir_end, filename) \
 
272
        ((fpath)->bv_len = lutil_strcopy(dir_end, filename) - (fpath)->bv_val)
 
273
 
 
274
 
 
275
/* .ldif entry filename length <-> subtree dirname length. */
 
276
#define ldif2dir_len(bv)  ((bv).bv_len -= STRLENOF(LDIF))
 
277
#define dir2ldif_len(bv)  ((bv).bv_len += STRLENOF(LDIF))
 
278
/* .ldif entry filename <-> subtree dirname, both with dirname length. */
 
279
#define ldif2dir_name(bv) ((bv).bv_val[(bv).bv_len] = '\0')
 
280
#define dir2ldif_name(bv) ((bv).bv_val[(bv).bv_len] = LDIF_FILETYPE_SEP)
 
281
 
 
282
/* Get the parent directory path, plus the LDIF suffix overwritten by a \0. */
 
283
static int
 
284
get_parent_path( struct berval *dnpath, struct berval *res )
 
285
{
 
286
        ber_len_t i = dnpath->bv_len;
 
287
 
 
288
        while ( i > 0 && dnpath->bv_val[ --i ] != LDAP_DIRSEP[0] ) ;
 
289
        if ( res == NULL ) {
 
290
                res = dnpath;
 
291
        } else {
 
292
                res->bv_val = SLAP_MALLOC( i + 1 + STRLENOF(LDIF) );
 
293
                if ( res->bv_val == NULL )
 
294
                        return LDAP_OTHER;
 
295
                AC_MEMCPY( res->bv_val, dnpath->bv_val, i );
 
296
        }
 
297
        res->bv_len = i;
 
298
        strcpy( res->bv_val + i, LDIF );
 
299
        res->bv_val[i] = '\0';
 
300
        return LDAP_SUCCESS;
 
301
}
 
302
 
 
303
/* Make temporary filename pattern for mkstemp() based on dnpath. */
 
304
static char *
 
305
ldif_tempname( const struct berval *dnpath )
 
306
{
 
307
        static const char suffix[] = ".XXXXXX";
 
308
        ber_len_t len = dnpath->bv_len - STRLENOF( LDIF );
 
309
        char *name = SLAP_MALLOC( len + sizeof( suffix ) );
 
310
 
 
311
        if ( name != NULL ) {
 
312
                AC_MEMCPY( name, dnpath->bv_val, len );
 
313
                strcpy( name + len, suffix );
 
314
        }
 
315
        return name;
 
316
}
 
317
 
 
318
/*
 
319
 * Read a file, or stat() it if datap == NULL.  Allocate and fill *datap.
 
320
 * Return LDAP_SUCCESS, LDAP_NO_SUCH_OBJECT (no such file), or another error.
 
321
 */
 
322
static int
 
323
ldif_read_file( const char *path, char **datap )
 
324
{
 
325
        int rc, fd, len;
 
326
        int res = -1;   /* 0:success, <0:error, >0:file too big/growing. */
224
327
        struct stat st;
225
 
 
226
 
        fstat(fd, &st);
227
 
        entry_size = st.st_size;
228
 
        entry = ch_malloc( entry_size+1 );
229
 
        entry_pos = entry;
230
 
        
231
 
        while(1) {
232
 
                read_chars = read(fd, (void *) entry_pos, entry_size - read_chars_total);
233
 
                if(read_chars == -1) {
234
 
                        SLAP_FREE(entry);
235
 
                        return NULL;
236
 
                }
237
 
                if(read_chars == 0) {
238
 
                        entry[read_chars_total] = '\0';
239
 
                        break;
240
 
                }
241
 
                else {
242
 
                        read_chars_total += read_chars;
243
 
                        entry_pos += read_chars;
244
 
                }
245
 
        }
246
 
        return entry;
 
328
        char *data = NULL, *ptr;
 
329
 
 
330
        if ( datap == NULL ) {
 
331
                res = stat( path, &st );
 
332
                goto done;
 
333
        }
 
334
        fd = open( path, O_RDONLY );
 
335
        if ( fd >= 0 ) {
 
336
                if ( fstat( fd, &st ) == 0 ) {
 
337
                        if ( st.st_size > INT_MAX - 2 ) {
 
338
                                res = 1;
 
339
                        } else {
 
340
                                len = st.st_size + 1; /* +1 detects file size > st.st_size */
 
341
                                *datap = data = ptr = SLAP_MALLOC( len + 1 );
 
342
                                if ( ptr != NULL ) {
 
343
                                        while ( len && (res = read( fd, ptr, len )) ) {
 
344
                                                if ( res > 0 ) {
 
345
                                                        len -= res;
 
346
                                                        ptr += res;
 
347
                                                } else if ( errno != EINTR ) {
 
348
                                                        break;
 
349
                                                }
 
350
                                        }
 
351
                                        *ptr = '\0';
 
352
                                }
 
353
                        }
 
354
                }
 
355
                if ( close( fd ) < 0 )
 
356
                        res = -1;
 
357
        }
 
358
 
 
359
 done:
 
360
        if ( res == 0 ) {
 
361
                Debug( LDAP_DEBUG_TRACE, "ldif_read_file: %s: \"%s\"\n",
 
362
                        datap ? "read entry file" : "entry file exists", path, 0 );
 
363
                rc = LDAP_SUCCESS;
 
364
        } else {
 
365
                if ( res < 0 && errno == ENOENT ) {
 
366
                        Debug( LDAP_DEBUG_TRACE, "ldif_read_file: "
 
367
                                "no entry file \"%s\"\n", path, 0, 0 );
 
368
                        rc = LDAP_NO_SUCH_OBJECT;
 
369
                } else {
 
370
                        const char *msg = res < 0 ? STRERROR( errno ) : "bad stat() size";
 
371
                        Debug( LDAP_DEBUG_ANY, "ldif_read_file: %s for \"%s\"\n",
 
372
                                msg, path, 0 );
 
373
                        rc = LDAP_OTHER;
 
374
                }
 
375
                if ( data != NULL )
 
376
                        SLAP_FREE( data );
 
377
        }
 
378
        return rc;
247
379
}
248
380
 
249
381
/*
250
382
 * return nonnegative for success or -1 for error
251
383
 * do not return numbers less than -1
252
384
 */
253
 
static int spew_file(int fd, char * spew, int len) {
 
385
static int
 
386
spew_file( int fd, const char *spew, int len, int *save_errno )
 
387
{
254
388
        int writeres = 0;
255
 
        
 
389
 
256
390
        while(len > 0) {
257
391
                writeres = write(fd, spew, len);
258
392
                if(writeres == -1) {
259
 
                        return -1;
 
393
                        *save_errno = errno;
 
394
                        if (*save_errno != EINTR)
 
395
                                break;
260
396
                }
261
397
                else {
262
398
                        spew += writeres;
266
402
        return writeres;
267
403
}
268
404
 
 
405
/* Write an entry LDIF file.  Create parentdir first if non-NULL. */
269
406
static int
270
 
spew_entry( Entry * e, struct berval * path, int dolock, int *save_errnop )
 
407
ldif_write_entry(
 
408
        Operation *op,
 
409
        Entry *e,
 
410
        const struct berval *path,
 
411
        const char *parentdir,
 
412
        const char **text )
271
413
{
272
 
        int rs, save_errno = 0;
273
 
        int openres;
274
 
        int res, spew_res;
275
 
        int entry_length;
276
 
        char * entry_as_string;
277
 
        char *tmpfname = NULL;
278
 
 
279
 
        tmpfname = ch_malloc( path->bv_len + STRLENOF( "XXXXXX" ) + 1 );
280
 
        AC_MEMCPY( tmpfname, path->bv_val, path->bv_len );
281
 
        AC_MEMCPY( &tmpfname[ path->bv_len ], "XXXXXX", STRLENOF( "XXXXXX" ) + 1 );
282
 
 
283
 
        openres = mkstemp( tmpfname );
284
 
        if ( openres == -1 ) {
285
 
                save_errno = errno;
286
 
                rs = LDAP_UNWILLING_TO_PERFORM;
287
 
                Debug( LDAP_DEBUG_ANY, "could not create tmpfile \"%s\": %s\n",
288
 
                        tmpfname, STRERROR( save_errno ), 0 );
 
414
        int rc = LDAP_OTHER, res, save_errno = 0;
 
415
        int fd, entry_length;
 
416
        char *entry_as_string, *tmpfname;
 
417
 
 
418
        if ( op->o_abandon )
 
419
                return SLAPD_ABANDON;
 
420
 
 
421
        if ( parentdir != NULL && mkdir( parentdir, 0750 ) < 0 ) {
 
422
                save_errno = errno;
 
423
                Debug( LDAP_DEBUG_ANY, "ldif_write_entry: %s \"%s\": %s\n",
 
424
                        "cannot create parent directory",
 
425
                        parentdir, STRERROR( save_errno ) );
 
426
                *text = "internal error (cannot create parent directory)";
 
427
                return rc;
 
428
        }
 
429
 
 
430
        tmpfname = ldif_tempname( path );
 
431
        fd = tmpfname == NULL ? -1 : mkstemp( tmpfname );
 
432
        if ( fd < 0 ) {
 
433
                save_errno = errno;
 
434
                Debug( LDAP_DEBUG_ANY, "ldif_write_entry: %s for \"%s\": %s\n",
 
435
                        "cannot create file", e->e_dn, STRERROR( save_errno ) );
 
436
                *text = "internal error (cannot create file)";
289
437
 
290
438
        } else {
 
439
                ber_len_t dn_len = e->e_name.bv_len;
291
440
                struct berval rdn;
292
 
                int tmp;
293
441
 
294
442
                /* Only save the RDN onto disk */
295
443
                dnRdn( &e->e_name, &rdn );
296
 
                if ( rdn.bv_len != e->e_name.bv_len ) {
 
444
                if ( rdn.bv_len != dn_len ) {
297
445
                        e->e_name.bv_val[rdn.bv_len] = '\0';
298
 
                        tmp = e->e_name.bv_len;
299
446
                        e->e_name.bv_len = rdn.bv_len;
300
 
                        rdn.bv_len = tmp;
301
 
                }
302
 
 
303
 
                spew_res = -2;
304
 
                if ( dolock ) {
305
 
                        ldap_pvt_thread_mutex_lock(&entry2str_mutex);
306
 
                }
307
 
 
308
 
                entry_as_string = entry2str(e, &entry_length);
309
 
                if ( entry_as_string != NULL ) {
310
 
                        spew_res = spew_file( openres,
311
 
                                entry_as_string, entry_length );
312
 
                        if ( spew_res == -1 ) {
313
 
                                save_errno = errno;
314
 
                        }
315
 
                }
316
 
 
317
 
                if ( dolock ) {
318
 
                        ldap_pvt_thread_mutex_unlock(&entry2str_mutex);
319
 
                }
 
447
                }
 
448
 
 
449
                res = -2;
 
450
                ldap_pvt_thread_mutex_lock( &entry2str_mutex );
 
451
                entry_as_string = entry2str( e, &entry_length );
 
452
                if ( entry_as_string != NULL )
 
453
                        res = spew_file( fd, entry_as_string, entry_length, &save_errno );
 
454
                ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
320
455
 
321
456
                /* Restore full DN */
322
 
                if ( rdn.bv_len != e->e_name.bv_len ) {
323
 
                        e->e_name.bv_val[e->e_name.bv_len] = ',';
324
 
                        e->e_name.bv_len = rdn.bv_len;
325
 
                }
326
 
 
327
 
                res = close( openres );
328
 
                rs = LDAP_UNWILLING_TO_PERFORM;
329
 
 
330
 
                if ( spew_res > -2 ) {
331
 
                        if ( res == -1 || spew_res == -1 ) {
332
 
                                if ( save_errno == 0 ) {
333
 
                                        save_errno = errno;
334
 
                                }
335
 
                                Debug( LDAP_DEBUG_ANY, "write error to tmpfile \"%s\": %s\n",
336
 
                                        tmpfname, STRERROR( save_errno ), 0 );
337
 
 
 
457
                if ( rdn.bv_len != dn_len ) {
 
458
                        e->e_name.bv_val[rdn.bv_len] = ',';
 
459
                        e->e_name.bv_len = dn_len;
 
460
                }
 
461
 
 
462
                if ( close( fd ) < 0 && res >= 0 ) {
 
463
                        res = -1;
 
464
                        save_errno = errno;
 
465
                }
 
466
 
 
467
                if ( res >= 0 ) {
 
468
                        if ( move_file( tmpfname, path->bv_val ) == 0 ) {
 
469
                                Debug( LDAP_DEBUG_TRACE, "ldif_write_entry: "
 
470
                                        "wrote entry \"%s\"\n", e->e_name.bv_val, 0, 0 );
 
471
                                rc = LDAP_SUCCESS;
338
472
                        } else {
339
 
                                res = rename( tmpfname, path->bv_val );
340
 
                                if ( res == 0 ) {
341
 
                                        rs = LDAP_SUCCESS;
342
 
 
343
 
                                } else {
344
 
                                        save_errno = errno;
345
 
                                        switch ( save_errno ) {
346
 
                                        case ENOENT:
347
 
                                                rs = LDAP_NO_SUCH_OBJECT;
348
 
                                                break;
349
 
 
350
 
                                        default:
351
 
                                                break;
352
 
                                        }
353
 
                                }
 
473
                                save_errno = errno;
 
474
                                Debug( LDAP_DEBUG_ANY, "ldif_write_entry: "
 
475
                                        "could not put entry file for \"%s\" in place: %s\n",
 
476
                                        e->e_name.bv_val, STRERROR( save_errno ), 0 );
 
477
                                *text = "internal error (could not put entry file in place)";
354
478
                        }
 
479
                } else if ( res == -1 ) {
 
480
                        Debug( LDAP_DEBUG_ANY, "ldif_write_entry: %s \"%s\": %s\n",
 
481
                                "write error to", tmpfname, STRERROR( save_errno ) );
 
482
                        *text = "internal error (write error to entry file)";
355
483
                }
356
484
 
357
 
                if ( rs != LDAP_SUCCESS ) {
 
485
                if ( rc != LDAP_SUCCESS ) {
358
486
                        unlink( tmpfname );
359
487
                }
360
488
        }
361
489
 
362
 
        ch_free( tmpfname );
363
 
 
364
 
        if ( rs != LDAP_SUCCESS && save_errnop != NULL ) {
365
 
                *save_errnop = save_errno;
366
 
        }
367
 
 
368
 
        return rs;
 
490
        if ( tmpfname )
 
491
                SLAP_FREE( tmpfname );
 
492
        return rc;
369
493
}
370
494
 
371
 
static Entry * get_entry_for_fd(int fd,
 
495
/*
 
496
 * Read the entry at path, or if entryp==NULL just see if it exists.
 
497
 * pdn and pndn are the parent's DN and normalized DN, or both NULL.
 
498
 * Return an LDAP result code.
 
499
 */
 
500
static int
 
501
ldif_read_entry(
 
502
        Operation *op,
 
503
        const char *path,
372
504
        struct berval *pdn,
373
 
        struct berval *pndn)
 
505
        struct berval *pndn,
 
506
        Entry **entryp,
 
507
        const char **text )
374
508
{
375
 
        char * entry = (char *) slurp_file(fd);
376
 
        Entry * ldentry = NULL;
377
 
        
378
 
        /* error reading file */
379
 
        if(entry == NULL) {
380
 
                goto return_value;
381
 
        }
382
 
 
383
 
        ldentry = str2entry(entry);
384
 
        if ( ldentry ) {
385
 
                struct berval rdn;
386
 
                rdn = ldentry->e_name;
387
 
                build_new_dn( &ldentry->e_name, pdn, &rdn, NULL );
388
 
                ch_free( rdn.bv_val );
389
 
                rdn = ldentry->e_nname;
390
 
                build_new_dn( &ldentry->e_nname, pndn, &rdn, NULL );
391
 
                ch_free( rdn.bv_val );
392
 
        }
393
 
 
394
 
 return_value:
395
 
        if(fd != -1) {
396
 
                if(close(fd) != 0) {
397
 
                        /* log error */
 
509
        int rc;
 
510
        Entry *entry;
 
511
        char *entry_as_string;
 
512
        struct berval rdn;
 
513
 
 
514
        /* TODO: Does slapd prevent Abandon of Bind as per rfc4511?
 
515
         * If so we need not check for LDAP_REQ_BIND here.
 
516
         */
 
517
        if ( op->o_abandon && op->o_tag != LDAP_REQ_BIND )
 
518
                return SLAPD_ABANDON;
 
519
 
 
520
        rc = ldif_read_file( path, entryp ? &entry_as_string : NULL );
 
521
 
 
522
        switch ( rc ) {
 
523
        case LDAP_SUCCESS:
 
524
                if ( entryp == NULL )
 
525
                        break;
 
526
                *entryp = entry = str2entry( entry_as_string );
 
527
                SLAP_FREE( entry_as_string );
 
528
                if ( entry == NULL ) {
 
529
                        rc = LDAP_OTHER;
 
530
                        if ( text != NULL )
 
531
                                *text = "internal error (cannot parse some entry file)";
 
532
                        break;
398
533
                }
 
534
                if ( pdn == NULL || BER_BVISEMPTY( pdn ) )
 
535
                        break;
 
536
                /* Append parent DN to DN from LDIF file */
 
537
                rdn = entry->e_name;
 
538
                build_new_dn( &entry->e_name, pdn, &rdn, NULL );
 
539
                SLAP_FREE( rdn.bv_val );
 
540
                rdn = entry->e_nname;
 
541
                build_new_dn( &entry->e_nname, pndn, &rdn, NULL );
 
542
                SLAP_FREE( rdn.bv_val );
 
543
                break;
 
544
 
 
545
        case LDAP_OTHER:
 
546
                if ( text != NULL )
 
547
                        *text = entryp
 
548
                                ? "internal error (cannot read some entry file)"
 
549
                                : "internal error (cannot stat some entry file)";
 
550
                break;
399
551
        }
400
 
        if(entry != NULL)
401
 
                SLAP_FREE(entry);
402
 
        return ldentry;
 
552
 
 
553
        return rc;
403
554
}
404
555
 
 
556
/*
 
557
 * Read the operation's entry, or if entryp==NULL just see if it exists.
 
558
 * Return an LDAP result code.  May set *text to a message on failure.
 
559
 * If pathp is non-NULL, set it to the entry filename on success.
 
560
 */
405
561
static int
406
562
get_entry(
407
563
        Operation *op,
408
564
        Entry **entryp,
409
 
        struct berval *pathp )
 
565
        struct berval *pathp,
 
566
        const char **text )
410
567
{
411
568
        int rc;
412
569
        struct berval path, pdn, pndn;
413
 
        int fd;
414
570
 
415
 
        dnParent(&op->o_req_dn, &pdn);
416
 
        dnParent(&op->o_req_ndn, &pndn);
 
571
        dnParent( &op->o_req_dn, &pdn );
 
572
        dnParent( &op->o_req_ndn, &pndn );
417
573
        dn2path( op->o_bd, &op->o_req_ndn, &path );
418
 
        fd = open(path.bv_val, O_RDONLY);
419
 
        /* error opening file (mebbe should log error) */
420
 
        if ( fd == -1 && ( errno != ENOENT || op->o_tag != LDAP_REQ_ADD ) ) {
421
 
                Debug( LDAP_DEBUG_ANY, "failed to open file \"%s\": %s\n",
422
 
                        path.bv_val, STRERROR(errno), 0 );
423
 
        }
424
 
        *entryp = fd < 0 ? NULL : get_entry_for_fd( fd, &pdn, &pndn );
425
 
        rc = *entryp ? LDAP_SUCCESS : LDAP_NO_SUCH_OBJECT;
 
574
        rc = ldif_read_entry( op, path.bv_val, &pdn, &pndn, entryp, text );
426
575
 
427
576
        if ( rc == LDAP_SUCCESS && pathp != NULL ) {
428
577
                *pathp = path;
429
578
        } else {
430
 
                SLAP_FREE(path.bv_val);
 
579
                SLAP_FREE( path.bv_val );
431
580
        }
432
581
        return rc;
433
582
}
434
583
 
435
 
static void fullpath(struct berval *base, struct berval *name, struct berval *res) {
436
 
        char *ptr;
437
 
        res->bv_len = name->bv_len + base->bv_len + 1;
438
 
        res->bv_val = ch_malloc( res->bv_len + 1 );
439
 
        strcpy(res->bv_val, base->bv_val);
440
 
        ptr = res->bv_val + base->bv_len;
441
 
        *ptr++ = LDAP_DIRSEP[0];
442
 
        strcpy(ptr, name->bv_val);
443
 
}
444
584
 
 
585
/*
 
586
 * RDN-named directory entry, with special handling of "attr={num}val" RDNs.
 
587
 * For sorting, filename "attr=val.ldif" is truncated to "attr="val\0ldif",
 
588
 * and filename "attr={num}val.ldif" to "attr={\0um}val.ldif".
 
589
 * Does not sort escaped chars correctly, would need to un-escape them.
 
590
 */
445
591
typedef struct bvlist {
446
592
        struct bvlist *next;
447
 
        struct berval bv;
448
 
        struct berval num;
449
 
        int inum;
450
 
        int off;
 
593
        char *trunc;    /* filename was truncated here */
 
594
        int  inum;              /* num from "attr={num}" in filename, or INT_MIN */
 
595
        char savech;    /* original char at *trunc */
 
596
        char fname;             /* variable length array BVL_NAME(bvl) = &fname */
 
597
#       define BVL_NAME(bvl) ((char *) (bvl) + offsetof(bvlist, fname))
 
598
#       define BVL_SIZE(namelen) (sizeof(bvlist) + (namelen))
451
599
} bvlist;
452
600
 
453
 
 
454
 
static int r_enum_tree(enumCookie *ck, struct berval *path, int base,
455
 
        struct berval *pdn, struct berval *pndn)
 
601
static int
 
602
ldif_send_entry( Operation *op, SlapReply *rs, Entry *e, int scope )
456
603
{
457
 
        Entry *e = NULL;
458
 
        int fd = 0, rc = LDAP_SUCCESS;
459
 
 
460
 
        if ( !base ) {
461
 
                fd = open( path->bv_val, O_RDONLY );
462
 
                if ( fd < 0 ) {
463
 
                        Debug( LDAP_DEBUG_TRACE,
464
 
                                "=> ldif_enum_tree: failed to open %s: %s\n",
465
 
                                path->bv_val, STRERROR(errno), 0 );
466
 
                        return LDAP_NO_SUCH_OBJECT;
467
 
                }
468
 
 
469
 
                e = get_entry_for_fd(fd, pdn, pndn);
470
 
                if ( !e ) {
471
 
                        Debug( LDAP_DEBUG_ANY,
472
 
                                "=> ldif_enum_tree: failed to read entry for %s\n",
473
 
                                path->bv_val, 0, 0 );
474
 
                        return LDAP_BUSY;
475
 
                }
476
 
 
477
 
                if ( ck->op->ors_scope == LDAP_SCOPE_BASE ||
478
 
                        ck->op->ors_scope == LDAP_SCOPE_SUBTREE ) {
479
 
                        /* Send right away? */
480
 
                        if ( ck->rs ) {
481
 
                                /*
482
 
                                 * if it's a referral, add it to the list of referrals. only do
483
 
                                 * this for non-base searches, and don't check the filter
484
 
                                 * explicitly here since it's only a candidate anyway.
485
 
                                 */
486
 
                                if ( !get_manageDSAit( ck->op )
487
 
                                                && ck->op->ors_scope != LDAP_SCOPE_BASE
488
 
                                                && is_entry_referral( e ) )
489
 
                                {
490
 
                                        BerVarray erefs = get_entry_referrals( ck->op, e );
491
 
                                        ck->rs->sr_ref = referral_rewrite( erefs,
492
 
                                                        &e->e_name, NULL,
493
 
                                                        ck->op->oq_search.rs_scope == LDAP_SCOPE_ONELEVEL
494
 
                                                                ? LDAP_SCOPE_BASE : LDAP_SCOPE_SUBTREE );
495
 
        
496
 
                                        ck->rs->sr_entry = e;
497
 
                                        rc = send_search_reference( ck->op, ck->rs );
498
 
                                        ber_bvarray_free( ck->rs->sr_ref );
499
 
                                        ber_bvarray_free( erefs );
500
 
                                        ck->rs->sr_ref = NULL;
501
 
                                        ck->rs->sr_entry = NULL;
502
 
        
503
 
                                } else if ( test_filter( ck->op, e, ck->op->ors_filter ) == LDAP_COMPARE_TRUE )
504
 
                                {
505
 
                                        ck->rs->sr_entry = e;
506
 
                                        ck->rs->sr_attrs = ck->op->ors_attrs;
507
 
                                        ck->rs->sr_flags = REP_ENTRY_MODIFIABLE;
508
 
                                        rc = send_search_entry(ck->op, ck->rs);
509
 
                                        ck->rs->sr_entry = NULL;
510
 
                                }
511
 
                                fd = 1;
512
 
                                if ( rc )
 
604
        int rc = LDAP_SUCCESS;
 
605
 
 
606
        if ( scope == LDAP_SCOPE_BASE || scope == LDAP_SCOPE_SUBTREE ) {
 
607
                if ( rs == NULL ) {
 
608
                        /* Save the entry for tool mode */
 
609
                        struct ldif_tool *tl =
 
610
                                &((struct ldif_info *) op->o_bd->be_private)->li_tool;
 
611
 
 
612
                        if ( tl->ecount >= tl->elen ) {
 
613
                                /* Allocate/grow entries */
 
614
                                ID elen = tl->elen ? tl->elen * 2 : ENTRY_BUFF_INCREMENT;
 
615
                                Entry **entries = (Entry **) SLAP_REALLOC( tl->entries,
 
616
                                        sizeof(Entry *) * elen );
 
617
                                if ( entries == NULL ) {
 
618
                                        Debug( LDAP_DEBUG_ANY,
 
619
                                                "ldif_send_entry: out of memory\n", 0, 0, 0 );
 
620
                                        rc = LDAP_OTHER;
513
621
                                        goto done;
514
 
                        } else {
515
 
                        /* Queueing up for tool mode */
516
 
                                if(ck->entries == NULL) {
517
 
                                        ck->entries = (Entry **) ch_malloc(sizeof(Entry *) * ENTRY_BUFF_INCREMENT);
518
 
                                        ck->elen = ENTRY_BUFF_INCREMENT;
519
 
                                }
520
 
                                if(ck->eind >= ck->elen) { /* grow entries if necessary */      
521
 
                                        ck->entries = (Entry **) ch_realloc(ck->entries, sizeof(Entry *) * (ck->elen) * 2);
522
 
                                        ck->elen *= 2;
523
 
                                }
524
 
        
525
 
                                ck->entries[ck->eind++] = e;
526
 
                                fd = 0;
 
622
                                }
 
623
                                tl->elen = elen;
 
624
                                tl->entries = entries;
527
625
                        }
528
 
                } else {
529
 
                        fd = 1;
 
626
                        tl->entries[tl->ecount++] = e;
 
627
                        return rc;
 
628
                }
 
629
 
 
630
                else if ( !get_manageDSAit( op ) && is_entry_referral( e ) ) {
 
631
                        /* Send a continuation reference.
 
632
                         * (ldif_back_referrals() handles baseobject referrals.)
 
633
                         * Don't check the filter since it's only a candidate.
 
634
                         */
 
635
                        BerVarray refs = get_entry_referrals( op, e );
 
636
                        rs->sr_ref = referral_rewrite( refs, &e->e_name, NULL, scope );
 
637
                        rs->sr_entry = e;
 
638
                        rc = send_search_reference( op, rs );
 
639
                        ber_bvarray_free( rs->sr_ref );
 
640
                        ber_bvarray_free( refs );
 
641
                        rs->sr_ref = NULL;
 
642
                        rs->sr_entry = NULL;
 
643
                }
 
644
 
 
645
                else if ( test_filter( op, e, op->ors_filter ) == LDAP_COMPARE_TRUE ) {
 
646
                        rs->sr_entry = e;
 
647
                        rs->sr_attrs = op->ors_attrs;
 
648
                        rs->sr_flags = REP_ENTRY_MODIFIABLE;
 
649
                        rc = send_search_entry( op, rs );
 
650
                        rs->sr_entry = NULL;
530
651
                }
531
652
        }
532
653
 
533
 
        if ( ck->op->ors_scope != LDAP_SCOPE_BASE ) {
534
 
                DIR * dir_of_path;
535
 
                bvlist *list = NULL, *ptr;
536
 
 
537
 
                path->bv_len -= STRLENOF( LDIF );
538
 
                path->bv_val[path->bv_len] = '\0';
539
 
 
540
 
                dir_of_path = opendir(path->bv_val);
541
 
                if(dir_of_path == NULL) { /* can't open directory */
542
 
                        if ( errno != ENOENT ) {
543
 
                                /* it shouldn't be treated as an error
544
 
                                 * only if the directory doesn't exist */
545
 
                                rc = LDAP_BUSY;
546
 
                                Debug( LDAP_DEBUG_ANY,
547
 
                                        "=> ldif_enum_tree: failed to opendir %s (%d)\n",
548
 
                                        path->bv_val, errno, 0 );
549
 
                        }
550
 
                        goto done;
 
654
 done:
 
655
        entry_free( e );
 
656
        return rc;
 
657
}
 
658
 
 
659
/* Read LDIF directory <path> into <listp>.  Set *fname_maxlenp. */
 
660
static int
 
661
ldif_readdir(
 
662
        Operation *op,
 
663
        SlapReply *rs,
 
664
        const struct berval *path,
 
665
        bvlist **listp,
 
666
        ber_len_t *fname_maxlenp )
 
667
{
 
668
        int rc = LDAP_SUCCESS;
 
669
        DIR *dir_of_path;
 
670
 
 
671
        *listp = NULL;
 
672
        *fname_maxlenp = 0;
 
673
 
 
674
        dir_of_path = opendir( path->bv_val );
 
675
        if ( dir_of_path == NULL ) {
 
676
                int save_errno = errno;
 
677
                struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
 
678
                int is_rootDSE = (path->bv_len == li->li_base_path.bv_len);
 
679
 
 
680
                /* Absent directory is OK (leaf entry), except the database dir */
 
681
                if ( is_rootDSE || save_errno != ENOENT ) {
 
682
                        Debug( LDAP_DEBUG_ANY,
 
683
                                "=> ldif_search_entry: failed to opendir \"%s\": %s\n",
 
684
                                path->bv_val, STRERROR( save_errno ), 0 );
 
685
                        rc = LDAP_OTHER;
 
686
                        if ( rs != NULL )
 
687
                                rs->sr_text =
 
688
                                        save_errno != ENOENT ? "internal error (bad directory)"
 
689
                                        : !is_rootDSE ? "internal error (missing directory)"
 
690
                                        : "internal error (database directory does not exist)";
551
691
                }
552
 
        
553
 
                while(1) {
554
 
                        struct berval fname, itmp;
555
 
                        struct dirent * dir;
 
692
 
 
693
        } else {
 
694
                bvlist *ptr;
 
695
                struct dirent *dir;
 
696
                int save_errno = 0;
 
697
 
 
698
                while ( (dir = readdir( dir_of_path )) != NULL ) {
 
699
                        size_t fname_len;
556
700
                        bvlist *bvl, **prev;
557
 
 
558
 
                        dir = readdir(dir_of_path);
559
 
                        if(dir == NULL) break; /* end of the directory */
560
 
                        fname.bv_len = strlen( dir->d_name );
561
 
                        if ( fname.bv_len <= STRLENOF( LDIF ))
562
 
                                continue;
563
 
                        if ( strcmp( dir->d_name + (fname.bv_len - STRLENOF(LDIF)), LDIF))
564
 
                                continue;
565
 
                        fname.bv_val = dir->d_name;
566
 
 
567
 
                        bvl = ch_malloc( sizeof(bvlist) );
568
 
                        ber_dupbv( &bvl->bv, &fname );
569
 
                        BER_BVZERO( &bvl->num );
570
 
                        itmp.bv_val = ber_bvchr( &bvl->bv, IX_FSL );
571
 
                        if ( itmp.bv_val ) {
572
 
                                char *ptr;
573
 
                                itmp.bv_val++;
574
 
                                itmp.bv_len = bvl->bv.bv_len
575
 
                                        - ( itmp.bv_val - bvl->bv.bv_val );
576
 
                                ptr = ber_bvchr( &itmp, IX_FSR );
577
 
                                if ( ptr ) {
578
 
                                        itmp.bv_len = ptr - itmp.bv_val;
579
 
                                        ber_dupbv( &bvl->num, &itmp );
580
 
                                        bvl->inum = strtol( itmp.bv_val, NULL, 0 );
581
 
                                        itmp.bv_val[0] = '\0';
582
 
                                        bvl->off = itmp.bv_val - bvl->bv.bv_val;
 
701
                        char *trunc, *idxp, *endp, *endp2;
 
702
 
 
703
                        fname_len = strlen( dir->d_name );
 
704
                        if ( fname_len < STRLENOF( "x=" LDIF )) /* min filename size */
 
705
                                continue;
 
706
                        if ( strcmp( dir->d_name + fname_len - STRLENOF(LDIF), LDIF ))
 
707
                                continue;
 
708
 
 
709
                        if ( *fname_maxlenp < fname_len )
 
710
                                *fname_maxlenp = fname_len;
 
711
 
 
712
                        bvl = SLAP_MALLOC( BVL_SIZE( fname_len ) );
 
713
                        if ( bvl == NULL ) {
 
714
                                rc = LDAP_OTHER;
 
715
                                save_errno = errno;
 
716
                                break;
 
717
                        }
 
718
                        strcpy( BVL_NAME( bvl ), dir->d_name );
 
719
 
 
720
                        /* Make it sortable by ("attr=val" or <preceding {num}, num>) */
 
721
                        trunc = BVL_NAME( bvl ) + fname_len - STRLENOF( LDIF );
 
722
                        if ( (idxp = strchr( BVL_NAME( bvl ) + 2, IX_FSL )) != NULL &&
 
723
                                 (endp = strchr( ++idxp, IX_FSR )) != NULL && endp > idxp &&
 
724
                                 (eq_unsafe || idxp[-2] == '=' || endp + 1 == trunc) )
 
725
                        {
 
726
                                /* attr={n}val or bconfig.c's "pseudo-indexed" attr=val{n} */
 
727
                                bvl->inum = strtol( idxp, &endp2, 10 );
 
728
                                if ( endp2 == endp ) {
 
729
                                        trunc = idxp;
 
730
                                        goto truncate;
583
731
                                }
584
732
                        }
 
733
                        bvl->inum = INT_MIN;
 
734
                truncate:
 
735
                        bvl->trunc = trunc;
 
736
                        bvl->savech = *trunc;
 
737
                        *trunc = '\0';
585
738
 
586
 
                        for (prev = &list; (ptr = *prev) != NULL; prev = &ptr->next) {
587
 
                                int cmp = strcmp( bvl->bv.bv_val, ptr->bv.bv_val );
588
 
                                if ( !cmp && bvl->num.bv_val )
589
 
                                        cmp = bvl->inum - ptr->inum;
590
 
                                if ( cmp < 0 )
 
739
                        for ( prev = listp; (ptr = *prev) != NULL; prev = &ptr->next ) {
 
740
                                int cmp = strcmp( BVL_NAME( bvl ), BVL_NAME( ptr ));
 
741
                                if ( cmp < 0 || (cmp == 0 && bvl->inum < ptr->inum) )
591
742
                                        break;
592
743
                        }
593
744
                        *prev = bvl;
594
745
                        bvl->next = ptr;
595
 
                                
596
 
                }
597
 
                closedir(dir_of_path);
598
 
 
599
 
                if (ck->op->ors_scope == LDAP_SCOPE_ONELEVEL)
600
 
                        ck->op->ors_scope = LDAP_SCOPE_BASE;
601
 
                else if ( ck->op->ors_scope == LDAP_SCOPE_SUBORDINATE)
602
 
                        ck->op->ors_scope = LDAP_SCOPE_SUBTREE;
603
 
 
604
 
                while ( ( ptr = list ) ) {
605
 
                        struct berval fpath;
606
 
 
607
 
                        list = ptr->next;
608
 
 
609
 
                        if ( rc == LDAP_SUCCESS ) {
610
 
                                if ( ptr->num.bv_val )
611
 
                                        AC_MEMCPY( ptr->bv.bv_val + ptr->off, ptr->num.bv_val,
612
 
                                                ptr->num.bv_len );
613
 
                                fullpath( path, &ptr->bv, &fpath );
614
 
                                rc = r_enum_tree(ck, &fpath, 0,
615
 
                                        e != NULL ? &e->e_name : pdn,
616
 
                                        e != NULL ? &e->e_nname : pndn );
617
 
                                free(fpath.bv_val);
618
 
                        }
619
 
                        if ( ptr->num.bv_val )
620
 
                                free( ptr->num.bv_val );
621
 
                        free(ptr->bv.bv_val);
622
 
                        free(ptr);
623
 
                }
624
 
        }
625
 
done:
626
 
        if ( fd ) entry_free( e );
627
 
        return rc;
628
 
}
629
 
 
630
 
static int
631
 
enum_tree(
632
 
        enumCookie *ck
633
 
)
634
 
{
 
746
                }
 
747
 
 
748
                if ( closedir( dir_of_path ) < 0 ) {
 
749
                        save_errno = errno;
 
750
                        rc = LDAP_OTHER;
 
751
                        if ( rs != NULL )
 
752
                                rs->sr_text = "internal error (bad directory)";
 
753
                }
 
754
                if ( rc != LDAP_SUCCESS ) {
 
755
                        Debug( LDAP_DEBUG_ANY, "ldif_search_entry: %s \"%s\": %s\n",
 
756
                                "error reading directory", path->bv_val,
 
757
                                STRERROR( save_errno ) );
 
758
                }
 
759
        }
 
760
 
 
761
        return rc;
 
762
}
 
763
 
 
764
/*
 
765
 * Send an entry, recursively search its children, and free or save it.
 
766
 * Return an LDAP result code.  Parameters:
 
767
 *  op, rs  operation and reply.  rs == NULL for slap tools.
 
768
 *  e       entry to search, or NULL for rootDSE.
 
769
 *  scope   scope for the part of the search from this entry.
 
770
 *  path    LDIF filename -- bv_len and non-directory part are overwritten.
 
771
 */
 
772
static int
 
773
ldif_search_entry(
 
774
        Operation *op,
 
775
        SlapReply *rs,
 
776
        Entry *e,
 
777
        int scope,
 
778
        struct berval *path )
 
779
{
 
780
        int rc = LDAP_SUCCESS;
 
781
        struct berval dn = BER_BVC( "" ), ndn = BER_BVC( "" );
 
782
 
 
783
        if ( scope != LDAP_SCOPE_BASE && e != NULL ) {
 
784
                /* Copy DN/NDN since we send the entry with REP_ENTRY_MODIFIABLE,
 
785
                 * which bconfig.c seems to need.  (TODO: see config_rename_one.)
 
786
                 */
 
787
                if ( ber_dupbv( &dn,  &e->e_name  ) == NULL ||
 
788
                         ber_dupbv( &ndn, &e->e_nname ) == NULL )
 
789
                {
 
790
                        Debug( LDAP_DEBUG_ANY,
 
791
                                "ldif_search_entry: out of memory\n", 0, 0, 0 );
 
792
                        rc = LDAP_OTHER;
 
793
                        goto done;
 
794
                }
 
795
        }
 
796
 
 
797
        /* Send the entry if appropriate, and free or save it */
 
798
        if ( e != NULL )
 
799
                rc = ldif_send_entry( op, rs, e, scope );
 
800
 
 
801
        /* Search the children */
 
802
        if ( scope != LDAP_SCOPE_BASE && rc == LDAP_SUCCESS ) {
 
803
                bvlist *list, *ptr;
 
804
                struct berval fpath;    /* becomes child pathname */
 
805
                char *dir_end;  /* will point past dirname in fpath */
 
806
 
 
807
                ldif2dir_len( *path );
 
808
                ldif2dir_name( *path );
 
809
                rc = ldif_readdir( op, rs, path, &list, &fpath.bv_len );
 
810
 
 
811
                if ( list != NULL ) {
 
812
                        const char **text = rs == NULL ? NULL : &rs->sr_text;
 
813
 
 
814
                        if ( scope == LDAP_SCOPE_ONELEVEL )
 
815
                                scope = LDAP_SCOPE_BASE;
 
816
                        else if ( scope == LDAP_SCOPE_SUBORDINATE )
 
817
                                scope = LDAP_SCOPE_SUBTREE;
 
818
 
 
819
                        /* Allocate fpath and fill in directory part */
 
820
                        dir_end = fullpath_alloc( &fpath, path, fpath.bv_len );
 
821
                        if ( dir_end == NULL )
 
822
                                rc = LDAP_OTHER;
 
823
 
 
824
                        do {
 
825
                                ptr = list;
 
826
 
 
827
                                if ( rc == LDAP_SUCCESS ) {
 
828
                                        *ptr->trunc = ptr->savech;
 
829
                                        FILL_PATH( &fpath, dir_end, BVL_NAME( ptr ));
 
830
 
 
831
                                        rc = ldif_read_entry( op, fpath.bv_val, &dn, &ndn,
 
832
                                                &e, text );
 
833
                                        switch ( rc ) {
 
834
                                        case LDAP_SUCCESS:
 
835
                                                rc = ldif_search_entry( op, rs, e, scope, &fpath );
 
836
                                                break;
 
837
                                        case LDAP_NO_SUCH_OBJECT:
 
838
                                                /* Only the search baseDN may produce noSuchObject. */
 
839
                                                rc = LDAP_OTHER;
 
840
                                                if ( rs != NULL )
 
841
                                                        rs->sr_text = "internal error "
 
842
                                                                "(did someone just remove an entry file?)";
 
843
                                                Debug( LDAP_DEBUG_ANY, "ldif_search_entry: "
 
844
                                                        "file listed in parent directory does not exist: "
 
845
                                                        "\"%s\"\n", fpath.bv_val, 0, 0 );
 
846
                                                break;
 
847
                                        }
 
848
                                }
 
849
 
 
850
                                list = ptr->next;
 
851
                                SLAP_FREE( ptr );
 
852
                        } while ( list != NULL );
 
853
 
 
854
                        if ( !BER_BVISNULL( &fpath ) )
 
855
                                SLAP_FREE( fpath.bv_val );
 
856
                }
 
857
        }
 
858
 
 
859
 done:
 
860
        if ( !BER_BVISEMPTY( &dn ) )
 
861
                ber_memfree( dn.bv_val );
 
862
        if ( !BER_BVISEMPTY( &ndn ) )
 
863
                ber_memfree( ndn.bv_val );
 
864
        return rc;
 
865
}
 
866
 
 
867
static int
 
868
search_tree( Operation *op, SlapReply *rs )
 
869
{
 
870
        int rc = LDAP_SUCCESS;
 
871
        Entry *e = NULL;
635
872
        struct berval path;
636
873
        struct berval pdn, pndn;
637
 
        int rc;
638
 
 
639
 
        dnParent( &ck->op->o_req_dn, &pdn );
640
 
        dnParent( &ck->op->o_req_ndn, &pndn );
641
 
        dn2path( ck->op->o_bd, &ck->op->o_req_ndn, &path );
642
 
        rc = r_enum_tree(ck, &path, BER_BVISEMPTY( &ck->op->o_req_ndn ) ? 1 : 0, &pdn, &pndn);
 
874
 
 
875
        dn2path( op->o_bd, &op->o_req_ndn, &path );
 
876
        if ( !BER_BVISEMPTY( &op->o_req_ndn ) ) {
 
877
                /* Read baseObject */
 
878
                dnParent( &op->o_req_dn, &pdn );
 
879
                dnParent( &op->o_req_ndn, &pndn );
 
880
                rc = ldif_read_entry( op, path.bv_val, &pdn, &pndn, &e,
 
881
                        rs == NULL ? NULL : &rs->sr_text );
 
882
        }
 
883
        if ( rc == LDAP_SUCCESS )
 
884
                rc = ldif_search_entry( op, rs, e, op->ors_scope, &path );
 
885
 
643
886
        ch_free( path.bv_val );
644
887
        return rc;
645
888
}
646
889
 
647
890
 
648
 
/* Get the parent directory path, plus the LDIF suffix overwritten by a \0 */
649
 
static void
650
 
get_parent_path( struct berval *dnpath, struct berval *res )
 
891
/*
 
892
 * Prepare to create or rename an entry:
 
893
 * Check that the entry does not already exist.
 
894
 * Check that the parent entry exists and can have subordinates,
 
895
 * unless need_dir is NULL or adding the suffix entry.
 
896
 *
 
897
 * Return an LDAP result code.  May set *text to a message on failure.
 
898
 * If success, set *dnpath to LDIF entry path and *need_dir to
 
899
 * (directory must be created ? dirname : NULL).
 
900
 */
 
901
static int
 
902
ldif_prepare_create(
 
903
        Operation *op,
 
904
        Entry *e,
 
905
        struct berval *dnpath,
 
906
        char **need_dir,
 
907
        const char **text )
651
908
{
652
 
        int dnpathlen = dnpath->bv_len;
653
 
        int i;
654
 
        
655
 
        for(i = dnpathlen;i>0;i--) /* find the first path seperator */
656
 
                if(dnpath->bv_val[i] == LDAP_DIRSEP[0])
657
 
                        break;
658
 
        res->bv_len = i;
659
 
        res->bv_val = ch_malloc( res->bv_len + 1 + STRLENOF(LDIF) );
660
 
        strncpy(res->bv_val, dnpath->bv_val, i);
661
 
        strcpy(res->bv_val+i, LDIF);
662
 
        res->bv_val[i] = '\0';
 
909
        BackendDB *be = op->o_bd;
 
910
        struct ldif_info *li = (struct ldif_info *) be->be_private;
 
911
        struct berval *ndn = &e->e_nname;
 
912
        struct berval ppath = BER_BVNULL;
 
913
        struct stat st;
 
914
        Entry *parent = NULL;
 
915
        int rc = LDAP_SUCCESS;
 
916
 
 
917
        if ( op->o_abandon )
 
918
                return SLAPD_ABANDON;
 
919
 
 
920
        dn2path( be, ndn, dnpath );
 
921
 
 
922
        if ( stat( dnpath->bv_val, &st ) == 0 ) { /* entry .ldif file */
 
923
                rc = LDAP_ALREADY_EXISTS;
 
924
 
 
925
        } else if ( errno != ENOENT ) {
 
926
                Debug( LDAP_DEBUG_ANY,
 
927
                        "ldif_prepare_create: cannot stat \"%s\": %s\n",
 
928
                        dnpath->bv_val, STRERROR( errno ), 0 );
 
929
                rc = LDAP_OTHER;
 
930
                *text = "internal error (cannot check entry file)";
 
931
 
 
932
        } else if ( need_dir != NULL ) {
 
933
                *need_dir = NULL;
 
934
                rc = get_parent_path( dnpath, &ppath );
 
935
                /* If parent dir exists, so does parent .ldif:
 
936
                 * The directory gets created after and removed before the .ldif.
 
937
                 * Except with the database directory, which has no matching entry.
 
938
                 */
 
939
                if ( rc == LDAP_SUCCESS && stat( ppath.bv_val, &st ) < 0 ) {
 
940
                        rc = errno == ENOENT && ppath.bv_len > li->li_base_path.bv_len
 
941
                                ? LDAP_NO_SUCH_OBJECT : LDAP_OTHER;
 
942
                }
 
943
                switch ( rc ) {
 
944
                case LDAP_NO_SUCH_OBJECT:
 
945
                        /* No parent dir, check parent .ldif */
 
946
                        dir2ldif_name( ppath );
 
947
                        rc = ldif_read_entry( op, ppath.bv_val, NULL, NULL,
 
948
                                (op->o_tag != LDAP_REQ_ADD || get_manageDSAit( op )
 
949
                                 ? &parent : NULL),
 
950
                                text );
 
951
                        switch ( rc ) {
 
952
                        case LDAP_SUCCESS:
 
953
                                /* Check that parent is not a referral, unless
 
954
                                 * ldif_back_referrals() already checked.
 
955
                                 */
 
956
                                if ( parent != NULL ) {
 
957
                                        int is_ref = is_entry_referral( parent );
 
958
                                        entry_free( parent );
 
959
                                        if ( is_ref ) {
 
960
                                                rc = LDAP_AFFECTS_MULTIPLE_DSAS;
 
961
                                                *text = op->o_tag == LDAP_REQ_MODDN
 
962
                                                        ? "newSuperior is a referral object"
 
963
                                                        : "parent is a referral object";
 
964
                                                break;
 
965
                                        }
 
966
                                }
 
967
                                /* Must create parent directory. */
 
968
                                ldif2dir_name( ppath );
 
969
                                *need_dir = ppath.bv_val;
 
970
                                break;
 
971
                        case LDAP_NO_SUCH_OBJECT:
 
972
                                *text = op->o_tag == LDAP_REQ_MODDN
 
973
                                        ? "newSuperior object does not exist"
 
974
                                        : "parent does not exist";
 
975
                                break;
 
976
                        }
 
977
                        break;
 
978
                case LDAP_OTHER:
 
979
                        Debug( LDAP_DEBUG_ANY,
 
980
                                "ldif_prepare_create: cannot stat \"%s\" parent dir: %s\n",
 
981
                                ndn->bv_val, STRERROR( errno ), 0 );
 
982
                        *text = "internal error (cannot stat parent dir)";
 
983
                        break;
 
984
                }
 
985
                if ( *need_dir == NULL && ppath.bv_val != NULL )
 
986
                        SLAP_FREE( ppath.bv_val );
 
987
        }
 
988
 
 
989
        if ( rc != LDAP_SUCCESS ) {
 
990
                SLAP_FREE( dnpath->bv_val );
 
991
                BER_BVZERO( dnpath );
 
992
        }
 
993
        return rc;
663
994
}
664
995
 
665
 
static int apply_modify_to_entry(Entry * entry,
666
 
                                Modifications * modlist,
667
 
                                Operation * op,
668
 
                                SlapReply * rs)
 
996
static int
 
997
apply_modify_to_entry(
 
998
        Entry *entry,
 
999
        Modifications *modlist,
 
1000
        Operation *op,
 
1001
        SlapReply *rs )
669
1002
{
670
1003
        char textbuf[SLAP_TEXT_BUFLEN];
671
1004
        int rc = modlist ? LDAP_UNWILLING_TO_PERFORM : LDAP_SUCCESS;
689
1022
                                   &rs->sr_text, textbuf,
690
1023
                                   sizeof( textbuf ) );
691
1024
                        break;
692
 
                                
 
1025
 
693
1026
                case LDAP_MOD_DELETE:
694
1027
                        rc = modify_delete_values(entry, mods,
695
1028
                                get_permissiveModify(op),
696
1029
                                &rs->sr_text, textbuf,
697
1030
                                sizeof( textbuf ) );
698
1031
                        break;
699
 
                                
 
1032
 
700
1033
                case LDAP_MOD_REPLACE:
701
1034
                        rc = modify_replace_values(entry, mods,
702
1035
                                 get_permissiveModify(op),
726
1059
                if(rc != LDAP_SUCCESS) break;
727
1060
        }
728
1061
 
729
 
        if(rc == LDAP_SUCCESS) {
 
1062
        if ( rc == LDAP_SUCCESS ) {
 
1063
                rs->sr_text = NULL; /* Needed at least with SLAP_MOD_SOFTADD */
730
1064
                if ( is_oc ) {
731
1065
                        entry->e_ocflags = 0;
732
1066
                }
733
1067
                /* check that the entry still obeys the schema */
734
 
                rc = entry_schema_check( op, entry, NULL, 0, 0,
 
1068
                rc = entry_schema_check( op, entry, NULL, 0, 0, NULL,
735
1069
                          &rs->sr_text, textbuf, sizeof( textbuf ) );
736
1070
        }
737
1071
 
738
1072
        return rc;
739
1073
}
740
1074
 
741
 
int
 
1075
 
 
1076
static int
742
1077
ldif_back_referrals( Operation *op, SlapReply *rs )
743
1078
{
744
 
        struct ldif_info        *li = NULL;
745
 
        Entry                   *entry;
746
 
        int                     rc = LDAP_SUCCESS;
747
 
 
748
 
#if 0
749
 
        if ( op->o_tag == LDAP_REQ_SEARCH ) {
750
 
                /* let search take care of itself */
751
 
                return rc;
752
 
        }
753
 
#endif
754
 
 
755
 
        if ( get_manageDSAit( op ) ) {
756
 
                /* let op take care of DSA management */
757
 
                return rc;
758
 
        }
759
 
 
760
 
        if ( BER_BVISEMPTY( &op->o_req_ndn ) ) {
761
 
                /* the empty DN cannot be a referral */
762
 
                return rc;
763
 
        }
764
 
 
765
 
        li = (struct ldif_info *)op->o_bd->be_private;
 
1079
        struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
 
1080
        struct berval path, dn = op->o_req_dn, ndn = op->o_req_ndn;
 
1081
        ber_len_t min_dnlen;
 
1082
        Entry *entry = NULL, **entryp;
 
1083
        BerVarray ref;
 
1084
        int rc;
 
1085
 
 
1086
        min_dnlen = op->o_bd->be_nsuffix[0].bv_len;
 
1087
        if ( min_dnlen == 0 ) {
 
1088
                /* Catch root DSE (empty DN), it is not a referral */
 
1089
                min_dnlen = 1;
 
1090
                if ( BER_BVISEMPTY( &ndn ) )
 
1091
                        return LDAP_SUCCESS;
 
1092
        }
 
1093
 
 
1094
        entryp = get_manageDSAit( op ) ? NULL : &entry;
 
1095
        dn2path( op->o_bd, &ndn, &path );
766
1096
        ldap_pvt_thread_rdwr_rlock( &li->li_rdwr );
767
 
        get_entry( op, &entry, NULL );
768
 
 
769
 
        /* no object is found for them */
770
 
        if ( entry == NULL ) {
771
 
                struct berval   odn = op->o_req_dn;
772
 
                struct berval   ondn = op->o_req_ndn;
773
 
                struct berval   pndn = ondn;
774
 
                ber_len_t               min_dnlen = op->o_bd->be_nsuffix[0].bv_len;
775
 
 
776
 
                if ( min_dnlen == 0 )
777
 
                        min_dnlen = 1;     /* catch empty DN */
778
 
 
779
 
                for ( ; entry == NULL; ) {
780
 
                        dnParent( &pndn, &pndn );
781
 
                        if ( pndn.bv_len < min_dnlen ) {
782
 
                                break;
783
 
                        }
784
 
 
785
 
                        op->o_req_dn = pndn;
786
 
                        op->o_req_ndn = pndn;
787
 
 
788
 
                        get_entry( op, &entry, NULL );
789
 
                }
790
 
 
791
 
                ldap_pvt_thread_rdwr_runlock( &li->li_rdwr );
792
 
 
793
 
                op->o_req_dn = odn;
794
 
                op->o_req_ndn = ondn;
 
1097
 
 
1098
        for (;;) {
 
1099
                dnParent( &dn, &dn );
 
1100
                dnParent( &ndn, &ndn );
 
1101
                rc = ldif_read_entry( op, path.bv_val, &dn, &ndn,
 
1102
                        entryp, &rs->sr_text );
 
1103
                if ( rc != LDAP_NO_SUCH_OBJECT )
 
1104
                        break;
795
1105
 
796
1106
                rc = LDAP_SUCCESS;
797
 
                rs->sr_matched = NULL;
798
 
                if ( entry != NULL ) {
 
1107
                if ( ndn.bv_len < min_dnlen )
 
1108
                        break;
 
1109
                (void) get_parent_path( &path, NULL );
 
1110
                dir2ldif_name( path );
 
1111
                entryp = &entry;
 
1112
        }
 
1113
 
 
1114
        ldap_pvt_thread_rdwr_runlock( &li->li_rdwr );
 
1115
        SLAP_FREE( path.bv_val );
 
1116
 
 
1117
        if ( entry != NULL ) {
 
1118
                if ( is_entry_referral( entry ) ) {
799
1119
                        Debug( LDAP_DEBUG_TRACE,
800
1120
                                "ldif_back_referrals: tag=%lu target=\"%s\" matched=\"%s\"\n",
801
 
                                (unsigned long) op->o_tag, op->o_req_dn.bv_val, entry->e_name.bv_val );
802
 
 
803
 
                        if ( is_entry_referral( entry ) ) {
 
1121
                                (unsigned long) op->o_tag, op->o_req_dn.bv_val, entry->e_dn );
 
1122
 
 
1123
                        ref = get_entry_referrals( op, entry );
 
1124
                        rs->sr_ref = referral_rewrite( ref, &entry->e_name, &op->o_req_dn,
 
1125
                                op->o_tag == LDAP_REQ_SEARCH ?
 
1126
                                op->ors_scope : LDAP_SCOPE_DEFAULT );
 
1127
                        ber_bvarray_free( ref );
 
1128
 
 
1129
                        if ( rs->sr_ref != NULL ) {
 
1130
                                /* send referral */
 
1131
                                rc = rs->sr_err = LDAP_REFERRAL;
 
1132
                                rs->sr_matched = entry->e_dn;
 
1133
                                send_ldap_result( op, rs );
 
1134
                                ber_bvarray_free( rs->sr_ref );
 
1135
                                rs->sr_ref = NULL;
 
1136
                        } else {
804
1137
                                rc = LDAP_OTHER;
805
 
                                rs->sr_ref = get_entry_referrals( op, entry );
806
 
                                if ( rs->sr_ref ) {
807
 
                                        rs->sr_matched = ber_strdup_x(
808
 
                                        entry->e_name.bv_val, op->o_tmpmemctx );
809
 
                                }
 
1138
                                rs->sr_text = "bad referral object";
810
1139
                        }
811
 
 
812
 
                        entry_free(entry);
813
 
 
814
 
                } else if ( default_referral != NULL ) {
815
 
                        rc = LDAP_OTHER;
816
 
                        rs->sr_ref = referral_rewrite( default_referral,
817
 
                                NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
818
 
                }
819
 
 
820
 
                if ( rs->sr_ref != NULL ) {
821
 
                        /* send referrals */
822
 
                        rc = rs->sr_err = LDAP_REFERRAL;
823
 
                        send_ldap_result( op, rs );
824
 
                        ber_bvarray_free( rs->sr_ref );
825
 
                        rs->sr_ref = NULL;
826
 
 
827
 
                } else if ( rc != LDAP_SUCCESS ) {
828
 
                        rs->sr_text = rs->sr_matched ? "bad referral object" : NULL;
829
 
                }
830
 
 
831
 
                if ( rs->sr_matched ) {
832
 
                        op->o_tmpfree( (char *)rs->sr_matched, op->o_tmpmemctx );
833
1140
                        rs->sr_matched = NULL;
834
1141
                }
835
1142
 
836
 
                return rc;
837
 
        }
838
 
 
839
 
        ldap_pvt_thread_rdwr_runlock( &li->li_rdwr );
840
 
 
841
 
        if ( is_entry_referral( entry ) ) {
842
 
                /* entry is a referral */
843
 
                BerVarray refs = get_entry_referrals( op, entry );
844
 
                rs->sr_ref = referral_rewrite(
845
 
                        refs, &entry->e_name, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
846
 
 
847
 
                Debug( LDAP_DEBUG_TRACE,
848
 
                        "ldif_back_referrals: tag=%lu target=\"%s\" matched=\"%s\"\n",
849
 
                        (unsigned long) op->o_tag, op->o_req_dn.bv_val, entry->e_name.bv_val );
850
 
 
851
 
                rs->sr_matched = entry->e_name.bv_val;
852
 
                if ( rs->sr_ref != NULL ) {
853
 
                        rc = rs->sr_err = LDAP_REFERRAL;
854
 
                        send_ldap_result( op, rs );
855
 
                        ber_bvarray_free( rs->sr_ref );
856
 
                        rs->sr_ref = NULL;
857
 
 
858
 
                } else {
859
 
                        rc = LDAP_OTHER;
860
 
                        rs->sr_text = "bad referral object";
861
 
                }
862
 
 
863
 
                rs->sr_matched = NULL;
864
 
                ber_bvarray_free( refs );
865
 
        }
866
 
 
867
 
        entry_free( entry );
 
1143
                entry_free( entry );
 
1144
        }
868
1145
 
869
1146
        return rc;
870
1147
}
879
1156
        Attribute *a;
880
1157
        AttributeDescription *password = slap_schema.si_ad_userPassword;
881
1158
        int return_val;
882
 
        Entry *entry;
 
1159
        Entry *entry = NULL;
883
1160
 
884
1161
        switch ( be_rootdn_bind( op, rs ) ) {
885
1162
        case SLAP_CB_CONTINUE:
893
1170
 
894
1171
        li = (struct ldif_info *) op->o_bd->be_private;
895
1172
        ldap_pvt_thread_rdwr_rlock(&li->li_rdwr);
896
 
        return_val = get_entry(op, &entry, NULL);
 
1173
        return_val = get_entry(op, &entry, NULL, NULL);
897
1174
 
898
1175
        /* no object is found for them */
899
1176
        if(return_val != LDAP_SUCCESS) {
917
1194
        }
918
1195
 
919
1196
        /* let the front-end send success */
920
 
        return_val = 0;
921
 
        goto return_result;
 
1197
        return_val = LDAP_SUCCESS;
922
1198
 
923
1199
 return_result:
924
1200
        ldap_pvt_thread_rdwr_runlock(&li->li_rdwr);
925
 
        if(return_val != 0)
 
1201
        if(return_val != LDAP_SUCCESS)
926
1202
                send_ldap_result( op, rs );
927
1203
        if(entry != NULL)
928
1204
                entry_free(entry);
929
1205
        return return_val;
930
1206
}
931
1207
 
932
 
static int ldif_back_search(Operation *op, SlapReply *rs)
 
1208
static int
 
1209
ldif_back_search( Operation *op, SlapReply *rs )
933
1210
{
934
1211
        struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
935
 
        enumCookie ck = { NULL, NULL, NULL, 0, 0 };
936
1212
 
937
 
        ck.op = op;
938
 
        ck.rs = rs;
939
1213
        ldap_pvt_thread_rdwr_rlock(&li->li_rdwr);
940
 
        rs->sr_err = enum_tree( &ck );
 
1214
        rs->sr_err = search_tree( op, rs );
941
1215
        ldap_pvt_thread_rdwr_runlock(&li->li_rdwr);
942
1216
        send_ldap_result(op, rs);
943
1217
 
944
1218
        return rs->sr_err;
945
1219
}
946
1220
 
947
 
static int ldif_back_add(Operation *op, SlapReply *rs) {
 
1221
static int
 
1222
ldif_back_add( Operation *op, SlapReply *rs )
 
1223
{
948
1224
        struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
949
1225
        Entry * e = op->ora_e;
950
 
        struct berval dn = e->e_nname;
951
 
        struct berval leaf_path = BER_BVNULL;
952
 
        struct stat stats;
953
 
        int statres;
 
1226
        struct berval path;
 
1227
        char *parentdir;
954
1228
        char textbuf[SLAP_TEXT_BUFLEN];
955
 
 
956
 
        Debug( LDAP_DEBUG_TRACE, "ldif_back_add: \"%s\"\n", dn.bv_val, 0, 0);
957
 
 
958
 
        rs->sr_err = entry_schema_check(op, e, NULL, 0, 1,
 
1229
        int rc;
 
1230
 
 
1231
        Debug( LDAP_DEBUG_TRACE, "ldif_back_add: \"%s\"\n", e->e_dn, 0, 0 );
 
1232
 
 
1233
        rc = entry_schema_check( op, e, NULL, 0, 1, NULL,
959
1234
                &rs->sr_text, textbuf, sizeof( textbuf ) );
960
 
        if ( rs->sr_err != LDAP_SUCCESS ) goto send_res;
961
 
 
962
 
        rs->sr_err = slap_add_opattrs( op,
963
 
                &rs->sr_text, textbuf, sizeof( textbuf ), 1 );
964
 
        if ( rs->sr_err != LDAP_SUCCESS ) goto send_res;
965
 
 
966
 
        ldap_pvt_thread_rdwr_wlock(&li->li_rdwr);
967
 
 
968
 
        dn2path( op->o_bd, &dn, &leaf_path );
969
 
 
970
 
        if(leaf_path.bv_val != NULL) {
971
 
                struct berval base = BER_BVNULL;
972
 
                /* build path to container and ldif of container */
973
 
                get_parent_path(&leaf_path, &base);
974
 
 
975
 
                statres = stat(base.bv_val, &stats); /* check if container exists */
976
 
                if(statres == -1 && errno == ENOENT) { /* container missing */
977
 
                        base.bv_val[base.bv_len] = LDIF_FILETYPE_SEP;
978
 
                        statres = stat(base.bv_val, &stats); /* check for leaf node */
979
 
                        base.bv_val[base.bv_len] = '\0';
980
 
                        if(statres == -1 && errno == ENOENT) {
981
 
                                rs->sr_err = LDAP_NO_SUCH_OBJECT; /* parent doesn't exist */
982
 
                                rs->sr_text = "Parent does not exist";
983
 
                        }
984
 
                        else if(statres != -1) { /* create parent */
985
 
                                int mkdirres = mkdir(base.bv_val, 0750);
986
 
                                if(mkdirres == -1) {
987
 
                                        rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
988
 
                                        rs->sr_text = "Could not create parent folder";
989
 
                                        Debug( LDAP_DEBUG_ANY, "could not create folder \"%s\": %s\n",
990
 
                                                base.bv_val, STRERROR( errno ), 0 );
991
 
                                }
992
 
                        }
993
 
                        else
994
 
                                rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
995
 
                }/* container was possibly created, move on to add the entry */
996
 
                if(rs->sr_err == LDAP_SUCCESS) {
997
 
                        statres = stat(leaf_path.bv_val, &stats);
998
 
                        if(statres == -1 && errno == ENOENT) {
999
 
                                rs->sr_err = spew_entry(e, &leaf_path, 1, NULL);
1000
 
                        }
1001
 
                        else if ( statres == -1 ) {
1002
 
                                rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1003
 
                                Debug( LDAP_DEBUG_ANY, "could not stat file \"%s\": %s\n",
1004
 
                                        leaf_path.bv_val, STRERROR( errno ), 0 );
1005
 
                        }
1006
 
                        else /* it already exists */
1007
 
                                rs->sr_err = LDAP_ALREADY_EXISTS;
1008
 
                }
1009
 
                SLAP_FREE(base.bv_val);
1010
 
                SLAP_FREE(leaf_path.bv_val);
 
1235
        if ( rc != LDAP_SUCCESS )
 
1236
                goto send_res;
 
1237
 
 
1238
        rc = slap_add_opattrs( op, &rs->sr_text, textbuf, sizeof( textbuf ), 1 );
 
1239
        if ( rc != LDAP_SUCCESS )
 
1240
                goto send_res;
 
1241
 
 
1242
        ldap_pvt_thread_mutex_lock( &li->li_modop_mutex );
 
1243
 
 
1244
        rc = ldif_prepare_create( op, e, &path, &parentdir, &rs->sr_text );
 
1245
        if ( rc == LDAP_SUCCESS ) {
 
1246
                ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
 
1247
                rc = ldif_write_entry( op, e, &path, parentdir, &rs->sr_text );
 
1248
                ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
 
1249
 
 
1250
                SLAP_FREE( path.bv_val );
 
1251
                if ( parentdir != NULL )
 
1252
                        SLAP_FREE( parentdir );
1011
1253
        }
1012
1254
 
1013
 
        ldap_pvt_thread_rdwr_wunlock(&li->li_rdwr);
 
1255
        ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex );
1014
1256
 
1015
 
send_res:
1016
 
        Debug( LDAP_DEBUG_TRACE, 
1017
 
                        "ldif_back_add: err: %d text: %s\n", rs->sr_err, rs->sr_text ?
1018
 
                                rs->sr_text : "", 0);
1019
 
        send_ldap_result(op, rs);
 
1257
 send_res:
 
1258
        rs->sr_err = rc;
 
1259
        Debug( LDAP_DEBUG_TRACE, "ldif_back_add: err: %d text: %s\n",
 
1260
                rc, rs->sr_text ? rs->sr_text : "", 0 );
 
1261
        send_ldap_result( op, rs );
1020
1262
        slap_graduate_commit_csn( op );
1021
1263
        return rs->sr_err;
1022
1264
}
1023
1265
 
1024
 
static int ldif_back_modify(Operation *op, SlapReply *rs) {
 
1266
static int
 
1267
ldif_back_modify( Operation *op, SlapReply *rs )
 
1268
{
1025
1269
        struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
1026
1270
        Modifications * modlst = op->orm_modlist;
1027
1271
        struct berval path;
1028
1272
        Entry *entry;
1029
 
        int spew_res;
 
1273
        int rc;
1030
1274
 
1031
1275
        slap_mods_opattrs( op, &op->orm_modlist, 1 );
1032
1276
 
1033
 
        ldap_pvt_thread_rdwr_wlock(&li->li_rdwr);
 
1277
        ldap_pvt_thread_mutex_lock( &li->li_modop_mutex );
1034
1278
 
1035
 
        rs->sr_err = get_entry( op, &entry, &path );
1036
 
        if(entry != NULL) {
1037
 
                rs->sr_err = apply_modify_to_entry(entry, modlst, op, rs);
1038
 
                if(rs->sr_err == LDAP_SUCCESS) {
1039
 
                        int save_errno;
1040
 
                        spew_res = spew_entry(entry, &path, 1, &save_errno);
1041
 
                        if(spew_res == -1) {
1042
 
                                Debug( LDAP_DEBUG_ANY,
1043
 
                                        "%s ldif_back_modify: could not output entry \"%s\": %s\n",
1044
 
                                        op->o_log_prefix, entry->e_name.bv_val, STRERROR( save_errno ) );
1045
 
                                rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1046
 
                        }
 
1279
        rc = get_entry( op, &entry, &path, &rs->sr_text );
 
1280
        if ( rc == LDAP_SUCCESS ) {
 
1281
                rc = apply_modify_to_entry( entry, modlst, op, rs );
 
1282
                if ( rc == LDAP_SUCCESS ) {
 
1283
                        ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
 
1284
                        rc = ldif_write_entry( op, entry, &path, NULL, &rs->sr_text );
 
1285
                        ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
1047
1286
                }
1048
1287
 
1049
1288
                entry_free( entry );
1050
1289
                SLAP_FREE( path.bv_val );
1051
1290
        }
1052
1291
 
1053
 
        rs->sr_text = NULL;
1054
 
        ldap_pvt_thread_rdwr_wunlock(&li->li_rdwr);
1055
 
        send_ldap_result(op, rs);
 
1292
        ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex );
 
1293
 
 
1294
        rs->sr_err = rc;
 
1295
        send_ldap_result( op, rs );
1056
1296
        slap_graduate_commit_csn( op );
1057
1297
        return rs->sr_err;
1058
1298
}
1059
1299
 
1060
 
static int ldif_back_delete(Operation *op, SlapReply *rs) {
 
1300
static int
 
1301
ldif_back_delete( Operation *op, SlapReply *rs )
 
1302
{
1061
1303
        struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
1062
1304
        struct berval path;
1063
 
        int res = 0;
 
1305
        int rc = LDAP_SUCCESS;
1064
1306
 
1065
1307
        if ( BER_BVISEMPTY( &op->o_csn )) {
1066
1308
                struct berval csn;
1071
1313
                slap_get_csn( op, &csn, 1 );
1072
1314
        }
1073
1315
 
1074
 
        ldap_pvt_thread_rdwr_wlock(&li->li_rdwr);
 
1316
        ldap_pvt_thread_mutex_lock( &li->li_modop_mutex );
 
1317
        ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
 
1318
        if ( op->o_abandon ) {
 
1319
                rc = SLAPD_ABANDON;
 
1320
                goto done;
 
1321
        }
1075
1322
 
1076
1323
        dn2path( op->o_bd, &op->o_req_ndn, &path );
1077
 
        path.bv_val[path.bv_len - STRLENOF(LDIF)] = '\0';
1078
 
        res = rmdir(path.bv_val);
1079
 
        path.bv_val[path.bv_len - STRLENOF(LDIF)] = LDIF_FILETYPE_SEP;
1080
 
        rs->sr_err = LDAP_SUCCESS;
1081
 
        if ( res ) {
 
1324
        ldif2dir_len( path );
 
1325
        ldif2dir_name( path );
 
1326
        if ( rmdir( path.bv_val ) < 0 ) {
1082
1327
                switch ( errno ) {
1083
1328
                case ENOTEMPTY:
1084
 
                        rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
 
1329
                        rc = LDAP_NOT_ALLOWED_ON_NONLEAF;
1085
1330
                        break;
1086
 
 
1087
1331
                case ENOENT:
1088
1332
                        /* is leaf, go on */
1089
 
                        res = 0;
1090
1333
                        break;
1091
 
 
1092
1334
                default:
1093
 
                        rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
 
1335
                        rc = LDAP_OTHER;
 
1336
                        rs->sr_text = "internal error (cannot delete subtree directory)";
1094
1337
                        break;
1095
1338
                }
1096
1339
        }
1097
1340
 
1098
 
        if ( !res ) {
1099
 
                res = unlink(path.bv_val);
1100
 
                if ( res == -1 ) {
1101
 
                        switch ( errno ) {
1102
 
                        case ENOENT:
1103
 
                                rs->sr_err = LDAP_NO_SUCH_OBJECT;
1104
 
                                break;
1105
 
 
1106
 
                        default:
1107
 
                                rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1108
 
                                break;
 
1341
        if ( rc == LDAP_SUCCESS ) {
 
1342
                dir2ldif_name( path );
 
1343
                if ( unlink( path.bv_val ) < 0 ) {
 
1344
                        rc = LDAP_NO_SUCH_OBJECT;
 
1345
                        if ( errno != ENOENT ) {
 
1346
                                rc = LDAP_OTHER;
 
1347
                                rs->sr_text = "internal error (cannot delete entry file)";
1109
1348
                        }
1110
1349
                }
1111
1350
        }
1112
1351
 
1113
 
        SLAP_FREE(path.bv_val);
1114
 
        ldap_pvt_thread_rdwr_wunlock(&li->li_rdwr);
1115
 
        send_ldap_result(op, rs);
 
1352
        if ( rc == LDAP_OTHER ) {
 
1353
                Debug( LDAP_DEBUG_ANY, "ldif_back_delete: %s \"%s\": %s\n",
 
1354
                        "cannot delete", path.bv_val, STRERROR( errno ) );
 
1355
        }
 
1356
 
 
1357
        SLAP_FREE( path.bv_val );
 
1358
 done:
 
1359
        ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
 
1360
        ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex );
 
1361
        rs->sr_err = rc;
 
1362
        send_ldap_result( op, rs );
1116
1363
        slap_graduate_commit_csn( op );
1117
1364
        return rs->sr_err;
1118
1365
}
1122
1369
ldif_move_entry(
1123
1370
        Operation *op,
1124
1371
        Entry *entry,
1125
 
        struct berval *oldpath )
 
1372
        int same_ndn,
 
1373
        struct berval *oldpath,
 
1374
        const char **text )
1126
1375
{
1127
 
        int res;
1128
 
        int exists_res;
 
1376
        struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
1129
1377
        struct berval newpath;
1130
 
 
1131
 
        dn2path( op->o_bd, &entry->e_nname, &newpath );
1132
 
 
1133
 
        if((entry == NULL || oldpath->bv_val == NULL) || newpath.bv_val == NULL) {
1134
 
                /* some object doesn't exist */
1135
 
                res = LDAP_NO_SUCH_OBJECT;
1136
 
        }
1137
 
        else { /* do the modrdn */
1138
 
                exists_res = open(newpath.bv_val, O_RDONLY);
1139
 
                if(exists_res == -1 && errno == ENOENT) {
1140
 
                        ldap_pvt_thread_mutex_lock( &entry2str_mutex );
1141
 
                        res = spew_entry(entry, &newpath, 0, NULL);
1142
 
                        if(res != -1) {
1143
 
                                /* if this fails we should log something bad */
1144
 
                                res = unlink( oldpath->bv_val );
1145
 
                                oldpath->bv_val[oldpath->bv_len - STRLENOF(".ldif")] = '\0';
1146
 
                                newpath.bv_val[newpath.bv_len - STRLENOF(".ldif")] = '\0';
1147
 
                                res = rename( oldpath->bv_val, newpath.bv_val );
1148
 
                                res = LDAP_SUCCESS;
1149
 
                        }
1150
 
                        else {
1151
 
                                if(errno == ENOENT)
1152
 
                                        res = LDAP_NO_SUCH_OBJECT;
1153
 
                                else
1154
 
                                        res = LDAP_UNWILLING_TO_PERFORM;
1155
 
                                unlink(newpath.bv_val); /* in case file was created */
1156
 
                        }
1157
 
                        ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
1158
 
                }
1159
 
                else if(exists_res) {
1160
 
                        int close_res = close(exists_res);
1161
 
                        res = LDAP_ALREADY_EXISTS;
1162
 
                        if(close_res == -1) {
1163
 
                        /* log heinous error */
1164
 
                        }
1165
 
                }
1166
 
                else {
1167
 
                        res = LDAP_UNWILLING_TO_PERFORM;
1168
 
                }
1169
 
        }
1170
 
 
1171
 
        if(newpath.bv_val != NULL)
1172
 
                SLAP_FREE(newpath.bv_val);
1173
 
        return res;
 
1378
        char *parentdir = NULL, *trash;
 
1379
        int rc, rename_res;
 
1380
 
 
1381
        if ( same_ndn ) {
 
1382
                rc = LDAP_SUCCESS;
 
1383
                newpath = *oldpath;
 
1384
        } else {
 
1385
                rc = ldif_prepare_create( op, entry, &newpath,
 
1386
                        op->orr_newSup ? &parentdir : NULL, text );
 
1387
        }
 
1388
 
 
1389
        if ( rc == LDAP_SUCCESS ) {
 
1390
                ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
 
1391
 
 
1392
                rc = ldif_write_entry( op, entry, &newpath, parentdir, text );
 
1393
                if ( rc == LDAP_SUCCESS && !same_ndn ) {
 
1394
                        trash = oldpath->bv_val; /* will be .ldif file to delete */
 
1395
                        ldif2dir_len( newpath );
 
1396
                        ldif2dir_len( *oldpath );
 
1397
                        /* Move subdir before deleting old entry,
 
1398
                         * so .ldif always exists if subdir does.
 
1399
                         */
 
1400
                        ldif2dir_name( newpath );
 
1401
                        ldif2dir_name( *oldpath );
 
1402
                        rename_res = move_dir( oldpath->bv_val, newpath.bv_val );
 
1403
                        if ( rename_res != 0 && errno != ENOENT ) {
 
1404
                                rc = LDAP_OTHER;
 
1405
                                *text = "internal error (cannot move this subtree)";
 
1406
                                trash = newpath.bv_val;
 
1407
                        }
 
1408
 
 
1409
                        /* Delete old entry, or if error undo change */
 
1410
                        for (;;) {
 
1411
                                dir2ldif_name( newpath );
 
1412
                                dir2ldif_name( *oldpath );
 
1413
                                if ( unlink( trash ) == 0 )
 
1414
                                        break;
 
1415
                                if ( rc == LDAP_SUCCESS ) {
 
1416
                                        /* Prepare to undo change and return failure */
 
1417
                                        rc = LDAP_OTHER;
 
1418
                                        *text = "internal error (cannot move this entry)";
 
1419
                                        trash = newpath.bv_val;
 
1420
                                        if ( rename_res != 0 )
 
1421
                                                continue;
 
1422
                                        /* First move subdirectory back */
 
1423
                                        ldif2dir_name( newpath );
 
1424
                                        ldif2dir_name( *oldpath );
 
1425
                                        if ( move_dir( newpath.bv_val, oldpath->bv_val ) == 0 )
 
1426
                                                continue;
 
1427
                                }
 
1428
                                *text = "added new but couldn't delete old entry!";
 
1429
                                break;
 
1430
                        }
 
1431
 
 
1432
                        if ( rc != LDAP_SUCCESS ) {
 
1433
                                char s[128];
 
1434
                                snprintf( s, sizeof s, "%s (%s)", *text, STRERROR( errno ));
 
1435
                                Debug( LDAP_DEBUG_ANY,
 
1436
                                        "ldif_move_entry: %s: \"%s\" -> \"%s\"\n",
 
1437
                                        s, op->o_req_dn.bv_val, entry->e_dn );
 
1438
                        }
 
1439
                }
 
1440
 
 
1441
                ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
 
1442
                if ( !same_ndn )
 
1443
                        SLAP_FREE( newpath.bv_val );
 
1444
                if ( parentdir != NULL )
 
1445
                        SLAP_FREE( parentdir );
 
1446
        }
 
1447
 
 
1448
        return rc;
1174
1449
}
1175
1450
 
1176
1451
static int
1177
 
ldif_back_modrdn(Operation *op, SlapReply *rs)
 
1452
ldif_back_modrdn( Operation *op, SlapReply *rs )
1178
1453
{
1179
1454
        struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
1180
1455
        struct berval new_dn = BER_BVNULL, new_ndn = BER_BVNULL;
1181
1456
        struct berval p_dn, old_path;
1182
1457
        Entry *entry;
1183
 
        int rc;
 
1458
        int rc, same_ndn;
1184
1459
 
1185
1460
        slap_mods_opattrs( op, &op->orr_modlist, 1 );
1186
1461
 
1187
 
        ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
 
1462
        ldap_pvt_thread_mutex_lock( &li->li_modop_mutex );
1188
1463
 
1189
 
        rc = get_entry( op, &entry, &old_path );
 
1464
        rc = get_entry( op, &entry, &old_path, &rs->sr_text );
1190
1465
        if ( rc == LDAP_SUCCESS ) {
1191
1466
                /* build new dn, and new ndn for the entry */
1192
1467
                if ( op->oq_modrdn.rs_newSup != NULL ) {
1193
 
                        struct berval   op_dn = op->o_req_dn,
1194
 
                                        op_ndn = op->o_req_ndn;
1195
 
                        Entry           *np;
1196
 
 
1197
 
                        /* new superior */
1198
1468
                        p_dn = *op->oq_modrdn.rs_newSup;
1199
 
                        op->o_req_dn = *op->oq_modrdn.rs_newSup;
1200
 
                        op->o_req_ndn = *op->oq_modrdn.rs_nnewSup;
1201
 
                        rc = get_entry( op, &np, NULL );
1202
 
                        op->o_req_dn = op_dn;
1203
 
                        op->o_req_ndn = op_ndn;
1204
 
                        if ( rc != LDAP_SUCCESS ) {
1205
 
                                goto no_such_object;
1206
 
                        }
1207
 
                        entry_free( np );
1208
1469
                } else {
1209
1470
                        dnParent( &entry->e_name, &p_dn );
1210
1471
                }
1211
 
                build_new_dn( &new_dn, &p_dn, &op->oq_modrdn.rs_newrdn, NULL ); 
 
1472
                build_new_dn( &new_dn, &p_dn, &op->oq_modrdn.rs_newrdn, NULL );
1212
1473
                dnNormalize( 0, NULL, NULL, &new_dn, &new_ndn, NULL );
 
1474
                same_ndn = !ber_bvcmp( &entry->e_nname, &new_ndn );
1213
1475
                ber_memfree_x( entry->e_name.bv_val, NULL );
1214
1476
                ber_memfree_x( entry->e_nname.bv_val, NULL );
1215
1477
                entry->e_name = new_dn;
1218
1480
                /* perform the modifications */
1219
1481
                rc = apply_modify_to_entry( entry, op->orr_modlist, op, rs );
1220
1482
                if ( rc == LDAP_SUCCESS )
1221
 
                        rc = ldif_move_entry( op, entry, &old_path );
 
1483
                        rc = ldif_move_entry( op, entry, same_ndn, &old_path,
 
1484
                                &rs->sr_text );
1222
1485
 
1223
 
no_such_object:;
1224
1486
                entry_free( entry );
1225
1487
                SLAP_FREE( old_path.bv_val );
1226
1488
        }
1227
1489
 
1228
 
        rs->sr_text = "";
1229
 
        ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
 
1490
        ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex );
1230
1491
        rs->sr_err = rc;
1231
1492
        send_ldap_result( op, rs );
1232
1493
        slap_graduate_commit_csn( op );
1254
1515
        ldap_pvt_thread_rdwr_rlock( &li->li_rdwr );
1255
1516
        op->o_req_dn = *ndn;
1256
1517
        op->o_req_ndn = *ndn;
1257
 
        rc = get_entry( op, e, NULL );
 
1518
        rc = get_entry( op, e, NULL, NULL );
1258
1519
        op->o_req_dn = op_dn;
1259
1520
        op->o_req_ndn = op_ndn;
1260
1521
        ldap_pvt_thread_rdwr_runlock( &li->li_rdwr );
1271
1532
 
1272
1533
/* Slap tools */
1273
1534
 
1274
 
static int ldif_tool_entry_open(BackendDB *be, int mode) {
1275
 
        struct ldif_info *li = (struct ldif_info *) be->be_private;
1276
 
        li->li_tool_current = 0;
1277
 
        return 0;
1278
 
}                                       
1279
 
 
1280
 
static int ldif_tool_entry_close(BackendDB * be) {
1281
 
        struct ldif_info *li = (struct ldif_info *) be->be_private;
1282
 
 
1283
 
        SLAP_FREE(li->li_tool_cookie.entries);
1284
 
        return 0;
1285
 
}
1286
 
 
1287
 
static ID ldif_tool_entry_next(BackendDB *be)
1288
 
{
1289
 
        struct ldif_info *li = (struct ldif_info *) be->be_private;
1290
 
        if(li->li_tool_current >= li->li_tool_cookie.eind)
 
1535
static int
 
1536
ldif_tool_entry_open( BackendDB *be, int mode )
 
1537
{
 
1538
        struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;
 
1539
 
 
1540
        tl->ecurrent = 0;
 
1541
        return 0;
 
1542
}
 
1543
 
 
1544
static int
 
1545
ldif_tool_entry_close( BackendDB *be )
 
1546
{
 
1547
        struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;
 
1548
        Entry **entries = tl->entries;
 
1549
        ID i;
 
1550
 
 
1551
        for ( i = tl->ecount; i--; )
 
1552
                if ( entries[i] )
 
1553
                        entry_free( entries[i] );
 
1554
        SLAP_FREE( entries );
 
1555
        tl->entries = NULL;
 
1556
        tl->ecount = tl->elen = 0;
 
1557
        return 0;
 
1558
}
 
1559
 
 
1560
static ID
 
1561
ldif_tool_entry_next( BackendDB *be )
 
1562
{
 
1563
        struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;
 
1564
 
 
1565
        if ( tl->ecurrent >= tl->ecount )
1291
1566
                return NOID;
1292
1567
        else
1293
 
                return ++li->li_tool_current;
 
1568
                return ++tl->ecurrent;
1294
1569
}
1295
1570
 
1296
1571
static ID
1297
 
ldif_tool_entry_first(BackendDB *be)
 
1572
ldif_tool_entry_first( BackendDB *be )
1298
1573
{
1299
 
        struct ldif_info *li = (struct ldif_info *) be->be_private;
 
1574
        struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;
1300
1575
 
1301
 
        if(li->li_tool_cookie.entries == NULL) {
 
1576
        if ( tl->entries == NULL ) {
1302
1577
                Operation op = {0};
1303
1578
 
1304
1579
                op.o_bd = be;
1305
1580
                op.o_req_dn = *be->be_suffix;
1306
1581
                op.o_req_ndn = *be->be_nsuffix;
1307
1582
                op.ors_scope = LDAP_SCOPE_SUBTREE;
1308
 
                li->li_tool_cookie.op = &op;
1309
 
                (void)enum_tree( &li->li_tool_cookie );
1310
 
                li->li_tool_cookie.op = NULL;
 
1583
                if ( search_tree( &op, NULL ) != LDAP_SUCCESS ) {
 
1584
                        tl->ecurrent = tl->ecount; /* fail ldif_tool_entry_next() */
 
1585
                        return 0; /* fail ldif_tool_entry_get() */
 
1586
                }
1311
1587
        }
1312
1588
        return ldif_tool_entry_next( be );
1313
1589
}
1314
1590
 
1315
 
static Entry * ldif_tool_entry_get(BackendDB * be, ID id) {
1316
 
        struct ldif_info *li = (struct ldif_info *) be->be_private;
1317
 
        Entry * e;
 
1591
static Entry *
 
1592
ldif_tool_entry_get( BackendDB *be, ID id )
 
1593
{
 
1594
        struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;
 
1595
        Entry *e = NULL;
1318
1596
 
1319
 
        if(id > li->li_tool_cookie.eind || id < 1)
1320
 
                return NULL;
1321
 
        else {
1322
 
                e = li->li_tool_cookie.entries[id - 1];
1323
 
                li->li_tool_cookie.entries[id - 1] = NULL;
1324
 
                return e;
 
1597
        --id;
 
1598
        if ( id < tl->ecount ) {
 
1599
                e = tl->entries[id];
 
1600
                tl->entries[id] = NULL;
1325
1601
        }
 
1602
        return e;
1326
1603
}
1327
1604
 
1328
 
static ID ldif_tool_entry_put(BackendDB * be, Entry * e, struct berval *text) {
1329
 
        struct berval leaf_path = BER_BVNULL;
1330
 
        struct stat stats;
1331
 
        int statres;
1332
 
        int res = LDAP_SUCCESS;
1333
 
 
1334
 
        dn2path( be, &e->e_nname, &leaf_path );
1335
 
 
1336
 
        if(leaf_path.bv_val != NULL) {
1337
 
                struct berval base = BER_BVNULL;
1338
 
                /* build path to container, and path to ldif of container */
1339
 
                get_parent_path(&leaf_path, &base);
1340
 
 
1341
 
                statres = stat(base.bv_val, &stats); /* check if container exists */
1342
 
                if(statres == -1 && errno == ENOENT) { /* container missing */
1343
 
                        base.bv_val[base.bv_len] = LDIF_FILETYPE_SEP;
1344
 
                        statres = stat(base.bv_val, &stats); /* check for leaf node */
1345
 
                        base.bv_val[base.bv_len] = '\0';
1346
 
                        if(statres == -1 && errno == ENOENT) {
1347
 
                                res = LDAP_NO_SUCH_OBJECT; /* parent doesn't exist */
1348
 
                        }
1349
 
                        else if(statres != -1) { /* create parent */
1350
 
                                int mkdirres = mkdir(base.bv_val, 0750);
1351
 
                                if(mkdirres == -1) {
1352
 
                                        res = LDAP_UNWILLING_TO_PERFORM;
1353
 
                                }
1354
 
                        }
1355
 
                        else
1356
 
                                res = LDAP_UNWILLING_TO_PERFORM;
1357
 
                }/* container was possibly created, move on to add the entry */
1358
 
                if(res == LDAP_SUCCESS) {
1359
 
                        statres = stat(leaf_path.bv_val, &stats);
1360
 
                        if(statres == -1 && errno == ENOENT) {
1361
 
                                res = spew_entry(e, &leaf_path, 0, NULL);
1362
 
                        }
1363
 
                        else /* it already exists */
1364
 
                                res = LDAP_ALREADY_EXISTS;
1365
 
                }
1366
 
                SLAP_FREE(base.bv_val);
1367
 
                SLAP_FREE(leaf_path.bv_val);
1368
 
        }
1369
 
 
1370
 
        if(res == LDAP_SUCCESS) {
1371
 
                return 1;
1372
 
        }
1373
 
        else
1374
 
                return NOID;
 
1605
static ID
 
1606
ldif_tool_entry_put( BackendDB *be, Entry *e, struct berval *text )
 
1607
{
 
1608
        int rc;
 
1609
        const char *errmsg = NULL;
 
1610
        struct berval path;
 
1611
        char *parentdir;
 
1612
        Operation op = {0};
 
1613
 
 
1614
        op.o_bd = be;
 
1615
        rc = ldif_prepare_create( &op, e, &path, &parentdir, &errmsg );
 
1616
        if ( rc == LDAP_SUCCESS ) {
 
1617
                rc = ldif_write_entry( &op, e, &path, parentdir, &errmsg );
 
1618
 
 
1619
                SLAP_FREE( path.bv_val );
 
1620
                if ( parentdir != NULL )
 
1621
                        SLAP_FREE( parentdir );
 
1622
                if ( rc == LDAP_SUCCESS )
 
1623
                        return 1;
 
1624
        }
 
1625
 
 
1626
        if ( errmsg == NULL && rc != LDAP_OTHER )
 
1627
                errmsg = ldap_err2string( rc );
 
1628
        if ( errmsg != NULL )
 
1629
                snprintf( text->bv_val, text->bv_len, "%s", errmsg );
 
1630
        return NOID;
1375
1631
}
1376
1632
 
1377
1633
 
1385
1641
        li = ch_calloc( 1, sizeof(struct ldif_info) );
1386
1642
        be->be_private = li;
1387
1643
        be->be_cf_ocs = ldifocs;
1388
 
        ldap_pvt_thread_rdwr_init(&li->li_rdwr);
 
1644
        ldap_pvt_thread_mutex_init( &li->li_modop_mutex );
 
1645
        ldap_pvt_thread_rdwr_init( &li->li_rdwr );
1389
1646
        SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_ONE_SUFFIX;
1390
1647
        return 0;
1391
1648
}
1395
1652
{
1396
1653
        struct ldif_info *li = be->be_private;
1397
1654
 
1398
 
        ch_free(li->li_base_path.bv_val);
1399
 
        ldap_pvt_thread_rdwr_destroy(&li->li_rdwr);
 
1655
        ch_free( li->li_base_path.bv_val );
 
1656
        ldap_pvt_thread_rdwr_destroy( &li->li_rdwr );
 
1657
        ldap_pvt_thread_mutex_destroy( &li->li_modop_mutex );
1400
1658
        free( be->be_private );
1401
1659
        return 0;
1402
1660
}
1403
1661
 
1404
1662
static int
1405
 
ldif_back_db_open( Backend *be, ConfigReply *cr)
 
1663
ldif_back_db_open( Backend *be, ConfigReply *cr )
1406
1664
{
1407
1665
        struct ldif_info *li = (struct ldif_info *) be->be_private;
1408
1666
        if( BER_BVISEMPTY(&li->li_base_path)) {/* missing base path */
1413
1671
}
1414
1672
 
1415
1673
int
1416
 
ldif_back_initialize(
1417
 
                           BackendInfo  *bi
1418
 
                           )
 
1674
ldif_back_initialize( BackendInfo *bi )
1419
1675
{
1420
1676
        static char *controls[] = {
1421
1677
                LDAP_CONTROL_MANAGEDSAIT,
1471
1727
        bi->bi_tool_entry_put = ldif_tool_entry_put;
1472
1728
        bi->bi_tool_entry_reindex = 0;
1473
1729
        bi->bi_tool_sync = 0;
1474
 
        
 
1730
 
1475
1731
        bi->bi_tool_dn2id_get = 0;
1476
1732
        bi->bi_tool_entry_modify = 0;
1477
1733