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,15 @@
# Kconfig file for package zipfs
menuconfig LPKG_USING_ZIPFS
bool "zipfs: A file system for zip file"
select LPKG_USING_MINIZ
default n
depends on PRJ_KERNEL="rt-thread"
if LPKG_USING_ZIPFS
config LPKG_ZIPFS_DEMO
bool "Enable zipfs demo"
default n
endif

View File

@@ -0,0 +1,48 @@
# ZIP File System Library
## Overview
This library provides two approaches to handle ZIP files:
1. **ZIP File System**: Mount ZIP files or the block device where the ZIP data in as virtual file systems
2. **ZIP File Reader**: Directly read ZIP file contents
## ZIP File System
### API Functions
```c
int zipfs_mount(const char *zip_path, const char *mount_point);
int zipfs_unmount(const char *mount_point);
```
### Important Notes
- Not thread-safe, requires external locking in multi-threaded environments
- Mount point must be an empty directory
- Read-only access
## ZIP File Reader
### API Functions
```c
struct aic_zip_reader *aic_zip_reader_open(const char *source);
int aic_zip_reader_read(struct aic_zip_reader *reader,
struct aic_file_info file_info,
void *buffer);
void aic_zip_reader_close(struct aic_zip_reader *reader);
```
### Important Notes
- After opening a ZIP reader, you must manually call aic_zip_reader_close to close it
- You can adjust the read buffer size by modifying the READ_BUF_SIZE macro in zip_reader.h
- Large files are automatically streamed internally, but note that the provided buffer must be greater than or equal to the file size
- Encrypted ZIP and ZIP64 formats are not supported
## Demo Programs
The project includes two demonstration programs:
- `zip_fs_demo.c`: ZIP file system usage example
- `zip_reader_demo.c`: ZIP file reader usage example
## Dependencies
- RT-Thread: Real-time operating system

View File

@@ -0,0 +1,48 @@
# ZIP文件系统库
## 功能概述
本库提供两种处理ZIP文件的方式
1. **ZIP文件系统**将ZIP文件或包含zip文件的块设备挂载为虚拟文件系统
2. **ZIP文件读取器**直接读取ZIP文件内容
## ZIP文件系统
### 接口函数
```c
int zipfs_mount(const char *zip_path, const char *mount_point);
int zipfs_unmount(const char *mount_point);
```
### 注意事项
- 非线程安全,多线程环境需要外部加锁
- 挂载点必须是空的目录
- 只读访问
## ZIP文件读取器
### 接口函数
```c
struct aic_zip_reader *aic_zip_reader_open(const char *source);
int aic_zip_reader_read(struct aic_zip_reader *reader,
struct aic_file_info file_info,
void *buffer);
void aic_zip_reader_close(struct aic_zip_reader *reader);
```
### 注意事项
- 在打开ZIP读取器后必须手动调用aic_zip_reader_close关闭读取器
- 可以在zip_reader.h中通过修改宏READ_BUF_SIZE调整读取缓冲区大小
- 读取大文件时内部会自动流式但是要注意提供的buffer要大于或等于文件大小
- 不支持加密ZIP和ZIP64格式
## 示例程序
项目包含两个演示程序:
- `zip_fs_demo.c`: ZIP文件系统使用示例
- `zip_reader_demo.c`: ZIP文件读取器使用示例
## 依赖
- RT-Thread: 实时操作系统

View File

@@ -0,0 +1,24 @@
from building import *
Import('rtconfig')
src = []
cwd = GetCurrentDir()
install = []
if GetDepend('LPKG_USING_ZIPFS'):
src += Glob('src/*.c')
if GetDepend('LPKG_ZIPFS_DEMO'):
src += Glob('zip_reader_demo.c')
src += Glob('zip_fs_demo.c')
ins_dst = 'rodata/zipfs_test'
ins_src = 'test_zip_files/'
install = [(ins_src, ins_dst)]
# add include path.
path = [cwd + '/inc']
# add src and include to group.
group = DefineGroup('zipfs', src, depend = ['LPKG_USING_ZIPFS'], CPPPATH = path,
INSTALL = install)
Return('group')

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2025, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Authors: Cui Jiawei <jiawei.cui@artinchip.com>
*/
#ifndef __ZIPFS_H_
#define __ZIPFS_H_
#include <stddef.h>
#define FS_NAME "zipfs"
/**
* @brief Mount a specified ZIP archive as a virtual filesystem at the target path.
* Creates an in-memory read-only view under `mount_point`, where subsequent
* POSIX filesystem operations will transparently access files within the ZIP.
*
* @param source Full path to ZIP file in RAMDisk, or block name where ZIP data in
* example: "/rodata/zipfs_test/much_file.zip", "blk_rodata_r"
* @param mount_point Target mount location in the system (e.g., "/zipfs"). Must be an
* empty directory not currently mounted by other filesystems.
*
* @return Returns 0 on success; returns -1 on failure.
*/
int zipfs_mount(const char *source, const char *mount_point);
/**
* @brief Unmount a previously mounted ZIP filesystem, immediately releasing all resources
* associated with the specified mount point.
*
* @param mount_point The mount point of the ZIP filesystem to unmount.
*
* @return Returns 0 on success; returns -1 on failure.
*/
int zipfs_unmount(const char *mount_point);
#endif // __ZIPFS_H_

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2025, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Authors: Cui Jiawei <jiawei.cui@artinchip.com>
*/
#ifndef __ZIP_READER_H_
#define __ZIP_READER_H_
#include <stddef.h>
#include "miniz.h"
#include "miniz_zip.h"
#define READ_BUF_SIZE 4096
struct aic_file_info {
char *name;
size_t size;
};
struct aic_zip_reader {
void *zip_buffer; /* Memory buffer containing ZIP file */
size_t zip_size; /* Size of ZIP file in bytes */
mz_zip_archive archive; /* miniz ZIP archive structure */
uint32_t file_count; /* Number of files (including directories) in the ZIP archive */
struct aic_file_info *file_info; /* Array of structures containing file information */
};
/**
* @brief Open a ZIP file from RAMDisk
*
* @param source Full path to ZIP file in RAMDisk, or block name where ZIP data in
* example: "/rodata/zipfs_test/much_file.zip", "blk_rodata_r"
*
* @return aic_zip_reader* Pointer to ZIP reader instance, NULL on failure
*/
struct aic_zip_reader *aic_zip_reader_open(const char *source);
/**
* @brief Close ZIP reader and release all resources
*
* @param reader ZIP reader pointer
*/
void aic_zip_reader_close(struct aic_zip_reader *reader);
/**
* @brief Extract file content directly into provided buffer
*
* @param reader ZIP reader pointer
* @param file_info Struct representing the information of files to be read.
* @param buffer Destination buffer, Set the buffer size based on the size field of aic_file_info.
* @return int Number 0 on success, -1 on failure
*/
int aic_zip_reader_read(struct aic_zip_reader *reader, struct aic_file_info file_info,
void *buffer);
#endif // __ZIP_READER_H_

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;
}

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,137 @@
/*
* Copyright (c) 2025, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Authors: Cui Jiawei <jiawei.cui@artinchip.com>
*/
#include <string.h>
#include <finsh.h>
#include <aic_core.h>
#include <rtthread.h>
#include <dfs_posix.h>
#include <aic_common.h>
#include <aic_utils.h>
#include "zip_fs.h"
/**
* Note: An empty directory must be prepared as the mount point. It is recommended
* to add {ROMFS_DIRENT_DIR, "zipfs", RT_NULL, 0} in _mountpoint_root within
* ./target/xxx/demoxx-xxx/board.c.
*/
#define MOUNT_PATH "/zipfs"
#define SOURCE_FILE "/rodata/zipfs_test/big_file.zip"
#define SOURCE_BLK "blk_rodata_r"
static const char *g_file_name = MOUNT_PATH "/large_file.txt";
/**
* Reads and displays the entire contents of a file
*
* @param fd File descriptor to read from
* @return 0 on success, -1 on failure
*/
static int read_file(int fd)
{
off_t size = -1;
ssize_t bytes_read = -1;
char *buffer = NULL;
/* Get file size by seeking from start to end */
if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
pr_err("Seek to start failed\n");
return -1;
}
size = lseek(fd, 0, SEEK_END);
if (size == (off_t)-1) {
pr_err("Seek to end failed\n");
return -1;
}
/* Return to beginning of file */
if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
pr_err("Seek to start failed\n");
return -1;
}
/* Allocate buffer for file contents */
buffer = (char *)aicos_malloc(MEM_CMA, size + 1);
if (!buffer) {
pr_err("Memory allocation failed\n");
return -1;
}
uint64_t start_us = aic_get_time_us();
/* Read entire file */
bytes_read = read(fd, buffer, size);
show_speed("zip file read speed", bytes_read, aic_get_time_us() - start_us);
if (bytes_read == -1) {
aicos_free(MEM_CMA, buffer);
pr_err("File read failed\n");
return -1;
}
buffer[bytes_read] = '\0';
/* Display contents */
rt_kprintf("Read %lu bytes:\n", (unsigned long)bytes_read);
for (int i = 0; i < bytes_read; i++)
putchar(buffer[i]);
putchar('\n');
aicos_free(MEM_CMA, buffer);
return 0;
}
/**
* zip File Operations Demonstration
*
* Demonstrates:
* - Opening files using open()
* - Closing files using close()
* - Reading files (wrapped function)
*/
static int zip_fs_demo(int argc, char **argv)
{
int fd = -1, err = 0;
rt_kprintf("zip file system usage example start\n");
/* Mount zip file system */
err = zipfs_mount(SOURCE_FILE, MOUNT_PATH);
/* Or you can mount zip file system by zip blk */
// err = zipfs_mount(SOURCE_BLK, MOUNT_PATH);
if (err) {
pr_err("zipfs mount failed\n");
return err;
}
/* Open file */
rt_kprintf("Open file (open) :%s\n", g_file_name);
fd = open(g_file_name, O_RDONLY, 0644);
if (fd == -1) {
pr_err("File open failed\n");
err = -1;
goto exit;
}
/* Read file content */
rt_kprintf("Read File Content\n");
err = read_file(fd);
if (err)
pr_err("Read file failed\n");
exit:
/* Close file using close() */
rt_kprintf("Close File (close)\n");
if (close(fd) == -1)
pr_err("Final close failed");
/* Unmount zip file system */
zipfs_unmount(MOUNT_PATH);
rt_kprintf("zip file system example end\n");
return err;
}
MSH_CMD_EXPORT(zip_fs_demo, Zip file system example);

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2025, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Authors: Cui Jiawei <jiawei.cui@artinchip.com>
*/
#include <rtthread.h>
#include <rtdevice.h>
#include <aic_common.h>
#include <aic_core.h>
#include <aic_utils.h>
#include "zip_reader.h"
#define SOURCE_FILE "/rodata/zipfs_test/much_file.zip"
#define SOURCE_BLK "blk_rodata_r"
/**
* Demonstrates how to process a ZIP archive by extracting and
* printing contents of each entry.
*/
static int zip_reader_demo()
{
/* Open zip reader by zip file */
struct aic_zip_reader *reader = aic_zip_reader_open(SOURCE_FILE);
/* Or you can open zip reader by zip blk */
// struct aic_zip_reader *reader = aic_zip_reader_open(SOURCE_BLK);
if (!reader) {
pr_err("Failed to open zip reader by file: %s\n", SOURCE_FILE);
return -1;
}
/* Process each file */
for (int i = 0; i < reader->file_count; i++) {
size_t file_size = reader->file_info[i].size;
char *file_name = reader->file_info[i].name;
rt_kprintf("Processing %d: %s, size:%zu\n", i + 1, file_name, file_size);
if (file_name[strlen(file_name) - 1] == '/') {
rt_kprintf(" Skipping directory\n");
continue;
}
void *content = malloc(file_size);
if (!content) {
perror("Memory allocation failed");
aic_zip_reader_close(reader);
return -1;
}
uint64_t start_us = aic_get_time_us();
/* Read the file specified by index file_info. */
aic_zip_reader_read(reader, reader->file_info[i], content);
show_speed("zip file read speed", file_size, aic_get_time_us() - start_us);
for (size_t j = 0; j < file_size; j++) {
putchar(((char *)content)[j]);
}
rt_kprintf("\n");
free(content);
}
/* Close zip reader */
aic_zip_reader_close(reader);
return 0;
}
MSH_CMD_EXPORT(zip_reader_demo, zip reader demo);