chiark / gitweb /
8785f22071f2b5203e5b22578088830dbab6a305
[elogind.git] / src / libudev / libudev.c
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  */
47 struct 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("/etc/udev/udev.conf", "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("/etc/udev/udev.conf:%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("/etc/udev/udev.conf:%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 }