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 /* 227e3e5701SJan Parcel * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 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 *); 5745916cd2Sjpk 5845916cd2Sjpk int dmap_matchdev(devmap_t *, char *); 5945916cd2Sjpk int dmap_matchname(devmap_t *, char *); 6045916cd2Sjpk 6145916cd2Sjpk 627c478bd9Sstevel@tonic-gate /* 6345916cd2Sjpk * _dmapalloc - 6445916cd2Sjpk * allocates common buffers and structures. 6545916cd2Sjpk * returns pointer to the new structure, else returns NULL on error. 667c478bd9Sstevel@tonic-gate */ 6745916cd2Sjpk static struct _dmapbuff * 6845916cd2Sjpk _dmapalloc(void) 697c478bd9Sstevel@tonic-gate { 7045916cd2Sjpk struct _dmapbuff *_dmap = __dmapbuff; 7145916cd2Sjpk 7245916cd2Sjpk if (_dmap == NULL) { 7345916cd2Sjpk _dmap = (struct _dmapbuff *)calloc((unsigned)1, 7445916cd2Sjpk (unsigned)sizeof (*__dmapbuff)); 7545916cd2Sjpk if (_dmap == NULL) 767c478bd9Sstevel@tonic-gate return (NULL); 7745916cd2Sjpk DEVMAPS_FILE = "/etc/security/device_maps"; 7845916cd2Sjpk dmapf = NULL; 7945916cd2Sjpk __dmapbuff = _dmap; 807c478bd9Sstevel@tonic-gate } 8145916cd2Sjpk 8245916cd2Sjpk return (_dmap); 837c478bd9Sstevel@tonic-gate } 8445916cd2Sjpk 857c478bd9Sstevel@tonic-gate /* 8645916cd2Sjpk * setdmapent - 8745916cd2Sjpk * rewinds the device_maps file to the beginning. 8845916cd2Sjpk */ 8945916cd2Sjpk void 9045916cd2Sjpk setdmapent(void) 9145916cd2Sjpk { 9245916cd2Sjpk struct _dmapbuff *_dmap = _dmapalloc(); 9345916cd2Sjpk 9445916cd2Sjpk if (_dmap == NULL) 9545916cd2Sjpk return; 9645916cd2Sjpk if (dmapf == NULL) 97004388ebScasper dmapf = fopen(DEVMAPS_FILE, "rF"); 9845916cd2Sjpk else 9945916cd2Sjpk rewind(dmapf); 10045916cd2Sjpk } 10145916cd2Sjpk 10245916cd2Sjpk /* 10345916cd2Sjpk * enddmapent - 10445916cd2Sjpk * closes device_maps file. 10545916cd2Sjpk */ 10645916cd2Sjpk void 10745916cd2Sjpk enddmapent(void) 10845916cd2Sjpk { 10945916cd2Sjpk struct _dmapbuff *_dmap = _dmapalloc(); 11045916cd2Sjpk 11145916cd2Sjpk if (_dmap == NULL) 11245916cd2Sjpk return; 11345916cd2Sjpk if (dmapf != NULL) { 11445916cd2Sjpk (void) fclose(dmapf); 11545916cd2Sjpk dmapf = NULL; 11645916cd2Sjpk } 11745916cd2Sjpk } 11845916cd2Sjpk 11945916cd2Sjpk void 12045916cd2Sjpk freedmapent(devmap_t *dmap) 12145916cd2Sjpk { 12245916cd2Sjpk char **darp; 12345916cd2Sjpk 12445916cd2Sjpk if ((darp = dmap->dmap_devarray) != NULL) { 12545916cd2Sjpk while (*darp != NULL) 12645916cd2Sjpk free(*darp++); 12745916cd2Sjpk free(dmap->dmap_devarray); 12845916cd2Sjpk dmap->dmap_devarray = NULL; 12945916cd2Sjpk } 13045916cd2Sjpk } 13145916cd2Sjpk 13245916cd2Sjpk /* 13345916cd2Sjpk * setdmapfile - 13445916cd2Sjpk * changes the default device_maps file to the one specified. 13545916cd2Sjpk * It does not close the previous file. If this is desired, enddmapent 13645916cd2Sjpk * should be called prior to setdampfile. 13745916cd2Sjpk */ 13845916cd2Sjpk void 13945916cd2Sjpk setdmapfile(char *file) 14045916cd2Sjpk { 14145916cd2Sjpk struct _dmapbuff *_dmap = _dmapalloc(); 14245916cd2Sjpk 14345916cd2Sjpk if (_dmap == NULL) 14445916cd2Sjpk return; 14545916cd2Sjpk if (dmapf != NULL) { 14645916cd2Sjpk (void) fclose(dmapf); 14745916cd2Sjpk dmapf = NULL; 14845916cd2Sjpk } 14945916cd2Sjpk DEVMAPS_FILE = file; 15045916cd2Sjpk } 15145916cd2Sjpk 15245916cd2Sjpk /* 15345916cd2Sjpk * getdmapent - 15445916cd2Sjpk * When first called, returns a pointer to the first devmap_t structure 15545916cd2Sjpk * in device_maps; thereafter, it returns a pointer to the next devmap_t 15645916cd2Sjpk * structure in the file. Thus successive calls can be used to read the 15745916cd2Sjpk * entire file. 15845916cd2Sjpk * call to getdmapent should be bracketed by setdmapent and enddmapent. 15945916cd2Sjpk * returns pointer to devmap_t found, else returns NULL if no entry found 16045916cd2Sjpk * or on error. 16145916cd2Sjpk */ 16245916cd2Sjpk devmap_t * 16345916cd2Sjpk getdmapent(void) 16445916cd2Sjpk { 16545916cd2Sjpk devmap_t *dmap; 16645916cd2Sjpk struct _dmapbuff *_dmap = _dmapalloc(); 16745916cd2Sjpk 16845916cd2Sjpk if ((_dmap == 0) || (dmapf == NULL)) 16945916cd2Sjpk return (NULL); 17045916cd2Sjpk 17145916cd2Sjpk while (getdadmline(interpdmline, (int)sizeof (interpdmline), 17245916cd2Sjpk dmapf) != 0) { 17345916cd2Sjpk if ((dmap = dmap_interpret(interpdmline, 17445916cd2Sjpk &interpdevmap)) == NULL) 17545916cd2Sjpk continue; 17645916cd2Sjpk return (dmap); 17745916cd2Sjpk } 17845916cd2Sjpk 17945916cd2Sjpk return (NULL); 18045916cd2Sjpk } 18145916cd2Sjpk 18245916cd2Sjpk /* 18345916cd2Sjpk * getdmapnam - 18445916cd2Sjpk * searches from the beginning of device_maps for the device specified by 18545916cd2Sjpk * its name. 18645916cd2Sjpk * call to getdmapnam should be bracketed by setdmapent and enddmapent. 18745916cd2Sjpk * returns pointer to devmapt_t for the device if it is found, else 18845916cd2Sjpk * returns NULL if device not found or in case of error. 18945916cd2Sjpk */ 19045916cd2Sjpk devmap_t * 19145916cd2Sjpk getdmapnam(char *name) 19245916cd2Sjpk { 19345916cd2Sjpk devmap_t *dmap; 19445916cd2Sjpk struct _dmapbuff *_dmap = _dmapalloc(); 19545916cd2Sjpk 19645916cd2Sjpk if ((name == NULL) || (_dmap == 0) || (dmapf == NULL)) 19745916cd2Sjpk return (NULL); 19845916cd2Sjpk 19945916cd2Sjpk while (getdadmline(interpdmline, (int)sizeof (interpdmline), 20045916cd2Sjpk dmapf) != 0) { 20145916cd2Sjpk if (strstr(interpdmline, name) == NULL) 20245916cd2Sjpk continue; 20345916cd2Sjpk if ((dmap = dmap_interpretf(interpdmline, 20445916cd2Sjpk &interpdevmap)) == NULL) 20545916cd2Sjpk continue; 20645916cd2Sjpk if (dmap_matchname(dmap, name)) { 20745916cd2Sjpk if ((dmap = dmap_dlexpand(dmap)) == NULL) 20845916cd2Sjpk continue; 20945916cd2Sjpk enddmapent(); 21045916cd2Sjpk return (dmap); 21145916cd2Sjpk } 21245916cd2Sjpk freedmapent(dmap); 21345916cd2Sjpk } 21445916cd2Sjpk 21545916cd2Sjpk return (NULL); 21645916cd2Sjpk } 21745916cd2Sjpk 21845916cd2Sjpk /* 21945916cd2Sjpk * getdmapdev - 22045916cd2Sjpk * searches from the beginning of device_maps for the device specified by 22145916cd2Sjpk * its logical name. 22245916cd2Sjpk * call to getdmapdev should be bracketed by setdmapent and enddmapent. 22345916cd2Sjpk * returns pointer to the devmap_t for the device if device is found, 22445916cd2Sjpk * else returns NULL if device not found or on error. 22545916cd2Sjpk */ 22645916cd2Sjpk devmap_t * 22745916cd2Sjpk getdmapdev(char *dev) 22845916cd2Sjpk { 22945916cd2Sjpk devmap_t *dmap; 23045916cd2Sjpk struct _dmapbuff *_dmap = _dmapalloc(); 23145916cd2Sjpk 23245916cd2Sjpk if ((dev == NULL) || (_dmap == 0) || (dmapf == NULL)) 23345916cd2Sjpk return (NULL); 23445916cd2Sjpk 23545916cd2Sjpk while (getdadmline(interpdmline, (int)sizeof (interpdmline), 23645916cd2Sjpk dmapf) != 0) { 23745916cd2Sjpk if ((dmap = dmap_interpret(interpdmline, 23845916cd2Sjpk &interpdevmap)) == NULL) 23945916cd2Sjpk continue; 24045916cd2Sjpk if (dmap_matchdev(dmap, dev)) { 24145916cd2Sjpk enddmapent(); 24245916cd2Sjpk return (dmap); 24345916cd2Sjpk } 24445916cd2Sjpk freedmapent(dmap); 24545916cd2Sjpk } 24645916cd2Sjpk 24745916cd2Sjpk return (NULL); 24845916cd2Sjpk } 24945916cd2Sjpk 25045916cd2Sjpk /* 25145916cd2Sjpk * getdmaptype - 25245916cd2Sjpk * searches from the beginning of device_maps for the device specified by 25345916cd2Sjpk * its type. 25445916cd2Sjpk * call to getdmaptype should be bracketed by setdmapent and enddmapent. 25545916cd2Sjpk * returns pointer to devmap_t found, else returns NULL if no entry found 25645916cd2Sjpk * or on error. 25745916cd2Sjpk */ 25845916cd2Sjpk devmap_t * 25945916cd2Sjpk getdmaptype(char *type) 26045916cd2Sjpk { 26145916cd2Sjpk devmap_t *dmap; 26245916cd2Sjpk struct _dmapbuff *_dmap = _dmapalloc(); 26345916cd2Sjpk 26445916cd2Sjpk if ((type == NULL) || (_dmap == 0) || (dmapf == NULL)) 26545916cd2Sjpk return (NULL); 26645916cd2Sjpk 26745916cd2Sjpk while (getdadmline(interpdmline, (int)sizeof (interpdmline), 26845916cd2Sjpk dmapf) != 0) { 26945916cd2Sjpk if ((dmap = dmap_interpretf(interpdmline, 27045916cd2Sjpk &interpdevmap)) == NULL) 27145916cd2Sjpk continue; 27245916cd2Sjpk if (dmap->dmap_devtype != NULL && 27345916cd2Sjpk strcmp(type, dmap->dmap_devtype) == 0) { 27445916cd2Sjpk if ((dmap = dmap_dlexpand(dmap)) == NULL) 27545916cd2Sjpk continue; 27645916cd2Sjpk return (dmap); 27745916cd2Sjpk } 27845916cd2Sjpk freedmapent(dmap); 27945916cd2Sjpk } 28045916cd2Sjpk 28145916cd2Sjpk return (NULL); 28245916cd2Sjpk } 28345916cd2Sjpk 28445916cd2Sjpk /* 2857e3e5701SJan Parcel * dmap_match_one_dev - 2867e3e5701SJan Parcel * Checks if the specified devmap_t contains strings 2877e3e5701SJan Parcel * for the same logical link as the device specified. 2887e3e5701SJan Parcel * This guarantees that the beginnings of a devlist build 2897e3e5701SJan Parcel * match a more-complete devlist for the same device. 2907e3e5701SJan Parcel * 2917e3e5701SJan Parcel * Returns 1 for a match, else returns 0. 2927e3e5701SJan Parcel */ 2937e3e5701SJan Parcel static int 2947e3e5701SJan Parcel dmap_match_one_dev(devmap_t *dmap, char *dev) 2957e3e5701SJan Parcel { 2967e3e5701SJan Parcel char **dva; 2977e3e5701SJan Parcel char *dv; 2987e3e5701SJan Parcel 2997e3e5701SJan Parcel if (dmap->dmap_devarray == NULL) 3007e3e5701SJan Parcel return (0); 3017e3e5701SJan Parcel 3027e3e5701SJan Parcel for (dva = dmap->dmap_devarray; (dv = *dva) != NULL; dva++) { 3037e3e5701SJan Parcel if (strstr(dev, dv) != NULL) 3047e3e5701SJan Parcel return (1); 3057e3e5701SJan Parcel } 3067e3e5701SJan Parcel return (0); 3077e3e5701SJan Parcel } 3087e3e5701SJan Parcel 3097e3e5701SJan Parcel /* 31045916cd2Sjpk * dmap_matchdev - 31145916cd2Sjpk * checks if the specified devmap_t is for the device specified. 31245916cd2Sjpk * returns 1 if it is, else returns 0. 31345916cd2Sjpk */ 31445916cd2Sjpk int 31545916cd2Sjpk dmap_matchdev(devmap_t *dmap, char *dev) 31645916cd2Sjpk { 31745916cd2Sjpk char **dva; 31845916cd2Sjpk char *dv; 31945916cd2Sjpk 32045916cd2Sjpk if (dmap->dmap_devarray == NULL) 32145916cd2Sjpk return (0); 32245916cd2Sjpk for (dva = dmap->dmap_devarray; (dv = *dva) != NULL; dva ++) { 32345916cd2Sjpk if (strcmp(dv, dev) == 0) 32445916cd2Sjpk return (1); 32545916cd2Sjpk } 32645916cd2Sjpk 32745916cd2Sjpk return (0); 32845916cd2Sjpk } 32945916cd2Sjpk 33045916cd2Sjpk /* 3317e3e5701SJan Parcel * Requires a match of the /dev/?dsk links, not just the logical devname 3327e3e5701SJan Parcel * Returns 1 for match found, 0 for match not found, 2 for invalid arguments. 3337e3e5701SJan Parcel */ 3347e3e5701SJan Parcel int 3357e3e5701SJan Parcel dmap_exact_dev(devmap_t *dmap, char *dev, int *num) 3367e3e5701SJan Parcel { 3377e3e5701SJan Parcel char *dv; 3387e3e5701SJan Parcel 3397e3e5701SJan Parcel if ((dev == NULL) || (dmap->dmap_devname == NULL)) 3407e3e5701SJan Parcel return (2); 3417e3e5701SJan Parcel dv = dmap->dmap_devname; 3427e3e5701SJan Parcel dv += strcspn(dmap->dmap_devname, "0123456789"); 3437e3e5701SJan Parcel if (sscanf(dv, "%d", num) != 1) 3447e3e5701SJan Parcel return (2); 3457e3e5701SJan Parcel /* during some add processes, dev can be shorter than dmap */ 3467e3e5701SJan Parcel return (dmap_match_one_dev(dmap, dev)); 3477e3e5701SJan Parcel } 3487e3e5701SJan Parcel 3497e3e5701SJan Parcel /* 35045916cd2Sjpk * dmap_matchtype - 35145916cd2Sjpk * checks if the specified devmap_t is for the device specified. 35245916cd2Sjpk * returns 1 if it is, else returns 0. 35345916cd2Sjpk */ 35445916cd2Sjpk int 35545916cd2Sjpk dmap_matchtype(devmap_t *dmap, char *type) 35645916cd2Sjpk { 35745916cd2Sjpk if ((dmap->dmap_devtype == NULL) || (type == NULL)) 35845916cd2Sjpk return (0); 35945916cd2Sjpk 36045916cd2Sjpk return ((strcmp(dmap->dmap_devtype, type) == 0)); 36145916cd2Sjpk } 36245916cd2Sjpk 36345916cd2Sjpk /* 36445916cd2Sjpk * dmap_matchname - 36545916cd2Sjpk * checks if the specified devmap_t is for the device specified. 36645916cd2Sjpk * returns 1 if it is, else returns 0. 36745916cd2Sjpk */ 36845916cd2Sjpk int 36945916cd2Sjpk dmap_matchname(devmap_t *dmap, char *name) 37045916cd2Sjpk { 37145916cd2Sjpk if (dmap->dmap_devname == NULL) 37245916cd2Sjpk return (0); 37345916cd2Sjpk 37445916cd2Sjpk return ((strcmp(dmap->dmap_devname, name) == 0)); 37545916cd2Sjpk } 37645916cd2Sjpk 37745916cd2Sjpk /* 378*914d7362SJan Parcel * Temporarily duplicated directly from libdevinfo's is_minor_node(), 379*914d7362SJan Parcel * and renamed, because we cannot link this from libdevinfo. 380*914d7362SJan Parcel * 381*914d7362SJan Parcel * To be resolved in a couple of builds. 382*914d7362SJan Parcel * 383*914d7362SJan Parcel * The real fix is to move device allocation out of libbsm. 384*914d7362SJan Parcel * 385*914d7362SJan Parcel * returns 1 if contents is a minor node in /devices. 386*914d7362SJan Parcel * If mn_root is not NULL, mn_root is set to: 387*914d7362SJan Parcel * if contents is a /dev node, mn_root = contents 388*914d7362SJan Parcel * OR 389*914d7362SJan Parcel * if contents is a /devices node, mn_root set to the '/' 390*914d7362SJan Parcel * following /devices. 391*914d7362SJan Parcel */ 392*914d7362SJan Parcel static int 393*914d7362SJan Parcel dmap_minor_root(const char *contents, const char **mn_root) 394*914d7362SJan Parcel { 395*914d7362SJan Parcel char *ptr, *prefix; 396*914d7362SJan Parcel 397*914d7362SJan Parcel prefix = "../devices/"; 398*914d7362SJan Parcel 399*914d7362SJan Parcel if ((ptr = strstr(contents, prefix)) != NULL) { 400*914d7362SJan Parcel 401*914d7362SJan Parcel /* mn_root should point to the / following /devices */ 402*914d7362SJan Parcel if (mn_root != NULL) { 403*914d7362SJan Parcel *mn_root = ptr += strlen(prefix) - 1; 404*914d7362SJan Parcel } 405*914d7362SJan Parcel return (1); 406*914d7362SJan Parcel } 407*914d7362SJan Parcel 408*914d7362SJan Parcel prefix = "/devices/"; 409*914d7362SJan Parcel 410*914d7362SJan Parcel if (strncmp(contents, prefix, strlen(prefix)) == 0) { 411*914d7362SJan Parcel 412*914d7362SJan Parcel /* mn_root should point to the / following /devices/ */ 413*914d7362SJan Parcel if (mn_root != NULL) { 414*914d7362SJan Parcel *mn_root = contents + strlen(prefix) - 1; 415*914d7362SJan Parcel } 416*914d7362SJan Parcel return (1); 417*914d7362SJan Parcel } 418*914d7362SJan Parcel 419*914d7362SJan Parcel if (mn_root != NULL) { 420*914d7362SJan Parcel *mn_root = contents; 421*914d7362SJan Parcel } 422*914d7362SJan Parcel return (0); 423*914d7362SJan Parcel } 424*914d7362SJan Parcel 425*914d7362SJan Parcel /* 426*914d7362SJan Parcel * Temporarily duplicated directly from libdevinfo's devfs_resolve_link(), 427*914d7362SJan Parcel * and renamed, because we cannot link this from libdevinfo now, and will 428*914d7362SJan Parcel * create a sensible solution in the near future. 429*914d7362SJan Parcel * 430*914d7362SJan Parcel * returns 0 if resolved, -1 otherwise. 431*914d7362SJan Parcel * devpath: Absolute path to /dev link 432*914d7362SJan Parcel * devfs_path: Returns malloced string: /devices path w/out "/devices" 433*914d7362SJan Parcel */ 434*914d7362SJan Parcel static int 435*914d7362SJan Parcel dmap_resolve_link(char *devpath, char **devfs_path) 436*914d7362SJan Parcel { 437*914d7362SJan Parcel char contents[PATH_MAX + 1]; 438*914d7362SJan Parcel char stage_link[PATH_MAX + 1]; 439*914d7362SJan Parcel char *ptr; 440*914d7362SJan Parcel int linksize; 441*914d7362SJan Parcel char *slashdev = "/dev/"; 442*914d7362SJan Parcel 443*914d7362SJan Parcel if (devfs_path) { 444*914d7362SJan Parcel *devfs_path = NULL; 445*914d7362SJan Parcel } 446*914d7362SJan Parcel 447*914d7362SJan Parcel linksize = readlink(devpath, contents, PATH_MAX); 448*914d7362SJan Parcel 449*914d7362SJan Parcel if (linksize <= 0) { 450*914d7362SJan Parcel return (-1); 451*914d7362SJan Parcel } else { 452*914d7362SJan Parcel contents[linksize] = '\0'; 453*914d7362SJan Parcel } 454*914d7362SJan Parcel 455*914d7362SJan Parcel /* 456*914d7362SJan Parcel * if the link contents is not a minor node assume 457*914d7362SJan Parcel * that link contents is really a pointer to another 458*914d7362SJan Parcel * link, and if so recurse and read its link contents. 459*914d7362SJan Parcel */ 460*914d7362SJan Parcel if (dmap_minor_root((const char *)contents, (const char **)&ptr) != 461*914d7362SJan Parcel 1) { 462*914d7362SJan Parcel if (strncmp(contents, slashdev, strlen(slashdev)) == 0) { 463*914d7362SJan Parcel /* absolute path, starting with /dev */ 464*914d7362SJan Parcel (void) strcpy(stage_link, contents); 465*914d7362SJan Parcel } else { 466*914d7362SJan Parcel /* relative path, prefix devpath */ 467*914d7362SJan Parcel if ((ptr = strrchr(devpath, '/')) == NULL) { 468*914d7362SJan Parcel /* invalid link */ 469*914d7362SJan Parcel return (-1); 470*914d7362SJan Parcel } 471*914d7362SJan Parcel *ptr = '\0'; 472*914d7362SJan Parcel (void) strcpy(stage_link, devpath); 473*914d7362SJan Parcel *ptr = '/'; 474*914d7362SJan Parcel (void) strcat(stage_link, "/"); 475*914d7362SJan Parcel (void) strcat(stage_link, contents); 476*914d7362SJan Parcel 477*914d7362SJan Parcel } 478*914d7362SJan Parcel return (dmap_resolve_link(stage_link, devfs_path)); 479*914d7362SJan Parcel } 480*914d7362SJan Parcel 481*914d7362SJan Parcel if (devfs_path) { 482*914d7362SJan Parcel *devfs_path = strdup(ptr); 483*914d7362SJan Parcel if (*devfs_path == NULL) { 484*914d7362SJan Parcel return (-1); 485*914d7362SJan Parcel } 486*914d7362SJan Parcel } 487*914d7362SJan Parcel 488*914d7362SJan Parcel return (0); 489*914d7362SJan Parcel } 490*914d7362SJan Parcel 491*914d7362SJan Parcel /* 4927e3e5701SJan Parcel * dmap_physname: path to /devices device 4937e3e5701SJan Parcel * Returns: 4947e3e5701SJan Parcel * strdup'd (i.e. malloc'd) real device file if successful 4957e3e5701SJan Parcel * NULL on error 4967e3e5701SJan Parcel */ 4977e3e5701SJan Parcel char * 4987e3e5701SJan Parcel dmap_physname(devmap_t *dmap) 4997e3e5701SJan Parcel { 5007e3e5701SJan Parcel char *oldlink; 5017e3e5701SJan Parcel char stage_link[PATH_MAX + 1]; 5027e3e5701SJan Parcel 5037e3e5701SJan Parcel if ((dmap == NULL) || (dmap->dmap_devarray == NULL) || 5047e3e5701SJan Parcel (dmap->dmap_devarray[0] == NULL)) 5057e3e5701SJan Parcel return (NULL); 5067e3e5701SJan Parcel 5077e3e5701SJan Parcel (void) strncpy(stage_link, dmap->dmap_devarray[0], sizeof (stage_link)); 5087e3e5701SJan Parcel 509*914d7362SJan Parcel if (dmap_resolve_link(stage_link, &oldlink) == 0) 5107e3e5701SJan Parcel return (oldlink); 5117e3e5701SJan Parcel return (NULL); 5127e3e5701SJan Parcel } 5137e3e5701SJan Parcel 5147e3e5701SJan Parcel /* 51545916cd2Sjpk * dm_match - 51645916cd2Sjpk * calls dmap_matchname or dmap_matchtype as appropriate. 51745916cd2Sjpk */ 51845916cd2Sjpk int 51945916cd2Sjpk dm_match(devmap_t *dmap, da_args *dargs) 52045916cd2Sjpk { 52145916cd2Sjpk if (dargs->devinfo->devname) 52245916cd2Sjpk return (dmap_matchname(dmap, dargs->devinfo->devname)); 52345916cd2Sjpk else if (dargs->devinfo->devtype) 52445916cd2Sjpk return (dmap_matchtype(dmap, dargs->devinfo->devtype)); 52545916cd2Sjpk 52645916cd2Sjpk return (0); 52745916cd2Sjpk } 52845916cd2Sjpk 52945916cd2Sjpk /* 53045916cd2Sjpk * dmap_interpret - 53145916cd2Sjpk * calls dmap_interpretf and dmap_dlexpand to parse devmap_t line. 53245916cd2Sjpk * returns pointer to parsed devmapt_t entry, else returns NULL on error. 53345916cd2Sjpk */ 53445916cd2Sjpk devmap_t * 53545916cd2Sjpk dmap_interpret(char *val, devmap_t *dm) 53645916cd2Sjpk { 53745916cd2Sjpk if (dmap_interpretf(val, dm) == NULL) 53845916cd2Sjpk return (NULL); 53945916cd2Sjpk 54045916cd2Sjpk return (dmap_dlexpand(dm)); 54145916cd2Sjpk } 54245916cd2Sjpk 54345916cd2Sjpk /* 54445916cd2Sjpk * dmap_interpretf - 54545916cd2Sjpk * parses string "val" and initializes pointers in the given devmap_t to 54645916cd2Sjpk * fields in "val". 54745916cd2Sjpk * returns pointer to updated devmap_t. 54845916cd2Sjpk */ 54945916cd2Sjpk static devmap_t * 55045916cd2Sjpk dmap_interpretf(char *val, devmap_t *dm) 55145916cd2Sjpk { 55245916cd2Sjpk dm->dmap_devname = getdadmfield(val, KV_TOKEN_DELIMIT); 55345916cd2Sjpk dm->dmap_devtype = getdadmfield(NULL, KV_TOKEN_DELIMIT); 55445916cd2Sjpk dm->dmap_devlist = getdadmfield(NULL, KV_TOKEN_DELIMIT); 55545916cd2Sjpk dm->dmap_devarray = NULL; 55645916cd2Sjpk if (dm->dmap_devname == NULL || 55745916cd2Sjpk dm->dmap_devtype == NULL || 55845916cd2Sjpk dm->dmap_devlist == NULL) 55945916cd2Sjpk return (NULL); 56045916cd2Sjpk 56145916cd2Sjpk return (dm); 56245916cd2Sjpk } 56345916cd2Sjpk 56445916cd2Sjpk /* 56545916cd2Sjpk * dmap_dlexpand - 56645916cd2Sjpk * expands dmap_devlist of the form `devlist_generate` 56745916cd2Sjpk * returns unexpanded form if there is no '\`' or in case of error. 56845916cd2Sjpk */ 56945916cd2Sjpk static devmap_t * 57045916cd2Sjpk dmap_dlexpand(devmap_t *dmp) 57145916cd2Sjpk { 57245916cd2Sjpk char tmplist[DA_BUFSIZE + 1]; 57345916cd2Sjpk char *cp, *cpl, **darp; 57445916cd2Sjpk int count; 57545916cd2Sjpk FILE *expansion; 57645916cd2Sjpk 57745916cd2Sjpk dmp->dmap_devarray = NULL; 57845916cd2Sjpk if (dmp->dmap_devlist == NULL) 57945916cd2Sjpk return (NULL); 58045916cd2Sjpk if (*(dmp->dmap_devlist) != '`') { 58145916cd2Sjpk (void) strcpy(tmplist, dmp->dmap_devlist); 58245916cd2Sjpk } else { 58345916cd2Sjpk (void) strcpy(tmplist, dmp->dmap_devlist + 1); 58445916cd2Sjpk if ((cp = strchr(tmplist, '`')) != NULL) 58545916cd2Sjpk *cp = '\0'; 586004388ebScasper if ((expansion = popen(tmplist, "rF")) == NULL) 58745916cd2Sjpk return (NULL); 58845916cd2Sjpk count = fread(tmplist, 1, sizeof (tmplist) - 1, expansion); 58945916cd2Sjpk (void) pclose(expansion); 59045916cd2Sjpk tmplist[count] = '\0'; 59145916cd2Sjpk } 59245916cd2Sjpk 59345916cd2Sjpk /* cleanup the list */ 59445916cd2Sjpk count = pack_white(tmplist); 59545916cd2Sjpk dmp->dmap_devarray = darp = 59645916cd2Sjpk (char **)malloc((count + 2) * sizeof (char *)); 59745916cd2Sjpk if (darp == NULL) 59845916cd2Sjpk return (NULL); 59945916cd2Sjpk cp = tmplist; 60045916cd2Sjpk while ((cp = strtok_r(cp, " ", &cpl)) != NULL) { 60145916cd2Sjpk *darp = strdup(cp); 60245916cd2Sjpk if (*darp == NULL) { 60345916cd2Sjpk freedmapent(dmp); 60445916cd2Sjpk return (NULL); 60545916cd2Sjpk } 60645916cd2Sjpk darp++; 60745916cd2Sjpk cp = NULL; 60845916cd2Sjpk } 60945916cd2Sjpk *darp = NULL; 61045916cd2Sjpk 61145916cd2Sjpk return (dmp); 61245916cd2Sjpk } 61345916cd2Sjpk 61445916cd2Sjpk /* 61545916cd2Sjpk * dmapskip - 61645916cd2Sjpk * scans input string to find next colon or end of line. 61745916cd2Sjpk * returns pointer to next char. 6187c478bd9Sstevel@tonic-gate */ 6197c478bd9Sstevel@tonic-gate static char * 62045916cd2Sjpk dmapskip(char *p) 6217c478bd9Sstevel@tonic-gate { 6227c478bd9Sstevel@tonic-gate while (*p && *p != ':' && *p != '\n') 6237c478bd9Sstevel@tonic-gate ++p; 6247c478bd9Sstevel@tonic-gate if (*p == '\n') 6257c478bd9Sstevel@tonic-gate *p = '\0'; 6267c478bd9Sstevel@tonic-gate else if (*p != '\0') 6277c478bd9Sstevel@tonic-gate *p++ = '\0'; 62845916cd2Sjpk 6297c478bd9Sstevel@tonic-gate return (p); 6307c478bd9Sstevel@tonic-gate } 63145916cd2Sjpk 6327c478bd9Sstevel@tonic-gate /* 63345916cd2Sjpk * dmapdskip - 63445916cd2Sjpk * scans input string to find next space or end of line. 63545916cd2Sjpk * returns pointer to next char. 6367c478bd9Sstevel@tonic-gate */ 6377c478bd9Sstevel@tonic-gate static char * 63845916cd2Sjpk dmapdskip(p) 63945916cd2Sjpk register char *p; 6407c478bd9Sstevel@tonic-gate { 6417c478bd9Sstevel@tonic-gate while (*p && *p != ' ' && *p != '\n') 6427c478bd9Sstevel@tonic-gate ++p; 6437c478bd9Sstevel@tonic-gate if (*p != '\0') 6447c478bd9Sstevel@tonic-gate *p++ = '\0'; 64545916cd2Sjpk 6467c478bd9Sstevel@tonic-gate return (p); 6477c478bd9Sstevel@tonic-gate } 6487c478bd9Sstevel@tonic-gate 64945916cd2Sjpk char * 65045916cd2Sjpk getdmapfield(char *ptr) 6517c478bd9Sstevel@tonic-gate { 6527c478bd9Sstevel@tonic-gate static char *tptr; 65345916cd2Sjpk 6547c478bd9Sstevel@tonic-gate if (ptr == NULL) 6557c478bd9Sstevel@tonic-gate ptr = tptr; 6567c478bd9Sstevel@tonic-gate if (ptr == NULL) 6577c478bd9Sstevel@tonic-gate return (NULL); 6587c478bd9Sstevel@tonic-gate tptr = dmapskip(ptr); 6597c478bd9Sstevel@tonic-gate ptr = trim_white(ptr); 6607c478bd9Sstevel@tonic-gate if (ptr == NULL) 6617c478bd9Sstevel@tonic-gate return (NULL); 6627c478bd9Sstevel@tonic-gate if (*ptr == NULL) 6637c478bd9Sstevel@tonic-gate return (NULL); 66445916cd2Sjpk 6657c478bd9Sstevel@tonic-gate return (ptr); 6667c478bd9Sstevel@tonic-gate } 66745916cd2Sjpk 66845916cd2Sjpk char * 66945916cd2Sjpk getdmapdfield(char *ptr) 6707c478bd9Sstevel@tonic-gate { 6717c478bd9Sstevel@tonic-gate static char *tptr; 6727c478bd9Sstevel@tonic-gate if (ptr != NULL) { 6737c478bd9Sstevel@tonic-gate ptr = trim_white(ptr); 6747c478bd9Sstevel@tonic-gate } else { 6757c478bd9Sstevel@tonic-gate ptr = tptr; 6767c478bd9Sstevel@tonic-gate } 6777c478bd9Sstevel@tonic-gate if (ptr == NULL) 6787c478bd9Sstevel@tonic-gate return (NULL); 6797c478bd9Sstevel@tonic-gate tptr = dmapdskip(ptr); 6807c478bd9Sstevel@tonic-gate if (ptr == NULL) 6817c478bd9Sstevel@tonic-gate return (NULL); 6827c478bd9Sstevel@tonic-gate if (*ptr == NULL) 6837c478bd9Sstevel@tonic-gate return (NULL); 68445916cd2Sjpk 6857c478bd9Sstevel@tonic-gate return (ptr); 6867c478bd9Sstevel@tonic-gate } 687