#include <libscf.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <errno.h>
#include <uuid/uuid.h>
#include <sys/param.h>
#include <libintl.h>
#include <assert.h>
#include <strings.h>
#include "libshare.h"
#include "libshare_smbfs.h"
static void
smb_smf_scf_log_error(char *msg)
{
if (msg == NULL)
msg = "SMBC SMF problem";
syslog(LOG_ERR, "%s: %s", msg, scf_strerror(scf_error()));
}
void
smb_smf_scf_fini(smb_scfhandle_t *handle)
{
if (handle != NULL) {
int unbind = 0;
if (handle->scf_pg_iter != NULL) {
scf_iter_destroy(handle->scf_pg_iter);
handle->scf_pg_iter = NULL;
}
if (handle->scf_inst_iter != NULL) {
scf_iter_destroy(handle->scf_inst_iter);
handle->scf_inst_iter = NULL;
}
if (handle->scf_scope != NULL) {
unbind = 1;
scf_scope_destroy(handle->scf_scope);
handle->scf_scope = NULL;
}
if (handle->scf_instance != NULL) {
scf_instance_destroy(handle->scf_instance);
handle->scf_instance = NULL;
}
if (handle->scf_service != NULL) {
scf_service_destroy(handle->scf_service);
handle->scf_service = NULL;
}
if (handle->scf_pg != NULL) {
scf_pg_destroy(handle->scf_pg);
handle->scf_pg = NULL;
}
if (handle->scf_handle != NULL) {
handle->scf_state = SCH_STATE_UNINIT;
if (unbind)
(void) scf_handle_unbind(handle->scf_handle);
scf_handle_destroy(handle->scf_handle);
handle->scf_handle = NULL;
}
free(handle);
}
}
int
smb_smf_instance_exists(smb_scfhandle_t *handle, char *inst_name)
{
int ret = SMBC_SMF_OK;
if (handle == NULL) {
return (SMBC_SMF_SYSTEM_ERR);
}
handle->scf_instance = scf_instance_create(handle->scf_handle);
if (scf_service_get_instance(handle->scf_service, inst_name,
handle->scf_instance) != SCF_SUCCESS) {
ret = SMBC_SMF_SYSTEM_ERR;
}
scf_instance_destroy(handle->scf_instance);
handle->scf_instance = NULL;
return (ret);
}
int
smb_smf_instance_create(smb_scfhandle_t *handle, char *serv_prefix,
char *inst_name)
{
char *instance;
int ret = SMBC_SMF_OK;
int sz;
if (handle == NULL) {
return (SMBC_SMF_SYSTEM_ERR);
}
if (!serv_prefix || !inst_name) {
return (SMBC_SMF_SYSTEM_ERR);
}
sz = strlen(serv_prefix) + strlen(inst_name) + 2;
instance = malloc(sz);
if (!instance) {
return (SMBC_SMF_SYSTEM_ERR);
}
(void) snprintf(instance, sz, "%s:%s", serv_prefix, inst_name);
handle->scf_instance = scf_instance_create(handle->scf_handle);
if (scf_service_get_instance(handle->scf_service, inst_name,
handle->scf_instance) != SCF_SUCCESS) {
if (scf_service_add_instance(handle->scf_service,
inst_name, handle->scf_instance) == SCF_SUCCESS) {
if (smf_enable_instance(instance, 0))
ret = SMBC_SMF_SYSTEM_ERR;
} else {
ret = SMBC_SMF_SYSTEM_ERR;
}
} else {
if (smf_enable_instance(instance, 0))
ret = SMBC_SMF_SYSTEM_ERR;
}
free(instance);
return (ret);
}
int
smb_smf_instance_delete(smb_scfhandle_t *handle, char *inst_name)
{
int ret = SMBC_SMF_OK;
if (handle == NULL) {
return (SMBC_SMF_SYSTEM_ERR);
}
handle->scf_instance = scf_instance_create(handle->scf_handle);
if (scf_service_get_instance(handle->scf_service, inst_name,
handle->scf_instance) == SCF_SUCCESS) {
if (scf_instance_delete(handle->scf_instance) == SCF_SUCCESS) {
return (ret);
} else {
ret = SMBC_SMF_SYSTEM_ERR;
}
} else {
smb_smf_scf_log_error(NULL);
ret = SMBC_SMF_SYSTEM_ERR;
}
return (ret);
}
smb_scfhandle_t *
smb_smf_scf_init(char *svc_name)
{
smb_scfhandle_t *handle;
handle = malloc(sizeof (smb_scfhandle_t));
if (handle != NULL) {
bzero((char *)handle, sizeof (smb_scfhandle_t));
handle->scf_state = SCH_STATE_INITIALIZING;
handle->scf_handle = scf_handle_create(SCF_VERSION);
if (handle->scf_handle != NULL) {
if (scf_handle_bind(handle->scf_handle) == 0) {
handle->scf_scope =
scf_scope_create(handle->scf_handle);
if (scf_handle_get_local_scope(
handle->scf_handle, handle->scf_scope) != 0)
goto err;
handle->scf_service =
scf_service_create(handle->scf_handle);
if (scf_scope_get_service(handle->scf_scope,
svc_name, handle->scf_service)
!= SCF_SUCCESS) {
goto err;
}
handle->scf_pg =
scf_pg_create(handle->scf_handle);
handle->scf_state = SCH_STATE_INIT;
} else {
goto err;
}
} else {
free(handle);
handle = NULL;
smb_smf_scf_log_error(
"Could not access SMF repository");
}
}
return (handle);
err:
(void) smb_smf_scf_fini(handle);
if (scf_error() != SCF_ERROR_NOT_FOUND)
(void) smb_smf_scf_log_error("SMF initialization problem");
return (NULL);
}
int
smb_smf_create_service_pgroup(smb_scfhandle_t *handle, char *pgroup)
{
int ret = SMBC_SMF_OK;
int err;
if (handle == NULL) {
return (SMBC_SMF_SYSTEM_ERR);
}
if (handle->scf_pg == NULL) {
handle->scf_pg = scf_pg_create(handle->scf_handle);
}
if (scf_service_get_pg(handle->scf_service,
pgroup, handle->scf_pg) != 0) {
if (scf_service_add_pg(handle->scf_service, pgroup,
SCF_GROUP_FRAMEWORK, 0, handle->scf_pg) != 0) {
err = scf_error();
if (err != SCF_ERROR_NONE)
smb_smf_scf_log_error(NULL);
switch (err) {
case SCF_ERROR_PERMISSION_DENIED:
ret = SMBC_SMF_NO_PERMISSION;
break;
default:
ret = SMBC_SMF_SYSTEM_ERR;
break;
}
}
}
return (ret);
}
int
smb_smf_create_instance_pgroup(smb_scfhandle_t *handle, char *pgroup)
{
int ret = SMBC_SMF_OK;
int err;
if (handle == NULL) {
return (SMBC_SMF_SYSTEM_ERR);
}
if (handle->scf_pg == NULL) {
handle->scf_pg = scf_pg_create(handle->scf_handle);
}
if (scf_instance_get_pg(handle->scf_instance,
pgroup, handle->scf_pg) != 0) {
if (scf_instance_add_pg(handle->scf_instance, pgroup,
SCF_GROUP_APPLICATION, 0, handle->scf_pg) != 0) {
err = scf_error();
if (err != SCF_ERROR_NONE)
smb_smf_scf_log_error(NULL);
switch (err) {
case SCF_ERROR_PERMISSION_DENIED:
ret = SMBC_SMF_NO_PERMISSION;
break;
default:
ret = SMBC_SMF_SYSTEM_ERR;
break;
}
}
}
return (ret);
}
int
smb_smf_delete_service_pgroup(smb_scfhandle_t *handle, char *pgroup)
{
int ret = SMBC_SMF_OK;
int err;
if (handle == NULL) {
return (SMBC_SMF_SYSTEM_ERR);
}
if (handle->scf_pg == NULL) {
handle->scf_pg = scf_pg_create(handle->scf_handle);
}
if (scf_service_get_pg(handle->scf_service,
pgroup, handle->scf_pg) == 0) {
if (scf_pg_delete(handle->scf_pg) != 0) {
ret = SMBC_SMF_SYSTEM_ERR;
err = scf_error();
if (err != SCF_ERROR_NONE) {
smb_smf_scf_log_error("SMF delpg problem");
}
}
} else {
err = scf_error();
if (err != SCF_ERROR_NONE)
smb_smf_scf_log_error("SMF getpg problem");
ret = SMBC_SMF_SYSTEM_ERR;
}
if (ret == SMBC_SMF_SYSTEM_ERR &&
scf_error() == SCF_ERROR_PERMISSION_DENIED) {
ret = SMBC_SMF_NO_PERMISSION;
}
return (ret);
}
int
smb_smf_delete_instance_pgroup(smb_scfhandle_t *handle, char *pgroup)
{
int ret = SMBC_SMF_OK;
int err;
if (handle == NULL) {
return (SMBC_SMF_SYSTEM_ERR);
}
if (handle->scf_pg == NULL) {
handle->scf_pg = scf_pg_create(handle->scf_handle);
}
if (scf_instance_get_pg(handle->scf_instance,
pgroup, handle->scf_pg) == 0) {
if (scf_pg_delete(handle->scf_pg) != 0) {
ret = SMBC_SMF_SYSTEM_ERR;
err = scf_error();
if (err != SCF_ERROR_NONE) {
smb_smf_scf_log_error("SMF delpg problem");
}
}
} else {
err = scf_error();
if (err != SCF_ERROR_NONE)
smb_smf_scf_log_error("SMF getpg problem");
ret = SMBC_SMF_SYSTEM_ERR;
}
if (ret == SMBC_SMF_SYSTEM_ERR &&
scf_error() == SCF_ERROR_PERMISSION_DENIED) {
ret = SMBC_SMF_NO_PERMISSION;
}
return (ret);
}
int
smb_smf_start_transaction(smb_scfhandle_t *handle)
{
int ret = SMBC_SMF_OK;
if (!handle || (!handle->scf_pg)) {
return (SMBC_SMF_SYSTEM_ERR);
}
if (handle->scf_state == SCH_STATE_INIT) {
if (ret == SMBC_SMF_OK) {
handle->scf_trans =
scf_transaction_create(handle->scf_handle);
if (handle->scf_trans != NULL) {
if (scf_transaction_start(handle->scf_trans,
handle->scf_pg) != 0) {
ret = SMBC_SMF_SYSTEM_ERR;
scf_transaction_destroy(
handle->scf_trans);
handle->scf_trans = NULL;
}
} else {
ret = SMBC_SMF_SYSTEM_ERR;
}
}
}
if (ret == SMBC_SMF_SYSTEM_ERR &&
scf_error() == SCF_ERROR_PERMISSION_DENIED) {
ret = SMBC_SMF_NO_PERMISSION;
}
return (ret);
}
int
smb_smf_end_transaction(smb_scfhandle_t *handle)
{
int ret = SMBC_SMF_OK;
if (handle == NULL) {
return (SMBC_SMF_SYSTEM_ERR);
}
if (handle->scf_trans == NULL) {
ret = SMBC_SMF_SYSTEM_ERR;
} else {
if (scf_transaction_commit(handle->scf_trans) < 0) {
ret = SMBC_SMF_SYSTEM_ERR;
smb_smf_scf_log_error("Failed to commit transaction");
}
scf_transaction_destroy_children(handle->scf_trans);
scf_transaction_destroy(handle->scf_trans);
handle->scf_trans = NULL;
}
return (ret);
}
int
smb_smf_delete_property(smb_scfhandle_t *handle, char *propname)
{
int ret = SMBC_SMF_OK;
scf_transaction_entry_t *entry = NULL;
if (handle == NULL) {
return (SMBC_SMF_SYSTEM_ERR);
}
entry = scf_entry_create(handle->scf_handle);
if (entry != NULL) {
if (scf_transaction_property_delete(handle->scf_trans, entry,
propname) != 0) {
ret = SMBC_SMF_SYSTEM_ERR;
}
} else {
ret = SMBC_SMF_SYSTEM_ERR;
}
if (ret == SMBC_SMF_SYSTEM_ERR) {
if (scf_error() == SCF_ERROR_PERMISSION_DENIED) {
ret = SMBC_SMF_NO_PERMISSION;
}
}
if ((ret != SMBC_SMF_OK) && (entry != NULL)) {
scf_entry_destroy(entry);
}
return (ret);
}
int
smb_smf_set_string_property(smb_scfhandle_t *handle,
char *propname, char *valstr)
{
int ret = SMBC_SMF_OK;
scf_value_t *value = NULL;
scf_transaction_entry_t *entry = NULL;
if (handle == NULL) {
return (SMBC_SMF_SYSTEM_ERR);
}
value = scf_value_create(handle->scf_handle);
entry = scf_entry_create(handle->scf_handle);
if (value != NULL && entry != NULL) {
if (scf_transaction_property_change(handle->scf_trans, entry,
propname, SCF_TYPE_ASTRING) == 0 ||
scf_transaction_property_new(handle->scf_trans, entry,
propname, SCF_TYPE_ASTRING) == 0) {
if (scf_value_set_astring(value, valstr) == 0) {
if (scf_entry_add_value(entry, value) != 0) {
ret = SMBC_SMF_SYSTEM_ERR;
scf_value_destroy(value);
}
value = NULL;
} else {
ret = SMBC_SMF_SYSTEM_ERR;
}
entry = NULL;
} else {
ret = SMBC_SMF_SYSTEM_ERR;
}
} else {
ret = SMBC_SMF_SYSTEM_ERR;
}
if (ret == SMBC_SMF_SYSTEM_ERR) {
if (scf_error() == SCF_ERROR_PERMISSION_DENIED) {
ret = SMBC_SMF_NO_PERMISSION;
}
}
if (value != NULL)
scf_value_destroy(value);
if (entry != NULL)
scf_entry_destroy(entry);
return (ret);
}
int
smb_smf_get_string_property(smb_scfhandle_t *handle, char *propname,
char *valstr, size_t sz)
{
int ret = SMBC_SMF_OK;
scf_value_t *value;
scf_property_t *prop;
if (handle == NULL) {
return (SMBC_SMF_SYSTEM_ERR);
}
value = scf_value_create(handle->scf_handle);
prop = scf_property_create(handle->scf_handle);
if (value && prop &&
(scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
if (scf_property_get_value(prop, value) == 0) {
if (scf_value_get_astring(value, valstr, sz) < 0) {
ret = SMBC_SMF_SYSTEM_ERR;
}
} else {
ret = SMBC_SMF_SYSTEM_ERR;
}
} else {
ret = SMBC_SMF_SYSTEM_ERR;
}
if (value != NULL)
scf_value_destroy(value);
if (prop != NULL)
scf_property_destroy(prop);
return (ret);
}
int
smb_smf_set_integer_property(smb_scfhandle_t *handle, char *propname,
int64_t valint)
{
int ret = SMBC_SMF_OK;
scf_value_t *value = NULL;
scf_transaction_entry_t *entry = NULL;
if (handle == NULL) {
return (SMBC_SMF_SYSTEM_ERR);
}
value = scf_value_create(handle->scf_handle);
entry = scf_entry_create(handle->scf_handle);
if (value != NULL && entry != NULL) {
if (scf_transaction_property_change(handle->scf_trans, entry,
propname, SCF_TYPE_INTEGER) == 0 ||
scf_transaction_property_new(handle->scf_trans, entry,
propname, SCF_TYPE_INTEGER) == 0) {
scf_value_set_integer(value, valint);
if (scf_entry_add_value(entry, value) != 0) {
ret = SMBC_SMF_SYSTEM_ERR;
scf_value_destroy(value);
}
value = NULL;
}
entry = NULL;
} else {
ret = SMBC_SMF_SYSTEM_ERR;
}
if (ret == SMBC_SMF_SYSTEM_ERR) {
if (scf_error() == SCF_ERROR_PERMISSION_DENIED) {
ret = SMBC_SMF_NO_PERMISSION;
}
}
if (value != NULL)
scf_value_destroy(value);
if (entry != NULL)
scf_entry_destroy(entry);
return (ret);
}
int
smb_smf_get_integer_property(smb_scfhandle_t *handle, char *propname,
int64_t *valint)
{
int ret = SMBC_SMF_OK;
scf_value_t *value = NULL;
scf_property_t *prop = NULL;
if (handle == NULL) {
return (SMBC_SMF_SYSTEM_ERR);
}
value = scf_value_create(handle->scf_handle);
prop = scf_property_create(handle->scf_handle);
if ((prop) && (value) &&
(scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
if (scf_property_get_value(prop, value) == 0) {
if (scf_value_get_integer(value,
valint) != 0) {
ret = SMBC_SMF_SYSTEM_ERR;
}
} else {
ret = SMBC_SMF_SYSTEM_ERR;
}
} else {
ret = SMBC_SMF_SYSTEM_ERR;
}
if (value != NULL)
scf_value_destroy(value);
if (prop != NULL)
scf_property_destroy(prop);
return (ret);
}
int
smb_smf_set_boolean_property(smb_scfhandle_t *handle, char *propname,
uint8_t valbool)
{
int ret = SMBC_SMF_OK;
scf_value_t *value = NULL;
scf_transaction_entry_t *entry = NULL;
if (handle == NULL) {
return (SMBC_SMF_SYSTEM_ERR);
}
value = scf_value_create(handle->scf_handle);
entry = scf_entry_create(handle->scf_handle);
if (value != NULL && entry != NULL) {
if (scf_transaction_property_change(handle->scf_trans, entry,
propname, SCF_TYPE_BOOLEAN) == 0 ||
scf_transaction_property_new(handle->scf_trans, entry,
propname, SCF_TYPE_BOOLEAN) == 0) {
scf_value_set_boolean(value, valbool);
if (scf_entry_add_value(entry, value) != 0) {
ret = SMBC_SMF_SYSTEM_ERR;
scf_value_destroy(value);
}
value = NULL;
}
entry = NULL;
} else {
ret = SMBC_SMF_SYSTEM_ERR;
}
if (ret == SMBC_SMF_SYSTEM_ERR) {
if (scf_error() == SCF_ERROR_PERMISSION_DENIED) {
ret = SMBC_SMF_NO_PERMISSION;
}
}
if (value != NULL)
scf_value_destroy(value);
if (entry != NULL)
scf_entry_destroy(entry);
return (ret);
}
int
smb_smf_get_boolean_property(smb_scfhandle_t *handle, char *propname,
uint8_t *valbool)
{
int ret = SMBC_SMF_OK;
scf_value_t *value = NULL;
scf_property_t *prop = NULL;
if (handle == NULL) {
return (SMBC_SMF_SYSTEM_ERR);
}
value = scf_value_create(handle->scf_handle);
prop = scf_property_create(handle->scf_handle);
if ((prop) && (value) &&
(scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
if (scf_property_get_value(prop, value) == 0) {
if (scf_value_get_boolean(value,
valbool) != 0) {
ret = SMBC_SMF_SYSTEM_ERR;
}
} else {
ret = SMBC_SMF_SYSTEM_ERR;
}
} else {
ret = SMBC_SMF_SYSTEM_ERR;
}
if (value != NULL)
scf_value_destroy(value);
if (prop != NULL)
scf_property_destroy(prop);
return (ret);
}
int
smb_smf_set_opaque_property(smb_scfhandle_t *handle, char *propname,
void *voidval, size_t sz)
{
int ret = SMBC_SMF_OK;
scf_value_t *value;
scf_transaction_entry_t *entry;
if (handle == NULL) {
return (SMBC_SMF_SYSTEM_ERR);
}
value = scf_value_create(handle->scf_handle);
entry = scf_entry_create(handle->scf_handle);
if (value != NULL && entry != NULL) {
if (scf_transaction_property_change(handle->scf_trans, entry,
propname, SCF_TYPE_OPAQUE) == 0 ||
scf_transaction_property_new(handle->scf_trans, entry,
propname, SCF_TYPE_OPAQUE) == 0) {
if (scf_value_set_opaque(value, voidval, sz) == 0) {
if (scf_entry_add_value(entry, value) != 0) {
ret = SMBC_SMF_SYSTEM_ERR;
scf_value_destroy(value);
}
value = NULL;
} else {
ret = SMBC_SMF_SYSTEM_ERR;
}
entry = NULL;
} else {
ret = SMBC_SMF_SYSTEM_ERR;
}
} else {
ret = SMBC_SMF_SYSTEM_ERR;
}
if (ret == SMBC_SMF_SYSTEM_ERR) {
if (scf_error() == SCF_ERROR_PERMISSION_DENIED) {
ret = SMBC_SMF_NO_PERMISSION;
}
}
if (value != NULL)
scf_value_destroy(value);
if (entry != NULL)
scf_entry_destroy(entry);
return (ret);
}
int
smb_smf_get_opaque_property(smb_scfhandle_t *handle, char *propname,
void *v, size_t sz)
{
int ret = SMBC_SMF_OK;
scf_value_t *value = NULL;
scf_property_t *prop = NULL;
if (handle == NULL) {
return (SMBC_SMF_SYSTEM_ERR);
}
value = scf_value_create(handle->scf_handle);
prop = scf_property_create(handle->scf_handle);
if ((prop) && (value) &&
(scf_pg_get_property(handle->scf_pg, propname, prop) == 0)) {
if (scf_property_get_value(prop, value) == 0) {
if (scf_value_get_opaque(value, (char *)v, sz) != sz) {
ret = SMBC_SMF_SYSTEM_ERR;
}
} else {
ret = SMBC_SMF_SYSTEM_ERR;
}
} else {
ret = SMBC_SMF_SYSTEM_ERR;
}
if (value != NULL)
scf_value_destroy(value);
if (prop != NULL)
scf_property_destroy(prop);
return (ret);
}
smb_scfhandle_t *
smb_smf_get_iterator(char *svc_name)
{
smb_scfhandle_t *handle = NULL;
handle = smb_smf_scf_init(svc_name);
if (!handle) {
return (NULL);
}
handle->scf_inst_iter = scf_iter_create(handle->scf_handle);
if (handle->scf_inst_iter) {
if (scf_iter_service_instances(handle->scf_inst_iter,
handle->scf_service) != 0) {
smb_smf_scf_fini(handle);
handle = NULL;
} else {
handle->scf_instance = NULL;
}
} else {
smb_smf_scf_fini(handle);
handle = NULL;
}
return (handle);
}