1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright (c) 1996-1998 by Sun Microsystems, Inc. 24*0Sstevel@tonic-gate * All Rights reserved. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 27*0Sstevel@tonic-gate /* All Rights Reserved */ 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.2 */ 31*0Sstevel@tonic-gate /*LINTLIBRARY*/ 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate /* 34*0Sstevel@tonic-gate * devtab.c 35*0Sstevel@tonic-gate * 36*0Sstevel@tonic-gate * Contains functions that deal with the device table and are not for 37*0Sstevel@tonic-gate * consumption by the general user population. 38*0Sstevel@tonic-gate * 39*0Sstevel@tonic-gate * Functions defined: 40*0Sstevel@tonic-gate * _opendevtab() Opens the device table for commands 41*0Sstevel@tonic-gate * _setdevtab() Rewinds the open device table 42*0Sstevel@tonic-gate * _enddevtab() Closes the open device table 43*0Sstevel@tonic-gate * _getdevtabent() Gets the next entry in the device table 44*0Sstevel@tonic-gate * _freedevtabent() Frees memory allocated to a device-table entry 45*0Sstevel@tonic-gate * _getdevrec() Gets a specific record from the device table 46*0Sstevel@tonic-gate * _devtabpath() Get the pathname of the device table file 47*0Sstevel@tonic-gate * _validalias() Is a value a valid alias? 48*0Sstevel@tonic-gate */ 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate /* 51*0Sstevel@tonic-gate * Header files 52*0Sstevel@tonic-gate * 53*0Sstevel@tonic-gate * <sys/sysmacros.h> System macro definitions 54*0Sstevel@tonic-gate * <sys/types.h> System data types 55*0Sstevel@tonic-gate * <sys/mkdev.h> Device Macros 56*0Sstevel@tonic-gate * <unistd.h> System Symbolic Constants 57*0Sstevel@tonic-gate * <stdio.h> Standard I/O definitions 58*0Sstevel@tonic-gate * <string.h> String handling definitions 59*0Sstevel@tonic-gate * <ctype.h> Character types and macros 60*0Sstevel@tonic-gate * <errno.h> Error codes 61*0Sstevel@tonic-gate * <sys/stat.h> File status information 62*0Sstevel@tonic-gate * <devmgmt.h> Global Device Management definitions 63*0Sstevel@tonic-gate * "devtab.h" Local Device Management definitions 64*0Sstevel@tonic-gate */ 65*0Sstevel@tonic-gate 66*0Sstevel@tonic-gate #include <sys/sysmacros.h> 67*0Sstevel@tonic-gate #include <sys/types.h> 68*0Sstevel@tonic-gate #ifndef SUNOS41 69*0Sstevel@tonic-gate #include <sys/mkdev.h> 70*0Sstevel@tonic-gate #endif 71*0Sstevel@tonic-gate #include <unistd.h> 72*0Sstevel@tonic-gate #include <stdio.h> 73*0Sstevel@tonic-gate #include <string.h> 74*0Sstevel@tonic-gate #include <ctype.h> 75*0Sstevel@tonic-gate #include <errno.h> 76*0Sstevel@tonic-gate #include <sys/stat.h> 77*0Sstevel@tonic-gate #include <devmgmt.h> 78*0Sstevel@tonic-gate #include "devtab.h" 79*0Sstevel@tonic-gate #include <stdlib.h> 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate /* 82*0Sstevel@tonic-gate * Static data definitions: 83*0Sstevel@tonic-gate * dtabrecnum Record number of the current record (0 to n-1) 84*0Sstevel@tonic-gate * leftoff Addr of char to begin next parse using 85*0Sstevel@tonic-gate * getfld(), getattrval(), getquoted() 86*0Sstevel@tonic-gate * recbufsz The size of the buffer used for reading records 87*0Sstevel@tonic-gate * recbuf Addr of malloc() buffer for reading records 88*0Sstevel@tonic-gate * xtndcnt Number of malloc()/realloc() calls on record buffer 89*0Sstevel@tonic-gate */ 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate static int xtndcnt = 0; 92*0Sstevel@tonic-gate static char *recbuf = NULL; 93*0Sstevel@tonic-gate static int recbufsz = 0; 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate static char *leftoff = NULL; 96*0Sstevel@tonic-gate static int dtabrecnum = 0; 97*0Sstevel@tonic-gate 98*0Sstevel@tonic-gate /* 99*0Sstevel@tonic-gate * int samedev(x, y) 100*0Sstevel@tonic-gate * struct stat x, y 101*0Sstevel@tonic-gate * 102*0Sstevel@tonic-gate * Compares pertinent information in a stat() structure 103*0Sstevel@tonic-gate * to see if the two structures describe the same device. 104*0Sstevel@tonic-gate * If the file modes are the same and they have the same 105*0Sstevel@tonic-gate * file system and i-node (i.e. they're links) or they 106*0Sstevel@tonic-gate * are block or character devices and have the same major 107*0Sstevel@tonic-gate * and minor device numbers (i.e. "mknod"s for the same 108*0Sstevel@tonic-gate * device), it's the same device. 109*0Sstevel@tonic-gate * 110*0Sstevel@tonic-gate * Returns: int 111*0Sstevel@tonic-gate * TRUE if the two structures describe the same device 112*0Sstevel@tonic-gate * FALSE otherwise 113*0Sstevel@tonic-gate */ 114*0Sstevel@tonic-gate 115*0Sstevel@tonic-gate static int 116*0Sstevel@tonic-gate samedev(struct stat64 x, struct stat64 y) 117*0Sstevel@tonic-gate { 118*0Sstevel@tonic-gate int same; 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate /* If the devices are of the same type ... */ 122*0Sstevel@tonic-gate if ((x.st_mode & 0170000) == (y.st_mode & 0170000)) { 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gate /* 125*0Sstevel@tonic-gate * If they are described by the same inode on the same device, 126*0Sstevel@tonic-gate * the two devices are the same. Otherwise, if the devices are 127*0Sstevel@tonic-gate * character-special or block-special devices, try to match by 128*0Sstevel@tonic-gate * device type and major and minor device numbers. 129*0Sstevel@tonic-gate */ 130*0Sstevel@tonic-gate 131*0Sstevel@tonic-gate if ((x.st_dev == y.st_dev) && (x.st_ino == y.st_ino)) same = TRUE; 132*0Sstevel@tonic-gate else 133*0Sstevel@tonic-gate if (((x.st_mode & 0170000) == 0020000) || 134*0Sstevel@tonic-gate ((x.st_mode & 0170000) == 0060000)) { 135*0Sstevel@tonic-gate if ((major(x.st_rdev) == major(y.st_rdev)) && 136*0Sstevel@tonic-gate (minor(x.st_rdev) == minor(y.st_rdev))) same = TRUE; 137*0Sstevel@tonic-gate else same = FALSE; 138*0Sstevel@tonic-gate } else same = FALSE; 139*0Sstevel@tonic-gate 140*0Sstevel@tonic-gate } else same = FALSE; 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate return (same); 143*0Sstevel@tonic-gate } 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate /* 146*0Sstevel@tonic-gate * void _setdevtab() 147*0Sstevel@tonic-gate * 148*0Sstevel@tonic-gate * This function rewinds the open device table so that the next 149*0Sstevel@tonic-gate * _getdevtabent() returns the first record in the device table. 150*0Sstevel@tonic-gate * 151*0Sstevel@tonic-gate * Arguments: None 152*0Sstevel@tonic-gate * 153*0Sstevel@tonic-gate * Returns: Void 154*0Sstevel@tonic-gate */ 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate void 157*0Sstevel@tonic-gate _setdevtab(void) 158*0Sstevel@tonic-gate { 159*0Sstevel@tonic-gate /* If the device table file is open, rewind the file */ 160*0Sstevel@tonic-gate if (oam_devtab != NULL) { 161*0Sstevel@tonic-gate rewind(oam_devtab); 162*0Sstevel@tonic-gate dtabrecnum = 0; 163*0Sstevel@tonic-gate } 164*0Sstevel@tonic-gate } 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate /* 167*0Sstevel@tonic-gate * void _enddevtab() 168*0Sstevel@tonic-gate * 169*0Sstevel@tonic-gate * This function closes the open device table. It resets the 170*0Sstevel@tonic-gate * open device table external variable to NULL. 171*0Sstevel@tonic-gate * 172*0Sstevel@tonic-gate * Arguments: None 173*0Sstevel@tonic-gate * 174*0Sstevel@tonic-gate * Returns: Void 175*0Sstevel@tonic-gate */ 176*0Sstevel@tonic-gate 177*0Sstevel@tonic-gate void 178*0Sstevel@tonic-gate _enddevtab(void) 179*0Sstevel@tonic-gate { 180*0Sstevel@tonic-gate /* If the device table file is open, close it */ 181*0Sstevel@tonic-gate if (oam_devtab != NULL) { 182*0Sstevel@tonic-gate (void) fclose(oam_devtab); 183*0Sstevel@tonic-gate oam_devtab = NULL; 184*0Sstevel@tonic-gate dtabrecnum = 0; 185*0Sstevel@tonic-gate } 186*0Sstevel@tonic-gate } 187*0Sstevel@tonic-gate 188*0Sstevel@tonic-gate /* 189*0Sstevel@tonic-gate * char *getfld(ptr, delims) 190*0Sstevel@tonic-gate * char *ptr 191*0Sstevel@tonic-gate * char *delims 192*0Sstevel@tonic-gate * 193*0Sstevel@tonic-gate * Notes: 194*0Sstevel@tonic-gate * - Can't use "strtok()" because of its use of static data. The caller 195*0Sstevel@tonic-gate * may be using strtok() and we'll really mess them up. 196*0Sstevel@tonic-gate * - The function returns NULL if it didn't find any token -- '\0' can't 197*0Sstevel@tonic-gate * be a delimiter using this algorithm. 198*0Sstevel@tonic-gate */ 199*0Sstevel@tonic-gate 200*0Sstevel@tonic-gate static char * 201*0Sstevel@tonic-gate getfld( 202*0Sstevel@tonic-gate char *ptr, /* String to parse */ 203*0Sstevel@tonic-gate char *delims) /* List of delimiters */ 204*0Sstevel@tonic-gate { 205*0Sstevel@tonic-gate int done; /* TRUE if we're finished */ 206*0Sstevel@tonic-gate char *p, *q; /* Temp pointers */ 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gate /* 209*0Sstevel@tonic-gate * Figure out where to start. 210*0Sstevel@tonic-gate * If given a pointer, use that. 211*0Sstevel@tonic-gate * Otherwise, use where we left off. 212*0Sstevel@tonic-gate */ 213*0Sstevel@tonic-gate 214*0Sstevel@tonic-gate p = ptr ? ptr : leftoff; 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate 217*0Sstevel@tonic-gate /* 218*0Sstevel@tonic-gate * If there's anything to parse, search the string for the first 219*0Sstevel@tonic-gate * occurrence of any of the delimiters. If one is found, change it 220*0Sstevel@tonic-gate * to '\0' and remember the place to start for next time. If not 221*0Sstevel@tonic-gate * found, forget the restart address and prepare to return NULL. 222*0Sstevel@tonic-gate * Don't terminate on "escaped" characters. 223*0Sstevel@tonic-gate */ 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate if (p) { /* Anything to do ?? */ 226*0Sstevel@tonic-gate q = p; /* Where to begin */ 227*0Sstevel@tonic-gate done = FALSE; /* We're not done yet */ 228*0Sstevel@tonic-gate while (*q && !done) { /* Any more chars */ 229*0Sstevel@tonic-gate if (*q == '\\') { /* Escaped ? */ 230*0Sstevel@tonic-gate if (*(++q)) q++; /* Skip escaped char */ 231*0Sstevel@tonic-gate } else /* Not escaped */ 232*0Sstevel@tonic-gate if (!strchr(delims, *q)) q++; /* Skip non-delim */ 233*0Sstevel@tonic-gate else done = TRUE; /* Otherwise, done */ 234*0Sstevel@tonic-gate } 235*0Sstevel@tonic-gate if (*q) { /* Terminator found? */ 236*0Sstevel@tonic-gate *q++ = '\0'; /* Null-terminate token */ 237*0Sstevel@tonic-gate leftoff = q; /* Remember restart pt. */ 238*0Sstevel@tonic-gate } else 239*0Sstevel@tonic-gate leftoff = p = NULL; /* Nothin found or left */ 240*0Sstevel@tonic-gate } 241*0Sstevel@tonic-gate 242*0Sstevel@tonic-gate /* Finished */ 243*0Sstevel@tonic-gate return (p); /* Return ptr to token */ 244*0Sstevel@tonic-gate } 245*0Sstevel@tonic-gate 246*0Sstevel@tonic-gate /* 247*0Sstevel@tonic-gate * char *getquoted(ptr) 248*0Sstevel@tonic-gate * char *ptr; 249*0Sstevel@tonic-gate * 250*0Sstevel@tonic-gate * This function extracts a quoted string from the string pointed 251*0Sstevel@tonic-gate * to by <ptr>, or, if <ptr> is NULL, wherever we left off 252*0Sstevel@tonic-gate * last time. 253*0Sstevel@tonic-gate * 254*0Sstevel@tonic-gate * Arguments: 255*0Sstevel@tonic-gate * char *ptr Pointer to the character-string to parse, or 256*0Sstevel@tonic-gate * (char *) NULL if we're to pick up where we 257*0Sstevel@tonic-gate * [getquoted(), getfld(), and getattrval()] left off. 258*0Sstevel@tonic-gate * 259*0Sstevel@tonic-gate * Returns: char * 260*0Sstevel@tonic-gate * The address of malloc()ed space that contains the possibly quoted 261*0Sstevel@tonic-gate * string. 262*0Sstevel@tonic-gate * 263*0Sstevel@tonic-gate * Notes: 264*0Sstevel@tonic-gate * - This code only works if it can assume that the last character in 265*0Sstevel@tonic-gate * the string it's parsing is a '\n', something that is guarenteed 266*0Sstevel@tonic-gate * by the getnextrec() function. 267*0Sstevel@tonic-gate */ 268*0Sstevel@tonic-gate 269*0Sstevel@tonic-gate static char * 270*0Sstevel@tonic-gate getquoted(char *ptr) 271*0Sstevel@tonic-gate { 272*0Sstevel@tonic-gate /* Automatic data */ 273*0Sstevel@tonic-gate char *rtn; /* Value to return */ 274*0Sstevel@tonic-gate char *p, *q; /* Temps */ 275*0Sstevel@tonic-gate 276*0Sstevel@tonic-gate /* Figure out where to start off */ 277*0Sstevel@tonic-gate p = ptr ? ptr : leftoff; 278*0Sstevel@tonic-gate 279*0Sstevel@tonic-gate /* If there's anything to parse and it's a quoted string ... */ 280*0Sstevel@tonic-gate if ((p) && (*p == '"') && (p = getfld(p+1, "\""))) { 281*0Sstevel@tonic-gate 282*0Sstevel@tonic-gate /* Copy string for the caller */ 283*0Sstevel@tonic-gate if (rtn = malloc(strlen(p)+1)) { /* Malloc() space */ 284*0Sstevel@tonic-gate q = rtn; /* Set up temp ptr */ 285*0Sstevel@tonic-gate do { 286*0Sstevel@tonic-gate if (*p == '\\') p++; /* Skip escape */ 287*0Sstevel@tonic-gate *q++ = *p; /* Copy char */ 288*0Sstevel@tonic-gate } while (*p++); /* While there's chars */ 289*0Sstevel@tonic-gate } else leftoff = rtn = NULL; 290*0Sstevel@tonic-gate } else leftoff = rtn = NULL; 291*0Sstevel@tonic-gate 292*0Sstevel@tonic-gate /* Fini */ 293*0Sstevel@tonic-gate return (rtn); 294*0Sstevel@tonic-gate } 295*0Sstevel@tonic-gate 296*0Sstevel@tonic-gate /* 297*0Sstevel@tonic-gate * struct attrval *getattrval(ptr) 298*0Sstevel@tonic-gate * char *ptr 299*0Sstevel@tonic-gate * 300*0Sstevel@tonic-gate * This function extracts the next attr=val pair from <ptr> or wherever 301*0Sstevel@tonic-gate * getfld() left off... 302*0Sstevel@tonic-gate * 303*0Sstevel@tonic-gate * Arguments: 304*0Sstevel@tonic-gate * char *ptr The string to parse, or (char *) NULL if we're to 305*0Sstevel@tonic-gate * begin wherever we left off last time. 306*0Sstevel@tonic-gate * 307*0Sstevel@tonic-gate * Returns: struct attrval * 308*0Sstevel@tonic-gate * The address of a malloc()ed structure containing the attribute and the 309*0Sstevel@tonic-gate * value of the attr=val pair extracted. 310*0Sstevel@tonic-gate */ 311*0Sstevel@tonic-gate 312*0Sstevel@tonic-gate static struct attrval * 313*0Sstevel@tonic-gate getattrval(char *ptr) 314*0Sstevel@tonic-gate { 315*0Sstevel@tonic-gate /* Automatic data */ 316*0Sstevel@tonic-gate struct attrval *rtn; /* Ptr to struct to return */ 317*0Sstevel@tonic-gate char *p, *q; /* Temp pointers */ 318*0Sstevel@tonic-gate 319*0Sstevel@tonic-gate 320*0Sstevel@tonic-gate /* Use what's given to us or wherever we left off */ 321*0Sstevel@tonic-gate p = ptr ? ptr : leftoff; 322*0Sstevel@tonic-gate 323*0Sstevel@tonic-gate /* If there's anything to parse, extract the next attr=val pair */ 324*0Sstevel@tonic-gate if (p) { 325*0Sstevel@tonic-gate 326*0Sstevel@tonic-gate /* Eat white space */ 327*0Sstevel@tonic-gate while (*p && isspace((unsigned char)*p)) p++; 328*0Sstevel@tonic-gate 329*0Sstevel@tonic-gate /* Extract the attribute name, if any */ 330*0Sstevel@tonic-gate if (*p && getfld(p, "=")) { 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate /* Allocate space for the structure we're building */ 333*0Sstevel@tonic-gate if (rtn = malloc(sizeof (struct attrval))) { 334*0Sstevel@tonic-gate 335*0Sstevel@tonic-gate /* Allocate space for the attribute name */ 336*0Sstevel@tonic-gate if (rtn->attr = malloc(strlen(p)+1)) { 337*0Sstevel@tonic-gate 338*0Sstevel@tonic-gate /* Copy the attribute name into alloc'd space */ 339*0Sstevel@tonic-gate q = rtn->attr; /* Set up temp ptr */ 340*0Sstevel@tonic-gate do { 341*0Sstevel@tonic-gate if (*p == '\\') p++; /* Skip escape */ 342*0Sstevel@tonic-gate *q++ = *p; /* Copy char */ 343*0Sstevel@tonic-gate } while (*p++); /* While more */ 344*0Sstevel@tonic-gate 345*0Sstevel@tonic-gate /* Extract the value */ 346*0Sstevel@tonic-gate if (!(rtn->val = getquoted(NULL))) { 347*0Sstevel@tonic-gate /* Error getting value, free resources */ 348*0Sstevel@tonic-gate free(rtn->attr); 349*0Sstevel@tonic-gate free(rtn); 350*0Sstevel@tonic-gate leftoff = NULL; 351*0Sstevel@tonic-gate rtn = NULL; 352*0Sstevel@tonic-gate } 353*0Sstevel@tonic-gate } else { 354*0Sstevel@tonic-gate /* Error getting space for attribute, free resources */ 355*0Sstevel@tonic-gate free(rtn); 356*0Sstevel@tonic-gate leftoff = NULL; 357*0Sstevel@tonic-gate rtn = NULL; 358*0Sstevel@tonic-gate } 359*0Sstevel@tonic-gate 360*0Sstevel@tonic-gate } else { 361*0Sstevel@tonic-gate /* No space for attr struct */ 362*0Sstevel@tonic-gate leftoff = NULL; 363*0Sstevel@tonic-gate rtn = NULL; 364*0Sstevel@tonic-gate } 365*0Sstevel@tonic-gate 366*0Sstevel@tonic-gate } else { 367*0Sstevel@tonic-gate /* No attribute name */ 368*0Sstevel@tonic-gate leftoff = NULL; 369*0Sstevel@tonic-gate rtn = NULL; 370*0Sstevel@tonic-gate } 371*0Sstevel@tonic-gate 372*0Sstevel@tonic-gate } else { 373*0Sstevel@tonic-gate /* Nothing to parse */ 374*0Sstevel@tonic-gate leftoff = NULL; 375*0Sstevel@tonic-gate rtn = NULL; 376*0Sstevel@tonic-gate } 377*0Sstevel@tonic-gate 378*0Sstevel@tonic-gate /* Done */ 379*0Sstevel@tonic-gate return (rtn); 380*0Sstevel@tonic-gate } 381*0Sstevel@tonic-gate 382*0Sstevel@tonic-gate /* 383*0Sstevel@tonic-gate * char *getnextrec() 384*0Sstevel@tonic-gate * 385*0Sstevel@tonic-gate * This function gets the next record from the input stream "oam_devtab" 386*0Sstevel@tonic-gate * and puts it in the device-table record buffer (whose address is in 387*0Sstevel@tonic-gate * "recbuf"). If the buffer is not allocated or is too small to 388*0Sstevel@tonic-gate * accommodate the record, the function allocates more space to the 389*0Sstevel@tonic-gate * buffer. 390*0Sstevel@tonic-gate * 391*0Sstevel@tonic-gate * Arguments: None 392*0Sstevel@tonic-gate * 393*0Sstevel@tonic-gate * Returns: char * 394*0Sstevel@tonic-gate * The address of the buffer containing the record. 395*0Sstevel@tonic-gate * 396*0Sstevel@tonic-gate * Static Data Referenced: 397*0Sstevel@tonic-gate * recbuf Address of the buffer containing records read from the 398*0Sstevel@tonic-gate * device table file 399*0Sstevel@tonic-gate * recbufsz Current size of the record buffer 400*0Sstevel@tonic-gate * xtndcnt Number of times the record buffer has been extended 401*0Sstevel@tonic-gate * oam_devtab Device table stream, expected to be open for (at 402*0Sstevel@tonic-gate * least) reading 403*0Sstevel@tonic-gate * 404*0Sstevel@tonic-gate * Notes: 405*0Sstevel@tonic-gate * - The string returned in the buffer <buf> ALWAYS end in a '\n' (newline) 406*0Sstevel@tonic-gate * character followed by a '\0' (null). 407*0Sstevel@tonic-gate */ 408*0Sstevel@tonic-gate 409*0Sstevel@tonic-gate static char * 410*0Sstevel@tonic-gate getnextrec(void) 411*0Sstevel@tonic-gate { 412*0Sstevel@tonic-gate /* Automatic data */ 413*0Sstevel@tonic-gate char *recp; /* Value to return */ 414*0Sstevel@tonic-gate char *p; /* Temp pointer */ 415*0Sstevel@tonic-gate int done; /* TRUE if we're finished */ 416*0Sstevel@tonic-gate int reclen; /* Number of chars in record */ 417*0Sstevel@tonic-gate 418*0Sstevel@tonic-gate 419*0Sstevel@tonic-gate /* If there's no buffer for records, try to get one */ 420*0Sstevel@tonic-gate if (!recbuf) { 421*0Sstevel@tonic-gate if (recbuf = malloc(DTAB_BUFSIZ)) { 422*0Sstevel@tonic-gate recbufsz = DTAB_BUFSIZ; 423*0Sstevel@tonic-gate xtndcnt = 0; 424*0Sstevel@tonic-gate } else return (NULL); 425*0Sstevel@tonic-gate } 426*0Sstevel@tonic-gate 427*0Sstevel@tonic-gate 428*0Sstevel@tonic-gate /* Get the next record */ 429*0Sstevel@tonic-gate recp = fgets(recbuf, recbufsz, oam_devtab); 430*0Sstevel@tonic-gate done = FALSE; 431*0Sstevel@tonic-gate 432*0Sstevel@tonic-gate /* While we've something to return and we're not finished ... */ 433*0Sstevel@tonic-gate while (recp && !done) { 434*0Sstevel@tonic-gate 435*0Sstevel@tonic-gate /* If our return string isn't a null-string ... */ 436*0Sstevel@tonic-gate if ((reclen = (int)strlen(recp)) != 0) { 437*0Sstevel@tonic-gate 438*0Sstevel@tonic-gate /* If we have a complete record, we're finished */ 439*0Sstevel@tonic-gate if ((*(recp+reclen-1) == '\n') && 440*0Sstevel@tonic-gate ((reclen == 1) || (*(recp+reclen-2) != '\\'))) done = TRUE; 441*0Sstevel@tonic-gate else while (!done) { 442*0Sstevel@tonic-gate 443*0Sstevel@tonic-gate /* 444*0Sstevel@tonic-gate * Need to complete the record. A complete record is 445*0Sstevel@tonic-gate * one which is terminated by an unescaped new-line 446*0Sstevel@tonic-gate * character. 447*0Sstevel@tonic-gate */ 448*0Sstevel@tonic-gate 449*0Sstevel@tonic-gate /* If the buffer is full, expand it and continue reading */ 450*0Sstevel@tonic-gate if (reclen == recbufsz-1) { 451*0Sstevel@tonic-gate 452*0Sstevel@tonic-gate /* Have we reached our maximum extension count? */ 453*0Sstevel@tonic-gate if (xtndcnt < XTND_MAXCNT) { 454*0Sstevel@tonic-gate 455*0Sstevel@tonic-gate /* Expand the record buffer */ 456*0Sstevel@tonic-gate if (p = realloc(recbuf, 457*0Sstevel@tonic-gate (size_t)recbufsz+DTAB_BUFINC)) { 458*0Sstevel@tonic-gate 459*0Sstevel@tonic-gate /* Update buffer information */ 460*0Sstevel@tonic-gate xtndcnt++; 461*0Sstevel@tonic-gate recbuf = p; 462*0Sstevel@tonic-gate recbufsz += DTAB_BUFINC; 463*0Sstevel@tonic-gate 464*0Sstevel@tonic-gate } else { 465*0Sstevel@tonic-gate 466*0Sstevel@tonic-gate /* Expansion failed */ 467*0Sstevel@tonic-gate recp = NULL; 468*0Sstevel@tonic-gate done = TRUE; 469*0Sstevel@tonic-gate } 470*0Sstevel@tonic-gate 471*0Sstevel@tonic-gate } else { 472*0Sstevel@tonic-gate 473*0Sstevel@tonic-gate /* Maximum extend count exceeded. Insane table */ 474*0Sstevel@tonic-gate recp = NULL; 475*0Sstevel@tonic-gate done = TRUE; 476*0Sstevel@tonic-gate } 477*0Sstevel@tonic-gate 478*0Sstevel@tonic-gate } 479*0Sstevel@tonic-gate 480*0Sstevel@tonic-gate /* Complete the record */ 481*0Sstevel@tonic-gate if (!done) { 482*0Sstevel@tonic-gate 483*0Sstevel@tonic-gate /* Read stuff into the expanded space */ 484*0Sstevel@tonic-gate if (fgets(recbuf+reclen, recbufsz-reclen, oam_devtab)) { 485*0Sstevel@tonic-gate reclen = (int)strlen(recbuf); 486*0Sstevel@tonic-gate recp = recbuf; 487*0Sstevel@tonic-gate if ((*(recp+reclen-1) == '\n') && 488*0Sstevel@tonic-gate ((reclen == 1) || (*(recp+reclen-2) != '\\'))) 489*0Sstevel@tonic-gate done = TRUE; 490*0Sstevel@tonic-gate } else { 491*0Sstevel@tonic-gate /* Read failed, corrupt record? */ 492*0Sstevel@tonic-gate recp = NULL; 493*0Sstevel@tonic-gate done = TRUE; 494*0Sstevel@tonic-gate } 495*0Sstevel@tonic-gate } 496*0Sstevel@tonic-gate 497*0Sstevel@tonic-gate } /* End incomplete record handling */ 498*0Sstevel@tonic-gate 499*0Sstevel@tonic-gate } else { 500*0Sstevel@tonic-gate 501*0Sstevel@tonic-gate /* Read a null string? (corrupt table) */ 502*0Sstevel@tonic-gate recp = NULL; 503*0Sstevel@tonic-gate done = TRUE; 504*0Sstevel@tonic-gate } 505*0Sstevel@tonic-gate 506*0Sstevel@tonic-gate } /* while (recp && !done) */ 507*0Sstevel@tonic-gate 508*0Sstevel@tonic-gate /* Return what we've got (if anything) */ 509*0Sstevel@tonic-gate return (recp); 510*0Sstevel@tonic-gate } 511*0Sstevel@tonic-gate 512*0Sstevel@tonic-gate /* 513*0Sstevel@tonic-gate * char *_devtabpath() 514*0Sstevel@tonic-gate * 515*0Sstevel@tonic-gate * Get the pathname of the device table 516*0Sstevel@tonic-gate * 517*0Sstevel@tonic-gate * Arguments: None 518*0Sstevel@tonic-gate * 519*0Sstevel@tonic-gate * Returns: char * 520*0Sstevel@tonic-gate * Returns the pathname to the device table of NULL if 521*0Sstevel@tonic-gate * there was a problem getting the memory needed to contain the 522*0Sstevel@tonic-gate * pathname. 523*0Sstevel@tonic-gate * 524*0Sstevel@tonic-gate * Algorithm: 525*0Sstevel@tonic-gate * 1. If OAM_DEVTAB is defined in the environment and is not 526*0Sstevel@tonic-gate * defined as "", it returns the value of that environment 527*0Sstevel@tonic-gate * variable. 528*0Sstevel@tonic-gate * 2. Otherwise, use the value of the environment variable DTAB_PATH. 529*0Sstevel@tonic-gate */ 530*0Sstevel@tonic-gate 531*0Sstevel@tonic-gate 532*0Sstevel@tonic-gate char * 533*0Sstevel@tonic-gate _devtabpath(void) 534*0Sstevel@tonic-gate { 535*0Sstevel@tonic-gate 536*0Sstevel@tonic-gate /* Automatic data */ 537*0Sstevel@tonic-gate #ifdef DEBUG 538*0Sstevel@tonic-gate char *path; /* Ptr to path in environment */ 539*0Sstevel@tonic-gate #endif 540*0Sstevel@tonic-gate char *rtnval; /* Ptr to value to return */ 541*0Sstevel@tonic-gate 542*0Sstevel@tonic-gate 543*0Sstevel@tonic-gate /* 544*0Sstevel@tonic-gate * If compiled with -DDEBUG=1, 545*0Sstevel@tonic-gate * look for the pathname in the environment 546*0Sstevel@tonic-gate */ 547*0Sstevel@tonic-gate 548*0Sstevel@tonic-gate #ifdef DEBUG 549*0Sstevel@tonic-gate if (((path = getenv(OAM_DEVTAB)) != NULL) && (*path)) { 550*0Sstevel@tonic-gate if (rtnval = malloc(strlen(path)+1)) 551*0Sstevel@tonic-gate (void) strcpy(rtnval, path); 552*0Sstevel@tonic-gate } else { 553*0Sstevel@tonic-gate #endif 554*0Sstevel@tonic-gate /* 555*0Sstevel@tonic-gate * Use the standard device table. 556*0Sstevel@tonic-gate */ 557*0Sstevel@tonic-gate 558*0Sstevel@tonic-gate if (rtnval = malloc(strlen(DTAB_PATH)+1)) 559*0Sstevel@tonic-gate (void) strcpy(rtnval, DTAB_PATH); 560*0Sstevel@tonic-gate 561*0Sstevel@tonic-gate #ifdef DEBUG 562*0Sstevel@tonic-gate } 563*0Sstevel@tonic-gate #endif 564*0Sstevel@tonic-gate 565*0Sstevel@tonic-gate /* Finished */ 566*0Sstevel@tonic-gate return (rtnval); 567*0Sstevel@tonic-gate } 568*0Sstevel@tonic-gate 569*0Sstevel@tonic-gate /* 570*0Sstevel@tonic-gate * int _opendevtab(mode) 571*0Sstevel@tonic-gate * char *mode 572*0Sstevel@tonic-gate * 573*0Sstevel@tonic-gate * The _opendevtab() function opens a device table for a command. 574*0Sstevel@tonic-gate * 575*0Sstevel@tonic-gate * Arguments: 576*0Sstevel@tonic-gate * mode The open mode to use to open the file. (i.e. "r" for 577*0Sstevel@tonic-gate * reading, "w" for writing. See FOPEN(BA_OS) in SVID.) 578*0Sstevel@tonic-gate * 579*0Sstevel@tonic-gate * Returns: int 580*0Sstevel@tonic-gate * TRUE if it successfully opens the device table file, FALSE otherwise 581*0Sstevel@tonic-gate */ 582*0Sstevel@tonic-gate 583*0Sstevel@tonic-gate int 584*0Sstevel@tonic-gate _opendevtab(char *mode) 585*0Sstevel@tonic-gate { 586*0Sstevel@tonic-gate /* 587*0Sstevel@tonic-gate * Automatic data 588*0Sstevel@tonic-gate */ 589*0Sstevel@tonic-gate 590*0Sstevel@tonic-gate char *devtabname; /* Ptr to the device table name */ 591*0Sstevel@tonic-gate int rtnval; /* Value to return */ 592*0Sstevel@tonic-gate 593*0Sstevel@tonic-gate 594*0Sstevel@tonic-gate rtnval = TRUE; 595*0Sstevel@tonic-gate if (devtabname = _devtabpath()) { 596*0Sstevel@tonic-gate if (oam_devtab) (void) fclose(oam_devtab); 597*0Sstevel@tonic-gate if (oam_devtab = fopen(devtabname, mode)) 598*0Sstevel@tonic-gate dtabrecnum = 0; /* :-) */ 599*0Sstevel@tonic-gate else rtnval = FALSE; /* :-( */ 600*0Sstevel@tonic-gate } else rtnval = FALSE; /* :-( */ 601*0Sstevel@tonic-gate return (rtnval); 602*0Sstevel@tonic-gate } 603*0Sstevel@tonic-gate 604*0Sstevel@tonic-gate /* 605*0Sstevel@tonic-gate * int _validalias(alias) 606*0Sstevel@tonic-gate * char *alias 607*0Sstevel@tonic-gate * 608*0Sstevel@tonic-gate * Determine if <alias> is a valid alias. Returns TRUE if it is 609*0Sstevel@tonic-gate * a valid alias, FALSE otherwise. 610*0Sstevel@tonic-gate * 611*0Sstevel@tonic-gate * Arguments: 612*0Sstevel@tonic-gate * alias Value to check out 613*0Sstevel@tonic-gate * 614*0Sstevel@tonic-gate * Returns: int 615*0Sstevel@tonic-gate * TRUE if <alias> is a valid alias, FALSE otherwise. 616*0Sstevel@tonic-gate */ 617*0Sstevel@tonic-gate 618*0Sstevel@tonic-gate int 619*0Sstevel@tonic-gate _validalias(char *alias) /* Alias to validate */ 620*0Sstevel@tonic-gate { 621*0Sstevel@tonic-gate /* Automatic data */ 622*0Sstevel@tonic-gate char *p; /* Temp pointer */ 623*0Sstevel@tonic-gate size_t len; /* Length of <alias> */ 624*0Sstevel@tonic-gate int rtn; /* Value to return */ 625*0Sstevel@tonic-gate 626*0Sstevel@tonic-gate 627*0Sstevel@tonic-gate /* Assume the worst */ 628*0Sstevel@tonic-gate rtn = FALSE; 629*0Sstevel@tonic-gate 630*0Sstevel@tonic-gate /* 631*0Sstevel@tonic-gate * A valid alias contains 0 < i <= 14 characters. The first 632*0Sstevel@tonic-gate * must be alphanumeric or "@$_." and the rest must be alphanumeric 633*0Sstevel@tonic-gate * or "@#$_+-." 634*0Sstevel@tonic-gate */ 635*0Sstevel@tonic-gate 636*0Sstevel@tonic-gate /* Check length */ 637*0Sstevel@tonic-gate if ((alias != NULL) && ((len = strlen(alias)) > 0) && (len <= 14)) { 638*0Sstevel@tonic-gate 639*0Sstevel@tonic-gate /* Check the first character */ 640*0Sstevel@tonic-gate p = alias; 641*0Sstevel@tonic-gate if (isalnum((unsigned char)*p) || strchr("@$_.", *p)) { 642*0Sstevel@tonic-gate 643*0Sstevel@tonic-gate /* Check the rest of the characters */ 644*0Sstevel@tonic-gate for (p++; *p && (isalnum((unsigned char)*p) || 645*0Sstevel@tonic-gate strchr("@#$_-+.", *p)); p++) 646*0Sstevel@tonic-gate ; 647*0Sstevel@tonic-gate if (!(*p)) rtn = TRUE; 648*0Sstevel@tonic-gate } 649*0Sstevel@tonic-gate } 650*0Sstevel@tonic-gate 651*0Sstevel@tonic-gate /* Return indicator... */ 652*0Sstevel@tonic-gate return (rtn); 653*0Sstevel@tonic-gate 654*0Sstevel@tonic-gate } /* int _validalias() */ 655*0Sstevel@tonic-gate 656*0Sstevel@tonic-gate /* 657*0Sstevel@tonic-gate * struct devtabent *_getdevtabent() 658*0Sstevel@tonic-gate * 659*0Sstevel@tonic-gate * This function returns the next entry in the device table. 660*0Sstevel@tonic-gate * If no device table is open, it opens the standard device table 661*0Sstevel@tonic-gate * and returns the first record in the table. 662*0Sstevel@tonic-gate * 663*0Sstevel@tonic-gate * Arguments: None. 664*0Sstevel@tonic-gate * 665*0Sstevel@tonic-gate * Returns: struct devtabent * 666*0Sstevel@tonic-gate * Pointer to the next record in the device table, or 667*0Sstevel@tonic-gate * (struct devtabent *) NULL if it was unable to open the file or there 668*0Sstevel@tonic-gate * are no more records to read. "errno" reflects the situation. If 669*0Sstevel@tonic-gate * errno is not changed and the function returns NULL, there are no more 670*0Sstevel@tonic-gate * records to read. If errno is set, it indicates the error. 671*0Sstevel@tonic-gate * 672*0Sstevel@tonic-gate * Notes: 673*0Sstevel@tonic-gate * - The caller should set "errno" to 0 before calling this function. 674*0Sstevel@tonic-gate */ 675*0Sstevel@tonic-gate 676*0Sstevel@tonic-gate struct devtabent * 677*0Sstevel@tonic-gate _getdevtabent(void) 678*0Sstevel@tonic-gate { 679*0Sstevel@tonic-gate /* Automatic data */ 680*0Sstevel@tonic-gate struct devtabent *ent; /* Ptr to dev table entry structure */ 681*0Sstevel@tonic-gate struct attrval *attr; /* Ptr to struct for attr/val pair */ 682*0Sstevel@tonic-gate struct attrval *t; /* Tmp ptr to attr/val struct */ 683*0Sstevel@tonic-gate char *record; /* Ptr to the record just read */ 684*0Sstevel@tonic-gate char *p, *q; /* Tmp char ptrs */ 685*0Sstevel@tonic-gate int done; /* TRUE if we've built an entry */ 686*0Sstevel@tonic-gate 687*0Sstevel@tonic-gate 688*0Sstevel@tonic-gate /* Open the device table if it's not already open */ 689*0Sstevel@tonic-gate if (oam_devtab == NULL) { 690*0Sstevel@tonic-gate if (!_opendevtab("r")) 691*0Sstevel@tonic-gate return (NULL); 692*0Sstevel@tonic-gate } 693*0Sstevel@tonic-gate 694*0Sstevel@tonic-gate /* Get space for the structure we're returning */ 695*0Sstevel@tonic-gate if (!(ent = malloc(sizeof (struct devtabent)))) { 696*0Sstevel@tonic-gate return (NULL); 697*0Sstevel@tonic-gate } 698*0Sstevel@tonic-gate 699*0Sstevel@tonic-gate done = FALSE; 700*0Sstevel@tonic-gate while (!done && (record = getnextrec())) { 701*0Sstevel@tonic-gate 702*0Sstevel@tonic-gate /* Save record number in structure */ 703*0Sstevel@tonic-gate ent->entryno = dtabrecnum++; 704*0Sstevel@tonic-gate 705*0Sstevel@tonic-gate /* Comment record? If so, just save the value and we're through */ 706*0Sstevel@tonic-gate if (strchr("#\n", *record) || isspace((unsigned char)*record)) { 707*0Sstevel@tonic-gate ent->comment = TRUE; 708*0Sstevel@tonic-gate done = TRUE; 709*0Sstevel@tonic-gate if (ent->attrstr = malloc(strlen(record)+1)) { 710*0Sstevel@tonic-gate q = ent->attrstr; 711*0Sstevel@tonic-gate p = record; 712*0Sstevel@tonic-gate do { 713*0Sstevel@tonic-gate if (*p == '\\') p++; 714*0Sstevel@tonic-gate *q++ = *p; 715*0Sstevel@tonic-gate } while (*p++); 716*0Sstevel@tonic-gate } else { 717*0Sstevel@tonic-gate free(ent); 718*0Sstevel@tonic-gate ent = NULL; 719*0Sstevel@tonic-gate } 720*0Sstevel@tonic-gate } 721*0Sstevel@tonic-gate 722*0Sstevel@tonic-gate else { 723*0Sstevel@tonic-gate 724*0Sstevel@tonic-gate /* Record is a data record. Parse it. */ 725*0Sstevel@tonic-gate ent->comment = FALSE; 726*0Sstevel@tonic-gate ent->attrstr = NULL; /* For now */ 727*0Sstevel@tonic-gate 728*0Sstevel@tonic-gate /* Extract the device alias */ 729*0Sstevel@tonic-gate if (p = getfld(record, ":")) { 730*0Sstevel@tonic-gate if (*p) { 731*0Sstevel@tonic-gate if (ent->alias = malloc(strlen(p)+1)) { 732*0Sstevel@tonic-gate q = ent->alias; 733*0Sstevel@tonic-gate do { 734*0Sstevel@tonic-gate if (*p == '\\') p++; 735*0Sstevel@tonic-gate *q++ = *p; 736*0Sstevel@tonic-gate } while (*p++); 737*0Sstevel@tonic-gate } 738*0Sstevel@tonic-gate } else ent->alias = NULL; 739*0Sstevel@tonic-gate 740*0Sstevel@tonic-gate /* Extract the character-device name */ 741*0Sstevel@tonic-gate if ((p = getfld(NULL, ":")) == NULL) { 742*0Sstevel@tonic-gate if (ent->alias) 743*0Sstevel@tonic-gate free(ent->alias); 744*0Sstevel@tonic-gate } else { 745*0Sstevel@tonic-gate if (*p) { 746*0Sstevel@tonic-gate if (ent->cdevice = malloc(strlen(p)+1)) { 747*0Sstevel@tonic-gate q = ent->cdevice; 748*0Sstevel@tonic-gate do { 749*0Sstevel@tonic-gate if (*p == '\\') p++; 750*0Sstevel@tonic-gate *q++ = *p; 751*0Sstevel@tonic-gate } while (*p++); 752*0Sstevel@tonic-gate } 753*0Sstevel@tonic-gate } else ent->cdevice = NULL; 754*0Sstevel@tonic-gate 755*0Sstevel@tonic-gate /* Extract the block-device name */ 756*0Sstevel@tonic-gate if (!(p = getfld(NULL, ":"))) { 757*0Sstevel@tonic-gate if (ent->alias) free(ent->alias); 758*0Sstevel@tonic-gate if (ent->cdevice) free(ent->cdevice); 759*0Sstevel@tonic-gate } else { 760*0Sstevel@tonic-gate if (*p) { 761*0Sstevel@tonic-gate if (ent->bdevice = malloc(strlen(p)+1)) { 762*0Sstevel@tonic-gate q = ent->bdevice; 763*0Sstevel@tonic-gate do { 764*0Sstevel@tonic-gate if (*p == '\\') p++; 765*0Sstevel@tonic-gate *q++ = *p; 766*0Sstevel@tonic-gate } while (*p++); 767*0Sstevel@tonic-gate } 768*0Sstevel@tonic-gate } else 769*0Sstevel@tonic-gate ent->bdevice = NULL; 770*0Sstevel@tonic-gate 771*0Sstevel@tonic-gate /* Extract the pathname */ 772*0Sstevel@tonic-gate if ((p = getfld(NULL, ":\n")) == NULL) { 773*0Sstevel@tonic-gate if (ent->alias) free(ent->alias); 774*0Sstevel@tonic-gate if (ent->cdevice) free(ent->cdevice); 775*0Sstevel@tonic-gate if (ent->bdevice) free(ent->bdevice); 776*0Sstevel@tonic-gate } else { 777*0Sstevel@tonic-gate if (*p) { 778*0Sstevel@tonic-gate if (ent->pathname = malloc(strlen(p)+1)) { 779*0Sstevel@tonic-gate q = ent->pathname; 780*0Sstevel@tonic-gate do { 781*0Sstevel@tonic-gate if (*p == '\\') p++; 782*0Sstevel@tonic-gate *q++ = *p; 783*0Sstevel@tonic-gate } while (*p++); 784*0Sstevel@tonic-gate } 785*0Sstevel@tonic-gate } else 786*0Sstevel@tonic-gate ent->pathname = NULL; 787*0Sstevel@tonic-gate 788*0Sstevel@tonic-gate /* Found a valid record */ 789*0Sstevel@tonic-gate done = TRUE; 790*0Sstevel@tonic-gate 791*0Sstevel@tonic-gate /* 792*0Sstevel@tonic-gate * Extract attributes, build a linked list of 793*0Sstevel@tonic-gate * 'em (may be none) 794*0Sstevel@tonic-gate */ 795*0Sstevel@tonic-gate if (attr = getattrval(NULL)) { 796*0Sstevel@tonic-gate ent->attrlist = attr; 797*0Sstevel@tonic-gate t = attr; 798*0Sstevel@tonic-gate while (attr = getattrval(NULL)) { 799*0Sstevel@tonic-gate t->next = attr; 800*0Sstevel@tonic-gate t = attr; 801*0Sstevel@tonic-gate } 802*0Sstevel@tonic-gate t->next = NULL; 803*0Sstevel@tonic-gate } else 804*0Sstevel@tonic-gate ent->attrlist = NULL; 805*0Sstevel@tonic-gate 806*0Sstevel@tonic-gate } /* pathname extracted */ 807*0Sstevel@tonic-gate } /* bdevice extracted */ 808*0Sstevel@tonic-gate } /* cdevice extracted */ 809*0Sstevel@tonic-gate } /* alias extracted */ 810*0Sstevel@tonic-gate } 811*0Sstevel@tonic-gate } /* !done && record read */ 812*0Sstevel@tonic-gate 813*0Sstevel@tonic-gate /* If no entry was read, free space allocated to the structure */ 814*0Sstevel@tonic-gate if (!done) { 815*0Sstevel@tonic-gate free(ent); 816*0Sstevel@tonic-gate ent = NULL; 817*0Sstevel@tonic-gate } 818*0Sstevel@tonic-gate 819*0Sstevel@tonic-gate return (ent); 820*0Sstevel@tonic-gate } 821*0Sstevel@tonic-gate 822*0Sstevel@tonic-gate /* 823*0Sstevel@tonic-gate * void _freedevtabent(devtabent) 824*0Sstevel@tonic-gate * struct devtabent *devtabent; 825*0Sstevel@tonic-gate * 826*0Sstevel@tonic-gate * This function frees space allocated to a device table entry. 827*0Sstevel@tonic-gate * 828*0Sstevel@tonic-gate * Arguments: 829*0Sstevel@tonic-gate * struct devtabent *devtabent The structure whose space is to be 830*0Sstevel@tonic-gate * freed. 831*0Sstevel@tonic-gate * 832*0Sstevel@tonic-gate * Returns: void 833*0Sstevel@tonic-gate */ 834*0Sstevel@tonic-gate 835*0Sstevel@tonic-gate void 836*0Sstevel@tonic-gate _freedevtabent(struct devtabent *ent) 837*0Sstevel@tonic-gate { 838*0Sstevel@tonic-gate /* 839*0Sstevel@tonic-gate * Automatic data 840*0Sstevel@tonic-gate */ 841*0Sstevel@tonic-gate 842*0Sstevel@tonic-gate struct attrval *p; /* Structure being freed */ 843*0Sstevel@tonic-gate struct attrval *q; /* Next structure to free */ 844*0Sstevel@tonic-gate 845*0Sstevel@tonic-gate if (!ent->comment) { 846*0Sstevel@tonic-gate 847*0Sstevel@tonic-gate /* 848*0Sstevel@tonic-gate * Free the attribute list. For each item in the attribute 849*0Sstevel@tonic-gate * list, 850*0Sstevel@tonic-gate * 1. Free the attribute name (always defined), 851*0Sstevel@tonic-gate * 2. Free the value (if any -- it's not defined if we're 852*0Sstevel@tonic-gate * changing an existing attribute), 853*0Sstevel@tonic-gate * 3. Free the space allocated to the structure. 854*0Sstevel@tonic-gate */ 855*0Sstevel@tonic-gate 856*0Sstevel@tonic-gate q = ent->attrlist; 857*0Sstevel@tonic-gate if (q) 858*0Sstevel@tonic-gate do { 859*0Sstevel@tonic-gate p = q; 860*0Sstevel@tonic-gate q = p->next; 861*0Sstevel@tonic-gate free(p->attr); 862*0Sstevel@tonic-gate if (p->val) free(p->val); 863*0Sstevel@tonic-gate free(p); 864*0Sstevel@tonic-gate } while (q); 865*0Sstevel@tonic-gate 866*0Sstevel@tonic-gate /* Free the standard fields (alias, cdevice, bdevice, pathname) */ 867*0Sstevel@tonic-gate if (ent->alias) free(ent->alias); 868*0Sstevel@tonic-gate if (ent->cdevice) free(ent->cdevice); 869*0Sstevel@tonic-gate if (ent->bdevice) free(ent->bdevice); 870*0Sstevel@tonic-gate if (ent->pathname) free(ent->pathname); 871*0Sstevel@tonic-gate } 872*0Sstevel@tonic-gate 873*0Sstevel@tonic-gate /* Free the attribute string */ 874*0Sstevel@tonic-gate if (ent->attrstr) free(ent->attrstr); 875*0Sstevel@tonic-gate 876*0Sstevel@tonic-gate /* Free the space allocated to the structure */ 877*0Sstevel@tonic-gate free(ent); 878*0Sstevel@tonic-gate } 879*0Sstevel@tonic-gate 880*0Sstevel@tonic-gate /* 881*0Sstevel@tonic-gate * struct devtabent *_getdevrec(device) 882*0Sstevel@tonic-gate * char *device 883*0Sstevel@tonic-gate * 884*0Sstevel@tonic-gate * Thie _getdevrec() function returns a pointer to a structure that 885*0Sstevel@tonic-gate * contains the information in the device-table entry that describes 886*0Sstevel@tonic-gate * the device <device>. 887*0Sstevel@tonic-gate * 888*0Sstevel@tonic-gate * The device <device> can be a device alias, a pathname contained in 889*0Sstevel@tonic-gate * the entry as the "cdevice", "bdevice", or "pathname" attribute, 890*0Sstevel@tonic-gate * or a pathname to a device described using the "cdevice", "bdevice", 891*0Sstevel@tonic-gate * or "pathname" attribute (depending on whether the pathname references 892*0Sstevel@tonic-gate * a character-special file, block-special file, or something else, 893*0Sstevel@tonic-gate * respectively. 894*0Sstevel@tonic-gate * 895*0Sstevel@tonic-gate * Arguments: 896*0Sstevel@tonic-gate * char *device A character-string describing the device whose record 897*0Sstevel@tonic-gate * is to be retrieved from the device table. 898*0Sstevel@tonic-gate * 899*0Sstevel@tonic-gate * Returns: struct devtabent * 900*0Sstevel@tonic-gate * A pointer to a structure describing the device. 901*0Sstevel@tonic-gate * 902*0Sstevel@tonic-gate * Notes: 903*0Sstevel@tonic-gate * - Someday, add a cache so that repeated requests for the same record 904*0Sstevel@tonic-gate * don't require going to the filesystem. (Maybe -- this might belong 905*0Sstevel@tonic-gate * in devattr()...) 906*0Sstevel@tonic-gate */ 907*0Sstevel@tonic-gate 908*0Sstevel@tonic-gate struct devtabent * 909*0Sstevel@tonic-gate _getdevrec(char *device) /* The device to search for */ 910*0Sstevel@tonic-gate { 911*0Sstevel@tonic-gate /* 912*0Sstevel@tonic-gate * Automatic data 913*0Sstevel@tonic-gate */ 914*0Sstevel@tonic-gate 915*0Sstevel@tonic-gate struct stat64 devstatbuf; /* Stat struct, <device> */ 916*0Sstevel@tonic-gate struct stat64 tblstatbuf; /* Stat struct, tbl entry */ 917*0Sstevel@tonic-gate struct devtabent *devrec; /* Pointer to current record */ 918*0Sstevel@tonic-gate int found; /* TRUE if record found */ 919*0Sstevel@tonic-gate int olderrno; /* Old value of errno */ 920*0Sstevel@tonic-gate 921*0Sstevel@tonic-gate 922*0Sstevel@tonic-gate /* 923*0Sstevel@tonic-gate * Search the device table looking for the requested device 924*0Sstevel@tonic-gate */ 925*0Sstevel@tonic-gate 926*0Sstevel@tonic-gate _setdevtab(); 927*0Sstevel@tonic-gate olderrno = errno; 928*0Sstevel@tonic-gate found = FALSE; 929*0Sstevel@tonic-gate if ((device != NULL) && !_validalias(device)) { 930*0Sstevel@tonic-gate while (!found && (devrec = _getdevtabent())) { 931*0Sstevel@tonic-gate if (!devrec->comment) { 932*0Sstevel@tonic-gate if (devrec->cdevice) 933*0Sstevel@tonic-gate if (strcmp(device, devrec->cdevice) == 0) found = TRUE; 934*0Sstevel@tonic-gate if (devrec->bdevice) 935*0Sstevel@tonic-gate if (strcmp(device, devrec->bdevice) == 0) found = TRUE; 936*0Sstevel@tonic-gate if (devrec->pathname) 937*0Sstevel@tonic-gate if (strcmp(device, devrec->pathname) == 0) found = TRUE; 938*0Sstevel@tonic-gate } else _freedevtabent(devrec); 939*0Sstevel@tonic-gate } 940*0Sstevel@tonic-gate 941*0Sstevel@tonic-gate /* 942*0Sstevel@tonic-gate * If the device <device> wasn't named explicitly in the device 943*0Sstevel@tonic-gate * table, compare it against like entries by comparing file- 944*0Sstevel@tonic-gate * system, major device number, and minor device number 945*0Sstevel@tonic-gate */ 946*0Sstevel@tonic-gate 947*0Sstevel@tonic-gate if (!found) { 948*0Sstevel@tonic-gate _setdevtab(); 949*0Sstevel@tonic-gate 950*0Sstevel@tonic-gate /* Status the file <device>. If fails, invalid device */ 951*0Sstevel@tonic-gate if (stat64(device, &devstatbuf) != 0) errno = ENODEV; 952*0Sstevel@tonic-gate else { 953*0Sstevel@tonic-gate 954*0Sstevel@tonic-gate /* 955*0Sstevel@tonic-gate * If <device> is a block-special device. See if it is 956*0Sstevel@tonic-gate * in the table by matching its file-system indicator 957*0Sstevel@tonic-gate * and major/minor device numbers against the 958*0Sstevel@tonic-gate * file-system and major/minor device numbers of the 959*0Sstevel@tonic-gate * "bdevice" entries. 960*0Sstevel@tonic-gate */ 961*0Sstevel@tonic-gate 962*0Sstevel@tonic-gate if ((devstatbuf.st_mode & 0170000) == 0020000) { 963*0Sstevel@tonic-gate while (!found && (devrec = _getdevtabent())) { 964*0Sstevel@tonic-gate if (!devrec->comment && 965*0Sstevel@tonic-gate (devrec->cdevice != NULL)) 966*0Sstevel@tonic-gate if (stat64(devrec->cdevice, &tblstatbuf) == 0) { 967*0Sstevel@tonic-gate if (samedev(tblstatbuf, devstatbuf)) 968*0Sstevel@tonic-gate found = TRUE; 969*0Sstevel@tonic-gate } else { 970*0Sstevel@tonic-gate /* Ignore stat() errs */ 971*0Sstevel@tonic-gate errno = olderrno; 972*0Sstevel@tonic-gate } 973*0Sstevel@tonic-gate if (!found) _freedevtabent(devrec); 974*0Sstevel@tonic-gate } 975*0Sstevel@tonic-gate } 976*0Sstevel@tonic-gate 977*0Sstevel@tonic-gate /* 978*0Sstevel@tonic-gate * If <device> is a block-special device. See if it is 979*0Sstevel@tonic-gate * in the table by matching its file-system indicator 980*0Sstevel@tonic-gate * and major/minor device numbers against the 981*0Sstevel@tonic-gate * file-system and major/minor device numbers of the 982*0Sstevel@tonic-gate * "bdevice" entries. 983*0Sstevel@tonic-gate */ 984*0Sstevel@tonic-gate 985*0Sstevel@tonic-gate else if ((devstatbuf.st_mode & 0170000) == 0060000) { 986*0Sstevel@tonic-gate while (!found && (devrec = _getdevtabent())) { 987*0Sstevel@tonic-gate if (!devrec->comment && 988*0Sstevel@tonic-gate (devrec->bdevice != NULL)) 989*0Sstevel@tonic-gate if (stat64(devrec->bdevice, &tblstatbuf) == 0) { 990*0Sstevel@tonic-gate if (samedev(tblstatbuf, devstatbuf)) 991*0Sstevel@tonic-gate found = TRUE; 992*0Sstevel@tonic-gate } else { 993*0Sstevel@tonic-gate /* Ignore stat() errs */ 994*0Sstevel@tonic-gate errno = olderrno; 995*0Sstevel@tonic-gate } 996*0Sstevel@tonic-gate if (!found) _freedevtabent(devrec); 997*0Sstevel@tonic-gate } 998*0Sstevel@tonic-gate } 999*0Sstevel@tonic-gate 1000*0Sstevel@tonic-gate /* 1001*0Sstevel@tonic-gate * If <device> is neither a block-special or character- 1002*0Sstevel@tonic-gate * special device. See if it is in the table by 1003*0Sstevel@tonic-gate * matching its file-system indicator and major/minor 1004*0Sstevel@tonic-gate * device numbers against the file-system and 1005*0Sstevel@tonic-gate * major/minor device numbers of the "pathname" entries. 1006*0Sstevel@tonic-gate */ 1007*0Sstevel@tonic-gate 1008*0Sstevel@tonic-gate else { 1009*0Sstevel@tonic-gate while (!found && (devrec = _getdevtabent())) { 1010*0Sstevel@tonic-gate if (!devrec->comment && 1011*0Sstevel@tonic-gate (devrec->pathname != NULL)) 1012*0Sstevel@tonic-gate if (stat64(devrec->pathname, 1013*0Sstevel@tonic-gate &tblstatbuf) == 0) { 1014*0Sstevel@tonic-gate if (samedev(tblstatbuf, devstatbuf)) 1015*0Sstevel@tonic-gate found = TRUE; 1016*0Sstevel@tonic-gate } else { 1017*0Sstevel@tonic-gate /* Ignore stat() errs */ 1018*0Sstevel@tonic-gate errno = olderrno; 1019*0Sstevel@tonic-gate } 1020*0Sstevel@tonic-gate if (!found) _freedevtabent(devrec); 1021*0Sstevel@tonic-gate } 1022*0Sstevel@tonic-gate } 1023*0Sstevel@tonic-gate 1024*0Sstevel@tonic-gate if (!found) { 1025*0Sstevel@tonic-gate devrec = NULL; 1026*0Sstevel@tonic-gate errno = ENODEV; 1027*0Sstevel@tonic-gate } 1028*0Sstevel@tonic-gate 1029*0Sstevel@tonic-gate } /* End case where stat() on the <device> succeeded */ 1030*0Sstevel@tonic-gate 1031*0Sstevel@tonic-gate } /* End case handling pathname not explicitly in device table */ 1032*0Sstevel@tonic-gate 1033*0Sstevel@tonic-gate } /* End case handling <device> as a fully-qualified pathname */ 1034*0Sstevel@tonic-gate 1035*0Sstevel@tonic-gate 1036*0Sstevel@tonic-gate /* 1037*0Sstevel@tonic-gate * Otherwise the device <device> is an alias. 1038*0Sstevel@tonic-gate * Search the table for a record that has as the "alias" attribute 1039*0Sstevel@tonic-gate * the value <device>. 1040*0Sstevel@tonic-gate */ 1041*0Sstevel@tonic-gate 1042*0Sstevel@tonic-gate else { 1043*0Sstevel@tonic-gate while (!found && (devrec = _getdevtabent())) { 1044*0Sstevel@tonic-gate if (!devrec->comment && (device != NULL) && 1045*0Sstevel@tonic-gate strcmp(device, devrec->alias) == 0) 1046*0Sstevel@tonic-gate found = TRUE; 1047*0Sstevel@tonic-gate else _freedevtabent(devrec); 1048*0Sstevel@tonic-gate } 1049*0Sstevel@tonic-gate if (!found) { 1050*0Sstevel@tonic-gate devrec = NULL; 1051*0Sstevel@tonic-gate errno = ENODEV; 1052*0Sstevel@tonic-gate } 1053*0Sstevel@tonic-gate } 1054*0Sstevel@tonic-gate 1055*0Sstevel@tonic-gate /* Fini */ 1056*0Sstevel@tonic-gate return (devrec); 1057*0Sstevel@tonic-gate } 1058