简化版udev, 抓取uevent事件


  • #include <errno.h>2 M4 J( q* I$ J/ C" ^- w
  • #include <stdio.h>
  • #include <stdlib.h>
  • #include <sys/stat.h>
  • #include <sys/types.h>
  • #include <fcntl.h>
  • #include <dirent.h>
  • #include <unistd.h>
  • #include <string.h>
  • #include <sys/socket.h>
  • #include <sys/un.h>
  • #include <linux/netlink.h>
  • //#include <private/android_filesystem_config.h>
  • #include <sys/time.h>
  • #include <asm/page.h>
  • struct uevent {
  •     const char *action;
  •     const char *path;
  •     const char *subsystem;
  •     const char *firmware;
  •     int major;
  •     int minor;
  • };
  • static int open_uevent_socket(void)
  • {
  •     struct sockaddr_nl addr;
  •     int sz = 64*1024; // XXX larger? udev uses
  •     int on = 1;
  •     int s;
  •     memset(&addr, 0, sizeof(addr));
  •     addr.nl_family = AF_NETLINK;
  •     addr.nl_pid = getpid();
  •     addr.nl_groups = 0xffffffff;
  •     s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
  •     if(< 0)
  •         return -1;
  •     setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz));
  •     setsockopt(s, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
  •     if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
  •         close(s);
  •         return -1;
  •     }
  •     return s;
  • }
  • static void parse_event(const char *msg, struct uevent *uevent)
  • {
  • #if 1
  •     uevent->action = "";
  •     uevent->path = "";
  •     uevent->subsystem = "";
  •     uevent->firmware = "";
  •     uevent->major = -1;
  •     uevent->minor = -1;
  •         /* currently ignoring SEQNUM */
  •     while(*msg) {
  •         if(!strncmp(msg, "ACTION=", 7)) {
  •             msg += 7;
  •             uevent->action = msg;
  •         } else if(!strncmp(msg, "DEVPATH=", 8)) {
  •             msg += 8;
  •             uevent->path = msg;
  •         } else if(!strncmp(msg, "SUBSYSTEM=", 10)) {
  •             msg += 10;
  •             uevent->subsystem = msg;
  •         } else if(!strncmp(msg, "FIRMWARE=", 9)) {
  •             msg += 9;
  •             uevent->firmware = msg;
  •         } else if(!strncmp(msg, "MAJOR=", 6)) {
  •             msg += 6;
  •             uevent->major = atoi(msg);
  •         } else if(!strncmp(msg, "MINOR=", 6)) {
  •             msg += 6;
  •             uevent->minor = atoi(msg);
  •         }
  •             /* advance to after the next \*/
  •         while(*msg++)
  •             ;
  •     }
  •     printf("event { '%s', '%s', '%s', '%s', %d, %d }\n",
  •                     uevent->action, uevent->path, uevent->subsystem,
  •                     uevent->firmware, uevent->major, uevent->minor);
  • #endif
  • }
  • #define UEVENT_MSG_LEN 1024
  • void handle_device_fd(int fd)
  • {
  •     printf("enter %s\n", __func__);
  •     for(;;) {
  •         char msg[UEVENT_MSG_LEN+2];
  •         char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
  •         struct iovec iov = {msg, sizeof(msg)};
  •         struct sockaddr_nl snl;
  •         struct msghdr hdr = {&snl, sizeof(snl), &iov, 1, cred_msg, sizeof(cred_msg), 0};
  •         ssize_t n = recvmsg(fd, &hdr, 0);
  •         if (<= 0) {
  •             break;
  •         }
  •         if ((snl.nl_groups != 1) || (snl.nl_pid != 0)) {
  •             /* ignoring non-kernel netlink multicast message */
  •             continue;
  •         }
  •         struct cmsghdr * cmsg = CMSG_FIRSTHDR(&hdr);
  •         if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) {
  •             /* no sender credentials received, ignore message */
  •             continue;
  •         }
  •         struct ucred * cred = (struct ucred *)CMSG_DATA(cmsg);
  •         if (cred->uid != 0) {
  •             /* message from non-root user, ignore */
  •             continue;
  •         }
  •         if(>= UEVENT_MSG_LEN) /* overflow -- discard */
  •             continue;
  •         msg[n] = '\0';
  •         msg[n+1] = '\0';
  •         struct uevent uevent;
  •         parse_event(msg, &uevent);
  •     }
  • }
  • int main(void)
  • {
  •     int fd = 0;
  •     fd = open_uevent_socket();
  •     if (fd < 0) {
  •         printf("error!\n");
  •         return -1;
  •     }
  • //    fcntl(fd, F_SETFD, FD_CLOEXEC);
  • // fcntl(fd, F_SETFL, O_NONBLOCK);
  •     handle_device_fd(fd);
  • }

你可能感兴趣的:(简化版udev, 抓取uevent事件)