/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <libgen.h>
#include "cfga_fp.h"
/* The following are used by update_fabric_wwn_list() */
static char *HDR =
"#\n"
"# fabric_WWN_map\n"
"#\n"
"# The physical ap_id list of configured fabric devices.\n"
"# Do NOT edit this file by hand -- refer to the cfgadm_fp(1M)\n"
"# man page and use cfgadm(1m) instead.\n"
"#\n";
/*
* This function searches for "srch_str" (of length "slen") in "buf" (of length
* "buflen"). If it is not found, "write_offset" has the offset in "buf" where
* "srch_str" would have to be added in "buf". If "srch_str" is found in "buf",
* "write_offset" has its offset in "buf"
*
* ARGUMENTS :
* buf - buffer to search in
* buflen - length of buffer
* srch_str - string to search
* slen - length of srch_str
* write_offset - Set in function on exit
* - It is the offset in buf where srch_str is or should be
* bytes_left - Set in function on exit
* - It is the # of bytes left beyond write_offset in buf
*
* Notes :
* - This function assumes "buf" is sorted in ascending order
* - If 'buflen' is > 0, it assumes it has a header on top and skips it
* - "srch_str" has '\n' at the end, but when update_fabric_wwn_list() calls
* this function, 'slen' does not include the last `\n'
*
* RETURN VALUES :
* Zero - "srch_str" found in "buf"... "write_offset" has offset in "buf"
* > 0 - "srch_str" NOT found in "buf" ... "write_offset" has offset in "buf"
* where "srch_str" can fit in.
* "buf" had contents > "srch_str"
* < 0 - "srch_str" NOT found in "buf" ... "write_offset" has offset in "buf"
* where "srch_str" can fit in.
* "buf" had contents < "srch_str"
*/
static int
int *write_offset, int *bytes_left)
{
*bytes_left = buflen;
*write_offset = 0;
return (-2); /* Arbitrary -ve val. srch_str not found */
return (0); /* This says srch_str was found */
if (buflen >= sizeof_rep_hdr) {
/* skip header */
*bytes_left -= sizeof_rep_hdr;
}
while (*bytes_left >= slen) {
/* strncmp will pass if srch_str is a substring */
return (retval);
}
/* retval < 0 */
*write_offset = buflen;
return (retval);
}
/* Get the length of this line */
}
if (*bytes_left > 0) {
/* In this case the bytes left will be less than slen */
} else {
*write_offset = buflen;
}
return (retval);
}
/* Should return a value < 0 to show that search string goes to eof */
return (-1);
}
/*
* This function sets an advisory lock on the file pointed to by the argument
* fd, which is a file descriptor. The lock is set using fcntl() which uses
* flock structure.
*/
int
{
}
/* Lot of places to cleanup - Less chance of missing out using this macro */
if (fd != -1) { \
} \
if (copy_fd != -1) { \
} \
if (tmp_fd != -1) { \
} \
} \
} \
} \
} \
} \
} \
return (ret)
/*
* INPUTS:
* cmd - ADD_ENTRY or REMOVE_ENTRY
* update_str - string for repository operation
* - Assumed NOT to have a '\n' and that it is null terminated
* errstring - Pointer that will be updated by this function
* - Any error msgs that has to be sent back to caller
*
* RETURNS :
* FPCFGA_OK on success
* FPCFGA_LIB_ERR on error
*
* SYNOPSIS:
* This function adds or deletes 'update_str' from FAB_REPOSITORY based on
* value of 'cmd'. The repository has a warning line on the top to disallow
* manual editing of the file. If the repository is being created fresh or if
* it is of zero length or if it has only warning lines in it, the operation
* speicified by 'cmd' is performed and returned. If the repository exists
* and has some data, it is expected to be of atleast the size of the lenght
* of the warning header. This is the only check that is performed on the
* validity of the file. No other checks are performed. On a valid
* repository, to perform the update, this function basically makes use of
* 3 buffers - the original buffer (repbuf), a copy buffer (c_repbuf) and a
* temp buffer (t_repbuf).
* The contents of the repository are mmap-ed into the repbuf and then
* copied into the c_repbuf. All further operations are done using the copy.
* t_repbuf is created to be the size of c_repbuf +/- 'slen' (based on
* 'update_str', the c_repbuf is copied to a OLD_FAB_REPOSITORY and t_repbuf
* is made FAB_REPOSITORY.
*
*/
int
{
/* Do some initializations */
/*
* Set the mode to read only. Root user can still open as RDWR.
* We ignore errors in general here. But, just notice ENOENTs
*/
new_file_flag = 1;
}
/* Create the repository if its not there */
return (FPCFGA_LIB_ERR);
}
/* Now try to chmod again. This time we dont ignore errors */
return (FPCFGA_LIB_ERR);
}
return (FPCFGA_LIB_ERR);
}
return (FPCFGA_LIB_ERR);
}
/* A very Minimal check on repository */
/*
* If there is some data, it should be atleast the size of
* the header
*/
return (FPCFGA_LIB_ERR);
}
/*
* Just return success
*/
return (FPCFGA_OK);
}
return (FPCFGA_LIB_ERR);
}
if (filesize > 0) {
}
getpid());
}
return (FPCFGA_LIB_ERR);
}
}
}
}
/*
* We cannot close the repository since we hold a lock
* But we'll free up the mmap-ed area.
*/
}
/*
* If we just created this file, or it was an empty repository file
* add a header to the beginning of file.
* If it had was a repository file with just the header,
*/
if ((filesize != sizeof_rep_hdr) &&
}
/*
* We know its a new file, empty file or a file with only a
* header so lets get the update operation done with
*/
switch (cmd) {
case ADD_ENTRY:
/* If there is a header, we have to skip it */
}
}
if (filesize > 0) {
/* Now create the '.old' file */
ERR_UPD_REP, 0);
}
ERR_UPD_REP, 0);
}
}
case REMOVE_ENTRY:
/*
* So, the side effect of a remove on an empty or
* non-existing repository is that the repository got
* created
*/
default:
}
}
/* Now, size and filesize are > sizeof_rep_hdr */
switch (cmd) {
case ADD_ENTRY:
/*
* We'll search the full repository, header included, since
* we dont expect upd_str to match anything in the header.
*/
/* line already exists in repository or len == 0 */
}
/* construct temp file name using pid. */
}
/* Open tmp repository file in absolute mode */
}
}
}
}
if (write_offset != filesize) {
}
/*
* we are using the copy of FAB_REPOSITORY and will
* do msync first since it will be renamed to '.old' file.
*/
}
}
}
}
/* here we do rename and rename before close fd */
}
case REMOVE_ENTRY:
/*
* No need to init the 'else' part (size < len) because
* in that case, there will be nothing to delete from
* the file and so 'size' will not be used in the code
* below since search_line() will not find upd_str.
*/
}
&write_offset, &bytes_left) != 0) {
/* this line does not exists - nothing to remove */
}
/* construct temp file name using pid. */
}
/* Open tmp repository file in absolute mode */
}
if (size > 0) {
}
}
}
if ((bytes_left - len) > 0) {
bytes_left - len);
}
}
}
}
/*
* we are using the copy of FAB_REPOSITORY and will
* do msync first since it will be renamed to bak file.
*/
}
}
/* Close and invalidate the fd's */
/* here we do rename and rename before close fd */
}
default:
/* Unexpected - just getout */
break;
}
}