/*
* 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
*/
/*
*/
#include <stdio.h>
#include <string.h>
#include "libdevinfo.h"
#include <fcntl.h>
#include <stdlib.h>
#include <libsysevent.h>
#include <unistd.h>
/* pca: <chassis-name> <chassis-serial> -> <alias-id> mapping */
struct di_pca_hdl {
int h_init_flag;
int h_nrec;
};
/* implementation of a <chassis-name>.<chassis-serial> to <alias-id> map */
struct di_pca_rec {
char *r_product_id;
char *r_chassis_id;
char *r_alias_id;
char *r_comment;
int r_lnum;
};
/*
* Print out messages if flag is set to print
*/
static void
{
int len;
return;
len = ERROR_BUFLEN;
return;
if (lnum > 0) {
}
if (len > 2) {
*buf++ = '\n';
*buf++ = 0;
}
/*
* NOTE: to improve diagnosis, we could use fmadm
* strerror trick based on newline in fmt string...
*/
}
/*
* Add a new record to the link list.
*/
/* ARGSUSED */
static void
{
di_pca_rec_t r;
return;
if (product_id)
if (chassis_id)
if (alias_id)
if (comment)
h->h_rec_ptr = r;
} else {
lr = h->h_l_rec_ptr;
}
h->h_l_rec_ptr = r;
h->h_nrec++;
}
static void
{
if (r == NULL)
return;
if (r->r_product_id)
free(r->r_product_id);
if (r->r_chassis_id)
free(r->r_chassis_id);
if (r->r_alias_id)
free(r->r_alias_id);
if (r->r_comment)
free(r);
}
/*
* Check for a duplicate record entry
*/
static int
{
di_pca_rec_t r;
if (r->r_alias_id) {
_pca_error_print(h, r->r_lnum,
"error: duplicate <alias-id>: %s",
r->r_alias_id);
return (DI_PCA_FAILURE);
}
}
if (r->r_product_id && r->r_chassis_id) {
_pca_error_print(h, r->r_lnum,
"<chassis-name>", "<chassis-serial>",
return (DI_PCA_FAILURE);
}
}
}
return (DI_PCA_SUCCESS);
}
/* ARGSUSED */
static int
{
char *dup_str;
_pca_error_print(h, 0,
"error: reserved <alias-id> name: %s", DI_CRODC_SYSALIAS);
return (DI_PCA_FAILURE);
}
_pca_error_print(h, 0,
"error: reserved character being used in <alias-id>: '%s'",
return (DI_PCA_FAILURE);
}
return (DI_PCA_SUCCESS);
}
/* ARGSUSED */
static int
{
char *dup_str;
_pca_error_print(h, 0,
"error: invalid character being used in name: '%s'",
entry);
_pca_error_print(h, 0,
"invalid characters shown with _: '%s'",
dup_str);
return (DI_PCA_FAILURE);
}
return (DI_PCA_SUCCESS);
}
/*
* Add a record but verify that this is valid record(not a comment)
* to add and that it doesn't already exist
*/
/* ARGSUSED */
int
{
int err;
/* If here, everything looks good, add this record */
return (DI_PCA_FAILURE);
if (err)
return (err);
if (err)
return (err);
if (err)
return (err);
if (err)
return (err);
if (!comment) {
} else {
if (*comment != '#')
else
}
return (DI_PCA_SUCCESS);
}
void
{
if (!h || !r_del)
return;
/* First record in list */
/* More records */
} else {
/* Only record */
h->h_l_rec_ptr = NULL;
}
/*
* Last record in list when more than 1 record
* first if statement above took care of only 1 record
*/
h->h_l_rec_ptr = r_prev;
} else {
/* In the middle of the list somewhere */
}
}
/*
* Remove a non comment record. The match_str can be
* <chassis-name>.<chassis-serial> || <alias-id>
* so when looking for matches, must check these fields.
*/
/* ARGSUSED */
int
{
di_pca_rec_t r;
if (h == NULL)
return (DI_PCA_FAILURE);
r->r_product_id, r->r_chassis_id);
_pca_rec_remove(h, r);
_pca_rec_remove(h, r);
}
}
return (DI_PCA_SUCCESS);
}
{
if (h == NULL)
return (NULL);
if (r == NULL)
return (h->h_rec_ptr);
return (r->r_next);
}
char *
{
if (r)
return (r->r_product_id);
return (NULL);
}
char *
{
if (r)
return (r->r_chassis_id);
return (NULL);
}
char *
{
if (r)
return (r->r_alias_id);
return (NULL);
}
char *
{
if (r)
return (r->r_comment);
return (NULL);
}
/*
* Create the list of records from DI_PCA_ALIASES_FILE file. Comments in
* file will generate a record as well (to preserve line number and contents
* on update). If there is an error in file, return a NULL handle.
* If DI_PCA_INIT_FLAG_PRINT is set, we will print out messages describing
* the problem.
*/
/* ARGSUSED */
{
di_pca_hdl_t h = NULL;
char *aliases_file;
int lnum = 0;
char *seperator;
return (NULL);
h->h_init_flag = init_flag;
/*
* Read in the /DI_PCA_ALIASES_FILE file. A valid line contains
* "<chassis-name>.<chassis-serial> <white-space> <alias-id> \
* [ # comment]"
*/
return (h);
lnum++;
/* blank or comment line */
continue;
}
/*
* Check to make sure there is
* <chassis-name>.<chassis-serial>
*/
_pca_error_print(h, lnum,
"error: no separator on line");
goto err;
}
/* Check to make sure <chassis-id> supplied */
_pca_error_print(h, lnum,
"error: no <chassis-id> on line");
goto err;
}
/* Check to make sure <chassis-name> was supplied */
_pca_error_print(h, lnum,
"error: no <chassis-name> on line");
goto err;
}
/* If here, valid <chassis-name>.<chassis-serial>. */
*seperator = '\0';
(*alias == '#')) {
_pca_error_print(h, lnum,
"error: no <alias-id> on line");
goto err;
}
_pca_error_print(h, lnum,
"error: too many fields on line");
goto err;
}
_pca_error_print(h, lnum,
"error: duplicate information");
goto err;
}
}
return (h);
di_pca_fini(h);
return (NULL);
}
void
{
if (h == NULL)
return;
(void) _pca_rec_free(r);
}
free(h);
}
void
{
char *pi;
char *ci;
char *nn;
char *cmt;
return;
pi = di_pca_rec_get_product_id(r);
ci = di_pca_rec_get_chassis_id(r);
nn = di_pca_rec_get_alias_id(r);
cmt = di_pca_rec_get_comment(r);
else if (pi)
else if (cmt)
else
}
static int
{
int fd;
di_pca_rec_t r;
int sok = 0;
int errno_s;
if (fd == -1) {
_pca_error_print(h, 0,
"error: failed to create temporary file");
return (DI_PCA_FAILURE);
}
(void) unlink(unique_name);
return (DI_PCA_FAILURE);
}
di_pca_rec_print(tfp, r);
/* Get current permissions on file */
sok = 1;
(void) unlink(unique_name);
return (DI_PCA_FAILURE);
}
if (sok)
return (DI_PCA_SUCCESS);
}
int
{
int err;
if (err == DI_PCA_SUCCESS)
return (err);
}
/*ARGSUSED*/
static void
{
(void) mutex_lock(&di_pca_event_mutex);
(void) cond_broadcast(&di_pca_event_completed_cv);
(void) mutex_unlock(&di_pca_event_mutex);
}
int
{
int err;
if (h == NULL)
return (DI_PCA_FAILURE);
if ((flag & DI_PCA_SYNC_FLAG_COMMIT) &&
return (err);
/* Setup receiver for topo refresh finish */
_pca_error_print(h, 0,
"error: failed to bind to sysevent handler");
return (DI_PCA_FAILURE);
}
esc[0] = ESC_CRO_DBUPDATE_FINISH;
_pca_error_print(h, 0,
"error: failed to subscribe to CRO events");
return (DI_PCA_FAILURE);
}
/* send event to notify users */
(void) mutex_lock(&di_pca_event_mutex);
/* Wait for event completion confirmation from devchassisd */
&di_pca_event_mutex, &to);
(void) mutex_unlock(&di_pca_event_mutex);
_pca_error_print(h, 0, "WARNING: /dev/chassis namespace "
"update still in progress...");
return (DI_PCA_FAILURE);
}
return (DI_PCA_SUCCESS);
}
{
di_pca_rec_t r;
r->r_product_id, r->r_chassis_id);
return (r);
return (r);
}
}
}
return (NULL);
}
/*ARGSUSED*/
int
{
int query_len;
char *query;
di_cro_rec_t r = NULL;
return (0);
/* see if there is a cro record associated with the alias */
goto out;
return (r ? 1 : 0);
}