This commit is contained in:
刘可亮
2025-10-21 13:59:50 +08:00
parent 33c375efac
commit 3e10f578d3
7070 changed files with 998841 additions and 1402535 deletions

View File

@@ -0,0 +1,265 @@
/*
* Copyright (c) 2025, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Authors: Cui Jiawei <jiawei.cui@artinchip.com>
*/
#include <rtthread.h>
#include <dfs_posix.h>
#include <aic_errno.h>
#include "zip_reader.h"
#include "stdbool.h"
#include "zip_fs.h"
static const struct dfs_file_ops zipfs_fops;
static int zipfs_ops_mount(struct dfs_filesystem *fs, unsigned long rwflag, const void *data)
{
fs->data = (void *)data;
return 0;
}
static int zipfs_ops_unmount(struct dfs_filesystem *fs)
{
struct aic_zip_reader *reader = (struct aic_zip_reader *)fs->data;
aic_zip_reader_close(reader);
return 0;
}
static int zipfs_ops_stat(struct dfs_filesystem *fs, const char *path, struct stat *st)
{
struct aic_zip_reader *reader = (struct aic_zip_reader *)fs->data;
int i = 0;
for (i = 0; i < reader->file_count; i++) {
size_t file_size = reader->file_info[i].size;
char *file_name = reader->file_info[i].name;
int j = 0;
for (j = 0; j < strlen(path) && path[j] == file_name[j]; j++) {
}
if (j == strlen(path)) {
if (file_name[j] == '/') {
st->st_mode = S_IFDIR;
st->st_size = 0;
} else if (file_name[j] == '\0') {
st->st_mode = S_IFREG;
st->st_size = file_size;
} else {
continue;
}
return 0;
}
}
return -ENOENT;
}
static const struct dfs_filesystem_ops zipfs_ops = {
FS_NAME,
DFS_FS_FLAG_DEFAULT,
&zipfs_fops,
zipfs_ops_mount, /* mount */
zipfs_ops_unmount, /* unmount */
NULL, /* mkfs */
NULL, /* statfs */
NULL, /* unlink */
zipfs_ops_stat, /* stat */
NULL, /* rename */
};
static int zipfs_fopen(struct dfs_fd *fd)
{
struct aic_zip_reader *reader = (struct aic_zip_reader *)fd->fs->data;
int i = 0;
if ((fd->flags & O_ACCMODE) != O_RDONLY)
return -EINVAL;
if (strcmp(fd->path, "/") == 0)
return 0;
for (i = 0; i < reader->file_count; i++) {
char *file_name = reader->file_info[i].name;
int j = 0;
for (j = 0; j < strlen(fd->path) && fd->path[j] == file_name[j]; j++) {
}
if (j == strlen(fd->path)) {
if (file_name[j] == '/' && fd->flags == O_DIRECTORY) {
return 0;
} else if (file_name[j] == '\0' && fd->flags != O_DIRECTORY) {
fd->size = reader->file_info[i].size;
fd->data = mz_zip_reader_extract_file_iter_new(&reader->archive, file_name + 1, 0);
return 0;
} else {
continue;
}
}
}
return -ENOENT;
}
static int zipfs_fread(struct dfs_fd *fd, void *buf, size_t count)
{
struct aic_zip_reader *reader = (struct aic_zip_reader *)fd->fs->data;
rt_size_t length;
size_t read_size = 0;
length = count > (fd->size - fd->pos) ? (fd->size - fd->pos) : count;
if (length > 0) {
for (int i = 0; i < reader->file_count; i++) {
char *file_name = reader->file_info[i].name;
if (!strcmp(fd->path, file_name)) {
mz_zip_reader_extract_iter_state *iter =
(mz_zip_reader_extract_iter_state *)fd->data;
read_size = mz_zip_reader_extract_iter_read(iter, buf, length);
break;
}
}
}
fd->pos += read_size;
return read_size;
}
static int zipfs_fclose(struct dfs_fd *fd)
{
if (fd->data != NULL) {
mz_zip_reader_extract_iter_free(fd->data);
fd->data = NULL;
}
return 0;
}
static int zipfs_lseek(struct dfs_fd *fd, off_t offset)
{
mz_zip_reader_extract_iter_state *iter = NULL;
uint8_t *temp_buf = NULL;
if (offset < 0 || offset > fd->size)
return -EINVAL;
if (offset == fd->pos)
return offset;
if (offset < fd->pos) {
struct aic_zip_reader *reader = (struct aic_zip_reader *)fd->fs->data;
iter = (mz_zip_reader_extract_iter_state *)fd->data;
uint32_t file_index = iter->file_stat.m_file_index;
mz_zip_reader_extract_iter_free(iter);
fd->data = mz_zip_reader_extract_iter_new(&reader->archive, file_index, 0);
fd->pos = 0;
}
temp_buf = malloc(offset);
iter = (mz_zip_reader_extract_iter_state *)fd->data;
mz_zip_reader_extract_iter_read(iter, temp_buf, offset);
free(temp_buf);
return offset;
}
static int zipfs_getdents(struct dfs_fd *fd, struct dirent *dirp, uint32_t count)
{
struct aic_zip_reader *reader = (struct aic_zip_reader *)fd->fs->data;
const char *path = fd->path;
int index = 0;
uint32_t i = 0;
uint32_t entries_processed = fd->pos;
const uint32_t max_entries = count / sizeof(struct dirent);
if (max_entries == 0)
return -EINVAL;
for (i = entries_processed; i < reader->file_count && index < max_entries; i++) {
const char *file_name = reader->file_info[i].name;
uint32_t l = 0, r = 0;
for (l = 0; l < strlen(path) && path[l] == file_name[l]; l++) {
}
if (l == 1)
l = 0;
else if (l == 0 || (file_name[l] != '\0' && file_name[l] != '/'))
continue;
for (r = l + 1; r < strlen(file_name) && file_name[r] != '\0' && file_name[r] != '/'; r++) {
}
if (r == (l + 1))
continue;
bool duplicate = false;
for (int k = 0; k < entries_processed; k++) {
if (strncmp(dirp[k].d_name, file_name + l + 1, r - l - 1) == 0) {
duplicate = true;
break;
}
}
if (duplicate)
continue;
dirp[index].d_type = (file_name[r] == '/') ? DT_DIR : DT_REG;
dirp[index].d_namlen = r - l;
dirp[index].d_reclen = (uint16_t)sizeof(struct dirent);
strncpy(dirp[index].d_name, file_name + l + 1, r - l - 1);
dirp[index].d_name[r - l] = '\0';
index++;
}
fd->pos = i;
return index * sizeof(struct dirent);
}
static const struct dfs_file_ops zipfs_fops = {
zipfs_fopen, /* open */
zipfs_fclose, /* close */
NULL, /* ioctl */
zipfs_fread, /* read */
NULL, /* write */
NULL, /* flush */
zipfs_lseek, /* lseek */
zipfs_getdents, /* getdents */
NULL, /* poll */
};
int zipfs_register()
{
if (dfs_register(&zipfs_ops) != 0)
return -1;
return 0;
}
int zipfs_mount(const char *source, const char *mount_point)
{
struct aic_zip_reader *reader = aic_zip_reader_open(source);
if (reader == NULL)
return -1;
if (dfs_mount(RT_NULL, mount_point, FS_NAME, 0, reader) != 0) {
aic_zip_reader_close(reader);
return -1;
}
printf("ZIP mounted at %s\n", mount_point);
return 0;
}
int zipfs_unmount(const char *mount_point)
{
if (dfs_unmount(mount_point) != 0)
return -1;
return 0;
}
INIT_COMPONENT_EXPORT(zipfs_register);

View File

@@ -0,0 +1,256 @@
/*
* Copyright (c) 2025, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Authors: Cui Jiawei <jiawei.cui@artinchip.com>
*/
#include "zip_reader.h"
#include <rtthread.h>
#include <rtdevice.h>
#include <dfs_posix.h>
#include <aic_utils.h>
#include <aic_core.h>
#include <string.h>
#define ZIP_FILE_HEADER 0x04034B50
#define ZIP_FILE_EOCD_SIGN 0x06054B50
#pragma pack(push, 1)
struct zip_eocd {
rt_uint32_t signature;
rt_uint16_t disk_number;
rt_uint16_t cd_disk;
rt_uint16_t cd_records;
rt_uint16_t total_cd_records;
rt_uint32_t cd_size;
rt_uint32_t cd_offset;
rt_uint16_t comment_len;
};
#pragma pack(pop)
static size_t get_zip_size_from_blk(const char *blk_name)
{
rt_device_t flash_dev;
struct rt_device_blk_geometry flash_geo;
struct zip_eocd *eocd = NULL;
size_t len = 0, i;
uint32_t blk_count = 0;
uint8_t *blk_data = NULL;
flash_dev = rt_device_find(blk_name);
if (!flash_dev)
return 0;
if (rt_device_open(flash_dev, RT_DEVICE_OFLAG_RDWR) != RT_EOK)
return 0;
rt_device_control(flash_dev, RT_DEVICE_CTRL_BLK_GETGEOME, &flash_geo);
blk_data = (uint8_t *)malloc(flash_geo.block_size);
rt_device_read(flash_dev, 0, blk_data, 1);
hexdump(blk_data, flash_geo.block_size, 16);
if (*(uint32_t *)blk_data != ZIP_FILE_HEADER) {
rt_kprintf("head:%d\n", *(uint32_t *)blk_data);
goto exit;
}
for (i = 4; i < flash_geo.block_size - sizeof(struct zip_eocd); i++) {
eocd = (struct zip_eocd *)(blk_data + i);
if (eocd->signature == ZIP_FILE_EOCD_SIGN) {
len = i + sizeof(struct zip_eocd) + eocd->comment_len;
goto exit;
}
}
blk_count = flash_geo.bytes_per_sector * flash_geo.sector_count / flash_geo.block_size;
for (i = 1; i < blk_count; i++) {
rt_device_read(flash_dev, i, blk_data, 1);
for (int j = 0; j < flash_geo.block_size - sizeof(struct zip_eocd); j++) {
eocd = (struct zip_eocd *)(blk_data + j);
if (eocd->signature == ZIP_FILE_EOCD_SIGN) {
len = j + sizeof(struct zip_eocd) + eocd->comment_len + i * flash_geo.block_size;
goto exit;
}
}
}
exit:
rt_device_close(flash_dev);
if (blk_data)
free(blk_data);
return len;
}
static int get_zip_data_from_blk(const char *blk_name, void *buffer, size_t len)
{
rt_device_t flash_dev;
struct rt_device_blk_geometry flash_geo;
size_t read_size = 0;
uint8_t *blk_data = NULL;
flash_dev = rt_device_find(blk_name);
if (!flash_dev)
return -1;
if (rt_device_open(flash_dev, RT_DEVICE_OFLAG_RDWR) != RT_EOK)
return -1;
rt_device_control(flash_dev, RT_DEVICE_CTRL_BLK_GETGEOME, &flash_geo);
read_size = RT_ALIGN(len, flash_geo.block_size);
blk_data = (uint8_t *)malloc(read_size);
rt_device_read(flash_dev, 0, blk_data, read_size / flash_geo.block_size);
memcpy(buffer, blk_data, len);
rt_device_close(flash_dev);
if (blk_data)
free(blk_data);
return 0;
}
struct aic_zip_reader *aic_zip_reader_open(const char *source)
{
int fd = -1;
struct aic_zip_reader *reader = NULL;
void *buffer = NULL;
size_t zip_size = 0;
struct stat st;
bool is_file = false;
fd = open(source, O_RDONLY);
if (fd == -1) {
zip_size = get_zip_size_from_blk(source);
if (zip_size == 0) {
pr_err("zip file data get failed\n");
return NULL;
}
} else {
is_file = true;
if (fstat(fd, &st) == -1) {
close(fd);
pr_err("Stat file failed\n");
return NULL;
}
zip_size = st.st_size;
}
buffer = (char *)malloc(zip_size);
if (!buffer) {
if (is_file)
close(fd);
pr_err("Memory allocation failed\n");
return NULL;
}
if (is_file) {
if (read(fd, buffer, zip_size) != zip_size) {
free(buffer);
close(fd);
pr_err("File read failed\n");
return NULL;
}
if (close(fd) == -1) {
free(buffer);
pr_err("File close failed\n");
return NULL;
}
} else {
if (get_zip_data_from_blk(source, buffer, zip_size) == -1) {
free(buffer);
return NULL;
}
}
// Create reader instance
reader = (struct aic_zip_reader *)malloc(sizeof(struct aic_zip_reader));
if (!reader) {
free(buffer);
return NULL;
}
memset(reader, 0, sizeof(struct aic_zip_reader));
// Initialize miniz ZIP archive
memset(&reader->archive, 0, sizeof(mz_zip_archive));
if (!mz_zip_reader_init_mem(&reader->archive, buffer, zip_size, 0)) {
pr_err("Failed to init ZIP archive: %s\n",
mz_zip_get_error_string(mz_zip_get_last_error(&reader->archive)));
aic_zip_reader_close(reader);
return NULL;
}
reader->zip_buffer = buffer;
reader->zip_size = zip_size;
reader->file_count = mz_zip_reader_get_num_files(&reader->archive);
reader->file_info = malloc(sizeof(struct aic_file_info) * reader->file_count);
memset(reader->file_info, 0, sizeof(struct aic_file_info) * reader->file_count);
for (int i = 0; i < reader->file_count; i++) {
mz_zip_archive_file_stat stat;
if (!mz_zip_reader_file_stat(&reader->archive, i, &stat)) {
aic_zip_reader_close(reader);
return NULL;
}
reader->file_info[i].name = malloc(strlen(stat.m_filename) + 2);
if (!reader->file_info[i].name) {
aic_zip_reader_close(reader);
return NULL;
}
reader->file_info[i].name[0] = '/';
memcpy(reader->file_info[i].name + 1, stat.m_filename, strlen(stat.m_filename) + 1);
reader->file_info[i].size = stat.m_uncomp_size;
}
return reader;
}
void aic_zip_reader_close(struct aic_zip_reader *reader)
{
if (reader) {
if (reader->file_info) {
for (int i = 0; i < reader->file_count; i++)
if (reader->file_info[i].name)
free(reader->file_info[i].name);
free(reader->file_info);
}
if (reader->zip_buffer)
free(reader->zip_buffer);
mz_zip_reader_end(&reader->archive);
free(reader);
}
}
int aic_zip_reader_read(struct aic_zip_reader *reader, struct aic_file_info file_info, void *buffer)
{
if (!reader || !buffer) {
return -1;
}
const char *file_name = file_info.name + 1;
size_t buffer_size = file_info.size;
size_t extacted_size = 0;
mz_zip_reader_extract_iter_state *iter =
mz_zip_reader_extract_file_iter_new(&reader->archive, file_name, 0);
while (extacted_size < buffer_size) {
size_t byte_read =
mz_zip_reader_extract_iter_read(iter, buffer + extacted_size, READ_BUF_SIZE);
if (byte_read == 0)
break;
extacted_size += byte_read;
}
mz_zip_reader_extract_iter_free(iter);
return 0;
}