扫描文件或文件夹的元数据,放入数组结构
/*
* brief: 扫描文件夹的所有文件或单文件元数据,放入pdir_metedata,如果是文件则pdir长度只有1
* param: parray传入外部空指针。 scan_dir传入文件夹路径。
* return: 返回true代表获取成功,否则失败。
*/
bool get_dir_metedata(GPtrArray** pdir_metedata, const pchar scan_dir, int* pstop_flag,
PSCANING_INFO pscaning_info, const pchar prefix_path)
{
log_info(__FILE__, __LINE__, "get_dir_metedata begin dir :%s\n", scan_dir);
struct stat filestat;
char dir[MAX_PATH] = {0};
uint ulen = strlen(scan_dir);
memcpy(dir, scan_dir, ulen > MAX_PATH ? MAX_PATH : ulen);
int ret = lstat(scan_dir, &filestat);
if (ret == -1)
{
log_debug(__FILE__,__LINE__," get_dir_metedata(const pchar scan_dir){ ret = %d \n",ret);
return false;
}
//*pdir_metedata = g_ptr_array_sized_new(1);
*pdir_metedata = g_ptr_array_new_full(1, g_free);
if (S_ISDIR(filestat.st_mode))
{
append_slash(dir);
log_debug(__FILE__, __LINE__, "4 scan_dir : %s \n",dir);
//uint ufiles_count = count_files(dir);
get_parent_metedata(pdir_metedata, dir, pscaning_info, prefix_path);
scan_folder_metedata(*pdir_metedata, dir, pstop_flag, pscaning_info);
}
else
{
get_parent_metedata(pdir_metedata, scan_dir, pscaning_info, prefix_path);
}
log_debug(__FILE__, __LINE__, " scan_dir %s files count:%d\n", dir, (*pdir_metedata)->len);
log_debug(__FILE__, __LINE__, " get_dir_metedata(%s) is over\n", scan_dir);
return true;
}
/*
* brief: 扫描指定路径,将文件元数据放入 pdir_metedata中
* param: path传入路径
*/
void scan_folder_metedata(GPtrArray* pdir_metedata, const pchar path,int *pstop_flag, PSCANING_INFO pscaning_info)
{
if (pscaning_info == NULL)
log_info(__FILE__, __LINE__, " scan_folder_metedata pscaning_info is null, no product info");
if (pstop_flag != NULL && *pstop_flag)
{
log_debug(__FILE__, __LINE__, " scan_folder_metedata stop through *pstop_flag");
return;
}
if (!pdir_metedata)
{
log_error(__FILE__, __LINE__, " scan_folder pdir_metedata is null");
return;
}
DIR *dir;
struct dirent *entry;
log_info(__FILE__, __LINE__, "scan_folder : %s\n", path);
if (!(dir = opendir(path)))
{
log_error(__FILE__, __LINE__, "Cannot open directory: %s\n", path);
return;
}
while ((entry = readdir(dir)) != NULL)
{
if (pstop_flag != NULL && *pstop_flag)
{
log_debug(__FILE__, __LINE__, " scan_folder_metedata while ((entry = readdir(dir)) != NULL) stop through *pstop_flag");
return;
}
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
log_info(__FILE__, __LINE__, "scan_folder entry->d_name : %s\n", entry->d_name);
PFILE_METEDATA pfile_metedata = malloc(sizeof(FILE_METEDATA));
memset(pfile_metedata, 0, sizeof(FILE_METEDATA));
char file_name[MAX_PATH] = {0};
sprintf_s(file_name, MAX_PATH, "%s%s", path,entry->d_name);
/*file_metedata->p_file_name = malloc(strlen(file_name) + 1);//+1是因为可能会补一下'/'符号
memset(file_metedata->p_file_name, 0, strlen(file_name) + 1);*/
struct stat stat_info;
//memcpy(file_metedata->p_file_name, file_name, strlen(file_name));
memcpy(pfile_metedata->file_name, file_name, strlen(file_name));
int ret = lstat(pfile_metedata->file_name, &stat_info);
if (ret != -1)
{
pfile_metedata->file_stat = stat_info;
if (pscaning_info)
{
pscaning_info->utotal_size += pfile_metedata->file_stat.st_size;
pscaning_info->ufile_counts++;
log_debug(__FILE__, __LINE__, "scan_folder cursize:%u totalsize:%u file_counts:%u",
pfile_metedata->file_stat.st_size, pscaning_info->utotal_size, pscaning_info->ufile_counts);
}
if (S_ISDIR(stat_info.st_mode))
{
append_slash(pfile_metedata->file_name);
pfile_metedata->cfile_type = ZTYPE_IS_DIR;
log_debug(__FILE__, __LINE__, "scan_folder Directory: %s\n", pfile_metedata->file_name);
g_ptr_array_add(pdir_metedata, (gpointer)pfile_metedata);
scan_folder_metedata(pdir_metedata, pfile_metedata->file_name, pstop_flag, pscaning_info);
}
else
{
if (S_ISBLK(stat_info.st_mode))
pfile_metedata->cfile_type = ZTYPE_IS_BLOCK_DEV;
else if(S_ISCHR(stat_info.st_mode))
pfile_metedata->cfile_type = ZTYPE_IS_C_DEV;
else if (S_ISLNK(stat_info.st_mode))
pfile_metedata->cfile_type = ZTYPE_IS_LINK;
else if (S_ISFIFO(stat_info.st_mode))
pfile_metedata->cfile_type = ZTYPE_IS_FIFO;
else if (S_ISSOCK(stat_info.st_mode))
pfile_metedata->cfile_type = ZTYPE_IS_SOCK;
else
pfile_metedata->cfile_type = ZTYPE_IS_FILE;
//char pmd5[MD5_LENGTH] = {0};
//get_file_md5sum(pfile_metedata->file_name, pmd5);
//md5_to_half(pmd5, pfile_metedata->file_md5);
//log_debug(__FILE__, __LINE__, "scan_folder File: %s md5:%s half_md5:%u\n"
//, pfile_metedata->file_name, pmd5, pfile_metedata->file_md5);
log_debug(__FILE__, __LINE__, "scan_folder File: %s\n", pfile_metedata->file_name);
g_ptr_array_add(pdir_metedata, (gpointer)pfile_metedata);
}
}
else
log_error(__FILE__, __LINE__, " stat filename = %s is error", pfile_metedata->file_name);
log_info(__FILE__,__LINE__,"scan_folder file_metedata->file_name : %s\n", pfile_metedata->file_name);
}
closedir(dir);
}
/*
* brief: 将文件或目录的filestat属性 加入 pdir_metedata数组。
* param: pdir_metedata 返回的ptr数组,scan_dir 目录或文件,pscaning_info 扫描过程中产生的数据,filestat 外部已经获得的filestat
*/
void add_to_ptrarray(GPtrArray** pdir_metedata, const pchar scan_dir, PSCANING_INFO pscaning_info, struct stat* filestat)
{
PFILE_METEDATA pfile_metedata = malloc(sizeof(FILE_METEDATA));
memset(pfile_metedata, 0, sizeof(FILE_METEDATA));
memcpy(pfile_metedata->file_name, scan_dir, strlen(scan_dir));
pfile_metedata->file_stat = *filestat;
if (S_ISBLK(filestat->st_mode))
pfile_metedata->cfile_type = ZTYPE_IS_BLOCK_DEV;
else if(S_ISCHR(filestat->st_mode))
pfile_metedata->cfile_type = ZTYPE_IS_C_DEV;
else if (S_ISLNK(filestat->st_mode))
pfile_metedata->cfile_type = ZTYPE_IS_LINK;
else if (S_ISDIR(filestat->st_mode))
pfile_metedata->cfile_type = ZTYPE_IS_DIR;
else if (S_ISSOCK(filestat->st_mode))
pfile_metedata->cfile_type = ZTYPE_IS_SOCK;
else if (S_ISFIFO(filestat->st_mode))
pfile_metedata->cfile_type = ZTYPE_IS_FIFO;
else
pfile_metedata->cfile_type = ZTYPE_IS_FILE;
if (pscaning_info)
{
pscaning_info->utotal_size += pfile_metedata->file_stat.st_size;
pscaning_info->ufile_counts++;
log_debug(__FILE__, __LINE__, "get_dir_metedata cursize:%u totalsize:%u",
pfile_metedata->file_stat.st_size, pscaning_info->utotal_size);
}
g_ptr_array_add(*pdir_metedata, (gpointer)pfile_metedata);
}
/*
* brief: 获取所有父目录的metedata,除了/。该方法不提供外部使用,需要的话自行封一个
* param: pdir_metedata 返回的ptr数组,scan_dir 目录或文件,pscaning_info 扫描过程中产生的数据
*/
void get_parent_metedata(GPtrArray** pdir_metedata, const pchar scan_dir, PSCANING_INFO pscaning_info, const pchar prefix_path)
{
struct stat st;
char parent[MAX_PATH] = {0};
strcpy(parent, scan_dir);
char prefix_temp[MAX_PATH] = {0};
if (prefix_path)
strcpy(prefix_temp, prefix_path);
// 反复直到到达根目录
while (lstat(parent, &st) != -1 && st.st_ino != 2 && (strcmp(parent, "/") != 0 && strcmp(parent, prefix_temp) != 0))
{
add_to_ptrarray(pdir_metedata, parent, pscaning_info, &st);
// 获取上一级目录
char tmp[MAX_PATH] = {0};
strcpy(tmp, dirname(parent));
strcpy(parent, tmp);
append_slash(parent);
}
}
/*
* brief: 扫描文件的元数据,放入pdir_metedata
* param: file_name传入文件路径,pfile_metedata由外部申请,是一个回参
* return: 返回true代表获取成功,否则失败。
*/
bool get_file_metedata(const pchar file_name, PFILE_METEDATA pfile_metedata, bool is_md5)
{
log_debug(__FILE__, __LINE__, "%s\n", file_name);
struct stat filestat;
int ret = lstat(file_name, &filestat);
if (ret == -1)
{
log_debug(__FILE__,__LINE__," stat(file_name, &filestat); ret = %d,%s\n",ret, strerror(errno));
return false;
}
strcpy_s(pfile_metedata->file_name, MAX_PATH, file_name);
pfile_metedata->file_stat = filestat;
if (S_ISDIR(filestat.st_mode))
pfile_metedata->cfile_type = ZTYPE_IS_DIR;
else if (S_ISBLK(filestat.st_mode))
pfile_metedata->cfile_type = ZTYPE_IS_BLOCK_DEV;
else if(S_ISCHR(filestat.st_mode))
pfile_metedata->cfile_type = ZTYPE_IS_C_DEV;
else if (S_ISLNK(filestat.st_mode))
pfile_metedata->cfile_type = ZTYPE_IS_LINK;
else if (S_ISSOCK(filestat.st_mode))
pfile_metedata->cfile_type = ZTYPE_IS_SOCK;
else if (S_ISFIFO(filestat.st_mode))
pfile_metedata->cfile_type = ZTYPE_IS_FIFO;
else
pfile_metedata->cfile_type = ZTYPE_IS_FILE;
if(is_md5 == true)
{
/*
char pmd5[MD5_LENGTH] = {0};
get_file_md5sum(pfile_metedata->file_name, pmd5);
md5_to_half(pmd5, pfile_metedata->file_md5);
log_debug(__FILE__, __LINE__, "scan_folder File: %s md5:%s half_md5:%u"
, pfile_metedata->file_name, pmd5, pfile_metedata->file_md5);
*/
char a_md5[MD5_MIN_SIZE * 2 + 1] = {0};
//calculate_file_md5(pfile_metedata->file_name, pfile_metedata->file_md5);
boost_get_md5(g_hash_table, pfile_metedata, "get_file_metedata");
get_md5_format(&pfile_metedata->file_md5, a_md5);
log_debug(__FILE__, __LINE__, "scan_folder File: %s md5:%s" , pfile_metedata->file_name, a_md5);
}
else
{
//char* pmd5 = md5minto32(file_metedata->file_md5);
log_debug(__FILE__, __LINE__, "scan_folder File: %s", pfile_metedata->file_name);
}
return true;
}
以上内容包含了glib 的数据结构、md5的计算方式,可自行替换。