root/lm-sensors/trunk/lib/access.c @ 2345

Revision 2345, 16.8 KB (checked in by mmh, 9 years ago)

Patch by Philipp Thomas <pth@…>:

Current gcc versions warn when type punning is used, as this breaks the
strict aliasing analysis gcc 3.3 does by default. When checking the causes
for these warnings I discovered that sensors_malloc_array,
sensors_free_array, sensors_add_array_el and sensors_add_array_els in
lib/general.c all take a 'void **' for the list. This is plain wrong as
the C standard only allow 'char *' and 'void *' to alias any other type, so
if these functions should take a generic pointer, it *must* be a 'void *'
that's internally cast to a 'void **'.

The attached patch does this and adapts all places where these functions are
called. Note that when done correctly, no cast what-so-ever in the calling
code is needed.

The patch is against current lm_sensors2 cvs version.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    access.c - Part of libsensors, a Linux library for reading sensor data.
3    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18*/
19
20#include <stdlib.h>
21#include <string.h>
22#include <math.h>
23#include "access.h"
24#include "sensors.h"
25#include "data.h"
26#include "error.h"
27#include "proc.h"
28#include "general.h"
29
30static int sensors_do_this_chip_sets(sensors_chip_name name);
31
32/* Compare two chips name descriptions, to see whether they could match.
33   Return 0 if it does not match, return 1 if it does match. */
34int sensors_match_chip(sensors_chip_name chip1, sensors_chip_name chip2)
35{
36  if ((chip1.prefix != SENSORS_CHIP_NAME_PREFIX_ANY) &&
37      (chip2.prefix != SENSORS_CHIP_NAME_PREFIX_ANY) &&
38      strcasecmp(chip1.prefix,chip2.prefix))
39    return 0;
40  if ((chip1.bus != SENSORS_CHIP_NAME_BUS_ANY) && 
41      (chip2.bus != SENSORS_CHIP_NAME_BUS_ANY) &&
42      (chip1.bus != chip2.bus)) {
43    if ((chip1.bus == SENSORS_CHIP_NAME_BUS_ISA) ||
44        (chip2.bus == SENSORS_CHIP_NAME_BUS_ISA))
45      return 0;
46    if ((chip1.bus != SENSORS_CHIP_NAME_BUS_ANY_I2C) &&
47        (chip2.bus != SENSORS_CHIP_NAME_BUS_ANY_I2C))
48      return 0;
49  }
50  if ((chip1.addr != chip2.addr) &&
51      (chip1.addr != SENSORS_CHIP_NAME_ADDR_ANY) &&
52      (chip2.addr != SENSORS_CHIP_NAME_ADDR_ANY))
53    return 0;
54  return 1;
55}
56
57/* Returns, one by one, a pointer to all sensor_chip structs of the
58   config file which match with the given chip name. Last should be
59   the value returned by the last call, or NULL if this is the first
60   call. Returns NULL if no more matches are found. Do not modify
61   the struct the return value points to!
62   Note that this visits the list of chips from last to first. Usually,
63   you want the match that was latest in the config file. */
64sensors_chip *sensors_for_all_config_chips(sensors_chip_name chip_name, 
65                                           const sensors_chip *last)
66{
67  int nr,i;
68  sensors_chip_name_list chips;
69
70  for (nr = last?(last-sensors_config_chips)-1:sensors_config_chips_count-1; 
71       nr >= 0; nr--) {
72    chips = sensors_config_chips[nr].chips;
73    for (i =0; i < chips.fits_count; i++) {
74      if (sensors_match_chip(chips.fits[i],chip_name))
75        return sensors_config_chips+nr;
76    }
77  }
78  return NULL;
79}
80
81/* Look up a resource in the intern chip list, and return a pointer to it.
82   Do not modify the struct the return value points to! Returns NULL if
83   not found.*/
84const sensors_chip_feature *sensors_lookup_feature_nr(const char *prefix, 
85                                                      int feature)
86{
87  int i,j;
88  const sensors_chip_feature *features;
89  for (i = 0; sensors_chip_features_list[i].prefix; i++)
90    if (!strcasecmp(sensors_chip_features_list[i].prefix,prefix)) {
91      features = sensors_chip_features_list[i].feature;
92      for (j=0;  features[j].name; j++) 
93        if (features[j].number == feature)
94          return features + j;
95    }
96  return NULL;
97}
98
99/* Look up a resource in the intern chip list, and return a pointer to it.
100   Do not modify the struct the return value points to! Returns NULL if
101   not found.*/
102const sensors_chip_feature *sensors_lookup_feature_name(const char *prefix,
103                                                        const char *feature)
104{
105  int i,j;
106  const sensors_chip_feature *features;
107  for (i = 0; sensors_chip_features_list[i].prefix; i++)
108    if (!strcasecmp(sensors_chip_features_list[i].prefix,prefix)) {
109      features = sensors_chip_features_list[i].feature;
110      for (j=0;  features[j].name; j++) 
111        if (!strcasecmp(features[j].name,feature))
112          return features + j;
113    }
114  return NULL;
115}
116
117
118/* Check whether the chip name is an 'absolute' name, which can only match
119   one chip, or whether it has wildcards. Returns 0 if it is absolute, 1
120   if there are wildcards. */
121int sensors_chip_name_has_wildcards(sensors_chip_name chip)
122{
123  extern int foundsysfs;
124
125  if(foundsysfs) {
126    if (chip.prefix == SENSORS_CHIP_NAME_PREFIX_ANY)
127      return 1;
128    else
129      return 0;
130  }     
131  if ((chip.prefix == SENSORS_CHIP_NAME_PREFIX_ANY) ||
132      (chip.bus == SENSORS_CHIP_NAME_BUS_ANY) ||
133      (chip.bus == SENSORS_CHIP_NAME_BUS_ANY_I2C) ||
134      (chip.addr == SENSORS_CHIP_NAME_ADDR_ANY))
135    return 1;
136  else
137    return 0;
138}
139
140/* Look up the label which belongs to this chip. Note that chip should not
141   contain wildcard values! *result is newly allocated (free it yourself).
142   This function will return 0 on success, and <0 on failure. 
143   Changed behaviour as of libsensors.so.1: now we actually take notice
144   of the logical class, as documented, but not done before! */
145int sensors_get_label(sensors_chip_name name, int feature, char **result)
146{
147  const sensors_chip *chip;
148  const sensors_chip_feature *featureptr;
149  const sensors_chip_feature *alt_featureptr;
150  int i;
151
152  *result=NULL;
153  if (sensors_chip_name_has_wildcards(name))
154    return -SENSORS_ERR_WILDCARDS;
155  if (! (featureptr = sensors_lookup_feature_nr(name.prefix,feature)))
156    return -SENSORS_ERR_NO_ENTRY;
157  if (featureptr->logical_mapping == SENSORS_NO_MAPPING)
158    alt_featureptr = NULL;
159  else if (! (alt_featureptr =
160                   sensors_lookup_feature_nr(name.prefix,
161                                             featureptr->logical_mapping)))
162    return -SENSORS_ERR_NO_ENTRY;
163  for (chip = NULL; (chip = sensors_for_all_config_chips(name,chip));)
164    for (i = 0; i < chip->labels_count; i++)
165      if (!strcasecmp(featureptr->name, chip->labels[i].name)) {
166        if (*result)
167          free(*result);
168        if (! (*result = strdup(chip->labels[i].value)))
169          sensors_fatal_error("sensors_get_label","Allocating label text");
170        return 0; /* Exact match always overrules! */
171      } else if (alt_featureptr && 
172                 !strcasecmp(alt_featureptr->name, chip->labels[i].name)) {
173        if (*result)
174          free(*result);
175        if (! (*result = strdup(chip->labels[i].value)))
176          sensors_fatal_error("sensors_get_label","Allocating label text");
177      }
178  if (! (*result = strdup(featureptr->name)))
179    sensors_fatal_error("sensors_get_label","Allocating label text");
180  return 0;
181}
182
183int sensors_get_ignored(sensors_chip_name name, int feature)
184{
185  const sensors_chip *chip;
186  const sensors_chip_feature *featureptr;
187  const sensors_chip_feature *alt_featureptr;
188  int i,res;
189
190  res = 1; /* Default: valid */
191  if (sensors_chip_name_has_wildcards(name))
192    return -SENSORS_ERR_WILDCARDS;
193  if (! (featureptr = sensors_lookup_feature_nr(name.prefix,feature)))
194    return -SENSORS_ERR_NO_ENTRY;
195  if (featureptr->logical_mapping == SENSORS_NO_MAPPING)
196    alt_featureptr = NULL;
197  else if (! (alt_featureptr =
198                   sensors_lookup_feature_nr(name.prefix,
199                                             featureptr->logical_mapping)))
200    return -SENSORS_ERR_NO_ENTRY;
201  for (chip = NULL; (chip = sensors_for_all_config_chips(name,chip));)
202    for (i = 0; i < chip->ignores_count; i++)
203      if (!strcasecmp(featureptr->name, chip->ignores[i].name))
204        return 0; /* Exact match always overrules! */
205      else if (alt_featureptr &&
206               !strcasecmp(alt_featureptr->name, chip->ignores[i].name))
207        res = 0;
208  return res;
209}
210
211/* Read the value of a feature of a certain chip. Note that chip should not
212   contain wildcard values! This function will return 0 on success, and <0
213   on failure. */
214int sensors_get_feature(sensors_chip_name name, int feature, double *result)
215{
216  const sensors_chip_feature *main_feature;
217  const sensors_chip_feature *alt_feature;
218  const sensors_chip *chip;
219  const sensors_expr *expr = NULL;
220  double val;
221  int res,i;
222  int final_expr=0;
223
224  if (sensors_chip_name_has_wildcards(name))
225    return -SENSORS_ERR_WILDCARDS;
226  if (! (main_feature = sensors_lookup_feature_nr(name.prefix,feature)))
227    return -SENSORS_ERR_NO_ENTRY;
228  if (main_feature->compute_mapping == SENSORS_NO_MAPPING)
229    alt_feature = NULL;
230  else if (! (alt_feature =
231                   sensors_lookup_feature_nr(name.prefix,
232                                             main_feature->compute_mapping)))
233    return -SENSORS_ERR_NO_ENTRY;
234  if (! (main_feature->mode & SENSORS_MODE_R))
235    return -SENSORS_ERR_ACCESS_R;
236  for (chip = NULL; !expr && (chip = sensors_for_all_config_chips(name,chip));)
237    for (i = 0; !final_expr && (i < chip->computes_count); i++) {
238      if (!strcasecmp(main_feature->name,chip->computes[i].name)) {
239        expr = chip->computes[i].from_proc;
240        final_expr = 1;
241      } else if (alt_feature && 
242                 !strcasecmp(alt_feature->name,chip->computes[i].name))
243        expr = chip->computes[i].from_proc;
244    }
245  if (sensors_read_proc(name,feature,&val))
246    return -SENSORS_ERR_PROC;
247  if (! expr)
248    *result = val;
249  else if ((res = sensors_eval_expr(name,expr,val,result)))
250    return res;
251  return 0;
252}
253     
254/* Set the value of a feature of a certain chip. Note that chip should not
255   contain wildcard values! This function will return 0 on success, and <0
256   on failure. */
257int sensors_set_feature(sensors_chip_name name, int feature, double value)
258{
259  const sensors_chip_feature *main_feature;
260  const sensors_chip_feature *alt_feature;
261  const sensors_chip *chip;
262  const sensors_expr *expr = NULL;
263  int i,res;
264  int final_expr=0;
265  double to_write;
266
267  if (sensors_chip_name_has_wildcards(name))
268    return -SENSORS_ERR_WILDCARDS;
269  if (! (main_feature = sensors_lookup_feature_nr(name.prefix,feature)))
270    return -SENSORS_ERR_NO_ENTRY;
271  if (main_feature->compute_mapping == SENSORS_NO_MAPPING)
272    alt_feature = NULL;
273  else if (! (alt_feature =
274                   sensors_lookup_feature_nr(name.prefix,
275                                             main_feature->compute_mapping)))
276    return -SENSORS_ERR_NO_ENTRY;
277  if (! (main_feature->mode & SENSORS_MODE_W))
278    return -SENSORS_ERR_ACCESS_W;
279  for (chip = NULL; !expr && (chip = sensors_for_all_config_chips(name,chip));)
280    for (i = 0; !final_expr && (i < chip->computes_count); i++)
281      if (!strcasecmp(main_feature->name,chip->computes[i].name)) {
282        expr = chip->computes->to_proc;
283        final_expr = 1;
284      } else if (alt_feature && 
285                 !strcasecmp(alt_feature->name,chip->computes[i].name))
286        expr = chip->computes[i].to_proc;
287
288  to_write = value;
289  if (expr)
290    if ((res = sensors_eval_expr(name,expr,value,&to_write)))
291      return res;
292  if (sensors_write_proc(name,feature,to_write))
293    return -SENSORS_ERR_PROC;
294  return 0;
295}
296
297const sensors_chip_name *sensors_get_detected_chips (int *nr)
298{
299  const sensors_chip_name *res;
300  res =  *nr >= sensors_proc_chips_count?NULL:&sensors_proc_chips[*nr].name;
301  (*nr)++;
302  return res;
303}
304
305const char *sensors_get_adapter_name(int bus_nr)
306{
307  int i;
308
309  if (bus_nr == SENSORS_CHIP_NAME_BUS_ISA)
310    return "ISA adapter";
311  if (bus_nr == SENSORS_CHIP_NAME_BUS_DUMMY)
312    return "Dummy adapter";
313  for (i=0; i < sensors_proc_bus_count; i++)
314    if (sensors_proc_bus[i].number == bus_nr)
315      return sensors_proc_bus[i].adapter;
316  return NULL;
317}
318
319const char *sensors_get_algorithm_name(int bus_nr)
320{
321  int i;
322
323  if (bus_nr == SENSORS_CHIP_NAME_BUS_ISA)
324    return "ISA algorithm";
325  if (bus_nr == SENSORS_CHIP_NAME_BUS_DUMMY)
326    return "Dummy algorithm";
327  for (i=0; i < sensors_proc_bus_count; i++)
328    if (sensors_proc_bus[i].number == bus_nr)
329      return sensors_proc_bus[i].algorithm;
330  return NULL;
331}
332
333/* nr1-1 is the last main feature found; nr2-1 is the last subfeature found */
334const sensors_feature_data *sensors_get_all_features (sensors_chip_name name, 
335                                                      int *nr1, int*nr2)
336{
337  sensors_chip_feature *feature_list;
338  int i;
339
340  for (i = 0; sensors_chip_features_list[i].prefix; i++)
341    if (!strcasecmp(sensors_chip_features_list[i].prefix,name.prefix)) {
342      feature_list=sensors_chip_features_list[i].feature;
343      if (!*nr1 && !*nr2) { /* Return the first entry */
344        if (!feature_list[0].name) /* The list may be empty */
345          return NULL;
346        *nr1 = *nr2 = 1;
347        return (sensors_feature_data *) (feature_list + 0);
348      }
349      for ((*nr2)++; feature_list[*nr2-1].name; (*nr2)++) 
350        if (feature_list[*nr2-1].logical_mapping == feature_list[*nr1-1].number)
351          return (sensors_feature_data *) (feature_list + *nr2 - 1);
352      for ((*nr1)++; feature_list[*nr1-1].name && 
353                  (feature_list[*nr1-1].logical_mapping != SENSORS_NO_MAPPING);
354           (*nr1)++);
355      *nr2 = *nr1;
356      if (! feature_list[*nr1-1].name)
357        return NULL;
358      return (sensors_feature_data *) (feature_list + *nr1 - 1);
359    }
360  return NULL;
361}
362
363int sensors_eval_expr(sensors_chip_name chipname, const sensors_expr *expr,
364                      double val, double *result)
365{
366  double res1,res2;
367  int res;
368  const sensors_chip_feature *feature;
369
370  if (expr->kind == sensors_kind_val) {
371    *result = expr->data.val;
372    return 0;
373  }
374  if (expr->kind == sensors_kind_source) {
375    *result = val;
376    return 0;
377  }
378  if (expr->kind == sensors_kind_var) {
379    if (! (feature = sensors_lookup_feature_name(chipname.prefix,
380                                                expr->data.var)))
381      return SENSORS_ERR_NO_ENTRY;
382    if (! (res = sensors_get_feature(chipname,feature->number,result)))
383      return res;
384    return 0;
385  }
386  if ((res = sensors_eval_expr(chipname,expr->data.subexpr.sub1,val,&res1)))
387    return res;
388  if (expr->data.subexpr.sub2 &&
389      (res = sensors_eval_expr(chipname,expr->data.subexpr.sub2,val,&res2)))
390    return res;
391  switch(expr->data.subexpr.op) {
392  case sensors_add:
393    *result = res1 + res2;
394    return 0;
395  case sensors_sub:
396    *result = res1 - res2;
397    return 0;
398  case sensors_multiply:
399    *result = res1 * res2;
400    return 0;
401  case sensors_divide:
402    if (res2 == 0.0)
403      return -SENSORS_ERR_DIV_ZERO;
404    *result = res1 / res2;
405    return 0;
406  case sensors_negate:
407    *result = -res1;
408    return 0;
409  case sensors_exp:
410    *result = exp(res1);
411    return 0;
412  case sensors_log:
413    if (res1 < 0.0)
414      return -SENSORS_ERR_DIV_ZERO;
415    *result = log(res1);
416    return 0;
417  }
418  return 0;
419}
420
421/* Execute all set statements for this particular chip. The chip may not
422   contain wildcards!  This function will return 0 on success, and <0 on
423   failure. */
424int sensors_do_this_chip_sets(sensors_chip_name name)
425{
426  sensors_chip *chip;
427  double value;
428  int err,i,j;
429  int res = 0;
430  const sensors_chip_feature *feature;
431  int *feature_list = NULL;
432  int feature_count = 0;
433  int feature_max = 0;
434  int feature_nr;
435
436  for(chip = NULL; (chip = sensors_for_all_config_chips(name,chip));)
437    for(i = 0; i < chip->sets_count; i++) {
438      feature = sensors_lookup_feature_name(name.prefix,chip->sets[i].name);
439      if (! feature) {
440        sensors_parse_error("Unknown feature name",chip->sets[i].lineno);
441        err = SENSORS_ERR_NO_ENTRY;
442        continue;
443      }
444      feature_nr = feature->number;
445
446      /* Check whether we already set this feature */
447      for(j = 0; j < feature_count; j++)
448        if(feature_list[j] == feature_nr)
449          break;
450      if (j != feature_count)
451        continue;
452      sensors_add_array_el(&feature_nr,&feature_list,&feature_count,
453                        &feature_max, sizeof(int));
454
455      res = sensors_eval_expr(name,chip->sets[i].value,0,&value);
456      if (res) {
457        sensors_parse_error("Parsing expression",chip->sets[i].lineno);
458        err = res;
459        continue;
460      }
461      if ((res = sensors_set_feature(name,feature_nr,value))) {
462        err = res;
463        continue;
464      }
465    }
466  free(feature_list);
467  return res;
468}
469
470/* Execute all set statements for this particular chip. The chip may contain
471   wildcards!  This function will return 0 on success, and <0 on failure. */
472int sensors_do_chip_sets(sensors_chip_name name)
473{
474  int nr,this_res;
475  const sensors_chip_name *found_name;
476  int res = 0;
477
478  for (nr = 0; (found_name = sensors_get_detected_chips(&nr));)
479    if (sensors_match_chip(name,*found_name)) {
480      this_res = sensors_do_this_chip_sets(*found_name);
481      if (! res)
482        res = this_res;
483    }
484  return res;
485}
486
487/* Execute all set statements for all detected chips. This is the same as
488   calling sensors_do_chip_sets with an all wildcards chip name */
489int sensors_do_all_sets(void)
490{
491  sensors_chip_name name = { SENSORS_CHIP_NAME_PREFIX_ANY, 
492                             SENSORS_CHIP_NAME_BUS_ANY,
493                             SENSORS_CHIP_NAME_ADDR_ANY };
494  return sensors_do_chip_sets(name);
495}
496
Note: See TracBrowser for help on using the browser.