| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <string.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <fcntl.h> |
| |
| #include <mtd/mtd-abi.h> |
| #include <errno.h> |
| |
| #include <sys/ioctl.h> |
| #include "mtd_api.h" |
| |
| #define MTD_PATH_LENGTH_MAX (256) |
| |
| static ssize_t readn(int fd, void *vptr, size_t n); |
| static ssize_t writen(int fd, const void *vptr, size_t n); |
| |
| /******************************************************************************* |
| * 内部函数/mtd_private.h * |
| *******************************************************************************/ |
| /** |
| * @brief 从文件描述符读取数据 |
| * @param fd 入参,文件描述符 |
| * @param vptr 出参,数据缓冲区 |
| * @param n 入参,内容字节数 |
| * @return 成功返回成功读取的字节数,失败返回-1 |
| * @retval |
| * @note 封装read接口,读取被打断时会重试直到全部读取成功 |
| * @warning |
| */ |
| static ssize_t readn(int fd, void *vptr, size_t n) |
| { |
| size_t nleft; |
| ssize_t nread; |
| char *ptr; |
| |
| ptr = vptr; |
| nleft = n; |
| while (nleft > 0) |
| { |
| if ((nread = read(fd, ptr, nleft)) < 0) |
| { |
| if (errno == EINTR) |
| { |
| nread = 0; /* and call read() again */ |
| } |
| else |
| { |
| return (-1); |
| } |
| } |
| else if (nread == 0) |
| { |
| break; /* EOF */ |
| } |
| |
| nleft -= nread; |
| ptr += nread; |
| } |
| return (n - nleft); /* return >= 0 */ |
| } |
| |
| /** |
| * @brief 向文件描述符写入数据 |
| * @param fd 入参,文件描述符 |
| * @param vptr 入参,数据缓冲区 |
| * @param n 入参,内容字节数 |
| * @return 成功返回成功写入的字节数,失败返回-1 |
| * @retval |
| * @note 封装write接口,写入被打断时会重试直到全部写入成功 |
| * @warning |
| */ |
| static ssize_t writen(int fd, const void *vptr, size_t n) |
| { |
| size_t nleft; |
| ssize_t nwritten; |
| const char *ptr; |
| |
| ptr = vptr; |
| nleft = n; |
| while (nleft > 0) |
| { |
| nwritten = write(fd, ptr, nleft); |
| if (nwritten < 0) |
| { |
| if (errno == EINTR) |
| { |
| nwritten = 0; /* call write() again */ |
| } |
| else |
| { |
| return (-1); /* error */ |
| } |
| } |
| else if (nwritten == 0) |
| { |
| break; |
| } |
| |
| nleft -= nwritten; |
| ptr += nwritten; |
| } |
| return (n - nleft); /* return >= 0 */ |
| } |
| |
| /******************************************************************************* |
| * 外部函数定义 * |
| *******************************************************************************/ |
| int mtd_find(const char *i_parti_name, device_type_t device_type, char *o_mtd_path, unsigned int o_mtd_path_len) |
| { |
| FILE *fp_mtd = 0; |
| char buf[128]; |
| char *line_str; |
| |
| if (!o_mtd_path_len) |
| { |
| return -1; |
| } |
| |
| fp_mtd = fopen("/proc/mtd", "r+"); |
| if (NULL == fp_mtd) |
| { |
| printf("[libmtd]: mtd_find, open file error:%s", strerror(errno)); |
| return -1; |
| } |
| // printf("[libmtd]: 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, 0, sizeof(buf)); |
| line_str = fgets(buf, sizeof(buf) - 1, fp_mtd); |
| |
| if (NULL == line_str) |
| { |
| printf("[libmtd]: mtd_find, get info from mtd error:%s\n", strerror(errno)); |
| fclose(fp_mtd); |
| return -1; |
| } |
| // 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, 0, 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("[libmtd]: mtd_find, unknown device type %d\n", device_type); |
| fclose(fp_mtd); |
| return -1; |
| } |
| // printf("[libmtd]: o_mtd_path=[%s]\n", o_mtd_path); |
| break; |
| } |
| } |
| fclose(fp_mtd); |
| return 0; |
| } |
| |
| int mtd_get_info(int fd, struct mtd_info_user *info) |
| { |
| if (0 != ioctl(fd, MEMGETINFO, info)) |
| { |
| printf("[libmtd]: mtd_get_info, get fd(%d) info error, %s\n", fd, strerror(errno)); |
| return -1; |
| } |
| return 0; |
| } |
| |
| int mtd_block_isbad(int fd, off_t offset) |
| { |
| int ret = 0; |
| ret = ioctl(fd, MEMGETBADBLOCK, &offset); |
| if (ret > 0) |
| { |
| printf("[libmtd]: mtd_block_isbad, bad block at 0x%lx, ret = %d\n", offset, ret); |
| ret = 1; |
| } |
| else if (ret < 0) |
| { |
| printf("[libmtd]: mtd_block_isbad, ioctl(MEMGETBADBLOCK) error at 0x%lx, %s, ret = %d\n", offset, strerror(errno), ret); |
| ret = -1; |
| } |
| return ret; |
| } |
| |
| int mtd_erase_partition(const char *partition_name) |
| { |
| int ret = 0; |
| char mtd_path[MTD_PATH_LENGTH_MAX] = {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, DEVICE_MTD, mtd_path, MTD_PATH_LENGTH_MAX); |
| if (ret < 0) |
| { |
| printf("[libmtd]: mtd_erase_partition, mtd_find %s failed\n", partition_name); |
| ret = -1; |
| goto out; |
| } |
| fd_mtd = open(mtd_path, O_RDWR); |
| if (fd_mtd < 0) |
| { |
| printf("[libmtd]: mtd_erase_partition, open %s error, %s\n", partition_name, strerror(errno)); |
| return -1; |
| } |
| ret = mtd_get_info(fd_mtd, &meminfo); |
| if (ret < 0) |
| { |
| printf("[libmtd]: mtd_erase_partition, 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) |
| { |
| ret = mtd_block_isbad(fd_mtd, erase_info.start); |
| if (1 == ret) |
| { |
| continue; |
| } |
| else if (-1 == ret) |
| { |
| printf("[libmtd]: mtd_erase_partition, mtd_block_isbad %s error\n", partition_name); |
| goto out; |
| } |
| |
| if (0 != ioctl(fd_mtd, MEMERASE64, &erase_info)) |
| { |
| printf("[libmtd]: mtd_erase_partition, erasing %s failure at 0x%llx\n", partition_name, erase_info.start); |
| if (ioctl(fd_mtd, MEMSETBADBLOCK, &(erase_info.start)) < 0) |
| { |
| printf("[libmtd]: mtd_erase_partition, mark %s bad block error, %s\n", partition_name, strerror(errno)); |
| ret = -1; |
| goto out; |
| } |
| continue; |
| } |
| } |
| 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; |
| ssize_t wr_len; |
| char mtd_path[MTD_PATH_LENGTH_MAX] = {0}; |
| int fd_mtd = -1; |
| struct mtd_info_user meminfo = {0}; |
| |
| off_t data_size = 0; |
| off_t index = 0; |
| off_t fd_img_index = 0; |
| int fd_img = -1; |
| char *buf = NULL; |
| struct stat statbuff = {0}; |
| |
| if (NULL == partition_name || NULL == image_file) |
| { |
| return -1; |
| } |
| |
| ret = mtd_find(partition_name, DEVICE_MTD, mtd_path, MTD_PATH_LENGTH_MAX); |
| if (ret < 0) |
| { |
| printf("[libmtd]: mtd_write_partition, mtd_find %s failed\n", partition_name); |
| ret = -1; |
| goto out; |
| } |
| fd_mtd = open(mtd_path, O_RDWR); |
| if (fd_mtd < 0) |
| { |
| printf("[libmtd]: mtd_write_partition, open %s error, %s\n", partition_name, strerror(errno)); |
| return -1; |
| } |
| ret = mtd_get_info(fd_mtd, &meminfo); |
| if (ret < 0) |
| { |
| printf("[libmtd]: mtd_write_partition, get %s info error, %s\n", partition_name, strerror(errno)); |
| ret = -1; |
| goto out; |
| } |
| |
| if (stat(image_file, &statbuff) < 0) |
| { |
| printf("[libmtd]: mtd_write_partition, stat %s failed, %s\n", image_file, strerror(errno)); |
| ret = -1; |
| goto out; |
| } |
| |
| fd_img = open(image_file, O_RDONLY); |
| if (fd_img < 0) |
| { |
| printf("[libmtd]: mtd_write_partition, open %s failed, %s\n", image_file, strerror(errno)); |
| ret = -1; |
| goto out; |
| } |
| |
| buf = (char *)malloc(meminfo.erasesize); |
| if (!buf) |
| { |
| printf("[libmtd]: mtd_write_partition, malloc failed\n"); |
| ret = -1; |
| goto out; |
| } |
| |
| for (index = 0; index < meminfo.size && fd_img_index < statbuff.st_size; index += meminfo.erasesize) |
| { |
| ret = mtd_block_isbad(fd_mtd, index); |
| if (1 == ret) |
| { |
| continue; |
| } |
| else if (-1 == ret) |
| { |
| printf("[libmtd]: mtd_write_partition, mtd_block_isbad %s error,at 0x%llx\n", partition_name, index); |
| goto out; |
| } |
| |
| if (lseek(fd_img, fd_img_index, SEEK_SET) < 0) |
| { |
| printf("[libmtd]: mtd_write_partition, lseek %s error = %s!\n", image_file, strerror(errno)); |
| ret = -1; |
| goto out; |
| } |
| if (fd_img_index + meminfo.erasesize > statbuff.st_size) |
| { |
| data_size = statbuff.st_size - fd_img_index; |
| } |
| else |
| { |
| data_size = meminfo.erasesize; |
| } |
| wr_len = readn(fd_img, buf, (size_t)data_size); |
| if (wr_len < 0) |
| { |
| printf("[libmtd]: mtd_write_partition, read %s error, %s\n", image_file, strerror(errno)); |
| ret = -1; |
| goto out; |
| } |
| fd_img_index += data_size; |
| |
| if (lseek(fd_mtd, index, SEEK_SET) < 0) |
| { |
| printf("[libmtd]: mtd_write_partition, lseek %s error = %s!\n", partition_name, strerror(errno)); |
| ret = -1; |
| goto out; |
| } |
| wr_len = writen(fd_mtd, buf, (size_t)data_size); |
| if (wr_len < 0) |
| { |
| printf("[libmtd]: mtd_write_partition, write %s error, %s\n", partition_name, strerror(errno)); |
| ret = -1; |
| goto out; |
| } |
| memset(buf, 0xFF, meminfo.erasesize); |
| } |
| if (fd_img_index < statbuff.st_size) |
| { |
| printf("[libmtd]: mtd_write_partition, No space left, writelen=0x%lx, filesize=0x%lx\n", fd_img_index, statbuff.st_size); |
| ret = -1; |
| goto out; |
| } |
| ret = 0; |
| out: |
| if (fd_mtd >= 0) |
| { |
| close(fd_mtd); |
| } |
| |
| if (buf != NULL) |
| { |
| // memset(buf, 0xFF, meminfo.erasesize); |
| free(buf); |
| } |
| |
| if (fd_img >= 0) |
| { |
| close(fd_img); |
| } |
| |
| return ret; |
| } |
| |
| int mtd_erase_offset(int fd, off_t offset) |
| { |
| struct mtd_info_user meminfo = {0}; |
| struct erase_info_user64 erase_info = {0}; |
| |
| if (fd < 0) |
| { |
| printf("[libmtd]: mtd_erase_offset, fd(%d) error\n", fd); |
| return -1; |
| } |
| |
| if (0 != mtd_get_info(fd, &meminfo)) |
| { |
| printf("[libmtd]: mtd_erase_offset, get fd(%d) info error, %s\n", fd, strerror(errno)); |
| return -1; |
| } |
| |
| if (0 != (offset % meminfo.erasesize)) |
| { |
| printf("[libmtd]: mtd_erase_offset, not at the beginning of a block, erasesize is %d\n", meminfo.erasesize); |
| return -1; |
| } |
| |
| erase_info.length = meminfo.erasesize; |
| erase_info.start = offset; |
| |
| if (mtd_block_isbad(fd, erase_info.start)) |
| { |
| return -1; |
| } |
| if (0 != ioctl(fd, MEMERASE64, &erase_info)) |
| { |
| printf("[libmtd]: mtd_erase_offset, erasing failure at 0x%llx\n", erase_info.start); |
| if (ioctl(fd, MEMSETBADBLOCK, &(erase_info.start)) < 0) |
| { |
| printf("[libmtd]: mtd_erase_offset, mark bad block error, %s\n", strerror(errno)); |
| } |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| ssize_t mtd_write_offset(int fd, off_t offset, const void *buf, size_t count) |
| { |
| ssize_t writen_len; |
| struct mtd_info_user meminfo = {0}; |
| |
| if (fd < 0) |
| { |
| return -1; |
| } |
| |
| if (0 != mtd_get_info(fd, &meminfo)) |
| { |
| printf("[libmtd]: mtd_write_offset, get fd(%d) info error, %s\n", fd, strerror(errno)); |
| return -1; |
| } |
| if (count <= 0 || count > meminfo.erasesize) |
| { |
| printf("[libmtd]: mtd_write_offset, count(0x%lx), less than 0, or larger than erasesize(0x%x)\n", count, meminfo.erasesize); |
| return -1; |
| } |
| if (0 != (offset % meminfo.erasesize)) |
| { |
| printf("[libmtd]: mtd_write_offset, not at the beginning of a block, erasesize is 0x%x\n", meminfo.erasesize); |
| return -1; |
| } |
| |
| if (mtd_block_isbad(fd, offset)) |
| { |
| return -1; |
| } |
| |
| if (lseek(fd, offset, SEEK_SET) < 0) |
| { |
| printf("[libmtd]: mtd_write_offset, lseek error = %s!\n", strerror(errno)); |
| return -1; |
| } |
| writen_len = writen(fd, buf, count); |
| if (writen_len != count) |
| { |
| if (-1 == writen_len) |
| { |
| printf("[libmtd]: mtd_write_offset, write error, %s\n", strerror(errno)); |
| } |
| return -1; |
| } |
| |
| return writen_len; |
| } |
| |
| ssize_t mtd_read_offset(int fd, off_t offset, void *buf, size_t count) |
| { |
| ssize_t readn_len; |
| struct mtd_info_user meminfo = {0}; |
| |
| if (fd < 0) |
| { |
| return -1; |
| } |
| |
| if (0 != mtd_get_info(fd, &meminfo)) |
| { |
| printf("[libmtd]: mtd_read_offset, get fd(%d) info error, %s\n", fd, strerror(errno)); |
| return -1; |
| } |
| if (count <= 0 || count > meminfo.erasesize) |
| { |
| printf("[libmtd]: mtd_read_offset, count(0x%lx), less than 0, or larger than erasesize(0x%x)\n", count, meminfo.erasesize); |
| return -1; |
| } |
| if (0 != (offset % meminfo.erasesize)) |
| { |
| printf("[libmtd]: mtd_read_offset, not at the beginning of a block, erasesize is %x\n", meminfo.erasesize); |
| return -1; |
| } |
| |
| if (mtd_block_isbad(fd, offset)) |
| { |
| return -1; |
| } |
| |
| if (lseek(fd, offset, SEEK_SET) < 0) |
| { |
| printf("[libmtd]: mtd_read_offset, lseek error = %s!\n", strerror(errno)); |
| return -1; |
| } |
| readn_len = readn(fd, buf, count); |
| if (readn_len != count) |
| { |
| if (-1 == readn_len) |
| { |
| printf("[libmtd]: mtd_read_offset, read error, %s\n", strerror(errno)); |
| } |
| return -1; |
| } |
| |
| return readn_len; |
| } |
| |
| static int zftl_verify_partition(const char *partition_name, const char *image_file) |
| { |
| int ret = 0; |
| ssize_t rd_len; |
| size_t read_size = 4096; |
| char zftl_path[MTD_PATH_LENGTH_MAX] = {0}; |
| int fd_zftl = -1; |
| struct mtd_info_user meminfo = {0}; |
| |
| off_t data_size = 0; |
| off_t index = 0; |
| off_t fd_img_index = 0; |
| int fd_img = -1; |
| char *buf = NULL; |
| char *buf2 = NULL; |
| struct stat statbuff = {0}; |
| |
| if (NULL == partition_name || NULL == image_file) |
| { |
| return -1; |
| } |
| |
| ret = mtd_find(partition_name, DEVICE_ZFTL, zftl_path, MTD_PATH_LENGTH_MAX); |
| if (ret < 0) |
| { |
| printf("[libmtd]: zftl_verify_partition, mtd_find %s failed\n", partition_name); |
| return -1; |
| } |
| fd_zftl = open(zftl_path, O_RDONLY); |
| if (fd_zftl < 0) |
| { |
| printf("[libmtd]: zftl_verify_partition, open %s error, %s\n", partition_name, strerror(errno)); |
| return -1; |
| } |
| |
| if (stat(image_file, &statbuff) < 0) |
| { |
| printf("[libmtd]: zftl_verify_partition, stat %s failed, %s\n", image_file, strerror(errno)); |
| ret = -1; |
| goto out; |
| } |
| |
| fd_img = open(image_file, O_RDONLY); |
| if (fd_img < 0) |
| { |
| printf("[libmtd]: zftl_verify_partition, open %s failed, %s\n", image_file, strerror(errno)); |
| ret = -1; |
| goto out; |
| } |
| |
| buf = (char *)malloc(read_size); |
| if (!buf) |
| { |
| printf("[libmtd]: zftl_verify_partition, malloc failed\n"); |
| ret = -1; |
| goto out; |
| } |
| buf2 = (char *)malloc(read_size); |
| if (!buf2) |
| { |
| printf("[libmtd]: zftl_verify_partition, malloc2 failed\n"); |
| ret = -1; |
| goto out; |
| } |
| |
| for (index = 0; fd_img_index < statbuff.st_size; index += read_size) |
| { |
| //memset(buf, 0xFF, read_size); |
| |
| if (fd_img_index + read_size > statbuff.st_size) |
| { |
| data_size = statbuff.st_size - fd_img_index; |
| } |
| else |
| { |
| data_size = read_size; |
| } |
| // data_size = (fd_img_index + read_size > statbuff.st_size) ? (statbuff.st_size - fd_img_index) : (read_size); |
| |
| rd_len = readn(fd_img, buf, (size_t)data_size); |
| if (rd_len < 0) |
| { |
| printf("[libmtd]: zftl_verify_partition, read image file %s error, %s\n", image_file, strerror(errno)); |
| ret = -1; |
| goto out; |
| } |
| fd_img_index += data_size; |
| |
| rd_len = readn(fd_zftl, buf2, (size_t)data_size); |
| if (rd_len < 0) |
| { |
| printf("[libmtd]: zftl_verify_partition, read zftl %s error, %s\n", partition_name, strerror(errno)); |
| ret = -1; |
| goto out; |
| } |
| |
| if (memcmp(buf, buf2, (size_t)data_size) != 0) |
| { |
| printf("[libmtd]: zftl_verify_partition, data memcmp %s error\n", partition_name); |
| ret = -1; |
| goto out; |
| } |
| } |
| |
| ret = 0; |
| out: |
| if (fd_zftl >= 0) |
| { |
| //fsync(fd_zftl); |
| close(fd_zftl); |
| } |
| |
| if (buf != NULL) |
| { |
| // memset(buf, 0xFF, meminfo.erasesize); |
| free(buf); |
| } |
| if (buf2 != NULL) |
| { |
| // memset(buf, 0xFF, meminfo.erasesize); |
| free(buf2); |
| } |
| |
| if (fd_img >= 0) |
| { |
| close(fd_img); |
| } |
| if (ret == 0) |
| { |
| printf("[libmtd]: zftl %s verify sucess\n", partition_name); |
| } |
| else |
| { |
| printf("[libmtd]: zftl %s verify fail\n", partition_name); |
| } |
| |
| return ret; |
| } |
| |
| int zftl_write_partition(const char *partition_name, const char *image_file) |
| { |
| int ret = 0; |
| ssize_t wr_len; |
| size_t write_size = 4096; |
| char zftl_path[MTD_PATH_LENGTH_MAX] = {0}; |
| int fd_zftl = -1; |
| struct mtd_info_user meminfo = {0}; |
| |
| off_t data_size = 0; |
| off_t index = 0; |
| off_t fd_img_index = 0; |
| int fd_img = -1; |
| char *buf = NULL; |
| struct stat statbuff = {0}; |
| |
| if (NULL == partition_name || NULL == image_file) |
| { |
| return -1; |
| } |
| |
| ret = mtd_find(partition_name, DEVICE_ZFTL, zftl_path, MTD_PATH_LENGTH_MAX); |
| if (ret < 0) |
| { |
| printf("[libmtd]: zftl_write_partition, mtd_find %s failed\n", partition_name); |
| return -1; |
| } |
| fd_zftl = open(zftl_path, O_RDWR); |
| if (fd_zftl < 0) |
| { |
| printf("[libmtd]: zftl_write_partition, open %s error, %s\n", partition_name, strerror(errno)); |
| return -1; |
| } |
| |
| if (stat(image_file, &statbuff) < 0) |
| { |
| printf("[libmtd]: zftl_write_partition, stat %s failed, %s\n", image_file, strerror(errno)); |
| ret = -1; |
| goto out; |
| } |
| |
| fd_img = open(image_file, O_RDONLY); |
| if (fd_img < 0) |
| { |
| printf("[libmtd]: zftl_write_partition, open %s failed, %s\n", image_file, strerror(errno)); |
| ret = -1; |
| goto out; |
| } |
| |
| buf = (char *)malloc(write_size); |
| if (!buf) |
| { |
| printf("[libmtd]: zftl_write_partition, malloc failed\n"); |
| ret = -1; |
| goto out; |
| } |
| |
| for (index = 0; fd_img_index < statbuff.st_size; index += write_size) |
| { |
| memset(buf, 0xFF, write_size); |
| |
| if (fd_img_index + write_size > statbuff.st_size) |
| { |
| data_size = statbuff.st_size - fd_img_index; |
| } |
| else |
| { |
| data_size = write_size; |
| } |
| // data_size = (fd_img_index + write_size > statbuff.st_size) ? (statbuff.st_size - fd_img_index) : (write_size); |
| |
| wr_len = readn(fd_img, buf, (size_t)data_size); |
| if (wr_len < 0) |
| { |
| printf("[libmtd]: zftl_write_partition, read %s error, %s\n", image_file, strerror(errno)); |
| ret = -1; |
| goto out; |
| } |
| fd_img_index += data_size; |
| |
| wr_len = writen(fd_zftl, buf, (size_t)data_size); |
| if (wr_len < 0) |
| { |
| printf("[libmtd]: zftl_write_partition, write %s error, %s\n", partition_name, strerror(errno)); |
| ret = -1; |
| goto out; |
| } |
| |
| } |
| if (fd_img_index < statbuff.st_size) |
| { |
| printf("[libmtd]: zftl_write_partition, No space left, writelen=0x%lx, filesize=0x%lx\n", fd_img_index, statbuff.st_size); |
| ret = -1; |
| goto out; |
| } |
| ret = 0; |
| out: |
| if (fd_zftl >= 0) |
| { |
| fsync(fd_zftl); |
| close(fd_zftl); |
| } |
| |
| if (buf != NULL) |
| { |
| // memset(buf, 0xFF, meminfo.erasesize); |
| free(buf); |
| } |
| |
| if (fd_img >= 0) |
| { |
| close(fd_img); |
| } |
| |
| if (ret == 0) |
| { |
| //write sucess then do verify |
| ret = zftl_verify_partition(partition_name, image_file); |
| } |
| |
| return ret; |
| } |