17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright (c) 1996-1997, by Sun Microsystems, Inc. 247c478bd9Sstevel@tonic-gate * All Rights reserved. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 277c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 287c478bd9Sstevel@tonic-gate 29*4656d474SGarrett D'Amore /* 30*4656d474SGarrett D'Amore * Copyright 2010 Nexenta Systems, Inc. All rights reserved. 31*4656d474SGarrett D'Amore */ 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate /* LINTLIBRARY */ 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate /* 367c478bd9Sstevel@tonic-gate * putdev.c 377c478bd9Sstevel@tonic-gate * 387c478bd9Sstevel@tonic-gate * Global Definitions: 397c478bd9Sstevel@tonic-gate * _adddevtabrec() Add a record to the device table 407c478bd9Sstevel@tonic-gate * _putdevtabrec() Write a record to the device table 417c478bd9Sstevel@tonic-gate * _moddevtabrec() Modify a device-table record 427c478bd9Sstevel@tonic-gate * _rmdevtabrec() Remove a device-table record 437c478bd9Sstevel@tonic-gate * _rmdevtabattrs() Remove attributes from a device-table record 447c478bd9Sstevel@tonic-gate * oam_devtab File descriptor of the open device table 457c478bd9Sstevel@tonic-gate */ 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate /* 487c478bd9Sstevel@tonic-gate * G L O B A L R E F E R E N C E S 497c478bd9Sstevel@tonic-gate * 507c478bd9Sstevel@tonic-gate * Header Files 517c478bd9Sstevel@tonic-gate * Externals Referenced 527c478bd9Sstevel@tonic-gate */ 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate /* 557c478bd9Sstevel@tonic-gate * Header Files 567c478bd9Sstevel@tonic-gate * <sys/types.h> UNIX(r) Data Types 577c478bd9Sstevel@tonic-gate * <sys/stat.h> 587c478bd9Sstevel@tonic-gate * <stdio.h> Standard I/O definitions 597c478bd9Sstevel@tonic-gate * <fcntl.h> Definitions for file control 607c478bd9Sstevel@tonic-gate * <errno.h> Error handling definitions 617c478bd9Sstevel@tonic-gate * <string.h> String Handling Definitions 627c478bd9Sstevel@tonic-gate * <devmgmt.h> Device Management Definitions 637c478bd9Sstevel@tonic-gate * <unistd.h> Get UNIX(r) Standard Definitions 647c478bd9Sstevel@tonic-gate * "devtab.h" Local Device Management Definitions 657c478bd9Sstevel@tonic-gate */ 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate #include <sys/types.h> 687c478bd9Sstevel@tonic-gate #include <sys/stat.h> 697c478bd9Sstevel@tonic-gate #include <stdio.h> 707c478bd9Sstevel@tonic-gate #include <fcntl.h> 717c478bd9Sstevel@tonic-gate #include <errno.h> 727c478bd9Sstevel@tonic-gate #include <string.h> 737c478bd9Sstevel@tonic-gate #include <devmgmt.h> 747c478bd9Sstevel@tonic-gate #include <unistd.h> 757c478bd9Sstevel@tonic-gate #include <stdlib.h> 767c478bd9Sstevel@tonic-gate #include "devtab.h" 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate /* 797c478bd9Sstevel@tonic-gate * L O C A L D E F I N I T I O N S 807c478bd9Sstevel@tonic-gate * 817c478bd9Sstevel@tonic-gate * TDTABNM Name of the temporary device table (in the 827c478bd9Sstevel@tonic-gate * directory of the existing table) 837c478bd9Sstevel@tonic-gate */ 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate #define TDTABNM "%sdevtab.%6.6d" 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate /* 897c478bd9Sstevel@tonic-gate * Static functions 907c478bd9Sstevel@tonic-gate * strcatesc Copies a character-string from one place to another 917c478bd9Sstevel@tonic-gate * escaping the appropriate characters 927c478bd9Sstevel@tonic-gate * lkdevtab Locks the device table 937c478bd9Sstevel@tonic-gate * unlkdevtab Unlocks the device table 947c478bd9Sstevel@tonic-gate * mkdevtabent Builds a device-table entry from the alias and the 957c478bd9Sstevel@tonic-gate * list of attr=val pairs given 967c478bd9Sstevel@tonic-gate * opennewdevtab Opens a new device table (as a temp file) 977c478bd9Sstevel@tonic-gate * mknewdevtab Makes the temp device table the new devtab 987c478bd9Sstevel@tonic-gate * rmnewdevtab Remove the temporary device table and free space 997c478bd9Sstevel@tonic-gate * allocated to the filename of that file. 1007c478bd9Sstevel@tonic-gate */ 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate static char *strcatesc(char *, char *); 1037c478bd9Sstevel@tonic-gate static int lkdevtab(char *, short); 1047c478bd9Sstevel@tonic-gate static int unlkdevtab(void); 1057c478bd9Sstevel@tonic-gate static struct devtabent *mkdevtabent(char *, char **); 1067c478bd9Sstevel@tonic-gate static FILE *opennewdevtab(char **); 1077c478bd9Sstevel@tonic-gate static int mknewdevtab(char *); 1087c478bd9Sstevel@tonic-gate static int rmnewdevtab(char *); 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate /* 1117c478bd9Sstevel@tonic-gate * char *strcatesc(p, q) 1127c478bd9Sstevel@tonic-gate * char *p 1137c478bd9Sstevel@tonic-gate * char *q 1147c478bd9Sstevel@tonic-gate * 1157c478bd9Sstevel@tonic-gate * Write the character-string pointed to by "q" to the place 1167c478bd9Sstevel@tonic-gate * pointed to by "p", escaping those characters in "q" found in the 1177c478bd9Sstevel@tonic-gate * string "DTAB_ESCS" by preceding them with '\\'. Return a pointer to 1187c478bd9Sstevel@tonic-gate * the byte beyond the last character written to "p". 1197c478bd9Sstevel@tonic-gate * 1207c478bd9Sstevel@tonic-gate * Arguments: 1217c478bd9Sstevel@tonic-gate * p The place to begin writing to 1227c478bd9Sstevel@tonic-gate * q The string to write 1237c478bd9Sstevel@tonic-gate * 1247c478bd9Sstevel@tonic-gate * Returns: char * 1257c478bd9Sstevel@tonic-gate * The address of the byte beyond the last character written into "p" 1267c478bd9Sstevel@tonic-gate */ 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate static char * 1297c478bd9Sstevel@tonic-gate strcatesc( 1307c478bd9Sstevel@tonic-gate char *p, /* Place to write to */ 1317c478bd9Sstevel@tonic-gate char *q) /* Thing to write */ 1327c478bd9Sstevel@tonic-gate { 1337c478bd9Sstevel@tonic-gate while (*q) { 1347c478bd9Sstevel@tonic-gate if (strchr(DTAB_ESCS, *q)) *p++ = '\\'; 1357c478bd9Sstevel@tonic-gate *p++ = *q++; 1367c478bd9Sstevel@tonic-gate } 1377c478bd9Sstevel@tonic-gate return (p); 1387c478bd9Sstevel@tonic-gate } 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate /* 1417c478bd9Sstevel@tonic-gate * FILE *opennewdevtab(pname) 1427c478bd9Sstevel@tonic-gate * char **pname 1437c478bd9Sstevel@tonic-gate * 1447c478bd9Sstevel@tonic-gate * Generates a temporary device-table name from the existing 1457c478bd9Sstevel@tonic-gate * device table name (in the same directory) and opens that 1467c478bd9Sstevel@tonic-gate * file for writing. It puts a pointer to the malloc()ed space 1477c478bd9Sstevel@tonic-gate * containing the temp device table's name at the place referenced 1487c478bd9Sstevel@tonic-gate * by <pname>. 1497c478bd9Sstevel@tonic-gate * 1507c478bd9Sstevel@tonic-gate * Arguments: 1517c478bd9Sstevel@tonic-gate * pname Pointer to the char * to contain the address of the name 1527c478bd9Sstevel@tonic-gate * of the temporary file 1537c478bd9Sstevel@tonic-gate * 1547c478bd9Sstevel@tonic-gate * Returns: FILE * 1557c478bd9Sstevel@tonic-gate * A pointer to the opened stream or (FILE *) NULL if an error occurred. 1567c478bd9Sstevel@tonic-gate * If an error occurred, "errno" will be set to reflect the problem. 1577c478bd9Sstevel@tonic-gate */ 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate static FILE * 1607c478bd9Sstevel@tonic-gate opennewdevtab(char **pname) /* A(ptr to temp filename's path) */ 1617c478bd9Sstevel@tonic-gate { 1627c478bd9Sstevel@tonic-gate char *oldname; /* Ptr to the device-table's name */ 1637c478bd9Sstevel@tonic-gate char *buf; /* Ptr to the temp file's name */ 1647c478bd9Sstevel@tonic-gate char *dirname; /* Directory containing devtab */ 1657c478bd9Sstevel@tonic-gate char *p; /* Ptr to last '/' in devtab name */ 1667c478bd9Sstevel@tonic-gate int fd; /* Opened file descriptor */ 1677c478bd9Sstevel@tonic-gate FILE *fp; /* Opened file pointer */ 1687c478bd9Sstevel@tonic-gate struct stat64 sbuf; /* stat buf for old devtab file */ 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate fp = NULL; 1717c478bd9Sstevel@tonic-gate if (oldname = _devtabpath()) { 1727c478bd9Sstevel@tonic-gate /* 1737c478bd9Sstevel@tonic-gate * It is possible for us to have sufficient permissions to create 1747c478bd9Sstevel@tonic-gate * the new file without having sufficient permissions to write the 1757c478bd9Sstevel@tonic-gate * original devtab file. For consistency with the operations which 1767c478bd9Sstevel@tonic-gate * modify the original file by writing it directly we require write 1777c478bd9Sstevel@tonic-gate * permissions for the original file in order to make a new one. 1787c478bd9Sstevel@tonic-gate */ 1797c478bd9Sstevel@tonic-gate if ((fd = open(oldname, O_WRONLY)) == -1) 1807c478bd9Sstevel@tonic-gate return (NULL); 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate if (fstat64(fd, &sbuf) == -1) { 1837c478bd9Sstevel@tonic-gate (void) close(fd); 1847c478bd9Sstevel@tonic-gate return (NULL); 1857c478bd9Sstevel@tonic-gate } 1867c478bd9Sstevel@tonic-gate (void) close(fd); 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate if (p = strrchr(oldname, '/')) { 1897c478bd9Sstevel@tonic-gate *(p+1) = '\0'; 1907c478bd9Sstevel@tonic-gate dirname = oldname; 1917c478bd9Sstevel@tonic-gate } else dirname = "./"; 192*4656d474SGarrett D'Amore if (asprintf(&buf, TDTABNM, dirname, getpid()) >= 0) { 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate /* 195*4656d474SGarrett D'Amore * Build the name of the temp device table and 196*4656d474SGarrett D'Amore * open the file. We must reset the owner, group 197*4656d474SGarrett D'Amore * and perms to those of the original devtab file. 1987c478bd9Sstevel@tonic-gate */ 1997c478bd9Sstevel@tonic-gate if (fp = fopen(buf, "w")) { 2007c478bd9Sstevel@tonic-gate *pname = buf; 2017c478bd9Sstevel@tonic-gate (void) fchmod(fileno(fp), sbuf.st_mode & 0777); 2027c478bd9Sstevel@tonic-gate (void) fchown(fileno(fp), sbuf.st_uid, sbuf.st_gid); 2037c478bd9Sstevel@tonic-gate } else { 2047c478bd9Sstevel@tonic-gate free(buf); 2057c478bd9Sstevel@tonic-gate } 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate /* 2097c478bd9Sstevel@tonic-gate * 2107c478bd9Sstevel@tonic-gate * Free the space containing the device table's name. 2117c478bd9Sstevel@tonic-gate */ 2127c478bd9Sstevel@tonic-gate free(oldname); 2137c478bd9Sstevel@tonic-gate } 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate /* Finished. Return what we've got */ 2167c478bd9Sstevel@tonic-gate return (fp); 2177c478bd9Sstevel@tonic-gate } 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate /* 2207c478bd9Sstevel@tonic-gate * int rmnewdevtab(tempname) 2217c478bd9Sstevel@tonic-gate * char *tempname 2227c478bd9Sstevel@tonic-gate * 2237c478bd9Sstevel@tonic-gate * Unlink the temp device table and free the memory allocated to 2247c478bd9Sstevel@tonic-gate * contain the name of that file 2257c478bd9Sstevel@tonic-gate * 2267c478bd9Sstevel@tonic-gate * Arguments: 2277c478bd9Sstevel@tonic-gate * tempname Name of the temporary file 2287c478bd9Sstevel@tonic-gate * 2297c478bd9Sstevel@tonic-gate * Returns: int 2307c478bd9Sstevel@tonic-gate * TRUE if successful, FALSE otherwise 2317c478bd9Sstevel@tonic-gate */ 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate static int 2347c478bd9Sstevel@tonic-gate rmnewdevtab(char *tempname) /* Filename of new device table */ 2357c478bd9Sstevel@tonic-gate { 2367c478bd9Sstevel@tonic-gate int noerr; /* Flag, TRUE if no error, FALSE otherwise */ 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate /* Unlink the file */ 2397c478bd9Sstevel@tonic-gate noerr = (unlink(tempname) == 0); 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate /* Free the space allocated to the filename */ 2427c478bd9Sstevel@tonic-gate free(tempname); 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate /* Return success indicator */ 2457c478bd9Sstevel@tonic-gate return (noerr); 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate /* 2497c478bd9Sstevel@tonic-gate * int mknewdevtab(tempname) 2507c478bd9Sstevel@tonic-gate * char *tempname 2517c478bd9Sstevel@tonic-gate * 2527c478bd9Sstevel@tonic-gate * Make the temporary device-table the new system device table 2537c478bd9Sstevel@tonic-gate * 2547c478bd9Sstevel@tonic-gate * Arguments: 2557c478bd9Sstevel@tonic-gate * tempname Name of the temporary file 2567c478bd9Sstevel@tonic-gate * 2577c478bd9Sstevel@tonic-gate * Returns: int 2587c478bd9Sstevel@tonic-gate * TRUE if successful, FALSE otherwise 2597c478bd9Sstevel@tonic-gate * 2607c478bd9Sstevel@tonic-gate * Notes: 2617c478bd9Sstevel@tonic-gate * - Need to use rename() someday instead of link()/unlink() 2627c478bd9Sstevel@tonic-gate * - This code is somewhat ineffecient in that asks for the name 2637c478bd9Sstevel@tonic-gate * of the device-table more than once. Done so that we don't 2647c478bd9Sstevel@tonic-gate * have to manage that space, but this may be somewhat lazy. 2657c478bd9Sstevel@tonic-gate */ 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate static int 2687c478bd9Sstevel@tonic-gate mknewdevtab(char *tempname) /* Ptr to name of temp dev tab */ 2697c478bd9Sstevel@tonic-gate { 2707c478bd9Sstevel@tonic-gate char *devtabname; /* Ptr to the device table's name */ 2717c478bd9Sstevel@tonic-gate int noerr; /* FLAG, TRUE if all's well */ 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate /* Get the device table's pathname */ 2747c478bd9Sstevel@tonic-gate if (devtabname = _devtabpath()) { 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate /* Unlink the existing file */ 2777c478bd9Sstevel@tonic-gate if (unlink(devtabname) == 0) { 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate /* Make the temp file the real device table */ 2807c478bd9Sstevel@tonic-gate noerr = (link(tempname, devtabname) == 0) ? TRUE : FALSE; 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate /* Remove the temp file (and resources) */ 2837c478bd9Sstevel@tonic-gate if (noerr) (void) rmnewdevtab(tempname); 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate } else noerr = FALSE; /* unlink() failed */ 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate /* Free the device table's name */ 2887c478bd9Sstevel@tonic-gate free(devtabname); 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate } else noerr = FALSE; /* devtabpath() failed */ 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate /* Finished. Return success indicator */ 2937c478bd9Sstevel@tonic-gate return (noerr); 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate /* 2977c478bd9Sstevel@tonic-gate * static int lkdevtab(o_mode, lktype) 2987c478bd9Sstevel@tonic-gate * char *o_mode 2997c478bd9Sstevel@tonic-gate * short lktype 3007c478bd9Sstevel@tonic-gate * 3017c478bd9Sstevel@tonic-gate * Lock the device table for writing. If it isn't available, it waits 3027c478bd9Sstevel@tonic-gate * until it is. 3037c478bd9Sstevel@tonic-gate * 3047c478bd9Sstevel@tonic-gate * Arguments: 3057c478bd9Sstevel@tonic-gate * o_mode The open() mode to use when opening the device table 3067c478bd9Sstevel@tonic-gate * lktype The type of lock to apply 3077c478bd9Sstevel@tonic-gate * 3087c478bd9Sstevel@tonic-gate * Returns: int 3097c478bd9Sstevel@tonic-gate * TRUE if successful, FALSE with errno set otherwise 3107c478bd9Sstevel@tonic-gate */ 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate static int 3137c478bd9Sstevel@tonic-gate lkdevtab( 3147c478bd9Sstevel@tonic-gate char *o_mode, /* Open mode */ 3157c478bd9Sstevel@tonic-gate short lktype) /* Lock type */ 3167c478bd9Sstevel@tonic-gate { 3177c478bd9Sstevel@tonic-gate /* Automatic data */ 3187c478bd9Sstevel@tonic-gate struct flock lockinfo; /* File locking structure */ 3197c478bd9Sstevel@tonic-gate int noerr; /* FLAG, TRUE if no error */ 3207c478bd9Sstevel@tonic-gate int olderrno; /* Old value of "errno" */ 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate /* Close the device table (if it's open) */ 3247c478bd9Sstevel@tonic-gate _enddevtab(); 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate /* Open the device table for read/append */ 3277c478bd9Sstevel@tonic-gate noerr = TRUE; 3287c478bd9Sstevel@tonic-gate if (_opendevtab(o_mode)) { 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate /* 3317c478bd9Sstevel@tonic-gate * Lock the device table (for writing). If it's not 3327c478bd9Sstevel@tonic-gate * available, wait until it is, then close and open the 3337c478bd9Sstevel@tonic-gate * table (modify and delete change the table!) and try 3347c478bd9Sstevel@tonic-gate * to lock it again 3357c478bd9Sstevel@tonic-gate */ 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate /* Build the locking structure */ 3387c478bd9Sstevel@tonic-gate lockinfo.l_type = lktype; 3397c478bd9Sstevel@tonic-gate lockinfo.l_whence = 0; 3407c478bd9Sstevel@tonic-gate lockinfo.l_start = 0L; 3417c478bd9Sstevel@tonic-gate lockinfo.l_len = 0L; 3427c478bd9Sstevel@tonic-gate olderrno = errno; 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate /* Keep on going until we lock the file or an error happens */ 3457c478bd9Sstevel@tonic-gate while ((fcntl(fileno(oam_devtab), F_SETLK, &lockinfo) == -1) && 3467c478bd9Sstevel@tonic-gate !noerr) { 3477c478bd9Sstevel@tonic-gate if (errno == EACCES) { 3487c478bd9Sstevel@tonic-gate if (fcntl(fileno(oam_devtab), F_SETLKW, &lockinfo) == -1) 3497c478bd9Sstevel@tonic-gate noerr = FALSE; 3507c478bd9Sstevel@tonic-gate else { 3517c478bd9Sstevel@tonic-gate /* Reopen the file (maybe it's moved?) */ 3527c478bd9Sstevel@tonic-gate _enddevtab(); 3537c478bd9Sstevel@tonic-gate if (!_opendevtab(o_mode)) noerr = FALSE; 3547c478bd9Sstevel@tonic-gate else errno = olderrno; 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate } else noerr = FALSE; 3577c478bd9Sstevel@tonic-gate } 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate if (!noerr) _enddevtab(); /* Don't keep open if in error */ 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate } else noerr = FALSE; 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate /* Done */ 3647c478bd9Sstevel@tonic-gate return (noerr); 3657c478bd9Sstevel@tonic-gate } 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate /* 3687c478bd9Sstevel@tonic-gate * int unlkdevtab() 3697c478bd9Sstevel@tonic-gate * 3707c478bd9Sstevel@tonic-gate * Unlock the locked device table. 3717c478bd9Sstevel@tonic-gate * 3727c478bd9Sstevel@tonic-gate * Arguments: None 3737c478bd9Sstevel@tonic-gate * 3747c478bd9Sstevel@tonic-gate * Returns: int 3757c478bd9Sstevel@tonic-gate * Whatever fcntl() returns... 3767c478bd9Sstevel@tonic-gate */ 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate static int 3797c478bd9Sstevel@tonic-gate unlkdevtab(void) 3807c478bd9Sstevel@tonic-gate { 3817c478bd9Sstevel@tonic-gate /* Automatic data */ 3827c478bd9Sstevel@tonic-gate struct flock lockinfo; /* Locking structure */ 3837c478bd9Sstevel@tonic-gate int noerr; /* FLAG, TRUE if all's well */ 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate /* Build the locking structure */ 3867c478bd9Sstevel@tonic-gate lockinfo.l_type = F_UNLCK; /* Lock type */ 3877c478bd9Sstevel@tonic-gate lockinfo.l_whence = 0; /* Count from top of file */ 3887c478bd9Sstevel@tonic-gate lockinfo.l_start = 0L; /* From beginning */ 3897c478bd9Sstevel@tonic-gate lockinfo.l_len = 0L; /* Length of locked data */ 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate /* Unlock it */ 3927c478bd9Sstevel@tonic-gate noerr = (fcntl(fileno(oam_devtab), F_SETLK, &lockinfo) != -1); 3937c478bd9Sstevel@tonic-gate _enddevtab(); 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate /* Finished */ 3967c478bd9Sstevel@tonic-gate return (noerr); 3977c478bd9Sstevel@tonic-gate } 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate /* 4007c478bd9Sstevel@tonic-gate * struct devtabent *mkdevtabent(alias, attrlist) 4017c478bd9Sstevel@tonic-gate * char *alias 4027c478bd9Sstevel@tonic-gate * char **attrlist 4037c478bd9Sstevel@tonic-gate * 4047c478bd9Sstevel@tonic-gate * This function builds a struct devtabent structure describing the 4057c478bd9Sstevel@tonic-gate * alias <alias> using the information in the attribute list <attrlist>. 4067c478bd9Sstevel@tonic-gate * The <attrlist> contains data of the form attr=value where attr is 4077c478bd9Sstevel@tonic-gate * the name of an attribute and value is the value of that attribute. 4087c478bd9Sstevel@tonic-gate * 4097c478bd9Sstevel@tonic-gate * Arguments: 4107c478bd9Sstevel@tonic-gate * alias The alias being added to the device table 4117c478bd9Sstevel@tonic-gate * attrlist The attributes and values for that alias 4127c478bd9Sstevel@tonic-gate * 4137c478bd9Sstevel@tonic-gate * Returns: struct devtabent * 4147c478bd9Sstevel@tonic-gate * A completed struct devtabent structure containing the description 4157c478bd9Sstevel@tonic-gate * of the alias. The structure, and all of the data in the structure 4167c478bd9Sstevel@tonic-gate * are each in space allocated using the malloc() function and should 4177c478bd9Sstevel@tonic-gate * be freed using the free() function (or the _freedevtabent() function). 4187c478bd9Sstevel@tonic-gate * 4197c478bd9Sstevel@tonic-gate * Errors: 4207c478bd9Sstevel@tonic-gate * EINVAL If "alias" is used as an attribute in an attr=val pair 4217c478bd9Sstevel@tonic-gate * EAGAIN If an attribute is specified more than once 4227c478bd9Sstevel@tonic-gate */ 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate static struct devtabent * 4257c478bd9Sstevel@tonic-gate mkdevtabent( 4267c478bd9Sstevel@tonic-gate char *alias, /* Alias of entry */ 4277c478bd9Sstevel@tonic-gate char **attrlist) /* Attributes of new entry */ 4287c478bd9Sstevel@tonic-gate { 4297c478bd9Sstevel@tonic-gate /* Automatic data */ 4307c478bd9Sstevel@tonic-gate struct devtabent *devtabent; /* * to struct we're making */ 4317c478bd9Sstevel@tonic-gate struct attrval *prevattrval; /* * to prev attr/val struct */ 4327c478bd9Sstevel@tonic-gate struct attrval *attrval; /* * to current struct */ 4337c478bd9Sstevel@tonic-gate char **pp; /* Ptr into list of ptrs */ 4347c478bd9Sstevel@tonic-gate char *peq; /* Ptr to '=' in string */ 4357c478bd9Sstevel@tonic-gate char *val; /* Ptr to space for value */ 4367c478bd9Sstevel@tonic-gate char *name; /* Ptr to space for name */ 4377c478bd9Sstevel@tonic-gate ssize_t len; /* Length of name */ 4387c478bd9Sstevel@tonic-gate int noerr; /* TRUE if all's well */ 4397c478bd9Sstevel@tonic-gate int found; /* TRUE the attr is found */ 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate /* No problems (yet) */ 4437c478bd9Sstevel@tonic-gate noerr = TRUE; 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate /* Get space for the structure */ 4467c478bd9Sstevel@tonic-gate if (devtabent = malloc(sizeof (struct devtabent))) { 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate /* Fill in default values */ 4497c478bd9Sstevel@tonic-gate if (devtabent->alias = malloc(strlen(alias)+1)) { 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate (void) strcpy(devtabent->alias, alias); /* alias */ 4527c478bd9Sstevel@tonic-gate devtabent->comment = FALSE; /* data rec */ 4537c478bd9Sstevel@tonic-gate devtabent->cdevice = NULL; /* cdevice */ 4547c478bd9Sstevel@tonic-gate devtabent->bdevice = NULL; /* bdevice */ 4557c478bd9Sstevel@tonic-gate devtabent->pathname = NULL; /* pathname */ 4567c478bd9Sstevel@tonic-gate devtabent->attrstr = NULL; /* string */ 4577c478bd9Sstevel@tonic-gate devtabent->attrlist = NULL; /* attr list */ 4587c478bd9Sstevel@tonic-gate 4597c478bd9Sstevel@tonic-gate /* Add attributes to the structure */ 4607c478bd9Sstevel@tonic-gate prevattrval = NULL; 4617c478bd9Sstevel@tonic-gate if ((pp = attrlist) != NULL) 4627c478bd9Sstevel@tonic-gate while (*pp && noerr) { 4637c478bd9Sstevel@tonic-gate 4647c478bd9Sstevel@tonic-gate /* Valid attr=value pair? */ 4657c478bd9Sstevel@tonic-gate if (((peq = strchr(*pp, '=')) != NULL) && 4667c478bd9Sstevel@tonic-gate ((len = peq - *pp) > 0)) { 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate /* Get space for the value */ 4697c478bd9Sstevel@tonic-gate if (val = malloc(strlen(peq))) { 4707c478bd9Sstevel@tonic-gate (void) strcpy(val, peq+1); /* Copy it */ 4717c478bd9Sstevel@tonic-gate 4727c478bd9Sstevel@tonic-gate /* Get space for attribute name */ 4737c478bd9Sstevel@tonic-gate if (name = malloc((size_t)(len + 1))) { 4747c478bd9Sstevel@tonic-gate (void) strncpy(name, *pp, (size_t)len); 4757c478bd9Sstevel@tonic-gate *(name+len) = '\0'; 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate /* Specifying the alias? If so, ERROR */ 4787c478bd9Sstevel@tonic-gate if (strcmp(name, DTAB_ALIAS) == 0) { 4797c478bd9Sstevel@tonic-gate noerr = FALSE; 4807c478bd9Sstevel@tonic-gate free(name); 4817c478bd9Sstevel@tonic-gate free(val); 4827c478bd9Sstevel@tonic-gate errno = EINVAL; 4837c478bd9Sstevel@tonic-gate } 4847c478bd9Sstevel@tonic-gate 4857c478bd9Sstevel@tonic-gate /* Specifying the char device path? */ 4867c478bd9Sstevel@tonic-gate else if (strcmp(name, DTAB_CDEVICE) == 0) { 4877c478bd9Sstevel@tonic-gate if (!devtabent->cdevice) { 4887c478bd9Sstevel@tonic-gate if (val[0] != '/') { 4897c478bd9Sstevel@tonic-gate noerr = FALSE; 4907c478bd9Sstevel@tonic-gate free(name); 4917c478bd9Sstevel@tonic-gate free(val); 4927c478bd9Sstevel@tonic-gate errno = ENXIO; 4937c478bd9Sstevel@tonic-gate } else { 4947c478bd9Sstevel@tonic-gate devtabent->cdevice = val; 4957c478bd9Sstevel@tonic-gate free(name); 4967c478bd9Sstevel@tonic-gate } 4977c478bd9Sstevel@tonic-gate } else { 4987c478bd9Sstevel@tonic-gate noerr = FALSE; 4997c478bd9Sstevel@tonic-gate free(name); 5007c478bd9Sstevel@tonic-gate free(val); 5017c478bd9Sstevel@tonic-gate errno = EAGAIN; 5027c478bd9Sstevel@tonic-gate } 5037c478bd9Sstevel@tonic-gate } 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate /* Specifying the block device path? */ 5067c478bd9Sstevel@tonic-gate else if (strcmp(name, DTAB_BDEVICE) == 0) { 5077c478bd9Sstevel@tonic-gate if (!devtabent->bdevice) { 5087c478bd9Sstevel@tonic-gate if (val[0] != '/') { 5097c478bd9Sstevel@tonic-gate noerr = FALSE; 5107c478bd9Sstevel@tonic-gate free(name); 5117c478bd9Sstevel@tonic-gate free(val); 5127c478bd9Sstevel@tonic-gate errno = ENXIO; 5137c478bd9Sstevel@tonic-gate } else { 5147c478bd9Sstevel@tonic-gate devtabent->bdevice = val; 5157c478bd9Sstevel@tonic-gate free(name); 5167c478bd9Sstevel@tonic-gate } 5177c478bd9Sstevel@tonic-gate } else { 5187c478bd9Sstevel@tonic-gate noerr = FALSE; 5197c478bd9Sstevel@tonic-gate free(name); 5207c478bd9Sstevel@tonic-gate free(val); 5217c478bd9Sstevel@tonic-gate errno = EAGAIN; 5227c478bd9Sstevel@tonic-gate } 5237c478bd9Sstevel@tonic-gate } 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate /* Specifying the pathname (generic)? */ 5267c478bd9Sstevel@tonic-gate else if (strcmp(name, DTAB_PATHNAME) == 0) { 5277c478bd9Sstevel@tonic-gate if (!devtabent->pathname) { 5287c478bd9Sstevel@tonic-gate if (val[0] != '/') { 5297c478bd9Sstevel@tonic-gate noerr = FALSE; 5307c478bd9Sstevel@tonic-gate free(name); 5317c478bd9Sstevel@tonic-gate free(val); 5327c478bd9Sstevel@tonic-gate errno = ENXIO; 5337c478bd9Sstevel@tonic-gate } else { 5347c478bd9Sstevel@tonic-gate devtabent->pathname = val; 5357c478bd9Sstevel@tonic-gate free(name); 5367c478bd9Sstevel@tonic-gate } 5377c478bd9Sstevel@tonic-gate } else { 5387c478bd9Sstevel@tonic-gate noerr = FALSE; 5397c478bd9Sstevel@tonic-gate free(name); 5407c478bd9Sstevel@tonic-gate free(val); 5417c478bd9Sstevel@tonic-gate errno = EAGAIN; 5427c478bd9Sstevel@tonic-gate } 5437c478bd9Sstevel@tonic-gate } 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate /* Some other attribute */ 5467c478bd9Sstevel@tonic-gate else { 5477c478bd9Sstevel@tonic-gate found = FALSE; 5487c478bd9Sstevel@tonic-gate if ((attrval = devtabent->attrlist) != NULL) 5497c478bd9Sstevel@tonic-gate do { 5507c478bd9Sstevel@tonic-gate if (strcmp(attrval->attr, 5517c478bd9Sstevel@tonic-gate name) == 0) { 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate noerr = FALSE; 5547c478bd9Sstevel@tonic-gate free(name); 5557c478bd9Sstevel@tonic-gate free(val); 5567c478bd9Sstevel@tonic-gate errno = EAGAIN; 5577c478bd9Sstevel@tonic-gate } 5587c478bd9Sstevel@tonic-gate } while (!found && noerr && 5597c478bd9Sstevel@tonic-gate (attrval = attrval->next)); 5607c478bd9Sstevel@tonic-gate 5617c478bd9Sstevel@tonic-gate if (!found && noerr) { 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate /* Get space for attr/val structure */ 5647c478bd9Sstevel@tonic-gate if (attrval = 5657c478bd9Sstevel@tonic-gate malloc(sizeof (struct attrval))) { 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate /* Fill attr/val structure */ 5687c478bd9Sstevel@tonic-gate attrval->attr = name; 5697c478bd9Sstevel@tonic-gate attrval->val = val; 5707c478bd9Sstevel@tonic-gate attrval->next = NULL; 5717c478bd9Sstevel@tonic-gate 5727c478bd9Sstevel@tonic-gate /* 5737c478bd9Sstevel@tonic-gate * Link into the list of attributes 5747c478bd9Sstevel@tonic-gate */ 5757c478bd9Sstevel@tonic-gate if (prevattrval) 5767c478bd9Sstevel@tonic-gate prevattrval->next = attrval; 5777c478bd9Sstevel@tonic-gate else devtabent->attrlist = attrval; 5787c478bd9Sstevel@tonic-gate prevattrval = attrval; 5797c478bd9Sstevel@tonic-gate 5807c478bd9Sstevel@tonic-gate } else { 5817c478bd9Sstevel@tonic-gate /* malloc() for attrval failed */ 5827c478bd9Sstevel@tonic-gate noerr = FALSE; 5837c478bd9Sstevel@tonic-gate free(name); 5847c478bd9Sstevel@tonic-gate free(val); 5857c478bd9Sstevel@tonic-gate } 5867c478bd9Sstevel@tonic-gate } 5877c478bd9Sstevel@tonic-gate } /* End else (some other attribute) */ 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate } else { /* malloc() for attribute name failed */ 5907c478bd9Sstevel@tonic-gate noerr = FALSE; 5917c478bd9Sstevel@tonic-gate free(val); 5927c478bd9Sstevel@tonic-gate } 5937c478bd9Sstevel@tonic-gate 5947c478bd9Sstevel@tonic-gate } else noerr = FALSE; /* Malloc() for "val" failed */ 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate /* If we saw an error, free structure, returning NULL */ 5977c478bd9Sstevel@tonic-gate if (!noerr) { 5987c478bd9Sstevel@tonic-gate _freedevtabent(devtabent); 5997c478bd9Sstevel@tonic-gate devtabent = NULL; 6007c478bd9Sstevel@tonic-gate } 6017c478bd9Sstevel@tonic-gate 6027c478bd9Sstevel@tonic-gate } /* Ignore invalid attr=val pair */ 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate if (noerr) pp++; 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate } /* End attribute processing loop */ 6077c478bd9Sstevel@tonic-gate 6087c478bd9Sstevel@tonic-gate } else { /* malloc() failed */ 6097c478bd9Sstevel@tonic-gate free(devtabent); 6107c478bd9Sstevel@tonic-gate devtabent = NULL; 6117c478bd9Sstevel@tonic-gate } 6127c478bd9Sstevel@tonic-gate } 6137c478bd9Sstevel@tonic-gate 6147c478bd9Sstevel@tonic-gate /* Finished */ 6157c478bd9Sstevel@tonic-gate return (devtabent); 6167c478bd9Sstevel@tonic-gate } 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate /* 6197c478bd9Sstevel@tonic-gate * int _putdevtabrec(stream, rec) 6207c478bd9Sstevel@tonic-gate * FILE *stream 6217c478bd9Sstevel@tonic-gate * struct devtabent *rec 6227c478bd9Sstevel@tonic-gate * 6237c478bd9Sstevel@tonic-gate * Write a device table record containing the information in the struct 6247c478bd9Sstevel@tonic-gate * devtab structure <rec> to the current position of the standard I/O 6257c478bd9Sstevel@tonic-gate * stream <stream>. 6267c478bd9Sstevel@tonic-gate * 6277c478bd9Sstevel@tonic-gate * Arguments: 6287c478bd9Sstevel@tonic-gate * stream The stream to write to 6297c478bd9Sstevel@tonic-gate * rec The structure containing the information to write 6307c478bd9Sstevel@tonic-gate * 6317c478bd9Sstevel@tonic-gate * Returns: int 6327c478bd9Sstevel@tonic-gate * The number of characters written or EOF if there was some error. 6337c478bd9Sstevel@tonic-gate */ 6347c478bd9Sstevel@tonic-gate 6357c478bd9Sstevel@tonic-gate int 6367c478bd9Sstevel@tonic-gate _putdevtabrec( 6377c478bd9Sstevel@tonic-gate FILE *stream, /* Stream to which to write */ 6387c478bd9Sstevel@tonic-gate struct devtabent *rec) /* Record to write */ 6397c478bd9Sstevel@tonic-gate { 6407c478bd9Sstevel@tonic-gate /* Automatic Data */ 6417c478bd9Sstevel@tonic-gate struct attrval *attrval; /* Ptr to attr/val pair */ 6427c478bd9Sstevel@tonic-gate char *buf; /* Allocated buffer */ 6437c478bd9Sstevel@tonic-gate char *p; /* Temp char pointer */ 6447c478bd9Sstevel@tonic-gate int count; /* Number of chars written */ 6457c478bd9Sstevel@tonic-gate size_t size = 0; /* Size of needed buffer */ 6467c478bd9Sstevel@tonic-gate 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate /* Comment or data record? */ 6497c478bd9Sstevel@tonic-gate if (rec->comment) { 6507c478bd9Sstevel@tonic-gate 6517c478bd9Sstevel@tonic-gate /* 6527c478bd9Sstevel@tonic-gate * Record is a comment 6537c478bd9Sstevel@tonic-gate */ 6547c478bd9Sstevel@tonic-gate 6557c478bd9Sstevel@tonic-gate /* Copy (escaping chars) record into temp buffer */ 6567c478bd9Sstevel@tonic-gate size = (strlen(rec->attrstr)*2)+1; /* Max rec size */ 6577c478bd9Sstevel@tonic-gate if (buf = malloc(size+1)) { 6587c478bd9Sstevel@tonic-gate /* Alloc space */ 6597c478bd9Sstevel@tonic-gate p = strcatesc(buf, rec->attrstr); /* Copy "escaped" */ 6607c478bd9Sstevel@tonic-gate *(p-2) = '\n'; /* Unescape last \n */ 6617c478bd9Sstevel@tonic-gate *(p-1) = '\0'; /* Terminate string */ 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate /* Write the record */ 6647c478bd9Sstevel@tonic-gate count = fputs(buf, stream); 6657c478bd9Sstevel@tonic-gate free(buf); 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate } else count = EOF; /* malloc() failed */ 6687c478bd9Sstevel@tonic-gate } 6697c478bd9Sstevel@tonic-gate 6707c478bd9Sstevel@tonic-gate else { 6717c478bd9Sstevel@tonic-gate 6727c478bd9Sstevel@tonic-gate /* 6737c478bd9Sstevel@tonic-gate * Record is a data record 6747c478bd9Sstevel@tonic-gate */ 6757c478bd9Sstevel@tonic-gate 6767c478bd9Sstevel@tonic-gate /* 6777c478bd9Sstevel@tonic-gate * Figure out maximum amount of space you're going to need. 6787c478bd9Sstevel@tonic-gate * (Assume every escapable character is escaped to determine the 6797c478bd9Sstevel@tonic-gate * maximum size needed) 6807c478bd9Sstevel@tonic-gate */ 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate if (rec->cdevice) 6837c478bd9Sstevel@tonic-gate size += (strlen(rec->cdevice)*2) + 1; /* cdevice: */ 6847c478bd9Sstevel@tonic-gate if (rec->bdevice) 6857c478bd9Sstevel@tonic-gate size += (strlen(rec->bdevice)*2) + 1; /* bdevice: */ 6867c478bd9Sstevel@tonic-gate if (rec->pathname) 6877c478bd9Sstevel@tonic-gate size += (strlen(rec->pathname)*2) + 1; /* pathname: */ 6887c478bd9Sstevel@tonic-gate if ((attrval = rec->attrlist) != NULL) do { /* Attributes */ 6897c478bd9Sstevel@tonic-gate if (attrval->attr) 6907c478bd9Sstevel@tonic-gate size += (strlen(attrval->attr)*2); /* attr */ 6917c478bd9Sstevel@tonic-gate if (attrval->val) { 6927c478bd9Sstevel@tonic-gate /* val & '="" ' or val & '=""\n' */ 6937c478bd9Sstevel@tonic-gate size += (strlen(attrval->val)*2) +4; 6947c478bd9Sstevel@tonic-gate } 6957c478bd9Sstevel@tonic-gate } while ((attrval = attrval->next) != NULL); /* Next attr/val */ 6967c478bd9Sstevel@tonic-gate else size++; /* Else make room for trailing '\n' */ 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate /* Alloc space for "escaped" record */ 6997c478bd9Sstevel@tonic-gate if (buf = malloc(size+1)) { 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate /* Initializations */ 7027c478bd9Sstevel@tonic-gate p = buf; 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate /* Write the alias ("alias" attribute) */ 7057c478bd9Sstevel@tonic-gate p = strcatesc(p, rec->alias); 7067c478bd9Sstevel@tonic-gate *p++ = ':'; 7077c478bd9Sstevel@tonic-gate 7087c478bd9Sstevel@tonic-gate /* Write the character device ("cdevice" attribute) */ 7097c478bd9Sstevel@tonic-gate if (rec->cdevice) p = strcatesc(p, rec->cdevice); 7107c478bd9Sstevel@tonic-gate *p++ = ':'; 7117c478bd9Sstevel@tonic-gate 7127c478bd9Sstevel@tonic-gate /* Write the block device ("bdevice" attribute) */ 7137c478bd9Sstevel@tonic-gate if (rec->bdevice) p = strcatesc(p, rec->bdevice); 7147c478bd9Sstevel@tonic-gate *p++ = ':'; 7157c478bd9Sstevel@tonic-gate 7167c478bd9Sstevel@tonic-gate /* Write the pathname ("pathname" attribute) */ 7177c478bd9Sstevel@tonic-gate if (rec->pathname) p = strcatesc(p, rec->pathname); 7187c478bd9Sstevel@tonic-gate *p++ = ':'; 7197c478bd9Sstevel@tonic-gate 7207c478bd9Sstevel@tonic-gate /* Write the rest of the attributes */ 7217c478bd9Sstevel@tonic-gate if ((attrval = rec->attrlist) != NULL) 7227c478bd9Sstevel@tonic-gate do { 7237c478bd9Sstevel@tonic-gate p = strcatesc(p, attrval->attr); 7247c478bd9Sstevel@tonic-gate *p++ = '='; 7257c478bd9Sstevel@tonic-gate *p++ = '"'; 7267c478bd9Sstevel@tonic-gate p = strcatesc(p, attrval->val); 7277c478bd9Sstevel@tonic-gate *p++ = '"'; 7287c478bd9Sstevel@tonic-gate if ((attrval = attrval->next) != NULL) 7297c478bd9Sstevel@tonic-gate *p++ = ' '; 7307c478bd9Sstevel@tonic-gate } while (attrval); 7317c478bd9Sstevel@tonic-gate 7327c478bd9Sstevel@tonic-gate /* Terminate the record */ 7337c478bd9Sstevel@tonic-gate *p++ = '\n'; 7347c478bd9Sstevel@tonic-gate *p = '\0'; 7357c478bd9Sstevel@tonic-gate 7367c478bd9Sstevel@tonic-gate /* Write the record */ 7377c478bd9Sstevel@tonic-gate count = fputs(buf, stream); 7387c478bd9Sstevel@tonic-gate free(buf); 7397c478bd9Sstevel@tonic-gate } else count = EOF; /* malloc() failed */ 7407c478bd9Sstevel@tonic-gate } 7417c478bd9Sstevel@tonic-gate 7427c478bd9Sstevel@tonic-gate /* Finished */ 7437c478bd9Sstevel@tonic-gate return (count); 7447c478bd9Sstevel@tonic-gate } 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate /* 7477c478bd9Sstevel@tonic-gate * int _adddevtabrec(alias, attrval) 7487c478bd9Sstevel@tonic-gate * char *alias 7497c478bd9Sstevel@tonic-gate * char **attrval 7507c478bd9Sstevel@tonic-gate * 7517c478bd9Sstevel@tonic-gate * This function adds a record to the device table. That record will 7527c478bd9Sstevel@tonic-gate * have the alias <alias> and will have the attributes described in 7537c478bd9Sstevel@tonic-gate * the list referenced by <attrval>. 7547c478bd9Sstevel@tonic-gate * 7557c478bd9Sstevel@tonic-gate * It always adds the record to the end of the table. 7567c478bd9Sstevel@tonic-gate * 7577c478bd9Sstevel@tonic-gate * Arguments: 7587c478bd9Sstevel@tonic-gate * alias The alias of the device whose description is being 7597c478bd9Sstevel@tonic-gate * added to the device table. 7607c478bd9Sstevel@tonic-gate * attrval The pointer to the first item of a list of attributes 7617c478bd9Sstevel@tonic-gate * defining the device whose description is being added. 7627c478bd9Sstevel@tonic-gate * (This value may be (char **) NULL). 7637c478bd9Sstevel@tonic-gate * 7647c478bd9Sstevel@tonic-gate * Returns: int 7657c478bd9Sstevel@tonic-gate * TRUE if successful, FALSE with errno set otherwise. 7667c478bd9Sstevel@tonic-gate */ 7677c478bd9Sstevel@tonic-gate 7687c478bd9Sstevel@tonic-gate int 7697c478bd9Sstevel@tonic-gate _adddevtabrec( 7707c478bd9Sstevel@tonic-gate char *alias, /* Alias to add to the device table */ 7717c478bd9Sstevel@tonic-gate char **attrval) /* Attributes for that device */ 7727c478bd9Sstevel@tonic-gate { 7737c478bd9Sstevel@tonic-gate /* Automatic data */ 7747c478bd9Sstevel@tonic-gate struct devtabent *devtabent; /* Ptr to dev tab entry */ 7757c478bd9Sstevel@tonic-gate int olderrno; /* Errno on entry */ 7767c478bd9Sstevel@tonic-gate int noerr; /* FLAG, TRUE if all's well */ 7777c478bd9Sstevel@tonic-gate 7787c478bd9Sstevel@tonic-gate /* Validate the device alias. Error (EINVAL) if it's not valid */ 7797c478bd9Sstevel@tonic-gate if (!_validalias(alias)) { 7807c478bd9Sstevel@tonic-gate errno = EINVAL; 7817c478bd9Sstevel@tonic-gate return (FALSE); 7827c478bd9Sstevel@tonic-gate } 7837c478bd9Sstevel@tonic-gate 7847c478bd9Sstevel@tonic-gate /* 7857c478bd9Sstevel@tonic-gate * Lock the device table. This only returns if the table is locked or 7867c478bd9Sstevel@tonic-gate * some error occurred. It waits until the table is available. 7877c478bd9Sstevel@tonic-gate */ 7887c478bd9Sstevel@tonic-gate if (!lkdevtab("a+", F_WRLCK)) 7897c478bd9Sstevel@tonic-gate return (FALSE); 7907c478bd9Sstevel@tonic-gate 7917c478bd9Sstevel@tonic-gate /* Make sure that the alias isn't already in the table */ 7927c478bd9Sstevel@tonic-gate noerr = TRUE; 7937c478bd9Sstevel@tonic-gate olderrno = errno; 7947c478bd9Sstevel@tonic-gate if (devtabent = _getdevrec(alias)) { 7957c478bd9Sstevel@tonic-gate 7967c478bd9Sstevel@tonic-gate /* The alias is already in the table */ 7977c478bd9Sstevel@tonic-gate _freedevtabent(devtabent); /* Free device table info */ 7987c478bd9Sstevel@tonic-gate errno = EEXIST; /* Set errno, entry exists */ 7997c478bd9Sstevel@tonic-gate noerr = FALSE; /* All's not well */ 8007c478bd9Sstevel@tonic-gate } else if ((errno == ENOENT) || (errno == ENODEV)) { 8017c478bd9Sstevel@tonic-gate 8027c478bd9Sstevel@tonic-gate /* The alias wasn't in the table or there wasn't a table. */ 8037c478bd9Sstevel@tonic-gate 8047c478bd9Sstevel@tonic-gate errno = olderrno; /* Reset errno */ 8057c478bd9Sstevel@tonic-gate 8067c478bd9Sstevel@tonic-gate /* Build a struct devtabent that describes the new alias */ 8077c478bd9Sstevel@tonic-gate if (devtabent = mkdevtabent(alias, attrval)) { 8087c478bd9Sstevel@tonic-gate 8097c478bd9Sstevel@tonic-gate /* Position to the end of the existing table */ 8107c478bd9Sstevel@tonic-gate if (fseek(oam_devtab, 0, SEEK_END) == 0) 8117c478bd9Sstevel@tonic-gate 8127c478bd9Sstevel@tonic-gate /* Write the new entry */ 8137c478bd9Sstevel@tonic-gate noerr = (_putdevtabrec(oam_devtab, devtabent) != EOF); 8147c478bd9Sstevel@tonic-gate 8157c478bd9Sstevel@tonic-gate /* Free the info we just wrote */ 8167c478bd9Sstevel@tonic-gate _freedevtabent(devtabent); 8177c478bd9Sstevel@tonic-gate 8187c478bd9Sstevel@tonic-gate } else noerr = FALSE; /* mkdevtabent() failed */ 8197c478bd9Sstevel@tonic-gate } else noerr = FALSE; /* Some odd error, _devtab */ 8207c478bd9Sstevel@tonic-gate 8217c478bd9Sstevel@tonic-gate /* Unlock and close the device table */ 8227c478bd9Sstevel@tonic-gate (void) unlkdevtab(); 8237c478bd9Sstevel@tonic-gate 8247c478bd9Sstevel@tonic-gate /* Fini */ 8257c478bd9Sstevel@tonic-gate return (noerr); 8267c478bd9Sstevel@tonic-gate } 8277c478bd9Sstevel@tonic-gate 8287c478bd9Sstevel@tonic-gate /* 8297c478bd9Sstevel@tonic-gate * int _moddevtabrec(device, attrval) 8307c478bd9Sstevel@tonic-gate * char *device 8317c478bd9Sstevel@tonic-gate * char **attrval 8327c478bd9Sstevel@tonic-gate * 8337c478bd9Sstevel@tonic-gate * This function modifies the description for the specified device 8347c478bd9Sstevel@tonic-gate * so that it has the attributes and values as specified in the 8357c478bd9Sstevel@tonic-gate * given list. 8367c478bd9Sstevel@tonic-gate * 8377c478bd9Sstevel@tonic-gate * Arguments: 8387c478bd9Sstevel@tonic-gate * device The name of the device whose description 8397c478bd9Sstevel@tonic-gate * is being modified 8407c478bd9Sstevel@tonic-gate * attrval The first attr/val value in the list (attr=val) of 8417c478bd9Sstevel@tonic-gate * the attributes that are to change 8427c478bd9Sstevel@tonic-gate * 8437c478bd9Sstevel@tonic-gate * Returns: int 8447c478bd9Sstevel@tonic-gate * TRUE if all went well, FALSE with errno set otherwise 8457c478bd9Sstevel@tonic-gate */ 8467c478bd9Sstevel@tonic-gate 8477c478bd9Sstevel@tonic-gate int 8487c478bd9Sstevel@tonic-gate _moddevtabrec( 8497c478bd9Sstevel@tonic-gate char *device, /* Device to modify */ 8507c478bd9Sstevel@tonic-gate char **attrval) /* Attributes to add or change */ 8517c478bd9Sstevel@tonic-gate { 8527c478bd9Sstevel@tonic-gate /* Automatic data */ 8537c478bd9Sstevel@tonic-gate FILE *fd; /* File ptr, new device table */ 8547c478bd9Sstevel@tonic-gate struct devtabent *ent; /* Device's current description */ 8557c478bd9Sstevel@tonic-gate struct devtabent *chg; /* Changes to make to description */ 8567c478bd9Sstevel@tonic-gate struct attrval *new; /* New attribute/value desc */ 8577c478bd9Sstevel@tonic-gate struct attrval *old; /* Old attribute/value desc */ 8587c478bd9Sstevel@tonic-gate struct attrval *newnew; /* Next "new" value to look at */ 8597c478bd9Sstevel@tonic-gate struct attrval *prevnew; /* Previous item in the 'new' list */ 8607c478bd9Sstevel@tonic-gate char *tname; /* name of temp devtab file */ 8617c478bd9Sstevel@tonic-gate int noerr; /* FLAG, TRUE if all's well */ 8627c478bd9Sstevel@tonic-gate int found; /* FLAG, TRUE if attr found for dev */ 8637c478bd9Sstevel@tonic-gate 8647c478bd9Sstevel@tonic-gate /* Lock the device table */ 8657c478bd9Sstevel@tonic-gate if (!lkdevtab("r", F_WRLCK)) 8667c478bd9Sstevel@tonic-gate return (FALSE); 8677c478bd9Sstevel@tonic-gate 8687c478bd9Sstevel@tonic-gate /* No problems (so far) */ 8697c478bd9Sstevel@tonic-gate noerr = TRUE; 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate /* Get the entry to modify */ 8727c478bd9Sstevel@tonic-gate if (ent = _getdevrec(device)) { 8737c478bd9Sstevel@tonic-gate 8747c478bd9Sstevel@tonic-gate /* Build a structure describing the changes */ 8757c478bd9Sstevel@tonic-gate if (chg = mkdevtabent(device, attrval)) { 8767c478bd9Sstevel@tonic-gate 8777c478bd9Sstevel@tonic-gate /* If the "cdevice" field is specified, change it */ 8787c478bd9Sstevel@tonic-gate if (chg->cdevice) { 8797c478bd9Sstevel@tonic-gate if (ent->cdevice) free(ent->cdevice); 8807c478bd9Sstevel@tonic-gate ent->cdevice = chg->cdevice; 8817c478bd9Sstevel@tonic-gate chg->cdevice = NULL; 8827c478bd9Sstevel@tonic-gate } 8837c478bd9Sstevel@tonic-gate 8847c478bd9Sstevel@tonic-gate /* If the "bdevice" field is specified, change it */ 8857c478bd9Sstevel@tonic-gate if (chg->bdevice) { 8867c478bd9Sstevel@tonic-gate if (ent->bdevice) free(ent->bdevice); 8877c478bd9Sstevel@tonic-gate ent->bdevice = chg->bdevice; 8887c478bd9Sstevel@tonic-gate chg->bdevice = NULL; 8897c478bd9Sstevel@tonic-gate } 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate /* If the "pathname" field is specified, change it */ 8927c478bd9Sstevel@tonic-gate if (chg->pathname) { 8937c478bd9Sstevel@tonic-gate if (ent->pathname) free(ent->pathname); 8947c478bd9Sstevel@tonic-gate ent->pathname = chg->pathname; 8957c478bd9Sstevel@tonic-gate chg->pathname = NULL; 8967c478bd9Sstevel@tonic-gate } 8977c478bd9Sstevel@tonic-gate 8987c478bd9Sstevel@tonic-gate /* Change the other attributes (if any) */ 8997c478bd9Sstevel@tonic-gate if (ent->attrlist) { 9007c478bd9Sstevel@tonic-gate prevnew = NULL; 9017c478bd9Sstevel@tonic-gate if ((new = chg->attrlist) != NULL) do { 9027c478bd9Sstevel@tonic-gate 9037c478bd9Sstevel@tonic-gate found = FALSE; 9047c478bd9Sstevel@tonic-gate for (old = ent->attrlist; !found && old; 9057c478bd9Sstevel@tonic-gate old = old->next) { 9067c478bd9Sstevel@tonic-gate if (strcmp(old->attr, new->attr) == 0) { 9077c478bd9Sstevel@tonic-gate found = TRUE; 9087c478bd9Sstevel@tonic-gate free(old->val); 9097c478bd9Sstevel@tonic-gate old->val = new->val; 9107c478bd9Sstevel@tonic-gate new->val = NULL; 9117c478bd9Sstevel@tonic-gate } 9127c478bd9Sstevel@tonic-gate } /* Loop through the existing attribute list */ 9137c478bd9Sstevel@tonic-gate 9147c478bd9Sstevel@tonic-gate /* 9157c478bd9Sstevel@tonic-gate * If the attribute wasn't found, add it to the list 9167c478bd9Sstevel@tonic-gate * of attributes for the device. If it was found, just 9177c478bd9Sstevel@tonic-gate * bump to the next one and look for it 9187c478bd9Sstevel@tonic-gate */ 9197c478bd9Sstevel@tonic-gate 9207c478bd9Sstevel@tonic-gate if (!found) { 9217c478bd9Sstevel@tonic-gate 9227c478bd9Sstevel@tonic-gate /* 9237c478bd9Sstevel@tonic-gate * Not found. Move attr/val description to the 9247c478bd9Sstevel@tonic-gate * device's list of attributes 9257c478bd9Sstevel@tonic-gate */ 9267c478bd9Sstevel@tonic-gate 9277c478bd9Sstevel@tonic-gate if (prevnew) prevnew->next = new->next; 9287c478bd9Sstevel@tonic-gate else chg->attrlist = new->next; 9297c478bd9Sstevel@tonic-gate newnew = new->next; 9307c478bd9Sstevel@tonic-gate new->next = ent->attrlist; 9317c478bd9Sstevel@tonic-gate ent->attrlist = new; 9327c478bd9Sstevel@tonic-gate new = newnew; 9337c478bd9Sstevel@tonic-gate } else { 9347c478bd9Sstevel@tonic-gate 9357c478bd9Sstevel@tonic-gate /* Attribute changed, bump to the next one */ 9367c478bd9Sstevel@tonic-gate prevnew = new; 9377c478bd9Sstevel@tonic-gate new = new->next; 9387c478bd9Sstevel@tonic-gate } 9397c478bd9Sstevel@tonic-gate } while (new); /* Loop for each attr to add or modify */ 9407c478bd9Sstevel@tonic-gate 9417c478bd9Sstevel@tonic-gate } else { 9427c478bd9Sstevel@tonic-gate 9437c478bd9Sstevel@tonic-gate /* Device had no attributes -- add entire list */ 9447c478bd9Sstevel@tonic-gate ent->attrlist = chg->attrlist; 9457c478bd9Sstevel@tonic-gate chg->attrlist = NULL; 9467c478bd9Sstevel@tonic-gate } 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate /* Free the structure containing the changes */ 9497c478bd9Sstevel@tonic-gate _freedevtabent(chg); 9507c478bd9Sstevel@tonic-gate 9517c478bd9Sstevel@tonic-gate } else noerr = FALSE; /* Couldn't build changes struct */ 9527c478bd9Sstevel@tonic-gate 9537c478bd9Sstevel@tonic-gate /* If there hasn't been an error (so far), write the new record */ 9547c478bd9Sstevel@tonic-gate if (noerr) { 9557c478bd9Sstevel@tonic-gate 9567c478bd9Sstevel@tonic-gate /* Open the new device table */ 9577c478bd9Sstevel@tonic-gate if (fd = opennewdevtab(&tname)) { 9587c478bd9Sstevel@tonic-gate 9597c478bd9Sstevel@tonic-gate /* 9607c478bd9Sstevel@tonic-gate * For each entry in the existing table, write that entry 9617c478bd9Sstevel@tonic-gate * to the new table. If the entry is the one being 9627c478bd9Sstevel@tonic-gate * modified, write the modified entry instead of the 9637c478bd9Sstevel@tonic-gate * original entry. 9647c478bd9Sstevel@tonic-gate */ 9657c478bd9Sstevel@tonic-gate 9667c478bd9Sstevel@tonic-gate _setdevtab(); /* Rewind existing table */ 9677c478bd9Sstevel@tonic-gate chg = ent; /* Remember new record */ 9687c478bd9Sstevel@tonic-gate while (((ent = _getdevtabent()) != NULL) && noerr) { 9697c478bd9Sstevel@tonic-gate if (ent->entryno != chg->entryno) 9707c478bd9Sstevel@tonic-gate noerr = _putdevtabrec(fd, ent) != EOF; 9717c478bd9Sstevel@tonic-gate else noerr = _putdevtabrec(fd, chg) != EOF; 9727c478bd9Sstevel@tonic-gate _freedevtabent(ent); 9737c478bd9Sstevel@tonic-gate } 9747c478bd9Sstevel@tonic-gate 9757c478bd9Sstevel@tonic-gate /* 9767c478bd9Sstevel@tonic-gate * If we successfully generated the new table, make it the 9777c478bd9Sstevel@tonic-gate * new system device table. Otherwise, just remove the 9787c478bd9Sstevel@tonic-gate * temporary file we've created. 9797c478bd9Sstevel@tonic-gate */ 9807c478bd9Sstevel@tonic-gate 9817c478bd9Sstevel@tonic-gate if (noerr) { 9827c478bd9Sstevel@tonic-gate (void) fclose(fd); 9837c478bd9Sstevel@tonic-gate noerr = mknewdevtab(tname); 9847c478bd9Sstevel@tonic-gate } else { 9857c478bd9Sstevel@tonic-gate (void) fclose(fd); 9867c478bd9Sstevel@tonic-gate (void) rmnewdevtab(tname); 9877c478bd9Sstevel@tonic-gate } 9887c478bd9Sstevel@tonic-gate 9897c478bd9Sstevel@tonic-gate /* Free the changed device structure */ 9907c478bd9Sstevel@tonic-gate _freedevtabent(chg); 9917c478bd9Sstevel@tonic-gate 9927c478bd9Sstevel@tonic-gate } /* if (_opennewdevtab()) */ 9937c478bd9Sstevel@tonic-gate else noerr = FALSE; 9947c478bd9Sstevel@tonic-gate 9957c478bd9Sstevel@tonic-gate } else _freedevtabent(ent); /* if (noerr) */ 9967c478bd9Sstevel@tonic-gate 9977c478bd9Sstevel@tonic-gate } else noerr = FALSE; /* Device not found? */ 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gate /* Finished. Unlock the device table and quit */ 10007c478bd9Sstevel@tonic-gate (void) unlkdevtab(); 10017c478bd9Sstevel@tonic-gate return (noerr); 10027c478bd9Sstevel@tonic-gate } 10037c478bd9Sstevel@tonic-gate 10047c478bd9Sstevel@tonic-gate /* 10057c478bd9Sstevel@tonic-gate * int _rmdevtabrec(device) 10067c478bd9Sstevel@tonic-gate * char *device 10077c478bd9Sstevel@tonic-gate * 10087c478bd9Sstevel@tonic-gate * This function removes the record in the device table for the specified 10097c478bd9Sstevel@tonic-gate * device. 10107c478bd9Sstevel@tonic-gate * 10117c478bd9Sstevel@tonic-gate * Arguments: 10127c478bd9Sstevel@tonic-gate * device The device (alias, cdevice, bdevice, pathname, or link to one) 10137c478bd9Sstevel@tonic-gate * whose entry is to be removed 10147c478bd9Sstevel@tonic-gate * 10157c478bd9Sstevel@tonic-gate * Returns: int 10167c478bd9Sstevel@tonic-gate * Success indicator: TRUE if successful, FALSE with errno set otherwise. 10177c478bd9Sstevel@tonic-gate */ 10187c478bd9Sstevel@tonic-gate 10197c478bd9Sstevel@tonic-gate int 10207c478bd9Sstevel@tonic-gate _rmdevtabrec(char *device) /* Device to remove */ 10217c478bd9Sstevel@tonic-gate { 10227c478bd9Sstevel@tonic-gate struct devtabent *rment; 10237c478bd9Sstevel@tonic-gate struct devtabent *devtabent; 10247c478bd9Sstevel@tonic-gate char *tempname; 10257c478bd9Sstevel@tonic-gate FILE *fd; 10267c478bd9Sstevel@tonic-gate int noerr; 10277c478bd9Sstevel@tonic-gate 10287c478bd9Sstevel@tonic-gate if (!lkdevtab("r", F_WRLCK)) 10297c478bd9Sstevel@tonic-gate return (FALSE); 10307c478bd9Sstevel@tonic-gate noerr = TRUE; 10317c478bd9Sstevel@tonic-gate if (rment = _getdevrec(device)) { 10327c478bd9Sstevel@tonic-gate if (fd = opennewdevtab(&tempname)) { 10337c478bd9Sstevel@tonic-gate _setdevtab(); 10347c478bd9Sstevel@tonic-gate while (((devtabent = _getdevtabent()) != NULL) && noerr) { 10357c478bd9Sstevel@tonic-gate if (devtabent->entryno != rment->entryno) 10367c478bd9Sstevel@tonic-gate noerr = _putdevtabrec(fd, devtabent) != EOF; 10377c478bd9Sstevel@tonic-gate _freedevtabent(devtabent); 10387c478bd9Sstevel@tonic-gate } 10397c478bd9Sstevel@tonic-gate if (noerr) { 10407c478bd9Sstevel@tonic-gate (void) fclose(fd); 10417c478bd9Sstevel@tonic-gate noerr = mknewdevtab(tempname); 10427c478bd9Sstevel@tonic-gate } else { 10437c478bd9Sstevel@tonic-gate (void) fclose(fd); 10447c478bd9Sstevel@tonic-gate (void) rmnewdevtab(tempname); 10457c478bd9Sstevel@tonic-gate } 10467c478bd9Sstevel@tonic-gate } else noerr = FALSE; 10477c478bd9Sstevel@tonic-gate _freedevtabent(rment); 10487c478bd9Sstevel@tonic-gate } else noerr = FALSE; 10497c478bd9Sstevel@tonic-gate (void) unlkdevtab(); 10507c478bd9Sstevel@tonic-gate return (noerr); 10517c478bd9Sstevel@tonic-gate } 10527c478bd9Sstevel@tonic-gate 10537c478bd9Sstevel@tonic-gate /* 10547c478bd9Sstevel@tonic-gate * int _rmdevtabattrs(device, attributes, notfounds) 10557c478bd9Sstevel@tonic-gate * char *device 10567c478bd9Sstevel@tonic-gate * char **attributes 10577c478bd9Sstevel@tonic-gate * char ***notfounds 10587c478bd9Sstevel@tonic-gate * 10597c478bd9Sstevel@tonic-gate * Remove the specified attributes from the specified device. The 10607c478bd9Sstevel@tonic-gate * device is specified by <device>, <attributes> is the address of 10617c478bd9Sstevel@tonic-gate * the first char * in the list of char * pointing to the attributes 10627c478bd9Sstevel@tonic-gate * to remove from the device, and <notfounds> is the address of a 10637c478bd9Sstevel@tonic-gate * char ** to put the address of the first element in the malloc()ed 10647c478bd9Sstevel@tonic-gate * list of (char *) pointing to requested attributes that were not 10657c478bd9Sstevel@tonic-gate * defined for the device <device>. 10667c478bd9Sstevel@tonic-gate * 10677c478bd9Sstevel@tonic-gate * Arguments: 10687c478bd9Sstevel@tonic-gate * device The device from which attributes are to be removed 10697c478bd9Sstevel@tonic-gate * attributes The address of the first element in the list of 10707c478bd9Sstevel@tonic-gate * attributes to remove. This list is terminated by 10717c478bd9Sstevel@tonic-gate * (char *) NULL. 10727c478bd9Sstevel@tonic-gate * notfounds The place to put the address of the list of addresses 10737c478bd9Sstevel@tonic-gate * referencing the requested attributes that are not 10747c478bd9Sstevel@tonic-gate * defined for the specified device. 10757c478bd9Sstevel@tonic-gate * 10767c478bd9Sstevel@tonic-gate * Returns: int 10777c478bd9Sstevel@tonic-gate * TRUE if successful, FALSE with errno set otherwise. 10787c478bd9Sstevel@tonic-gate * 10797c478bd9Sstevel@tonic-gate * Notes: 10807c478bd9Sstevel@tonic-gate * - "alias" may not be undefined 10817c478bd9Sstevel@tonic-gate * - "cdevice", "bdevice", and "pathname" are made "null", not really 10827c478bd9Sstevel@tonic-gate * undefined 10837c478bd9Sstevel@tonic-gate */ 10847c478bd9Sstevel@tonic-gate 10857c478bd9Sstevel@tonic-gate int 10867c478bd9Sstevel@tonic-gate _rmdevtabattrs( 10877c478bd9Sstevel@tonic-gate char *device, /* Device to modify */ 10887c478bd9Sstevel@tonic-gate char **attributes, /* Attributes to remove */ 10897c478bd9Sstevel@tonic-gate char ***notfounds) /* Attributes req'd but not found */ 10907c478bd9Sstevel@tonic-gate { 10917c478bd9Sstevel@tonic-gate /* Automatics */ 10927c478bd9Sstevel@tonic-gate char **pnxt; /* Ptr to next attribute */ 10937c478bd9Sstevel@tonic-gate char **pp; /* Ptr to current attr name */ 10947c478bd9Sstevel@tonic-gate struct devtabent *modent; /* Entry being modified */ 10957c478bd9Sstevel@tonic-gate struct devtabent *devtabent; /* Entry being copied */ 10967c478bd9Sstevel@tonic-gate struct attrval *attrval; /* Ptr to attr/val desc */ 10977c478bd9Sstevel@tonic-gate struct attrval *prevattrval; /* Ptr to prev attr/val */ 10987c478bd9Sstevel@tonic-gate FILE *fd; /* File desc, temp file */ 10997c478bd9Sstevel@tonic-gate char *tempname; /* Name of temp file */ 11007c478bd9Sstevel@tonic-gate int nattrs; /* Number of attrs to remove */ 11017c478bd9Sstevel@tonic-gate int nobaderr; /* TRUE if no fatal error */ 11027c478bd9Sstevel@tonic-gate int noerr; /* TRUE if no non-fatal error */ 11037c478bd9Sstevel@tonic-gate int found; /* TRUE if attribute found */ 11047c478bd9Sstevel@tonic-gate int nonotfounds; /* TRUE if no attrs not fount */ 11057c478bd9Sstevel@tonic-gate 11067c478bd9Sstevel@tonic-gate 11077c478bd9Sstevel@tonic-gate /* Initializations */ 11087c478bd9Sstevel@tonic-gate nobaderr = TRUE; 11097c478bd9Sstevel@tonic-gate noerr = TRUE; 11107c478bd9Sstevel@tonic-gate 11117c478bd9Sstevel@tonic-gate /* Count attributes to remove -- make sure "alias" isn't specified */ 11127c478bd9Sstevel@tonic-gate for (pp = attributes, nattrs = 0; *pp; pp++, nattrs++) 11137c478bd9Sstevel@tonic-gate if (strcmp(*pp, DTAB_ALIAS) == 0) { 11147c478bd9Sstevel@tonic-gate *notfounds = NULL; 11157c478bd9Sstevel@tonic-gate errno = EINVAL; 11167c478bd9Sstevel@tonic-gate return (FALSE); 11177c478bd9Sstevel@tonic-gate } 11187c478bd9Sstevel@tonic-gate 11197c478bd9Sstevel@tonic-gate /* Lock the device table */ 11207c478bd9Sstevel@tonic-gate if (!lkdevtab("r", F_WRLCK)) 11217c478bd9Sstevel@tonic-gate return (FALSE); 11227c478bd9Sstevel@tonic-gate 11237c478bd9Sstevel@tonic-gate /* Is there a record for the requested device? */ 11247c478bd9Sstevel@tonic-gate if (modent = _getdevrec(device)) { 11257c478bd9Sstevel@tonic-gate 11267c478bd9Sstevel@tonic-gate /* Record found. Try to modify it */ 11277c478bd9Sstevel@tonic-gate nonotfounds = TRUE; 11287c478bd9Sstevel@tonic-gate 11297c478bd9Sstevel@tonic-gate /* For each of the attributes in the attribute list ... */ 11307c478bd9Sstevel@tonic-gate for (pp = attributes; nobaderr && *pp; pp++) { 11317c478bd9Sstevel@tonic-gate 11327c478bd9Sstevel@tonic-gate /* 11337c478bd9Sstevel@tonic-gate * Modify the device description, removing the requested 11347c478bd9Sstevel@tonic-gate * attributes from the structure 11357c478bd9Sstevel@tonic-gate */ 11367c478bd9Sstevel@tonic-gate 11377c478bd9Sstevel@tonic-gate found = FALSE; /* Not found yet */ 11387c478bd9Sstevel@tonic-gate 11397c478bd9Sstevel@tonic-gate /* If it's the "cdevice" attribute, make it a null-string */ 11407c478bd9Sstevel@tonic-gate if (strcmp(*pp, DTAB_CDEVICE) == 0) { 11417c478bd9Sstevel@tonic-gate if (modent->cdevice) { 11427c478bd9Sstevel@tonic-gate free(modent->cdevice); 11437c478bd9Sstevel@tonic-gate modent->cdevice = NULL; 11447c478bd9Sstevel@tonic-gate } 11457c478bd9Sstevel@tonic-gate found = TRUE; 11467c478bd9Sstevel@tonic-gate } 11477c478bd9Sstevel@tonic-gate 11487c478bd9Sstevel@tonic-gate /* If it's the "bdevice" attribute, make it a null-string */ 11497c478bd9Sstevel@tonic-gate else if (strcmp(*pp, DTAB_BDEVICE) == 0) { 11507c478bd9Sstevel@tonic-gate if (modent->bdevice) { 11517c478bd9Sstevel@tonic-gate free(modent->bdevice); 11527c478bd9Sstevel@tonic-gate modent->bdevice = NULL; 11537c478bd9Sstevel@tonic-gate } 11547c478bd9Sstevel@tonic-gate found = TRUE; 11557c478bd9Sstevel@tonic-gate } 11567c478bd9Sstevel@tonic-gate 11577c478bd9Sstevel@tonic-gate /* If it's the "pathname" attribute, make it a null-string */ 11587c478bd9Sstevel@tonic-gate else if (strcmp(*pp, DTAB_PATHNAME) == 0) { 11597c478bd9Sstevel@tonic-gate if (modent->pathname) { 11607c478bd9Sstevel@tonic-gate free(modent->pathname); 11617c478bd9Sstevel@tonic-gate modent->pathname = NULL; 11627c478bd9Sstevel@tonic-gate } 11637c478bd9Sstevel@tonic-gate found = TRUE; 11647c478bd9Sstevel@tonic-gate } 11657c478bd9Sstevel@tonic-gate 11667c478bd9Sstevel@tonic-gate /* Must be one of the other "auxilliary" attributes */ 11677c478bd9Sstevel@tonic-gate else { 11687c478bd9Sstevel@tonic-gate 11697c478bd9Sstevel@tonic-gate /* Search the attribute list for the attribute */ 11707c478bd9Sstevel@tonic-gate prevattrval = NULL; 11717c478bd9Sstevel@tonic-gate if ((attrval = modent->attrlist) != NULL) do { 11727c478bd9Sstevel@tonic-gate if (strcmp(*pp, attrval->attr) == 0) { 11737c478bd9Sstevel@tonic-gate 11747c478bd9Sstevel@tonic-gate /* Found. Remove from attribute list */ 11757c478bd9Sstevel@tonic-gate found = TRUE; 11767c478bd9Sstevel@tonic-gate free(attrval->attr); 11777c478bd9Sstevel@tonic-gate free(attrval->val); 11787c478bd9Sstevel@tonic-gate if (prevattrval) { 11797c478bd9Sstevel@tonic-gate prevattrval->next = attrval->next; 11807c478bd9Sstevel@tonic-gate free(attrval); 11817c478bd9Sstevel@tonic-gate attrval = prevattrval->next; 11827c478bd9Sstevel@tonic-gate } else { 11837c478bd9Sstevel@tonic-gate modent->attrlist = attrval->next; 11847c478bd9Sstevel@tonic-gate free(attrval); 11857c478bd9Sstevel@tonic-gate attrval = modent->attrlist; 11867c478bd9Sstevel@tonic-gate } 11877c478bd9Sstevel@tonic-gate } else { 11887c478bd9Sstevel@tonic-gate prevattrval = attrval; /* Advance to next */ 11897c478bd9Sstevel@tonic-gate attrval = attrval->next; 11907c478bd9Sstevel@tonic-gate } 11917c478bd9Sstevel@tonic-gate } while (!found && attrval); 11927c478bd9Sstevel@tonic-gate 11937c478bd9Sstevel@tonic-gate } /* End attribute search loop */ 11947c478bd9Sstevel@tonic-gate 11957c478bd9Sstevel@tonic-gate /* 11967c478bd9Sstevel@tonic-gate * If the requested attribute wasn't defined for the device, 11977c478bd9Sstevel@tonic-gate * put it in the list of attributes not found 11987c478bd9Sstevel@tonic-gate */ 11997c478bd9Sstevel@tonic-gate 12007c478bd9Sstevel@tonic-gate if (!found) { 12017c478bd9Sstevel@tonic-gate 12027c478bd9Sstevel@tonic-gate /* 12037c478bd9Sstevel@tonic-gate * If there's no list (yet), alloc enough space for 12047c478bd9Sstevel@tonic-gate * the list 12057c478bd9Sstevel@tonic-gate */ 12067c478bd9Sstevel@tonic-gate 12077c478bd9Sstevel@tonic-gate if (nonotfounds) 12087c478bd9Sstevel@tonic-gate if (*notfounds = malloc(sizeof (char **)*(nattrs+1))) { 12097c478bd9Sstevel@tonic-gate 12107c478bd9Sstevel@tonic-gate /* List allocated -- put in the first entry */ 12117c478bd9Sstevel@tonic-gate nonotfounds = FALSE; 12127c478bd9Sstevel@tonic-gate pnxt = *notfounds; 12137c478bd9Sstevel@tonic-gate if (*pnxt = malloc(strlen(*pp)+1)) { 12147c478bd9Sstevel@tonic-gate errno = EINVAL; 12157c478bd9Sstevel@tonic-gate noerr = FALSE; 12167c478bd9Sstevel@tonic-gate (void) strcpy(*pnxt++, *pp); 12177c478bd9Sstevel@tonic-gate } else { 12187c478bd9Sstevel@tonic-gate /* malloc() failed, free list */ 12197c478bd9Sstevel@tonic-gate free(*notfounds); 12207c478bd9Sstevel@tonic-gate *notfounds = NULL; 12217c478bd9Sstevel@tonic-gate nonotfounds = TRUE; 12227c478bd9Sstevel@tonic-gate nobaderr = FALSE; 12237c478bd9Sstevel@tonic-gate } 12247c478bd9Sstevel@tonic-gate 12257c478bd9Sstevel@tonic-gate } else nobaderr = FALSE; /* malloc() failed */ 12267c478bd9Sstevel@tonic-gate 12277c478bd9Sstevel@tonic-gate else { 12287c478bd9Sstevel@tonic-gate /* Already a list, add this attribute to it */ 12297c478bd9Sstevel@tonic-gate if (*pnxt = malloc(strlen(*pp)+1)) 12307c478bd9Sstevel@tonic-gate (void) strcpy(*pnxt++, *pp); 12317c478bd9Sstevel@tonic-gate else { 12327c478bd9Sstevel@tonic-gate /* Out of memory, clean up */ 12337c478bd9Sstevel@tonic-gate for (pnxt = *notfounds; *pnxt; pnxt++) 12347c478bd9Sstevel@tonic-gate free(*pnxt); 12357c478bd9Sstevel@tonic-gate free(*notfounds); 12367c478bd9Sstevel@tonic-gate *notfounds = NULL; 12377c478bd9Sstevel@tonic-gate nonotfounds = TRUE; 12387c478bd9Sstevel@tonic-gate nobaderr = FALSE; 12397c478bd9Sstevel@tonic-gate } 12407c478bd9Sstevel@tonic-gate } 12417c478bd9Sstevel@tonic-gate 12427c478bd9Sstevel@tonic-gate } /* end if (!found) */ 12437c478bd9Sstevel@tonic-gate 12447c478bd9Sstevel@tonic-gate /* Terminate the not-found list */ 12457c478bd9Sstevel@tonic-gate if (!nonotfounds) *pnxt = NULL; 12467c478bd9Sstevel@tonic-gate 12477c478bd9Sstevel@tonic-gate } /* end (for each attribute in attribute list) loop */ 12487c478bd9Sstevel@tonic-gate 12497c478bd9Sstevel@tonic-gate 12507c478bd9Sstevel@tonic-gate /* 12517c478bd9Sstevel@tonic-gate * If we haven't seen any problems so far, 12527c478bd9Sstevel@tonic-gate * write the new device table 12537c478bd9Sstevel@tonic-gate */ 12547c478bd9Sstevel@tonic-gate 12557c478bd9Sstevel@tonic-gate if (nobaderr) { 12567c478bd9Sstevel@tonic-gate 12577c478bd9Sstevel@tonic-gate /* Open the new device table */ 12587c478bd9Sstevel@tonic-gate if (fd = opennewdevtab(&tempname)) { 12597c478bd9Sstevel@tonic-gate 12607c478bd9Sstevel@tonic-gate /* 12617c478bd9Sstevel@tonic-gate * For each entry in the existing table, write that entry 12627c478bd9Sstevel@tonic-gate * to the new table. If the entry is the one being 12637c478bd9Sstevel@tonic-gate * modified, write the modified entry instead of the 12647c478bd9Sstevel@tonic-gate * original entry. 12657c478bd9Sstevel@tonic-gate */ 12667c478bd9Sstevel@tonic-gate 12677c478bd9Sstevel@tonic-gate _setdevtab(); /* Rewind existing table */ 12687c478bd9Sstevel@tonic-gate while (((devtabent = _getdevtabent()) != NULL) && 12697c478bd9Sstevel@tonic-gate nobaderr) { 12707c478bd9Sstevel@tonic-gate 12717c478bd9Sstevel@tonic-gate if (devtabent->entryno != modent->entryno) 12727c478bd9Sstevel@tonic-gate nobaderr = _putdevtabrec(fd, devtabent) != EOF; 12737c478bd9Sstevel@tonic-gate else nobaderr = _putdevtabrec(fd, modent) != EOF; 12747c478bd9Sstevel@tonic-gate _freedevtabent(devtabent); 12757c478bd9Sstevel@tonic-gate } 12767c478bd9Sstevel@tonic-gate 12777c478bd9Sstevel@tonic-gate /* 12787c478bd9Sstevel@tonic-gate * If we successfully generated the new table, make it the 12797c478bd9Sstevel@tonic-gate * new system device table. Otherwise, just remove the 12807c478bd9Sstevel@tonic-gate * temporary file we've created. 12817c478bd9Sstevel@tonic-gate */ 12827c478bd9Sstevel@tonic-gate 12837c478bd9Sstevel@tonic-gate if (nobaderr) { 12847c478bd9Sstevel@tonic-gate (void) fclose(fd); 12857c478bd9Sstevel@tonic-gate nobaderr = mknewdevtab(tempname); 12867c478bd9Sstevel@tonic-gate } else { 12877c478bd9Sstevel@tonic-gate (void) fclose(fd); 12887c478bd9Sstevel@tonic-gate (void) rmnewdevtab(tempname); 12897c478bd9Sstevel@tonic-gate } 12907c478bd9Sstevel@tonic-gate 12917c478bd9Sstevel@tonic-gate } /* if (_opennewdevtab()) */ 12927c478bd9Sstevel@tonic-gate else nobaderr = FALSE; 12937c478bd9Sstevel@tonic-gate 12947c478bd9Sstevel@tonic-gate /* 12957c478bd9Sstevel@tonic-gate * If there was some error, we need to clean up 12967c478bd9Sstevel@tonic-gate * allocated resources 12977c478bd9Sstevel@tonic-gate */ 12987c478bd9Sstevel@tonic-gate if (!nobaderr && !nonotfounds) { 12997c478bd9Sstevel@tonic-gate for (pnxt = *notfounds; *pnxt; pnxt++) 13007c478bd9Sstevel@tonic-gate free(*pnxt); 13017c478bd9Sstevel@tonic-gate free(*notfounds); 13027c478bd9Sstevel@tonic-gate *notfounds = NULL; 13037c478bd9Sstevel@tonic-gate nonotfounds = TRUE; 13047c478bd9Sstevel@tonic-gate } 13057c478bd9Sstevel@tonic-gate 13067c478bd9Sstevel@tonic-gate } /* if (nobaderr) */ 13077c478bd9Sstevel@tonic-gate 13087c478bd9Sstevel@tonic-gate /* Free the resources alloc'ed for <device>'s entry */ 13097c478bd9Sstevel@tonic-gate _freedevtabent(modent); 13107c478bd9Sstevel@tonic-gate 13117c478bd9Sstevel@tonic-gate } else { 13127c478bd9Sstevel@tonic-gate /* _getdevrec(device) failed */ 13137c478bd9Sstevel@tonic-gate nobaderr = FALSE; 13147c478bd9Sstevel@tonic-gate *notfounds = NULL; 13157c478bd9Sstevel@tonic-gate } 13167c478bd9Sstevel@tonic-gate 13177c478bd9Sstevel@tonic-gate /* Unlock the device table */ 13187c478bd9Sstevel@tonic-gate (void) unlkdevtab(); 13197c478bd9Sstevel@tonic-gate 13207c478bd9Sstevel@tonic-gate /* We're finished */ 13217c478bd9Sstevel@tonic-gate return (noerr && nobaderr); 13227c478bd9Sstevel@tonic-gate } 1323