blob: 0e5880c6e2ced4efe9e2cdd90df39ba4ec6b5364 [file] [log] [blame]
#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)
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);
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;
}
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();
return CPNV_ERROR;
}