]> git.ipfire.org Git - thirdparty/systemd.git/blame - udev/lib/libudev-device.c
libudev: rename libudev-utils.c libudev-util.c
[thirdparty/systemd.git] / udev / lib / libudev-device.c
CommitLineData
eb1f0e66
KS
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
11d543c1
KS
35struct udev_device {
36 int refcount;
37 struct udev *udev;
38 char *devpath;
39 char *syspath;
40 char *devname;
41 char *subsystem;
42 struct list_head link_list;
43 struct list_head env_list;
c4f5f942
KS
44 char *action;
45 char *driver;
46 char *devpath_old;
47 char *physdevpath;
48 int timeout;
49 dev_t devnum;
6bd1c78a
KS
50 unsigned long long int seqnum;
51 int num_fake_partitions;
e88a82b5 52 int devlink_priority;
6bd1c78a 53 int ignore_remove;
11d543c1
KS
54};
55
e88a82b5
KS
56static size_t devpath_to_db_path(struct udev *udev, const char *devpath, char *filename, size_t len)
57{
58 size_t start;
59
60 /* translate to location of db file */
61 strlcpy(filename, udev_get_dev_path(udev), len);
62 start = strlcat(filename, "/.udev/db/", len);
63 strlcat(filename, devpath, len);
7a01f11a 64 return util_path_encode(&filename[start], len - start);
e88a82b5
KS
65}
66
67static int device_read_db(struct udev_device *udev_device)
68{
69 struct stat stats;
70 char filename[PATH_SIZE];
71 char line[PATH_SIZE];
72 FILE *f;
73 int rc = 0;
74
75 devpath_to_db_path(udev_device->udev, udev_device->devpath, filename, sizeof(filename));
76
77 if (lstat(filename, &stats) != 0) {
78 info(udev_device->udev, "no db file to read %s: %s\n", filename, strerror(errno));
79 return -1;
80 }
81 if ((stats.st_mode & S_IFMT) == S_IFLNK) {
82 char target[NAME_SIZE];
83 int target_len;
84
85 info(udev_device->udev, "found a symlink as db file\n");
86 target_len = readlink(filename, target, sizeof(target));
87 if (target_len > 0)
88 target[target_len] = '\0';
89 else {
90 info(udev_device->udev, "error reading db link %s: %s\n", filename, strerror(errno));
91 return -1;
92 }
93 dbg(udev_device->udev, "db link points to '%s'\n", target);
94 if (asprintf(&udev_device->devname, "%s/%s", udev_get_dev_path(udev_device->udev), target) < 0)
95 return -ENOMEM;
96 return 0;
97 }
98
99 f = fopen(filename, "r");
100 if (f == NULL) {
101 info(udev_device->udev, "error reading db file %s: %s\n", filename, strerror(errno));
102 return -1;
103 }
104 while (fgets(line, sizeof(line), f)) {
105 ssize_t len;
106 const char *val;
107 unsigned int maj, min;
108
109 len = strlen(line);
110 if (len < 4)
111 break;
112 line[len-1] = '\0';
113 val = &line[2];
114
115 switch(line[0]) {
116 case 'N':
117 asprintf(&udev_device->devname, "%s/%s", udev_get_dev_path(udev_device->udev), val);
118 break;
119 case 'M':
120 sscanf(val, "%u:%u", &maj, &min);
121 device_set_devnum(udev_device, makedev(maj, min));
122 break;
123 case 'S':
124 strlcpy(filename, udev_get_dev_path(udev_device->udev), sizeof(filename));
125 strlcat(filename, "/", sizeof(filename));
126 strlcat(filename, val, sizeof(filename));
127 device_add_devlink(udev_device, filename);
128 break;
129 case 'L':
130 device_set_devlink_priority(udev_device, atoi(val));
131 break;
132 case 'T':
133 device_set_timeout(udev_device, atoi(val));
134 break;
135 case 'A':
136 device_set_num_fake_partitions(udev_device, atoi(val));
137 break;
138 case 'R':
139 device_set_ignore_remove(udev_device, atoi(val));
140 break;
141 case 'E':
142 device_add_property(udev_device, val);
143 break;
144 }
145 }
146 fclose(f);
147
148 return rc;
149}
150
ba6929f6 151struct udev_device *device_init(struct udev *udev)
eb1f0e66
KS
152{
153 struct udev_device *udev_device;
154
ba6929f6
KS
155 if (udev == NULL)
156 return NULL;
157
eb1f0e66
KS
158 udev_device = malloc(sizeof(struct udev_device));
159 if (udev_device == NULL)
160 return NULL;
161 memset(udev_device, 0x00, sizeof(struct udev_device));
162 udev_device->refcount = 1;
163 udev_device->udev = udev;
ba6929f6
KS
164 INIT_LIST_HEAD(&udev_device->link_list);
165 INIT_LIST_HEAD(&udev_device->env_list);
7d563a17 166 info(udev_device->udev, "udev_device: %p created\n", udev_device);
eb1f0e66
KS
167 return udev_device;
168}
169
170/**
171 * udev_device_new_from_devpath:
172 * @udev: udev library context
173 * @devpath: sys device path
174 *
175 * Create new udev device, and fill in information from the sysfs
176 * device and the udev database entry. The devpath must not contain
177 * the sysfs mount path, and must contain a leading '/'.
178 *
179 * The initial refcount is 1, and needs to be decremented to
180 * release the ressources of the udev device.
181 *
182 * Returns: a new udev device, or #NULL, if it does not exist
183 **/
184struct udev_device *udev_device_new_from_devpath(struct udev *udev, const char *devpath)
185{
186 char path[PATH_SIZE];
187 struct stat statbuf;
188 struct udev_device *udev_device;
eb1f0e66 189
ba6929f6
KS
190 if (udev == NULL)
191 return NULL;
192 if (devpath == NULL)
193 return NULL;
194
eb1f0e66
KS
195 strlcpy(path, udev_get_sys_path(udev), sizeof(path));
196 strlcat(path, devpath, sizeof(path));
197 if (stat(path, &statbuf) != 0)
198 return NULL;
199 if (!S_ISDIR(statbuf.st_mode))
200 return NULL;
201
202 udev_device = device_init(udev);
203 if (udev_device == NULL)
204 return NULL;
205
ba6929f6 206 /* resolve possible symlink to real path */
eb1f0e66 207 strlcpy(path, devpath, sizeof(path));
b21b95d7 208 util_resolve_sys_link(udev, path, sizeof(path));
e88a82b5 209 device_set_devpath(udev_device, path);
7d563a17 210 info(udev, "device %p has devpath '%s'\n", udev_device, udev_device_get_devpath(udev_device));
eb1f0e66 211
e88a82b5 212 if (device_read_db(udev_device) >= 0)
7d563a17 213 info(udev, "device %p filled with udev database data\n", udev_device);
ba6929f6 214
eb1f0e66
KS
215 return udev_device;
216}
217
218/**
219 * udev_device_get_udev:
7d8787b3 220 * @udev_device: udev device
eb1f0e66
KS
221 *
222 * Retrieve the udev library context the device was created with.
223 *
224 * Returns: the udev library context
225 **/
226struct udev *udev_device_get_udev(struct udev_device *udev_device)
227{
ba6929f6
KS
228 if (udev_device == NULL)
229 return NULL;
eb1f0e66
KS
230 return udev_device->udev;
231}
232
233/**
234 * udev_device_ref:
235 * @udev_device: udev device
236 *
237 * Take a reference of a udev device.
238 *
239 * Returns: the passed udev device
240 **/
241struct udev_device *udev_device_ref(struct udev_device *udev_device)
242{
ba6929f6
KS
243 if (udev_device == NULL)
244 return NULL;
eb1f0e66
KS
245 udev_device->refcount++;
246 return udev_device;
247}
248
249/**
250 * udev_device_unref:
251 * @udev_device: udev device
252 *
253 * Drop a reference of a udev device. If the refcount reaches zero,
254 * the ressources of the device will be released.
255 *
256 **/
257void udev_device_unref(struct udev_device *udev_device)
258{
ba6929f6
KS
259 if (udev_device == NULL)
260 return;
eb1f0e66
KS
261 udev_device->refcount--;
262 if (udev_device->refcount > 0)
263 return;
11d543c1 264 free(udev_device->syspath);
ba6929f6
KS
265 free(udev_device->devname);
266 free(udev_device->subsystem);
7a01f11a
KS
267 util_name_list_cleanup(udev_device->udev, &udev_device->link_list);
268 util_name_list_cleanup(udev_device->udev, &udev_device->env_list);
1c7047ea
KS
269 free(udev_device->action);
270 free(udev_device->driver);
271 free(udev_device->devpath_old);
272 free(udev_device->physdevpath);
7d563a17 273 info(udev_device->udev, "udev_device: %p released\n", udev_device);
eb1f0e66
KS
274 free(udev_device);
275}
276
277/**
278 * udev_device_get_devpath:
279 * @udev_device: udev device
280 *
11d543c1
KS
281 * Retrieve the kernel devpath value of the udev device. The path
282 * does not contain the sys mount point, and starts with a '/'.
eb1f0e66 283 *
11d543c1 284 * Returns: the devpath of the udev device
eb1f0e66
KS
285 **/
286const char *udev_device_get_devpath(struct udev_device *udev_device)
287{
ba6929f6
KS
288 if (udev_device == NULL)
289 return NULL;
290 return udev_device->devpath;
eb1f0e66
KS
291}
292
11d543c1
KS
293/**
294 * udev_device_get_syspath:
295 * @udev_device: udev device
296 *
297 * Retrieve the sys path of the udev device. The path is an
298 * absolute path and starts with the sys mount point.
299 *
300 * Returns: the sys path of the udev device
301 **/
302const char *udev_device_get_syspath(struct udev_device *udev_device)
303{
304 if (udev_device == NULL)
305 return NULL;
306 return udev_device->syspath;
307}
308
eb1f0e66
KS
309/**
310 * udev_device_get_devname:
311 * @udev_device: udev device
312 *
313 * Retrieve the device node file name belonging to the udev device.
ba6929f6 314 * The path is an absolute path, and starts with the device directory.
eb1f0e66
KS
315 *
316 * Returns: the device node file name of the udev device, or #NULL if no device node exists
317 **/
318const char *udev_device_get_devname(struct udev_device *udev_device)
319{
ba6929f6 320 if (udev_device == NULL)
eb1f0e66 321 return NULL;
ba6929f6 322 return udev_device->devname;
eb1f0e66
KS
323}
324
325/**
326 * udev_device_get_subsystem:
327 * @udev_device: udev device
328 *
329 * Retrieve the subsystem string of the udev device. The string does not
330 * contain any "/".
331 *
332 * Returns: the subsystem name of the udev device, or #NULL if it can not be determined
333 **/
334const char *udev_device_get_subsystem(struct udev_device *udev_device)
335{
ba6929f6
KS
336 char subsystem[NAME_SIZE];
337
338 if (udev_device == NULL)
339 return NULL;
340 if (udev_device->subsystem != NULL)
341 return udev_device->subsystem;
342 if (util_get_sys_subsystem(udev_device->udev, udev_device->devpath, subsystem, sizeof(subsystem)) < 2)
eb1f0e66 343 return NULL;
ba6929f6
KS
344 udev_device->subsystem = strdup(subsystem);
345 return udev_device->subsystem;
eb1f0e66
KS
346}
347
348/**
349 * udev_device_get_devlinks:
350 * @udev_device: udev device
351 * @cb: function to be called for every device link found
352 * @data: data to be passed to the function
353 *
354 * Retrieve the device links pointing to the device file of the
355 * udev device. For every device link, the passed function will be
ba6929f6
KS
356 * called with the device link string.
357 * The path is an absolute path, and starts with the device directory.
358 * If the function returns 1, remaning device links will be ignored.
eb1f0e66
KS
359 *
360 * Returns: the number of device links passed to the caller, or a negative value on error
361 **/
362int udev_device_get_devlinks(struct udev_device *udev_device,
363 int (*cb)(struct udev_device *udev_device, const char *value, void *data),
364 void *data)
365{
366 struct name_entry *name_loop;
367 int count = 0;
368
ba6929f6
KS
369 if (udev_device == NULL)
370 return -1;
371 list_for_each_entry(name_loop, &udev_device->link_list, node) {
eb1f0e66
KS
372 count++;
373 if (cb(udev_device, name_loop->name, data) != 0)
374 break;
375 }
376 return count;
377}
378
379/**
380 * udev_device_get_properties:
381 * @udev_device: udev device
382 * @cb: function to be called for every property found
383 * @data: data to be passed to the function
384 *
385 * Retrieve the property key/value pairs belonging to the
386 * udev device. For every key/value pair, the passed function will be
387 * called. If the function returns 1, remaning properties will be
388 * ignored.
389 *
390 * Returns: the number of properties passed to the caller, or a negative value on error
391 **/
392int udev_device_get_properties(struct udev_device *udev_device,
393 int (*cb)(struct udev_device *udev_device, const char *key, const char *value, void *data),
394 void *data)
395{
396 struct name_entry *name_loop;
397 int count = 0;
398
ba6929f6
KS
399 if (udev_device == NULL)
400 return -1;
401 list_for_each_entry(name_loop, &udev_device->env_list, node) {
eb1f0e66
KS
402 char name[PATH_SIZE];
403 char *val;
404
405 strncpy(name, name_loop->name, PATH_SIZE);
406 name[PATH_SIZE-1] = '\0';
407 val = strchr(name, '=');
408 if (val == NULL)
409 continue;
410 val[0] = '\0';
411 val = &val[1];
ba6929f6 412 count++;
eb1f0e66
KS
413 if (cb(udev_device, name, val, data) != 0)
414 break;
415 }
416 return count;
417}
11d543c1 418
c4f5f942
KS
419const char *udev_device_get_driver(struct udev_device *udev_device)
420{
95d90c4f
KS
421 char driver[NAME_SIZE];
422
c4f5f942
KS
423 if (udev_device == NULL)
424 return NULL;
95d90c4f
KS
425 if (udev_device->driver != NULL)
426 return udev_device->driver;
427 if (util_get_sys_driver(udev_device->udev, udev_device->devpath, driver, sizeof(driver)) < 2)
428 return NULL;
429 udev_device->driver = strdup(driver);
c4f5f942
KS
430 return udev_device->driver;
431}
432
433dev_t udev_device_get_devnum(struct udev_device *udev_device)
434{
435 if (udev_device == NULL)
436 return makedev(0, 0);
437 return udev_device->devnum;
438}
439
440const char *udev_device_get_action(struct udev_device *udev_device)
441{
442 if (udev_device == NULL)
443 return NULL;
444 return udev_device->action;
445}
446
37372bbc
KS
447unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device)
448{
449 if (udev_device == NULL)
450 return 0;
451 return udev_device->seqnum;
452}
453
11d543c1
KS
454int device_set_devpath(struct udev_device *udev_device, const char *devpath)
455{
456 if (asprintf(&udev_device->syspath, "%s%s", udev_get_sys_path(udev_device->udev), devpath) < 0)
457 return -ENOMEM;
458 udev_device->devpath = &udev_device->syspath[strlen(udev_get_sys_path(udev_device->udev))];
459 return 0;
460}
461
462int device_set_subsystem(struct udev_device *udev_device, const char *subsystem)
463{
464 udev_device->subsystem = strdup(subsystem);
465 if (udev_device->subsystem == NULL)
466 return -1;
467 return 0;
468}
469
470int device_set_devname(struct udev_device *udev_device, const char *devname)
471{
472 udev_device->devname = strdup(devname);
473 if (udev_device->devname == NULL)
474 return -ENOMEM;
475 return 0;
476}
477
478int device_add_devlink(struct udev_device *udev_device, const char *devlink)
479{
7a01f11a 480 if (util_name_list_add(udev_device->udev, &udev_device->link_list, devlink, 0) == NULL)
11d543c1
KS
481 return -ENOMEM;
482 return 0;
483}
484
485int device_add_property(struct udev_device *udev_device, const char *property)
486{
7a01f11a 487 if (util_name_list_add(udev_device->udev, &udev_device->env_list, property, 0) == NULL)
11d543c1
KS
488 return -ENOMEM;
489 return 0;
490}
c4f5f942
KS
491
492int device_set_action(struct udev_device *udev_device, const char *action)
493{
494 udev_device->action = strdup(action);
495 if (udev_device->action == NULL)
496 return -ENOMEM;
497 return 0;
498}
499
500int device_set_driver(struct udev_device *udev_device, const char *driver)
501{
502 udev_device->driver = strdup(driver);
503 if (udev_device->driver == NULL)
504 return -ENOMEM;
505 return 0;
506}
507
508const char *device_get_devpath_old(struct udev_device *udev_device)
509{
510 if (udev_device == NULL)
511 return NULL;
512 return udev_device->devpath_old;
513}
514
515int device_set_devpath_old(struct udev_device *udev_device, const char *devpath_old)
516{
517 udev_device->devpath_old = strdup(devpath_old);
518 if (udev_device->devpath_old == NULL)
519 return -ENOMEM;
520 return 0;
521}
522
523const char *device_get_physdevpath(struct udev_device *udev_device)
524{
525 if (udev_device == NULL)
526 return NULL;
527 return udev_device->physdevpath;
528}
529
530int device_set_physdevpath(struct udev_device *udev_device, const char *physdevpath)
531{
532 udev_device->physdevpath = strdup(physdevpath);
533 if (udev_device->physdevpath == NULL)
534 return -ENOMEM;
535 return 0;
536}
537
538int device_get_timeout(struct udev_device *udev_device)
539{
540 if (udev_device == NULL)
541 return -1;
542 return udev_device->timeout;
543}
544
545int device_set_timeout(struct udev_device *udev_device, int timeout)
546{
547 udev_device->timeout = timeout;
548 return 0;
549}
550
37372bbc
KS
551int device_set_seqnum(struct udev_device *udev_device, unsigned long long int seqnum)
552{
553 udev_device->seqnum = seqnum;
554 return 0;
555}
556
c4f5f942
KS
557int device_set_devnum(struct udev_device *udev_device, dev_t devnum)
558{
559 udev_device->devnum = devnum;
560 return 0;
561}
6bd1c78a
KS
562
563int device_get_num_fake_partitions(struct udev_device *udev_device)
564{
565 if (udev_device == NULL)
566 return -1;
567 return udev_device->num_fake_partitions;
568}
569
570int device_set_num_fake_partitions(struct udev_device *udev_device, int num)
571{
572 udev_device->num_fake_partitions = num;
e88a82b5 573 return 0;
6bd1c78a
KS
574}
575
e88a82b5 576int device_get_devlink_priority(struct udev_device *udev_device)
6bd1c78a
KS
577{
578 if (udev_device == NULL)
579 return -1;
e88a82b5 580 return udev_device->devlink_priority;
6bd1c78a
KS
581}
582
e88a82b5 583int device_set_devlink_priority(struct udev_device *udev_device, int prio)
6bd1c78a 584{
e88a82b5
KS
585 udev_device->devlink_priority = prio;
586 return 0;
6bd1c78a
KS
587}
588
589int device_get_ignore_remove(struct udev_device *udev_device)
590{
591 if (udev_device == NULL)
592 return -1;
593 return udev_device->ignore_remove;
594}
595
596int device_set_ignore_remove(struct udev_device *udev_device, int ignore)
597{
e88a82b5
KS
598 udev_device->ignore_remove = ignore;
599 return 0;
6bd1c78a 600}
e88a82b5 601