Example #1
0
void
search_list_search(struct search_list *this_, struct attr *search_attr, int partial)
{
	struct search_list_level *le;
	int level=search_list_level(search_attr->type);
	this_->item=NULL;
	interpolation_clear(&this_->inter);
	//dbg(0,"level=%d\n", level);
	if (level != -1) {
		this_->result.id=0;
		this_->level=level;
		le=&this_->levels[level];
		search_list_search_free(this_, level);
		le->attr=attr_dup(search_attr);
		le->partial=partial;
		if (level > 0) {
			le=&this_->levels[level-1];
			le->curr=le->list;
		}
		//dbg(0,"le=%p partial=%d\n", le, partial);
	} else if (search_attr->type == attr_postal) {
		g_free(this_->postal);
		this_->postal=g_strdup(search_attr->u.str);
	}
}
Example #2
0
static int translucent_search_cb(Operation *op, SlapReply *rs) {
	trans_ctx *tc;
	BackendDB *db;
	slap_overinst *on;
	translucent_info *ov;
	Entry *le, *re;
	Attribute *a, *ax, *an, *as = NULL;
	int rc;
	int test_f = 0;

	tc = op->o_callback->sc_private;

	/* Don't let the op complete while we're gathering data */
	if ( rs->sr_type == REP_RESULT && ( tc->step & USE_LIST ))
		return 0;

	if(rs->sr_type != REP_SEARCH || !rs->sr_entry)
		return(SLAP_CB_CONTINUE);

	Debug(LDAP_DEBUG_TRACE, "==> translucent_search_cb: %s\n",
		rs->sr_entry->e_name.bv_val, 0, 0);

	op->ors_slimit = tc->slimit + ( tc->slimit > 0 ? 1 : 0 );
	if ( op->ors_attrs == slap_anlist_all_attributes ) {
		op->ors_attrs = tc->attrs;
		rs->sr_attrs = tc->attrs;
		rs->sr_attr_flags = slap_attr_flags( rs->sr_attrs );
	}

	on = tc->on;
	ov = on->on_bi.bi_private;

	db = op->o_bd;
	re = NULL;

	/* If we have local, get remote */
	if ( tc->step & LCL_SIDE ) {
		le = rs->sr_entry;
		/* If entry is already on list, use it */
		if ( tc->step & USE_LIST ) {
			re = tavl_delete( &tc->list, le, entry_dn_cmp );
			if ( re ) {
				rs_flush_entry( op, rs, on );
				rc = test_filter( op, re, tc->orig );
				if ( rc == LDAP_COMPARE_TRUE ) {
					rs->sr_flags |= REP_ENTRY_MUSTBEFREED;
					rs->sr_entry = re;

					if ( tc->slimit >= 0 && rs->sr_nentries >= tc->slimit ) {
						return LDAP_SIZELIMIT_EXCEEDED;
					}

					return SLAP_CB_CONTINUE;
				} else {
					entry_free( re );
					rs->sr_entry = NULL;
					return 0;
				}
			}
		}
		op->o_bd = &ov->db;
		rc = be_entry_get_rw( op, &rs->sr_entry->e_nname, NULL, NULL, 0, &re );
		if ( rc == LDAP_SUCCESS && re ) {
			Entry *tmp = entry_dup( re );
			be_entry_release_r( op, re );
			re = tmp;
			test_f = 1;
		}
	} else {
	/* Else we have remote, get local */
		op->o_bd = tc->db;
		le = NULL;
		rc = overlay_entry_get_ov(op, &rs->sr_entry->e_nname, NULL, NULL, 0, &le, on);
		if ( rc == LDAP_SUCCESS && le ) {
			re = entry_dup( rs->sr_entry );
			rs_flush_entry( op, rs, on );
		} else {
			le = NULL;
		}
	}

/*
** if we got remote and local entry:
**	foreach local attr:
**		foreach remote attr:
**			if match, remote attr with local attr;
**			if new local, add to list;
**	append new local attrs to remote;
**
*/

	if ( re && le ) {
		for(ax = le->e_attrs; ax; ax = ax->a_next) {
			for(a = re->e_attrs; a; a = a->a_next) {
				if(a->a_desc == ax->a_desc) {
					test_f = 1;
					if(a->a_vals != a->a_nvals)
						ber_bvarray_free(a->a_nvals);
					ber_bvarray_free(a->a_vals);
					ber_bvarray_dup_x( &a->a_vals, ax->a_vals, NULL );
					if ( ax->a_vals == ax->a_nvals ) {
						a->a_nvals = a->a_vals;
					} else {
						ber_bvarray_dup_x( &a->a_nvals, ax->a_nvals, NULL );
					}
					break;
				}
			}
			if(a) continue;
			an = attr_dup(ax);
			an->a_next = as;
			as = an;
		}
		/* Dispose of local entry */
		if ( tc->step & LCL_SIDE ) {
			rs_flush_entry(op, rs, on);
		} else {
			overlay_entry_release_ov(op, le, 0, on);
		}

		/* literally append, so locals are always last */
		if(as) {
			if(re->e_attrs) {
				for(ax = re->e_attrs; ax->a_next; ax = ax->a_next);
				ax->a_next = as;
			} else {
				re->e_attrs = as;
			}
		}
		/* If both filters, save entry for later */
		if ( tc->step == (USE_LIST|RMT_SIDE) ) {
			tavl_insert( &tc->list, re, entry_dn_cmp, avl_dup_error );
			rs->sr_entry = NULL;
			rc = 0;
		} else {
		/* send it now */
			rs->sr_entry = re;
			rs->sr_flags |= REP_ENTRY_MUSTBEFREED;
			if ( test_f ) {
				rc = test_filter( op, rs->sr_entry, tc->orig );
				if ( rc == LDAP_COMPARE_TRUE ) {
					rc = SLAP_CB_CONTINUE;
				} else {
					rc = 0;
				}
			} else {
				rc = SLAP_CB_CONTINUE;
			}
		}
	} else if ( le ) {
	/* Only a local entry: remote was deleted
	 * Ought to delete the local too...
	 */
	 	rc = 0;
	} else if ( tc->step & USE_LIST ) {
	/* Only a remote entry, but both filters:
	 * Test the complete filter
	 */
		rc = test_filter( op, rs->sr_entry, tc->orig );
		if ( rc == LDAP_COMPARE_TRUE ) {
			rc = SLAP_CB_CONTINUE;
		} else {
			rc = 0;
		}
	} else {
	/* Only a remote entry, only remote filter:
	 * just pass thru
	 */
		rc = SLAP_CB_CONTINUE;
	}

	op->o_bd = db;

	if ( rc == SLAP_CB_CONTINUE && tc->slimit >= 0 && rs->sr_nentries >= tc->slimit ) {
		return LDAP_SIZELIMIT_EXCEEDED;
	}

	return rc;
}
Example #3
0
static int translucent_modify(Operation *op, SlapReply *rs) {
	SlapReply nrs = { REP_RESULT };

	slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
	translucent_info *ov = on->on_bi.bi_private;
	Entry *e = NULL, *re = NULL;
	Attribute *a, *ax;
	Modifications *m, **mm;
	BackendDB *db;
	int del, rc, erc = 0;
	slap_callback cb = { 0 };

	Debug(LDAP_DEBUG_TRACE, "==> translucent_modify: %s\n",
		op->o_req_dn.bv_val, 0, 0);

	if(ov->defer_db_open) {
		send_ldap_error(op, rs, LDAP_UNAVAILABLE,
			"remote DB not available");
		return(rs->sr_err);
	}
/*
** fetch entry from the captive backend;
** if it did not exist, fail;
** release it, if captive backend supports this;
**
*/

	db = op->o_bd;
	op->o_bd = &ov->db;
	ov->db.be_acl = op->o_bd->be_acl;
	rc = ov->db.bd_info->bi_entry_get_rw(op, &op->o_req_ndn, NULL, NULL, 0, &re);
	op->o_bd = db;
	if(rc != LDAP_SUCCESS || re == NULL ) {
		send_ldap_error((op), rs, LDAP_NO_SUCH_OBJECT,
			"attempt to modify nonexistent local record");
		return(rs->sr_err);
	}
/*
** fetch entry from local backend;
** if it exists:
**	foreach Modification:
**	    if attr not present in local:
**		if Mod == LDAP_MOD_DELETE:
**		    if remote attr not present, return NO_SUCH;
**		    if remote attr present, drop this Mod;
**		else force this Mod to LDAP_MOD_ADD;
**	return CONTINUE;
**
*/

	op->o_bd->bd_info = (BackendInfo *) on->on_info->oi_orig;
	rc = be_entry_get_rw(op, &op->o_req_ndn, NULL, NULL, 0, &e);
	op->o_bd->bd_info = (BackendInfo *) on;

	if(e && rc == LDAP_SUCCESS) {
		Debug(LDAP_DEBUG_TRACE, "=> translucent_modify: found local entry\n", 0, 0, 0);
		for(mm = &op->orm_modlist; *mm; ) {
			m = *mm;
			for(a = e->e_attrs; a; a = a->a_next)
				if(a->a_desc == m->sml_desc) break;
			if(a) {
				mm = &m->sml_next;
				continue;		/* found local attr */
			}
			if(m->sml_op == LDAP_MOD_DELETE) {
				for(a = re->e_attrs; a; a = a->a_next)
					if(a->a_desc == m->sml_desc) break;
				/* not found remote attr */
				if(!a) {
					erc = LDAP_NO_SUCH_ATTRIBUTE;
					goto release;
				}
				if(ov->strict) {
					erc = LDAP_CONSTRAINT_VIOLATION;
					goto release;
				}
				Debug(LDAP_DEBUG_TRACE,
					"=> translucent_modify: silently dropping delete: %s\n",
					m->sml_desc->ad_cname.bv_val, 0, 0);
				*mm = m->sml_next;
				m->sml_next = NULL;
				slap_mods_free(m, 1);
				continue;
			}
			m->sml_op = LDAP_MOD_ADD;
			mm = &m->sml_next;
		}
		erc = SLAP_CB_CONTINUE;
release:
		if(re) {
			if(ov->db.bd_info->bi_entry_release_rw) {
				op->o_bd = &ov->db;
				ov->db.bd_info->bi_entry_release_rw(op, re, 0);
				op->o_bd = db;
			} else
				entry_free(re);
		}
		op->o_bd->bd_info = (BackendInfo *) on->on_info->oi_orig;
		be_entry_release_r(op, e);
		op->o_bd->bd_info = (BackendInfo *) on;
		if(erc == SLAP_CB_CONTINUE) {
			return(erc);
		} else if(erc) {
			send_ldap_error(op, rs, erc,
				"attempt to delete nonexistent attribute");
			return(erc);
		}
	}

	/* don't leak remote entry copy */
	if(re) {
		if(ov->db.bd_info->bi_entry_release_rw) {
			op->o_bd = &ov->db;
			ov->db.bd_info->bi_entry_release_rw(op, re, 0);
			op->o_bd = db;
		} else
			entry_free(re);
	}
/*
** foreach Modification:
**	if MOD_ADD or MOD_REPLACE, add Attribute;
** if no Modifications were suitable:
**	if strict, throw CONSTRAINT_VIOLATION;
**	else, return early SUCCESS;
** fabricate Entry with new Attribute chain;
** glue_parent() for this Entry;
** call bi_op_add() in local backend;
**
*/

	Debug(LDAP_DEBUG_TRACE, "=> translucent_modify: fabricating local add\n", 0, 0, 0);
	a = NULL;
	for(del = 0, ax = NULL, m = op->orm_modlist; m; m = m->sml_next) {
		Attribute atmp;
		if(((m->sml_op & LDAP_MOD_OP) != LDAP_MOD_ADD) &&
		   ((m->sml_op & LDAP_MOD_OP) != LDAP_MOD_REPLACE)) {
			Debug(LDAP_DEBUG_ANY,
				"=> translucent_modify: silently dropped modification(%d): %s\n",
				m->sml_op, m->sml_desc->ad_cname.bv_val, 0);
			if((m->sml_op & LDAP_MOD_OP) == LDAP_MOD_DELETE) del++;
			continue;
		}
		atmp.a_desc = m->sml_desc;
		atmp.a_vals = m->sml_values;
		atmp.a_nvals = m->sml_nvalues ? m->sml_nvalues : atmp.a_vals;
		atmp.a_numvals = m->sml_numvals;
		atmp.a_flags = 0;
		a = attr_dup( &atmp );
		a->a_next  = ax;
		ax = a;
	}

	if(del && ov->strict) {
		attrs_free( a );
		send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION,
			"attempt to delete attributes from local database");
		return(rs->sr_err);
	}

	if(!ax) {
		if(ov->strict) {
			send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION,
				"modification contained other than ADD or REPLACE");
			return(rs->sr_err);
		}
		/* rs->sr_text = "no valid modification found"; */
		rs->sr_err = LDAP_SUCCESS;
		send_ldap_result(op, rs);
		return(rs->sr_err);
	}

	e = entry_alloc();
	ber_dupbv( &e->e_name, &op->o_req_dn );
	ber_dupbv( &e->e_nname, &op->o_req_ndn );
	e->e_attrs = a;

	op->o_tag	= LDAP_REQ_ADD;
	cb.sc_response = translucent_tag_cb;
	cb.sc_private = op->orm_modlist;
	op->oq_add.rs_e	= e;

	glue_parent(op);

	cb.sc_next = op->o_callback;
	op->o_callback = &cb;
	rc = on->on_info->oi_orig->bi_op_add(op, &nrs);
	if ( op->ora_e == e )
		entry_free( e );
	op->o_callback = cb.sc_next;

	return(rc);
}
Example #4
0
/*
 * Fixup types when modes given in defid().
 */
void
gcc_modefix(NODE *p)
{
	struct attr *ap;
#ifdef TARGET_TIMODE
	struct attr *a2;
#endif
	struct symtab *sp;
	char *s;
	int i, u;

	if ((ap = attr_find(p->n_ap, GCC_ATYP_MODE)) == NULL)
		return;

	u = ISUNSIGNED(BTYPE(p->n_type));
	if ((i = amatch(ap->aa[0].sarg, mods, ATSZ)) == 0) {
		werror("unknown mode arg %s", ap->aa[0].sarg);
		return;
	}
	i = mods[i].typ;
	if (i >= 1 && i <= MAXTYPES) {
		MODTYPE(p->n_type, ctype(i));
		if (u)
			p->n_type = ENUNSIGN(p->n_type);
	} else switch (i) {
#ifdef TARGET_TIMODE
	case 800:
		if (BTYPE(p->n_type) == STRTY)
			break;
		MODTYPE(p->n_type, tisp->stype);
		p->n_df = tisp->sdf;
		p->n_ap = tisp->sap;
		if (ap->iarg(1) == u)
			break;
		/* must add a new mode struct to avoid overwriting */
		a2 = attr_new(GCC_ATYP_MODE, 3);
		a2->sarg(0) = ap->sarg(0);
		a2->iarg(1) = u;
		p->n_ap = attr_add(p->n_ap, a2);
		break;
#endif
	case FCOMPLEX:
	case COMPLEX:
	case LCOMPLEX:
		/* Destination should have been converted to a struct already */
		if (BTYPE(p->n_type) != STRTY)
			uerror("gcc_modefix: complex not STRTY");
		i -= (FCOMPLEX-FLOAT);
		ap = strattr(p->n_ap);
		sp = ap->amlist;
		if (sp->stype == (unsigned)i)
			return; /* Already correct type */
		/* we must change to another struct */
		s = i == FLOAT ? "0f" :
		    i == DOUBLE ? "0d" :
		    i == LDOUBLE ? "0l" : 0;
		sp = lookup(addname(s), 0);
		for (ap = sp->sap; ap != NULL; ap = ap->next)
			p->n_ap = attr_add(p->n_ap, attr_dup(ap));
		break;

	default:
		cerror("gcc_modefix");
	}
}