root/usr/src/lib/libbsm/common/getdevicerange.c
/*
 * 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
 * or http://www.opensolaris.org/os/licensing.
 * 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
 */

/*
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#include <stdlib.h>
#include <errno.h>
#include <tsol/label.h>
#include <bsm/devices.h>


/*
 * getdevicerange
 *      Gets the minimum and maximum labels within which the device can
 *      be used. If label range is not specified for the device in
 *      device_allocate, defaults to admin_low and admin_high.
 *      Returns malloc'ed blrange pointer, or NULL on any error.
 */
blrange_t *
getdevicerange(const char *dev)
{
        int             err;
        char            *lstr;
        devalloc_t      *da;
        devmap_t        *dm;
        blrange_t       *range;

        errno = 0;
        if ((range = malloc(sizeof (blrange_t))) == NULL)
                return (NULL);
        if ((range->lower_bound = blabel_alloc()) == NULL) {
                free(range);
                return (NULL);
        }
        if ((range->upper_bound = blabel_alloc()) == NULL) {
                blabel_free(range->lower_bound);
                free(range);
                return (NULL);
        }

        /*
         * If an entry is found for the named device,
         * return its label range.
         */
        setdaent();
        if ((da = getdanam((char *)dev)) == NULL) {
                setdmapent();
                /* check for an actual device file */
                if ((dm = getdmapdev((char *)dev)) != NULL) {
                        da = getdanam(dm->dmap_devname);
                        freedmapent(dm);
                }
                enddmapent();
        }
        enddaent();
        if (da == NULL) {
                bsllow(range->lower_bound);
                bslhigh(range->upper_bound);
        } else {
                lstr = kva_match(da->da_devopts, DAOPT_MINLABEL);
                if (lstr == NULL) {
                        bsllow(range->lower_bound);
                } else if (stobsl(lstr, range->lower_bound, NO_CORRECTION,
                    &err) == 0) {
                        blabel_free(range->lower_bound);
                        blabel_free(range->upper_bound);
                        free(range);
                        errno = ENOTSUP;
                        return (NULL);
                }
                lstr = kva_match(da->da_devopts, DAOPT_MAXLABEL);
                if (lstr == NULL) {
                        bslhigh(range->upper_bound);
                } else if (stobsl(lstr, range->upper_bound, NO_CORRECTION,
                    &err) == 0) {
                        blabel_free(range->lower_bound);
                        blabel_free(range->upper_bound);
                        free(range);
                        errno = ENOTSUP;
                        return (NULL);
                }
                freedaent(da);
        }

        return (range);
}