/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
#include <strings.h>
#include <dirent.h>
#include <libnvpair.h>
#include <libzfs.h>
#include <errno.h>
#include <fcntl.h>
#include <note.h>
#include <unistd.h>
#include <synch.h>
#include <libshare.h>
#include <libshare_impl.h>
static int sa_zfs_init(void);
static void sa_zfs_fini(void);
static void *sa_zfs_open(libshare_handle_t *);
static void sa_zfs_close(void *);
static void sa_zfs_reset(libshare_handle_t *);
static int sa_zfs_share_read(libshare_handle_t *, const char *, const char *,
nvlist_t **);
nvlist_t **);
static int sa_zfs_share_remove(libshare_handle_t *, const char *,
const char *, boolean_t);
static int sa_zfs_share_get_acl(libshare_handle_t *, const char *,
const char *, acl_t **);
static int sa_zfs_share_set_acl(libshare_handle_t *, const char *,
const char *, acl_t *);
static int sa_zfs_get_mntpnt_for_path(libshare_handle_t *, const char *,
static int sa_zfs_sharing_enabled(libshare_handle_t *, const char *,
const char *, sa_proto_t *);
static int sa_zfs_sharing_get_prop(libshare_handle_t *, const char *,
const char *, sa_proto_t, char **);
static int sa_zfs_sharing_set_prop(libshare_handle_t *, const char *,
const char *, sa_proto_t, const char *);
static int sa_zfs_is_legacy(libshare_handle_t *, const char *,
boolean_t *);
static void sa_zfs_share_notify(libshare_handle_t *, const char *,
sa_notify_op_t, nvlist_t *);
.saf_hdr = {
.pi_ptype = SA_PLUGIN_FS,
.pi_name = "ZFS",
.pi_flags = 0,
.pi_init = sa_zfs_init,
},
.saf_open = sa_zfs_open,
};
static int
sa_zfs_init(void)
{
return (SA_OK);
}
static void
sa_zfs_fini(void)
{
/* do nothing */
}
static void *
{
salog_error(0, "libshare_zfs: failed to open libzfs handle");
return (NULL);
}
return (hdl);
}
static void
{
}
static void
{
int rc;
return;
}
}
/*
* sazfs_add_mntpnt
*
* Add the mountpoint to the share path.
* This is called after the share has been read from disk
* since share paths are stored relative to the mountpoint
* in case the dataset mountpoint is modified after the
* share has been created.
*
* The mountpoint itself is also added to the share in the
* SA_PROP_MNTPNT ("mntpnt") property.
*/
static int
{
int rc;
char *sh_path;
/*
* If the expected mntpnt property is already there, assume that the
* filesystem plugin also set the expected absolute share path.
*/
return (SA_OK);
return (SA_NO_SHARE_PATH);
}
/*
* add mountpoint property to share
*/
return (rc);
/*
* store the full path to share
*/
(void) sa_fixup_path(new_path);
return (rc);
return (SA_OK);
}
static int
{
int rc;
return (rc);
return (rc);
}
static int
{
int rc;
return (rc);
if (rc != 0) {
if (rc != SA_SHARE_NOT_FOUND)
return (rc);
}
/*
* shares are stored with paths relative to the mountpoint.
* So prefix mountpoint to beginning of share path and update share.
*/
sh_name);
return (rc);
}
return (rc);
}
static int
{
int rc;
/* Note: we are only called for fs's in current zone */
return (rc);
if (rc != 0) {
"failed to set up zfs_share_read_init for %s",
srhp->srh_mntpnt);
return (SA_SHARE_NOT_FOUND);
}
return (SA_OK);
}
/* ARGSUSED */
static int
{
int rc;
return (rc);
}
/*
* shares are stored with paths relative to the mountpoint.
* So prefix mountpoint to beginning of share path and update share.
*/
if (rc == 0 &&
}
return (rc);
}
/* ARGSUSED */
static int
{
return (SA_OK);
}
return (SA_OK);
}
static int
{
int rc;
return (rc);
if (rc != 0) {
return (rc);
}
if (rc != 0) {
switch (errno) {
case EPERM:
return (SA_NO_PERMISSION);
case ENOENT:
break;
default:
salog_error(0, "libshare_zfs: "
"error removing share file for %s: %s",
return (SA_SYSTEM_ERR);
}
}
return (SA_OK);
}
static int
{
int rc;
return (rc);
if (rc != 0) {
return (rc);
}
rc = SA_NO_MEMORY;
return (rc);
}
if (rc != 0) {
switch (errno) {
case EACCES:
break;
case ENOENT:
break;
case ENOTSUP:
break;
case EIO:
case ENOSYS:
default:
rc = SA_SYSTEM_ERR;
break;
}
} else {
}
return (rc);
}
static int
{
int rc;
return (rc);
if (rc != 0) {
return (rc);
}
rc = SA_NO_MEMORY;
return (rc);
}
if (rc != 0) {
switch (errno) {
case EACCES:
break;
case ENOENT:
break;
case ENOTSUP:
break;
case EIO:
case ENOSYS:
default:
rc = SA_SYSTEM_ERR;
break;
}
} else {
}
return (rc);
}
/*
* Return the mountpoint and optionally the dataset name from a
* path.
*/
static int
{
int rc;
return (rc);
if (rc != 0)
return (SA_MNTPNT_NOT_FOUND);
else
return (SA_OK);
}
static int
{
int rc;
*protos = SA_PROT_NONE;
return (rc);
protos));
}
static int
{
int rc;
return (rc);
props));
}
static int
{
int rc;
return (rc);
props));
}
static int
{
int rc;
return (rc);
return (SA_PATH_NOT_FOUND);
}
sizeof (mountpoint)) == 0) {
else
} else {
}
return (rc);
}
static int
{
int rc;
return (rc);
return (SA_MNTPNT_NOT_FOUND);
}
return (SA_OK);
}
/*
* Take an opcode {publish|unpublish} and a list of per-protocol error codes
* from libshare in the following format:
* nvlist:
* name=protocol tag{"nfs"|"smb"|"any"}, value=error code
*
* If a sharing protocol is not enabled for a given share, its tag (and error
* code) will not be present in the list. If sharing is enabled for multiple
* protocols, track the state after publish as "shared" if any publish attempt
* succeeds, and track the state after unpublish as "unshared" only if all
* unpublish attempts succeed. Avoid changing the state if all protocols report
* lack of permission. Otherwise notify shares when publish fails but not when
* unpublish fails.
*
* The "any" protocol tag indicates that libshare did not distinguish which
* protocol was resposible for the error code, so it could apply to any or all
* protocols.
*/
static int
{
int n = 0;
int intval;
return (SA_INVALID_PROTO);
}
return (SA_INTERNAL_ERR);
switch (intval) {
case SA_OK:
if (notify_op == SA_NOTIFY_OP_PUBLISH) {
}
break;
case SA_NO_PERMISSION:
if (notify_op == SA_NOTIFY_OP_UNPUBLISH)
break;
default:
if (notify_op == SA_NOTIFY_OP_PUBLISH) {
} else {
}
}
n++;
}
/*
* If the "any" proto tag is present, it should be the only tag in the
* list.
*/
if (any && n > 1)
return (SA_INVALID_PROTO);
if (notify) {
if (notify_op == SA_NOTIFY_OP_PUBLISH) {
} else {
}
}
return (SA_OK);
}
static void
{
int rc;
return;
}
return;
}
return;
}
goto out;
}
goto out;
}
if (notify) {
(void) zfssa_add_share_notification(zhp,
}
}
out:
}