midlevel.c (bc9767f9) | midlevel.c (dfac3eb2) |
---|---|
1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 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 --- 10 unchanged lines hidden (view full) --- 19 * CDDL HEADER END 20 */ 21 22/* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 | 1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 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 --- 10 unchanged lines hidden (view full) --- 19 * CDDL HEADER END 20 */ 21 22/* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 |
27#pragma ident "%Z%%M% %I% %E% SMI" 28 | |
29#include "libscf_impl.h" 30 31#include <libuutil.h> 32#include <stdio.h> 33#include <strings.h> 34#include <string.h> 35#include <stdlib.h> 36#include <sys/param.h> 37#include <errno.h> 38#include <libgen.h> | 27#include "libscf_impl.h" 28 29#include <libuutil.h> 30#include <stdio.h> 31#include <strings.h> 32#include <string.h> 33#include <stdlib.h> 34#include <sys/param.h> 35#include <errno.h> 36#include <libgen.h> |
37#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); \ 46 abort(); \ --- 2433 unchanged lines hidden (view full) --- 2480 2481 if (temp_filename) { 2482 (void) strcpy(temp_filename, filename); 2483 (void) strcat(temp_filename, "XXXXXX"); 2484 } 2485 2486 return (0); 2487} | 38#include "midlevel_impl.h" 39#include "lowlevel_impl.h" 40 41#ifndef NDEBUG 42#define bad_error(func, err) { \ 43 uu_warn("%s:%d: %s failed with unexpected error %d. Aborting.\n", \ 44 __FILE__, __LINE__, func, err); \ 45 abort(); \ --- 2433 unchanged lines hidden (view full) --- 2479 2480 if (temp_filename) { 2481 (void) strcpy(temp_filename, filename); 2482 (void) strcat(temp_filename, "XXXXXX"); 2483 } 2484 2485 return (0); 2486} |
2487 2488static scf_type_t 2489scf_true_base_type(scf_type_t type) 2490{ 2491 scf_type_t base = type; 2492 2493 do { 2494 type = base; 2495 (void) scf_type_base_type(type, &base); 2496 } while (base != type); 2497 2498 return (base); 2499} 2500 2501/* 2502 * Convenience routine which frees all strings and opaque data 2503 * allocated by scf_read_propvec. 2504 * 2505 * Like free(3C), this function preserves the value of errno. 2506 */ 2507void 2508scf_clean_propvec(scf_propvec_t *propvec) 2509{ 2510 int saved_errno = errno; 2511 scf_propvec_t *prop; 2512 2513 for (prop = propvec; prop->pv_prop != NULL; prop++) { 2514 assert(prop->pv_type != SCF_TYPE_INVALID); 2515 if (prop->pv_type == SCF_TYPE_OPAQUE) { 2516 scf_opaque_t *o = prop->pv_ptr; 2517 2518 if (o->so_addr != NULL) 2519 free(o->so_addr); 2520 } else if (scf_true_base_type(prop->pv_type) == 2521 SCF_TYPE_ASTRING) { 2522 if (*(char **)prop->pv_ptr != NULL) 2523 free(*(char **)prop->pv_ptr); 2524 } 2525 } 2526 2527 errno = saved_errno; 2528} 2529 2530static int 2531count_props(scf_propvec_t *props) 2532{ 2533 int count = 0; 2534 2535 for (; props->pv_prop != NULL; props++) 2536 count++; 2537 return (count); 2538} 2539 2540/* 2541 * Reads a vector of properties from the specified fmri/property group. 2542 * If 'running' is true, reads from the running snapshot instead of the 2543 * editing snapshot. 2544 * 2545 * For string types, a buffer is allocated using malloc(3C) to hold the 2546 * zero-terminated string, a pointer to which is stored in the 2547 * caller-provided char **. It is the caller's responsbility to free 2548 * this string. To simplify error handling, unread strings are 2549 * initialized to NULL. 2550 * 2551 * For opaque types, a buffer is allocated using malloc(3C) to hold the 2552 * opaque data. A pointer to this buffer and its size are stored in 2553 * the caller-provided scf_opaque_t. It is the caller's responsibility 2554 * to free this buffer. To simplify error handling, the address fields 2555 * for unread opaque data are initialized to NULL. 2556 * 2557 * All other data is stored directly in caller-provided variables or 2558 * structures. 2559 * 2560 * If this function fails to read a specific property, *badprop is set 2561 * to point at that property's entry in the properties array. 2562 * 2563 * On all failures, all memory allocated by this function is freed. 2564 */ 2565int 2566scf_read_propvec(const char *fmri, const char *pgname, boolean_t running, 2567 scf_propvec_t *properties, scf_propvec_t **badprop) 2568{ 2569 scf_handle_t *h = handle_create(); 2570 scf_service_t *s = scf_service_create(h); 2571 scf_instance_t *i = scf_instance_create(h); 2572 scf_snapshot_t *snap = running ? scf_snapshot_create(h) : NULL; 2573 scf_propertygroup_t *pg = scf_pg_create(h); 2574 scf_property_t *p = scf_property_create(h); 2575 scf_value_t *v = scf_value_create(h); 2576 boolean_t instance = B_TRUE; 2577 scf_propvec_t *prop; 2578 int error = 0; 2579 2580 if (h == NULL || s == NULL || i == NULL || (running && snap == NULL) || 2581 pg == NULL || p == NULL || v == NULL) 2582 goto scferror; 2583 2584 if (scf_handle_decode_fmri(h, fmri, NULL, s, i, NULL, NULL, 0) == -1) 2585 goto scferror; 2586 2587 if (scf_instance_to_fmri(i, NULL, 0) == -1) { 2588 if (scf_error() != SCF_ERROR_NOT_SET) 2589 goto scferror; 2590 instance = B_FALSE; 2591 } 2592 2593 if (running) { 2594 if (!instance) { 2595 error = SCF_ERROR_TYPE_MISMATCH; 2596 goto out; 2597 } 2598 2599 if (scf_instance_get_snapshot(i, "running", snap) != 2600 SCF_SUCCESS) 2601 goto scferror; 2602 } 2603 2604 if ((instance ? scf_instance_get_pg_composed(i, snap, pgname, pg) : 2605 scf_service_get_pg(s, pgname, pg)) == -1) 2606 goto scferror; 2607 2608 for (prop = properties; prop->pv_prop != NULL; prop++) { 2609 if (prop->pv_type == SCF_TYPE_OPAQUE) 2610 ((scf_opaque_t *)prop->pv_ptr)->so_addr = NULL; 2611 else if (scf_true_base_type(prop->pv_type) == SCF_TYPE_ASTRING) 2612 *((char **)prop->pv_ptr) = NULL; 2613 } 2614 2615 for (prop = properties; prop->pv_prop != NULL; prop++) { 2616 int ret = 0; 2617 2618 if (scf_pg_get_property(pg, prop->pv_prop, p) == -1 || 2619 scf_property_get_value(p, v) == -1) { 2620 *badprop = prop; 2621 goto scferror; 2622 } 2623 switch (prop->pv_type) { 2624 case SCF_TYPE_BOOLEAN: { 2625 uint8_t b; 2626 2627 ret = scf_value_get_boolean(v, &b); 2628 if (ret == -1) 2629 break; 2630 if (prop->pv_aux != 0) { 2631 uint64_t *bits = prop->pv_ptr; 2632 *bits = b ? (*bits | prop->pv_aux) : 2633 (*bits & ~prop->pv_aux); 2634 } else { 2635 boolean_t *bool = prop->pv_ptr; 2636 *bool = b ? B_TRUE : B_FALSE; 2637 } 2638 break; 2639 } 2640 case SCF_TYPE_COUNT: 2641 ret = scf_value_get_count(v, prop->pv_ptr); 2642 break; 2643 case SCF_TYPE_INTEGER: 2644 ret = scf_value_get_integer(v, prop->pv_ptr); 2645 break; 2646 case SCF_TYPE_TIME: { 2647 scf_time_t *time = prop->pv_ptr; 2648 2649 ret = scf_value_get_time(v, &time->st_sec, 2650 &time->st_nanosec); 2651 break; 2652 } 2653 case SCF_TYPE_OPAQUE: { 2654 scf_opaque_t *opaque = prop->pv_ptr; 2655 ssize_t size = scf_value_get_opaque(v, NULL, 0); 2656 2657 if (size == -1) { 2658 *badprop = prop; 2659 goto scferror; 2660 } 2661 if ((opaque->so_addr = malloc(size)) == NULL) { 2662 error = SCF_ERROR_NO_MEMORY; 2663 goto out; 2664 } 2665 opaque->so_size = size; 2666 ret = scf_value_get_opaque(v, opaque->so_addr, size); 2667 break; 2668 } 2669 default: { 2670 char *s; 2671 ssize_t size; 2672 2673 assert(scf_true_base_type(prop->pv_type) == 2674 SCF_TYPE_ASTRING); 2675 2676 size = scf_value_get_astring(v, NULL, 0); 2677 if (size == -1) { 2678 *badprop = prop; 2679 goto scferror; 2680 } 2681 if ((s = malloc(++size)) == NULL) { 2682 error = SCF_ERROR_NO_MEMORY; 2683 goto out; 2684 } 2685 ret = scf_value_get_astring(v, s, size); 2686 *(char **)prop->pv_ptr = s; 2687 } 2688 2689 if (ret == -1) { 2690 *badprop = prop; 2691 goto scferror; 2692 } 2693 2694 } 2695 } 2696 2697 goto out; 2698 2699scferror: 2700 error = scf_error(); 2701 scf_clean_propvec(properties); 2702 2703out: 2704 scf_pg_destroy(pg); 2705 scf_snapshot_destroy(snap); 2706 scf_instance_destroy(i); 2707 scf_service_destroy(s); 2708 scf_handle_destroy(h); 2709 2710 if (error != 0) { 2711 (void) scf_set_error(error); 2712 return (SCF_FAILED); 2713 } 2714 2715 return (SCF_SUCCESS); 2716} 2717 2718/* 2719 * Writes a vector of properties to the specified fmri/property group. 2720 * 2721 * If this function fails to write a specific property, *badprop is set 2722 * to point at that property's entry in the properties array. 2723 * 2724 * One significant difference between this function and the 2725 * scf_read_propvec function is that for string types, pv_ptr is a 2726 * char *, not a char **. This means that you can't write a propvec 2727 * you just read, but makes other uses (hopefully the majority) simpler. 2728 */ 2729int 2730scf_write_propvec(const char *fmri, const char *pgname, 2731 scf_propvec_t *properties, scf_propvec_t **badprop) 2732{ 2733 scf_handle_t *h = handle_create(); 2734 scf_service_t *s = scf_service_create(h); 2735 scf_instance_t *inst = scf_instance_create(h); 2736 scf_snapshot_t *snap = scf_snapshot_create(h); 2737 scf_propertygroup_t *pg = scf_pg_create(h); 2738 scf_property_t *p = scf_property_create(h); 2739 scf_transaction_t *tx = scf_transaction_create(h); 2740 scf_value_t **v = NULL; 2741 scf_transaction_entry_t **e = NULL; 2742 boolean_t instance = B_TRUE; 2743 int i, n; 2744 scf_propvec_t *prop; 2745 int error = 0, ret; 2746 2747 n = count_props(properties); 2748 v = calloc(n, sizeof (scf_value_t *)); 2749 e = calloc(n, sizeof (scf_transaction_entry_t *)); 2750 2751 if (v == NULL || e == NULL) { 2752 error = SCF_ERROR_NO_MEMORY; 2753 goto out; 2754 } 2755 2756 if (h == NULL || s == NULL || inst == NULL || pg == NULL || p == NULL || 2757 tx == NULL) 2758 goto scferror; 2759 2760 for (i = 0; i < n; i++) { 2761 v[i] = scf_value_create(h); 2762 e[i] = scf_entry_create(h); 2763 if (v[i] == NULL || e[i] == NULL) 2764 goto scferror; 2765 } 2766 2767 if (scf_handle_decode_fmri(h, fmri, NULL, s, inst, NULL, NULL, 0) 2768 != SCF_SUCCESS) 2769 goto scferror; 2770 2771 if (scf_instance_to_fmri(inst, NULL, 0) == -1) { 2772 if (scf_error() != SCF_ERROR_NOT_SET) 2773 goto scferror; 2774 instance = B_FALSE; 2775 } 2776 2777 if ((instance ? scf_instance_get_pg(inst, pgname, pg) : 2778 scf_service_get_pg(s, pgname, pg)) == -1) 2779 goto scferror; 2780 2781top: 2782 if (scf_transaction_start(tx, pg) == -1) 2783 goto scferror; 2784 2785 for (prop = properties, i = 0; prop->pv_prop != NULL; prop++, i++) { 2786 ret = scf_transaction_property_change(tx, e[i], prop->pv_prop, 2787 prop->pv_type); 2788 if (ret == -1 && scf_error() == SCF_ERROR_NOT_FOUND) 2789 ret = scf_transaction_property_new(tx, e[i], 2790 prop->pv_prop, prop->pv_type); 2791 2792 if (ret == -1) { 2793 *badprop = prop; 2794 goto scferror; 2795 } 2796 2797 switch (prop->pv_type) { 2798 case SCF_TYPE_BOOLEAN: { 2799 boolean_t b = (prop->pv_aux != 0) ? 2800 (*(uint64_t *)prop->pv_ptr & prop->pv_aux) != 0 : 2801 *(boolean_t *)prop->pv_ptr; 2802 2803 scf_value_set_boolean(v[i], b ? 1 : 0); 2804 break; 2805 } 2806 case SCF_TYPE_COUNT: 2807 scf_value_set_count(v[i], *(uint64_t *)prop->pv_ptr); 2808 break; 2809 case SCF_TYPE_INTEGER: 2810 scf_value_set_integer(v[i], *(int64_t *)prop->pv_ptr); 2811 break; 2812 case SCF_TYPE_TIME: { 2813 scf_time_t *time = prop->pv_ptr; 2814 2815 ret = scf_value_set_time(v[i], time->st_sec, 2816 time->st_nanosec); 2817 break; 2818 } 2819 case SCF_TYPE_OPAQUE: { 2820 scf_opaque_t *opaque = prop->pv_ptr; 2821 2822 ret = scf_value_set_opaque(v[i], opaque->so_addr, 2823 opaque->so_size); 2824 break; 2825 } 2826 case SCF_TYPE_ASTRING: 2827 ret = scf_value_set_astring(v[i], 2828 (const char *)prop->pv_ptr); 2829 break; 2830 default: 2831 ret = scf_value_set_from_string(v[i], prop->pv_type, 2832 (const char *)prop->pv_ptr); 2833 } 2834 2835 if (ret == -1 || scf_entry_add_value(e[i], v[i]) == -1) { 2836 *badprop = prop; 2837 goto scferror; 2838 } 2839 } 2840 2841 ret = scf_transaction_commit(tx); 2842 if (ret == 1) 2843 goto out; 2844 2845 if (ret == 0 && scf_pg_update(pg) != -1) { 2846 scf_transaction_reset(tx); 2847 goto top; 2848 } 2849 2850scferror: 2851 error = scf_error(); 2852 2853out: 2854 if (v != NULL) { 2855 for (i = 0; i < n; i++) 2856 scf_value_destroy(v[i]); 2857 free(v); 2858 } 2859 2860 if (e != NULL) { 2861 for (i = 0; i < n; i++) 2862 scf_entry_destroy(e[i]); 2863 free(e); 2864 } 2865 2866 scf_transaction_destroy(tx); 2867 scf_property_destroy(p); 2868 scf_pg_destroy(pg); 2869 scf_snapshot_destroy(snap); 2870 scf_instance_destroy(inst); 2871 scf_service_destroy(s); 2872 scf_handle_destroy(h); 2873 2874 if (error != 0) { 2875 (void) scf_set_error(error); 2876 return (SCF_FAILED); 2877 } 2878 2879 return (SCF_SUCCESS); 2880} |
|