This commit is contained in:
illiliti
2020-07-04 09:25:16 +03:00
commit 7a09bb0557
13 changed files with 1301 additions and 0 deletions

15
LICENSE Normal file
View File

@@ -0,0 +1,15 @@
ISC License
Copyright (c) 2020 illiliti <illiliti@protonmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

49
Makefile Normal file
View File

@@ -0,0 +1,49 @@
# .POSIX ??
PREFIX = /usr/local
XCFLAGS = ${CFLAGS} -pedantic -fPIC -fvisibility=hidden \
-D_POSIX_VERSION=200809L -D_XOPEN_SOURCE=700 -std=c99 \
-Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
-Wno-return-type -Wno-unused-parameter
XLDFLAGS = ${LDFLAGS} -shared -Wl,-soname,libudev.so.1
XARFLAGS = -rc
OBJ = \
udev.o \
udev_list.o \
udev_util.o \
udev_device.o \
udev_monitor.o \
udev_enumerate.o
all: libudev.so libudev.a
.c.o:
${CC} ${XCFLAGS} -c -o $@ $<
libudev.a: ${OBJ}
${AR} ${XARFLAGS} $@ ${OBJ}
libudev.so: ${OBJ}
${CC} ${XCFLAGS} -o $@ ${OBJ} ${XLDFLAGS}
install: libudev.so libudev.a
mkdir -p ${DESTDIR}${INCLUDEDIR} ${DESTDIR}${LIBDIR}
cp -f udev.h ${DESTDIR}${INCLUDEDIR}/libudev.h
chmod 0644 ${DESTDIR}${INCLUDEDIR}/libudev.h
cp -f libudev.a ${DESTDIR}${LIBDIR}/libudev.a
chmod 0644 ${DESTDIR}${LIBDIR}/libudev.a
cp -f libudev.so ${DESTDIR}${LIBDIR}/libudev.so
chmod 0755 ${DESTDIR}${LIBDIR}/libudev.so
ln -s libudev.so ${DESTDIR}${LIBDIR}/libudev.so.1
uninstall:
rm -f ${DESTDIR}${LIBDIR}/libudev.a \
${DESTDIR}${LIBDIR}/libudev.so \
${DESTDIR}${LIBDIR}/libudev.so.1 \
${DESTDIR}${INCLUDEDIR}/libudev.h
clean:
rm -f libudev.so libudev.a ${OBJ}
.PHONY: all clean install uninstall

1
README.md Normal file
View File

@@ -0,0 +1 @@
Nothing works here(yet), move along

40
udev.c Normal file
View File

@@ -0,0 +1,40 @@
#include <stdlib.h>
#include "udev.h"
struct udev
{
int refcount;
};
UDEV_EXPORT struct udev *udev_new(void)
{
struct udev *udev;
udev = calloc(1, sizeof(struct udev));
return udev;
}
UDEV_EXPORT struct udev *udev_ref(struct udev *udev)
{
if (!udev) {
return NULL;
}
udev->refcount++;
return udev;
}
UDEV_EXPORT struct udev *udev_unref(struct udev *udev)
{
if (!udev) {
return NULL;
}
if (--udev->refcount > 0) {
return udev;
}
free(udev);
return NULL;
}

98
udev.h Normal file
View File

@@ -0,0 +1,98 @@
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
#define UDEV_EXPORT __attribute__ ((visibility("default")))
#define udev_list_entry_foreach(list_entry, first_entry) \
for (list_entry = first_entry; \
list_entry != NULL; \
list_entry = udev_list_entry_get_next(list_entry))
struct udev;
struct udev_device;
struct udev_monitor;
struct udev_enumerate;
struct udev_list_entry;
struct udev *udev_new(void);
struct udev *udev_ref(struct udev *udev);
struct udev *udev_unref(struct udev *udev);
const char *udev_device_get_syspath(struct udev_device *udev_device);
const char *udev_device_get_sysname(struct udev_device *udev_device);
const char *udev_device_get_sysnum(struct udev_device *udev_device);
const char *udev_device_get_devpath(struct udev_device *udev_device);
const char *udev_device_get_devnode(struct udev_device *udev_device);
dev_t udev_device_get_devnum(struct udev_device *udev_device);
const char *udev_device_get_devtype(struct udev_device *udev_device);
const char *udev_device_get_subsystem(struct udev_device *udev_device);
const char *udev_device_get_driver(struct udev_device *udev_device);
struct udev *udev_device_get_udev(struct udev_device *udev_device);
struct udev_device *udev_device_get_parent(struct udev_device *udev_device);
struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype);
int udev_device_get_is_initialized(struct udev_device *udev_device);
const char *udev_device_get_action(struct udev_device *udev_device);
int udev_device_has_tag(struct udev_device *udev_device, const char *tag);
struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device);
struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device);
struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device);
struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device);
const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key);
const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr);
int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, const char *value);
struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath);
struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum);
struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname);
struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id);
struct udev_device *udev_device_new_from_environment(struct udev *udev);
struct udev_device *udev_device_ref(struct udev_device *udev_device);
struct udev_device *udev_device_unref(struct udev_device *udev_device);
int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem);
int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem);
int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value);
int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value);
int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value);
int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname);
int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag);
int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent);
int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate);
int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate);
int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate);
struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate);
int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath);
struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate);
struct udev_enumerate *udev_enumerate_new(struct udev *udev);
struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate);
struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate);
struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry);
struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name);
const char *udev_list_entry_get_name(struct udev_list_entry *list_entry);
const char *udev_list_entry_get_value(struct udev_list_entry *list_entry);
struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor);
int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor);
int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size);
int udev_monitor_get_fd(struct udev_monitor *udev_monitor);
struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor);
int udev_monitor_filter_update(struct udev_monitor *udev_monitor);
int udev_monitor_filter_remove(struct udev_monitor *udev_monitor);
int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor, const char *subsystem, const char *devtype);
int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag);
struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name);
struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor);
struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor);
#ifdef __cplusplus
}
#endif

643
udev_device.c Normal file
View File

@@ -0,0 +1,643 @@
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include "udev.h"
#include "udev_list.h"
#include "udev_util.h"
#include "udev_device.h"
struct udev_device
{
struct udev_list_entry properties;
struct udev_list_entry sysattrs;
struct udev_device *parent;
struct udev *udev;
char *subsystem;
char *syspath;
char *sysname;
char *devpath;
char *devnode;
char *devtype;
char *driver;
char *sysnum;
dev_t devnum;
int refcount;
};
UDEV_EXPORT const char *udev_device_get_syspath(struct udev_device *udev_device)
{
if (!udev_device) {
return NULL;
}
return udev_device->syspath;
}
UDEV_EXPORT const char *udev_device_get_sysname(struct udev_device *udev_device)
{
if (!udev_device) {
return NULL;
}
return udev_device->sysname;
}
UDEV_EXPORT const char *udev_device_get_sysnum(struct udev_device *udev_device)
{
if (!udev_device) {
return NULL;
}
return udev_device->sysnum;
}
UDEV_EXPORT const char *udev_device_get_devpath(struct udev_device *udev_device)
{
if (!udev_device) {
return NULL;
}
return udev_device->devpath;
}
UDEV_EXPORT const char *udev_device_get_devnode(struct udev_device *udev_device)
{
if (!udev_device) {
return NULL;
}
return udev_device->devnode;
}
UDEV_EXPORT dev_t udev_device_get_devnum(struct udev_device *udev_device)
{
if (!udev_device) {
return makedev(0, 0);
}
return udev_device->devnum;
}
UDEV_EXPORT const char *udev_device_get_devtype(struct udev_device *udev_device)
{
if (!udev_device) {
return NULL;
}
return udev_device->devtype;
}
UDEV_EXPORT const char *udev_device_get_subsystem(struct udev_device *udev_device)
{
if (!udev_device) {
return NULL;
}
return udev_device->subsystem;
}
UDEV_EXPORT const char *udev_device_get_driver(struct udev_device *udev_device)
{
if (!udev_device) {
return NULL;
}
return udev_device->driver;
}
UDEV_EXPORT struct udev *udev_device_get_udev(struct udev_device *udev_device)
{
if (!udev_device) {
return NULL;
}
return udev_device->udev;
}
UDEV_EXPORT struct udev_device *udev_device_get_parent(struct udev_device *udev_device)
{
char *path;
int slash;
if (!udev_device) {
return NULL;
}
path = strdup(udev_device->syspath);
while (1) {
slash = strrchr(path, '/') - path;
if (!slash) {
free(path);
return NULL;
}
path[slash] = '\0';
udev_device->parent = udev_device_new_from_syspath(udev_device->udev, path);
if (udev_device->parent) {
free(path);
return udev_device->parent;
}
}
}
UDEV_EXPORT struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype)
{
const char *parent_subsystem, *parent_devtype;
struct udev_device *parent;
if (!udev_device || !subsystem) {
return NULL;
}
while ((parent = udev_device_get_parent(udev_device))) {
parent_subsystem = udev_device_get_subsystem(parent);
parent_devtype = udev_device_get_devtype(parent);
if (parent_subsystem && strcmp(parent_subsystem, subsystem) == 0) {
if (!devtype) {
return parent;
}
if (parent_devtype && strcmp(parent_devtype, devtype) == 0) {
return parent;
}
}
}
return NULL;
}
UDEV_EXPORT int udev_device_get_is_initialized(struct udev_device *udev_device)
{
return 1;
}
UDEV_EXPORT const char *udev_device_get_action(struct udev_device *udev_device)
{
return NULL;
}
UDEV_EXPORT int udev_device_has_tag(struct udev_device *udev_device, const char *tag)
{
// XXX NOT IMPLEMENTED
return 0;
}
UDEV_EXPORT struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device)
{
// XXX NOT IMPLEMENTED
return NULL;
}
UDEV_EXPORT struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device)
{
if (!udev_device) {
return NULL;
}
return &udev_device->properties;
}
UDEV_EXPORT struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device)
{
// XXX NOT IMPLEMENTED
return NULL;
}
UDEV_EXPORT struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device)
{
if (!udev_device) {
return NULL;
}
return &udev_device->sysattrs;
}
UDEV_EXPORT const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key)
{
}
UDEV_EXPORT const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr)
{
struct udev_list_entry *list_entry;
char data[1024], *path = NULL;
struct stat st;
ssize_t len;
int fd;
if (!udev_device || !sysattr) {
return NULL;
}
list_entry = udev_list_entry_get_by_name(&udev_device->sysattrs, sysattr);
if (list_entry) {
return udev_list_entry_get_value(list_entry);
}
if (xasprintf(path, "%s/%s", udev_device->syspath, sysattr) == -1) {
return NULL;
}
if (stat(path, &st) != 0 || S_ISDIR(st.st_mode)) {
free(path);
return NULL;
}
fd = open(path, O_RDONLY);
if (fd == -1) {
free(path);
return NULL;
}
len = read(fd, data, sizeof(data));
if (len == -1) {
close(fd);
free(path);
return NULL;
}
close(fd);
free(path);
data[len] = '\0';
list_entry = udev_list_entry_add(&udev_device->sysattrs, sysattr, data);
return udev_list_entry_get_value(list_entry);
}
UDEV_EXPORT int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, const char *value)
{
size_t len = strlen(value);
char *path = NULL;
struct stat st;
int fd;
if (!udev_device || !sysattr || !value) {
return -1;
}
if (xasprintf(path, "%s/%s", udev_device->syspath, sysattr) == -1) {
return -1;
}
if (stat(path, &st) != 0 || S_ISDIR(st.st_mode)) {
free(path);
return -1;
}
fd = open(path, O_WRONLY | O_NOFOLLOW);
if (fd == -1) {
free(path);
return -1;
}
if (write(fd, value, len) == -1) {
close(fd);
free(path);
return -1;
}
close(fd);
free(path);
udev_list_entry_add(&udev_device->sysattrs, sysattr, value);
return 0;
}
char *udev_device_read_uevent(struct udev_device *udev_device, const char *name)
{
char *line, *path = NULL, *data = NULL;
size_t nlen = strlen(name), glen = 0;
FILE *file;
if (xasprintf(path, "%s/%s", udev_device->syspath, "uevent") == -1) {
return NULL;
}
file = fopen(path, "r");
if (!file) {
free(path);
return NULL;
}
while (getline(&line, &glen, file) != -1) {
if (strncmp(line, name, nlen) == 0) {
data = strdup(line + nlen);
break;
}
}
fclose(file);
free(line);
free(path);
return data;
}
char *udev_device_read_symlink(struct udev_device *udev_device, const char *name)
{
char *link, *data, *path = NULL;
if (xasprintf(path, "%s/%s", udev_device->syspath, name) == -1) {
return NULL;
}
link = realpath(path, NULL); // XXX XSI
if (!link) {
free(path);
return NULL;
}
data = strdup(strrchr(link, '/') + 1);
free(path);
free(link);
return data;
}
void udev_device_set_subsystem(struct udev_device *udev_device)
{
char *subsystem;
udev_device->subsystem = NULL;
subsystem = udev_device_read_symlink(udev_device, "subsystem");
if (!subsystem) {
return;
}
udev_device->subsystem = subsystem;
}
void udev_device_set_sysname(struct udev_device *udev_device)
{
char *devname, *sysname;
udev_device->sysname = NULL;
devname = udev_device_read_uevent(udev_device, "DEVNAME=");
if (!devname) {
return;
}
sysname = strrchr(devname, '/');
if (!sysname) {
sysname = devname;
}
else {
sysname++;
}
udev_device->sysname = strdup(sysname);
free(devname);
}
void udev_device_set_devnode(struct udev_device *udev_device)
{
char *devname, *devnode = NULL;
udev_device->devnode = NULL;
devname = udev_device_read_uevent(udev_device, "DEVNAME=");
if (!devname) {
return;
}
if (xasprintf(devnode, "/dev/%s", devname) == -1) {
free(devname);
return;
}
udev_device->devnode = devnode;
free(devname);
}
void udev_device_set_devtype(struct udev_device *udev_device)
{
char *devtype;
udev_device->devtype = NULL;
devtype = udev_device_read_uevent(udev_device, "DEVTYPE=");
if (!devtype) {
return;
}
udev_device->devtype = devtype;
}
void udev_device_set_driver(struct udev_device *udev_device)
{
char *driver;
udev_device->driver = NULL;
driver = udev_device_read_symlink(udev_device, "driver");
if (!driver) {
return;
}
udev_device->driver = driver;
}
void udev_device_set_devnum(struct udev_device *udev_device)
{
char *major, *minor;
udev_device->devnum = makedev(0, 0);
major = udev_device_read_uevent(udev_device, "MAJOR=");
minor = udev_device_read_uevent(udev_device, "MINOR=");
if (!major && !minor) {
return;
}
udev_device->devnum = makedev(atoi(major), atoi(minor));
free(major);
free(minor);
}
void udev_device_set_sysnum(struct udev_device *udev_device)
{
int i;
udev_device->sysnum = NULL;
if (!udev_device->sysname) {
return;
}
for (i = 0; udev_device->sysname[i] != '\0'; i++) {
if (udev_device->sysname[i] >= '0' &&
udev_device->sysname[i] <= '9') {
udev_device->sysnum = strdup(udev_device->sysname + i);
return;
}
}
}
void udev_device_set_properties(struct udev_device *udev_device)
{
}
UDEV_EXPORT struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath)
{
struct udev_device *udev_device;
char *path, *file = NULL;
struct stat st;
if (!udev || !syspath) {
return NULL;
}
path = realpath(syspath, NULL); // XXX XSI
if (!path) {
return NULL;
}
if (stat(path, &st) != 0 || S_ISDIR(st.st_mode) == 0) {
free(path);
return NULL;
}
if (xasprintf(file, "%s/%s", path, "uevent") == -1) {
free(path);
return NULL;
}
if (access(file, R_OK) == -1) {
free(file);
free(path);
return NULL;
}
free(file);
udev_device = calloc(1, sizeof(struct udev_device));
if (!udev_device) {
free(path);
return NULL;
}
udev_device->udev = udev;
udev_device->refcount = 1;
udev_device->syspath = path;
udev_device->devpath = strdup(path + 4);
udev_list_entry_init(&udev_device->properties);
udev_list_entry_init(&udev_device->sysattrs);
udev_device_set_properties(udev_device);
udev_device_set_subsystem(udev_device);
udev_device_set_sysname(udev_device);
udev_device_set_devnode(udev_device);
udev_device_set_devtype(udev_device);
udev_device_set_driver(udev_device);
udev_device_set_sysnum(udev_device);
udev_device_set_devnum(udev_device);
return udev_device;
}
UDEV_EXPORT struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum)
{
struct udev_device *udev_device;
char *path = NULL;
if (!udev || !type || !devnum) {
return NULL;
}
switch (type) {
case 'c':
xasprintf(path, "/sys/dev/char/%d:%d", major(devnum), minor(devnum));
break;
case 'b':
xasprintf(path, "/sys/dev/block/%d:%d", major(devnum), minor(devnum));
break;
default:
return NULL;
}
udev_device = udev_device_new_from_syspath(udev, path);
free(path);
return udev_device;
}
UDEV_EXPORT struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname)
{
// XXX NOT IMPLEMENTED
return NULL;
}
UDEV_EXPORT struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id)
{
// XXX NOT IMPLEMENTED
return NULL;
}
UDEV_EXPORT struct udev_device *udev_device_new_from_environment(struct udev *udev)
{
// XXX NOT IMPLEMENTED
return NULL;
}
UDEV_EXPORT struct udev_device *udev_device_ref(struct udev_device *udev_device)
{
if (!udev_device) {
return NULL;
}
udev_device->refcount++;
return udev_device;
}
UDEV_EXPORT struct udev_device *udev_device_unref(struct udev_device *udev_device)
{
if (!udev_device) {
return NULL;
}
if (--udev_device->refcount > 0) {
return NULL;
}
if (udev_device->parent) {
udev_device_unref(udev_device->parent);
}
udev_list_entry_free_all(&udev_device->properties);
udev_list_entry_free_all(&udev_device->sysattrs);
free(udev_device->subsystem);
free(udev_device->syspath);
free(udev_device->devpath);
free(udev_device->sysname);
free(udev_device->devnode);
free(udev_device->devtype);
free(udev_device->driver);
free(udev_device->sysnum);
free(udev_device);
return NULL;
}

10
udev_device.h Normal file
View File

@@ -0,0 +1,10 @@
char *udev_device_read_uevent(struct udev_device *udev_device, const char *name);
char *udev_device_read_symlink(struct udev_device *udev_device, const char *name);
void udev_device_set_properties(struct udev_device *udev_device);
void udev_device_set_subsystem(struct udev_device *udev_device);
void udev_device_set_sysname(struct udev_device *udev_device);
void udev_device_set_devnode(struct udev_device *udev_device);
void udev_device_set_devtype(struct udev_device *udev_device);
void udev_device_set_driver(struct udev_device *udev_device);
void udev_device_set_sysnum(struct udev_device *udev_device);
void udev_device_set_devnum(struct udev_device *udev_device);

162
udev_enumerate.c Normal file
View File

@@ -0,0 +1,162 @@
#include <stdlib.h>
#include "udev.h"
#include "udev_list.h"
struct udev_enumerate
{
struct udev_list_entry subsystem_nomatch;
struct udev_list_entry subsystem_match;
struct udev_list_entry sysattr_nomatch;
struct udev_list_entry property_match;
struct udev_list_entry sysattr_match;
struct udev_list_entry sysname_match;
struct udev_list_entry devices;
struct udev *udev;
int refcount;
};
UDEV_EXPORT int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem)
{
if (!udev_enumerate || !subsystem) {
return -1;
}
return udev_list_entry_add(&udev_enumerate->subsystem_match, subsystem, NULL) ? 0 : -1;
}
UDEV_EXPORT int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem)
{
if (!udev_enumerate || !subsystem) {
return -1;
}
return udev_list_entry_add(&udev_enumerate->subsystem_nomatch, subsystem, NULL) ? 0 : -1;
}
UDEV_EXPORT int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value)
{
if (!udev_enumerate || !sysattr) {
return -1;
}
return udev_list_entry_add(&udev_enumerate->sysattr_match, sysattr, value) ? 0 : -1;
}
UDEV_EXPORT int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value)
{
if (!udev_enumerate || !sysattr) {
return -1;
}
return udev_list_entry_add(&udev_enumerate->sysattr_nomatch, sysattr, value) ? 0 : -1;
}
UDEV_EXPORT int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value)
{
if (!udev_enumerate || !property) {
return -1;
}
return udev_list_entry_add(&udev_enumerate->property_match, property, value) ? 0 : -1;
}
UDEV_EXPORT int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname)
{
if (!udev_enumerate || !sysname) {
return -1;
}
return udev_list_entry_add(&udev_enumerate->sysname_match, sysname, NULL) ? 0 : -1;
}
UDEV_EXPORT int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag)
{
// XXX NOT IMPLEMENTED
return 0;
}
UDEV_EXPORT int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent)
{
// XXX NOT IMPLEMENTED
return 0;
}
UDEV_EXPORT int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate)
{
return 0;
}
UDEV_EXPORT int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate)
{
}
UDEV_EXPORT int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate)
{
}
UDEV_EXPORT struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate)
{
if (!udev_enumerate) {
return NULL;
}
return &udev_enumerate->devices;
}
UDEV_EXPORT int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath)
{
// XXX NOT IMPLEMENTED
return 0;
}
UDEV_EXPORT struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate)
{
if (!udev_enumerate) {
return NULL;
}
return udev_enumerate->udev;
}
UDEV_EXPORT struct udev_enumerate *udev_enumerate_new(struct udev *udev)
{
struct udev_enumerate *udev_enumerate;
if (!udev) {
return NULL;
}
udev_enumerate = calloc(1, sizeof(struct udev_enumerate));
if (!udev_enumerate) {
return NULL;
}
udev_enumerate->refcount = 1;
udev_enumerate->udev = udev;
udev_list_entry_init(&udev_enumerate->subsystem_nomatch);
udev_list_entry_init(&udev_enumerate->subsystem_match);
udev_list_entry_init(&udev_enumerate->sysattr_nomatch);
udev_list_entry_init(&udev_enumerate->property_match);
udev_list_entry_init(&udev_enumerate->sysattr_match);
udev_list_entry_init(&udev_enumerate->sysname_match);
udev_list_entry_init(&udev_enumerate->devices);
return udev_enumerate;
}
UDEV_EXPORT struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate)
{
if (!udev_enumerate) {
return NULL;
}
udev_enumerate->refcount++;
return udev_enumerate;
}
UDEV_EXPORT struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate)
{
}

109
udev_list.c Normal file
View File

@@ -0,0 +1,109 @@
#include <string.h>
#include <stdlib.h>
#include "udev.h"
#include "udev_list.h"
void udev_list_entry_init(struct udev_list_entry *list_entry)
{
list_entry->value = NULL;
list_entry->name = NULL;
list_entry->next = NULL;
}
void udev_list_entry_free(struct udev_list_entry *list_entry)
{
free(list_entry->value);
free(list_entry->name);
free(list_entry);
}
void udev_list_entry_free_all(struct udev_list_entry *list_entry)
{
struct udev_list_entry *tmp, *tmp2;
tmp = list_entry;
while (tmp) {
tmp2 = tmp;
tmp = tmp->next;
udev_list_entry_free(tmp2);
}
}
struct udev_list_entry *udev_list_entry_add(struct udev_list_entry *list_entry, const char *name, const char *value)
{
struct udev_list_entry *new, *old;
old = udev_list_entry_get_by_name(list_entry, name);
if (old) {
free(old->value);
old->value = strdup(value);
return old;
}
new = calloc(1, sizeof(struct udev_list_entry));
if (!new) {
return NULL;
}
udev_list_entry_init(new);
new->value = value ? strdup(value) : NULL;
new->name = strdup(name);
new->next = list_entry->next;
list_entry->next = new;
return new;
}
UDEV_EXPORT struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry)
{
if (!list_entry) {
return NULL;
}
return list_entry->next;
}
UDEV_EXPORT struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name)
{
struct udev_list_entry *tmp;
if (!list_entry || !name) {
return NULL;
}
tmp = list_entry;
while (tmp) {
if (strcmp(tmp->name, name) == 0) {
return tmp;
}
tmp = tmp->next;
}
return NULL;
}
UDEV_EXPORT const char *udev_list_entry_get_name(struct udev_list_entry *list_entry)
{
if (!list_entry) {
return NULL;
}
return list_entry->name;
}
UDEV_EXPORT const char *udev_list_entry_get_value(struct udev_list_entry *list_entry)
{
if (!list_entry) {
return NULL;
}
return list_entry->value;
}

11
udev_list.h Normal file
View File

@@ -0,0 +1,11 @@
struct udev_list_entry
{
struct udev_list_entry *next;
char *value;
char *name;
};
void udev_list_entry_init(struct udev_list_entry *list_entry);
void udev_list_entry_free(struct udev_list_entry *list_entry);
void udev_list_entry_free_all(struct udev_list_entry *list_entry);
struct udev_list_entry *udev_list_entry_add(struct udev_list_entry *list_entry, const char *name, const char *value);

125
udev_monitor.c Normal file
View File

@@ -0,0 +1,125 @@
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include "udev.h"
struct udev_monitor
{
struct udev *udev;
int refcount;
int fd[2];
};
UDEV_EXPORT struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor)
{
return (void *)1;
}
UDEV_EXPORT int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor)
{
return 0;
}
UDEV_EXPORT int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size)
{
return 0;
}
UDEV_EXPORT int udev_monitor_get_fd(struct udev_monitor *udev_monitor)
{
if (!udev_monitor) {
return -1;
}
return udev_monitor->fd[0];
}
UDEV_EXPORT struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor)
{
if (!udev_monitor) {
return NULL;
}
return udev_monitor->udev;
}
UDEV_EXPORT int udev_monitor_filter_update(struct udev_monitor *udev_monitor)
{
return 0;
}
UDEV_EXPORT int udev_monitor_filter_remove(struct udev_monitor *udev_monitor)
{
return 0;
}
UDEV_EXPORT int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor, const char *subsystem, const char *devtype)
{
return 0;
}
UDEV_EXPORT int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag)
{
return 0;
}
UDEV_EXPORT struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name)
{
struct udev_monitor *udev_monitor;
int i;
if (!udev || !name) {
return NULL;
}
udev_monitor = calloc(1, sizeof(struct udev_monitor));
if (!udev_monitor) {
return NULL;
}
// TODO better no-op, HELP WANTED !
if (pipe(udev_monitor->fd) == -1) {
free(udev_monitor);
return NULL;
}
for (i = 0; i < 2; i++) {
fcntl(udev_monitor->fd[i], F_SETFD, FD_CLOEXEC | O_NONBLOCK);
}
udev_monitor->refcount = 1;
udev_monitor->udev = udev;
return udev_monitor;
}
UDEV_EXPORT struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor)
{
if (!udev_monitor) {
return NULL;
}
udev_monitor->refcount++;
return udev_monitor;
}
UDEV_EXPORT struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor)
{
int i;
if (!udev_monitor) {
return NULL;
}
if (--udev_monitor->refcount > 0) {
return NULL;
}
for (i = 0; i < 2; i++) {
close(udev_monitor->fd[i]);
}
free(udev_monitor);
return NULL;
}

37
udev_util.c Normal file
View File

@@ -0,0 +1,37 @@
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include "udev_util.h"
#include "udev.h"
int xasprintf(char *str, const char *fmt, ...)
{
va_list list;
int len;
va_start(list, fmt);
len = vsnprintf(NULL, 0, fmt, list);
va_end(list);
if (len == -1) {
return -1;
}
str = malloc(len + 1);
if (!str) {
return -1;
}
len = vsnprintf(str, len + 1, fmt, list);
if (len == -1) {
free(str);
return -1;
}
return len;
}
// TODO readlink+malloc

1
udev_util.h Normal file
View File

@@ -0,0 +1 @@
int xasprintf(char *str, const char *fmt, ...);