#include "scan.h" /* 主函数 * * * */ //#define PRINT_TEST int main(int argc, const char *argv[]) { /*****************获取数据库*********************************************/ struct isoinfo iso;//镜像信息结构体 char content[1024]; memset(content,0,sizeof(content)); if(get_iso_info(&iso)!=0)//获取当前系统id { sprintf(content,"iso|2|iso_name:%s|镜像在数据库中未找到",iso.name); } else { sprintf(content,"iso|1|iso_name:%s|iso_version:%s|iso_md5:%s|iso_id:%d|iso_issue=%s",iso.name,iso.version,iso.md5,iso.id,iso.issue); } put_diff_log(content); /******************获取镜像信息*****************************************/ FILE *fp; char now_name[256]; struct pkginfo now_pkg,data_pkg; struct fileinfo now_file,data_file; struct datalib file_list; //获取当前系统安装包列表 if ((fp = fopen(PKGLIST,"r")) == NULL) { printf("can't open PKGLIST\n"); return 0; } int progress_i=0,progress_j=0,progress_sum=0,progress_sleep=0; char progress_bar[101]={0}; if ( argc >=2 ) { progress_sleep=atoi(argv[1]); } //每读取一条,便在数据库中搜索该安装包是否存在。 while(fgets(now_name,255,fp) != NULL) { /***********************读取当前安装包列表*******************************/ get_now_pkg(now_name,&now_pkg); if ( argc >= 3 ) { progress_sum=atoi(argv[2]); progress_j=progress_i*100/progress_sum; printf("[%-100s] [%s] [%d%%]\n",progress_bar,now_pkg.name,progress_j); fflush(stdout); progress_bar[progress_j]='#'; progress_i++; } /***************************打印对比进度********************************/ memset(content,0,sizeof(content)); if(get_pkg_info(&iso,&now_pkg,&data_pkg,FROM_NOWISO) == 0) { sprintf(content,"pkg|1|name:%s|version:%s|md5:%s",data_pkg.name,data_pkg.version,data_pkg.md5); put_diff_log(content); //安装包是默认安装 } else if(get_pkg_info(&iso,&now_pkg,&data_pkg,FROM_DATALIB) == 0) { sprintf(content,"pkg|2|name:%s|version:%s|md5:%s",data_pkg.name,data_pkg.version,data_pkg.md5); put_diff_log(content); //安装包在数据库中存在 } else { sprintf(content,"pkg|3|name:%s|version:%s",now_pkg.name,now_pkg.version); put_diff_log(content); continue; //安装包在数据库不存在 } /**************根据当前安装包列表搜索数据库中该安装包是否存在*************/ get_datafile_list(data_pkg,&data_file,&file_list); //获取安装包文件列表 int i=0; for(i=file_list.ncolumn;i<((file_list.nrow+1)*file_list.ncolumn);i=i+file_list.ncolumn) { memset(&data_file,0,sizeof(data_file)); memset(&now_file,0,sizeof(now_file)); get_datafile_info(i,&file_list,&data_file); //获取数据库中该安装包文件信息 if(get_nowfile_info(&now_file,&data_file) == -1) { //文件在当前系统不存在 memset(content,0,sizeof(content)); sprintf(content,"file|3|name@@%s|type@@%s|md5@@%s|permis@@%s|owner@@%d|genus@@%d|acl@@%s|capable@@%s|mac@@%s|"\ ,data_file.pathname,data_file.type,data_file.md5,data_file.permis,data_file.owner,data_file.genus\ ,data_file.acl,data_file.capable,data_file.mac); clean_n(content); put_diff_log(content); continue; } //获取当前系统中该文件信息 diff_file_info(now_file,data_file); //对比数据库中与当前系统中文件信息的差异 usleep(progress_sleep); //对程序性能进行限制 } sqlite3_free_table(file_list.db_result); } /**************对比当前安装包列表文件信息是否正常*************/ fclose(fp); return 0; } /* * 功能 根据当前检测系统来获取当前镜像信息,获取依据为本系统的/etc/issue文件。 * 输入 镜像信息结构体 * 输出 正确返回镜像id 错误返回 -1 */ int get_iso_info(struct isoinfo *iso) { FILE *fp; int i = 0; //获取当前系统版本 if ((fp = fopen("/etc/issue","r")) == NULL) { printf("can't open /etc/issue\n"); return -1; } char c; memset(iso->issue,0,sizeof(iso->issue)); while( (c=getc(fp)) != EOF) { if(c != '\n') { iso->issue[i] = c; } else { iso->issue[i] = ' '; } i++; } // printf("%s\n",iso->issue); //获取数据库product表中的系统版本 和镜像id sqlite3 *db; int ret = 0; ret = sqlite3_open(DATALIB,&db); if(ret != SQLITE_OK) { printf("open database error : %s\n",sqlite3_errmsg(db)); sqlite3_close(db); return -1; } /*获取数据库*/ int nrow,ncolumn; char ** db_result; ret = 0; char select_query[1024]; iso->issue[strlen(iso->issue)-1]=0; sprintf(select_query,"select product_id,product_name,product_version,product_md5 from product where product_issue=\"%s\";",iso->issue); ret = sqlite3_get_table(db,select_query,&db_result,&nrow,&ncolumn,NULL); if(ret != SQLITE_OK) { printf("openside database error : %s\n",sqlite3_errmsg(db)); sqlite3_close(db); return -1; } if(nrow < 1) { printf("未找到该镜像\n"); sqlite3_close(db); return -2; } for(i=ncolumn;i<(nrow+1)*ncolumn;i=i+ncolumn) { iso->id=atoi(db_result[i]); strcpy(iso->name,db_result[i+1]); strcpy(iso->version,db_result[i+2]); strcpy(iso->md5,db_result[i+3]); } sqlite3_close(db); fclose(fp); sqlite3_free_table(db_result); return 0; } /* * 功能 对pkglist文件读取出的数据进行处理,输入到当前安装包信息结构体中。 * * 输入 获取到的安装包名 当前安装包结构体 * 输出 正确返回0 */ int get_now_pkg(char *now_name,struct pkginfo *now_pkg) { //获取当前系统安装包名 int a=0; int b=0; while(now_name[a] != '\n') { if(now_name[a] != ' ') { now_pkg->name[a] = now_name[a]; a++; } else { now_pkg->name[a] = '\0'; a++; break; } } //获取当前系统安装包版本 while(now_name[a] != '\n') { now_pkg->version[b] = now_name[a]; a++; b++; } now_pkg->version[b] = '\0'; return 0; } /* * 功能 根据标志位,获取数据库中安装包信息。 * 标志位 * FROM_PKGID:根据安装包id获取安装包信息 * FROM_NOWISO:根据安装包和安装包版本在当前产品默认安装包的包列表中查找 * FROM_DATALIB:根据安装包名和安装包版本遍历整个数据库 * * 输入 镜像信息结构体 当前安装包信息结构体 数据库安装包信息结构体 获取标志位 * 输出 正确返回镜像id 错误返回 -1 */ int get_pkg_info(struct isoinfo *iso,struct pkginfo *now_pkg,struct pkginfo *data_pkg,int statu) { sqlite3 *db; int ret = 0; ret = sqlite3_open(DATALIB,&db); if(ret != SQLITE_OK) { printf("open database error : %s\n",sqlite3_errmsg(db)); sqlite3_close(db); return -1; } /*获取数据库*/ int nrow,ncolumn; char ** db_result; ret = 0; char select_query[2048]; switch (statu) { case FROM_PKGID: //根据安装包id获取安装包信息 sprintf(select_query,"select pkg_name,pkg_version,pkg_id,pkg_md5 from pkg where pkg_id = %d;",now_pkg->id); break; case FROM_NOWISO: //根据安装包和安装包版本在当前产品默认安装包的包列表中查找 sprintf(select_query,"select pkg.pkg_name,pkg.pkg_version,pkg.pkg_id,pkg.pkg_md5 from product_and_pkg,pkg where product_id=%d and pkg.pkg_name=\"%s\" and pkg.pkg_version=\"%s\" and product_and_pkg.pkg_id=pkg.pkg_id;",iso->id,now_pkg->name,now_pkg->version); break; case FROM_DATALIB: //根据安装包名和安装包版本遍历整个数据库 sprintf(select_query,"select pkg.pkg_name,pkg.pkg_version,pkg.pkg_id,pkg.pkg_md5 from pkg where pkg_name=\"%s\" and pkg_version=\"%s\" ;",now_pkg->name,now_pkg->version); break; } //printf("%s\n",select_query); ret = sqlite3_get_table(db,select_query,&db_result,&nrow,&ncolumn,NULL); if(ret != SQLITE_OK) { printf("未发现当前安装包信息\n"); printf("openside database error : %s\n",sqlite3_errmsg(db)); sqlite3_close(db); return -1; } if(nrow != 0) { strcpy(data_pkg->name,db_result[4]); strcpy(data_pkg->version,db_result[5]); data_pkg->id=atoi(db_result[6]); strcpy(data_pkg->md5,db_result[7]); #ifdef PRINT_TEST printf("pkg_name:%s pkg_version:%s pkg_id:%s pkg_md5:%s\n ",db_result[4],db_result[5],db_result[6],db_result[7]); #endif sqlite3_close(db); sqlite3_free_table(db_result); return 0; } else { sqlite3_close(db); sqlite3_free_table(db_result); return -2; } } /* * 功能 根据安装包信息,获取数据库中该安装包的文件列表 * * 输入 数据库安装包信息结构体 数据库文件信息结构体 * 输出 正确返回0 错误返回-1 */ int get_datafile_list(struct pkginfo data_pkg,struct fileinfo *data_file,struct datalib *file_list) { int ret = 0; char select_query[2048]; sqlite3 *db; ret = sqlite3_open(DATALIB,&db); if(ret != SQLITE_OK) { printf("open database error : %s\n",sqlite3_errmsg(db)); sqlite3_close(db); return -1; } /*获取数据库*/ sprintf(select_query,"select file_id,file_name,file_pathname,file_md5,file_type,file_owner,file_genus,file_permis,file_size,file_acl,file_capable,file_level,file_mac from file where pkg_id=%d;",data_pkg.id); //根据安装包id获取其对应文件的信息 ret = sqlite3_get_table(db,select_query,&file_list->db_result,&file_list->nrow,&file_list->ncolumn,NULL); if(ret != SQLITE_OK) { printf("未发现当前安装包信息\n"); printf("openside database error : %s\n",sqlite3_errmsg(db)); sqlite3_close(db); return -1; } sqlite3_close(db); return 0; } /* 将获取的文件信息转入到文件信息结构体中 * * 输入 获取列表中第几个文件 安装包文件列表信息结构体 文件信息结构体 * 输出 无 * */ void get_datafile_info(int i,struct datalib *file_list,struct fileinfo *data_file) { data_file->id=atoi(file_list->db_result[i]); strcpy(data_file->name,file_list->db_result[i+1]); strcpy(data_file->pathname,file_list->db_result[i+2]); strcpy(data_file->md5,file_list->db_result[i+3]); strcpy(data_file->type,file_list->db_result[i+4]); data_file->owner=atoi(file_list->db_result[i+5]); data_file->genus=atoi(file_list->db_result[i+6]); strcpy(data_file->permis,file_list->db_result[i+7]); data_file->size=atoi(file_list->db_result[i+8]); strcpy(data_file->acl,file_list->db_result[i+9]); strcpy(data_file->capable,file_list->db_result[i+10]); strcpy(data_file->level,file_list->db_result[i+11]); strcpy(data_file->mac,file_list->db_result[i+12]); #ifdef PRINT_TEST printf("file_name=%s\n",data_file->name); #endif } /* 获取当期系统的具体文件信息 * * 输入 当前文件信息结构体 数据库文件信息结构体 * 输出 获取正常返回0 错误返回-1 * */ int get_nowfile_info( struct fileinfo *now_file,struct fileinfo *data_file ) { struct stat filestat; strcpy(now_file->name,data_file->name); strcpy(now_file->pathname,data_file->pathname); if(lstat(now_file->pathname,&filestat) < 0) { printf("cannot access the file %s\n",now_file->pathname); perror("error : "); return -1; } strcpy(now_file->md5,"");//清除now_file->md5 //获取文件类型 switch(filestat.st_mode & S_IFMT){ case S_IFDIR : sprintf(now_file->type,"d"); break; case S_IFBLK : sprintf(now_file->type,"b"); //获取文件md5值 get_file_md5(now_file->pathname,now_file->md5); break; case S_IFSOCK : sprintf(now_file->type,"s"); //获取文件md5值 get_file_md5(now_file->pathname,now_file->md5); break; case S_IFLNK : sprintf(now_file->type,"l"); break; case S_IFREG : sprintf(now_file->type,"-"); //获取文件md5值 get_file_md5(now_file->pathname,now_file->md5); break; case S_IFCHR : sprintf(now_file->type,"c"); break; case S_IFIFO : sprintf(now_file->type,"p"); break; } //获取文件大小 now_file->size = filestat.st_size; //获取文件权限 sprintf(now_file->permis,"%o",(filestat.st_mode&S_ISUGV)+(filestat.st_mode&S_IRWXU)+(filestat.st_mode&S_IRWXG)+(filestat.st_mode&S_IRWXO)); //获取文件属主 now_file->owner=filestat.st_uid; //获取文件属组 now_file->genus=filestat.st_gid; //获取文件acl get_acl(now_file); //获取文件capable get_cap(now_file); //获取文件mac get_mac(now_file); //获取文件level //now_file->level=NULL; return 0 ; } /* 对比当前文件信息和数据库中文件信息的差异 * * 输入 当前文件信息结构体 数据库文件信息结构体 * 输出 正确返回0 * */ int diff_file_info(struct fileinfo now_file,struct fileinfo data_file) { char content[9][512]={{0}}; char log[1024]={0}; int status=1; sprintf(content[0],"name@%s",now_file.pathname); if(strcmp(now_file.type,data_file.type) != 0) { sprintf(content[1],"type@%s@%s",now_file.type,data_file.type); status=2; } if(now_file.type[0] != 'l')//如果文件类型为链接文件,则不需要比较md5值 { if(strcmp(now_file.md5,data_file.md5) != 0) { sprintf(content[2],"md5@%s@%s",now_file.md5,data_file.md5); status=2; } } if(strcmp(now_file.permis,data_file.permis) != 0) { sprintf(content[3],"permis@%s@%s",now_file.permis,data_file.permis); status=2; } if(now_file.owner != data_file.owner) { sprintf(content[4],"owner@%d@%d",now_file.owner,data_file.owner); status=2; } if(now_file.genus != data_file.genus) { sprintf(content[5],"genus@%d@%d",now_file.genus,data_file.genus); status=2; } if(strcmp(now_file.acl,data_file.acl) != 0) { sprintf(content[6],"acl@%s@%s",now_file.acl,data_file.acl); status=2; } if(strcmp(now_file.capable,data_file.capable) != 0) { sprintf(content[7],"capable@%s@%s",now_file.capable,data_file.capable); status=2; } if(strcmp(now_file.mac,data_file.mac) != 0) { sprintf(content[8],"mac@%s@%s",now_file.mac,data_file.mac); status=2; } sprintf(log,"file|%d|%s|%s|%s|%s|%s|%s|%s|%s|%s|",status,content[0],content[1],content[2],content[3],content[4],content[5],content[6],content[7],content[8]); clean_n(log); put_diff_log(log); return 0 ; } /* 打印信息到记录日志 * * 输入 需要打印的信息指针 * 输出 正确返回0 失败返回-1 */ int put_diff_log(char *content) { FILE *fp=NULL; if ((fp = fopen(FILEDIFF,"a")) == NULL) { perror("can't open FILEDIFF:"); return -1; } fputs(content,fp); putc('\n',fp); fflush(fp); fclose(fp); return 0; } /* 获取shell指令的输出 * * 输入 shell指令指针 输出信息指针 输出信息的大小 * 输出 正确返回0 错误返回-1 */ int myshell(char *command,char *buff,int num) { FILE *fp; if ((fp=popen(command,"r")) == NULL) { perror("popen fp error"); return -1; } fread(buff,sizeof(char),num,fp); if (pclose(fp) == -1) { perror("pclose fp error"); return -2; } return 0; } /* 获取文件acl * * 将根据当前结构提中文件名获取该文件的acl并存储到结构体中 * * 输入 文件信息结构体 * 输出 无返回 */ void get_acl(struct fileinfo *now_file) { memset(now_file->acl,0,sizeof(now_file->acl)); if ( now_file->type[0] == 'c' || now_file->type[0] == 'p' || now_file->type[0] == 'l') return ; char command[1024]={0}; sprintf(command,"getfacl --absolute-name \"%s\" 2>&1",now_file->pathname); myshell(command,now_file->acl,sizeof(now_file->acl)); now_file->acl[strlen(now_file->acl)-2]='\0'; } /* 获取文件mac * * 将根据当前结构提中文件名获取该文件的mac并存储到结构体中 * * 输入 文件信息结构体 * 输出 无返回 */ void get_mac(struct fileinfo *now_file) { memset(now_file->mac,0,sizeof(now_file->mac)); if ( now_file->type[0] == 'c' || now_file->type[0] == 'p' || now_file->type[0] == 'l') return ; char command[1024]={0}; sprintf(command,"getfmac \"%s\" 2>/dev/null",now_file->pathname); myshell(command,now_file->mac,sizeof(now_file->mac)); now_file->mac[strlen(now_file->mac)-1]='\0'; } /* 获取文件cap * * 将根据当前结构提中文件名获取该文件的cap并存储到结构体中 * * 输入 文件信息结构体 * 输出 无返回 */ void get_cap(struct fileinfo *now_file) { memset(now_file->capable,0,sizeof(now_file->capable)); if ( now_file->type[0] == 'c' || now_file->type[0] == 'p' || now_file->type[0] == 'l') return ; char command[1024]={0}; sprintf(command,"getcap \"%s\" 2>/dev/null",now_file->pathname); myshell(command,now_file->capable,sizeof(now_file->capable)); now_file->capable[strlen(now_file->capable)-1]='\0'; } void clean_n(char *log){ int i=0; while(i