chiark / gitweb /
a5f33eb08fa2b3de5e367d52ce8c1b8e73892dd4
[elogind.git] / udev / lib / libudev.c
1 /*
2  * libudev - interface to udev device information
3  *
4  * Copyright (C) 2008 Kay Sievers <kay.sievers@vrfy.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, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "config.h"
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stddef.h>
25 #include <unistd.h>
26 #include <errno.h>
27 #include <string.h>
28 #include <dirent.h>
29 #include <sys/stat.h>
30
31 #include "libudev.h"
32 #include "libudev-private.h"
33 #include "../udev.h"
34
35 struct udev {
36         int refcount;
37         void (*log_fn)(struct udev *udev,
38                        int priority, const char *file, int line, const char *fn,
39                        const char *format, va_list args);
40 };
41
42 void udev_log(struct udev *udev,
43               int priority, const char *file, int line, const char *fn,
44               const char *format, ...)
45 {
46         va_list args;
47
48         va_start(args, format);
49         udev->log_fn(udev, priority, file, line, fn, format, args);
50         va_end(args);
51 }
52
53 static void log_stderr(struct udev *udev,
54                        int priority, const char *file, int line, const char *fn,
55                        const char *format, va_list args)
56 {
57         static int log = -1;
58
59         if (log == -1) {
60                 if (getenv("LIBUDEV_DEBUG") != NULL)
61                         log = 1;
62                 else
63                         log = 0;
64         }
65
66         if (log == 1) {
67                 fprintf(stderr, "libudev: %s: ", fn);
68                 vfprintf(stderr, format, args);
69         }
70 }
71
72 /* glue to udev logging, needed until udev logging code is "fixed" */
73 #ifdef USE_LOG
74 void log_message(int priority, const char *format, ...)
75 {
76         va_list args;
77
78         va_start(args, format);
79         log_stderr(NULL, priority, NULL, 0, "", format, args);
80         va_end(args);
81 }
82 #endif
83
84 /**
85  * udev_new:
86  *
87  * Create udev library context.
88  *
89  * The initial refcount is 1, and needs to be decremented to
90  * release the ressources of the udev library context.
91  *
92  * Returns: a new udev library context
93  **/
94 struct udev *udev_new(void)
95 {
96         struct udev *udev;
97
98         udev = malloc(sizeof(struct udev));
99         if (udev == NULL)
100                 return NULL;
101         memset(udev, 0x00, (sizeof(struct udev)));
102         udev->refcount = 1;
103         udev->log_fn = log_stderr;
104         udev_config_init();
105         sysfs_init();
106         log_info(udev, "context %p created\n", udev);
107         return udev;
108 }
109
110 /**
111  * udev_ref:
112  * @udev: udev library context
113  *
114  * Take a reference of the udev library context.
115  *
116  * Returns: the passed udev library context
117  **/
118 struct udev *udev_ref(struct udev *udev)
119 {
120         if (udev == NULL)
121                 return NULL;
122         udev->refcount++;
123         return udev;
124 }
125
126 /**
127  * udev_unref:
128  * @udev: udev library context
129  *
130  * Drop a reference of the udev library context. If the refcount
131  * reaches zero, the ressources of the context will be released.
132  *
133  **/
134 void udev_unref(struct udev *udev)
135 {
136         if (udev == NULL)
137                 return;
138         udev->refcount--;
139         if (udev->refcount > 0)
140                 return;
141         sysfs_cleanup();
142         log_info(udev, "context %p released\n", udev);
143         free(udev);
144 }
145
146 /**
147  * udev_set_log_fn:
148  * @udev: udev library context
149  * @log_fn: function to be called for logging messages
150  *
151  * The built-in logging, which writes to stderr if the
152  * LIBUDEV_DEBUG environment variable is set, can be
153  * overridden by a custom function, to plug log messages
154  * into the users logging functionality.
155  *
156  **/
157 void udev_set_log_fn(struct udev *udev,
158                      void (*log_fn)(struct udev *udev,
159                                     int priority, const char *file, int line, const char *fn,
160                                     const char *format, va_list args))
161 {
162         udev->log_fn = log_fn;
163         log_info(udev, "custom logging function %p registered\n", udev);
164 }
165
166 /**
167  * udev_get_sys_path:
168  * @udev: udev library context
169  *
170  * Retrieve the sysfs mount point. The default is "/sys". For
171  * testing purposes, it can be overridden with the environment
172  * variable SYSFS_PATH.
173  *
174  * Returns: the sys mount point
175  **/
176 const char *udev_get_sys_path(struct udev *udev)
177 {
178         if (udev == NULL)
179                 return NULL;
180         return sysfs_path;
181 }
182
183 /**
184  * udev_get_dev_path:
185  * @udev: udev library context
186  *
187  * Retrieve the device directory path. The default value is "/dev",
188  * the actual value may be overridden in the udev configuration
189  * file.
190  *
191  * Returns: the device directory path
192  **/
193 const char *udev_get_dev_path(struct udev *udev)
194 {
195         if (udev == NULL)
196                 return NULL;
197         return udev_root;
198 }