dse_add(Slapi_PBlock *pb) /* JCM There should only be one exit point from this function! */
{
    Slapi_Entry *e = NULL;      /*The new entry to add*/
    Slapi_Entry *e_copy = NULL; /* copy of added entry */
    char *errbuf = NULL;
    int rc = LDAP_SUCCESS;
    int error = -1;
    int dont_write_file = 0; /* default */
    struct dse *pdse;
    int returncode = LDAP_SUCCESS;
    char returntext[SLAPI_DSE_RETURNTEXT_SIZE] = "";
    Slapi_DN *sdn = NULL;
    Slapi_DN parent;
    int need_be_postop = 0;
    PRBool global_lock_owned = PR_FALSE;

    /*
     * Get the database, the dn and the entry to add
     */
    if (slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &pdse) < 0 ||
        slapi_pblock_get(pb, SLAPI_ADD_TARGET_SDN, &sdn) < 0 ||
        slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &e) < 0 || (NULL == pdse)) {
        rc = LDAP_OPERATIONS_ERROR;
        goto done;
    }

    slapi_pblock_get(pb, SLAPI_DSE_DONT_WRITE_WHEN_ADDING, &dont_write_file);
    if (!dont_write_file && dse_check_for_readonly_error(pb, pdse)) {
        return (error); /* result already sent */
    }

    /*
     * Check to make sure the entry passes the schema check
     */
    if (slapi_entry_schema_check(pb, e) != 0) {
        char *errtext;
        slapi_log_err(SLAPI_DSE_TRACELEVEL,
                      "dse_add", "entry failed schema check\n");
        slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &errtext);
        if (errtext && errtext[0]) {
            PL_strncpyz(returntext, errtext, sizeof(returntext));
        }
        rc = LDAP_OBJECT_CLASS_VIOLATION;
        e = NULL; /* caller will free upon error */
        goto done;
    }

    /* Check if the attribute values in the entry obey the syntaxes */
    if (slapi_entry_syntax_check(pb, e, 0) != 0) {
        char *errtext;
        slapi_log_err(SLAPI_DSE_TRACELEVEL,
                      "dse_add", "entry failed syntax check\n");
        slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &errtext);
        if (errtext && errtext[0]) {
            PL_strncpyz(returntext, errtext, sizeof(returntext));
        }
        rc = LDAP_INVALID_SYNTAX;
        e = NULL; /* caller will free upon error */
        goto done;
    }

    /*
     * Attempt to find this dn.
     */
    {
        Slapi_Entry *existingentry = dse_get_entry_copy(pdse, sdn, DSE_USE_LOCK);
        if (existingentry != NULL) {
            /*
             * If we've reached this code, there is an entry
             * whose dn matches dn, so tell the user and return
             */
            slapi_entry_free(existingentry);
            rc = LDAP_ALREADY_EXISTS;
            e = NULL; /* caller will free upon error */
            goto done;
        }
    }

    /*
     * Get the parent dn and see if the corresponding entry exists.
     * If the parent does not exist, only allow the "root" user to
     * add the entry.
     */
    slapi_sdn_init(&parent);
    slapi_sdn_get_parent(sdn, &parent);
    if (!slapi_sdn_isempty(&parent)) {
        Slapi_Entry *parententry = NULL;
        parententry = dse_get_entry_copy(pdse, &parent, DSE_USE_LOCK);
        if (parententry == NULL) {
            rc = LDAP_NO_SUCH_OBJECT;
            slapi_log_err(SLAPI_DSE_TRACELEVEL, " dse_add", "Narent does not exist\n");
            slapi_sdn_done(&parent);
            e = NULL; /* caller will free upon error */
            goto done;
        }
        rc = plugin_call_acl_plugin(pb, parententry, NULL, NULL, SLAPI_ACL_ADD, ACLPLUGIN_ACCESS_DEFAULT, &errbuf);
        slapi_entry_free(parententry);
        if (rc != LDAP_SUCCESS) {
            slapi_log_err(SLAPI_DSE_TRACELEVEL, "dse_add", "No access to parent\n");
            if (errbuf && errbuf[0]) {
                PL_strncpyz(returntext, errbuf, sizeof(returntext));
            }
            slapi_ch_free_string(&errbuf);
            slapi_sdn_done(&parent);
            e = NULL; /* caller will free upon error */
            goto done;
        }
    } else {
        /* no parent */
        int isroot;
        slapi_pblock_get(pb, SLAPI_REQUESTOR_ISROOT, &isroot);
        if (!isroot) {
            slapi_log_err(SLAPI_DSE_TRACELEVEL, "dse_add", "No parent and not root\n");
            rc = LDAP_INSUFFICIENT_ACCESS;
            slapi_sdn_done(&parent);
            e = NULL; /* caller will free upon error */
            goto done;
        }
    }
    slapi_sdn_done(&parent);

    /*
     * Before we add the entry, find out if the syntax of the aci
     * aci attribute values are correct or not. We don't want to add
     * the entry if the syntax is incorrect.
     */
    if (plugin_call_acl_verify_syntax(pb, e, &errbuf) != 0) {
        if (errbuf && errbuf[0]) {
            PL_strncpyz(returntext, errbuf, sizeof(returntext));
            slapi_ch_free_string(&errbuf);
        }
        rc = LDAP_INVALID_SYNTAX;
        e = NULL; /* caller will free upon error */
        goto done;
    }

    /* Possibly acquire the global backend lock */
    if (global_backend_lock_requested()) {
        global_backend_lock_lock();
        global_lock_owned = PR_TRUE;
    }

    if (dse_call_callback(pdse, pb, SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, e,
                          NULL, &returncode, returntext) != SLAPI_DSE_CALLBACK_OK) {
        if (!returncode) {
            slapi_log_err(SLAPI_LOG_ERR, "dse_add",
                          "DSE PREOP callback returned error but did not set returncode\n");
            returncode = LDAP_OPERATIONS_ERROR;
        }
        rc = returncode;
        e = NULL; /* caller will free upon error */
        goto done;
    }
    /* next, give the be plugins a crack at it */
    slapi_pblock_set(pb, SLAPI_RESULT_CODE, &returncode);
    plugin_call_plugins(pb, SLAPI_PLUGIN_BE_PRE_ADD_FN);
    need_be_postop = 1; /* have to call be postops now */
    if (!returncode) {
        slapi_pblock_get(pb, SLAPI_RESULT_CODE, &returncode);
    }
    if (!returncode) {
        /* finally, give the betxn plugins a crack at it */
        plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_PRE_ADD_FN);
        if (!returncode) {
            slapi_pblock_get(pb, SLAPI_RESULT_CODE, &returncode);
        }
    }
    if (returncode) {
        if (!returntext[0]) {
            char *ldap_result_message = NULL;
            slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
            if (ldap_result_message && ldap_result_message[0]) {
                PL_strncpyz(returntext, ldap_result_message, sizeof(returntext));
            }
        }
        rc = returncode;
        e = NULL; /* caller will free upon error */
        goto done;
    }
    /*
     * Check if we are adding a plugin
     */
    if (dse_add_plugin(e, returntext)) {
        returncode = LDAP_UNWILLING_TO_PERFORM;
        goto done;
    }

    /* make copy for postop fns because add_entry_pb consumes the given entry */
    e_copy = slapi_entry_dup(e);
    if (dse_add_entry_pb(pdse, e_copy, pb) != 0) {
        rc = LDAP_OPERATIONS_ERROR;
        e = NULL; /* caller will free upon error */
        goto done;
    }
    /* The postop must be called after the write lock is released. */
    dse_call_callback(pdse, pb, SLAPI_OPERATION_ADD, DSE_FLAG_POSTOP, e, NULL, &returncode, returntext);
done:
    if (e) {
        slapi_pblock_set(pb, SLAPI_ENTRY_POST_OP, slapi_entry_dup(e));
    }

    /* make sure OPRETURN and RESULT_CODE are set */
    slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &error);
    if (rc || returncode) {
        if (!error) {
            slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, rc ? &rc : &returncode);
        }
        if (!returncode) {
            returncode = rc;
        }
    }
    if (need_be_postop) {
        /* next, give the be txn plugins a crack at it */
        slapi_pblock_set(pb, SLAPI_RESULT_CODE, &returncode);
        plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_POST_ADD_FN);

        /* finally, give the be plugins a crack at it */
        plugin_call_plugins(pb, SLAPI_PLUGIN_BE_POST_ADD_FN);
        if (!returncode) {
            slapi_pblock_get(pb, SLAPI_RESULT_CODE, &returncode);
        }
    }
    if (global_lock_owned) {
        global_backend_lock_unlock();
    }
    slapi_send_ldap_result(pb, returncode, NULL, returntext[0] ? returntext : NULL, 0, NULL);
    return dse_add_return(rc, e);
}