Back to index

openldap  2.4.31
Classes | Defines | Typedefs | Enumerations | Functions | Variables
ldif.c File Reference
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ac/dirent.h>
#include <fcntl.h>
#include <ac/errno.h>
#include <ac/unistd.h>
#include "slap.h"
#include "lutil.h"
#include "config.h"

Go to the source code of this file.

Classes

struct  ldif_tool
struct  ldif_info
struct  assert_safe_filenames
struct  bvlist

Defines

#define ENTRY_BUFF_INCREMENT   500 /* initial entries[] length */
#define move_file(from, to)   rename(from, to)
#define move_dir(from, to)   rename(from, to)
#define LDIF   ".ldif"
#define LDIF_FILETYPE_SEP   '.' /* LDIF[0] */
#define LDIF_ESCAPE_CHAR   '\\'
#define LDIF_UNSAFE_CHAR(c)   ((c) == '/' || (c) == ':')
#define IX_DNL   '{'
#define IX_DNR   '}'
#define IX_FSL   IX_DNL
#define IX_FSR   IX_DNR
#define LDIF_NEED_ESCAPE(c)
#define LDIF_MAYBE_UNSAFE(c, x)
#define FILL_PATH(fpath, dir_end, filename)   ((fpath)->bv_len = lutil_strcopy(dir_end, filename) - (fpath)->bv_val)
#define ldif2dir_len(bv)   ((bv).bv_len -= STRLENOF(LDIF))
#define dir2ldif_len(bv)   ((bv).bv_len += STRLENOF(LDIF))
#define ldif2dir_name(bv)   ((bv).bv_val[(bv).bv_len] = '\0')
#define dir2ldif_name(bv)   ((bv).bv_val[(bv).bv_len] = LDIF_FILETYPE_SEP)
#define CRC1   crc = crctab[(crc ^ *buf++) & 0xff] ^ (crc >> 8)
#define CRC8   CRC1; CRC1; CRC1; CRC1; CRC1; CRC1; CRC1; CRC1
#define HEADER   "# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.\n"
#define BVL_NAME(bvl)   ((char *) ((bvl) + 1))
#define BVL_SIZE(namelen)   (sizeof(bvlist) + (namelen) + 1)

Typedefs

typedef struct bvlist bvlist

Enumerations

enum  { eq_unsafe = LDIF_UNSAFE_CHAR('='), safe_filenames }

Functions

static int write_data (int fd, const char *spew, int len, int *save_errno)
static int ndn2path (Operation *op, struct berval *dn, struct berval *res, int empty_ok)
static char * fullpath_alloc (struct berval *dest, const struct berval *dir, ber_len_t more)
static int get_parent_path (struct berval *dnpath, struct berval *res)
static char * ldif_tempname (const struct berval *dnpath)
unsigned int crc32 (const void *vbuf, int len)
static int ldif_read_file (const char *path, char **datap)
static int spew_file (int fd, const char *spew, int len, int *save_errno)
static int ldif_write_entry (Operation *op, Entry *e, const struct berval *path, const char *parentdir, const char **text)
static int ldif_read_entry (Operation *op, const char *path, struct berval *pdn, struct berval *pndn, Entry **entryp, const char **text)
static int get_entry (Operation *op, Entry **entryp, struct berval *pathp, const char **text)
static int ldif_send_entry (Operation *op, SlapReply *rs, Entry *e, int scope)
static int ldif_readdir (Operation *op, SlapReply *rs, const struct berval *path, bvlist **listp, ber_len_t *fname_maxlenp)
static int ldif_search_entry (Operation *op, SlapReply *rs, Entry *e, int scope, struct berval *path)
static int search_tree (Operation *op, SlapReply *rs)
static int ldif_prepare_create (Operation *op, Entry *e, struct berval *dnpath, char **need_dir, const char **text)
static int apply_modify_to_entry (Entry *entry, Modifications *modlist, Operation *op, SlapReply *rs, char *textbuf)
static int ldif_back_referrals (Operation *op, SlapReply *rs)
static int ldif_back_bind (Operation *op, SlapReply *rs)
static int ldif_back_search (Operation *op, SlapReply *rs)
static int ldif_back_add (Operation *op, SlapReply *rs)
static int ldif_back_modify (Operation *op, SlapReply *rs)
static int ldif_back_delete (Operation *op, SlapReply *rs)
static int ldif_move_entry (Operation *op, Entry *entry, int same_ndn, struct berval *oldpath, const char **text)
static int ldif_back_modrdn (Operation *op, SlapReply *rs)
static int ldif_back_entry_get (Operation *op, struct berval *ndn, ObjectClass *oc, AttributeDescription *at, int rw, Entry **e)
static int ldif_tool_entry_open (BackendDB *be, int mode)
static int ldif_tool_entry_close (BackendDB *be)
static ID ldif_tool_entry_next (BackendDB *be)
static ID ldif_tool_entry_first_x (BackendDB *be, struct berval *base, int scope, Filter *f)
static Entryldif_tool_entry_get (BackendDB *be, ID id)
static ID ldif_tool_entry_put (BackendDB *be, Entry *e, struct berval *text)
static int ldif_back_db_init (BackendDB *be, ConfigReply *cr)
static int ldif_back_db_destroy (Backend *be, ConfigReply *cr)
static int ldif_back_db_open (Backend *be, ConfigReply *cr)
int ldif_back_initialize (BackendInfo *bi)

Variables

static ConfigTable ldifcfg []
static ConfigOCs ldifocs []
static const ber_uint_t crctab [256]

Class Documentation

struct ldif_tool

Definition at line 34 of file ldif.c.

Collaboration diagram for ldif_tool:
Class Members
ID ecount
ID ecurrent
ID elen
Entry ** entries
struct berval * tl_base
Filter * tl_filter
int tl_scope
struct ldif_info

Definition at line 46 of file ldif.c.

Collaboration diagram for ldif_info:
Class Members
ldap_pvt_thread_mutex_t li_modop_mutex
ldap_pvt_thread_rdwr_t li_rdwr
struct assert_safe_filenames

Definition at line 161 of file ldif.c.

Class Members
int assert_safe_filenames: safe_filenames ? 2 : -2
struct bvlist

Definition at line 726 of file ldif.c.

Collaboration diagram for bvlist:
Class Members
int inum
struct bvlist * next
char savech
char * trunc

Define Documentation

#define BVL_NAME (   bvl)    ((char *) ((bvl) + 1))

Definition at line 732 of file ldif.c.

#define BVL_SIZE (   namelen)    (sizeof(bvlist) + (namelen) + 1)

Definition at line 733 of file ldif.c.

#define CRC1   crc = crctab[(crc ^ *buf++) & 0xff] ^ (crc >> 8)

Definition at line 391 of file ldif.c.

#define CRC8   CRC1; CRC1; CRC1; CRC1; CRC1; CRC1; CRC1; CRC1

Definition at line 392 of file ldif.c.

#define dir2ldif_len (   bv)    ((bv).bv_len += STRLENOF(LDIF))

Definition at line 289 of file ldif.c.

#define dir2ldif_name (   bv)    ((bv).bv_val[(bv).bv_len] = LDIF_FILETYPE_SEP)

Definition at line 292 of file ldif.c.

#define ENTRY_BUFF_INCREMENT   500 /* initial entries[] length */

Definition at line 39 of file ldif.c.

#define FILL_PATH (   fpath,
  dir_end,
  filename 
)    ((fpath)->bv_len = lutil_strcopy(dir_end, filename) - (fpath)->bv_val)

Definition at line 283 of file ldif.c.

#define HEADER   "# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.\n"
#define IX_DNL   '{'

Definition at line 119 of file ldif.c.

#define IX_DNR   '}'

Definition at line 120 of file ldif.c.

#define IX_FSL   IX_DNL

Definition at line 122 of file ldif.c.

#define IX_FSR   IX_DNR

Definition at line 123 of file ldif.c.

#define LDIF   ".ldif"

Definition at line 72 of file ldif.c.

#define ldif2dir_len (   bv)    ((bv).bv_len -= STRLENOF(LDIF))

Definition at line 288 of file ldif.c.

#define ldif2dir_name (   bv)    ((bv).bv_val[(bv).bv_len] = '\0')

Definition at line 291 of file ldif.c.

#define LDIF_ESCAPE_CHAR   '\\'

Definition at line 101 of file ldif.c.

#define LDIF_FILETYPE_SEP   '.' /* LDIF[0] */

Definition at line 73 of file ldif.c.

#define LDIF_MAYBE_UNSAFE (   c,
 
)
Value:
(!(LDIF_UNSAFE_CHAR(x) || (x) == '\\' || (x) == IX_DNL || (x) == IX_DNR) \
        && (c) == (x))

Definition at line 148 of file ldif.c.

#define LDIF_NEED_ESCAPE (   c)
Value:
((LDIF_UNSAFE_CHAR(c)) || \
        LDIF_MAYBE_UNSAFE(c, LDIF_ESCAPE_CHAR) || \
        LDIF_MAYBE_UNSAFE(c, LDIF_FILETYPE_SEP) || \
        LDIF_MAYBE_UNSAFE(c, IX_FSL) || \
        (IX_FSR != IX_FSL && LDIF_MAYBE_UNSAFE(c, IX_FSR)))

Definition at line 137 of file ldif.c.

#define LDIF_UNSAFE_CHAR (   c)    ((c) == '/' || (c) == ':')

Definition at line 102 of file ldif.c.

#define move_dir (   from,
  to 
)    rename(from, to)

Definition at line 69 of file ldif.c.

#define move_file (   from,
  to 
)    rename(from, to)

Definition at line 67 of file ldif.c.


Typedef Documentation

typedef struct bvlist bvlist

Enumeration Type Documentation

anonymous enum
Enumerator:
eq_unsafe 
safe_filenames 

Definition at line 153 of file ldif.c.

     {
       eq_unsafe = LDIF_UNSAFE_CHAR('='),
       safe_filenames = STRLENOF("" LDAP_DIRSEP "") == 1 && !(
              LDIF_UNSAFE_CHAR('-') || /* for "{-1}frontend" in bconfig.c */
              LDIF_UNSAFE_CHAR(LDIF_ESCAPE_CHAR) ||
              LDIF_UNSAFE_CHAR(IX_FSL) || LDIF_UNSAFE_CHAR(IX_FSR))
};

Function Documentation

static int apply_modify_to_entry ( Entry entry,
Modifications modlist,
Operation op,
SlapReply rs,
char *  textbuf 
) [static]

Definition at line 1140 of file ldif.c.

{
       int rc = modlist ? LDAP_UNWILLING_TO_PERFORM : LDAP_SUCCESS;
       int is_oc = 0;
       Modification *mods;

       if (!acl_check_modlist(op, entry, modlist)) {
              return LDAP_INSUFFICIENT_ACCESS;
       }

       for (; modlist != NULL; modlist = modlist->sml_next) {
              mods = &modlist->sml_mod;

              if ( mods->sm_desc == slap_schema.si_ad_objectClass ) {
                     is_oc = 1;
              }
              switch (mods->sm_op) {
              case LDAP_MOD_ADD:
                     rc = modify_add_values(entry, mods,
                               get_permissiveModify(op),
                               &rs->sr_text, textbuf,
                               SLAP_TEXT_BUFLEN );
                     break;

              case LDAP_MOD_DELETE:
                     rc = modify_delete_values(entry, mods,
                            get_permissiveModify(op),
                            &rs->sr_text, textbuf,
                            SLAP_TEXT_BUFLEN );
                     break;

              case LDAP_MOD_REPLACE:
                     rc = modify_replace_values(entry, mods,
                             get_permissiveModify(op),
                             &rs->sr_text, textbuf,
                             SLAP_TEXT_BUFLEN );
                     break;

              case LDAP_MOD_INCREMENT:
                     rc = modify_increment_values( entry,
                            mods, get_permissiveModify(op),
                            &rs->sr_text, textbuf,
                            SLAP_TEXT_BUFLEN );
                     break;

              case SLAP_MOD_SOFTADD:
                     mods->sm_op = LDAP_MOD_ADD;
                     rc = modify_add_values(entry, mods,
                               get_permissiveModify(op),
                               &rs->sr_text, textbuf,
                               SLAP_TEXT_BUFLEN );
                     mods->sm_op = SLAP_MOD_SOFTADD;
                     if (rc == LDAP_TYPE_OR_VALUE_EXISTS) {
                            rc = LDAP_SUCCESS;
                     }
                     break;

              case SLAP_MOD_SOFTDEL:
                     mods->sm_op = LDAP_MOD_DELETE;
                     rc = modify_delete_values(entry, mods,
                               get_permissiveModify(op),
                               &rs->sr_text, textbuf,
                               SLAP_TEXT_BUFLEN );
                     mods->sm_op = SLAP_MOD_SOFTDEL;
                     if (rc == LDAP_NO_SUCH_ATTRIBUTE) {
                            rc = LDAP_SUCCESS;
                     }
                     break;

              case SLAP_MOD_ADD_IF_NOT_PRESENT:
                     if ( attr_find( entry->e_attrs, mods->sm_desc ) ) {
                            rc = LDAP_SUCCESS;
                            break;
                     }
                     mods->sm_op = LDAP_MOD_ADD;
                     rc = modify_add_values(entry, mods,
                               get_permissiveModify(op),
                               &rs->sr_text, textbuf,
                               SLAP_TEXT_BUFLEN );
                     mods->sm_op = SLAP_MOD_ADD_IF_NOT_PRESENT;
                     break;
              }
              if(rc != LDAP_SUCCESS) break;
       }

       if ( rc == LDAP_SUCCESS ) {
              rs->sr_text = NULL; /* Needed at least with SLAP_MOD_SOFTADD */
              if ( is_oc ) {
                     entry->e_ocflags = 0;
              }
              /* check that the entry still obeys the schema */
              rc = entry_schema_check( op, entry, NULL, 0, 0, NULL,
                       &rs->sr_text, textbuf, SLAP_TEXT_BUFLEN );
       }

       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

unsigned int crc32 ( const void vbuf,
int  len 
)

Definition at line 394 of file ldif.c.

{
       const unsigned char  *buf = vbuf;
       ber_uint_t           crc = 0xffffffff;
       int                         i;

       while (len > 7) {
              CRC8;
              len -= 8;
       }
       while (len) {
              CRC1;
              len--;
       }

       return crc ^ 0xffffffff;
}

Here is the caller graph for this function:

static char* fullpath_alloc ( struct berval dest,
const struct berval dir,
ber_len_t  more 
) [static]

Definition at line 262 of file ldif.c.

{
       char *s = SLAP_MALLOC( dir->bv_len + more + 2 );

       dest->bv_val = s;
       if ( s == NULL ) {
              dest->bv_len = 0;
              Debug( LDAP_DEBUG_ANY, "back-ldif: out of memory\n", 0, 0, 0 );
       } else {
              s = lutil_strcopy( dest->bv_val, dir->bv_val );
              *s++ = LDAP_DIRSEP[0];
              *s = '\0';
              dest->bv_len = s - dest->bv_val;
       }
       return s;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int get_entry ( Operation op,
Entry **  entryp,
struct berval pathp,
const char **  text 
) [static]

Definition at line 692 of file ldif.c.

{
       int rc;
       struct berval path, pdn, pndn;

       dnParent( &op->o_req_dn, &pdn );
       dnParent( &op->o_req_ndn, &pndn );
       rc = ndn2path( op, &op->o_req_ndn, &path, 0 );
       if ( rc != LDAP_SUCCESS ) {
              goto done;
       }

       rc = ldif_read_entry( op, path.bv_val, &pdn, &pndn, entryp, text );

       if ( rc == LDAP_SUCCESS && pathp != NULL ) {
              *pathp = path;
       } else {
              SLAP_FREE( path.bv_val );
       }
 done:
       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int get_parent_path ( struct berval dnpath,
struct berval res 
) [static]

Definition at line 296 of file ldif.c.

{
       ber_len_t i = dnpath->bv_len;

       while ( i > 0 && dnpath->bv_val[ --i ] != LDAP_DIRSEP[0] ) ;
       if ( res == NULL ) {
              res = dnpath;
       } else {
              res->bv_val = SLAP_MALLOC( i + 1 + STRLENOF(LDIF) );
              if ( res->bv_val == NULL )
                     return LDAP_OTHER;
              AC_MEMCPY( res->bv_val, dnpath->bv_val, i );
       }
       res->bv_len = i;
       strcpy( res->bv_val + i, LDIF );
       res->bv_val[i] = '\0';
       return LDAP_SUCCESS;
}

Here is the caller graph for this function:

static int ldif_back_add ( Operation op,
SlapReply rs 
) [static]

Definition at line 1390 of file ldif.c.

{
       struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
       Entry * e = op->ora_e;
       struct berval path;
       char *parentdir;
       char textbuf[SLAP_TEXT_BUFLEN];
       int rc;

       Debug( LDAP_DEBUG_TRACE, "ldif_back_add: \"%s\"\n", e->e_dn, 0, 0 );

       rc = entry_schema_check( op, e, NULL, 0, 1, NULL,
              &rs->sr_text, textbuf, sizeof( textbuf ) );
       if ( rc != LDAP_SUCCESS )
              goto send_res;

       rc = slap_add_opattrs( op, &rs->sr_text, textbuf, sizeof( textbuf ), 1 );
       if ( rc != LDAP_SUCCESS )
              goto send_res;

       ldap_pvt_thread_mutex_lock( &li->li_modop_mutex );

       rc = ldif_prepare_create( op, e, &path, &parentdir, &rs->sr_text );
       if ( rc == LDAP_SUCCESS ) {
              ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
              rc = ldif_write_entry( op, e, &path, parentdir, &rs->sr_text );
              ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );

              SLAP_FREE( path.bv_val );
              if ( parentdir != NULL )
                     SLAP_FREE( parentdir );
       }

       ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex );

 send_res:
       rs->sr_err = rc;
       Debug( LDAP_DEBUG_TRACE, "ldif_back_add: err: %d text: %s\n",
              rc, rs->sr_text ? rs->sr_text : "", 0 );
       send_ldap_result( op, rs );
       slap_graduate_commit_csn( op );
       rs->sr_text = NULL;  /* remove possible pointer to textbuf */
       return rs->sr_err;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ldif_back_bind ( Operation op,
SlapReply rs 
) [static]

Definition at line 1321 of file ldif.c.

{
       struct ldif_info *li;
       Attribute *a;
       AttributeDescription *password = slap_schema.si_ad_userPassword;
       int return_val;
       Entry *entry = NULL;

       switch ( be_rootdn_bind( op, rs ) ) {
       case SLAP_CB_CONTINUE:
              break;

       default:
              /* in case of success, front end will send result;
               * otherwise, be_rootdn_bind() did */
              return rs->sr_err;
       }

       li = (struct ldif_info *) op->o_bd->be_private;
       ldap_pvt_thread_rdwr_rlock(&li->li_rdwr);
       return_val = get_entry(op, &entry, NULL, NULL);

       /* no object is found for them */
       if(return_val != LDAP_SUCCESS) {
              rs->sr_err = return_val = LDAP_INVALID_CREDENTIALS;
              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;
       }

       /* 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;
       }

       /* let the front-end send success */
       return_val = LDAP_SUCCESS;

 return_result:
       ldap_pvt_thread_rdwr_runlock(&li->li_rdwr);
       if(return_val != LDAP_SUCCESS)
              send_ldap_result( op, rs );
       if(entry != NULL)
              entry_free(entry);
       return return_val;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ldif_back_db_destroy ( Backend be,
ConfigReply *  cr 
) [static]

Definition at line 1849 of file ldif.c.

{
       struct ldif_info *li = be->be_private;

       ch_free( li->li_base_path.bv_val );
       ldap_pvt_thread_rdwr_destroy( &li->li_rdwr );
       ldap_pvt_thread_mutex_destroy( &li->li_modop_mutex );
       free( be->be_private );
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ldif_back_db_init ( BackendDB be,
ConfigReply *  cr 
) [static]

Definition at line 1835 of file ldif.c.

{
       struct ldif_info *li;

       li = ch_calloc( 1, sizeof(struct ldif_info) );
       be->be_private = li;
       be->be_cf_ocs = ldifocs;
       ldap_pvt_thread_mutex_init( &li->li_modop_mutex );
       ldap_pvt_thread_rdwr_init( &li->li_rdwr );
       SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_ONE_SUFFIX;
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ldif_back_db_open ( Backend be,
ConfigReply *  cr 
) [static]

Definition at line 1861 of file ldif.c.

{
       struct ldif_info *li = (struct ldif_info *) be->be_private;
       if( BER_BVISEMPTY(&li->li_base_path)) {/* missing base path */
              Debug( LDAP_DEBUG_ANY, "missing base path for back-ldif\n", 0, 0, 0);
              return 1;
       }
       return 0;
}

Here is the caller graph for this function:

static int ldif_back_delete ( Operation op,
SlapReply rs 
) [static]

Definition at line 1472 of file ldif.c.

{
       struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
       struct berval path;
       int rc = LDAP_SUCCESS;

       if ( BER_BVISEMPTY( &op->o_csn )) {
              struct berval csn;
              char csnbuf[LDAP_PVT_CSNSTR_BUFSIZE];

              csn.bv_val = csnbuf;
              csn.bv_len = sizeof( csnbuf );
              slap_get_csn( op, &csn, 1 );
       }

       ldap_pvt_thread_mutex_lock( &li->li_modop_mutex );
       ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
       if ( op->o_abandon ) {
              rc = SLAPD_ABANDON;
              goto done;
       }

       rc = ndn2path( op, &op->o_req_ndn, &path, 0 );
       if ( rc != LDAP_SUCCESS ) {
              goto done;
       }

       ldif2dir_len( path );
       ldif2dir_name( path );
       if ( rmdir( path.bv_val ) < 0 ) {
              switch ( errno ) {
              case ENOTEMPTY:
                     rc = LDAP_NOT_ALLOWED_ON_NONLEAF;
                     break;
              case ENOENT:
                     /* is leaf, go on */
                     break;
              default:
                     rc = LDAP_OTHER;
                     rs->sr_text = "internal error (cannot delete subtree directory)";
                     break;
              }
       }

       if ( rc == LDAP_SUCCESS ) {
              dir2ldif_name( path );
              if ( unlink( path.bv_val ) < 0 ) {
                     rc = LDAP_NO_SUCH_OBJECT;
                     if ( errno != ENOENT ) {
                            rc = LDAP_OTHER;
                            rs->sr_text = "internal error (cannot delete entry file)";
                     }
              }
       }

       if ( rc == LDAP_OTHER ) {
              Debug( LDAP_DEBUG_ANY, "ldif_back_delete: %s \"%s\": %s\n",
                     "cannot delete", path.bv_val, STRERROR( errno ) );
       }

       SLAP_FREE( path.bv_val );
 done:
       ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
       ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex );
       rs->sr_err = rc;
       send_ldap_result( op, rs );
       slap_graduate_commit_csn( op );
       return rs->sr_err;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ldif_back_entry_get ( Operation op,
struct berval ndn,
ObjectClass oc,
AttributeDescription at,
int  rw,
Entry **  e 
) [static]

Definition at line 1677 of file ldif.c.

{
       struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
       struct berval op_dn = op->o_req_dn, op_ndn = op->o_req_ndn;
       int rc;

       assert( ndn != NULL );
       assert( !BER_BVISNULL( ndn ) );

       ldap_pvt_thread_rdwr_rlock( &li->li_rdwr );
       op->o_req_dn = *ndn;
       op->o_req_ndn = *ndn;
       rc = get_entry( op, e, NULL, NULL );
       op->o_req_dn = op_dn;
       op->o_req_ndn = op_ndn;
       ldap_pvt_thread_rdwr_runlock( &li->li_rdwr );

       if ( rc == LDAP_SUCCESS && oc && !is_entry_objectclass_or_sub( *e, oc ) ) {
              rc = LDAP_NO_SUCH_ATTRIBUTE;
              entry_free( *e );
              *e = NULL;
       }

       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1872 of file ldif.c.

{
       static char *controls[] = {
              LDAP_CONTROL_MANAGEDSAIT,
              NULL
       };
       int rc;

       bi->bi_flags |=
              SLAP_BFLAG_INCREMENT |
              SLAP_BFLAG_REFERRALS;

       bi->bi_controls = controls;

       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 = config_generic_wrapper;
       bi->bi_db_open = ldif_back_db_open;
       bi->bi_db_close = 0;
       bi->bi_db_destroy = ldif_back_db_destroy;

       bi->bi_op_bind = ldif_back_bind;
       bi->bi_op_unbind = 0;
       bi->bi_op_search = ldif_back_search;
       bi->bi_op_compare = 0;
       bi->bi_op_modify = ldif_back_modify;
       bi->bi_op_modrdn = ldif_back_modrdn;
       bi->bi_op_add = ldif_back_add;
       bi->bi_op_delete = ldif_back_delete;
       bi->bi_op_abandon = 0;

       bi->bi_extended = 0;

       bi->bi_chk_referrals = ldif_back_referrals;

       bi->bi_connection_init = 0;
       bi->bi_connection_destroy = 0;

       bi->bi_entry_get_rw = ldif_back_entry_get;

#if 0  /* NOTE: uncomment to completely disable access control */
       bi->bi_access_allowed = slap_access_always_allowed;
#endif

       bi->bi_tool_entry_open = ldif_tool_entry_open;
       bi->bi_tool_entry_close = ldif_tool_entry_close;
       bi->bi_tool_entry_first = backend_tool_entry_first;
       bi->bi_tool_entry_first_x = ldif_tool_entry_first_x;
       bi->bi_tool_entry_next = ldif_tool_entry_next;
       bi->bi_tool_entry_get = ldif_tool_entry_get;
       bi->bi_tool_entry_put = ldif_tool_entry_put;
       bi->bi_tool_entry_reindex = 0;
       bi->bi_tool_sync = 0;

       bi->bi_tool_dn2id_get = 0;
       bi->bi_tool_entry_modify = 0;

       bi->bi_cf_ocs = ldifocs;

       rc = config_register_schema( ldifcfg, ldifocs );
       if ( rc ) return rc;
       return 0;
}

Here is the call graph for this function:

static int ldif_back_modify ( Operation op,
SlapReply rs 
) [static]

Definition at line 1436 of file ldif.c.

{
       struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
       Modifications * modlst = op->orm_modlist;
       struct berval path;
       Entry *entry;
       char textbuf[SLAP_TEXT_BUFLEN];
       int rc;

       slap_mods_opattrs( op, &op->orm_modlist, 1 );

       ldap_pvt_thread_mutex_lock( &li->li_modop_mutex );

       rc = get_entry( op, &entry, &path, &rs->sr_text );
       if ( rc == LDAP_SUCCESS ) {
              rc = apply_modify_to_entry( entry, modlst, op, rs, textbuf );
              if ( rc == LDAP_SUCCESS ) {
                     ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
                     rc = ldif_write_entry( op, entry, &path, NULL, &rs->sr_text );
                     ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
              }

              entry_free( entry );
              SLAP_FREE( path.bv_val );
       }

       ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex );

       rs->sr_err = rc;
       send_ldap_result( op, rs );
       slap_graduate_commit_csn( op );
       rs->sr_text = NULL;  /* remove possible pointer to textbuf */
       return rs->sr_err;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ldif_back_modrdn ( Operation op,
SlapReply rs 
) [static]

Definition at line 1627 of file ldif.c.

{
       struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
       struct berval new_dn = BER_BVNULL, new_ndn = BER_BVNULL;
       struct berval p_dn, old_path;
       Entry *entry;
       char textbuf[SLAP_TEXT_BUFLEN];
       int rc, same_ndn;

       slap_mods_opattrs( op, &op->orr_modlist, 1 );

       ldap_pvt_thread_mutex_lock( &li->li_modop_mutex );

       rc = get_entry( op, &entry, &old_path, &rs->sr_text );
       if ( rc == LDAP_SUCCESS ) {
              /* build new dn, and new ndn for the entry */
              if ( op->oq_modrdn.rs_newSup != NULL ) {
                     p_dn = *op->oq_modrdn.rs_newSup;
              } else {
                     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, &new_ndn, NULL );
              same_ndn = !ber_bvcmp( &entry->e_nname, &new_ndn );
              ber_memfree_x( entry->e_name.bv_val, NULL );
              ber_memfree_x( entry->e_nname.bv_val, NULL );
              entry->e_name = new_dn;
              entry->e_nname = new_ndn;

              /* perform the modifications */
              rc = apply_modify_to_entry( entry, op->orr_modlist, op, rs, textbuf );
              if ( rc == LDAP_SUCCESS )
                     rc = ldif_move_entry( op, entry, same_ndn, &old_path,
                            &rs->sr_text );

              entry_free( entry );
              SLAP_FREE( old_path.bv_val );
       }

       ldap_pvt_thread_mutex_unlock( &li->li_modop_mutex );
       rs->sr_err = rc;
       send_ldap_result( op, rs );
       slap_graduate_commit_csn( op );
       rs->sr_text = NULL;  /* remove possible pointer to textbuf */
       return rs->sr_err;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ldif_back_referrals ( Operation op,
SlapReply rs 
) [static]

Definition at line 1245 of file ldif.c.

{
       struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
       struct berval path, dn = op->o_req_dn, ndn = op->o_req_ndn;
       ber_len_t min_dnlen;
       Entry *entry = NULL, **entryp;
       BerVarray ref;
       int rc;

       min_dnlen = op->o_bd->be_nsuffix[0].bv_len;
       if ( min_dnlen == 0 ) {
              /* Catch root DSE (empty DN), it is not a referral */
              min_dnlen = 1;
       }
       if ( ndn2path( op, &ndn, &path, 0 ) != LDAP_SUCCESS ) {
              return LDAP_SUCCESS; /* Root DSE again */
       }

       entryp = get_manageDSAit( op ) ? NULL : &entry;
       ldap_pvt_thread_rdwr_rlock( &li->li_rdwr );

       for (;;) {
              dnParent( &dn, &dn );
              dnParent( &ndn, &ndn );
              rc = ldif_read_entry( op, path.bv_val, &dn, &ndn,
                     entryp, &rs->sr_text );
              if ( rc != LDAP_NO_SUCH_OBJECT )
                     break;

              rc = LDAP_SUCCESS;
              if ( ndn.bv_len < min_dnlen )
                     break;
              (void) get_parent_path( &path, NULL );
              dir2ldif_name( path );
              entryp = &entry;
       }

       ldap_pvt_thread_rdwr_runlock( &li->li_rdwr );
       SLAP_FREE( path.bv_val );

       if ( entry != NULL ) {
              if ( is_entry_referral( entry ) ) {
                     Debug( LDAP_DEBUG_TRACE,
                            "ldif_back_referrals: tag=%lu target=\"%s\" matched=\"%s\"\n",
                            (unsigned long) op->o_tag, op->o_req_dn.bv_val, entry->e_dn );

                     ref = get_entry_referrals( op, entry );
                     rs->sr_ref = referral_rewrite( ref, &entry->e_name, &op->o_req_dn,
                            op->o_tag == LDAP_REQ_SEARCH ?
                            op->ors_scope : LDAP_SCOPE_DEFAULT );
                     ber_bvarray_free( ref );

                     if ( rs->sr_ref != NULL ) {
                            /* send referral */
                            rc = rs->sr_err = LDAP_REFERRAL;
                            rs->sr_matched = entry->e_dn;
                            send_ldap_result( op, rs );
                            ber_bvarray_free( rs->sr_ref );
                            rs->sr_ref = NULL;
                     } else {
                            rc = LDAP_OTHER;
                            rs->sr_text = "bad referral object";
                     }
                     rs->sr_matched = NULL;
              }

              entry_free( entry );
       }

       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ldif_back_search ( Operation op,
SlapReply rs 
) [static]

Definition at line 1377 of file ldif.c.

{
       struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;

       ldap_pvt_thread_rdwr_rlock(&li->li_rdwr);
       rs->sr_err = search_tree( op, rs );
       ldap_pvt_thread_rdwr_runlock(&li->li_rdwr);
       send_ldap_result(op, rs);

       return rs->sr_err;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ldif_move_entry ( Operation op,
Entry entry,
int  same_ndn,
struct berval oldpath,
const char **  text 
) [static]

Definition at line 1544 of file ldif.c.

{
       struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
       struct berval newpath;
       char *parentdir = NULL, *trash;
       int rc, rename_res;

       if ( same_ndn ) {
              rc = LDAP_SUCCESS;
              newpath = *oldpath;
       } else {
              rc = ldif_prepare_create( op, entry, &newpath,
                     op->orr_newSup ? &parentdir : NULL, text );
       }

       if ( rc == LDAP_SUCCESS ) {
              ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );

              rc = ldif_write_entry( op, entry, &newpath, parentdir, text );
              if ( rc == LDAP_SUCCESS && !same_ndn ) {
                     trash = oldpath->bv_val; /* will be .ldif file to delete */
                     ldif2dir_len( newpath );
                     ldif2dir_len( *oldpath );
                     /* Move subdir before deleting old entry,
                      * so .ldif always exists if subdir does.
                      */
                     ldif2dir_name( newpath );
                     ldif2dir_name( *oldpath );
                     rename_res = move_dir( oldpath->bv_val, newpath.bv_val );
                     if ( rename_res != 0 && errno != ENOENT ) {
                            rc = LDAP_OTHER;
                            *text = "internal error (cannot move this subtree)";
                            trash = newpath.bv_val;
                     }

                     /* Delete old entry, or if error undo change */
                     for (;;) {
                            dir2ldif_name( newpath );
                            dir2ldif_name( *oldpath );
                            if ( unlink( trash ) == 0 )
                                   break;
                            if ( rc == LDAP_SUCCESS ) {
                                   /* Prepare to undo change and return failure */
                                   rc = LDAP_OTHER;
                                   *text = "internal error (cannot move this entry)";
                                   trash = newpath.bv_val;
                                   if ( rename_res != 0 )
                                          continue;
                                   /* First move subdirectory back */
                                   ldif2dir_name( newpath );
                                   ldif2dir_name( *oldpath );
                                   if ( move_dir( newpath.bv_val, oldpath->bv_val ) == 0 )
                                          continue;
                            }
                            *text = "added new but couldn't delete old entry!";
                            break;
                     }

                     if ( rc != LDAP_SUCCESS ) {
                            char s[128];
                            snprintf( s, sizeof s, "%s (%s)", *text, STRERROR( errno ));
                            Debug( LDAP_DEBUG_ANY,
                                   "ldif_move_entry: %s: \"%s\" -> \"%s\"\n",
                                   s, op->o_req_dn.bv_val, entry->e_dn );
                     }
              }

              ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
              if ( !same_ndn )
                     SLAP_FREE( newpath.bv_val );
              if ( parentdir != NULL )
                     SLAP_FREE( parentdir );
       }

       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ldif_prepare_create ( Operation op,
Entry e,
struct berval dnpath,
char **  need_dir,
const char **  text 
) [static]

Definition at line 1043 of file ldif.c.

{
       struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
       struct berval *ndn = &e->e_nname;
       struct berval ppath = BER_BVNULL;
       struct stat st;
       Entry *parent = NULL;
       int rc;

       if ( op->o_abandon )
              return SLAPD_ABANDON;

       rc = ndn2path( op, ndn, dnpath, 0 );
       if ( rc != LDAP_SUCCESS ) {
              return rc;
       }

       if ( stat( dnpath->bv_val, &st ) == 0 ) { /* entry .ldif file */
              rc = LDAP_ALREADY_EXISTS;

       } else if ( errno != ENOENT ) {
              Debug( LDAP_DEBUG_ANY,
                     "ldif_prepare_create: cannot stat \"%s\": %s\n",
                     dnpath->bv_val, STRERROR( errno ), 0 );
              rc = LDAP_OTHER;
              *text = "internal error (cannot check entry file)";

       } else if ( need_dir != NULL ) {
              *need_dir = NULL;
              rc = get_parent_path( dnpath, &ppath );
              /* If parent dir exists, so does parent .ldif:
               * The directory gets created after and removed before the .ldif.
               * Except with the database directory, which has no matching entry.
               */
              if ( rc == LDAP_SUCCESS && stat( ppath.bv_val, &st ) < 0 ) {
                     rc = errno == ENOENT && ppath.bv_len > li->li_base_path.bv_len
                            ? LDAP_NO_SUCH_OBJECT : LDAP_OTHER;
              }
              switch ( rc ) {
              case LDAP_NO_SUCH_OBJECT:
                     /* No parent dir, check parent .ldif */
                     dir2ldif_name( ppath );
                     rc = ldif_read_entry( op, ppath.bv_val, NULL, NULL,
                            (op->o_tag != LDAP_REQ_ADD || get_manageDSAit( op )
                             ? &parent : NULL),
                            text );
                     switch ( rc ) {
                     case LDAP_SUCCESS:
                            /* Check that parent is not a referral, unless
                             * ldif_back_referrals() already checked.
                             */
                            if ( parent != NULL ) {
                                   int is_ref = is_entry_referral( parent );
                                   entry_free( parent );
                                   if ( is_ref ) {
                                          rc = LDAP_AFFECTS_MULTIPLE_DSAS;
                                          *text = op->o_tag == LDAP_REQ_MODDN
                                                 ? "newSuperior is a referral object"
                                                 : "parent is a referral object";
                                          break;
                                   }
                            }
                            /* Must create parent directory. */
                            ldif2dir_name( ppath );
                            *need_dir = ppath.bv_val;
                            break;
                     case LDAP_NO_SUCH_OBJECT:
                            *text = op->o_tag == LDAP_REQ_MODDN
                                   ? "newSuperior object does not exist"
                                   : "parent does not exist";
                            break;
                     }
                     break;
              case LDAP_OTHER:
                     Debug( LDAP_DEBUG_ANY,
                            "ldif_prepare_create: cannot stat \"%s\" parent dir: %s\n",
                            ndn->bv_val, STRERROR( errno ), 0 );
                     *text = "internal error (cannot stat parent dir)";
                     break;
              }
              if ( *need_dir == NULL && ppath.bv_val != NULL )
                     SLAP_FREE( ppath.bv_val );
       }

       if ( rc != LDAP_SUCCESS ) {
              SLAP_FREE( dnpath->bv_val );
              BER_BVZERO( dnpath );
       }
       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ldif_read_entry ( Operation op,
const char *  path,
struct berval pdn,
struct berval pndn,
Entry **  entryp,
const char **  text 
) [static]

Definition at line 631 of file ldif.c.

{
       int rc;
       Entry *entry;
       char *entry_as_string;
       struct berval rdn;

       /* TODO: Does slapd prevent Abandon of Bind as per rfc4511?
        * If so we need not check for LDAP_REQ_BIND here.
        */
       if ( op->o_abandon && op->o_tag != LDAP_REQ_BIND )
              return SLAPD_ABANDON;

       rc = ldif_read_file( path, entryp ? &entry_as_string : NULL );

       switch ( rc ) {
       case LDAP_SUCCESS:
              if ( entryp == NULL )
                     break;
              *entryp = entry = str2entry( entry_as_string );
              SLAP_FREE( entry_as_string );
              if ( entry == NULL ) {
                     rc = LDAP_OTHER;
                     if ( text != NULL )
                            *text = "internal error (cannot parse some entry file)";
                     break;
              }
              if ( pdn == NULL || BER_BVISEMPTY( pdn ) )
                     break;
              /* Append parent DN to DN from LDIF file */
              rdn = entry->e_name;
              build_new_dn( &entry->e_name, pdn, &rdn, NULL );
              SLAP_FREE( rdn.bv_val );
              rdn = entry->e_nname;
              build_new_dn( &entry->e_nname, pndn, &rdn, NULL );
              SLAP_FREE( rdn.bv_val );
              break;

       case LDAP_OTHER:
              if ( text != NULL )
                     *text = entryp
                            ? "internal error (cannot read some entry file)"
                            : "internal error (cannot stat some entry file)";
              break;
       }

       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ldif_read_file ( const char *  path,
char **  datap 
) [static]

Definition at line 417 of file ldif.c.

{
       int rc = LDAP_SUCCESS, fd, len;
       int res = -1; /* 0:success, <0:error, >0:file too big/growing. */
       struct stat st;
       char *data = NULL, *ptr = NULL;
       const char *msg;

       if ( datap == NULL ) {
              res = stat( path, &st );
              goto done;
       }
       fd = open( path, O_RDONLY );
       if ( fd >= 0 ) {
              if ( fstat( fd, &st ) == 0 ) {
                     if ( st.st_size > INT_MAX - 2 ) {
                            res = 1;
                     } else {
                            len = st.st_size + 1; /* +1 detects file size > st.st_size */
                            *datap = data = ptr = SLAP_MALLOC( len + 1 );
                            if ( ptr != NULL ) {
                                   while ( len && (res = read( fd, ptr, len )) ) {
                                          if ( res > 0 ) {
                                                 len -= res;
                                                 ptr += res;
                                          } else if ( errno != EINTR ) {
                                                 break;
                                          }
                                   }
                                   *ptr = '\0';
                            }
                     }
              }
              if ( close( fd ) < 0 )
                     res = -1;
       }

 done:
       if ( res == 0 ) {
#ifdef LDAP_DEBUG
              msg = "entry file exists";
              if ( datap ) {
                     msg = "read entry file";
                     len = ptr - data;
                     ptr = strstr( data, "\n# CRC32" );
                     if (!ptr) {
                            msg = "read entry file without checksum";
                     } else {
                            unsigned int crc1 = 0, crc2 = 1;
                            if ( sscanf( ptr + 9, "%08x", &crc1) == 1) {
                                   ptr = strchr(ptr+1, '\n');
                                   if ( ptr ) {
                                          ptr++;
                                          len -= (ptr - data);
                                          crc2 = crc32( ptr, len );
                                   }
                            }
                            if ( crc1 != crc2 ) {
                                   Debug( LDAP_DEBUG_ANY, "ldif_read_file: checksum error on \"%s\"\n",
                                          path, 0, 0 );
                                   return rc;
                            }
                     }
              }
              Debug( LDAP_DEBUG_TRACE, "ldif_read_file: %s: \"%s\"\n", msg, path, 0 );
#endif /* LDAP_DEBUG */
       } else {
              if ( res < 0 && errno == ENOENT ) {
                     Debug( LDAP_DEBUG_TRACE, "ldif_read_file: "
                            "no entry file \"%s\"\n", path, 0, 0 );
                     rc = LDAP_NO_SUCH_OBJECT;
              } else {
                     msg = res < 0 ? STRERROR( errno ) : "bad stat() size";
                     Debug( LDAP_DEBUG_ANY, "ldif_read_file: %s for \"%s\"\n",
                            msg, path, 0 );
                     rc = LDAP_OTHER;
              }
              if ( data != NULL )
                     SLAP_FREE( data );
       }
       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ldif_readdir ( Operation op,
SlapReply rs,
const struct berval path,
bvlist **  listp,
ber_len_t fname_maxlenp 
) [static]

Definition at line 801 of file ldif.c.

{
       int rc = LDAP_SUCCESS;
       DIR *dir_of_path;

       *listp = NULL;
       *fname_maxlenp = 0;

       dir_of_path = opendir( path->bv_val );
       if ( dir_of_path == NULL ) {
              int save_errno = errno;
              struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
              int is_rootDSE = (path->bv_len == li->li_base_path.bv_len);

              /* Absent directory is OK (leaf entry), except the database dir */
              if ( is_rootDSE || save_errno != ENOENT ) {
                     Debug( LDAP_DEBUG_ANY,
                            "=> ldif_search_entry: failed to opendir \"%s\": %s\n",
                            path->bv_val, STRERROR( save_errno ), 0 );
                     rc = LDAP_OTHER;
                     if ( rs != NULL )
                            rs->sr_text =
                                   save_errno != ENOENT ? "internal error (bad directory)"
                                   : !is_rootDSE ? "internal error (missing directory)"
                                   : "internal error (database directory does not exist)";
              }

       } else {
              bvlist *ptr;
              struct dirent *dir;
              int save_errno = 0;

              while ( (dir = readdir( dir_of_path )) != NULL ) {
                     size_t fname_len;
                     bvlist *bvl, **prev;
                     char *trunc, *idxp, *endp, *endp2;

                     fname_len = strlen( dir->d_name );
                     if ( fname_len < STRLENOF( "x=" LDIF )) /* min filename size */
                            continue;
                     if ( strcmp( dir->d_name + fname_len - STRLENOF(LDIF), LDIF ))
                            continue;

                     if ( *fname_maxlenp < fname_len )
                            *fname_maxlenp = fname_len;

                     bvl = SLAP_MALLOC( BVL_SIZE( fname_len ) );
                     if ( bvl == NULL ) {
                            rc = LDAP_OTHER;
                            save_errno = errno;
                            break;
                     }
                     strcpy( BVL_NAME( bvl ), dir->d_name );

                     /* Make it sortable by ("attr=val" or <preceding {num}, num>) */
                     trunc = BVL_NAME( bvl ) + fname_len - STRLENOF( LDIF );
                     if ( (idxp = strchr( BVL_NAME( bvl ) + 2, IX_FSL )) != NULL &&
                             (endp = strchr( ++idxp, IX_FSR )) != NULL && endp > idxp &&
                             (eq_unsafe || idxp[-2] == '=' || endp + 1 == trunc) )
                     {
                            /* attr={n}val or bconfig.c's "pseudo-indexed" attr=val{n} */
                            bvl->inum = strtol( idxp, &endp2, 10 );
                            if ( endp2 == endp ) {
                                   trunc = idxp;
                                   goto truncate;
                            }
                     }
                     bvl->inum = INT_MIN;
              truncate:
                     bvl->trunc = trunc;
                     bvl->savech = *trunc;
                     *trunc = '\0';

                     /* Insertion sort */
                     for ( prev = listp; (ptr = *prev) != NULL; prev = &ptr->next ) {
                            int cmp = strcmp( BVL_NAME( bvl ), BVL_NAME( ptr ));
                            if ( cmp < 0 || (cmp == 0 && bvl->inum < ptr->inum) )
                                   break;
                     }
                     *prev = bvl;
                     bvl->next = ptr;
              }

              if ( closedir( dir_of_path ) < 0 ) {
                     save_errno = errno;
                     rc = LDAP_OTHER;
                     if ( rs != NULL )
                            rs->sr_text = "internal error (bad directory)";
              }
              if ( rc != LDAP_SUCCESS ) {
                     Debug( LDAP_DEBUG_ANY, "ldif_search_entry: %s \"%s\": %s\n",
                            "error reading directory", path->bv_val,
                            STRERROR( save_errno ) );
              }
       }

       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ldif_search_entry ( Operation op,
SlapReply rs,
Entry e,
int  scope,
struct berval path 
) [static]

Definition at line 914 of file ldif.c.

{
       int rc = LDAP_SUCCESS;
       struct berval dn = BER_BVC( "" ), ndn = BER_BVC( "" );

       if ( scope != LDAP_SCOPE_BASE && e != NULL ) {
              /* Copy DN/NDN since we send the entry with REP_ENTRY_MODIFIABLE,
               * which bconfig.c seems to need.  (TODO: see config_rename_one.)
               */
              if ( ber_dupbv( &dn,  &e->e_name  ) == NULL ||
                      ber_dupbv( &ndn, &e->e_nname ) == NULL )
              {
                     Debug( LDAP_DEBUG_ANY,
                            "ldif_search_entry: out of memory\n", 0, 0, 0 );
                     rc = LDAP_OTHER;
                     goto done;
              }
       }

       /* Send the entry if appropriate, and free or save it */
       if ( e != NULL )
              rc = ldif_send_entry( op, rs, e, scope );

       /* Search the children */
       if ( scope != LDAP_SCOPE_BASE && rc == LDAP_SUCCESS ) {
              bvlist *list, *ptr;
              struct berval fpath; /* becomes child pathname */
              char *dir_end;       /* will point past dirname in fpath */

              ldif2dir_len( *path );
              ldif2dir_name( *path );
              rc = ldif_readdir( op, rs, path, &list, &fpath.bv_len );

              if ( list != NULL ) {
                     const char **text = rs == NULL ? NULL : &rs->sr_text;

                     if ( scope == LDAP_SCOPE_ONELEVEL )
                            scope = LDAP_SCOPE_BASE;
                     else if ( scope == LDAP_SCOPE_SUBORDINATE )
                            scope = LDAP_SCOPE_SUBTREE;

                     /* Allocate fpath and fill in directory part */
                     dir_end = fullpath_alloc( &fpath, path, fpath.bv_len );
                     if ( dir_end == NULL )
                            rc = LDAP_OTHER;

                     do {
                            ptr = list;

                            if ( rc == LDAP_SUCCESS ) {
                                   *ptr->trunc = ptr->savech;
                                   FILL_PATH( &fpath, dir_end, BVL_NAME( ptr ));

                                   rc = ldif_read_entry( op, fpath.bv_val, &dn, &ndn,
                                          &e, text );
                                   switch ( rc ) {
                                   case LDAP_SUCCESS:
                                          rc = ldif_search_entry( op, rs, e, scope, &fpath );
                                          break;
                                   case LDAP_NO_SUCH_OBJECT:
                                          /* Only the search baseDN may produce noSuchObject. */
                                          rc = LDAP_OTHER;
                                          if ( rs != NULL )
                                                 rs->sr_text = "internal error "
                                                        "(did someone just remove an entry file?)";
                                          Debug( LDAP_DEBUG_ANY, "ldif_search_entry: "
                                                 "file listed in parent directory does not exist: "
                                                 "\"%s\"\n", fpath.bv_val, 0, 0 );
                                          break;
                                   }
                            }

                            list = ptr->next;
                            SLAP_FREE( ptr );
                     } while ( list != NULL );

                     if ( !BER_BVISNULL( &fpath ) )
                            SLAP_FREE( fpath.bv_val );
              }
       }

 done:
       if ( !BER_BVISEMPTY( &dn ) )
              ber_memfree( dn.bv_val );
       if ( !BER_BVISEMPTY( &ndn ) )
              ber_memfree( ndn.bv_val );
       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ldif_send_entry ( Operation op,
SlapReply rs,
Entry e,
int  scope 
) [static]

Definition at line 737 of file ldif.c.

{
       int rc = LDAP_SUCCESS;

       if ( scope == LDAP_SCOPE_BASE || scope == LDAP_SCOPE_SUBTREE ) {
              if ( rs == NULL ) {
                     /* Save the entry for tool mode */
                     struct ldif_tool *tl =
                            &((struct ldif_info *) op->o_bd->be_private)->li_tool;

                     if ( tl->ecount >= tl->elen ) {
                            /* Allocate/grow entries */
                            ID elen = tl->elen ? tl->elen * 2 : ENTRY_BUFF_INCREMENT;
                            Entry **entries = (Entry **) SLAP_REALLOC( tl->entries,
                                   sizeof(Entry *) * elen );
                            if ( entries == NULL ) {
                                   Debug( LDAP_DEBUG_ANY,
                                          "ldif_send_entry: out of memory\n", 0, 0, 0 );
                                   rc = LDAP_OTHER;
                                   goto done;
                            }
                            tl->elen = elen;
                            tl->entries = entries;
                     }
                     tl->entries[tl->ecount++] = e;
                     return rc;
              }

              else if ( !get_manageDSAit( op ) && is_entry_referral( e ) ) {
                     /* Send a continuation reference.
                      * (ldif_back_referrals() handles baseobject referrals.)
                      * Don't check the filter since it's only a candidate.
                      */
                     BerVarray refs = get_entry_referrals( op, e );
                     rs->sr_ref = referral_rewrite( refs, &e->e_name, NULL, scope );
                     rs->sr_entry = e;
                     rc = send_search_reference( op, rs );
                     ber_bvarray_free( rs->sr_ref );
                     ber_bvarray_free( refs );
                     rs->sr_ref = NULL;
                     rs->sr_entry = NULL;
              }

              else if ( test_filter( op, e, op->ors_filter ) == LDAP_COMPARE_TRUE ) {
                     rs->sr_entry = e;
                     rs->sr_attrs = op->ors_attrs;
                     /* Could set REP_ENTRY_MUSTBEFREED too for efficiency,
                      * but refraining lets us test unFREEable MODIFIABLE
                      * entries.  Like entries built on the stack.
                      */
                     rs->sr_flags = REP_ENTRY_MODIFIABLE;
                     rc = send_search_entry( op, rs );
                     rs->sr_entry = NULL;
                     rs->sr_attrs = NULL;
              }
       }

 done:
       entry_free( e );
       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* ldif_tempname ( const struct berval dnpath) [static]

Definition at line 317 of file ldif.c.

{
       static const char suffix[] = ".XXXXXX";
       ber_len_t len = dnpath->bv_len - STRLENOF( LDIF );
       char *name = SLAP_MALLOC( len + sizeof( suffix ) );

       if ( name != NULL ) {
              AC_MEMCPY( name, dnpath->bv_val, len );
              strcpy( name + len, suffix );
       }
       return name;
}

Here is the caller graph for this function:

static int ldif_tool_entry_close ( BackendDB be) [static]

Definition at line 1722 of file ldif.c.

{
       struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;
       Entry **entries = tl->entries;
       ID i;

       for ( i = tl->ecount; i--; )
              if ( entries[i] )
                     entry_free( entries[i] );
       SLAP_FREE( entries );
       tl->entries = NULL;
       tl->ecount = tl->elen = 0;
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static ID ldif_tool_entry_first_x ( BackendDB be,
struct berval base,
int  scope,
Filter f 
) [static]

Definition at line 1766 of file ldif.c.

{
       struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;

       tl->tl_base = base;
       tl->tl_scope = scope;
       tl->tl_filter = f;

       if ( tl->entries == NULL ) {
              Operation op = {0};

              op.o_bd = be;
              op.o_req_dn = *be->be_suffix;
              op.o_req_ndn = *be->be_nsuffix;
              op.ors_scope = LDAP_SCOPE_SUBTREE;
              if ( search_tree( &op, NULL ) != LDAP_SUCCESS ) {
                     tl->ecurrent = tl->ecount; /* fail ldif_tool_entry_next() */
                     return 0; /* fail ldif_tool_entry_get() */
              }
       }
       return ldif_tool_entry_next( be );
}

Here is the call graph for this function:

Here is the caller graph for this function:

static Entry* ldif_tool_entry_get ( BackendDB be,
ID  id 
) [static]

Definition at line 1790 of file ldif.c.

{
       struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;
       Entry *e = NULL;

       --id;
       if ( id < tl->ecount ) {
              e = tl->entries[id];
              tl->entries[id] = NULL;
       }
       return e;
}

Here is the caller graph for this function:

static ID ldif_tool_entry_next ( BackendDB be) [static]

Definition at line 1738 of file ldif.c.

{
       struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;

       do {
              Entry *e = tl->entries[ tl->ecurrent ];

              if ( tl->ecurrent >= tl->ecount ) {
                     return NOID;
              }

              ++tl->ecurrent;

              if ( tl->tl_base && !dnIsSuffixScope( &e->e_nname, tl->tl_base, tl->tl_scope ) ) {
                     continue;
              }

              if ( tl->tl_filter && test_filter( NULL, e, tl->tl_filter  ) != LDAP_COMPARE_TRUE ) {
                     continue;
              }

              break;
       } while ( 1 );

       return tl->ecurrent;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ldif_tool_entry_open ( BackendDB be,
int  mode 
) [static]

Definition at line 1713 of file ldif.c.

{
       struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;

       tl->ecurrent = 0;
       return 0;
}

Here is the caller graph for this function:

static ID ldif_tool_entry_put ( BackendDB be,
Entry e,
struct berval text 
) [static]

Definition at line 1804 of file ldif.c.

{
       int rc;
       const char *errmsg = NULL;
       struct berval path;
       char *parentdir;
       Operation op = {0};

       op.o_bd = be;
       rc = ldif_prepare_create( &op, e, &path, &parentdir, &errmsg );
       if ( rc == LDAP_SUCCESS ) {
              rc = ldif_write_entry( &op, e, &path, parentdir, &errmsg );

              SLAP_FREE( path.bv_val );
              if ( parentdir != NULL )
                     SLAP_FREE( parentdir );
              if ( rc == LDAP_SUCCESS )
                     return 1;
       }

       if ( errmsg == NULL && rc != LDAP_OTHER )
              errmsg = ldap_err2string( rc );
       if ( errmsg != NULL )
              snprintf( text->bv_val, text->bv_len, "%s", errmsg );
       return NOID;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ldif_write_entry ( Operation op,
Entry e,
const struct berval path,
const char *  parentdir,
const char **  text 
) [static]

Definition at line 537 of file ldif.c.

{
       int rc = LDAP_OTHER, res, save_errno = 0;
       int fd, entry_length;
       char *entry_as_string, *tmpfname;

       if ( op->o_abandon )
              return SLAPD_ABANDON;

       if ( parentdir != NULL && mkdir( parentdir, 0750 ) < 0 ) {
              save_errno = errno;
              Debug( LDAP_DEBUG_ANY, "ldif_write_entry: %s \"%s\": %s\n",
                     "cannot create parent directory",
                     parentdir, STRERROR( save_errno ) );
              *text = "internal error (cannot create parent directory)";
              return rc;
       }

       tmpfname = ldif_tempname( path );
       fd = tmpfname == NULL ? -1 : mkstemp( tmpfname );
       if ( fd < 0 ) {
              save_errno = errno;
              Debug( LDAP_DEBUG_ANY, "ldif_write_entry: %s for \"%s\": %s\n",
                     "cannot create file", e->e_dn, STRERROR( save_errno ) );
              *text = "internal error (cannot create file)";

       } else {
              ber_len_t dn_len = e->e_name.bv_len;
              struct berval rdn;

              /* Only save the RDN onto disk */
              dnRdn( &e->e_name, &rdn );
              if ( rdn.bv_len != dn_len ) {
                     e->e_name.bv_val[rdn.bv_len] = '\0';
                     e->e_name.bv_len = rdn.bv_len;
              }

              res = -2;
              ldap_pvt_thread_mutex_lock( &entry2str_mutex );
              entry_as_string = entry2str( e, &entry_length );
              if ( entry_as_string != NULL )
                     res = spew_file( fd, entry_as_string, entry_length, &save_errno );
              ldap_pvt_thread_mutex_unlock( &entry2str_mutex );

              /* Restore full DN */
              if ( rdn.bv_len != dn_len ) {
                     e->e_name.bv_val[rdn.bv_len] = ',';
                     e->e_name.bv_len = dn_len;
              }

              if ( close( fd ) < 0 && res >= 0 ) {
                     res = -1;
                     save_errno = errno;
              }

              if ( res >= 0 ) {
                     if ( move_file( tmpfname, path->bv_val ) == 0 ) {
                            Debug( LDAP_DEBUG_TRACE, "ldif_write_entry: "
                                   "wrote entry \"%s\"\n", e->e_name.bv_val, 0, 0 );
                            rc = LDAP_SUCCESS;
                     } else {
                            save_errno = errno;
                            Debug( LDAP_DEBUG_ANY, "ldif_write_entry: "
                                   "could not put entry file for \"%s\" in place: %s\n",
                                   e->e_name.bv_val, STRERROR( save_errno ), 0 );
                            *text = "internal error (could not put entry file in place)";
                     }
              } else if ( res == -1 ) {
                     Debug( LDAP_DEBUG_ANY, "ldif_write_entry: %s \"%s\": %s\n",
                            "write error to", tmpfname, STRERROR( save_errno ) );
                     *text = "internal error (write error to entry file)";
              }

              if ( rc != LDAP_SUCCESS ) {
                     unlink( tmpfname );
              }
       }

       if ( tmpfname )
              SLAP_FREE( tmpfname );
       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ndn2path ( Operation op,
struct berval dn,
struct berval res,
int  empty_ok 
) [static]

Definition at line 193 of file ldif.c.

{
       BackendDB *be = op->o_bd;
       struct ldif_info *li = (struct ldif_info *) be->be_private;
       struct berval *suffixdn = &be->be_nsuffix[0];
       const char *start, *end, *next, *p;
       char ch, *ptr;
       ber_len_t len;
       static const char hex[] = "0123456789ABCDEF";

       assert( dn != NULL );
       assert( !BER_BVISNULL( dn ) );
       assert( suffixdn != NULL );
       assert( !BER_BVISNULL( suffixdn ) );
       assert( dnIsSuffix( dn, suffixdn ) );

       if ( dn->bv_len == 0 && !empty_ok ) {
              return LDAP_UNWILLING_TO_PERFORM;
       }

       start = dn->bv_val;
       end = start + dn->bv_len;

       /* Room for dir, dirsep, dn, LDIF, "\hexpair"-escaping of unsafe chars */
       len = li->li_base_path.bv_len + dn->bv_len + (1 + STRLENOF( LDIF ));
       for ( p = start; p < end; ) {
              ch = *p++;
              if ( LDIF_NEED_ESCAPE( ch ) )
                     len += 2;
       }
       res->bv_val = ch_malloc( len + 1 );

       ptr = lutil_strcopy( res->bv_val, li->li_base_path.bv_val );
       for ( next = end - suffixdn->bv_len; end > start; end = next ) {
              /* Set p = start of DN component, next = &',' or start of DN */
              while ( (p = next) > start ) {
                     --next;
                     if ( DN_SEPARATOR( *next ) )
                            break;
              }
              /* Append <dirsep> <p..end-1: RDN or database-suffix> */
              for ( *ptr++ = LDAP_DIRSEP[0]; p < end; *ptr++ = ch ) {
                     ch = *p++;
                     if ( LDIF_ESCAPE_CHAR != '\\' && ch == '\\' ) {
                            ch = LDIF_ESCAPE_CHAR;
                     } else if ( IX_FSL != IX_DNL && ch == IX_DNL ) {
                            ch = IX_FSL;
                     } else if ( IX_FSR != IX_DNR && ch == IX_DNR ) {
                            ch = IX_FSR;
                     } else if ( LDIF_NEED_ESCAPE( ch ) ) {
                            *ptr++ = LDIF_ESCAPE_CHAR;
                            *ptr++ = hex[(ch & 0xFFU) >> 4];
                            ch = hex[ch & 0x0FU];
                     }
              }
       }
       ptr = lutil_strcopy( ptr, LDIF );
       res->bv_len = ptr - res->bv_val;

       assert( res->bv_len <= len );

       return LDAP_SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int search_tree ( Operation op,
SlapReply rs 
) [static]

Definition at line 1009 of file ldif.c.

{
       int rc = LDAP_SUCCESS;
       Entry *e = NULL;
       struct berval path;
       struct berval pdn, pndn;

       (void) ndn2path( op, &op->o_req_ndn, &path, 1 );
       if ( !BER_BVISEMPTY( &op->o_req_ndn ) ) {
              /* Read baseObject */
              dnParent( &op->o_req_dn, &pdn );
              dnParent( &op->o_req_ndn, &pndn );
              rc = ldif_read_entry( op, path.bv_val, &pdn, &pndn, &e,
                     rs == NULL ? NULL : &rs->sr_text );
       }
       if ( rc == LDAP_SUCCESS )
              rc = ldif_search_entry( op, rs, e, op->ors_scope, &path );

       ch_free( path.bv_val );
       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int spew_file ( int  fd,
const char *  spew,
int  len,
int save_errno 
) [static]

Definition at line 505 of file ldif.c.

{
       int writeres;
#define HEADER       "# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.\n"
       char header[sizeof(HEADER "# CRC32 12345678\n")];

       sprintf(header, HEADER "# CRC32 %08x\n", crc32(spew, len));
       writeres = write_data(fd, header, sizeof(header)-1, save_errno);
       return writeres < 0 ? writeres : write_data(fd, spew, len, save_errno);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int write_data ( int  fd,
const char *  spew,
int  len,
int save_errno 
) [static]

Definition at line 517 of file ldif.c.

{
       int writeres = 0;
       while(len > 0) {
              writeres = write(fd, spew, len);
              if(writeres == -1) {
                     *save_errno = errno;
                     if (*save_errno != EINTR)
                            break;
              }
              else {
                     spew += writeres;
                     len -= writeres;
              }
       }
       return writeres;
}

Here is the caller graph for this function:


Variable Documentation

const ber_uint_t crctab[256] [static]

Definition at line 336 of file ldif.c.

ConfigTable ldifcfg[] [static]
Initial value:
 {
       { "directory", "dir", 2, 2, 0, ARG_BERVAL|ARG_OFFSET,
              (void *)offsetof(struct ldif_info, li_base_path),
              "( OLcfgDbAt:0.1 NAME 'olcDbDirectory' "
                     "DESC 'Directory for database content' "
                     "EQUALITY caseIgnoreMatch "
                     "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
       { NULL, NULL, 0, 0, 0, ARG_IGNORED,
              NULL, NULL, NULL, NULL }
}

Definition at line 166 of file ldif.c.

ConfigOCs ldifocs[] [static]
Initial value:
 {
       { "( OLcfgDbOc:2.1 "
              "NAME 'olcLdifConfig' "
              "DESC 'LDIF backend configuration' "
              "SUP olcDatabaseConfig "
              "MUST ( olcDbDirectory ) )", Cft_Database, ldifcfg },
       { NULL, 0, NULL }
}

Definition at line 177 of file ldif.c.