Last active
September 26, 2016 00:43
-
-
Save matrixd/b905772f4375da5a09a5cf4059093f7b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <libudev.h> | |
| #include <sys/time.h> | |
| #include <sys/types.h> | |
| #include <unistd.h> | |
| #include <string.h> | |
| #include <signal.h> | |
| #include <sys/mount.h> | |
| #include <sys/stat.h> | |
| #include <unistd.h> | |
| #include <errno.h> | |
| #include <dirent.h> | |
| #include <fcntl.h> | |
| #include <libgen.h> | |
| int runtmp = 1; | |
| int *run = &runtmp; | |
| void handleFinish(int sig) | |
| { | |
| printf("shutting down\n"); | |
| *run = 0; | |
| } | |
| void finish(struct udev *u, struct udev_monitor *umon) | |
| { | |
| udev_monitor_unref(umon); | |
| udev_unref(u); | |
| } | |
| void handleDevice(struct udev_device *dev, const char *src_filename, | |
| const char *src_file) | |
| { | |
| const char *blk_dev_name = udev_device_get_property_value(dev, "DEVNAME"); | |
| if (blk_dev_name == NULL) | |
| { | |
| fprintf(stderr, "can't get DEVNAME\n"); | |
| return; | |
| } | |
| const char *mount_point = "/tmp/customdev"; | |
| const char *fs = "vfat"; | |
| unsigned long flags = MS_RELATIME | MS_NODEV | MS_NOSUID; | |
| int ret = mkdir(mount_point, 0); | |
| if (ret != 0 && errno != EEXIST) | |
| { | |
| perror("mkdir"); | |
| return; | |
| } | |
| ret = mount(blk_dev_name, mount_point, fs, flags, NULL); | |
| if (ret != 0) | |
| { | |
| perror("mount"); | |
| return; | |
| } | |
| chdir(mount_point); | |
| DIR *d = opendir("."); | |
| struct dirent *dir; | |
| if (d) | |
| { | |
| while ((dir = readdir(d)) != NULL) | |
| { | |
| if (dir->d_type != DT_DIR && dir->d_type != DT_CHR && | |
| dir->d_type != DT_BLK) | |
| { | |
| printf("deleting %s\n", dir->d_name); | |
| unlink(dir->d_name); | |
| } | |
| } | |
| closedir(d); | |
| } | |
| int src = open(src_file, O_RDONLY); | |
| int dest = creat(src_filename, 0); | |
| if (src < 0) | |
| { | |
| perror("open source file"); | |
| } | |
| else if(dest < 0) | |
| { | |
| perror("open destination file"); | |
| } | |
| else | |
| { | |
| char buf[8192]; | |
| ssize_t result = 1; | |
| while(result) | |
| { | |
| result = read(src, buf, sizeof(buf)); | |
| if (result > 0) | |
| { | |
| if (write(dest, buf, result) != result) | |
| { | |
| perror("i/o error"); | |
| break; | |
| } | |
| } | |
| } | |
| } | |
| close(src); | |
| close(dest); | |
| chdir("/"); | |
| //TODO sync | |
| umount(mount_point); | |
| } | |
| int check_action(struct udev_device *dev, const char *action) | |
| { | |
| int ret = 1; | |
| const char *devaction = udev_device_get_action(dev); | |
| if ((devaction != NULL) && (strcmp(devaction, action) == 0)) | |
| ret = 0; | |
| return ret; | |
| } | |
| int check_vid_pid(struct udev_device *dev, const char *vid, const char *pid) | |
| { | |
| int ret = 1; | |
| const char *vendor = udev_device_get_property_value(dev, "ID_VENDOR_ID"); | |
| const char *model = udev_device_get_property_value(dev, "ID_MODEL_ID"); | |
| if ((vendor != NULL) && (model != NULL)) | |
| { | |
| printf("%s:%s\n", vendor, model); | |
| if (strcmp(vendor, vid) == 0 &&\ | |
| strcmp(model, pid) == 0) | |
| { | |
| printf("it'syour device\n"); | |
| ret = 0; | |
| } | |
| } | |
| return ret; | |
| } | |
| int main(int argc, char *argv[]) | |
| { | |
| char src_file[2048]; | |
| char *src_filename; | |
| if (argc == 2) | |
| { | |
| char buf[1790]; | |
| getcwd(buf, sizeof(buf)); | |
| sprintf(src_file, "%s/%s", buf, argv[1]); | |
| src_filename = basename(argv[1]); | |
| printf("name: %s\n", src_filename); | |
| printf("path: %s\n", src_file); | |
| } | |
| else | |
| { | |
| fprintf(stderr, "worng arguments, pass file as argument\n"); | |
| exit(1); | |
| } | |
| struct udev *ud = udev_new(); | |
| struct udev_monitor *umon = udev_monitor_new_from_netlink(ud, "udev"); | |
| const char *sys = "block"; | |
| const char *devtype = "disk"; | |
| int ret = udev_monitor_filter_add_match_subsystem_devtype(umon, sys, devtype); | |
| if (ret != 0) | |
| { | |
| perror("filter"); | |
| finish(ud, umon); | |
| exit(1); | |
| } | |
| ret = udev_monitor_enable_receiving(umon); | |
| if (ret != 0) | |
| { | |
| perror("receiving"); | |
| finish(ud, umon); | |
| exit(1); | |
| } | |
| int fd = udev_monitor_get_fd(umon); | |
| signal(SIGTERM, handleFinish); | |
| signal(SIGINT, handleFinish); | |
| while(*run) | |
| { | |
| fd_set fds; | |
| struct timeval tv; | |
| int ret; | |
| FD_ZERO(&fds); | |
| FD_SET(fd, &fds); | |
| tv.tv_sec = 1; | |
| tv.tv_usec = 0; | |
| ret = select(fd+1, &fds, NULL, NULL, &tv); | |
| if (ret > 0 && FD_ISSET(fd, &fds)) | |
| { | |
| struct udev_device *dev = udev_monitor_receive_device(umon); | |
| if (dev) | |
| { | |
| if (check_vid_pid(dev, "04cc", "0003") == 0) | |
| { | |
| if (check_action(dev, "add") == 0) | |
| { | |
| printf("new device\n"); | |
| handleDevice(dev, src_filename, src_file); | |
| } | |
| else if (check_action(dev, "remove") == 0) | |
| { | |
| printf("\033[2J"); // Clear screen | |
| printf("device has been removed\n"); | |
| } | |
| } | |
| udev_device_unref(dev); | |
| } | |
| } | |
| } | |
| finish(ud, umon); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment