10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
51676Sjpk * Common Development and Distribution License (the "License").
61676Sjpk * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*12373SJan.Parcel@Sun.COM * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
23*12373SJan.Parcel@Sun.COM *
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #include <string.h>
2711529SJan.Parcel@Sun.COM #include <strings.h>
281676Sjpk #include <stdlib.h>
2911529SJan.Parcel@Sun.COM #include <unistd.h>
3011529SJan.Parcel@Sun.COM #include <limits.h>
310Sstevel@tonic-gate #include <bsm/devices.h>
321676Sjpk #include <bsm/devalloc.h>
331676Sjpk
341676Sjpk char *strtok_r(char *, const char *, char **);
350Sstevel@tonic-gate
361676Sjpk /* externs from getdaent.c */
371676Sjpk extern char *trim_white(char *);
381676Sjpk extern int pack_white(char *);
391676Sjpk extern char *getdadmfield(char *, char *);
401676Sjpk extern int getdadmline(char *, int, FILE *);
410Sstevel@tonic-gate
420Sstevel@tonic-gate static struct _dmapbuff {
431676Sjpk FILE *_dmapf; /* for /etc/security/device_maps */
441676Sjpk devmap_t _interpdevmap;
451676Sjpk char _interpdmline[DA_BUFSIZE + 1];
461676Sjpk char *_DEVMAP;
470Sstevel@tonic-gate } *__dmapbuff;
480Sstevel@tonic-gate
491676Sjpk #define dmapf (_dmap->_dmapf)
501676Sjpk #define interpdevmap (_dmap->_interpdevmap)
511676Sjpk #define interpdmline (_dmap->_interpdmline)
521676Sjpk #define DEVMAPS_FILE (_dmap->_DEVMAP)
531676Sjpk
541676Sjpk devmap_t *dmap_interpret(char *, devmap_t *);
551676Sjpk static devmap_t *dmap_interpretf(char *, devmap_t *);
561676Sjpk static devmap_t *dmap_dlexpand(devmap_t *);
57*12373SJan.Parcel@Sun.COM static int dmap_resolve_link(char *devpath, char **devfs_path);
581676Sjpk
591676Sjpk int dmap_matchdev(devmap_t *, char *);
601676Sjpk int dmap_matchname(devmap_t *, char *);
611676Sjpk
621676Sjpk
631676Sjpk /*
641676Sjpk * _dmapalloc -
651676Sjpk * allocates common buffers and structures.
661676Sjpk * returns pointer to the new structure, else returns NULL on error.
671676Sjpk */
681676Sjpk static struct _dmapbuff *
_dmapalloc(void)691676Sjpk _dmapalloc(void)
701676Sjpk {
711676Sjpk struct _dmapbuff *_dmap = __dmapbuff;
721676Sjpk
731676Sjpk if (_dmap == NULL) {
741676Sjpk _dmap = (struct _dmapbuff *)calloc((unsigned)1,
751676Sjpk (unsigned)sizeof (*__dmapbuff));
761676Sjpk if (_dmap == NULL)
771676Sjpk return (NULL);
781676Sjpk DEVMAPS_FILE = "/etc/security/device_maps";
791676Sjpk dmapf = NULL;
801676Sjpk __dmapbuff = _dmap;
811676Sjpk }
821676Sjpk
831676Sjpk return (_dmap);
841676Sjpk }
851676Sjpk
861676Sjpk /*
871676Sjpk * setdmapent -
881676Sjpk * rewinds the device_maps file to the beginning.
891676Sjpk */
901676Sjpk void
setdmapent(void)911676Sjpk setdmapent(void)
921676Sjpk {
931676Sjpk struct _dmapbuff *_dmap = _dmapalloc();
941676Sjpk
951676Sjpk if (_dmap == NULL)
961676Sjpk return;
971676Sjpk if (dmapf == NULL)
981914Scasper dmapf = fopen(DEVMAPS_FILE, "rF");
991676Sjpk else
1001676Sjpk rewind(dmapf);
1011676Sjpk }
1021676Sjpk
1031676Sjpk /*
1041676Sjpk * enddmapent -
1051676Sjpk * closes device_maps file.
1061676Sjpk */
1071676Sjpk void
enddmapent(void)1081676Sjpk enddmapent(void)
1091676Sjpk {
1101676Sjpk struct _dmapbuff *_dmap = _dmapalloc();
1111676Sjpk
1121676Sjpk if (_dmap == NULL)
1131676Sjpk return;
1141676Sjpk if (dmapf != NULL) {
1151676Sjpk (void) fclose(dmapf);
1161676Sjpk dmapf = NULL;
1171676Sjpk }
1181676Sjpk }
1191676Sjpk
1201676Sjpk void
freedmapent(devmap_t * dmap)1211676Sjpk freedmapent(devmap_t *dmap)
1221676Sjpk {
1231676Sjpk char **darp;
1241676Sjpk
1251676Sjpk if ((darp = dmap->dmap_devarray) != NULL) {
1261676Sjpk while (*darp != NULL)
1271676Sjpk free(*darp++);
1281676Sjpk free(dmap->dmap_devarray);
1291676Sjpk dmap->dmap_devarray = NULL;
1301676Sjpk }
1311676Sjpk }
1321676Sjpk
1331676Sjpk /*
1341676Sjpk * setdmapfile -
1351676Sjpk * changes the default device_maps file to the one specified.
1361676Sjpk * It does not close the previous file. If this is desired, enddmapent
1371676Sjpk * should be called prior to setdampfile.
1381676Sjpk */
1391676Sjpk void
setdmapfile(char * file)1401676Sjpk setdmapfile(char *file)
1411676Sjpk {
1421676Sjpk struct _dmapbuff *_dmap = _dmapalloc();
1431676Sjpk
1441676Sjpk if (_dmap == NULL)
1451676Sjpk return;
1461676Sjpk if (dmapf != NULL) {
1471676Sjpk (void) fclose(dmapf);
1481676Sjpk dmapf = NULL;
1491676Sjpk }
1501676Sjpk DEVMAPS_FILE = file;
1511676Sjpk }
1521676Sjpk
1531676Sjpk /*
1541676Sjpk * getdmapent -
1551676Sjpk * When first called, returns a pointer to the first devmap_t structure
1561676Sjpk * in device_maps; thereafter, it returns a pointer to the next devmap_t
1571676Sjpk * structure in the file. Thus successive calls can be used to read the
1581676Sjpk * entire file.
1591676Sjpk * call to getdmapent should be bracketed by setdmapent and enddmapent.
1601676Sjpk * returns pointer to devmap_t found, else returns NULL if no entry found
1611676Sjpk * or on error.
1621676Sjpk */
1631676Sjpk devmap_t *
getdmapent(void)1641676Sjpk getdmapent(void)
1651676Sjpk {
1661676Sjpk devmap_t *dmap;
1671676Sjpk struct _dmapbuff *_dmap = _dmapalloc();
1681676Sjpk
1691676Sjpk if ((_dmap == 0) || (dmapf == NULL))
1701676Sjpk return (NULL);
1711676Sjpk
1721676Sjpk while (getdadmline(interpdmline, (int)sizeof (interpdmline),
1731676Sjpk dmapf) != 0) {
1741676Sjpk if ((dmap = dmap_interpret(interpdmline,
1751676Sjpk &interpdevmap)) == NULL)
1761676Sjpk continue;
1771676Sjpk return (dmap);
1781676Sjpk }
1791676Sjpk
1801676Sjpk return (NULL);
1811676Sjpk }
1821676Sjpk
1831676Sjpk /*
1841676Sjpk * getdmapnam -
1851676Sjpk * searches from the beginning of device_maps for the device specified by
1861676Sjpk * its name.
1871676Sjpk * call to getdmapnam should be bracketed by setdmapent and enddmapent.
1881676Sjpk * returns pointer to devmapt_t for the device if it is found, else
1891676Sjpk * returns NULL if device not found or in case of error.
1901676Sjpk */
1911676Sjpk devmap_t *
getdmapnam(char * name)1921676Sjpk getdmapnam(char *name)
1931676Sjpk {
1941676Sjpk devmap_t *dmap;
1951676Sjpk struct _dmapbuff *_dmap = _dmapalloc();
1961676Sjpk
1971676Sjpk if ((name == NULL) || (_dmap == 0) || (dmapf == NULL))
1981676Sjpk return (NULL);
1991676Sjpk
2001676Sjpk while (getdadmline(interpdmline, (int)sizeof (interpdmline),
2011676Sjpk dmapf) != 0) {
2021676Sjpk if (strstr(interpdmline, name) == NULL)
2031676Sjpk continue;
2041676Sjpk if ((dmap = dmap_interpretf(interpdmline,
2051676Sjpk &interpdevmap)) == NULL)
2061676Sjpk continue;
2071676Sjpk if (dmap_matchname(dmap, name)) {
2081676Sjpk if ((dmap = dmap_dlexpand(dmap)) == NULL)
2091676Sjpk continue;
2101676Sjpk enddmapent();
2111676Sjpk return (dmap);
2121676Sjpk }
2131676Sjpk freedmapent(dmap);
2141676Sjpk }
2151676Sjpk
2161676Sjpk return (NULL);
2171676Sjpk }
2181676Sjpk
2190Sstevel@tonic-gate /*
2201676Sjpk * getdmapdev -
2211676Sjpk * searches from the beginning of device_maps for the device specified by
2221676Sjpk * its logical name.
2231676Sjpk * call to getdmapdev should be bracketed by setdmapent and enddmapent.
2241676Sjpk * returns pointer to the devmap_t for the device if device is found,
2251676Sjpk * else returns NULL if device not found or on error.
2261676Sjpk */
2271676Sjpk devmap_t *
getdmapdev(char * dev)2281676Sjpk getdmapdev(char *dev)
2291676Sjpk {
2301676Sjpk devmap_t *dmap;
2311676Sjpk struct _dmapbuff *_dmap = _dmapalloc();
2321676Sjpk
2331676Sjpk if ((dev == NULL) || (_dmap == 0) || (dmapf == NULL))
2341676Sjpk return (NULL);
2351676Sjpk
2361676Sjpk while (getdadmline(interpdmline, (int)sizeof (interpdmline),
2371676Sjpk dmapf) != 0) {
2381676Sjpk if ((dmap = dmap_interpret(interpdmline,
2391676Sjpk &interpdevmap)) == NULL)
2401676Sjpk continue;
2411676Sjpk if (dmap_matchdev(dmap, dev)) {
2421676Sjpk enddmapent();
2431676Sjpk return (dmap);
2441676Sjpk }
2451676Sjpk freedmapent(dmap);
2461676Sjpk }
2471676Sjpk
2481676Sjpk return (NULL);
2491676Sjpk }
2501676Sjpk
2511676Sjpk /*
2521676Sjpk * getdmaptype -
2531676Sjpk * searches from the beginning of device_maps for the device specified by
2541676Sjpk * its type.
2551676Sjpk * call to getdmaptype should be bracketed by setdmapent and enddmapent.
2561676Sjpk * returns pointer to devmap_t found, else returns NULL if no entry found
2571676Sjpk * or on error.
2581676Sjpk */
2591676Sjpk devmap_t *
getdmaptype(char * type)2601676Sjpk getdmaptype(char *type)
2611676Sjpk {
2621676Sjpk devmap_t *dmap;
2631676Sjpk struct _dmapbuff *_dmap = _dmapalloc();
2641676Sjpk
2651676Sjpk if ((type == NULL) || (_dmap == 0) || (dmapf == NULL))
2661676Sjpk return (NULL);
2671676Sjpk
2681676Sjpk while (getdadmline(interpdmline, (int)sizeof (interpdmline),
2691676Sjpk dmapf) != 0) {
2701676Sjpk if ((dmap = dmap_interpretf(interpdmline,
2711676Sjpk &interpdevmap)) == NULL)
2721676Sjpk continue;
2731676Sjpk if (dmap->dmap_devtype != NULL &&
2741676Sjpk strcmp(type, dmap->dmap_devtype) == 0) {
2751676Sjpk if ((dmap = dmap_dlexpand(dmap)) == NULL)
2761676Sjpk continue;
2771676Sjpk return (dmap);
2781676Sjpk }
2791676Sjpk freedmapent(dmap);
2801676Sjpk }
2811676Sjpk
2821676Sjpk return (NULL);
2831676Sjpk }
2841676Sjpk
2851676Sjpk /*
28611529SJan.Parcel@Sun.COM * dmap_match_one_dev -
28711529SJan.Parcel@Sun.COM * Checks if the specified devmap_t contains strings
288*12373SJan.Parcel@Sun.COM * for the same link as the device specified.
28911529SJan.Parcel@Sun.COM *
29011529SJan.Parcel@Sun.COM * Returns 1 for a match, else returns 0.
29111529SJan.Parcel@Sun.COM */
29211529SJan.Parcel@Sun.COM static int
dmap_match_one_dev(devmap_t * dmap,char * dev)29311529SJan.Parcel@Sun.COM dmap_match_one_dev(devmap_t *dmap, char *dev)
29411529SJan.Parcel@Sun.COM {
29511529SJan.Parcel@Sun.COM char **dva;
29611529SJan.Parcel@Sun.COM char *dv;
297*12373SJan.Parcel@Sun.COM char *dmap_link;
298*12373SJan.Parcel@Sun.COM char *dev_link;
299*12373SJan.Parcel@Sun.COM char stage_link[PATH_MAX + 1];
30011529SJan.Parcel@Sun.COM
30111529SJan.Parcel@Sun.COM if (dmap->dmap_devarray == NULL)
30211529SJan.Parcel@Sun.COM return (0);
30311529SJan.Parcel@Sun.COM
30411529SJan.Parcel@Sun.COM for (dva = dmap->dmap_devarray; (dv = *dva) != NULL; dva++) {
30511529SJan.Parcel@Sun.COM if (strstr(dev, dv) != NULL)
30611529SJan.Parcel@Sun.COM return (1);
30711529SJan.Parcel@Sun.COM }
308*12373SJan.Parcel@Sun.COM /* check if both refer to same physical device */
309*12373SJan.Parcel@Sun.COM (void) strncpy(stage_link, dmap->dmap_devarray[0], sizeof (stage_link));
310*12373SJan.Parcel@Sun.COM if (dmap_resolve_link(stage_link, &dmap_link) != 0)
311*12373SJan.Parcel@Sun.COM return (0);
312*12373SJan.Parcel@Sun.COM (void) strncpy(stage_link, dev, sizeof (stage_link));
313*12373SJan.Parcel@Sun.COM if (dmap_resolve_link(stage_link, &dev_link) != 0) {
314*12373SJan.Parcel@Sun.COM free(dmap_link);
315*12373SJan.Parcel@Sun.COM return (0);
316*12373SJan.Parcel@Sun.COM }
317*12373SJan.Parcel@Sun.COM if (strcmp(dev_link, dmap_link) == 0) {
318*12373SJan.Parcel@Sun.COM free(dmap_link);
319*12373SJan.Parcel@Sun.COM free(dev_link);
320*12373SJan.Parcel@Sun.COM return (1);
321*12373SJan.Parcel@Sun.COM }
322*12373SJan.Parcel@Sun.COM free(dmap_link);
323*12373SJan.Parcel@Sun.COM free(dev_link);
32411529SJan.Parcel@Sun.COM return (0);
32511529SJan.Parcel@Sun.COM }
32611529SJan.Parcel@Sun.COM
32711529SJan.Parcel@Sun.COM /*
3281676Sjpk * dmap_matchdev -
3291676Sjpk * checks if the specified devmap_t is for the device specified.
3301676Sjpk * returns 1 if it is, else returns 0.
3311676Sjpk */
3321676Sjpk int
dmap_matchdev(devmap_t * dmap,char * dev)3331676Sjpk dmap_matchdev(devmap_t *dmap, char *dev)
3341676Sjpk {
3351676Sjpk char **dva;
3361676Sjpk char *dv;
3371676Sjpk
3381676Sjpk if (dmap->dmap_devarray == NULL)
3391676Sjpk return (0);
3401676Sjpk for (dva = dmap->dmap_devarray; (dv = *dva) != NULL; dva ++) {
3411676Sjpk if (strcmp(dv, dev) == 0)
3421676Sjpk return (1);
3431676Sjpk }
3441676Sjpk
3451676Sjpk return (0);
3461676Sjpk }
3471676Sjpk
3481676Sjpk /*
349*12373SJan.Parcel@Sun.COM * Requires a match of the /dev/? links, not just the logical devname
35011529SJan.Parcel@Sun.COM * Returns 1 for match found, 0 for match not found, 2 for invalid arguments.
351*12373SJan.Parcel@Sun.COM *
352*12373SJan.Parcel@Sun.COM * Also looks for an instance number at the end of the logical name, and
353*12373SJan.Parcel@Sun.COM * puts instance or -1 into *num.
35411529SJan.Parcel@Sun.COM */
35511529SJan.Parcel@Sun.COM int
dmap_exact_dev(devmap_t * dmap,char * dev,int * num)35611529SJan.Parcel@Sun.COM dmap_exact_dev(devmap_t *dmap, char *dev, int *num)
35711529SJan.Parcel@Sun.COM {
35811529SJan.Parcel@Sun.COM char *dv;
35911529SJan.Parcel@Sun.COM
36011529SJan.Parcel@Sun.COM if ((dev == NULL) || (dmap->dmap_devname == NULL))
36111529SJan.Parcel@Sun.COM return (2);
36211529SJan.Parcel@Sun.COM dv = dmap->dmap_devname;
36311529SJan.Parcel@Sun.COM dv += strcspn(dmap->dmap_devname, "0123456789");
36411529SJan.Parcel@Sun.COM if (sscanf(dv, "%d", num) != 1)
365*12373SJan.Parcel@Sun.COM *num = -1;
36611529SJan.Parcel@Sun.COM /* during some add processes, dev can be shorter than dmap */
36711529SJan.Parcel@Sun.COM return (dmap_match_one_dev(dmap, dev));
36811529SJan.Parcel@Sun.COM }
36911529SJan.Parcel@Sun.COM
37011529SJan.Parcel@Sun.COM /*
3711676Sjpk * dmap_matchtype -
3721676Sjpk * checks if the specified devmap_t is for the device specified.
3731676Sjpk * returns 1 if it is, else returns 0.
3741676Sjpk */
3751676Sjpk int
dmap_matchtype(devmap_t * dmap,char * type)3761676Sjpk dmap_matchtype(devmap_t *dmap, char *type)
3771676Sjpk {
3781676Sjpk if ((dmap->dmap_devtype == NULL) || (type == NULL))
3791676Sjpk return (0);
3801676Sjpk
3811676Sjpk return ((strcmp(dmap->dmap_devtype, type) == 0));
3821676Sjpk }
3831676Sjpk
3841676Sjpk /*
3851676Sjpk * dmap_matchname -
3861676Sjpk * checks if the specified devmap_t is for the device specified.
3871676Sjpk * returns 1 if it is, else returns 0.
3881676Sjpk */
3891676Sjpk int
dmap_matchname(devmap_t * dmap,char * name)3901676Sjpk dmap_matchname(devmap_t *dmap, char *name)
3911676Sjpk {
3921676Sjpk if (dmap->dmap_devname == NULL)
3931676Sjpk return (0);
3941676Sjpk
3951676Sjpk return ((strcmp(dmap->dmap_devname, name) == 0));
3961676Sjpk }
3971676Sjpk
3981676Sjpk /*
39911612SJan.Parcel@Sun.COM * Temporarily duplicated directly from libdevinfo's is_minor_node(),
40011612SJan.Parcel@Sun.COM * and renamed, because we cannot link this from libdevinfo.
40111612SJan.Parcel@Sun.COM *
40211612SJan.Parcel@Sun.COM * To be resolved in a couple of builds.
40311612SJan.Parcel@Sun.COM *
40411612SJan.Parcel@Sun.COM * The real fix is to move device allocation out of libbsm.
40511612SJan.Parcel@Sun.COM *
40611612SJan.Parcel@Sun.COM * returns 1 if contents is a minor node in /devices.
40711612SJan.Parcel@Sun.COM * If mn_root is not NULL, mn_root is set to:
40811612SJan.Parcel@Sun.COM * if contents is a /dev node, mn_root = contents
40911612SJan.Parcel@Sun.COM * OR
41011612SJan.Parcel@Sun.COM * if contents is a /devices node, mn_root set to the '/'
41111612SJan.Parcel@Sun.COM * following /devices.
41211612SJan.Parcel@Sun.COM */
41311612SJan.Parcel@Sun.COM static int
dmap_minor_root(const char * contents,const char ** mn_root)41411612SJan.Parcel@Sun.COM dmap_minor_root(const char *contents, const char **mn_root)
41511612SJan.Parcel@Sun.COM {
41611612SJan.Parcel@Sun.COM char *ptr, *prefix;
41711612SJan.Parcel@Sun.COM
41811612SJan.Parcel@Sun.COM prefix = "../devices/";
41911612SJan.Parcel@Sun.COM
42011612SJan.Parcel@Sun.COM if ((ptr = strstr(contents, prefix)) != NULL) {
42111612SJan.Parcel@Sun.COM
42211612SJan.Parcel@Sun.COM /* mn_root should point to the / following /devices */
42311612SJan.Parcel@Sun.COM if (mn_root != NULL) {
42411612SJan.Parcel@Sun.COM *mn_root = ptr += strlen(prefix) - 1;
42511612SJan.Parcel@Sun.COM }
42611612SJan.Parcel@Sun.COM return (1);
42711612SJan.Parcel@Sun.COM }
42811612SJan.Parcel@Sun.COM
42911612SJan.Parcel@Sun.COM prefix = "/devices/";
43011612SJan.Parcel@Sun.COM
43111612SJan.Parcel@Sun.COM if (strncmp(contents, prefix, strlen(prefix)) == 0) {
43211612SJan.Parcel@Sun.COM
43311612SJan.Parcel@Sun.COM /* mn_root should point to the / following /devices/ */
43411612SJan.Parcel@Sun.COM if (mn_root != NULL) {
43511612SJan.Parcel@Sun.COM *mn_root = contents + strlen(prefix) - 1;
43611612SJan.Parcel@Sun.COM }
43711612SJan.Parcel@Sun.COM return (1);
43811612SJan.Parcel@Sun.COM }
43911612SJan.Parcel@Sun.COM
44011612SJan.Parcel@Sun.COM if (mn_root != NULL) {
44111612SJan.Parcel@Sun.COM *mn_root = contents;
44211612SJan.Parcel@Sun.COM }
44311612SJan.Parcel@Sun.COM return (0);
44411612SJan.Parcel@Sun.COM }
44511612SJan.Parcel@Sun.COM
44611612SJan.Parcel@Sun.COM /*
44711612SJan.Parcel@Sun.COM * Temporarily duplicated directly from libdevinfo's devfs_resolve_link(),
44811612SJan.Parcel@Sun.COM * and renamed, because we cannot link this from libdevinfo now, and will
44911612SJan.Parcel@Sun.COM * create a sensible solution in the near future.
45011612SJan.Parcel@Sun.COM *
45111612SJan.Parcel@Sun.COM * returns 0 if resolved, -1 otherwise.
45211612SJan.Parcel@Sun.COM * devpath: Absolute path to /dev link
45311612SJan.Parcel@Sun.COM * devfs_path: Returns malloced string: /devices path w/out "/devices"
45411612SJan.Parcel@Sun.COM */
45511612SJan.Parcel@Sun.COM static int
dmap_resolve_link(char * devpath,char ** devfs_path)45611612SJan.Parcel@Sun.COM dmap_resolve_link(char *devpath, char **devfs_path)
45711612SJan.Parcel@Sun.COM {
45811612SJan.Parcel@Sun.COM char contents[PATH_MAX + 1];
45911612SJan.Parcel@Sun.COM char stage_link[PATH_MAX + 1];
46011612SJan.Parcel@Sun.COM char *ptr;
46111612SJan.Parcel@Sun.COM int linksize;
46211612SJan.Parcel@Sun.COM char *slashdev = "/dev/";
46311612SJan.Parcel@Sun.COM
46411612SJan.Parcel@Sun.COM if (devfs_path) {
46511612SJan.Parcel@Sun.COM *devfs_path = NULL;
46611612SJan.Parcel@Sun.COM }
46711612SJan.Parcel@Sun.COM
46811612SJan.Parcel@Sun.COM linksize = readlink(devpath, contents, PATH_MAX);
46911612SJan.Parcel@Sun.COM
47011612SJan.Parcel@Sun.COM if (linksize <= 0) {
47111612SJan.Parcel@Sun.COM return (-1);
47211612SJan.Parcel@Sun.COM } else {
47311612SJan.Parcel@Sun.COM contents[linksize] = '\0';
47411612SJan.Parcel@Sun.COM }
47511612SJan.Parcel@Sun.COM
47611612SJan.Parcel@Sun.COM /*
47711612SJan.Parcel@Sun.COM * if the link contents is not a minor node assume
47811612SJan.Parcel@Sun.COM * that link contents is really a pointer to another
47911612SJan.Parcel@Sun.COM * link, and if so recurse and read its link contents.
48011612SJan.Parcel@Sun.COM */
48111612SJan.Parcel@Sun.COM if (dmap_minor_root((const char *)contents, (const char **)&ptr) !=
48211612SJan.Parcel@Sun.COM 1) {
48311612SJan.Parcel@Sun.COM if (strncmp(contents, slashdev, strlen(slashdev)) == 0) {
48411612SJan.Parcel@Sun.COM /* absolute path, starting with /dev */
48511612SJan.Parcel@Sun.COM (void) strcpy(stage_link, contents);
48611612SJan.Parcel@Sun.COM } else {
48711612SJan.Parcel@Sun.COM /* relative path, prefix devpath */
48811612SJan.Parcel@Sun.COM if ((ptr = strrchr(devpath, '/')) == NULL) {
48911612SJan.Parcel@Sun.COM /* invalid link */
49011612SJan.Parcel@Sun.COM return (-1);
49111612SJan.Parcel@Sun.COM }
49211612SJan.Parcel@Sun.COM *ptr = '\0';
49311612SJan.Parcel@Sun.COM (void) strcpy(stage_link, devpath);
49411612SJan.Parcel@Sun.COM *ptr = '/';
49511612SJan.Parcel@Sun.COM (void) strcat(stage_link, "/");
49611612SJan.Parcel@Sun.COM (void) strcat(stage_link, contents);
49711612SJan.Parcel@Sun.COM
49811612SJan.Parcel@Sun.COM }
49911612SJan.Parcel@Sun.COM return (dmap_resolve_link(stage_link, devfs_path));
50011612SJan.Parcel@Sun.COM }
50111612SJan.Parcel@Sun.COM
50211612SJan.Parcel@Sun.COM if (devfs_path) {
50311612SJan.Parcel@Sun.COM *devfs_path = strdup(ptr);
50411612SJan.Parcel@Sun.COM if (*devfs_path == NULL) {
50511612SJan.Parcel@Sun.COM return (-1);
50611612SJan.Parcel@Sun.COM }
50711612SJan.Parcel@Sun.COM }
50811612SJan.Parcel@Sun.COM
50911612SJan.Parcel@Sun.COM return (0);
51011612SJan.Parcel@Sun.COM }
51111612SJan.Parcel@Sun.COM
51211612SJan.Parcel@Sun.COM /*
51311529SJan.Parcel@Sun.COM * dmap_physname: path to /devices device
51411529SJan.Parcel@Sun.COM * Returns:
51511529SJan.Parcel@Sun.COM * strdup'd (i.e. malloc'd) real device file if successful
51611529SJan.Parcel@Sun.COM * NULL on error
51711529SJan.Parcel@Sun.COM */
51811529SJan.Parcel@Sun.COM char *
dmap_physname(devmap_t * dmap)51911529SJan.Parcel@Sun.COM dmap_physname(devmap_t *dmap)
52011529SJan.Parcel@Sun.COM {
52111529SJan.Parcel@Sun.COM char *oldlink;
52211529SJan.Parcel@Sun.COM char stage_link[PATH_MAX + 1];
52311529SJan.Parcel@Sun.COM
52411529SJan.Parcel@Sun.COM if ((dmap == NULL) || (dmap->dmap_devarray == NULL) ||
52511529SJan.Parcel@Sun.COM (dmap->dmap_devarray[0] == NULL))
52611529SJan.Parcel@Sun.COM return (NULL);
52711529SJan.Parcel@Sun.COM
52811529SJan.Parcel@Sun.COM (void) strncpy(stage_link, dmap->dmap_devarray[0], sizeof (stage_link));
52911529SJan.Parcel@Sun.COM
53011612SJan.Parcel@Sun.COM if (dmap_resolve_link(stage_link, &oldlink) == 0)
53111529SJan.Parcel@Sun.COM return (oldlink);
53211529SJan.Parcel@Sun.COM return (NULL);
53311529SJan.Parcel@Sun.COM }
53411529SJan.Parcel@Sun.COM
53511529SJan.Parcel@Sun.COM /*
5361676Sjpk * dm_match -
5371676Sjpk * calls dmap_matchname or dmap_matchtype as appropriate.
5381676Sjpk */
5391676Sjpk int
dm_match(devmap_t * dmap,da_args * dargs)5401676Sjpk dm_match(devmap_t *dmap, da_args *dargs)
5411676Sjpk {
5421676Sjpk if (dargs->devinfo->devname)
5431676Sjpk return (dmap_matchname(dmap, dargs->devinfo->devname));
5441676Sjpk else if (dargs->devinfo->devtype)
5451676Sjpk return (dmap_matchtype(dmap, dargs->devinfo->devtype));
5461676Sjpk
5471676Sjpk return (0);
5481676Sjpk }
5491676Sjpk
5501676Sjpk /*
5511676Sjpk * dmap_interpret -
5521676Sjpk * calls dmap_interpretf and dmap_dlexpand to parse devmap_t line.
5531676Sjpk * returns pointer to parsed devmapt_t entry, else returns NULL on error.
5541676Sjpk */
5551676Sjpk devmap_t *
dmap_interpret(char * val,devmap_t * dm)5561676Sjpk dmap_interpret(char *val, devmap_t *dm)
5571676Sjpk {
5581676Sjpk if (dmap_interpretf(val, dm) == NULL)
5591676Sjpk return (NULL);
5601676Sjpk
5611676Sjpk return (dmap_dlexpand(dm));
5621676Sjpk }
5631676Sjpk
5641676Sjpk /*
5651676Sjpk * dmap_interpretf -
5661676Sjpk * parses string "val" and initializes pointers in the given devmap_t to
5671676Sjpk * fields in "val".
5681676Sjpk * returns pointer to updated devmap_t.
5691676Sjpk */
5701676Sjpk static devmap_t *
dmap_interpretf(char * val,devmap_t * dm)5711676Sjpk dmap_interpretf(char *val, devmap_t *dm)
5721676Sjpk {
5731676Sjpk dm->dmap_devname = getdadmfield(val, KV_TOKEN_DELIMIT);
5741676Sjpk dm->dmap_devtype = getdadmfield(NULL, KV_TOKEN_DELIMIT);
5751676Sjpk dm->dmap_devlist = getdadmfield(NULL, KV_TOKEN_DELIMIT);
5761676Sjpk dm->dmap_devarray = NULL;
5771676Sjpk if (dm->dmap_devname == NULL ||
5781676Sjpk dm->dmap_devtype == NULL ||
5791676Sjpk dm->dmap_devlist == NULL)
5801676Sjpk return (NULL);
5811676Sjpk
5821676Sjpk return (dm);
5831676Sjpk }
5841676Sjpk
5851676Sjpk /*
5861676Sjpk * dmap_dlexpand -
5871676Sjpk * expands dmap_devlist of the form `devlist_generate`
5881676Sjpk * returns unexpanded form if there is no '\`' or in case of error.
5891676Sjpk */
5901676Sjpk static devmap_t *
dmap_dlexpand(devmap_t * dmp)5911676Sjpk dmap_dlexpand(devmap_t *dmp)
5921676Sjpk {
5931676Sjpk char tmplist[DA_BUFSIZE + 1];
5941676Sjpk char *cp, *cpl, **darp;
5951676Sjpk int count;
5961676Sjpk FILE *expansion;
5971676Sjpk
5981676Sjpk dmp->dmap_devarray = NULL;
5991676Sjpk if (dmp->dmap_devlist == NULL)
6001676Sjpk return (NULL);
6011676Sjpk if (*(dmp->dmap_devlist) != '`') {
6021676Sjpk (void) strcpy(tmplist, dmp->dmap_devlist);
6031676Sjpk } else {
6041676Sjpk (void) strcpy(tmplist, dmp->dmap_devlist + 1);
6051676Sjpk if ((cp = strchr(tmplist, '`')) != NULL)
6061676Sjpk *cp = '\0';
6071914Scasper if ((expansion = popen(tmplist, "rF")) == NULL)
6081676Sjpk return (NULL);
6091676Sjpk count = fread(tmplist, 1, sizeof (tmplist) - 1, expansion);
6101676Sjpk (void) pclose(expansion);
6111676Sjpk tmplist[count] = '\0';
6121676Sjpk }
6131676Sjpk
6141676Sjpk /* cleanup the list */
6151676Sjpk count = pack_white(tmplist);
6161676Sjpk dmp->dmap_devarray = darp =
6171676Sjpk (char **)malloc((count + 2) * sizeof (char *));
6181676Sjpk if (darp == NULL)
6191676Sjpk return (NULL);
6201676Sjpk cp = tmplist;
6211676Sjpk while ((cp = strtok_r(cp, " ", &cpl)) != NULL) {
6221676Sjpk *darp = strdup(cp);
6231676Sjpk if (*darp == NULL) {
6241676Sjpk freedmapent(dmp);
6251676Sjpk return (NULL);
6261676Sjpk }
6271676Sjpk darp++;
6281676Sjpk cp = NULL;
6291676Sjpk }
6301676Sjpk *darp = NULL;
6311676Sjpk
6321676Sjpk return (dmp);
6331676Sjpk }
6341676Sjpk
6351676Sjpk /*
6361676Sjpk * dmapskip -
6371676Sjpk * scans input string to find next colon or end of line.
6381676Sjpk * returns pointer to next char.
6390Sstevel@tonic-gate */
6400Sstevel@tonic-gate static char *
dmapskip(char * p)6411676Sjpk dmapskip(char *p)
6420Sstevel@tonic-gate {
6430Sstevel@tonic-gate while (*p && *p != ':' && *p != '\n')
6440Sstevel@tonic-gate ++p;
6450Sstevel@tonic-gate if (*p == '\n')
6460Sstevel@tonic-gate *p = '\0';
6470Sstevel@tonic-gate else if (*p != '\0')
6480Sstevel@tonic-gate *p++ = '\0';
6491676Sjpk
6500Sstevel@tonic-gate return (p);
6510Sstevel@tonic-gate }
6521676Sjpk
6530Sstevel@tonic-gate /*
6541676Sjpk * dmapdskip -
6551676Sjpk * scans input string to find next space or end of line.
6561676Sjpk * returns pointer to next char.
6570Sstevel@tonic-gate */
6580Sstevel@tonic-gate static char *
dmapdskip(p)6591676Sjpk dmapdskip(p)
6601676Sjpk register char *p;
6610Sstevel@tonic-gate {
6620Sstevel@tonic-gate while (*p && *p != ' ' && *p != '\n')
6630Sstevel@tonic-gate ++p;
6640Sstevel@tonic-gate if (*p != '\0')
6650Sstevel@tonic-gate *p++ = '\0';
6661676Sjpk
6670Sstevel@tonic-gate return (p);
6680Sstevel@tonic-gate }
6690Sstevel@tonic-gate
6701676Sjpk char *
getdmapfield(char * ptr)6711676Sjpk getdmapfield(char *ptr)
6720Sstevel@tonic-gate {
6730Sstevel@tonic-gate static char *tptr;
6741676Sjpk
6750Sstevel@tonic-gate if (ptr == NULL)
6760Sstevel@tonic-gate ptr = tptr;
6770Sstevel@tonic-gate if (ptr == NULL)
6780Sstevel@tonic-gate return (NULL);
6790Sstevel@tonic-gate tptr = dmapskip(ptr);
6800Sstevel@tonic-gate ptr = trim_white(ptr);
6810Sstevel@tonic-gate if (ptr == NULL)
6820Sstevel@tonic-gate return (NULL);
6830Sstevel@tonic-gate if (*ptr == NULL)
6840Sstevel@tonic-gate return (NULL);
6851676Sjpk
6860Sstevel@tonic-gate return (ptr);
6870Sstevel@tonic-gate }
6881676Sjpk
6891676Sjpk char *
getdmapdfield(char * ptr)6901676Sjpk getdmapdfield(char *ptr)
6910Sstevel@tonic-gate {
6920Sstevel@tonic-gate static char *tptr;
6930Sstevel@tonic-gate if (ptr != NULL) {
6940Sstevel@tonic-gate ptr = trim_white(ptr);
6950Sstevel@tonic-gate } else {
6960Sstevel@tonic-gate ptr = tptr;
6970Sstevel@tonic-gate }
6980Sstevel@tonic-gate if (ptr == NULL)
6990Sstevel@tonic-gate return (NULL);
7000Sstevel@tonic-gate tptr = dmapdskip(ptr);
7010Sstevel@tonic-gate if (ptr == NULL)
7020Sstevel@tonic-gate return (NULL);
7030Sstevel@tonic-gate if (*ptr == NULL)
7040Sstevel@tonic-gate return (NULL);
7051676Sjpk
7060Sstevel@tonic-gate return (ptr);
7070Sstevel@tonic-gate }
708