summaryrefslogtreecommitdiffstats
path: root/src/back-shr.c
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin@dahyabhai.net>2012-01-19 07:15:40 -0500
committerNalin Dahyabhai <nalin@dahyabhai.net>2012-01-19 07:15:40 -0500
commit338657055966f3273958243e7125d7605ac879bc (patch)
treec9c40d9c72d8a4e5190e41d0fa51b6eb25de061b /src/back-shr.c
parent1953630d37072f53d8da81edb7f9eca1bebf4af7 (diff)
downloadslapi-nis-338657055966f3273958243e7125d7605ac879bc.tar.gz
slapi-nis-338657055966f3273958243e7125d7605ac879bc.tar.xz
slapi-nis-338657055966f3273958243e7125d7605ac879bc.zip
- don't lean so hard on slapi_entry_diff(), when if we do it ourselves, the official mods list already narrows down the work needed to get the results we're interested in seeing
Diffstat (limited to 'src/back-shr.c')
-rw-r--r--src/back-shr.c186
1 files changed, 184 insertions, 2 deletions
diff --git a/src/back-shr.c b/src/back-shr.c
index 3130d08..c553b12 100644
--- a/src/back-shr.c
+++ b/src/back-shr.c
@@ -829,7 +829,7 @@ backend_shr_mods_as_string(LDAPMod **mods)
ret = NULL;
for (i = 0, length = 0; (mods != NULL) && (mods[i] != NULL); i++) {
- length += (strlen(mods[i]->mod_type) + 1);
+ length += (strlen(mods[i]->mod_type) + 1 + 8);
}
if (length > 0) {
ret = malloc(length);
@@ -839,6 +839,18 @@ backend_shr_mods_as_string(LDAPMod **mods)
if (i > 0) {
strcpy(ret + length++, ",");
}
+ if (SLAPI_IS_MOD_ADD(mods[i]->mod_op)) {
+ strcpy(ret + length, "add:");
+ length += 4;
+ }
+ if (SLAPI_IS_MOD_REPLACE(mods[i]->mod_op)) {
+ strcpy(ret + length, "replace:");
+ length += 8;
+ }
+ if (SLAPI_IS_MOD_DELETE(mods[i]->mod_op)) {
+ strcpy(ret + length, "delete:");
+ length += 7;
+ }
strcpy(ret + length, mods[i]->mod_type);
length += strlen(mods[i]->mod_type);
}
@@ -1741,6 +1753,174 @@ backend_shr_modify_entry_cb(const char *group, const char *set, bool_t flag,
return TRUE;
}
+static Slapi_Mod *
+backend_shr_mod_as_smod(LDAPMod *mod)
+{
+ Slapi_Mod *ret;
+ ret = slapi_mod_new();
+ slapi_mod_init_byval(ret, mod);
+ return ret;
+}
+
+/* Walk the list of mods, picking out those which won't have an effect, and
+ * adding the rest to the "relevant" list. */
+static void
+backend_shr_filter_mods(LDAPMod **mods, Slapi_Entry *pre, Slapi_Entry *post,
+ Slapi_Mods *relevant)
+{
+ LDAPMod *mod;
+ Slapi_ValueSet *values;
+ Slapi_Value *value, *mval;
+ const struct berval *mbv, *ebv;
+ struct berval msv;
+ char *actual_attr;
+ int i, j, k, result, disposition, buffer_flags;
+
+ if (mods == NULL) {
+ return;
+ }
+ mval = slapi_value_new();
+ for (i = 0; mods[i] != NULL; i++) {
+ mod = mods[i];
+ if (slapi_vattr_values_get(pre, mod->mod_type, &values,
+ &disposition, &actual_attr,
+ 0, &buffer_flags) != 0) {
+ /* error of some kind, punt */
+ slapi_mods_add_smod(relevant, backend_shr_mod_as_smod(mod));
+ continue;
+ }
+ if (SLAPI_IS_MOD_DELETE(mod->mod_op)) {
+ /* if the target entry has values, and one of the ones
+ * we're removing is in the entry, keep it */
+ if (slapi_valueset_count(values) != 0) {
+ if (mod->mod_op & LDAP_MOD_BVALUES) {
+ if (mod->mod_vals.modv_bvals == NULL) {
+ /* request is to remove all values */
+ slapi_mods_add_smod(relevant, backend_shr_mod_as_smod(mod));
+ } else
+ for (j = 0; mod->mod_vals.modv_bvals[j] != NULL; j++) {
+ mbv = mod->mod_vals.modv_bvals[j];
+ mval = slapi_value_set_berval(mval, mbv);
+ if ((slapi_vattr_value_compare(pre, mod->mod_type, mval, &result, 0) == 0) &&
+ (result == 1)) {
+ /* request is to remove a value that is present */
+ slapi_mods_add_smod(relevant, backend_shr_mod_as_smod(mod));
+ break;
+ }
+ }
+ } else {
+ if (mod->mod_vals.modv_strvals == NULL) {
+ /* request is to remove all values */
+ slapi_mods_add_smod(relevant, backend_shr_mod_as_smod(mod));
+ } else
+ for (j = 0; mod->mod_vals.modv_strvals[j] != NULL; j++) {
+ msv.bv_val = mod->mod_vals.modv_strvals[j];
+ msv.bv_len = strlen(msv.bv_val);
+ mval = slapi_value_set_berval(mval, &msv);
+ if ((slapi_vattr_value_compare(pre, mod->mod_type, mval, &result, 0) == 0) &&
+ (result == 1)) {
+ /* request is to remove a value that is present */
+ slapi_mods_add_smod(relevant, backend_shr_mod_as_smod(mod));
+ break;
+ }
+ }
+ }
+ }
+ } else
+ if (SLAPI_IS_MOD_ADD(mod->mod_op)) {
+ /* if all of the provided values are already in the
+ * entry, then skip it */
+ if (mod->mod_op & LDAP_MOD_BVALUES) {
+ if (mod->mod_vals.modv_bvals != NULL) {
+ for (j = 0; mod->mod_vals.modv_bvals[j] != NULL; j++) {
+ mbv = mod->mod_vals.modv_bvals[j];
+ mval = slapi_value_set_berval(mval, mbv);
+ if ((slapi_vattr_value_compare(pre, mod->mod_type, mval, &result, 0) != 0) ||
+ (result != 1)) {
+ /* request is to add a value that is not present */
+ slapi_mods_add_smod(relevant, backend_shr_mod_as_smod(mod));
+ break;
+ }
+ }
+ }
+ } else {
+ if (mod->mod_vals.modv_strvals != NULL) {
+ for (j = 0; mod->mod_vals.modv_strvals[j] != NULL; j++) {
+ msv.bv_val = mod->mod_vals.modv_strvals[j];
+ msv.bv_len = strlen(msv.bv_val);
+ mval = slapi_value_set_berval(mval, &msv);
+ if ((slapi_vattr_value_compare(pre, mod->mod_type, mval, &result, 0) != 0) ||
+ (result != 1)) {
+ /* request is to add a value that is not present */
+ slapi_mods_add_smod(relevant, backend_shr_mod_as_smod(mod));
+ break;
+ }
+ }
+ }
+ }
+ } else
+ if (SLAPI_IS_MOD_REPLACE(mod->mod_op)) {
+ /* if the value set is the same as the list we're
+ * given, then skip it */
+ j = 0;
+ if (mod->mod_op & LDAP_MOD_BVALUES) {
+ if (mod->mod_vals.modv_bvals != NULL) {
+ for (j = 0; mod->mod_vals.modv_bvals[j] != NULL; j++) {
+ continue;
+ }
+ }
+ if (slapi_valueset_count(values) != j) {
+ /* different number of values */
+ slapi_mods_add_smod(relevant, backend_shr_mod_as_smod(mod));
+ } else {
+ for (j = 0;
+ (mod->mod_vals.modv_bvals != NULL) &&
+ (mod->mod_vals.modv_bvals[j] != NULL);
+ j++) {
+ mbv = mod->mod_vals.modv_bvals[j];
+ mval = slapi_value_set_berval(mval, mbv);
+ if ((slapi_vattr_value_compare(pre, mod->mod_type, mval, &result, 0) != 0) ||
+ (result != 1)) {
+ /* request includes a value that is not present */
+ slapi_mods_add_smod(relevant, backend_shr_mod_as_smod(mod));
+ break;
+ }
+ }
+ }
+ } else {
+ if (mod->mod_vals.modv_strvals != NULL) {
+ for (j = 0; mod->mod_vals.modv_strvals[j] != NULL; j++) {
+ continue;
+ }
+ }
+ if (slapi_valueset_count(values) != j) {
+ /* different number of values */
+ slapi_mods_add_smod(relevant, backend_shr_mod_as_smod(mod));
+ } else {
+ for (j = 0;
+ (mod->mod_vals.modv_strvals != NULL) &&
+ (mod->mod_vals.modv_strvals[j] != NULL);
+ j++) {
+ msv.bv_val = mod->mod_vals.modv_strvals[j];
+ msv.bv_len = strlen(msv.bv_val);
+ mval = slapi_value_set_berval(mval, &msv);
+ if ((slapi_vattr_value_compare(pre, mod->mod_type, mval, &result, 0) != 0) ||
+ (result != 1)) {
+ /* request includes a value that is not present */
+ slapi_mods_add_smod(relevant, backend_shr_mod_as_smod(mod));
+ break;
+ }
+ }
+ }
+ }
+ } else {
+ slapi_mods_add_smod(relevant, backend_shr_mod_as_smod(mod));
+ }
+ slapi_vattr_values_free(&values, &actual_attr, buffer_flags);
+ }
+ slapi_value_free(&mval);
+}
+
static int
backend_shr_modify_cb(Slapi_PBlock *pb)
{
@@ -1805,7 +1985,8 @@ backend_shr_modify_cb(Slapi_PBlock *pb)
/* Don't do a lot of work for other plugins which initiated a no-op
* modify. */
cbdata.real_mods = slapi_mods_new();
- slapi_entry_diff(cbdata.real_mods, cbdata.e_pre, cbdata.e_post, 0);
+ backend_shr_filter_mods(cbdata.mods, cbdata.e_pre, cbdata.e_post,
+ cbdata.real_mods);
cbdata.mods = slapi_mods_get_ldapmods_byref(cbdata.real_mods);
cbdata.ndn = slapi_entry_get_ndn(cbdata.e_pre);
if (cbdata.mods == NULL) {
@@ -1843,6 +2024,7 @@ backend_shr_modify_cb(Slapi_PBlock *pb)
cbdata.mods, cbdata.modlist);
/* Done with the "real" mods. Put the fake ones back. */
slapi_mods_free(&cbdata.real_mods);
+ cbdata.real_mods = NULL;
slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &cbdata.mods);
/* If it's a map configuration entry, reconfigure, clear, and
* repopulate the map. */