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;
}