| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <string.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <fcntl.h> |
| #include <errno.h> |
| #include "openssl/md5.h" |
| #include "mtd.h" |
| #include "libcpnv.h" |
| #include "cfg_api.h" |
| #include "flags_api.h" |
| #include "zxicbasic_api.h" |
| |
| |
| /******************************************************************************* |
| * 功能描述: copyfile |
| * 参数说明: |
| * (传入参数) to:目标文件 |
| * (传入参数) from:源文件 |
| * 返 回 值: 0表示成功,负值失败 |
| * 其它说明: |
| *******************************************************************************/ |
| static int copyfile(const char *from, const char *to) |
| { |
| int fd_to; |
| int fd_from; |
| char buf[4096]; |
| ssize_t nread; |
| int ret = -1; |
| |
| fd_from = open(from, O_RDONLY); |
| if (fd_from < 0) |
| return -2; |
| |
| fd_to = open(to, O_RDWR | O_CREAT | O_TRUNC | O_SYNC, 0640); |
| if (fd_to < 0) { |
| ret = -3; |
| goto out_error; |
| } |
| |
| while (1) |
| { |
| char *out_ptr; |
| ssize_t nwritten; |
| |
| nread = read(fd_from, buf, sizeof(buf)); |
| if (nread == 0) |
| { |
| break; /* read file done*/ |
| } |
| else |
| { |
| if (nread < 0 ) |
| { |
| if (errno == EINTR || errno == EAGAIN) |
| { |
| continue; |
| } |
| else |
| { |
| ret = -4; |
| goto out_error; |
| } |
| } |
| } |
| |
| out_ptr = buf; |
| do |
| { |
| nwritten = write(fd_to, out_ptr, nread); |
| if (nwritten > 0) |
| { |
| nread -= nwritten; |
| out_ptr += nwritten; |
| } |
| else |
| { |
| if (nwritten < 0) |
| { |
| if (errno == EINTR || errno == EAGAIN) |
| { |
| continue; |
| } |
| else |
| { |
| ret = -5; |
| goto out_error; |
| } |
| } |
| } |
| } while (nread > 0); |
| } |
| |
| ret = fsync(fd_to); |
| if (ret < 0) { |
| printf("Sync Failed:%s, file path:%s", strerror(errno), to); |
| goto out_error; |
| } |
| |
| if (close(fd_to) < 0) |
| { |
| fd_to = -1; |
| ret = -6; |
| goto out_error; |
| } |
| close(fd_from); |
| |
| /* Success! */ |
| return 0; |
| |
| out_error: |
| printf("copyfile %s to %s error:%d\n", from, to, ret); |
| close(fd_from); |
| if (fd_to >= 0) |
| close(fd_to); |
| |
| return ret; |
| } |
| |
| int nvrofs2_mount(int rw) |
| { |
| if (rw) |
| return zxic_system("/bin/mount -t jffs2 -o rw,sync mtd:nvrofs2 /mnt/nvrofs2"); |
| else |
| return zxic_system("/bin/mount -t jffs2 -o ro mtd:nvrofs2 /mnt/nvrofs2"); |
| } |
| int nvrofs2_umount(void) |
| { |
| return zxic_system("/bin/umount -f -l /mnt/nvrofs2"); |
| } |
| |
| unsigned char *bin2hex(const unsigned char *old, const size_t oldlen) |
| { |
| unsigned char *result = (unsigned char *)malloc(oldlen * 2 + 1); |
| size_t i, j; |
| int b = 0; |
| |
| for (i = j = 0; i < oldlen; i++) |
| { |
| b = old[i] >> 4; |
| result[j++] = (char)(87 + b + (((b - 10) >> 31) & -39)); |
| b = old[i] & 0xf; |
| result[j++] = (char)(87 + b + (((b - 10) >> 31) & -39)); |
| } |
| result[j] = '\0'; |
| return result; |
| } |
| |
| int calc_file_hash(const char *file_in, unsigned char *hash_value) |
| { |
| MD5_CTX ctx; |
| unsigned char *buf; |
| int offset; |
| int fd; |
| ssize_t len; |
| |
| fd = open(file_in, O_RDONLY); |
| if (fd < 0) |
| return -1; |
| buf = malloc(4096); |
| if (buf == NULL) |
| { |
| close(fd); |
| return -1; |
| } |
| MD5_Init(&ctx); |
| do |
| { |
| len = full_read(fd, buf, 4096); |
| MD5_Update(&ctx, buf, len); |
| if (len < 4096) |
| break; |
| } while(1); |
| |
| MD5_Final(hash_value, &ctx); |
| free(buf); |
| close(fd); |
| return 0; |
| } |
| |
| int file_hash(const char *file_in, const char *file_hash) |
| { |
| unsigned char hash_value[16] = {0}; |
| unsigned char *hash_str; |
| int ret; |
| ssize_t ret_s; |
| |
| ret = calc_file_hash(file_in, hash_value); |
| if (ret < 0) |
| return -1; |
| hash_str = bin2hex(hash_value, 16); |
| ret_s = open_write_close(file_hash, hash_str, 32); |
| free(hash_str); |
| if (ret_s != 32) |
| return -1; |
| return 0; |
| } |
| int file_hash_check(const char *file_in, const char *file_hash) |
| { |
| unsigned char hash_value[16] = {0}; |
| unsigned char *hash_str; |
| unsigned char hash_str2[33] = {0}; |
| int ret; |
| ssize_t ret_s; |
| |
| ret = calc_file_hash(file_in, hash_value); |
| if (ret < 0) |
| return -1; |
| hash_str = bin2hex(hash_value, 16); |
| memset(hash_str2, 0, sizeof(hash_str2)); |
| ret_s = open_read_close(file_hash, hash_str2, 32); |
| if (ret_s != 32) |
| return -1; |
| if (strcmp(hash_str, hash_str2) == 0) |
| { |
| return 0; |
| } |
| return -1; |
| } |
| |
| unsigned int cpnv_NvroBackup(void) |
| { |
| char mtd_path[MAX_PATH] = {0}; |
| int ret; |
| |
| ret = mtd_find("nvrofs2", mtd_path, DEVICE_MTD_BLOCK, MAX_PATH); |
| if (ret < 0) |
| { |
| printf("[error]cpnv can not find nvrofs2\n"); |
| return CPNV_ERROR; |
| } |
| ret = mtd_erase_partition("nvrofs2"); |
| if (ret != 0) |
| { |
| printf("[error]cpnv erase nvrofs2\n"); |
| return CPNV_ERROR; |
| } |
| |
| ret = nvrofs2_mount(1); |
| if (ret != 0) |
| { |
| nvrofs2_umount(); |
| ret = nvrofs2_mount(1); |
| if (ret != 0) |
| { |
| printf("[error]cpnv nvrofs2_mount\n"); |
| return CPNV_ERROR; |
| } |
| } |
| ret = copyfile("/mnt/nvrofs/nvroall.bin", "/mnt/nvrofs2/nvroall.bin"); |
| if (ret != 0) |
| { |
| printf("[error]cpnv nvrofs2 copyfile\n"); |
| goto out_err; |
| } |
| ret = file_hash("/mnt/nvrofs2/nvroall.bin", "/mnt/nvrofs2/nvroall.bin.hash"); |
| if (ret != 0) |
| { |
| printf("[error]cpnv file_hash\n"); |
| goto out_err; |
| } |
| ret = nvrofs2_umount(); |
| if (ret < 0) |
| { |
| printf("[error]cpnv nvrofs2_umount\n"); |
| return CPNV_ERROR; |
| } |
| |
| ret = flags_set_nvroflag(NVRO_BACKED_UP); |
| if (ret != 0) |
| { |
| printf("[error]cpnv NVRO_BACKED_UP\n"); |
| return CPNV_ERROR; |
| } |
| return CPNV_OK; |
| |
| out_err: |
| nvrofs2_umount(); |
| |
| return CPNV_ERROR; |
| } |
| |
| unsigned int cpnv_NvroRestore(void) |
| { |
| int ret; |
| unsigned int ret_u; |
| unsigned int nvro_flag; |
| |
| nvro_flag = flags_get_nvroflag(); |
| if (nvro_flag != NVRO_RESTORING) |
| { |
| printf("[error]cpnv_NvroRestore nvro flag error\n"); |
| return CPNV_ERROR; |
| } |
| nvrofs2_umount(); |
| ret = nvrofs2_mount(0); |
| if (ret != 0) |
| { |
| printf("[error]cpnv nvrofs2_mount\n"); |
| return CPNV_ERROR; |
| } |
| ret = file_hash_check("/mnt/nvrofs2/nvroall.bin", "/mnt/nvrofs2/nvroall.bin.hash"); |
| if (ret != 0) |
| { |
| printf("[error]cpnv file_hash_check\n"); |
| goto out_err; |
| } |
| ret_u = cpnv_ChangeFsPartitionAttr(FS_NVROFS, 1); |
| if (ret_u != CPNV_OK) |
| { |
| printf("[error]cpnv nvrofs Attr 1\n"); |
| goto out_err; |
| } |
| ret = copyfile("/mnt/nvrofs2/nvroall.bin", "/mnt/nvrofs/nvroall.bin"); |
| if (ret != 0) |
| { |
| printf("[error]cpnv nvrofs2 restore copyfile\n"); |
| goto out_err; |
| } |
| ret_u = cpnv_ChangeFsPartitionAttr(FS_NVROFS, 0); |
| if (ret_u != CPNV_OK) |
| { |
| printf("[error]cpnv nvrofs Attr 0\n"); |
| goto out_err; |
| } |
| ret = nvrofs2_umount(); |
| if (ret < 0) |
| { |
| printf("[error]cpnv nvrofs2_umount\n"); |
| return CPNV_ERROR; |
| } |
| ret = flags_set_nvroflag(NVRO_BACKED_UP); |
| if (ret != 0) |
| { |
| printf("[error]cpnv_NvroRestore set NVRO_BACKED_UP\n"); |
| return CPNV_ERROR; |
| } |
| return CPNV_OK; |
| |
| out_err: |
| nvrofs2_umount(); |
| flags_set_nvroflag(NVRO_BACKED_UP); |
| |
| return CPNV_ERROR; |
| } |