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#include <unistd.h>
2N/A#include <strings.h>
2N/A#include <fcntl.h>
2N/A#include <errno.h>
2N/A#include <note.h>
2N/A#include <libshare.h>
2N/A#include <libshare_impl.h>
2N/A#include <sys/types.h>
2N/A#include <sys/stat.h>
2N/A#include <sharefs/share.h>
2N/A
2N/A#define SHAREFS_DEV_PATH "/devices/pseudo/sharefs@0:sharefs"
2N/A#define SHRBUF_SIZE 8 * 1024
2N/A
2N/A/*
2N/A * The cache plugin library interface with the share cache in
2N/A * sharetab via sharefs ioctl call.
2N/A *
2N/A */
2N/Astatic int cache_pi_init(void);
2N/Astatic void cache_pi_fini(void);
2N/Astatic int sa_cache_init(void *);
2N/Astatic void sa_cache_fini(void *);
2N/Astatic int sa_cache_share_add(nvlist_t *);
2N/Astatic int sa_cache_share_update(nvlist_t *);
2N/Astatic int sa_cache_share_remove(const char *);
2N/Astatic int sa_cache_flush(void);
2N/Astatic int sa_cache_lookup(const char *, const char *, sa_proto_t,
2N/A nvlist_t **);
2N/Astatic int sa_cache_find_init(const char *, sa_proto_t, void **);
2N/Astatic int sa_cache_find_next(void *, nvlist_t **);
2N/Astatic int sa_cache_find_fini(void *);
2N/A
2N/Astatic int sa_cache_validate_name(const char *, sa_validate_flags_t);
2N/Astatic int sa_cache_open_sharetab(void);
2N/Astatic void sa_cache_close_sharetab(void);
2N/Astatic int sa_cache_cvt_err(int);
2N/A
2N/Asa_cache_ops_t sa_plugin_ops = {
2N/A .sac_hdr = {
2N/A .pi_ptype = SA_PLUGIN_CACHE,
2N/A .pi_type = 0,
2N/A .pi_name = "shared",
2N/A .pi_version = SA_LIBSHARE_VERSION,
2N/A .pi_flags = 0,
2N/A .pi_init = cache_pi_init,
2N/A .pi_fini = cache_pi_fini
2N/A },
2N/A .sac_init = sa_cache_init,
2N/A .sac_fini = sa_cache_fini,
2N/A .sac_share_add = sa_cache_share_add,
2N/A .sac_share_update = sa_cache_share_update,
2N/A .sac_share_remove = sa_cache_share_remove,
2N/A .sac_flush = sa_cache_flush,
2N/A .sac_share_lookup = sa_cache_lookup,
2N/A .sac_share_find_init = sa_cache_find_init,
2N/A .sac_share_find_next = sa_cache_find_next,
2N/A .sac_share_find_fini = sa_cache_find_fini,
2N/A .sac_share_ds_find_init = NULL,
2N/A .sac_share_ds_find_get = NULL,
2N/A .sac_share_ds_find_fini = NULL,
2N/A .sac_share_validate_name = sa_cache_validate_name,
2N/A};
2N/A
2N/AFILE *sharefs_fp = NULL;
2N/Aint sharefs_fd = -1;
2N/A
2N/Astatic int
2N/Acache_pi_init(void)
2N/A{
2N/A return (sa_cache_open_sharetab());
2N/A}
2N/A
2N/Astatic void
2N/Acache_pi_fini(void)
2N/A{
2N/A sa_cache_close_sharetab();
2N/A}
2N/A
2N/Astatic int
2N/Asa_cache_init(void *hdl)
2N/A{
2N/A NOTE(ARGUNUSED(hdl))
2N/A
2N/A return (SA_OK);
2N/A}
2N/A
2N/Astatic void
2N/Asa_cache_fini(void *hdl)
2N/A{
2N/A NOTE(ARGUNUSED(hdl))
2N/A}
2N/A
2N/Astatic int
2N/Asa_cache_share_add(nvlist_t *share)
2N/A{
2N/A NOTE(ARGUNUSED(share))
2N/A
2N/A return (SA_OK);
2N/A}
2N/A
2N/Astatic int
2N/Asa_cache_share_update(nvlist_t *share)
2N/A{
2N/A NOTE(ARGUNUSED(share))
2N/A
2N/A return (SA_OK);
2N/A}
2N/A
2N/Astatic int
2N/Asa_cache_share_remove(const char *sh_name)
2N/A{
2N/A NOTE(ARGUNUSED(sh_name))
2N/A
2N/A return (SA_OK);
2N/A}
2N/A
2N/Astatic int
2N/Asa_cache_flush(void)
2N/A{
2N/A return (SA_OK);
2N/A}
2N/A
2N/Astatic int
2N/Asa_cache_lookup(const char *sh_name, const char *sh_path, sa_proto_t proto,
2N/A nvlist_t **share)
2N/A{
2N/A uint32_t ioclen;
2N/A sharefs_ioc_lookup_t *ioc;
2N/A int rc;
2N/A
2N/A if (sh_name == NULL)
2N/A return (SA_INVALID_SHARE_NAME);
2N/A
2N/A if (share == NULL)
2N/A return (SA_INVALID_SHARE);
2N/A
2N/A ioclen = sizeof (sharefs_ioc_lookup_t) + SHRBUF_SIZE;
2N/A if ((ioc = calloc(1, ioclen)) == NULL)
2N/A return (SA_NO_MEMORY);
2N/A
2N/A (void) strlcpy(ioc->sh_name, sh_name, SHAREFS_SH_NAME_MAX);
2N/A if (sh_path != NULL)
2N/A (void) strlcpy(ioc->sh_path, sh_path, MAXPATHLEN);
2N/A ioc->proto = proto;
2N/A ioc->shrlen = SHRBUF_SIZE;
2N/A
2N/A ioc->hdr.version = SHAREFS_IOC_VERSION;
2N/A ioc->hdr.cmd = SHAREFS_IOC_LOOKUP;
2N/A ioc->hdr.len = ioclen;
2N/A ioc->hdr.crc = 0;
2N/A ioc->hdr.crc = sa_crc_gen((uint8_t *)ioc,
2N/A sizeof (sharefs_ioc_hdr_t));
2N/A
2N/A if (ioctl(sharefs_fd, SHAREFS_IOC_LOOKUP, ioc) < 0) {
2N/A rc = sa_cache_cvt_err(errno);
2N/A } else {
2N/A int err;
2N/A
2N/A err = nvlist_unpack(ioc->share, ioc->shrlen, share, 0);
2N/A if (err != 0) {
2N/A switch (err) {
2N/A case EFAULT:
2N/A case ENOTSUP:
2N/A rc = SA_XDR_DECODE_ERR;
2N/A break;
2N/A default:
2N/A rc = sa_cache_cvt_err(err);
2N/A break;
2N/A }
2N/A } else {
2N/A rc = SA_OK;
2N/A }
2N/A }
2N/A
2N/A if (ioc != NULL)
2N/A free(ioc);
2N/A
2N/A return (rc);
2N/A}
2N/A
2N/Astatic int
2N/Asa_cache_find_init(const char *mntpnt, sa_proto_t proto, void **hdl)
2N/A{
2N/A int32_t ioclen;
2N/A sharefs_ioc_find_init_t *ioc;
2N/A int rc;
2N/A
2N/A if (hdl == NULL)
2N/A return (SA_INTERNAL_ERR);
2N/A
2N/A ioclen = sizeof (sharefs_ioc_find_init_t);
2N/A if ((ioc = calloc(1, ioclen)) == NULL)
2N/A return (SA_NO_MEMORY);
2N/A
2N/A if (mntpnt != NULL)
2N/A (void) strlcpy(ioc->mntpnt, mntpnt, MAXPATHLEN);
2N/A ioc->proto = (uint32_t)proto;
2N/A
2N/A ioc->hdr.version = SHAREFS_IOC_VERSION;
2N/A ioc->hdr.cmd = SHAREFS_IOC_FIND_INIT;
2N/A ioc->hdr.len = ioclen;
2N/A ioc->hdr.crc = 0;
2N/A ioc->hdr.crc = sa_crc_gen((uint8_t *)ioc,
2N/A sizeof (sharefs_ioc_hdr_t));
2N/A
2N/A if (ioctl(sharefs_fd, SHAREFS_IOC_FIND_INIT, ioc) < 0) {
2N/A rc = sa_cache_cvt_err(errno);
2N/A } else {
2N/A *hdl = calloc(1, sizeof (sharefs_find_hdl_t));
2N/A if (*hdl == NULL)
2N/A rc = SA_NO_MEMORY;
2N/A else {
2N/A /*
2N/A * memory will be freed in find_fini
2N/A */
2N/A bcopy(&ioc->hdl, *hdl, sizeof (sharefs_find_hdl_t));
2N/A rc = SA_OK;
2N/A }
2N/A }
2N/A
2N/A if (ioc != NULL)
2N/A free(ioc);
2N/A
2N/A return (rc);
2N/A}
2N/A
2N/Astatic int
2N/Asa_cache_find_next(void *hdl, nvlist_t **share)
2N/A{
2N/A uint32_t ioclen;
2N/A sharefs_ioc_find_next_t *ioc;
2N/A int rc;
2N/A
2N/A if (hdl == NULL || share == NULL)
2N/A return (SA_INTERNAL_ERR);
2N/A
2N/A ioclen = sizeof (sharefs_ioc_find_next_t) + SHRBUF_SIZE;
2N/A if ((ioc = calloc(1, ioclen)) == NULL)
2N/A return (SA_NO_MEMORY);
2N/A
2N/A bcopy(hdl, &ioc->hdl, sizeof (sharefs_find_hdl_t));
2N/A
2N/A ioc->shrlen = SHRBUF_SIZE;
2N/A
2N/A ioc->hdr.version = SHAREFS_IOC_VERSION;
2N/A ioc->hdr.cmd = SHAREFS_IOC_FIND_NEXT;
2N/A ioc->hdr.len = ioclen;
2N/A ioc->hdr.crc = 0;
2N/A ioc->hdr.crc = sa_crc_gen((uint8_t *)ioc,
2N/A sizeof (sharefs_ioc_hdr_t));
2N/A
2N/A if (ioctl(sharefs_fd, SHAREFS_IOC_FIND_NEXT, ioc) < 0) {
2N/A rc = sa_cache_cvt_err(errno);
2N/A } else {
2N/A int err;
2N/A
2N/A err = nvlist_unpack(ioc->share, ioc->shrlen, share, 0);
2N/A if (err != 0) {
2N/A switch (err) {
2N/A case EFAULT:
2N/A case ENOTSUP:
2N/A rc = SA_XDR_DECODE_ERR;
2N/A break;
2N/A default:
2N/A rc = sa_cache_cvt_err(err);
2N/A break;
2N/A }
2N/A } else {
2N/A bcopy(&ioc->hdl, hdl, sizeof (sharefs_find_hdl_t));
2N/A rc = SA_OK;
2N/A }
2N/A }
2N/A
2N/A if (ioc != NULL)
2N/A free(ioc);
2N/A
2N/A return (rc);
2N/A}
2N/A
2N/Astatic int
2N/Asa_cache_find_fini(void *hdl)
2N/A{
2N/A int32_t ioclen;
2N/A sharefs_ioc_find_fini_t *ioc;
2N/A int rc;
2N/A
2N/A ioclen = sizeof (sharefs_ioc_find_fini_t);
2N/A if ((ioc = calloc(1, ioclen)) == NULL)
2N/A return (SA_NO_MEMORY);
2N/A
2N/A bcopy(hdl, &ioc->hdl, sizeof (sharefs_find_hdl_t));
2N/A
2N/A ioc->hdr.version = SHAREFS_IOC_VERSION;
2N/A ioc->hdr.cmd = SHAREFS_IOC_FIND_FINI;
2N/A ioc->hdr.len = ioclen;
2N/A ioc->hdr.crc = 0;
2N/A ioc->hdr.crc = sa_crc_gen((uint8_t *)ioc,
2N/A sizeof (sharefs_ioc_hdr_t));
2N/A
2N/A if (ioctl(sharefs_fd, SHAREFS_IOC_FIND_FINI, ioc) < 0) {
2N/A rc = sa_cache_cvt_err(errno);
2N/A } else {
2N/A rc = SA_OK;
2N/A }
2N/A
2N/A free(hdl);
2N/A
2N/A if (ioc != NULL)
2N/A free(ioc);
2N/A
2N/A return (rc);
2N/A}
2N/A
2N/Astatic int
2N/Asa_cache_validate_name(const char *sh_name, sa_validate_flags_t flags)
2N/A{
2N/A NOTE(ARGUNUSED(sh_name))
2N/A NOTE(ARGUNUSED(flags))
2N/A
2N/A return (SA_NOT_IMPLEMENTED);
2N/A}
2N/A
2N/Astatic int
2N/Asa_cache_open_sharetab(void)
2N/A{
2N/A sa_cache_close_sharetab();
2N/A
2N/A sharefs_fp = fopen(SHARETAB, "r");
2N/A if (sharefs_fp == NULL) {
2N/A salog_error(0, "libshare_cache: Error opening %s: %s",
2N/A SHARETAB, strerror(errno));
2N/A return (SA_SYSTEM_ERR);
2N/A }
2N/A
2N/A sharefs_fd = fileno(sharefs_fp);
2N/A
2N/A return (SA_OK);
2N/A}
2N/A
2N/Astatic void
2N/Asa_cache_close_sharetab(void)
2N/A{
2N/A if (sharefs_fp != NULL) {
2N/A (void) fclose(sharefs_fp);
2N/A sharefs_fd = -1;
2N/A sharefs_fp = NULL;
2N/A }
2N/A}
2N/A
2N/Astatic int
2N/Asa_cache_cvt_err(int err)
2N/A{
2N/A int rc;
2N/A
2N/A switch (err) {
2N/A case ENOENT:
2N/A rc = SA_SHARE_NOT_FOUND;
2N/A break;
2N/A case EFAULT:
2N/A rc = SA_INTERNAL_ERR;
2N/A break;
2N/A case ENOTTY:
2N/A rc = SA_NOT_SUPPORTED;
2N/A break;
2N/A case EINVAL:
2N/A rc = SA_INVALID_SHARE;
2N/A break;
2N/A case EAGAIN:
2N/A rc = SA_BUSY;
2N/A break;
2N/A case ENOMEM:
2N/A rc = SA_NO_MEMORY;
2N/A break;
2N/A case ESTALE:
2N/A rc = SA_STALE_HANDLE;
2N/A break;
2N/A default:
2N/A rc = SA_SYSTEM_ERR;
2N/A break;
2N/A }
2N/A
2N/A return (rc);
2N/A}