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 * putdgrp.c 35*7c478bd9Sstevel@tonic-gate * 36*7c478bd9Sstevel@tonic-gate * Global Definitions: 37*7c478bd9Sstevel@tonic-gate * _putdgrptabrec() Write a device-group record to a stream 38*7c478bd9Sstevel@tonic-gate * _rmdgrptabrec() Remove a device-group table record 39*7c478bd9Sstevel@tonic-gate * _rmdgrpmems() Remove specific members from a device group 40*7c478bd9Sstevel@tonic-gate * _adddgrptabrec() Add a device-group record to the table 41*7c478bd9Sstevel@tonic-gate */ 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate /* 44*7c478bd9Sstevel@tonic-gate * G L O B A L R E F E R E N C E S 45*7c478bd9Sstevel@tonic-gate * 46*7c478bd9Sstevel@tonic-gate * Header Files 47*7c478bd9Sstevel@tonic-gate * Externals Referenced 48*7c478bd9Sstevel@tonic-gate */ 49*7c478bd9Sstevel@tonic-gate 50*7c478bd9Sstevel@tonic-gate /* 51*7c478bd9Sstevel@tonic-gate * Header Files 52*7c478bd9Sstevel@tonic-gate * <sys/types.h> UNIX System Data Types 53*7c478bd9Sstevel@tonic-gate * <stdio.h> Standard I/O definitions 54*7c478bd9Sstevel@tonic-gate * <fcntl.h> Definitions for file control 55*7c478bd9Sstevel@tonic-gate * <errno.h> Error handling definitions 56*7c478bd9Sstevel@tonic-gate * <string.h> String Handling Definitions 57*7c478bd9Sstevel@tonic-gate * <unistd.h> Standard UNIX(r) Definitions 58*7c478bd9Sstevel@tonic-gate * <devmgmt.h> Device Management Definitions 59*7c478bd9Sstevel@tonic-gate * "devtab.h" Local Device Management Definitions 60*7c478bd9Sstevel@tonic-gate */ 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 63*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 64*7c478bd9Sstevel@tonic-gate #include <stdio.h> 65*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 66*7c478bd9Sstevel@tonic-gate #include <errno.h> 67*7c478bd9Sstevel@tonic-gate #include <string.h> 68*7c478bd9Sstevel@tonic-gate #include <unistd.h> 69*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 70*7c478bd9Sstevel@tonic-gate #include <devmgmt.h> 71*7c478bd9Sstevel@tonic-gate #include "devtab.h" 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate /* 74*7c478bd9Sstevel@tonic-gate * L O C A L D E F I N I T I O N S 75*7c478bd9Sstevel@tonic-gate * TDGTABNM Name of the temporary device-group table (in the 76*7c478bd9Sstevel@tonic-gate * directory of the existing table) 77*7c478bd9Sstevel@tonic-gate * TDGTABNMLN Number of characters added to the directory 78*7c478bd9Sstevel@tonic-gate * name -- the length of the device-group table temp name 79*7c478bd9Sstevel@tonic-gate */ 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate #define TDGTABNM "%sdgroup.%6.6d" 82*7c478bd9Sstevel@tonic-gate #define TDGTABNMLN 13 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate /* 86*7c478bd9Sstevel@tonic-gate * Static functions 87*7c478bd9Sstevel@tonic-gate * lkdgrptab Locks the device-group table 88*7c478bd9Sstevel@tonic-gate * unlkdgrptab Unlocks the device-group table 89*7c478bd9Sstevel@tonic-gate * mkdgrptabent Builds a device-group table entry from the alias and the 90*7c478bd9Sstevel@tonic-gate * list of attr=val pairs given 91*7c478bd9Sstevel@tonic-gate * opennewdgrptab Opens a new device-group table (as a temp file) 92*7c478bd9Sstevel@tonic-gate * mknewdgrptab Makes the temp device-group table the new dgrptab 93*7c478bd9Sstevel@tonic-gate * rmnewdgrptab Remove the temporary device-group table and free space 94*7c478bd9Sstevel@tonic-gate * allocated to the filename of that file. 95*7c478bd9Sstevel@tonic-gate */ 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate static int lkdgrptab(char *o_mode, short lktype); 98*7c478bd9Sstevel@tonic-gate static int unlkdgrptab(void); 99*7c478bd9Sstevel@tonic-gate static struct dgrptabent *mkdgrptabent(char *dgroup, char **members); 100*7c478bd9Sstevel@tonic-gate static FILE *opennewdgrptab(char **pname); 101*7c478bd9Sstevel@tonic-gate static int mknewdgrptab(char *tempname); 102*7c478bd9Sstevel@tonic-gate static int rmnewdgrptab(char *tempname); 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate /* 105*7c478bd9Sstevel@tonic-gate * FILE *opennewdgrptab(pname) 106*7c478bd9Sstevel@tonic-gate * char **pname 107*7c478bd9Sstevel@tonic-gate * 108*7c478bd9Sstevel@tonic-gate * Generates a temporary device-group table name from the existing 109*7c478bd9Sstevel@tonic-gate * device-group table name (in the same directory) and opens that 110*7c478bd9Sstevel@tonic-gate * file for writing. It puts a pointer to the malloc()ed space 111*7c478bd9Sstevel@tonic-gate * containing the temp device-group table's name at the place 112*7c478bd9Sstevel@tonic-gate * referenced by <pname>. 113*7c478bd9Sstevel@tonic-gate * 114*7c478bd9Sstevel@tonic-gate * Arguments: 115*7c478bd9Sstevel@tonic-gate * pname Pointer to the char * to contain the address of the name 116*7c478bd9Sstevel@tonic-gate * of the temporary file 117*7c478bd9Sstevel@tonic-gate * 118*7c478bd9Sstevel@tonic-gate * Returns: FILE * 119*7c478bd9Sstevel@tonic-gate * A pointer to the opened stream or (FILE *) NULL if an error occurred. 120*7c478bd9Sstevel@tonic-gate * If an error occurred, "errno" will be set to reflect the problem. 121*7c478bd9Sstevel@tonic-gate */ 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate static FILE * 124*7c478bd9Sstevel@tonic-gate opennewdgrptab(char **pname) /* A(ptr to temp filename's path) */ 125*7c478bd9Sstevel@tonic-gate { 126*7c478bd9Sstevel@tonic-gate char *oldname; /* Ptr to the dgrptab name */ 127*7c478bd9Sstevel@tonic-gate char *buf; /* Ptr to the temp file's name */ 128*7c478bd9Sstevel@tonic-gate char *dirname; /* Directory containing dgrptab */ 129*7c478bd9Sstevel@tonic-gate char *p; /* Ptr to last '/' in dgrptab name */ 130*7c478bd9Sstevel@tonic-gate int fd; /* Opened file descriptor */ 131*7c478bd9Sstevel@tonic-gate FILE *fp; /* Opened file pointer */ 132*7c478bd9Sstevel@tonic-gate struct stat64 sbuf; /* stat buf for old dgrptab file */ 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate /* Initializations */ 136*7c478bd9Sstevel@tonic-gate fp = NULL; 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate /* Get the name of the device-group table */ 139*7c478bd9Sstevel@tonic-gate if (oldname = _dgrptabpath()) { 140*7c478bd9Sstevel@tonic-gate /* 141*7c478bd9Sstevel@tonic-gate * It is possible for us to have sufficient permissions to create 142*7c478bd9Sstevel@tonic-gate * the new file without having sufficient permissions to write the 143*7c478bd9Sstevel@tonic-gate * original dgrptab file. For consistency with the operations which 144*7c478bd9Sstevel@tonic-gate * modify the original file by writing it directly we require write 145*7c478bd9Sstevel@tonic-gate * permissions for the original file in order to make a new one. 146*7c478bd9Sstevel@tonic-gate */ 147*7c478bd9Sstevel@tonic-gate if ((fd = open(oldname, O_WRONLY)) == -1) 148*7c478bd9Sstevel@tonic-gate return (NULL); 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate if (fstat64(fd, &sbuf) == -1) { 151*7c478bd9Sstevel@tonic-gate (void) close(fd); 152*7c478bd9Sstevel@tonic-gate return (NULL); 153*7c478bd9Sstevel@tonic-gate } 154*7c478bd9Sstevel@tonic-gate (void) close(fd); 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate /* Get the directory that the device-group table lives in */ 157*7c478bd9Sstevel@tonic-gate if (p = strrchr(oldname, '/')) { 158*7c478bd9Sstevel@tonic-gate *(p+1) = '\0'; 159*7c478bd9Sstevel@tonic-gate dirname = oldname; 160*7c478bd9Sstevel@tonic-gate } else 161*7c478bd9Sstevel@tonic-gate dirname = "./"; 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate /* Get space for the temp dgrptab pathname */ 164*7c478bd9Sstevel@tonic-gate if (buf = malloc(TDGTABNMLN+strlen(dirname)+1)) { 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate /* 167*7c478bd9Sstevel@tonic-gate * Build the name of the temp dgrptab and open the 168*7c478bd9Sstevel@tonic-gate * file. We must reset the owner, group and perms to those 169*7c478bd9Sstevel@tonic-gate * of the original dgrptab file. 170*7c478bd9Sstevel@tonic-gate */ 171*7c478bd9Sstevel@tonic-gate (void) sprintf(buf, TDGTABNM, dirname, getpid()); 172*7c478bd9Sstevel@tonic-gate if (fp = fopen(buf, "w")) { 173*7c478bd9Sstevel@tonic-gate *pname = buf; 174*7c478bd9Sstevel@tonic-gate (void) fchmod(fileno(fp), sbuf.st_mode & 0777); 175*7c478bd9Sstevel@tonic-gate (void) fchown(fileno(fp), sbuf.st_uid, sbuf.st_gid); 176*7c478bd9Sstevel@tonic-gate } else { 177*7c478bd9Sstevel@tonic-gate free(buf); 178*7c478bd9Sstevel@tonic-gate } 179*7c478bd9Sstevel@tonic-gate } 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate /* Free the space containing the dgrptab's name */ 182*7c478bd9Sstevel@tonic-gate free(oldname); 183*7c478bd9Sstevel@tonic-gate } 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate /* Finished. Return what we've got */ 186*7c478bd9Sstevel@tonic-gate return (fp); 187*7c478bd9Sstevel@tonic-gate } 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate /* 190*7c478bd9Sstevel@tonic-gate * int rmnewdgrptab(tempname) 191*7c478bd9Sstevel@tonic-gate * char *tempname 192*7c478bd9Sstevel@tonic-gate * 193*7c478bd9Sstevel@tonic-gate * Unlink the temp dgrptab and free the memory allocated to 194*7c478bd9Sstevel@tonic-gate * contain the name of that file 195*7c478bd9Sstevel@tonic-gate * 196*7c478bd9Sstevel@tonic-gate * Arguments: 197*7c478bd9Sstevel@tonic-gate * tempname Name of the temporary file 198*7c478bd9Sstevel@tonic-gate * 199*7c478bd9Sstevel@tonic-gate * Returns: int 200*7c478bd9Sstevel@tonic-gate * TRUE if successful, FALSE otherwise 201*7c478bd9Sstevel@tonic-gate */ 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate static int 204*7c478bd9Sstevel@tonic-gate rmnewdgrptab(char *tempname) 205*7c478bd9Sstevel@tonic-gate { 206*7c478bd9Sstevel@tonic-gate /* Automatic data */ 207*7c478bd9Sstevel@tonic-gate int noerr; 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate /* Unlink the temporary file */ 210*7c478bd9Sstevel@tonic-gate noerr = (unlink(tempname) == 0); 211*7c478bd9Sstevel@tonic-gate free(tempname); 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate /* Finished */ 214*7c478bd9Sstevel@tonic-gate return (noerr); 215*7c478bd9Sstevel@tonic-gate } 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate /* 218*7c478bd9Sstevel@tonic-gate * int mknewdgrptab(tempname) 219*7c478bd9Sstevel@tonic-gate * char *tempname 220*7c478bd9Sstevel@tonic-gate * 221*7c478bd9Sstevel@tonic-gate * Make the temporary device-group table the new system 222*7c478bd9Sstevel@tonic-gate * device-group table 223*7c478bd9Sstevel@tonic-gate * 224*7c478bd9Sstevel@tonic-gate * Arguments: 225*7c478bd9Sstevel@tonic-gate * tempname Name of the temporary file 226*7c478bd9Sstevel@tonic-gate * 227*7c478bd9Sstevel@tonic-gate * Returns: int 228*7c478bd9Sstevel@tonic-gate * TRUE if successful, FALSE otherwise 229*7c478bd9Sstevel@tonic-gate * 230*7c478bd9Sstevel@tonic-gate * Notes: 231*7c478bd9Sstevel@tonic-gate * - Need to use rename() someday instead of link()/unlink() 232*7c478bd9Sstevel@tonic-gate * - This code is somewhat ineffecient in that asks for the name 233*7c478bd9Sstevel@tonic-gate * of the device-group table more than once. Done so that we don't 234*7c478bd9Sstevel@tonic-gate * have to manage that space, but this may be somewhat lazy. 235*7c478bd9Sstevel@tonic-gate */ 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate static int 238*7c478bd9Sstevel@tonic-gate mknewdgrptab(char *tempname) /* Ptr to name of temp dgrp tab */ 239*7c478bd9Sstevel@tonic-gate { 240*7c478bd9Sstevel@tonic-gate char *dgrpname; /* Ptr to the dgrptab's name */ 241*7c478bd9Sstevel@tonic-gate int noerr; /* FLAG, TRUE if all's well */ 242*7c478bd9Sstevel@tonic-gate 243*7c478bd9Sstevel@tonic-gate /* Get the dgrptab's pathname */ 244*7c478bd9Sstevel@tonic-gate if (dgrpname = _dgrptabpath()) { 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate /* Unlink the existing file */ 247*7c478bd9Sstevel@tonic-gate if (unlink(dgrpname) == 0) { 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate /* Make the temp file the real device-group table */ 250*7c478bd9Sstevel@tonic-gate noerr = (link(tempname, dgrpname) == 0) ? TRUE : FALSE; 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate /* Remove the temp file */ 253*7c478bd9Sstevel@tonic-gate if (noerr) noerr = rmnewdgrptab(tempname); 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate } else noerr = FALSE; /* unlink() failed */ 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate /* Free the dgrptab's name */ 258*7c478bd9Sstevel@tonic-gate free(dgrpname); 259*7c478bd9Sstevel@tonic-gate 260*7c478bd9Sstevel@tonic-gate } else noerr = FALSE; /* dgrptabpath() failed */ 261*7c478bd9Sstevel@tonic-gate 262*7c478bd9Sstevel@tonic-gate /* Finished. Return success indicator */ 263*7c478bd9Sstevel@tonic-gate return (noerr); 264*7c478bd9Sstevel@tonic-gate } 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate /* 267*7c478bd9Sstevel@tonic-gate * int lkdgrptab(o_mode, lktype) 268*7c478bd9Sstevel@tonic-gate * char *o_mode 269*7c478bd9Sstevel@tonic-gate * short lktype 270*7c478bd9Sstevel@tonic-gate * 271*7c478bd9Sstevel@tonic-gate * Lock the device-group table for writing. If it isn't available, it 272*7c478bd9Sstevel@tonic-gate * waits until it is. 273*7c478bd9Sstevel@tonic-gate * 274*7c478bd9Sstevel@tonic-gate * Arguments: 275*7c478bd9Sstevel@tonic-gate * o_mode The open() mode to use when opening the device-group table 276*7c478bd9Sstevel@tonic-gate * lktype The type of lock to apply 277*7c478bd9Sstevel@tonic-gate * 278*7c478bd9Sstevel@tonic-gate * Returns: int 279*7c478bd9Sstevel@tonic-gate * TRUE if successful, FALSE with errno set otherwise 280*7c478bd9Sstevel@tonic-gate */ 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate static int 283*7c478bd9Sstevel@tonic-gate lkdgrptab( 284*7c478bd9Sstevel@tonic-gate char *o_mode, /* Open mode */ 285*7c478bd9Sstevel@tonic-gate short lktype) /* Lock type */ 286*7c478bd9Sstevel@tonic-gate { 287*7c478bd9Sstevel@tonic-gate /* Automatic data */ 288*7c478bd9Sstevel@tonic-gate struct flock lockinfo; /* File locking structure */ 289*7c478bd9Sstevel@tonic-gate int noerr; /* FLAG, TRUE if no error */ 290*7c478bd9Sstevel@tonic-gate int olderrno; /* Former value of errno */ 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate 293*7c478bd9Sstevel@tonic-gate /* Close the device-group table (if it's open) */ 294*7c478bd9Sstevel@tonic-gate _enddgrptab(); 295*7c478bd9Sstevel@tonic-gate 296*7c478bd9Sstevel@tonic-gate /* Open the device-group table for read/append */ 297*7c478bd9Sstevel@tonic-gate noerr = TRUE; 298*7c478bd9Sstevel@tonic-gate if (_opendgrptab(o_mode)) { 299*7c478bd9Sstevel@tonic-gate 300*7c478bd9Sstevel@tonic-gate /* 301*7c478bd9Sstevel@tonic-gate * Lock the device-group table (for writing). If it's not 302*7c478bd9Sstevel@tonic-gate * available, wait until it is, then close and open the 303*7c478bd9Sstevel@tonic-gate * table (modify and delete change the table!) and try 304*7c478bd9Sstevel@tonic-gate * to lock it again 305*7c478bd9Sstevel@tonic-gate */ 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate /* Build the locking structure */ 308*7c478bd9Sstevel@tonic-gate lockinfo.l_type = lktype; 309*7c478bd9Sstevel@tonic-gate lockinfo.l_whence = 0; 310*7c478bd9Sstevel@tonic-gate lockinfo.l_start = 0L; 311*7c478bd9Sstevel@tonic-gate lockinfo.l_len = 0L; 312*7c478bd9Sstevel@tonic-gate olderrno = errno; 313*7c478bd9Sstevel@tonic-gate 314*7c478bd9Sstevel@tonic-gate /* Keep on going until we lock the file or an error happens */ 315*7c478bd9Sstevel@tonic-gate while ((fcntl(fileno(oam_dgroup), F_SETLK, &lockinfo) == -1) && 316*7c478bd9Sstevel@tonic-gate !noerr) { 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate /* 319*7c478bd9Sstevel@tonic-gate * fcntl() failed. 320*7c478bd9Sstevel@tonic-gate * If errno=EACCES, it's because the file's locked by someone 321*7c478bd9Sstevel@tonic-gate * else. Wait for the file to be unlocked, then close and 322*7c478bd9Sstevel@tonic-gate * reopen the file and try the lock again. 323*7c478bd9Sstevel@tonic-gate */ 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate if (errno == EACCES) { 326*7c478bd9Sstevel@tonic-gate if (fcntl(fileno(oam_dgroup), F_SETLKW, &lockinfo) == -1) 327*7c478bd9Sstevel@tonic-gate noerr = FALSE; 328*7c478bd9Sstevel@tonic-gate else { 329*7c478bd9Sstevel@tonic-gate _enddgrptab(); 330*7c478bd9Sstevel@tonic-gate if (!_opendgrptab(o_mode)) noerr = FALSE; 331*7c478bd9Sstevel@tonic-gate else errno = olderrno; 332*7c478bd9Sstevel@tonic-gate } 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate } else noerr = FALSE; /* fcntl() failed hard */ 335*7c478bd9Sstevel@tonic-gate 336*7c478bd9Sstevel@tonic-gate } /* End while (fcntl() && !noerr) */ 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate /* Don't keep file open if an error happened */ 339*7c478bd9Sstevel@tonic-gate if (!noerr) _enddgrptab(); 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate } else noerr = FALSE; /* _opendgrptab() failed */ 342*7c478bd9Sstevel@tonic-gate 343*7c478bd9Sstevel@tonic-gate /* Done */ 344*7c478bd9Sstevel@tonic-gate return (noerr); 345*7c478bd9Sstevel@tonic-gate } 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate /* 348*7c478bd9Sstevel@tonic-gate * int unlkdgrptab() 349*7c478bd9Sstevel@tonic-gate * 350*7c478bd9Sstevel@tonic-gate * Unlock the locked device-group table. 351*7c478bd9Sstevel@tonic-gate * 352*7c478bd9Sstevel@tonic-gate * Arguments: None 353*7c478bd9Sstevel@tonic-gate * 354*7c478bd9Sstevel@tonic-gate * Returns: int 355*7c478bd9Sstevel@tonic-gate * Whatever fcntl() returns... 356*7c478bd9Sstevel@tonic-gate */ 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate static int 359*7c478bd9Sstevel@tonic-gate unlkdgrptab(void) 360*7c478bd9Sstevel@tonic-gate { 361*7c478bd9Sstevel@tonic-gate /* Automatic data */ 362*7c478bd9Sstevel@tonic-gate struct flock lockinfo; /* Locking structure */ 363*7c478bd9Sstevel@tonic-gate int noerr; /* FLAG, TRUE if all's well */ 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate /* Build the locking structure */ 366*7c478bd9Sstevel@tonic-gate lockinfo.l_type = F_UNLCK; /* Lock type */ 367*7c478bd9Sstevel@tonic-gate lockinfo.l_whence = 0; /* Count from top of file */ 368*7c478bd9Sstevel@tonic-gate lockinfo.l_start = 0L; /* From beginning */ 369*7c478bd9Sstevel@tonic-gate lockinfo.l_len = 0L; /* Length of locked data */ 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate /* Unlock it */ 372*7c478bd9Sstevel@tonic-gate noerr = (fcntl(fileno(oam_dgroup), F_SETLK, &lockinfo) != -1); 373*7c478bd9Sstevel@tonic-gate _enddgrptab(); 374*7c478bd9Sstevel@tonic-gate 375*7c478bd9Sstevel@tonic-gate /* Finished */ 376*7c478bd9Sstevel@tonic-gate return (noerr); 377*7c478bd9Sstevel@tonic-gate } 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate /* 380*7c478bd9Sstevel@tonic-gate * struct dgrptabent *mkdgrptabent(dgroup, members) 381*7c478bd9Sstevel@tonic-gate * char *dgroup 382*7c478bd9Sstevel@tonic-gate * char **members 383*7c478bd9Sstevel@tonic-gate * 384*7c478bd9Sstevel@tonic-gate * This function builds a struct dgrptabent structure describing the 385*7c478bd9Sstevel@tonic-gate * device-group <dgroup> so that it contains the members in the 386*7c478bd9Sstevel@tonic-gate * membership list <members>. 387*7c478bd9Sstevel@tonic-gate * 388*7c478bd9Sstevel@tonic-gate * Arguments: 389*7c478bd9Sstevel@tonic-gate * dgroup The device-group being added to the device-group table 390*7c478bd9Sstevel@tonic-gate * members The members of the device-group 391*7c478bd9Sstevel@tonic-gate * 392*7c478bd9Sstevel@tonic-gate * Returns: struct dgrptabent * 393*7c478bd9Sstevel@tonic-gate * A completed struct dgrptabent structure containing the description 394*7c478bd9Sstevel@tonic-gate * of the device group. The structure, and all of the data in the 395*7c478bd9Sstevel@tonic-gate * structure are each in space allocated using the malloc() function 396*7c478bd9Sstevel@tonic-gate * and should be freed using the free() function (or the _freedgrptabent() 397*7c478bd9Sstevel@tonic-gate * function. 398*7c478bd9Sstevel@tonic-gate */ 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate static struct dgrptabent * 401*7c478bd9Sstevel@tonic-gate mkdgrptabent( 402*7c478bd9Sstevel@tonic-gate char *dgroup, /* Device-group being created (or modified) */ 403*7c478bd9Sstevel@tonic-gate char **members) /* Members to add to that entry */ 404*7c478bd9Sstevel@tonic-gate { 405*7c478bd9Sstevel@tonic-gate /* Automatic data */ 406*7c478bd9Sstevel@tonic-gate struct dgrptabent *ent; /* Ptr to struct we're making */ 407*7c478bd9Sstevel@tonic-gate struct member *prev; /* Ptr to prev attr/val struct */ 408*7c478bd9Sstevel@tonic-gate struct member *member; /* Ptr to current struct */ 409*7c478bd9Sstevel@tonic-gate char **pp; /* Ptr into list of ptrs */ 410*7c478bd9Sstevel@tonic-gate int noerr; /* TRUE if all's well */ 411*7c478bd9Sstevel@tonic-gate 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate /* No problems (yet) */ 414*7c478bd9Sstevel@tonic-gate noerr = TRUE; 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate /* Get space for the structure */ 417*7c478bd9Sstevel@tonic-gate if (ent = malloc(sizeof (struct dgrptabent))) { 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate /* Fill in default values */ 420*7c478bd9Sstevel@tonic-gate ent->name = NULL; /* alias */ 421*7c478bd9Sstevel@tonic-gate ent->entryno = 0; /* Entry no. */ 422*7c478bd9Sstevel@tonic-gate ent->comment = FALSE; /* data rec */ 423*7c478bd9Sstevel@tonic-gate ent->dataspace = NULL; /* string */ 424*7c478bd9Sstevel@tonic-gate ent->membership = NULL; /* attr list */ 425*7c478bd9Sstevel@tonic-gate 426*7c478bd9Sstevel@tonic-gate /* Fill in the device-group name */ 427*7c478bd9Sstevel@tonic-gate if (ent->name = malloc(strlen(dgroup)+1)) { 428*7c478bd9Sstevel@tonic-gate (void) strcpy(ent->name, dgroup); 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate /* Add membership to the structure */ 431*7c478bd9Sstevel@tonic-gate prev = NULL; 432*7c478bd9Sstevel@tonic-gate if ((pp = members) != NULL) 433*7c478bd9Sstevel@tonic-gate while (*pp && noerr) { 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate if (member = malloc(sizeof (struct member))) { 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate if (member->name = malloc(strlen(*pp)+1)) { 438*7c478bd9Sstevel@tonic-gate (void) strcpy(member->name, *pp); 439*7c478bd9Sstevel@tonic-gate if (prev) prev->next = member; 440*7c478bd9Sstevel@tonic-gate else ent->membership = member; 441*7c478bd9Sstevel@tonic-gate member->next = NULL; 442*7c478bd9Sstevel@tonic-gate prev = member; 443*7c478bd9Sstevel@tonic-gate } else { 444*7c478bd9Sstevel@tonic-gate noerr = FALSE; 445*7c478bd9Sstevel@tonic-gate free(member); 446*7c478bd9Sstevel@tonic-gate } 447*7c478bd9Sstevel@tonic-gate } else noerr = FALSE; 448*7c478bd9Sstevel@tonic-gate pp++; 449*7c478bd9Sstevel@tonic-gate } /* End membership processing loop */ 450*7c478bd9Sstevel@tonic-gate 451*7c478bd9Sstevel@tonic-gate } else noerr = FALSE; /* malloc() failed */ 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate /* 454*7c478bd9Sstevel@tonic-gate * If there was a problem, clean up the mess we've made 455*7c478bd9Sstevel@tonic-gate */ 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate if (!noerr) { 458*7c478bd9Sstevel@tonic-gate 459*7c478bd9Sstevel@tonic-gate _freedgrptabent(ent); 460*7c478bd9Sstevel@tonic-gate ent = NULL; 461*7c478bd9Sstevel@tonic-gate 462*7c478bd9Sstevel@tonic-gate } /* if (noerr) */ 463*7c478bd9Sstevel@tonic-gate 464*7c478bd9Sstevel@tonic-gate } else noerr = FALSE; /* if (malloc(dgrptabent space)) */ 465*7c478bd9Sstevel@tonic-gate 466*7c478bd9Sstevel@tonic-gate /* Finished */ 467*7c478bd9Sstevel@tonic-gate return (ent); 468*7c478bd9Sstevel@tonic-gate } 469*7c478bd9Sstevel@tonic-gate 470*7c478bd9Sstevel@tonic-gate /* 471*7c478bd9Sstevel@tonic-gate * int _putdgrptabrec(stream, rec) 472*7c478bd9Sstevel@tonic-gate * FILE *stream 473*7c478bd9Sstevel@tonic-gate * struct dgrptabent *rec 474*7c478bd9Sstevel@tonic-gate * 475*7c478bd9Sstevel@tonic-gate * Write a device-group table record containing the information in the 476*7c478bd9Sstevel@tonic-gate * struct dgrptab structure <rec> to the current position of the 477*7c478bd9Sstevel@tonic-gate * standard I/O stream <stream>. 478*7c478bd9Sstevel@tonic-gate * 479*7c478bd9Sstevel@tonic-gate * Arguments: 480*7c478bd9Sstevel@tonic-gate * stream The stream to write to 481*7c478bd9Sstevel@tonic-gate * rec The structure containing the information to write 482*7c478bd9Sstevel@tonic-gate * 483*7c478bd9Sstevel@tonic-gate * Returns: int 484*7c478bd9Sstevel@tonic-gate * The number of characters written or EOF if there was some error. 485*7c478bd9Sstevel@tonic-gate */ 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate int 488*7c478bd9Sstevel@tonic-gate _putdgrptabrec( 489*7c478bd9Sstevel@tonic-gate FILE *stream, /* Stream to write to */ 490*7c478bd9Sstevel@tonic-gate struct dgrptabent *rec) /* Record to write */ 491*7c478bd9Sstevel@tonic-gate { 492*7c478bd9Sstevel@tonic-gate /* Automatic Data */ 493*7c478bd9Sstevel@tonic-gate struct member *mem; /* Ptr to attr/val pair */ 494*7c478bd9Sstevel@tonic-gate char *buf; /* Allocated buffer */ 495*7c478bd9Sstevel@tonic-gate char *p; /* Temp char pointer */ 496*7c478bd9Sstevel@tonic-gate char *q; /* Temp char pointer */ 497*7c478bd9Sstevel@tonic-gate int count; /* Number of chars written */ 498*7c478bd9Sstevel@tonic-gate int size; /* Size of needed buffer */ 499*7c478bd9Sstevel@tonic-gate 500*7c478bd9Sstevel@tonic-gate 501*7c478bd9Sstevel@tonic-gate /* Comment or data record? */ 502*7c478bd9Sstevel@tonic-gate if (rec->comment) count = fputs(rec->dataspace, stream); 503*7c478bd9Sstevel@tonic-gate else { 504*7c478bd9Sstevel@tonic-gate 505*7c478bd9Sstevel@tonic-gate /* 506*7c478bd9Sstevel@tonic-gate * Record is a data record 507*7c478bd9Sstevel@tonic-gate */ 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate /* Figure out the amount of space the record needs */ 510*7c478bd9Sstevel@tonic-gate size = (int)strlen(rec->name) + 1; /* "name:" */ 511*7c478bd9Sstevel@tonic-gate if ((mem = rec->membership) != NULL) 512*7c478bd9Sstevel@tonic-gate do { /* members */ 513*7c478bd9Sstevel@tonic-gate /* "membername " or "membername\n" */ 514*7c478bd9Sstevel@tonic-gate size += (int)strlen(mem->name) + 1; 515*7c478bd9Sstevel@tonic-gate } while ((mem = mem->next) != NULL); /* Next attr/val */ 516*7c478bd9Sstevel@tonic-gate else 517*7c478bd9Sstevel@tonic-gate size++; /* Count trailing '\n' if empty grp */ 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate 520*7c478bd9Sstevel@tonic-gate /* Alloc space for the record */ 521*7c478bd9Sstevel@tonic-gate if (buf = malloc((size_t) size+1)) { 522*7c478bd9Sstevel@tonic-gate 523*7c478bd9Sstevel@tonic-gate /* Initializations */ 524*7c478bd9Sstevel@tonic-gate p = buf; 525*7c478bd9Sstevel@tonic-gate 526*7c478bd9Sstevel@tonic-gate /* Write the device-group name */ 527*7c478bd9Sstevel@tonic-gate q = rec->name; 528*7c478bd9Sstevel@tonic-gate while (*q) *p++ = *q++; 529*7c478bd9Sstevel@tonic-gate *p++ = ':'; 530*7c478bd9Sstevel@tonic-gate 531*7c478bd9Sstevel@tonic-gate /* Write the membership list */ 532*7c478bd9Sstevel@tonic-gate if ((mem = rec->membership) != NULL) do { 533*7c478bd9Sstevel@tonic-gate q = mem->name; 534*7c478bd9Sstevel@tonic-gate while (*q) *p++ = *q++; 535*7c478bd9Sstevel@tonic-gate if ((mem = mem->next) != NULL) *p++ = ','; 536*7c478bd9Sstevel@tonic-gate } while (mem); 537*7c478bd9Sstevel@tonic-gate 538*7c478bd9Sstevel@tonic-gate /* Terminate the record */ 539*7c478bd9Sstevel@tonic-gate *p++ = '\n'; 540*7c478bd9Sstevel@tonic-gate *p = '\0'; 541*7c478bd9Sstevel@tonic-gate 542*7c478bd9Sstevel@tonic-gate /* Write the record */ 543*7c478bd9Sstevel@tonic-gate count = fputs(buf, stream); 544*7c478bd9Sstevel@tonic-gate free(buf); 545*7c478bd9Sstevel@tonic-gate } else 546*7c478bd9Sstevel@tonic-gate count = EOF; /* malloc() failed */ 547*7c478bd9Sstevel@tonic-gate } 548*7c478bd9Sstevel@tonic-gate 549*7c478bd9Sstevel@tonic-gate /* Finished */ 550*7c478bd9Sstevel@tonic-gate return (count); 551*7c478bd9Sstevel@tonic-gate } 552*7c478bd9Sstevel@tonic-gate 553*7c478bd9Sstevel@tonic-gate /* 554*7c478bd9Sstevel@tonic-gate * int _adddgrptabrec(dgrp, members) 555*7c478bd9Sstevel@tonic-gate * char *dgrp 556*7c478bd9Sstevel@tonic-gate * char **members 557*7c478bd9Sstevel@tonic-gate * 558*7c478bd9Sstevel@tonic-gate * If <dgrp> doesn't exist, this function adds a record to the 559*7c478bd9Sstevel@tonic-gate * device-group table for that device-group. That record will 560*7c478bd9Sstevel@tonic-gate * have the name <dgrp> and will have a membership described in 561*7c478bd9Sstevel@tonic-gate * the list referenced by <members>. The record is added to the 562*7c478bd9Sstevel@tonic-gate * end of the table. 563*7c478bd9Sstevel@tonic-gate * 564*7c478bd9Sstevel@tonic-gate * If <dgrp> already exists in the table, the function adds the 565*7c478bd9Sstevel@tonic-gate * members in the <members> list to the group's membership. 566*7c478bd9Sstevel@tonic-gate * 567*7c478bd9Sstevel@tonic-gate * Arguments: 568*7c478bd9Sstevel@tonic-gate * dgrp The name of the device-group being added to the 569*7c478bd9Sstevel@tonic-gate * device-group table. 570*7c478bd9Sstevel@tonic-gate * members A pointer to the first item of the list of members 571*7c478bd9Sstevel@tonic-gate * in the device-group being added to the table. 572*7c478bd9Sstevel@tonic-gate * (This value may be (char **) NULL). 573*7c478bd9Sstevel@tonic-gate * 574*7c478bd9Sstevel@tonic-gate * Returns: int 575*7c478bd9Sstevel@tonic-gate * TRUE if successful, FALSE with "errno" set otherwise. 576*7c478bd9Sstevel@tonic-gate */ 577*7c478bd9Sstevel@tonic-gate 578*7c478bd9Sstevel@tonic-gate int 579*7c478bd9Sstevel@tonic-gate _adddgrptabrec( 580*7c478bd9Sstevel@tonic-gate char *dgrp, /* Devgrp to add to the table */ 581*7c478bd9Sstevel@tonic-gate char **members) /* Members for that devgrp */ 582*7c478bd9Sstevel@tonic-gate { 583*7c478bd9Sstevel@tonic-gate /* Automatic data */ 584*7c478bd9Sstevel@tonic-gate struct dgrptabent *ent; /* Ptr to dev tab entry */ 585*7c478bd9Sstevel@tonic-gate struct dgrptabent *new; /* Ptr to new dev tab info */ 586*7c478bd9Sstevel@tonic-gate struct dgrptabent *p; /* Temp ptr to dev tab info */ 587*7c478bd9Sstevel@tonic-gate struct member *pm, *qm, *rm; /* Tmp ptrs to struct member */ 588*7c478bd9Sstevel@tonic-gate FILE *fd; /* File descr, temp file */ 589*7c478bd9Sstevel@tonic-gate char *path; /* Ptr to new devtab name */ 590*7c478bd9Sstevel@tonic-gate int olderrno; /* Errno on entry */ 591*7c478bd9Sstevel@tonic-gate int noerr; /* FLAG, TRUE if all's well */ 592*7c478bd9Sstevel@tonic-gate 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate /* Make a structure describing the new information */ 595*7c478bd9Sstevel@tonic-gate if ((new = mkdgrptabent(dgrp, members)) == NULL) 596*7c478bd9Sstevel@tonic-gate return (FALSE); 597*7c478bd9Sstevel@tonic-gate 598*7c478bd9Sstevel@tonic-gate /* 599*7c478bd9Sstevel@tonic-gate * Lock the device-group table. This only returns if the 600*7c478bd9Sstevel@tonic-gate * table is locked or some error occurred. It waits until the 601*7c478bd9Sstevel@tonic-gate * table is available. 602*7c478bd9Sstevel@tonic-gate */ 603*7c478bd9Sstevel@tonic-gate if (!lkdgrptab("a+", F_WRLCK)) { 604*7c478bd9Sstevel@tonic-gate _freedgrptabent(new); 605*7c478bd9Sstevel@tonic-gate return (FALSE); 606*7c478bd9Sstevel@tonic-gate } 607*7c478bd9Sstevel@tonic-gate 608*7c478bd9Sstevel@tonic-gate /* 609*7c478bd9Sstevel@tonic-gate * If the device-group is already in the table, add 610*7c478bd9Sstevel@tonic-gate * the specified members 611*7c478bd9Sstevel@tonic-gate */ 612*7c478bd9Sstevel@tonic-gate 613*7c478bd9Sstevel@tonic-gate noerr = TRUE; 614*7c478bd9Sstevel@tonic-gate olderrno = errno; 615*7c478bd9Sstevel@tonic-gate if (ent = _getdgrprec(dgrp)) { 616*7c478bd9Sstevel@tonic-gate 617*7c478bd9Sstevel@tonic-gate /* Any members to add? If not, do nothing. */ 618*7c478bd9Sstevel@tonic-gate if (new->membership) { 619*7c478bd9Sstevel@tonic-gate 620*7c478bd9Sstevel@tonic-gate /* Any existing members? */ 621*7c478bd9Sstevel@tonic-gate if ((pm = ent->membership) != NULL) { 622*7c478bd9Sstevel@tonic-gate 623*7c478bd9Sstevel@tonic-gate /* Find the end of the existing membership list */ 624*7c478bd9Sstevel@tonic-gate while (pm->next) pm = pm->next; 625*7c478bd9Sstevel@tonic-gate 626*7c478bd9Sstevel@tonic-gate /* Append the new members to the membership list */ 627*7c478bd9Sstevel@tonic-gate pm->next = new->membership; 628*7c478bd9Sstevel@tonic-gate 629*7c478bd9Sstevel@tonic-gate /* Remove any duplicates */ 630*7c478bd9Sstevel@tonic-gate for (pm = ent->membership; pm; pm = pm->next) { 631*7c478bd9Sstevel@tonic-gate qm = pm; 632*7c478bd9Sstevel@tonic-gate while ((rm = qm->next) != NULL) { 633*7c478bd9Sstevel@tonic-gate if (strcmp(pm->name, rm->name) == 0) { 634*7c478bd9Sstevel@tonic-gate qm->next = rm->next; 635*7c478bd9Sstevel@tonic-gate free(rm->name); 636*7c478bd9Sstevel@tonic-gate free(rm); 637*7c478bd9Sstevel@tonic-gate } else qm = rm; 638*7c478bd9Sstevel@tonic-gate } 639*7c478bd9Sstevel@tonic-gate } 640*7c478bd9Sstevel@tonic-gate } else ent->membership = new->membership; 641*7c478bd9Sstevel@tonic-gate 642*7c478bd9Sstevel@tonic-gate /* No members in the new list any more */ 643*7c478bd9Sstevel@tonic-gate new->membership = NULL; 644*7c478bd9Sstevel@tonic-gate 645*7c478bd9Sstevel@tonic-gate /* 646*7c478bd9Sstevel@tonic-gate * Make a new device-group table, replacing the 647*7c478bd9Sstevel@tonic-gate * record for the specified device-group 648*7c478bd9Sstevel@tonic-gate */ 649*7c478bd9Sstevel@tonic-gate 650*7c478bd9Sstevel@tonic-gate _setdgrptab(); /* Rewind existing table */ 651*7c478bd9Sstevel@tonic-gate 652*7c478bd9Sstevel@tonic-gate /* Open a temp file */ 653*7c478bd9Sstevel@tonic-gate if (fd = opennewdgrptab(&path)) { 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate /* While there's more records and no error ... */ 656*7c478bd9Sstevel@tonic-gate while (((p = _getdgrptabent()) != NULL) && noerr) { 657*7c478bd9Sstevel@tonic-gate 658*7c478bd9Sstevel@tonic-gate /* 659*7c478bd9Sstevel@tonic-gate * If this isn't the record we're replacing, 660*7c478bd9Sstevel@tonic-gate * write it to the temporary file. Otherwise, 661*7c478bd9Sstevel@tonic-gate * write the updated record 662*7c478bd9Sstevel@tonic-gate */ 663*7c478bd9Sstevel@tonic-gate 664*7c478bd9Sstevel@tonic-gate if (ent->entryno != p->entryno) 665*7c478bd9Sstevel@tonic-gate noerr = _putdgrptabrec(fd, p) != EOF; 666*7c478bd9Sstevel@tonic-gate else noerr = _putdgrptabrec(fd, ent) != EOF; 667*7c478bd9Sstevel@tonic-gate _freedgrptabent(p); 668*7c478bd9Sstevel@tonic-gate } 669*7c478bd9Sstevel@tonic-gate 670*7c478bd9Sstevel@tonic-gate /* Fix the files */ 671*7c478bd9Sstevel@tonic-gate if (noerr) { 672*7c478bd9Sstevel@tonic-gate (void) fclose(fd); 673*7c478bd9Sstevel@tonic-gate noerr = mknewdgrptab(path); 674*7c478bd9Sstevel@tonic-gate } else { 675*7c478bd9Sstevel@tonic-gate (void) fclose(fd); 676*7c478bd9Sstevel@tonic-gate (void) rmnewdgrptab(path); 677*7c478bd9Sstevel@tonic-gate } 678*7c478bd9Sstevel@tonic-gate } /* if (opennewdgrptab()) */ 679*7c478bd9Sstevel@tonic-gate 680*7c478bd9Sstevel@tonic-gate } /* If there's members to add */ 681*7c478bd9Sstevel@tonic-gate 682*7c478bd9Sstevel@tonic-gate /* Free the memory associated with the updated entry */ 683*7c478bd9Sstevel@tonic-gate _freedgrptabent(ent); 684*7c478bd9Sstevel@tonic-gate } 685*7c478bd9Sstevel@tonic-gate 686*7c478bd9Sstevel@tonic-gate /* 687*7c478bd9Sstevel@tonic-gate * Otherwise, add the device-group to the end of the table 688*7c478bd9Sstevel@tonic-gate */ 689*7c478bd9Sstevel@tonic-gate 690*7c478bd9Sstevel@tonic-gate else if (errno == EINVAL) { 691*7c478bd9Sstevel@tonic-gate errno = olderrno; 692*7c478bd9Sstevel@tonic-gate if (fseek(oam_dgroup, 0, SEEK_END) == 0) 693*7c478bd9Sstevel@tonic-gate noerr = (_putdgrptabrec(oam_dgroup, new) != EOF); 694*7c478bd9Sstevel@tonic-gate } else noerr = FALSE; 695*7c478bd9Sstevel@tonic-gate 696*7c478bd9Sstevel@tonic-gate /* Finished */ 697*7c478bd9Sstevel@tonic-gate (void) unlkdgrptab(); /* Unlock the file */ 698*7c478bd9Sstevel@tonic-gate _freedgrptabent(new); /* Free the new dgrptab info struct */ 699*7c478bd9Sstevel@tonic-gate return (noerr); /* Return with success indicator */ 700*7c478bd9Sstevel@tonic-gate } 701*7c478bd9Sstevel@tonic-gate 702*7c478bd9Sstevel@tonic-gate /* 703*7c478bd9Sstevel@tonic-gate * int _rmdgrptabrec(dgrp) 704*7c478bd9Sstevel@tonic-gate * char *dgrp 705*7c478bd9Sstevel@tonic-gate * 706*7c478bd9Sstevel@tonic-gate * This function removes the record in the device-group table 707*7c478bd9Sstevel@tonic-gate * for the specified device-group. 708*7c478bd9Sstevel@tonic-gate * 709*7c478bd9Sstevel@tonic-gate * Arguments: 710*7c478bd9Sstevel@tonic-gate * dgrp The device-group to be removed 711*7c478bd9Sstevel@tonic-gate * 712*7c478bd9Sstevel@tonic-gate * Returns: int 713*7c478bd9Sstevel@tonic-gate * Success indicator: TRUE if successful, FALSE with errno set otherwise. 714*7c478bd9Sstevel@tonic-gate */ 715*7c478bd9Sstevel@tonic-gate 716*7c478bd9Sstevel@tonic-gate int 717*7c478bd9Sstevel@tonic-gate _rmdgrptabrec(char *dgrp) /* Device-group to remove */ 718*7c478bd9Sstevel@tonic-gate { 719*7c478bd9Sstevel@tonic-gate /* Automatic data */ 720*7c478bd9Sstevel@tonic-gate struct dgrptabent *ent; /* Entry to remove */ 721*7c478bd9Sstevel@tonic-gate struct dgrptabent *p; /* Entry being copied */ 722*7c478bd9Sstevel@tonic-gate FILE *fd; /* Temp file's file descriptor */ 723*7c478bd9Sstevel@tonic-gate char *path; /* Pathname of temp file */ 724*7c478bd9Sstevel@tonic-gate int noerr; /* FLAG, TRUE if all's well */ 725*7c478bd9Sstevel@tonic-gate 726*7c478bd9Sstevel@tonic-gate noerr = TRUE; 727*7c478bd9Sstevel@tonic-gate if (!lkdgrptab("r", F_WRLCK)) 728*7c478bd9Sstevel@tonic-gate return (FALSE); 729*7c478bd9Sstevel@tonic-gate if (ent = _getdgrprec(dgrp)) { 730*7c478bd9Sstevel@tonic-gate _setdgrptab(); 731*7c478bd9Sstevel@tonic-gate if (fd = opennewdgrptab(&path)) { 732*7c478bd9Sstevel@tonic-gate while (((p = _getdgrptabent()) != NULL) && noerr) { 733*7c478bd9Sstevel@tonic-gate if (ent->entryno != p->entryno) 734*7c478bd9Sstevel@tonic-gate noerr = _putdgrptabrec(fd, p) != EOF; 735*7c478bd9Sstevel@tonic-gate _freedgrptabent(p); 736*7c478bd9Sstevel@tonic-gate } 737*7c478bd9Sstevel@tonic-gate if (noerr) { 738*7c478bd9Sstevel@tonic-gate (void) fclose(fd); 739*7c478bd9Sstevel@tonic-gate noerr = mknewdgrptab(path); 740*7c478bd9Sstevel@tonic-gate } else { 741*7c478bd9Sstevel@tonic-gate (void) fclose(fd); 742*7c478bd9Sstevel@tonic-gate (void) rmnewdgrptab(path); 743*7c478bd9Sstevel@tonic-gate } 744*7c478bd9Sstevel@tonic-gate } else noerr = FALSE; 745*7c478bd9Sstevel@tonic-gate _freedgrptabent(ent); 746*7c478bd9Sstevel@tonic-gate } else noerr = FALSE; 747*7c478bd9Sstevel@tonic-gate (void) unlkdgrptab(); 748*7c478bd9Sstevel@tonic-gate return (noerr); 749*7c478bd9Sstevel@tonic-gate } 750*7c478bd9Sstevel@tonic-gate 751*7c478bd9Sstevel@tonic-gate /* 752*7c478bd9Sstevel@tonic-gate * int _rmdgrpmems(dgrp, mems, notfounds) 753*7c478bd9Sstevel@tonic-gate * char *dgrp 754*7c478bd9Sstevel@tonic-gate * char **mems 755*7c478bd9Sstevel@tonic-gate * char ***notfounds 756*7c478bd9Sstevel@tonic-gate * 757*7c478bd9Sstevel@tonic-gate * Remove the specified members from the membership of the specified 758*7c478bd9Sstevel@tonic-gate * device-group. Any members not found in that device-group are 759*7c478bd9Sstevel@tonic-gate * returned in the list referenced by <notfounds>. 760*7c478bd9Sstevel@tonic-gate * 761*7c478bd9Sstevel@tonic-gate * Arguments: 762*7c478bd9Sstevel@tonic-gate * dgrp The device-group from which members are to be removed 763*7c478bd9Sstevel@tonic-gate * mems The address of the first element in the list of 764*7c478bd9Sstevel@tonic-gate * members to remove. This list is terminated by 765*7c478bd9Sstevel@tonic-gate * (char *) NULL. 766*7c478bd9Sstevel@tonic-gate * notfounds The place to put the address of the list of addresses 767*7c478bd9Sstevel@tonic-gate * referencing the requested members that were not 768*7c478bd9Sstevel@tonic-gate * members of the specified device-group 769*7c478bd9Sstevel@tonic-gate * 770*7c478bd9Sstevel@tonic-gate * Returns: int 771*7c478bd9Sstevel@tonic-gate * TRUE if successful, FALSE with errno set otherwise. 772*7c478bd9Sstevel@tonic-gate */ 773*7c478bd9Sstevel@tonic-gate 774*7c478bd9Sstevel@tonic-gate int 775*7c478bd9Sstevel@tonic-gate _rmdgrpmems( 776*7c478bd9Sstevel@tonic-gate char *dgrp, /* Device-group to modify */ 777*7c478bd9Sstevel@tonic-gate char **mems, /* Members to remove */ 778*7c478bd9Sstevel@tonic-gate char ***notfounds) /* Members req'd but not found */ 779*7c478bd9Sstevel@tonic-gate { 780*7c478bd9Sstevel@tonic-gate /* Automatic data */ 781*7c478bd9Sstevel@tonic-gate struct dgrptabent *ent; /* Entry to modify */ 782*7c478bd9Sstevel@tonic-gate struct dgrptabent *p; /* Entry being copied */ 783*7c478bd9Sstevel@tonic-gate struct member *pm; /* Ptr to member being examined */ 784*7c478bd9Sstevel@tonic-gate struct member *prev; /* Ptr to previous member */ 785*7c478bd9Sstevel@tonic-gate char **nflst; /* Ptr to not-found list */ 786*7c478bd9Sstevel@tonic-gate char **pnf; /* Ptr into not-found list */ 787*7c478bd9Sstevel@tonic-gate char **pp; /* Ptr into members-to-rm list */ 788*7c478bd9Sstevel@tonic-gate FILE *fd; /* Temp file's file descriptor */ 789*7c478bd9Sstevel@tonic-gate char *path; /* Pathname of temp file */ 790*7c478bd9Sstevel@tonic-gate int noerr; /* TRUE if all's well */ 791*7c478bd9Sstevel@tonic-gate int found; /* TRUE if member is in membership */ 792*7c478bd9Sstevel@tonic-gate int i; /* Temp counter */ 793*7c478bd9Sstevel@tonic-gate 794*7c478bd9Sstevel@tonic-gate noerr = TRUE; 795*7c478bd9Sstevel@tonic-gate 796*7c478bd9Sstevel@tonic-gate /* Lock the device-group table */ 797*7c478bd9Sstevel@tonic-gate if (!lkdgrptab("r", F_WRLCK)) 798*7c478bd9Sstevel@tonic-gate return (FALSE); 799*7c478bd9Sstevel@tonic-gate 800*7c478bd9Sstevel@tonic-gate /* Nothing is "not found" yet */ 801*7c478bd9Sstevel@tonic-gate *notfounds = NULL; 802*7c478bd9Sstevel@tonic-gate 803*7c478bd9Sstevel@tonic-gate /* Get the entry we're to modify */ 804*7c478bd9Sstevel@tonic-gate if (ent = _getdgrprec(dgrp)) { 805*7c478bd9Sstevel@tonic-gate 806*7c478bd9Sstevel@tonic-gate /* Allocate space for the not-found list */ 807*7c478bd9Sstevel@tonic-gate i = 1; 808*7c478bd9Sstevel@tonic-gate if (mems) 809*7c478bd9Sstevel@tonic-gate for (pp = mems; *pp; pp++) 810*7c478bd9Sstevel@tonic-gate i++; 811*7c478bd9Sstevel@tonic-gate if (nflst = malloc(i*sizeof (char *))) { 812*7c478bd9Sstevel@tonic-gate pnf = nflst; 813*7c478bd9Sstevel@tonic-gate *pnf = NULL; 814*7c478bd9Sstevel@tonic-gate 815*7c478bd9Sstevel@tonic-gate /* For each member to remove ... (if any) */ 816*7c478bd9Sstevel@tonic-gate if (mems) 817*7c478bd9Sstevel@tonic-gate for (pp = mems; *pp; pp++) { 818*7c478bd9Sstevel@tonic-gate 819*7c478bd9Sstevel@tonic-gate found = FALSE; 820*7c478bd9Sstevel@tonic-gate 821*7c478bd9Sstevel@tonic-gate /* Compare against each member in the membership list */ 822*7c478bd9Sstevel@tonic-gate pm = ent->membership; 823*7c478bd9Sstevel@tonic-gate prev = NULL; 824*7c478bd9Sstevel@tonic-gate while (pm && !found) { 825*7c478bd9Sstevel@tonic-gate 826*7c478bd9Sstevel@tonic-gate if (strcmp(*pp, pm->name) == 0) { 827*7c478bd9Sstevel@tonic-gate 828*7c478bd9Sstevel@tonic-gate /* Found. Remove from linked list */ 829*7c478bd9Sstevel@tonic-gate if (prev) prev->next = pm->next; 830*7c478bd9Sstevel@tonic-gate else ent->membership = pm->next; 831*7c478bd9Sstevel@tonic-gate if (pm->name) free(pm->name); 832*7c478bd9Sstevel@tonic-gate free(pm); 833*7c478bd9Sstevel@tonic-gate found = TRUE; 834*7c478bd9Sstevel@tonic-gate 835*7c478bd9Sstevel@tonic-gate } else { 836*7c478bd9Sstevel@tonic-gate 837*7c478bd9Sstevel@tonic-gate /* Bump to the next member */ 838*7c478bd9Sstevel@tonic-gate prev = pm; 839*7c478bd9Sstevel@tonic-gate pm = pm->next; 840*7c478bd9Sstevel@tonic-gate 841*7c478bd9Sstevel@tonic-gate } 842*7c478bd9Sstevel@tonic-gate 843*7c478bd9Sstevel@tonic-gate } /* For each member in the group */ 844*7c478bd9Sstevel@tonic-gate 845*7c478bd9Sstevel@tonic-gate /* 846*7c478bd9Sstevel@tonic-gate * If the requested member-to-remove wasn't found, 847*7c478bd9Sstevel@tonic-gate * add it to the list of not-found members 848*7c478bd9Sstevel@tonic-gate */ 849*7c478bd9Sstevel@tonic-gate if (!found) { 850*7c478bd9Sstevel@tonic-gate if (*pnf = malloc(strlen(*pp)+1)) { 851*7c478bd9Sstevel@tonic-gate (void) strcpy(*pnf++, *pp); 852*7c478bd9Sstevel@tonic-gate *pnf = NULL; 853*7c478bd9Sstevel@tonic-gate } else noerr = FALSE; 854*7c478bd9Sstevel@tonic-gate } 855*7c478bd9Sstevel@tonic-gate 856*7c478bd9Sstevel@tonic-gate } /* for (each requested member to remove */ 857*7c478bd9Sstevel@tonic-gate 858*7c478bd9Sstevel@tonic-gate _setdgrptab(); /* Rewind existing table */ 859*7c478bd9Sstevel@tonic-gate 860*7c478bd9Sstevel@tonic-gate if (fd = opennewdgrptab(&path)) { 861*7c478bd9Sstevel@tonic-gate while (((p = _getdgrptabent()) != NULL) && noerr) { 862*7c478bd9Sstevel@tonic-gate if (ent->entryno != p->entryno) 863*7c478bd9Sstevel@tonic-gate noerr = _putdgrptabrec(fd, p) != EOF; 864*7c478bd9Sstevel@tonic-gate else noerr = _putdgrptabrec(fd, ent) != EOF; 865*7c478bd9Sstevel@tonic-gate _freedgrptabent(p); 866*7c478bd9Sstevel@tonic-gate } 867*7c478bd9Sstevel@tonic-gate if (noerr) { 868*7c478bd9Sstevel@tonic-gate (void) fclose(fd); 869*7c478bd9Sstevel@tonic-gate noerr = mknewdgrptab(path); 870*7c478bd9Sstevel@tonic-gate } else { 871*7c478bd9Sstevel@tonic-gate (void) fclose(fd); 872*7c478bd9Sstevel@tonic-gate (void) rmnewdgrptab(path); 873*7c478bd9Sstevel@tonic-gate } 874*7c478bd9Sstevel@tonic-gate } else noerr = FALSE; /* if (opennewdgrptab()) */ 875*7c478bd9Sstevel@tonic-gate 876*7c478bd9Sstevel@tonic-gate /* 877*7c478bd9Sstevel@tonic-gate * If there was no error but there was requested members 878*7c478bd9Sstevel@tonic-gate * that weren't found, set the not-found list and the error 879*7c478bd9Sstevel@tonic-gate * information. Otherwise, free the not-found list 880*7c478bd9Sstevel@tonic-gate */ 881*7c478bd9Sstevel@tonic-gate 882*7c478bd9Sstevel@tonic-gate if (noerr && (pnf != nflst)) { 883*7c478bd9Sstevel@tonic-gate *notfounds = nflst; 884*7c478bd9Sstevel@tonic-gate errno = ENODEV; 885*7c478bd9Sstevel@tonic-gate noerr = FALSE; 886*7c478bd9Sstevel@tonic-gate } else { 887*7c478bd9Sstevel@tonic-gate for (pnf = nflst; *pnf; pnf++) free(*pnf); 888*7c478bd9Sstevel@tonic-gate free(nflst); 889*7c478bd9Sstevel@tonic-gate if (!noerr) *notfounds = NULL; 890*7c478bd9Sstevel@tonic-gate } 891*7c478bd9Sstevel@tonic-gate } else noerr = FALSE; 892*7c478bd9Sstevel@tonic-gate 893*7c478bd9Sstevel@tonic-gate /* Free the description of the modified device group */ 894*7c478bd9Sstevel@tonic-gate _freedgrptabent(ent); 895*7c478bd9Sstevel@tonic-gate 896*7c478bd9Sstevel@tonic-gate } else noerr = FALSE; /* _getdgrprec() failed */ 897*7c478bd9Sstevel@tonic-gate 898*7c478bd9Sstevel@tonic-gate /* Unlock the original device-group table */ 899*7c478bd9Sstevel@tonic-gate (void) unlkdgrptab(); 900*7c478bd9Sstevel@tonic-gate return (noerr); 901*7c478bd9Sstevel@tonic-gate } 902