6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
25 * Copyright 2018 RackTop Systems.
26 */
27
28 #include "libscf_impl.h"
29
30 #include <assert.h>
31 #include <libuutil.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <sys/param.h>
36 #include <errno.h>
37 #include <libgen.h>
38 #include <assert.h>
39 #include "midlevel_impl.h"
40 #include "lowlevel_impl.h"
41
42 #ifndef NDEBUG
43 #define bad_error(func, err) { \
44 uu_warn("%s:%d: %s failed with unexpected error %d. Aborting.\n", \
45 __FILE__, __LINE__, func, err); \
501 ret = enabled;
502
503 out:
504 scf_pg_destroy(gpg);
505 scf_property_destroy(eprop);
506 scf_value_destroy(v);
507 return (ret);
508 }
509
510 /*
511 * set_inst_enabled() is a "master" enable/disable call that takes the
512 * instance and the desired state for the enabled bit in the instance's
513 * named property group. If the group doesn't exist, it's created with the
514 * given flags. Called by smf_{dis,en}able_instance().
515 */
516 static int
517 set_inst_enabled(const scf_instance_t *inst, uint8_t desired,
518 const char *pgname, uint32_t pgflags)
519 {
520 scf_transaction_t *tx = NULL;
521 scf_transaction_entry_t *ent = NULL;
522 scf_propertygroup_t *gpg = NULL;
523 scf_property_t *eprop = NULL;
524 scf_value_t *v = NULL;
525 scf_handle_t *h = NULL;
526 int ret = -1;
527 int committed;
528 uint8_t b;
529
530 if ((h = scf_instance_handle(inst)) == NULL)
531 return (-1);
532
533 if ((gpg = scf_pg_create(h)) == NULL ||
534 (eprop = scf_property_create(h)) == NULL ||
535 (v = scf_value_create(h)) == NULL ||
536 (tx = scf_transaction_create(h)) == NULL ||
537 (ent = scf_entry_create(h)) == NULL)
538 goto out;
539
540 general_pg_get:
541 if (scf_instance_get_pg(inst, SCF_PG_GENERAL, gpg) == -1) {
542 if (scf_error() != SCF_ERROR_NOT_FOUND)
543 goto out;
544
545 if (scf_instance_add_pg(inst, SCF_PG_GENERAL,
546 SCF_GROUP_FRAMEWORK, SCF_PG_GENERAL_FLAGS, gpg) == -1) {
547 if (scf_error() != SCF_ERROR_EXISTS)
548 goto out;
549 goto general_pg_get;
550 }
551 }
552
553 if (strcmp(pgname, SCF_PG_GENERAL) != 0) {
554 get:
555 if (scf_instance_get_pg(inst, pgname, gpg) == -1) {
556 if (scf_error() != SCF_ERROR_NOT_FOUND)
557 goto out;
584
585 default:
586 goto out;
587 }
588 }
589 if (scf_value_get_boolean(v, &b) == -1) {
590 if (scf_error() != SCF_ERROR_TYPE_MISMATCH)
591 goto out;
592 goto set;
593 }
594 if (b == desired) {
595 ret = 0;
596 goto out;
597 }
598
599 set:
600 do {
601 if (scf_transaction_start(tx, gpg) == -1)
602 goto out;
603
604 if (transaction_property_set(tx, ent, SCF_PROPERTY_ENABLED,
605 SCF_TYPE_BOOLEAN) != 0) {
606 switch (scf_error()) {
607 case SCF_ERROR_CONNECTION_BROKEN:
608 case SCF_ERROR_DELETED:
609 default:
610 goto out;
611
612 case SCF_ERROR_HANDLE_MISMATCH:
613 case SCF_ERROR_INVALID_ARGUMENT:
614 case SCF_ERROR_NOT_BOUND:
615 case SCF_ERROR_NOT_SET:
616 bad_error("transaction_property_set",
617 scf_error());
618 }
619 }
620
621 scf_value_set_boolean(v, desired);
622 if (scf_entry_add_value(ent, v) == -1)
623 goto out;
624
625 committed = scf_transaction_commit(tx);
626 if (committed == -1)
627 goto out;
628
629 scf_transaction_reset(tx);
630
631 if (committed == 0) { /* out-of-sync */
632 if (scf_pg_update(gpg) == -1)
633 goto out;
634 }
635 } while (committed == 0);
636
637 ret = 0;
638
639 out:
640 scf_value_destroy(v);
641 scf_entry_destroy(ent);
642 scf_transaction_destroy(tx);
643 scf_property_destroy(eprop);
644 scf_pg_destroy(gpg);
645
646 return (ret);
647 }
648
649 static int
650 delete_inst_enabled(const scf_instance_t *inst, const char *pgname)
651 {
652 scf_transaction_t *tx = NULL;
653 scf_transaction_entry_t *ent = NULL;
654 scf_propertygroup_t *gpg = NULL;
655 scf_handle_t *h = NULL;
656 int ret = -1;
657 int committed;
658
659 if ((h = scf_instance_handle(inst)) == NULL)
660 return (-1);
661
662 if ((gpg = scf_pg_create(h)) == NULL ||
663 (tx = scf_transaction_create(h)) == NULL ||
664 (ent = scf_entry_create(h)) == NULL)
665 goto out;
666
667 if (scf_instance_get_pg(inst, pgname, gpg) != 0)
668 goto error;
669 do {
670 if (scf_transaction_start(tx, gpg) == -1 ||
671 scf_transaction_property_delete(tx, ent,
672 SCF_PROPERTY_ENABLED) == -1 ||
673 (committed = scf_transaction_commit(tx)) == -1)
674 goto error;
675
676 scf_transaction_reset(tx);
677
678 if (committed == 0 && scf_pg_update(gpg) == -1)
679 goto error;
680 } while (committed == 0);
681
682 ret = 0;
683 goto out;
684
685 error:
686 switch (scf_error()) {
687 case SCF_ERROR_DELETED:
688 case SCF_ERROR_NOT_FOUND:
689 /* success */
690 ret = 0;
691 }
692
693 out:
694 scf_entry_destroy(ent);
695 scf_transaction_destroy(tx);
696 scf_pg_destroy(gpg);
697
698 return (ret);
699 }
700
701 /*
702 * Returns 0 on success or -1 on failure. On failure leaves scf_error() set to
703 * SCF_ERROR_HANDLE_DESTROYED - inst's handle has been destroyed
704 * SCF_ERROR_NOT_BOUND - inst's handle is not bound
705 * SCF_ERROR_CONNECTION_BROKEN - the repository connection was broken
706 * SCF_ERROR_NOT_SET - inst is not set
707 * SCF_ERROR_DELETED - inst was deleted
708 * SCF_ERROR_PERMISSION_DENIED
709 * SCF_ERROR_BACKEND_ACCESS
710 * SCF_ERROR_BACKEND_READONLY
711 */
712 static int
713 set_inst_action_inst(scf_instance_t *inst, const char *action)
714 {
|
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
25 * Copyright 2018 RackTop Systems.
26 * Copyright 2020 Joyent, Inc.
27 */
28
29 #include "libscf_impl.h"
30
31 #include <assert.h>
32 #include <libuutil.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include <sys/param.h>
37 #include <errno.h>
38 #include <libgen.h>
39 #include <assert.h>
40 #include "midlevel_impl.h"
41 #include "lowlevel_impl.h"
42
43 #ifndef NDEBUG
44 #define bad_error(func, err) { \
45 uu_warn("%s:%d: %s failed with unexpected error %d. Aborting.\n", \
46 __FILE__, __LINE__, func, err); \
502 ret = enabled;
503
504 out:
505 scf_pg_destroy(gpg);
506 scf_property_destroy(eprop);
507 scf_value_destroy(v);
508 return (ret);
509 }
510
511 /*
512 * set_inst_enabled() is a "master" enable/disable call that takes the
513 * instance and the desired state for the enabled bit in the instance's
514 * named property group. If the group doesn't exist, it's created with the
515 * given flags. Called by smf_{dis,en}able_instance().
516 */
517 static int
518 set_inst_enabled(const scf_instance_t *inst, uint8_t desired,
519 const char *pgname, uint32_t pgflags)
520 {
521 scf_transaction_t *tx = NULL;
522 scf_transaction_entry_t *ent1 = NULL;
523 scf_transaction_entry_t *ent2 = NULL;
524 scf_propertygroup_t *gpg = NULL;
525 scf_property_t *eprop = NULL;
526 scf_value_t *v = NULL;
527 scf_handle_t *h = NULL;
528 int ret = -1;
529 int committed;
530 uint8_t b;
531
532 if ((h = scf_instance_handle(inst)) == NULL)
533 return (-1);
534
535 if ((gpg = scf_pg_create(h)) == NULL ||
536 (eprop = scf_property_create(h)) == NULL ||
537 (v = scf_value_create(h)) == NULL ||
538 (tx = scf_transaction_create(h)) == NULL ||
539 (ent1 = scf_entry_create(h)) == NULL ||
540 (ent2 = scf_entry_create(h)) == NULL)
541 goto out;
542
543 general_pg_get:
544 if (scf_instance_get_pg(inst, SCF_PG_GENERAL, gpg) == -1) {
545 if (scf_error() != SCF_ERROR_NOT_FOUND)
546 goto out;
547
548 if (scf_instance_add_pg(inst, SCF_PG_GENERAL,
549 SCF_GROUP_FRAMEWORK, SCF_PG_GENERAL_FLAGS, gpg) == -1) {
550 if (scf_error() != SCF_ERROR_EXISTS)
551 goto out;
552 goto general_pg_get;
553 }
554 }
555
556 if (strcmp(pgname, SCF_PG_GENERAL) != 0) {
557 get:
558 if (scf_instance_get_pg(inst, pgname, gpg) == -1) {
559 if (scf_error() != SCF_ERROR_NOT_FOUND)
560 goto out;
587
588 default:
589 goto out;
590 }
591 }
592 if (scf_value_get_boolean(v, &b) == -1) {
593 if (scf_error() != SCF_ERROR_TYPE_MISMATCH)
594 goto out;
595 goto set;
596 }
597 if (b == desired) {
598 ret = 0;
599 goto out;
600 }
601
602 set:
603 do {
604 if (scf_transaction_start(tx, gpg) == -1)
605 goto out;
606
607 if (transaction_property_set(tx, ent1, SCF_PROPERTY_ENABLED,
608 SCF_TYPE_BOOLEAN) != 0) {
609 switch (scf_error()) {
610 case SCF_ERROR_CONNECTION_BROKEN:
611 case SCF_ERROR_DELETED:
612 default:
613 goto out;
614
615 case SCF_ERROR_HANDLE_MISMATCH:
616 case SCF_ERROR_INVALID_ARGUMENT:
617 case SCF_ERROR_NOT_BOUND:
618 case SCF_ERROR_NOT_SET:
619 bad_error("transaction_property_set",
620 scf_error());
621 }
622 }
623
624 scf_value_set_boolean(v, desired);
625 if (scf_entry_add_value(ent1, v) == -1)
626 goto out;
627
628 /* If we're enabling, clear out any disabled comment. */
629 if (desired) {
630 ret = scf_transaction_property_delete(tx, ent2,
631 SCF_PROPERTY_COMMENT);
632
633 if (ret == -1 && scf_error() != SCF_ERROR_DELETED &&
634 scf_error() != SCF_ERROR_NOT_FOUND)
635 goto out;
636 }
637
638 committed = scf_transaction_commit(tx);
639 if (committed == -1)
640 goto out;
641
642 scf_transaction_reset(tx);
643
644 if (committed == 0) { /* out-of-sync */
645 if (scf_pg_update(gpg) == -1)
646 goto out;
647 }
648 } while (committed == 0);
649
650 ret = 0;
651
652 out:
653 scf_value_destroy(v);
654 scf_entry_destroy(ent1);
655 scf_entry_destroy(ent2);
656 scf_transaction_destroy(tx);
657 scf_property_destroy(eprop);
658 scf_pg_destroy(gpg);
659
660 return (ret);
661 }
662
663 static int
664 delete_inst_enabled(const scf_instance_t *inst, const char *pgname)
665 {
666 scf_transaction_t *tx = NULL;
667 scf_transaction_entry_t *ent1 = NULL;
668 scf_transaction_entry_t *ent2 = NULL;
669 scf_propertygroup_t *gpg = NULL;
670 scf_handle_t *h = NULL;
671 int ret = -1;
672 int committed;
673
674 if ((h = scf_instance_handle(inst)) == NULL)
675 return (-1);
676
677 if ((gpg = scf_pg_create(h)) == NULL ||
678 (tx = scf_transaction_create(h)) == NULL ||
679 (ent1 = scf_entry_create(h)) == NULL ||
680 (ent2 = scf_entry_create(h)) == NULL)
681 goto out;
682
683 if (scf_instance_get_pg(inst, pgname, gpg) != 0)
684 goto error;
685 do {
686 if (scf_transaction_start(tx, gpg) == -1)
687 goto error;
688
689 ret = scf_transaction_property_delete(tx, ent1,
690 SCF_PROPERTY_ENABLED);
691
692 if (ret == -1 && scf_error() != SCF_ERROR_DELETED &&
693 scf_error() != SCF_ERROR_NOT_FOUND)
694 goto error;
695
696 ret = scf_transaction_property_delete(tx, ent2,
697 SCF_PROPERTY_COMMENT);
698
699 if (ret == -1 && scf_error() != SCF_ERROR_DELETED &&
700 scf_error() != SCF_ERROR_NOT_FOUND)
701 goto error;
702
703 if ((committed = scf_transaction_commit(tx)) == -1)
704 goto error;
705
706 scf_transaction_reset(tx);
707
708 if (committed == 0 && scf_pg_update(gpg) == -1)
709 goto error;
710 } while (committed == 0);
711
712 ret = 0;
713 goto out;
714
715 error:
716 switch (scf_error()) {
717 case SCF_ERROR_DELETED:
718 case SCF_ERROR_NOT_FOUND:
719 /* success */
720 ret = 0;
721 }
722
723 out:
724 scf_entry_destroy(ent1);
725 scf_entry_destroy(ent2);
726 scf_transaction_destroy(tx);
727 scf_pg_destroy(gpg);
728
729 return (ret);
730 }
731
732 /*
733 * Returns 0 on success or -1 on failure. On failure leaves scf_error() set to
734 * SCF_ERROR_HANDLE_DESTROYED - inst's handle has been destroyed
735 * SCF_ERROR_NOT_BOUND - inst's handle is not bound
736 * SCF_ERROR_CONNECTION_BROKEN - the repository connection was broken
737 * SCF_ERROR_NOT_SET - inst is not set
738 * SCF_ERROR_DELETED - inst was deleted
739 * SCF_ERROR_PERMISSION_DENIED
740 * SCF_ERROR_BACKEND_ACCESS
741 * SCF_ERROR_BACKEND_READONLY
742 */
743 static int
744 set_inst_action_inst(scf_instance_t *inst, const char *action)
745 {
|