/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1996-1997, by Sun Microsystems, Inc.
* All Rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Copyright 2010 Nexenta Systems, Inc. All rights reserved.
*/
/* LINTLIBRARY */
/*
*
* Global Definitions:
* _putdgrptabrec() Write a device-group record to a stream
* _rmdgrptabrec() Remove a device-group table record
* _rmdgrpmems() Remove specific members from a device group
* _adddgrptabrec() Add a device-group record to the table
*/
/*
* G L O B A L R E F E R E N C E S
*
* Header Files
* Externals Referenced
*/
/*
* Header Files
* <stdio.h> Standard I/O definitions
* <fcntl.h> Definitions for file control
* <errno.h> Error handling definitions
* <string.h> String Handling Definitions
* <unistd.h> Standard UNIX(r) Definitions
* <devmgmt.h> Device Management Definitions
* "devtab.h" Local Device Management Definitions
*/
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <devmgmt.h>
#include "devtab.h"
/*
* L O C A L D E F I N I T I O N S
* TDGTABNM Name of the temporary device-group table (in the
* directory of the existing table)
*/
/*
* Static functions
* lkdgrptab Locks the device-group table
* unlkdgrptab Unlocks the device-group table
* mkdgrptabent Builds a device-group table entry from the alias and the
* list of attr=val pairs given
* opennewdgrptab Opens a new device-group table (as a temp file)
* mknewdgrptab Makes the temp device-group table the new dgrptab
* rmnewdgrptab Remove the temporary device-group table and free space
* allocated to the filename of that file.
*/
static int unlkdgrptab(void);
static int mknewdgrptab(char *tempname);
static int rmnewdgrptab(char *tempname);
/*
* FILE *opennewdgrptab(pname)
* char **pname
*
* Generates a temporary device-group table name from the existing
* device-group table name (in the same directory) and opens that
* file for writing. It puts a pointer to the malloc()ed space
* containing the temp device-group table's name at the place
* referenced by <pname>.
*
* Arguments:
* pname Pointer to the char * to contain the address of the name
* of the temporary file
*
* Returns: FILE *
* A pointer to the opened stream or (FILE *) NULL if an error occurred.
* If an error occurred, "errno" will be set to reflect the problem.
*/
static FILE *
{
char *p; /* Ptr to last '/' in dgrptab name */
/* Initializations */
/* Get the name of the device-group table */
if (oldname = _dgrptabpath()) {
/*
* It is possible for us to have sufficient
* permissions to create the new file without having
* sufficient permissions to write the original
* dgrptab file. For consistency with the operations
* which modify the original file by writing it
* directly we require write permissions for the
* original file in order to make a new one.
*/
return (NULL);
return (NULL);
}
/* Get the directory that the device-group table lives in */
*(p+1) = '\0';
} else
dirname = "./";
/* Get space for the temp dgrptab pathname */
/*
* Build the name of the temp dgrptab and open
* the file. We must reset the owner, group
* and perms to those of the original dgrptab
* file.
*/
} else {
}
}
/* Free the space containing the dgrptab's name */
}
/* Finished. Return what we've got */
return (fp);
}
/*
* int rmnewdgrptab(tempname)
* char *tempname
*
* Unlink the temp dgrptab and free the memory allocated to
* contain the name of that file
*
* Arguments:
* tempname Name of the temporary file
*
* Returns: int
* TRUE if successful, FALSE otherwise
*/
static int
{
/* Automatic data */
int noerr;
/* Unlink the temporary file */
/* Finished */
return (noerr);
}
/*
* int mknewdgrptab(tempname)
* char *tempname
*
* Make the temporary device-group table the new system
* device-group table
*
* Arguments:
* tempname Name of the temporary file
*
* Returns: int
* TRUE if successful, FALSE otherwise
*
* Notes:
* - Need to use rename() someday instead of link()/unlink()
* - This code is somewhat ineffecient in that asks for the name
* of the device-group table more than once. Done so that we don't
* have to manage that space, but this may be somewhat lazy.
*/
static int
{
/* Get the dgrptab's pathname */
if (dgrpname = _dgrptabpath()) {
/* Unlink the existing file */
/* Make the temp file the real device-group table */
/* Remove the temp file */
if (noerr)
} else {
}
/* Free the dgrptab's name */
} else {
}
/* Finished. Return success indicator */
return (noerr);
}
/*
* int lkdgrptab(o_mode, lktype)
* char *o_mode
* short lktype
*
* Lock the device-group table for writing. If it isn't available, it
* waits until it is.
*
* Arguments:
* o_mode The open() mode to use when opening the device-group table
* lktype The type of lock to apply
*
* Returns: int
* TRUE if successful, FALSE with errno set otherwise
*/
static int
char *o_mode, /* Open mode */
short lktype) /* Lock type */
{
/* Automatic data */
/* Close the device-group table (if it's open) */
_enddgrptab();
if (_opendgrptab(o_mode)) {
/*
* Lock the device-group table (for writing). If it's not
* available, wait until it is, then close and open the
* table (modify and delete change the table!) and try
* to lock it again
*/
/* Build the locking structure */
/* Keep on going until we lock the file or an error happens */
!noerr) {
/*
* fcntl() failed. If errno=EACCES, it's
* because the file's locked by someone else.
* Wait for the file to be unlocked, then
* close and reopen the file and try the lock
* again.
*/
&lockinfo) == -1)
else {
_enddgrptab();
if (!_opendgrptab(o_mode))
else
}
} else
} /* End while (fcntl() && !noerr) */
/* Don't keep file open if an error happened */
if (!noerr) _enddgrptab();
} else
/* Done */
return (noerr);
}
/*
* int unlkdgrptab()
*
* Unlock the locked device-group table.
*
* Arguments: None
*
* Returns: int
* Whatever fcntl() returns...
*/
static int
unlkdgrptab(void)
{
/* Automatic data */
/* Build the locking structure */
/* Unlock it */
_enddgrptab();
/* Finished */
return (noerr);
}
/*
* struct dgrptabent *mkdgrptabent(dgroup, members)
* char *dgroup
* char **members
*
* This function builds a struct dgrptabent structure describing the
* device-group <dgroup> so that it contains the members in the
* membership list <members>.
*
* Arguments:
* dgroup The device-group being added to the device-group table
* members The members of the device-group
*
* Returns: struct dgrptabent *
* A completed struct dgrptabent structure containing the description
* of the device group. The structure, and all of the data in the
* structure are each in space allocated using the malloc() function
* and should be freed using the free() function (or the _freedgrptabent()
* function.
*/
static struct dgrptabent *
char *dgroup, /* Device-group being created (or modified) */
char **members) /* Members to add to that entry */
{
/* Automatic data */
/* No problems (yet) */
/* Get space for the structure */
/* Fill in default values */
/* Fill in the device-group name */
/* Add membership to the structure */
} else {
}
pp++;
} /* End membership processing loop */
/*
* If there was a problem, clean up the mess we've made
*/
if (!noerr) {
} /* if (noerr) */
/* Finished */
return (ent);
}
/*
* int _putdgrptabrec(stream, rec)
* FILE *stream
* struct dgrptabent *rec
*
* Write a device-group table record containing the information in the
* struct dgrptab structure <rec> to the current position of the
* standard I/O stream <stream>.
*
* Arguments:
* stream The stream to write to
* rec The structure containing the information to write
*
* Returns: int
* The number of characters written or EOF if there was some error.
*/
int
{
/* Automatic Data */
char *p; /* Temp char pointer */
char *q; /* Temp char pointer */
/* Comment or data record? */
else {
/*
* Record is a data record
*/
/* Figure out the amount of space the record needs */
do { /* members */
/* "membername " or "membername\n" */
else
size++; /* Count trailing '\n' if empty grp */
/* Alloc space for the record */
/* Initializations */
p = buf;
/* Write the device-group name */
while (*q) *p++ = *q++;
*p++ = ':';
/* Write the membership list */
while (*q) *p++ = *q++;
} while (mem);
/* Terminate the record */
*p++ = '\n';
*p = '\0';
/* Write the record */
} else
}
/* Finished */
return (count);
}
/*
* int _adddgrptabrec(dgrp, members)
* char *dgrp
* char **members
*
* If <dgrp> doesn't exist, this function adds a record to the
* device-group table for that device-group. That record will
* have the name <dgrp> and will have a membership described in
* the list referenced by <members>. The record is added to the
* end of the table.
*
* If <dgrp> already exists in the table, the function adds the
* members in the <members> list to the group's membership.
*
* Arguments:
* dgrp The name of the device-group being added to the
* device-group table.
* members A pointer to the first item of the list of members
* in the device-group being added to the table.
* (This value may be (char **) NULL).
*
* Returns: int
* TRUE if successful, FALSE with "errno" set otherwise.
*/
int
char *dgrp, /* Devgrp to add to the table */
char **members) /* Members for that devgrp */
{
/* Automatic data */
struct dgrptabent *p; /* Temp ptr to dev tab info */
/* Make a structure describing the new information */
return (FALSE);
/*
* Lock the device-group table. This only returns if the
* table is locked or some error occurred. It waits until the
* table is available.
*/
return (FALSE);
}
/*
* If the device-group is already in the table, add
* the specified members
*/
/* Any members to add? If not, do nothing. */
if (new->membership) {
/* Any existing members? */
/* Find the end of the existing membership list */
/* Append the new members to the membership list */
/* Remove any duplicates */
}
}
/* No members in the new list any more */
/*
* Make a new device-group table, replacing the
* record for the specified device-group
*/
_setdgrptab(); /* Rewind existing table */
/* Open a temp file */
/* While there's more records and no error ... */
/*
* If this isn't the record we're replacing,
* write it to the temporary file. Otherwise,
* write the updated record
*/
_freedgrptabent(p);
}
/* Fix the files */
if (noerr) {
} else {
(void) rmnewdgrptab(path);
}
} /* if (opennewdgrptab()) */
} /* If there's members to add */
/* Free the memory associated with the updated entry */
}
/*
* Otherwise, add the device-group to the end of the table
*/
/* Finished */
(void) unlkdgrptab(); /* Unlock the file */
return (noerr); /* Return with success indicator */
}
/*
* int _rmdgrptabrec(dgrp)
* char *dgrp
*
* This function removes the record in the device-group table
* for the specified device-group.
*
* Arguments:
* dgrp The device-group to be removed
*
* Returns: int
* Success indicator: TRUE if successful, FALSE with errno set otherwise.
*/
int
{
/* Automatic data */
struct dgrptabent *p; /* Entry being copied */
return (FALSE);
_setdgrptab();
_freedgrptabent(p);
}
if (noerr) {
} else {
(void) rmnewdgrptab(path);
}
(void) unlkdgrptab();
return (noerr);
}
/*
* int _rmdgrpmems(dgrp, mems, notfounds)
* char *dgrp
* char **mems
* char ***notfounds
*
* Remove the specified members from the membership of the specified
* device-group. Any members not found in that device-group are
* returned in the list referenced by <notfounds>.
*
* Arguments:
* dgrp The device-group from which members are to be removed
* mems The address of the first element in the list of
* members to remove. This list is terminated by
* (char *) NULL.
* notfounds The place to put the address of the list of addresses
* referencing the requested members that were not
* members of the specified device-group
*
* Returns: int
* TRUE if successful, FALSE with errno set otherwise.
*/
int
char *dgrp, /* Device-group to modify */
char **mems, /* Members to remove */
char ***notfounds) /* Members req'd but not found */
{
/* Automatic data */
struct dgrptabent *p; /* Entry being copied */
int i; /* Temp counter */
/* Lock the device-group table */
return (FALSE);
/* Nothing is "not found" yet */
/* Get the entry we're to modify */
/* Allocate space for the not-found list */
i = 1;
if (mems)
i++;
/* For each member to remove ... (if any) */
if (mems)
/* Compare against each member in the membership list */
/* Found. Remove from linked list */
} else {
/* Bump to the next member */
}
} /* For each member in the group */
/*
* If the requested member-to-remove wasn't found,
* add it to the list of not-found members
*/
if (!found) {
}
} /* for (each requested member to remove */
_setdgrptab(); /* Rewind existing table */
_freedgrptabent(p);
}
if (noerr) {
} else {
(void) rmnewdgrptab(path);
}
/*
* If there was no error but there was requested members
* that weren't found, set the not-found list and the error
* information. Otherwise, free the not-found list
*/
} else {
}
/* Free the description of the modified device group */
/* Unlock the original device-group table */
(void) unlkdgrptab();
return (noerr);
}