Net2/usr/src/contrib/isode/quipu/ds_remove.c

/* ds_remove.c - */

#ifndef lint
static char *rcsid = "$Header: /f/osi/quipu/RCS/ds_remove.c,v 7.2 91/02/22 09:38:57 mrose Interim $";
#endif

/*
 * $Header: /f/osi/quipu/RCS/ds_remove.c,v 7.2 91/02/22 09:38:57 mrose Interim $
 *
 *
 * $Log:	ds_remove.c,v $
 * Revision 7.2  91/02/22  09:38:57  mrose
 * Interim 6.8
 * 
 * Revision 7.1  90/10/17  11:53:52  mrose
 * sync
 * 
 * Revision 7.0  89/11/23  22:17:15  mrose
 * Release 6.0
 * 
 */

/*
 *                                NOTICE
 *
 *    Acquisition, use, and distribution of this module and related
 *    materials are subject to the restrictions of a license agreement.
 *    Consult the Preface in the User's Manual for the full terms of
 *    this agreement.
 *
 */


#include "quipu/util.h"
#include "quipu/entry.h"
#include "quipu/remove.h"
#include "pepsy.h"
#include "quipu/DAS_pre_defs.h"

extern LLog * log_dsap;
extern int local_master_size;
#ifdef TURBO_AVL
extern int entry_cmp();
#endif

do_ds_removeentry (arg, error, binddn, target, di_p, dsp)
    struct ds_removeentry_arg      *arg;
    struct DSError              *error;
    DN                          binddn;
    DN				target;
    struct di_block		**di_p;
    char 			dsp;
{
Entry  entryptr, delent = NULLENTRY;
char * new_version ();
int retval;
extern int read_only;

	DLOG (log_dsap,LLOG_TRACE,("ds remove entry"));

	if (!dsp)
		target = arg->rma_object;

	/* stop aliases being dereferenced */
	arg->rma_common.ca_servicecontrol.svc_options |= SVC_OPT_DONTDEREFERENCEALIAS;

	if (target == NULLDN) {
		error->dse_type = DSE_NAMEERROR;
		error->ERR_NAME.DSE_na_problem = DSE_NA_NOSUCHOBJECT;
		error->ERR_NAME.DSE_na_matched = NULLDN;
		return (DS_ERROR_REMOTE);
	}

	switch(find_entry(target,&(arg->rma_common),binddn,NULLDNSEQ,TRUE,&(entryptr), error, di_p, OP_REMOVEENTRY))
	{
	case DS_OK:
	    /* Filled out entryptr - carry on */
	    break;
	case DS_CONTINUE:
	    /* Filled out di_p - what do we do with it ?? */
	    return(DS_CONTINUE);

	case DS_X500_ERROR:
	    /* Filled out error - what do we do with it ?? */
	    return(DS_X500_ERROR);
	default:
	    /* SCREAM */
	    LLOG(log_dsap, LLOG_EXCEPTIONS, ("do_ds_remove() - find_entry failed"));
	    return(DS_ERROR_LOCAL);
	}

	/* entry found, so remove it  */

	/* Strong authentication  */
	if ((retval = check_security_parms((caddr_t) arg,
			_ZRemoveEntryArgumentDataDAS,
			&_ZDAS_mod,
			arg->rma_common.ca_security,
			arg->rma_common.ca_sig, &binddn)) != 0)
	{
		error->dse_type = DSE_SECURITYERROR;
		error->ERR_SECURITY.DSE_sc_problem = retval;
		return (DS_ERROR_REMOTE);
	}

	if (read_only || entryptr->e_parent->e_lock) {
		error->dse_type = DSE_SERVICEERROR;
		error->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNAVAILABLE;
		return (DS_ERROR_REMOTE);
	}

	/* not prepared to accept operation over DSP */
	if (dsp) {
		error->dse_type = DSE_SECURITYERROR;
		error->ERR_SECURITY.DSE_sc_problem = DSE_SC_AUTHENTICATION;
		return (DS_ERROR_REMOTE);
	}

	if ( ! (isleaf(entryptr))) {
		error->dse_type = DSE_UPDATEERROR;
		error->ERR_UPDATE.DSE_up_problem = DSE_UP_NOTONNONLEAF;
		return (DS_ERROR_REMOTE);
	}

	if ( ((entryptr->e_parent->e_data == E_TYPE_CONSTRUCTOR) && (check_acl (binddn,ACL_WRITE,entryptr->e_acl->ac_entry, target) == NOTOK))
	     || (check_acl (binddn, ACL_WRITE, entryptr->e_parent->e_acl->ac_child, target) == NOTOK)) {
		error->dse_type = DSE_SECURITYERROR;
		error->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
		return (DS_ERROR_REMOTE);
	}


#ifdef TURBO_AVL
	if (avl_onenode(entryptr->e_parent->e_children)) {
#else
	if (entryptr->e_sibling == NULLENTRY) {
#endif
#ifdef NOTANYMORE

/*
   We have been asked to remove the last node at one level,
   This means the parent has become a leaf.  The parent however may be
   held in another DSA - which will need updating.
   Also the edbinfo attribute will need modifing.
   Leave till later...
*/
		if (entryptr->e_parent->e_data != E_DATA_MASTER) {
			error->dse_type = DSE_UPDATEERROR;
			error->ERR_UPDATE.DSE_up_problem = DSE_UP_AFFECTSMULTIPLEDSAS;
		} else {
			error->dse_type = DSE_SERVICEERROR;
			error->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNWILLINGTOPERFORM;
		}
		return (DS_ERROR_REMOTE);
#endif

#ifdef TURBO_AVL
#ifdef TURBO_INDEX
		/* delete index references to this node */
		turbo_index_delete(entryptr);
#endif
		/* removed node in core */
		(void) avl_delete(&entryptr->e_parent->e_children,(caddr_t) entryptr,entry_cmp);
#else
		entryptr->e_parent->e_child = NULLENTRY ;
#endif /* TURBO_AVL */
		entryptr->e_parent->e_allchildrenpresent = 2 ;

		if (entryptr->e_parent->e_edbversion)
			free (entryptr->e_parent->e_edbversion);
		entryptr->e_parent->e_edbversion = new_version();

#ifdef TURBO_DISK
		/* remove node on disk */
		if (turbo_delete(entryptr) != OK)
			fatal(-35, "turbo delete failed - check database");
#else
		{
		DN      save_dn ;
		char   *filename ;
		Entry   empty_entry = get_default_entry (NULLENTRY) ;
		char   *dn2edbfile() ;

		empty_entry->e_data = E_DATA_MASTER ;

		save_dn = get_copy_dn(entryptr->e_parent) ;

		if ((filename = dn2edbfile(save_dn)) == NULLCP)
		{
			fatal(-33, "SPT: ds_modify: 1 creating new NLN out failed.\n") ;
		}
		if (write_edb(empty_entry, filename) != OK)
		{
			(void) unlink (filename);
			fatal(-33, "SPT: ds_modify: 2 writing new NLN out failed.\n") ;
		}

		dn_free (save_dn);
		}
#endif /* TURBO_DISK */
		entry_free (entryptr);
		local_master_size--;
		return (DS_OK);

	}
	else
	{
		/* removed node node in core */
#ifdef TURBO_AVL
#ifdef TURBO_INDEX
		/* delete index references to this node */
		turbo_index_delete(entryptr);
#endif
		(void) avl_delete(&entryptr->e_parent->e_children,(caddr_t) entryptr,entry_cmp);
#else
		entryptr->e_parent->e_child = entryptr->e_sibling;
#ifndef  TURBO_DISK
		delent = entryptr;
		entryptr = entryptr->e_sibling;
#endif
#endif
	}

	if (entryptr->e_parent->e_edbversion)
		free (entryptr->e_parent->e_edbversion);
	entryptr->e_parent->e_edbversion = new_version();

	/* remove node on disk */
#ifdef TURBO_DISK
	if (turbo_delete(entryptr) != OK)
		fatal (-35,"turbo remove failed - check database");
#else
	if (journal (entryptr) != OK) 
		fatal (-35,"remove rewrite fail - check database");
#endif

	if (delent)
		entry_free (delent);
	else
		entry_free (entryptr);
	local_master_size--;
	return (DS_OK);

}