1/*	$NetBSD: operational.c,v 1.3 2021/08/14 16:15:00 christos Exp $	*/
2
3/* operational.c - mdb backend operational attributes function */
4/* $OpenLDAP$ */
5/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6 *
7 * Copyright 2000-2021 The OpenLDAP Foundation.
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted only as authorized by the OpenLDAP
12 * Public License.
13 *
14 * A copy of this license is available in the file LICENSE in the
15 * top-level directory of the distribution or, alternatively, at
16 * <http://www.OpenLDAP.org/license.html>.
17 */
18
19#include <sys/cdefs.h>
20__RCSID("$NetBSD: operational.c,v 1.3 2021/08/14 16:15:00 christos Exp $");
21
22#include "portable.h"
23
24#include <stdio.h>
25
26#include <ac/string.h>
27#include <ac/socket.h>
28
29#include "slap.h"
30#include "back-mdb.h"
31
32/*
33 * sets *hasSubordinates to LDAP_COMPARE_TRUE/LDAP_COMPARE_FALSE
34 * if the entry has children or not.
35 */
36int
37mdb_hasSubordinates(
38	Operation	*op,
39	Entry		*e,
40	int		*hasSubordinates )
41{
42	struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
43	MDB_txn		*rtxn;
44	mdb_op_info	opinfo = {{{0}}}, *moi = &opinfo;
45	int		rc;
46
47	assert( e != NULL );
48
49	rc = mdb_opinfo_get(op, mdb, 1, &moi);
50	switch(rc) {
51	case 0:
52		break;
53	default:
54		rc = LDAP_OTHER;
55		goto done;
56	}
57
58	rtxn = moi->moi_txn;
59
60	rc = mdb_dn2id_children( op, rtxn, e );
61
62	switch( rc ) {
63	case 0:
64		*hasSubordinates = LDAP_COMPARE_TRUE;
65		break;
66
67	case MDB_NOTFOUND:
68		*hasSubordinates = LDAP_COMPARE_FALSE;
69		rc = LDAP_SUCCESS;
70		break;
71
72	default:
73		Debug(LDAP_DEBUG_ARGS,
74			"<=- " LDAP_XSTRING(mdb_hasSubordinates)
75			": has_children failed: %s (%d)\n",
76			mdb_strerror(rc), rc );
77		rc = LDAP_OTHER;
78	}
79
80done:;
81	if ( moi == &opinfo ) {
82		mdb_txn_reset( moi->moi_txn );
83		LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next );
84	} else {
85		moi->moi_ref--;
86	}
87	return rc;
88}
89
90/*
91 * sets the supported operational attributes (if required)
92 */
93int
94mdb_operational(
95	Operation	*op,
96	SlapReply	*rs )
97{
98	Attribute	**ap;
99
100	assert( rs->sr_entry != NULL );
101
102	for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next ) {
103		if ( (*ap)->a_desc == slap_schema.si_ad_hasSubordinates ) {
104			break;
105		}
106	}
107
108	if ( *ap == NULL &&
109		attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_hasSubordinates ) == NULL &&
110		( SLAP_OPATTRS( rs->sr_attr_flags ) ||
111			ad_inlist( slap_schema.si_ad_hasSubordinates, rs->sr_attrs ) ) )
112	{
113		int	hasSubordinates, rc;
114
115		rc = mdb_hasSubordinates( op, rs->sr_entry, &hasSubordinates );
116		if ( rc == LDAP_SUCCESS ) {
117			*ap = slap_operational_hasSubordinate( hasSubordinates == LDAP_COMPARE_TRUE );
118			assert( *ap != NULL );
119
120			ap = &(*ap)->a_next;
121		}
122	}
123
124	return LDAP_SUCCESS;
125}
126
127