|
|
1.1 root 1: /* update.c - write EDB back to disk after modify */
2:
3: #ifndef lint
4: static char *rcsid = "$Header: /f/osi/quipu/RCS/update.c,v 7.3 90/07/09 14:46:49 mrose Exp $";
5: #endif
6:
7: /*
8: * $Header: /f/osi/quipu/RCS/update.c,v 7.3 90/07/09 14:46:49 mrose Exp $
9: *
10: *
11: * $Log: update.c,v $
12: * Revision 7.3 90/07/09 14:46:49 mrose
13: * sync
14: *
15: * Revision 7.2 90/03/15 11:19:14 mrose
16: * quipu-sync
17: *
18: * Revision 7.1 89/12/19 16:20:54 mrose
19: * sync
20: *
21: * Revision 7.0 89/11/23 22:18:18 mrose
22: * Release 6.0
23: *
24: */
25:
26: /*
27: * NOTICE
28: *
29: * Acquisition, use, and distribution of this module and related
30: * materials are subject to the restrictions of a license agreement.
31: * Consult the Preface in the User's Manual for the full terms of
32: * this agreement.
33: *
34: */
35:
36:
37: #include "quipu/util.h"
38: #include "quipu/entry.h"
39: #include "tailor.h"
40: #include "quipu/read.h"
41: #include "quipu/dua.h"
42: #include "quipu/connection.h"
43:
44: #ifndef NO_STATS
45: extern LLog * log_stat;
46: #endif
47: extern int dn_print ();
48: extern char *new_version ();
49:
50: extern LLog * log_dsap;
51: extern char remote_lookup;
52: extern int local_slave_size;
53: extern int slave_edbs;
54: extern DN mydsadn;
55: struct oper_act * oper_alloc();
56: struct oper_act * make_get_edb_op();
57:
58: /* routine name is historic - not significant */
59:
60: journal (myentry)
61: Entry myentry;
62: {
63: char * filename, *dn2edbfile();
64: char savefile [LINESIZE], newfile[LINESIZE];
65: DN dn;
66: extern char * treedir;
67: extern char * parse_file;
68: Entry liststart;
69: extern int errno;
70:
71: if (myentry == NULLENTRY) {
72: LLOG (log_dsap,LLOG_FATAL,("update edb problem"));
73: return NOTOK;
74: }
75:
76: if ((myentry->e_parent != NULLENTRY) && (myentry->e_parent->e_leaf)) {
77: liststart = myentry;
78: dn = get_copy_dn (liststart->e_parent);
79: if ((filename = dn2edbfile (dn)) == NULLCP) {
80: dn_free (dn);
81: return NOTOK;
82: }
83: myentry->e_parent->e_leaf = FALSE; /* not a leaf now !! */
84:
85: if ( write_edb(liststart,filename) != OK)
86: return NOTOK;
87: } else {
88: if (myentry->e_parent == NULLENTRY) {
89: liststart = myentry;
90: dn = NULLDN;
91: } else {
92: liststart = myentry->e_parent->e_child;
93: dn = get_copy_dn (liststart->e_parent);
94: }
95: if ((filename = dn2edbfile (dn)) == NULLCP) {
96: dn_free (dn);
97: return NOTOK;
98: }
99:
100: (void) strcpy (newfile,filename);
101: (void) strcat (newfile,".new");
102:
103: if ( write_edb(liststart,newfile) != OK) {
104: (void) unlink (newfile);
105: return NOTOK;
106: }
107:
108: (void) strcpy (savefile,filename);
109: (void) strcat (savefile,".bak");
110:
111: (void) unlink (savefile);
112: if (link (filename, savefile) == NOTOK)
113: SLOG (log_dsap, LLOG_EXCEPTIONS, savefile,
114: ("unable to link %s to", filename));
115: if (rename (newfile, filename) == NOTOK) {
116: SLOG (log_dsap, LLOG_EXCEPTIONS, filename,
117: ("unable to rename %s to", newfile));
118: if (link (savefile, filename) == NOTOK
119: && !fileexists (filename))
120: LLOG (log_dsap, LLOG_EXCEPTIONS,
121: ("and couldn't get old file back - PANIC!!!"));
122: return NOTOK;
123: }
124: }
125:
126: return OK;
127: }
128:
129: modify_attr (eptr,who)
130: Entry eptr;
131: DN who;
132: {
133: AttributeType at;
134: AttributeValue av;
135: AV_Sequence avs;
136: Attr_Sequence as, old;
137: extern int no_last_mod;
138:
139: if (no_last_mod)
140: return;
141:
142: if ((at = AttrT_new (LAST_MOD_OID)) == NULLAttrT) {
143: LLOG (log_dsap, LLOG_EXCEPTIONS, ("last mod oid missing"));
144: return;
145: }
146:
147: av = AttrV_alloc ();
148: av->av_syntax = str2syntax ("UTCTime");
149: av->av_struct = (caddr_t) new_version();
150:
151: avs = avs_comp_new(av);
152:
153: if ((old = as_find_type (eptr->e_attributes,at)) == NULLATTR) {
154: as = as_comp_new (at,avs,NULLACL_INFO);
155: eptr->e_attributes = as_merge (eptr->e_attributes,as);
156: } else {
157: avs_free (old->attr_value);
158: old->attr_value = avs;
159: AttrT_free (at);
160: }
161:
162: if ((at = AttrT_new (MOD_BY_OID)) == NULLAttrT) {
163: LLOG (log_dsap, LLOG_EXCEPTIONS, ("last mod by oid missing"));
164: return;
165: }
166:
167: av = AttrV_alloc ();
168: av->av_syntax = str2syntax ("DN");
169: av->av_struct = (caddr_t) dn_cpy (who);
170:
171: avs = avs_comp_new(av);
172:
173: if ((old = as_find_type (eptr->e_attributes,at)) == NULLATTR) {
174: as = as_comp_new (at,avs,NULLACL_INFO);
175: eptr->e_attributes = as_merge (eptr->e_attributes,as);
176: } else {
177: avs_free (old->attr_value);
178: old->attr_value = avs;
179: AttrT_free (at);
180: }
181: }
182:
183: static allowed_to_send (a,b)
184: register DN a,b;
185: {
186: /* Return TRUE if the DNs are the same */
187: /* Return TRUE if all components of 'a' match, but 'b' has one extra */
188: /* False otherwise */
189:
190: if ((a == NULLDN) || (b == NULLDN))
191: return FALSE;
192:
193: for (; a != NULLDN && b != NULLDN ; a = a->dn_parent, b = b->dn_parent)
194: if ( dn_comp_cmp (a,b) == NOTOK)
195: return FALSE;
196:
197: if (( b == NULLDN) || (b->dn_parent == NULLDN))
198: return TRUE;
199: else
200: return FALSE;
201:
202: }
203:
204:
205: do_get_edb (arg,error,result,binddn)
206: struct getedb_arg *arg;
207: struct DSError *error;
208: struct getedb_result *result;
209: DN binddn;
210: {
211: Entry eptr;
212: Entry my_entry;
213: AV_Sequence avs;
214: struct edb_info * dsainfo;
215: char proceed = FALSE;
216: struct dn_seq * dnseq;
217: struct di_block * di;
218:
219: DLOG (log_dsap,LLOG_DEBUG,("getedb '%s'",arg->ga_version));
220:
221: switch(really_find_entry (arg->ga_entry,FALSE,NULLDNSEQ,FALSE,&(eptr),error,&(di)))
222: {
223: case DS_OK:
224: /*
225: * Entry has been found and returned via eptr.
226: * Go through and process this entry.
227: */
228: break;
229:
230: case DS_CONTINUE:
231: /*
232: * Get edb operations should never generate referrals.
233: * Free the di_blocks generated and return an error.
234: */
235: error->dse_type = DSE_SERVICEERROR;
236: error->ERR_SERVICE.DSE_sv_problem = DSE_SV_CHAININGREQUIRED;
237: return (DS_X500_ERROR);
238:
239: case DS_X500_ERROR:
240: /* something wrong with the request - error should be filled out */
241: return(DS_X500_ERROR);
242:
243: default:
244: LLOG(log_dsap, LLOG_EXCEPTIONS, ("do_get_edb() - really_find_entry() failed"));
245: error->dse_type = DSE_SERVICEERROR;
246: error->ERR_SERVICE.DSE_sv_problem = DSE_SV_DITERROR;
247: return (DS_X500_ERROR);
248: }
249:
250: if ((my_entry = local_find_entry (mydsadn,TRUE)) == NULLENTRY)
251: fatal (84,"my entry has gone - no getedb");
252:
253: /* Check we will send to this DSA */
254: for (avs = my_entry->e_dsainfo->dsa_attr ; avs != NULLAV; avs=avs->avseq_next) {
255: if (avs->avseq_av.av_struct == NULL)
256: continue;
257: dsainfo = (struct edb_info *) avs->avseq_av.av_struct;
258: if (dn_cmp(dsainfo->edb_name,arg->ga_entry) == 0) {
259: for (dnseq=dsainfo->edb_allowed; dnseq!=NULLDNSEQ; dnseq=dnseq->dns_next) {
260: if (allowed_to_send(dnseq->dns_dn,binddn)) {
261: proceed = TRUE;
262: break;
263: }
264: }
265: }
266: if (proceed)
267: break;
268: }
269:
270: if (!proceed) {
271: error->dse_type = DSE_SECURITYERROR;
272: error->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
273: return (DS_ERROR_REMOTE);
274: }
275:
276: if ((eptr->e_child == NULLENTRY)
277: || ((eptr->e_child->e_data != E_DATA_MASTER)
278: && (eptr->e_child->e_data != E_TYPE_SLAVE))) {
279: error->dse_type = DSE_SERVICEERROR;
280: error->ERR_SERVICE.DSE_sv_problem = DSE_SV_DITERROR;
281: return (DS_X500_ERROR);
282: }
283:
284: if (eptr->e_edbversion != NULLCP) {
285: DLOG(log_dsap, LLOG_DEBUG, ("edb_ver = %s", eptr->e_edbversion));
286:
287: if (lexequ (arg->ga_version,eptr->e_edbversion) == 0) {
288: result->gr_version = eptr->e_edbversion;
289: result->gr_edb = NULLENTRY;
290: result->gr_next = NULL_GETRESULT;
291: return (DS_OK);
292: }
293: } else
294: eptr->e_edbversion = new_version();
295:
296: result->gr_version = eptr->e_edbversion;
297: result->gr_edb = eptr->e_child;
298: result->gr_next = NULL_GETRESULT;
299: return (DS_OK);
300: }
301:
302: slave_update ()
303: {
304: extern time_t lastedb_update, timenow;
305:
306: (void) update_aux (NULLDN, 0);
307: lastedb_update = timenow;
308: }
309:
310: update_aux (dn, isroot)
311: DN dn;
312: int isroot;
313: {
314: Entry my_entry, make_path();
315: Entry find_sibling();
316: extern DN mydsadn;
317: struct edb_info * dsainfo;
318: Entry eptr;
319: static char *version = NULLCP;
320: AV_Sequence avs;
321: AV_Sequence avs_head;
322: int success;
323:
324: DLOG (log_dsap,LLOG_TRACE,("slave update"));
325:
326: if ((my_entry = local_find_entry (mydsadn,TRUE)) == NULLENTRY)
327: fatal (82,"Can't update slaves - my entry has gone");
328:
329: avs_head = avs_cpy(my_entry->e_dsainfo->dsa_attr);
330:
331: for (avs = avs_head ; avs != NULLAV; avs=avs->avseq_next)
332: {
333: if (avs->avseq_av.av_struct == NULL)
334: continue;
335: dsainfo = (struct edb_info *) avs->avseq_av.av_struct;
336: if (dsainfo->edb_getfrom == NULLDN)
337: continue; /* not an EDB to update */
338: if ((dn || isroot) && dn_cmp (dn, dsainfo -> edb_name) != OK)
339: continue; /* not an EDB this time */
340:
341: if ((eptr = local_find_entry (dsainfo->edb_name,FALSE)) == NULLENTRY) {
342: version = "0000000000Z";
343: eptr = make_path (dsainfo->edb_name);
344: }
345: else
346: {
347: if((version = eptr->e_edbversion) == NULLCP)
348: {
349: LLOG(log_dsap, LLOG_NOTICE, ("update_aux: edbversion was NULLCP"));
350: version = "0000000000Z";
351: }
352: }
353:
354: success = send_get_edb(version, dsainfo->edb_name, dsainfo->edb_getfrom);
355:
356: if(dn || isroot)
357: break;
358:
359: dsa_wait (0); /* accept any results of previous ops */
360:
361: }
362: avs_free (avs_head);
363:
364: return((dn || isroot) ? success : OK);
365: }
366:
367: int send_get_edb (version,dn,from)
368: char * version;
369: DN dn,from;
370: {
371: struct di_block * di;
372: struct DSError error;
373: struct oper_act * on;
374: char buffer[BUFSIZ];
375: PS ps;
376:
377: switch(get_dsa_info(from, NULLDNSEQ, &(error), &(di)))
378: {
379: case DS_OK:
380: /*
381: * di is a completed dsa info block
382: * Make a get_edb operation from it, attempt to send the operation
383: * and link the operation onto the global list of get_edb
384: * operations.
385: */
386: if (ps = ps_alloc (str_open)) {
387: if (str_setup (ps, buffer, sizeof buffer, 1) != NOTOK) {
388: ps_printf (ps, "contact ");
389: dn_print (ps, from, EDBOUT);
390: ps_printf (ps, " for ");
391: if (dn)
392: dn_print (ps, dn, EDBOUT);
393: *ps -> ps_ptr = NULL;
394:
395: LLOG (log_dsap, LLOG_NOTICE, ("%s", buffer));
396: }
397:
398: (void) ps_free (ps);
399: }
400:
401: #ifdef DEBUG
402: DLOG(log_dsap, LLOG_DEBUG, ("send_get_edb - get_dsa_info OK:"));
403: di_list_log(di);
404: #endif
405: if((on = make_get_edb_op(dn, version, di)) == NULLOPER)
406: {
407: /* Flake out screaming */
408: LLOG(log_dsap, LLOG_EXCEPTIONS, ("make_get_edb_op failed for send_get_edb"));
409: return(NOTOK);
410: }
411:
412: if(oper_chain(on) != OK)
413: {
414: LLOG(log_dsap, LLOG_NOTICE, ("Could not chain a getEDB operation"));
415: return(NOTOK);
416: }
417:
418: on->on_next_task = get_edb_ops;
419: get_edb_ops = on;
420: return(OK);
421:
422: case DS_CONTINUE:
423: /*
424: * di is a deferred dsa info block
425: * make the operation and suspend waiting for the di_block to be
426: * woken up.
427: */
428: #ifdef DEBUG
429: DLOG(log_dsap, LLOG_DEBUG, ("send_get_edb - get_dsa_info CONT:"));
430: di_list_log(di);
431: #endif
432: if((on = make_get_edb_op(dn, version, di)) == NULLOPER)
433: {
434: /* Flake out screaming */
435: LLOG(log_dsap, LLOG_EXCEPTIONS, ("make_get_edb_op failed for send_get_edb"));
436: return(NOTOK);
437: }
438:
439: on->on_state = ON_DEFERRED;
440:
441: on->on_next_task = get_edb_ops;
442: get_edb_ops = on;
443:
444: if (ps = ps_alloc (str_open)) {
445: if (str_setup (ps, buffer, sizeof buffer, 1) != NOTOK) {
446: ps_printf (ps, "contact ");
447: dn_print (ps, from, EDBOUT);
448: ps_printf (ps, " for ");
449: if (dn)
450: dn_print (ps, dn, EDBOUT);
451: *ps -> ps_ptr = NULL;
452:
453: LLOG (log_dsap, LLOG_NOTICE, ("%s", buffer));
454: }
455:
456: (void) ps_free (ps);
457: }
458:
459: return(OK);
460:
461: case DS_X500_ERROR:
462: /* Error encountered generating di_block */
463: LLOG(log_dsap, LLOG_NOTICE, ("send_get_edb - get_dsa_info returned X500 ERROR"));
464: log_ds_error (&error);
465: ds_error_free (&error);
466: return(NOTOK);
467:
468: default:
469: LLOG(log_dsap, LLOG_EXCEPTIONS, ("send_get_edb - get_dsa_info unexpected return"));
470: return(NOTOK);
471: }
472: /* NOTREACHED */
473: }
474:
475: process_edb(on)
476: struct oper_act * on;
477: {
478: extern DN mydsadn;
479: Entry make_path(), find_sibling();
480: Entry new_entry, old_entry, temp, sibl, next;
481: Entry eptr;
482: /* up 'n' down to make sure first child !!! */
483: struct DSError error;
484: struct getedb_result * result = &(on->on_resp.di_result.dr_res.dcr_dsres.res_ge);
485: int entry_cnt = 0;
486:
487: if ((eptr = local_find_entry (on->on_req.dca_dsarg.arg_ge.ga_entry,FALSE)) == NULLENTRY) {
488: pslog (log_dsap,LLOG_EXCEPTIONS,"Updating something which does not exist !!!",
489: dn_print,(caddr_t)on->on_req.dca_dsarg.arg_ge.ga_entry);
490: return;
491: }
492:
493: if ((new_entry = result->gr_edb) == NULLENTRY) {
494: DLOG (log_dsap, LLOG_NOTICE,(" EDBs are the same (%d): %s",on->on_id,on->on_getedb_ver));
495: return;
496: } else {
497: DLOG (log_dsap, LLOG_NOTICE,(" EDB updated from (%d): %s to: %s", on->on_id,on->on_getedb_ver, result->gr_version));
498: ;
499: }
500:
501: #ifndef NO_STATS
502: {
503: DN tmp_dn;
504: tmp_dn = get_copy_dn (eptr);
505: pslog (log_stat,LLOG_NOTICE,"Slave update",dn_print,(caddr_t)tmp_dn);
506: dn_free (tmp_dn);
507: }
508: #endif
509:
510: if (eptr->e_edbversion)
511: free (eptr->e_edbversion);
512:
513: if (result->gr_version == NULLCP) {
514: eptr->e_edbversion = "Unknown";
515: LLOG(log_dsap, LLOG_EXCEPTIONS, ("EDBRES: NULL version"));
516: } else
517: eptr->e_edbversion = strdup (result->gr_version);
518:
519: for (temp = new_entry; temp != NULLENTRY; temp=temp->e_sibling) {
520: temp->e_parent = eptr;
521: if (unravel_attribute (temp,&error) != OK) {
522: LLOG (log_dsap,LLOG_EXCEPTIONS, ("Error in new EDB - continuing with old"));
523: log_ds_error (&error);
524: return;
525: }
526: }
527:
528: for (temp = new_entry; temp != NULLENTRY; temp=temp->e_sibling) {
529: entry_cnt++;
530: if ((old_entry = find_sibling (temp->e_name,eptr->e_child)) != NULLENTRY) {
531: temp->e_leaf = old_entry->e_leaf;
532: temp->e_allchildrenpresent = old_entry->e_allchildrenpresent;
533: temp->e_child = old_entry->e_child;
534: for (sibl = temp->e_child; sibl != NULLENTRY; sibl=sibl->e_sibling)
535: sibl->e_parent = temp;
536: if (old_entry->e_edbversion != NULLCP)
537: temp->e_edbversion = strdup (old_entry->e_edbversion);
538: }
539:
540: }
541:
542: if (eptr->e_child == NULLENTRY)
543: slave_edbs++;
544:
545: for (temp = eptr->e_child; temp != NULLENTRY; temp=next) {
546: next = temp->e_sibling;
547: local_slave_size--;
548: entry_free (temp);
549: }
550:
551: sync (); /* Photos - no evidence - just a guess !!! */
552:
553: local_slave_size += entry_cnt;
554: eptr->e_child = new_entry;
555: eptr->e_allchildrenpresent = TRUE;
556: eptr->e_leaf = FALSE;
557:
558: #ifdef TURBO_DISK
559: if (turbo_writeall(new_entry) != OK)
560: fatal (-79,"Lost old EDB, can't write new one!!!");
561: #else
562: if (journal (new_entry) != OK)
563: fatal (-79,"Lost old EDB, can't write new one !!!");
564: #endif
565:
566: if (local_find_entry (mydsadn,TRUE) == NULLENTRY)
567: fatal (-80,"My entry has disappeared from the DIT !!!");
568: }
569:
570: /*
571: * get_edb_fail_wakeup suffices for both fail and error conditions
572: * arising on a get edb operation.
573: */
574: get_edb_fail_wakeup(on)
575: struct oper_act * on;
576: {
577: struct oper_act * on_tmp;
578: struct oper_act **on_p;
579:
580: DLOG(log_dsap, LLOG_TRACE, ("get_edb_fail_wakeup"));
581:
582: /* Should do extra logging here */
583:
584: on_p = &(get_edb_ops);
585: for(on_tmp = get_edb_ops; on_tmp != NULLOPER; on_tmp = on_tmp->on_next_task)
586: {
587: if(on_tmp == on)
588: break;
589:
590: on_p = &(on_tmp->on_next_task);
591: }
592:
593: if(on_tmp != NULLOPER)
594: {
595: (*on_p) = on_tmp->on_next_task;
596: }
597: else
598: {
599: LLOG(log_dsap, LLOG_EXCEPTIONS, ("get_edb_fail_wakeup - op escaped from get_edb_ops (the global list)"));
600: }
601:
602: oper_conn_extract(on);
603: oper_free(on);
604: }
605:
606: struct oper_act * make_get_edb_op(dn, version, di)
607: DN dn;
608: char * version;
609: struct di_block * di;
610: {
611: struct di_block * di_tmp;
612: struct oper_act * on_tmp;
613: struct getedb_arg * arg;
614:
615: DLOG(log_dsap, LLOG_TRACE, ("make_get_edb_op"));
616:
617: if((on_tmp = oper_alloc()) == NULLOPER)
618: {
619: LLOG(log_dsap, LLOG_EXCEPTIONS, ("make_get_edb_op - out of memory"));
620: return(NULLOPER);
621: }
622:
623: on_tmp->on_type = ON_TYPE_GET_EDB;
624: on_tmp->on_arg = &(on_tmp->on_req);
625: on_tmp->on_req.dca_dsarg.arg_type = OP_GETEDB;
626: on_tmp->on_getedb_ver = version;
627:
628: arg = &(on_tmp->on_req.dca_dsarg.arg_ge);
629:
630: arg->ga_entry = dn_cpy(dn);
631: arg->ga_version = strdup(version);
632: DLOG(log_dsap, LLOG_NOTICE, ("EDBARG: ver = %s", arg->ga_version));
633:
634: on_tmp->on_dsas = di;
635: for(di_tmp=di; di_tmp!=NULL_DI_BLOCK; di_tmp=di_tmp->di_next)
636: {
637: #ifdef DEBUG
638: DLOG(log_dsap, LLOG_DEBUG, ("Linking a di_block to this op"));
639: di_log(di_tmp);
640: #endif
641: di_tmp->di_type = DI_OPERATION;
642: di_tmp->di_oper = on_tmp;
643: }
644:
645: return(on_tmp);
646: }
647:
648: get_edb_extract(on)
649: struct oper_act * on;
650: {
651: struct oper_act * on_tmp;
652: struct oper_act **next_on;
653:
654: next_on = &(get_edb_ops);
655: for(on_tmp=get_edb_ops; on_tmp!=NULLOPER; on_tmp=on_tmp->on_next_task)
656: {
657: if(on_tmp == on)
658: break;
659: next_on = &(on_tmp->on_next_task);
660: }
661: if(on_tmp != NULLOPER)
662: {
663: (*next_on) = on_tmp->on_next_task;
664: }
665: else
666: {
667: LLOG(log_dsap, LLOG_EXCEPTIONS, ("Not on get_edb list"));
668: }
669: }
670:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.