|
|
1.1 root 1: /* ds_modify.c - */
2:
3: #ifndef lint
4: static char *rcsid = "$Header: /f/osi/quipu/RCS/ds_modify.c,v 7.2 90/07/09 14:45:45 mrose Exp $";
5: #endif
6:
7: /*
8: * $Header: /f/osi/quipu/RCS/ds_modify.c,v 7.2 90/07/09 14:45:45 mrose Exp $
9: *
10: *
11: * $Log: ds_modify.c,v $
12: * Revision 7.2 90/07/09 14:45:45 mrose
13: * sync
14: *
15: * Revision 7.1 89/12/19 16:20:16 mrose
16: * sync
17: *
18: * Revision 7.0 89/11/23 22:17:10 mrose
19: * Release 6.0
20: *
21: */
22:
23: /*
24: * NOTICE
25: *
26: * Acquisition, use, and distribution of this module and related
27: * materials are subject to the restrictions of a license agreement.
28: * Consult the Preface in the User's Manual for the full terms of
29: * this agreement.
30: *
31: */
32:
33:
34: #include "quipu/config.h"
35: #include "quipu/util.h"
36: #include "quipu/entry.h"
37: #include "quipu/modify.h"
38: #include "quipu/malloc.h"
39: #include "config.h"
40:
41: static check_remove_values ();
42: static check_remove_type ();
43: extern Entry database_root;
44: extern LLog * log_dsap;
45: extern int encode_DAS_ModifyEntryArgumentData();
46:
47: struct acl *acl_list;
48: int updateerror;
49:
50: do_ds_modifyentry (arg, error, binddn, target, di_p, dsp)
51: struct ds_modifyentry_arg *arg;
52: struct DSError *error;
53: DN binddn;
54: DN target;
55: struct di_block **di_p;
56: char dsp;
57: {
58: Entry entryptr;
59: Entry real_entry;
60: struct entrymod *eptr;
61: Entry entry_cpy ();
62: int remove = NOTOK;
63: int retval;
64: extern AttributeType at_control;
65: extern AttributeType at_acl;
66: extern int read_only;
67: char * new_version ();
68: Attr_Sequence as;
69:
70: DLOG (log_dsap,LLOG_TRACE,("ds_modifyentry"));
71:
72: if (!dsp)
73: target = arg->mea_object;
74:
75: /* stop aliases being dereferenced */
76: arg->mea_common.ca_servicecontrol.svc_options |= SVC_OPT_DONTDEREFERENCEALIAS;
77:
78: /* check for control sequence */
79: if (!dsp && arg->mea_changes
80: && (arg->mea_changes->em_type == EM_ADDATTRIBUTE)) {
81: if ( AttrT_cmp (arg->mea_changes->em_what->attr_type,at_control) == 0) {
82: int res;
83: res = dsa_control (arg->mea_changes->em_what,error,binddn);
84: return (res);
85: }
86: }
87:
88: if (target == NULLDN) {
89: error->dse_type = DSE_NAMEERROR;
90: error->ERR_NAME.DSE_na_problem = DSE_NA_NOSUCHOBJECT;
91: error->ERR_NAME.DSE_na_matched = NULLDN;
92: return (DS_ERROR_REMOTE);
93: }
94:
95: switch(find_entry(target,&(arg->mea_common),binddn,NULLDNSEQ,TRUE,&(real_entry), error, di_p))
96: {
97: case DS_OK:
98: /* Filled out entryptr - carry on */
99: break;
100: case DS_CONTINUE:
101: /* Filled out di_p - what do we do with it ?? */
102: return(DS_CONTINUE);
103:
104: case DS_X500_ERROR:
105: /* Filled out error - what do we do with it ?? */
106: return(DS_X500_ERROR);
107: default:
108: /* SCREAM */
109: LLOG(log_dsap, LLOG_EXCEPTIONS, ("do_ds_modify() - find_entry failed"));
110: return(DS_ERROR_LOCAL);
111: }
112:
113: /* Strong authentication */
114: if ((retval = check_security_parms((caddr_t) arg,
115: encode_DAS_ModifyEntryArgumentData,
116: arg->mea_common.ca_security,
117: arg->mea_common.ca_sig, &binddn)) != 0)
118: {
119: error->dse_type = DSE_SECURITYERROR;
120: error->ERR_SECURITY.DSE_sc_problem = retval;
121: return (DS_ERROR_REMOTE);
122: }
123:
124: if (read_only || real_entry->e_parent->e_lock) {
125: error->dse_type = DSE_SERVICEERROR;
126: error->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNAVAILABLE;
127: return (DS_ERROR_REMOTE);
128: }
129:
130: /* not prepared to accept operation over DSP */
131: if (dsp) {
132: error->dse_type = DSE_SECURITYERROR;
133: error->ERR_SECURITY.DSE_sc_problem = DSE_SC_AUTHENTICATION;
134: return (DS_ERROR_REMOTE);
135: }
136:
137: DATABASE_HEAP;
138: entryptr = entry_cpy (real_entry);
139: acl_list = real_entry->e_acl;
140: GENERAL_HEAP;
141:
142: if (check_acl (binddn, ACL_ADD, acl_list->ac_entry,target) == NOTOK) {
143: error->dse_type = DSE_SECURITYERROR;
144: error->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
145: entry_free (entryptr);
146: return (DS_ERROR_REMOTE);
147: }
148:
149: if (check_acl (binddn, ACL_WRITE, acl_list->ac_entry,target) == OK)
150: remove = OK;
151:
152: for (eptr = arg->mea_changes; eptr!=NULLMOD; eptr=eptr->em_next) {
153: switch (eptr->em_type) {
154: case EM_ADDVALUES:
155: if (mod_add_value (entryptr,eptr->em_what,error,binddn,target,real_entry) != OK) {
156: entry_free (entryptr);
157: return (DS_ERROR_REMOTE);
158: }
159: break;
160: case EM_ADDATTRIBUTE:
161: if (add_attribute (entryptr,eptr->em_what,error,binddn,target) != OK) {
162: entry_free (entryptr);
163: return (DS_ERROR_REMOTE);
164: }
165: break;
166: case EM_REMOVEATTRIBUTE:
167: /* must not do this if attribute is rdn */
168: if (check_remove_type (entryptr->e_name,eptr->em_what->attr_type) == NOTOK) {
169: error->dse_type = DSE_UPDATEERROR;
170: error->ERR_UPDATE.DSE_up_problem = updateerror;;
171:
172: entry_free (entryptr);
173: return (DS_ERROR_REMOTE);
174: }
175: if (remove == OK) {
176: if (remove_attribute (entryptr,eptr->em_what->attr_type,error,binddn,target,real_entry) != OK) {
177: entry_free (entryptr);
178: return (DS_ERROR_REMOTE);
179: }
180: } else {
181: error->dse_type = DSE_SECURITYERROR;
182: error->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
183: entry_free (entryptr);
184: return (DS_ERROR_REMOTE);
185: }
186: break;
187: case EM_REMOVEVALUES:
188: if (check_remove_values (entryptr->e_name, eptr->em_what) == NOTOK) {
189: error->dse_type = DSE_UPDATEERROR;
190: error->ERR_UPDATE.DSE_up_problem = updateerror;;
191:
192: entry_free (entryptr);
193: return (DS_ERROR_REMOTE);
194: }
195: if (remove == OK) {
196: if (remove_value (entryptr,eptr->em_what,error,binddn,target,real_entry) != OK) {
197: entry_free (entryptr);
198: return (DS_ERROR_REMOTE);
199: }
200: } else {
201: error->dse_type = DSE_SECURITYERROR;
202: error->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
203: entry_free (entryptr);
204: return (DS_ERROR_REMOTE);
205: }
206: break;
207: }
208: }
209:
210: /* check the last value of an attribute has not been removed */
211: for (as = entryptr->e_attributes; as!=NULLATTR; as=as->attr_link)
212: if (as->attr_value == NULLAV) {
213: error->dse_type = DSE_ATTRIBUTEERROR;
214: error->ERR_ATTRIBUTE.DSE_at_name = get_copy_dn (entryptr);
215: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what =DSE_AT_CONSTRAINTVIOLATION;
216: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy (as->attr_type);
217: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = NULLAttrV;
218: error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = DSE_AT_NOPROBLEM;
219: entry_free (entryptr);
220: return (DS_ERROR_REMOTE);
221: }
222:
223: DATABASE_HEAP;
224: modify_attr (entryptr,binddn);
225: if (unravel_attribute (entryptr,error) != OK) {
226: GENERAL_HEAP;
227: entry_free (entryptr);
228: return (DS_ERROR_REMOTE);
229: } else if (check_schema (entryptr,NULLATTR,error) == OK) {
230: GENERAL_HEAP;
231:
232: /* Check user has not prevented further modification by themselves ! */
233: if ((acl_list != entryptr->e_acl)
234: && (acl_cmp (acl_list,entryptr->e_acl) != 0)) {
235: as = as_find_type (entryptr->e_attributes,at_acl);
236: if ((check_acl (binddn, ACL_WRITE, as->attr_acl,target) == NOTOK) ||
237: (check_acl (binddn, ACL_WRITE, entryptr->e_acl->ac_entry,target) == NOTOK)) {
238: entry_free (entryptr);
239: LLOG(log_dsap,LLOG_NOTICE,("Not modifying due to future access problem"));
240: error->dse_type = DSE_SERVICEERROR;
241: error->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNWILLINGTOPERFORM;
242: return (DS_ERROR_REMOTE);
243: }
244: }
245:
246: /* changes made OK, so add new entry into tree */
247: if (entryptr->e_parent == NULLENTRY) {
248: database_root = entryptr;
249: entry_free (real_entry);
250: } else {
251: entryptr->e_parent->e_child = entryptr;
252: entry_free (real_entry);
253: /* now alter all parent pointers */
254: for (real_entry = entryptr->e_child; real_entry!=NULLENTRY; real_entry=real_entry->e_sibling)
255: real_entry->e_parent = entryptr;
256: }
257:
258: if (entryptr->e_parent != NULLENTRY) {
259: if (entryptr->e_parent->e_edbversion)
260: free (entryptr->e_parent->e_edbversion);
261: entryptr->e_parent->e_edbversion = new_version();
262: }
263: #ifdef TURBO_DISK
264: if (turbo_write(entryptr) != OK)
265: fatal (-33,"modify rewrite failed - check database");
266: #else
267: if (journal (entryptr) != OK)
268: fatal (-33,"modify rewrite failed - check database");
269: #endif
270:
271: return (DS_OK);
272: } else {
273: entry_free (entryptr);
274: return (DS_ERROR_REMOTE);
275: }
276: }
277:
278: remove_attribute (eptr,at,error,requestor,dn,real_entry)
279: Entry eptr,real_entry;
280: AttributeType at;
281: struct DSError *error;
282: DN requestor,dn;
283: {
284: register Attr_Sequence as, trail= NULLATTR, real_as;
285: extern oid_table_attr * tab_acl;
286:
287: DLOG (log_dsap,LLOG_DEBUG,("remove attribute"));
288:
289: for (as=eptr->e_attributes; as!=NULLATTR; as=as->attr_link) {
290: if ((AttrT_cmp (as->attr_type,at)) == 0)
291: break;
292: trail = as;
293: }
294: if (as == NULLATTR) {
295: error->dse_type = DSE_ATTRIBUTEERROR;
296: error->ERR_ATTRIBUTE.DSE_at_name = get_copy_dn (eptr);
297: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what =DSE_AT_NOSUCHATTRIBUTE;
298: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy (at);
299: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = NULLAttrV;
300: error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = DSE_AT_NOPROBLEM;
301: return (DS_ERROR_REMOTE);
302: }
303:
304: if ( (real_as = as_find_type (real_entry->e_attributes,at)) == NULLATTR) {
305: error->dse_type = DSE_ATTRIBUTEERROR;
306: error->ERR_ATTRIBUTE.DSE_at_name = get_copy_dn (eptr);
307: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what =DSE_AT_NOSUCHATTRIBUTE;
308: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy (at);
309: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = NULLAttrV;
310: error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = DSE_AT_NOPROBLEM;
311: return (DS_ERROR_REMOTE);
312: }
313:
314: if (check_acl(requestor,ACL_WRITE,real_as->attr_acl,dn) == NOTOK) {
315: error->dse_type = DSE_SECURITYERROR;
316: error->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
317: return (DS_ERROR_REMOTE);
318: }
319:
320: if (trail == NULLATTR) {
321: /* first in sequence */
322: eptr->e_attributes = as->attr_link;
323: as_comp_free (as);
324: } else
325: as_delnext (trail);
326:
327: return (OK);
328: }
329:
330:
331: static check_remove_type (rdn,at)
332: register RDN rdn;
333: register AttributeType at;
334: {
335: extern AttributeType at_objectclass;
336:
337: if ( AttrT_cmp (at,at_objectclass) == 0) {
338: updateerror = DSE_UP_NOOBJECTCLASSMODS;
339: return (NOTOK);
340: }
341:
342: /* check attribute type is not distinguished */
343:
344: for (; rdn!=NULLRDN; rdn=rdn->rdn_next)
345: if (AttrT_cmp (rdn->rdn_at,at) == 0) {
346: updateerror = DSE_UP_NOTONRDN;
347: return (NOTOK);
348: }
349: return (OK);
350: }
351:
352: static check_remove_values (rdn,as)
353: register RDN rdn;
354: register Attr_Sequence as;
355: {
356: register AV_Sequence as_avs;
357: extern AttributeType at_objectclass;
358:
359: /* check that the value trying to remove is not distinguished */
360: for (; rdn!=NULLRDN; rdn=rdn->rdn_next)
361: if (AttrT_cmp (rdn->rdn_at,as->attr_type) == 0)
362: for (as_avs=as->attr_value; as_avs!=NULLAV; as_avs=as_avs->avseq_next)
363: if (AttrV_cmp (&rdn->rdn_av,&as_avs->avseq_av) == 0) {
364: updateerror = DSE_UP_NOTONRDN;
365: return (NOTOK);
366: }
367: return (OK);
368: }
369:
370:
371:
372: remove_value (eptr,rmas,error,requestor,dn,real_entry)
373: Entry eptr, real_entry;
374: Attr_Sequence rmas;
375: struct DSError *error;
376: DN requestor,dn;
377: {
378: register Attr_Sequence as,real_as;
379: register AV_Sequence rmavs,avs,trail = NULLAV;
380: int i;
381:
382:
383: DLOG (log_dsap,LLOG_DEBUG,("remove attribute value"));
384:
385: for (as=eptr->e_attributes; as!=NULLATTR; as=as->attr_link) {
386: if ((AttrT_cmp (as->attr_type,rmas->attr_type)) == 0)
387: break;
388: }
389: if (as == NULLATTR) {
390: error->dse_type = DSE_ATTRIBUTEERROR;
391: error->ERR_ATTRIBUTE.DSE_at_name = get_copy_dn (eptr);
392: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what =DSE_AT_NOSUCHATTRIBUTE;
393: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy (rmas->attr_type);
394: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = NULLAttrV;
395: error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = DSE_AT_NOPROBLEM;
396: return (DS_ERROR_REMOTE);
397: }
398:
399: if ( (real_as = as_find_type (real_entry->e_attributes,as->attr_type)) == NULLATTR) {
400: error->dse_type = DSE_ATTRIBUTEERROR;
401: error->ERR_ATTRIBUTE.DSE_at_name = get_copy_dn (eptr);
402: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what =DSE_AT_NOSUCHATTRIBUTE;
403: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy (rmas->attr_type);
404: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = NULLAttrV;
405: error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = DSE_AT_NOPROBLEM;
406: return (DS_ERROR_REMOTE);
407: }
408:
409: if (check_acl(requestor,ACL_WRITE,real_as->attr_acl,dn) == NOTOK) {
410: error->dse_type = DSE_SECURITYERROR;
411: error->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
412: return (NOTOK);
413: }
414:
415: for (rmavs=rmas->attr_value; rmavs != NULLAV; rmavs = rmavs->avseq_next) {
416:
417: for (avs=as->attr_value; avs!=NULLAV; avs=avs->avseq_next) {
418: if ((i = AttrV_cmp(&avs->avseq_av,&rmas->attr_value->avseq_av)) == 0)
419: break;
420: if (i == -2) {
421: error->dse_type = DSE_ATTRIBUTEERROR;
422: error->ERR_ATTRIBUTE.DSE_at_name = NULLDN;
423: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what = DSE_AT_INAPPROPRIATEMATCHING;
424: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy (as->attr_type);
425: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = AttrV_cpy(&rmas->attr_value->avseq_av);
426: error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = DSE_AT_NOPROBLEM;
427: return (DS_ERROR_REMOTE);
428: }
429: trail = avs;
430: }
431:
432: if (avs == NULLAV) {
433: error->dse_type = DSE_ATTRIBUTEERROR;
434: error->ERR_ATTRIBUTE.DSE_at_name = get_copy_dn (eptr);
435: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what =DSE_AT_NOSUCHATTRIBUTE;
436: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy (rmas->attr_type);
437: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = AttrV_cpy (&rmas->attr_value->avseq_av);
438: error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = DSE_AT_NOPROBLEM;
439: return (DS_ERROR_REMOTE);
440: }
441: if (trail == NULLAV) {
442: /* first in sequence */
443: as->attr_value = avs->avseq_next;
444: avs_comp_free (avs);
445: } else
446: avs_delnext (trail);
447: }
448:
449: return (OK);
450: }
451:
452: add_attribute (eptr,newas,error,requestor,dn)
453: Entry eptr;
454: Attr_Sequence newas;
455: struct DSError *error;
456: DN requestor,dn;
457: {
458: struct acl_attr * aa;
459: struct acl_info * ai = NULLACL_INFO;
460: struct oid_seq * oidptr;
461:
462: DLOG (log_dsap,LLOG_DEBUG,("add attribute"));
463:
464: if (as_find_type (eptr->e_attributes,newas->attr_type) != NULLATTR) {
465: error->dse_type = DSE_ATTRIBUTEERROR;
466: error->ERR_ATTRIBUTE.DSE_at_name = dn_cpy (dn);
467: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what = DSE_AT_TYPEORVALUEEXISTS;
468: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy (newas->attr_type);
469: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = NULLAttrV;
470: error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = DSE_AT_NOPROBLEM;
471: DLOG (log_dsap,LLOG_DEBUG,("add exists error"));
472: return (NOTOK);
473: }
474:
475: for ( aa = acl_list->ac_attributes; aa!=NULLACL_ATTR; aa=aa->aa_next) {
476: for ( oidptr=aa->aa_types;oidptr != NULLOIDSEQ; oidptr=oidptr->oid_next) {
477: if (oid_cmp (oidptr->oid_oid,grab_oid(newas->attr_type)) == 0) {
478: ai = aa->aa_acl;
479: break;
480: }
481: }
482: if (ai != NULLACL_INFO)
483: break;
484: }
485: if (ai == NULLACL_INFO)
486: ai = acl_list->ac_default;
487:
488: if (check_acl(requestor,ACL_WRITE,ai,dn) == NOTOK) {
489: error->dse_type = DSE_SECURITYERROR;
490: error->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
491: DLOG (log_dsap,LLOG_DEBUG,("add acl failed"));
492: return (NOTOK);
493: }
494:
495: DATABASE_HEAP;
496: eptr->e_attributes = as_merge (as_cpy(newas),eptr->e_attributes);
497: GENERAL_HEAP;
498:
499: return (OK);
500: }
501:
502:
503: mod_add_value (eptr,newas,error,requestor,dn,real_entry)
504: Entry eptr,real_entry;
505: Attr_Sequence newas;
506: struct DSError *error;
507: DN requestor,dn;
508: {
509: register Attr_Sequence as;
510: AV_Sequence avs;
511:
512: DLOG (log_dsap,LLOG_DEBUG,("add value"));
513:
514: if ( (as = as_find_type (real_entry->e_attributes,newas->attr_type)) == NULLATTR) {
515: error->dse_type = DSE_ATTRIBUTEERROR;
516: error->ERR_ATTRIBUTE.DSE_at_name = dn_cpy (dn);
517: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what = DSE_AT_NOSUCHATTRIBUTE;
518: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy (newas->attr_type);
519: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = NULLAttrV;
520: error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = DSE_AT_NOPROBLEM;
521: return (NOTOK);
522: }
523:
524: if (check_acl(requestor,ACL_WRITE,as->attr_acl,dn) == NOTOK) {
525: error->dse_type = DSE_SECURITYERROR;
526: error->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
527: DLOG (log_dsap,LLOG_DEBUG,("add acl failed"));
528: return (NOTOK);
529: }
530:
531: for (avs=as->attr_value; avs != NULLAV; avs=avs->avseq_next)
532: if (AttrV_cmp(&avs->avseq_av,&newas->attr_value->avseq_av) == 0) {
533: error->dse_type = DSE_ATTRIBUTEERROR;
534: error->ERR_ATTRIBUTE.DSE_at_name = dn_cpy (dn);
535: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what = DSE_AT_TYPEORVALUEEXISTS;
536: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy (newas->attr_type);
537: error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = AttrV_cpy (&newas->attr_value->avseq_av);
538: error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = DSE_AT_NOPROBLEM;
539: DLOG (log_dsap,LLOG_DEBUG,("add value exists error"));
540: return (NOTOK);
541: }
542:
543: DATABASE_HEAP;
544: eptr->e_attributes = as_merge (as_cpy(newas),eptr->e_attributes);
545: GENERAL_HEAP;
546:
547: return (OK);
548: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.