Skip to content

Instantly share code, notes, and snippets.

@matrixd
Last active September 26, 2016 00:43
Show Gist options
  • Select an option

  • Save matrixd/b905772f4375da5a09a5cf4059093f7b to your computer and use it in GitHub Desktop.

Select an option

Save matrixd/b905772f4375da5a09a5cf4059093f7b to your computer and use it in GitHub Desktop.
#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