fmd_log.c revision 7ee93e3bbce920c0d0742deb6632b0939e30b783
/*
* 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 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <alloca.h>
#include <unistd.h>
#include <limits.h>
#include <strings.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <libgen.h>
#include <dirent.h>
#include <fmd_log_impl.h>
#include <fmd_log.h>
static void fmd_log_free_record(fmd_log_record_t *);
static const char FMD_CREATOR[] = "fmd";
/*
* fmd_log_set_errno is used as a utility function throughout the library. It
* sets both lp->log_errno and errno to the specified value. If the current
* error is EFDL_EXACCT, we store it internally as that value plus ea_error().
* If no ea_error() is present, we assume EFDL_BADTAG (catalog tag mismatch).
*/
static int
{
else if (err == EFDL_EXACCT)
else
return (-1);
}
/*PRINTFLIKE2*/
static void
{
}
}
/*
* fmd_log_load_record() is used to load the exacct object at the current file
* location into the specified fmd_log_record structure. Once the caller has
* made use of this information, it can clean up using fmd_log_free_record().
*/
static int
{
int err;
if (iflags & FMD_LOG_XITER_OFFS) {
}
}
if (iflags & FMD_LOG_XITER_OFFS)
switch (obj->eo_catalog) {
case CAT_FMA_NVLIST:
}
break;
case CAT_FMA_TODSEC:
break;
case CAT_FMA_TODNSEC:
break;
case CAT_FMA_GROUP:
break;
}
}
}
}
return (0);
}
/*
* fmd_log_free_record frees memory associated with the specified record. If
* cross-references are contained in this record, we proceed recursively.
*/
static void
{
uint_t i;
}
}
/*
* fmd_log_load_xref loads the cross-reference represented by the specified
* exacct group 'grp' into the next empty slot in rp->rec_xrefs. This function
* is called repeatedly by fmd_log_load_xrefs() for each embedded reference.
*/
static int
{
switch (obj->eo_catalog) {
case CAT_FMA_MAJOR:
break;
case CAT_FMA_MINOR:
break;
case CAT_FMA_INODE:
break;
case CAT_FMA_OFFSET:
break;
case CAT_FMA_UUID:
break;
}
}
/*
* Search our xref list for matching (dev_t, ino64_t) or (uuid).
* If we can't find one, return silently without
* doing anything. We expect log xrefs to be broken whenever log
* files are trimmed or removed; their only purpose is to help us
* debug diagnosis engine algorithms.
*/
break;
break;
}
else
return (0);
}
return (fmd_log_load_record(xlp,
}
/*
* fmd_log_load_xrdir is called by fmd_log_load_xrefs when the FMD_LF_XREFS bit
* is not yet set, indicating we haven't looked for cross-referenced files. We
* open the directory associated with the specified log file and attempt to
* we are successful, the files are chained on to lp->log_xrefs, where the
*/
static void
{
return; /* failed to open directory; just skip it */
continue; /* skip "." and ".." and hidden files */
}
}
}
/*
* fmd_log_load_xrefs iterates again over the record's exacct group and for
* each cross-reference (embedded CAT_FMA_GROUP), attempts to fill in the
* corresponding xref. rp->rec_nrefs is reset to the number of valid items
* in the finished rp->rec_xrefs array; see fmd_log_load_xref() for more info.
*/
static int
{
if (!(iflags & FMD_LOG_XITER_REFS))
return (0); /* do not load any xrefs */
/*
* Make a second pass through the record group to locate and process
* each cross-reference sub-group. The structure of the groups is
* as follows (left-hand-side symbols named after the variables used):
*
* rgrp := CAT_FMA_TODSEC CAT_FMA_TODNSEC CAT_FMA_NVLIST grp*
* grp := obj* (i.e. zero or more groups of xref items)
* obj := CAT_FMA_MAJOR CAT_FMA_MINOR CAT_FMA_INODE CAT_FMA_OFFSET
*
* For each xref 'obj', we call fmd_log_load_xref() to parse the four
* xref members and then load the specified record into rp->rec_xrefs.
*/
continue; /* ignore anything that isn't a group */
return (-1); /* errno is set for us */
}
}
return (0);
}
static fmd_log_t *
{
return (NULL);
}
{
int fd;
if (abi > FMD_LOG_VERSION)
}
/*
* Read the first group of log meta-data: the write-once read-only
* file header. We read all records in this group, ignoring all but
* the VERSION and LABEL, which are required and must be verified.
*/
}
switch (obj->eo_catalog) {
case CAT_FMA_VERSION:
}
break;
case CAT_FMA_LABEL:
}
break;
case CAT_FMA_OSREL:
}
break;
case CAT_FMA_OSVER:
}
break;
case CAT_FMA_PLAT:
}
break;
case CAT_FMA_UUID:
}
break;
}
}
/*
* Read the second group of log meta-data: the table of contents. At
* present there are no records libfmd_log needs in here, so we just
* skip over this entire group so that fmd_log_xiter() starts after it.
*/
}
return (lp);
}
void
{
return; /* permit null lp to simply caller code */
}
}
const char *
{
}
void
{
}
/*
* Note: this will be verrrry slow for big files. If this function becomes
* important, we'll need to add a function to libexacct to let us rewind.
* Currently libexacct has no notion of seeking other than record-at-a-time.
*/
int
{
continue; /* rewind until beginning of file */
else
else
}
return (0);
}
static int
{
uint_t i, j;
for (i = 0; i < fac; i++) {
break; /* logical OR of this class is true */
}
return (0); /* logical AND of filter is false */
}
return (1); /* logical AND of filter is true */
}
static int
{
}
int
const fmd_log_record_t *rp)
{
/*
* If a filter array was provided, create an array of filtvec structs
*/
for (i = 0; i < fc; i++) {
}
}
int
{
int rv = 0;
if (flag & ~FMD_LOG_XITER_MASK)
/*
* If a filter array was provided, create an array of filtvec structs
* where each filtvec holds a pointer to an equivalent list of filters,
* as determined by their filt_func. We sort the input array by func,
* and then fill in the filtvec struct array. We can then compute the
* logical OR of equivalent filters by iterating over filt_argv, and
* we can compute the logical AND of 'fv' by iterating over filt_argc.
*/
if (fc != 0) {
for (i = 0; i < fc; i++) {
}
}
do {
break; /* end-of-file reached */
rcnt++;
} else {
rcnt++;
}
} while (rv == 0);
if (fac != 0)
return (rv);
}
int
{
}
int
{
return (0);
}
static const char *const _fmd_errs[] = {
"client requires newer version of libfmd_log", /* EFDL_VERSION */
"required memory allocation failed", /* EFDL_NOMEM */
"log header did not contain required field", /* EFDL_BADHDR */
"log record did not contain protocol class", /* EFDL_NOCLASS */
"log record has invalid catalog tag", /* EFDL_BADTAG */
"log record has invalid cross-reference group", /* EFDL_BADREF */
"log record has invalid cross-reference dev_t", /* EFDL_BADDEV */
"log record was not of expected type", /* EFDL_EXACCT + OK */
"log access system call failed", /* EXR_SYSCALL_FAIL */
"log file corruption detected", /* EXR_CORRUPT_FILE */
"end-of-file reached", /* EXR_EOF */
"log file does not have appropriate creator", /* EXR_NO_CREATOR */
"invalid unpack buffer specified", /* EXR_INVALID_BUF */
"invalid exacct operation for log file", /* EXR_NOTSUPP */
"log file requires newer version of libexacct", /* EXR_UNKN_VERSION */
"invalid object buffer specified", /* EXR_INVALID_OBJ */
};
/*ARGSUSED*/
const char *
{
const char *msg;
else
}
int
{
}