Home | History | Annotate | Download | only in libdevinfo
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #include <stdio.h>
     27 #include <strings.h>
     28 #include <unistd.h>
     29 #include <stdarg.h>
     30 #include <fcntl.h>
     31 #include <stdlib.h>
     32 #include <libnvpair.h>
     33 #include <libdevinfo.h>
     34 #include <syslog.h>
     35 #include <sys/param.h>
     36 #include <errno.h>
     37 #include <assert.h>
     38 #include <sys/systeminfo.h>
     39 #include <sys/modctl.h>
     40 #include <sys/fs/sdev_impl.h>
     41 
     42 /*
     43  * Private interfaces for non-global /dev profile
     44  */
     45 
     46 /*
     47  * Allocate opaque data structure for passing profile to the kernel for
     48  * the given mount point.
     49  *
     50  * Note that this interface returns an empty, initialized, profile.
     51  * It does not return what may have been previously committed.
     52  */
     53 int
     54 di_prof_init(const char *mountpt, di_prof_t *profp)
     55 {
     56 	nvlist_t	*nvl;
     57 
     58 	if (nvlist_alloc(&nvl, 0, 0))
     59 		return (-1);
     60 
     61 	if (nvlist_add_string(nvl, SDEV_NVNAME_MOUNTPT, mountpt)) {
     62 		nvlist_free(nvl);
     63 		return (-1);
     64 	}
     65 
     66 	*profp = (di_prof_t)nvl;
     67 	return (0);
     68 }
     69 
     70 /*
     71  * Free space allocated by di_prof_init().
     72  */
     73 void
     74 di_prof_fini(di_prof_t prof)
     75 {
     76 	nvlist_free((nvlist_t *)prof);
     77 }
     78 
     79 /*
     80  * Sends profile to the kernel.
     81  */
     82 int
     83 di_prof_commit(di_prof_t prof)
     84 {
     85 	char	*buf = NULL;
     86 	size_t	buflen = 0;
     87 	int	rv;
     88 
     89 	if (nvlist_pack((nvlist_t *)prof, &buf, &buflen, NV_ENCODE_NATIVE, 0))
     90 		return (-1);
     91 	rv = modctl(MODDEVNAME, MODDEVNAME_PROFILE, buf, buflen);
     92 	free(buf);
     93 	return (rv);
     94 }
     95 
     96 /*
     97  * Add a device or directory to profile's include list.
     98  *
     99  * Note that there is no arbitration between conflicting
    100  * include and exclude profile entries, most recent
    101  * is the winner.
    102  */
    103 int
    104 di_prof_add_dev(di_prof_t prof, const char *dev)
    105 {
    106 	if (nvlist_add_string((nvlist_t *)prof, SDEV_NVNAME_INCLUDE, dev))
    107 		return (-1);
    108 	return (0);
    109 }
    110 
    111 /*
    112  * Add a device or directory to profile's exclude list.
    113  * This can effectively remove a previously committed device.
    114  */
    115 int
    116 di_prof_add_exclude(di_prof_t prof, const char *dev)
    117 {
    118 	if (nvlist_add_string((nvlist_t *)prof, SDEV_NVNAME_EXCLUDE, dev))
    119 		return (-1);
    120 	return (0);
    121 }
    122 
    123 /*
    124  * Add a symlink to profile.
    125  */
    126 int
    127 di_prof_add_symlink(di_prof_t prof, const char *linkname, const char *target)
    128 {
    129 	nvlist_t	*nvl = (nvlist_t *)prof;
    130 	char		*syml[2];
    131 
    132 	syml[0] = (char *)linkname;	/* 1st entry must be the symlink */
    133 	syml[1] = (char *)target;	/* 2nd entry must be the target */
    134 	if (nvlist_add_string_array(nvl, SDEV_NVNAME_SYMLINK, syml, 2))
    135 		return (-1);
    136 	return (0);
    137 }
    138 
    139 /*
    140  * Add a name mapping to profile.
    141  */
    142 int
    143 di_prof_add_map(di_prof_t prof, const char *source, const char *target)
    144 {
    145 	nvlist_t	*nvl = (nvlist_t *)prof;
    146 	char		*map[2];
    147 
    148 	map[0] = (char *)source;	/* 1st entry must be the source */
    149 	map[1] = (char *)target;	/* 2nd entry must be the target */
    150 	if (nvlist_add_string_array(nvl, SDEV_NVNAME_MAP, map, 2))
    151 		return (-1);
    152 	return (0);
    153 }
    154