| #define _GNU_SOURCE | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <unistd.h> | |
| #include <string.h> | |
| #include <sys/types.h> | |
| #include <sys/stat.h> | |
| #include <fcntl.h> | |
| #include <sys/vfs.h> | |
| #include <assert.h> | |
| #include <mtd/mtd-abi.h> | |
| #include <errno.h> | |
| #include <sys/ioctl.h> | |
| #include "fs_check.h" | |
| #include "cfg_api.h" | |
| #include "pub_debug_info.h" | |
| /******************************************************************************* | |
| * Macro definitions * | |
| ******************************************************************************/ | |
| #define MOUNTS_INFO_FILE "/proc/mounts" | |
| #define NV_FS_FAC_MAIN_PATH "/mnt/imagefs/nvrwall.bin" | |
| #define NV_FS_RW_HASH_FAC_PATH "/mnt/imagefs/nvrwall.hash" | |
| #define NV_FS_RW_TOP_PATH "/etc_rw/psnv" | |
| #define NV_FS_RW_HASH_WORK_PATH "/etc_rw/psnv/nvrwall.hash" | |
| #define NV_FS_RW_MAIN_PATH "/etc_rw/psnv/rw_work" | |
| #define NV_FS_RW_BACKUP_PATH "/etc_rw/psnv/rw_backup" | |
| #define NV_FS_FAC_SYMBOL_PATH "/etc_rw/psnv/fac_flag" | |
| #define NV_FS_RW_MAIN_SYMBOL_PATH "/etc_rw/psnv/work_flag" | |
| #define NV_FS_RW_BACKUP_SYMBOL_PATH "/etc_rw/psnv/backup_flag" | |
| #define NV_FS_RW_AP_NV_MAIN_PATH "/etc_rw/nv/main/cfg" | |
| #define NV_FS_RW_AP_NV_BACKUP_PATH "/etc_rw/nv/backup/cfg" | |
| #define MOUNTS_LINE_LEN (256) | |
| #define MOUNTS_LINE_ELEMENT_LEN (64) | |
| #define MAX_PATH (256) | |
| #define BUF_MAX_LEN (32) | |
| #define UBI_DEV_MAX_NUM (10) | |
| #define SYSTEM_EXEC_FAIL (0) | |
| #define SYSTEM_EXEC_SUCC (1) | |
| #define USERDATA_RESET_FREE_BLOCK_LEVEL (2) | |
| #define USERDATA_FREE_DATA_SIZE (128) | |
| typedef enum { | |
| DEVICE_MTD = 0, | |
| DEVICE_ZFTL = 1, | |
| DEVICE_MTD_BLOCK, | |
| } device_type_t; | |
| char *g_path_prefix = ""; | |
| static int check_mount_result(const char *parti_mp) | |
| { | |
| char *line_p, *temp_p; | |
| char line[MOUNTS_LINE_LEN] = {0}; | |
| char line_element[MOUNTS_LINE_ELEMENT_LEN] = {0}; | |
| int found; | |
| FILE *fp = NULL; | |
| int mp_str_len; | |
| if (parti_mp == NULL) | |
| return -1; | |
| if ((fp = fopen(MOUNTS_INFO_FILE, "r")) == NULL) { | |
| printf("fs_check fopen %s failed, error:%s\n", MOUNTS_INFO_FILE, strerror(errno)); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check fopen %s failed, error:%s\n", MOUNTS_INFO_FILE, strerror(errno)); | |
| goto error; | |
| } | |
| found = 0; | |
| while (1) { | |
| memset(line, 0, sizeof(line)); | |
| if (NULL == fgets(line, sizeof(line), fp)) { | |
| break; | |
| } | |
| //upi_log("line: %s", line); | |
| line_p = line; | |
| while (*line_p != '\0' && *line_p != ' ') { // first element | |
| line_p++; | |
| } | |
| line_p++; | |
| memset(line_element, 0, sizeof(line_element)); | |
| temp_p = line_element; | |
| while (*line_p != '\0' && *line_p != ' ') { // second element, this is what we need | |
| *temp_p = *line_p; | |
| temp_p++; | |
| line_p++; | |
| } | |
| //upi_log("line_element: %s", line_element); | |
| mp_str_len = strlen(parti_mp); | |
| if (mp_str_len <= strlen(line_element)) { | |
| if (strncmp(line_element + strlen(line_element) - mp_str_len, parti_mp, mp_str_len) == 0) { | |
| found = 1; | |
| break; | |
| } | |
| } | |
| } | |
| if (found == 0) { | |
| printf("fs_check did not find any mount info about %s\n", parti_mp); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check did not find any mount info about %s\n", parti_mp); | |
| goto error; | |
| } | |
| if (NULL != fp) | |
| fclose(fp); | |
| return 0; | |
| error: | |
| if (fp != NULL) | |
| fclose(fp); | |
| return -1; | |
| } | |
| int mtd_find(const char *i_parti_name, char *o_mtd_path, device_type_t device_type, unsigned int o_mtd_path_len) | |
| { | |
| FILE *fd_mtd = 0; | |
| char buf[128]; | |
| char *line_str; | |
| if (!o_mtd_path_len) | |
| return -1; | |
| fd_mtd = fopen("/proc/mtd", "r+"); | |
| if (NULL == fd_mtd) { | |
| printf("fs_check open file error:%s", strerror(errno)); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check open file error:%s", strerror(errno)); | |
| goto error0; | |
| } | |
| //printf("fs_check partition name:%s\n", i_parti_name); | |
| while (1) { | |
| int matches = 0; | |
| char mtdname[64] = {0}; | |
| int mtdnum = 0; | |
| unsigned int mtdsize, mtderasesize; | |
| memset(buf, 0x00, sizeof(buf)); | |
| line_str = fgets(buf, sizeof(buf), fd_mtd); | |
| if (NULL == line_str) { | |
| printf("fs_check get info from mtd error:%s\n", strerror(errno)); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check get info from mtd error:%s\n", strerror(errno)); | |
| goto error1; | |
| } | |
| //mtd5: 00100000 00020000 "fotaflag" | |
| matches = sscanf(buf, "mtd%d: %x %x \"%63[^\"]", | |
| &mtdnum, &mtdsize, &mtderasesize, mtdname); | |
| mtdname[63] = '\0'; | |
| if ((matches == 4) && (strcmp(mtdname, i_parti_name) == 0)) { | |
| memset(o_mtd_path, 0x00, o_mtd_path_len); | |
| if (device_type == DEVICE_MTD_BLOCK) { | |
| snprintf(o_mtd_path, o_mtd_path_len, "/dev/mtdblock%d", mtdnum); | |
| } else if (device_type == DEVICE_MTD) { | |
| snprintf(o_mtd_path, o_mtd_path_len, "/dev/mtd%d", mtdnum); | |
| } else if (device_type == DEVICE_ZFTL) { | |
| snprintf(o_mtd_path, o_mtd_path_len, "/dev/zftl%d", mtdnum); | |
| } else { | |
| printf("fs_check unknown device type %d\n", device_type); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check unknown device type %d\n", device_type); | |
| goto error1; | |
| } | |
| //printf("fs_check o_mtd_path=[%s]\n", o_mtd_path); | |
| break; | |
| } | |
| } | |
| fclose(fd_mtd); | |
| return 0; | |
| error1: | |
| fclose(fd_mtd); | |
| error0: | |
| return -1; | |
| } | |
| int system_exec_status(int status) | |
| { | |
| if (-1 == status) | |
| return SYSTEM_EXEC_FAIL; | |
| if (!WIFEXITED(status)) | |
| return SYSTEM_EXEC_FAIL; | |
| if (WEXITSTATUS(status)) | |
| return SYSTEM_EXEC_FAIL; | |
| return SYSTEM_EXEC_SUCC; | |
| } | |
| int get_ubifs_device_num(int recv_mtdnum) | |
| { | |
| int vol_num = -1; | |
| int fd_ubi = -1; | |
| int ret = -1; | |
| int mytmp = 0; | |
| int add_len = 10; | |
| struct stat st = {0}; | |
| char read_buf[BUF_MAX_LEN] = {0}; | |
| char ubidev_path[MAX_PATH] = {0}; | |
| for (; mytmp < UBI_DEV_MAX_NUM; mytmp++) | |
| { | |
| snprintf(ubidev_path, sizeof(ubidev_path), "/sys/devices/virtual/ubi/ubi%d", mytmp); | |
| ret = stat(ubidev_path, &st); | |
| if (ret < 0) { | |
| printf("fs_check get stat info from error:%s\n", strerror(errno)); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check get stat info from error:%s\n", strerror(errno)); | |
| break; | |
| } | |
| if (S_ISDIR(st.st_mode)) { | |
| strncat(ubidev_path, "/mtd_num", add_len); | |
| fd_ubi = open(ubidev_path, O_RDONLY); | |
| if (fd_ubi < 0) { | |
| printf("fs_check open file error:%s", strerror(errno)); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check open file error:%s", strerror(errno)); | |
| break; | |
| } | |
| memset(read_buf, 0, sizeof(read_buf)); | |
| ret = read(fd_ubi, read_buf, sizeof(read_buf)); | |
| if (ret < 0) { | |
| printf("fs_check get info from ubi error:%s\n", strerror(errno)); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check get info from ubi error:%s\n", strerror(errno)); | |
| close(fd_ubi); | |
| break; | |
| } | |
| if (atoi(read_buf) == recv_mtdnum) { | |
| vol_num = mytmp; | |
| close(fd_ubi); | |
| break; | |
| } | |
| close(fd_ubi); | |
| } | |
| } | |
| return vol_num; | |
| } | |
| /************************************************************************** | |
| * º¯ÊýÃû³Æ£º read_file | |
| * ¹¦ÄÜÃèÊö£º ¶ÁÈ¡Îļþ | |
| * ²ÎÊý˵Ã÷£º (IN) | |
| * p_file: Îļþ | |
| * len: ³¤¶È | |
| * (OUT) | |
| * ·µ »Ø Öµ Îļþ¶ÁÈ¡³É¹¦Çé¿ö£¨1¡¢·µ»Ø·ÇNULL£»2¡¢¿ÕÎļþ·µ»ØNULLÇÒlenµÈÓÚ0£©£¬ | |
| Îļþ¶Áȡʧ°ÜÇé¿ö£º·µ»ØNULL£¬ÇÒlen´óÓÚ0 | |
| * ÆäËü˵Ã÷£º·µ»ØÖµµ÷ÓÃÕßÊÍ·Å | |
| **************************************************************************/ | |
| static char *read_file(const char *p_file, unsigned int *len) | |
| { | |
| FILE * fd = 0; | |
| struct stat buf = {0}; | |
| char * p_buf = NULL; | |
| size_t read_size; | |
| *len = 0xffff; /* init file length > 0 for error */ | |
| if(p_file == NULL) | |
| return NULL; | |
| if(stat(p_file, &buf) < 0) | |
| { | |
| printf("read_file stat %s failed\n", p_file); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "read_file stat %s failed\n", p_file); | |
| return NULL; | |
| } | |
| if (buf.st_size == 0) | |
| { | |
| *len = 0; /* empty file */ | |
| return NULL; | |
| } | |
| *len = buf.st_size; | |
| fd = fopen(p_file, "rb"); | |
| if(!fd) | |
| { | |
| printf("read_file open %s fail\n", p_file); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "read_file open %s fail\n", p_file); | |
| return NULL; | |
| } | |
| p_buf = (char *)malloc(buf.st_size); | |
| if (p_buf == NULL) | |
| { | |
| printf("read_file malloc fail\n"); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "read_file malloc fail\n"); | |
| fclose(fd); | |
| return NULL; | |
| } | |
| read_size = fread(p_buf,1, buf.st_size,fd); | |
| if (read_size != buf.st_size) | |
| { | |
| printf("read_file fread %s fail\n", p_file); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "read_file fread %s fail\n", p_file); | |
| fclose(fd); | |
| free(p_buf); | |
| return NULL; | |
| } | |
| if (ferror(fd)) | |
| { | |
| clearerr(fd); | |
| printf("read_file ferror %s fail\n", p_file); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "read_file ferror %s fail\n", p_file); | |
| fclose(fd); | |
| free(p_buf); | |
| return NULL; | |
| } | |
| fclose(fd); | |
| return p_buf; | |
| } | |
| /************************************************************************** | |
| * º¯ÊýÃû³Æ£º compare_file | |
| * ¹¦ÄÜÃèÊö£º ±È½ÏÄ¿±êÎļþºÍÔ´ÎļþÊÇ·ñÒ»Ñù | |
| * ²ÎÊý˵Ã÷£º (IN) | |
| * p_dst_file: Ä¿±êÎļþ | |
| * p_src_file: Ô´Îļþ | |
| * (OUT) | |
| * ·µ »Ø Öµ£ºÎļþÒ»Ñù·µ»Ø0, ·ñÔò·µ»Ø-1 | |
| * ÆäËü˵Ã÷£º | |
| **************************************************************************/ | |
| static int compare_file(const char *p_dst_file, const char *p_src_file) | |
| { | |
| char *p_dst; | |
| char *p_src; | |
| unsigned int dst_len; | |
| unsigned int src_len; | |
| int ret = 0; | |
| if(p_dst_file == NULL || p_src_file == NULL) | |
| return -1; | |
| p_dst = read_file(p_dst_file, &dst_len); | |
| p_src = read_file(p_src_file, &src_len); | |
| if (p_dst == NULL && p_src == NULL) | |
| { | |
| assert(dst_len == 0); | |
| assert(src_len == 0); | |
| return 0; //both empty file | |
| } | |
| else if (p_dst == NULL || p_src == NULL) | |
| { | |
| printf("compare_file size dstbuf = %d, srcbuf = %d\n", dst_len, src_len); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "compare_file size dstbuf = %d, srcbuf = %d\n", dst_len, src_len); | |
| ret = -1; | |
| goto out; | |
| } | |
| else | |
| { | |
| if(dst_len != src_len) | |
| { | |
| printf("compare_file size dstbuf = %d, srcbuf = %d\n", dst_len, src_len); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "compare_file size dstbuf = %d, srcbuf = %d\n", dst_len, src_len); | |
| ret = -1; | |
| goto out; | |
| } | |
| if(memcmp(p_src, p_dst, src_len) != 0) | |
| { | |
| printf("compare_file memcmp not same\n"); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "compare_file memcmp not same\n"); | |
| ret = -1; | |
| goto out; | |
| } | |
| ret = 0; | |
| } | |
| out: | |
| if (p_src) | |
| { | |
| free(p_src); | |
| } | |
| if (p_dst) | |
| { | |
| free(p_dst); | |
| } | |
| return ret; | |
| } | |
| /************************************************************************** | |
| * º¯ÊýÃû³Æ£º check_files_access | |
| * ¹¦ÄÜÃèÊö£º ¼ì²éuserdataÎļþϵͳϵÄÎļþÊÇ·ñ´æÔÚÇÒÓжÁдȨÏÞ | |
| * ²ÎÊý˵Ã÷£º ÎÞ | |
| * ·µ »Ø Öµ£º¼ì²éÕý³£·µ»Ø0, ·ñÔò·µ»Ø-1£¬½øÐÐuserdata·ÖÇøµÄ²Á³ý | |
| * ÆäËü˵Ã÷£º | |
| **************************************************************************/ | |
| static int check_files_access() | |
| { | |
| if(access(NV_FS_RW_MAIN_PATH,W_OK | R_OK) < 0) | |
| { | |
| printf("fs_check file: %s permission loss \n",NV_FS_RW_MAIN_PATH); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check file: %s permission loss \n",NV_FS_RW_MAIN_PATH); | |
| return -1;//²é¿´rw_workÎļþÊÇ·ñ¿É¶Áд | |
| } | |
| if(access(NV_FS_RW_BACKUP_PATH, W_OK | R_OK) < 0) | |
| { | |
| printf("fs_check file: %s permission loss \n",NV_FS_RW_BACKUP_PATH); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check file: %s permission loss \n",NV_FS_RW_BACKUP_PATH); | |
| return -1;//²é¿´rw_backupÎļþÊÇ·ñ¿É¶Áд | |
| } | |
| if(access(NV_FS_FAC_SYMBOL_PATH, W_OK | R_OK) < 0) | |
| { | |
| printf("fs_check file: %s permission loss \n",NV_FS_FAC_SYMBOL_PATH); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check file: %s permission loss \n",NV_FS_FAC_SYMBOL_PATH); | |
| return -1;//²é¿´fac_flagÎļþÊÇ·ñ¿É¶Áд | |
| } | |
| if(access(NV_FS_RW_MAIN_SYMBOL_PATH, W_OK | R_OK) < 0) | |
| { | |
| printf("fs_check file: %s permission loss \n",NV_FS_RW_MAIN_SYMBOL_PATH); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check file: %s permission loss \n",NV_FS_RW_MAIN_SYMBOL_PATH); | |
| return -1;//²é¿´work_flagÎļþÊÇ·ñ¿É¶Áд | |
| } | |
| if(access(NV_FS_RW_BACKUP_SYMBOL_PATH, W_OK | R_OK) < 0) | |
| { | |
| printf("fs_check file: %s permission loss \n",NV_FS_RW_BACKUP_SYMBOL_PATH); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check file: %s permission loss \n",NV_FS_RW_BACKUP_SYMBOL_PATH); | |
| return -1;//²é¿´backup_flagÎļþÊÇ·ñ¿É¶Áд | |
| } | |
| if(access(NV_FS_RW_AP_NV_MAIN_PATH, W_OK | R_OK) < 0) | |
| { | |
| printf("fs_check file: %s permission loss \n",NV_FS_RW_AP_NV_MAIN_PATH); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check file: %s permission loss \n",NV_FS_RW_AP_NV_MAIN_PATH); | |
| return -1;//²é¿´apϹ¤×÷nvÎļþÊÇ·ñ¿É¶Áд | |
| } | |
| if(access(NV_FS_RW_AP_NV_BACKUP_PATH, W_OK | R_OK) < 0) | |
| { | |
| printf("fs_check file: %s permission loss \n",NV_FS_RW_AP_NV_BACKUP_PATH); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check file: %s permission loss \n",NV_FS_RW_AP_NV_BACKUP_PATH); | |
| return -1;//²é¿´apϱ¸·ÝnvÎļþÊÇ·ñ¿É¶Áд | |
| } | |
| return 0; | |
| } | |
| /* read success return 0, file not exist return 0, other return -1*/ | |
| static int file_read_test(const char *filename) | |
| { | |
| char *buf; | |
| size_t read_size; | |
| struct stat file_stat; | |
| int result = stat(filename, &file_stat); | |
| if (result == -1 && errno == ENOENT) | |
| { | |
| return 0; /* file not exist */ | |
| } | |
| else | |
| { | |
| if (result != 0) | |
| { | |
| return -1; | |
| } | |
| } | |
| buf = read_file(filename, &read_size); | |
| if (buf == NULL) | |
| { | |
| if (read_size == 0) | |
| { | |
| return 0; /* empty file */ | |
| } | |
| else | |
| { | |
| return -1; /* file read error */ | |
| } | |
| } | |
| else | |
| { | |
| free(buf); | |
| return 0; | |
| } | |
| } | |
| /************************************************************************** | |
| * º¯ÊýÃû³Æ£º check_files_read | |
| * ¹¦ÄÜÃèÊö£º ¼ì²éuserdataÎļþϵͳϵÄÎļþreadÊÇ·ñÕý³£ | |
| * ²ÎÊý˵Ã÷£º ÎÞ | |
| * ·µ »Ø Öµ£º¼ì²éÕý³£·µ»Ø0, ·ñÔò·µ»Ø-1£¬½øÐÐuserdata·ÖÇøµÄ²Á³ý | |
| * ÆäËü˵Ã÷£º | |
| **************************************************************************/ | |
| static int check_files_read() | |
| { | |
| if(file_read_test(NV_FS_RW_MAIN_PATH) < 0) | |
| { | |
| printf("fs_check file: %s read loss \n",NV_FS_RW_MAIN_PATH); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check file: %s read loss \n",NV_FS_RW_MAIN_PATH); | |
| return -1;//²é¿´rw_workÎļþÊÇ·ñ¿É¶Á | |
| } | |
| if(file_read_test(NV_FS_RW_BACKUP_PATH) < 0) | |
| { | |
| printf("fs_check file: %s read loss \n",NV_FS_RW_BACKUP_PATH); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check file: %s read loss \n",NV_FS_RW_BACKUP_PATH); | |
| return -1;//²é¿´rw_backupÎļþÊÇ·ñ¿É¶Á | |
| } | |
| if(file_read_test(NV_FS_FAC_SYMBOL_PATH) < 0) | |
| { | |
| printf("fs_check file: %s read loss \n",NV_FS_FAC_SYMBOL_PATH); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check file: %s read loss \n",NV_FS_FAC_SYMBOL_PATH); | |
| return -1;//²é¿´fac_flagÎļþÊÇ·ñ¿É¶Á | |
| } | |
| if(file_read_test(NV_FS_RW_MAIN_SYMBOL_PATH) < 0) | |
| { | |
| printf("fs_check file: %s read loss \n",NV_FS_RW_MAIN_SYMBOL_PATH); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check file: %s read loss \n",NV_FS_RW_MAIN_SYMBOL_PATH); | |
| return -1;//²é¿´work_flagÎļþÊÇ·ñ¿É¶Á | |
| } | |
| if(file_read_test(NV_FS_RW_BACKUP_SYMBOL_PATH) < 0) | |
| { | |
| printf("fs_check file: %s read loss \n",NV_FS_RW_BACKUP_SYMBOL_PATH); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check file: %s read loss \n",NV_FS_RW_BACKUP_SYMBOL_PATH); | |
| return -1;//²é¿´backup_flagÎļþÊÇ·ñ¿É¶Á | |
| } | |
| if(file_read_test(NV_FS_RW_AP_NV_MAIN_PATH) < 0) | |
| { | |
| printf("fs_check file: %s read loss \n",NV_FS_RW_AP_NV_MAIN_PATH); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check file: %s read loss \n",NV_FS_RW_AP_NV_MAIN_PATH); | |
| return -1;//²é¿´apϹ¤×÷nvÎļþÊÇ·ñ¿É¶Á | |
| } | |
| if(file_read_test(NV_FS_RW_AP_NV_BACKUP_PATH) < 0) | |
| { | |
| printf("fs_check file: %s read loss \n",NV_FS_RW_AP_NV_BACKUP_PATH); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check file: %s read loss \n",NV_FS_RW_AP_NV_BACKUP_PATH); | |
| return -1;//²é¿´apϱ¸·ÝnvÎļþÊÇ·ñ¿É¶Á | |
| } | |
| return 0; | |
| } | |
| /************************************************************************** | |
| * º¯ÊýÃû³Æ£º check_userdata_is_space_enough | |
| * ¹¦ÄÜÃèÊö£º ¼ì²éuserdata·ÖÇøÏÂÃæµÄ¿Õ¼äÊÇ·ñ×ã¹»£¬²»×ãʱÐèÒªÖØÐ»ָ´userdata·ÖÇø | |
| * ²ÎÊý˵Ã÷£º (IN) | |
| * (OUT) | |
| * ·µ »Ø Öµ£º¼ì²é¿Õ¼ä×ã¹»·µ»Ø0, ¿Õ¼ä²»×㣬ÐèÒªÖØÐ»ָ´·ÖÇø·µ»Ø-1 | |
| * ÆäËü˵Ã÷£º | |
| **************************************************************************/ | |
| int check_userdata_space_enough() | |
| { | |
| int fd = 0; | |
| char fsckname[] = "/etc_rw/fscheck"; | |
| char buf[] = "filesystem checking"; | |
| int len = strlen(buf); | |
| char *ptr = buf; | |
| int res = 0; | |
| int ret = 0; | |
| #if 0 | |
| struct statfs diskinfo; | |
| statfs("/mnt/userdata", &diskinfo); | |
| printf("fs_check f_bsize = %d, f_blocks = %d, f_bfree = %d, f_bavail = %d, f_files = %d, , f_ffree = %d\n", \ | |
| diskinfo.f_bsize, diskinfo.f_blocks, diskinfo.f_bfree, diskinfo.f_bavail, diskinfo.f_files, diskinfo.f_ffree); | |
| //»ñȡʣÓà¿Õ¼äÊÇ·ñ´óÓÚµÈÓÚÁ½¸öblock | |
| if ((diskinfo.f_bsize * diskinfo.f_bfree < CONFIG_BLOCK_SIZE * USERDATA_RESET_FREE_BLOCK_LEVEL) || | |
| (diskinfo.f_bsize * diskinfo.f_bavail < CONFIG_BLOCK_SIZE * USERDATA_RESET_FREE_BLOCK_LEVEL)) | |
| return -1; | |
| #endif | |
| fd = open(fsckname, O_WRONLY | O_CREAT | O_TRUNC, 0644); | |
| if (fd < 0) | |
| { | |
| printf("open %s failed errno %d\n", fsckname, errno); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "open %s failed errno %d\n", fsckname, errno); | |
| return -1; | |
| } | |
| while (len > 0) | |
| { | |
| res = write(fd, ptr, len); | |
| if (res < 0) | |
| { | |
| if (errno == EINTR) | |
| { | |
| res = 0; | |
| } | |
| else | |
| { | |
| printf("write %s failed errno %d\n", fsckname, errno); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "write %s failed errno %d\n", fsckname, errno); | |
| ret = -1; | |
| break; | |
| } | |
| } | |
| ptr += res; | |
| len -= res; | |
| } | |
| if (close(fd) < 0) | |
| { | |
| printf("close %s failed errno %d\n", fsckname, errno); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "close %s failed errno %d\n", fsckname, errno); | |
| return -1; | |
| } | |
| return ret; | |
| } | |
| /************************************************************************** | |
| * º¯ÊýÃû³Æ£º check_userdata_is_normal | |
| * ¹¦ÄÜÃèÊö£º ¼ì²éuserdata·ÖÇøÏÂÃæµÄÎļþÊÇ·ñÕý³££¬Èç¹û´æÔÚÒì³££¬ÔòÐèÒªÖØÐ»ָ´userdata·ÖÇø | |
| * ²ÎÊý˵Ã÷£º (IN) | |
| * dst_file: Ä¿±êÎļþ | |
| * src_file: Ô´Îļþ | |
| * (OUT) | |
| * ·µ »Ø Öµ£º¼ì²éÕý³£·µ»Ø0, ÐèÒªÖØÐ»ָ´·ÖÇø·µ»Ø-1 | |
| * ÆäËü˵Ã÷£º | |
| **************************************************************************/ | |
| int check_userdata_is_normal() | |
| { | |
| struct stat fac_nv_buf = {0}; | |
| struct stat work_buf = {0}; | |
| struct stat backup_buf = {0}; | |
| if (check_userdata_space_enough() < 0) | |
| return -1; | |
| if (access(NV_FS_RW_TOP_PATH, F_OK) != 0) | |
| { | |
| if (mkdir(NV_FS_RW_TOP_PATH, 0755) != 0) | |
| { | |
| printf("fs_check access and mkdir %s failed\n", NV_FS_RW_TOP_PATH); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check access and mkdir %s failed\n", NV_FS_RW_TOP_PATH); | |
| return -1; | |
| } | |
| } | |
| /*userdata·ÖÇøÊÇ·ñ¼ì²éÐèÒªÂú×ãÒÔÏÂÁ½¸öÌõ¼þ£º | |
| *1)²é¿´userdata·ÖÇøÏÂÃæµÄnvrwall.hashÊÇ·ñ´æÔÚ£¬²»´æÔÚ±íʾÊǸÕÉÕÍê°æ±¾£¬Õâʱºò²»¼ì²é | |
| *2)imageϵÄhashºÍpsnvĿ¼ÏÂÃæµÄnvrwall.hashÊÇ·ñÒ»Ö£¬Èç¹ûÒ»Ö½øÐмì²é£¬·ñÔò²»½øÐмì²é£¨¹ýÂËfotaÉý¼¶£© | |
| */ | |
| if(access(NV_FS_RW_HASH_WORK_PATH, F_OK) < 0) | |
| return 0; | |
| if (check_files_read() < 0) | |
| { | |
| return -1;//userdata·ÖÇøÏµÄÎļþ¶ÁÊÇ·ñÕý³£ | |
| } | |
| if(compare_file(NV_FS_RW_HASH_FAC_PATH, NV_FS_RW_HASH_WORK_PATH) == 0) | |
| { | |
| if(check_files_access() < 0) | |
| { | |
| return -1;//userdata·ÖÇøÏµÄÎļþ·ÃÎÊȨÏÞÒì³£ÐèÒª»Ö¸´ | |
| } | |
| if(stat(NV_FS_FAC_MAIN_PATH, &fac_nv_buf) < 0) | |
| { | |
| return 0; | |
| } | |
| if(stat(NV_FS_RW_MAIN_PATH, &work_buf) < 0) | |
| { | |
| printf("fs_check stat %s failed\n",NV_FS_RW_MAIN_PATH); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check stat %s failed\n",NV_FS_RW_MAIN_PATH); | |
| return -1; | |
| } | |
| if(stat(NV_FS_RW_BACKUP_PATH, &backup_buf) < 0) | |
| { | |
| printf("fs_check stat %s failed\n",NV_FS_RW_BACKUP_PATH); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check stat %s failed\n",NV_FS_RW_BACKUP_PATH); | |
| return -1; | |
| } | |
| if(work_buf.st_size < fac_nv_buf.st_size || backup_buf.st_size < fac_nv_buf.st_size) | |
| { | |
| printf("fs_check rw_backup or rw_work file corrupted\n"); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check rw_backup or rw_work file corrupted\n"); | |
| return -1;//userdata·ÖÇøÏµĹ¤×÷ÇønvºÍ±¸·ÝÇønv±È³ö³§ÇønvС£¬ÐèÒª»Ö¸´ | |
| } | |
| } | |
| return 0; | |
| } | |
| int mount_fs_partition(struct mtd_fs *p_fs) | |
| { | |
| int ret = -1; | |
| int ubi_num = 0; | |
| int mtd_blk_num = 0; | |
| char mount_cmd[MAX_PATH] = {0}; | |
| char mtd_path[MAX_PATH] = {0}; | |
| char attach_cmd[MAX_PATH] = {0}; | |
| if (NULL == p_fs->patition_name || NULL == p_fs->mount_point || NULL == p_fs->fs_type) | |
| return -1; | |
| //printf("fs_check i_parti_name=%s, parti_mp=%s, parti_mt=%s\n", p_fs->patition_name, p_fs->mount_point, p_fs->fs_type); | |
| if (strcmp(p_fs->patition_name, "cpfs") == 0) { | |
| ret = mtd_find(p_fs->patition_name, mtd_path, DEVICE_MTD_BLOCK, MAX_PATH); | |
| if (ret < 0) { | |
| printf("fs_check partition name is not find\n"); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check partition name is not find\n"); | |
| return -1; | |
| } | |
| snprintf(mount_cmd, sizeof(mount_cmd), "%s/bin/mount -t yaffs2 -o \"inband-tags\" %s %s", g_path_prefix,mtd_path, p_fs->mount_point); | |
| } else if (strcmp(p_fs->fs_type, "jffs2") == 0) { | |
| ret = mtd_find(p_fs->patition_name, mtd_path, DEVICE_MTD_BLOCK, MAX_PATH); | |
| if (ret < 0) { | |
| printf("fs_check partition name is not find\n"); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check partition name is not find\n"); | |
| return -1; | |
| } | |
| snprintf(mount_cmd, sizeof(mount_cmd), "%s/bin/mount -t jffs2 %s %s %s", g_path_prefix,p_fs->mount_opt ,mtd_path, p_fs->mount_point); | |
| } else if (strcmp(p_fs->fs_type, "ubifs") == 0) { | |
| ret = mtd_find(p_fs->patition_name, mtd_path, DEVICE_MTD_BLOCK, MAX_PATH); | |
| if (ret < 0) { | |
| printf("fs_check partition name is not find\n"); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check partition name is not find\n"); | |
| return -1; | |
| } | |
| sscanf(mtd_path, "/dev/mtdblock%d", &mtd_blk_num); | |
| snprintf(attach_cmd, sizeof(attach_cmd), "%s/usr/sbin/ubiattach /dev/ubi_ctrl -m %d", g_path_prefix,mtd_blk_num); | |
| ret = system_exec_status(zxic_system(attach_cmd)); | |
| if (ret == SYSTEM_EXEC_FAIL) { | |
| printf("fs_check: %s fail\n",attach_cmd); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check: %s fail\n",attach_cmd); | |
| return -1; | |
| } | |
| ubi_num = get_ubifs_device_num(mtd_blk_num); | |
| if (ubi_num < 0) { | |
| printf("fs_check ubi_num not match\n"); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check ubi_num not match\n"); | |
| return -1; | |
| } | |
| snprintf(mount_cmd, sizeof(mount_cmd), "%s/bin/mount -t ubifs -o rw ubi%d_0 %s", g_path_prefix,ubi_num, p_fs->mount_point); | |
| } else { | |
| printf("fs_check unknown mount type: %s\n", p_fs->fs_type); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check unknown mount type: %s\n", p_fs->fs_type); | |
| return -1; | |
| } | |
| ret = zxic_system(mount_cmd); | |
| if (check_mount_result(p_fs->mount_point) < 0) { | |
| printf("fs_check : %s fail\n", mount_cmd); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check : %s fail\n", mount_cmd); | |
| return -1; | |
| } | |
| return 0; | |
| } | |
| int unmount_fs_partition(struct mtd_fs *p_fs) | |
| { | |
| int ret = -1; | |
| int ubi_num = 0; | |
| int mtd_blk_num = 0; | |
| char umount_cmd[MAX_PATH] = {0}; | |
| char mtd_path[MAX_PATH] = {0}; | |
| char detach_cmd[MAX_PATH] = {0}; | |
| if (NULL == p_fs->patition_name || NULL == p_fs->mount_point || NULL == p_fs->fs_type) | |
| return -1; | |
| if (strcmp(p_fs->patition_name, "cpfs") == 0) { | |
| snprintf(umount_cmd, sizeof(umount_cmd), "%s/bin/umount -f %s ", g_path_prefix,p_fs->mount_point); | |
| } else if (strcmp(p_fs->fs_type, "jffs2") == 0) { | |
| snprintf(umount_cmd, sizeof(umount_cmd), "%s/bin/umount -f %s", g_path_prefix,p_fs->mount_point); | |
| } else if (strcmp(p_fs->fs_type, "ubifs") == 0) { | |
| snprintf(umount_cmd, sizeof(umount_cmd), "%s/bin/umount -f %s", g_path_prefix,p_fs->mount_point); | |
| zxic_system(umount_cmd); | |
| printf("fs_check umount : %s\n", umount_cmd); | |
| ret = mtd_find(p_fs->patition_name, mtd_path, DEVICE_MTD_BLOCK, MAX_PATH); | |
| if (ret < 0) { | |
| printf("fs_check partition name is not find\n"); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check partition name is not find\n"); | |
| return -1; | |
| } | |
| sscanf(mtd_path, "/dev/mtdblock%d", &mtd_blk_num); | |
| ubi_num = get_ubifs_device_num(mtd_blk_num); | |
| snprintf(detach_cmd, sizeof(detach_cmd), "%s/usr/sbin/ubidetach /dev/ubi_ctrl -d %d", g_path_prefix,ubi_num); | |
| ret = system_exec_status(zxic_system(detach_cmd)); | |
| if (ret == SYSTEM_EXEC_FAIL) { | |
| printf("fs_check: %s fail\n",detach_cmd); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check: %s fail\n",detach_cmd); | |
| return -1; | |
| } | |
| return 0; | |
| } else { | |
| printf("fs_check unknown umount type: %s\n", p_fs->fs_type); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check unknown umount type: %s\n", p_fs->fs_type); | |
| return -1; | |
| } | |
| printf("fs_check umount : %s\n", umount_cmd); | |
| ret = zxic_system(umount_cmd); | |
| return 0; | |
| } | |
| int mtd_erase_partition(const char* partition_name) | |
| { | |
| int ret = 0; | |
| char mtd_path[MAX_PATH] = {0}; | |
| int fd_mtd = -1; | |
| struct mtd_info_user meminfo = {0}; | |
| struct erase_info_user64 erase_info = {0}; | |
| if (NULL == partition_name) { | |
| return -1; | |
| } | |
| ret = mtd_find(partition_name, mtd_path, DEVICE_MTD, MAX_PATH); | |
| if (ret < 0) { | |
| printf("fs_check mtd_find %s failed\n", partition_name); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check mtd_find %s failed\n", partition_name); | |
| ret = -1; | |
| goto out; | |
| } | |
| fd_mtd = open(mtd_path, O_RDWR); | |
| if (fd_mtd < 0) { | |
| printf("fs_check open %s error, %s\n", partition_name, strerror(errno)); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check open %s error, %s\n", partition_name, strerror(errno)); | |
| ret = -1; | |
| goto out; | |
| } | |
| if (ioctl(fd_mtd, MEMGETINFO, &meminfo) != 0) { | |
| printf("fs_check get %s info error, %s\n", partition_name, strerror(errno)); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check get %s info error, %s\n", partition_name, strerror(errno)); | |
| ret = -1; | |
| goto out; | |
| } | |
| erase_info.length = meminfo.erasesize; | |
| for (erase_info.start = 0; erase_info.start < meminfo.size; erase_info.start += meminfo.erasesize) { | |
| if (ioctl(fd_mtd, MEMGETBADBLOCK, &(erase_info.start)) > 0) { | |
| printf("fs_check mtd, not erasing bad block at 0x%llx\n", erase_info.start); | |
| continue; | |
| } | |
| if (ioctl(fd_mtd, MEMERASE64, &erase_info) < 0) { | |
| printf("fs_check mtd, erasing failure at 0x%llx\n", erase_info.start); | |
| } | |
| } | |
| ret = 0; | |
| out: | |
| if (fd_mtd >= 0) { | |
| close(fd_mtd); | |
| } | |
| return ret; | |
| } | |
| int mtd_write_partition(const char* partition_name, const char* image_file) | |
| { | |
| int ret = 0; | |
| char mtd_path[MAX_PATH] = {0}; | |
| int fd_mtd = -1; | |
| struct mtd_info_user meminfo = {0}; | |
| long long index = 0; | |
| int len = 0; | |
| FILE * fp = NULL; | |
| char * buf = NULL; | |
| struct stat statbuff = {0}; | |
| if (NULL == partition_name || NULL == image_file) | |
| return -1; | |
| ret = mtd_find(partition_name, mtd_path, DEVICE_MTD, MAX_PATH); | |
| if (ret < 0) { | |
| printf("fs_check mtd_find %s failed\n", partition_name); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check mtd_find %s failed\n", partition_name); | |
| ret = -1; | |
| goto out; | |
| } | |
| fd_mtd = open(mtd_path, O_RDWR); | |
| if (fd_mtd < 0) { | |
| printf("fs_check open %s error, %s\n", partition_name, strerror(errno)); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check open %s error, %s\n", partition_name, strerror(errno)); | |
| ret = -1; | |
| goto out; | |
| } | |
| if (ioctl(fd_mtd, MEMGETINFO, &meminfo) != 0) { | |
| printf("fs_check get %s info error, %s\n", partition_name, strerror(errno)); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check get %s info error, %s\n", partition_name, strerror(errno)); | |
| ret = -1; | |
| goto out; | |
| } | |
| if(stat(image_file, &statbuff) < 0) | |
| { | |
| printf("fs_check stat %s failed\n", image_file); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check stat %s failed\n", image_file); | |
| ret = -1; | |
| goto out; | |
| } | |
| fp = fopen(image_file, "ro"); | |
| if (!fp) | |
| { | |
| printf("fs_check fopen %s failed\n", image_file); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check fopen %s failed\n", image_file); | |
| ret = -1; | |
| goto out; | |
| } | |
| buf = (char *)malloc(meminfo.erasesize); | |
| if(!buf) | |
| { | |
| printf("fs_check malloc failed\n"); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check malloc failed\n"); | |
| ret = -1; | |
| goto out; | |
| } | |
| for (index = 0; index < meminfo.size && len < statbuff.st_size; index += meminfo.erasesize) | |
| { | |
| if (ioctl(fd_mtd, MEMGETBADBLOCK, &index) > 0) | |
| { | |
| printf("fs_check mtd, not erasing bad block at %lld\n", index); | |
| continue; | |
| } | |
| memset(buf, 0xff, meminfo.erasesize); | |
| ret = fread(buf, 1, meminfo.erasesize, fp); | |
| if(ret < 0) | |
| { | |
| printf("fs_check mtd, fread error = %d!\n", ret); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check mtd, fread error = %d!\n", ret); | |
| ret = -1; | |
| goto out; | |
| } | |
| ret = lseek(fd_mtd, (long)index, SEEK_SET); | |
| if(ret < 0) | |
| { | |
| printf("fs_check mtd, lseek error = %s!\n", strerror(errno)); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check mtd, lseek error = %s!\n", strerror(errno)); | |
| ret = -1; | |
| goto out; | |
| } | |
| ret = write(fd_mtd, buf, (size_t)meminfo.erasesize); | |
| if (ret < 0 || ret != meminfo.erasesize) | |
| { | |
| printf("fs_check mtd, write %s error = %d!\n", partition_name, ret); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check mtd, write %s error = %d!\n", partition_name, ret); | |
| ret = -1; | |
| goto out; | |
| } | |
| len += meminfo.erasesize; | |
| } | |
| if (len < statbuff.st_size) | |
| { | |
| printf("fs_check mtd, No space left,writelen=%d, filesize=%d\n",len,statbuff.st_size); | |
| sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check mtd, No space left,writelen=%d, filesize=%d\n",len,statbuff.st_size); | |
| } | |
| ret = 0; | |
| out: | |
| if (fd_mtd >= 0) | |
| close(fd_mtd); | |
| if (buf != NULL) { | |
| memset(buf, 0, meminfo.erasesize); | |
| free(buf); | |
| } | |
| if (fp != NULL) | |
| fclose(fp); | |
| return ret; | |
| } | |