/*
* 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 <string.h>
#include <strings.h>
#include <stdio.h>
#include <libintl.h>
#include <errno.h>
#include <stdarg.h>
#include <assert.h>
#include <libuutil.h>
#include "suri_impl.h"
#include "suri_strings.h"
/*
* Error model in libsuri(3LIB)
* ============================
* See suri.h for a generic description of the error model.
*
* How to work with error setting functions in libsuri(3LIB) code
* ==============================================================
* If a public API function fails it MUST return a specific libsuri(3LIB) error
* value since libsuri does not explicitly set errno(3C) unless as specifically
* documented in internal man page suri_alloc(3SURI). Libsuri error values are
* defined in <suri.h>. The returned error code is also cached in the handle and
* cat be accessed via suri_err_code().
*
* If a public AP function succeeds, if MUST return ESURI_OK unless it is
* designed to always succeed, and it MUST reset the action and the description
* strings via suri_err_clear(). We assert if error messages are being retrieved
* from the handle upon success.
*
* We always expect the action string to carry an object name that is being
* worked on, be it a URI or a device path (being mapped back to a URI).
*
* Any non-public API function that accepts a handle and fails MUST set the
* description string and MUST return a libsuri(3LIB) errno unless it is
* designed to always succeed. Use only suri_err_set_desc() or
* suri_err_set_static_desc() to set the description. So, if a function
* accepting a handle fails, the caller knows that the description has been
* already set and will not try to re-set it. Usually, the libsuri(3LIB) errno
* set in the lowest level function that failed SHOULD be propagated up to the
* highest level caller without a change. When the highest level libsuri(3LIB)
* function finally gets an error, it knows that a description error string has
* been already set and MUST set an action string via suri_err_set_action().
* Internally, we assert that the description string is already set in
* suri_err_set_action(). After that, the highest level function returns the
* libsuri(3LIB) errno to the consumer of the library.
*
* How libsuri(3LIB) consumers are supposed to use error functions
* ===============================================================
*
* if ((ret = suri_map(h)) != ESURI_OK) {
* if (ret == ESURI_NOENT) {
* ret = suri_create(...)
* ...
* } else {
* (void) fprintf(stderr, "%s: %s\n",
* suri_err_action(h), suri_err_description(h));
* }
* }
* ...
*
* Example error messages (format is "action: description")
* ========================================================
*
* Failed to parse URI "lu:xuname.naa.2000001d38089fb": Expecting "luname", got
* "xuname"
* Failed to parse URI "file://authorityX": Authority not empty: "authorityX"
* Failed to map URI "file:///xljsfdlfjd": File does not exist: "/xljsfdlfjd"
* Failed to map "/x" to a URI: Not block or character device: "/x"
*/
/*
* Check whether there are warnings set in the handle.
*/
{
int i;
return (B_FALSE);
}
return (B_TRUE);
}
/*
* Clear all warnings.
*/
static void
{
}
/*
* Check whether there are errors set in the handle.
*/
{
return (B_FALSE);
}
return (B_TRUE);
}
/*
* Get cached return code for the last operation. Useful with functions that may
* return multiple handles.
*/
{
return (sh->sh_err_code);
}
/*
* Get an action string.
*/
const char *
{
/*
* Calling this function when a previous operation succeeded is
* considered an unrecoverable error.
*/
/* We have cleared any possible warnings in suri_err_description() */
return (sh->sh_err_action);
}
/*
* Get a description string.
*/
const char *
{
/*
* Calling this function when a previous operation succeeded is
* considered an unrecoverable error.
*/
return (sh->sh_err_static_desc);
return (sh->sh_err_desc);
}
/*
* Get warning strings.
*/
char **
{
return (NULL);
}
/*
* This internal function is used to set the action string.
*/
/* PRINTFLIKE2 */
void
{
int n;
/* Make sure we set the action string just once per error. */
/*
* The description is expected to have been always set before this
* function is called.
*/
/*
* If we had any warnings they have been already cleared in our
* suri_err_set(_static|)_desc() functions.
*/
}
/*
* Internal function to set a dynamic error description string.
*/
/* PRINTFLIKE2 */
void
{
int n;
/*
* Make sure we set the description string just once per error and
* before setting the action error string.
*/
/*
* While we could have some warnings in the handle, they are no longer
* relevant if the operation fails.
*/
}
/*
* If a dynamic description is not needed, use a static description derived from
* the libsuri(3LIB) list of errno values and return 'err'.
*/
{
/*
* Make sure we set the description string just once per error and
* before setting the action error string.
*/
switch (err) {
case ESURI_NOMEM:
break;
case ESURI_NAMETOOLONG:
break;
default:
assert(0);
}
/*
* While we could have some warnings in the handle, they are no longer
* relevant if the operation fails.
*/
return (err);
}
/*
* Internal function to set a warning. Warnings can be used only if the function
* returns ESURI_OK. Note that for now we support only two warnings per a
* handle.
*/
/* PRINTFLIKE2 */
void
{
int i, n;
/* Find the first free warning string */
break;
}
/* If the warning array if already full it it an internal error. */
/* "Publicize" the warning string */
/* The warning we are gonna use must be empty; no leftovers allowed. */
/* We expect the terminating NULL to be already there. */
assert(n < SURI_WARN_STR_LEN);
}
/*
* Clear any previous handle errors. This function is usually to be used only
* upon entry to public API functions. However, we also use it for URI specific
* mapping operations involving devinfo tree where we must clear errors before
* trying again with a full device discovery.
*/
void
{
int i;
for (i = 0; i < 2; ++i)
}