xref: /third_party/eudev/src/libudev/libudev.c (revision 99ca880a)
1/***
2  This file is part of systemd.
3
4  Copyright 2008-2014 Kay Sievers <kay@vrfy.org>
5
6  systemd is free software; you can redistribute it and/or modify it
7  under the terms of the GNU Lesser General Public License as published by
8  the Free Software Foundation; either version 2.1 of the License, or
9  (at your option) any later version.
10
11  systemd is distributed in the hope that it will be useful, but
12  WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  Lesser General Public License for more details.
15
16  You should have received a copy of the GNU Lesser General Public License
17  along with systemd; If not, see <http://www.gnu.org/licenses/>.
18***/
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <stddef.h>
23#include <stdarg.h>
24#include <unistd.h>
25#include <errno.h>
26#include <string.h>
27#include <ctype.h>
28#include <time.h>
29
30#include "libudev.h"
31#include "libudev-private.h"
32#include "missing.h"
33
34/**
35 * SECTION:libudev
36 * @short_description: libudev context
37 *
38 * The context contains the default values read from the udev config file,
39 * and is passed to all library operations.
40 */
41
42/**
43 * udev:
44 *
45 * Opaque object representing the library context.
46 */
47struct udev {
48        int refcount;
49        void (*log_fn)(struct udev *udev,
50                       int priority, const char *file, int line, const char *fn,
51                       const char *format, va_list args);
52        void *userdata;
53};
54
55/**
56 * udev_get_userdata:
57 * @udev: udev library context
58 *
59 * Retrieve stored data pointer from library context. This might be useful
60 * to access from callbacks.
61 *
62 * Returns: stored userdata
63 **/
64_public_ void *udev_get_userdata(struct udev *udev) {
65        if (udev == NULL)
66                return NULL;
67        return udev->userdata;
68}
69
70/**
71 * udev_set_userdata:
72 * @udev: udev library context
73 * @userdata: data pointer
74 *
75 * Store custom @userdata in the library context.
76 **/
77_public_ void udev_set_userdata(struct udev *udev, void *userdata) {
78        if (udev == NULL)
79                return;
80        udev->userdata = userdata;
81}
82
83/**
84 * udev_new:
85 *
86 * Create udev library context. This reads the udev configuration
87 * file, and fills in the default values.
88 *
89 * The initial refcount is 1, and needs to be decremented to
90 * release the resources of the udev library context.
91 *
92 * Returns: a new udev library context
93 **/
94_public_ struct udev *udev_new(void) {
95        struct udev *udev;
96        _cleanup_fclose_ FILE *f = NULL;
97
98        udev = new0(struct udev, 1);
99        if (udev == NULL)
100                return NULL;
101        udev->refcount = 1;
102
103        f = fopen( UDEV_CONF_FILE, "re");
104        if (f != NULL) {
105                char line[UTIL_LINE_SIZE];
106                unsigned line_nr = 0;
107
108                while (fgets(line, sizeof(line), f)) {
109                        size_t len;
110                        char *key;
111                        char *val;
112
113                        line_nr++;
114
115                        /* find key */
116                        key = line;
117                        while (isspace(key[0]))
118                                key++;
119
120                        /* comment or empty line */
121                        if (key[0] == '#' || key[0] == '\0')
122                                continue;
123
124                        /* split key/value */
125                        val = strchr(key, '=');
126                        if (val == NULL) {
127                                log_debug(UDEV_CONF_FILE ":%u: missing assignment,  skipping line.", line_nr);
128                                continue;
129                        }
130                        val[0] = '\0';
131                        val++;
132
133                        /* find value */
134                        while (isspace(val[0]))
135                                val++;
136
137                        /* terminate key */
138                        len = strlen(key);
139                        if (len == 0)
140                                continue;
141                        while (isspace(key[len-1]))
142                                len--;
143                        key[len] = '\0';
144
145                        /* terminate value */
146                        len = strlen(val);
147                        if (len == 0)
148                                continue;
149                        while (isspace(val[len-1]))
150                                len--;
151                        val[len] = '\0';
152
153                        if (len == 0)
154                                continue;
155
156                        /* unquote */
157                        if (val[0] == '"' || val[0] == '\'') {
158                                if (val[len-1] != val[0]) {
159                                        log_debug(UDEV_CONF_FILE ":%u: inconsistent quoting, skipping line.", line_nr);
160                                        continue;
161                                }
162                                val[len-1] = '\0';
163                                val++;
164                        }
165
166                        if (streq(key, "udev_log")) {
167                                int prio;
168
169                                prio = util_log_priority(val);
170                                if (prio < 0)
171                                        log_debug("/etc/udev/udev.conf:%u: invalid log level '%s', ignoring.", line_nr, val);
172                                else
173                                        log_set_max_level(prio);
174                                continue;
175                        }
176                }
177        }
178
179        return udev;
180}
181
182/**
183 * udev_ref:
184 * @udev: udev library context
185 *
186 * Take a reference of the udev library context.
187 *
188 * Returns: the passed udev library context
189 **/
190_public_ struct udev *udev_ref(struct udev *udev) {
191        if (udev == NULL)
192                return NULL;
193        udev->refcount++;
194        return udev;
195}
196
197/**
198 * udev_unref:
199 * @udev: udev library context
200 *
201 * Drop a reference of the udev library context. If the refcount
202 * reaches zero, the resources of the context will be released.
203 *
204 * Returns: the passed udev library context if it has still an active reference, or #NULL otherwise.
205 **/
206_public_ struct udev *udev_unref(struct udev *udev) {
207        if (udev == NULL)
208                return NULL;
209        udev->refcount--;
210        if (udev->refcount > 0)
211                return udev;
212        free(udev);
213        return NULL;
214}
215
216/**
217 * udev_set_log_fn:
218 * @udev: udev library context
219 * @log_fn: function to be called for log messages
220 *
221 * This function is deprecated.
222 *
223 **/
224_public_ void udev_set_log_fn(struct udev *udev,
225                     void (*log_fn)(struct udev *udev,
226                                    int priority, const char *file, int line, const char *fn,
227                                    const char *format, va_list args)) {
228        return;
229}
230
231/**
232 * udev_get_log_priority:
233 * @udev: udev library context
234 *
235 * This function is deprecated.
236 *
237 **/
238_public_ int udev_get_log_priority(struct udev *udev) {
239        return log_get_max_level();
240}
241
242/**
243 * udev_set_log_priority:
244 * @udev: udev library context
245 * @priority: the new log priority
246 *
247 * This function is deprecated.
248 *
249 **/
250_public_ void udev_set_log_priority(struct udev *udev, int priority) {
251        log_set_max_level(priority);
252}
253