Exemplo n.º 1
0
/*
 * Unshare a filesystem by mountpoint.
 */
static int
unshare_one(libzfs_handle_t *hdl, const char *name, const char *mountpoint,
    zfs_share_proto_t proto)
{
	sa_share_t share;
	int err;
	char *mntpt;
	/*
	 * Mountpoint could get trashed if libshare calls getmntany
	 * which it does during API initialization, so strdup the
	 * value.
	 */
	mntpt = zfs_strdup(hdl, mountpoint);

	/* make sure libshare initialized */
	if ((err = zfs_init_libshare(hdl, SA_INIT_SHARE_API)) != SA_OK) {
		free(mntpt);	/* don't need the copy anymore */
		return (zfs_error_fmt(hdl, EZFS_SHARENFSFAILED,
		    dgettext(TEXT_DOMAIN, "cannot unshare '%s': %s"),
		    name, sa_errorstr(err)));
	}

	share = sa_find_share(hdl->libzfs_sharehdl, mntpt);
	free(mntpt);	/* don't need the copy anymore */

	if (share != NULL) {
		err = sa_disable_share(share, proto_table[proto].p_name);
		if (err != SA_OK) {
			return (zfs_error_fmt(hdl, EZFS_UNSHARENFSFAILED,
			    dgettext(TEXT_DOMAIN, "cannot unshare '%s': %s"),
			    name, sa_errorstr(err)));
		}
	} else {
		return (zfs_error_fmt(hdl, EZFS_UNSHARENFSFAILED,
		    dgettext(TEXT_DOMAIN, "cannot unshare '%s': not found"),
		    name));
	}
	return (0);
}
Exemplo n.º 2
0
/*
 * Share the given filesystem according to the options in the specified
 * protocol specific properties (sharenfs, sharesmb).  We rely
 * on "libshare" to the dirty work for us.
 */
static int
zfs_share_proto(zfs_handle_t *zhp, zfs_share_proto_t *proto)
{
	char mountpoint[ZFS_MAXPROPLEN];
	char shareopts[ZFS_MAXPROPLEN];
	char sourcestr[ZFS_MAXPROPLEN];
	libzfs_handle_t *hdl = zhp->zfs_hdl;
	sa_share_t share;
	zfs_share_proto_t *curr_proto;
	zprop_source_t sourcetype;
	int ret;

	if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL))
		return (0);

	if ((ret = zfs_init_libshare(hdl, SA_INIT_SHARE_API)) != SA_OK) {
		(void) zfs_error_fmt(hdl, EZFS_SHARENFSFAILED,
		    dgettext(TEXT_DOMAIN, "cannot share '%s': %s"),
		    zfs_get_name(zhp), sa_errorstr(ret));
		return (-1);
	}

	for (curr_proto = proto; *curr_proto != PROTO_END; curr_proto++) {
		/*
		 * Return success if there are no share options.
		 */
		if (zfs_prop_get(zhp, proto_table[*curr_proto].p_prop,
		    shareopts, sizeof (shareopts), &sourcetype, sourcestr,
		    ZFS_MAXPROPLEN, B_FALSE) != 0 ||
		    strcmp(shareopts, "off") == 0)
			continue;

		/*
		 * If the 'zoned' property is set, then zfs_is_mountable()
		 * will have already bailed out if we are in the global zone.
		 * But local zones cannot be NFS servers, so we ignore it for
		 * local zones as well.
		 */
		if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED))
			continue;

		share = sa_find_share(hdl->libzfs_sharehdl, mountpoint);
		if (share == NULL) {
			/*
			 * This may be a new file system that was just
			 * created so isn't in the internal cache
			 * (second time through). Rather than
			 * reloading the entire configuration, we can
			 * assume ZFS has done the checking and it is
			 * safe to add this to the internal
			 * configuration.
			 */
			if (sa_zfs_process_share(hdl->libzfs_sharehdl,
			    NULL, NULL, mountpoint,
			    proto_table[*curr_proto].p_name, sourcetype,
			    shareopts, sourcestr, zhp->zfs_name) != SA_OK) {
				(void) zfs_error_fmt(hdl,
				    proto_table[*curr_proto].p_share_err,
				    dgettext(TEXT_DOMAIN, "cannot share '%s'"),
				    zfs_get_name(zhp));
				return (-1);
			}
			hdl->libzfs_shareflags |= ZFSSHARE_MISS;
			share = sa_find_share(hdl->libzfs_sharehdl,
			    mountpoint);
		}
		if (share != NULL) {
			int err;
			err = sa_enable_share(share,
			    proto_table[*curr_proto].p_name);
			if (err != SA_OK) {
				(void) zfs_error_fmt(hdl,
				    proto_table[*curr_proto].p_share_err,
				    dgettext(TEXT_DOMAIN, "cannot share '%s'"),
				    zfs_get_name(zhp));
				return (-1);
			}
		} else {
			(void) zfs_error_fmt(hdl,
			    proto_table[*curr_proto].p_share_err,
			    dgettext(TEXT_DOMAIN, "cannot share '%s'"),
			    zfs_get_name(zhp));
			return (-1);
		}

	}
	return (0);
}
Exemplo n.º 3
0
int
sa_get_zfs_shares(sa_handle_t handle, char *groupname)
{
	sa_group_t zfsgroup;
	boolean_t nfs;
	boolean_t nfs_inherited;
	boolean_t smb;
	boolean_t smb_inherited;
	zfs_handle_t **zlist;
	char nfsshareopts[ZFS_MAXPROPLEN];
	char smbshareopts[ZFS_MAXPROPLEN];
	sa_share_t share;
	zprop_source_t source;
	char nfssourcestr[ZFS_MAXPROPLEN];
	char smbsourcestr[ZFS_MAXPROPLEN];
	char mountpoint[ZFS_MAXPROPLEN];
	size_t count = 0, i;
	libzfs_handle_t *zfs_libhandle;
	int err = SA_OK;

	/*
	 * If we can't access libzfs, don't bother doing anything.
	 */
	zfs_libhandle = ((sa_handle_impl_t)handle)->zfs_libhandle;
	if (zfs_libhandle == NULL)
		return (SA_SYSTEM_ERR);

	zfsgroup = find_or_create_group(handle, groupname, NULL, &err);
	/* Not an error, this could be a legacy condition */
	if (zfsgroup == NULL)
		return (SA_OK);

	/*
	 * need to walk the mounted ZFS pools and datasets to
	 * find shares that are possible.
	 */
	get_all_filesystems((sa_handle_impl_t)handle, &zlist, &count);
	qsort(zlist, count, sizeof (void *), mountpoint_compare);

	for (i = 0; i < count; i++) {
		char *dataset;

		source = ZPROP_SRC_ALL;
		/* If no mountpoint, skip. */
		if (zfs_prop_get(zlist[i], ZFS_PROP_MOUNTPOINT,
		    mountpoint, sizeof (mountpoint), NULL, NULL, 0,
		    B_FALSE) != 0)
			continue;

		/*
		 * zfs_get_name value must not be freed. It is just a
		 * pointer to a value in the handle.
		 */
		if ((dataset = (char *)zfs_get_name(zlist[i])) == NULL)
			continue;

		/*
		 * only deal with "mounted" file systems since
		 * unmounted file systems can't actually be shared.
		 */

		if (!zfs_is_mounted(zlist[i], NULL))
			continue;

		nfs = nfs_inherited = B_FALSE;

		if (zfs_prop_get(zlist[i], ZFS_PROP_SHARENFS, nfsshareopts,
		    sizeof (nfsshareopts), &source, nfssourcestr,
		    ZFS_MAXPROPLEN, B_FALSE) == 0 &&
		    strcmp(nfsshareopts, "off") != 0) {
			if (source & ZPROP_SRC_INHERITED)
				nfs_inherited = B_TRUE;
			else
				nfs = B_TRUE;
		}

		smb = smb_inherited = B_FALSE;
		if (zfs_prop_get(zlist[i], ZFS_PROP_SHARESMB, smbshareopts,
		    sizeof (smbshareopts), &source, smbsourcestr,
		    ZFS_MAXPROPLEN, B_FALSE) == 0 &&
		    strcmp(smbshareopts, "off") != 0) {
			if (source & ZPROP_SRC_INHERITED)
				smb_inherited = B_TRUE;
			else
				smb = B_TRUE;
		}

		/*
		 * If the mountpoint is already shared, it must be a
		 * non-ZFS share. We want to remove the share from its
		 * parent group and reshare it under ZFS.
		 */
		share = sa_find_share(handle, mountpoint);
		if (share != NULL &&
		    (nfs || smb || nfs_inherited || smb_inherited)) {
			err = sa_remove_share(share);
			share = NULL;
		}

		/*
		 * At this point, we have the information needed to
		 * determine what to do with the share.
		 *
		 * If smb or nfs is set, we have a new sub-group.
		 * If smb_inherit and/or nfs_inherit is set, then
		 * place on an existing sub-group. If both are set,
		 * the existing sub-group is the closest up the tree.
		 */
		if (nfs || smb) {
			/*
			 * Non-inherited is the straightforward
			 * case. sa_zfs_process_share handles it
			 * directly. Make sure that if the "other"
			 * protocol is inherited, that we treat it as
			 * non-inherited as well.
			 */
			if (nfs || nfs_inherited) {
				err = sa_zfs_process_share(handle, zfsgroup,
				    share, mountpoint, "nfs",
				    0, nfsshareopts,
				    nfssourcestr, dataset);
				share = sa_find_share(handle, mountpoint);
			}
			if (smb || smb_inherited) {
				err = sa_zfs_process_share(handle, zfsgroup,
				    share, mountpoint, "smb",
				    0, smbshareopts,
				    smbsourcestr, dataset);
			}
		} else if (nfs_inherited || smb_inherited) {
			char *grpdataset;
			/*
			 * If we only have inherited groups, it is
			 * important to find the closer of the two if
			 * the protocols are set at different
			 * levels. The closest sub-group is the one we
			 * want to work with.
			 */
			if (nfs_inherited && smb_inherited) {
				if (strcmp(nfssourcestr, smbsourcestr) <= 0)
					grpdataset = nfssourcestr;
				else
					grpdataset = smbsourcestr;
			} else if (nfs_inherited) {
				grpdataset = nfssourcestr;
			} else if (smb_inherited) {
				grpdataset = smbsourcestr;
			}
			if (nfs_inherited) {
				err = sa_zfs_process_share(handle, zfsgroup,
				    share, mountpoint, "nfs",
				    ZPROP_SRC_INHERITED, nfsshareopts,
				    grpdataset, dataset);
				share = sa_find_share(handle, mountpoint);
			}
			if (smb_inherited) {
				err = sa_zfs_process_share(handle, zfsgroup,
				    share, mountpoint, "smb",
				    ZPROP_SRC_INHERITED, smbshareopts,
				    grpdataset, dataset);
			}
		}
	}
	/*
	 * Don't need to free the "zlist" variable since it is only a
	 * pointer to a cached value that will be freed when
	 * sa_fini() is called.
	 */
	return (err);
}