Blame source/uds/errors.c

Packit Service 310c69
/*
Packit Service 310c69
 * Copyright (c) 2020 Red Hat, Inc.
Packit Service 310c69
 *
Packit Service 310c69
 * This program is free software; you can redistribute it and/or
Packit Service 310c69
 * modify it under the terms of the GNU General Public License
Packit Service 310c69
 * as published by the Free Software Foundation; either version 2
Packit Service 310c69
 * of the License, or (at your option) any later version.
Packit Service 310c69
 * 
Packit Service 310c69
 * This program is distributed in the hope that it will be useful,
Packit Service 310c69
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 310c69
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 310c69
 * GNU General Public License for more details.
Packit Service 310c69
 * 
Packit Service 310c69
 * You should have received a copy of the GNU General Public License
Packit Service 310c69
 * along with this program; if not, write to the Free Software
Packit Service 310c69
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit Service 310c69
 * 02110-1301, USA. 
Packit Service 310c69
 *
Packit Service 310c69
 * $Id: //eng/uds-releases/jasper/src/uds/errors.c#11 $
Packit Service 310c69
 */
Packit Service 310c69
Packit Service 310c69
#include "errors.h"
Packit Service 310c69
Packit Service 310c69
#include "common.h"
Packit Service 310c69
#include "permassert.h"
Packit Service 310c69
#include "stringUtils.h"
Packit Service 310c69
Packit Service 310c69
#ifdef __KERNEL__
Packit Service 310c69
#include <linux/errno.h>
Packit Service 310c69
#endif
Packit Service 310c69
Packit Service 310c69
static const struct errorInfo successful = { "UDS_SUCCESS", "Success" };
Packit Service 310c69
Packit Service 310c69
#ifdef __KERNEL__
Packit Service 310c69
static const char *const messageTable[] = {
Packit Service 310c69
  [EPERM]   = "Operation not permitted",
Packit Service 310c69
  [ENOENT]  = "No such file or directory",
Packit Service 310c69
  [ESRCH]   = "No such process",
Packit Service 310c69
  [EINTR]   = "Interrupted system call",
Packit Service 310c69
  [EIO]     = "Input/output error",
Packit Service 310c69
  [ENXIO]   = "No such device or address",
Packit Service 310c69
  [E2BIG]   = "Argument list too long",
Packit Service 310c69
  [ENOEXEC] = "Exec format error",
Packit Service 310c69
  [EBADF]   = "Bad file descriptor",
Packit Service 310c69
  [ECHILD]  = "No child processes",
Packit Service 310c69
  [EAGAIN]  = "Resource temporarily unavailable",
Packit Service 310c69
  [ENOMEM]  = "Cannot allocate memory",
Packit Service 310c69
  [EACCES]  = "Permission denied",
Packit Service 310c69
  [EFAULT]  = "Bad address",
Packit Service 310c69
  [ENOTBLK] = "Block device required",
Packit Service 310c69
  [EBUSY]   = "Device or resource busy",
Packit Service 310c69
  [EEXIST]  = "File exists",
Packit Service 310c69
  [EXDEV]   = "Invalid cross-device link",
Packit Service 310c69
  [ENODEV]  = "No such device",
Packit Service 310c69
  [ENOTDIR] = "Not a directory",
Packit Service 310c69
  [EISDIR]  = "Is a directory",
Packit Service 310c69
  [EINVAL]  = "Invalid argument",
Packit Service 310c69
  [ENFILE]  = "Too many open files in system",
Packit Service 310c69
  [EMFILE]  = "Too many open files",
Packit Service 310c69
  [ENOTTY]  = "Inappropriate ioctl for device",
Packit Service 310c69
  [ETXTBSY] = "Text file busy",
Packit Service 310c69
  [EFBIG]   = "File too large",
Packit Service 310c69
  [ENOSPC]  = "No space left on device",
Packit Service 310c69
  [ESPIPE]  = "Illegal seek",
Packit Service 310c69
  [EROFS]   = "Read-only file system",
Packit Service 310c69
  [EMLINK]  = "Too many links",
Packit Service 310c69
  [EPIPE]   = "Broken pipe",
Packit Service 310c69
  [EDOM]    = "Numerical argument out of domain",
Packit Service 310c69
  [ERANGE]  = "Numerical result out of range"
Packit Service 310c69
};
Packit Service 310c69
#endif
Packit Service 310c69
Packit Service 310c69
static const struct errorInfo errorList[] = {
Packit Service 310c69
  { "UDS_UNINITIALIZED", "UDS library is not initialized" },
Packit Service 310c69
  { "UDS_SHUTTINGDOWN", "UDS library is shutting down" },
Packit Service 310c69
  { "UDS_EMODULE_LOAD", "Could not load modules" },
Packit Service 310c69
  { "UDS_ENOTHREADS", "Could not create a new thread" },
Packit Service 310c69
  { "UDS_NOCONTEXT", "Could not find the requested library context" },
Packit Service 310c69
  { "UDS_DISABLED", "UDS library context is disabled" },
Packit Service 310c69
  { "UDS_CORRUPT_COMPONENT", "Corrupt saved component" },
Packit Service 310c69
  { "UDS_UNKNOWN_ERROR", "Unknown error" },
Packit Service 310c69
  { "UDS_UNUSED_CODE_8", "Unused error code 8" },
Packit Service 310c69
  { "UDS_UNUSED_CODE_9", "Unused error code 9" },
Packit Service 310c69
  { "UDS_UNSUPPORTED_VERSION", "Unsupported version" },
Packit Service 310c69
  { "UDS_NO_INDEXSESSION", "Index session not known" },
Packit Service 310c69
  { "UDS_CORRUPT_DATA", "Index data in memory is corrupt" },
Packit Service 310c69
  { "UDS_SHORT_READ", "Could not read requested number of bytes" },
Packit Service 310c69
  { "UDS_UNUSED_CODE_14", "Unused error code 14" },
Packit Service 310c69
  { "UDS_RESOURCE_LIMIT_EXCEEDED", "Internal resource limits exceeded" },
Packit Service 310c69
  { "UDS_VOLUME_OVERFLOW", "Memory overflow due to storage failure" },
Packit Service 310c69
  { "UDS_UNUSED_CODE_17", "Unused error code 17" },
Packit Service 310c69
  { "UDS_UNUSED_CODE_18", "Unused error code 18" },
Packit Service 310c69
  { "UDS_UNUSED_CODE_19", "Unused error code 19" },
Packit Service 310c69
  { "UDS_CONF_PTR_REQUIRED", "A configuration pointer is required" },
Packit Service 310c69
  { "UDS_INDEX_STATS_PTR_REQUIRED", "An index stats pointer is required" },
Packit Service 310c69
  { "UDS_CONTEXT_STATS_PTR_REQUIRED", "A context stats pointer is required" },
Packit Service 310c69
  { "UDS_UNUSED_CODE_23", "Unused error code 23" },
Packit Service 310c69
  { "UDS_UNUSED_CODE_24", "Unused error code 24" },
Packit Service 310c69
  { "UDS_UNUSED_CODE_25", "Unused error code 25" },
Packit Service 310c69
  { "UDS_UNUSED_CODE_26", "Unused error code 26" },
Packit Service 310c69
  { "UDS_UNUSED_CODE_27", "Unused error code 27" },
Packit Service 310c69
  { "UDS_INVALID_MEMORY_SIZE",
Packit Service 310c69
    "Configured memory too small or unsupported size" },
Packit Service 310c69
  { "UDS_UNUSED_CODE_29", "Unused error code 29" },
Packit Service 310c69
  { "UDS_INDEX_NAME_REQUIRED", "An index name is required" },
Packit Service 310c69
  { "UDS_CONF_REQUIRED", "A configuration is required" },
Packit Service 310c69
  { "UDS_UNUSED_CODE_32", "Unused error code 32" },
Packit Service 310c69
  { "UDS_UNUSED_CODE_33", "Unused error code 33" },
Packit Service 310c69
  { "UDS_UNUSED_CODE_34", "Unused error code 34" },
Packit Service 310c69
  { "UDS_UNUSED_CODE_35", "Unused error code 35" },
Packit Service 310c69
  { "UDS_UNUSED_CODE_36", "Unused error code 36" },
Packit Service 310c69
  { "UDS_NO_INDEX", "No index found" },
Packit Service 310c69
  { "UDS_BAD_CHECKPOINT_FREQUENCY", "Checkpoint frequency out of range" },
Packit Service 310c69
  { "UDS_WRONG_INDEX_CONFIG", "Wrong type of index configuration" },
Packit Service 310c69
  { "UDS_UNUSED_CODE_40", "Unused error code 40" },
Packit Service 310c69
  { "UDS_UNUSED_CODE_41", "Unused error code 41" },
Packit Service 310c69
  { "UDS_UNUSED_CODE_42", "Unused error code 42" },
Packit Service 310c69
  { "UDS_UNUSED_CODE_43", "Unused error code 43" },
Packit Service 310c69
  { "UDS_END_OF_FILE", "Unexpected end of file" },
Packit Service 310c69
  { "UDS_INDEX_NOT_SAVED_CLEANLY", "Index not saved cleanly" },
Packit Service 310c69
  { "UDS_UNUSED_CODE_46", "Unused error code 46" },
Packit Service 310c69
  { "UDS_INSUFFICIENT_INDEX_SPACE", "Insufficient index space" },
Packit Service 310c69
  { "UDS_UNUSED_CODE_48", "Unused error code 48" },
Packit Service 310c69
  { "UDS_UNUSED_CODE_49", "Unused error code 49" },
Packit Service 310c69
  { "UDS_SUSPENDED", "Index suspended"},
Packit Service 310c69
  { "UDS_UNUSED_CODE_51", "Unused error code 51" },
Packit Service 310c69
  { "UDS_INDEXSESSION_IN_USE", "Index session in use"},
Packit Service 310c69
  { "UDS_CALLBACK_REQUIRED", "A callback function is required"},
Packit Service 310c69
  { "UDS_INVALID_OPERATION_TYPE", "Invalid type of request operation"},
Packit Service 310c69
};
Packit Service 310c69
Packit Service 310c69
static const struct errorInfo internalErrorList[] = {
Packit Service 310c69
  { "UDS_INTERNAL_UNUSED_0", "Unused internal error 0" },
Packit Service 310c69
  { "UDS_OVERFLOW", "Index overflow" },
Packit Service 310c69
  { "UDS_INTERNAL_UNUSED_2", "Unused internal error 2" },
Packit Service 310c69
  { "UDS_INVALID_ARGUMENT", "Invalid argument passed to internal routine" },
Packit Service 310c69
  { "UDS_BAD_STATE", "UDS data structures are in an invalid state" },
Packit Service 310c69
  { "UDS_DUPLICATE_NAME",
Packit Service 310c69
    "Attempt to enter the same name into a delta index twice" },
Packit Service 310c69
  { "UDS_UNEXPECTED_RESULT", "Unexpected result from internal routine" },
Packit Service 310c69
  { "UDS_INJECTED_ERROR", "Injected error" },
Packit Service 310c69
  { "UDS_ASSERTION_FAILED", "Assertion failed" },
Packit Service 310c69
  { "UDS_INTERNAL_UNUSED_9", "Unused internal error 9" },
Packit Service 310c69
  { "UDS_QUEUED", "Request queued" },
Packit Service 310c69
  { "UDS_INTERNAL_UNUSED_11", "Unused internal error 11" },
Packit Service 310c69
  { "UDS_INTERNAL_UNUSED_12", "Unused internal error 12" },
Packit Service 310c69
  { "UDS_BUFFER_ERROR", "Buffer error" },
Packit Service 310c69
  { "UDS_INTERNAL_UNUSED_14", "Unused internal error 14" },
Packit Service 310c69
  { "UDS_INTERNAL_UNUSED_15", "Unused internal error 15" },
Packit Service 310c69
  { "UDS_NO_DIRECTORY", "Expected directory is missing" },
Packit Service 310c69
  { "UDS_CHECKPOINT_INCOMPLETE", "Checkpoint not completed" },
Packit Service 310c69
  { "UDS_INTERNAL_UNUSED_18", "Unused internal error 18" },
Packit Service 310c69
  { "UDS_INTERNAL_UNUSED_19", "Unused internal error 19" },
Packit Service 310c69
  { "UDS_ALREADY_REGISTERED", "Error range already registered" },
Packit Service 310c69
  { "UDS_BAD_IO_DIRECTION", "Bad I/O direction" },
Packit Service 310c69
  { "UDS_INCORRECT_ALIGNMENT", "Offset not at block alignment" },
Packit Service 310c69
  { "UDS_OUT_OF_RANGE", "Cannot access data outside specified limits" },
Packit Service 310c69
};
Packit Service 310c69
Packit Service 310c69
typedef struct errorBlock {
Packit Service 310c69
  const char      *name;
Packit Service 310c69
  int              base;
Packit Service 310c69
  int              last;
Packit Service 310c69
  int              max;
Packit Service 310c69
  const ErrorInfo *infos;
Packit Service 310c69
} ErrorBlock;
Packit Service 310c69
Packit Service 310c69
enum {
Packit Service 310c69
  MAX_ERROR_BLOCKS = 6          // needed for testing
Packit Service 310c69
};
Packit Service 310c69
Packit Service 310c69
static struct errorInformation {
Packit Service 310c69
  int        allocated;
Packit Service 310c69
  int        count;
Packit Service 310c69
  ErrorBlock blocks[MAX_ERROR_BLOCKS];
Packit Service 310c69
} registeredErrors = {
Packit Service 310c69
  .allocated = MAX_ERROR_BLOCKS,
Packit Service 310c69
  .count     = 2,
Packit Service 310c69
  .blocks    = {
Packit Service 310c69
    {
Packit Service 310c69
      .name  = "UDS Error",
Packit Service 310c69
      .base  = UDS_ERROR_CODE_BASE,
Packit Service 310c69
      .last  = UDS_ERROR_CODE_LAST,
Packit Service 310c69
      .max   = UDS_ERROR_CODE_BLOCK_END,
Packit Service 310c69
      .infos = errorList,
Packit Service 310c69
    },
Packit Service 310c69
    {
Packit Service 310c69
      .name  = "UDS Internal Error",
Packit Service 310c69
      .base  = UDS_INTERNAL_ERROR_CODE_BASE,
Packit Service 310c69
      .last  = UDS_INTERNAL_ERROR_CODE_LAST,
Packit Service 310c69
      .max   = UDS_INTERNAL_ERROR_CODE_BLOCK_END,
Packit Service 310c69
      .infos = internalErrorList,
Packit Service 310c69
    }
Packit Service 310c69
  }
Packit Service 310c69
};
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Fetch the error info (if any) for the error number.
Packit Service 310c69
 *
Packit Service 310c69
 * @param errnum        the error number
Packit Service 310c69
 * @param infoPtr       the place to store the info for this error (if known),
Packit Service 310c69
 *                      otherwise set to NULL
Packit Service 310c69
 *
Packit Service 310c69
 * @return              the name of the error block (if known), NULL othersise
Packit Service 310c69
 **/
Packit Service 310c69
static const char *getErrorInfo(int errnum, const ErrorInfo **infoPtr)
Packit Service 310c69
{
Packit Service 310c69
Packit Service 310c69
  if (errnum == UDS_SUCCESS) {
Packit Service 310c69
    if (infoPtr != NULL) {
Packit Service 310c69
      *infoPtr = &successful;
Packit Service 310c69
    }
Packit Service 310c69
    return NULL;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  ErrorBlock *block;
Packit Service 310c69
  for (block = registeredErrors.blocks;
Packit Service 310c69
       block < registeredErrors.blocks + registeredErrors.count;
Packit Service 310c69
       ++block) {
Packit Service 310c69
    if ((errnum >= block->base) && (errnum < block->last)) {
Packit Service 310c69
      if (infoPtr != NULL) {
Packit Service 310c69
        *infoPtr = block->infos + (errnum - block->base);
Packit Service 310c69
      }
Packit Service 310c69
      return block->name;
Packit Service 310c69
    } else if ((errnum >= block->last) && (errnum < block->max)) {
Packit Service 310c69
      if (infoPtr != NULL) {
Packit Service 310c69
        *infoPtr = NULL;
Packit Service 310c69
      }
Packit Service 310c69
      return block->name;
Packit Service 310c69
    }
Packit Service 310c69
  }
Packit Service 310c69
  if (infoPtr != NULL) {
Packit Service 310c69
    *infoPtr = NULL;
Packit Service 310c69
  }
Packit Service 310c69
  return NULL;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Return string describing a system error message
Packit Service 310c69
 *
Packit Service 310c69
 * @param errnum  System error number
Packit Service 310c69
 * @param buf     Buffer that can be used to contain the return value
Packit Service 310c69
 * @param buflen  Length of the buffer
Packit Service 310c69
 *
Packit Service 310c69
 * @return The error string, which may be a string constant or may be
Packit Service 310c69
 *         returned in the buf argument
Packit Service 310c69
 **/
Packit Service 310c69
#ifdef __KERNEL__
Packit Service 310c69
static const char *systemStringError(int errnum, char *buf, size_t buflen)
Packit Service 310c69
{
Packit Service 310c69
  const char *errorString = NULL;
Packit Service 310c69
  if ((errnum > 0) && (errnum < COUNT_OF(messageTable))) {
Packit Service 310c69
    errorString = messageTable[errnum];
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  size_t len = ((errorString == NULL)
Packit Service 310c69
                ? snprintf(buf, buflen, "Unknown error %d", errnum)
Packit Service 310c69
                : snprintf(buf, buflen, "%s", errorString));
Packit Service 310c69
  if (len < buflen) {
Packit Service 310c69
    return buf;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  buf[0] = '\0';
Packit Service 310c69
  return "System error";
Packit Service 310c69
}
Packit Service 310c69
#else
Packit Service 310c69
static INLINE const char *systemStringError(int errnum, char *buf,
Packit Service 310c69
                                            size_t buflen)
Packit Service 310c69
{
Packit Service 310c69
  return strerror_r(errnum, buf, buflen);
Packit Service 310c69
}
Packit Service 310c69
#endif
Packit Service 310c69
Packit Service 310c69
/*****************************************************************************/
Packit Service 310c69
const char *stringError(int errnum, char *buf, size_t buflen)
Packit Service 310c69
{
Packit Service 310c69
  if (buf == NULL) {
Packit Service 310c69
    return NULL;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  char *buffer = buf;
Packit Service 310c69
  char *bufEnd = buf + buflen;
Packit Service 310c69
Packit Service 310c69
  if (isUnrecoverable(errnum)) {
Packit Service 310c69
    buffer = appendToBuffer(buffer, bufEnd, "Unrecoverable error: ");
Packit Service 310c69
    errnum = sansUnrecoverable(errnum);
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  const ErrorInfo *info      = NULL;
Packit Service 310c69
  const char      *blockName = getErrorInfo(errnum, &info;;
Packit Service 310c69
Packit Service 310c69
  if (blockName != NULL) {
Packit Service 310c69
    if (info != NULL) {
Packit Service 310c69
      buffer = appendToBuffer(buffer, bufEnd,
Packit Service 310c69
                              "%s: %s", blockName, info->message);
Packit Service 310c69
    } else {
Packit Service 310c69
      buffer = appendToBuffer(buffer, bufEnd,
Packit Service 310c69
                              "Unknown %s %d", blockName, errnum);
Packit Service 310c69
    }
Packit Service 310c69
  } else if (info != NULL) {
Packit Service 310c69
    buffer = appendToBuffer(buffer, bufEnd, "%s", info->message);
Packit Service 310c69
  } else {
Packit Service 310c69
    const char *tmp = systemStringError(errnum, buffer, bufEnd - buffer);
Packit Service 310c69
    if (tmp != buffer) {
Packit Service 310c69
      buffer = appendToBuffer(buffer, bufEnd, "%s", tmp);
Packit Service 310c69
    } else {
Packit Service 310c69
      buffer += strlen(tmp);
Packit Service 310c69
    }
Packit Service 310c69
  }
Packit Service 310c69
  return buf;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/*****************************************************************************/
Packit Service 310c69
const char *stringErrorName(int errnum, char *buf, size_t buflen)
Packit Service 310c69
{
Packit Service 310c69
  errnum = sansUnrecoverable(errnum);
Packit Service 310c69
Packit Service 310c69
  char *buffer = buf;
Packit Service 310c69
  char *bufEnd = buf + buflen;
Packit Service 310c69
Packit Service 310c69
  const ErrorInfo *info      = NULL;
Packit Service 310c69
  const char      *blockName = getErrorInfo(errnum, &info;;
Packit Service 310c69
Packit Service 310c69
  if (blockName != NULL) {
Packit Service 310c69
    if (info != NULL) {
Packit Service 310c69
      buffer = appendToBuffer(buffer, bufEnd, "%s", info->name);
Packit Service 310c69
    } else {
Packit Service 310c69
      buffer = appendToBuffer(buffer, bufEnd, "%s %d", blockName, errnum);
Packit Service 310c69
    }
Packit Service 310c69
  } else if (info != NULL) {
Packit Service 310c69
    buffer = appendToBuffer(buffer, bufEnd, "%s", info->name);
Packit Service 310c69
  } else {
Packit Service 310c69
    const char *tmp = systemStringError(errnum, buffer, bufEnd - buffer);
Packit Service 310c69
    if (tmp != buffer) {
Packit Service 310c69
      buffer = appendToBuffer(buffer, bufEnd, "%s", tmp);
Packit Service 310c69
    } else {
Packit Service 310c69
      buffer += strlen(tmp);
Packit Service 310c69
    }
Packit Service 310c69
  }
Packit Service 310c69
  return buf;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/*****************************************************************************/
Packit Service 310c69
int registerErrorBlock(const char      *blockName,
Packit Service 310c69
                       int              firstError,
Packit Service 310c69
                       int              lastReservedError,
Packit Service 310c69
                       const ErrorInfo *infos,
Packit Service 310c69
                       size_t           infoSize)
Packit Service 310c69
{
Packit Service 310c69
  int result = ASSERT(firstError < lastReservedError,
Packit Service 310c69
                      "bad error block range");
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  if (registeredErrors.count == registeredErrors.allocated) {
Packit Service 310c69
    // could reallocate and grow, but should never happen
Packit Service 310c69
    return UDS_OVERFLOW;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  ErrorBlock *block;
Packit Service 310c69
  for (block = registeredErrors.blocks;
Packit Service 310c69
       block < registeredErrors.blocks + registeredErrors.count;
Packit Service 310c69
       ++block) {
Packit Service 310c69
    if (strcmp(blockName, block->name) == 0) {
Packit Service 310c69
      return UDS_DUPLICATE_NAME;
Packit Service 310c69
    }
Packit Service 310c69
    // check for overlap in error ranges
Packit Service 310c69
    if ((firstError < block->max) && (lastReservedError > block->base)) {
Packit Service 310c69
      return UDS_ALREADY_REGISTERED;
Packit Service 310c69
    }
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  registeredErrors.blocks[registeredErrors.count++] = (ErrorBlock) {
Packit Service 310c69
    .name  = blockName,
Packit Service 310c69
    .base  = firstError,
Packit Service 310c69
    .last  = firstError + (infoSize / sizeof(ErrorInfo)),
Packit Service 310c69
    .max   = lastReservedError,
Packit Service 310c69
    .infos = infos
Packit Service 310c69
  };
Packit Service 310c69
Packit Service 310c69
  return UDS_SUCCESS;
Packit Service 310c69
}