From: http://blog.csdn.net/qwyang/article/details/6425555
总体规划:
使用netlink接口向内核注册hotplug事件通知,获取事件通知后进行相关动作如(Action==add)挂载或(action==remove)卸载,使用Socket IPC机制向需要响应USB热拔插事件的应用程序报告。
功能包括:
1、获取usb卷标
2、挂载、卸载usb
3、动态监测usb热拔插事件
4、使用socket向应用程序报告热拔插事件
函数接口说明:
int reportToIplayer(USBEvent event,const char *servername);
向应用程序IPlayer报告热拔插事件
void check();
程序启动开始先检查当前u盘状态(空或者已存在)
int getDevPath(const char *buf,char *path,int size);
从热拔插事件的Diagram消息即buf中获得usb的设备路径存放到path,size为path缓冲大小
int rm_dir(const char *path);
删除挂载时建立的空目录
int make_dir(const char *devPath,const char *dstPath);
挂载钱建立一个空目录dstPath,dstPath为挂载目录
int get_label(const char *dev,char *buf,int size);
获取u盘卷标
int recordDstPath(int no,const char *dstPath);
记录下挂载路径,便于rm_dir查询
int init_hotplug_sock(void);
向内核注册hotplug事件
#include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <sys/un.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <linux/netlink.h> #include <errno.h> #include <sys/stat.h> #include <sys/types.h> #include <dirent.h> #include <stddef.h> typedef struct USBEvent { int event; char path[30]; }USBEvent; int init_hotplug_sock(void) { struct sockaddr_nl snl; const int buffersize = 16*1024*1024; int retval; memset(&snl,0x00,sizeof(struct sockaddr_nl)); snl.nl_family = AF_NETLINK; snl.nl_pid = getpid(); snl.nl_groups = 1; int hotplug_sock = socket(PF_NETLINK,SOCK_DGRAM,NETLINK_KOBJECT_UEVENT); if(hotplug_sock == 1) { printf("error get socket:%s",strerror(errno)); return -1; } /* set receive buffersize */ setsockopt(hotplug_sock,SOL_SOCKET,SO_RCVBUFFORCE,&buffersize,sizeof(buffersize)); retval = bind(hotplug_sock,(struct sockaddr *)&snl,sizeof(struct sockaddr_nl)); if(0>retval) { printf("bind failed:%s",strerror(errno)); close(hotplug_sock); hotplug_sock = -1; return -1; } return hotplug_sock; } char dstPathTable[8][30]; int recordDstPath(int no,const char *dstPath) { if(strlen(dstPath) >= 30 || no>8) { printf("pathname = %s,no = %d",dstPath,no); return -1; } strcpy(dstPathTable[no-1],dstPath); printf("%s has been recorded",dstPathTable[no-1]); return 0; } const char *LABEL = "label_tmp"; void trim(char *buf) { int i = strlen(buf)-1; while(i == '\n' || i == ' ') { --i; printf("true/n"); } buf[i+1] = 0; } int get_label(const char *dev,char *buf,int size) { static int noLabel = 0; int ret,fd; char comm[200] = {0}; sprintf(comm,"vol_id -l %s | sed -n '$p' > %s",dev,LABEL); system(comm); printf("get_label\n"); fd = open(LABEL,O_RDONLY); if(fd == -1) { perror("open in get_label"); goto error; } ret = read(fd,buf,size-1); if(-1 == ret) { perror("read in get_label"); goto error; } close(fd); buf[ret-1] = 0; printf("get_label:%s,%d",buf,strlen(buf)); if(strlen(buf) <= 1) { ++noLabel; sprintf(buf,"usb%d",noLabel); } return 0; error: ++noLabel; sprintf(buf,"use%d",noLabel); return -1; } int make_dir(const char *devPath,const char *dstPath) { mode_t dMode = S_IRWXU|S_IRWXG|S_IRWXO; int ret; int no = devPath[strlen(devPath)-1]-'0'; ret = mkdir(dstPath,dMode); if(ret == -1) { perror("make_dir"); return ret; } return recordDstPath(no,dstPath); } int rm_dir(const char *path) { int no = path[strlen(path)-1]-'0'; printf("rmdir:%s\n",dstPathTable[no-1]); int ret = rmdir(dstPathTable[no-1]); if(ret == -1) perror("rm_dir"); dstPathTable[no-1][0] = 0; return 0; } int getDevPath(const char *buf,char *path,int size) { int i; char tmp[20]; for(i = 1;i <= 8;++i) { sprintf(tmp,"/sdb%d",i); if(strstr(buf,tmp)) { strcpy(path,"/dev"); strcat(path,tmp); printf("getDevPath:%s\n",path); return 0; } } printf("getDevPath:null\n"); path[0] = 0; return -1; } const int ADD_EVENT = 0; const int REMOVE_EVENT = 1; void check() { char devPath[20]; char label[21]; char dstPath[30]; char comm[100]; char tmp[30]; int i,ret; struct stat sb; struct dirent *file; USBEvent event; memset(&event,0,sizeof(event)); for(i = 1;i<9;++i) { sprintf(devPath,"/dev/sdb%d",i); sprintf(comm,"umount %s",devPath); // umount /dev/sdb1-8 system(comm); } DIR *dir = opendir("/media/usb"); while((file = readdir(dir)) != NULL) { sprintf(tmp,"/media/usb/%s",file->d_name); ret = rmdir(tmp); if(0 == ret) printf("%s has been deleted!",tmp); } closedir(dir); for(i = 0;i<9;++i) { sprintf(devPath,O_RDONLY); // what????? if(-1 != ret) { close(ret); printf("%s found\n",devPath); get_label(devPath,label,21); printf(dstPath,"/media/usb/%s",label); make_dir(devPath,dstPath); sprintf(comm,"mount -t auto -o utf8,rw %s %s",devPath,dstPath); ret = system(comm); event.event = ADD_EVENT; strcpy(event.path,dstPath); reportTolplayer(event,"server.socket"); printf("ret:%s\n",ret); } } printf("check exit\n"); } int reportTolplayer(USBEvent event,const char *servername) { const char *CLIENT_PATH = "/tmp/cli"; struct sockaddr_un un; int ret,fd,size,i; unlink(CLIENT_PATH); memset(&un,0,sizeof(un)); un.sun_family = AF_UNIX; sprintf(un.sun_path,"%s%5d",CLIENT_PATH,getpid()); size = offsetof(struct sockaddr_un,sun_path)+strlen(un.sun_path); fd = socket(AF_UNIX,SOCK_STREAM,0); if(-1 == fd) { perror("socket error"); return -1; } unlink(un.sun_path); ret = bind(fd,(struct sockaddr *)&un,size); if(-1 == ret) { perror("bind error"); return -1; } memset(&un,0,sizeof(un)); un.sun_family = AF_UNIX; strcpy(un.sun_path,servername); ret = connect(fd,(struct sockaddr *)&un,size); if(-1 == ret) { perror("connect error"); return -1; } ret = write(fd,&event,sizeof(event)); if(-1 == ret) { perror("write error"); return -1; } ret = close(fd); if(-1 == ret) { perror("close error"); return -1; } } void splitString(char *buf, char *seps) { if(buf && seps) { char *p = buf; p = strtok(buf, seps); while(p) { printf("p=[%s]\n", p); p = strtok(NULL, seps); } printf("\n"); } } int getConsoleOutput(char *command, char *mode, char *out, int maxLen) { FILE *p = popen(command, mode); if(p == NULL) { perror("popen"); return 0; } fread(out, 1, maxLen, p); return ferror(p) == 0; } int main(int argc,char **argv) { char buf[1024] = {0}; char comm[200] = {0}; char dstPath[30] = {0}; char devPath[30] = {0}; char vol[21] = {0}; int hotplug_sock; int sum,size; char *str; USBEvent event; memset(&event,0,sizeof(event)); check(); hotplug_sock = init_hotplug_sock(); while(1) { sum = 0; size = recv(hotplug_sock,buf,sizeof(buf),0); printf("size=%d, buf=[%s], strlen(buf)=%d\n", size, buf, strlen(buf)); while(sum < size) { str = buf + sum; sum += strlen(str); buf[sum] = '\n'; } buf[sum] = 0; //printf("buf=[%s]\n\n", buf); splitString(buf, "\n"); if(strstr(buf,"ACTION=add")) { printf("ACTION=add\n"); if(getDevPath(buf,devPath,30) == 0) { get_label(devPath,vol,21); sprintf(dstPath,"/media/usb/%s",vol); make_dir(devPath,dstPath); sprintf(comm,"mount -t auto -o utf8,rw %s %s",devPath,dstPath); system(comm); event.event = ADD_EVENT; strcpy(event.path,dstPath); reportTolplayer(event,"server.socket"); } } if(strstr(buf,"ACTION=remove")) { printf("ACTION = remove\n"); if(getDevPath(buf,devPath,30) == 0) { sprintf(comm,"umount %s",devPath); system(comm); rm_dir(devPath); event.event = REMOVE_EVENT; reportTolplayer(event,"server.socket"); } } } return 0; }