Print this page
12721 would like svcadm disable -c


   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 {