This source file includes following definitions.
- cib_file_is_live
- cib_file_perform_op_delegate
- load_file_cib
- cib_file_signon
- cib_file_write_live
- cib_file_signoff
- cib_file_free
- cib_file_inputfd
- cib_file_register_notification
- cib_file_set_connection_dnotify
- cib_file_client_id
- cib_file_new
- cib_file_verify_digest
- cib_file_read_and_verify
- cib_file_backup
- cib_file_prepare_xml
- cib_file_write_with_digest
1
2
3
4
5
6
7
8
9
10
11 #include <crm_internal.h>
12 #include <unistd.h>
13 #include <limits.h>
14 #include <stdlib.h>
15 #include <stdint.h>
16 #include <stdio.h>
17 #include <stdarg.h>
18 #include <string.h>
19 #include <pwd.h>
20
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <glib.h>
24
25 #include <crm/crm.h>
26 #include <crm/cib/internal.h>
27 #include <crm/msg_xml.h>
28 #include <crm/common/ipc.h>
29 #include <crm/common/xml.h>
30 #include <crm/common/xml_internal.h>
31
32 #define CIB_SERIES "cib"
33 #define CIB_SERIES_MAX 100
34 #define CIB_SERIES_BZIP FALSE
35
36
37
38 #define CIB_LIVE_NAME CIB_SERIES ".xml"
39
40 enum cib_file_flags {
41 cib_file_flag_dirty = (1 << 0),
42 cib_file_flag_live = (1 << 1),
43 };
44
45 typedef struct cib_file_opaque_s {
46 uint32_t flags;
47 char *filename;
48 } cib_file_opaque_t;
49
50 struct cib_func_entry {
51 const char *op;
52 gboolean read_only;
53 cib_op_t fn;
54 };
55
56 static struct cib_func_entry cib_file_ops[] = {
57 { PCMK__CIB_REQUEST_QUERY, TRUE, cib_process_query },
58 { PCMK__CIB_REQUEST_MODIFY, FALSE, cib_process_modify },
59 { PCMK__CIB_REQUEST_APPLY_PATCH, FALSE, cib_process_diff },
60 { PCMK__CIB_REQUEST_BUMP, FALSE, cib_process_bump },
61 { PCMK__CIB_REQUEST_REPLACE, FALSE, cib_process_replace },
62 { PCMK__CIB_REQUEST_CREATE, FALSE, cib_process_create },
63 { PCMK__CIB_REQUEST_DELETE, FALSE, cib_process_delete },
64 { PCMK__CIB_REQUEST_ERASE, FALSE, cib_process_erase },
65 { PCMK__CIB_REQUEST_UPGRADE, FALSE, cib_process_upgrade },
66 };
67
68 static xmlNode *in_mem_cib = NULL;
69
70
71
72
73
74 static uid_t cib_file_owner = 0;
75 static uid_t cib_file_group = 0;
76 static gboolean cib_do_chown = FALSE;
77
78 #define cib_set_file_flags(cibfile, flags_to_set) do { \
79 (cibfile)->flags = pcmk__set_flags_as(__func__, __LINE__, \
80 LOG_TRACE, "CIB file", \
81 cibfile->filename, \
82 (cibfile)->flags, \
83 (flags_to_set), \
84 #flags_to_set); \
85 } while (0)
86
87 #define cib_clear_file_flags(cibfile, flags_to_clear) do { \
88 (cibfile)->flags = pcmk__clear_flags_as(__func__, __LINE__, \
89 LOG_TRACE, "CIB file", \
90 cibfile->filename, \
91 (cibfile)->flags, \
92 (flags_to_clear), \
93 #flags_to_clear); \
94 } while (0)
95
96
97
98
99
100
101
102
103
104 static gboolean
105 cib_file_is_live(const char *filename)
106 {
107 gboolean same = FALSE;
108
109 if (filename != NULL) {
110
111 char *real_filename = NULL;
112
113 if (pcmk__real_path(filename, &real_filename) == pcmk_rc_ok) {
114 char *real_livename = NULL;
115
116 if (pcmk__real_path(CRM_CONFIG_DIR "/" CIB_LIVE_NAME,
117 &real_livename) == pcmk_rc_ok) {
118 same = !strcmp(real_filename, real_livename);
119 free(real_livename);
120 }
121 free(real_filename);
122 }
123 }
124 return same;
125 }
126
127 static int
128 cib_file_perform_op_delegate(cib_t *cib, const char *op, const char *host,
129 const char *section, xmlNode *data,
130 xmlNode **output_data, int call_options,
131 const char *user_name)
132 {
133 int rc = pcmk_ok;
134 char *effective_user = NULL;
135 gboolean query = FALSE;
136 gboolean changed = FALSE;
137 xmlNode *request = NULL;
138 xmlNode *output = NULL;
139 xmlNode *cib_diff = NULL;
140 xmlNode *result_cib = NULL;
141 cib_op_t *fn = NULL;
142 int lpc = 0;
143 static int max_msg_types = PCMK__NELEM(cib_file_ops);
144 cib_file_opaque_t *private = cib->variant_opaque;
145
146 crm_info("Handling %s operation for %s as %s",
147 (op? op : "invalid"), (section? section : "entire CIB"),
148 (user_name? user_name : "default user"));
149
150 cib__set_call_options(call_options, "file operation",
151 cib_no_mtime|cib_inhibit_bcast|cib_scope_local);
152
153 if (cib->state == cib_disconnected) {
154 return -ENOTCONN;
155 }
156
157 if (output_data != NULL) {
158 *output_data = NULL;
159 }
160
161 if (op == NULL) {
162 return -EINVAL;
163 }
164
165 for (lpc = 0; lpc < max_msg_types; lpc++) {
166 if (pcmk__str_eq(op, cib_file_ops[lpc].op, pcmk__str_casei)) {
167 fn = &(cib_file_ops[lpc].fn);
168 query = cib_file_ops[lpc].read_only;
169 break;
170 }
171 }
172
173 if (fn == NULL) {
174 return -EPROTONOSUPPORT;
175 }
176
177 cib->call_id++;
178 request = cib_create_op(cib->call_id, op, host, section, data, call_options,
179 user_name);
180 if(user_name) {
181 crm_xml_add(request, XML_ACL_TAG_USER, user_name);
182 }
183
184
185 if (section != NULL && data != NULL && pcmk__str_eq(crm_element_name(data), XML_TAG_CIB, pcmk__str_none)) {
186 data = pcmk_find_cib_element(data, section);
187 }
188
189 rc = cib_perform_op(op, call_options, fn, query,
190 section, request, data, TRUE, &changed, in_mem_cib, &result_cib, &cib_diff,
191 &output);
192
193 free_xml(request);
194 if (rc == -pcmk_err_schema_validation) {
195 validate_xml_verbose(result_cib);
196 }
197
198 if (rc != pcmk_ok) {
199 free_xml(result_cib);
200
201 } else if (query == FALSE) {
202 pcmk__output_t *out = NULL;
203
204 rc = pcmk_rc2legacy(pcmk__log_output_new(&out));
205 CRM_CHECK(rc == pcmk_ok, goto done);
206
207 pcmk__output_set_log_level(out, LOG_DEBUG);
208 rc = out->message(out, "xml-patchset", cib_diff);
209 out->finish(out, pcmk_rc2exitc(rc), true, NULL);
210 pcmk__output_free(out);
211 rc = pcmk_ok;
212
213 free_xml(in_mem_cib);
214 in_mem_cib = result_cib;
215 cib_set_file_flags(private, cib_file_flag_dirty);
216 }
217
218 if (cib->op_callback != NULL) {
219 cib->op_callback(NULL, cib->call_id, rc, output);
220 }
221
222 if ((output_data != NULL) && (output != NULL)) {
223 *output_data = (output == in_mem_cib)? copy_xml(output) : output;
224 }
225
226 done:
227 free_xml(cib_diff);
228
229 if ((output_data == NULL) && (output != in_mem_cib)) {
230
231
232
233 free_xml(output);
234 }
235 free(effective_user);
236 return rc;
237 }
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253 static int
254 load_file_cib(const char *filename)
255 {
256 struct stat buf;
257 xmlNode *root = NULL;
258
259
260 if (strcmp(filename, "-") && (stat(filename, &buf) < 0)) {
261 return -ENXIO;
262 }
263
264
265 root = filename2xml(filename);
266 if (root == NULL) {
267 return -pcmk_err_schema_validation;
268 }
269
270
271 if (find_xml_node(root, XML_CIB_TAG_STATUS, FALSE) == NULL) {
272 create_xml_node(root, XML_CIB_TAG_STATUS);
273 }
274
275
276 if (validate_xml(root, NULL, TRUE) == FALSE) {
277 const char *schema = crm_element_value(root, XML_ATTR_VALIDATION);
278
279 crm_err("CIB does not validate against %s", schema);
280 free_xml(root);
281 return -pcmk_err_schema_validation;
282 }
283
284
285 in_mem_cib = root;
286 return pcmk_ok;
287 }
288
289 static int
290 cib_file_signon(cib_t *cib, const char *name, enum cib_conn_type type)
291 {
292 int rc = pcmk_ok;
293 cib_file_opaque_t *private = cib->variant_opaque;
294
295 if (private->filename == NULL) {
296 rc = -EINVAL;
297 } else {
298 rc = load_file_cib(private->filename);
299 }
300
301 if (rc == pcmk_ok) {
302 crm_debug("Opened connection to local file '%s' for %s",
303 private->filename, name);
304 cib->state = cib_connected_command;
305 cib->type = cib_command;
306
307 } else {
308 crm_info("Connection to local file '%s' for %s failed: %s\n",
309 private->filename, name, pcmk_strerror(rc));
310 }
311 return rc;
312 }
313
314
315
316
317
318
319
320
321
322 static int
323 cib_file_write_live(char *path)
324 {
325 uid_t uid = geteuid();
326 struct passwd *daemon_pwent;
327 char *sep = strrchr(path, '/');
328 const char *cib_dirname, *cib_filename;
329 int rc = 0;
330
331
332 errno = 0;
333 daemon_pwent = getpwnam(CRM_DAEMON_USER);
334 if (daemon_pwent == NULL) {
335 crm_perror(LOG_ERR, "Could not find %s user", CRM_DAEMON_USER);
336 return -1;
337 }
338
339
340
341
342
343 if ((uid != 0) && (uid != daemon_pwent->pw_uid)) {
344 crm_perror(LOG_ERR, "Must be root or %s to modify live CIB",
345 CRM_DAEMON_USER);
346 return 0;
347 }
348
349
350
351
352
353 if (sep == NULL) {
354 cib_dirname = "./";
355 cib_filename = path;
356 } else if (sep == path) {
357 cib_dirname = "/";
358 cib_filename = path + 1;
359 } else {
360 *sep = '\0';
361 cib_dirname = path;
362 cib_filename = sep + 1;
363 }
364
365
366 if (uid == 0) {
367 cib_file_owner = daemon_pwent->pw_uid;
368 cib_file_group = daemon_pwent->pw_gid;
369 cib_do_chown = TRUE;
370 }
371
372
373 if (cib_file_write_with_digest(in_mem_cib, cib_dirname,
374 cib_filename) != pcmk_ok) {
375 rc = -1;
376 }
377
378
379 if (uid == 0) {
380 cib_do_chown = FALSE;
381 }
382
383
384 if ((sep != NULL) && (*sep == '\0')) {
385 *sep = '/';
386 }
387
388 return rc;
389 }
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404 static int
405 cib_file_signoff(cib_t *cib)
406 {
407 int rc = pcmk_ok;
408 cib_file_opaque_t *private = cib->variant_opaque;
409
410 crm_debug("Disconnecting from the CIB manager");
411 cib->state = cib_disconnected;
412 cib->type = cib_no_connection;
413
414
415 if (pcmk_is_set(private->flags, cib_file_flag_dirty)) {
416
417
418 if (pcmk_is_set(private->flags, cib_file_flag_live)) {
419 if (cib_file_write_live(private->filename) < 0) {
420 rc = pcmk_err_generic;
421 }
422
423
424 } else {
425 gboolean do_bzip = pcmk__ends_with_ext(private->filename, ".bz2");
426
427 if (write_xml_file(in_mem_cib, private->filename, do_bzip) <= 0) {
428 rc = pcmk_err_generic;
429 }
430 }
431
432 if (rc == pcmk_ok) {
433 crm_info("Wrote CIB to %s", private->filename);
434 cib_clear_file_flags(private, cib_file_flag_dirty);
435 } else {
436 crm_err("Could not write CIB to %s", private->filename);
437 }
438 }
439
440
441 free_xml(in_mem_cib);
442 in_mem_cib = NULL;
443 return rc;
444 }
445
446 static int
447 cib_file_free(cib_t *cib)
448 {
449 int rc = pcmk_ok;
450
451 if (cib->state != cib_disconnected) {
452 rc = cib_file_signoff(cib);
453 }
454
455 if (rc == pcmk_ok) {
456 cib_file_opaque_t *private = cib->variant_opaque;
457
458 free(private->filename);
459 free(cib->cmds);
460 free(private);
461 free(cib);
462
463 } else {
464 fprintf(stderr, "Couldn't sign off: %d\n", rc);
465 }
466
467 return rc;
468 }
469
470 static int
471 cib_file_inputfd(cib_t *cib)
472 {
473 return -EPROTONOSUPPORT;
474 }
475
476 static int
477 cib_file_register_notification(cib_t *cib, const char *callback, int enabled)
478 {
479 return -EPROTONOSUPPORT;
480 }
481
482 static int
483 cib_file_set_connection_dnotify(cib_t *cib,
484 void (*dnotify) (gpointer user_data))
485 {
486 return -EPROTONOSUPPORT;
487 }
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504 static int
505 cib_file_client_id(const cib_t *cib, const char **async_id,
506 const char **sync_id)
507 {
508 if (async_id != NULL) {
509 *async_id = NULL;
510 }
511 if (sync_id != NULL) {
512 *sync_id = NULL;
513 }
514 return -EPROTONOSUPPORT;
515 }
516
517 cib_t *
518 cib_file_new(const char *cib_location)
519 {
520 cib_file_opaque_t *private = NULL;
521 cib_t *cib = cib_new_variant();
522
523 if (cib == NULL) {
524 return NULL;
525 }
526
527 private = calloc(1, sizeof(cib_file_opaque_t));
528
529 if (private == NULL) {
530 free(cib);
531 return NULL;
532 }
533
534 cib->variant = cib_file;
535 cib->variant_opaque = private;
536
537 if (cib_location == NULL) {
538 cib_location = getenv("CIB_file");
539 CRM_CHECK(cib_location != NULL, return NULL);
540 }
541 private->flags = 0;
542 if (cib_file_is_live(cib_location)) {
543 cib_set_file_flags(private, cib_file_flag_live);
544 crm_trace("File %s detected as live CIB", cib_location);
545 }
546 private->filename = strdup(cib_location);
547
548
549 cib->delegate_fn = cib_file_perform_op_delegate;
550 cib->cmds->signon = cib_file_signon;
551 cib->cmds->signoff = cib_file_signoff;
552 cib->cmds->free = cib_file_free;
553 cib->cmds->inputfd = cib_file_inputfd;
554
555 cib->cmds->register_notification = cib_file_register_notification;
556 cib->cmds->set_connection_dnotify = cib_file_set_connection_dnotify;
557
558 cib->cmds->client_id = cib_file_client_id;
559
560 return cib;
561 }
562
563
564
565
566
567
568
569
570
571
572 static gboolean
573 cib_file_verify_digest(xmlNode *root, const char *sigfile)
574 {
575 gboolean passed = FALSE;
576 char *expected;
577 int rc = pcmk__file_contents(sigfile, &expected);
578
579 switch (rc) {
580 case pcmk_rc_ok:
581 if (expected == NULL) {
582 crm_err("On-disk digest at %s is empty", sigfile);
583 return FALSE;
584 }
585 break;
586 case ENOENT:
587 crm_warn("No on-disk digest present at %s", sigfile);
588 return TRUE;
589 default:
590 crm_err("Could not read on-disk digest from %s: %s",
591 sigfile, pcmk_rc_str(rc));
592 return FALSE;
593 }
594 passed = pcmk__verify_digest(root, expected);
595 free(expected);
596 return passed;
597 }
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614 int
615 cib_file_read_and_verify(const char *filename, const char *sigfile, xmlNode **root)
616 {
617 int s_res;
618 struct stat buf;
619 char *local_sigfile = NULL;
620 xmlNode *local_root = NULL;
621
622 CRM_ASSERT(filename != NULL);
623 if (root) {
624 *root = NULL;
625 }
626
627
628 s_res = stat(filename, &buf);
629 if (s_res < 0) {
630 crm_perror(LOG_WARNING, "Could not verify cluster configuration file %s", filename);
631 return -errno;
632 } else if (buf.st_size == 0) {
633 crm_warn("Cluster configuration file %s is corrupt (size is zero)", filename);
634 return -pcmk_err_cib_corrupt;
635 }
636
637
638 local_root = filename2xml(filename);
639 if (local_root == NULL) {
640 crm_warn("Cluster configuration file %s is corrupt (unparseable as XML)", filename);
641 return -pcmk_err_cib_corrupt;
642 }
643
644
645 if (sigfile == NULL) {
646 sigfile = local_sigfile = crm_strdup_printf("%s.sig", filename);
647 }
648
649
650 if (cib_file_verify_digest(local_root, sigfile) == FALSE) {
651 free(local_sigfile);
652 free_xml(local_root);
653 return -pcmk_err_cib_modified;
654 }
655
656 free(local_sigfile);
657 if (root) {
658 *root = local_root;
659 } else {
660 free_xml(local_root);
661 }
662 return pcmk_ok;
663 }
664
665
666
667
668
669
670
671
672
673
674 static int
675 cib_file_backup(const char *cib_dirname, const char *cib_filename)
676 {
677 int rc = 0;
678 unsigned int seq;
679 char *cib_path = crm_strdup_printf("%s/%s", cib_dirname, cib_filename);
680 char *cib_digest = crm_strdup_printf("%s.sig", cib_path);
681 char *backup_path;
682 char *backup_digest;
683
684
685 if (pcmk__read_series_sequence(cib_dirname, CIB_SERIES,
686 &seq) != pcmk_rc_ok) {
687
688 seq = 0;
689 }
690 backup_path = pcmk__series_filename(cib_dirname, CIB_SERIES, seq,
691 CIB_SERIES_BZIP);
692 backup_digest = crm_strdup_printf("%s.sig", backup_path);
693
694
695 unlink(backup_path);
696 unlink(backup_digest);
697
698
699 if ((link(cib_path, backup_path) < 0) && (errno != ENOENT)) {
700 crm_perror(LOG_ERR, "Could not archive %s by linking to %s",
701 cib_path, backup_path);
702 rc = -1;
703
704
705 } else if ((link(cib_digest, backup_digest) < 0) && (errno != ENOENT)) {
706 crm_perror(LOG_ERR, "Could not archive %s by linking to %s",
707 cib_digest, backup_digest);
708 rc = -1;
709
710
711 } else {
712 pcmk__write_series_sequence(cib_dirname, CIB_SERIES, ++seq,
713 CIB_SERIES_MAX);
714 if (cib_do_chown) {
715 int rc2;
716
717 if ((chown(backup_path, cib_file_owner, cib_file_group) < 0)
718 && (errno != ENOENT)) {
719 crm_perror(LOG_ERR, "Could not set owner of %s", backup_path);
720 rc = -1;
721 }
722 if ((chown(backup_digest, cib_file_owner, cib_file_group) < 0)
723 && (errno != ENOENT)) {
724 crm_perror(LOG_ERR, "Could not set owner of %s", backup_digest);
725 rc = -1;
726 }
727 rc2 = pcmk__chown_series_sequence(cib_dirname, CIB_SERIES,
728 cib_file_owner, cib_file_group);
729 if (rc2 != pcmk_rc_ok) {
730 crm_err("Could not set owner of sequence file in %s: %s",
731 cib_dirname, pcmk_rc_str(rc2));
732 rc = -1;
733 }
734 }
735 pcmk__sync_directory(cib_dirname);
736 crm_info("Archived previous version as %s", backup_path);
737 }
738
739 free(cib_path);
740 free(cib_digest);
741 free(backup_path);
742 free(backup_digest);
743 return rc;
744 }
745
746
747
748
749
750
751
752
753
754
755
756
757 static void
758 cib_file_prepare_xml(xmlNode *root)
759 {
760 xmlNode *cib_status_root = NULL;
761
762
763 crm_xml_add(root, XML_ATTR_NUMUPDATES, "0");
764 pcmk__xe_add_last_written(root);
765
766
767
768 cib_status_root = find_xml_node(root, XML_CIB_TAG_STATUS, TRUE);
769 CRM_LOG_ASSERT(cib_status_root != NULL);
770 if (cib_status_root != NULL) {
771 free_xml(cib_status_root);
772 }
773 }
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788 int
789 cib_file_write_with_digest(xmlNode *cib_root, const char *cib_dirname,
790 const char *cib_filename)
791 {
792 int exit_rc = pcmk_ok;
793 int rc, fd;
794 char *digest = NULL;
795
796
797 const char *epoch = crm_element_value(cib_root, XML_ATTR_GENERATION);
798 const char *admin_epoch = crm_element_value(cib_root,
799 XML_ATTR_GENERATION_ADMIN);
800
801
802 char *cib_path = crm_strdup_printf("%s/%s", cib_dirname, cib_filename);
803 char *digest_path = crm_strdup_printf("%s.sig", cib_path);
804
805
806 char *tmp_cib = crm_strdup_printf("%s/cib.XXXXXX", cib_dirname);
807 char *tmp_digest = crm_strdup_printf("%s/cib.XXXXXX", cib_dirname);
808
809 CRM_ASSERT((cib_path != NULL) && (digest_path != NULL)
810 && (tmp_cib != NULL) && (tmp_digest != NULL));
811
812
813 crm_trace("Reading cluster configuration file %s", cib_path);
814 rc = cib_file_read_and_verify(cib_path, NULL, NULL);
815 if ((rc != pcmk_ok) && (rc != -ENOENT)) {
816 crm_err("%s was manually modified while the cluster was active!",
817 cib_path);
818 exit_rc = pcmk_err_cib_modified;
819 goto cleanup;
820 }
821
822
823 if (cib_file_backup(cib_dirname, cib_filename) < 0) {
824 exit_rc = pcmk_err_cib_backup;
825 goto cleanup;
826 }
827
828 crm_debug("Writing CIB to disk");
829 umask(S_IWGRP | S_IWOTH | S_IROTH);
830 cib_file_prepare_xml(cib_root);
831
832
833 fd = mkstemp(tmp_cib);
834 if (fd < 0) {
835 crm_perror(LOG_ERR, "Couldn't open temporary file %s for writing CIB",
836 tmp_cib);
837 exit_rc = pcmk_err_cib_save;
838 goto cleanup;
839 }
840
841
842 if (fchmod(fd, S_IRUSR | S_IWUSR) < 0) {
843 crm_perror(LOG_ERR, "Couldn't protect temporary file %s for writing CIB",
844 tmp_cib);
845 exit_rc = pcmk_err_cib_save;
846 goto cleanup;
847 }
848 if (cib_do_chown && (fchown(fd, cib_file_owner, cib_file_group) < 0)) {
849 crm_perror(LOG_ERR, "Couldn't protect temporary file %s for writing CIB",
850 tmp_cib);
851 exit_rc = pcmk_err_cib_save;
852 goto cleanup;
853 }
854
855
856 if (write_xml_fd(cib_root, tmp_cib, fd, FALSE) <= 0) {
857 crm_err("Changes couldn't be written to %s", tmp_cib);
858 exit_rc = pcmk_err_cib_save;
859 goto cleanup;
860 }
861
862
863 digest = calculate_on_disk_digest(cib_root);
864 CRM_ASSERT(digest != NULL);
865 crm_info("Wrote version %s.%s.0 of the CIB to disk (digest: %s)",
866 (admin_epoch ? admin_epoch : "0"), (epoch ? epoch : "0"), digest);
867
868
869 fd = mkstemp(tmp_digest);
870 if (fd < 0) {
871 crm_perror(LOG_ERR, "Could not create temporary file for CIB digest");
872 exit_rc = pcmk_err_cib_save;
873 goto cleanup;
874 }
875 if (cib_do_chown && (fchown(fd, cib_file_owner, cib_file_group) < 0)) {
876 crm_perror(LOG_ERR, "Couldn't protect temporary file %s for writing CIB",
877 tmp_cib);
878 exit_rc = pcmk_err_cib_save;
879 close(fd);
880 goto cleanup;
881 }
882 rc = pcmk__write_sync(fd, digest);
883 if (rc != pcmk_rc_ok) {
884 crm_err("Could not write digest to %s: %s",
885 tmp_digest, pcmk_rc_str(rc));
886 exit_rc = pcmk_err_cib_save;
887 close(fd);
888 goto cleanup;
889 }
890 close(fd);
891 crm_debug("Wrote digest %s to disk", digest);
892
893
894 crm_info("Reading cluster configuration file %s (digest: %s)",
895 tmp_cib, tmp_digest);
896 rc = cib_file_read_and_verify(tmp_cib, tmp_digest, NULL);
897 CRM_ASSERT(rc == 0);
898
899
900 crm_debug("Activating %s", tmp_cib);
901 if (rename(tmp_cib, cib_path) < 0) {
902 crm_perror(LOG_ERR, "Couldn't rename %s as %s", tmp_cib, cib_path);
903 exit_rc = pcmk_err_cib_save;
904 }
905 if (rename(tmp_digest, digest_path) < 0) {
906 crm_perror(LOG_ERR, "Couldn't rename %s as %s", tmp_digest,
907 digest_path);
908 exit_rc = pcmk_err_cib_save;
909 }
910 pcmk__sync_directory(cib_dirname);
911
912 cleanup:
913 free(cib_path);
914 free(digest_path);
915 free(digest);
916 free(tmp_digest);
917 free(tmp_cib);
918 return exit_rc;
919 }