root/lm-sensors/trunk/lib/init.c @ 5730

Revision 5730, 7.8 KB (checked in by khali, 5 years ago)

From Yuriy Kaminskiy:

Most filesystems (in particular - reiserfs, jfs, xfs, nfs); maybe,

some legacy installation of ext2/3 too) always return dirent->dt_type =
DT_UNKNOWN, so libsensors fails to parse /etc/sensors.d.

Also, symlink (DT_LNK) can point to directory, or FIFO/socket/device

(very bad!) - current check insufficient anyways.

Fixed by always using stat() to check what each entry is, rather than
relying on dirent->dt_type.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    init.c - Part of libsensors, a Linux library for reading sensor data.
3    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>
4    Copyright (C) 2007, 2009  Jean Delvare <khali@linux-fr.org>
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19    MA 02110-1301 USA.
20*/
21
22/* Needed for scandir() and alphasort() */
23#define _BSD_SOURCE
24
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <locale.h>
28#include <stdlib.h>
29#include <stdio.h>
30#include <string.h>
31#include <errno.h>
32#include <dirent.h>
33#include <unistd.h>
34#include "sensors.h"
35#include "data.h"
36#include "error.h"
37#include "access.h"
38#include "conf.h"
39#include "sysfs.h"
40#include "scanner.h"
41#include "init.h"
42
43#define DEFAULT_CONFIG_FILE     ETCDIR "/sensors3.conf"
44#define ALT_CONFIG_FILE         ETCDIR "/sensors.conf"
45#define DEFAULT_CONFIG_DIR      ETCDIR "/sensors.d"
46
47/* Wrapper around sensors_yyparse(), which clears the locale so that
48   the decimal numbers are always parsed properly. */
49static int sensors_parse(void)
50{
51        int res;
52        char *locale;
53
54        /* Remember the current locale and clear it */
55        locale = setlocale(LC_ALL, NULL);
56        if (locale) {
57                locale = strdup(locale);
58                if (!locale)
59                        sensors_fatal_error(__func__, "Out of memory");
60
61                setlocale(LC_ALL, "C");
62        }
63
64        res = sensors_yyparse();
65
66        /* Restore the old locale */
67        if (locale) {
68                setlocale(LC_ALL, locale);
69                free(locale);
70        }
71
72        return res;
73}
74
75static void free_bus(sensors_bus *bus)
76{
77        free(bus->adapter);
78}
79
80static void free_config_busses(void)
81{
82        int i;
83
84        for (i = 0; i < sensors_config_busses_count; i++)
85                free_bus(&sensors_config_busses[i]);
86        free(sensors_config_busses);
87        sensors_config_busses = NULL;
88        sensors_config_busses_count = sensors_config_busses_max = 0;
89}
90
91static int parse_config(FILE *input, const char *name)
92{
93        int err;
94        char *name_copy;
95
96        if (name) {
97                /* Record configuration file name for error reporting */
98                name_copy = strdup(name);
99                if (!name_copy)
100                        sensors_fatal_error(__func__, "Out of memory");
101                sensors_add_config_files(&name_copy);
102        } else
103                name_copy = NULL;
104
105        if (sensors_scanner_init(input, name_copy)) {
106                err = -SENSORS_ERR_PARSE;
107                goto exit_cleanup;
108        }
109        err = sensors_parse();
110        sensors_scanner_exit();
111        if (err) {
112                err = -SENSORS_ERR_PARSE;
113                goto exit_cleanup;
114        }
115
116        err = sensors_substitute_busses();
117
118exit_cleanup:
119        free_config_busses();
120        return err;
121}
122
123static int config_file_filter(const struct dirent *entry)
124{
125        return entry->d_name[0] != '.';         /* Skip hidden files */
126}
127
128static int add_config_from_dir(const char *dir)
129{
130        int count, res, i;
131        struct dirent **namelist;
132
133        count = scandir(dir, &namelist, config_file_filter, alphasort);
134        if (count < 0) {
135                /* Do not return an error if directory does not exist */
136                if (errno == ENOENT)
137                        return 0;
138               
139                sensors_parse_error_wfn(strerror(errno), NULL, 0);
140                return -SENSORS_ERR_PARSE;
141        }
142
143        for (res = 0, i = 0; !res && i < count; i++) {
144                int len;
145                char path[PATH_MAX];
146                FILE *input;
147                struct stat st;
148
149                len = snprintf(path, sizeof(path), "%s/%s", dir,
150                               namelist[i]->d_name);
151                if (len < 0 || len >= (int)sizeof(path)) {
152                        res = -SENSORS_ERR_PARSE;
153                        continue;
154                }
155
156                /* Only accept regular files */
157                if (stat(path, &st) < 0 || !S_ISREG(st.st_mode))
158                        continue;
159
160                input = fopen(path, "r");
161                if (input) {
162                        res = parse_config(input, path);
163                        fclose(input);
164                } else {
165                        res = -SENSORS_ERR_PARSE;
166                        sensors_parse_error_wfn(strerror(errno), path, 0);
167                }
168        }
169
170        /* Free memory allocated by scandir() */
171        for (i = 0; i < count; i++)
172                free(namelist[i]);
173        free(namelist);
174
175        return res;
176}
177
178int sensors_init(FILE *input)
179{
180        int res;
181
182        if (!sensors_init_sysfs())
183                return -SENSORS_ERR_KERNEL;
184        if ((res = sensors_read_sysfs_bus()) ||
185            (res = sensors_read_sysfs_chips()))
186                goto exit_cleanup;
187
188        if (input) {
189                res = parse_config(input, NULL);
190                if (res)
191                        goto exit_cleanup;
192        } else {
193                const char* name;
194
195                /* No configuration provided, use default */
196                input = fopen(name = DEFAULT_CONFIG_FILE, "r");
197                if (!input && errno == ENOENT)
198                        input = fopen(name = ALT_CONFIG_FILE, "r");
199                if (input) {
200                        res = parse_config(input, name);
201                        fclose(input);
202                        if (res)
203                                goto exit_cleanup;
204
205                } else if (errno != ENOENT) {
206                        sensors_parse_error_wfn(strerror(errno), name, 0);
207                        res = -SENSORS_ERR_PARSE;
208                        goto exit_cleanup;
209                }
210
211                /* Also check for files in default directory */
212                res = add_config_from_dir(DEFAULT_CONFIG_DIR);
213                if (res)
214                        goto exit_cleanup;
215        }
216
217        return 0;
218
219exit_cleanup:
220        sensors_cleanup();
221        return res;
222}
223
224static void free_chip_name(sensors_chip_name *name)
225{
226        free(name->prefix);
227        free(name->path);
228}
229
230static void free_chip_features(sensors_chip_features *features)
231{
232        int i;
233
234        for (i = 0; i < features->subfeature_count; i++)
235                free(features->subfeature[i].name);
236        free(features->subfeature);
237        for (i = 0; i < features->feature_count; i++)
238                free(features->feature[i].name);
239        free(features->feature);
240}
241
242static void free_label(sensors_label *label)
243{
244        free(label->name);
245        free(label->value);
246}
247
248void sensors_free_expr(sensors_expr *expr)
249{
250        if (expr->kind == sensors_kind_var)
251                free(expr->data.var);
252        else if (expr->kind == sensors_kind_sub) {
253                if (expr->data.subexpr.sub1)
254                        sensors_free_expr(expr->data.subexpr.sub1);
255                if (expr->data.subexpr.sub2)
256                        sensors_free_expr(expr->data.subexpr.sub2);
257        }
258        free(expr);
259}
260
261static void free_set(sensors_set *set)
262{
263        free(set->name);
264        sensors_free_expr(set->value);
265}
266
267static void free_compute(sensors_compute *compute)
268{
269        free(compute->name);
270        sensors_free_expr(compute->from_proc);
271        sensors_free_expr(compute->to_proc);
272}
273
274static void free_ignore(sensors_ignore *ignore)
275{
276        free(ignore->name);
277}
278
279static void free_chip(sensors_chip *chip)
280{
281        int i;
282
283        for (i = 0; i < chip->chips.fits_count; i++)
284                free_chip_name(&chip->chips.fits[i]);
285        free(chip->chips.fits);
286        chip->chips.fits_count = chip->chips.fits_max = 0;
287
288        for (i = 0; i < chip->labels_count; i++)
289                free_label(&chip->labels[i]);
290        free(chip->labels);
291        chip->labels_count = chip->labels_max = 0;
292
293        for (i = 0; i < chip->sets_count; i++)
294                free_set(&chip->sets[i]);
295        free(chip->sets);
296        chip->sets_count = chip->sets_max = 0;
297
298        for (i = 0; i < chip->computes_count; i++)
299                free_compute(&chip->computes[i]);
300        free(chip->computes);
301        chip->computes_count = chip->computes_max = 0;
302
303        for (i = 0; i < chip->ignores_count; i++)
304                free_ignore(&chip->ignores[i]);
305        free(chip->ignores);
306        chip->ignores_count = chip->ignores_max = 0;
307}
308
309void sensors_cleanup(void)
310{
311        int i;
312
313        for (i = 0; i < sensors_proc_chips_count; i++) {
314                free_chip_name(&sensors_proc_chips[i].chip);
315                free_chip_features(&sensors_proc_chips[i]);
316        }
317        free(sensors_proc_chips);
318        sensors_proc_chips = NULL;
319        sensors_proc_chips_count = sensors_proc_chips_max = 0;
320
321        for (i = 0; i < sensors_config_chips_count; i++)
322                free_chip(&sensors_config_chips[i]);
323        free(sensors_config_chips);
324        sensors_config_chips = NULL;
325        sensors_config_chips_count = sensors_config_chips_max = 0;
326        sensors_config_chips_subst = 0;
327
328        for (i = 0; i < sensors_proc_bus_count; i++)
329                free_bus(&sensors_proc_bus[i]);
330        free(sensors_proc_bus);
331        sensors_proc_bus = NULL;
332        sensors_proc_bus_count = sensors_proc_bus_max = 0;
333
334        for (i = 0; i < sensors_config_files_count; i++)
335                free(sensors_config_files[i]);
336        free(sensors_config_files);
337        sensors_config_files = NULL;
338        sensors_config_files_count = sensors_config_files_max = 0;
339}
Note: See TracBrowser for help on using the browser.