libudev.c revision ba6929f6690a72485ac3c6b7610ffbd5ab319be7
ee9c9500ab13c1093fc3feaf2aa5a0d330d0bfadKay Sievers/*
c343be283b7152554bac0c02493a4e1759c163f7Kay Sievers * libudev - interface to udev device information
c343be283b7152554bac0c02493a4e1759c163f7Kay Sievers *
c343be283b7152554bac0c02493a4e1759c163f7Kay Sievers * Copyright (C) 2008 Kay Sievers <kay.sievers@vrfy.org>
b3ae710c251d0ce5cf2cef63208e325497b5e323Zbigniew Jędrzejewski-Szmek *
b3ae710c251d0ce5cf2cef63208e325497b5e323Zbigniew Jędrzejewski-Szmek * This program is free software: you can redistribute it and/or modify
19aadacf92ad86967ffb678e37b2ff9e83cb9480Jan Engelhardt * it under the terms of the GNU General Public License as published by
cff452c7e974db5053cdbd0d7bbbab2e3b4c91b9Kay Sievers * the Free Software Foundation, either version 2 of the License, or
cff452c7e974db5053cdbd0d7bbbab2e3b4c91b9Kay Sievers * (at your option) any later version.
cff452c7e974db5053cdbd0d7bbbab2e3b4c91b9Kay Sievers *
cff452c7e974db5053cdbd0d7bbbab2e3b4c91b9Kay Sievers * This program is distributed in the hope that it will be useful,
f957632b960a0a42999b38ded7089fa602b41745Kay Sievers * but WITHOUT ANY WARRANTY; without even the implied warranty of
f957632b960a0a42999b38ded7089fa602b41745Kay Sievers * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f957632b960a0a42999b38ded7089fa602b41745Kay Sievers * GNU General Public License for more details.
f957632b960a0a42999b38ded7089fa602b41745Kay Sievers *
a40593a0d0d740efa387e35411e1e456a6c5aba7Lennart Poettering * You should have received a copy of the GNU General Public License
20ffc4c4a9226b0e45cc02ad9c0108981626c0bbKay Sievers * along with this program. If not, see <http://www.gnu.org/licenses/>.
04ac799283f517672a5424e7c5bf066cfa4ca020Zbigniew Jędrzejewski-Szmek */
04ac799283f517672a5424e7c5bf066cfa4ca020Zbigniew Jędrzejewski-Szmek
04ac799283f517672a5424e7c5bf066cfa4ca020Zbigniew Jędrzejewski-Szmek#include "config.h"
04ac799283f517672a5424e7c5bf066cfa4ca020Zbigniew Jędrzejewski-Szmek
374c356979ba7222fa7e09005824fe6996b0e91eDavid Herrmann#include <stdio.h>
374c356979ba7222fa7e09005824fe6996b0e91eDavid Herrmann#include <stdlib.h>
374c356979ba7222fa7e09005824fe6996b0e91eDavid Herrmann#include <stddef.h>
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering#include <unistd.h>
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering#include <errno.h>
466784c8710e5cb0e0b86a16506d992d7ec5b619Kay Sievers#include <string.h>
55d32caf94d8df547ca763be52b0c35bb6388606Lennart Poettering#include <dirent.h>
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering#include <sys/stat.h>
bafb15bab99887d1b6b8a35136531bac6c3876a6Lennart Poettering
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering#include "libudev.h"
bafb15bab99887d1b6b8a35136531bac6c3876a6Lennart Poettering#include "libudev-private.h"
eb124a97fb72d076014253b1acde69d428f15ecfLennart Poettering#include "../udev.h"
154ff088d371bee5651eaa2bc9bde8a34c185656Lennart Poettering
3de03738fc970496d2d3da668c72767a48ccc41bLennart Poetteringstruct udev {
3de03738fc970496d2d3da668c72767a48ccc41bLennart Poettering int refcount;
3de03738fc970496d2d3da668c72767a48ccc41bLennart Poettering void (*log_fn)(struct udev *udev,
3de03738fc970496d2d3da668c72767a48ccc41bLennart Poettering int priority, const char *file, int line, const char *fn,
eaa3b74dfd6395c8abaa8416d90dac5e0dc00e15Lennart Poettering const char *format, va_list args);
eaa3b74dfd6395c8abaa8416d90dac5e0dc00e15Lennart Poettering};
5c868fe2e980216b32588e16fa949ebb1f1f7b95Lennart Poettering
5c868fe2e980216b32588e16fa949ebb1f1f7b95Lennart Poetteringvoid udev_log(struct udev *udev,
8891f695c71bd4c266d827c9aaedbbbbaf79d3ebLennart Poettering int priority, const char *file, int line, const char *fn,
8891f695c71bd4c266d827c9aaedbbbbaf79d3ebLennart Poettering const char *format, ...)
8891f695c71bd4c266d827c9aaedbbbbaf79d3ebLennart Poettering{
2b1c3767515672dfd0f5e0a9c9d7ac3a16a6a361Lennart Poettering va_list args;
2b1c3767515672dfd0f5e0a9c9d7ac3a16a6a361Lennart Poettering
1df52dd282cd6014ace8ca2279dd90d9ea52d2a4Lennart Poettering va_start(args, format);
8dfb5bced205a12d5380c95de035100ad6c09454Lennart Poettering udev->log_fn(udev, priority, file, line, fn, format, args);
1df52dd282cd6014ace8ca2279dd90d9ea52d2a4Lennart Poettering va_end(args);
37efac5ddb21fd91ed420c070ed07f375e78b3b9Lennart Poettering}
37efac5ddb21fd91ed420c070ed07f375e78b3b9Lennart Poettering
7348b3adb324614132cf376f478e883bd7de28f1Lennart Poetteringstatic void log_stderr(struct udev *udev,
7348b3adb324614132cf376f478e883bd7de28f1Lennart Poettering int priority, const char *file, int line, const char *fn,
7348b3adb324614132cf376f478e883bd7de28f1Lennart Poettering const char *format, va_list args)
7348b3adb324614132cf376f478e883bd7de28f1Lennart Poettering{
f55b9bdfae46e3683c74c30f1d063642a41368a5Lennart Poettering static int log = -1;
f55b9bdfae46e3683c74c30f1d063642a41368a5Lennart Poettering
f55b9bdfae46e3683c74c30f1d063642a41368a5Lennart Poettering if (log == -1) {
f55b9bdfae46e3683c74c30f1d063642a41368a5Lennart Poettering if (getenv("LIBUDEV_DEBUG") != NULL)
e107ed185ef08945102834234a05ec51bb438685Lennart Poettering log = 1;
e107ed185ef08945102834234a05ec51bb438685Lennart Poettering else
e107ed185ef08945102834234a05ec51bb438685Lennart Poettering log = 0;
e107ed185ef08945102834234a05ec51bb438685Lennart Poettering }
eaa3b74dfd6395c8abaa8416d90dac5e0dc00e15Lennart Poettering
e107ed185ef08945102834234a05ec51bb438685Lennart Poettering if (log == 1) {
e107ed185ef08945102834234a05ec51bb438685Lennart Poettering fprintf(stderr, "libudev: %s: ", fn);
e107ed185ef08945102834234a05ec51bb438685Lennart Poettering vfprintf(stderr, format, args);
e30fa16e27cbd48f960113a1d72d9a15c3b2d67bLennart Poettering }
e30fa16e27cbd48f960113a1d72d9a15c3b2d67bLennart Poettering}
f598ac3e28b729dd0b1d0a881df3e16465687a2bLennart Poettering
11fb37f16ed99c1603c9d770b60ce4953b96a58dLennart Poettering/* glue to udev logging, needed until udev logging code is "fixed" */
01083ad094664e5c685060f4fb35a05ea2f212edLennart Poettering#ifdef USE_LOG
01083ad094664e5c685060f4fb35a05ea2f212edLennart Poetteringvoid log_message(int priority, const char *format, ...)
a2b135e3d8d5dfa103a87e304ed8a91b01fdbb02Lennart Poettering{
a2b135e3d8d5dfa103a87e304ed8a91b01fdbb02Lennart Poettering va_list args;
a2b135e3d8d5dfa103a87e304ed8a91b01fdbb02Lennart Poettering
a2b135e3d8d5dfa103a87e304ed8a91b01fdbb02Lennart Poettering va_start(args, format);
b107b705cc97d3033e37c44229deb37b5aa31df5Lennart Poettering log_stderr(NULL, priority, NULL, 0, "", format, args);
b107b705cc97d3033e37c44229deb37b5aa31df5Lennart Poettering va_end(args);
edb2935c5c5b95c42b8679086f60da5eafad74cbLennart Poettering}
edb2935c5c5b95c42b8679086f60da5eafad74cbLennart Poettering#endif
769918ecd30c0f7ee6e87b9aa6226d956bd2f530Lennart Poettering
769918ecd30c0f7ee6e87b9aa6226d956bd2f530Lennart Poettering/**
769918ecd30c0f7ee6e87b9aa6226d956bd2f530Lennart Poettering * udev_new:
769918ecd30c0f7ee6e87b9aa6226d956bd2f530Lennart Poettering *
6a3f892a23db71544d0439355f96c44350dafa8fLennart Poettering * Create udev library context.
2a781fc9bd33982c81e5ff75974a442a33d4f167Lennart Poettering *
2a781fc9bd33982c81e5ff75974a442a33d4f167Lennart Poettering * The initial refcount is 1, and needs to be decremented to
6a3f892a23db71544d0439355f96c44350dafa8fLennart Poettering * release the ressources of the udev library context.
6a3f892a23db71544d0439355f96c44350dafa8fLennart Poettering *
efc141b8ffbfa1e449da40ce27fccaa81428f779Lennart Poettering * Returns: a new udev library context
efc141b8ffbfa1e449da40ce27fccaa81428f779Lennart Poettering **/
d28315e4aff91560ed4c2fc9f876ec8bfc559f2dJan Engelhardtstruct udev *udev_new(void)
efc141b8ffbfa1e449da40ce27fccaa81428f779Lennart Poettering{
efc141b8ffbfa1e449da40ce27fccaa81428f779Lennart Poettering struct udev *udev;
726a6e963056a7238a512cfe6ce612af2c2d1419Lennart Poettering
7ba4fedb8048182fb765bd6ae5aa1e548389bef3Lennart Poettering udev = malloc(sizeof(struct udev));
23fae27185ddde98706faac0f45d77b11ecd66e6Lennart Poettering if (udev == NULL)
23fae27185ddde98706faac0f45d77b11ecd66e6Lennart Poettering return NULL;
650264033f2f98f6319513958d94d59078654af8Lennart Poettering memset(udev, 0x00, (sizeof(struct udev)));
650264033f2f98f6319513958d94d59078654af8Lennart Poettering udev->refcount = 1;
650264033f2f98f6319513958d94d59078654af8Lennart Poettering udev->log_fn = log_stderr;
f8901862b2b030921b3d5aba4157044ceab16451Lennart Poettering udev_config_init();
eda8f06755bd98c4639293c26b856c225f0d1fe1Lennart Poettering sysfs_init();
eda8f06755bd98c4639293c26b856c225f0d1fe1Lennart Poettering log_info(udev, "context %p created\n", udev);
d4fdc205a4610965cee46408dbd046c922e7620cLennart Poettering return udev;
d4fdc205a4610965cee46408dbd046c922e7620cLennart Poettering}
d4fdc205a4610965cee46408dbd046c922e7620cLennart Poettering
af1082b04a3d45a9b1d796b4271f44e87e307026Lennart Poettering/**
af1082b04a3d45a9b1d796b4271f44e87e307026Lennart Poettering * udev_ref:
af1082b04a3d45a9b1d796b4271f44e87e307026Lennart Poettering * @udev: udev library context
af1082b04a3d45a9b1d796b4271f44e87e307026Lennart Poettering *
488ad3b32a7e2b5b1380abf4a15e5f65fa65f3feLennart Poettering * Take a reference of the udev library context.
488ad3b32a7e2b5b1380abf4a15e5f65fa65f3feLennart Poettering *
488ad3b32a7e2b5b1380abf4a15e5f65fa65f3feLennart Poettering * Returns: the passed udev library context
488ad3b32a7e2b5b1380abf4a15e5f65fa65f3feLennart Poettering **/
488ad3b32a7e2b5b1380abf4a15e5f65fa65f3feLennart Poetteringstruct udev *udev_ref(struct udev *udev)
488ad3b32a7e2b5b1380abf4a15e5f65fa65f3feLennart Poettering{
47c94a96df29080f8b3a97e7362df4e9c6ba3265Lennart Poettering if (udev == NULL)
47c94a96df29080f8b3a97e7362df4e9c6ba3265Lennart Poettering return NULL;
09ecd746c9d6581664873674c2188f8c93ed7780Lennart Poettering udev->refcount++;
09ecd746c9d6581664873674c2188f8c93ed7780Lennart Poettering return udev;
09ecd746c9d6581664873674c2188f8c93ed7780Lennart Poettering}
09ecd746c9d6581664873674c2188f8c93ed7780Lennart Poettering
09ecd746c9d6581664873674c2188f8c93ed7780Lennart Poettering/**
09ecd746c9d6581664873674c2188f8c93ed7780Lennart Poettering * udev_unref:
09ecd746c9d6581664873674c2188f8c93ed7780Lennart Poettering * @udev: udev library context
ef417cfd2211ae017a38b9796c6db29130133e63Zbigniew Jędrzejewski-Szmek *
ef417cfd2211ae017a38b9796c6db29130133e63Zbigniew Jędrzejewski-Szmek * Drop a reference of the udev library context. If the refcount
3333d748facc15f49935b6b793490ba0824976e6Zbigniew Jędrzejewski-Szmek * reaches zero, the ressources of the context will be released.
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering *
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering **/
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poetteringvoid udev_unref(struct udev *udev)
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering{
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering if (udev == NULL)
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering return;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering udev->refcount--;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering if (udev->refcount > 0)
0bee65f0622c4faa8ac8ae771cc0c8a936dfa284Lennart Poettering return;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering sysfs_cleanup();
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering log_info(udev, "context %p released\n", udev);
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering free(udev);
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering}
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
47c94a96df29080f8b3a97e7362df4e9c6ba3265Lennart Poettering/**
47c94a96df29080f8b3a97e7362df4e9c6ba3265Lennart Poettering * udev_set_log_fn:
718db96199eb307751264e4163555662c9a389faLennart Poettering * @udev: udev library context
718db96199eb307751264e4163555662c9a389faLennart Poettering * @log_fn: function to be called for logging messages
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering *
718db96199eb307751264e4163555662c9a389faLennart Poettering * The built-in logging, which writes to stderr if the
718db96199eb307751264e4163555662c9a389faLennart Poettering * LIBUDEV_DEBUG environment variable is set, can be
718db96199eb307751264e4163555662c9a389faLennart Poettering * overridden by a custom function, to plug log messages
966204e010ed432a1d7a0481d41a326d8ec7b0c8Lennart Poettering * into the users logging functionality.
966204e010ed432a1d7a0481d41a326d8ec7b0c8Lennart Poettering *
94676f3e9352cbf1f72e0a512ee0d2ed83ff676dLennart Poettering **/
6fd4d0209827e5c3e52fa8c7144852f550f8f95cLennart Poetteringvoid udev_set_log_fn(struct udev *udev,
ced4d06784dbb19666688947901961f949f2aa6dLennart Poettering void (*log_fn)(struct udev *udev,
ced4d06784dbb19666688947901961f949f2aa6dLennart Poettering int priority, const char *file, int line, const char *fn,
af1082b04a3d45a9b1d796b4271f44e87e307026Lennart Poettering const char *format, va_list args))
416446221d905b6815175dc4d525d27f8ae43d1bLennart Poettering{
416446221d905b6815175dc4d525d27f8ae43d1bLennart Poettering udev->log_fn = log_fn;
416446221d905b6815175dc4d525d27f8ae43d1bLennart Poettering log_info(udev, "custom logging function %p registered\n", udev);
7f79cd7109a60810140a045cc725291fc5515264Lennart Poettering}
0aafd43d235982510d1c40564079f7bcec0c7c19Lennart Poettering
19aadacf92ad86967ffb678e37b2ff9e83cb9480Jan Engelhardt/**
19aadacf92ad86967ffb678e37b2ff9e83cb9480Jan Engelhardt * udev_get_sys_path:
df5f6971e6e15b4632884916c71daa076c8bae96Lennart Poettering * @udev: udev library context
df5f6971e6e15b4632884916c71daa076c8bae96Lennart Poettering *
fcba531ed4c6e6f8f21d8ca4e3a56e3162b1c578Lennart Poettering * Retrieve the sysfs mount point. The default is "/sys". For
fcba531ed4c6e6f8f21d8ca4e3a56e3162b1c578Lennart Poettering * testing purposes, it can be overridden with the environment
8b8f259170e35b93e6c6d1757cb8b835bbdaa40cZbigniew Jędrzejewski-Szmek * variable SYSFS_PATH.
8b8f259170e35b93e6c6d1757cb8b835bbdaa40cZbigniew Jędrzejewski-Szmek *
e10e429f2dcbb586215e65f62847f40c7d8b5956David Herrmann * Returns: the sys mount point
e1b7e7ec9b34ae6ae54a4c8084395cbf2bfe9960Lennart Poettering **/
6aaa8c2f783cd1b3ac27c5ce40625d032e7e3d71Zbigniew Jędrzejewski-Szmekconst char *udev_get_sys_path(struct udev *udev)
c3bb87dbab8b79bb9253407cb5b7f3e6fe8db395Lennart Poettering{
d28315e4aff91560ed4c2fc9f876ec8bfc559f2dJan Engelhardt if (udev == NULL)
18d4e7c26e7806ac363d19989df7144d5058ce41Lennart Poettering return NULL;
bdeeb6b543a2a2d0a494f17b85f1498859cdfc2fLennart Poettering return sysfs_path;
bdeeb6b543a2a2d0a494f17b85f1498859cdfc2fLennart Poettering}
bdeeb6b543a2a2d0a494f17b85f1498859cdfc2fLennart Poettering
bdeeb6b543a2a2d0a494f17b85f1498859cdfc2fLennart Poettering/**
4e09014daf8f98584b3f15e64e93bed232e70a6bLennart Poettering * udev_get_dev_path:
4e09014daf8f98584b3f15e64e93bed232e70a6bLennart Poettering * @udev: udev library context
4e09014daf8f98584b3f15e64e93bed232e70a6bLennart Poettering *
6bb648a16ae4a682ad4784412af706d2e6a3e4daTom Gundersen * Retrieve the device directory path. The default value is "/dev",
e30fa16e27cbd48f960113a1d72d9a15c3b2d67bLennart Poettering * the actual value may be overridden in the udev configuration
d28315e4aff91560ed4c2fc9f876ec8bfc559f2dJan Engelhardt * file.
7973ca1927e1f3bac9438f3529458c9ff868905dLennart Poettering *
7973ca1927e1f3bac9438f3529458c9ff868905dLennart Poettering * Returns: the device directory path
7973ca1927e1f3bac9438f3529458c9ff868905dLennart Poettering **/
7973ca1927e1f3bac9438f3529458c9ff868905dLennart Poetteringconst char *udev_get_dev_path(struct udev *udev)
7973ca1927e1f3bac9438f3529458c9ff868905dLennart Poettering{
7973ca1927e1f3bac9438f3529458c9ff868905dLennart Poettering if (udev == NULL)
7973ca1927e1f3bac9438f3529458c9ff868905dLennart Poettering return NULL;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering return udev_root;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering}
80caea6cc72ebd311a311b1527cc6b87201c13bfLennart Poettering