初始提交卡包 USB 工程
纳入固件源码、屏幕组件、nand_xfer 工具和文档。忽略本机构建产物、sdkconfig,以及含本机路径的依赖锁。 Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -0,0 +1,438 @@
|
||||
//version 1.0.1
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#include "esp_log.h"
|
||||
#include "MINIZ/miniz.h"
|
||||
#include <stdbool.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_task_wdt.h"
|
||||
#include "event.h"
|
||||
#include <errno.h>
|
||||
static const char *TAG_ZIP = "ZIP_EXTRACTOR";
|
||||
|
||||
/* 最近一次解压成功对应的表情包 ID(如 'A'/'B'),供 main 识别下载成功并播放 */
|
||||
static char s_last_downloaded_pack_id = '0';
|
||||
|
||||
char zip_extractor_get_last_downloaded_pack(void)
|
||||
{
|
||||
return s_last_downloaded_pack_id;
|
||||
}
|
||||
|
||||
void extract_zip_file(const char* zip_path, const char* extract_dir);
|
||||
// static mz_bool extract_file_with_callback(mz_zip_archive* zip_archive, mz_uint file_index, const char* output_path);
|
||||
// static mz_bool extract_file_low_memory(mz_zip_archive* zip_archive, mz_uint file_index, const char* output_path);
|
||||
// static void check_memory_status(void);
|
||||
// void extract_zip_file_optimized(const char* zip_path, const char* extract_dir);
|
||||
|
||||
const char* get_zip_error_string(mz_zip_error error);
|
||||
void extract_zip_file(const char* zip_path, const char* extract_dir);
|
||||
// 创建目录的函数
|
||||
static int create_directory(const char *path) {
|
||||
char dir_path[256];
|
||||
char *p;
|
||||
|
||||
strncpy(dir_path, path, sizeof(dir_path) - 1);
|
||||
dir_path[sizeof(dir_path) - 1] = '\0';
|
||||
|
||||
// 逐级创建目录
|
||||
for (p = dir_path + 1; *p; p++) {
|
||||
if (*p == '/') {
|
||||
*p = '\0';
|
||||
mkdir(dir_path, 0755); // 创建目录,忽略错误(目录可能已存在)
|
||||
*p = '/';
|
||||
}
|
||||
}
|
||||
printf("%s\n0",dir_path);
|
||||
return mkdir(dir_path, 0755); // 创建最终目录
|
||||
}
|
||||
|
||||
// 检查文件是否存在
|
||||
static bool file_exists(const char *path) {
|
||||
struct stat st;
|
||||
return (stat(path, &st) == 0);
|
||||
}
|
||||
|
||||
// // 从文件路径中提取目录部分
|
||||
static void extract_directory(const char *filepath, char *dir_path, size_t dir_path_size) {
|
||||
const char *last_slash = strrchr(filepath, '/');
|
||||
printf("%s\n",last_slash);
|
||||
if (last_slash) {
|
||||
size_t dir_len = last_slash - filepath;
|
||||
if (dir_len < dir_path_size - 1) {
|
||||
strncpy(dir_path, filepath, dir_len);
|
||||
printf("%d\n",dir_len);
|
||||
dir_path[dir_len] = '\0';
|
||||
} else {
|
||||
dir_path[0] = '\0';
|
||||
}
|
||||
} else {
|
||||
// 没有目录,只有文件名
|
||||
dir_path[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
void extract_zip_file(const char* zip_path, const char* extract_dir) {
|
||||
ESP_LOGI(TAG_ZIP, "开始解压ZIP文件: %s 到目录: %s", zip_path, extract_dir);
|
||||
|
||||
// 使用静态或堆分配的大缓冲区,避免栈分配
|
||||
mz_zip_archive* zip_archive = (mz_zip_archive*)malloc(sizeof(mz_zip_archive));
|
||||
mz_zip_zero_struct(zip_archive); // 使用 miniz 的专用初始化函数
|
||||
if (zip_archive == NULL) {
|
||||
ESP_LOGE(TAG_ZIP, "内存不足");
|
||||
return;
|
||||
}
|
||||
ESP_LOGI(TAG_ZIP, "Main task stack free: %d", uxTaskGetStackHighWaterMark(NULL));
|
||||
ESP_LOGW(TAG_ZIP, "内存足够");
|
||||
// 1. 初始化ZIP读取器
|
||||
if (!mz_zip_reader_init_file(zip_archive, zip_path, 0)) {
|
||||
ESP_LOGE(TAG_ZIP, "无法初始化ZIP读取器: %s", zip_path);
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG_ZIP, "ZIP文件打开成功");
|
||||
|
||||
// 2. 获取文件数量
|
||||
mz_uint num_files = mz_zip_reader_get_num_files(zip_archive);
|
||||
ESP_LOGI(TAG_ZIP, "ZIP文件中包含 %u 个文件", num_files);
|
||||
|
||||
// 使用堆分配路径缓冲区,避免大数组在栈上
|
||||
char *output_path = malloc(1024);
|
||||
char *dir_path = malloc(1024);
|
||||
|
||||
if (!output_path || !dir_path) {
|
||||
ESP_LOGE(TAG_ZIP, "内存分配失败");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// 3. 遍历并解压每个文件
|
||||
for (mz_uint i = 0; i < num_files; i++) {
|
||||
mz_zip_archive_file_stat file_stat;
|
||||
if (mz_zip_reader_file_stat(zip_archive, i, &file_stat)) {
|
||||
// 跳过目录条目
|
||||
if (mz_zip_reader_is_file_a_directory(zip_archive, i)) {
|
||||
ESP_LOGI(TAG_ZIP, "跳过目录: %s", file_stat.m_filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG_ZIP, "处理文件: %s (大小: %llu 字节)",
|
||||
file_stat.m_filename, file_stat.m_uncomp_size);
|
||||
|
||||
// 构建完整的输出文件路径
|
||||
snprintf(output_path, 1024, "%s/%s", extract_dir, file_stat.m_filename);
|
||||
//char *underscore = strchr(output_path, '_');
|
||||
//if (underscore) *underscore = '\0';
|
||||
// 检查并创建必要的目录
|
||||
extract_directory(output_path, dir_path, 1024);
|
||||
if (strlen(dir_path) > 0) {
|
||||
create_directory(dir_path);
|
||||
}
|
||||
|
||||
char* last_slash = strrchr(output_path, '/');
|
||||
|
||||
if (last_slash != NULL) {
|
||||
// 斜杠后面的部分就是文件名
|
||||
char* filename = last_slash + 1;
|
||||
printf("文件名: %s\n", filename);
|
||||
snprintf(output_path, 512, "%s/%s", extract_dir, filename);
|
||||
} else {
|
||||
printf("没有找到斜杠\n");
|
||||
}
|
||||
FILE *f = fopen(output_path, "wb");
|
||||
if (!f) {
|
||||
ESP_LOGE("FILE", "无法打开文件: %s, errno=%d (%s)", output_path, errno, strerror(errno));
|
||||
return;
|
||||
}
|
||||
// printf("%s0\n",output_path);
|
||||
// FILE* f = fopen(output_path, "wb");
|
||||
fclose(f);
|
||||
//taskENTER_CRITICAL();
|
||||
/*
|
||||
FILE* f = fopen(output_path, "wb");
|
||||
if (!f) {
|
||||
ESP_LOGE("FILE", "无法打开文件: %s", output_path);
|
||||
return;
|
||||
}
|
||||
// 验证文件指针
|
||||
if (fseek(f, 0, SEEK_SET) != 0) {
|
||||
ESP_LOGE("FILE", "文件指针无效: %s", output_path);
|
||||
fclose(f);
|
||||
return;
|
||||
}*/
|
||||
// ESP_LOGI("FILE", "文件打开成功: %p, 路径: %s", f, output_path);
|
||||
// void*ff = (void*)f;
|
||||
// ESP_LOGI("void*addr", "文件打开成功: %p, 路径: %s", ff, output_path);
|
||||
// FILE* fff = (FILE*)ff;
|
||||
// ESP_LOGI("FILE", "文件打开成功: %p, 路径: %s", fff, output_path);
|
||||
|
||||
//fclose(f);
|
||||
mz_bool result = mz_zip_reader_extract_to_file(zip_archive, i, output_path, MZ_ZIP_FLAG_CASE_SENSITIVE | MZ_ZIP_FLAG_IGNORE_PATH);
|
||||
|
||||
// 8. 检查解压结果
|
||||
if (!result) {
|
||||
mz_zip_error error = mz_zip_get_last_error(zip_archive);
|
||||
ESP_LOGE(TAG_ZIP, "解压失败, 错误: %s (%d)",
|
||||
get_zip_error_string(error), error);
|
||||
|
||||
// 根据错误类型提供具体建议
|
||||
switch (error) {
|
||||
case MZ_ZIP_NO_ERROR:
|
||||
ESP_LOGI(TAG_ZIP, "操作成功完成");
|
||||
break;
|
||||
case MZ_ZIP_FILE_OPEN_FAILED:
|
||||
ESP_LOGE(TAG_ZIP, "建议: 检查文件路径、权限或磁盘空间,确认文件存在");
|
||||
break;
|
||||
case MZ_ZIP_FILE_CREATE_FAILED:
|
||||
ESP_LOGE(TAG_ZIP, "建议: 检查输出目录权限和磁盘空间");
|
||||
break;
|
||||
case MZ_ZIP_FILE_WRITE_FAILED:
|
||||
ESP_LOGE(TAG_ZIP, "建议: 磁盘空间不足或文件系统只读");
|
||||
break;
|
||||
case MZ_ZIP_FILE_READ_FAILED:
|
||||
ESP_LOGE(TAG_ZIP, "建议: 文件可能被占用或损坏");
|
||||
break;
|
||||
case MZ_ZIP_DECOMPRESSION_FAILED:
|
||||
ESP_LOGE(TAG_ZIP, "建议: ZIP文件可能已损坏或使用不支持的压缩算法");
|
||||
break;
|
||||
case MZ_ZIP_CRC_CHECK_FAILED:
|
||||
ESP_LOGE(TAG_ZIP, "建议: 文件校验失败,可能下载不完整或被修改");
|
||||
break;
|
||||
case MZ_ZIP_UNSUPPORTED_METHOD:
|
||||
ESP_LOGE(TAG_ZIP, "建议: 使用不支持的压缩方法,尝试使用标准ZIP格式");
|
||||
break;
|
||||
case MZ_ZIP_UNSUPPORTED_ENCRYPTION:
|
||||
ESP_LOGE(TAG_ZIP, "建议: 不支持加密的ZIP文件");
|
||||
break;
|
||||
case MZ_ZIP_ALLOC_FAILED:
|
||||
ESP_LOGE(TAG_ZIP, "建议: 系统内存不足,关闭其他应用或减小文件大小");
|
||||
break;
|
||||
case MZ_ZIP_BUF_TOO_SMALL:
|
||||
ESP_LOGE(TAG_ZIP, "建议: 缓冲区太小,增加缓冲区大小");
|
||||
break;
|
||||
case MZ_ZIP_INVALID_HEADER_OR_CORRUPTED:
|
||||
ESP_LOGE(TAG_ZIP, "建议: ZIP文件头损坏或不是有效的ZIP文件");
|
||||
break;
|
||||
case MZ_ZIP_NOT_AN_ARCHIVE:
|
||||
ESP_LOGE(TAG_ZIP, "建议: 文件不是有效的ZIP归档文件");
|
||||
break;
|
||||
case MZ_ZIP_FILE_TOO_LARGE:
|
||||
ESP_LOGE(TAG_ZIP, "建议: 文件太大,超出系统限制");
|
||||
break;
|
||||
case MZ_ZIP_ARCHIVE_TOO_LARGE:
|
||||
ESP_LOGE(TAG_ZIP, "建议: 归档文件总体积太大");
|
||||
break;
|
||||
case MZ_ZIP_TOO_MANY_FILES:
|
||||
ESP_LOGE(TAG_ZIP, "建议: 归档内文件数量过多");
|
||||
break;
|
||||
case MZ_ZIP_FAILED_FINDING_CENTRAL_DIR:
|
||||
ESP_LOGE(TAG_ZIP, "建议: 无法找到中央目录,ZIP文件不完整");
|
||||
break;
|
||||
case MZ_ZIP_UNSUPPORTED_MULTIDISK:
|
||||
ESP_LOGE(TAG_ZIP, "建议: 不支持多卷ZIP文件");
|
||||
break;
|
||||
case MZ_ZIP_WRITE_CALLBACK_FAILED:
|
||||
ESP_LOGE(TAG_ZIP, "建议: 写回调函数失败,检查文件系统状态");
|
||||
break;
|
||||
case MZ_ZIP_FILE_SEEK_FAILED:
|
||||
ESP_LOGE(TAG_ZIP, "建议: 文件定位失败,可能文件被截断");
|
||||
break;
|
||||
case MZ_ZIP_INVALID_FILENAME:
|
||||
ESP_LOGE(TAG_ZIP, "建议: 文件名包含非法字符或路径过长");
|
||||
break;
|
||||
case MZ_ZIP_INVALID_PARAMETER:
|
||||
ESP_LOGE(TAG_ZIP, "建议: 函数参数无效,检查调用代码");
|
||||
break;
|
||||
case MZ_ZIP_FILE_NOT_FOUND:
|
||||
ESP_LOGE(TAG_ZIP, "建议: 指定的文件不存在");
|
||||
break;
|
||||
case MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE:
|
||||
ESP_LOGE(TAG_ZIP, "建议: 解压后大小与预期不符,文件可能损坏");
|
||||
break;
|
||||
case MZ_ZIP_COMPRESSION_FAILED:
|
||||
ESP_LOGE(TAG_ZIP, "建议: 压缩过程失败");
|
||||
break;
|
||||
case MZ_ZIP_FILE_CLOSE_FAILED:
|
||||
ESP_LOGE(TAG_ZIP, "建议: 文件关闭失败,可能磁盘错误");
|
||||
break;
|
||||
case MZ_ZIP_FILE_STAT_FAILED:
|
||||
ESP_LOGE(TAG_ZIP, "建议: 无法获取文件状态信息");
|
||||
break;
|
||||
case MZ_ZIP_VALIDATION_FAILED:
|
||||
ESP_LOGE(TAG_ZIP, "建议: ZIP文件验证失败");
|
||||
break;
|
||||
case MZ_ZIP_UNDEFINED_ERROR:
|
||||
case MZ_ZIP_INTERNAL_ERROR:
|
||||
case MZ_ZIP_TOTAL_ERRORS:
|
||||
default:
|
||||
ESP_LOGE(TAG_ZIP, "建议: 检查系统资源、文件完整性和库版本");
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 直接解压到文件
|
||||
// if (mz_zip_reader_extract_to_file(&zip_archive, i, output_path, 0)) {
|
||||
// ESP_LOGI(TAG, "成功解压到: %s", output_path);
|
||||
// }
|
||||
else {
|
||||
ESP_LOGI(TAG_ZIP, "解压成功: %s", output_path);
|
||||
}
|
||||
// 让出CPU,避免长时间占用
|
||||
if (i % 5 == 0) {
|
||||
vTaskDelay(pdMS_TO_TICKS(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
free(output_path);
|
||||
free(dir_path);
|
||||
|
||||
// 4. 结束读取
|
||||
if (!mz_zip_reader_end(zip_archive)) {
|
||||
ESP_LOGE(TAG_ZIP, "[EMOJI_DEBUG] ZIP读取器结束失败");
|
||||
set_system_event(DOWNLOAD_FAILED_BIT);
|
||||
ESP_LOGE(TAG_ZIP, "[EMOJI_DEBUG] 已设置 DOWNLOAD_FAILED_BIT");
|
||||
} else {
|
||||
ESP_LOGI(TAG_ZIP, "[EMOJI_DEBUG] ZIP解压完成, extract_dir=%s", extract_dir);
|
||||
const char *last_slash = strrchr(extract_dir, '/');
|
||||
ESP_LOGI(TAG_ZIP, "[EMOJI_DEBUG] strrchr(extract_dir, '/') = %s", last_slash ? last_slash : "NULL");
|
||||
if (last_slash && *(last_slash + 1))
|
||||
{
|
||||
s_last_downloaded_pack_id = *(last_slash + 1);
|
||||
ESP_LOGI(TAG_ZIP, "[EMOJI_DEBUG] 从目录名解析 pack_id='%c'", s_last_downloaded_pack_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
s_last_downloaded_pack_id = '0';
|
||||
ESP_LOGW(TAG_ZIP, "[EMOJI_DEBUG] 无法从目录名解析 pack_id, 设为 '0'");
|
||||
}
|
||||
|
||||
/* 列出解压目录下的文件,确认解压结果 */
|
||||
DIR *dir = opendir(extract_dir);
|
||||
if (dir)
|
||||
{
|
||||
struct dirent *ent;
|
||||
int file_count = 0;
|
||||
ESP_LOGI(TAG_ZIP, "[EMOJI_DEBUG] 解压目录 %s 文件列表:", extract_dir);
|
||||
while ((ent = readdir(dir)) != NULL)
|
||||
{
|
||||
if (ent->d_name[0] == '.') continue;
|
||||
ESP_LOGI(TAG_ZIP, "[EMOJI_DEBUG] - %s", ent->d_name);
|
||||
file_count++;
|
||||
}
|
||||
closedir(dir);
|
||||
ESP_LOGI(TAG_ZIP, "[EMOJI_DEBUG] 解压目录共 %d 个文件", file_count);
|
||||
|
||||
char default_check[128];
|
||||
snprintf(default_check, sizeof(default_check), "%s/default.json", extract_dir);
|
||||
struct stat st;
|
||||
if (stat(default_check, &st) == 0)
|
||||
{
|
||||
ESP_LOGI(TAG_ZIP, "[EMOJI_DEBUG] default.json 存在, 大小=%ld bytes", (long)st.st_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGW(TAG_ZIP, "[EMOJI_DEBUG] default.json 不存在于 %s !", extract_dir);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(TAG_ZIP, "[EMOJI_DEBUG] 无法打开解压目录 %s", extract_dir);
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG_ZIP, "[EMOJI_DEBUG] 准备设置 DOWNLOAD_SUCCESS_BIT, pack_id='%c'", s_last_downloaded_pack_id);
|
||||
set_system_event(DOWNLOAD_SUCCESS_BIT);
|
||||
ESP_LOGI(TAG_ZIP, "[EMOJI_DEBUG] DOWNLOAD_SUCCESS_BIT 已设置");
|
||||
}
|
||||
free(zip_archive);
|
||||
}
|
||||
|
||||
const char* get_zip_error_string(mz_zip_error error) {
|
||||
switch (error) {
|
||||
case MZ_ZIP_NO_ERROR: return "MZ_ZIP_NO_ERROR";
|
||||
case MZ_ZIP_UNDEFINED_ERROR: return "MZ_ZIP_UNDEFINED_ERROR";
|
||||
case MZ_ZIP_TOO_MANY_FILES: return "MZ_ZIP_TOO_MANY_FILES";
|
||||
case MZ_ZIP_FILE_TOO_LARGE: return "MZ_ZIP_FILE_TOO_LARGE";
|
||||
case MZ_ZIP_UNSUPPORTED_METHOD: return "MZ_ZIP_UNSUPPORTED_METHOD";
|
||||
case MZ_ZIP_UNSUPPORTED_ENCRYPTION: return "MZ_ZIP_UNSUPPORTED_ENCRYPTION";
|
||||
case MZ_ZIP_UNSUPPORTED_FEATURE: return "MZ_ZIP_UNSUPPORTED_FEATURE";
|
||||
case MZ_ZIP_FAILED_FINDING_CENTRAL_DIR: return "MZ_ZIP_FAILED_FINDING_CENTRAL_DIR";
|
||||
case MZ_ZIP_NOT_AN_ARCHIVE: return "MZ_ZIP_NOT_AN_ARCHIVE";
|
||||
case MZ_ZIP_INVALID_HEADER_OR_CORRUPTED: return "MZ_ZIP_INVALID_HEADER_OR_CORRUPTED";
|
||||
case MZ_ZIP_UNSUPPORTED_MULTIDISK: return "MZ_ZIP_UNSUPPORTED_MULTIDISK";
|
||||
case MZ_ZIP_DECOMPRESSION_FAILED: return "MZ_ZIP_DECOMPRESSION_FAILED";
|
||||
case MZ_ZIP_COMPRESSION_FAILED: return "MZ_ZIP_COMPRESSION_FAILED";
|
||||
case MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE: return "MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE";
|
||||
case MZ_ZIP_CRC_CHECK_FAILED: return "MZ_ZIP_CRC_CHECK_FAILED";
|
||||
case MZ_ZIP_UNSUPPORTED_CDIR_SIZE: return "MZ_ZIP_UNSUPPORTED_CDIR_SIZE";
|
||||
case MZ_ZIP_ALLOC_FAILED: return "MZ_ZIP_ALLOC_FAILED";
|
||||
case MZ_ZIP_FILE_OPEN_FAILED: return "MZ_ZIP_FILE_OPEN_FAILED";
|
||||
case MZ_ZIP_FILE_CREATE_FAILED: return "MZ_ZIP_FILE_CREATE_FAILED";
|
||||
case MZ_ZIP_FILE_WRITE_FAILED: return "MZ_ZIP_FILE_WRITE_FAILED";
|
||||
case MZ_ZIP_FILE_READ_FAILED: return "MZ_ZIP_FILE_READ_FAILED";
|
||||
case MZ_ZIP_FILE_CLOSE_FAILED: return "MZ_ZIP_FILE_CLOSE_FAILED";
|
||||
case MZ_ZIP_FILE_SEEK_FAILED: return "MZ_ZIP_FILE_SEEK_FAILED";
|
||||
case MZ_ZIP_FILE_STAT_FAILED: return "MZ_ZIP_FILE_STAT_FAILED";
|
||||
case MZ_ZIP_INVALID_PARAMETER: return "MZ_ZIP_INVALID_PARAMETER";
|
||||
case MZ_ZIP_INVALID_FILENAME: return "MZ_ZIP_INVALID_FILENAME";
|
||||
case MZ_ZIP_BUF_TOO_SMALL: return "MZ_ZIP_BUF_TOO_SMALL";
|
||||
case MZ_ZIP_INTERNAL_ERROR: return "MZ_ZIP_INTERNAL_ERROR";
|
||||
case MZ_ZIP_FILE_NOT_FOUND: return "MZ_ZIP_FILE_NOT_FOUND";
|
||||
case MZ_ZIP_ARCHIVE_TOO_LARGE: return "MZ_ZIP_ARCHIVE_TOO_LARGE";
|
||||
case MZ_ZIP_VALIDATION_FAILED: return "MZ_ZIP_VALIDATION_FAILED";
|
||||
case MZ_ZIP_WRITE_CALLBACK_FAILED: return "MZ_ZIP_WRITE_CALLBACK_FAILED";
|
||||
default: return "UNKNOWN_ERROR";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void extract_json_zip(char* filename) {
|
||||
ESP_LOGI(TAG_ZIP, "[EMOJI_DEBUG] ===== extract_json_zip 开始 =====");
|
||||
ESP_LOGI(TAG_ZIP, "[EMOJI_DEBUG] filename=%s", filename ? filename : "NULL");
|
||||
|
||||
if (!filename || filename[0] == '\0') {
|
||||
ESP_LOGE(TAG_ZIP, "[EMOJI_DEBUG] extract_json_zip: filename 为空");
|
||||
return;
|
||||
}
|
||||
char zip_file_path[64] = {0};
|
||||
char extract_directory[96] = {0};
|
||||
const char *base = strrchr(filename, '/');
|
||||
if (base)
|
||||
base++;
|
||||
else
|
||||
base = filename;
|
||||
|
||||
ESP_LOGI(TAG_ZIP, "[EMOJI_DEBUG] base (去除路径后)=%s", base);
|
||||
|
||||
snprintf(zip_file_path, sizeof(zip_file_path), "%s/%s", "/extflash", filename);
|
||||
char pack_name[16] = {0};
|
||||
size_t blen = strlen(base);
|
||||
if (blen > 4 && strcasecmp(base + blen - 4, ".zip") == 0) {
|
||||
strncpy(pack_name, base, blen - 4);
|
||||
pack_name[blen - 4] = '\0';
|
||||
} else {
|
||||
strncpy(pack_name, base, sizeof(pack_name) - 1);
|
||||
pack_name[sizeof(pack_name) - 1] = '\0';
|
||||
}
|
||||
snprintf(extract_directory, sizeof(extract_directory), "%s/%s", "/extflash", pack_name);
|
||||
|
||||
ESP_LOGI(TAG_ZIP, "[EMOJI_DEBUG] zip_file_path=%s", zip_file_path);
|
||||
ESP_LOGI(TAG_ZIP, "[EMOJI_DEBUG] pack_name=%s", pack_name);
|
||||
ESP_LOGI(TAG_ZIP, "[EMOJI_DEBUG] extract_directory=%s", extract_directory);
|
||||
|
||||
struct stat st;
|
||||
if (stat(zip_file_path, &st) != 0) {
|
||||
ESP_LOGE(TAG_ZIP, "[EMOJI_DEBUG] ZIP文件不存在: %s", zip_file_path);
|
||||
set_system_event(DOWNLOAD_FAILED_BIT);
|
||||
return;
|
||||
}
|
||||
ESP_LOGI(TAG_ZIP, "[EMOJI_DEBUG] 找到ZIP文件, 大小=%ld bytes", (long)st.st_size);
|
||||
|
||||
int mk_ret = mkdir(extract_directory, 0755);
|
||||
ESP_LOGI(TAG_ZIP, "[EMOJI_DEBUG] mkdir(%s) 返回: %d", extract_directory, mk_ret);
|
||||
|
||||
extract_zip_file(zip_file_path, extract_directory);
|
||||
ESP_LOGI(TAG_ZIP, "[EMOJI_DEBUG] ===== extract_json_zip 结束 =====");
|
||||
}
|
||||
Reference in New Issue
Block a user