Systemd/src/test/test-libudev.c
Zbigniew Jędrzejewski-Szmek 960787ae27 hostnamectl: show only specific hostname when requested
Existing --pretty, --transient, --static options, used previously
for 'set-hostname' verb, are reused for the 'status' verb. If one
of them is given, only the specified hostname is printed. This
way there's no need to employ awk to get the hostname in a script.
2013-08-14 19:06:54 -04:00

521 lines
18 KiB
C

/***
This file is part of systemd.
Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <getopt.h>
#include <syslog.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include "libudev.h"
#include "util.h"
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
static void log_fn(struct udev *udev,
int priority, const char *file, int line, const char *fn,
const char *format, va_list args)
{
printf("test-libudev: %s %s:%d ", fn, file, line);
vprintf(format, args);
}
static void print_device(struct udev_device *device)
{
const char *str;
dev_t devnum;
int count;
struct udev_list_entry *list_entry;
printf("*** device: %p ***\n", device);
str = udev_device_get_action(device);
if (str != NULL)
printf("action: '%s'\n", str);
str = udev_device_get_syspath(device);
printf("syspath: '%s'\n", str);
str = udev_device_get_sysname(device);
printf("sysname: '%s'\n", str);
str = udev_device_get_sysnum(device);
if (str != NULL)
printf("sysnum: '%s'\n", str);
str = udev_device_get_devpath(device);
printf("devpath: '%s'\n", str);
str = udev_device_get_subsystem(device);
if (str != NULL)
printf("subsystem: '%s'\n", str);
str = udev_device_get_devtype(device);
if (str != NULL)
printf("devtype: '%s'\n", str);
str = udev_device_get_driver(device);
if (str != NULL)
printf("driver: '%s'\n", str);
str = udev_device_get_devnode(device);
if (str != NULL)
printf("devname: '%s'\n", str);
devnum = udev_device_get_devnum(device);
if (major(devnum) > 0)
printf("devnum: %u:%u\n", major(devnum), minor(devnum));
count = 0;
udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(device)) {
printf("link: '%s'\n", udev_list_entry_get_name(list_entry));
count++;
}
if (count > 0)
printf("found %i links\n", count);
count = 0;
udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(device)) {
printf("property: '%s=%s'\n",
udev_list_entry_get_name(list_entry),
udev_list_entry_get_value(list_entry));
count++;
}
if (count > 0)
printf("found %i properties\n", count);
str = udev_device_get_property_value(device, "MAJOR");
if (str != NULL)
printf("MAJOR: '%s'\n", str);
str = udev_device_get_sysattr_value(device, "dev");
if (str != NULL)
printf("attr{dev}: '%s'\n", str);
printf("\n");
}
static int test_device(struct udev *udev, const char *syspath)
{
struct udev_device *device;
printf("looking at device: %s\n", syspath);
device = udev_device_new_from_syspath(udev, syspath);
if (device == NULL) {
printf("no device found\n");
return -1;
}
print_device(device);
udev_device_unref(device);
return 0;
}
static int test_device_parents(struct udev *udev, const char *syspath)
{
struct udev_device *device;
struct udev_device *device_parent;
printf("looking at device: %s\n", syspath);
device = udev_device_new_from_syspath(udev, syspath);
if (device == NULL)
return -1;
printf("looking at parents\n");
device_parent = device;
do {
print_device(device_parent);
device_parent = udev_device_get_parent(device_parent);
} while (device_parent != NULL);
printf("looking at parents again\n");
device_parent = device;
do {
print_device(device_parent);
device_parent = udev_device_get_parent(device_parent);
} while (device_parent != NULL);
udev_device_unref(device);
return 0;
}
static int test_device_devnum(struct udev *udev)
{
dev_t devnum = makedev(1, 3);
struct udev_device *device;
printf("looking up device: %u:%u\n", major(devnum), minor(devnum));
device = udev_device_new_from_devnum(udev, 'c', devnum);
if (device == NULL)
return -1;
print_device(device);
udev_device_unref(device);
return 0;
}
static int test_device_subsys_name(struct udev *udev)
{
struct udev_device *device;
printf("looking up device: 'block':'sda'\n");
device = udev_device_new_from_subsystem_sysname(udev, "block", "sda");
if (device == NULL)
return -1;
print_device(device);
udev_device_unref(device);
printf("looking up device: 'subsystem':'pci'\n");
device = udev_device_new_from_subsystem_sysname(udev, "subsystem", "pci");
if (device == NULL)
return -1;
print_device(device);
udev_device_unref(device);
printf("looking up device: 'drivers':'scsi:sd'\n");
device = udev_device_new_from_subsystem_sysname(udev, "drivers", "scsi:sd");
if (device == NULL)
return -1;
print_device(device);
udev_device_unref(device);
printf("looking up device: 'module':'printk'\n");
device = udev_device_new_from_subsystem_sysname(udev, "module", "printk");
if (device == NULL)
return -1;
print_device(device);
udev_device_unref(device);
return 0;
}
static int test_enumerate_print_list(struct udev_enumerate *enumerate)
{
struct udev_list_entry *list_entry;
int count = 0;
udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) {
struct udev_device *device;
device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerate),
udev_list_entry_get_name(list_entry));
if (device != NULL) {
printf("device: '%s' (%s)\n",
udev_device_get_syspath(device),
udev_device_get_subsystem(device));
udev_device_unref(device);
count++;
}
}
printf("found %i devices\n\n", count);
return count;
}
static int test_monitor(struct udev *udev)
{
struct udev_monitor *udev_monitor = NULL;
int fd_ep;
int fd_udev = -1;
struct epoll_event ep_udev, ep_stdin;
fd_ep = epoll_create1(EPOLL_CLOEXEC);
if (fd_ep < 0) {
printf("error creating epoll fd: %m\n");
goto out;
}
udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
if (udev_monitor == NULL) {
printf("no socket\n");
goto out;
}
fd_udev = udev_monitor_get_fd(udev_monitor);
if (udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "block", NULL) < 0 ||
udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "tty", NULL) < 0 ||
udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", "usb_device") < 0) {
printf("filter failed\n");
goto out;
}
if (udev_monitor_enable_receiving(udev_monitor) < 0) {
printf("bind failed\n");
goto out;
}
memset(&ep_udev, 0, sizeof(struct epoll_event));
ep_udev.events = EPOLLIN;
ep_udev.data.fd = fd_udev;
if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_udev, &ep_udev) < 0) {
printf("fail to add fd to epoll: %m\n");
goto out;
}
memset(&ep_stdin, 0, sizeof(struct epoll_event));
ep_stdin.events = EPOLLIN;
ep_stdin.data.fd = STDIN_FILENO;
if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, STDIN_FILENO, &ep_stdin) < 0) {
printf("fail to add fd to epoll: %m\n");
goto out;
}
for (;;) {
int fdcount;
struct epoll_event ev[4];
struct udev_device *device;
int i;
printf("waiting for events from udev, press ENTER to exit\n");
fdcount = epoll_wait(fd_ep, ev, ARRAY_SIZE(ev), -1);
printf("epoll fd count: %i\n", fdcount);
for (i = 0; i < fdcount; i++) {
if (ev[i].data.fd == fd_udev && ev[i].events & EPOLLIN) {
device = udev_monitor_receive_device(udev_monitor);
if (device == NULL) {
printf("no device from socket\n");
continue;
}
print_device(device);
udev_device_unref(device);
} else if (ev[i].data.fd == STDIN_FILENO && ev[i].events & EPOLLIN) {
printf("exiting loop\n");
goto out;
}
}
}
out:
if (fd_ep >= 0)
close(fd_ep);
udev_monitor_unref(udev_monitor);
return 0;
}
static int test_queue(struct udev *udev)
{
struct udev_queue *udev_queue;
unsigned long long int seqnum;
struct udev_list_entry *list_entry;
udev_queue = udev_queue_new(udev);
if (udev_queue == NULL)
return -1;
seqnum = udev_queue_get_kernel_seqnum(udev_queue);
printf("seqnum kernel: %llu\n", seqnum);
seqnum = udev_queue_get_udev_seqnum(udev_queue);
printf("seqnum udev : %llu\n", seqnum);
if (udev_queue_get_queue_is_empty(udev_queue))
printf("queue is empty\n");
printf("get queue list\n");
udev_list_entry_foreach(list_entry, udev_queue_get_queued_list_entry(udev_queue))
printf("queued: '%s' [%s]\n", udev_list_entry_get_name(list_entry), udev_list_entry_get_value(list_entry));
printf("\n");
printf("get queue list again\n");
udev_list_entry_foreach(list_entry, udev_queue_get_queued_list_entry(udev_queue))
printf("queued: '%s' [%s]\n", udev_list_entry_get_name(list_entry), udev_list_entry_get_value(list_entry));
printf("\n");
list_entry = udev_queue_get_queued_list_entry(udev_queue);
if (list_entry != NULL) {
printf("event [%llu] is queued\n", seqnum);
seqnum = strtoull(udev_list_entry_get_value(list_entry), NULL, 10);
if (udev_queue_get_seqnum_is_finished(udev_queue, seqnum))
printf("event [%llu] is not finished\n", seqnum);
else
printf("event [%llu] is finished\n", seqnum);
}
printf("\n");
udev_queue_unref(udev_queue);
return 0;
}
static int test_enumerate(struct udev *udev, const char *subsystem)
{
struct udev_enumerate *udev_enumerate;
printf("enumerate '%s'\n", subsystem == NULL ? "<all>" : subsystem);
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
udev_enumerate_add_match_subsystem(udev_enumerate, subsystem);
udev_enumerate_scan_devices(udev_enumerate);
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
printf("enumerate 'net' + duplicated scan + null + zero\n");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
udev_enumerate_add_match_subsystem(udev_enumerate, "net");
udev_enumerate_scan_devices(udev_enumerate);
udev_enumerate_scan_devices(udev_enumerate);
udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero");
udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/null");
udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero");
udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/null");
udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero");
udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/null");
udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/null");
udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero");
udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero");
udev_enumerate_scan_devices(udev_enumerate);
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
printf("enumerate 'block'\n");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
udev_enumerate_add_match_subsystem(udev_enumerate,"block");
udev_enumerate_add_match_is_initialized(udev_enumerate);
udev_enumerate_scan_devices(udev_enumerate);
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
printf("enumerate 'not block'\n");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
udev_enumerate_add_nomatch_subsystem(udev_enumerate, "block");
udev_enumerate_scan_devices(udev_enumerate);
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
printf("enumerate 'pci, mem, vc'\n");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
udev_enumerate_add_match_subsystem(udev_enumerate, "pci");
udev_enumerate_add_match_subsystem(udev_enumerate, "mem");
udev_enumerate_add_match_subsystem(udev_enumerate, "vc");
udev_enumerate_scan_devices(udev_enumerate);
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
printf("enumerate 'subsystem'\n");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
udev_enumerate_scan_subsystems(udev_enumerate);
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
printf("enumerate 'property IF_FS_*=filesystem'\n");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
udev_enumerate_add_match_property(udev_enumerate, "ID_FS*", "filesystem");
udev_enumerate_scan_devices(udev_enumerate);
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
return 0;
}
static int test_hwdb(struct udev *udev, const char *modalias) {
struct udev_hwdb *hwdb;
struct udev_list_entry *entry;
hwdb = udev_hwdb_new(udev);
udev_list_entry_foreach(entry, udev_hwdb_get_properties_list_entry(hwdb, modalias, 0))
printf("'%s'='%s'\n", udev_list_entry_get_name(entry), udev_list_entry_get_value(entry));
printf("\n");
hwdb = udev_hwdb_unref(hwdb);
return 0;
}
int main(int argc, char *argv[])
{
struct udev *udev = NULL;
static const struct option options[] = {
{ "syspath", required_argument, NULL, 'p' },
{ "subsystem", required_argument, NULL, 's' },
{ "debug", no_argument, NULL, 'd' },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
{}
};
const char *syspath = "/devices/virtual/mem/null";
const char *subsystem = NULL;
char path[1024];
udev = udev_new();
printf("context: %p\n", udev);
if (udev == NULL) {
printf("no context\n");
return 1;
}
udev_set_log_fn(udev, log_fn);
printf("set log: %p\n", log_fn);
for (;;) {
int option;
option = getopt_long(argc, argv, "+p:s:dhV", options, NULL);
if (option == -1)
break;
switch (option) {
case 'p':
syspath = optarg;
break;
case 's':
subsystem = optarg;
break;
case 'd':
if (udev_get_log_priority(udev) < LOG_INFO)
udev_set_log_priority(udev, LOG_INFO);
break;
case 'h':
printf("--debug --syspath= --subsystem= --help\n");
goto out;
case 'V':
printf("%s\n", VERSION);
goto out;
default:
goto out;
}
}
/* add sys path if needed */
if (!startswith(syspath, "/sys")) {
snprintf(path, sizeof(path), "/sys/%s", syspath);
syspath = path;
}
test_device(udev, syspath);
test_device_devnum(udev);
test_device_subsys_name(udev);
test_device_parents(udev, syspath);
test_enumerate(udev, subsystem);
test_queue(udev);
test_hwdb(udev, "usb:v0D50p0011*");
test_monitor(udev);
out:
udev_unref(udev);
return 0;
}