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 * putdgrp.c
377c478bd9Sstevel@tonic-gate *
387c478bd9Sstevel@tonic-gate * Global Definitions:
397c478bd9Sstevel@tonic-gate * _putdgrptabrec() Write a device-group record to a stream
407c478bd9Sstevel@tonic-gate * _rmdgrptabrec() Remove a device-group table record
417c478bd9Sstevel@tonic-gate * _rmdgrpmems() Remove specific members from a device group
427c478bd9Sstevel@tonic-gate * _adddgrptabrec() Add a device-group record to the table
437c478bd9Sstevel@tonic-gate */
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate /*
467c478bd9Sstevel@tonic-gate * G L O B A L R E F E R E N C E S
477c478bd9Sstevel@tonic-gate *
487c478bd9Sstevel@tonic-gate * Header Files
497c478bd9Sstevel@tonic-gate * Externals Referenced
507c478bd9Sstevel@tonic-gate */
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate /*
537c478bd9Sstevel@tonic-gate * Header Files
547c478bd9Sstevel@tonic-gate * <sys/types.h> UNIX System Data Types
557c478bd9Sstevel@tonic-gate * <stdio.h> Standard I/O definitions
567c478bd9Sstevel@tonic-gate * <fcntl.h> Definitions for file control
577c478bd9Sstevel@tonic-gate * <errno.h> Error handling definitions
587c478bd9Sstevel@tonic-gate * <string.h> String Handling Definitions
597c478bd9Sstevel@tonic-gate * <unistd.h> Standard UNIX(r) Definitions
607c478bd9Sstevel@tonic-gate * <devmgmt.h> Device Management Definitions
617c478bd9Sstevel@tonic-gate * "devtab.h" Local Device Management Definitions
627c478bd9Sstevel@tonic-gate */
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate #include <sys/types.h>
657c478bd9Sstevel@tonic-gate #include <sys/stat.h>
667c478bd9Sstevel@tonic-gate #include <stdio.h>
677c478bd9Sstevel@tonic-gate #include <fcntl.h>
687c478bd9Sstevel@tonic-gate #include <errno.h>
697c478bd9Sstevel@tonic-gate #include <string.h>
707c478bd9Sstevel@tonic-gate #include <unistd.h>
717c478bd9Sstevel@tonic-gate #include <stdlib.h>
727c478bd9Sstevel@tonic-gate #include <devmgmt.h>
737c478bd9Sstevel@tonic-gate #include "devtab.h"
747c478bd9Sstevel@tonic-gate
757c478bd9Sstevel@tonic-gate /*
767c478bd9Sstevel@tonic-gate * L O C A L D E F I N I T I O N S
777c478bd9Sstevel@tonic-gate * TDGTABNM Name of the temporary device-group table (in the
787c478bd9Sstevel@tonic-gate * directory of the existing table)
797c478bd9Sstevel@tonic-gate */
807c478bd9Sstevel@tonic-gate
817c478bd9Sstevel@tonic-gate #define TDGTABNM "%sdgroup.%6.6d"
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate
847c478bd9Sstevel@tonic-gate /*
857c478bd9Sstevel@tonic-gate * Static functions
867c478bd9Sstevel@tonic-gate * lkdgrptab Locks the device-group table
877c478bd9Sstevel@tonic-gate * unlkdgrptab Unlocks the device-group table
887c478bd9Sstevel@tonic-gate * mkdgrptabent Builds a device-group table entry from the alias and the
897c478bd9Sstevel@tonic-gate * list of attr=val pairs given
907c478bd9Sstevel@tonic-gate * opennewdgrptab Opens a new device-group table (as a temp file)
917c478bd9Sstevel@tonic-gate * mknewdgrptab Makes the temp device-group table the new dgrptab
927c478bd9Sstevel@tonic-gate * rmnewdgrptab Remove the temporary device-group table and free space
937c478bd9Sstevel@tonic-gate * allocated to the filename of that file.
947c478bd9Sstevel@tonic-gate */
957c478bd9Sstevel@tonic-gate
967c478bd9Sstevel@tonic-gate static int lkdgrptab(char *o_mode, short lktype);
977c478bd9Sstevel@tonic-gate static int unlkdgrptab(void);
987c478bd9Sstevel@tonic-gate static struct dgrptabent *mkdgrptabent(char *dgroup, char **members);
997c478bd9Sstevel@tonic-gate static FILE *opennewdgrptab(char **pname);
1007c478bd9Sstevel@tonic-gate static int mknewdgrptab(char *tempname);
1017c478bd9Sstevel@tonic-gate static int rmnewdgrptab(char *tempname);
1027c478bd9Sstevel@tonic-gate
1037c478bd9Sstevel@tonic-gate /*
1047c478bd9Sstevel@tonic-gate * FILE *opennewdgrptab(pname)
1057c478bd9Sstevel@tonic-gate * char **pname
1067c478bd9Sstevel@tonic-gate *
1077c478bd9Sstevel@tonic-gate * Generates a temporary device-group table name from the existing
1087c478bd9Sstevel@tonic-gate * device-group table name (in the same directory) and opens that
1097c478bd9Sstevel@tonic-gate * file for writing. It puts a pointer to the malloc()ed space
1107c478bd9Sstevel@tonic-gate * containing the temp device-group table's name at the place
1117c478bd9Sstevel@tonic-gate * referenced by <pname>.
1127c478bd9Sstevel@tonic-gate *
1137c478bd9Sstevel@tonic-gate * Arguments:
1147c478bd9Sstevel@tonic-gate * pname Pointer to the char * to contain the address of the name
1157c478bd9Sstevel@tonic-gate * of the temporary file
1167c478bd9Sstevel@tonic-gate *
1177c478bd9Sstevel@tonic-gate * Returns: FILE *
1187c478bd9Sstevel@tonic-gate * A pointer to the opened stream or (FILE *) NULL if an error occurred.
1197c478bd9Sstevel@tonic-gate * If an error occurred, "errno" will be set to reflect the problem.
1207c478bd9Sstevel@tonic-gate */
1217c478bd9Sstevel@tonic-gate
1227c478bd9Sstevel@tonic-gate static FILE *
opennewdgrptab(char ** pname)1237c478bd9Sstevel@tonic-gate opennewdgrptab(char **pname) /* A(ptr to temp filename's path) */
1247c478bd9Sstevel@tonic-gate {
1257c478bd9Sstevel@tonic-gate char *oldname; /* Ptr to the dgrptab name */
1267c478bd9Sstevel@tonic-gate char *buf; /* Ptr to the temp file's name */
1277c478bd9Sstevel@tonic-gate char *dirname; /* Directory containing dgrptab */
1287c478bd9Sstevel@tonic-gate char *p; /* Ptr to last '/' in dgrptab name */
1297c478bd9Sstevel@tonic-gate int fd; /* Opened file descriptor */
1307c478bd9Sstevel@tonic-gate FILE *fp; /* Opened file pointer */
1317c478bd9Sstevel@tonic-gate struct stat64 sbuf; /* stat buf for old dgrptab file */
1327c478bd9Sstevel@tonic-gate
1337c478bd9Sstevel@tonic-gate
1347c478bd9Sstevel@tonic-gate /* Initializations */
1357c478bd9Sstevel@tonic-gate fp = NULL;
1367c478bd9Sstevel@tonic-gate
1377c478bd9Sstevel@tonic-gate /* Get the name of the device-group table */
1387c478bd9Sstevel@tonic-gate if (oldname = _dgrptabpath()) {
1397c478bd9Sstevel@tonic-gate /*
140*4656d474SGarrett D'Amore * It is possible for us to have sufficient
141*4656d474SGarrett D'Amore * permissions to create the new file without having
142*4656d474SGarrett D'Amore * sufficient permissions to write the original
143*4656d474SGarrett D'Amore * dgrptab file. For consistency with the operations
144*4656d474SGarrett D'Amore * which modify the original file by writing it
145*4656d474SGarrett D'Amore * directly we require write permissions for the
146*4656d474SGarrett D'Amore * original file in order to make a new one.
1477c478bd9Sstevel@tonic-gate */
1487c478bd9Sstevel@tonic-gate if ((fd = open(oldname, O_WRONLY)) == -1)
1497c478bd9Sstevel@tonic-gate return (NULL);
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate if (fstat64(fd, &sbuf) == -1) {
1527c478bd9Sstevel@tonic-gate (void) close(fd);
1537c478bd9Sstevel@tonic-gate return (NULL);
1547c478bd9Sstevel@tonic-gate }
1557c478bd9Sstevel@tonic-gate (void) close(fd);
1567c478bd9Sstevel@tonic-gate
1577c478bd9Sstevel@tonic-gate /* Get the directory that the device-group table lives in */
1587c478bd9Sstevel@tonic-gate if (p = strrchr(oldname, '/')) {
1597c478bd9Sstevel@tonic-gate *(p+1) = '\0';
1607c478bd9Sstevel@tonic-gate dirname = oldname;
1617c478bd9Sstevel@tonic-gate } else
1627c478bd9Sstevel@tonic-gate dirname = "./";
1637c478bd9Sstevel@tonic-gate
1647c478bd9Sstevel@tonic-gate /* Get space for the temp dgrptab pathname */
165*4656d474SGarrett D'Amore if (asprintf(&buf, TDGTABNM, dirname, getpid()) >= 0) {
1667c478bd9Sstevel@tonic-gate /*
167*4656d474SGarrett D'Amore * Build the name of the temp dgrptab and open
168*4656d474SGarrett D'Amore * the file. We must reset the owner, group
169*4656d474SGarrett D'Amore * and perms to those of the original dgrptab
170*4656d474SGarrett D'Amore * file.
1717c478bd9Sstevel@tonic-gate */
1727c478bd9Sstevel@tonic-gate if (fp = fopen(buf, "w")) {
1737c478bd9Sstevel@tonic-gate *pname = buf;
1747c478bd9Sstevel@tonic-gate (void) fchmod(fileno(fp), sbuf.st_mode & 0777);
175*4656d474SGarrett D'Amore (void) fchown(fileno(fp), sbuf.st_uid,
176*4656d474SGarrett D'Amore sbuf.st_gid);
1777c478bd9Sstevel@tonic-gate } else {
1787c478bd9Sstevel@tonic-gate free(buf);
1797c478bd9Sstevel@tonic-gate }
1807c478bd9Sstevel@tonic-gate }
1817c478bd9Sstevel@tonic-gate
1827c478bd9Sstevel@tonic-gate /* Free the space containing the dgrptab's name */
1837c478bd9Sstevel@tonic-gate free(oldname);
1847c478bd9Sstevel@tonic-gate }
1857c478bd9Sstevel@tonic-gate
1867c478bd9Sstevel@tonic-gate /* Finished. Return what we've got */
1877c478bd9Sstevel@tonic-gate return (fp);
1887c478bd9Sstevel@tonic-gate }
1897c478bd9Sstevel@tonic-gate
1907c478bd9Sstevel@tonic-gate /*
1917c478bd9Sstevel@tonic-gate * int rmnewdgrptab(tempname)
1927c478bd9Sstevel@tonic-gate * char *tempname
1937c478bd9Sstevel@tonic-gate *
1947c478bd9Sstevel@tonic-gate * Unlink the temp dgrptab and free the memory allocated to
1957c478bd9Sstevel@tonic-gate * contain the name of that file
1967c478bd9Sstevel@tonic-gate *
1977c478bd9Sstevel@tonic-gate * Arguments:
1987c478bd9Sstevel@tonic-gate * tempname Name of the temporary file
1997c478bd9Sstevel@tonic-gate *
2007c478bd9Sstevel@tonic-gate * Returns: int
2017c478bd9Sstevel@tonic-gate * TRUE if successful, FALSE otherwise
2027c478bd9Sstevel@tonic-gate */
2037c478bd9Sstevel@tonic-gate
2047c478bd9Sstevel@tonic-gate static int
rmnewdgrptab(char * tempname)2057c478bd9Sstevel@tonic-gate rmnewdgrptab(char *tempname)
2067c478bd9Sstevel@tonic-gate {
2077c478bd9Sstevel@tonic-gate /* Automatic data */
2087c478bd9Sstevel@tonic-gate int noerr;
2097c478bd9Sstevel@tonic-gate
2107c478bd9Sstevel@tonic-gate /* Unlink the temporary file */
2117c478bd9Sstevel@tonic-gate noerr = (unlink(tempname) == 0);
2127c478bd9Sstevel@tonic-gate free(tempname);
2137c478bd9Sstevel@tonic-gate
2147c478bd9Sstevel@tonic-gate /* Finished */
2157c478bd9Sstevel@tonic-gate return (noerr);
2167c478bd9Sstevel@tonic-gate }
2177c478bd9Sstevel@tonic-gate
2187c478bd9Sstevel@tonic-gate /*
2197c478bd9Sstevel@tonic-gate * int mknewdgrptab(tempname)
2207c478bd9Sstevel@tonic-gate * char *tempname
2217c478bd9Sstevel@tonic-gate *
2227c478bd9Sstevel@tonic-gate * Make the temporary device-group table the new system
2237c478bd9Sstevel@tonic-gate * device-group table
2247c478bd9Sstevel@tonic-gate *
2257c478bd9Sstevel@tonic-gate * Arguments:
2267c478bd9Sstevel@tonic-gate * tempname Name of the temporary file
2277c478bd9Sstevel@tonic-gate *
2287c478bd9Sstevel@tonic-gate * Returns: int
2297c478bd9Sstevel@tonic-gate * TRUE if successful, FALSE otherwise
2307c478bd9Sstevel@tonic-gate *
2317c478bd9Sstevel@tonic-gate * Notes:
2327c478bd9Sstevel@tonic-gate * - Need to use rename() someday instead of link()/unlink()
2337c478bd9Sstevel@tonic-gate * - This code is somewhat ineffecient in that asks for the name
2347c478bd9Sstevel@tonic-gate * of the device-group table more than once. Done so that we don't
2357c478bd9Sstevel@tonic-gate * have to manage that space, but this may be somewhat lazy.
2367c478bd9Sstevel@tonic-gate */
2377c478bd9Sstevel@tonic-gate
2387c478bd9Sstevel@tonic-gate static int
mknewdgrptab(char * tempname)2397c478bd9Sstevel@tonic-gate mknewdgrptab(char *tempname) /* Ptr to name of temp dgrp tab */
2407c478bd9Sstevel@tonic-gate {
2417c478bd9Sstevel@tonic-gate char *dgrpname; /* Ptr to the dgrptab's name */
2427c478bd9Sstevel@tonic-gate int noerr; /* FLAG, TRUE if all's well */
2437c478bd9Sstevel@tonic-gate
2447c478bd9Sstevel@tonic-gate /* Get the dgrptab's pathname */
2457c478bd9Sstevel@tonic-gate if (dgrpname = _dgrptabpath()) {
2467c478bd9Sstevel@tonic-gate
2477c478bd9Sstevel@tonic-gate /* Unlink the existing file */
2487c478bd9Sstevel@tonic-gate if (unlink(dgrpname) == 0) {
2497c478bd9Sstevel@tonic-gate
2507c478bd9Sstevel@tonic-gate /* Make the temp file the real device-group table */
2517c478bd9Sstevel@tonic-gate noerr = (link(tempname, dgrpname) == 0) ? TRUE : FALSE;
2527c478bd9Sstevel@tonic-gate
2537c478bd9Sstevel@tonic-gate /* Remove the temp file */
254*4656d474SGarrett D'Amore if (noerr)
255*4656d474SGarrett D'Amore noerr = rmnewdgrptab(tempname);
2567c478bd9Sstevel@tonic-gate
257*4656d474SGarrett D'Amore } else {
258*4656d474SGarrett D'Amore noerr = FALSE; /* unlink() failed */
259*4656d474SGarrett D'Amore }
2607c478bd9Sstevel@tonic-gate
2617c478bd9Sstevel@tonic-gate /* Free the dgrptab's name */
2627c478bd9Sstevel@tonic-gate free(dgrpname);
2637c478bd9Sstevel@tonic-gate
264*4656d474SGarrett D'Amore } else {
265*4656d474SGarrett D'Amore noerr = FALSE; /* dgrptabpath() failed */
266*4656d474SGarrett D'Amore }
2677c478bd9Sstevel@tonic-gate
2687c478bd9Sstevel@tonic-gate /* Finished. Return success indicator */
2697c478bd9Sstevel@tonic-gate return (noerr);
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate /*
2737c478bd9Sstevel@tonic-gate * int lkdgrptab(o_mode, lktype)
2747c478bd9Sstevel@tonic-gate * char *o_mode
2757c478bd9Sstevel@tonic-gate * short lktype
2767c478bd9Sstevel@tonic-gate *
2777c478bd9Sstevel@tonic-gate * Lock the device-group table for writing. If it isn't available, it
2787c478bd9Sstevel@tonic-gate * waits until it is.
2797c478bd9Sstevel@tonic-gate *
2807c478bd9Sstevel@tonic-gate * Arguments:
2817c478bd9Sstevel@tonic-gate * o_mode The open() mode to use when opening the device-group table
2827c478bd9Sstevel@tonic-gate * lktype The type of lock to apply
2837c478bd9Sstevel@tonic-gate *
2847c478bd9Sstevel@tonic-gate * Returns: int
2857c478bd9Sstevel@tonic-gate * TRUE if successful, FALSE with errno set otherwise
2867c478bd9Sstevel@tonic-gate */
2877c478bd9Sstevel@tonic-gate
2887c478bd9Sstevel@tonic-gate static int
lkdgrptab(char * o_mode,short lktype)2897c478bd9Sstevel@tonic-gate lkdgrptab(
2907c478bd9Sstevel@tonic-gate char *o_mode, /* Open mode */
2917c478bd9Sstevel@tonic-gate short lktype) /* Lock type */
2927c478bd9Sstevel@tonic-gate {
2937c478bd9Sstevel@tonic-gate /* Automatic data */
2947c478bd9Sstevel@tonic-gate struct flock lockinfo; /* File locking structure */
2957c478bd9Sstevel@tonic-gate int noerr; /* FLAG, TRUE if no error */
2967c478bd9Sstevel@tonic-gate int olderrno; /* Former value of errno */
2977c478bd9Sstevel@tonic-gate
2987c478bd9Sstevel@tonic-gate
2997c478bd9Sstevel@tonic-gate /* Close the device-group table (if it's open) */
3007c478bd9Sstevel@tonic-gate _enddgrptab();
3017c478bd9Sstevel@tonic-gate
3027c478bd9Sstevel@tonic-gate /* Open the device-group table for read/append */
3037c478bd9Sstevel@tonic-gate noerr = TRUE;
3047c478bd9Sstevel@tonic-gate if (_opendgrptab(o_mode)) {
3057c478bd9Sstevel@tonic-gate
3067c478bd9Sstevel@tonic-gate /*
3077c478bd9Sstevel@tonic-gate * Lock the device-group table (for writing). If it's not
3087c478bd9Sstevel@tonic-gate * available, wait until it is, then close and open the
3097c478bd9Sstevel@tonic-gate * table (modify and delete change the table!) and try
3107c478bd9Sstevel@tonic-gate * to lock it again
3117c478bd9Sstevel@tonic-gate */
3127c478bd9Sstevel@tonic-gate
3137c478bd9Sstevel@tonic-gate /* Build the locking structure */
3147c478bd9Sstevel@tonic-gate lockinfo.l_type = lktype;
3157c478bd9Sstevel@tonic-gate lockinfo.l_whence = 0;
3167c478bd9Sstevel@tonic-gate lockinfo.l_start = 0L;
3177c478bd9Sstevel@tonic-gate lockinfo.l_len = 0L;
3187c478bd9Sstevel@tonic-gate olderrno = errno;
3197c478bd9Sstevel@tonic-gate
3207c478bd9Sstevel@tonic-gate /* Keep on going until we lock the file or an error happens */
3217c478bd9Sstevel@tonic-gate while ((fcntl(fileno(oam_dgroup), F_SETLK, &lockinfo) == -1) &&
3227c478bd9Sstevel@tonic-gate !noerr) {
3237c478bd9Sstevel@tonic-gate
3247c478bd9Sstevel@tonic-gate /*
325*4656d474SGarrett D'Amore * fcntl() failed. If errno=EACCES, it's
326*4656d474SGarrett D'Amore * because the file's locked by someone else.
327*4656d474SGarrett D'Amore * Wait for the file to be unlocked, then
328*4656d474SGarrett D'Amore * close and reopen the file and try the lock
329*4656d474SGarrett D'Amore * again.
3307c478bd9Sstevel@tonic-gate */
3317c478bd9Sstevel@tonic-gate
3327c478bd9Sstevel@tonic-gate if (errno == EACCES) {
333*4656d474SGarrett D'Amore if (fcntl(fileno(oam_dgroup), F_SETLKW,
334*4656d474SGarrett D'Amore &lockinfo) == -1)
3357c478bd9Sstevel@tonic-gate noerr = FALSE;
3367c478bd9Sstevel@tonic-gate else {
3377c478bd9Sstevel@tonic-gate _enddgrptab();
338*4656d474SGarrett D'Amore if (!_opendgrptab(o_mode))
339*4656d474SGarrett D'Amore noerr = FALSE;
340*4656d474SGarrett D'Amore else
341*4656d474SGarrett D'Amore errno = olderrno;
3427c478bd9Sstevel@tonic-gate }
3437c478bd9Sstevel@tonic-gate
344*4656d474SGarrett D'Amore } else
345*4656d474SGarrett D'Amore noerr = FALSE; /* fcntl() failed hard */
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate } /* End while (fcntl() && !noerr) */
3487c478bd9Sstevel@tonic-gate
3497c478bd9Sstevel@tonic-gate /* Don't keep file open if an error happened */
3507c478bd9Sstevel@tonic-gate if (!noerr) _enddgrptab();
3517c478bd9Sstevel@tonic-gate
352*4656d474SGarrett D'Amore } else
353*4656d474SGarrett D'Amore noerr = FALSE; /* _opendgrptab() failed */
3547c478bd9Sstevel@tonic-gate
3557c478bd9Sstevel@tonic-gate /* Done */
3567c478bd9Sstevel@tonic-gate return (noerr);
3577c478bd9Sstevel@tonic-gate }
3587c478bd9Sstevel@tonic-gate
3597c478bd9Sstevel@tonic-gate /*
3607c478bd9Sstevel@tonic-gate * int unlkdgrptab()
3617c478bd9Sstevel@tonic-gate *
3627c478bd9Sstevel@tonic-gate * Unlock the locked device-group table.
3637c478bd9Sstevel@tonic-gate *
3647c478bd9Sstevel@tonic-gate * Arguments: None
3657c478bd9Sstevel@tonic-gate *
3667c478bd9Sstevel@tonic-gate * Returns: int
3677c478bd9Sstevel@tonic-gate * Whatever fcntl() returns...
3687c478bd9Sstevel@tonic-gate */
3697c478bd9Sstevel@tonic-gate
3707c478bd9Sstevel@tonic-gate static int
unlkdgrptab(void)3717c478bd9Sstevel@tonic-gate unlkdgrptab(void)
3727c478bd9Sstevel@tonic-gate {
3737c478bd9Sstevel@tonic-gate /* Automatic data */
3747c478bd9Sstevel@tonic-gate struct flock lockinfo; /* Locking structure */
3757c478bd9Sstevel@tonic-gate int noerr; /* FLAG, TRUE if all's well */
3767c478bd9Sstevel@tonic-gate
3777c478bd9Sstevel@tonic-gate /* Build the locking structure */
3787c478bd9Sstevel@tonic-gate lockinfo.l_type = F_UNLCK; /* Lock type */
3797c478bd9Sstevel@tonic-gate lockinfo.l_whence = 0; /* Count from top of file */
3807c478bd9Sstevel@tonic-gate lockinfo.l_start = 0L; /* From beginning */
3817c478bd9Sstevel@tonic-gate lockinfo.l_len = 0L; /* Length of locked data */
3827c478bd9Sstevel@tonic-gate
3837c478bd9Sstevel@tonic-gate /* Unlock it */
3847c478bd9Sstevel@tonic-gate noerr = (fcntl(fileno(oam_dgroup), F_SETLK, &lockinfo) != -1);
3857c478bd9Sstevel@tonic-gate _enddgrptab();
3867c478bd9Sstevel@tonic-gate
3877c478bd9Sstevel@tonic-gate /* Finished */
3887c478bd9Sstevel@tonic-gate return (noerr);
3897c478bd9Sstevel@tonic-gate }
3907c478bd9Sstevel@tonic-gate
3917c478bd9Sstevel@tonic-gate /*
3927c478bd9Sstevel@tonic-gate * struct dgrptabent *mkdgrptabent(dgroup, members)
3937c478bd9Sstevel@tonic-gate * char *dgroup
3947c478bd9Sstevel@tonic-gate * char **members
3957c478bd9Sstevel@tonic-gate *
3967c478bd9Sstevel@tonic-gate * This function builds a struct dgrptabent structure describing the
3977c478bd9Sstevel@tonic-gate * device-group <dgroup> so that it contains the members in the
3987c478bd9Sstevel@tonic-gate * membership list <members>.
3997c478bd9Sstevel@tonic-gate *
4007c478bd9Sstevel@tonic-gate * Arguments:
4017c478bd9Sstevel@tonic-gate * dgroup The device-group being added to the device-group table
4027c478bd9Sstevel@tonic-gate * members The members of the device-group
4037c478bd9Sstevel@tonic-gate *
4047c478bd9Sstevel@tonic-gate * Returns: struct dgrptabent *
4057c478bd9Sstevel@tonic-gate * A completed struct dgrptabent structure containing the description
4067c478bd9Sstevel@tonic-gate * of the device group. The structure, and all of the data in the
4077c478bd9Sstevel@tonic-gate * structure are each in space allocated using the malloc() function
4087c478bd9Sstevel@tonic-gate * and should be freed using the free() function (or the _freedgrptabent()
4097c478bd9Sstevel@tonic-gate * function.
4107c478bd9Sstevel@tonic-gate */
4117c478bd9Sstevel@tonic-gate
4127c478bd9Sstevel@tonic-gate static struct dgrptabent *
mkdgrptabent(char * dgroup,char ** members)4137c478bd9Sstevel@tonic-gate mkdgrptabent(
4147c478bd9Sstevel@tonic-gate char *dgroup, /* Device-group being created (or modified) */
4157c478bd9Sstevel@tonic-gate char **members) /* Members to add to that entry */
4167c478bd9Sstevel@tonic-gate {
4177c478bd9Sstevel@tonic-gate /* Automatic data */
4187c478bd9Sstevel@tonic-gate struct dgrptabent *ent; /* Ptr to struct we're making */
4197c478bd9Sstevel@tonic-gate struct member *prev; /* Ptr to prev attr/val struct */
4207c478bd9Sstevel@tonic-gate struct member *member; /* Ptr to current struct */
4217c478bd9Sstevel@tonic-gate char **pp; /* Ptr into list of ptrs */
4227c478bd9Sstevel@tonic-gate int noerr; /* TRUE if all's well */
4237c478bd9Sstevel@tonic-gate
4247c478bd9Sstevel@tonic-gate
4257c478bd9Sstevel@tonic-gate /* No problems (yet) */
4267c478bd9Sstevel@tonic-gate noerr = TRUE;
4277c478bd9Sstevel@tonic-gate
4287c478bd9Sstevel@tonic-gate /* Get space for the structure */
4297c478bd9Sstevel@tonic-gate if (ent = malloc(sizeof (struct dgrptabent))) {
4307c478bd9Sstevel@tonic-gate
4317c478bd9Sstevel@tonic-gate /* Fill in default values */
4327c478bd9Sstevel@tonic-gate ent->name = NULL; /* alias */
4337c478bd9Sstevel@tonic-gate ent->entryno = 0; /* Entry no. */
4347c478bd9Sstevel@tonic-gate ent->comment = FALSE; /* data rec */
4357c478bd9Sstevel@tonic-gate ent->dataspace = NULL; /* string */
4367c478bd9Sstevel@tonic-gate ent->membership = NULL; /* attr list */
4377c478bd9Sstevel@tonic-gate
4387c478bd9Sstevel@tonic-gate /* Fill in the device-group name */
4397c478bd9Sstevel@tonic-gate if (ent->name = malloc(strlen(dgroup)+1)) {
4407c478bd9Sstevel@tonic-gate (void) strcpy(ent->name, dgroup);
4417c478bd9Sstevel@tonic-gate
4427c478bd9Sstevel@tonic-gate /* Add membership to the structure */
4437c478bd9Sstevel@tonic-gate prev = NULL;
4447c478bd9Sstevel@tonic-gate if ((pp = members) != NULL)
4457c478bd9Sstevel@tonic-gate while (*pp && noerr) {
4467c478bd9Sstevel@tonic-gate
4477c478bd9Sstevel@tonic-gate if (member = malloc(sizeof (struct member))) {
4487c478bd9Sstevel@tonic-gate
4497c478bd9Sstevel@tonic-gate if (member->name = malloc(strlen(*pp)+1)) {
4507c478bd9Sstevel@tonic-gate (void) strcpy(member->name, *pp);
4517c478bd9Sstevel@tonic-gate if (prev) prev->next = member;
4527c478bd9Sstevel@tonic-gate else ent->membership = member;
4537c478bd9Sstevel@tonic-gate member->next = NULL;
4547c478bd9Sstevel@tonic-gate prev = member;
4557c478bd9Sstevel@tonic-gate } else {
4567c478bd9Sstevel@tonic-gate noerr = FALSE;
4577c478bd9Sstevel@tonic-gate free(member);
4587c478bd9Sstevel@tonic-gate }
4597c478bd9Sstevel@tonic-gate } else noerr = FALSE;
4607c478bd9Sstevel@tonic-gate pp++;
4617c478bd9Sstevel@tonic-gate } /* End membership processing loop */
4627c478bd9Sstevel@tonic-gate
4637c478bd9Sstevel@tonic-gate } else noerr = FALSE; /* malloc() failed */
4647c478bd9Sstevel@tonic-gate
4657c478bd9Sstevel@tonic-gate /*
4667c478bd9Sstevel@tonic-gate * If there was a problem, clean up the mess we've made
4677c478bd9Sstevel@tonic-gate */
4687c478bd9Sstevel@tonic-gate
4697c478bd9Sstevel@tonic-gate if (!noerr) {
4707c478bd9Sstevel@tonic-gate
4717c478bd9Sstevel@tonic-gate _freedgrptabent(ent);
4727c478bd9Sstevel@tonic-gate ent = NULL;
4737c478bd9Sstevel@tonic-gate
4747c478bd9Sstevel@tonic-gate } /* if (noerr) */
4757c478bd9Sstevel@tonic-gate
4767c478bd9Sstevel@tonic-gate } else noerr = FALSE; /* if (malloc(dgrptabent space)) */
4777c478bd9Sstevel@tonic-gate
4787c478bd9Sstevel@tonic-gate /* Finished */
4797c478bd9Sstevel@tonic-gate return (ent);
4807c478bd9Sstevel@tonic-gate }
4817c478bd9Sstevel@tonic-gate
4827c478bd9Sstevel@tonic-gate /*
4837c478bd9Sstevel@tonic-gate * int _putdgrptabrec(stream, rec)
4847c478bd9Sstevel@tonic-gate * FILE *stream
4857c478bd9Sstevel@tonic-gate * struct dgrptabent *rec
4867c478bd9Sstevel@tonic-gate *
4877c478bd9Sstevel@tonic-gate * Write a device-group table record containing the information in the
4887c478bd9Sstevel@tonic-gate * struct dgrptab structure <rec> to the current position of the
4897c478bd9Sstevel@tonic-gate * standard I/O stream <stream>.
4907c478bd9Sstevel@tonic-gate *
4917c478bd9Sstevel@tonic-gate * Arguments:
4927c478bd9Sstevel@tonic-gate * stream The stream to write to
4937c478bd9Sstevel@tonic-gate * rec The structure containing the information to write
4947c478bd9Sstevel@tonic-gate *
4957c478bd9Sstevel@tonic-gate * Returns: int
4967c478bd9Sstevel@tonic-gate * The number of characters written or EOF if there was some error.
4977c478bd9Sstevel@tonic-gate */
4987c478bd9Sstevel@tonic-gate
4997c478bd9Sstevel@tonic-gate int
_putdgrptabrec(FILE * stream,struct dgrptabent * rec)5007c478bd9Sstevel@tonic-gate _putdgrptabrec(
5017c478bd9Sstevel@tonic-gate FILE *stream, /* Stream to write to */
5027c478bd9Sstevel@tonic-gate struct dgrptabent *rec) /* Record to write */
5037c478bd9Sstevel@tonic-gate {
5047c478bd9Sstevel@tonic-gate /* Automatic Data */
5057c478bd9Sstevel@tonic-gate struct member *mem; /* Ptr to attr/val pair */
5067c478bd9Sstevel@tonic-gate char *buf; /* Allocated buffer */
5077c478bd9Sstevel@tonic-gate char *p; /* Temp char pointer */
5087c478bd9Sstevel@tonic-gate char *q; /* Temp char pointer */
5097c478bd9Sstevel@tonic-gate int count; /* Number of chars written */
5107c478bd9Sstevel@tonic-gate int size; /* Size of needed buffer */
5117c478bd9Sstevel@tonic-gate
5127c478bd9Sstevel@tonic-gate
5137c478bd9Sstevel@tonic-gate /* Comment or data record? */
514*4656d474SGarrett D'Amore if (rec->comment)
515*4656d474SGarrett D'Amore count = fputs(rec->dataspace, stream);
5167c478bd9Sstevel@tonic-gate else {
5177c478bd9Sstevel@tonic-gate
5187c478bd9Sstevel@tonic-gate /*
5197c478bd9Sstevel@tonic-gate * Record is a data record
5207c478bd9Sstevel@tonic-gate */
5217c478bd9Sstevel@tonic-gate
5227c478bd9Sstevel@tonic-gate /* Figure out the amount of space the record needs */
5237c478bd9Sstevel@tonic-gate size = (int)strlen(rec->name) + 1; /* "name:" */
5247c478bd9Sstevel@tonic-gate if ((mem = rec->membership) != NULL)
5257c478bd9Sstevel@tonic-gate do { /* members */
5267c478bd9Sstevel@tonic-gate /* "membername " or "membername\n" */
5277c478bd9Sstevel@tonic-gate size += (int)strlen(mem->name) + 1;
5287c478bd9Sstevel@tonic-gate } while ((mem = mem->next) != NULL); /* Next attr/val */
5297c478bd9Sstevel@tonic-gate else
5307c478bd9Sstevel@tonic-gate size++; /* Count trailing '\n' if empty grp */
5317c478bd9Sstevel@tonic-gate
5327c478bd9Sstevel@tonic-gate
5337c478bd9Sstevel@tonic-gate /* Alloc space for the record */
5347c478bd9Sstevel@tonic-gate if (buf = malloc((size_t) size+1)) {
5357c478bd9Sstevel@tonic-gate
5367c478bd9Sstevel@tonic-gate /* Initializations */
5377c478bd9Sstevel@tonic-gate p = buf;
5387c478bd9Sstevel@tonic-gate
5397c478bd9Sstevel@tonic-gate /* Write the device-group name */
5407c478bd9Sstevel@tonic-gate q = rec->name;
5417c478bd9Sstevel@tonic-gate while (*q) *p++ = *q++;
5427c478bd9Sstevel@tonic-gate *p++ = ':';
5437c478bd9Sstevel@tonic-gate
5447c478bd9Sstevel@tonic-gate /* Write the membership list */
5457c478bd9Sstevel@tonic-gate if ((mem = rec->membership) != NULL) do {
5467c478bd9Sstevel@tonic-gate q = mem->name;
5477c478bd9Sstevel@tonic-gate while (*q) *p++ = *q++;
5487c478bd9Sstevel@tonic-gate if ((mem = mem->next) != NULL) *p++ = ',';
5497c478bd9Sstevel@tonic-gate } while (mem);
5507c478bd9Sstevel@tonic-gate
5517c478bd9Sstevel@tonic-gate /* Terminate the record */
5527c478bd9Sstevel@tonic-gate *p++ = '\n';
5537c478bd9Sstevel@tonic-gate *p = '\0';
5547c478bd9Sstevel@tonic-gate
5557c478bd9Sstevel@tonic-gate /* Write the record */
5567c478bd9Sstevel@tonic-gate count = fputs(buf, stream);
5577c478bd9Sstevel@tonic-gate free(buf);
5587c478bd9Sstevel@tonic-gate } else
5597c478bd9Sstevel@tonic-gate count = EOF; /* malloc() failed */
5607c478bd9Sstevel@tonic-gate }
5617c478bd9Sstevel@tonic-gate
5627c478bd9Sstevel@tonic-gate /* Finished */
5637c478bd9Sstevel@tonic-gate return (count);
5647c478bd9Sstevel@tonic-gate }
5657c478bd9Sstevel@tonic-gate
5667c478bd9Sstevel@tonic-gate /*
5677c478bd9Sstevel@tonic-gate * int _adddgrptabrec(dgrp, members)
5687c478bd9Sstevel@tonic-gate * char *dgrp
5697c478bd9Sstevel@tonic-gate * char **members
5707c478bd9Sstevel@tonic-gate *
5717c478bd9Sstevel@tonic-gate * If <dgrp> doesn't exist, this function adds a record to the
5727c478bd9Sstevel@tonic-gate * device-group table for that device-group. That record will
5737c478bd9Sstevel@tonic-gate * have the name <dgrp> and will have a membership described in
5747c478bd9Sstevel@tonic-gate * the list referenced by <members>. The record is added to the
5757c478bd9Sstevel@tonic-gate * end of the table.
5767c478bd9Sstevel@tonic-gate *
5777c478bd9Sstevel@tonic-gate * If <dgrp> already exists in the table, the function adds the
5787c478bd9Sstevel@tonic-gate * members in the <members> list to the group's membership.
5797c478bd9Sstevel@tonic-gate *
5807c478bd9Sstevel@tonic-gate * Arguments:
5817c478bd9Sstevel@tonic-gate * dgrp The name of the device-group being added to the
5827c478bd9Sstevel@tonic-gate * device-group table.
5837c478bd9Sstevel@tonic-gate * members A pointer to the first item of the list of members
5847c478bd9Sstevel@tonic-gate * in the device-group being added to the table.
5857c478bd9Sstevel@tonic-gate * (This value may be (char **) NULL).
5867c478bd9Sstevel@tonic-gate *
5877c478bd9Sstevel@tonic-gate * Returns: int
5887c478bd9Sstevel@tonic-gate * TRUE if successful, FALSE with "errno" set otherwise.
5897c478bd9Sstevel@tonic-gate */
5907c478bd9Sstevel@tonic-gate
5917c478bd9Sstevel@tonic-gate int
_adddgrptabrec(char * dgrp,char ** members)5927c478bd9Sstevel@tonic-gate _adddgrptabrec(
5937c478bd9Sstevel@tonic-gate char *dgrp, /* Devgrp to add to the table */
5947c478bd9Sstevel@tonic-gate char **members) /* Members for that devgrp */
5957c478bd9Sstevel@tonic-gate {
5967c478bd9Sstevel@tonic-gate /* Automatic data */
5977c478bd9Sstevel@tonic-gate struct dgrptabent *ent; /* Ptr to dev tab entry */
5987c478bd9Sstevel@tonic-gate struct dgrptabent *new; /* Ptr to new dev tab info */
5997c478bd9Sstevel@tonic-gate struct dgrptabent *p; /* Temp ptr to dev tab info */
6007c478bd9Sstevel@tonic-gate struct member *pm, *qm, *rm; /* Tmp ptrs to struct member */
6017c478bd9Sstevel@tonic-gate FILE *fd; /* File descr, temp file */
6027c478bd9Sstevel@tonic-gate char *path; /* Ptr to new devtab name */
6037c478bd9Sstevel@tonic-gate int olderrno; /* Errno on entry */
6047c478bd9Sstevel@tonic-gate int noerr; /* FLAG, TRUE if all's well */
6057c478bd9Sstevel@tonic-gate
6067c478bd9Sstevel@tonic-gate
6077c478bd9Sstevel@tonic-gate /* Make a structure describing the new information */
6087c478bd9Sstevel@tonic-gate if ((new = mkdgrptabent(dgrp, members)) == NULL)
6097c478bd9Sstevel@tonic-gate return (FALSE);
6107c478bd9Sstevel@tonic-gate
6117c478bd9Sstevel@tonic-gate /*
6127c478bd9Sstevel@tonic-gate * Lock the device-group table. This only returns if the
6137c478bd9Sstevel@tonic-gate * table is locked or some error occurred. It waits until the
6147c478bd9Sstevel@tonic-gate * table is available.
6157c478bd9Sstevel@tonic-gate */
6167c478bd9Sstevel@tonic-gate if (!lkdgrptab("a+", F_WRLCK)) {
6177c478bd9Sstevel@tonic-gate _freedgrptabent(new);
6187c478bd9Sstevel@tonic-gate return (FALSE);
6197c478bd9Sstevel@tonic-gate }
6207c478bd9Sstevel@tonic-gate
6217c478bd9Sstevel@tonic-gate /*
6227c478bd9Sstevel@tonic-gate * If the device-group is already in the table, add
6237c478bd9Sstevel@tonic-gate * the specified members
6247c478bd9Sstevel@tonic-gate */
6257c478bd9Sstevel@tonic-gate
6267c478bd9Sstevel@tonic-gate noerr = TRUE;
6277c478bd9Sstevel@tonic-gate olderrno = errno;
6287c478bd9Sstevel@tonic-gate if (ent = _getdgrprec(dgrp)) {
6297c478bd9Sstevel@tonic-gate
6307c478bd9Sstevel@tonic-gate /* Any members to add? If not, do nothing. */
6317c478bd9Sstevel@tonic-gate if (new->membership) {
6327c478bd9Sstevel@tonic-gate
6337c478bd9Sstevel@tonic-gate /* Any existing members? */
6347c478bd9Sstevel@tonic-gate if ((pm = ent->membership) != NULL) {
6357c478bd9Sstevel@tonic-gate
6367c478bd9Sstevel@tonic-gate /* Find the end of the existing membership list */
6377c478bd9Sstevel@tonic-gate while (pm->next) pm = pm->next;
6387c478bd9Sstevel@tonic-gate
6397c478bd9Sstevel@tonic-gate /* Append the new members to the membership list */
6407c478bd9Sstevel@tonic-gate pm->next = new->membership;
6417c478bd9Sstevel@tonic-gate
6427c478bd9Sstevel@tonic-gate /* Remove any duplicates */
6437c478bd9Sstevel@tonic-gate for (pm = ent->membership; pm; pm = pm->next) {
6447c478bd9Sstevel@tonic-gate qm = pm;
6457c478bd9Sstevel@tonic-gate while ((rm = qm->next) != NULL) {
6467c478bd9Sstevel@tonic-gate if (strcmp(pm->name, rm->name) == 0) {
6477c478bd9Sstevel@tonic-gate qm->next = rm->next;
6487c478bd9Sstevel@tonic-gate free(rm->name);
6497c478bd9Sstevel@tonic-gate free(rm);
6507c478bd9Sstevel@tonic-gate } else qm = rm;
6517c478bd9Sstevel@tonic-gate }
6527c478bd9Sstevel@tonic-gate }
6537c478bd9Sstevel@tonic-gate } else ent->membership = new->membership;
6547c478bd9Sstevel@tonic-gate
6557c478bd9Sstevel@tonic-gate /* No members in the new list any more */
6567c478bd9Sstevel@tonic-gate new->membership = NULL;
6577c478bd9Sstevel@tonic-gate
6587c478bd9Sstevel@tonic-gate /*
6597c478bd9Sstevel@tonic-gate * Make a new device-group table, replacing the
6607c478bd9Sstevel@tonic-gate * record for the specified device-group
6617c478bd9Sstevel@tonic-gate */
6627c478bd9Sstevel@tonic-gate
6637c478bd9Sstevel@tonic-gate _setdgrptab(); /* Rewind existing table */
6647c478bd9Sstevel@tonic-gate
6657c478bd9Sstevel@tonic-gate /* Open a temp file */
6667c478bd9Sstevel@tonic-gate if (fd = opennewdgrptab(&path)) {
6677c478bd9Sstevel@tonic-gate
6687c478bd9Sstevel@tonic-gate /* While there's more records and no error ... */
6697c478bd9Sstevel@tonic-gate while (((p = _getdgrptabent()) != NULL) && noerr) {
6707c478bd9Sstevel@tonic-gate
6717c478bd9Sstevel@tonic-gate /*
6727c478bd9Sstevel@tonic-gate * If this isn't the record we're replacing,
6737c478bd9Sstevel@tonic-gate * write it to the temporary file. Otherwise,
6747c478bd9Sstevel@tonic-gate * write the updated record
6757c478bd9Sstevel@tonic-gate */
6767c478bd9Sstevel@tonic-gate
6777c478bd9Sstevel@tonic-gate if (ent->entryno != p->entryno)
6787c478bd9Sstevel@tonic-gate noerr = _putdgrptabrec(fd, p) != EOF;
6797c478bd9Sstevel@tonic-gate else noerr = _putdgrptabrec(fd, ent) != EOF;
6807c478bd9Sstevel@tonic-gate _freedgrptabent(p);
6817c478bd9Sstevel@tonic-gate }
6827c478bd9Sstevel@tonic-gate
6837c478bd9Sstevel@tonic-gate /* Fix the files */
6847c478bd9Sstevel@tonic-gate if (noerr) {
6857c478bd9Sstevel@tonic-gate (void) fclose(fd);
6867c478bd9Sstevel@tonic-gate noerr = mknewdgrptab(path);
6877c478bd9Sstevel@tonic-gate } else {
6887c478bd9Sstevel@tonic-gate (void) fclose(fd);
6897c478bd9Sstevel@tonic-gate (void) rmnewdgrptab(path);
6907c478bd9Sstevel@tonic-gate }
6917c478bd9Sstevel@tonic-gate } /* if (opennewdgrptab()) */
6927c478bd9Sstevel@tonic-gate
6937c478bd9Sstevel@tonic-gate } /* If there's members to add */
6947c478bd9Sstevel@tonic-gate
6957c478bd9Sstevel@tonic-gate /* Free the memory associated with the updated entry */
6967c478bd9Sstevel@tonic-gate _freedgrptabent(ent);
6977c478bd9Sstevel@tonic-gate }
6987c478bd9Sstevel@tonic-gate
6997c478bd9Sstevel@tonic-gate /*
7007c478bd9Sstevel@tonic-gate * Otherwise, add the device-group to the end of the table
7017c478bd9Sstevel@tonic-gate */
7027c478bd9Sstevel@tonic-gate
7037c478bd9Sstevel@tonic-gate else if (errno == EINVAL) {
7047c478bd9Sstevel@tonic-gate errno = olderrno;
7057c478bd9Sstevel@tonic-gate if (fseek(oam_dgroup, 0, SEEK_END) == 0)
7067c478bd9Sstevel@tonic-gate noerr = (_putdgrptabrec(oam_dgroup, new) != EOF);
7077c478bd9Sstevel@tonic-gate } else noerr = FALSE;
7087c478bd9Sstevel@tonic-gate
7097c478bd9Sstevel@tonic-gate /* Finished */
7107c478bd9Sstevel@tonic-gate (void) unlkdgrptab(); /* Unlock the file */
7117c478bd9Sstevel@tonic-gate _freedgrptabent(new); /* Free the new dgrptab info struct */
7127c478bd9Sstevel@tonic-gate return (noerr); /* Return with success indicator */
7137c478bd9Sstevel@tonic-gate }
7147c478bd9Sstevel@tonic-gate
7157c478bd9Sstevel@tonic-gate /*
7167c478bd9Sstevel@tonic-gate * int _rmdgrptabrec(dgrp)
7177c478bd9Sstevel@tonic-gate * char *dgrp
7187c478bd9Sstevel@tonic-gate *
7197c478bd9Sstevel@tonic-gate * This function removes the record in the device-group table
7207c478bd9Sstevel@tonic-gate * for the specified device-group.
7217c478bd9Sstevel@tonic-gate *
7227c478bd9Sstevel@tonic-gate * Arguments:
7237c478bd9Sstevel@tonic-gate * dgrp The device-group to be removed
7247c478bd9Sstevel@tonic-gate *
7257c478bd9Sstevel@tonic-gate * Returns: int
7267c478bd9Sstevel@tonic-gate * Success indicator: TRUE if successful, FALSE with errno set otherwise.
7277c478bd9Sstevel@tonic-gate */
7287c478bd9Sstevel@tonic-gate
7297c478bd9Sstevel@tonic-gate int
_rmdgrptabrec(char * dgrp)7307c478bd9Sstevel@tonic-gate _rmdgrptabrec(char *dgrp) /* Device-group to remove */
7317c478bd9Sstevel@tonic-gate {
7327c478bd9Sstevel@tonic-gate /* Automatic data */
7337c478bd9Sstevel@tonic-gate struct dgrptabent *ent; /* Entry to remove */
7347c478bd9Sstevel@tonic-gate struct dgrptabent *p; /* Entry being copied */
7357c478bd9Sstevel@tonic-gate FILE *fd; /* Temp file's file descriptor */
7367c478bd9Sstevel@tonic-gate char *path; /* Pathname of temp file */
7377c478bd9Sstevel@tonic-gate int noerr; /* FLAG, TRUE if all's well */
7387c478bd9Sstevel@tonic-gate
7397c478bd9Sstevel@tonic-gate noerr = TRUE;
7407c478bd9Sstevel@tonic-gate if (!lkdgrptab("r", F_WRLCK))
7417c478bd9Sstevel@tonic-gate return (FALSE);
7427c478bd9Sstevel@tonic-gate if (ent = _getdgrprec(dgrp)) {
7437c478bd9Sstevel@tonic-gate _setdgrptab();
7447c478bd9Sstevel@tonic-gate if (fd = opennewdgrptab(&path)) {
7457c478bd9Sstevel@tonic-gate while (((p = _getdgrptabent()) != NULL) && noerr) {
7467c478bd9Sstevel@tonic-gate if (ent->entryno != p->entryno)
7477c478bd9Sstevel@tonic-gate noerr = _putdgrptabrec(fd, p) != EOF;
7487c478bd9Sstevel@tonic-gate _freedgrptabent(p);
7497c478bd9Sstevel@tonic-gate }
7507c478bd9Sstevel@tonic-gate if (noerr) {
7517c478bd9Sstevel@tonic-gate (void) fclose(fd);
7527c478bd9Sstevel@tonic-gate noerr = mknewdgrptab(path);
7537c478bd9Sstevel@tonic-gate } else {
7547c478bd9Sstevel@tonic-gate (void) fclose(fd);
7557c478bd9Sstevel@tonic-gate (void) rmnewdgrptab(path);
7567c478bd9Sstevel@tonic-gate }
7577c478bd9Sstevel@tonic-gate } else noerr = FALSE;
7587c478bd9Sstevel@tonic-gate _freedgrptabent(ent);
7597c478bd9Sstevel@tonic-gate } else noerr = FALSE;
7607c478bd9Sstevel@tonic-gate (void) unlkdgrptab();
7617c478bd9Sstevel@tonic-gate return (noerr);
7627c478bd9Sstevel@tonic-gate }
7637c478bd9Sstevel@tonic-gate
7647c478bd9Sstevel@tonic-gate /*
7657c478bd9Sstevel@tonic-gate * int _rmdgrpmems(dgrp, mems, notfounds)
7667c478bd9Sstevel@tonic-gate * char *dgrp
7677c478bd9Sstevel@tonic-gate * char **mems
7687c478bd9Sstevel@tonic-gate * char ***notfounds
7697c478bd9Sstevel@tonic-gate *
7707c478bd9Sstevel@tonic-gate * Remove the specified members from the membership of the specified
7717c478bd9Sstevel@tonic-gate * device-group. Any members not found in that device-group are
7727c478bd9Sstevel@tonic-gate * returned in the list referenced by <notfounds>.
7737c478bd9Sstevel@tonic-gate *
7747c478bd9Sstevel@tonic-gate * Arguments:
7757c478bd9Sstevel@tonic-gate * dgrp The device-group from which members are to be removed
7767c478bd9Sstevel@tonic-gate * mems The address of the first element in the list of
7777c478bd9Sstevel@tonic-gate * members to remove. This list is terminated by
7787c478bd9Sstevel@tonic-gate * (char *) NULL.
7797c478bd9Sstevel@tonic-gate * notfounds The place to put the address of the list of addresses
7807c478bd9Sstevel@tonic-gate * referencing the requested members that were not
7817c478bd9Sstevel@tonic-gate * members of the specified device-group
7827c478bd9Sstevel@tonic-gate *
7837c478bd9Sstevel@tonic-gate * Returns: int
7847c478bd9Sstevel@tonic-gate * TRUE if successful, FALSE with errno set otherwise.
7857c478bd9Sstevel@tonic-gate */
7867c478bd9Sstevel@tonic-gate
7877c478bd9Sstevel@tonic-gate int
_rmdgrpmems(char * dgrp,char ** mems,char *** notfounds)7887c478bd9Sstevel@tonic-gate _rmdgrpmems(
7897c478bd9Sstevel@tonic-gate char *dgrp, /* Device-group to modify */
7907c478bd9Sstevel@tonic-gate char **mems, /* Members to remove */
7917c478bd9Sstevel@tonic-gate char ***notfounds) /* Members req'd but not found */
7927c478bd9Sstevel@tonic-gate {
7937c478bd9Sstevel@tonic-gate /* Automatic data */
7947c478bd9Sstevel@tonic-gate struct dgrptabent *ent; /* Entry to modify */
7957c478bd9Sstevel@tonic-gate struct dgrptabent *p; /* Entry being copied */
7967c478bd9Sstevel@tonic-gate struct member *pm; /* Ptr to member being examined */
7977c478bd9Sstevel@tonic-gate struct member *prev; /* Ptr to previous member */
7987c478bd9Sstevel@tonic-gate char **nflst; /* Ptr to not-found list */
7997c478bd9Sstevel@tonic-gate char **pnf; /* Ptr into not-found list */
8007c478bd9Sstevel@tonic-gate char **pp; /* Ptr into members-to-rm list */
8017c478bd9Sstevel@tonic-gate FILE *fd; /* Temp file's file descriptor */
8027c478bd9Sstevel@tonic-gate char *path; /* Pathname of temp file */
8037c478bd9Sstevel@tonic-gate int noerr; /* TRUE if all's well */
8047c478bd9Sstevel@tonic-gate int found; /* TRUE if member is in membership */
8057c478bd9Sstevel@tonic-gate int i; /* Temp counter */
8067c478bd9Sstevel@tonic-gate
8077c478bd9Sstevel@tonic-gate noerr = TRUE;
8087c478bd9Sstevel@tonic-gate
8097c478bd9Sstevel@tonic-gate /* Lock the device-group table */
8107c478bd9Sstevel@tonic-gate if (!lkdgrptab("r", F_WRLCK))
8117c478bd9Sstevel@tonic-gate return (FALSE);
8127c478bd9Sstevel@tonic-gate
8137c478bd9Sstevel@tonic-gate /* Nothing is "not found" yet */
8147c478bd9Sstevel@tonic-gate *notfounds = NULL;
8157c478bd9Sstevel@tonic-gate
8167c478bd9Sstevel@tonic-gate /* Get the entry we're to modify */
8177c478bd9Sstevel@tonic-gate if (ent = _getdgrprec(dgrp)) {
8187c478bd9Sstevel@tonic-gate
8197c478bd9Sstevel@tonic-gate /* Allocate space for the not-found list */
8207c478bd9Sstevel@tonic-gate i = 1;
8217c478bd9Sstevel@tonic-gate if (mems)
8227c478bd9Sstevel@tonic-gate for (pp = mems; *pp; pp++)
8237c478bd9Sstevel@tonic-gate i++;
8247c478bd9Sstevel@tonic-gate if (nflst = malloc(i*sizeof (char *))) {
8257c478bd9Sstevel@tonic-gate pnf = nflst;
8267c478bd9Sstevel@tonic-gate *pnf = NULL;
8277c478bd9Sstevel@tonic-gate
8287c478bd9Sstevel@tonic-gate /* For each member to remove ... (if any) */
8297c478bd9Sstevel@tonic-gate if (mems)
8307c478bd9Sstevel@tonic-gate for (pp = mems; *pp; pp++) {
8317c478bd9Sstevel@tonic-gate
8327c478bd9Sstevel@tonic-gate found = FALSE;
8337c478bd9Sstevel@tonic-gate
8347c478bd9Sstevel@tonic-gate /* Compare against each member in the membership list */
8357c478bd9Sstevel@tonic-gate pm = ent->membership;
8367c478bd9Sstevel@tonic-gate prev = NULL;
8377c478bd9Sstevel@tonic-gate while (pm && !found) {
8387c478bd9Sstevel@tonic-gate
8397c478bd9Sstevel@tonic-gate if (strcmp(*pp, pm->name) == 0) {
8407c478bd9Sstevel@tonic-gate
8417c478bd9Sstevel@tonic-gate /* Found. Remove from linked list */
8427c478bd9Sstevel@tonic-gate if (prev) prev->next = pm->next;
8437c478bd9Sstevel@tonic-gate else ent->membership = pm->next;
8447c478bd9Sstevel@tonic-gate if (pm->name) free(pm->name);
8457c478bd9Sstevel@tonic-gate free(pm);
8467c478bd9Sstevel@tonic-gate found = TRUE;
8477c478bd9Sstevel@tonic-gate
8487c478bd9Sstevel@tonic-gate } else {
8497c478bd9Sstevel@tonic-gate
8507c478bd9Sstevel@tonic-gate /* Bump to the next member */
8517c478bd9Sstevel@tonic-gate prev = pm;
8527c478bd9Sstevel@tonic-gate pm = pm->next;
8537c478bd9Sstevel@tonic-gate
8547c478bd9Sstevel@tonic-gate }
8557c478bd9Sstevel@tonic-gate
8567c478bd9Sstevel@tonic-gate } /* For each member in the group */
8577c478bd9Sstevel@tonic-gate
8587c478bd9Sstevel@tonic-gate /*
8597c478bd9Sstevel@tonic-gate * If the requested member-to-remove wasn't found,
8607c478bd9Sstevel@tonic-gate * add it to the list of not-found members
8617c478bd9Sstevel@tonic-gate */
8627c478bd9Sstevel@tonic-gate if (!found) {
8637c478bd9Sstevel@tonic-gate if (*pnf = malloc(strlen(*pp)+1)) {
8647c478bd9Sstevel@tonic-gate (void) strcpy(*pnf++, *pp);
8657c478bd9Sstevel@tonic-gate *pnf = NULL;
8667c478bd9Sstevel@tonic-gate } else noerr = FALSE;
8677c478bd9Sstevel@tonic-gate }
8687c478bd9Sstevel@tonic-gate
8697c478bd9Sstevel@tonic-gate } /* for (each requested member to remove */
8707c478bd9Sstevel@tonic-gate
8717c478bd9Sstevel@tonic-gate _setdgrptab(); /* Rewind existing table */
8727c478bd9Sstevel@tonic-gate
8737c478bd9Sstevel@tonic-gate if (fd = opennewdgrptab(&path)) {
8747c478bd9Sstevel@tonic-gate while (((p = _getdgrptabent()) != NULL) && noerr) {
8757c478bd9Sstevel@tonic-gate if (ent->entryno != p->entryno)
8767c478bd9Sstevel@tonic-gate noerr = _putdgrptabrec(fd, p) != EOF;
8777c478bd9Sstevel@tonic-gate else noerr = _putdgrptabrec(fd, ent) != EOF;
8787c478bd9Sstevel@tonic-gate _freedgrptabent(p);
8797c478bd9Sstevel@tonic-gate }
8807c478bd9Sstevel@tonic-gate if (noerr) {
8817c478bd9Sstevel@tonic-gate (void) fclose(fd);
8827c478bd9Sstevel@tonic-gate noerr = mknewdgrptab(path);
8837c478bd9Sstevel@tonic-gate } else {
8847c478bd9Sstevel@tonic-gate (void) fclose(fd);
8857c478bd9Sstevel@tonic-gate (void) rmnewdgrptab(path);
8867c478bd9Sstevel@tonic-gate }
8877c478bd9Sstevel@tonic-gate } else noerr = FALSE; /* if (opennewdgrptab()) */
8887c478bd9Sstevel@tonic-gate
8897c478bd9Sstevel@tonic-gate /*
8907c478bd9Sstevel@tonic-gate * If there was no error but there was requested members
8917c478bd9Sstevel@tonic-gate * that weren't found, set the not-found list and the error
8927c478bd9Sstevel@tonic-gate * information. Otherwise, free the not-found list
8937c478bd9Sstevel@tonic-gate */
8947c478bd9Sstevel@tonic-gate
8957c478bd9Sstevel@tonic-gate if (noerr && (pnf != nflst)) {
8967c478bd9Sstevel@tonic-gate *notfounds = nflst;
8977c478bd9Sstevel@tonic-gate errno = ENODEV;
8987c478bd9Sstevel@tonic-gate noerr = FALSE;
8997c478bd9Sstevel@tonic-gate } else {
9007c478bd9Sstevel@tonic-gate for (pnf = nflst; *pnf; pnf++) free(*pnf);
9017c478bd9Sstevel@tonic-gate free(nflst);
9027c478bd9Sstevel@tonic-gate if (!noerr) *notfounds = NULL;
9037c478bd9Sstevel@tonic-gate }
9047c478bd9Sstevel@tonic-gate } else noerr = FALSE;
9057c478bd9Sstevel@tonic-gate
9067c478bd9Sstevel@tonic-gate /* Free the description of the modified device group */
9077c478bd9Sstevel@tonic-gate _freedgrptabent(ent);
9087c478bd9Sstevel@tonic-gate
9097c478bd9Sstevel@tonic-gate } else noerr = FALSE; /* _getdgrprec() failed */
9107c478bd9Sstevel@tonic-gate
9117c478bd9Sstevel@tonic-gate /* Unlock the original device-group table */
9127c478bd9Sstevel@tonic-gate (void) unlkdgrptab();
9137c478bd9Sstevel@tonic-gate return (noerr);
9147c478bd9Sstevel@tonic-gate }
915