#include <stdio.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <asm/types.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>

struct rtnl_handle
{
        int fd;
        struct sockaddr_nl  local;
        struct sockaddr_nl  peer;
         __u32 seq;
        __u32  dump;
};

#define ADD_STR "add@/block/sd"
#define REMOVE_STR "remove@/block/sd"

int main(int argc, char** argv)
{
    int addr_len;

    int fd = socket(AF_NETLINK, SOCK_DGRAM, 15);
    if (fd < 0) {
        perror("cannot open netlink socket");
        return -1;
    }

    struct sockaddr_nl local;
    memset(&local, 0, sizeof(local));
    local.nl_family = AF_NETLINK;
    local.nl_pid = getpid();
    local.nl_groups = 1;

    if (bind(fd, (struct sockaddr*)&local, sizeof(local)) < 0)
    {
        perror("cannot bind netlink socket");
        return -1;
    }

    fd_set fds;
    struct timeval tv;
    char buffer[1024];
    int fd_sd[26];

    for (;;) {
        FD_ZERO (&fds);
        FD_SET (fd, &fds);
        tv.tv_sec = 0;
        tv.tv_usec = 100000;
        while ((select(fd + 1, &fds, NULL, NULL, &tv)) > 0) {

        int i = read(fd, buffer, sizeof(buffer));
        printf("READ: %d bytes\n", i);
        buffer[i] = 0;
        printf("%s\n", buffer);
        if ((strlen(buffer) == strlen(ADD_STR) + 1) && (!strncmp(buffer, ADD_STR, strlen(ADD_STR)))) {
            char dev = buffer[strlen(ADD_STR)];
            int dev_idx = dev - 'a';
            char dev_path[64];
            sprintf(dev_path, "/dev/sd%c", dev);
            printf("***** OPEN %s\n", dev_path);
            fd_sd[dev_idx] = open(dev_path, O_RDONLY, O_NONBLOCK);
        }
        if ((strlen(buffer) == strlen(REMOVE_STR) + 1) && (!strncmp(buffer, REMOVE_STR, strlen(REMOVE_STR)))) {
            char dev = buffer[strlen(REMOVE_STR)];
            int dev_idx = dev - 'a';
            printf("***** CLOSE /dev/sd%c\n", dev);
            close(fd_sd[dev_idx]);
        }

        }
    }

    return 0;
}
