1 /*****************************************************************************\
2  *  $Id: ipmi-sdr.c,v 1.20 2010-02-08 22:09:40 chu11 Exp $
3  *****************************************************************************
4  *  Copyright (C) 2007-2015 Lawrence Livermore National Security, LLC.
5  *  Copyright (C) 2006-2007 The Regents of the University of California.
6  *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
7  *  Written by Albert Chu <chu11@llnl.gov>
8  *  UCRL-CODE-222073
9  *
10  *  This file is part of Ipmimonitoring, an IPMI sensor monitoring
11  *  library.  For details, see http://www.llnl.gov/linux/.
12  *
13  *  Ipmimonitoring is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by the
15  *  Free Software Foundation; either version 3 of the License, or (at your
16  *  option) any later version.
17  *
18  *  Ipmimonitoring is distributed in the hope that it will be useful, but
19  *  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20  *  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
21  *  for more details.
22  *
23  *  You should have received a copy of the GNU General Public License along
24  *  with Ipmimonitoring.  If not, see <http://www.gnu.org/licenses/>.
25 \*****************************************************************************/
26 
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif /* HAVE_CONFIG_H */
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #if STDC_HEADERS
34 #include <string.h>
35 #endif /* STDC_HEADERS */
36 #if HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif /* HAVE_UNISTD_H */
39 #include <sys/mman.h>
40 #include <assert.h>
41 #include <errno.h>
42 
43 #include "freeipmi/sdr/ipmi-sdr.h"
44 
45 #include "ipmi-sdr-common.h"
46 #include "ipmi-sdr-defs.h"
47 #include "ipmi-sdr-trace.h"
48 #include "ipmi-sdr-util.h"
49 
50 #include "freeipmi-portability.h"
51 
52 static char *ipmi_sdr_cache_errmsgs[] =
53   {
54     "success",
55     "context null",
56     "context invalid",
57     "invalid parameters",
58     "out of memory",
59     "filename invalid",
60     "file system error",
61     "filename path permission error",
62     "context performing other operation",
63     "SDR cache exists",
64     "SDR record with an identical record id already written",
65     "SDR record length invalid",
66     "SDR record count invalid",
67     "SDR cache reading initialization already called",
68     "cache reading not initialized",
69     "SDR cache does not exist",
70     "SDR cache invalid",
71     "SDR cache out of date",
72     "stats not compiled",
73     "invalid sdr record",
74     "incomplete sdr record",
75     "cannot parse or calculate",
76     "error returned in callback",
77     "not found",
78     "internal IPMI error",
79     "internal system error",
80     "buffer overflow",
81     "internal error",
82     "errnum out of range",
83     NULL
84   };
85 
86 ipmi_sdr_ctx_t
ipmi_sdr_ctx_create(void)87 ipmi_sdr_ctx_create (void)
88 {
89   struct ipmi_sdr_ctx *ctx = NULL;
90 
91   if (!(ctx = (ipmi_sdr_ctx_t)malloc (sizeof (struct ipmi_sdr_ctx))))
92     {
93       ERRNO_TRACE (errno);
94       return (NULL);
95     }
96   memset (ctx, '\0', sizeof (struct ipmi_sdr_ctx));
97   ctx->magic = IPMI_SDR_CTX_MAGIC;
98   ctx->flags = IPMI_SDR_FLAGS_DEFAULT;
99   ctx->debug_prefix = NULL;
100 
101   if (!(ctx->saved_offsets = list_create ((ListDelF)free)))
102     {
103       ERRNO_TRACE (errno);
104       goto cleanup;
105     }
106 
107   sdr_init_ctx (ctx);
108   return (ctx);
109 
110  cleanup:
111   if (ctx)
112     {
113       if (ctx->saved_offsets)
114         list_destroy (ctx->saved_offsets);
115       free (ctx);
116     }
117   return (NULL);
118 }
119 
120 void
ipmi_sdr_ctx_destroy(ipmi_sdr_ctx_t ctx)121 ipmi_sdr_ctx_destroy (ipmi_sdr_ctx_t ctx)
122 {
123   if (!ctx || ctx->magic != IPMI_SDR_CTX_MAGIC)
124     return;
125 
126   if (ctx->callback_lock)
127     {
128       SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_CONTEXT_PERFORMING_OTHER_OPERATION);
129       return;
130     }
131 
132   /* ignore potential error, destroy path */
133   if (ctx->fd >= 0)
134     close (ctx->fd);
135   /* ignore potential error, void return func */
136   if (ctx->sdr_cache)
137     munmap (ctx->sdr_cache, ctx->file_size);
138 
139   list_destroy (ctx->saved_offsets);
140 
141   ctx->magic = ~IPMI_SDR_CTX_MAGIC;
142   ctx->operation = IPMI_SDR_OPERATION_UNINITIALIZED;
143   free (ctx->debug_prefix);
144   free (ctx);
145 }
146 
147 int
ipmi_sdr_ctx_errnum(ipmi_sdr_ctx_t ctx)148 ipmi_sdr_ctx_errnum (ipmi_sdr_ctx_t ctx)
149 {
150   if (!ctx)
151     return (IPMI_SDR_ERR_CONTEXT_NULL);
152   else if (ctx->magic != IPMI_SDR_CTX_MAGIC)
153     return (IPMI_SDR_ERR_CONTEXT_INVALID);
154   else
155     return (ctx->errnum);
156 }
157 
158 char *
ipmi_sdr_ctx_strerror(int errnum)159 ipmi_sdr_ctx_strerror (int errnum)
160 {
161   if (errnum >= IPMI_SDR_ERR_SUCCESS && errnum <= IPMI_SDR_ERR_ERRNUMRANGE)
162     return (ipmi_sdr_cache_errmsgs[errnum]);
163   else
164     return (ipmi_sdr_cache_errmsgs[IPMI_SDR_ERR_ERRNUMRANGE]);
165 }
166 
167 char *
ipmi_sdr_ctx_errormsg(ipmi_sdr_ctx_t ctx)168 ipmi_sdr_ctx_errormsg (ipmi_sdr_ctx_t ctx)
169 {
170   return (ipmi_sdr_ctx_strerror (ipmi_sdr_ctx_errnum (ctx)));
171 }
172 
173 int
ipmi_sdr_ctx_get_flags(ipmi_sdr_ctx_t ctx,unsigned int * flags)174 ipmi_sdr_ctx_get_flags (ipmi_sdr_ctx_t ctx, unsigned int *flags)
175 {
176   if (!ctx || ctx->magic != IPMI_SDR_CTX_MAGIC)
177     {
178       ERR_TRACE (ipmi_sdr_ctx_errormsg (ctx), ipmi_sdr_ctx_errnum (ctx));
179       return (-1);
180     }
181 
182   if (!flags)
183     {
184       SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARAMETERS);
185       return (-1);
186     }
187 
188   *flags = ctx->flags;
189   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
190   return (0);
191 }
192 
193 int
ipmi_sdr_ctx_set_flags(ipmi_sdr_ctx_t ctx,unsigned int flags)194 ipmi_sdr_ctx_set_flags (ipmi_sdr_ctx_t ctx, unsigned int flags)
195 {
196   if (!ctx || ctx->magic != IPMI_SDR_CTX_MAGIC)
197     {
198       ERR_TRACE (ipmi_sdr_ctx_errormsg (ctx), ipmi_sdr_ctx_errnum (ctx));
199       return (-1);
200     }
201 
202   if (flags & ~IPMI_SDR_FLAGS_DEBUG_DUMP)
203     {
204       SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_PARAMETERS);
205       return (-1);
206     }
207 
208   ctx->flags = flags;
209   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
210   return (0);
211 }
212 
213 char *
ipmi_sdr_ctx_get_debug_prefix(ipmi_sdr_ctx_t ctx)214 ipmi_sdr_ctx_get_debug_prefix (ipmi_sdr_ctx_t ctx)
215 {
216   if (!ctx || ctx->magic != IPMI_SDR_CTX_MAGIC)
217     {
218       ERR_TRACE (ipmi_sdr_ctx_errormsg (ctx), ipmi_sdr_ctx_errnum (ctx));
219       return (NULL);
220     }
221 
222   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
223   return (ctx)->debug_prefix;
224 }
225 
226 int
ipmi_sdr_ctx_set_debug_prefix(ipmi_sdr_ctx_t ctx,const char * debug_prefix)227 ipmi_sdr_ctx_set_debug_prefix (ipmi_sdr_ctx_t ctx, const char *debug_prefix)
228 {
229   if (!ctx || ctx->magic != IPMI_SDR_CTX_MAGIC)
230     {
231       ERR_TRACE (ipmi_sdr_ctx_errormsg (ctx), ipmi_sdr_ctx_errnum (ctx));
232       return (-1);
233     }
234 
235   free (ctx->debug_prefix);
236   ctx->debug_prefix = NULL;
237 
238   if (debug_prefix)
239     {
240       if (!(ctx->debug_prefix = strdup (debug_prefix)))
241         {
242           SDR_SET_ERRNUM (ctx, IPMI_SDR_ERR_OUT_OF_MEMORY);
243           return (-1);
244         }
245     }
246 
247   ctx->errnum = IPMI_SDR_ERR_SUCCESS;
248   return (0);
249 }
250