]> git.sur5r.net Git - openldap/commitdiff
Sync with HEAD
authorKurt Zeilenga <kurt@openldap.org>
Thu, 17 Mar 2005 23:29:48 +0000 (23:29 +0000)
committerKurt Zeilenga <kurt@openldap.org>
Thu, 17 Mar 2005 23:29:48 +0000 (23:29 +0000)
23 files changed:
include/ldap_defaults.h
servers/slapd/acl.c
servers/slapd/add.c
servers/slapd/back-bdb/config.c
servers/slapd/back-bdb/init.c
servers/slapd/back-bdb/referral.c
servers/slapd/back-ldif/ldif.c
servers/slapd/backover.c
servers/slapd/bconfig.c
servers/slapd/config.c
servers/slapd/config.h
servers/slapd/daemon.c
servers/slapd/delete.c
servers/slapd/main.c
servers/slapd/modify.c
servers/slapd/modrdn.c
servers/slapd/overlays/glue.c
servers/slapd/passwd.c
servers/slapd/proto-slap.h
servers/slapd/result.c
servers/slapd/schema_check.c
servers/slapd/slap.h
servers/slapd/slapcommon.c

index 440417f7c4201b57be39945d91b30da89abd4c87..414413c56a1722528baa49075ba7aa48db3d4572 100644 (file)
@@ -46,6 +46,7 @@
  */
        /* location of the default slapd config file */
 #define SLAPD_DEFAULT_CONFIGFILE       LDAP_SYSCONFDIR LDAP_DIRSEP "slapd.conf"
+#define SLAPD_DEFAULT_CONFIGDIR                LDAP_SYSCONFDIR LDAP_DIRSEP "slapd.d"
 #define SLAPD_DEFAULT_DB_DIR           LDAP_RUNDIR LDAP_DIRSEP "openldap-data"
 #define SLAPD_DEFAULT_DB_MODE          0600
 #define SLAPD_DEFAULT_UCDATA           LDAP_DATADIR LDAP_DIRSEP "ucdata"
index 6babdba3390e2b99a823f28f490c83677cf7fec6..fdb2b9156f6781f49d9bba493699b5dbcfb2c2b7 100644 (file)
@@ -2042,6 +2042,7 @@ aci_set_gather( SetCookie *cookie, struct berval *name, AttributeDescription *de
        op2.ors_tlimit = SLAP_NO_LIMIT;
        op2.ors_attrs = anlistp;
        op2.ors_attrsonly = 0;
+       op2.o_private = cp->op->o_private;
 
        cb.sc_private = &p;
 
index 92f6759aea4780fd17e2f8be50c7ea0757c758b0..d15fb7f3fcf34b4eb2de16fa7cf6ec623a235fbf 100644 (file)
@@ -205,6 +205,7 @@ fe_op_add( Operation *op, SlapReply *rs )
        Modifications   *modlist = op->ora_modlist;
        Modifications   **modtail = &modlist;
        int             rc = 0;
+       BackendDB *op_be;
 
        manageDSAit = get_manageDSAit( op );
 
@@ -236,6 +237,12 @@ fe_op_add( Operation *op, SlapReply *rs )
                goto done;
        }
 
+       /* If we've got a glued backend, check the real backend */
+       op_be = op->o_bd;
+       if ( SLAP_GLUE_INSTANCE( op->o_bd )) {
+               op->o_bd = select_backend( &e->e_nname, manageDSAit, 0 );
+       }
+
        /* check restrictions */
        if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) {
                send_ldap_result( op, rs );
@@ -269,6 +276,8 @@ fe_op_add( Operation *op, SlapReply *rs )
                        size_t          textlen = sizeof( textbuf );
                        slap_callback   cb = { NULL, slap_replog_cb, NULL, NULL };
 
+                       op->o_bd = op_be;
+
                        if ( !update ) {
                                rs->sr_err = slap_mods_no_update_check( modlist,
                                                &rs->sr_text,
index a6d4d28e68df2ced04eefe1b7c439dfaf531acbb..a70fbb3e8f0c1b1af1e65fa8fa29d27bf559f2ae 100644 (file)
@@ -122,7 +122,7 @@ static ConfigOCs bdbocs[] = {
 static int
 bdb_cf_oc(ConfigArgs *c)
 {
-       if ( c->emit ) {
+       if ( c->op == SLAP_CONFIG_EMIT ) {
                value_add_one( &c->rvalue_vals, &bdb_oc->soc_cname );
                return 0;
        }
@@ -144,7 +144,7 @@ bdb_cf_gen(ConfigArgs *c)
        struct bdb_info *bdb = c->be->be_private;
        int rc;
 
-       if ( c->emit ) {
+       if ( c->op == SLAP_CONFIG_EMIT ) {
                rc = 0;
                switch( c->type ) {
                case BDB_CHKPT:
@@ -240,28 +240,8 @@ int bdb_back_init_cf( BackendInfo *bi )
        int rc;
        bi->bi_cf_table = bdbcfg;
 
-       rc = init_config_attrs( bdbcfg );
+       rc = config_register_schema( bdbcfg, bdbocs );
        if ( rc ) return rc;
        bdbcfg[0].ad = slap_schema.si_ad_objectClass;
-       rc = init_config_ocs( bdbocs );
-       return rc;
-}
-
-int bdb_db_config( Backend *be, const char *fname, int lineno, int argc,
-       char **argv )
-{
-       ConfigArgs c = { 0 };
-       int rc;
-
-       c.be = be;
-       c.fname = fname;
-       c.lineno = lineno;
-       c.argc = argc;
-       c.argv = argv;
-       sprintf( c.log, "%s: line %lu", fname, lineno );
-
-       rc = parse_config_table( bdbcfg, &c );
-       if ( rc == ARG_UNKNOWN )
-               rc = SLAP_CONF_UNKNOWN;
-       return rc;
+       return 0;
 }
index 8893333fc356506a22ca6e0aef3637ba98839bc1..e202de4cfcfb137bc65309a3076991919621b8be 100644 (file)
@@ -536,7 +536,7 @@ bdb_back_initialize(
        bi->bi_destroy = 0;
 
        bi->bi_db_init = bdb_db_init;
-       bi->bi_db_config = bdb_db_config;
+       bi->bi_db_config = config_generic_wrapper;
        bi->bi_db_open = bdb_db_open;
        bi->bi_db_close = bdb_db_close;
        bi->bi_db_destroy = bdb_db_destroy;
index c52288bc2615fdb4a545bca6cc5b6af430bfbc22..c79aee60577fc15a5baeeea085567ad6b7a73375 100644 (file)
@@ -53,7 +53,13 @@ dn2entry_retry:
        /* get entry */
        rc = bdb_dn2entry( op, NULL, &op->o_req_ndn, &ei, 1, locker, &lock );
 
-       e = ei->bei_e;
+       /* bdb_dn2entry() may legally leave ei == NULL
+        * if rc != 0 and rc != DB_NOTFOUND
+        */
+       if ( ei ) {
+               e = ei->bei_e;
+       }
+
        switch(rc) {
        case DB_NOTFOUND:
        case 0:
index 56f147489df995a5ed1113e262a703381bcac143..bba08ade48bd9cf93c68ef08d2002f1174b7149c 100644 (file)
 #include <ac/unistd.h>
 #include "slap.h"
 #include "lutil.h"
+#include "config.h"
 
 struct ldif_info {
        struct berval li_base_path;
-       ID tool_current;  
+       ID tool_current;
        Entry ** tool_entries;
        int tool_put_entry_flag;
        int tool_numentries;
@@ -43,14 +44,52 @@ struct ldif_info {
 
 #define ENTRY_BUFF_INCREMENT 500
 
-static char *
-dn2path(struct berval * dn, struct berval * rootdn, struct berval * base_path)
+static ObjectClass *ldif_oc;
+
+static ConfigDriver ldif_cf;
+
+static ConfigTable ldifcfg[] = {
+       { "", "", 0, 0, 0, ARG_MAGIC,
+               ldif_cf, NULL, NULL, NULL },
+       { "directory", "dir", 2, 2, 0, ARG_BERVAL|ARG_OFFSET,
+               (void *)offsetof(struct ldif_info, li_base_path),
+               "( OLcfgAt:1.1 NAME 'dbDirectory' "
+                       "DESC 'Directory for database content' "
+                       "EQUALITY caseIgnoreMatch "
+                       "SYNTAX OMsDirectoryString )", NULL, NULL },
+       { NULL, NULL, 0, 0, 0, ARG_IGNORED,
+               NULL, NULL, NULL, NULL }
+};
+
+static ConfigOCs ldifocs[] = {
+       { "( OLcfgOc:2.1 "
+               "NAME 'ldifConfig' "
+               "DESC 'LDIF backend configuration' "
+               "AUXILIARY "
+               "MAY ( dbDirectory ) )",
+               &ldif_oc },
+       { NULL, NULL }
+};
+
+static int
+ldif_cf( ConfigArgs *c )
+{
+       if ( c->op == SLAP_CONFIG_EMIT ) {
+               value_add_one( &c->rvalue_vals, &ldif_oc->soc_cname );
+               return 0;
+       }
+       return 1;
+}
+
+static void
+dn2path(struct berval * dn, struct berval * rootdn, struct berval * base_path,
+       struct berval *res)
 {
-       char *result = ch_malloc( dn->bv_len + base_path->bv_len + 2 +
-               STRLENOF( LDIF ));
        char *ptr, *sep, *end;
 
-       ptr = lutil_strcopy( result, base_path->bv_val );
+       res->bv_len = dn->bv_len + base_path->bv_len + 1 + STRLENOF( LDIF );
+       res->bv_val = ch_malloc( res->bv_len + 1 );
+       ptr = lutil_strcopy( res->bv_val, base_path->bv_val );
        *ptr++ = LDAP_DIRSEP[0];
        ptr = lutil_strcopy( ptr, rootdn->bv_val );
        end = dn->bv_val + dn->bv_len - rootdn->bv_len - 1;
@@ -61,10 +100,9 @@ dn2path(struct berval * dn, struct berval * rootdn, struct berval * base_path)
                end = sep;
        }
        strcpy(ptr, LDIF);
-       return result;
 }
 
-static char * slurp_file(int fd) {  
+static char * slurp_file(int fd) {
        int entry_buf_size = 40 * ENTRY_BUFF_INCREMENT;
        int read_chars_total = 0;
        int read_chars = 0;
@@ -73,29 +111,29 @@ static char * slurp_file(int fd) {
        char * entry_pos = entry;
        
        while(1) {
-         if(entry_size - read_chars_total == 0) {
-           entry = (char *) realloc(entry, sizeof(char) * 2 * entry_size);
-           entry_size = 2 * entry_size;
-         }
-         read_chars = read(fd, (void *) entry_pos, entry_size - read_chars_total);
-         if(read_chars == -1) {
-           SLAP_FREE(entry);
-           return NULL;
-         }
-         entry_pos += read_chars;
-         if(read_chars == 0) {
-           if(entry_size - read_chars_total > 0)
-       entry[read_chars_total] = '\0';
-           else {
-       entry = (char *) realloc(entry, sizeof(char) * entry_size + 1);
-       entry_size = entry_size + 1;
-       entry[read_chars_total] = '\0';
-           }   
-           break;
-         }
-         else {
-           read_chars_total += read_chars;
-         }
+               if(entry_size - read_chars_total == 0) {
+                       entry = (char *) realloc(entry, sizeof(char) * 2 * entry_size);
+                       entry_size = 2 * entry_size;
+               }
+               read_chars = read(fd, (void *) entry_pos, entry_size - read_chars_total);
+               if(read_chars == -1) {
+                       SLAP_FREE(entry);
+                       return NULL;
+               }
+               entry_pos += read_chars;
+               if(read_chars == 0) {
+                       if(entry_size - read_chars_total > 0)
+                               entry[read_chars_total] = '\0';
+                       else {
+                               entry = (char *) realloc(entry, sizeof(char) * entry_size + 1);
+                               entry_size = entry_size + 1;
+                               entry[read_chars_total] = '\0';
+                       }       
+                       break;
+               }
+               else {
+                       read_chars_total += read_chars;
+               }
        }
        return entry;
 }
@@ -107,48 +145,48 @@ static int spew_file(int fd, char * spew) {
        char * spewptr = spew;
        
        while(written < len) {
-         writeres = write(fd, spewptr, len - written);
-         if(writeres == -1) {
-           perror("could not spew write");
-           return -1;
-         }
-         else {
-           spewptr += writeres;
-           written += writeres;
-         }
+               writeres = write(fd, spewptr, len - written);
+               if(writeres == -1) {
+                       perror("could not spew write");
+                       return -1;
+               }
+               else {
+                       spewptr += writeres;
+                       written += writeres;
+               }
        }
        return writeres;
 }
 
-static int spew_entry(Entry * e, char * path) {
+static int spew_entry(Entry * e, struct berval * path) {
        int rs;
        int openres;
        int spew_res;
        int entry_length;
        char * entry_as_string;
 
-       openres = open(path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+       openres = open(path->bv_val, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
        if(openres == -1) {
-         if(errno == ENOENT)
-           rs = LDAP_NO_SUCH_OBJECT;
-         else
-           rs = LDAP_UNWILLING_TO_PERFORM;
+               if(errno == ENOENT)
+                       rs = LDAP_NO_SUCH_OBJECT;
+               else
+                       rs = LDAP_UNWILLING_TO_PERFORM;
        }
        else {
-         entry_as_string = entry2str(e, &entry_length);
-         if(entry_as_string == NULL) {
-           rs = LDAP_UNWILLING_TO_PERFORM;
-           close(openres);
-         }
-         else {
-           spew_res = spew_file(openres, entry_as_string);
-           close(openres);
-           if(spew_res == -1)
-       rs = LDAP_UNWILLING_TO_PERFORM;
-           else
-       rs = LDAP_SUCCESS;
-         }
-       }    
+               entry_as_string = entry2str(e, &entry_length);
+               if(entry_as_string == NULL) {
+                       rs = LDAP_UNWILLING_TO_PERFORM;
+                       close(openres);
+               }
+               else {
+                       spew_res = spew_file(openres, entry_as_string);
+                       close(openres);
+                       if(spew_res == -1)
+                               rs = LDAP_UNWILLING_TO_PERFORM;
+                       else
+                               rs = LDAP_SUCCESS;
+               }
+       }
        return rs;
 }
 
@@ -158,132 +196,171 @@ static Entry * get_entry_for_fd(int fd) {
        
        /* error reading file */
        if(entry == NULL) {
-         goto return_value;
+               goto return_value;
        }
 
        ldentry = str2entry(entry);
 
  return_value:
        if(fd != -1) {
-         if(close(fd) != 0) {
-           /* log error */
-         }
+               if(close(fd) != 0) {
+                       /* log error */
+               }
        }
        if(entry != NULL)
-         SLAP_FREE(entry);
+               SLAP_FREE(entry);
        return ldentry;
 }
 
 static Entry * get_entry(struct berval * dn, struct berval * rootdn, struct berval * base_path) {
-       char * path = (char *) dn2path(dn, rootdn, base_path);
-       int fd = open(path, O_RDONLY);
+       struct berval path;
+       int fd;
 
+       dn2path(dn, rootdn, base_path, &path);
+       fd = open(path.bv_val, O_RDONLY);
        /* error opening file (mebbe should log error) */
        if(fd == -1) {
-         perror("failed to open file");
-         goto return_value;
+               perror("failed to open file");
        }
-       goto return_value;
 
- return_value:
-       if(path != NULL)
-         SLAP_FREE(path);
+       if(path.bv_val != NULL)
+               SLAP_FREE(path.bv_val);
        return get_entry_for_fd(fd);
 }
 
-/* takes a base path and a filename and opens that file */
-static int fd_for_path_components(char * base, char * name) {
-       char * absolutepath;
-       int fd;
-       absolutepath = (char *) SLAP_MALLOC(sizeof(char) * 
-                                     (strlen(base) + 
-                                      strlen(name) + 2));
-       absolutepath[0] = '\0';
-       strcat(absolutepath, base);
-       strcat(absolutepath, LDAP_DIRSEP);
-       strcat(absolutepath, name);
-       fd = open(absolutepath, O_RDONLY);
-       SLAP_FREE(absolutepath);
-       return fd;
+static void fullpath(struct berval *base, struct berval *name, struct berval *res) {
+       char *ptr;
+       res->bv_len = name->bv_len + base->bv_len + 1;
+       res->bv_val = ch_malloc( res->bv_len + 1 );
+       strcpy(res->bv_val, base->bv_val);
+       ptr = res->bv_val + base->bv_len;
+       *ptr++ = LDAP_DIRSEP[0];
+       strcpy(ptr, name->bv_val);
 }
 
-static Entry ** r_enum_tree(Entry ** entries, int *elen, int *eind, char * path) {
-       DIR * dir_of_path = opendir(path);
-       int fd;
-       struct dirent * dir;
-       char * newpath;
-       Entry * e;
+typedef struct bvlist {
+       struct bvlist *next;
+       struct berval bv;
+} bvlist;
+
+static Entry ** r_enum_tree(Entry ** entries, int *elen, int *eind,
+       struct berval * path, int scope) {
 
        if(entries == NULL) {
-         entries = (Entry **) SLAP_MALLOC(sizeof(Entry *) * ENTRY_BUFF_INCREMENT);
-         *elen = ENTRY_BUFF_INCREMENT;
+               entries = (Entry **) SLAP_MALLOC(sizeof(Entry *) * ENTRY_BUFF_INCREMENT);
+               *elen = ENTRY_BUFF_INCREMENT;
        }
-       if(dir_of_path == NULL) {/* can't open directory */
-         perror("failed to open directory");
-         return entries;
+
+       if ( scope == LDAP_SCOPE_BASE || scope == LDAP_SCOPE_SUBTREE ) {
+               int fd;
+               Entry * e;
+               if(! (*eind < *elen)) { /* grow entries if necessary */ 
+                       entries = (Entry **) SLAP_REALLOC(entries, sizeof(Entry *) * (*elen) * 2);
+                       *elen = *elen * 2;
+               }
+               fd = open( path->bv_val, O_RDONLY );
+               if ( fd < 0 ) {
+                       Debug( LDAP_DEBUG_TRACE,
+                               "=> ldif_enum_tree: failed to open %s\n",
+                               path->bv_val, 0, 0 );
+                       goto leave;
+               }
+
+               e = get_entry_for_fd(fd);
+               if(e != NULL) {
+                       entries[*eind] = e;
+                       *eind = *eind + 1;
+               }
+               else {
+                       Debug( LDAP_DEBUG_ANY,
+                               "=> ldif_enum_tree: failed to read entry for %s\n",
+                               path->bv_val, 0, 0 );
+                       goto leave;
+               }
        }
+       if ( scope != LDAP_SCOPE_BASE ) {
+               DIR * dir_of_path;
+               bvlist *list = NULL, *ptr;
+
+               path->bv_len -= STRLENOF( LDIF );
+               path->bv_val[path->bv_len] = '\0';
+
+               dir_of_path = opendir(path->bv_val);
+               if(dir_of_path == NULL) {/* can't open directory */
+                       Debug( LDAP_DEBUG_TRACE,
+                               "=> ldif_enum_tree: failed to opendir %s\n",
+                               path->bv_val, 0, 0 );
+                       goto leave;
+               }
        
-       while(1) {
-         dir = readdir(dir_of_path);
-         if(dir == NULL) break; /* end of the directory */
-         if(dir->d_type == DT_REG) { /* regular file, read the entry into memory */
-           if(! (*eind < *elen)) { /* grow entries if necessary */     
-       entries = (Entry **) SLAP_REALLOC(entries, sizeof(Entry *) * (*elen) * 2);
-       *elen = *elen * 2;
-           }
-           fd = fd_for_path_components(path, dir->d_name);
-           if(fd != -1) {
-       e = get_entry_for_fd(fd);
-       if(e != NULL) {
-         entries[*eind] = e;
-         *eind = *eind + 1;
+               while(1) {
+                       struct berval fname;
+                       struct dirent * dir;
+                       bvlist *bvl, *prev;
+
+                       dir = readdir(dir_of_path);
+                       if(dir == NULL) break; /* end of the directory */
+                       fname.bv_len = strlen( dir->d_name );
+                       if ( fname.bv_len <= STRLENOF( LDIF ))
+                               continue;
+                       if ( strcmp( dir->d_name + (fname.bv_len - STRLENOF(LDIF)), LDIF))
+                               continue;
+                       fname.bv_val = dir->d_name;
+
+                       bvl = ch_malloc( sizeof(bvlist) );
+                       ber_dupbv( &bvl->bv, &fname );
+
+                       for (ptr = list, prev = (bvlist *)&list; ptr;
+                               prev = ptr, ptr = ptr->next) {
+                               if ( strcmp( bvl->bv.bv_val, ptr->bv.bv_val ) < 0 )
+                                       break;
+                       }
+                       prev->next = bvl;
+                       bvl->next = ptr;
+                               
+               }
+               closedir(dir_of_path);
+
+               for ( ptr = list; ptr; ptr=ptr->next ) {
+                       struct berval fpath;
+                       fullpath( path, &ptr->bv, &fpath );
+                       entries = r_enum_tree(entries, elen, eind, &fpath,
+                               scope == LDAP_SCOPE_ONELEVEL ? LDAP_SCOPE_BASE : scope);
+                       free(fpath.bv_val);
+               }
        }
-       else
-         perror("failed to read entry");
-           }
-           else
-       perror("failed to open fd");
-         }
-         else if(dir->d_type == DT_DIR) {
-           if(! (strcasecmp(dir->d_name, ".") == 0 || strcasecmp(dir->d_name, "..") == 0)) {
-       newpath = (char *) SLAP_MALLOC(sizeof(char) * 
-                                      (strlen(path) + strlen(dir->d_name) + 2));
-       newpath[0] = '\0';
-       strcat(newpath, path);
-       strcat(newpath, LDAP_DIRSEP);
-       strcat(newpath, dir->d_name);
-       entries = r_enum_tree(entries, elen, eind, newpath);
-       SLAP_FREE(newpath);
-           }
-         }
-       }
-       closedir(dir_of_path);
+leave:
        return entries;
 }
 
-static Entry ** enum_tree(struct berval * path, int * length) {
+static Entry ** enum_tree(BackendDB *be, struct berval * ndn, int * length, int scope) {
+       struct ldif_info *ni = (struct ldif_info *) be->be_private;
+       struct berval path;
        int index = 0;
-       return r_enum_tree(NULL, &index, length, path->bv_val);
+
+       dn2path(ndn, &be->be_nsuffix[0], &ni->li_base_path, &path);
+       return r_enum_tree(NULL, &index, length, &path, scope);
 }
 
-static char * get_parent_path(char * dnpath) {
-       int dnpathlen = strlen(dnpath);
-       char * result;
+/* Get the parent path plus the LDIF suffix */
+static void get_parent_path(struct berval * dnpath, struct berval *res) {
+       int dnpathlen = dnpath->bv_len;
        int i;
        
        for(i = dnpathlen;i>0;i--) /* find the first path seperator */
-         if(dnpath[i] == LDAP_DIRSEP[0])
-           break;
-       result = ch_malloc( i + 1 );
-       strncpy(result, dnpath, i);
-       result[i] = '\0';
-       return result;
+               if(dnpath->bv_val[i] == LDAP_DIRSEP[0])
+                       break;
+       res->bv_len = i;
+       res->bv_val = ch_malloc( res->bv_len + 1 + STRLENOF(LDIF) );
+       strncpy(res->bv_val, dnpath->bv_val, i);
+       strcpy(res->bv_val+i, LDIF);
+       res->bv_val[i] = '\0';
 }
 
-static int apply_modify_to_entry(Entry * entry, 
-                         Modifications * modlist, 
-                         Operation * op,
-                         SlapReply * rs) 
+static int apply_modify_to_entry(Entry * entry,
+                               Modifications * modlist,
+                               Operation * op,
+                               SlapReply * rs)
 {
        char textbuf[SLAP_TEXT_BUFLEN];
        size_t textlen = sizeof textbuf;
@@ -293,65 +370,65 @@ static int apply_modify_to_entry(Entry * entry,
        Attribute *save_attrs;
 
        if (!acl_check_modlist(op, entry, modlist)) {
-         return LDAP_INSUFFICIENT_ACCESS;
+               return LDAP_INSUFFICIENT_ACCESS;
        }
 
        /*  save_attrs = entry->e_attrs; Why?
-           entry->e_attrs = attrs_dup(entry->e_attrs); */
+                       entry->e_attrs = attrs_dup(entry->e_attrs); */
 
        for (; modlist != NULL; modlist = modlist->sml_next) {
-         mods = &modlist->sml_mod;
-
-         switch (mods->sm_op) {
-         case LDAP_MOD_ADD:
-           rc = modify_add_values(entry, mods, 
-                            get_permissiveModify(op), 
-                            &rs->sr_text, textbuf, 
-                            textlen);
-           break;
+               mods = &modlist->sml_mod;
+
+               switch (mods->sm_op) {
+               case LDAP_MOD_ADD:
+                       rc = modify_add_values(entry, mods,
+                                  get_permissiveModify(op),
+                                  &rs->sr_text, textbuf,
+                                  textlen);
+                       break;
                                
-         case LDAP_MOD_DELETE:
-           rc = modify_delete_values(entry, mods, 
-                               get_permissiveModify(op), 
-                               &rs->sr_text, textbuf, 
+               case LDAP_MOD_DELETE:
+                       rc = modify_delete_values(entry, mods,
+                               get_permissiveModify(op),
+                               &rs->sr_text, textbuf,
                                textlen);
 
-           break;
+                       break;
                                
-         case LDAP_MOD_REPLACE:
-           rc = modify_replace_values(entry, mods, 
-                                get_permissiveModify(op), 
-                                &rs->sr_text, textbuf, 
+               case LDAP_MOD_REPLACE:
+                       rc = modify_replace_values(entry, mods,
+                                get_permissiveModify(op),
+                                &rs->sr_text, textbuf,
                                 textlen);
 
-           break;
-         case LDAP_MOD_INCREMENT:
-           break;
-         case SLAP_MOD_SOFTADD:
-           mods->sm_op = LDAP_MOD_ADD;
-           rc = modify_add_values(entry, mods, 
-                            get_permissiveModify(op),
-                            &rs->sr_text, textbuf, 
-                            textlen);
-           mods->sm_op = SLAP_MOD_SOFTADD;
-           if (rc == LDAP_TYPE_OR_VALUE_EXISTS) {
-       rc = LDAP_SUCCESS;
-           }      
-           break;
-         default:
-           break;
-         }
-         if(rc != LDAP_SUCCESS) break;
+                       break;
+               case LDAP_MOD_INCREMENT:
+                       break;
+               case SLAP_MOD_SOFTADD:
+                       mods->sm_op = LDAP_MOD_ADD;
+                       rc = modify_add_values(entry, mods,
+                                  get_permissiveModify(op),
+                                  &rs->sr_text, textbuf,
+                                  textlen);
+                       mods->sm_op = SLAP_MOD_SOFTADD;
+                       if (rc == LDAP_TYPE_OR_VALUE_EXISTS) {
+                               rc = LDAP_SUCCESS;
+                       }
+                       break;
+               default:
+                       break;
+               }
+               if(rc != LDAP_SUCCESS) break;
        }
        
        if(rc == LDAP_SUCCESS) {
-         if ( mods->sm_desc == slap_schema.si_ad_objectClass ) {
-           entry->e_ocflags = 0;
-         }
-         /* check that the entry still obeys the schema */
-         rc = entry_schema_check(op->o_bd, entry,
-                           save_attrs, &rs->sr_text, 
-                           textbuf, textlen);
+               if ( mods->sm_desc == slap_schema.si_ad_objectClass ) {
+                       entry->e_ocflags = 0;
+               }
+               /* check that the entry still obeys the schema */
+               rc = entry_schema_check(op->o_bd, entry,
+                                 save_attrs, &rs->sr_text,
+                                 textbuf, textlen);
        }
        return rc;
 }
@@ -371,35 +448,35 @@ ldif_back_bind( Operation *op, SlapReply *rs )
 
        /* no object is found for them */
        if(entry == NULL) {
-         if(be_isroot_pw(op)) {
-           return_val = LDAP_SUCCESS;
-           goto return_result;
-         }
-         else if(be_root_dn(op->o_bd)) {
-           return_val = LDAP_INVALID_CREDENTIALS;
-           rs->sr_err = LDAP_INVALID_CREDENTIALS;
-           goto return_result;
-         }
-         else {
-           rs->sr_err = LDAP_NO_SUCH_OBJECT;
-           return_val = 1;
-           goto return_result;
-         }
+               if(be_isroot_pw(op)) {
+                       return_val = LDAP_SUCCESS;
+                       goto return_result;
+               }
+               else if(be_root_dn(op->o_bd)) {
+                       return_val = LDAP_INVALID_CREDENTIALS;
+                       rs->sr_err = LDAP_INVALID_CREDENTIALS;
+                       goto return_result;
+               }
+               else {
+                       rs->sr_err = LDAP_NO_SUCH_OBJECT;
+                       return_val = 1;
+                       goto return_result;
+               }
        }
 
        /* they don't have userpassword */
        if((a = attr_find(entry->e_attrs, password)) == NULL) {
-         rs->sr_err = LDAP_INAPPROPRIATE_AUTH;
-         return_val = 1;
-         goto return_result;
+               rs->sr_err = LDAP_INAPPROPRIATE_AUTH;
+               return_val = 1;
+               goto return_result;
        }
 
        /* authentication actually failed */
        if(slap_passwd_check(op, entry, a, &op->oq_bind.rb_cred,
-                      &rs->sr_text) != 0) {
-         rs->sr_err = LDAP_INVALID_CREDENTIALS;
-         return_val = 1;
-         goto return_result;
+                            &rs->sr_text) != 0) {
+               rs->sr_err = LDAP_INVALID_CREDENTIALS;
+               return_val = 1;
+               goto return_result;
        }
 
        /* let the front-end send success */
@@ -409,9 +486,9 @@ ldif_back_bind( Operation *op, SlapReply *rs )
  return_result:
        ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
        if(return_val != 0)
-         send_ldap_result( op, rs );
+               send_ldap_result( op, rs );
        if(entry != NULL)
-         entry_free(entry);
+               entry_free(entry);
        return return_val;
 }
 
@@ -423,27 +500,27 @@ static int ldif_back_search(Operation *op, SlapReply *rs)
        Entry ** entries = NULL;
 
        ldap_pvt_thread_mutex_lock(&ni->li_mutex);
-       entries = (Entry **) enum_tree(&ni->li_base_path, &numentries);
+       entries = (Entry **) enum_tree(op->o_bd, &op->o_req_ndn, &numentries, op->ors_scope);
 
        if(entries != NULL) {
-         for(i=0;i<numentries;i++) {
-           if(test_filter(op, entries[i], op->ors_filter) == LDAP_COMPARE_TRUE) {
-       rs->sr_entry = entries[i];
-       rs->sr_attrs = op->ors_attrs;
-       rs->sr_flags = REP_ENTRY_MODIFIABLE;
-       send_search_entry(op, rs);
-           }
-           entry_free(entries[i]);
-         }
-         SLAP_FREE(entries);
-         rs->sr_err = LDAP_SUCCESS;
-         ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
-         send_ldap_result(op, rs);
+               for(i=0;i<numentries;i++) {
+                       if(test_filter(op, entries[i], op->ors_filter) == LDAP_COMPARE_TRUE) {
+                               rs->sr_entry = entries[i];
+                               rs->sr_attrs = op->ors_attrs;
+                               rs->sr_flags = REP_ENTRY_MODIFIABLE;
+                               send_search_entry(op, rs);
+                       }
+                       entry_free(entries[i]);
+               }
+               SLAP_FREE(entries);
+               rs->sr_err = LDAP_SUCCESS;
+               ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
+               send_ldap_result(op, rs);
        }
        else {
-         rs->sr_err = LDAP_BUSY;
-         ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
-         send_ldap_result(op, rs);
+               rs->sr_err = LDAP_BUSY;
+               ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
+               send_ldap_result(op, rs);
        }
 
        return 0;
@@ -452,205 +529,196 @@ static int ldif_back_search(Operation *op, SlapReply *rs)
 static int ldif_back_add(Operation *op, SlapReply *rs) {
        struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private;
        Entry * e = op->ora_e;
-       Attribute *save_attrs;
        struct berval dn = e->e_nname;
-       char * leaf_path = NULL;
-       char * base = NULL;
-       char * base_ldif = NULL;
+       struct berval leaf_path = BER_BVNULL;
        struct stat stats;
        int statres;
        char textbuf[SLAP_TEXT_BUFLEN];
        size_t textlen = sizeof textbuf;
 
+       rs->sr_err = entry_schema_check(op->o_bd, e,
+                                 NULL, &rs->sr_text, textbuf, textlen);
+       if ( rs->sr_err != LDAP_SUCCESS ) goto send_res;
+                               
        ldap_pvt_thread_mutex_lock(&ni->li_mutex);
-       ldap_pvt_thread_mutex_lock(&entry2str_mutex);
 
-       leaf_path = (char *) dn2path(&dn, &op->o_bd->be_nsuffix[0], &ni->li_base_path);
-
-       /*  save_attrs = e->e_attrs; why?
-           e->e_attrs = attrs_dup(e->e_attrs);*/
-
-       if(leaf_path != NULL) {
-         char * tmp;
-         /* build path to container, and path to ldif of container */
-         base = (char *) get_parent_path(leaf_path);
-         base_ldif = (char *) SLAP_MALLOC(sizeof(char) * (strlen(base) + 6));
-         tmp = (char *) lutil_strcopy(base_ldif, base);
-         lutil_strcopy(tmp, LDIF);
-
-         rs->sr_err = entry_schema_check(op->o_bd, e,
-                                   save_attrs, 
-                                   &rs->sr_text, 
-                                   textbuf, textlen);
-         if(rs->sr_err == LDAP_SUCCESS) {
-           statres = stat(base, &stats); /* check if container exists */
-           if(statres == -1 && errno == ENOENT) { /* container missing */
-       statres = stat(base_ldif, &stats); /* check for leaf node */
-       if(statres == -1 && errno == ENOENT) {
-         rs->sr_err = LDAP_NO_SUCH_OBJECT; /* parent doesn't exist */
-       }
-       else if(statres != -1) { /* create parent */
-         int mkdirres = mkdir(base, 0750);
-         if(mkdirres == -1) {
-           rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
-         }
+       dn2path(&dn, &op->o_bd->be_nsuffix[0], &ni->li_base_path, &leaf_path);
+
+       if(leaf_path.bv_val != NULL) {
+               struct berval base = BER_BVNULL;
+               /* build path to container and ldif of container */
+               get_parent_path(&leaf_path, &base);
+
+               statres = stat(base.bv_val, &stats); /* check if container exists */
+               if(statres == -1 && errno == ENOENT) { /* container missing */
+                       base.bv_val[base.bv_len] = '.';
+                       statres = stat(base.bv_val, &stats); /* check for leaf node */
+                       base.bv_val[base.bv_len] = '\0';
+                       if(statres == -1 && errno == ENOENT) {
+                               rs->sr_err = LDAP_NO_SUCH_OBJECT; /* parent doesn't exist */
+                       }
+                       else if(statres != -1) { /* create parent */
+                               int mkdirres = mkdir(base.bv_val, 0750);
+                               if(mkdirres == -1) {
+                                       rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+                               }
+                       }
+                       else
+                               rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+               }/* container was possibly created, move on to add the entry */
+               if(rs->sr_err == LDAP_SUCCESS) {
+                       statres = stat(leaf_path.bv_val, &stats);
+                       if(statres == -1 && errno == ENOENT) {
+                               ldap_pvt_thread_mutex_lock(&entry2str_mutex);
+                               rs->sr_err = (int) spew_entry(e, &leaf_path);
+                               ldap_pvt_thread_mutex_unlock(&entry2str_mutex);
+                       }
+                       else /* it already exists */
+                               rs->sr_err = LDAP_ALREADY_EXISTS;
+               }
+               SLAP_FREE(base.bv_val);
+               SLAP_FREE(leaf_path.bv_val);
        }
-       else
-         rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
-           }/* container was possibly created, move on to add the entry */
-           if(rs->sr_err == LDAP_SUCCESS) {
-       statres = stat(leaf_path, &stats);
-       if(statres == -1 && errno == ENOENT) {
-         rs->sr_err = (int) spew_entry(e, leaf_path);
-       }
-       else /* it already exists */
-         rs->sr_err = LDAP_ALREADY_EXISTS;
-           }  
-         }
-       }    
 
        ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
-       ldap_pvt_thread_mutex_unlock(&entry2str_mutex);
 
-       send_ldap_result(op, rs);  
-       if(leaf_path != NULL)
-         SLAP_FREE(leaf_path);
-       if(base != NULL)
-         SLAP_FREE(base);
-       if(base_ldif != NULL)
-         SLAP_FREE(base_ldif);
+send_res:
+       send_ldap_result(op, rs);
        return 0;
 }
 
 static int ldif_back_modify(Operation *op, SlapReply *rs) {
        struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private;
        Modifications * modlst = op->orm_modlist;
-       char * path = NULL;
+       struct berval path = BER_BVNULL;
        Entry * entry = NULL;
        int spew_res;
 
        ldap_pvt_thread_mutex_lock(&ni->li_mutex);
-       ldap_pvt_thread_mutex_lock(&entry2str_mutex);
-       path = (char *) dn2path(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path);
-       entry = (Entry *) get_entry(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path);
+       dn2path(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path,
+               &path);
+       entry = (Entry *) get_entry(&op->o_req_ndn, &op->o_bd->be_nsuffix[0],
+               &ni->li_base_path);
 
        if(entry != NULL) {
-         rs->sr_err = apply_modify_to_entry(entry, modlst, op, rs);
-         if(rs->sr_err == LDAP_SUCCESS) {
-           spew_res = spew_entry(entry, path);
-           if(spew_res == -1) {
-       perror("could not output entry");
-       rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
-           }
-         }
+               rs->sr_err = apply_modify_to_entry(entry, modlst, op, rs);
+               if(rs->sr_err == LDAP_SUCCESS) {
+                       ldap_pvt_thread_mutex_lock(&entry2str_mutex);
+                       spew_res = spew_entry(entry, &path);
+                       ldap_pvt_thread_mutex_unlock(&entry2str_mutex);
+                       if(spew_res == -1) {
+                               perror("could not output entry");
+                               rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+                       }
+               }
        }
        else {
-         rs->sr_err = LDAP_NO_SUCH_OBJECT;
+               rs->sr_err = LDAP_NO_SUCH_OBJECT;
        }
        
-       if(path != NULL)
-         SLAP_FREE(path);
        if(entry != NULL)
-         entry_free(entry);
-       rs->sr_text = "";
+               entry_free(entry);
+       if(path.bv_val != NULL)
+               SLAP_FREE(path.bv_val);
+       rs->sr_text = NULL;
        ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
-       ldap_pvt_thread_mutex_unlock(&entry2str_mutex);
        send_ldap_result(op, rs);
        return 0;
 }
 
 static int ldif_back_delete(Operation *op, SlapReply *rs) {
        struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private;
-       char * path = NULL;
+       struct berval path = BER_BVNULL;
        int res = 0;
 
        ldap_pvt_thread_mutex_lock(&ni->li_mutex);
-       path = (char *) dn2path(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path);
-       res = unlink(path);
+       dn2path(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path, &path);
+       res = unlink(path.bv_val);
 
        if(res == -1) {
-         if(errno == ENOENT)
-           rs->sr_err = LDAP_NO_SUCH_OBJECT;
-         else
-           rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+               if(errno == ENOENT)
+                       rs->sr_err = LDAP_NO_SUCH_OBJECT;
+               else
+                       rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
        }
        else
-         rs->sr_err = LDAP_SUCCESS;
+               rs->sr_err = LDAP_SUCCESS;
 
-       SLAP_FREE(path);
+       SLAP_FREE(path.bv_val);
        ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
        send_ldap_result(op, rs);
        return 0;
 }
 
-static int is_leaf_node(char * path) {
-       DIR * nonleafnode;  
-       int path_len = strlen(path);
-       char * nonleafpath = (char *) SLAP_MALLOC(sizeof(char) * path_len + 1);
+static int is_leaf_node(struct berval * path) {
+       DIR * nonleafnode;
+       int path_len = path->bv_len;
        int res;
 
-       strncpy(nonleafpath, path, path_len);
-       nonleafpath[path_len - 5] = '\0';
-       nonleafnode = opendir(nonleafpath);
+       path->bv_val[path->bv_len - STRLENOF(LDIF)] = '\0';
+       nonleafnode = opendir(path->bv_val);
+       path->bv_val[path->bv_len - STRLENOF(LDIF)] = '.';
        if(nonleafnode == NULL) {
-         res = 1;
+               res = 1;
        }
        else {
-         closedir(nonleafnode);
-         res = 0;
+               closedir(nonleafnode);
+               res = 0;
        }
-       SLAP_FREE(nonleafpath);
        return res;
 }
 
-static int move_entry(Entry * entry, struct berval * ndn, 
-              struct berval * newndn, struct berval * rootdn,
-              struct berval * base_path) {
+static int move_entry(Entry * entry, struct berval * ndn,
+                          struct berval * newndn, struct berval * rootdn,
+                          struct berval * base_path) {
        int res;
        int exists_res;
-       char * path = (char *) dn2path(ndn, rootdn, base_path);
-       char * newpath = (char *) dn2path(newndn, rootdn, base_path);
-       int path_len = strlen(path);
+       struct berval path;
+       struct berval newpath;
 
-       if((entry == NULL || path == NULL) || newpath == NULL) { /* some object doesn't exist */
-         res = LDAP_NO_SUCH_OBJECT;
+       dn2path(ndn, rootdn, base_path, &path);
+       dn2path(newndn, rootdn, base_path, &newpath);
+
+       if((entry == NULL || path.bv_val == NULL) || newpath.bv_val == NULL) {
+               /* some object doesn't exist */
+               res = LDAP_NO_SUCH_OBJECT;
        }
-       else if(! is_leaf_node(path)) { /* entry is not a leaf node */
-         res = LDAP_NOT_ALLOWED_ON_NONLEAF;
+       else if(! is_leaf_node(&path)) { /* entry is not a leaf node */
+               res = LDAP_NOT_ALLOWED_ON_NONLEAF;
        }
        else { /* do the modrdn */
-         exists_res = open(newpath, O_RDONLY);
-         if(exists_res == -1 && errno == ENOENT) {
-           res = spew_entry(entry, newpath);
-           if(res != -1) {
-       /* if this fails we should log something bad */
-       res = unlink(path);
-       res = LDAP_SUCCESS;
-           }
-           else {
-       if(errno == ENOENT)
-         res = LDAP_NO_SUCH_OBJECT;
-       else
-         res = LDAP_UNWILLING_TO_PERFORM;
-       unlink(newpath); /* in case file was created */            
-           }
-         }
-         else if(exists_res) {
-           res = LDAP_ALREADY_EXISTS;
-           int close_res = close(exists_res);
-           if(close_res == -1) {
-       /* log heinous error */
-           }
-         }
-         else {
-           res = LDAP_UNWILLING_TO_PERFORM;
-         }
-       }
-
-       if(path != NULL)
-         SLAP_FREE(path);
-       if(newpath != NULL)
-         SLAP_FREE(newpath);
+               exists_res = open(newpath.bv_val, O_RDONLY);
+               if(exists_res == -1 && errno == ENOENT) {
+                       res = spew_entry(entry, &newpath);
+                       if(res != -1) {
+                               /* if this fails we should log something bad */
+                               res = unlink(path.bv_val);
+                               res = LDAP_SUCCESS;
+                       }
+                       else {
+                               if(errno == ENOENT)
+                                       res = LDAP_NO_SUCH_OBJECT;
+                               else
+                                       res = LDAP_UNWILLING_TO_PERFORM;
+                               unlink(newpath.bv_val); /* in case file was created */
+                       }
+               }
+               else if(exists_res) {
+                       int close_res = close(exists_res);
+                       res = LDAP_ALREADY_EXISTS;
+                       if(close_res == -1) {
+                       /* log heinous error */
+                       }
+               }
+               else {
+                       res = LDAP_UNWILLING_TO_PERFORM;
+               }
+       }
+
+       if(newpath.bv_val != NULL)
+               SLAP_FREE(newpath.bv_val);
+       if(path.bv_val != NULL)
+               SLAP_FREE(path.bv_val);
        return res;
 }
 
@@ -658,7 +726,7 @@ static int ldif_back_modrdn(Operation *op, SlapReply *rs) {
        struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private;
        struct berval new_dn = {0, NULL}, new_ndn = {0, NULL};
        struct berval * new_parent_dn = NULL;
-       struct berval p_dn;
+       struct berval p_dn, bv = {0, NULL};
        Entry * entry = NULL;
        LDAPRDN new_rdn = NULL;
        LDAPRDN old_rdn = NULL;
@@ -667,56 +735,57 @@ static int ldif_back_modrdn(Operation *op, SlapReply *rs) {
 
        ldap_pvt_thread_mutex_lock(&ni->li_mutex);
        ldap_pvt_thread_mutex_lock(&entry2str_mutex);
-       entry = (Entry *) get_entry(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path);
+       entry = (Entry *) get_entry(&op->o_req_ndn, &op->o_bd->be_nsuffix[0],
+               &ni->li_base_path);
 
        /* build the mods to the entry */
        if(entry != NULL) {
-         if(ldap_bv2rdn(&op->oq_modrdn.rs_newrdn, &new_rdn, (char **)&rs->sr_text, 
-                  LDAP_DN_FORMAT_LDAP)) {
-           rs->sr_err = LDAP_INVALID_DN_SYNTAX;
-         }
-         else if(op->oq_modrdn.rs_deleteoldrdn &&
-           ldap_bv2rdn(&op->o_req_dn, &old_rdn, (char **)&rs->sr_text,
+               if(ldap_bv2rdn(&op->oq_modrdn.rs_newrdn, &new_rdn,
+                       (char **)&rs->sr_text, LDAP_DN_FORMAT_LDAP)) {
+                       rs->sr_err = LDAP_INVALID_DN_SYNTAX;
+               }
+               else if(op->oq_modrdn.rs_deleteoldrdn &&
+                       ldap_bv2rdn(&op->o_req_dn, &old_rdn, (char **)&rs->sr_text,
                        LDAP_DN_FORMAT_LDAP)) {
-           rs->sr_err = LDAP_OTHER;
-         }
-         else { /* got both rdns successfully, ready to build mods */
-           if(slap_modrdn2mods(op, rs, entry, old_rdn, new_rdn, &mods) != LDAP_SUCCESS) {
-       rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
-           }
-           else { /* built mods successfully */
-
-       /* build new dn, and new ndn for the entry */
-       if(op->oq_modrdn.rs_newSup != NULL) /* new superior */
-         p_dn = *op->oq_modrdn.rs_newSup;
-       else
-         p_dn = slap_empty_bv;
-       dnParent(&entry->e_name, &p_dn);
-       build_new_dn(&new_dn, &p_dn, &op->oq_modrdn.rs_newrdn, NULL); 
-       struct berval bv = {0, NULL};
-       dnNormalize( 0, NULL, NULL, &new_dn, &bv, op->o_tmpmemctx );
-       ber_dupbv( &new_ndn, &bv );
-       entry->e_name = new_dn;
-       entry->e_nname = new_ndn;
-
-       /* perform the modifications */
-       res = apply_modify_to_entry(entry, mods, op, rs);
-       if(res == LDAP_SUCCESS) {
-         rs->sr_err = move_entry(entry, &op->o_req_ndn, 
-                                 &new_ndn,
-                                 &op->o_bd->be_nsuffix[0],
-                                 &ni->li_base_path);
-       }
-       else
-         rs->sr_err = res;
-           }
-         }
+                       rs->sr_err = LDAP_OTHER;
+               }
+               else { /* got both rdns successfully, ready to build mods */
+                       if(slap_modrdn2mods(op, rs, entry, old_rdn, new_rdn, &mods)
+                               != LDAP_SUCCESS) {
+                               rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+                       }
+                       else { /* built mods successfully */
+
+                               /* build new dn, and new ndn for the entry */
+                               if(op->oq_modrdn.rs_newSup != NULL) /* new superior */
+                                       p_dn = *op->oq_modrdn.rs_newSup;
+                               else
+                                       p_dn = slap_empty_bv;
+                               dnParent(&entry->e_name, &p_dn);
+                               build_new_dn(&new_dn, &p_dn, &op->oq_modrdn.rs_newrdn, NULL); 
+                               dnNormalize( 0, NULL, NULL, &new_dn, &bv, op->o_tmpmemctx );
+                               ber_dupbv( &new_ndn, &bv );
+                               entry->e_name = new_dn;
+                               entry->e_nname = new_ndn;
+
+                               /* perform the modifications */
+                               res = apply_modify_to_entry(entry, mods, op, rs);
+                               if(res == LDAP_SUCCESS) {
+                                       rs->sr_err = move_entry(entry, &op->o_req_ndn,
+                                                               &new_ndn,
+                                                               &op->o_bd->be_nsuffix[0],
+                                                               &ni->li_base_path);
+                               }
+                               else
+                                       rs->sr_err = res;
+                       }
+               }
        }
        else /* entry was null */
-         rs->sr_err = LDAP_NO_SUCH_OBJECT;
+               rs->sr_err = LDAP_NO_SUCH_OBJECT;
 
        if(entry != NULL)
-         entry_free(entry);
+               entry_free(entry);
        rs->sr_text = "";
        ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
        ldap_pvt_thread_mutex_unlock(&entry2str_mutex);
@@ -731,38 +800,37 @@ static int ldif_back_compare(Operation *op, SlapReply *rs) {
 
        ldap_pvt_thread_mutex_lock(&ni->li_mutex);
 
-       e = (Entry *) get_entry(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path);
+       e = (Entry *) get_entry(&op->o_req_ndn, &op->o_bd->be_nsuffix[0],
+               &ni->li_base_path);
        if(e != NULL) {
-         for(a = attrs_find( e->e_attrs, op->oq_compare.rs_ava->aa_desc );
-       a != NULL;
-       a = attrs_find( a->a_next, op->oq_compare.rs_ava->aa_desc ))
-           {
-       rs->sr_err = LDAP_COMPARE_FALSE;
-       
-       if (value_find_ex(op->oq_compare.rs_ava->aa_desc,
-                         SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
-                         SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
-                         a->a_nvals, &op->oq_compare.rs_ava->aa_value,
-                         op->o_tmpmemctx ) == 0)
-         {
-           rs->sr_err = LDAP_COMPARE_TRUE;
-           break;
-         }
-           }
+               for(a = attrs_find( e->e_attrs, op->oq_compare.rs_ava->aa_desc );
+                       a != NULL;
+                       a = attrs_find( a->a_next, op->oq_compare.rs_ava->aa_desc )) {
+                       rs->sr_err = LDAP_COMPARE_FALSE;
+               
+                       if (value_find_ex(op->oq_compare.rs_ava->aa_desc,
+                                               SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
+                                               SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
+                                               a->a_nvals, &op->oq_compare.rs_ava->aa_value,
+                                               op->o_tmpmemctx ) == 0) {
+                               rs->sr_err = LDAP_COMPARE_TRUE;
+                               break;
+                       }
+               }
        }
        else {
-         rs->sr_err = LDAP_NO_SUCH_OBJECT;
+               rs->sr_err = LDAP_NO_SUCH_OBJECT;
        }
 
        if(e != NULL)
-         entry_free(e);
+               entry_free(e);
        ldap_pvt_thread_mutex_unlock(&ni->li_mutex);
        send_ldap_result(op, rs);
        return 0;
 }
 
 static int ldif_tool_entry_open(BackendDB * be, int mode) {
-       struct ldif_info *ni = (struct ldif_info *) be->be_private;  
+       struct ldif_info *ni = (struct ldif_info *) be->be_private;
        ni->tool_entries = NULL;
        ni->tool_numentries = 0;
        ni->tool_current = 0;
@@ -771,143 +839,107 @@ static int ldif_tool_entry_open(BackendDB * be, int mode) {
 }                                      
 
 static int ldif_tool_entry_close(BackendDB * be) {
-       struct ldif_info *ni = (struct ldif_info *) be->be_private;  
-       int i;
-       /*if(ni->tool_entries != NULL) {
-         for(i=0;i<ni->tool_numentries;i++) {
-           SLAP_FREE(ni->tool_entries[i]);
-           }*/
+       struct ldif_info *ni = (struct ldif_info *) be->be_private;
+
        SLAP_FREE(ni->tool_entries);
        return 0;
 }
 
 static ID ldif_tool_entry_first(BackendDB *be) {
-       struct ldif_info *ni = (struct ldif_info *) be->be_private;  
+       struct ldif_info *ni = (struct ldif_info *) be->be_private;
        ID id = 1; /* first entry in the array of entries shifted by one */
+
        ni->tool_current = 1;
        if(ni->tool_entries == NULL || ni->tool_put_entry_flag) {
-         ni->tool_entries = (Entry **) enum_tree(&ni->li_base_path, &ni->tool_numentries);
-         ni->tool_put_entry_flag = 0;
+               ni->tool_entries = (Entry **) enum_tree(be, &be->be_nsuffix[0],
+                       &ni->tool_numentries, LDAP_SCOPE_SUBTREE);
+               ni->tool_put_entry_flag = 0;
        }
        return id;
 }
 
 static ID ldif_tool_entry_next(BackendDB *be) {
-       struct ldif_info *ni = (struct ldif_info *) be->be_private;  
+       struct ldif_info *ni = (struct ldif_info *) be->be_private;
        ni->tool_current += 1;
        if(ni->tool_put_entry_flag) {
-         ni->tool_entries = (Entry **) enum_tree(&ni->li_base_path, &ni->tool_numentries);
-         ni->tool_put_entry_flag = 0;
+               ni->tool_entries = (Entry **) enum_tree(be, &be->be_nsuffix[0],
+                       &ni->tool_numentries, LDAP_SCOPE_SUBTREE);
+               ni->tool_put_entry_flag = 0;
        }
        if(ni->tool_current > ni->tool_numentries)
-         return NOID;
+               return NOID;
        else
-         return ni->tool_current;
+               return ni->tool_current;
 }
 
 static Entry * ldif_tool_entry_get(BackendDB * be, ID id) {
-       struct ldif_info *ni = (struct ldif_info *) be->be_private;  
+       struct ldif_info *ni = (struct ldif_info *) be->be_private;
        Entry * e;
 
        if(id > ni->tool_numentries || id < 1)
-         return NULL;
+               return NULL;
        else {
-         e = ni->tool_entries[id - 1];
-         ni->tool_entries[id - 1] = NULL;
-         return e;
+               e = ni->tool_entries[id - 1];
+               ni->tool_entries[id - 1] = NULL;
+               return e;
        }
 }
 
 static ID ldif_tool_entry_put(BackendDB * be, Entry * e, struct berval *text) {
-       struct ldif_info *ni = (struct ldif_info *) be->be_private;  
-         Attribute *save_attrs;
+       struct ldif_info *ni = (struct ldif_info *) be->be_private;
+       Attribute *save_attrs;
        struct berval dn = e->e_nname;
-       char * leaf_path = NULL;
-       char * base = NULL;
-       char * base_ldif = NULL;
+       struct berval leaf_path = BER_BVNULL;
        struct stat stats;
        int statres;
        char textbuf[SLAP_TEXT_BUFLEN];
        size_t textlen = sizeof textbuf;
        int res = LDAP_SUCCESS;
 
-       leaf_path = (char *) dn2path(&dn, &be->be_nsuffix[0], &ni->li_base_path);
-
-       /*  save_attrs = e->e_attrs; why?
-           e->e_attrs = attrs_dup(e->e_attrs);*/
-
-       if(leaf_path != NULL) {
-         char * tmp;
-         /* build path to container, and path to ldif of container */
-         base = (char *) get_parent_path(leaf_path);
-         base_ldif = (char *) SLAP_MALLOC(sizeof(char) * (strlen(base) + 6));
-         tmp = (char *) lutil_strcopy(base_ldif, base);
-         lutil_strcopy(tmp, LDIF);
-
-         statres = stat(base, &stats); /* check if container exists */
-         if(statres == -1 && errno == ENOENT) { /* container missing */
-           statres = stat(base_ldif, &stats); /* check for leaf node */
-           if(statres == -1 && errno == ENOENT) {
-       res = LDAP_NO_SUCH_OBJECT; /* parent doesn't exist */
-           }
-           else if(statres != -1) { /* create parent */
-       int mkdirres = mkdir(base, 0750);
-       if(mkdirres == -1) {
-         res = LDAP_UNWILLING_TO_PERFORM;
-       }
-           }
-           else
-       res = LDAP_UNWILLING_TO_PERFORM;
-         }/* container was possibly created, move on to add the entry */
-         if(res == LDAP_SUCCESS) {
-           statres = stat(leaf_path, &stats);
-           if(statres == -1 && errno == ENOENT) {
-       res = (int) spew_entry(e, leaf_path);
-           }
-           else /* it already exists */
-       res = LDAP_ALREADY_EXISTS;
-         }  
-       }
-
-       if(leaf_path != NULL)
-         SLAP_FREE(leaf_path);
-       if(base != NULL)
-         SLAP_FREE(base);
-       if(base_ldif != NULL)
-         SLAP_FREE(base_ldif);
-       if(res == LDAP_SUCCESS) {
-         ni->tool_put_entry_flag = 1;
-         return 1;
+       dn2path(&dn, &be->be_nsuffix[0], &ni->li_base_path, &leaf_path);
+
+       if(leaf_path.bv_val != NULL) {
+               struct berval base = BER_BVNULL;
+               /* build path to container, and path to ldif of container */
+               get_parent_path(&leaf_path, &base);
+
+               statres = stat(base.bv_val, &stats); /* check if container exists */
+               if(statres == -1 && errno == ENOENT) { /* container missing */
+                       base.bv_val[base.bv_len] = '.';
+                       statres = stat(base.bv_val, &stats); /* check for leaf node */
+                       base.bv_val[base.bv_len] = '\0';
+                       if(statres == -1 && errno == ENOENT) {
+                               res = LDAP_NO_SUCH_OBJECT; /* parent doesn't exist */
+                       }
+                       else if(statres != -1) { /* create parent */
+                               int mkdirres = mkdir(base.bv_val, 0750);
+                               if(mkdirres == -1) {
+                                       res = LDAP_UNWILLING_TO_PERFORM;
+                               }
+                       }
+                       else
+                               res = LDAP_UNWILLING_TO_PERFORM;
+               }/* container was possibly created, move on to add the entry */
+               if(res == LDAP_SUCCESS) {
+                       statres = stat(leaf_path.bv_val, &stats);
+                       if(statres == -1 && errno == ENOENT) {
+                               res = (int) spew_entry(e, &leaf_path);
+                       }
+                       else /* it already exists */
+                               res = LDAP_ALREADY_EXISTS;
+               }
+               SLAP_FREE(base.bv_val);
+               SLAP_FREE(leaf_path.bv_val);
        }
-       else
-         return NOID;
-}
 
-static int
-ldif_back_db_config(
-                   BackendDB   *be,
-                   const char  *fname,
-                   int                 lineno,
-                   int                 argc,
-                   char                **argv )
-{
-       struct ldif_info *ni = (struct ldif_info *) be->be_private;
-
-       if ( strcasecmp( argv[0], "directory" ) == 0 ) {
-         if ( argc < 2 ) {
-           fprintf( stderr,
-              "%s: line %d: missing <path> in \"directory <path>\" line\n",
-              fname, lineno );
-           return 1;
-         }
-         ber_str2bv(argv[1], 0, 1, &ni->li_base_path);
-       } else {
-         return SLAP_CONF_UNKNOWN;
+       if(res == LDAP_SUCCESS) {
+               ni->tool_put_entry_flag = 1;
+               return 1;
        }
-       return 0;
+       else
+               return NOID;
 }
 
-
 static int
 ldif_back_db_init( BackendDB *be )
 {
@@ -915,14 +947,15 @@ ldif_back_db_init( BackendDB *be )
 
        ni = ch_calloc( 1, sizeof(struct ldif_info) );
        be->be_private = ni;
+       be->be_cf_table = be->bd_info->bi_cf_table;
        ldap_pvt_thread_mutex_init(&ni->li_mutex);
        return 0;
 }
 
 static int
 ldif_back_db_destroy(
-                    Backend    *be
-                    )
+                          Backend      *be
+                          )
 {
        struct ldif_info *ni = be->be_private;
        ldap_pvt_thread_mutex_destroy(&ni->li_mutex);
@@ -932,29 +965,33 @@ ldif_back_db_destroy(
 
 static int
 ldif_back_db_open(
-                 Backend       *be
-                 )
+                       Backend *be
+                       )
 {
        struct ldif_info *ni = (struct ldif_info *) be->be_private;
        if( BER_BVISEMPTY(&ni->li_base_path)) {/* missing base path */
-         fprintf(stderr, "missing base path for back-ldif\n");
-         return 1;
+               fprintf(stderr, "missing base path for back-ldif\n");
+               return 1;
        }
        return 0;
 }
 
 int
 ldif_back_initialize(
-                    BackendInfo        *bi
-                    )
+                          BackendInfo  *bi
+                          )
 {
+       int rc;
+
+       bi->bi_cf_table = ldifcfg;
+
        bi->bi_open = 0;
        bi->bi_close = 0;
        bi->bi_config = 0;
        bi->bi_destroy = 0;
 
        bi->bi_db_init = ldif_back_db_init;
-       bi->bi_db_config = ldif_back_db_config;
+       bi->bi_db_config = config_generic_wrapper;
        bi->bi_db_open = ldif_back_db_open;
        bi->bi_db_close = 0;
        bi->bi_db_destroy = ldif_back_db_destroy;
@@ -989,5 +1026,8 @@ ldif_back_initialize(
        bi->bi_tool_id2entry_get = 0;
        bi->bi_tool_entry_modify = 0;
 
+       rc = config_register_schema( ldifcfg, ldifocs );
+       if ( rc ) return rc;
+       ldifcfg[0].ad = slap_schema.si_ad_objectClass;
        return 0;
 }
index 8532f4b7085f2b746b488319681a1e7433b593d3..e1b31a50c1d6f6817afd4502e376361d11c2d112 100644 (file)
@@ -659,9 +659,11 @@ overlay_config( BackendDB *be, const char *ov )
 
        /* Any initialization needed? */
        if ( on->on_bi.bi_db_init ) {
+               int rc;
                be->bd_info = (BackendInfo *)on2;
-               on2->on_bi.bi_db_init( be );
+               rc = on2->on_bi.bi_db_init( be );
                be->bd_info = (BackendInfo *)oi;
+               if ( rc ) return rc;
        }
 
        return 0;
index 171b688354f6411bacc82addfedea4d0bf0e40bf..e83f6c737b9683ee0c73c6a2d4b7c3a9cb0acdc3 100644 (file)
@@ -36,7 +36,6 @@
 #include "config.h"
 
 static struct berval config_rdn = BER_BVC("cn=config");
-static struct berval access_rdn = BER_BVC("cn=access");
 
 #ifdef SLAPD_MODULES
 typedef struct modpath_s {
@@ -57,10 +56,24 @@ typedef struct ConfigFile {
        BerVarray c_dseFiles;
 } ConfigFile;
 
+typedef struct CfOcInfo {
+       struct berval *co_name;
+       ConfigTable *co_table;
+} CfOcInfo;
+
+typedef enum {
+       Cf_Global = 1,
+       Cf_Include,
+       Cf_Backend,
+       Cf_Database,
+       Cf_Overlay
+} CfEtypes;
+
 typedef struct CfEntryInfo {
        struct CfEntryInfo *ce_sibs;
        struct CfEntryInfo *ce_kids;
        Entry *ce_entry;
+       CfEtypes ce_type;
        BackendInfo *ce_bi;
        BackendDB *ce_be;
 } CfEntryInfo;
@@ -68,6 +81,8 @@ typedef struct CfEntryInfo {
 typedef struct {
        ConfigFile *cb_config;
        CfEntryInfo *cb_root;
+       BackendDB       cb_db;  /* underlying database */
+       int             cb_got_ldif;
 } CfBackInfo;
 
 /* These do nothing in slapd, they're kept only to make them
@@ -80,19 +95,25 @@ static char *passwd_salt;
 static char    *logfileName;
 static BerVarray authz_rewrites;
 
+static struct berval cfdir;
+
+/* Private state */
 static AttributeDescription *cfAd_backend, *cfAd_database, *cfAd_overlay,
        *cfAd_include;
 
 static ObjectClass *cfOc_global, *cfOc_backend, *cfOc_database,
-       *cfOc_include, *cfOc_overlay, *cfOc_access;
+       *cfOc_include, *cfOc_overlay;
 
 static ConfigFile cf_prv, *cfn = &cf_prv;
 
+static Avlnode *CfOcTree;
+
 static int add_syncrepl LDAP_P(( Backend *, char **, int ));
 static int parse_syncrepl_line LDAP_P(( char **, int, syncinfo_t *));
 static void syncrepl_unparse LDAP_P (( syncinfo_t *, struct berval *));
 
 static ConfigDriver config_fname;
+static ConfigDriver config_cfdir;
 static ConfigDriver config_generic;
 static ConfigDriver config_search_base;
 static ConfigDriver config_passwd_hash;
@@ -191,6 +212,11 @@ ConfigTable config_back_cf_table[] = {
                        "DESC 'File for slapd configuration directives' "
                        "EQUALITY caseIgnoreMatch "
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
+       { "", "", 0, 0, 0, ARG_MAGIC,
+               &config_cfdir, "( OLcfgAt:79 NAME 'olcConfigDir' "
+                       "DESC 'Directory for slapd configuration backend' "
+                       "EQUALITY caseIgnoreMatch "
+                       "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
        { "access",     NULL, 0, 0, 0, ARG_MAY_DB|ARG_MAGIC|CFG_ACL,
                &config_generic, "( OLcfgAt:1 NAME 'olcAccess' "
                        "DESC 'Access Control List' "
@@ -238,10 +264,10 @@ ConfigTable config_back_cf_table[] = {
        { "concurrency", "level", 2, 2, 0, ARG_INT|ARG_NONZERO|ARG_MAGIC|CFG_CONCUR,
                &config_generic, "( OLcfgAt:10 NAME 'olcConcurrency' "
                        "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
-       { "conn_max_pending", "max", 2, 2, 0, ARG_LONG,
+       { "conn_max_pending", "max", 2, 2, 0, ARG_INT,
                &slap_conn_max_pending, "( OLcfgAt:11 NAME 'olcConnMaxPending' "
                        "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
-       { "conn_max_pending_auth", "max", 2, 2, 0, ARG_LONG,
+       { "conn_max_pending_auth", "max", 2, 2, 0, ARG_INT,
                &slap_conn_max_pending_auth, "( OLcfgAt:12 NAME 'olcConnMaxPendingAuth' "
                        "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
        { "database", "type", 2, 2, 0, ARG_MAGIC|CFG_DATABASE,
@@ -291,7 +317,7 @@ ConfigTable config_back_cf_table[] = {
        { "limits", "limits", 2, 0, 0, ARG_DB|ARG_MAGIC|CFG_LIMITS,
                &config_generic, "( OLcfgAt:25 NAME 'olcLimits' "
                        "SYNTAX OMsDirectoryString )", NULL, NULL },
-       { "localSSF", "ssf", 2, 2, 0, ARG_LONG,
+       { "localSSF", "ssf", 2, 2, 0, ARG_INT,
                &local_ssf, "( OLcfgAt:26 NAME 'olcLocalSSF' "
                        "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
        { "logfile", "file", 2, 2, 0, ARG_STRING|ARG_MAGIC|CFG_LOGFILE,
@@ -439,10 +465,10 @@ ConfigTable config_back_cf_table[] = {
        { "sizelimit", "limit", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC|CFG_SIZE,
                &config_sizelimit, "( OLcfgAt:60 NAME 'olcSizeLimit' "
                        "SYNTAX OMsInteger )", NULL, NULL },
-       { "sockbuf_max_incoming", "max", 2, 2, 0, ARG_LONG,
+       { "sockbuf_max_incoming", "max", 2, 2, 0, ARG_BER_LEN_T,
                &sockbuf_max_incoming, "( OLcfgAt:61 NAME 'olcSockbufMaxIncoming' "
                        "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
-       { "sockbuf_max_incoming_auth", "max", 2, 2, 0, ARG_LONG,
+       { "sockbuf_max_incoming_auth", "max", 2, 2, 0, ARG_BER_LEN_T,
                &sockbuf_max_incoming_auth, "( OLcfgAt:62 NAME 'olcSockbufMaxIncomingAuth' "
                        "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
        { "srvtab", "file", 2, 2, 0,
@@ -551,7 +577,7 @@ static ConfigOCs cf_ocs[] = {
                "NAME 'olcGlobal' "
                "DESC 'OpenLDAP Global configuration options' "
                "SUP olcConfig STRUCTURAL "
-               "MAY ( olcAllows $ olcArgsFile $ olcAttributeOptions $ "
+               "MAY ( olcConfigDir $ olcAllows $ olcArgsFile $ olcAttributeOptions $ "
                 "olcAuthIDRewrite $ olcAuthzPolicy $ olcAuthzRegexp $ "
                 "olcConcurrency $ olcConnMaxPending $ olcConnMaxPendingAuth $ "
                 "olcDefaultSearchBase $ olcDisallows $ olcGentleHUP $ "
@@ -578,7 +604,7 @@ static ConfigOCs cf_ocs[] = {
                "NAME 'olcDatabaseConfig' "
                "DESC 'OpenLDAP Database-specific options' "
                "SUP olcConfig STRUCTURAL "
-               "MAY ( olcDatabase $ olcLastMod $ olcLimits $ "
+               "MAY ( olcDatabase $ olcAccess $ olcLastMod $ olcLimits $ "
                 "olcMaxDerefDepth $ olcPlugin $ olcReadOnly $ olcReplica $ "
                 "olcReplogFile $ olcRequires $ olcRestrict $ olcRootDN $ olcRootPW $ "
                 "olcSchemaDN $ olcSecurity $ olcSizeLimit $ olcSuffix $ olcSyncrepl $ "
@@ -594,11 +620,6 @@ static ConfigOCs cf_ocs[] = {
                "DESC 'OpenLDAP Overlay-specific options' "
                "SUP olcConfig STRUCTURAL "
                "MAY ( olcOverlay ) )", &cfOc_overlay },
-       { "( OLcfgOc:8 "
-               "NAME 'olcACL' "
-               "DESC 'OpenLDAP Access Control List' "
-               "SUP olcConfig STRUCTURAL "
-               "MUST ( olcAccess ) )", &cfOc_access },
        { NULL, NULL }
 };
 
@@ -607,7 +628,7 @@ config_generic(ConfigArgs *c) {
        char *p;
        int i;
 
-       if ( c->emit ) {
+       if ( c->op == SLAP_CONFIG_EMIT ) {
                int rc = 0;
                switch(c->type) {
                case CFG_CONCUR:
@@ -1038,7 +1059,7 @@ config_generic(ConfigArgs *c) {
 
 static int
 config_fname(ConfigArgs *c) {
-       if(c->emit && c->line) {
+       if(c->op == SLAP_CONFIG_EMIT && c->line) {
                ConfigFile *cf = (ConfigFile *)c->line;
                value_add_one( &c->rvalue_vals, &cf->c_file );
                return 0;
@@ -1046,11 +1067,20 @@ config_fname(ConfigArgs *c) {
        return(1);
 }
 
+static int
+config_cfdir(ConfigArgs *c) {
+       if(c->op == SLAP_CONFIG_EMIT) {
+               value_add_one( &c->rvalue_vals, &cfdir );
+               return 0;
+       }
+       return(1);
+}
+
 static int
 config_search_base(ConfigArgs *c) {
        struct berval dn;
 
-       if(c->emit) {
+       if(c->op == SLAP_CONFIG_EMIT) {
                int rc = 1;
                if (!BER_BVISEMPTY(&default_search_base)) {
                        value_add_one(&c->rvalue_vals, &default_search_base);
@@ -1084,7 +1114,7 @@ config_search_base(ConfigArgs *c) {
 static int
 config_passwd_hash(ConfigArgs *c) {
        int i;
-       if (c->emit) {
+       if (c->op == SLAP_CONFIG_EMIT) {
                struct berval bv;
                for (i=0; default_passwd_hash && default_passwd_hash[i]; i++) {
                        ber_str2bv(default_passwd_hash[i], 0, 0, &bv);
@@ -1117,12 +1147,14 @@ config_passwd_hash(ConfigArgs *c) {
 
 static int
 config_schema_dn(ConfigArgs *c) {
-       struct berval dn;
-       int rc;
-       if ( c->emit ) {
-               value_add_one(&c->rvalue_vals, &c->be->be_schemadn);
-               value_add_one(&c->rvalue_nvals, &c->be->be_schemandn);
-               return 0;
+       if ( c->op == SLAP_CONFIG_EMIT ) {
+               int rc = 1;
+               if ( !BER_BVISEMPTY( &c->be->be_schemadn )) {
+                       value_add_one(&c->rvalue_vals, &c->be->be_schemadn);
+                       value_add_one(&c->rvalue_nvals, &c->be->be_schemandn);
+                       rc = 0;
+               }
+               return rc;
        }
        c->be->be_schemadn = c->value_dn;
        c->be->be_schemandn = c->value_ndn;
@@ -1134,7 +1166,7 @@ config_sizelimit(ConfigArgs *c) {
        int i, rc = 0;
        char *next;
        struct slap_limits_set *lim = &c->be->be_def_limit;
-       if (c->emit) {
+       if (c->op == SLAP_CONFIG_EMIT) {
                char buf[8192];
                struct berval bv;
                bv.bv_val = buf;
@@ -1182,7 +1214,7 @@ config_timelimit(ConfigArgs *c) {
        int i, rc = 0;
        char *next;
        struct slap_limits_set *lim = &c->be->be_def_limit;
-       if (c->emit) {
+       if (c->op == SLAP_CONFIG_EMIT) {
                char buf[8192];
                struct berval bv;
                bv.bv_val = buf;
@@ -1227,7 +1259,7 @@ config_timelimit(ConfigArgs *c) {
 
 static int
 config_overlay(ConfigArgs *c) {
-       if (c->emit) {
+       if (c->op == SLAP_CONFIG_EMIT) {
                return 1;
        }
        if(c->argv[1][0] == '-' && overlay_config(c->be, &c->argv[1][1])) {
@@ -1245,7 +1277,7 @@ config_suffix(ConfigArgs *c) {
        Backend *tbe;
        struct berval pdn, ndn;
        int rc;
-       if (c->emit) {
+       if (c->op == SLAP_CONFIG_EMIT) {
                if ( !BER_BVISNULL( &c->be->be_suffix[0] )) {
                        value_add( &c->rvalue_vals, c->be->be_suffix );
                        value_add( &c->rvalue_nvals, c->be->be_nsuffix );
@@ -1289,7 +1321,7 @@ config_suffix(ConfigArgs *c) {
 
 static int
 config_rootdn(ConfigArgs *c) {
-       if (c->emit) {
+       if (c->op == SLAP_CONFIG_EMIT) {
                if ( !BER_BVISNULL( &c->be->be_rootdn )) {
                        value_add_one(&c->rvalue_vals, &c->be->be_rootdn);
                        value_add_one(&c->rvalue_nvals, &c->be->be_rootndn);
@@ -1306,7 +1338,7 @@ config_rootdn(ConfigArgs *c) {
 static int
 config_rootpw(ConfigArgs *c) {
        Backend *tbe;
-       if (c->emit) {
+       if (c->op == SLAP_CONFIG_EMIT) {
                if (!BER_BVISEMPTY(&c->be->be_rootpw)) {
                        c->value_string=ch_strdup("*");
                        return 0;
@@ -1348,7 +1380,7 @@ config_restrict(ConfigArgs *c) {
                { BER_BVNULL,   0 }
        };
 
-       if (c->emit) {
+       if (c->op == SLAP_CONFIG_EMIT) {
                return mask_to_verbs( restrictable_ops, c->be->be_restrictops,
                        &c->rvalue_vals );
        }
@@ -1376,7 +1408,7 @@ config_allows(ConfigArgs *c) {
                { BER_BVC("update_anon"),       SLAP_ALLOW_UPDATE_ANON },
                { BER_BVNULL,   0 }
        };
-       if (c->emit) {
+       if (c->op == SLAP_CONFIG_EMIT) {
                return mask_to_verbs( allowable_ops, global_allows, &c->rvalue_vals );
        }
        i = verbs_to_mask(c->argc, c->argv, allowable_ops, &allows);
@@ -1402,7 +1434,7 @@ config_disallows(ConfigArgs *c) {
                { BER_BVC("tls_authc"),         SLAP_DISALLOW_TLS_AUTHC },
                { BER_BVNULL, 0 }
        };
-       if (c->emit) {
+       if (c->op == SLAP_CONFIG_EMIT) {
                return mask_to_verbs( disallowable_ops, global_disallows, &c->rvalue_vals );
        }
        i = verbs_to_mask(c->argc, c->argv, disallowable_ops, &disallows);
@@ -1428,7 +1460,7 @@ config_requires(ConfigArgs *c) {
                { BER_BVC("strong"),            SLAP_REQUIRE_STRONG },
                { BER_BVNULL, 0 }
        };
-       if (c->emit) {
+       if (c->op == SLAP_CONFIG_EMIT) {
                return mask_to_verbs( requires_ops, c->be->be_requires, &c->rvalue_vals );
        }
        i = verbs_to_mask(c->argc, c->argv, requires_ops, &requires);
@@ -1465,7 +1497,7 @@ config_loglevel(ConfigArgs *c) {
                { BER_BVNULL,   0 }
        };
 
-       if (c->emit) {
+       if (c->op == SLAP_CONFIG_EMIT) {
                return mask_to_verbs( loglevel_ops, ldap_syslog, &c->rvalue_vals );
        }
 
@@ -1501,7 +1533,7 @@ config_loglevel(ConfigArgs *c) {
 
 static int
 config_syncrepl(ConfigArgs *c) {
-       if (c->emit) {
+       if (c->op == SLAP_CONFIG_EMIT) {
                if ( c->be->be_syncinfo ) {
                        struct berval bv;
                        syncrepl_unparse( c->be->be_syncinfo, &bv ); 
@@ -1525,7 +1557,7 @@ config_syncrepl(ConfigArgs *c) {
 static int
 config_referral(ConfigArgs *c) {
        struct berval vals[2];
-       if (c->emit) {
+       if (c->op == SLAP_CONFIG_EMIT) {
                if ( default_referral ) {
                        value_add( &c->rvalue_vals, default_referral );
                        return 0;
@@ -1567,7 +1599,7 @@ config_security(ConfigArgs *c) {
        slap_ssf_set_t *set = &c->be->be_ssf_set;
        char *next;
        int i, j;
-       if (c->emit) {
+       if (c->op == SLAP_CONFIG_EMIT) {
                char numbuf[32];
                struct berval bv;
                slap_ssf_t *tgt;
@@ -1686,7 +1718,7 @@ config_replica(ConfigArgs *c) {
        char *replicahost, *replicauri;
        LDAPURLDesc *ludp;
 
-       if (c->emit) {
+       if (c->op == SLAP_CONFIG_EMIT) {
                if (c->be->be_replica) {
                        struct berval bv;
                        for (i=0;c->be->be_replica[i]; i++) {
@@ -1791,7 +1823,7 @@ static int
 config_updatedn(ConfigArgs *c) {
        struct berval dn;
        int rc;
-       if (c->emit) {
+       if (c->op == SLAP_CONFIG_EMIT) {
                if (!BER_BVISEMPTY(&c->be->be_update_ndn)) {
                        value_add_one(&c->rvalue_vals, &c->be->be_update_ndn);
                        value_add_one(&c->rvalue_nvals, &c->be->be_update_ndn);
@@ -1824,7 +1856,7 @@ config_updatedn(ConfigArgs *c) {
 static int
 config_updateref(ConfigArgs *c) {
        struct berval vals[2];
-       if (c->emit) {
+       if (c->op == SLAP_CONFIG_EMIT) {
                if ( c->be->be_update_refs ) {
                        value_add( &c->rvalue_vals, c->be->be_update_refs );
                        return 0;
@@ -1858,7 +1890,7 @@ config_include(ConfigArgs *c) {
        ConfigFile *cf;
        ConfigFile *cfsave = cfn;
        ConfigFile *cf2 = NULL;
-       if (c->emit) {
+       if (c->op == SLAP_CONFIG_EMIT) {
                return 1;
        }
        cf = ch_calloc( 1, sizeof(ConfigFile));
@@ -1900,7 +1932,7 @@ config_tls_option(ConfigArgs *c) {
                                        "unknown tls_option <%x>\n",
                                        c->log, c->type, 0);
        }
-       if (c->emit) {
+       if (c->op == SLAP_CONFIG_EMIT) {
                return ldap_pvt_tls_get_option( NULL, flag, &c->value_string );
        }
        ch_free(c->value_string);
@@ -1935,7 +1967,7 @@ config_tls_config(ConfigArgs *c) {
                                        "unknown tls_option <%x>\n",
                                        c->log, c->type, 0);
        }
-       if (c->emit) {
+       if (c->op == SLAP_CONFIG_EMIT) {
                ldap_pvt_tls_get_option( NULL, flag, &c->value_int );
                for (i=0; !BER_BVISNULL(&keys[i].word); i++) {
                        if (keys[i].mask == c->value_int) {
@@ -2471,38 +2503,17 @@ syncrepl_unparse( syncinfo_t *si, struct berval *bv )
        ber_dupbv( bv, &bc );
 }
 
-
-int
-read_config(const char *fname, int depth) {
-
-       if ( !backend_db_init( "config" ))
-               return 1;
-
-       ber_str2bv( fname, 0, 1, &cf_prv.c_file );
-       return read_config_file(fname, depth, NULL);
-}
-
-static int
-config_back_bind( Operation *op, SlapReply *rs )
-{
-       if ( op->orb_method == LDAP_AUTH_SIMPLE && be_isroot_pw( op )) {
-               ber_dupbv( &op->orb_edn, be_root_dn( op->o_bd ));
-               /* frontend sends result */
-               return LDAP_SUCCESS;
-       }
-
-       rs->sr_err = LDAP_INVALID_CREDENTIALS;
-       send_ldap_result( op, rs );
-
-       return rs->sr_err;
-}
-
 static CfEntryInfo *
 config_find_base( CfEntryInfo *root, struct berval *dn, CfEntryInfo **last )
 {
        struct berval cdn;
        char *c;
 
+       if ( !root ) {
+               *last = NULL;
+               return NULL;
+       }
+
        if ( dn_match( &root->ce_entry->e_nname, dn ))
                return root;
 
@@ -2531,6 +2542,183 @@ config_find_base( CfEntryInfo *root, struct berval *dn, CfEntryInfo **last )
        return root;
 }
 
+static int
+config_ldif_resp( Operation *op, SlapReply *rs )
+{
+       if ( rs->sr_type == REP_SEARCH ) {
+               CfBackInfo *cfb = op->o_callback->sc_private;
+               CfEntryInfo *ce, *last;
+
+               cfb->cb_got_ldif = 1;
+               config_find_base( cfb->cb_root, &rs->sr_entry->e_nname, &last );
+               ce = ch_calloc( 1, sizeof(CfEntryInfo) );
+               ce->ce_entry = entry_dup( rs->sr_entry );
+               ce->ce_entry->e_private = ce;
+               if ( !last ) {
+                       cfb->cb_root = ce;
+               } else if ( last->ce_kids ) {
+                       CfEntryInfo *c2;
+
+                       for (c2=last->ce_kids; c2 && c2->ce_sibs; c2 = c2->ce_sibs);
+                       c2->ce_sibs = ce;
+               } else {
+                       last->ce_kids = ce;
+               }
+       }
+       return 0;
+}
+
+/* Configure and read the underlying back-ldif store */
+static int
+config_setup_ldif( BackendDB *be, const char *dir ) {
+       CfBackInfo *cfb = be->be_private;
+       ConfigArgs c = {0};
+       ConfigTable *ct;
+       char *argv[3];
+       int rc;
+       slap_callback cb = { NULL, config_ldif_resp, NULL, NULL };
+       Connection conn = {0};
+       char opbuf[OPERATION_BUFFER_SIZE];
+       Operation *op;
+       SlapReply rs = {REP_RESULT};
+       Filter filter = { LDAP_FILTER_PRESENT };
+       struct berval filterstr = BER_BVC("(objectclass=*)");
+
+       cfb->cb_db.bd_info = backend_info( "ldif" );
+       if ( !cfb->cb_db.bd_info )
+               return 1;
+
+       if ( cfb->cb_db.bd_info->bi_db_init( &cfb->cb_db )) return 1;
+
+       /* Mark that back-ldif type is in use */
+       cfb->cb_db.bd_info->bi_nDB++;
+
+       cfb->cb_db.be_suffix = be->be_suffix;
+       cfb->cb_db.be_nsuffix = be->be_nsuffix;
+       cfb->cb_db.be_rootdn = be->be_rootdn;
+       cfb->cb_db.be_rootndn = be->be_rootndn;
+
+       ber_str2bv( dir, 0, 1, &cfdir );
+
+       c.be = &cfb->cb_db;
+       c.fname = "slapd";
+       c.argc = 2;
+       argv[0] = "directory";
+       argv[1] = (char *)dir;
+       argv[2] = NULL;
+       c.argv = argv;
+
+       ct = config_find_keyword( c.be->be_cf_table, &c );
+       if ( !ct )
+               return 1;
+
+       if ( config_add_vals( ct, &c ))
+               return 1;
+
+       if ( backend_startup_one( &cfb->cb_db ))
+               return 1;
+
+       op = (Operation *)opbuf;
+       connection_fake_init( &conn, op, cfb );
+
+       filter.f_desc = slap_schema.si_ad_objectClass;
+       
+       op->o_tag = LDAP_REQ_SEARCH;
+
+       op->ors_filter = &filter;
+       op->ors_filterstr = filterstr;
+       op->ors_scope = LDAP_SCOPE_SUBTREE;
+
+       op->o_dn = be->be_rootdn;
+       op->o_ndn = be->be_rootndn;
+
+       op->o_req_dn = be->be_suffix[0];
+       op->o_req_ndn = be->be_nsuffix[0];
+
+       op->ors_tlimit = SLAP_NO_LIMIT;
+       op->ors_slimit = SLAP_NO_LIMIT;
+
+       op->ors_attrs = slap_anlist_all_attributes;
+       op->ors_attrsonly = 0;
+
+       op->o_callback = &cb;
+       cb.sc_private = cfb;
+
+       op->o_bd = &cfb->cb_db;
+       op->o_bd->be_search( op, &rs );
+       
+       return 0;
+}
+
+static int
+CfOcInfo_cmp( const void *c1, const void *c2 ) {
+       const CfOcInfo *co1 = c1;
+       const CfOcInfo *co2 = c2;
+
+       return ber_bvcmp( co1->co_name, co2->co_name );
+}
+
+int
+config_register_schema(ConfigTable *ct, ConfigOCs *ocs) {
+       int i;
+       CfOcInfo *co;
+
+       i = init_config_attrs( ct );
+       if ( i ) return i;
+
+       /* set up the objectclasses */
+       i = init_config_ocs( ocs );
+       if ( i ) return i;
+
+       for (i=0; ocs[i].def; i++) {
+               if ( ocs[i].oc ) {
+                       co = ch_malloc( sizeof(CfOcInfo) );
+                       co->co_name = &(*ocs[i].oc)->soc_cname;
+                       co->co_table = ct;
+                       avl_insert( &CfOcTree, co, CfOcInfo_cmp, avl_dup_error );
+               }
+       }
+       return 0;
+}
+
+int
+read_config(const char *fname, const char *dir) {
+       BackendDB *be;
+
+       /* Setup the config backend */
+       be = backend_db_init( "config" );
+       if ( !be )
+               return 1;
+
+       /* Setup the underlying back-ldif backend */
+       if ( config_setup_ldif( be, dir ))
+               return 1;
+
+#if 0  /* not yet
+       /* If we read the config from back-ldif, nothing to do here */
+       if ( cfb->cb_got_ldif )
+               return 0;
+#endif
+       ber_str2bv( fname, 0, 1, &cf_prv.c_file );
+
+       return read_config_file(fname, 0, NULL);
+}
+
+static int
+config_back_bind( Operation *op, SlapReply *rs )
+{
+       if ( op->orb_method == LDAP_AUTH_SIMPLE && be_isroot_pw( op )) {
+               ber_dupbv( &op->orb_edn, be_root_dn( op->o_bd ));
+               /* frontend sends result */
+               return LDAP_SUCCESS;
+       }
+
+       rs->sr_err = LDAP_INVALID_CREDENTIALS;
+       send_ldap_result( op, rs );
+
+       return rs->sr_err;
+}
+
 static int
 config_send( Operation *op, SlapReply *rs, CfEntryInfo *ce, int depth )
 {
@@ -2578,6 +2766,13 @@ config_back_modify( Operation *op, SlapReply *rs )
                goto out;
        }
        ldap_pvt_thread_pool_pause( &connection_pool );
+
+       /* Strategy:
+        * 1) perform the Modify on the cached Entry.
+        * 2) verify that the Entry still satisfies the schema.
+        * 3) perform the individual config operations.
+        * 4) store Modified entry in underlying LDIF backend.
+        */
        ldap_pvt_thread_pool_resume( &connection_pool );
 out:
        send_ldap_result( op, rs );
@@ -2656,6 +2851,7 @@ config_build_entry( ConfigArgs *c, Entry *e, ObjectClass *oc,
 
        vals[0] = oc->soc_cname;
        attr_merge(e, slap_schema.si_ad_objectClass, vals, NULL );
+       attr_merge(e, slap_schema.si_ad_structuralObjectClass, vals, NULL );
        ptr = strchr(rdn->bv_val, '=');
        ad_name.bv_val = rdn->bv_val;
        ad_name.bv_len = ptr - rdn->bv_val;
@@ -2672,14 +2868,15 @@ config_build_entry( ConfigArgs *c, Entry *e, ObjectClass *oc,
                if ((*at)->sat_ad == ad || (*at)->sat_ad == slap_schema.si_ad_cn )
                        continue;
                for (i=0;ct[i].name;i++) {
-                       if (ct[i].ad == (*at)->sat_ad)
+                       if (ct[i].ad == (*at)->sat_ad) {
+                               rc = config_get_vals(&ct[i], c);
+                               if (rc == LDAP_SUCCESS) {
+                                       attr_merge(e, ct[i].ad, c->rvalue_vals, c->rvalue_nvals);
+                                       ber_bvarray_free( c->rvalue_nvals );
+                                       ber_bvarray_free( c->rvalue_vals );
+                               }
                                break;
-               }
-               rc = config_get_vals(&ct[i], c);
-               if (rc == LDAP_SUCCESS) {
-                       attr_merge(e, ct[i].ad, c->rvalue_vals, c->rvalue_nvals);
-                       ber_bvarray_free( c->rvalue_nvals );
-                       ber_bvarray_free( c->rvalue_vals );
+                       }
                }
        }
 
@@ -2688,14 +2885,15 @@ config_build_entry( ConfigArgs *c, Entry *e, ObjectClass *oc,
                if ((*at)->sat_ad == ad || (*at)->sat_ad == slap_schema.si_ad_cn )
                        continue;
                for (i=0;ct[i].name;i++) {
-                       if (ct[i].ad == (*at)->sat_ad)
+                       if (ct[i].ad == (*at)->sat_ad) {
+                               rc = config_get_vals(&ct[i], c);
+                               if (rc == LDAP_SUCCESS) {
+                                       attr_merge(e, ct[i].ad, c->rvalue_vals, c->rvalue_nvals);
+                                       ber_bvarray_free( c->rvalue_nvals );
+                                       ber_bvarray_free( c->rvalue_vals );
+                               }
                                break;
-               }
-               rc = config_get_vals(&ct[i], c);
-               if (rc == LDAP_SUCCESS) {
-                       attr_merge(e, ct[i].ad, c->rvalue_vals, c->rvalue_nvals);
-                       ber_bvarray_free( c->rvalue_nvals );
-                       ber_bvarray_free( c->rvalue_vals );
+                       }
                }
        }
 
@@ -2717,7 +2915,8 @@ config_build_entry( ConfigArgs *c, Entry *e, ObjectClass *oc,
 }
 
 static CfEntryInfo *
-config_build_includes( ConfigArgs *c, Entry *parent )
+config_build_includes( ConfigArgs *c, Entry *parent,
+       Operation *op, SlapReply *rs )
 {
        Entry *e;
        int i;
@@ -2733,7 +2932,11 @@ config_build_includes( ConfigArgs *c, Entry *parent )
                c->line = (char *)cf;
                config_build_entry( c, e, cfOc_include, &c->value_dn,
                        c->bi->bi_cf_table, NO_TABLE );
+               op->ora_e = e;
+               op->o_bd->be_add( op, rs );
                ce = e->e_private;
+               ce->ce_type = Cf_Include;
+               ce->ce_bi = c->bi;
                if ( !ceparent->ce_kids ) {
                        ceparent->ce_kids = ce;
                } else {
@@ -2742,7 +2945,7 @@ config_build_includes( ConfigArgs *c, Entry *parent )
                ceprev = ce;
                if ( cf->c_kids ) {
                        c->line = (char *)cf->c_kids;
-                       config_build_includes( c, e );
+                       config_build_includes( c, e, op, rs );
                }
        }
        return ce;
@@ -2760,6 +2963,25 @@ config_back_db_open( BackendDB *be )
        BackendDB *bptr;
        ConfigArgs c;
        ConfigTable *ct;
+       Connection conn = {0};
+       char opbuf[OPERATION_BUFFER_SIZE];
+       Operation *op;
+       slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
+       SlapReply rs = {REP_RESULT};
+
+       /* If we read the config from back-ldif, nothing to do here */
+       if ( cfb->cb_got_ldif )
+               return 0;
+
+       op = (Operation *)opbuf;
+       connection_fake_init( &conn, op, cfb );
+
+       op->o_dn = be->be_rootdn;
+       op->o_ndn = be->be_rootndn;
+
+       op->o_tag = LDAP_REQ_ADD;
+       op->o_callback = &cb;
+       op->o_bd = &cfb->cb_db;
 
        /* create root of tree */
        rdn = config_rdn;
@@ -2771,6 +2993,10 @@ config_back_db_open( BackendDB *be )
        c.line = (char *)cfb->cb_config;
        ct = c.bi->bi_cf_table;
        config_build_entry( &c, e, cfOc_global, &rdn, ct, NO_TABLE );
+       op->ora_e = e;
+       op->o_bd->be_add( op, &rs );
+       ce->ce_type = Cf_Global;
+       ce->ce_bi = c.bi;
 
        parent = e;
        ceparent = ce;
@@ -2778,7 +3004,7 @@ config_back_db_open( BackendDB *be )
        /* Create includeFile nodes... */
        if ( cfb->cb_config->c_kids ) {
                c.line = (char *)cfb->cb_config->c_kids;
-               ceprev = config_build_includes( &c, parent );
+               ceprev = config_build_includes( &c, parent, op, &rs );
        }
 
        /* Create backend nodes. Skip if they don't provide a cf_table.
@@ -2795,9 +3021,12 @@ config_back_db_open( BackendDB *be )
                rdn.bv_len = sprintf(rdn.bv_val, "%s=%s", cfAd_backend->ad_cname.bv_val, bi->bi_type);
                e = config_alloc_entry( &parent->e_nname, &rdn );
                ce = e->e_private;
+               ce->ce_type = Cf_Backend;
                ce->ce_bi = bi;
                c.bi = bi;
                config_build_entry( &c, e, cfOc_backend, &rdn, ct, BI_TABLE );
+               op->ora_e = e;
+               op->o_bd->be_add( op, &rs );
                if ( !ceparent->ce_kids ) {
                        ceparent->ce_kids = ce;
                } else {
@@ -2827,9 +3056,12 @@ config_back_db_open( BackendDB *be )
                ce = e->e_private;
                c.be = bptr;
                c.bi = bi;
+               ce->ce_type = Cf_Database;
                ce->ce_be = c.be;
                ce->ce_bi = c.bi;
                config_build_entry( &c, e, cfOc_database, &rdn, ct, BE_TABLE );
+               op->ora_e = e;
+               op->o_bd->be_add( op, &rs );
                if ( !ceparent->ce_kids ) {
                        ceparent->ce_kids = ce;
                } else {
@@ -2851,9 +3083,12 @@ config_back_db_open( BackendDB *be )
                                ce = oe->e_private;
                                c.be = bptr;
                                c.bi = &on->on_bi;
+                               ce->ce_type = Cf_Overlay;
                                ce->ce_be = c.be;
                                ce->ce_bi = c.bi;
                                config_build_entry( &c, oe, cfOc_overlay, &rdn, ct, BI_TABLE );
+                               op->ora_e = oe;
+                               op->o_bd->be_add( op, &rs );
                                if ( !opar->ce_kids ) {
                                        opar->ce_kids = ce;
                                } else {
@@ -2862,24 +3097,6 @@ config_back_db_open( BackendDB *be )
                                oprev = ce;
                        }
                }
-               /* Set up ACLs */
-               if ( bptr->be_acl ) {
-                       Entry *ae;
-                       CfEntryInfo *opar = ce;
-
-                       ae = config_alloc_entry( &e->e_nname, &access_rdn );
-                       ce = ae->e_private;
-                       c.be = bptr;
-                       c.bi = bi;
-                       ce->ce_be = c.be;
-                       ce->ce_bi = c.bi;
-                       config_build_entry( &c, ae, cfOc_access, &access_rdn, ct,
-                               NO_TABLE );
-                       if ( opar->ce_kids ) {
-                               ce->ce_sibs = opar->ce_kids;
-                       }
-                       opar->ce_kids = ce;
-               }
        }
 
        return 0;
@@ -2909,6 +3126,9 @@ config_back_db_init( Backend *be )
        ber_dupbv( &dn, &be->be_rootdn );
        ber_bvarray_add( &be->be_nsuffix, &dn );
 
+       /* Hide from namingContexts */
+       SLAP_BFLAGS(be) |= SLAP_BFLAG_CONFIG;
+
        return 0;
 }
 
@@ -2969,7 +3189,9 @@ config_back_initialize( BackendInfo *bi )
                parse_oidm( "slapd", i, 3, argv );
        }
 
-       i = init_config_attrs( ct );
+       bi->bi_cf_table = ct;
+
+       i = config_register_schema( ct, cf_ocs );
        if ( i ) return i;
 
        /* set up the notable AttributeDescriptions */
@@ -2977,8 +3199,6 @@ config_back_initialize( BackendInfo *bi )
        ads[3].sub = slap_schema.si_ad_ditContentRules;
        ads[5].sub = slap_schema.si_ad_objectClasses;
 
-       bi->bi_cf_table = ct;
-
        i = 0;
        for (;ct->name;ct++) {
                if (strcmp(ct->name, ads[i].name)) continue;
@@ -2991,9 +3211,6 @@ config_back_initialize( BackendInfo *bi )
                if (!ads[i].name) break;
        }
 
-       /* set up the objectclasses */
-       i = init_config_ocs( cf_ocs );
-
-       return i;
+       return 0;
 }
 
index 48cba471a426626efe619d790d40089645d2b29f..747df41959a22ff93d3b5d0f4a7a6733f7208460 100644 (file)
@@ -72,8 +72,6 @@ int   slap_conn_max_pending_auth = SLAP_CONN_MAX_PENDING_AUTH;
 char   *slapd_pid_file  = NULL;
 char   *slapd_args_file = NULL;
 
-char   *strtok_quote_ptr;
-
 int use_reverse_lookup = 0;
 
 #ifdef LDAP_SLAPI
@@ -84,7 +82,7 @@ static int fp_getline(FILE *fp, ConfigArgs *c);
 static void fp_getline_init(ConfigArgs *c);
 static int fp_parse_line(ConfigArgs *c);
 
-static char    *strtok_quote(char *line, char *sep);
+static char    *strtok_quote(char *line, char *sep, char **quote_ptr);
 
 int read_config_file(const char *fname, int depth, ConfigArgs *cf);
 
@@ -103,55 +101,61 @@ new_config_args( BackendDB *be, const char *fname, int lineno, int argc, char **
        return(c);
 }
 
-int parse_config_table(ConfigTable *Conf, ConfigArgs *c) {
+ConfigTable *config_find_keyword(ConfigTable *Conf, ConfigArgs *c) {
+       int i;
+
+       for(i = 0; Conf[i].name; i++)
+               if( (Conf[i].length && (!strncasecmp(c->argv[0], Conf[i].name, Conf[i].length))) ||
+                       (!strcasecmp(c->argv[0], Conf[i].name)) ) break;
+       if ( !Conf[i].name ) return NULL;
+       return Conf+i;
+}
+
+int config_add_vals(ConfigTable *Conf, ConfigArgs *c) {
        int i, rc, arg_user, arg_type, iarg;
        long larg;
        ber_len_t barg;
        void *ptr;
 
-       for(i = 0; Conf[i].name; i++)
-               if( (Conf[i].length && (!strncasecmp(c->argv[0], Conf[i].name, Conf[i].length))) ||
-                       (!strcasecmp(c->argv[0], Conf[i].name)) ) break;
-       if(!Conf[i].name) return(ARG_UNKNOWN);
-       arg_type = Conf[i].arg_type;
+       arg_type = Conf->arg_type;
        if(arg_type == ARG_IGNORED) {
                Debug(LDAP_DEBUG_CONFIG, "%s: keyword <%s> ignored\n",
-                       c->log, Conf[i].name, 0);
+                       c->log, Conf->name, 0);
                return(0);
        }
-       if(Conf[i].min_args && (c->argc < Conf[i].min_args)) {
+       if(Conf->min_args && (c->argc < Conf->min_args)) {
                Debug(LDAP_DEBUG_CONFIG, "%s: keyword <%s> missing <%s> argument\n",
-                       c->log, Conf[i].name, Conf[i].what);
+                       c->log, Conf->name, Conf->what);
                return(ARG_BAD_CONF);
        }
-       if(Conf[i].max_args && (c->argc > Conf[i].max_args)) {
+       if(Conf->max_args && (c->argc > Conf->max_args)) {
                Debug(LDAP_DEBUG_CONFIG, "%s: extra cruft after <%s> in <%s> line (ignored)\n",
-                       c->log, Conf[i].what, Conf[i].name);
+                       c->log, Conf->what, Conf->name);
        }
        if((arg_type & ARG_DB) && !c->be) {
                Debug(LDAP_DEBUG_CONFIG, "%s: keyword <%s> allowed only within database declaration\n",
-                       c->log, Conf[i].name, 0);
+                       c->log, Conf->name, 0);
                return(ARG_BAD_CONF);
        }
        if((arg_type & ARG_PRE_BI) && c->bi) {
                Debug(LDAP_DEBUG_CONFIG, "%s: keyword <%s> must appear before any backend %sdeclaration\n",
-                       c->log, Conf[i].name, ((arg_type & ARG_PRE_DB)
+                       c->log, Conf->name, ((arg_type & ARG_PRE_DB)
                        ? "or database " : "") );
                return(ARG_BAD_CONF);
        }
        if((arg_type & ARG_PRE_DB) && c->be && c->be != frontendDB) {
                Debug(LDAP_DEBUG_CONFIG, "%s: keyword <%s> must appear before any database declaration\n",
-                       c->log, Conf[i].name, 0);
+                       c->log, Conf->name, 0);
                return(ARG_BAD_CONF);
        }
        if((arg_type & ARG_PAREN) && *c->argv[1] != '(' /*')'*/) {
                Debug(LDAP_DEBUG_CONFIG, "%s: old <%s> format not supported\n",
-                       c->log, Conf[i].name, 0);
+                       c->log, Conf->name, 0);
                return(ARG_BAD_CONF);
        }
-       if((arg_type & ARGS_POINTER) && !Conf[i].arg_item) {
+       if((arg_type & ARGS_POINTER) && !Conf->arg_item && !(arg_type & ARG_OFFSET)) {
                Debug(LDAP_DEBUG_CONFIG, "%s: null arg_item for <%s>\n",
-                       c->log, Conf[i].name, 0);
+                       c->log, Conf->name, 0);
                return(ARG_BAD_CONF);
        }
        c->type = arg_user = (arg_type & ARGS_USERLAND);
@@ -175,7 +179,7 @@ int parse_config_table(ConfigTable *Conf, ConfigArgs *c) {
                                } else {
                                        Debug(LDAP_DEBUG_CONFIG, "%s: ignoring ", c->log, 0, 0);
                                        Debug(LDAP_DEBUG_CONFIG, "invalid %s value (%s) in <%s> line\n",
-                                               Conf[i].what, c->argv[1], Conf[i].name);
+                                               Conf->what, c->argv[1], Conf->name);
                                        return(0);
                                }
                                break;
@@ -184,7 +188,7 @@ int parse_config_table(ConfigTable *Conf, ConfigArgs *c) {
                if(iarg < j || larg < j || barg < j ) {
                        larg = larg ? larg : (barg ? barg : iarg);
                        Debug(LDAP_DEBUG_CONFIG, "%s: " , c->log, 0, 0);
-                       Debug(LDAP_DEBUG_CONFIG, "invalid %s value (%ld) in <%s> line\n", Conf[i].what, larg, Conf[i].name);
+                       Debug(LDAP_DEBUG_CONFIG, "invalid %s value (%ld) in <%s> line\n", Conf->what, larg, Conf->name);
                        return(ARG_BAD_CONF);
                }
                switch(arg_type & ARGS_NUMERIC) {
@@ -194,7 +198,9 @@ int parse_config_table(ConfigTable *Conf, ConfigArgs *c) {
                        case ARG_BER_LEN_T:     c->value_ber_t = barg;          break;
                }
        } else if(arg_type & ARG_STRING) {
-                c->value_string = ch_strdup(c->argv[1]);
+               c->value_string = ch_strdup(c->argv[1]);
+       } else if(arg_type & ARG_BERVAL) {
+               ber_str2bv( c->argv[1], 0, 1, &c->value_bv );
        } else if(arg_type & ARG_DN) {
                struct berval bv;
                ber_str2bv( c->argv[1], 0, 0, &bv );
@@ -202,17 +208,17 @@ int parse_config_table(ConfigTable *Conf, ConfigArgs *c) {
                if ( rc != LDAP_SUCCESS ) {
                        Debug(LDAP_DEBUG_CONFIG, "%s: " , c->log, 0, 0);
                        Debug(LDAP_DEBUG_CONFIG, "%s DN is invalid %d (%s)\n",
-                               Conf[i].name, rc, ldap_err2string( rc ));
+                               Conf->name, rc, ldap_err2string( rc ));
                        return(ARG_BAD_CONF);
                }
        }
        if(arg_type & ARG_MAGIC) {
                if(!c->be) c->be = frontendDB;
-               rc = (*((ConfigDriver*)Conf[i].arg_item))(c);
+               rc = (*((ConfigDriver*)Conf->arg_item))(c);
                if(c->be == frontendDB) c->be = NULL;
                if(rc) {
-                       Debug(LDAP_DEBUG_CONFIG, "%s: handler for <%s> exited with %d!",
-                               c->log, Conf[i].name, rc);
+                       Debug(LDAP_DEBUG_CONFIG, "%s: handler for <%s> exited with %d!\n",
+                               c->log, Conf->name, rc);
                        return(ARG_BAD_CONF);
                }
                return(0);
@@ -223,15 +229,16 @@ int parse_config_table(ConfigTable *Conf, ConfigArgs *c) {
                else if (c->bi)
                        ptr = c->bi->bi_private;
                else {
-                       Debug(LDAP_DEBUG_CONFIG, "%s: offset for <%s> missing base pointer!",
-                               c->log, Conf[i].name, 0);
+                       Debug(LDAP_DEBUG_CONFIG, "%s: offset for <%s> missing base pointer!\n",
+                               c->log, Conf->name, 0);
                        return(ARG_BAD_CONF);
                }
-               ptr = (void *)((char *)ptr + (int)Conf[i].arg_item);
+               ptr = (void *)((char *)ptr + (int)Conf->arg_item);
        } else if (arg_type & ARGS_POINTER) {
-               ptr = Conf[i].arg_item;
+               ptr = Conf->arg_item;
        }
-       if(arg_type & ARGS_POINTER) switch(arg_type & ARGS_POINTER) {
+       if(arg_type & ARGS_POINTER)
+               switch(arg_type & ARGS_POINTER) {
                        case ARG_ON_OFF:
                        case ARG_INT:           *(int*)ptr = iarg;                      break;
                        case ARG_LONG:          *(long*)ptr = larg;                     break;
@@ -241,7 +248,7 @@ int parse_config_table(ConfigTable *Conf, ConfigArgs *c) {
                                if(cc) {
                                        if (arg_type & ARG_UNIQUE) {
                                                Debug(LDAP_DEBUG_CONFIG, "%s: already set %s!\n",
-                                                       c->log, Conf[i].name, 0 );
+                                                       c->log, Conf->name, 0 );
                                                return(ARG_BAD_CONF);
                                        }
                                        ch_free(cc);    /* potential memory leak */
@@ -249,10 +256,19 @@ int parse_config_table(ConfigTable *Conf, ConfigArgs *c) {
                                *(char **)ptr = c->value_string;
                                break;
                                }
-       }
+                       case ARG_BERVAL:
+                               *(struct berval *)ptr = c->value_bv;
+                               break;
+               }
        return(arg_user);
 }
 
+int
+config_del_vals(ConfigTable *cf, ConfigArgs *c)
+{
+       int rc = 0;
+}
+
 int
 config_get_vals(ConfigTable *cf, ConfigArgs *c)
 {
@@ -267,7 +283,7 @@ config_get_vals(ConfigTable *cf, ConfigArgs *c)
        memset(&c->values, 0, sizeof(c->values));
        c->rvalue_vals = NULL;
        c->rvalue_nvals = NULL;
-       c->emit = 1;
+       c->op = SLAP_CONFIG_EMIT;
        c->type = cf->arg_type & ARGS_USERLAND;
 
        if ( cf->arg_type & ARG_MAGIC ) {
@@ -295,14 +311,16 @@ config_get_vals(ConfigTable *cf, ConfigArgs *c)
                        if ( *(char **)ptr )
                                c->value_string = ch_strdup(*(char **)ptr);
                        break;
+               case ARG_BERVAL:
+                       ber_dupbv( &c->value_bv, (struct berval *)ptr ); break;
                }
        }
        if ( cf->arg_type & ARGS_POINTER) {
                bv.bv_val = c->log;
                switch(cf->arg_type & ARGS_POINTER) {
                case ARG_INT: bv.bv_len = sprintf(bv.bv_val, "%d", c->value_int); break;
-               case ARG_LONG: bv.bv_len = sprintf(bv.bv_val, "%l", c->value_long); break;
-               case ARG_BER_LEN_T: bv.bv_len =sprintf(bv.bv_val, "%l",c->value_ber_t); break;
+               case ARG_LONG: bv.bv_len = sprintf(bv.bv_val, "%ld", c->value_long); break;
+               case ARG_BER_LEN_T: bv.bv_len = sprintf(bv.bv_val, "%ld", c->value_ber_t); break;
                case ARG_ON_OFF: bv.bv_len = sprintf(bv.bv_val, "%s",
                        c->value_int ? "TRUE" : "FALSE"); break;
                case ARG_STRING:
@@ -312,6 +330,13 @@ config_get_vals(ConfigTable *cf, ConfigArgs *c)
                                return 1;
                        }
                        break;
+               case ARG_BERVAL:
+                       if ( !BER_BVISEMPTY( &c->value_bv )) {
+                               bv = c->value_bv;
+                       } else {
+                               return 1;
+                       }
+                       break;
                }
                if (( cf->arg_type & ARGS_POINTER ) == ARG_STRING )
                        ber_bvarray_add(&c->rvalue_vals, &bv);
@@ -388,6 +413,7 @@ int
 read_config_file(const char *fname, int depth, ConfigArgs *cf)
 {
        FILE *fp;
+       ConfigTable *ct;
        ConfigArgs *c;
        int rc;
 
@@ -430,6 +456,7 @@ read_config_file(const char *fname, int depth, ConfigArgs *cf)
                snprintf( c->log, sizeof( c->log ), "%s: line %lu",
                                c->fname, c->lineno );
 
+               c->argc = 0;
                if ( fp_parse_line( c ) ) {
                        goto badline;
                }
@@ -439,58 +466,69 @@ read_config_file(const char *fname, int depth, ConfigArgs *cf)
                        continue;
                }
 
-               rc = parse_config_table( config_back_cf_table, c );
-               if ( !rc ) {
-                       continue;
-               }
-               if ( rc & ARGS_USERLAND ) {
-                       switch(rc) {    /* XXX a usertype would be opaque here */
-                       default:
-                               Debug(LDAP_DEBUG_CONFIG, "%s: unknown user type <%d>\n",
-                                       c->log, *c->argv, 0);
+               c->op = LDAP_MOD_ADD;
+
+               ct = config_find_keyword( config_back_cf_table, c );
+               if ( ct ) {
+                       rc = config_add_vals( ct, c );
+                       if ( !rc ) continue;
+
+                       if ( rc & ARGS_USERLAND ) {
+                               /* XXX a usertype would be opaque here */
+                               Debug(LDAP_DEBUG_CONFIG, "%s: unknown user type <%s>\n",
+                                       c->log, c->argv[0], 0);
                                goto badline;
-                       }
 
-               } else if ( rc == ARG_BAD_CONF || rc != ARG_UNKNOWN ) {
-                       goto badline;
+                       } else if ( rc == ARG_BAD_CONF ) {
+                               goto badline;
+                       }
                        
-               } else if ( c->bi && c->bi->bi_config ) {               /* XXX to check: could both be/bi_config? oops */
-                       rc = (*c->bi->bi_config)(c->bi, c->fname, c->lineno, c->argc, c->argv);
+               } else if ( c->bi ) {
+                       rc = SLAP_CONF_UNKNOWN;
+                       if ( c->bi->bi_cf_table ) {
+                               ct = config_find_keyword( c->bi->bi_cf_table, c );
+                               if ( ct ) {
+                                       rc = config_add_vals( ct, c );
+                               }
+                       }
+                       if ( c->bi->bi_config && rc == SLAP_CONF_UNKNOWN ) {
+                               rc = (*c->bi->bi_config)(c->bi, c->fname, c->lineno,
+                                       c->argc, c->argv);
+                       }
                        if ( rc ) {
                                switch(rc) {
                                case SLAP_CONF_UNKNOWN:
                                        Debug(LDAP_DEBUG_CONFIG, "%s: "
                                                "unknown directive <%s> inside backend info definition (ignored)\n",
-                                               c->log, *c->argv, 0);
+                                               c->log, *c->argv, 0);
                                        continue;
                                default:
                                        goto badline;
                                }
                        }
-                       
+
                } else if ( c->be ) {
+                       rc = SLAP_CONF_UNKNOWN;
                        if ( c->be->be_cf_table ) {
-                               rc = parse_config_table( c->be->be_cf_table, c );
-
-                               if ( !rc ) continue;
-
-                               if ( rc != ARG_UNKNOWN ) goto badline;
+                               ct = config_find_keyword( c->be->be_cf_table, c );
+                               if ( ct ) {
+                                       rc = config_add_vals( ct, c );
+                               }
                        }
-
-                       if ( c->be->be_config ) {
+                       if ( c->be->be_config && rc == SLAP_CONF_UNKNOWN ) {
                                rc = (*c->be->be_config)(c->be, c->fname, c->lineno,
                                        c->argc, c->argv);
-                               if ( rc ) {
-                                       switch(rc) {
-                                       case SLAP_CONF_UNKNOWN:
-                                               Debug( LDAP_DEBUG_CONFIG, "%s: "
-                                                       "unknown directive <%s> inside backend database "
-                                                       "definition (ignored)\n",
-                                                       c->log, *c->argv, 0);
-                                               continue;
-                                       default:
-                                               goto badline;
-                                       }
+                       }
+                       if ( rc ) {
+                               switch(rc) {
+                               case SLAP_CONF_UNKNOWN:
+                                       Debug( LDAP_DEBUG_CONFIG, "%s: "
+                                               "unknown directive <%s> inside backend database "
+                                               "definition (ignored)\n",
+                                               c->log, *c->argv, 0);
+                                       continue;
+                               default:
+                                       goto badline;
                                }
                        }
 
@@ -709,13 +747,13 @@ void bindconf_free( slap_bindconf *bc ) {
 
 
 static char *
-strtok_quote( char *line, char *sep )
+strtok_quote( char *line, char *sep, char **quote_ptr )
 {
        int             inquote;
        char            *tmp;
        static char     *next;
 
-       strtok_quote_ptr = NULL;
+       *quote_ptr = NULL;
        if ( line != NULL ) {
                next = line;
        }
@@ -750,7 +788,7 @@ strtok_quote( char *line, char *sep )
                default:
                        if ( ! inquote ) {
                                if ( strchr( sep, *next ) != NULL ) {
-                                       strtok_quote_ptr = next;
+                                       *quote_ptr = next;
                                        *next++ = '\0';
                                        return( tmp );
                                }
@@ -838,17 +876,18 @@ fp_parse_line(ConfigArgs *c)
        char *token;
        char *tline = ch_strdup(c->line);
        char *hide[] = { "rootpw", "replica", "bindpw", "pseudorootpw", "dbpasswd", '\0' };
+       char *quote_ptr;
        int i;
 
-       c->argc = 0;
-       token = strtok_quote(tline, " \t");
+       token = strtok_quote(tline, " \t", &quote_ptr);
 
        if(token) for(i = 0; hide[i]; i++) if(!strcasecmp(token, hide[i])) break;
-       if(strtok_quote_ptr) *strtok_quote_ptr = ' ';
-       Debug(LDAP_DEBUG_CONFIG, "line %lu (%s%s)\n", c->lineno, hide[i] ? hide[i] : c->line, hide[i] ? " ***" : "");
-       if(strtok_quote_ptr) *strtok_quote_ptr = '\0';
+       if(quote_ptr) *quote_ptr = ' ';
+       Debug(LDAP_DEBUG_CONFIG, "line %lu (%s%s)\n", c->lineno,
+               hide[i] ? hide[i] : c->line, hide[i] ? " ***" : "");
+       if(quote_ptr) *quote_ptr = '\0';
 
-       for(; token; token = strtok_quote(NULL, " \t")) {
+       for(; token; token = strtok_quote(NULL, " \t", &quote_ptr)) {
                if(c->argc == c->argv_size - 1) {
                        char **tmp;
                        tmp = ch_realloc(c->argv, (c->argv_size + ARGS_STEP) * sizeof(*c->argv));
@@ -929,3 +968,24 @@ slap_str2clist( char ***out, char *in, const char *brkstr )
        free( str );
        return( *out );
 }
+
+int config_generic_wrapper( Backend *be, const char *fname, int lineno,
+       int argc, char **argv )
+{
+       ConfigArgs c = { 0 };
+       ConfigTable *ct;
+       int rc;
+
+       c.be = be;
+       c.fname = fname;
+       c.lineno = lineno;
+       c.argc = argc;
+       c.argv = argv;
+       sprintf( c.log, "%s: line %lu", fname, lineno );
+
+       rc = SLAP_CONF_UNKNOWN;
+       ct = config_find_keyword( be->be_cf_table, &c );
+       if ( ct )
+               rc = config_add_vals( ct, &c );
+       return rc;
+}
index d43c442977786dc20e4bef82797de18dbe987a5f..ac4ceab069a504b8fea58acaa9ddc7d4defe41b8 100644 (file)
@@ -29,15 +29,15 @@ typedef struct ConfigTable {
 
 #define ARGS_USERLAND  0x00000fff
 #define ARGS_TYPES     0x000ff000
-#define ARGS_POINTER   0x0001f000
+#define ARGS_POINTER   0x0003f000
 #define ARGS_NUMERIC   0x0000f000
 #define ARG_INT                0x00001000
 #define ARG_LONG       0x00002000
 #define ARG_BER_LEN_T  0x00004000
 #define ARG_ON_OFF     0x00008000
 #define ARG_STRING     0x00010000
-#define ARG_DN         0x00020000
-#define ARG_EXISTS     0x00040000      /* XXX not yet */
+#define ARG_BERVAL     0x00020000
+#define ARG_DN         0x00040000
 #define ARG_IGNORED    0x00080000
 
 #define ARGS_SYNTAX    0xfff00000
@@ -77,6 +77,7 @@ typedef struct config_args_s {
                long v_long;
                ber_len_t v_ber_t;
                char *v_string;
+               struct berval v_bv;
                struct {
                        struct berval vdn_dn;
                        struct berval vdn_ndn;
@@ -85,7 +86,8 @@ typedef struct config_args_s {
        /* return values for emit mode */
        BerVarray rvalue_vals;
        BerVarray rvalue_nvals;
-       int emit;       /* emit instead of setting */
+#define        SLAP_CONFIG_EMIT        0x2000  /* emit instead of set */
+       int op;
        int type;       /* ConfigTable.arg_type & ARGS_USERLAND */
        BackendDB *be;
        BackendInfo *bi;
@@ -95,9 +97,13 @@ typedef struct config_args_s {
 #define value_long values.v_long
 #define value_ber_t values.v_ber_t
 #define value_string values.v_string
+#define value_bv values.v_bv
 #define value_dn values.v_dn.vdn_dn
 #define value_ndn values.v_dn.vdn_ndn
 
 typedef int (ConfigDriver)(ConfigArgs *c);
 
+int config_register_schema(ConfigTable *ct, ConfigOCs *co);
 int config_get_vals(ConfigTable *ct, ConfigArgs *c);
+int config_add_vals(ConfigTable *ct, ConfigArgs *c);
+ConfigTable * config_find_keyword(ConfigTable *ct, ConfigArgs *c);
index 3438fe1df67769851993e3710a041b01193358ef..2893a905f90c1f05de7eb85f2332dd0cd2605439 100644 (file)
@@ -980,8 +980,8 @@ static int slap_open_listener(
                case AF_LOCAL:
 #ifdef LOCAL_CREDS
                {
-                   int one = 1;
-                   setsockopt(l.sl_sd, 0, LOCAL_CREDS, &one, sizeof one);
+                       int one = 1;
+                       setsockopt(l.sl_sd, 0, LOCAL_CREDS, &one, sizeof one);
                }
 #endif
                addrlen = sizeof(struct sockaddr_un);
@@ -1672,7 +1672,7 @@ slapd_daemon_task(
                }
                ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
 
-               if ( cat != NULL ) {
+               if ( cat && cat->tv_sec ) {
                        time_t diff = difftime( cat->tv_sec, now );
                        if ( diff == 0 )
                                diff = tdelta;
index 6762093c4ace96e27fa5dfb3184dfe79fa229f0d..40a87c07f3bd67e051c54c9d1c1290d30e036849 100644 (file)
@@ -107,6 +107,7 @@ fe_op_delete( Operation *op, SlapReply *rs )
 {
        struct berval   pdn = BER_BVNULL;
        int             manageDSAit;
+       BackendDB *op_be;
        
        manageDSAit = get_manageDSAit( op );
 
@@ -138,6 +139,12 @@ fe_op_delete( Operation *op, SlapReply *rs )
                goto cleanup;
        }
 
+       /* If we've got a glued backend, check the real backend */
+       op_be = op->o_bd;
+       if ( SLAP_GLUE_INSTANCE( op->o_bd )) {
+               op->o_bd = select_backend( &op->o_req_ndn, manageDSAit, 0 );
+       }
+
        /* check restrictions */
        if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) {
                send_ldap_result( op, rs );
@@ -196,6 +203,8 @@ fe_op_delete( Operation *op, SlapReply *rs )
                        int             org_managedsait;
                        slap_callback   cb = { NULL, slap_replog_cb, NULL, NULL };
 
+                       op->o_bd = op_be;
+
                        if ( !repl_user ) {
                                struct berval csn = BER_BVNULL;
                                char csnbuf[LDAP_LUTIL_CSNSTR_BUFSIZE];
index c88876e046dcfbc2c281e7f92d2ed4144a9ffab9..944faff679c8cefdb3285fe57b004a65dbf3035b 100644 (file)
@@ -253,8 +253,10 @@ int main( int argc, char **argv )
 
 #ifdef HAVE_NT_SERVICE_MANAGER
        char            *configfile = ".\\slapd.conf";
+       char            *configdir = ".\\slapd.d";
 #else
        char            *configfile = SLAPD_DEFAULT_CONFIGFILE;
+       char            *configdir = SLAPD_DEFAULT_CONFIGDIR;
 #endif
        char        *serverName;
        int         serverMode = SLAP_SERVER_MODE;
@@ -288,6 +290,7 @@ int main( int argc, char **argv )
        {
                int *i;
                char *newConfigFile;
+               char *newConfigDir;
                char *newUrls;
                char *regService = NULL;
 
@@ -319,11 +322,17 @@ int main( int argc, char **argv )
                        configfile = newConfigFile;
                        Debug ( LDAP_DEBUG_ANY, "new config file from registry is: %s\n", configfile, 0, 0 );
                }
+
+               newConfigDir = (char*)lutil_getRegParam( regService, "ConfigDir" );
+               if ( newConfigDir != NULL ) {
+                       configdir = newConfigDir;
+                       Debug ( LDAP_DEBUG_ANY, "new config dir from registry is: %s\n", configdir, 0, 0 );
+               }
        }
 #endif
 
        while ( (i = getopt( argc, argv,
-                            "c:d:f:h:n:o:s:StT:V"
+                            "c:d:f:F:h:n:o:s:StT:V"
 #if LDAP_PF_INET6
                                "46"
 #endif
@@ -385,6 +394,10 @@ int main( int argc, char **argv )
                        configfile = ch_strdup( optarg );
                        break;
 
+               case 'F':       /* use config dir */
+                       configdir = ch_strdup( optarg );
+                       break;
+
                case 'o': {
                        char            *val = strchr( optarg, '=' );
                        struct berval   opt;
@@ -624,7 +637,7 @@ unhandled_option:;
        }
 #endif /* SLAP_DYNACL */
 
-       if ( read_config( configfile, 0 ) != 0 ) {
+       if ( read_config( configfile, configdir ) != 0 ) {
                rc = 1;
                SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 19 );
 
index ea961ef57f7d3823746d468195d278009aad5cec..5f7199f4f159e3eab7d41f37beace0754d158f48 100644 (file)
@@ -225,6 +225,7 @@ fe_op_modify( Operation *op, SlapReply *rs )
 #endif
        int             increment = op->orm_increment;
        int             rc = 0;
+       BackendDB *op_be;
        
        if( op->o_req_ndn.bv_len == 0 ) {
                Debug( LDAP_DEBUG_ANY, "do_modify: root dse!\n", 0, 0, 0 );
@@ -330,6 +331,12 @@ fe_op_modify( Operation *op, SlapReply *rs )
                goto cleanup;
        }
 
+       /* If we've got a glued backend, check the real backend */
+       op_be = op->o_bd;
+       if ( SLAP_GLUE_INSTANCE( op->o_bd )) {
+               op->o_bd = select_backend( &op->o_req_ndn, manageDSAit, 0 );
+       }
+
        /* check restrictions */
        if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) {
                send_ldap_result( op, rs );
@@ -424,6 +431,7 @@ fe_op_modify( Operation *op, SlapReply *rs )
                        size_t          textlen = sizeof( textbuf );
                        slap_callback   cb = { NULL, slap_replog_cb, NULL, NULL };
 
+                       op->o_bd = op_be;
 
                        if ( !update ) {
                                rs->sr_err = slap_mods_no_update_check( modlist,
index c9e6c02dac31bd97e23a3a9c6017c0579ff5c354..c9171d709bb52e6d5ebd5d5003a64264095b8e40 100644 (file)
@@ -203,6 +203,7 @@ fe_op_modrdn( Operation *op, SlapReply *rs )
        Backend         *newSuperior_be = NULL;
        int             manageDSAit;
        struct berval   pdn = BER_BVNULL;
+       BackendDB *op_be;
        
        if( op->o_req_ndn.bv_len == 0 ) {
                Debug( LDAP_DEBUG_ANY, "do_modrdn: root dse!\n", 0, 0, 0 );
@@ -252,6 +253,12 @@ fe_op_modrdn( Operation *op, SlapReply *rs )
                goto cleanup;
        }
 
+       /* If we've got a glued backend, check the real backend */
+       op_be = op->o_bd;
+       if ( SLAP_GLUE_INSTANCE( op->o_bd )) {
+               op->o_bd = select_backend( &op->o_req_ndn, manageDSAit, 0 );
+       }
+
        /* check restrictions */
        if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) {
                send_ldap_result( op, rs );
@@ -320,6 +327,9 @@ fe_op_modrdn( Operation *op, SlapReply *rs )
 #endif
                {
                        slap_callback cb = { NULL, slap_replog_cb, NULL, NULL };
+
+                       op->o_bd = op_be;
+
 #ifdef SLAPD_MULTIMASTER
                        if ( !op->o_bd->be_update_ndn.bv_len || !repl_user )
 #endif
index b5e53f13c868c6aed96268e374bf32e666eccecc..13da05a95285a622f527564a209c6d1a5b6f5dab 100644 (file)
@@ -271,7 +271,11 @@ glue_op_search ( Operation *op, SlapReply *rs )
 
        switch (op->ors_scope) {
        case LDAP_SCOPE_BASE:
-               return SLAP_CB_CONTINUE;
+               rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+               if (op->o_bd && op->o_bd->be_search) {
+                       rs->sr_err = op->o_bd->be_search( op, rs );
+               }
+               return rs->sr_err;
 
        case LDAP_SCOPE_ONELEVEL:
        case LDAP_SCOPE_SUBTREE:
index e056a83604070c85767c7205ec90302c176d4557..a262a9911aa74009a485b084d9ad4139f9e2d982 100644 (file)
@@ -51,6 +51,7 @@ int passwd_extop(
        int i, nhash;
        char **hashes;
        int     rc;
+       BackendDB *op_be;
 
        cb2.sc_next = &cb;
 
@@ -108,6 +109,12 @@ int passwd_extop(
                goto error_return;
        }
 
+       /* If we've got a glued backend, check the real backend */
+       op_be = op->o_bd;
+       if ( SLAP_GLUE_INSTANCE( op->o_bd )) {
+               op->o_bd = select_backend( &op->o_req_ndn, 0, 0 );
+       }
+
        if (backend_check_restrictions( op, rs,
                        (struct berval *)&slap_EXOP_MODIFY_PASSWD ) != LDAP_SUCCESS) {
                rc = rs->sr_err;
@@ -159,6 +166,8 @@ int passwd_extop(
                goto error_return;
        }
 
+       op->o_bd = op_be;
+
        /* Give the backend a chance to handle this itself */
        if ( op->o_bd->be_extended ) {
                rs->sr_err = op->o_bd->be_extended( op, rs );
index be1ce92e6052daeb9d228c83dee12d018c8d4a6f..f91874a5aee67b688fe253a9af297f043ae6c603 100644 (file)
@@ -439,7 +439,7 @@ LDAP_SLAPD_F (int) slap_global_control LDAP_P ((
 /*
  * config.c
  */
-LDAP_SLAPD_F (int) read_config LDAP_P(( const char *fname, int depth ));
+LDAP_SLAPD_F (int) read_config LDAP_P(( const char *fname, const char *dir ));
 LDAP_SLAPD_F (void) config_destroy LDAP_P ((void));
 LDAP_SLAPD_F (char **) slap_str2clist LDAP_P((
        char ***, char *, const char * ));
@@ -454,6 +454,8 @@ LDAP_SLAPD_F (int) bindconf_parse LDAP_P((
 LDAP_SLAPD_F (int) bindconf_unparse LDAP_P((
        slap_bindconf *bc, struct berval *bv ));
 LDAP_SLAPD_F (void) bindconf_free LDAP_P(( slap_bindconf *bc ));
+LDAP_SLAPD_F (int) config_generic_wrapper LDAP_P(( Backend *be,
+       const char *fname, int lineno, int argc, char **argv ));
 
 #ifdef LDAP_SLAPI
 LDAP_SLAPD_V (int) slapi_plugins_used;
index 2dfc11eb75e82fee6b32497c03db555b655ef955..f1abb5110b8970cc2a1af9b83cdd7adf807beb4b 100644 (file)
@@ -579,7 +579,7 @@ slap_send_ldap_result( Operation *op, SlapReply *rs )
         * should just set SLAPI_RESULT_CODE rather than sending a
         * result if they wish to change the result.
         */
-       if ( op->o_pb != NULL ) {
+       if ( op->o_callback == NULL && op->o_pb != NULL ) {
                slapi_int_pblock_set_operation( op->o_pb, op );
                slapi_pblock_set( op->o_pb, SLAPI_RESULT_CODE,
                        (void *)rs->sr_err );
index d76593475873fb1d3815261825f904dc93bae520..0cc2b886ed6c90c8dcc05a32d933dd389be5e77e 100644 (file)
@@ -424,6 +424,7 @@ entry_schema_check(
        }
 
        if( extensible ) {
+               *text = NULL;
                return LDAP_SUCCESS;
        }
 
@@ -471,6 +472,7 @@ entry_schema_check(
                }
        }
 
+       *text = NULL;
        return LDAP_SUCCESS;
 }
 
index 2214f0cb8e3247086e1e8f8b01724ac3f932a0d4..da0d71040eba205be8ed9e0ac157e3a79e43efd2 100644 (file)
 
 LDAP_BEGIN_DECL
 
-#ifdef LDAP_DEVEL
 #define SLAP_ACL_HONOR_DISCLOSE        /* partially implemented */
+
+#ifdef LDAP_DEVEL
 #define SLAP_DYNACL
-#define LDAP_COMP_MATCH                        /* experimental */
+#define LDAP_COMP_MATCH
 #define LDAP_DYNAMIC_OBJECTS
 #define LDAP_SYNC_TIMESTAMP
 #define LDAP_COLLECTIVE_ATTRIBUTES
 #define SLAP_CONTROL_X_TREE_DELETE LDAP_CONTROL_X_TREE_DELETE
+
+#ifdef ENABLE_REWRITE
+#define SLAP_AUTH_REWRITE      1 /* use librewrite for sasl-regexp */
+#endif
 #endif
 
-#if defined(LDAP_DEVEL) && defined(ENABLE_REWRITE)
-/* use librewrite for sasl-regexp */
-#define SLAP_AUTH_REWRITE      1
-#endif /* LDAP_DEVEL && ENABLE_REWRITE */
 
 /*
  * SLAPD Memory allocation macros
@@ -822,6 +823,7 @@ struct slap_internal_schema {
        AttributeDescription *si_ad_monitorContext;
        AttributeDescription *si_ad_vendorName;
        AttributeDescription *si_ad_vendorVersion;
+       AttributeDescription *si_ad_configContext;
 
        /* subentry attribute descriptions */
        AttributeDescription *si_ad_administrativeRole;
@@ -2029,6 +2031,7 @@ struct slap_backend_info {
 
        slap_mask_t     bi_flags; /* backend flags */
 #define SLAP_BFLAG_MONITOR                     0x0001U /* a monitor backend */
+#define SLAP_BFLAG_CONFIG                      0x0002U /* a config backend */
 #define SLAP_BFLAG_NOLASTMODCMD                0x0010U
 #define SLAP_BFLAG_INCREMENT           0x0100U
 #define SLAP_BFLAG_ALIASES                     0x1000U
@@ -2038,6 +2041,7 @@ struct slap_backend_info {
 
 #define SLAP_BFLAGS(be)                ((be)->bd_info->bi_flags)
 #define SLAP_MONITOR(be)       (SLAP_BFLAGS(be) & SLAP_BFLAG_MONITOR)
+#define SLAP_CONFIG(be)                (SLAP_BFLAGS(be) & SLAP_BFLAG_CONFIG)
 #define SLAP_INCREMENT(be)     (SLAP_BFLAGS(be) & SLAP_BFLAG_INCREMENT)
 #define SLAP_ALIASES(be)       (SLAP_BFLAGS(be) & SLAP_BFLAG_ALIASES)
 #define SLAP_REFERRALS(be)     (SLAP_BFLAGS(be) & SLAP_BFLAG_REFERRALS)
index b49c6c53256639cf16ef42bb5d389cf5e0579806..4a0c55a600dd3c9527f81981c0179877251ea9c1 100644 (file)
@@ -108,6 +108,7 @@ slap_tool_init(
 {
        char *options;
        char *conffile = SLAPD_DEFAULT_CONFIGFILE;
+       char *confdir = SLAPD_DEFAULT_CONFIGDIR;
        struct berval base = BER_BVNULL;
        char *filterstr = NULL;
        char *subtree = NULL;
@@ -127,36 +128,36 @@ slap_tool_init(
 
        switch( tool ) {
        case SLAPADD:
-               options = "b:cd:f:l:n:qtuvw";
+               options = "b:cd:f:F:l:n:qtuvw";
                break;
 
        case SLAPCAT:
-               options = "a:b:cd:f:l:n:s:v";
+               options = "a:b:cd:f:F:l:n:s:v";
                mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY;
                break;
 
        case SLAPDN:
-               options = "d:f:v";
+               options = "d:f:F:v";
                mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY;
                break;
 
        case SLAPTEST:
-               options = "d:f:uv";
+               options = "d:f:F:uv";
                mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY;
                break;
 
        case SLAPAUTH:
-               options = "d:f:M:R:U:vX:";
+               options = "d:f:F:M:R:U:vX:";
                mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY;
                break;
 
        case SLAPINDEX:
-               options = "b:cd:f:n:qv";
+               options = "b:cd:f:F:n:qv";
                mode |= SLAP_TOOL_READMAIN;
                break;
 
        case SLAPACL:
-               options = "b:D:d:f:U:v";
+               options = "b:D:d:f:F:U:v";
                mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY;
                break;
 
@@ -192,6 +193,10 @@ slap_tool_init(
                        conffile = strdup( optarg );
                        break;
 
+               case 'F':       /* specify a conf dir */
+                       confdir = strdup( optarg );
+                       break;
+
                case 'l':       /* LDIF file */
                        ldiffile = strdup( optarg );
                        break;
@@ -336,7 +341,7 @@ slap_tool_init(
                exit( EXIT_FAILURE );
        }
 
-       rc = read_config( conffile, 0 );
+       rc = read_config( conffile, confdir );
 
        if ( rc != 0 ) {
                fprintf( stderr, "%s: bad configuration file!\n", progname );