2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A
2N/A/*
2N/A * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A#include <strings.h>
2N/A#include <libintl.h>
2N/A#include <libnvpair.h>
2N/A#include <sys/stat.h>
2N/A#include <errno.h>
2N/A#include <synch.h>
2N/A#include <note.h>
2N/A#include <sys/param.h>
2N/A#include <sys/sysmacros.h>
2N/A#include <sys/mnttab.h>
2N/A
2N/A#include <libshare.h>
2N/A#include <libshare_impl.h>
2N/A#include <sharefs/share.h>
2N/A#include <sharefs/sharetab.h>
2N/A
2N/Astatic int sa_legacy_init(void);
2N/Astatic void sa_legacy_fini(void);
2N/Astatic void *sa_legacy_open(libshare_handle_t *);
2N/Astatic void sa_legacy_close(void *);
2N/Astatic int sa_legacy_share_write(libshare_handle_t *, nvlist_t *, boolean_t);
2N/Astatic int sa_legacy_share_read(libshare_handle_t *, const char *,
2N/A const char *, nvlist_t **);
2N/Astatic int sa_legacy_share_read_init(libshare_handle_t *, sa_read_hdl_t *);
2N/Astatic int sa_legacy_share_read_next(libshare_handle_t *, sa_read_hdl_t *,
2N/A nvlist_t **);
2N/Astatic int sa_legacy_share_read_fini(libshare_handle_t *, sa_read_hdl_t *);
2N/Astatic int sa_legacy_share_remove(libshare_handle_t *, const char *,
2N/A const char *, boolean_t);
2N/Astatic int sa_legacy_share_get_acl(libshare_handle_t *, const char *,
2N/A const char *, acl_t **);
2N/Astatic int sa_legacy_share_set_acl(libshare_handle_t *, const char *,
2N/A const char *, acl_t *);
2N/Astatic int sa_legacy_get_mntpnt_for_path(libshare_handle_t *, const char *,
2N/A char *, size_t, char *, size_t, char *, size_t);
2N/Astatic int sa_legacy_sharing_enabled(libshare_handle_t *, const char *,
2N/A const char *, sa_proto_t *);
2N/Astatic int sa_legacy_sharing_get_prop(libshare_handle_t *, const char *,
2N/A const char *, sa_proto_t, char **);
2N/Astatic int sa_legacy_sharing_set_prop(libshare_handle_t *, const char *,
2N/A const char *, sa_proto_t, const char *);
2N/Astatic int sa_legacy_is_legacy(libshare_handle_t *, const char *, boolean_t *);
2N/Astatic int sa_legacy_is_zoned(libshare_handle_t *, const char *, boolean_t *);
2N/A
2N/Astruct legacy_mount; /* forward declaration */
2N/Atypedef struct legacy_mount {
2N/A struct legacy_mount *lm_next;
2N/A char *lm_mntpnt;
2N/A char *lm_mntopts;
2N/A} legacy_mount_t;
2N/A
2N/Atypedef struct legacy_handle {
2N/A scf_handle_t *legacy_smf_hdl;
2N/A scf_instance_t *legacy_smf_instance;
2N/A scf_scope_t *legacy_smf_scope;
2N/A scf_service_t *legacy_smf_service;
2N/A legacy_mount_t *legacy_mounts;
2N/A} legacy_handle_t;
2N/A
2N/Astatic void sa_legacy_cleanup_smf(legacy_handle_t *);
2N/Astatic int sa_legacy_check_mounts(legacy_handle_t *, char *, char *, size_t,
2N/A char *, size_t);
2N/Astatic void sa_legacy_cleanup_mounts(legacy_handle_t *);
2N/A
2N/Asa_fs_ops_t sa_plugin_ops = {
2N/A .saf_hdr = {
2N/A .pi_ptype = SA_PLUGIN_FS,
2N/A .pi_type = SA_FS_LEGACY,
2N/A .pi_name = "legacy",
2N/A .pi_version = SA_LIBSHARE_VERSION,
2N/A .pi_flags = 0,
2N/A .pi_init = sa_legacy_init,
2N/A .pi_fini = sa_legacy_fini
2N/A },
2N/A .saf_open = sa_legacy_open,
2N/A .saf_close = sa_legacy_close,
2N/A .saf_reset = NULL,
2N/A .saf_share_write = sa_legacy_share_write,
2N/A .saf_share_read = sa_legacy_share_read,
2N/A .saf_share_read_init = sa_legacy_share_read_init,
2N/A .saf_share_read_next = sa_legacy_share_read_next,
2N/A .saf_share_read_fini = sa_legacy_share_read_fini,
2N/A .saf_share_remove = sa_legacy_share_remove,
2N/A .saf_share_get_acl = sa_legacy_share_get_acl,
2N/A .saf_share_set_acl = sa_legacy_share_set_acl,
2N/A .saf_get_mntpnt_for_path = sa_legacy_get_mntpnt_for_path,
2N/A .saf_sharing_enabled = sa_legacy_sharing_enabled,
2N/A .saf_sharing_get_prop = sa_legacy_sharing_get_prop,
2N/A .saf_sharing_set_prop = sa_legacy_sharing_set_prop,
2N/A .saf_is_legacy = sa_legacy_is_legacy,
2N/A .saf_is_zoned = sa_legacy_is_zoned,
2N/A .saf_share_notify = NULL
2N/A};
2N/A
2N/Astatic int
2N/Asa_legacy_init(void)
2N/A{
2N/A return (SA_OK);
2N/A}
2N/A
2N/Astatic void
2N/Asa_legacy_fini(void)
2N/A{
2N/A /* do nothing */
2N/A}
2N/A
2N/Astatic void
2N/Asa_legacy_cleanup_smf(legacy_handle_t *hdl)
2N/A{
2N/A if (hdl->legacy_smf_scope != NULL) {
2N/A scf_scope_destroy(hdl->legacy_smf_scope);
2N/A hdl->legacy_smf_scope = NULL;
2N/A }
2N/A
2N/A if (hdl->legacy_smf_hdl != NULL) {
2N/A scf_handle_destroy(hdl->legacy_smf_hdl);
2N/A hdl->legacy_smf_hdl = NULL;
2N/A }
2N/A
2N/A if (hdl->legacy_smf_instance != NULL) {
2N/A scf_instance_destroy(hdl->legacy_smf_instance);
2N/A hdl->legacy_smf_instance = NULL;
2N/A }
2N/A
2N/A if (hdl->legacy_smf_service != NULL) {
2N/A scf_service_destroy(hdl->legacy_smf_service);
2N/A hdl->legacy_smf_service = NULL;
2N/A }
2N/A}
2N/A
2N/Astatic void
2N/Asa_legacy_cleanup_mounts(legacy_handle_t *hdl)
2N/A{
2N/A legacy_mount_t *lm;
2N/A
2N/A while ((lm = hdl->legacy_mounts) != NULL) {
2N/A hdl->legacy_mounts = lm->lm_next;
2N/A free(lm->lm_mntpnt);
2N/A free(lm->lm_mntopts);
2N/A free(lm);
2N/A }
2N/A}
2N/A
2N/Astatic legacy_handle_t *
2N/Alegacy_init(void)
2N/A{
2N/A legacy_handle_t *hdl;
2N/A
2N/A if ((hdl = calloc(1, sizeof (legacy_handle_t))) == NULL)
2N/A return (NULL);
2N/A
2N/A if ((hdl->legacy_smf_hdl = scf_handle_create(SCF_VERSION)) == NULL)
2N/A goto err;
2N/A
2N/A if (scf_handle_bind(hdl->legacy_smf_hdl) != 0)
2N/A goto err;
2N/A
2N/A if ((hdl->legacy_smf_instance =
2N/A scf_instance_create(hdl->legacy_smf_hdl)) == NULL)
2N/A goto err;
2N/A
2N/A if ((hdl->legacy_smf_scope =
2N/A scf_scope_create(hdl->legacy_smf_hdl)) == NULL)
2N/A goto err;
2N/A
2N/A if (scf_handle_get_scope(hdl->legacy_smf_hdl, SCF_SCOPE_LOCAL,
2N/A hdl->legacy_smf_scope) != 0)
2N/A goto err;
2N/A
2N/A if ((hdl->legacy_smf_service =
2N/A scf_service_create(hdl->legacy_smf_hdl)) == NULL)
2N/A goto err;
2N/A
2N/A if (scf_scope_get_service(hdl->legacy_smf_scope, "network/shares",
2N/A hdl->legacy_smf_service) != 0)
2N/A goto err;
2N/A
2N/A if (scf_service_get_instance(hdl->legacy_smf_service, "default",
2N/A hdl->legacy_smf_instance) != 0)
2N/A goto err;
2N/A
2N/A return (hdl);
2N/Aerr:
2N/A sa_legacy_cleanup_smf(hdl);
2N/A free(hdl);
2N/A return (NULL);
2N/A}
2N/A
2N/Astatic void
2N/Alegacy_fini(legacy_handle_t *hdl)
2N/A{
2N/A sa_legacy_cleanup_smf(hdl);
2N/A sa_legacy_cleanup_mounts(hdl);
2N/A free(hdl);
2N/A}
2N/A
2N/Astatic void *
2N/Asa_legacy_open(libshare_handle_t *shdl)
2N/A{
2N/A NOTE(ARGUNUSED(shdl))
2N/A
2N/A legacy_handle_t *hdl;
2N/A
2N/A if ((hdl = legacy_init()) == NULL) {
2N/A salog_error(0, "libshare_legacy: failed to open legacy handle");
2N/A return (NULL);
2N/A }
2N/A
2N/A return (hdl);
2N/A}
2N/A
2N/Astatic void
2N/Asa_legacy_close(void *legacy_hdl)
2N/A{
2N/A legacy_fini(legacy_hdl);
2N/A}
2N/A
2N/A/*
2N/A * sa_legacy_fix_share_name
2N/A *
2N/A * some valid SMB share names contain characters illegal in SMF. This
2N/A * function maps to a valid character set. Since it is only used when
2N/A * referencing SMF, it only needs a one way mapping.
2N/A */
2N/Astatic char *
2N/Asa_legacy_fix_share_name(const char *sharename)
2N/A{
2N/A static char hex[] = "0123456789abcdef";
2N/A static char invalid[] = " .&,#$^(){}~_";
2N/A char buf[MAXNAMELEN];
2N/A char *newshare = buf;
2N/A char *limit = buf + MAXNAMELEN - 1;
2N/A
2N/A newshare += snprintf(buf, sizeof (buf), "S-");
2N/A while (*sharename != '\0' && newshare < limit) {
2N/A if (strchr(invalid, *sharename) != NULL) {
2N/A *newshare++ = '_';
2N/A *newshare++ = hex[(*sharename & 0xF0) >> 4];
2N/A *newshare++ = hex[*sharename & 0xF];
2N/A } else {
2N/A *newshare++ = *sharename;
2N/A }
2N/A sharename++;
2N/A }
2N/A
2N/A *newshare = '\0';
2N/A return (strdup(buf));
2N/A}
2N/A
2N/A/*
2N/A * legacy_common_transaction
2N/A *
2N/A * implements both store and remove of SMF property.
2N/A */
2N/A
2N/Astatic int
2N/Alegacy_common_transaction(legacy_handle_t *hdl, const char *shname,
2N/A char *buf, size_t buflen, boolean_t dowrite)
2N/A{
2N/A scf_transaction_t *trans = NULL;
2N/A scf_propertygroup_t *pg = NULL;
2N/A scf_value_t *value = NULL;
2N/A scf_transaction_entry_t *entry = NULL;
2N/A int ret = SA_OK;
2N/A char *sharename;
2N/A
2N/A sharename = sa_legacy_fix_share_name(shname);
2N/A if (sharename == NULL) {
2N/A ret = SA_NO_MEMORY;
2N/A goto err;
2N/A }
2N/A
2N/A trans = scf_transaction_create(hdl->legacy_smf_hdl);
2N/A if (trans == NULL) {
2N/A ret = SA_SYSTEM_ERR;
2N/A goto err;
2N/A }
2N/A
2N/A pg = scf_pg_create(hdl->legacy_smf_hdl);
2N/A if (pg == NULL) {
2N/A ret = SA_SYSTEM_ERR;
2N/A goto err;
2N/A }
2N/A
2N/A if (scf_instance_get_pg(hdl->legacy_smf_instance, LEGACY_PG, pg) != 0) {
2N/A if (scf_instance_add_pg(hdl->legacy_smf_instance, LEGACY_PG,
2N/A SCF_GROUP_FRAMEWORK, 0, pg) != 0) {
2N/A switch (scf_error()) {
2N/A case SCF_ERROR_PERMISSION_DENIED:
2N/A ret = SA_NO_PERMISSION;
2N/A break;
2N/A default:
2N/A ret = SA_SYSTEM_ERR;
2N/A break;
2N/A }
2N/A goto err;
2N/A }
2N/A }
2N/A
2N/A if (scf_transaction_start(trans, pg) != 0) {
2N/A ret = SA_SYSTEM_ERR;
2N/A goto err;
2N/A }
2N/A
2N/A value = scf_value_create(hdl->legacy_smf_hdl);
2N/A entry = scf_entry_create(hdl->legacy_smf_hdl);
2N/A if (value == NULL || entry == NULL) {
2N/A ret = SA_SYSTEM_ERR;
2N/A goto err;
2N/A }
2N/A
2N/A if (dowrite) {
2N/A if (scf_transaction_property_change(trans, entry,
2N/A sharename, SCF_TYPE_OPAQUE) == 0 ||
2N/A scf_transaction_property_new(trans, entry,
2N/A sharename, SCF_TYPE_OPAQUE) == 0) {
2N/A if (scf_value_set_opaque(value, buf, buflen) == 0) {
2N/A if (scf_entry_add_value(entry, value) != 0) {
2N/A ret = SA_SYSTEM_ERR;
2N/A scf_value_destroy(value);
2N/A }
2N/A /* The value is in the transaction */
2N/A value = NULL;
2N/A } else {
2N/A /* Value couldn't be constructed */
2N/A ret = SA_SYSTEM_ERR;
2N/A }
2N/A /* The entry is in the transaction or NULL */
2N/A entry = NULL;
2N/A } else {
2N/A ret = SA_SYSTEM_ERR;
2N/A }
2N/A } else {
2N/A if (scf_transaction_property_delete(trans, entry,
2N/A sharename) != 0)
2N/A ret = SA_SYSTEM_ERR;
2N/A else
2N/A entry = NULL;
2N/A }
2N/A
2N/A if (ret == SA_SYSTEM_ERR)
2N/A goto err;
2N/A
2N/A if (scf_transaction_commit(trans) < 0)
2N/A ret = SA_SYSTEM_ERR;
2N/A
2N/A scf_transaction_destroy_children(trans);
2N/A scf_transaction_destroy(trans);
2N/A
2N/Aerr:
2N/A if (ret == SA_SYSTEM_ERR &&
2N/A scf_error() == SCF_ERROR_PERMISSION_DENIED)
2N/A ret = SA_NO_PERMISSION;
2N/A
2N/A /*
2N/A * Cleanup if there were any errors that didn't leave these
2N/A * values where they would be cleaned up later.
2N/A */
2N/A if (value != NULL)
2N/A scf_value_destroy(value);
2N/A if (entry != NULL)
2N/A scf_entry_destroy(entry);
2N/A if (pg != NULL)
2N/A scf_pg_destroy(pg);
2N/A
2N/A switch (ret) {
2N/A case SA_SYSTEM_ERR:
2N/A salog_error(ret, "legacy_share_rsrc_write: SMF error: %s",
2N/A scf_strerror(scf_error()));
2N/A break;
2N/A default:
2N/A if (ret != SA_OK)
2N/A salog_error(ret, "legacy_share_rsrc_write");
2N/A break;
2N/A }
2N/A
2N/A free(sharename);
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/Astatic int
2N/Alegacy_share_rsrc_write(legacy_handle_t *hdl, char *shname, char *buf,
2N/A size_t buflen)
2N/A{
2N/A int ret;
2N/A
2N/A ret = legacy_common_transaction(hdl, shname, buf, buflen, B_TRUE);
2N/A return (ret);
2N/A}
2N/A
2N/A
2N/A/*ARGSUSED*/
2N/Astatic int
2N/Asa_legacy_share_write(libshare_handle_t *shdl, nvlist_t *share,
2N/A boolean_t persist)
2N/A{
2N/A legacy_handle_t *legacy_hdl;
2N/A char *sh_name;
2N/A size_t buflen;
2N/A char *bufp = NULL;
2N/A int rc;
2N/A
2N/A if ((sh_name = sa_share_get_name(share)) == NULL) {
2N/A rc = SA_NO_SHARE_NAME;
2N/A salog_error(rc, "sa_legacy_share_write");
2N/A goto out;
2N/A }
2N/A
2N/A if (nvlist_pack(share, &bufp, &buflen, NV_ENCODE_XDR, 0) != 0) {
2N/A rc = SA_XDR_ENCODE_ERR;
2N/A salog_error(rc, "sa_legacy_share_write: %s", sh_name);
2N/A goto out;
2N/A }
2N/A
2N/A if ((legacy_hdl = sa_get_fs_handle(shdl, SA_FS_LEGACY, &rc)) == NULL)
2N/A goto out;
2N/A
2N/A rc = legacy_share_rsrc_write(legacy_hdl, sh_name, bufp, buflen);
2N/A
2N/A if (rc < 0) {
2N/A rc = SA_SYSTEM_ERR;
2N/A salog_error(0, "sa_legacy_share_write: "
2N/A "error writing share '%s': %s",
2N/A sh_name, strerror(errno));
2N/A goto out;
2N/A } else {
2N/A rc = SA_OK;
2N/A }
2N/A
2N/Aout:
2N/A if (bufp != NULL)
2N/A free(bufp);
2N/A
2N/A return (rc);
2N/A}
2N/A
2N/Astatic int
2N/Asa_legacy_share_read(libshare_handle_t *shdl, const char *fs_name,
2N/A const char *sh_name, nvlist_t **share)
2N/A{
2N/A nvlist_t *shareval = NULL;
2N/A sa_read_hdl_t hdl;
2N/A int rc = SA_SHARE_NOT_FOUND;
2N/A char *path;
2N/A char *sharename;
2N/A char *mntpnt;
2N/A
2N/A rc = sa_legacy_share_read_init(shdl, &hdl);
2N/A if (rc != SA_OK)
2N/A return (rc);
2N/A
2N/A mntpnt = malloc(MAXPATHLEN);
2N/A if (mntpnt == NULL)
2N/A goto done;
2N/A
2N/A /* While fs_name should be a mountpoint, make sure */
2N/A rc = sa_legacy_get_mntpnt_for_path(shdl, fs_name, mntpnt,
2N/A MAXPATHLEN, NULL, 0, NULL, 0);
2N/A if (rc != SA_OK)
2N/A goto done;
2N/A
2N/A hdl.srh_mntpnt = mntpnt;
2N/A for (rc = sa_legacy_share_read_next(shdl, &hdl, &shareval);
2N/A rc == SA_OK && shareval != NULL;
2N/A rc = sa_legacy_share_read_next(shdl, &hdl, &shareval)) {
2N/A path = sa_share_get_path(shareval);
2N/A sharename = sa_share_get_name(shareval);
2N/A if (path == NULL || sharename == NULL) {
2N/A nvlist_free(shareval);
2N/A continue;
2N/A }
2N/A if (strcmp(sharename, sh_name) == 0) {
2N/A rc = SA_OK;
2N/A break;
2N/A }
2N/A nvlist_free(shareval);
2N/A }
2N/Adone:
2N/A if (rc == SA_OK)
2N/A *share = shareval;
2N/A (void) sa_legacy_share_read_fini(shdl, &hdl);
2N/A free(mntpnt);
2N/A return (rc);
2N/A}
2N/A
2N/Astatic int
2N/Asa_legacy_share_read_fini(libshare_handle_t *shdl, sa_read_hdl_t *hdl)
2N/A{
2N/A NOTE(ARGUNUSED(shdl))
2N/A
2N/A scf_pg_destroy(hdl->srh_smf_pg);
2N/A hdl->srh_smf_pg = NULL;
2N/A scf_iter_destroy(hdl->srh_smf_iter);
2N/A hdl->srh_smf_iter = NULL;
2N/A scf_value_destroy(hdl->srh_smf_value);
2N/A hdl->srh_smf_value = NULL;
2N/A scf_property_destroy(hdl->srh_smf_prop);
2N/A hdl->srh_smf_prop = NULL;
2N/A return (SA_OK);
2N/A}
2N/A
2N/Astatic int
2N/Asa_legacy_share_read_init(libshare_handle_t *shdl, sa_read_hdl_t *hdl)
2N/A{
2N/A legacy_handle_t *legacy_hdl;
2N/A int rc;
2N/A
2N/A if ((legacy_hdl = sa_get_fs_handle(shdl, SA_FS_LEGACY, &rc)) == NULL)
2N/A return (rc);
2N/A
2N/A hdl->srh_smf_pg = scf_pg_create(legacy_hdl->legacy_smf_hdl);
2N/A hdl->srh_smf_iter = scf_iter_create(legacy_hdl->legacy_smf_hdl);
2N/A hdl->srh_smf_value = scf_value_create(legacy_hdl->legacy_smf_hdl);
2N/A hdl->srh_smf_prop = scf_property_create(legacy_hdl->legacy_smf_hdl);
2N/A if (hdl->srh_smf_iter == NULL || hdl->srh_smf_value == NULL ||
2N/A hdl->srh_smf_prop == NULL || hdl->srh_smf_pg == NULL) {
2N/A rc = SA_SYSTEM_ERR;
2N/A } else {
2N/A if (scf_instance_get_pg(legacy_hdl->legacy_smf_instance,
2N/A LEGACY_PG, hdl->srh_smf_pg) != 0) {
2N/A if (scf_instance_add_pg(legacy_hdl->legacy_smf_instance,
2N/A LEGACY_PG, SCF_GROUP_FRAMEWORK, 0,
2N/A hdl->srh_smf_pg) != 0) {
2N/A rc = SA_SYSTEM_ERR;
2N/A }
2N/A }
2N/A if (scf_iter_pg_properties(hdl->srh_smf_iter,
2N/A hdl->srh_smf_pg) != 0) {
2N/A rc = SA_SYSTEM_ERR;
2N/A }
2N/A }
2N/A
2N/A if (rc != SA_OK)
2N/A (void) sa_legacy_share_read_fini(shdl, hdl);
2N/A return (rc);
2N/A}
2N/A
2N/Astatic int
2N/Asa_legacy_share_read_next(libshare_handle_t *shdl, sa_read_hdl_t *hdl,
2N/A nvlist_t **share)
2N/A{
2N/A NOTE(ARGUNUSED(shdl))
2N/A
2N/A int ret = SA_OK;
2N/A void *nvlist;
2N/A size_t nvlistsize;
2N/A char *name;
2N/A char *mntpnt;
2N/A
2N/A name = malloc(scf_limit(SCF_LIMIT_MAX_NAME_LENGTH));
2N/A if (name == NULL)
2N/A return (SA_NO_MEMORY);
2N/A
2N/A nvlistsize = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
2N/A nvlist = malloc(nvlistsize);
2N/A
2N/A if (nvlist == NULL) {
2N/A ret = SA_NO_MEMORY;
2N/A goto done;
2N/A }
2N/A while (ret == SA_OK) {
2N/A if (scf_iter_next_property(hdl->srh_smf_iter,
2N/A hdl->srh_smf_prop) == 0) {
2N/A ret = SA_SHARE_NOT_FOUND;
2N/A break;
2N/A }
2N/A
2N/A if (scf_property_get_name(hdl->srh_smf_prop, name,
2N/A scf_limit(SCF_LIMIT_MAX_NAME_LENGTH)) > 0) {
2N/A if (strcmp(name, "action_authorization") == 0 ||
2N/A strcmp(name, "value_authorization") == 0)
2N/A continue;
2N/A
2N/A if (scf_property_get_value(hdl->srh_smf_prop,
2N/A hdl->srh_smf_value) == 0) {
2N/A if (scf_value_get_opaque(hdl->srh_smf_value,
2N/A nvlist, nvlistsize) >= 0) {
2N/A if (nvlist_unpack(nvlist,
2N/A nvlistsize, share, 0) != 0)
2N/A ret = SA_SYSTEM_ERR;
2N/A } else {
2N/A ret = SA_SYSTEM_ERR;
2N/A }
2N/A
2N/A if (ret != SA_OK)
2N/A break;
2N/A
2N/A mntpnt = sa_share_get_mntpnt(*share);
2N/A if (mntpnt != NULL &&
2N/A strcmp(mntpnt, hdl->srh_mntpnt) == 0)
2N/A break;
2N/A
2N/A /* skip since on other file system */
2N/A nvlist_free(*share);
2N/A
2N/A *share = NULL;
2N/A } else {
2N/A ret = SA_SYSTEM_ERR;
2N/A }
2N/A } else {
2N/A ret = SA_SYSTEM_ERR;
2N/A }
2N/A }
2N/A
2N/Adone:
2N/A free(name);
2N/A if (nvlist != NULL)
2N/A free(nvlist);
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/Astatic int
2N/Asa_legacy_share_remove(libshare_handle_t *shdl, const char *fs_name,
2N/A const char *sh_name, boolean_t persist)
2N/A{
2N/A NOTE(ARGUNUSED(fs_name))
2N/A NOTE(ARGUNUSED(persist))
2N/A
2N/A legacy_handle_t *legacy_hdl;
2N/A scf_property_t *prop;
2N/A int rc;
2N/A
2N/A if ((legacy_hdl = sa_get_fs_handle(shdl, SA_FS_LEGACY, &rc)) == NULL)
2N/A return (rc);
2N/A
2N/A prop = scf_property_create(legacy_hdl->legacy_smf_hdl);
2N/A if (prop == NULL) {
2N/A rc = SA_SYSTEM_ERR;
2N/A goto err;
2N/A }
2N/A
2N/A rc = legacy_common_transaction(legacy_hdl, sh_name, NULL, 0, B_FALSE);
2N/Aerr:
2N/A if (rc == SA_SYSTEM_ERR && scf_error() == SCF_ERROR_PERMISSION_DENIED)
2N/A rc = SA_NO_PERMISSION;
2N/A
2N/A if (prop != NULL)
2N/A scf_property_destroy(prop);
2N/A
2N/A return (rc);
2N/A}
2N/A
2N/Astatic int
2N/Asa_legacy_share_get_acl(libshare_handle_t *shdl, const char *sh_name,
2N/A const char *sh_path, acl_t **aclp)
2N/A{
2N/A NOTE(ARGUNUSED(shdl))
2N/A NOTE(ARGUNUSED(sh_name))
2N/A NOTE(ARGUNUSED(sh_path))
2N/A NOTE(ARGUNUSED(aclp))
2N/A
2N/A return (SA_NOT_SUPPORTED);
2N/A}
2N/A
2N/Astatic int
2N/Asa_legacy_share_set_acl(libshare_handle_t *shdl, const char *sh_name,
2N/A const char *sh_path, acl_t *acl)
2N/A{
2N/A NOTE(ARGUNUSED(shdl))
2N/A NOTE(ARGUNUSED(sh_name))
2N/A NOTE(ARGUNUSED(sh_path))
2N/A NOTE(ARGUNUSED(acl))
2N/A
2N/A return (SA_NOT_SUPPORTED);
2N/A}
2N/A
2N/A/*
2N/A * sa_legacy_get_mntpnt_for_path
2N/A *
2N/A * A path identifies its mount point by its st_dev field in stat. To
2N/A * find the mount point, work backward up the path until the st_dev
2N/A * doesn't match. The last to match was the root (mountpoint).
2N/A */
2N/Astatic int
2N/Asa_legacy_get_mntpnt_for_path(libshare_handle_t *shdl, const char *sh_path,
2N/A char *mntpnt, size_t mp_len, char *volname, size_t vn_len, char *mntopts,
2N/A size_t opt_len)
2N/A{
2N/A NOTE(ARGUNUSED(shdl))
2N/A
2N/A legacy_handle_t *legacy_hdl;
2N/A char *path = NULL;
2N/A struct stat64 st;
2N/A FILE *mnttab;
2N/A struct mnttab entry, result;
2N/A int ret = SA_INVALID_SHARE_MNTPNT;
2N/A int err;
2N/A#if defined(lint)
2N/A volname = volname;
2N/A vn_len = vn_len;
2N/A#endif
2N/A
2N/A if (stat64(sh_path, &st) < 0)
2N/A return (SA_PATH_NOT_FOUND);
2N/A
2N/A mnttab = fopen(MNTTAB, "r");
2N/A if (mnttab == NULL)
2N/A return (SA_SYSTEM_ERR);
2N/A (void) memset(&entry, '\0', sizeof (entry));
2N/A entry.mnt_mountp = (char *)sh_path;
2N/A
2N/A /* special case of mount point being the path */
2N/A if (getmntany(mnttab, &result, &entry) == 0) {
2N/A (void) fclose(mnttab);
2N/A if (mntpnt != NULL)
2N/A (void) strlcpy(mntpnt, result.mnt_mountp, mp_len);
2N/A if (mntopts != 0)
2N/A (void) strlcpy(mntopts, result.mnt_mntopts, opt_len);
2N/A return (SA_OK);
2N/A }
2N/A
2N/A path = strdup(sh_path);
2N/A if (path == NULL) {
2N/A ret = SA_NO_MEMORY;
2N/A goto done;
2N/A }
2N/A
2N/A if ((legacy_hdl = sa_get_fs_handle(shdl, SA_FS_LEGACY, &err)) == NULL) {
2N/A ret = err;
2N/A goto done;
2N/A }
2N/A
2N/A while (*path != '\0') {
2N/A char *work;
2N/A work = strrchr(path, '/');
2N/A if (work != NULL) {
2N/A *work = '\0';
2N/A if (strlen(path) == 0) {
2N/A /*
2N/A * lookup mnttab entry for "/"
2N/A */
2N/A ret = sa_legacy_check_mounts(legacy_hdl, "/",
2N/A mntpnt, mp_len, mntopts, opt_len);
2N/A } else {
2N/A ret = sa_legacy_check_mounts(legacy_hdl, path,
2N/A mntpnt, mp_len, mntopts, opt_len);
2N/A }
2N/A
2N/A if (ret == SA_OK)
2N/A break;
2N/A
2N/A if (ret == SA_NO_SHARE_DIR)
2N/A ret = SA_PATH_NOT_FOUND;
2N/A }
2N/A }
2N/A
2N/Adone:
2N/A (void) fclose(mnttab);
2N/A free(path);
2N/A
2N/A return (ret);
2N/A
2N/A}
2N/A
2N/Astatic int
2N/Asa_legacy_sharing_enabled(libshare_handle_t *shdl, const char *sh_path,
2N/A const char *sh_name, sa_proto_t *protos)
2N/A{
2N/A NOTE(ARGUNUSED(shdl))
2N/A NOTE(ARGUNUSED(sh_path))
2N/A NOTE(ARGUNUSED(sh_name))
2N/A /*
2N/A * There isn't a way to mark a legacy file system as
2N/A * shareable. Assume ALL.
2N/A */
2N/A *protos = SA_PROT_ALL;
2N/A return (SA_OK);
2N/A}
2N/A
2N/Astatic int
2N/Asa_legacy_sharing_get_prop(libshare_handle_t *shdl, const char *mntpnt,
2N/A const char *sh_name, sa_proto_t protos, char **props)
2N/A{
2N/A NOTE(ARGUNUSED(shdl))
2N/A NOTE(ARGUNUSED(mntpnt))
2N/A NOTE(ARGUNUSED(sh_name))
2N/A NOTE(ARGUNUSED(protos))
2N/A
2N/A *props = strdup("on");
2N/A if (*props == NULL)
2N/A return (SA_NO_MEMORY);
2N/A return (SA_OK);
2N/A}
2N/A
2N/Astatic int
2N/Asa_legacy_sharing_set_prop(libshare_handle_t *shdl, const char *mntpnt,
2N/A const char *sh_name, sa_proto_t protos, const char *props)
2N/A{
2N/A NOTE(ARGUNUSED(shdl))
2N/A NOTE(ARGUNUSED(mntpnt))
2N/A NOTE(ARGUNUSED(sh_name))
2N/A NOTE(ARGUNUSED(protos))
2N/A NOTE(ARGUNUSED(props))
2N/A
2N/A return (SA_OK);
2N/A}
2N/A
2N/Astatic int
2N/Asa_legacy_is_legacy(libshare_handle_t *shdl, const char *sh_path,
2N/A boolean_t *legacy)
2N/A{
2N/A NOTE(ARGUNUSED(shdl))
2N/A NOTE(ARGUNUSED(sh_path))
2N/A
2N/A *legacy = B_TRUE;
2N/A return (SA_OK);
2N/A}
2N/A
2N/A/*
2N/A * sa_legacy_mntpnt_is_zoned
2N/A *
2N/A * always return negative
2N/A */
2N/A/* ARGSUSED */
2N/Astatic int
2N/Asa_legacy_is_zoned(libshare_handle_t *shdl, const char *mntpnt,
2N/A boolean_t *zoned)
2N/A{
2N/A NOTE(ARGUNUSED(shdl))
2N/A NOTE(ARGUNUSED(mntpnt))
2N/A
2N/A *zoned = B_FALSE;
2N/A return (0);
2N/A}
2N/A
2N/Astatic int
2N/Asa_legacy_check_mounts(legacy_handle_t *legacy_hdl, char *path, char *mntpnt,
2N/A size_t mp_len, char *mntopts, size_t opt_len)
2N/A{
2N/A legacy_mount_t *mount;
2N/A legacy_mount_t *prevmount;
2N/A FILE *mnttab;
2N/A int ret = SA_NO_SHARE_DIR;
2N/A struct mnttab entry;
2N/A struct stat64 st;
2N/A static struct stat64 check;
2N/A
2N/A if (check.st_mtime == 0)
2N/A (void) stat64(MNTTAB, &check);
2N/A
2N/A /*
2N/A * since sa_legacy_cleanup_mounts() sets legacy_mounts to NULL
2N/A * when cleaning so we use that to force a reload of the mount
2N/A * table.
2N/A */
2N/A if (legacy_hdl->legacy_mounts != NULL) {
2N/A (void) stat64(MNTTAB, &st);
2N/A if (st.st_mtime != check.st_mtime)
2N/A sa_legacy_cleanup_mounts(legacy_hdl);
2N/A check = st;
2N/A }
2N/A
2N/A if (legacy_hdl->legacy_mounts == NULL) {
2N/A mnttab = fopen(MNTTAB, "r");
2N/A if (mnttab == NULL) {
2N/A ret = SA_SYSTEM_ERR;
2N/A goto done;
2N/A }
2N/A prevmount = mount = NULL;
2N/A while (getmntent(mnttab, &entry) == 0) {
2N/A mount = calloc(1, sizeof (legacy_mount_t));
2N/A if (mount == NULL) {
2N/A ret = SA_NO_MEMORY;
2N/A break;
2N/A }
2N/A mount->lm_mntpnt = strdup(entry.mnt_mountp);
2N/A if (mount->lm_mntpnt == NULL) {
2N/A free(mount);
2N/A ret = SA_NO_MEMORY;
2N/A break;
2N/A }
2N/A mount->lm_mntopts = strdup(entry.mnt_mntopts);
2N/A if (mount->lm_mntopts == NULL) {
2N/A free(mount->lm_mntpnt);
2N/A free(mount);
2N/A ret = SA_NO_MEMORY;
2N/A break;
2N/A }
2N/A if (prevmount == NULL) {
2N/A legacy_hdl->legacy_mounts = mount;
2N/A } else {
2N/A prevmount->lm_next = mount;
2N/A }
2N/A prevmount = mount;
2N/A }
2N/A (void) fclose(mnttab);
2N/A }
2N/A
2N/A for (mount = legacy_hdl->legacy_mounts; mount != NULL;
2N/A mount = mount->lm_next) {
2N/A if (strcmp(path, mount->lm_mntpnt) == 0) {
2N/A if (mntpnt != NULL) {
2N/A (void) strlcpy(mntpnt, mount->lm_mntpnt,
2N/A mp_len);
2N/A }
2N/A if (mntopts != NULL) {
2N/A (void) strlcpy(mntopts, mount->lm_mntopts,
2N/A opt_len);
2N/A }
2N/A ret = SA_OK;
2N/A break;
2N/A }
2N/A }
2N/Adone:
2N/A if (ret != SA_OK && ret != SA_NO_SHARE_DIR)
2N/A sa_legacy_cleanup_mounts(legacy_hdl);
2N/A return (ret);
2N/A}