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