Files
SIC/code/datadifflib/main.c
2023-02-28 09:33:09 +08:00

700 lines
16 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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<strlen(log))
{
if(log[i] == '\n')
{
log[i]=' ';
}
i++;
}
}