17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
545916cd2Sjpk * Common Development and Distribution License (the "License").
645916cd2Sjpk * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22*399f0677SJan Parcel * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
23*399f0677SJan Parcel *
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include <string.h>
277e3e5701SJan Parcel #include <strings.h>
2845916cd2Sjpk #include <stdlib.h>
297e3e5701SJan Parcel #include <unistd.h>
307e3e5701SJan Parcel #include <limits.h>
317c478bd9Sstevel@tonic-gate #include <bsm/devices.h>
3245916cd2Sjpk #include <bsm/devalloc.h>
337c478bd9Sstevel@tonic-gate
3445916cd2Sjpk char *strtok_r(char *, const char *, char **);
3545916cd2Sjpk
3645916cd2Sjpk /* externs from getdaent.c */
3745916cd2Sjpk extern char *trim_white(char *);
3845916cd2Sjpk extern int pack_white(char *);
3945916cd2Sjpk extern char *getdadmfield(char *, char *);
4045916cd2Sjpk extern int getdadmline(char *, int, FILE *);
417c478bd9Sstevel@tonic-gate
427c478bd9Sstevel@tonic-gate static struct _dmapbuff {
4345916cd2Sjpk FILE *_dmapf; /* for /etc/security/device_maps */
447c478bd9Sstevel@tonic-gate devmap_t _interpdevmap;
4545916cd2Sjpk char _interpdmline[DA_BUFSIZE + 1];
467c478bd9Sstevel@tonic-gate char *_DEVMAP;
477c478bd9Sstevel@tonic-gate } *__dmapbuff;
487c478bd9Sstevel@tonic-gate
497c478bd9Sstevel@tonic-gate #define dmapf (_dmap->_dmapf)
507c478bd9Sstevel@tonic-gate #define interpdevmap (_dmap->_interpdevmap)
5145916cd2Sjpk #define interpdmline (_dmap->_interpdmline)
5245916cd2Sjpk #define DEVMAPS_FILE (_dmap->_DEVMAP)
5345916cd2Sjpk
5445916cd2Sjpk devmap_t *dmap_interpret(char *, devmap_t *);
5545916cd2Sjpk static devmap_t *dmap_interpretf(char *, devmap_t *);
5645916cd2Sjpk static devmap_t *dmap_dlexpand(devmap_t *);
57*399f0677SJan Parcel static int dmap_resolve_link(char *devpath, char **devfs_path);
5845916cd2Sjpk
5945916cd2Sjpk int dmap_matchdev(devmap_t *, char *);
6045916cd2Sjpk int dmap_matchname(devmap_t *, char *);
6145916cd2Sjpk
6245916cd2Sjpk
637c478bd9Sstevel@tonic-gate /*
6445916cd2Sjpk * _dmapalloc -
6545916cd2Sjpk * allocates common buffers and structures.
6645916cd2Sjpk * returns pointer to the new structure, else returns NULL on error.
677c478bd9Sstevel@tonic-gate */
6845916cd2Sjpk static struct _dmapbuff *
_dmapalloc(void)6945916cd2Sjpk _dmapalloc(void)
707c478bd9Sstevel@tonic-gate {
7145916cd2Sjpk struct _dmapbuff *_dmap = __dmapbuff;
7245916cd2Sjpk
7345916cd2Sjpk if (_dmap == NULL) {
7445916cd2Sjpk _dmap = (struct _dmapbuff *)calloc((unsigned)1,
7545916cd2Sjpk (unsigned)sizeof (*__dmapbuff));
7645916cd2Sjpk if (_dmap == NULL)
777c478bd9Sstevel@tonic-gate return (NULL);
7845916cd2Sjpk DEVMAPS_FILE = "/etc/security/device_maps";
7945916cd2Sjpk dmapf = NULL;
8045916cd2Sjpk __dmapbuff = _dmap;
817c478bd9Sstevel@tonic-gate }
8245916cd2Sjpk
8345916cd2Sjpk return (_dmap);
847c478bd9Sstevel@tonic-gate }
8545916cd2Sjpk
867c478bd9Sstevel@tonic-gate /*
8745916cd2Sjpk * setdmapent -
8845916cd2Sjpk * rewinds the device_maps file to the beginning.
8945916cd2Sjpk */
9045916cd2Sjpk void
setdmapent(void)9145916cd2Sjpk setdmapent(void)
9245916cd2Sjpk {
9345916cd2Sjpk struct _dmapbuff *_dmap = _dmapalloc();
9445916cd2Sjpk
9545916cd2Sjpk if (_dmap == NULL)
9645916cd2Sjpk return;
9745916cd2Sjpk if (dmapf == NULL)
98004388ebScasper dmapf = fopen(DEVMAPS_FILE, "rF");
9945916cd2Sjpk else
10045916cd2Sjpk rewind(dmapf);
10145916cd2Sjpk }
10245916cd2Sjpk
10345916cd2Sjpk /*
10445916cd2Sjpk * enddmapent -
10545916cd2Sjpk * closes device_maps file.
10645916cd2Sjpk */
10745916cd2Sjpk void
enddmapent(void)10845916cd2Sjpk enddmapent(void)
10945916cd2Sjpk {
11045916cd2Sjpk struct _dmapbuff *_dmap = _dmapalloc();
11145916cd2Sjpk
11245916cd2Sjpk if (_dmap == NULL)
11345916cd2Sjpk return;
11445916cd2Sjpk if (dmapf != NULL) {
11545916cd2Sjpk (void) fclose(dmapf);
11645916cd2Sjpk dmapf = NULL;
11745916cd2Sjpk }
11845916cd2Sjpk }
11945916cd2Sjpk
12045916cd2Sjpk void
freedmapent(devmap_t * dmap)12145916cd2Sjpk freedmapent(devmap_t *dmap)
12245916cd2Sjpk {
12345916cd2Sjpk char **darp;
12445916cd2Sjpk
12545916cd2Sjpk if ((darp = dmap->dmap_devarray) != NULL) {
12645916cd2Sjpk while (*darp != NULL)
12745916cd2Sjpk free(*darp++);
12845916cd2Sjpk free(dmap->dmap_devarray);
12945916cd2Sjpk dmap->dmap_devarray = NULL;
13045916cd2Sjpk }
13145916cd2Sjpk }
13245916cd2Sjpk
13345916cd2Sjpk /*
13445916cd2Sjpk * setdmapfile -
13545916cd2Sjpk * changes the default device_maps file to the one specified.
13645916cd2Sjpk * It does not close the previous file. If this is desired, enddmapent
13745916cd2Sjpk * should be called prior to setdampfile.
13845916cd2Sjpk */
13945916cd2Sjpk void
setdmapfile(char * file)14045916cd2Sjpk setdmapfile(char *file)
14145916cd2Sjpk {
14245916cd2Sjpk struct _dmapbuff *_dmap = _dmapalloc();
14345916cd2Sjpk
14445916cd2Sjpk if (_dmap == NULL)
14545916cd2Sjpk return;
14645916cd2Sjpk if (dmapf != NULL) {
14745916cd2Sjpk (void) fclose(dmapf);
14845916cd2Sjpk dmapf = NULL;
14945916cd2Sjpk }
15045916cd2Sjpk DEVMAPS_FILE = file;
15145916cd2Sjpk }
15245916cd2Sjpk
15345916cd2Sjpk /*
15445916cd2Sjpk * getdmapent -
15545916cd2Sjpk * When first called, returns a pointer to the first devmap_t structure
15645916cd2Sjpk * in device_maps; thereafter, it returns a pointer to the next devmap_t
15745916cd2Sjpk * structure in the file. Thus successive calls can be used to read the
15845916cd2Sjpk * entire file.
15945916cd2Sjpk * call to getdmapent should be bracketed by setdmapent and enddmapent.
16045916cd2Sjpk * returns pointer to devmap_t found, else returns NULL if no entry found
16145916cd2Sjpk * or on error.
16245916cd2Sjpk */
16345916cd2Sjpk devmap_t *
getdmapent(void)16445916cd2Sjpk getdmapent(void)
16545916cd2Sjpk {
16645916cd2Sjpk devmap_t *dmap;
16745916cd2Sjpk struct _dmapbuff *_dmap = _dmapalloc();
16845916cd2Sjpk
16945916cd2Sjpk if ((_dmap == 0) || (dmapf == NULL))
17045916cd2Sjpk return (NULL);
17145916cd2Sjpk
17245916cd2Sjpk while (getdadmline(interpdmline, (int)sizeof (interpdmline),
17345916cd2Sjpk dmapf) != 0) {
17445916cd2Sjpk if ((dmap = dmap_interpret(interpdmline,
17545916cd2Sjpk &interpdevmap)) == NULL)
17645916cd2Sjpk continue;
17745916cd2Sjpk return (dmap);
17845916cd2Sjpk }
17945916cd2Sjpk
18045916cd2Sjpk return (NULL);
18145916cd2Sjpk }
18245916cd2Sjpk
18345916cd2Sjpk /*
18445916cd2Sjpk * getdmapnam -
18545916cd2Sjpk * searches from the beginning of device_maps for the device specified by
18645916cd2Sjpk * its name.
18745916cd2Sjpk * call to getdmapnam should be bracketed by setdmapent and enddmapent.
18845916cd2Sjpk * returns pointer to devmapt_t for the device if it is found, else
18945916cd2Sjpk * returns NULL if device not found or in case of error.
19045916cd2Sjpk */
19145916cd2Sjpk devmap_t *
getdmapnam(char * name)19245916cd2Sjpk getdmapnam(char *name)
19345916cd2Sjpk {
19445916cd2Sjpk devmap_t *dmap;
19545916cd2Sjpk struct _dmapbuff *_dmap = _dmapalloc();
19645916cd2Sjpk
19745916cd2Sjpk if ((name == NULL) || (_dmap == 0) || (dmapf == NULL))
19845916cd2Sjpk return (NULL);
19945916cd2Sjpk
20045916cd2Sjpk while (getdadmline(interpdmline, (int)sizeof (interpdmline),
20145916cd2Sjpk dmapf) != 0) {
20245916cd2Sjpk if (strstr(interpdmline, name) == NULL)
20345916cd2Sjpk continue;
20445916cd2Sjpk if ((dmap = dmap_interpretf(interpdmline,
20545916cd2Sjpk &interpdevmap)) == NULL)
20645916cd2Sjpk continue;
20745916cd2Sjpk if (dmap_matchname(dmap, name)) {
20845916cd2Sjpk if ((dmap = dmap_dlexpand(dmap)) == NULL)
20945916cd2Sjpk continue;
21045916cd2Sjpk enddmapent();
21145916cd2Sjpk return (dmap);
21245916cd2Sjpk }
21345916cd2Sjpk freedmapent(dmap);
21445916cd2Sjpk }
21545916cd2Sjpk
21645916cd2Sjpk return (NULL);
21745916cd2Sjpk }
21845916cd2Sjpk
21945916cd2Sjpk /*
22045916cd2Sjpk * getdmapdev -
22145916cd2Sjpk * searches from the beginning of device_maps for the device specified by
22245916cd2Sjpk * its logical name.
22345916cd2Sjpk * call to getdmapdev should be bracketed by setdmapent and enddmapent.
22445916cd2Sjpk * returns pointer to the devmap_t for the device if device is found,
22545916cd2Sjpk * else returns NULL if device not found or on error.
22645916cd2Sjpk */
22745916cd2Sjpk devmap_t *
getdmapdev(char * dev)22845916cd2Sjpk getdmapdev(char *dev)
22945916cd2Sjpk {
23045916cd2Sjpk devmap_t *dmap;
23145916cd2Sjpk struct _dmapbuff *_dmap = _dmapalloc();
23245916cd2Sjpk
23345916cd2Sjpk if ((dev == NULL) || (_dmap == 0) || (dmapf == NULL))
23445916cd2Sjpk return (NULL);
23545916cd2Sjpk
23645916cd2Sjpk while (getdadmline(interpdmline, (int)sizeof (interpdmline),
23745916cd2Sjpk dmapf) != 0) {
23845916cd2Sjpk if ((dmap = dmap_interpret(interpdmline,
23945916cd2Sjpk &interpdevmap)) == NULL)
24045916cd2Sjpk continue;
24145916cd2Sjpk if (dmap_matchdev(dmap, dev)) {
24245916cd2Sjpk enddmapent();
24345916cd2Sjpk return (dmap);
24445916cd2Sjpk }
24545916cd2Sjpk freedmapent(dmap);
24645916cd2Sjpk }
24745916cd2Sjpk
24845916cd2Sjpk return (NULL);
24945916cd2Sjpk }
25045916cd2Sjpk
25145916cd2Sjpk /*
25245916cd2Sjpk * getdmaptype -
25345916cd2Sjpk * searches from the beginning of device_maps for the device specified by
25445916cd2Sjpk * its type.
25545916cd2Sjpk * call to getdmaptype should be bracketed by setdmapent and enddmapent.
25645916cd2Sjpk * returns pointer to devmap_t found, else returns NULL if no entry found
25745916cd2Sjpk * or on error.
25845916cd2Sjpk */
25945916cd2Sjpk devmap_t *
getdmaptype(char * type)26045916cd2Sjpk getdmaptype(char *type)
26145916cd2Sjpk {
26245916cd2Sjpk devmap_t *dmap;
26345916cd2Sjpk struct _dmapbuff *_dmap = _dmapalloc();
26445916cd2Sjpk
26545916cd2Sjpk if ((type == NULL) || (_dmap == 0) || (dmapf == NULL))
26645916cd2Sjpk return (NULL);
26745916cd2Sjpk
26845916cd2Sjpk while (getdadmline(interpdmline, (int)sizeof (interpdmline),
26945916cd2Sjpk dmapf) != 0) {
27045916cd2Sjpk if ((dmap = dmap_interpretf(interpdmline,
27145916cd2Sjpk &interpdevmap)) == NULL)
27245916cd2Sjpk continue;
27345916cd2Sjpk if (dmap->dmap_devtype != NULL &&
27445916cd2Sjpk strcmp(type, dmap->dmap_devtype) == 0) {
27545916cd2Sjpk if ((dmap = dmap_dlexpand(dmap)) == NULL)
27645916cd2Sjpk continue;
27745916cd2Sjpk return (dmap);
27845916cd2Sjpk }
27945916cd2Sjpk freedmapent(dmap);
28045916cd2Sjpk }
28145916cd2Sjpk
28245916cd2Sjpk return (NULL);
28345916cd2Sjpk }
28445916cd2Sjpk
28545916cd2Sjpk /*
2867e3e5701SJan Parcel * dmap_match_one_dev -
2877e3e5701SJan Parcel * Checks if the specified devmap_t contains strings
288*399f0677SJan Parcel * for the same link as the device specified.
2897e3e5701SJan Parcel *
2907e3e5701SJan Parcel * Returns 1 for a match, else returns 0.
2917e3e5701SJan Parcel */
2927e3e5701SJan Parcel static int
dmap_match_one_dev(devmap_t * dmap,char * dev)2937e3e5701SJan Parcel dmap_match_one_dev(devmap_t *dmap, char *dev)
2947e3e5701SJan Parcel {
2957e3e5701SJan Parcel char **dva;
2967e3e5701SJan Parcel char *dv;
297*399f0677SJan Parcel char *dmap_link;
298*399f0677SJan Parcel char *dev_link;
299*399f0677SJan Parcel char stage_link[PATH_MAX + 1];
3007e3e5701SJan Parcel
3017e3e5701SJan Parcel if (dmap->dmap_devarray == NULL)
3027e3e5701SJan Parcel return (0);
3037e3e5701SJan Parcel
3047e3e5701SJan Parcel for (dva = dmap->dmap_devarray; (dv = *dva) != NULL; dva++) {
3057e3e5701SJan Parcel if (strstr(dev, dv) != NULL)
3067e3e5701SJan Parcel return (1);
3077e3e5701SJan Parcel }
308*399f0677SJan Parcel /* check if both refer to same physical device */
309*399f0677SJan Parcel (void) strncpy(stage_link, dmap->dmap_devarray[0], sizeof (stage_link));
310*399f0677SJan Parcel if (dmap_resolve_link(stage_link, &dmap_link) != 0)
311*399f0677SJan Parcel return (0);
312*399f0677SJan Parcel (void) strncpy(stage_link, dev, sizeof (stage_link));
313*399f0677SJan Parcel if (dmap_resolve_link(stage_link, &dev_link) != 0) {
314*399f0677SJan Parcel free(dmap_link);
315*399f0677SJan Parcel return (0);
316*399f0677SJan Parcel }
317*399f0677SJan Parcel if (strcmp(dev_link, dmap_link) == 0) {
318*399f0677SJan Parcel free(dmap_link);
319*399f0677SJan Parcel free(dev_link);
320*399f0677SJan Parcel return (1);
321*399f0677SJan Parcel }
322*399f0677SJan Parcel free(dmap_link);
323*399f0677SJan Parcel free(dev_link);
3247e3e5701SJan Parcel return (0);
3257e3e5701SJan Parcel }
3267e3e5701SJan Parcel
3277e3e5701SJan Parcel /*
32845916cd2Sjpk * dmap_matchdev -
32945916cd2Sjpk * checks if the specified devmap_t is for the device specified.
33045916cd2Sjpk * returns 1 if it is, else returns 0.
33145916cd2Sjpk */
33245916cd2Sjpk int
dmap_matchdev(devmap_t * dmap,char * dev)33345916cd2Sjpk dmap_matchdev(devmap_t *dmap, char *dev)
33445916cd2Sjpk {
33545916cd2Sjpk char **dva;
33645916cd2Sjpk char *dv;
33745916cd2Sjpk
33845916cd2Sjpk if (dmap->dmap_devarray == NULL)
33945916cd2Sjpk return (0);
34045916cd2Sjpk for (dva = dmap->dmap_devarray; (dv = *dva) != NULL; dva ++) {
34145916cd2Sjpk if (strcmp(dv, dev) == 0)
34245916cd2Sjpk return (1);
34345916cd2Sjpk }
34445916cd2Sjpk
34545916cd2Sjpk return (0);
34645916cd2Sjpk }
34745916cd2Sjpk
34845916cd2Sjpk /*
349*399f0677SJan Parcel * Requires a match of the /dev/? links, not just the logical devname
3507e3e5701SJan Parcel * Returns 1 for match found, 0 for match not found, 2 for invalid arguments.
351*399f0677SJan Parcel *
352*399f0677SJan Parcel * Also looks for an instance number at the end of the logical name, and
353*399f0677SJan Parcel * puts instance or -1 into *num.
3547e3e5701SJan Parcel */
3557e3e5701SJan Parcel int
dmap_exact_dev(devmap_t * dmap,char * dev,int * num)3567e3e5701SJan Parcel dmap_exact_dev(devmap_t *dmap, char *dev, int *num)
3577e3e5701SJan Parcel {
3587e3e5701SJan Parcel char *dv;
3597e3e5701SJan Parcel
3607e3e5701SJan Parcel if ((dev == NULL) || (dmap->dmap_devname == NULL))
3617e3e5701SJan Parcel return (2);
3627e3e5701SJan Parcel dv = dmap->dmap_devname;
3637e3e5701SJan Parcel dv += strcspn(dmap->dmap_devname, "0123456789");
3647e3e5701SJan Parcel if (sscanf(dv, "%d", num) != 1)
365*399f0677SJan Parcel *num = -1;
3667e3e5701SJan Parcel /* during some add processes, dev can be shorter than dmap */
3677e3e5701SJan Parcel return (dmap_match_one_dev(dmap, dev));
3687e3e5701SJan Parcel }
3697e3e5701SJan Parcel
3707e3e5701SJan Parcel /*
37145916cd2Sjpk * dmap_matchtype -
37245916cd2Sjpk * checks if the specified devmap_t is for the device specified.
37345916cd2Sjpk * returns 1 if it is, else returns 0.
37445916cd2Sjpk */
37545916cd2Sjpk int
dmap_matchtype(devmap_t * dmap,char * type)37645916cd2Sjpk dmap_matchtype(devmap_t *dmap, char *type)
37745916cd2Sjpk {
37845916cd2Sjpk if ((dmap->dmap_devtype == NULL) || (type == NULL))
37945916cd2Sjpk return (0);
38045916cd2Sjpk
38145916cd2Sjpk return ((strcmp(dmap->dmap_devtype, type) == 0));
38245916cd2Sjpk }
38345916cd2Sjpk
38445916cd2Sjpk /*
38545916cd2Sjpk * dmap_matchname -
38645916cd2Sjpk * checks if the specified devmap_t is for the device specified.
38745916cd2Sjpk * returns 1 if it is, else returns 0.
38845916cd2Sjpk */
38945916cd2Sjpk int
dmap_matchname(devmap_t * dmap,char * name)39045916cd2Sjpk dmap_matchname(devmap_t *dmap, char *name)
39145916cd2Sjpk {
39245916cd2Sjpk if (dmap->dmap_devname == NULL)
39345916cd2Sjpk return (0);
39445916cd2Sjpk
39545916cd2Sjpk return ((strcmp(dmap->dmap_devname, name) == 0));
39645916cd2Sjpk }
39745916cd2Sjpk
39845916cd2Sjpk /*
399914d7362SJan Parcel * Temporarily duplicated directly from libdevinfo's is_minor_node(),
400914d7362SJan Parcel * and renamed, because we cannot link this from libdevinfo.
401914d7362SJan Parcel *
402914d7362SJan Parcel * To be resolved in a couple of builds.
403914d7362SJan Parcel *
404914d7362SJan Parcel * The real fix is to move device allocation out of libbsm.
405914d7362SJan Parcel *
406914d7362SJan Parcel * returns 1 if contents is a minor node in /devices.
407914d7362SJan Parcel * If mn_root is not NULL, mn_root is set to:
408914d7362SJan Parcel * if contents is a /dev node, mn_root = contents
409914d7362SJan Parcel * OR
410914d7362SJan Parcel * if contents is a /devices node, mn_root set to the '/'
411914d7362SJan Parcel * following /devices.
412914d7362SJan Parcel */
413914d7362SJan Parcel static int
dmap_minor_root(const char * contents,const char ** mn_root)414914d7362SJan Parcel dmap_minor_root(const char *contents, const char **mn_root)
415914d7362SJan Parcel {
416914d7362SJan Parcel char *ptr, *prefix;
417914d7362SJan Parcel
418914d7362SJan Parcel prefix = "../devices/";
419914d7362SJan Parcel
420914d7362SJan Parcel if ((ptr = strstr(contents, prefix)) != NULL) {
421914d7362SJan Parcel
422914d7362SJan Parcel /* mn_root should point to the / following /devices */
423914d7362SJan Parcel if (mn_root != NULL) {
424914d7362SJan Parcel *mn_root = ptr += strlen(prefix) - 1;
425914d7362SJan Parcel }
426914d7362SJan Parcel return (1);
427914d7362SJan Parcel }
428914d7362SJan Parcel
429914d7362SJan Parcel prefix = "/devices/";
430914d7362SJan Parcel
431914d7362SJan Parcel if (strncmp(contents, prefix, strlen(prefix)) == 0) {
432914d7362SJan Parcel
433914d7362SJan Parcel /* mn_root should point to the / following /devices/ */
434914d7362SJan Parcel if (mn_root != NULL) {
435914d7362SJan Parcel *mn_root = contents + strlen(prefix) - 1;
436914d7362SJan Parcel }
437914d7362SJan Parcel return (1);
438914d7362SJan Parcel }
439914d7362SJan Parcel
440914d7362SJan Parcel if (mn_root != NULL) {
441914d7362SJan Parcel *mn_root = contents;
442914d7362SJan Parcel }
443914d7362SJan Parcel return (0);
444914d7362SJan Parcel }
445914d7362SJan Parcel
446914d7362SJan Parcel /*
447914d7362SJan Parcel * Temporarily duplicated directly from libdevinfo's devfs_resolve_link(),
448914d7362SJan Parcel * and renamed, because we cannot link this from libdevinfo now, and will
449914d7362SJan Parcel * create a sensible solution in the near future.
450914d7362SJan Parcel *
451914d7362SJan Parcel * returns 0 if resolved, -1 otherwise.
452914d7362SJan Parcel * devpath: Absolute path to /dev link
453914d7362SJan Parcel * devfs_path: Returns malloced string: /devices path w/out "/devices"
454914d7362SJan Parcel */
455914d7362SJan Parcel static int
dmap_resolve_link(char * devpath,char ** devfs_path)456914d7362SJan Parcel dmap_resolve_link(char *devpath, char **devfs_path)
457914d7362SJan Parcel {
458914d7362SJan Parcel char contents[PATH_MAX + 1];
459914d7362SJan Parcel char stage_link[PATH_MAX + 1];
460914d7362SJan Parcel char *ptr;
461914d7362SJan Parcel int linksize;
462914d7362SJan Parcel char *slashdev = "/dev/";
463914d7362SJan Parcel
464914d7362SJan Parcel if (devfs_path) {
465914d7362SJan Parcel *devfs_path = NULL;
466914d7362SJan Parcel }
467914d7362SJan Parcel
468914d7362SJan Parcel linksize = readlink(devpath, contents, PATH_MAX);
469914d7362SJan Parcel
470914d7362SJan Parcel if (linksize <= 0) {
471914d7362SJan Parcel return (-1);
472914d7362SJan Parcel } else {
473914d7362SJan Parcel contents[linksize] = '\0';
474914d7362SJan Parcel }
475914d7362SJan Parcel
476914d7362SJan Parcel /*
477914d7362SJan Parcel * if the link contents is not a minor node assume
478914d7362SJan Parcel * that link contents is really a pointer to another
479914d7362SJan Parcel * link, and if so recurse and read its link contents.
480914d7362SJan Parcel */
481914d7362SJan Parcel if (dmap_minor_root((const char *)contents, (const char **)&ptr) !=
482914d7362SJan Parcel 1) {
483914d7362SJan Parcel if (strncmp(contents, slashdev, strlen(slashdev)) == 0) {
484914d7362SJan Parcel /* absolute path, starting with /dev */
485914d7362SJan Parcel (void) strcpy(stage_link, contents);
486914d7362SJan Parcel } else {
487914d7362SJan Parcel /* relative path, prefix devpath */
488914d7362SJan Parcel if ((ptr = strrchr(devpath, '/')) == NULL) {
489914d7362SJan Parcel /* invalid link */
490914d7362SJan Parcel return (-1);
491914d7362SJan Parcel }
492914d7362SJan Parcel *ptr = '\0';
493914d7362SJan Parcel (void) strcpy(stage_link, devpath);
494914d7362SJan Parcel *ptr = '/';
495914d7362SJan Parcel (void) strcat(stage_link, "/");
496914d7362SJan Parcel (void) strcat(stage_link, contents);
497914d7362SJan Parcel
498914d7362SJan Parcel }
499914d7362SJan Parcel return (dmap_resolve_link(stage_link, devfs_path));
500914d7362SJan Parcel }
501914d7362SJan Parcel
502914d7362SJan Parcel if (devfs_path) {
503914d7362SJan Parcel *devfs_path = strdup(ptr);
504914d7362SJan Parcel if (*devfs_path == NULL) {
505914d7362SJan Parcel return (-1);
506914d7362SJan Parcel }
507914d7362SJan Parcel }
508914d7362SJan Parcel
509914d7362SJan Parcel return (0);
510914d7362SJan Parcel }
511914d7362SJan Parcel
512914d7362SJan Parcel /*
5137e3e5701SJan Parcel * dmap_physname: path to /devices device
5147e3e5701SJan Parcel * Returns:
5157e3e5701SJan Parcel * strdup'd (i.e. malloc'd) real device file if successful
5167e3e5701SJan Parcel * NULL on error
5177e3e5701SJan Parcel */
5187e3e5701SJan Parcel char *
dmap_physname(devmap_t * dmap)5197e3e5701SJan Parcel dmap_physname(devmap_t *dmap)
5207e3e5701SJan Parcel {
5217e3e5701SJan Parcel char *oldlink;
5227e3e5701SJan Parcel char stage_link[PATH_MAX + 1];
5237e3e5701SJan Parcel
5247e3e5701SJan Parcel if ((dmap == NULL) || (dmap->dmap_devarray == NULL) ||
5257e3e5701SJan Parcel (dmap->dmap_devarray[0] == NULL))
5267e3e5701SJan Parcel return (NULL);
5277e3e5701SJan Parcel
5287e3e5701SJan Parcel (void) strncpy(stage_link, dmap->dmap_devarray[0], sizeof (stage_link));
5297e3e5701SJan Parcel
530914d7362SJan Parcel if (dmap_resolve_link(stage_link, &oldlink) == 0)
5317e3e5701SJan Parcel return (oldlink);
5327e3e5701SJan Parcel return (NULL);
5337e3e5701SJan Parcel }
5347e3e5701SJan Parcel
5357e3e5701SJan Parcel /*
53645916cd2Sjpk * dm_match -
53745916cd2Sjpk * calls dmap_matchname or dmap_matchtype as appropriate.
53845916cd2Sjpk */
53945916cd2Sjpk int
dm_match(devmap_t * dmap,da_args * dargs)54045916cd2Sjpk dm_match(devmap_t *dmap, da_args *dargs)
54145916cd2Sjpk {
54245916cd2Sjpk if (dargs->devinfo->devname)
54345916cd2Sjpk return (dmap_matchname(dmap, dargs->devinfo->devname));
54445916cd2Sjpk else if (dargs->devinfo->devtype)
54545916cd2Sjpk return (dmap_matchtype(dmap, dargs->devinfo->devtype));
54645916cd2Sjpk
54745916cd2Sjpk return (0);
54845916cd2Sjpk }
54945916cd2Sjpk
55045916cd2Sjpk /*
55145916cd2Sjpk * dmap_interpret -
55245916cd2Sjpk * calls dmap_interpretf and dmap_dlexpand to parse devmap_t line.
55345916cd2Sjpk * returns pointer to parsed devmapt_t entry, else returns NULL on error.
55445916cd2Sjpk */
55545916cd2Sjpk devmap_t *
dmap_interpret(char * val,devmap_t * dm)55645916cd2Sjpk dmap_interpret(char *val, devmap_t *dm)
55745916cd2Sjpk {
55845916cd2Sjpk if (dmap_interpretf(val, dm) == NULL)
55945916cd2Sjpk return (NULL);
56045916cd2Sjpk
56145916cd2Sjpk return (dmap_dlexpand(dm));
56245916cd2Sjpk }
56345916cd2Sjpk
56445916cd2Sjpk /*
56545916cd2Sjpk * dmap_interpretf -
56645916cd2Sjpk * parses string "val" and initializes pointers in the given devmap_t to
56745916cd2Sjpk * fields in "val".
56845916cd2Sjpk * returns pointer to updated devmap_t.
56945916cd2Sjpk */
57045916cd2Sjpk static devmap_t *
dmap_interpretf(char * val,devmap_t * dm)57145916cd2Sjpk dmap_interpretf(char *val, devmap_t *dm)
57245916cd2Sjpk {
57345916cd2Sjpk dm->dmap_devname = getdadmfield(val, KV_TOKEN_DELIMIT);
57445916cd2Sjpk dm->dmap_devtype = getdadmfield(NULL, KV_TOKEN_DELIMIT);
57545916cd2Sjpk dm->dmap_devlist = getdadmfield(NULL, KV_TOKEN_DELIMIT);
57645916cd2Sjpk dm->dmap_devarray = NULL;
57745916cd2Sjpk if (dm->dmap_devname == NULL ||
57845916cd2Sjpk dm->dmap_devtype == NULL ||
57945916cd2Sjpk dm->dmap_devlist == NULL)
58045916cd2Sjpk return (NULL);
58145916cd2Sjpk
58245916cd2Sjpk return (dm);
58345916cd2Sjpk }
58445916cd2Sjpk
58545916cd2Sjpk /*
58645916cd2Sjpk * dmap_dlexpand -
58745916cd2Sjpk * expands dmap_devlist of the form `devlist_generate`
58845916cd2Sjpk * returns unexpanded form if there is no '\`' or in case of error.
58945916cd2Sjpk */
59045916cd2Sjpk static devmap_t *
dmap_dlexpand(devmap_t * dmp)59145916cd2Sjpk dmap_dlexpand(devmap_t *dmp)
59245916cd2Sjpk {
59345916cd2Sjpk char tmplist[DA_BUFSIZE + 1];
59445916cd2Sjpk char *cp, *cpl, **darp;
59545916cd2Sjpk int count;
59645916cd2Sjpk FILE *expansion;
59745916cd2Sjpk
59845916cd2Sjpk dmp->dmap_devarray = NULL;
59945916cd2Sjpk if (dmp->dmap_devlist == NULL)
60045916cd2Sjpk return (NULL);
60145916cd2Sjpk if (*(dmp->dmap_devlist) != '`') {
60245916cd2Sjpk (void) strcpy(tmplist, dmp->dmap_devlist);
60345916cd2Sjpk } else {
60445916cd2Sjpk (void) strcpy(tmplist, dmp->dmap_devlist + 1);
60545916cd2Sjpk if ((cp = strchr(tmplist, '`')) != NULL)
60645916cd2Sjpk *cp = '\0';
607004388ebScasper if ((expansion = popen(tmplist, "rF")) == NULL)
60845916cd2Sjpk return (NULL);
60945916cd2Sjpk count = fread(tmplist, 1, sizeof (tmplist) - 1, expansion);
61045916cd2Sjpk (void) pclose(expansion);
61145916cd2Sjpk tmplist[count] = '\0';
61245916cd2Sjpk }
61345916cd2Sjpk
61445916cd2Sjpk /* cleanup the list */
61545916cd2Sjpk count = pack_white(tmplist);
61645916cd2Sjpk dmp->dmap_devarray = darp =
61745916cd2Sjpk (char **)malloc((count + 2) * sizeof (char *));
61845916cd2Sjpk if (darp == NULL)
61945916cd2Sjpk return (NULL);
62045916cd2Sjpk cp = tmplist;
62145916cd2Sjpk while ((cp = strtok_r(cp, " ", &cpl)) != NULL) {
62245916cd2Sjpk *darp = strdup(cp);
62345916cd2Sjpk if (*darp == NULL) {
62445916cd2Sjpk freedmapent(dmp);
62545916cd2Sjpk return (NULL);
62645916cd2Sjpk }
62745916cd2Sjpk darp++;
62845916cd2Sjpk cp = NULL;
62945916cd2Sjpk }
63045916cd2Sjpk *darp = NULL;
63145916cd2Sjpk
63245916cd2Sjpk return (dmp);
63345916cd2Sjpk }
63445916cd2Sjpk
63545916cd2Sjpk /*
63645916cd2Sjpk * dmapskip -
63745916cd2Sjpk * scans input string to find next colon or end of line.
63845916cd2Sjpk * returns pointer to next char.
6397c478bd9Sstevel@tonic-gate */
6407c478bd9Sstevel@tonic-gate static char *
dmapskip(char * p)64145916cd2Sjpk dmapskip(char *p)
6427c478bd9Sstevel@tonic-gate {
6437c478bd9Sstevel@tonic-gate while (*p && *p != ':' && *p != '\n')
6447c478bd9Sstevel@tonic-gate ++p;
6457c478bd9Sstevel@tonic-gate if (*p == '\n')
6467c478bd9Sstevel@tonic-gate *p = '\0';
6477c478bd9Sstevel@tonic-gate else if (*p != '\0')
6487c478bd9Sstevel@tonic-gate *p++ = '\0';
64945916cd2Sjpk
6507c478bd9Sstevel@tonic-gate return (p);
6517c478bd9Sstevel@tonic-gate }
65245916cd2Sjpk
6537c478bd9Sstevel@tonic-gate /*
65445916cd2Sjpk * dmapdskip -
65545916cd2Sjpk * scans input string to find next space or end of line.
65645916cd2Sjpk * returns pointer to next char.
6577c478bd9Sstevel@tonic-gate */
6587c478bd9Sstevel@tonic-gate static char *
dmapdskip(p)65945916cd2Sjpk dmapdskip(p)
66045916cd2Sjpk register char *p;
6617c478bd9Sstevel@tonic-gate {
6627c478bd9Sstevel@tonic-gate while (*p && *p != ' ' && *p != '\n')
6637c478bd9Sstevel@tonic-gate ++p;
6647c478bd9Sstevel@tonic-gate if (*p != '\0')
6657c478bd9Sstevel@tonic-gate *p++ = '\0';
66645916cd2Sjpk
6677c478bd9Sstevel@tonic-gate return (p);
6687c478bd9Sstevel@tonic-gate }
6697c478bd9Sstevel@tonic-gate
67045916cd2Sjpk char *
getdmapfield(char * ptr)67145916cd2Sjpk getdmapfield(char *ptr)
6727c478bd9Sstevel@tonic-gate {
6737c478bd9Sstevel@tonic-gate static char *tptr;
67445916cd2Sjpk
6757c478bd9Sstevel@tonic-gate if (ptr == NULL)
6767c478bd9Sstevel@tonic-gate ptr = tptr;
6777c478bd9Sstevel@tonic-gate if (ptr == NULL)
6787c478bd9Sstevel@tonic-gate return (NULL);
6797c478bd9Sstevel@tonic-gate tptr = dmapskip(ptr);
6807c478bd9Sstevel@tonic-gate ptr = trim_white(ptr);
6817c478bd9Sstevel@tonic-gate if (ptr == NULL)
6827c478bd9Sstevel@tonic-gate return (NULL);
6837c478bd9Sstevel@tonic-gate if (*ptr == NULL)
6847c478bd9Sstevel@tonic-gate return (NULL);
68545916cd2Sjpk
6867c478bd9Sstevel@tonic-gate return (ptr);
6877c478bd9Sstevel@tonic-gate }
68845916cd2Sjpk
68945916cd2Sjpk char *
getdmapdfield(char * ptr)69045916cd2Sjpk getdmapdfield(char *ptr)
6917c478bd9Sstevel@tonic-gate {
6927c478bd9Sstevel@tonic-gate static char *tptr;
6937c478bd9Sstevel@tonic-gate if (ptr != NULL) {
6947c478bd9Sstevel@tonic-gate ptr = trim_white(ptr);
6957c478bd9Sstevel@tonic-gate } else {
6967c478bd9Sstevel@tonic-gate ptr = tptr;
6977c478bd9Sstevel@tonic-gate }
6987c478bd9Sstevel@tonic-gate if (ptr == NULL)
6997c478bd9Sstevel@tonic-gate return (NULL);
7007c478bd9Sstevel@tonic-gate tptr = dmapdskip(ptr);
7017c478bd9Sstevel@tonic-gate if (ptr == NULL)
7027c478bd9Sstevel@tonic-gate return (NULL);
7037c478bd9Sstevel@tonic-gate if (*ptr == NULL)
7047c478bd9Sstevel@tonic-gate return (NULL);
70545916cd2Sjpk
7067c478bd9Sstevel@tonic-gate return (ptr);
7077c478bd9Sstevel@tonic-gate }
708