diff options
author | Kay Sievers <kay.sievers@suse.de> | 2005-08-01 20:22:46 +0200 |
---|---|---|
committer | Kay Sievers <kay.sievers@suse.de> | 2005-08-01 20:22:46 +0200 |
commit | 1bc33626787f089523192c270790f9f878a4edd7 (patch) | |
tree | 9364115ab0af3a31341fddc4e217c20025162be9 /udevmonitor.c | |
parent | d455b0085d65cd25915a34d84f894a4950d313a2 (diff) |
add udevmonitor, to debug netlink+udev events at the same time
This rule:
RUN+="socket:/org/kernel/udev/monitor"
send the event to the running monitor. Running udevstart give a nice
monitor output. Also the delay between the kernel uevent and the udev
udev event can be investigated:
pim:/home/kay/src/udev-kay # ./udevmonitor
UEVENT[1122920113] add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1
UEVENT[1122920113] add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0
UEVENT[1122920113] add@/class/scsi_host/host12
UEVENT[1122920113] add@/class/usb_device/usbdev2.99
UEVENT[1122920113] add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0/host12/target12:0:0/12:0:0:0
UDEV [1122920113] add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1
UEVENT[1122920113] add@/block/sda
UEVENT[1122920113] add@/class/scsi_generic/sg0
UEVENT[1122920113] add@/class/scsi_device/12:0:0:0
UDEV [1122920113] add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0
UDEV [1122920113] add@/class/scsi_host/host12
UDEV [1122920113] add@/class/usb_device/usbdev2.99
UDEV [1122920113] add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0/host12/target12:0:0/12:0:0:0
UDEV [1122920113] add@/block/sda
UDEV [1122920113] add@/class/scsi_generic/sg0
UDEV [1122920113] add@/class/scsi_device/12:0:0:0
UEVENT[1122920115] add@/block/sda/sda1
UDEV [1122920115] add@/block/sda/sda1
pim:/home/kay/src/udev-kay # ./udevmonitor --env
UDEV [1122920185] add@/block/sda/sda1
ACTION=add
DEVPATH=/block/sda/sda1
SUBSYSTEM=block
SEQNUM=2159
MINOR=1
MAJOR=8
PHYSDEVPATH=/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0/host13/target13:0:0/13:0:0:0
PHYSDEVBUS=scsi
PHYSDEVDRIVER=sd
UDEVD_EVENT=1
UDEV_LOG=3
ID_VENDOR=IBM
ID_MODEL=Memory_Key
ID_REVISION=3.04
ID_SERIAL=IBM_Memory_Key_0218B301030027E8
ID_TYPE=disk
ID_BUS=usb
ID_PATH=usb-0218B301030027E8:0:0:0
ID_FS_USAGE=filesystem
ID_FS_TYPE=vfat
ID_FS_VERSION=FAT16
ID_FS_UUID=42D8-9E02
ID_FS_LABEL_SAFE=s_p_c
DEVNAME=/dev/sda1
Signed-off-by: Kay Sievers <kay.sievers@suse.de>
Diffstat (limited to 'udevmonitor.c')
-rw-r--r-- | udevmonitor.c | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/udevmonitor.c b/udevmonitor.c new file mode 100644 index 0000000000..f4f28b1659 --- /dev/null +++ b/udevmonitor.c @@ -0,0 +1,185 @@ +/* + * udevmonitor.c + * + * Copyright (C) 2004-2005 Kay Sievers <kay.sievers@vrfy.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2 of the License. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <time.h> +#include <errno.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <sys/select.h> +#include <linux/netlink.h> +#include <asm/types.h> + +#include "udev.h" +#include "udevd.h" + +static int uevent_netlink_sock; +static int udev_monitor_sock; + +static int init_udev_monitor_socket(void) +{ + struct sockaddr_un saddr; + socklen_t addrlen; + const int feature_on = 1; + int retval; + + memset(&saddr, 0x00, sizeof(saddr)); + saddr.sun_family = AF_LOCAL; + /* use abstract namespace for socket path */ + strcpy(&saddr.sun_path[1], "/org/kernel/udev/monitor"); + addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(saddr.sun_path+1) + 1; + + udev_monitor_sock = socket(AF_LOCAL, SOCK_DGRAM, 0); + if (udev_monitor_sock == -1) { + fprintf(stderr, "error getting socket, %s\n", strerror(errno)); + return -1; + } + + /* the bind takes care of ensuring only one copy running */ + retval = bind(udev_monitor_sock, (struct sockaddr *) &saddr, addrlen); + if (retval < 0) { + fprintf(stderr, "bind failed, %s\n", strerror(errno)); + close(udev_monitor_sock); + return -1; + } + + /* enable receiving of the sender credentials */ + setsockopt(udev_monitor_sock, SOL_SOCKET, SO_PASSCRED, &feature_on, sizeof(feature_on)); + + return 0; +} + +static int init_uevent_netlink_sock(void) +{ + struct sockaddr_nl snl; + int retval; + + memset(&snl, 0x00, sizeof(struct sockaddr_nl)); + snl.nl_family = AF_NETLINK; + snl.nl_pid = getpid(); + snl.nl_groups = 0xffffffff; + + uevent_netlink_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); + if (uevent_netlink_sock == -1) { + fprintf(stderr, "error getting socket, %s\n", strerror(errno)); + return -1; + } + + retval = bind(uevent_netlink_sock, (struct sockaddr *) &snl, + sizeof(struct sockaddr_nl)); + if (retval < 0) { + fprintf(stderr, "bind failed, %s\n", strerror(errno)); + close(uevent_netlink_sock); + uevent_netlink_sock = -1; + return -1; + } + + return 0; +} + +int main(int argc, char *argv[]) +{ + int env = 0; + int maxsockplus; + fd_set readfds; + int retval; + + if (getuid() != 0) { + printf("need to be root, exit\n"); + exit(1); + } + + if (argc == 2 && strstr(argv[1], "--env")) + env = 1; + + init_uevent_netlink_sock(); + init_udev_monitor_socket(); + + FD_ZERO(&readfds); + FD_SET(uevent_netlink_sock, &readfds); + FD_SET(udev_monitor_sock, &readfds); + maxsockplus = udev_monitor_sock+1; + + while (1) { + static char buf[UEVENT_BUFFER_SIZE*2]; + ssize_t buflen; + fd_set workreadfds; + + buflen = 0; + workreadfds = readfds; + + retval = select(maxsockplus, &workreadfds, NULL, NULL, NULL); + if (retval < 0) { + if (errno != EINTR) + fprintf(stderr, "error receiving uevent message\n"); + continue; + } + + if (FD_ISSET(uevent_netlink_sock, &workreadfds)) { + buflen = recv(uevent_netlink_sock, &buf, sizeof(buf), 0); + if (buflen <= 0) { + fprintf(stderr, "error receiving uevent message\n"); + continue; + } + printf("UEVENT[%i] %s\n", time(NULL), buf); + } + + if (FD_ISSET(udev_monitor_sock, &workreadfds)) { + buflen = recv(udev_monitor_sock, &buf, sizeof(buf), 0); + if (buflen <= 0) { + fprintf(stderr, "error receiving udev message\n"); + continue; + } + printf("UDEV [%i] %s\n", time(NULL), buf); + } + + if (buflen == 0) + continue; + + /* print environment */ + if (env) { + size_t bufpos; + + /* start of payload */ + bufpos = strlen(buf) + 1; + + while (bufpos < (size_t)buflen) { + int keylen; + char *key; + + key = &buf[bufpos]; + keylen = strlen(key); + if (keylen == 0) + break; + printf("%s\n", key); + bufpos += keylen + 1; + } + printf("\n"); + } + } + + close(uevent_netlink_sock); + close(udev_monitor_sock); + exit(1); +} |