Print this page
    
4378 Clean up %C in *time() functions
438 need documentation for strftime %s flag
    
      
        | Split | Close | 
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/lib/libfru/libnvfru/nvfru.c
          +++ new/usr/src/lib/libfru/libnvfru/nvfru.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  
    | ↓ open down ↓ | 12 lines elided | ↑ open up ↑ | 
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
       23 + * Copyright (c) 2014 Gary Mills
       24 + *
  23   25   * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  24   26   */
  25   27  
  26   28  #include <stdio.h>
  27   29  #include <stdlib.h>
  28   30  #include <stdint.h>
  29   31  #include <strings.h>
  30   32  #include <assert.h>
  31   33  #include <pthread.h>
  32   34  #include <sys/byteorder.h>
  33   35  #include <sys/types.h>
  34   36  #include <sys/nvpair.h>
  35   37  
  36   38  #include "libfru.h"
  37   39  #include "libfrup.h"
  38   40  #include "fru_tag.h"
  39   41  #include "libfrureg.h"
  40   42  #include "nvfru.h"
  41   43  
  42   44  #define NUM_ITER_BYTES  4
  43   45  #define HEAD_ITER       0
  44   46  #define TAIL_ITER       1
  45   47  #define NUM_ITER        2
  46   48  #define MAX_ITER        3
  47   49  #define TIMESTRINGLEN   128
  48   50  
  49   51  #define PARSE_TIME      1
  50   52  
  51   53  static pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER;
  52   54  
  53   55  
  54   56  
  55   57  static void
  56   58  convert_field(const uint8_t *field, const fru_regdef_t *def, const char *path,
  57   59      nvlist_t *nv)
  58   60  {
  59   61          char timestring[TIMESTRINGLEN];
  60   62          int i;
  61   63          uint64_t value;
  62   64          time_t timefield;
  63   65  
  64   66          switch (def->dataType) {
  65   67          case FDTYPE_Binary:
  
    | ↓ open down ↓ | 33 lines elided | ↑ open up ↑ | 
  66   68                  assert(def->payloadLen <= sizeof (value));
  67   69                  switch (def->dispType) {
  68   70  #if PARSE_TIME == 1
  69   71                  case FDISP_Time:
  70   72                          if (def->payloadLen > sizeof (timefield)) {
  71   73                                  /* too big for formatting */
  72   74                                  return;
  73   75                          }
  74   76                          (void) memcpy(&timefield, field, sizeof (timefield));
  75   77                          timefield = BE_32(timefield);
  76      -                        if (strftime(timestring, sizeof (timestring), "%C",
       78 +                        if (strftime(timestring, sizeof (timestring), "%c",
  77   79                              localtime(&timefield)) == 0) {
  78   80                                  /* buffer too small */
  79   81                                  return;
  80   82                          }
  81   83                          (void) nvlist_add_string(nv, path, timestring);
  82   84                          return;
  83   85  #endif
  84   86  
  85   87                  case FDISP_Binary:
  86   88                  case FDISP_Octal:
  87   89                  case FDISP_Decimal:
  88   90                  case FDISP_Hex:
  89   91                  default:
  90   92                          value = 0;
  91   93                          (void) memcpy((((uint8_t *)&value) +
  92   94                              sizeof (value) - def->payloadLen),
  93   95                              field, def->payloadLen);
  94   96                          value = BE_64(value);
  95   97                          switch (def->payloadLen) {
  96   98                          case 1:
  97   99                                  (void) nvlist_add_uint8(nv, path,
  98  100                                      (uint8_t)value);
  99  101                                  break;
 100  102                          case 2:
 101  103                                  (void) nvlist_add_uint16(nv, path,
 102  104                                      (uint16_t)value);
 103  105                                  break;
 104  106                          case 4:
 105  107                                  (void) nvlist_add_uint32(nv, path,
 106  108                                      (uint32_t)value);
 107  109                                  break;
 108  110                          default:
 109  111                                  (void) nvlist_add_uint64(nv, path, value);
 110  112                          }
 111  113                          return;
 112  114                  }
 113  115  
 114  116          case FDTYPE_ASCII:
 115  117                  (void) nvlist_add_string(nv, path, (char *)field);
 116  118                  return;
 117  119  
 118  120          case FDTYPE_Enumeration:
 119  121                  value = 0;
 120  122                  (void) memcpy((((uint8_t *)&value) + sizeof (value) -
 121  123                      def->payloadLen), field, def->payloadLen);
 122  124                  value = BE_64(value);
 123  125                  for (i = 0; i < def->enumCount; i++) {
 124  126                          if (def->enumTable[i].value == value) {
 125  127                                  (void) nvlist_add_string(nv, path,
 126  128                                      def->enumTable[i].text);
 127  129                                  return;
 128  130                          }
 129  131                  }
 130  132          }
 131  133  
 132  134          /* nothing matched above, use byte array */
 133  135          (void) nvlist_add_byte_array(nv, path, (uchar_t *)field,
 134  136              def->payloadLen);
 135  137  }
 136  138  
 137  139  
 138  140  
 139  141  static void
 140  142  convert_element(const uint8_t *data, const fru_regdef_t *def, char *ppath,
 141  143      nvlist_t *nv, boolean_t from_iter)
 142  144  {
 143  145          int i;
 144  146          char *path;
 145  147  
 146  148          /* construct path */
 147  149          if ((def->iterationCount == 0) &&
 148  150              (def->iterationType != FRU_NOT_ITERATED)) {
 149  151                  path = ppath;
 150  152          } else {
 151  153                  path = (char *)def->name;
 152  154          }
 153  155  
 154  156          /* iteration, record and field */
 155  157          if (def->iterationCount) {
 156  158                  int iterlen, n;
 157  159                  uint8_t head, num;
 158  160                  fru_regdef_t newdef;
 159  161                  nvlist_t **nv_elems;
 160  162                  char num_str[32];
 161  163  
 162  164                  iterlen = (def->payloadLen - NUM_ITER_BYTES) /
 163  165                      def->iterationCount;
 164  166  
 165  167                  /*
 166  168                   * make a new element definition to describe the components of
 167  169                   * the iteration.
 168  170                   */
 169  171                  (void) memcpy(&newdef, def, sizeof (newdef));
 170  172                  newdef.iterationCount = 0;
 171  173                  newdef.payloadLen = iterlen;
 172  174  
 173  175                  /* validate the content of the iteration control bytes */
 174  176                  if ((data[HEAD_ITER] >= def->iterationCount) ||
 175  177                      (data[NUM_ITER] > def->iterationCount) ||
 176  178                      (data[MAX_ITER] != def->iterationCount)) {
 177  179                          /* invalid. show all iterations */
 178  180                          head = 0;
 179  181                          num = def->iterationCount;
 180  182                  } else {
 181  183                          head = data[HEAD_ITER];
 182  184                          num = data[NUM_ITER];
 183  185                  }
 184  186  
 185  187                  nv_elems = (nvlist_t **)malloc(num * sizeof (nvlist_t *));
 186  188                  if (!nv_elems)
 187  189                          return;
 188  190                  for (i = head, n = 0, data += sizeof (uint32_t); n < num;
 189  191                      i = ((i + 1) % def->iterationCount), n++) {
 190  192                          if (nvlist_alloc(&nv_elems[n], NV_UNIQUE_NAME, 0) != 0)
 191  193                                  return;
 192  194                          (void) snprintf(num_str, sizeof (num_str), "%d", n);
 193  195                          convert_element((data + i*iterlen), &newdef, num_str,
 194  196                              nv_elems[n], B_TRUE);
 195  197                  }
 196  198                  (void) nvlist_add_nvlist_array(nv, path, nv_elems, num);
 197  199  
 198  200          } else if (def->dataType == FDTYPE_Record) {
 199  201                  const fru_regdef_t *component;
 200  202                  nvlist_t *nv_record;
 201  203  
 202  204                  if (!from_iter) {
 203  205                          if (nvlist_alloc(&nv_record, NV_UNIQUE_NAME, 0) != 0) {
 204  206                                  return;
 205  207                          }
 206  208                  } else {
 207  209                          nv_record = nv;
 208  210                  }
 209  211  
 210  212                  for (i = 0; i < def->enumCount; i++,
 211  213                      data += component->payloadLen) {
 212  214                          component = fru_reg_lookup_def_by_name(
 213  215                              def->enumTable[i].text);
 214  216                          convert_element(data, component, "", nv_record,
 215  217                              B_FALSE);
 216  218                  }
 217  219  
 218  220                  (void) nvlist_add_nvlist(nv, path, nv_record);
 219  221  
 220  222          } else {
 221  223                  convert_field(data, def, path, nv);
 222  224          }
 223  225  }
 224  226  
 225  227  
 226  228  static fru_regdef_t *
 227  229  alloc_unknown_fru_regdef(void)
 228  230  {
 229  231          fru_regdef_t *p;
 230  232  
 231  233          p = malloc(sizeof (fru_regdef_t));
 232  234          if (!p) {
 233  235                  return (NULL);
 234  236          }
 235  237          p->version = REGDEF_VERSION;
 236  238          p->name = NULL;
 237  239          p->tagType = -1;
 238  240          p->tagDense = -1;
 239  241          p->payloadLen = -1;
 240  242          p->dataLength = -1;
 241  243          p->dataType = FDTYPE_ByteArray;
 242  244          p->dispType = FDISP_Hex;
 243  245          p->purgeable = FRU_WHICH_UNDEFINED;
 244  246          p->relocatable = FRU_WHICH_UNDEFINED;
 245  247          p->enumCount = 0;
 246  248          p-> enumTable = NULL;
 247  249          p->iterationCount = 0;
 248  250          p->iterationType = FRU_NOT_ITERATED;
 249  251          p->exampleString = NULL;
 250  252  
 251  253          return (p);
 252  254  }
 253  255  
 254  256  static int
 255  257  convert_packet(fru_tag_t *tag, uint8_t *payload, size_t length, void *args)
 256  258  {
 257  259          int tag_type;
 258  260          size_t payload_length;
 259  261          const fru_regdef_t *def;
 260  262          nvlist_t *nv = (nvlist_t *)args;
 261  263          char tagname[sizeof ("?_0123456789_0123456789")];
 262  264          tag_type = get_tag_type(tag);
 263  265          payload_length = 0;
 264  266  
 265  267          /* check for unrecognized tag */
 266  268          if ((tag_type == -1) ||
 267  269              ((payload_length = get_payload_length(tag)) != length)) {
 268  270                  fru_regdef_t *unknown;
 269  271  
 270  272                  unknown = alloc_unknown_fru_regdef();
 271  273                  unknown->payloadLen = length;
 272  274                  unknown->dataLength = unknown->payloadLen;
 273  275  
 274  276                  if (tag_type == -1) {
 275  277                          (void) snprintf(tagname, sizeof (tagname),
 276  278                              "INVALID");
 277  279                  } else {
 278  280                          (void) snprintf(tagname, sizeof (tagname),
 279  281                              "%s_%u_%u_%u", get_tagtype_str(tag_type),
 280  282                              get_tag_dense(tag), payload_length, length);
 281  283                  }
 282  284                  unknown->name = tagname;
 283  285                  convert_element(payload, unknown, "", nv, B_FALSE);
 284  286                  free(unknown);
 285  287  
 286  288          } else if ((def = fru_reg_lookup_def_by_tag(*tag)) == NULL) {
 287  289                  fru_regdef_t *unknown;
 288  290  
 289  291                  unknown = alloc_unknown_fru_regdef();
 290  292                  unknown->payloadLen = length;
 291  293                  unknown->dataLength = unknown->payloadLen;
 292  294  
 293  295                  (void) snprintf(tagname, sizeof (tagname), "%s_%u_%u",
 294  296                      get_tagtype_str(tag_type),
 295  297                      unknown->tagDense, payload_length);
 296  298  
 297  299                  unknown->name = tagname;
 298  300                  convert_element(payload, unknown, "", nv, B_FALSE);
 299  301                  free(unknown);
 300  302  
 301  303          } else {
 302  304  
 303  305                  convert_element(payload, def, "", nv, B_FALSE);
 304  306  
 305  307          }
 306  308  
 307  309          return (FRU_SUCCESS);
 308  310  }
 309  311  
 310  312  
 311  313  static int
 312  314  convert_packets_in_segment(fru_seghdl_t segment, void *args)
 313  315  {
 314  316          char *name;
 315  317          int ret;
 316  318          nvlist_t *nv = (nvlist_t *)args;
 317  319          nvlist_t *nv_segment;
 318  320  
 319  321          ret = fru_get_segment_name(segment, &name);
 320  322          if (ret != FRU_SUCCESS) {
 321  323                  return (ret);
 322  324          }
 323  325  
 324  326          /* create a new nvlist for each segment */
 325  327          ret = nvlist_alloc(&nv_segment, NV_UNIQUE_NAME, 0);
 326  328          if (ret) {
 327  329                  free(name);
 328  330                  return (FRU_FAILURE);
 329  331          }
 330  332  
 331  333          /* convert the segment to an nvlist */
 332  334          ret = fru_for_each_packet(segment, convert_packet, nv_segment);
 333  335          if (ret != FRU_SUCCESS) {
 334  336                  nvlist_free(nv_segment);
 335  337                  free(name);
 336  338                  return (ret);
 337  339          }
 338  340  
 339  341          /* add the nvlist for this segment */
 340  342          (void) nvlist_add_nvlist(nv, name, nv_segment);
 341  343  
 342  344          free(name);
 343  345  
 344  346          return (FRU_SUCCESS);
 345  347  }
 346  348  
 347  349  
 348  350  static int
 349  351  convert_fru(fru_nodehdl_t hdl, nvlist_t **nvlist)
 350  352  {
 351  353          int err;
 352  354          nvlist_t *nv;
 353  355          fru_node_t fru_type;
 354  356  
 355  357          if (fru_get_node_type(hdl, &fru_type) != FRU_SUCCESS) {
 356  358                  return (-1);
 357  359          }
 358  360  
 359  361          if (fru_type != FRU_NODE_CONTAINER) {
 360  362                  return (-1);
 361  363          }
 362  364  
 363  365          err = nvlist_alloc(&nv, NV_UNIQUE_NAME, 0);
 364  366          if (err) {
 365  367                  return (err);
 366  368          }
 367  369  
 368  370          if (fru_for_each_segment(hdl, convert_packets_in_segment, nv) !=
 369  371              FRU_SUCCESS) {
 370  372                  nvlist_free(nv);
 371  373                  return (-1);
 372  374          }
 373  375  
 374  376          *nvlist = nv;
 375  377  
 376  378          return (0);
 377  379  }
 378  380  
 379  381  
 380  382  int
 381  383  rawfru_to_nvlist(uint8_t *buffer, size_t bufsize, char *cont_type,
 382  384      nvlist_t **nvlist)
 383  385  {
 384  386          fru_errno_t fru_err;
 385  387          fru_nodehdl_t hdl;
 386  388          int err;
 387  389  
 388  390          (void) pthread_mutex_lock(&gLock);
 389  391          fru_err = fru_open_data_source("raw", buffer, bufsize, cont_type,
 390  392              NULL);
 391  393          if (fru_err != FRU_SUCCESS) {
 392  394                  (void) pthread_mutex_unlock(&gLock);
 393  395                  return (-1);
 394  396          }
 395  397          fru_err = fru_get_root(&hdl);
 396  398          if (fru_err != FRU_SUCCESS) {
 397  399                  (void) pthread_mutex_unlock(&gLock);
 398  400                  return (-1);
 399  401          }
 400  402  
 401  403          err = convert_fru(hdl, nvlist);
 402  404  
 403  405          fru_close_data_source();
 404  406  
 405  407          (void) pthread_mutex_unlock(&gLock);
 406  408  
 407  409          return (err);
 408  410  }
  
    | ↓ open down ↓ | 322 lines elided | ↑ open up ↑ | 
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX