1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright (c) 1996-1997, by Sun Microsystems, Inc. 24*7c478bd9Sstevel@tonic-gate * All Rights reserved. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 27*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.2 */ 31*7c478bd9Sstevel@tonic-gate /* LINTLIBRARY */ 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate /* 34*7c478bd9Sstevel@tonic-gate * putdev.c 35*7c478bd9Sstevel@tonic-gate * 36*7c478bd9Sstevel@tonic-gate * Global Definitions: 37*7c478bd9Sstevel@tonic-gate * _adddevtabrec() Add a record to the device table 38*7c478bd9Sstevel@tonic-gate * _putdevtabrec() Write a record to the device table 39*7c478bd9Sstevel@tonic-gate * _moddevtabrec() Modify a device-table record 40*7c478bd9Sstevel@tonic-gate * _rmdevtabrec() Remove a device-table record 41*7c478bd9Sstevel@tonic-gate * _rmdevtabattrs() Remove attributes from a device-table record 42*7c478bd9Sstevel@tonic-gate * oam_devtab File descriptor of the open device table 43*7c478bd9Sstevel@tonic-gate */ 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate /* 46*7c478bd9Sstevel@tonic-gate * G L O B A L R E F E R E N C E S 47*7c478bd9Sstevel@tonic-gate * 48*7c478bd9Sstevel@tonic-gate * Header Files 49*7c478bd9Sstevel@tonic-gate * Externals Referenced 50*7c478bd9Sstevel@tonic-gate */ 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate /* 53*7c478bd9Sstevel@tonic-gate * Header Files 54*7c478bd9Sstevel@tonic-gate * <sys/types.h> UNIX(r) Data Types 55*7c478bd9Sstevel@tonic-gate * <sys/stat.h> 56*7c478bd9Sstevel@tonic-gate * <stdio.h> Standard I/O definitions 57*7c478bd9Sstevel@tonic-gate * <fcntl.h> Definitions for file control 58*7c478bd9Sstevel@tonic-gate * <errno.h> Error handling definitions 59*7c478bd9Sstevel@tonic-gate * <string.h> String Handling Definitions 60*7c478bd9Sstevel@tonic-gate * <devmgmt.h> Device Management Definitions 61*7c478bd9Sstevel@tonic-gate * <unistd.h> Get UNIX(r) Standard Definitions 62*7c478bd9Sstevel@tonic-gate * "devtab.h" Local Device Management Definitions 63*7c478bd9Sstevel@tonic-gate */ 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 66*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 67*7c478bd9Sstevel@tonic-gate #include <stdio.h> 68*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 69*7c478bd9Sstevel@tonic-gate #include <errno.h> 70*7c478bd9Sstevel@tonic-gate #include <string.h> 71*7c478bd9Sstevel@tonic-gate #include <devmgmt.h> 72*7c478bd9Sstevel@tonic-gate #include <unistd.h> 73*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 74*7c478bd9Sstevel@tonic-gate #include "devtab.h" 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate /* 77*7c478bd9Sstevel@tonic-gate * L O C A L D E F I N I T I O N S 78*7c478bd9Sstevel@tonic-gate * 79*7c478bd9Sstevel@tonic-gate * TDTABNM Name of the temporary device table (in the 80*7c478bd9Sstevel@tonic-gate * directory of the existing table) 81*7c478bd9Sstevel@tonic-gate * TDTABNMLN Number of characters added to the directory 82*7c478bd9Sstevel@tonic-gate * name -- the length of the device table temp name 83*7c478bd9Sstevel@tonic-gate */ 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate #define TDTABNM "%sdevtab.%6.6d" 86*7c478bd9Sstevel@tonic-gate #define TDTABNMLN 13 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate 89*7c478bd9Sstevel@tonic-gate /* 90*7c478bd9Sstevel@tonic-gate * Static functions 91*7c478bd9Sstevel@tonic-gate * strcatesc Copies a character-string from one place to another 92*7c478bd9Sstevel@tonic-gate * escaping the appropriate characters 93*7c478bd9Sstevel@tonic-gate * lkdevtab Locks the device table 94*7c478bd9Sstevel@tonic-gate * unlkdevtab Unlocks the device table 95*7c478bd9Sstevel@tonic-gate * mkdevtabent Builds a device-table entry from the alias and the 96*7c478bd9Sstevel@tonic-gate * list of attr=val pairs given 97*7c478bd9Sstevel@tonic-gate * opennewdevtab Opens a new device table (as a temp file) 98*7c478bd9Sstevel@tonic-gate * mknewdevtab Makes the temp device table the new devtab 99*7c478bd9Sstevel@tonic-gate * rmnewdevtab Remove the temporary device table and free space 100*7c478bd9Sstevel@tonic-gate * allocated to the filename of that file. 101*7c478bd9Sstevel@tonic-gate */ 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate static char *strcatesc(char *, char *); 104*7c478bd9Sstevel@tonic-gate static int lkdevtab(char *, short); 105*7c478bd9Sstevel@tonic-gate static int unlkdevtab(void); 106*7c478bd9Sstevel@tonic-gate static struct devtabent *mkdevtabent(char *, char **); 107*7c478bd9Sstevel@tonic-gate static FILE *opennewdevtab(char **); 108*7c478bd9Sstevel@tonic-gate static int mknewdevtab(char *); 109*7c478bd9Sstevel@tonic-gate static int rmnewdevtab(char *); 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate /* 112*7c478bd9Sstevel@tonic-gate * char *strcatesc(p, q) 113*7c478bd9Sstevel@tonic-gate * char *p 114*7c478bd9Sstevel@tonic-gate * char *q 115*7c478bd9Sstevel@tonic-gate * 116*7c478bd9Sstevel@tonic-gate * Write the character-string pointed to by "q" to the place 117*7c478bd9Sstevel@tonic-gate * pointed to by "p", escaping those characters in "q" found in the 118*7c478bd9Sstevel@tonic-gate * string "DTAB_ESCS" by preceding them with '\\'. Return a pointer to 119*7c478bd9Sstevel@tonic-gate * the byte beyond the last character written to "p". 120*7c478bd9Sstevel@tonic-gate * 121*7c478bd9Sstevel@tonic-gate * Arguments: 122*7c478bd9Sstevel@tonic-gate * p The place to begin writing to 123*7c478bd9Sstevel@tonic-gate * q The string to write 124*7c478bd9Sstevel@tonic-gate * 125*7c478bd9Sstevel@tonic-gate * Returns: char * 126*7c478bd9Sstevel@tonic-gate * The address of the byte beyond the last character written into "p" 127*7c478bd9Sstevel@tonic-gate */ 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate static char * 130*7c478bd9Sstevel@tonic-gate strcatesc( 131*7c478bd9Sstevel@tonic-gate char *p, /* Place to write to */ 132*7c478bd9Sstevel@tonic-gate char *q) /* Thing to write */ 133*7c478bd9Sstevel@tonic-gate { 134*7c478bd9Sstevel@tonic-gate while (*q) { 135*7c478bd9Sstevel@tonic-gate if (strchr(DTAB_ESCS, *q)) *p++ = '\\'; 136*7c478bd9Sstevel@tonic-gate *p++ = *q++; 137*7c478bd9Sstevel@tonic-gate } 138*7c478bd9Sstevel@tonic-gate return (p); 139*7c478bd9Sstevel@tonic-gate } 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate /* 142*7c478bd9Sstevel@tonic-gate * FILE *opennewdevtab(pname) 143*7c478bd9Sstevel@tonic-gate * char **pname 144*7c478bd9Sstevel@tonic-gate * 145*7c478bd9Sstevel@tonic-gate * Generates a temporary device-table name from the existing 146*7c478bd9Sstevel@tonic-gate * device table name (in the same directory) and opens that 147*7c478bd9Sstevel@tonic-gate * file for writing. It puts a pointer to the malloc()ed space 148*7c478bd9Sstevel@tonic-gate * containing the temp device table's name at the place referenced 149*7c478bd9Sstevel@tonic-gate * by <pname>. 150*7c478bd9Sstevel@tonic-gate * 151*7c478bd9Sstevel@tonic-gate * Arguments: 152*7c478bd9Sstevel@tonic-gate * pname Pointer to the char * to contain the address of the name 153*7c478bd9Sstevel@tonic-gate * of the temporary file 154*7c478bd9Sstevel@tonic-gate * 155*7c478bd9Sstevel@tonic-gate * Returns: FILE * 156*7c478bd9Sstevel@tonic-gate * A pointer to the opened stream or (FILE *) NULL if an error occurred. 157*7c478bd9Sstevel@tonic-gate * If an error occurred, "errno" will be set to reflect the problem. 158*7c478bd9Sstevel@tonic-gate */ 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate static FILE * 161*7c478bd9Sstevel@tonic-gate opennewdevtab(char **pname) /* A(ptr to temp filename's path) */ 162*7c478bd9Sstevel@tonic-gate { 163*7c478bd9Sstevel@tonic-gate char *oldname; /* Ptr to the device-table's name */ 164*7c478bd9Sstevel@tonic-gate char *buf; /* Ptr to the temp file's name */ 165*7c478bd9Sstevel@tonic-gate char *dirname; /* Directory containing devtab */ 166*7c478bd9Sstevel@tonic-gate char *p; /* Ptr to last '/' in devtab name */ 167*7c478bd9Sstevel@tonic-gate int fd; /* Opened file descriptor */ 168*7c478bd9Sstevel@tonic-gate FILE *fp; /* Opened file pointer */ 169*7c478bd9Sstevel@tonic-gate struct stat64 sbuf; /* stat buf for old devtab file */ 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate fp = NULL; 172*7c478bd9Sstevel@tonic-gate if (oldname = _devtabpath()) { 173*7c478bd9Sstevel@tonic-gate /* 174*7c478bd9Sstevel@tonic-gate * It is possible for us to have sufficient permissions to create 175*7c478bd9Sstevel@tonic-gate * the new file without having sufficient permissions to write the 176*7c478bd9Sstevel@tonic-gate * original devtab file. For consistency with the operations which 177*7c478bd9Sstevel@tonic-gate * modify the original file by writing it directly we require write 178*7c478bd9Sstevel@tonic-gate * permissions for the original file in order to make a new one. 179*7c478bd9Sstevel@tonic-gate */ 180*7c478bd9Sstevel@tonic-gate if ((fd = open(oldname, O_WRONLY)) == -1) 181*7c478bd9Sstevel@tonic-gate return (NULL); 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate if (fstat64(fd, &sbuf) == -1) { 184*7c478bd9Sstevel@tonic-gate (void) close(fd); 185*7c478bd9Sstevel@tonic-gate return (NULL); 186*7c478bd9Sstevel@tonic-gate } 187*7c478bd9Sstevel@tonic-gate (void) close(fd); 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate if (p = strrchr(oldname, '/')) { 190*7c478bd9Sstevel@tonic-gate *(p+1) = '\0'; 191*7c478bd9Sstevel@tonic-gate dirname = oldname; 192*7c478bd9Sstevel@tonic-gate } else dirname = "./"; 193*7c478bd9Sstevel@tonic-gate if (buf = malloc(TDTABNMLN + strlen(dirname) + 1)) { 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate /* 196*7c478bd9Sstevel@tonic-gate * Build the name of the temp device table and open the 197*7c478bd9Sstevel@tonic-gate * file. We must reset the owner, group and perms to those 198*7c478bd9Sstevel@tonic-gate * of the original devtab file. 199*7c478bd9Sstevel@tonic-gate */ 200*7c478bd9Sstevel@tonic-gate (void) sprintf(buf, TDTABNM, dirname, getpid()); 201*7c478bd9Sstevel@tonic-gate if (fp = fopen(buf, "w")) { 202*7c478bd9Sstevel@tonic-gate *pname = buf; 203*7c478bd9Sstevel@tonic-gate (void) fchmod(fileno(fp), sbuf.st_mode & 0777); 204*7c478bd9Sstevel@tonic-gate (void) fchown(fileno(fp), sbuf.st_uid, sbuf.st_gid); 205*7c478bd9Sstevel@tonic-gate } else { 206*7c478bd9Sstevel@tonic-gate free(buf); 207*7c478bd9Sstevel@tonic-gate } 208*7c478bd9Sstevel@tonic-gate } 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate /* 211*7c478bd9Sstevel@tonic-gate * 212*7c478bd9Sstevel@tonic-gate * Free the space containing the device table's name. 213*7c478bd9Sstevel@tonic-gate */ 214*7c478bd9Sstevel@tonic-gate free(oldname); 215*7c478bd9Sstevel@tonic-gate } 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate /* Finished. Return what we've got */ 218*7c478bd9Sstevel@tonic-gate return (fp); 219*7c478bd9Sstevel@tonic-gate } 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate /* 222*7c478bd9Sstevel@tonic-gate * int rmnewdevtab(tempname) 223*7c478bd9Sstevel@tonic-gate * char *tempname 224*7c478bd9Sstevel@tonic-gate * 225*7c478bd9Sstevel@tonic-gate * Unlink the temp device table and free the memory allocated to 226*7c478bd9Sstevel@tonic-gate * contain the name of that file 227*7c478bd9Sstevel@tonic-gate * 228*7c478bd9Sstevel@tonic-gate * Arguments: 229*7c478bd9Sstevel@tonic-gate * tempname Name of the temporary file 230*7c478bd9Sstevel@tonic-gate * 231*7c478bd9Sstevel@tonic-gate * Returns: int 232*7c478bd9Sstevel@tonic-gate * TRUE if successful, FALSE otherwise 233*7c478bd9Sstevel@tonic-gate */ 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate static int 236*7c478bd9Sstevel@tonic-gate rmnewdevtab(char *tempname) /* Filename of new device table */ 237*7c478bd9Sstevel@tonic-gate { 238*7c478bd9Sstevel@tonic-gate int noerr; /* Flag, TRUE if no error, FALSE otherwise */ 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate /* Unlink the file */ 241*7c478bd9Sstevel@tonic-gate noerr = (unlink(tempname) == 0); 242*7c478bd9Sstevel@tonic-gate 243*7c478bd9Sstevel@tonic-gate /* Free the space allocated to the filename */ 244*7c478bd9Sstevel@tonic-gate free(tempname); 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate /* Return success indicator */ 247*7c478bd9Sstevel@tonic-gate return (noerr); 248*7c478bd9Sstevel@tonic-gate } 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate /* 251*7c478bd9Sstevel@tonic-gate * int mknewdevtab(tempname) 252*7c478bd9Sstevel@tonic-gate * char *tempname 253*7c478bd9Sstevel@tonic-gate * 254*7c478bd9Sstevel@tonic-gate * Make the temporary device-table the new system device table 255*7c478bd9Sstevel@tonic-gate * 256*7c478bd9Sstevel@tonic-gate * Arguments: 257*7c478bd9Sstevel@tonic-gate * tempname Name of the temporary file 258*7c478bd9Sstevel@tonic-gate * 259*7c478bd9Sstevel@tonic-gate * Returns: int 260*7c478bd9Sstevel@tonic-gate * TRUE if successful, FALSE otherwise 261*7c478bd9Sstevel@tonic-gate * 262*7c478bd9Sstevel@tonic-gate * Notes: 263*7c478bd9Sstevel@tonic-gate * - Need to use rename() someday instead of link()/unlink() 264*7c478bd9Sstevel@tonic-gate * - This code is somewhat ineffecient in that asks for the name 265*7c478bd9Sstevel@tonic-gate * of the device-table more than once. Done so that we don't 266*7c478bd9Sstevel@tonic-gate * have to manage that space, but this may be somewhat lazy. 267*7c478bd9Sstevel@tonic-gate */ 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate static int 270*7c478bd9Sstevel@tonic-gate mknewdevtab(char *tempname) /* Ptr to name of temp dev tab */ 271*7c478bd9Sstevel@tonic-gate { 272*7c478bd9Sstevel@tonic-gate char *devtabname; /* Ptr to the device table's name */ 273*7c478bd9Sstevel@tonic-gate int noerr; /* FLAG, TRUE if all's well */ 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate /* Get the device table's pathname */ 276*7c478bd9Sstevel@tonic-gate if (devtabname = _devtabpath()) { 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate /* Unlink the existing file */ 279*7c478bd9Sstevel@tonic-gate if (unlink(devtabname) == 0) { 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate /* Make the temp file the real device table */ 282*7c478bd9Sstevel@tonic-gate noerr = (link(tempname, devtabname) == 0) ? TRUE : FALSE; 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate /* Remove the temp file (and resources) */ 285*7c478bd9Sstevel@tonic-gate if (noerr) (void) rmnewdevtab(tempname); 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate } else noerr = FALSE; /* unlink() failed */ 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate /* Free the device table's name */ 290*7c478bd9Sstevel@tonic-gate free(devtabname); 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate } else noerr = FALSE; /* devtabpath() failed */ 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate /* Finished. Return success indicator */ 295*7c478bd9Sstevel@tonic-gate return (noerr); 296*7c478bd9Sstevel@tonic-gate } 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate /* 299*7c478bd9Sstevel@tonic-gate * static int lkdevtab(o_mode, lktype) 300*7c478bd9Sstevel@tonic-gate * char *o_mode 301*7c478bd9Sstevel@tonic-gate * short lktype 302*7c478bd9Sstevel@tonic-gate * 303*7c478bd9Sstevel@tonic-gate * Lock the device table for writing. If it isn't available, it waits 304*7c478bd9Sstevel@tonic-gate * until it is. 305*7c478bd9Sstevel@tonic-gate * 306*7c478bd9Sstevel@tonic-gate * Arguments: 307*7c478bd9Sstevel@tonic-gate * o_mode The open() mode to use when opening the device table 308*7c478bd9Sstevel@tonic-gate * lktype The type of lock to apply 309*7c478bd9Sstevel@tonic-gate * 310*7c478bd9Sstevel@tonic-gate * Returns: int 311*7c478bd9Sstevel@tonic-gate * TRUE if successful, FALSE with errno set otherwise 312*7c478bd9Sstevel@tonic-gate */ 313*7c478bd9Sstevel@tonic-gate 314*7c478bd9Sstevel@tonic-gate static int 315*7c478bd9Sstevel@tonic-gate lkdevtab( 316*7c478bd9Sstevel@tonic-gate char *o_mode, /* Open mode */ 317*7c478bd9Sstevel@tonic-gate short lktype) /* Lock type */ 318*7c478bd9Sstevel@tonic-gate { 319*7c478bd9Sstevel@tonic-gate /* Automatic data */ 320*7c478bd9Sstevel@tonic-gate struct flock lockinfo; /* File locking structure */ 321*7c478bd9Sstevel@tonic-gate int noerr; /* FLAG, TRUE if no error */ 322*7c478bd9Sstevel@tonic-gate int olderrno; /* Old value of "errno" */ 323*7c478bd9Sstevel@tonic-gate 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate /* Close the device table (if it's open) */ 326*7c478bd9Sstevel@tonic-gate _enddevtab(); 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate /* Open the device table for read/append */ 329*7c478bd9Sstevel@tonic-gate noerr = TRUE; 330*7c478bd9Sstevel@tonic-gate if (_opendevtab(o_mode)) { 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate /* 333*7c478bd9Sstevel@tonic-gate * Lock the device table (for writing). If it's not 334*7c478bd9Sstevel@tonic-gate * available, wait until it is, then close and open the 335*7c478bd9Sstevel@tonic-gate * table (modify and delete change the table!) and try 336*7c478bd9Sstevel@tonic-gate * to lock it again 337*7c478bd9Sstevel@tonic-gate */ 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate /* Build the locking structure */ 340*7c478bd9Sstevel@tonic-gate lockinfo.l_type = lktype; 341*7c478bd9Sstevel@tonic-gate lockinfo.l_whence = 0; 342*7c478bd9Sstevel@tonic-gate lockinfo.l_start = 0L; 343*7c478bd9Sstevel@tonic-gate lockinfo.l_len = 0L; 344*7c478bd9Sstevel@tonic-gate olderrno = errno; 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate /* Keep on going until we lock the file or an error happens */ 347*7c478bd9Sstevel@tonic-gate while ((fcntl(fileno(oam_devtab), F_SETLK, &lockinfo) == -1) && 348*7c478bd9Sstevel@tonic-gate !noerr) { 349*7c478bd9Sstevel@tonic-gate if (errno == EACCES) { 350*7c478bd9Sstevel@tonic-gate if (fcntl(fileno(oam_devtab), F_SETLKW, &lockinfo) == -1) 351*7c478bd9Sstevel@tonic-gate noerr = FALSE; 352*7c478bd9Sstevel@tonic-gate else { 353*7c478bd9Sstevel@tonic-gate /* Reopen the file (maybe it's moved?) */ 354*7c478bd9Sstevel@tonic-gate _enddevtab(); 355*7c478bd9Sstevel@tonic-gate if (!_opendevtab(o_mode)) noerr = FALSE; 356*7c478bd9Sstevel@tonic-gate else errno = olderrno; 357*7c478bd9Sstevel@tonic-gate } 358*7c478bd9Sstevel@tonic-gate } else noerr = FALSE; 359*7c478bd9Sstevel@tonic-gate } 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate if (!noerr) _enddevtab(); /* Don't keep open if in error */ 362*7c478bd9Sstevel@tonic-gate 363*7c478bd9Sstevel@tonic-gate } else noerr = FALSE; 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate /* Done */ 366*7c478bd9Sstevel@tonic-gate return (noerr); 367*7c478bd9Sstevel@tonic-gate } 368*7c478bd9Sstevel@tonic-gate 369*7c478bd9Sstevel@tonic-gate /* 370*7c478bd9Sstevel@tonic-gate * int unlkdevtab() 371*7c478bd9Sstevel@tonic-gate * 372*7c478bd9Sstevel@tonic-gate * Unlock the locked device table. 373*7c478bd9Sstevel@tonic-gate * 374*7c478bd9Sstevel@tonic-gate * Arguments: None 375*7c478bd9Sstevel@tonic-gate * 376*7c478bd9Sstevel@tonic-gate * Returns: int 377*7c478bd9Sstevel@tonic-gate * Whatever fcntl() returns... 378*7c478bd9Sstevel@tonic-gate */ 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate static int 381*7c478bd9Sstevel@tonic-gate unlkdevtab(void) 382*7c478bd9Sstevel@tonic-gate { 383*7c478bd9Sstevel@tonic-gate /* Automatic data */ 384*7c478bd9Sstevel@tonic-gate struct flock lockinfo; /* Locking structure */ 385*7c478bd9Sstevel@tonic-gate int noerr; /* FLAG, TRUE if all's well */ 386*7c478bd9Sstevel@tonic-gate 387*7c478bd9Sstevel@tonic-gate /* Build the locking structure */ 388*7c478bd9Sstevel@tonic-gate lockinfo.l_type = F_UNLCK; /* Lock type */ 389*7c478bd9Sstevel@tonic-gate lockinfo.l_whence = 0; /* Count from top of file */ 390*7c478bd9Sstevel@tonic-gate lockinfo.l_start = 0L; /* From beginning */ 391*7c478bd9Sstevel@tonic-gate lockinfo.l_len = 0L; /* Length of locked data */ 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate /* Unlock it */ 394*7c478bd9Sstevel@tonic-gate noerr = (fcntl(fileno(oam_devtab), F_SETLK, &lockinfo) != -1); 395*7c478bd9Sstevel@tonic-gate _enddevtab(); 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate /* Finished */ 398*7c478bd9Sstevel@tonic-gate return (noerr); 399*7c478bd9Sstevel@tonic-gate } 400*7c478bd9Sstevel@tonic-gate 401*7c478bd9Sstevel@tonic-gate /* 402*7c478bd9Sstevel@tonic-gate * struct devtabent *mkdevtabent(alias, attrlist) 403*7c478bd9Sstevel@tonic-gate * char *alias 404*7c478bd9Sstevel@tonic-gate * char **attrlist 405*7c478bd9Sstevel@tonic-gate * 406*7c478bd9Sstevel@tonic-gate * This function builds a struct devtabent structure describing the 407*7c478bd9Sstevel@tonic-gate * alias <alias> using the information in the attribute list <attrlist>. 408*7c478bd9Sstevel@tonic-gate * The <attrlist> contains data of the form attr=value where attr is 409*7c478bd9Sstevel@tonic-gate * the name of an attribute and value is the value of that attribute. 410*7c478bd9Sstevel@tonic-gate * 411*7c478bd9Sstevel@tonic-gate * Arguments: 412*7c478bd9Sstevel@tonic-gate * alias The alias being added to the device table 413*7c478bd9Sstevel@tonic-gate * attrlist The attributes and values for that alias 414*7c478bd9Sstevel@tonic-gate * 415*7c478bd9Sstevel@tonic-gate * Returns: struct devtabent * 416*7c478bd9Sstevel@tonic-gate * A completed struct devtabent structure containing the description 417*7c478bd9Sstevel@tonic-gate * of the alias. The structure, and all of the data in the structure 418*7c478bd9Sstevel@tonic-gate * are each in space allocated using the malloc() function and should 419*7c478bd9Sstevel@tonic-gate * be freed using the free() function (or the _freedevtabent() function). 420*7c478bd9Sstevel@tonic-gate * 421*7c478bd9Sstevel@tonic-gate * Errors: 422*7c478bd9Sstevel@tonic-gate * EINVAL If "alias" is used as an attribute in an attr=val pair 423*7c478bd9Sstevel@tonic-gate * EAGAIN If an attribute is specified more than once 424*7c478bd9Sstevel@tonic-gate */ 425*7c478bd9Sstevel@tonic-gate 426*7c478bd9Sstevel@tonic-gate static struct devtabent * 427*7c478bd9Sstevel@tonic-gate mkdevtabent( 428*7c478bd9Sstevel@tonic-gate char *alias, /* Alias of entry */ 429*7c478bd9Sstevel@tonic-gate char **attrlist) /* Attributes of new entry */ 430*7c478bd9Sstevel@tonic-gate { 431*7c478bd9Sstevel@tonic-gate /* Automatic data */ 432*7c478bd9Sstevel@tonic-gate struct devtabent *devtabent; /* * to struct we're making */ 433*7c478bd9Sstevel@tonic-gate struct attrval *prevattrval; /* * to prev attr/val struct */ 434*7c478bd9Sstevel@tonic-gate struct attrval *attrval; /* * to current struct */ 435*7c478bd9Sstevel@tonic-gate char **pp; /* Ptr into list of ptrs */ 436*7c478bd9Sstevel@tonic-gate char *peq; /* Ptr to '=' in string */ 437*7c478bd9Sstevel@tonic-gate char *val; /* Ptr to space for value */ 438*7c478bd9Sstevel@tonic-gate char *name; /* Ptr to space for name */ 439*7c478bd9Sstevel@tonic-gate ssize_t len; /* Length of name */ 440*7c478bd9Sstevel@tonic-gate int noerr; /* TRUE if all's well */ 441*7c478bd9Sstevel@tonic-gate int found; /* TRUE the attr is found */ 442*7c478bd9Sstevel@tonic-gate 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate /* No problems (yet) */ 445*7c478bd9Sstevel@tonic-gate noerr = TRUE; 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate /* Get space for the structure */ 448*7c478bd9Sstevel@tonic-gate if (devtabent = malloc(sizeof (struct devtabent))) { 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate /* Fill in default values */ 451*7c478bd9Sstevel@tonic-gate if (devtabent->alias = malloc(strlen(alias)+1)) { 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate (void) strcpy(devtabent->alias, alias); /* alias */ 454*7c478bd9Sstevel@tonic-gate devtabent->comment = FALSE; /* data rec */ 455*7c478bd9Sstevel@tonic-gate devtabent->cdevice = NULL; /* cdevice */ 456*7c478bd9Sstevel@tonic-gate devtabent->bdevice = NULL; /* bdevice */ 457*7c478bd9Sstevel@tonic-gate devtabent->pathname = NULL; /* pathname */ 458*7c478bd9Sstevel@tonic-gate devtabent->attrstr = NULL; /* string */ 459*7c478bd9Sstevel@tonic-gate devtabent->attrlist = NULL; /* attr list */ 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate /* Add attributes to the structure */ 462*7c478bd9Sstevel@tonic-gate prevattrval = NULL; 463*7c478bd9Sstevel@tonic-gate if ((pp = attrlist) != NULL) 464*7c478bd9Sstevel@tonic-gate while (*pp && noerr) { 465*7c478bd9Sstevel@tonic-gate 466*7c478bd9Sstevel@tonic-gate /* Valid attr=value pair? */ 467*7c478bd9Sstevel@tonic-gate if (((peq = strchr(*pp, '=')) != NULL) && 468*7c478bd9Sstevel@tonic-gate ((len = peq - *pp) > 0)) { 469*7c478bd9Sstevel@tonic-gate 470*7c478bd9Sstevel@tonic-gate /* Get space for the value */ 471*7c478bd9Sstevel@tonic-gate if (val = malloc(strlen(peq))) { 472*7c478bd9Sstevel@tonic-gate (void) strcpy(val, peq+1); /* Copy it */ 473*7c478bd9Sstevel@tonic-gate 474*7c478bd9Sstevel@tonic-gate /* Get space for attribute name */ 475*7c478bd9Sstevel@tonic-gate if (name = malloc((size_t)(len + 1))) { 476*7c478bd9Sstevel@tonic-gate (void) strncpy(name, *pp, (size_t)len); 477*7c478bd9Sstevel@tonic-gate *(name+len) = '\0'; 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate /* Specifying the alias? If so, ERROR */ 480*7c478bd9Sstevel@tonic-gate if (strcmp(name, DTAB_ALIAS) == 0) { 481*7c478bd9Sstevel@tonic-gate noerr = FALSE; 482*7c478bd9Sstevel@tonic-gate free(name); 483*7c478bd9Sstevel@tonic-gate free(val); 484*7c478bd9Sstevel@tonic-gate errno = EINVAL; 485*7c478bd9Sstevel@tonic-gate } 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate /* Specifying the char device path? */ 488*7c478bd9Sstevel@tonic-gate else if (strcmp(name, DTAB_CDEVICE) == 0) { 489*7c478bd9Sstevel@tonic-gate if (!devtabent->cdevice) { 490*7c478bd9Sstevel@tonic-gate if (val[0] != '/') { 491*7c478bd9Sstevel@tonic-gate noerr = FALSE; 492*7c478bd9Sstevel@tonic-gate free(name); 493*7c478bd9Sstevel@tonic-gate free(val); 494*7c478bd9Sstevel@tonic-gate errno = ENXIO; 495*7c478bd9Sstevel@tonic-gate } else { 496*7c478bd9Sstevel@tonic-gate devtabent->cdevice = val; 497*7c478bd9Sstevel@tonic-gate free(name); 498*7c478bd9Sstevel@tonic-gate } 499*7c478bd9Sstevel@tonic-gate } else { 500*7c478bd9Sstevel@tonic-gate noerr = FALSE; 501*7c478bd9Sstevel@tonic-gate free(name); 502*7c478bd9Sstevel@tonic-gate free(val); 503*7c478bd9Sstevel@tonic-gate errno = EAGAIN; 504*7c478bd9Sstevel@tonic-gate } 505*7c478bd9Sstevel@tonic-gate } 506*7c478bd9Sstevel@tonic-gate 507*7c478bd9Sstevel@tonic-gate /* Specifying the block device path? */ 508*7c478bd9Sstevel@tonic-gate else if (strcmp(name, DTAB_BDEVICE) == 0) { 509*7c478bd9Sstevel@tonic-gate if (!devtabent->bdevice) { 510*7c478bd9Sstevel@tonic-gate if (val[0] != '/') { 511*7c478bd9Sstevel@tonic-gate noerr = FALSE; 512*7c478bd9Sstevel@tonic-gate free(name); 513*7c478bd9Sstevel@tonic-gate free(val); 514*7c478bd9Sstevel@tonic-gate errno = ENXIO; 515*7c478bd9Sstevel@tonic-gate } else { 516*7c478bd9Sstevel@tonic-gate devtabent->bdevice = val; 517*7c478bd9Sstevel@tonic-gate free(name); 518*7c478bd9Sstevel@tonic-gate } 519*7c478bd9Sstevel@tonic-gate } else { 520*7c478bd9Sstevel@tonic-gate noerr = FALSE; 521*7c478bd9Sstevel@tonic-gate free(name); 522*7c478bd9Sstevel@tonic-gate free(val); 523*7c478bd9Sstevel@tonic-gate errno = EAGAIN; 524*7c478bd9Sstevel@tonic-gate } 525*7c478bd9Sstevel@tonic-gate } 526*7c478bd9Sstevel@tonic-gate 527*7c478bd9Sstevel@tonic-gate /* Specifying the pathname (generic)? */ 528*7c478bd9Sstevel@tonic-gate else if (strcmp(name, DTAB_PATHNAME) == 0) { 529*7c478bd9Sstevel@tonic-gate if (!devtabent->pathname) { 530*7c478bd9Sstevel@tonic-gate if (val[0] != '/') { 531*7c478bd9Sstevel@tonic-gate noerr = FALSE; 532*7c478bd9Sstevel@tonic-gate free(name); 533*7c478bd9Sstevel@tonic-gate free(val); 534*7c478bd9Sstevel@tonic-gate errno = ENXIO; 535*7c478bd9Sstevel@tonic-gate } else { 536*7c478bd9Sstevel@tonic-gate devtabent->pathname = val; 537*7c478bd9Sstevel@tonic-gate free(name); 538*7c478bd9Sstevel@tonic-gate } 539*7c478bd9Sstevel@tonic-gate } else { 540*7c478bd9Sstevel@tonic-gate noerr = FALSE; 541*7c478bd9Sstevel@tonic-gate free(name); 542*7c478bd9Sstevel@tonic-gate free(val); 543*7c478bd9Sstevel@tonic-gate errno = EAGAIN; 544*7c478bd9Sstevel@tonic-gate } 545*7c478bd9Sstevel@tonic-gate } 546*7c478bd9Sstevel@tonic-gate 547*7c478bd9Sstevel@tonic-gate /* Some other attribute */ 548*7c478bd9Sstevel@tonic-gate else { 549*7c478bd9Sstevel@tonic-gate found = FALSE; 550*7c478bd9Sstevel@tonic-gate if ((attrval = devtabent->attrlist) != NULL) 551*7c478bd9Sstevel@tonic-gate do { 552*7c478bd9Sstevel@tonic-gate if (strcmp(attrval->attr, 553*7c478bd9Sstevel@tonic-gate name) == 0) { 554*7c478bd9Sstevel@tonic-gate 555*7c478bd9Sstevel@tonic-gate noerr = FALSE; 556*7c478bd9Sstevel@tonic-gate free(name); 557*7c478bd9Sstevel@tonic-gate free(val); 558*7c478bd9Sstevel@tonic-gate errno = EAGAIN; 559*7c478bd9Sstevel@tonic-gate } 560*7c478bd9Sstevel@tonic-gate } while (!found && noerr && 561*7c478bd9Sstevel@tonic-gate (attrval = attrval->next)); 562*7c478bd9Sstevel@tonic-gate 563*7c478bd9Sstevel@tonic-gate if (!found && noerr) { 564*7c478bd9Sstevel@tonic-gate 565*7c478bd9Sstevel@tonic-gate /* Get space for attr/val structure */ 566*7c478bd9Sstevel@tonic-gate if (attrval = 567*7c478bd9Sstevel@tonic-gate malloc(sizeof (struct attrval))) { 568*7c478bd9Sstevel@tonic-gate 569*7c478bd9Sstevel@tonic-gate /* Fill attr/val structure */ 570*7c478bd9Sstevel@tonic-gate attrval->attr = name; 571*7c478bd9Sstevel@tonic-gate attrval->val = val; 572*7c478bd9Sstevel@tonic-gate attrval->next = NULL; 573*7c478bd9Sstevel@tonic-gate 574*7c478bd9Sstevel@tonic-gate /* 575*7c478bd9Sstevel@tonic-gate * Link into the list of attributes 576*7c478bd9Sstevel@tonic-gate */ 577*7c478bd9Sstevel@tonic-gate if (prevattrval) 578*7c478bd9Sstevel@tonic-gate prevattrval->next = attrval; 579*7c478bd9Sstevel@tonic-gate else devtabent->attrlist = attrval; 580*7c478bd9Sstevel@tonic-gate prevattrval = attrval; 581*7c478bd9Sstevel@tonic-gate 582*7c478bd9Sstevel@tonic-gate } else { 583*7c478bd9Sstevel@tonic-gate /* malloc() for attrval failed */ 584*7c478bd9Sstevel@tonic-gate noerr = FALSE; 585*7c478bd9Sstevel@tonic-gate free(name); 586*7c478bd9Sstevel@tonic-gate free(val); 587*7c478bd9Sstevel@tonic-gate } 588*7c478bd9Sstevel@tonic-gate } 589*7c478bd9Sstevel@tonic-gate } /* End else (some other attribute) */ 590*7c478bd9Sstevel@tonic-gate 591*7c478bd9Sstevel@tonic-gate } else { /* malloc() for attribute name failed */ 592*7c478bd9Sstevel@tonic-gate noerr = FALSE; 593*7c478bd9Sstevel@tonic-gate free(val); 594*7c478bd9Sstevel@tonic-gate } 595*7c478bd9Sstevel@tonic-gate 596*7c478bd9Sstevel@tonic-gate } else noerr = FALSE; /* Malloc() for "val" failed */ 597*7c478bd9Sstevel@tonic-gate 598*7c478bd9Sstevel@tonic-gate /* If we saw an error, free structure, returning NULL */ 599*7c478bd9Sstevel@tonic-gate if (!noerr) { 600*7c478bd9Sstevel@tonic-gate _freedevtabent(devtabent); 601*7c478bd9Sstevel@tonic-gate devtabent = NULL; 602*7c478bd9Sstevel@tonic-gate } 603*7c478bd9Sstevel@tonic-gate 604*7c478bd9Sstevel@tonic-gate } /* Ignore invalid attr=val pair */ 605*7c478bd9Sstevel@tonic-gate 606*7c478bd9Sstevel@tonic-gate if (noerr) pp++; 607*7c478bd9Sstevel@tonic-gate 608*7c478bd9Sstevel@tonic-gate } /* End attribute processing loop */ 609*7c478bd9Sstevel@tonic-gate 610*7c478bd9Sstevel@tonic-gate } else { /* malloc() failed */ 611*7c478bd9Sstevel@tonic-gate free(devtabent); 612*7c478bd9Sstevel@tonic-gate devtabent = NULL; 613*7c478bd9Sstevel@tonic-gate } 614*7c478bd9Sstevel@tonic-gate } 615*7c478bd9Sstevel@tonic-gate 616*7c478bd9Sstevel@tonic-gate /* Finished */ 617*7c478bd9Sstevel@tonic-gate return (devtabent); 618*7c478bd9Sstevel@tonic-gate } 619*7c478bd9Sstevel@tonic-gate 620*7c478bd9Sstevel@tonic-gate /* 621*7c478bd9Sstevel@tonic-gate * int _putdevtabrec(stream, rec) 622*7c478bd9Sstevel@tonic-gate * FILE *stream 623*7c478bd9Sstevel@tonic-gate * struct devtabent *rec 624*7c478bd9Sstevel@tonic-gate * 625*7c478bd9Sstevel@tonic-gate * Write a device table record containing the information in the struct 626*7c478bd9Sstevel@tonic-gate * devtab structure <rec> to the current position of the standard I/O 627*7c478bd9Sstevel@tonic-gate * stream <stream>. 628*7c478bd9Sstevel@tonic-gate * 629*7c478bd9Sstevel@tonic-gate * Arguments: 630*7c478bd9Sstevel@tonic-gate * stream The stream to write to 631*7c478bd9Sstevel@tonic-gate * rec The structure containing the information to write 632*7c478bd9Sstevel@tonic-gate * 633*7c478bd9Sstevel@tonic-gate * Returns: int 634*7c478bd9Sstevel@tonic-gate * The number of characters written or EOF if there was some error. 635*7c478bd9Sstevel@tonic-gate */ 636*7c478bd9Sstevel@tonic-gate 637*7c478bd9Sstevel@tonic-gate int 638*7c478bd9Sstevel@tonic-gate _putdevtabrec( 639*7c478bd9Sstevel@tonic-gate FILE *stream, /* Stream to which to write */ 640*7c478bd9Sstevel@tonic-gate struct devtabent *rec) /* Record to write */ 641*7c478bd9Sstevel@tonic-gate { 642*7c478bd9Sstevel@tonic-gate /* Automatic Data */ 643*7c478bd9Sstevel@tonic-gate struct attrval *attrval; /* Ptr to attr/val pair */ 644*7c478bd9Sstevel@tonic-gate char *buf; /* Allocated buffer */ 645*7c478bd9Sstevel@tonic-gate char *p; /* Temp char pointer */ 646*7c478bd9Sstevel@tonic-gate int count; /* Number of chars written */ 647*7c478bd9Sstevel@tonic-gate size_t size = 0; /* Size of needed buffer */ 648*7c478bd9Sstevel@tonic-gate 649*7c478bd9Sstevel@tonic-gate 650*7c478bd9Sstevel@tonic-gate /* Comment or data record? */ 651*7c478bd9Sstevel@tonic-gate if (rec->comment) { 652*7c478bd9Sstevel@tonic-gate 653*7c478bd9Sstevel@tonic-gate /* 654*7c478bd9Sstevel@tonic-gate * Record is a comment 655*7c478bd9Sstevel@tonic-gate */ 656*7c478bd9Sstevel@tonic-gate 657*7c478bd9Sstevel@tonic-gate /* Copy (escaping chars) record into temp buffer */ 658*7c478bd9Sstevel@tonic-gate size = (strlen(rec->attrstr)*2)+1; /* Max rec size */ 659*7c478bd9Sstevel@tonic-gate if (buf = malloc(size+1)) { 660*7c478bd9Sstevel@tonic-gate /* Alloc space */ 661*7c478bd9Sstevel@tonic-gate p = strcatesc(buf, rec->attrstr); /* Copy "escaped" */ 662*7c478bd9Sstevel@tonic-gate *(p-2) = '\n'; /* Unescape last \n */ 663*7c478bd9Sstevel@tonic-gate *(p-1) = '\0'; /* Terminate string */ 664*7c478bd9Sstevel@tonic-gate 665*7c478bd9Sstevel@tonic-gate /* Write the record */ 666*7c478bd9Sstevel@tonic-gate count = fputs(buf, stream); 667*7c478bd9Sstevel@tonic-gate free(buf); 668*7c478bd9Sstevel@tonic-gate 669*7c478bd9Sstevel@tonic-gate } else count = EOF; /* malloc() failed */ 670*7c478bd9Sstevel@tonic-gate } 671*7c478bd9Sstevel@tonic-gate 672*7c478bd9Sstevel@tonic-gate else { 673*7c478bd9Sstevel@tonic-gate 674*7c478bd9Sstevel@tonic-gate /* 675*7c478bd9Sstevel@tonic-gate * Record is a data record 676*7c478bd9Sstevel@tonic-gate */ 677*7c478bd9Sstevel@tonic-gate 678*7c478bd9Sstevel@tonic-gate /* 679*7c478bd9Sstevel@tonic-gate * Figure out maximum amount of space you're going to need. 680*7c478bd9Sstevel@tonic-gate * (Assume every escapable character is escaped to determine the 681*7c478bd9Sstevel@tonic-gate * maximum size needed) 682*7c478bd9Sstevel@tonic-gate */ 683*7c478bd9Sstevel@tonic-gate 684*7c478bd9Sstevel@tonic-gate if (rec->cdevice) 685*7c478bd9Sstevel@tonic-gate size += (strlen(rec->cdevice)*2) + 1; /* cdevice: */ 686*7c478bd9Sstevel@tonic-gate if (rec->bdevice) 687*7c478bd9Sstevel@tonic-gate size += (strlen(rec->bdevice)*2) + 1; /* bdevice: */ 688*7c478bd9Sstevel@tonic-gate if (rec->pathname) 689*7c478bd9Sstevel@tonic-gate size += (strlen(rec->pathname)*2) + 1; /* pathname: */ 690*7c478bd9Sstevel@tonic-gate if ((attrval = rec->attrlist) != NULL) do { /* Attributes */ 691*7c478bd9Sstevel@tonic-gate if (attrval->attr) 692*7c478bd9Sstevel@tonic-gate size += (strlen(attrval->attr)*2); /* attr */ 693*7c478bd9Sstevel@tonic-gate if (attrval->val) { 694*7c478bd9Sstevel@tonic-gate /* val & '="" ' or val & '=""\n' */ 695*7c478bd9Sstevel@tonic-gate size += (strlen(attrval->val)*2) +4; 696*7c478bd9Sstevel@tonic-gate } 697*7c478bd9Sstevel@tonic-gate } while ((attrval = attrval->next) != NULL); /* Next attr/val */ 698*7c478bd9Sstevel@tonic-gate else size++; /* Else make room for trailing '\n' */ 699*7c478bd9Sstevel@tonic-gate 700*7c478bd9Sstevel@tonic-gate /* Alloc space for "escaped" record */ 701*7c478bd9Sstevel@tonic-gate if (buf = malloc(size+1)) { 702*7c478bd9Sstevel@tonic-gate 703*7c478bd9Sstevel@tonic-gate /* Initializations */ 704*7c478bd9Sstevel@tonic-gate p = buf; 705*7c478bd9Sstevel@tonic-gate 706*7c478bd9Sstevel@tonic-gate /* Write the alias ("alias" attribute) */ 707*7c478bd9Sstevel@tonic-gate p = strcatesc(p, rec->alias); 708*7c478bd9Sstevel@tonic-gate *p++ = ':'; 709*7c478bd9Sstevel@tonic-gate 710*7c478bd9Sstevel@tonic-gate /* Write the character device ("cdevice" attribute) */ 711*7c478bd9Sstevel@tonic-gate if (rec->cdevice) p = strcatesc(p, rec->cdevice); 712*7c478bd9Sstevel@tonic-gate *p++ = ':'; 713*7c478bd9Sstevel@tonic-gate 714*7c478bd9Sstevel@tonic-gate /* Write the block device ("bdevice" attribute) */ 715*7c478bd9Sstevel@tonic-gate if (rec->bdevice) p = strcatesc(p, rec->bdevice); 716*7c478bd9Sstevel@tonic-gate *p++ = ':'; 717*7c478bd9Sstevel@tonic-gate 718*7c478bd9Sstevel@tonic-gate /* Write the pathname ("pathname" attribute) */ 719*7c478bd9Sstevel@tonic-gate if (rec->pathname) p = strcatesc(p, rec->pathname); 720*7c478bd9Sstevel@tonic-gate *p++ = ':'; 721*7c478bd9Sstevel@tonic-gate 722*7c478bd9Sstevel@tonic-gate /* Write the rest of the attributes */ 723*7c478bd9Sstevel@tonic-gate if ((attrval = rec->attrlist) != NULL) 724*7c478bd9Sstevel@tonic-gate do { 725*7c478bd9Sstevel@tonic-gate p = strcatesc(p, attrval->attr); 726*7c478bd9Sstevel@tonic-gate *p++ = '='; 727*7c478bd9Sstevel@tonic-gate *p++ = '"'; 728*7c478bd9Sstevel@tonic-gate p = strcatesc(p, attrval->val); 729*7c478bd9Sstevel@tonic-gate *p++ = '"'; 730*7c478bd9Sstevel@tonic-gate if ((attrval = attrval->next) != NULL) 731*7c478bd9Sstevel@tonic-gate *p++ = ' '; 732*7c478bd9Sstevel@tonic-gate } while (attrval); 733*7c478bd9Sstevel@tonic-gate 734*7c478bd9Sstevel@tonic-gate /* Terminate the record */ 735*7c478bd9Sstevel@tonic-gate *p++ = '\n'; 736*7c478bd9Sstevel@tonic-gate *p = '\0'; 737*7c478bd9Sstevel@tonic-gate 738*7c478bd9Sstevel@tonic-gate /* Write the record */ 739*7c478bd9Sstevel@tonic-gate count = fputs(buf, stream); 740*7c478bd9Sstevel@tonic-gate free(buf); 741*7c478bd9Sstevel@tonic-gate } else count = EOF; /* malloc() failed */ 742*7c478bd9Sstevel@tonic-gate } 743*7c478bd9Sstevel@tonic-gate 744*7c478bd9Sstevel@tonic-gate /* Finished */ 745*7c478bd9Sstevel@tonic-gate return (count); 746*7c478bd9Sstevel@tonic-gate } 747*7c478bd9Sstevel@tonic-gate 748*7c478bd9Sstevel@tonic-gate /* 749*7c478bd9Sstevel@tonic-gate * int _adddevtabrec(alias, attrval) 750*7c478bd9Sstevel@tonic-gate * char *alias 751*7c478bd9Sstevel@tonic-gate * char **attrval 752*7c478bd9Sstevel@tonic-gate * 753*7c478bd9Sstevel@tonic-gate * This function adds a record to the device table. That record will 754*7c478bd9Sstevel@tonic-gate * have the alias <alias> and will have the attributes described in 755*7c478bd9Sstevel@tonic-gate * the list referenced by <attrval>. 756*7c478bd9Sstevel@tonic-gate * 757*7c478bd9Sstevel@tonic-gate * It always adds the record to the end of the table. 758*7c478bd9Sstevel@tonic-gate * 759*7c478bd9Sstevel@tonic-gate * Arguments: 760*7c478bd9Sstevel@tonic-gate * alias The alias of the device whose description is being 761*7c478bd9Sstevel@tonic-gate * added to the device table. 762*7c478bd9Sstevel@tonic-gate * attrval The pointer to the first item of a list of attributes 763*7c478bd9Sstevel@tonic-gate * defining the device whose description is being added. 764*7c478bd9Sstevel@tonic-gate * (This value may be (char **) NULL). 765*7c478bd9Sstevel@tonic-gate * 766*7c478bd9Sstevel@tonic-gate * Returns: int 767*7c478bd9Sstevel@tonic-gate * TRUE if successful, FALSE with errno set otherwise. 768*7c478bd9Sstevel@tonic-gate */ 769*7c478bd9Sstevel@tonic-gate 770*7c478bd9Sstevel@tonic-gate int 771*7c478bd9Sstevel@tonic-gate _adddevtabrec( 772*7c478bd9Sstevel@tonic-gate char *alias, /* Alias to add to the device table */ 773*7c478bd9Sstevel@tonic-gate char **attrval) /* Attributes for that device */ 774*7c478bd9Sstevel@tonic-gate { 775*7c478bd9Sstevel@tonic-gate /* Automatic data */ 776*7c478bd9Sstevel@tonic-gate struct devtabent *devtabent; /* Ptr to dev tab entry */ 777*7c478bd9Sstevel@tonic-gate int olderrno; /* Errno on entry */ 778*7c478bd9Sstevel@tonic-gate int noerr; /* FLAG, TRUE if all's well */ 779*7c478bd9Sstevel@tonic-gate 780*7c478bd9Sstevel@tonic-gate /* Validate the device alias. Error (EINVAL) if it's not valid */ 781*7c478bd9Sstevel@tonic-gate if (!_validalias(alias)) { 782*7c478bd9Sstevel@tonic-gate errno = EINVAL; 783*7c478bd9Sstevel@tonic-gate return (FALSE); 784*7c478bd9Sstevel@tonic-gate } 785*7c478bd9Sstevel@tonic-gate 786*7c478bd9Sstevel@tonic-gate /* 787*7c478bd9Sstevel@tonic-gate * Lock the device table. This only returns if the table is locked or 788*7c478bd9Sstevel@tonic-gate * some error occurred. It waits until the table is available. 789*7c478bd9Sstevel@tonic-gate */ 790*7c478bd9Sstevel@tonic-gate if (!lkdevtab("a+", F_WRLCK)) 791*7c478bd9Sstevel@tonic-gate return (FALSE); 792*7c478bd9Sstevel@tonic-gate 793*7c478bd9Sstevel@tonic-gate /* Make sure that the alias isn't already in the table */ 794*7c478bd9Sstevel@tonic-gate noerr = TRUE; 795*7c478bd9Sstevel@tonic-gate olderrno = errno; 796*7c478bd9Sstevel@tonic-gate if (devtabent = _getdevrec(alias)) { 797*7c478bd9Sstevel@tonic-gate 798*7c478bd9Sstevel@tonic-gate /* The alias is already in the table */ 799*7c478bd9Sstevel@tonic-gate _freedevtabent(devtabent); /* Free device table info */ 800*7c478bd9Sstevel@tonic-gate errno = EEXIST; /* Set errno, entry exists */ 801*7c478bd9Sstevel@tonic-gate noerr = FALSE; /* All's not well */ 802*7c478bd9Sstevel@tonic-gate } else if ((errno == ENOENT) || (errno == ENODEV)) { 803*7c478bd9Sstevel@tonic-gate 804*7c478bd9Sstevel@tonic-gate /* The alias wasn't in the table or there wasn't a table. */ 805*7c478bd9Sstevel@tonic-gate 806*7c478bd9Sstevel@tonic-gate errno = olderrno; /* Reset errno */ 807*7c478bd9Sstevel@tonic-gate 808*7c478bd9Sstevel@tonic-gate /* Build a struct devtabent that describes the new alias */ 809*7c478bd9Sstevel@tonic-gate if (devtabent = mkdevtabent(alias, attrval)) { 810*7c478bd9Sstevel@tonic-gate 811*7c478bd9Sstevel@tonic-gate /* Position to the end of the existing table */ 812*7c478bd9Sstevel@tonic-gate if (fseek(oam_devtab, 0, SEEK_END) == 0) 813*7c478bd9Sstevel@tonic-gate 814*7c478bd9Sstevel@tonic-gate /* Write the new entry */ 815*7c478bd9Sstevel@tonic-gate noerr = (_putdevtabrec(oam_devtab, devtabent) != EOF); 816*7c478bd9Sstevel@tonic-gate 817*7c478bd9Sstevel@tonic-gate /* Free the info we just wrote */ 818*7c478bd9Sstevel@tonic-gate _freedevtabent(devtabent); 819*7c478bd9Sstevel@tonic-gate 820*7c478bd9Sstevel@tonic-gate } else noerr = FALSE; /* mkdevtabent() failed */ 821*7c478bd9Sstevel@tonic-gate } else noerr = FALSE; /* Some odd error, _devtab */ 822*7c478bd9Sstevel@tonic-gate 823*7c478bd9Sstevel@tonic-gate /* Unlock and close the device table */ 824*7c478bd9Sstevel@tonic-gate (void) unlkdevtab(); 825*7c478bd9Sstevel@tonic-gate 826*7c478bd9Sstevel@tonic-gate /* Fini */ 827*7c478bd9Sstevel@tonic-gate return (noerr); 828*7c478bd9Sstevel@tonic-gate } 829*7c478bd9Sstevel@tonic-gate 830*7c478bd9Sstevel@tonic-gate /* 831*7c478bd9Sstevel@tonic-gate * int _moddevtabrec(device, attrval) 832*7c478bd9Sstevel@tonic-gate * char *device 833*7c478bd9Sstevel@tonic-gate * char **attrval 834*7c478bd9Sstevel@tonic-gate * 835*7c478bd9Sstevel@tonic-gate * This function modifies the description for the specified device 836*7c478bd9Sstevel@tonic-gate * so that it has the attributes and values as specified in the 837*7c478bd9Sstevel@tonic-gate * given list. 838*7c478bd9Sstevel@tonic-gate * 839*7c478bd9Sstevel@tonic-gate * Arguments: 840*7c478bd9Sstevel@tonic-gate * device The name of the device whose description 841*7c478bd9Sstevel@tonic-gate * is being modified 842*7c478bd9Sstevel@tonic-gate * attrval The first attr/val value in the list (attr=val) of 843*7c478bd9Sstevel@tonic-gate * the attributes that are to change 844*7c478bd9Sstevel@tonic-gate * 845*7c478bd9Sstevel@tonic-gate * Returns: int 846*7c478bd9Sstevel@tonic-gate * TRUE if all went well, FALSE with errno set otherwise 847*7c478bd9Sstevel@tonic-gate */ 848*7c478bd9Sstevel@tonic-gate 849*7c478bd9Sstevel@tonic-gate int 850*7c478bd9Sstevel@tonic-gate _moddevtabrec( 851*7c478bd9Sstevel@tonic-gate char *device, /* Device to modify */ 852*7c478bd9Sstevel@tonic-gate char **attrval) /* Attributes to add or change */ 853*7c478bd9Sstevel@tonic-gate { 854*7c478bd9Sstevel@tonic-gate /* Automatic data */ 855*7c478bd9Sstevel@tonic-gate FILE *fd; /* File ptr, new device table */ 856*7c478bd9Sstevel@tonic-gate struct devtabent *ent; /* Device's current description */ 857*7c478bd9Sstevel@tonic-gate struct devtabent *chg; /* Changes to make to description */ 858*7c478bd9Sstevel@tonic-gate struct attrval *new; /* New attribute/value desc */ 859*7c478bd9Sstevel@tonic-gate struct attrval *old; /* Old attribute/value desc */ 860*7c478bd9Sstevel@tonic-gate struct attrval *newnew; /* Next "new" value to look at */ 861*7c478bd9Sstevel@tonic-gate struct attrval *prevnew; /* Previous item in the 'new' list */ 862*7c478bd9Sstevel@tonic-gate char *tname; /* name of temp devtab file */ 863*7c478bd9Sstevel@tonic-gate int noerr; /* FLAG, TRUE if all's well */ 864*7c478bd9Sstevel@tonic-gate int found; /* FLAG, TRUE if attr found for dev */ 865*7c478bd9Sstevel@tonic-gate 866*7c478bd9Sstevel@tonic-gate /* Lock the device table */ 867*7c478bd9Sstevel@tonic-gate if (!lkdevtab("r", F_WRLCK)) 868*7c478bd9Sstevel@tonic-gate return (FALSE); 869*7c478bd9Sstevel@tonic-gate 870*7c478bd9Sstevel@tonic-gate /* No problems (so far) */ 871*7c478bd9Sstevel@tonic-gate noerr = TRUE; 872*7c478bd9Sstevel@tonic-gate 873*7c478bd9Sstevel@tonic-gate /* Get the entry to modify */ 874*7c478bd9Sstevel@tonic-gate if (ent = _getdevrec(device)) { 875*7c478bd9Sstevel@tonic-gate 876*7c478bd9Sstevel@tonic-gate /* Build a structure describing the changes */ 877*7c478bd9Sstevel@tonic-gate if (chg = mkdevtabent(device, attrval)) { 878*7c478bd9Sstevel@tonic-gate 879*7c478bd9Sstevel@tonic-gate /* If the "cdevice" field is specified, change it */ 880*7c478bd9Sstevel@tonic-gate if (chg->cdevice) { 881*7c478bd9Sstevel@tonic-gate if (ent->cdevice) free(ent->cdevice); 882*7c478bd9Sstevel@tonic-gate ent->cdevice = chg->cdevice; 883*7c478bd9Sstevel@tonic-gate chg->cdevice = NULL; 884*7c478bd9Sstevel@tonic-gate } 885*7c478bd9Sstevel@tonic-gate 886*7c478bd9Sstevel@tonic-gate /* If the "bdevice" field is specified, change it */ 887*7c478bd9Sstevel@tonic-gate if (chg->bdevice) { 888*7c478bd9Sstevel@tonic-gate if (ent->bdevice) free(ent->bdevice); 889*7c478bd9Sstevel@tonic-gate ent->bdevice = chg->bdevice; 890*7c478bd9Sstevel@tonic-gate chg->bdevice = NULL; 891*7c478bd9Sstevel@tonic-gate } 892*7c478bd9Sstevel@tonic-gate 893*7c478bd9Sstevel@tonic-gate /* If the "pathname" field is specified, change it */ 894*7c478bd9Sstevel@tonic-gate if (chg->pathname) { 895*7c478bd9Sstevel@tonic-gate if (ent->pathname) free(ent->pathname); 896*7c478bd9Sstevel@tonic-gate ent->pathname = chg->pathname; 897*7c478bd9Sstevel@tonic-gate chg->pathname = NULL; 898*7c478bd9Sstevel@tonic-gate } 899*7c478bd9Sstevel@tonic-gate 900*7c478bd9Sstevel@tonic-gate /* Change the other attributes (if any) */ 901*7c478bd9Sstevel@tonic-gate if (ent->attrlist) { 902*7c478bd9Sstevel@tonic-gate prevnew = NULL; 903*7c478bd9Sstevel@tonic-gate if ((new = chg->attrlist) != NULL) do { 904*7c478bd9Sstevel@tonic-gate 905*7c478bd9Sstevel@tonic-gate found = FALSE; 906*7c478bd9Sstevel@tonic-gate for (old = ent->attrlist; !found && old; 907*7c478bd9Sstevel@tonic-gate old = old->next) { 908*7c478bd9Sstevel@tonic-gate if (strcmp(old->attr, new->attr) == 0) { 909*7c478bd9Sstevel@tonic-gate found = TRUE; 910*7c478bd9Sstevel@tonic-gate free(old->val); 911*7c478bd9Sstevel@tonic-gate old->val = new->val; 912*7c478bd9Sstevel@tonic-gate new->val = NULL; 913*7c478bd9Sstevel@tonic-gate } 914*7c478bd9Sstevel@tonic-gate } /* Loop through the existing attribute list */ 915*7c478bd9Sstevel@tonic-gate 916*7c478bd9Sstevel@tonic-gate /* 917*7c478bd9Sstevel@tonic-gate * If the attribute wasn't found, add it to the list 918*7c478bd9Sstevel@tonic-gate * of attributes for the device. If it was found, just 919*7c478bd9Sstevel@tonic-gate * bump to the next one and look for it 920*7c478bd9Sstevel@tonic-gate */ 921*7c478bd9Sstevel@tonic-gate 922*7c478bd9Sstevel@tonic-gate if (!found) { 923*7c478bd9Sstevel@tonic-gate 924*7c478bd9Sstevel@tonic-gate /* 925*7c478bd9Sstevel@tonic-gate * Not found. Move attr/val description to the 926*7c478bd9Sstevel@tonic-gate * device's list of attributes 927*7c478bd9Sstevel@tonic-gate */ 928*7c478bd9Sstevel@tonic-gate 929*7c478bd9Sstevel@tonic-gate if (prevnew) prevnew->next = new->next; 930*7c478bd9Sstevel@tonic-gate else chg->attrlist = new->next; 931*7c478bd9Sstevel@tonic-gate newnew = new->next; 932*7c478bd9Sstevel@tonic-gate new->next = ent->attrlist; 933*7c478bd9Sstevel@tonic-gate ent->attrlist = new; 934*7c478bd9Sstevel@tonic-gate new = newnew; 935*7c478bd9Sstevel@tonic-gate } else { 936*7c478bd9Sstevel@tonic-gate 937*7c478bd9Sstevel@tonic-gate /* Attribute changed, bump to the next one */ 938*7c478bd9Sstevel@tonic-gate prevnew = new; 939*7c478bd9Sstevel@tonic-gate new = new->next; 940*7c478bd9Sstevel@tonic-gate } 941*7c478bd9Sstevel@tonic-gate } while (new); /* Loop for each attr to add or modify */ 942*7c478bd9Sstevel@tonic-gate 943*7c478bd9Sstevel@tonic-gate } else { 944*7c478bd9Sstevel@tonic-gate 945*7c478bd9Sstevel@tonic-gate /* Device had no attributes -- add entire list */ 946*7c478bd9Sstevel@tonic-gate ent->attrlist = chg->attrlist; 947*7c478bd9Sstevel@tonic-gate chg->attrlist = NULL; 948*7c478bd9Sstevel@tonic-gate } 949*7c478bd9Sstevel@tonic-gate 950*7c478bd9Sstevel@tonic-gate /* Free the structure containing the changes */ 951*7c478bd9Sstevel@tonic-gate _freedevtabent(chg); 952*7c478bd9Sstevel@tonic-gate 953*7c478bd9Sstevel@tonic-gate } else noerr = FALSE; /* Couldn't build changes struct */ 954*7c478bd9Sstevel@tonic-gate 955*7c478bd9Sstevel@tonic-gate /* If there hasn't been an error (so far), write the new record */ 956*7c478bd9Sstevel@tonic-gate if (noerr) { 957*7c478bd9Sstevel@tonic-gate 958*7c478bd9Sstevel@tonic-gate /* Open the new device table */ 959*7c478bd9Sstevel@tonic-gate if (fd = opennewdevtab(&tname)) { 960*7c478bd9Sstevel@tonic-gate 961*7c478bd9Sstevel@tonic-gate /* 962*7c478bd9Sstevel@tonic-gate * For each entry in the existing table, write that entry 963*7c478bd9Sstevel@tonic-gate * to the new table. If the entry is the one being 964*7c478bd9Sstevel@tonic-gate * modified, write the modified entry instead of the 965*7c478bd9Sstevel@tonic-gate * original entry. 966*7c478bd9Sstevel@tonic-gate */ 967*7c478bd9Sstevel@tonic-gate 968*7c478bd9Sstevel@tonic-gate _setdevtab(); /* Rewind existing table */ 969*7c478bd9Sstevel@tonic-gate chg = ent; /* Remember new record */ 970*7c478bd9Sstevel@tonic-gate while (((ent = _getdevtabent()) != NULL) && noerr) { 971*7c478bd9Sstevel@tonic-gate if (ent->entryno != chg->entryno) 972*7c478bd9Sstevel@tonic-gate noerr = _putdevtabrec(fd, ent) != EOF; 973*7c478bd9Sstevel@tonic-gate else noerr = _putdevtabrec(fd, chg) != EOF; 974*7c478bd9Sstevel@tonic-gate _freedevtabent(ent); 975*7c478bd9Sstevel@tonic-gate } 976*7c478bd9Sstevel@tonic-gate 977*7c478bd9Sstevel@tonic-gate /* 978*7c478bd9Sstevel@tonic-gate * If we successfully generated the new table, make it the 979*7c478bd9Sstevel@tonic-gate * new system device table. Otherwise, just remove the 980*7c478bd9Sstevel@tonic-gate * temporary file we've created. 981*7c478bd9Sstevel@tonic-gate */ 982*7c478bd9Sstevel@tonic-gate 983*7c478bd9Sstevel@tonic-gate if (noerr) { 984*7c478bd9Sstevel@tonic-gate (void) fclose(fd); 985*7c478bd9Sstevel@tonic-gate noerr = mknewdevtab(tname); 986*7c478bd9Sstevel@tonic-gate } else { 987*7c478bd9Sstevel@tonic-gate (void) fclose(fd); 988*7c478bd9Sstevel@tonic-gate (void) rmnewdevtab(tname); 989*7c478bd9Sstevel@tonic-gate } 990*7c478bd9Sstevel@tonic-gate 991*7c478bd9Sstevel@tonic-gate /* Free the changed device structure */ 992*7c478bd9Sstevel@tonic-gate _freedevtabent(chg); 993*7c478bd9Sstevel@tonic-gate 994*7c478bd9Sstevel@tonic-gate } /* if (_opennewdevtab()) */ 995*7c478bd9Sstevel@tonic-gate else noerr = FALSE; 996*7c478bd9Sstevel@tonic-gate 997*7c478bd9Sstevel@tonic-gate } else _freedevtabent(ent); /* if (noerr) */ 998*7c478bd9Sstevel@tonic-gate 999*7c478bd9Sstevel@tonic-gate } else noerr = FALSE; /* Device not found? */ 1000*7c478bd9Sstevel@tonic-gate 1001*7c478bd9Sstevel@tonic-gate /* Finished. Unlock the device table and quit */ 1002*7c478bd9Sstevel@tonic-gate (void) unlkdevtab(); 1003*7c478bd9Sstevel@tonic-gate return (noerr); 1004*7c478bd9Sstevel@tonic-gate } 1005*7c478bd9Sstevel@tonic-gate 1006*7c478bd9Sstevel@tonic-gate /* 1007*7c478bd9Sstevel@tonic-gate * int _rmdevtabrec(device) 1008*7c478bd9Sstevel@tonic-gate * char *device 1009*7c478bd9Sstevel@tonic-gate * 1010*7c478bd9Sstevel@tonic-gate * This function removes the record in the device table for the specified 1011*7c478bd9Sstevel@tonic-gate * device. 1012*7c478bd9Sstevel@tonic-gate * 1013*7c478bd9Sstevel@tonic-gate * Arguments: 1014*7c478bd9Sstevel@tonic-gate * device The device (alias, cdevice, bdevice, pathname, or link to one) 1015*7c478bd9Sstevel@tonic-gate * whose entry is to be removed 1016*7c478bd9Sstevel@tonic-gate * 1017*7c478bd9Sstevel@tonic-gate * Returns: int 1018*7c478bd9Sstevel@tonic-gate * Success indicator: TRUE if successful, FALSE with errno set otherwise. 1019*7c478bd9Sstevel@tonic-gate */ 1020*7c478bd9Sstevel@tonic-gate 1021*7c478bd9Sstevel@tonic-gate int 1022*7c478bd9Sstevel@tonic-gate _rmdevtabrec(char *device) /* Device to remove */ 1023*7c478bd9Sstevel@tonic-gate { 1024*7c478bd9Sstevel@tonic-gate struct devtabent *rment; 1025*7c478bd9Sstevel@tonic-gate struct devtabent *devtabent; 1026*7c478bd9Sstevel@tonic-gate char *tempname; 1027*7c478bd9Sstevel@tonic-gate FILE *fd; 1028*7c478bd9Sstevel@tonic-gate int noerr; 1029*7c478bd9Sstevel@tonic-gate 1030*7c478bd9Sstevel@tonic-gate if (!lkdevtab("r", F_WRLCK)) 1031*7c478bd9Sstevel@tonic-gate return (FALSE); 1032*7c478bd9Sstevel@tonic-gate noerr = TRUE; 1033*7c478bd9Sstevel@tonic-gate if (rment = _getdevrec(device)) { 1034*7c478bd9Sstevel@tonic-gate if (fd = opennewdevtab(&tempname)) { 1035*7c478bd9Sstevel@tonic-gate _setdevtab(); 1036*7c478bd9Sstevel@tonic-gate while (((devtabent = _getdevtabent()) != NULL) && noerr) { 1037*7c478bd9Sstevel@tonic-gate if (devtabent->entryno != rment->entryno) 1038*7c478bd9Sstevel@tonic-gate noerr = _putdevtabrec(fd, devtabent) != EOF; 1039*7c478bd9Sstevel@tonic-gate _freedevtabent(devtabent); 1040*7c478bd9Sstevel@tonic-gate } 1041*7c478bd9Sstevel@tonic-gate if (noerr) { 1042*7c478bd9Sstevel@tonic-gate (void) fclose(fd); 1043*7c478bd9Sstevel@tonic-gate noerr = mknewdevtab(tempname); 1044*7c478bd9Sstevel@tonic-gate } else { 1045*7c478bd9Sstevel@tonic-gate (void) fclose(fd); 1046*7c478bd9Sstevel@tonic-gate (void) rmnewdevtab(tempname); 1047*7c478bd9Sstevel@tonic-gate } 1048*7c478bd9Sstevel@tonic-gate } else noerr = FALSE; 1049*7c478bd9Sstevel@tonic-gate _freedevtabent(rment); 1050*7c478bd9Sstevel@tonic-gate } else noerr = FALSE; 1051*7c478bd9Sstevel@tonic-gate (void) unlkdevtab(); 1052*7c478bd9Sstevel@tonic-gate return (noerr); 1053*7c478bd9Sstevel@tonic-gate } 1054*7c478bd9Sstevel@tonic-gate 1055*7c478bd9Sstevel@tonic-gate /* 1056*7c478bd9Sstevel@tonic-gate * int _rmdevtabattrs(device, attributes, notfounds) 1057*7c478bd9Sstevel@tonic-gate * char *device 1058*7c478bd9Sstevel@tonic-gate * char **attributes 1059*7c478bd9Sstevel@tonic-gate * char ***notfounds 1060*7c478bd9Sstevel@tonic-gate * 1061*7c478bd9Sstevel@tonic-gate * Remove the specified attributes from the specified device. The 1062*7c478bd9Sstevel@tonic-gate * device is specified by <device>, <attributes> is the address of 1063*7c478bd9Sstevel@tonic-gate * the first char * in the list of char * pointing to the attributes 1064*7c478bd9Sstevel@tonic-gate * to remove from the device, and <notfounds> is the address of a 1065*7c478bd9Sstevel@tonic-gate * char ** to put the address of the first element in the malloc()ed 1066*7c478bd9Sstevel@tonic-gate * list of (char *) pointing to requested attributes that were not 1067*7c478bd9Sstevel@tonic-gate * defined for the device <device>. 1068*7c478bd9Sstevel@tonic-gate * 1069*7c478bd9Sstevel@tonic-gate * Arguments: 1070*7c478bd9Sstevel@tonic-gate * device The device from which attributes are to be removed 1071*7c478bd9Sstevel@tonic-gate * attributes The address of the first element in the list of 1072*7c478bd9Sstevel@tonic-gate * attributes to remove. This list is terminated by 1073*7c478bd9Sstevel@tonic-gate * (char *) NULL. 1074*7c478bd9Sstevel@tonic-gate * notfounds The place to put the address of the list of addresses 1075*7c478bd9Sstevel@tonic-gate * referencing the requested attributes that are not 1076*7c478bd9Sstevel@tonic-gate * defined for the specified device. 1077*7c478bd9Sstevel@tonic-gate * 1078*7c478bd9Sstevel@tonic-gate * Returns: int 1079*7c478bd9Sstevel@tonic-gate * TRUE if successful, FALSE with errno set otherwise. 1080*7c478bd9Sstevel@tonic-gate * 1081*7c478bd9Sstevel@tonic-gate * Notes: 1082*7c478bd9Sstevel@tonic-gate * - "alias" may not be undefined 1083*7c478bd9Sstevel@tonic-gate * - "cdevice", "bdevice", and "pathname" are made "null", not really 1084*7c478bd9Sstevel@tonic-gate * undefined 1085*7c478bd9Sstevel@tonic-gate */ 1086*7c478bd9Sstevel@tonic-gate 1087*7c478bd9Sstevel@tonic-gate int 1088*7c478bd9Sstevel@tonic-gate _rmdevtabattrs( 1089*7c478bd9Sstevel@tonic-gate char *device, /* Device to modify */ 1090*7c478bd9Sstevel@tonic-gate char **attributes, /* Attributes to remove */ 1091*7c478bd9Sstevel@tonic-gate char ***notfounds) /* Attributes req'd but not found */ 1092*7c478bd9Sstevel@tonic-gate { 1093*7c478bd9Sstevel@tonic-gate /* Automatics */ 1094*7c478bd9Sstevel@tonic-gate char **pnxt; /* Ptr to next attribute */ 1095*7c478bd9Sstevel@tonic-gate char **pp; /* Ptr to current attr name */ 1096*7c478bd9Sstevel@tonic-gate struct devtabent *modent; /* Entry being modified */ 1097*7c478bd9Sstevel@tonic-gate struct devtabent *devtabent; /* Entry being copied */ 1098*7c478bd9Sstevel@tonic-gate struct attrval *attrval; /* Ptr to attr/val desc */ 1099*7c478bd9Sstevel@tonic-gate struct attrval *prevattrval; /* Ptr to prev attr/val */ 1100*7c478bd9Sstevel@tonic-gate FILE *fd; /* File desc, temp file */ 1101*7c478bd9Sstevel@tonic-gate char *tempname; /* Name of temp file */ 1102*7c478bd9Sstevel@tonic-gate int nattrs; /* Number of attrs to remove */ 1103*7c478bd9Sstevel@tonic-gate int nobaderr; /* TRUE if no fatal error */ 1104*7c478bd9Sstevel@tonic-gate int noerr; /* TRUE if no non-fatal error */ 1105*7c478bd9Sstevel@tonic-gate int found; /* TRUE if attribute found */ 1106*7c478bd9Sstevel@tonic-gate int nonotfounds; /* TRUE if no attrs not fount */ 1107*7c478bd9Sstevel@tonic-gate 1108*7c478bd9Sstevel@tonic-gate 1109*7c478bd9Sstevel@tonic-gate /* Initializations */ 1110*7c478bd9Sstevel@tonic-gate nobaderr = TRUE; 1111*7c478bd9Sstevel@tonic-gate noerr = TRUE; 1112*7c478bd9Sstevel@tonic-gate 1113*7c478bd9Sstevel@tonic-gate /* Count attributes to remove -- make sure "alias" isn't specified */ 1114*7c478bd9Sstevel@tonic-gate for (pp = attributes, nattrs = 0; *pp; pp++, nattrs++) 1115*7c478bd9Sstevel@tonic-gate if (strcmp(*pp, DTAB_ALIAS) == 0) { 1116*7c478bd9Sstevel@tonic-gate *notfounds = NULL; 1117*7c478bd9Sstevel@tonic-gate errno = EINVAL; 1118*7c478bd9Sstevel@tonic-gate return (FALSE); 1119*7c478bd9Sstevel@tonic-gate } 1120*7c478bd9Sstevel@tonic-gate 1121*7c478bd9Sstevel@tonic-gate /* Lock the device table */ 1122*7c478bd9Sstevel@tonic-gate if (!lkdevtab("r", F_WRLCK)) 1123*7c478bd9Sstevel@tonic-gate return (FALSE); 1124*7c478bd9Sstevel@tonic-gate 1125*7c478bd9Sstevel@tonic-gate /* Is there a record for the requested device? */ 1126*7c478bd9Sstevel@tonic-gate if (modent = _getdevrec(device)) { 1127*7c478bd9Sstevel@tonic-gate 1128*7c478bd9Sstevel@tonic-gate /* Record found. Try to modify it */ 1129*7c478bd9Sstevel@tonic-gate nonotfounds = TRUE; 1130*7c478bd9Sstevel@tonic-gate 1131*7c478bd9Sstevel@tonic-gate /* For each of the attributes in the attribute list ... */ 1132*7c478bd9Sstevel@tonic-gate for (pp = attributes; nobaderr && *pp; pp++) { 1133*7c478bd9Sstevel@tonic-gate 1134*7c478bd9Sstevel@tonic-gate /* 1135*7c478bd9Sstevel@tonic-gate * Modify the device description, removing the requested 1136*7c478bd9Sstevel@tonic-gate * attributes from the structure 1137*7c478bd9Sstevel@tonic-gate */ 1138*7c478bd9Sstevel@tonic-gate 1139*7c478bd9Sstevel@tonic-gate found = FALSE; /* Not found yet */ 1140*7c478bd9Sstevel@tonic-gate 1141*7c478bd9Sstevel@tonic-gate /* If it's the "cdevice" attribute, make it a null-string */ 1142*7c478bd9Sstevel@tonic-gate if (strcmp(*pp, DTAB_CDEVICE) == 0) { 1143*7c478bd9Sstevel@tonic-gate if (modent->cdevice) { 1144*7c478bd9Sstevel@tonic-gate free(modent->cdevice); 1145*7c478bd9Sstevel@tonic-gate modent->cdevice = NULL; 1146*7c478bd9Sstevel@tonic-gate } 1147*7c478bd9Sstevel@tonic-gate found = TRUE; 1148*7c478bd9Sstevel@tonic-gate } 1149*7c478bd9Sstevel@tonic-gate 1150*7c478bd9Sstevel@tonic-gate /* If it's the "bdevice" attribute, make it a null-string */ 1151*7c478bd9Sstevel@tonic-gate else if (strcmp(*pp, DTAB_BDEVICE) == 0) { 1152*7c478bd9Sstevel@tonic-gate if (modent->bdevice) { 1153*7c478bd9Sstevel@tonic-gate free(modent->bdevice); 1154*7c478bd9Sstevel@tonic-gate modent->bdevice = NULL; 1155*7c478bd9Sstevel@tonic-gate } 1156*7c478bd9Sstevel@tonic-gate found = TRUE; 1157*7c478bd9Sstevel@tonic-gate } 1158*7c478bd9Sstevel@tonic-gate 1159*7c478bd9Sstevel@tonic-gate /* If it's the "pathname" attribute, make it a null-string */ 1160*7c478bd9Sstevel@tonic-gate else if (strcmp(*pp, DTAB_PATHNAME) == 0) { 1161*7c478bd9Sstevel@tonic-gate if (modent->pathname) { 1162*7c478bd9Sstevel@tonic-gate free(modent->pathname); 1163*7c478bd9Sstevel@tonic-gate modent->pathname = NULL; 1164*7c478bd9Sstevel@tonic-gate } 1165*7c478bd9Sstevel@tonic-gate found = TRUE; 1166*7c478bd9Sstevel@tonic-gate } 1167*7c478bd9Sstevel@tonic-gate 1168*7c478bd9Sstevel@tonic-gate /* Must be one of the other "auxilliary" attributes */ 1169*7c478bd9Sstevel@tonic-gate else { 1170*7c478bd9Sstevel@tonic-gate 1171*7c478bd9Sstevel@tonic-gate /* Search the attribute list for the attribute */ 1172*7c478bd9Sstevel@tonic-gate prevattrval = NULL; 1173*7c478bd9Sstevel@tonic-gate if ((attrval = modent->attrlist) != NULL) do { 1174*7c478bd9Sstevel@tonic-gate if (strcmp(*pp, attrval->attr) == 0) { 1175*7c478bd9Sstevel@tonic-gate 1176*7c478bd9Sstevel@tonic-gate /* Found. Remove from attribute list */ 1177*7c478bd9Sstevel@tonic-gate found = TRUE; 1178*7c478bd9Sstevel@tonic-gate free(attrval->attr); 1179*7c478bd9Sstevel@tonic-gate free(attrval->val); 1180*7c478bd9Sstevel@tonic-gate if (prevattrval) { 1181*7c478bd9Sstevel@tonic-gate prevattrval->next = attrval->next; 1182*7c478bd9Sstevel@tonic-gate free(attrval); 1183*7c478bd9Sstevel@tonic-gate attrval = prevattrval->next; 1184*7c478bd9Sstevel@tonic-gate } else { 1185*7c478bd9Sstevel@tonic-gate modent->attrlist = attrval->next; 1186*7c478bd9Sstevel@tonic-gate free(attrval); 1187*7c478bd9Sstevel@tonic-gate attrval = modent->attrlist; 1188*7c478bd9Sstevel@tonic-gate } 1189*7c478bd9Sstevel@tonic-gate } else { 1190*7c478bd9Sstevel@tonic-gate prevattrval = attrval; /* Advance to next */ 1191*7c478bd9Sstevel@tonic-gate attrval = attrval->next; 1192*7c478bd9Sstevel@tonic-gate } 1193*7c478bd9Sstevel@tonic-gate } while (!found && attrval); 1194*7c478bd9Sstevel@tonic-gate 1195*7c478bd9Sstevel@tonic-gate } /* End attribute search loop */ 1196*7c478bd9Sstevel@tonic-gate 1197*7c478bd9Sstevel@tonic-gate /* 1198*7c478bd9Sstevel@tonic-gate * If the requested attribute wasn't defined for the device, 1199*7c478bd9Sstevel@tonic-gate * put it in the list of attributes not found 1200*7c478bd9Sstevel@tonic-gate */ 1201*7c478bd9Sstevel@tonic-gate 1202*7c478bd9Sstevel@tonic-gate if (!found) { 1203*7c478bd9Sstevel@tonic-gate 1204*7c478bd9Sstevel@tonic-gate /* 1205*7c478bd9Sstevel@tonic-gate * If there's no list (yet), alloc enough space for 1206*7c478bd9Sstevel@tonic-gate * the list 1207*7c478bd9Sstevel@tonic-gate */ 1208*7c478bd9Sstevel@tonic-gate 1209*7c478bd9Sstevel@tonic-gate if (nonotfounds) 1210*7c478bd9Sstevel@tonic-gate if (*notfounds = malloc(sizeof (char **)*(nattrs+1))) { 1211*7c478bd9Sstevel@tonic-gate 1212*7c478bd9Sstevel@tonic-gate /* List allocated -- put in the first entry */ 1213*7c478bd9Sstevel@tonic-gate nonotfounds = FALSE; 1214*7c478bd9Sstevel@tonic-gate pnxt = *notfounds; 1215*7c478bd9Sstevel@tonic-gate if (*pnxt = malloc(strlen(*pp)+1)) { 1216*7c478bd9Sstevel@tonic-gate errno = EINVAL; 1217*7c478bd9Sstevel@tonic-gate noerr = FALSE; 1218*7c478bd9Sstevel@tonic-gate (void) strcpy(*pnxt++, *pp); 1219*7c478bd9Sstevel@tonic-gate } else { 1220*7c478bd9Sstevel@tonic-gate /* malloc() failed, free list */ 1221*7c478bd9Sstevel@tonic-gate free(*notfounds); 1222*7c478bd9Sstevel@tonic-gate *notfounds = NULL; 1223*7c478bd9Sstevel@tonic-gate nonotfounds = TRUE; 1224*7c478bd9Sstevel@tonic-gate nobaderr = FALSE; 1225*7c478bd9Sstevel@tonic-gate } 1226*7c478bd9Sstevel@tonic-gate 1227*7c478bd9Sstevel@tonic-gate } else nobaderr = FALSE; /* malloc() failed */ 1228*7c478bd9Sstevel@tonic-gate 1229*7c478bd9Sstevel@tonic-gate else { 1230*7c478bd9Sstevel@tonic-gate /* Already a list, add this attribute to it */ 1231*7c478bd9Sstevel@tonic-gate if (*pnxt = malloc(strlen(*pp)+1)) 1232*7c478bd9Sstevel@tonic-gate (void) strcpy(*pnxt++, *pp); 1233*7c478bd9Sstevel@tonic-gate else { 1234*7c478bd9Sstevel@tonic-gate /* Out of memory, clean up */ 1235*7c478bd9Sstevel@tonic-gate for (pnxt = *notfounds; *pnxt; pnxt++) 1236*7c478bd9Sstevel@tonic-gate free(*pnxt); 1237*7c478bd9Sstevel@tonic-gate free(*notfounds); 1238*7c478bd9Sstevel@tonic-gate *notfounds = NULL; 1239*7c478bd9Sstevel@tonic-gate nonotfounds = TRUE; 1240*7c478bd9Sstevel@tonic-gate nobaderr = FALSE; 1241*7c478bd9Sstevel@tonic-gate } 1242*7c478bd9Sstevel@tonic-gate } 1243*7c478bd9Sstevel@tonic-gate 1244*7c478bd9Sstevel@tonic-gate } /* end if (!found) */ 1245*7c478bd9Sstevel@tonic-gate 1246*7c478bd9Sstevel@tonic-gate /* Terminate the not-found list */ 1247*7c478bd9Sstevel@tonic-gate if (!nonotfounds) *pnxt = NULL; 1248*7c478bd9Sstevel@tonic-gate 1249*7c478bd9Sstevel@tonic-gate } /* end (for each attribute in attribute list) loop */ 1250*7c478bd9Sstevel@tonic-gate 1251*7c478bd9Sstevel@tonic-gate 1252*7c478bd9Sstevel@tonic-gate /* 1253*7c478bd9Sstevel@tonic-gate * If we haven't seen any problems so far, 1254*7c478bd9Sstevel@tonic-gate * write the new device table 1255*7c478bd9Sstevel@tonic-gate */ 1256*7c478bd9Sstevel@tonic-gate 1257*7c478bd9Sstevel@tonic-gate if (nobaderr) { 1258*7c478bd9Sstevel@tonic-gate 1259*7c478bd9Sstevel@tonic-gate /* Open the new device table */ 1260*7c478bd9Sstevel@tonic-gate if (fd = opennewdevtab(&tempname)) { 1261*7c478bd9Sstevel@tonic-gate 1262*7c478bd9Sstevel@tonic-gate /* 1263*7c478bd9Sstevel@tonic-gate * For each entry in the existing table, write that entry 1264*7c478bd9Sstevel@tonic-gate * to the new table. If the entry is the one being 1265*7c478bd9Sstevel@tonic-gate * modified, write the modified entry instead of the 1266*7c478bd9Sstevel@tonic-gate * original entry. 1267*7c478bd9Sstevel@tonic-gate */ 1268*7c478bd9Sstevel@tonic-gate 1269*7c478bd9Sstevel@tonic-gate _setdevtab(); /* Rewind existing table */ 1270*7c478bd9Sstevel@tonic-gate while (((devtabent = _getdevtabent()) != NULL) && 1271*7c478bd9Sstevel@tonic-gate nobaderr) { 1272*7c478bd9Sstevel@tonic-gate 1273*7c478bd9Sstevel@tonic-gate if (devtabent->entryno != modent->entryno) 1274*7c478bd9Sstevel@tonic-gate nobaderr = _putdevtabrec(fd, devtabent) != EOF; 1275*7c478bd9Sstevel@tonic-gate else nobaderr = _putdevtabrec(fd, modent) != EOF; 1276*7c478bd9Sstevel@tonic-gate _freedevtabent(devtabent); 1277*7c478bd9Sstevel@tonic-gate } 1278*7c478bd9Sstevel@tonic-gate 1279*7c478bd9Sstevel@tonic-gate /* 1280*7c478bd9Sstevel@tonic-gate * If we successfully generated the new table, make it the 1281*7c478bd9Sstevel@tonic-gate * new system device table. Otherwise, just remove the 1282*7c478bd9Sstevel@tonic-gate * temporary file we've created. 1283*7c478bd9Sstevel@tonic-gate */ 1284*7c478bd9Sstevel@tonic-gate 1285*7c478bd9Sstevel@tonic-gate if (nobaderr) { 1286*7c478bd9Sstevel@tonic-gate (void) fclose(fd); 1287*7c478bd9Sstevel@tonic-gate nobaderr = mknewdevtab(tempname); 1288*7c478bd9Sstevel@tonic-gate } else { 1289*7c478bd9Sstevel@tonic-gate (void) fclose(fd); 1290*7c478bd9Sstevel@tonic-gate (void) rmnewdevtab(tempname); 1291*7c478bd9Sstevel@tonic-gate } 1292*7c478bd9Sstevel@tonic-gate 1293*7c478bd9Sstevel@tonic-gate } /* if (_opennewdevtab()) */ 1294*7c478bd9Sstevel@tonic-gate else nobaderr = FALSE; 1295*7c478bd9Sstevel@tonic-gate 1296*7c478bd9Sstevel@tonic-gate /* 1297*7c478bd9Sstevel@tonic-gate * If there was some error, we need to clean up 1298*7c478bd9Sstevel@tonic-gate * allocated resources 1299*7c478bd9Sstevel@tonic-gate */ 1300*7c478bd9Sstevel@tonic-gate if (!nobaderr && !nonotfounds) { 1301*7c478bd9Sstevel@tonic-gate for (pnxt = *notfounds; *pnxt; pnxt++) 1302*7c478bd9Sstevel@tonic-gate free(*pnxt); 1303*7c478bd9Sstevel@tonic-gate free(*notfounds); 1304*7c478bd9Sstevel@tonic-gate *notfounds = NULL; 1305*7c478bd9Sstevel@tonic-gate nonotfounds = TRUE; 1306*7c478bd9Sstevel@tonic-gate } 1307*7c478bd9Sstevel@tonic-gate 1308*7c478bd9Sstevel@tonic-gate } /* if (nobaderr) */ 1309*7c478bd9Sstevel@tonic-gate 1310*7c478bd9Sstevel@tonic-gate /* Free the resources alloc'ed for <device>'s entry */ 1311*7c478bd9Sstevel@tonic-gate _freedevtabent(modent); 1312*7c478bd9Sstevel@tonic-gate 1313*7c478bd9Sstevel@tonic-gate } else { 1314*7c478bd9Sstevel@tonic-gate /* _getdevrec(device) failed */ 1315*7c478bd9Sstevel@tonic-gate nobaderr = FALSE; 1316*7c478bd9Sstevel@tonic-gate *notfounds = NULL; 1317*7c478bd9Sstevel@tonic-gate } 1318*7c478bd9Sstevel@tonic-gate 1319*7c478bd9Sstevel@tonic-gate /* Unlock the device table */ 1320*7c478bd9Sstevel@tonic-gate (void) unlkdevtab(); 1321*7c478bd9Sstevel@tonic-gate 1322*7c478bd9Sstevel@tonic-gate /* We're finished */ 1323*7c478bd9Sstevel@tonic-gate return (noerr && nobaderr); 1324*7c478bd9Sstevel@tonic-gate } 1325