From 69a6d8ca2ffc32b364cc857f59541e843026f6a0 Mon Sep 17 00:00:00 2001
From: Hallvard Furuseth <hallvard@openldap.org>
Date: Tue, 11 Nov 2008 22:53:41 +0000
Subject: [PATCH] ITS#5408 part 1 - error handling, debug output, add error
 texts (rs->sr_text). - Reset rs->sr_text on success in
 apply_modify_to_entry(), not in its callers. - Fix error test from
 ldif_write_entry() in ldif_move_entry(). - Start changing
 LDAP_UNWILLING_TO_PERFORM -> LDAP_OTHER for internal errors. - Pass around
 LDAP result codes instead of errno. - Rename spew_entry() ->
 ldif_write_entry(), move entry2str_mutex lock into it. - Some other
 preparation for upcoming changes.

---
 servers/slapd/back-ldif/ldif.c | 128 ++++++++++++++++-----------------
 1 file changed, 61 insertions(+), 67 deletions(-)

diff --git a/servers/slapd/back-ldif/ldif.c b/servers/slapd/back-ldif/ldif.c
index 3acb687fd2..e5c133855e 100644
--- a/servers/slapd/back-ldif/ldif.c
+++ b/servers/slapd/back-ldif/ldif.c
@@ -267,7 +267,11 @@ static int spew_file(int fd, char * spew, int len) {
 }
 
 static int
-spew_entry( Entry * e, struct berval * path, int dolock, int *save_errnop )
+ldif_write_entry(
+	Operation *op,
+	Entry *e,
+	const struct berval *path,
+	const char **text )
 {
 	int rs, save_errno = 0;
 	int openres;
@@ -301,10 +305,7 @@ spew_entry( Entry * e, struct berval * path, int dolock, int *save_errnop )
 		}
 
 		spew_res = -2;
-		if ( dolock ) {
-			ldap_pvt_thread_mutex_lock(&entry2str_mutex);
-		}
-
+		ldap_pvt_thread_mutex_lock( &entry2str_mutex );
 		entry_as_string = entry2str(e, &entry_length);
 		if ( entry_as_string != NULL ) {
 			spew_res = spew_file( openres,
@@ -313,10 +314,7 @@ spew_entry( Entry * e, struct berval * path, int dolock, int *save_errnop )
 				save_errno = errno;
 			}
 		}
-
-		if ( dolock ) {
-			ldap_pvt_thread_mutex_unlock(&entry2str_mutex);
-		}
+		ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
 
 		/* Restore full DN */
 		if ( rdn.bv_len != e->e_name.bv_len ) {
@@ -367,10 +365,6 @@ spew_entry( Entry * e, struct berval * path, int dolock, int *save_errnop )
 
 	ch_free( tmpfname );
 
-	if ( rs != LDAP_SUCCESS && save_errnop != NULL ) {
-		*save_errnop = save_errno;
-	}
-
 	return rs;
 }
 
@@ -412,7 +406,8 @@ static int
 get_entry(
 	Operation *op,
 	Entry **entryp,
-	struct berval *pathp )
+	struct berval *pathp,
+	const char **text )
 {
 	int rc;
 	struct berval path, pdn, pndn;
@@ -732,7 +727,8 @@ static int apply_modify_to_entry(Entry * entry,
 		if(rc != LDAP_SUCCESS) break;
 	}
 
-	if(rc == LDAP_SUCCESS) {
+	if ( rc == LDAP_SUCCESS ) {
+		rs->sr_text = NULL; /* Needed at least with SLAP_MOD_SOFTADD */
 		if ( is_oc ) {
 			entry->e_ocflags = 0;
 		}
@@ -748,7 +744,7 @@ int
 ldif_back_referrals( Operation *op, SlapReply *rs )
 {
 	struct ldif_info	*li = NULL;
-	Entry			*entry;
+	Entry			*entry = NULL;
 	int			rc = LDAP_SUCCESS;
 
 #if 0
@@ -770,7 +766,7 @@ ldif_back_referrals( Operation *op, SlapReply *rs )
 
 	li = (struct ldif_info *)op->o_bd->be_private;
 	ldap_pvt_thread_rdwr_rlock( &li->li_rdwr );
-	get_entry( op, &entry, NULL );
+	get_entry( op, &entry, NULL, &rs->sr_text );
 
 	/* no object is found for them */
 	if ( entry == NULL ) {
@@ -791,7 +787,7 @@ ldif_back_referrals( Operation *op, SlapReply *rs )
 			op->o_req_dn = pndn;
 			op->o_req_ndn = pndn;
 
-			get_entry( op, &entry, NULL );
+			get_entry( op, &entry, NULL, &rs->sr_text );
 		}
 
 		ldap_pvt_thread_rdwr_runlock( &li->li_rdwr );
@@ -885,7 +881,7 @@ ldif_back_bind( Operation *op, SlapReply *rs )
 	Attribute *a;
 	AttributeDescription *password = slap_schema.si_ad_userPassword;
 	int return_val;
-	Entry *entry;
+	Entry *entry = NULL;
 
 	switch ( be_rootdn_bind( op, rs ) ) {
 	case SLAP_CB_CONTINUE:
@@ -899,7 +895,7 @@ ldif_back_bind( Operation *op, SlapReply *rs )
 
 	li = (struct ldif_info *) op->o_bd->be_private;
 	ldap_pvt_thread_rdwr_rlock(&li->li_rdwr);
-	return_val = get_entry(op, &entry, NULL);
+	return_val = get_entry(op, &entry, NULL, NULL);
 
 	/* no object is found for them */
 	if(return_val != LDAP_SUCCESS) {
@@ -1002,7 +998,7 @@ static int ldif_back_add(Operation *op, SlapReply *rs) {
 		if(rs->sr_err == LDAP_SUCCESS) {
 			statres = stat(leaf_path.bv_val, &stats);
 			if(statres == -1 && errno == ENOENT) {
-				rs->sr_err = spew_entry(e, &leaf_path, 1, NULL);
+				rs->sr_err = ldif_write_entry( op, e, &leaf_path, &rs->sr_text );
 			}
 			else if ( statres == -1 ) {
 				rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
@@ -1032,40 +1028,37 @@ static int ldif_back_modify(Operation *op, SlapReply *rs) {
 	Modifications * modlst = op->orm_modlist;
 	struct berval path;
 	Entry *entry;
-	int spew_res;
+	int rc;
 
 	slap_mods_opattrs( op, &op->orm_modlist, 1 );
 
 	ldap_pvt_thread_rdwr_wlock(&li->li_rdwr);
 
-	rs->sr_err = get_entry( op, &entry, &path );
-	if(entry != NULL) {
-		rs->sr_err = apply_modify_to_entry(entry, modlst, op, rs);
-		if(rs->sr_err == LDAP_SUCCESS) {
-			int save_errno;
-			spew_res = spew_entry(entry, &path, 1, &save_errno);
-			if(spew_res == -1) {
-				Debug( LDAP_DEBUG_ANY,
-					"%s ldif_back_modify: could not output entry \"%s\": %s\n",
-					op->o_log_prefix, entry->e_name.bv_val, STRERROR( save_errno ) );
-				rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
-			}
+	rc = get_entry( op, &entry, &path, &rs->sr_text );
+	if ( rc == LDAP_SUCCESS ) {
+		rc = apply_modify_to_entry( entry, modlst, op, rs );
+		if ( rc == LDAP_SUCCESS ) {
+			rc = ldif_write_entry( op, entry, &path, &rs->sr_text );
 		}
 
 		entry_free( entry );
 		SLAP_FREE( path.bv_val );
 	}
 
-	rs->sr_text = NULL;
 	ldap_pvt_thread_rdwr_wunlock(&li->li_rdwr);
-	send_ldap_result(op, rs);
+
+	rs->sr_err = rc;
+	send_ldap_result( op, rs );
 	slap_graduate_commit_csn( op );
 	return rs->sr_err;
 }
 
-static int ldif_back_delete(Operation *op, SlapReply *rs) {
+static int
+ldif_back_delete( Operation *op, SlapReply *rs )
+{
 	struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private;
 	struct berval path;
+	int rc = LDAP_SUCCESS;
 	int res = 0;
 
 	if ( BER_BVISEMPTY( &op->o_csn )) {
@@ -1083,42 +1076,36 @@ static int ldif_back_delete(Operation *op, SlapReply *rs) {
 	path.bv_val[path.bv_len - STRLENOF(LDIF)] = '\0';
 	res = rmdir(path.bv_val);
 	path.bv_val[path.bv_len - STRLENOF(LDIF)] = LDIF_FILETYPE_SEP;
-	rs->sr_err = LDAP_SUCCESS;
 	if ( res ) {
 		switch ( errno ) {
 		case ENOTEMPTY:
-			rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
+			rc = LDAP_NOT_ALLOWED_ON_NONLEAF;
 			break;
-
 		case ENOENT:
 			/* is leaf, go on */
-			res = 0;
 			break;
-
 		default:
-			rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+			rc = LDAP_OTHER;
+			rs->sr_text = "internal error (cannot delete subtree directory)";
 			break;
 		}
 	}
 
-	if ( !res ) {
+	if ( rc == LDAP_SUCCESS ) {
 		res = unlink(path.bv_val);
 		if ( res == -1 ) {
-			switch ( errno ) {
-			case ENOENT:
-				rs->sr_err = LDAP_NO_SUCH_OBJECT;
-				break;
-
-			default:
-				rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
-				break;
+			rc = LDAP_NO_SUCH_OBJECT;
+			if ( errno != ENOENT ) {
+				rc = LDAP_OTHER;
+				rs->sr_text = "internal error (cannot delete entry file)";
 			}
 		}
 	}
 
 	SLAP_FREE(path.bv_val);
 	ldap_pvt_thread_rdwr_wunlock(&li->li_rdwr);
-	send_ldap_result(op, rs);
+	rs->sr_err = rc;
+	send_ldap_result( op, rs );
 	slap_graduate_commit_csn( op );
 	return rs->sr_err;
 }
@@ -1128,7 +1115,8 @@ static int
 ldif_move_entry(
 	Operation *op,
 	Entry *entry,
-	struct berval *oldpath )
+	struct berval *oldpath,
+	const char **text )
 {
 	int res;
 	int exists_res;
@@ -1143,9 +1131,8 @@ ldif_move_entry(
 	else { /* do the modrdn */
 		exists_res = open(newpath.bv_val, O_RDONLY);
 		if(exists_res == -1 && errno == ENOENT) {
-			ldap_pvt_thread_mutex_lock( &entry2str_mutex );
-			res = spew_entry(entry, &newpath, 0, NULL);
-			if(res != -1) {
+			res = ldif_write_entry( op, entry, &newpath, text );
+			if ( res == LDAP_SUCCESS ) {
 				/* if this fails we should log something bad */
 				res = unlink( oldpath->bv_val );
 				oldpath->bv_val[oldpath->bv_len - STRLENOF(".ldif")] = '\0';
@@ -1160,7 +1147,6 @@ ldif_move_entry(
 					res = LDAP_UNWILLING_TO_PERFORM;
 				unlink(newpath.bv_val); /* in case file was created */
 			}
-			ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
 		}
 		else if(exists_res) {
 			int close_res = close(exists_res);
@@ -1192,7 +1178,7 @@ ldif_back_modrdn(Operation *op, SlapReply *rs)
 
 	ldap_pvt_thread_rdwr_wlock( &li->li_rdwr );
 
-	rc = get_entry( op, &entry, &old_path );
+	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 ) {
@@ -1204,7 +1190,7 @@ ldif_back_modrdn(Operation *op, SlapReply *rs)
 			p_dn = *op->oq_modrdn.rs_newSup;
 			op->o_req_dn = *op->oq_modrdn.rs_newSup;
 			op->o_req_ndn = *op->oq_modrdn.rs_nnewSup;
-			rc = get_entry( op, &np, NULL );
+			rc = get_entry( op, &np, NULL, &rs->sr_text );
 			op->o_req_dn = op_dn;
 			op->o_req_ndn = op_ndn;
 			if ( rc != LDAP_SUCCESS ) {
@@ -1224,14 +1210,13 @@ ldif_back_modrdn(Operation *op, SlapReply *rs)
 		/* perform the modifications */
 		rc = apply_modify_to_entry( entry, op->orr_modlist, op, rs );
 		if ( rc == LDAP_SUCCESS )
-			rc = ldif_move_entry( op, entry, &old_path );
+			rc = ldif_move_entry( op, entry, &old_path, &rs->sr_text );
 
 no_such_object:;
 		entry_free( entry );
 		SLAP_FREE( old_path.bv_val );
 	}
 
-	rs->sr_text = "";
 	ldap_pvt_thread_rdwr_wunlock( &li->li_rdwr );
 	rs->sr_err = rc;
 	send_ldap_result( op, rs );
@@ -1260,7 +1245,7 @@ ldif_back_entry_get(
 	ldap_pvt_thread_rdwr_rlock( &li->li_rdwr );
 	op->o_req_dn = *ndn;
 	op->o_req_ndn = *ndn;
-	rc = get_entry( op, e, NULL );
+	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 );
@@ -1331,11 +1316,16 @@ static Entry * ldif_tool_entry_get(BackendDB * be, ID id) {
 	}
 }
 
-static ID ldif_tool_entry_put(BackendDB * be, Entry * e, struct berval *text) {
+static ID
+ldif_tool_entry_put( BackendDB *be, Entry *e, struct berval *text )
+{
+	int rc;
+	const char *errmsg = NULL;
 	struct berval leaf_path = BER_BVNULL;
 	struct stat stats;
 	int statres;
 	int res = LDAP_SUCCESS;
+	Operation op = {0};
 
 	dn2path( be, &e->e_nname, &leaf_path );
 
@@ -1364,7 +1354,7 @@ static ID ldif_tool_entry_put(BackendDB * be, Entry * e, struct berval *text) {
 		if(res == LDAP_SUCCESS) {
 			statres = stat(leaf_path.bv_val, &stats);
 			if(statres == -1 && errno == ENOENT) {
-				res = spew_entry(e, &leaf_path, 0, NULL);
+				res = ldif_write_entry( &op, e, &leaf_path, &errmsg );
 			}
 			else /* it already exists */
 				res = LDAP_ALREADY_EXISTS;
@@ -1376,8 +1366,12 @@ static ID ldif_tool_entry_put(BackendDB * be, Entry * e, struct berval *text) {
 	if(res == LDAP_SUCCESS) {
 		return 1;
 	}
-	else
-		return NOID;
+	rc = res;
+	if ( errmsg == NULL && rc != LDAP_OTHER )
+		errmsg = ldap_err2string( rc );
+	if ( errmsg != NULL )
+		snprintf( text->bv_val, text->bv_len, "%s", errmsg );
+	return NOID;
 }
 
 
-- 
GitLab