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 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A#include <stdio.h>
2N/A#include <strings.h>
2N/A#include <unistd.h>
2N/A#include <stdarg.h>
2N/A#include <fcntl.h>
2N/A#include <stdlib.h>
2N/A#include <libnvpair.h>
2N/A#include <libdevinfo.h>
2N/A#include <syslog.h>
2N/A#include <sys/param.h>
2N/A#include <errno.h>
2N/A#include <assert.h>
2N/A#include <sys/systeminfo.h>
2N/A#include <sys/modctl.h>
2N/A#include <sys/fs/sdev_impl.h>
2N/A
2N/A/*
2N/A * Private interfaces for non-global /dev profile
2N/A */
2N/A
2N/A/*
2N/A * Allocate opaque data structure for passing profile to the kernel for
2N/A * the given mount point.
2N/A *
2N/A * Note that this interface returns an empty, initialized, profile.
2N/A * It does not return what may have been previously committed.
2N/A */
2N/Aint
2N/Adi_prof_init(const char *mountpt, di_prof_t *profp)
2N/A{
2N/A nvlist_t *nvl;
2N/A
2N/A if (nvlist_alloc(&nvl, 0, 0))
2N/A return (-1);
2N/A
2N/A if (nvlist_add_string(nvl, SDEV_NVNAME_MOUNTPT, mountpt)) {
2N/A nvlist_free(nvl);
2N/A return (-1);
2N/A }
2N/A
2N/A *profp = (di_prof_t)nvl;
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Free space allocated by di_prof_init().
2N/A */
2N/Avoid
2N/Adi_prof_fini(di_prof_t prof)
2N/A{
2N/A nvlist_free((nvlist_t *)prof);
2N/A}
2N/A
2N/A/*
2N/A * Sends profile to the kernel.
2N/A */
2N/Aint
2N/Adi_prof_commit(di_prof_t prof)
2N/A{
2N/A char *buf = NULL;
2N/A size_t buflen = 0;
2N/A int rv;
2N/A
2N/A if (nvlist_pack((nvlist_t *)prof, &buf, &buflen, NV_ENCODE_NATIVE, 0))
2N/A return (-1);
2N/A rv = modctl(MODDEVNAME, MODDEVNAME_PROFILE, buf, buflen);
2N/A free(buf);
2N/A return (rv);
2N/A}
2N/A
2N/A/*
2N/A * Add a device or directory to profile's include list.
2N/A *
2N/A * Note that there is no arbitration between conflicting
2N/A * include and exclude profile entries, most recent
2N/A * is the winner.
2N/A */
2N/Aint
2N/Adi_prof_add_dev(di_prof_t prof, const char *dev)
2N/A{
2N/A if (nvlist_add_string((nvlist_t *)prof, SDEV_NVNAME_INCLUDE, dev))
2N/A return (-1);
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Add a device annotation to the profile.
2N/A */
2N/Aint
2N/Adi_prof_add_devann(di_prof_t prof, const char *dev, const char *ann)
2N/A{
2N/A char *array[2];
2N/A
2N/A array[0] = (char *)dev;
2N/A array[1] = (char *)ann;
2N/A
2N/A if (nvlist_add_string_array((nvlist_t *)prof, SDEV_NVNAME_ANNOTATE,
2N/A array, 2))
2N/A return (-1);
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Add a device or directory to profile's exclude list.
2N/A * This can effectively remove a previously committed device.
2N/A */
2N/Aint
2N/Adi_prof_add_exclude(di_prof_t prof, const char *dev)
2N/A{
2N/A if (nvlist_add_string((nvlist_t *)prof, SDEV_NVNAME_EXCLUDE, dev))
2N/A return (-1);
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Add a symlink to profile.
2N/A */
2N/Aint
2N/Adi_prof_add_symlink(di_prof_t prof, const char *linkname, const char *target)
2N/A{
2N/A nvlist_t *nvl = (nvlist_t *)prof;
2N/A char *syml[2];
2N/A
2N/A syml[0] = (char *)linkname; /* 1st entry must be the symlink */
2N/A syml[1] = (char *)target; /* 2nd entry must be the target */
2N/A if (nvlist_add_string_array(nvl, SDEV_NVNAME_SYMLINK, syml, 2))
2N/A return (-1);
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Add a name mapping to profile.
2N/A */
2N/Aint
2N/Adi_prof_add_map(di_prof_t prof, const char *source, const char *target)
2N/A{
2N/A nvlist_t *nvl = (nvlist_t *)prof;
2N/A char *map[2];
2N/A
2N/A map[0] = (char *)source; /* 1st entry must be the source */
2N/A map[1] = (char *)target; /* 2nd entry must be the target */
2N/A if (nvlist_add_string_array(nvl, SDEV_NVNAME_MAP, map, 2))
2N/A return (-1);
2N/A return (0);
2N/A}