static char *rcsid
= "$Header: /f/osi/quipu/RCS/ds_add.c,v 7.4 91/02/22 09:38:41 mrose Interim $";
* $Header: /f/osi/quipu/RCS/ds_add.c,v 7.4 91/02/22 09:38:41 mrose Interim $
* Revision 7.4 91/02/22 09:38:41 mrose
* Revision 7.3 90/10/17 11:53:36 mrose
* Revision 7.2 90/07/09 14:45:37 mrose
* Revision 7.1 90/01/11 18:37:19 mrose
* Revision 7.0 89/11/23 22:17:03 mrose
* 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
#include "quipu/config.h"
#include "quipu/malloc.h"
#include "quipu/DAS_pre_defs.h"
extern Entry database_root
;
extern int local_master_size
;
extern AttributeType at_masterdsa
;
extern AttributeType at_slavedsa
;
extern AttributeType at_objectclass
;
extern AttributeType
*turbo_index_types
;
do_ds_addentry (arg
, error
, binddn
,target
,di_p
,dsp
)
struct ds_addentry_arg
*arg
;
register DN dntop
, dn
= NULLDN
;
extern Entry database_root
;
ContinuationRef
cont_ref_parent ();
DLOG (log_dsap
,LLOG_TRACE
,("ds_add"));
target
= arg
->ada_object
;
/* stop aliases being dereferenced */
arg
->ada_common
.ca_servicecontrol
.svc_options
|= SVC_OPT_DONTDEREFERENCEALIAS
;
error
->dse_type
= DSE_NOERROR
;
/* first of all see if entry exists */
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
->ada_common
),binddn
,NULLDNSEQ
,TRUE
,&entryptr
, error
, di_p
, OP_ADDENTRY
))
error
->dse_type
= DSE_UPDATEERROR
;
error
->ERR_UPDATE
.DSE_up_problem
= DSE_UP_ALREADYEXISTS
;
/* Filled out di_p - what do we do with it ?? */
/* Filled out error - what do we do with it ?? */
if ((error
->dse_type
!= DSE_NAMEERROR
) || (error
->ERR_NAME
.DSE_na_problem
!= DSE_NA_NOSUCHOBJECT
)) {
ds_error_free (error
); /* not interested - know it does not exist */
LLOG(log_dsap
, LLOG_EXCEPTIONS
, ("do_ds_read() - find_entry failed"));
/* object does not exist, so create it */
/* Strong authentication */
if ((retval
= check_security_parms((caddr_t
) arg
,
_ZAddEntryArgumentDataDAS
,
arg
->ada_common
.ca_security
,
arg
->ada_common
.ca_sig
, &binddn
)) != 0)
error
->dse_type
= DSE_SECURITYERROR
;
error
->ERR_SECURITY
.DSE_sc_problem
= retval
;
return (DS_ERROR_REMOTE
);
DLOG (log_dsap
,LLOG_TRACE
,("add - find parent"));
if ((dntop
= dn_cpy(target
)) != NULLDN
)
for (dn
=dntop
; dn
->dn_parent
!= NULLDN
; dn
=dn
->dn_parent
)
entryptr
= database_root
;
if (entryptr
->e_data
!= E_DATA_MASTER
) {
error
->dse_type
= DSE_REFERRAL
;
error
->ERR_REFERRAL
.DSE_ref_prefix
= NULLDN
;
if ((error
->ERR_REFERRAL
.DSE_ref_candidates
= cont_ref_parent (NULLDN
)) == NULLCONTINUATIONREF
) {
error
->dse_type
= DSE_SERVICEERROR
;
error
->ERR_SERVICE
.DSE_sv_problem
= DSE_SV_INVALIDREFERENCE
;
return (DS_ERROR_CONNECT
);
trail
->dn_parent
= NULLDN
;
switch(find_child_entry(dntop
,&(arg
->ada_common
),binddn
,NULLDNSEQ
,TRUE
,&(entryptr
), error
, di_p
))
/* Filled out entryptr - carry on */
/* Filled out di_p - what do we do with it ?? */
/* When add returns DS_CONTINUE the target must be changed */
/* Filled out error - what do we do with it ?? */
LLOG(log_dsap
, LLOG_EXCEPTIONS
, ("do_ds_add() - find_child_entry failed"));
if ( read_only
|| ((entryptr
->e_parent
!= NULLENTRY
) && (entryptr
->e_parent
->e_lock
))) {
error
->dse_type
= DSE_SERVICEERROR
;
error
->ERR_SERVICE
.DSE_sv_problem
= DSE_SV_UNWILLINGTOPERFORM
;
return (DS_ERROR_REMOTE
);
/* not prepared to accept operation over DSP */
error
->dse_type
= DSE_SECURITYERROR
;
error
->ERR_SECURITY
.DSE_sc_problem
= DSE_SC_AUTHENTICATION
;
return (DS_ERROR_REMOTE
);
DLOG (log_dsap
,LLOG_TRACE
,("add - acl"));
if (check_acl (binddn
,ACL_ADD
,entryptr
->e_acl
->ac_child
,dntop
) == NOTOK
) {
error
->dse_type
= DSE_SECURITYERROR
;
error
->ERR_SECURITY
.DSE_sc_problem
= DSE_SC_ACCESSRIGHTS
;
return (DS_ERROR_REMOTE
);
DLOG (log_dsap
,LLOG_TRACE
,("add - default"));
ptr
= get_default_entry (entryptr
);
ptr
->e_name
= rdn_cpy (dn
->dn_rdn
);
ptr
->e_attributes
= as_cpy (arg
->ada_entry
);
modify_attr (ptr
,binddn
);
DLOG (log_dsap
,LLOG_TRACE
,("add - unravel"));
if (unravel_attribute (ptr
,error
) != OK
) {
return (DS_ERROR_REMOTE
);
if ( ! check_oc_hierarchy(ptr
->e_oc
)) {
error
->dse_type
= DSE_UPDATEERROR
;
error
->ERR_UPDATE
.DSE_up_problem
= DSE_UP_OBJECTCLASSVIOLATION
;
return (DS_ERROR_REMOTE
);
DLOG (log_dsap
,LLOG_TRACE
,("add - schema"));
if (check_schema (ptr
,NULLATTR
,error
) != OK
) {
return (DS_ERROR_REMOTE
);
if ( (!ptr
->e_leaf
) && (!ptr
->e_external
) && (!ptr
->e_children
)) {
if ( (!ptr
->e_leaf
) && (!ptr
->e_external
) && (!ptr
->e_child
)) {
for (avs
= ptr
->e_master
; avs
!= NULLAV
; avs
=avs
->avseq_next
)
if (dn_cmp ((DN
)avs
->avseq_av
.av_struct
, mydsadn
) == 0) {
ptr
->e_allchildrenpresent
= FALSE
;
(void) avl_insert(&entryptr
->e_children
, (caddr_t
) ptr
, entry_cmp
, avl_dup_error
);
/* Turn leaf into non leaf, and add child */
/* Temporary until managemnet tools do it */
if (entryptr
->e_data
!= E_DATA_MASTER
) {
struct dn_seq
* dn_stack
= NULLDNSEQ
;
dn_found
= get_copy_dn (entryptr
);
res
= constructor_dsa_info(dn_found
,dn_stack
,TRUE
,entryptr
,error
,di_p
);
/* add master and slave attributes */
if ((entryptr
->e_parent
->e_slave
== NULLAV
) && (entryptr
->e_parent
->e_master
== NULLAV
)) {
entryptr
->e_master
= str2avs (mydsaname
,at_masterdsa
);
newas
= as_comp_new (AttrT_cpy(at_masterdsa
),entryptr
->e_master
,NULLACL_INFO
);
entryptr
->e_attributes
= as_merge (entryptr
->e_attributes
,newas
);
if ((entryptr
->e_master
= avs_cpy(entryptr
->e_parent
->e_master
)) != NULLAV
) {
newas
= as_comp_new (AttrT_cpy(at_masterdsa
),entryptr
->e_master
,NULLACL_INFO
);
entryptr
->e_attributes
= as_merge (entryptr
->e_attributes
,newas
);
if ((entryptr
->e_slave
= avs_cpy (entryptr
->e_parent
->e_slave
)) != NULLAV
) {
newas
= as_comp_new (AttrT_cpy(at_slavedsa
),entryptr
->e_slave
,NULLACL_INFO
);
entryptr
->e_attributes
= as_merge (entryptr
->e_attributes
,newas
);
/* add new QuipuNonLeaf objectclass */
/* see if OC inherited */
if (as_find_type(entryptr
->e_attributes
,at_objectclass
) == NULLATTR
) {
/* OC inherited - pull down */
newas
= as_comp_new (AttrT_cpy(at_objectclass
),avs_cpy(entryptr
->e_oc
),NULLACL_INFO
);
entryptr
->e_attributes
= as_merge (entryptr
->e_attributes
,newas
);
newas
= as_comp_new (AttrT_cpy(at_objectclass
),str2avs(NONLEAFOBJECT
,at_objectclass
),NULLACL_INFO
);
entryptr
->e_attributes
= as_merge (entryptr
->e_attributes
,newas
);
if (entryptr
->e_parent
!= NULLENTRY
) {
if (entryptr
->e_parent
->e_edbversion
)
free (entryptr
->e_parent
->e_edbversion
);
entryptr
->e_parent
->e_edbversion
= new_version();
if (entryptr
->e_edbversion
)
free (entryptr
->e_edbversion
);
entryptr
->e_edbversion
= new_version();
ptr
->e_edbversion
= new_version();
entryptr
->e_allchildrenpresent
= 2; /* Subtree ! */
modify_attr (entryptr
,binddn
);
if (unravel_attribute (entryptr
,error
) != OK
)
fatal (-31,"serious schema error");
turbo_add2index(ptr
); /* add new entry to index */
turbo_add2index(entryptr
); /* add parent to index */
/* write the new entry */
if (turbo_write(ptr
) == NOTOK
)
fatal(-32,"add turbo_write (2) failure - check database");
if (journal (ptr
) == NOTOK
)
fatal (-32,"add journal (2) failure - check database");
entryptr
->e_leaf
= FALSE
;
/* rewrite the parent as well */
if (turbo_write(entryptr
) == NOTOK
)
fatal(-31,"add parent turbo_write failed - check database");
if (journal (entryptr
) != OK
)
fatal (-31,"add parent journal failed - check database");
/* Management tools will take care of the situation properly */
error
->ERR_SERVICE
.DSE_sv_problem
= DSE_SV_UNWILLINGTOPERFORM
;
return(DS_ERROR_REMOTE
) ;
ptr
->e_sibling
= entryptr
->e_child
;
if (ptr
->e_parent
!= NULLENTRY
) {
if (ptr
->e_parent
->e_edbversion
)
free (ptr
->e_parent
->e_edbversion
);
ptr
->e_parent
->e_edbversion
= new_version();
if (turbo_write(ptr
) == NOTOK
)
fatal(-32,"add turbo_write failure - check database");
if (journal (ptr
) == NOTOK
)
fatal (-32,"add journal failure - check database");