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 * 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 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 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 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 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 * 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 * 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 * 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 * 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 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 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 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 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 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 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 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 * 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 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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