Logo Search packages:      
Sourcecode: lcrash version File versions  Download package

kl_libutil.c

/*
 * $Id: kl_libutil.c,v 1.1 2004/12/21 23:26:23 tjm Exp $
 *
 * This file is part of libutil.
 * A library which provides auxiliary functions.
 * libutil is part of lkcdutils -- utilities for Linux kernel crash dumps.
 *
 * Created by Silicon Graphics, Inc.
 * Contributions by IBM, NEC, and others
 *
 * Copyright (C) 1999 - 2004 Silicon Graphics, Inc. All rights reserved.
 * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
 * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
 *
 * This code is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version. See the file COPYING for more
 * information.
 */
#include <kl_lib.h>

#define MAX_LONG_LONG   0xffffffffffffffffULL

/*
 * kl_shift_value()
 */
int
kl_shift_value(uint64_t value)
{
      int i;

      if (value == 0) {
            return(-1);
      }

      for (i = 0; i < 64; i++) {
            if (value & (((uint64_t)1) << i)) {
                  break;
            }
      }
      return(i);
}

/*
 * kl_string_compare()
 */
int
kl_string_compare(char *s1, char *s2)
{
      int len_1 = strlen(s1);
      int len_2 = strlen(s2);

      if (len_1 > len_2) {
            return(1);
      }
      else if (len_2 > len_1) {
            return(-1);
      }
      return(strcmp(s1, s2));
}

/*
 * kl_string_match()
 */
int
kl_string_match(char *s1, char *s2)
{
      if (s1) {
            if (!s2) {
                  return(0);
            }
            else if (strcmp(s1, s2)) {
                  return(0);
            }
      }
      else if (s2) {
            return(0);
      }
      return(1);
}

static int
valid_digit(char c, int base)
{
      switch(base) {
            case 2:
                  if ((c >= '0') && (c <= '1')) {
                        return(1);
                  } else {
                        return(0);
                  }
            case 8:
                  if ((c >= '0') && (c <= '7')) {
                        return(1);
                  } else {
                        return(0);
                  }
            case 10:
                  if ((c >= '0') && (c <= '9')) {
                        return(1);
                  } else {
                        return(0);
                  }
            case 16:
                  if (((c >= '0') && (c <= '9'))
                              || ((c >= 'a') && (c <= 'f'))
                              || ((c >= 'A') && (c <= 'F'))) {
                        return(1);
                  } else {
                        return(0);
                  }
      }
      return(0);
}

static int
digit_value(char c, int base, int *val)
{
      if (!valid_digit(c, base)) {
            return(1);
      }
      switch (base) {
            case 2:
            case 8:
            case 10:
                  *val = (int)((int)(c - 48));
                  break;
            case 16:
                  if ((c >= 'a') && (c <= 'f')) {
                        *val = ((int)(c - 87));
                  } else if ((c >= 'A') && (c <= 'F')) {
                        *val = ((int)(c - 55));
                  } else {
                        *val = ((int)(c - 48));
                  }
      }
      return(0);
}

/*
 * kl_strtoull()
 */
uint64_t
kl_strtoull(char *str, char **loc, int base)
{
      int dval;
      uint64_t i = 1, v, value = 0;
      char *c, *cp = str;

      *loc = (char *)NULL;
      if (base == 0) {
            if (!strncmp(cp, "0x", 2) || !strncmp(cp, "0X", 2)) {
                  base = 16;
            } else if (cp[0] == '0') {
                  if (cp[1] == 'b') {
                        base = 2;
                  } else {
                        base = 8;
                  }
            } else if (strpbrk(cp, "abcdefABCDEF")) {
                  base = 16;
            } else {
                  base = 10;
            }
      }
      if ((base == 8) && (*cp == '0')) {
            cp += 1;
      } else if ((base == 2) && !strncmp(cp, "0b", 2)) {
            cp += 2;
      } else if ((base == 16) &&
                  (!strncmp(cp, "0x", 2) || !strncmp(cp, "0X", 2))) {
            cp += 2;
      }
      c = &cp[strlen(cp) - 1];
      while (c >= cp) {

            if (digit_value(*c, base, &dval)) {
                  if (loc) {
                        *loc = c;
                  }
                  return(value);
            }
            v = dval * i;
            if ((MAX_LONG_LONG - value) < v) {
                  errno = ERANGE;
                  return(MAX_LONG_LONG);
            }
            value += v;
            i *= (uint64_t)base;
            c--;
      }
      return(value);
}

#define SECONDS_IN_DAY 86400
#define SECONDS_IN_HOUR 3600
#define SECONDS_IN_MINUTE 60

/*
 * is_delim_char()
 */
static int
is_delim_char(char c, char *delimstr)
{
      int i;
      for (i = 0; i < strlen(delimstr); i++) {
            if (c == delimstr[i]) {
                  return(1);
            }
      }
      return(0);
}

/*
 * get_val()
 */
static int
get_val(char **tstr, long *val, int sz, char *delimstr)
{
      int i, cnt, len;
      long v;
      char *p, *tval = *tstr;
      char tmpstr[11];

      if (!tval) {
            return(1);
      }
      if (!(len = strlen(tval)))  {
            return(2);
      }

      for (cnt = 0; cnt < len; cnt++) {
            if (is_delim_char(tval[cnt], delimstr)) {
                  break;
            } else if (!isdigit(tval[cnt])) {
                  return(3);
            }
      }
      if (cnt == len) {
            *tstr = (char *)NULL;
      } else {
            *tstr = (char *)((unsigned long)tval + cnt + 1);
      }
      if (cnt > sz) {
            /* Exceeds the maximum field size
             */
            return(4);
      }
      for (i = 0; i < cnt; i++) {
            tmpstr[i] = tval[i];
      }
      tmpstr[i] = 0;
      errno = 0;
      v = strtol(tmpstr, &p, 10);
      if (p && *p) {
            return(5);
      } else if (errno) {
            return(99);
      }
      *val = v;
      return(0);
}

/*
 * kl_str_to_ctime()
 */
time_t
kl_str_to_ctime(char *timestr)
{
      int ret, i, offset;
      long val, days, months, years;
      int minutes = 0, hours = 0, seconds = 0;
      char *tval;
      time_t ctime = 0;
      struct tm ltime, gmtime;

      tval = timestr;

      /* Get month
       */
      if ((ret = get_val(&tval, &months, 2, "/"))) {
            return(-1);
      }

      /* Get day
       */
      if (get_val(&tval, &days, 2, "/")) {
            return(-2);
      }

      /* Get year
       */
      if (get_val(&tval, &years, 4, " ")) {
            return(-3);
      }

      /* Make sure our values are in range
       */
      if (months > 12) {
            return(-4);
      }

      if (years < 1970) {
            if ((years >= 70) && (years <= 99)) {
                  years += 1900;
            } else if ((years >= 0) && (years <= 50)) {
                  years += 2000;
            } else {
                  return(-5);
            }
      }

      switch(months) {
            case 2:
                  if (years % 4) {
                        if (days > 28) {
                              return(-6);
                        }
                  } else {
                        if (days > 29) {
                              return(-7);
                        }
                  }
                  break;

            case 4:
            case 6:
            case 9:
            case 11:
                  if (days > 30) {
                        return(-8);
                  }
                  break;

            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
            case 12:
                  if (days > 31) {
                        return(-9);
                  }
                  break;

      }

      /* Add the seconds for all full years.
       */
      for (i = 1970; i < years; i++) {
            if (i % 4) {
                  ctime += 365 * SECONDS_IN_DAY;
            } else {
                  ctime += 366 * SECONDS_IN_DAY;
            }
      }

      /* Add the seconds for all full months.
       */
      for (i = 1; i < months; i++) {
            switch (i) {

                  case 2:
                        if (years % 4) {
                              ctime += 28 *
                                    SECONDS_IN_DAY;
                        } else {
                              ctime += 29 *
                                    SECONDS_IN_DAY;
                        }
                        break;

                  case 4:
                  case 6:
                  case 9:
                  case 11:
                        ctime += 30 * SECONDS_IN_DAY;
                        break;

                  case 1:
                  case 3:
                  case 5:
                  case 7:
                  case 8:
                  case 10:
                        ctime += 31 * SECONDS_IN_DAY;
                        break;

            }
      }

      /* Add the seconds for all full days in the month
       */
      ctime += (days - 1) * SECONDS_IN_DAY;

      /* Add the time for the hours, minutes, and seconds
       */
      if (tval && isdigit(tval[0])) {
            if (get_val(&tval, &val, 2, " :")) {
                  return(-10);
            }
            hours = (int)val;
            if (tval) {
                  if (strstr(tval, "PM")) {
                        hours += 12;
                  }
                  if (tval && isdigit(tval[0])) {
                        if (get_val(&tval, &val, 2, " :")) {
                              return(-11);
                        }
                        minutes = (int)val;
                        if (tval && isdigit(tval[0])) {
                              if (get_val(&tval, &val, 2, " :")) {
                                    return(-12);
                              }
                              seconds = (int)val;
                        }
                  }
            }
            ctime += (hours * SECONDS_IN_HOUR);
            ctime += (minutes * SECONDS_IN_MINUTE);
            ctime += seconds;
      }

      /* Adjust for local time and daylight savings time.
       * We have to make sure that we watch for the case
       * where we are at the start of a month or year...
       */
      localtime_r(&ctime, &ltime);
      gmtime_r(&ctime, &gmtime);

      /* Determine the offset between local time and GMT
       */
      if (ltime.tm_yday == gmtime.tm_yday) {
            offset = (gmtime.tm_hour - ltime.tm_hour);
      } else if ((ltime.tm_year < gmtime.tm_year) ||
                  (ltime.tm_yday < gmtime.tm_yday)) {
            offset = (24 + gmtime.tm_hour) - ltime.tm_hour;
      } else {
            offset = (24 + ltime.tm_hour) - gmtime.tm_hour;
      }
      ctime += (offset * SECONDS_IN_HOUR);
      if (ctime > 2147483647) {
            return(-13);
      }
      return(ctime);
}

/*
 * kl_get_ra()
 *
 * This function returns its own return address.
 * Usefule when trying to capture where we came from.
 */
void*
kl_get_ra(void)
{
      return (__builtin_return_address(0));
}

Generated by  Doxygen 1.6.0   Back to index