From a2c5cb729a5d3f13efd0ff5e96eabf4309e4a2c9 Mon Sep 17 00:00:00 2001 From: anjiahao Date: Mon, 25 Sep 2023 16:25:34 +0800 Subject: [PATCH] fs:support zipfs,can mount zipfile we can mount a zipfile in nuttx use mount command like this: mount -t zipfs -o /data/test.zip /zip The zipfs is a read only file system,The advantage is that it does not occupy additional space when reading the decompressed file. When used, reading and decompression operations are simultaneous. The known disadvantage is that when using seek to read forward, it will reopen and cause slow speed problems. Signed-off-by: anjiahao --- boards/sim/sim/sim/configs/zipfs/defconfig | 72 +++ fs/Kconfig | 1 + fs/Makefile | 1 + fs/mount/fs_mount.c | 6 + fs/zipfs/CMakeLists.txt | 28 + fs/zipfs/Kconfig | 18 + fs/zipfs/Make.defs | 32 + fs/zipfs/zip_vfs.c | 655 +++++++++++++++++++++ fs/zipfs/zlib | 1 + include/sys/statfs.h | 1 + tools/nxstyle.c | 14 + 11 files changed, 829 insertions(+) create mode 100644 boards/sim/sim/sim/configs/zipfs/defconfig create mode 100644 fs/zipfs/CMakeLists.txt create mode 100644 fs/zipfs/Kconfig create mode 100644 fs/zipfs/Make.defs create mode 100644 fs/zipfs/zip_vfs.c create mode 120000 fs/zipfs/zlib diff --git a/boards/sim/sim/sim/configs/zipfs/defconfig b/boards/sim/sim/sim/configs/zipfs/defconfig new file mode 100644 index 0000000000..93673e3992 --- /dev/null +++ b/boards/sim/sim/sim/configs/zipfs/defconfig @@ -0,0 +1,72 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +CONFIG_ARCH="sim" +CONFIG_ARCH_BOARD="sim" +CONFIG_ARCH_BOARD_SIM=y +CONFIG_ARCH_CHIP="sim" +CONFIG_ARCH_SIM=y +CONFIG_BOARDCTL_APP_SYMTAB=y +CONFIG_BOARDCTL_POWEROFF=y +CONFIG_BOARD_LOOPSPERMSEC=0 +CONFIG_BOOT_RUNFROMEXTSRAM=y +CONFIG_BUILTIN=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEV_GPIO=y +CONFIG_DEV_LOOP=y +CONFIG_DEV_ZERO=y +CONFIG_EXAMPLES_GPIO=y +CONFIG_EXAMPLES_HELLO=y +CONFIG_FAT_LCNAMES=y +CONFIG_FAT_LFN=y +CONFIG_FSUTILS_PASSWD=y +CONFIG_FSUTILS_PASSWD_READONLY=y +CONFIG_FS_BINFS=y +CONFIG_FS_FAT=y +CONFIG_FS_HOSTFS=y +CONFIG_FS_PROCFS=y +CONFIG_FS_RAMMAP=y +CONFIG_FS_ROMFS=y +CONFIG_FS_ZIPFS=y +CONFIG_GPIO_LOWER_HALF=y +CONFIG_IDLETHREAD_STACKSIZE=4096 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_IOEXPANDER=y +CONFIG_IOEXPANDER_DUMMY=y +CONFIG_LIBC_ENVPATH=y +CONFIG_LIBC_EXECFUNCS=y +CONFIG_LIBC_LOCALE=y +CONFIG_LIBC_LOCALE_CATALOG=y +CONFIG_LIBC_LOCALE_GETTEXT=y +CONFIG_LIBC_MAX_EXITFUNS=1 +CONFIG_LIBC_NUMBERED_ARGS=y +CONFIG_LIB_ZLIB=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_ARCHROMFS=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FATDEVNO=2 +CONFIG_NSH_FILE_APPS=y +CONFIG_NSH_MOTD=y +CONFIG_NSH_MOTD_STRING="MOTD: username=admin password=Administrator" +CONFIG_NSH_READLINE=y +CONFIG_NSH_ROMFSDEVNO=1 +CONFIG_NSH_ROMFSETC=y +CONFIG_PATH_INITIAL="/bin" +CONFIG_PSEUDOFS_ATTRIBUTES=y +CONFIG_PSEUDOFS_SOFTLINKS=y +CONFIG_READLINE_TABCOMPLETION=y +CONFIG_SCHED_BACKTRACE=y +CONFIG_SCHED_HAVE_PARENT=y +CONFIG_SCHED_WAITPID=y +CONFIG_SIM_WALLTIME_SIGNAL=y +CONFIG_START_MONTH=6 +CONFIG_START_YEAR=2008 +CONFIG_SYSTEM_DUMPSTACK=y +CONFIG_SYSTEM_NSH=y +CONFIG_UTILS_UNZIP=y +CONFIG_UTILS_ZIP=y diff --git a/fs/Kconfig b/fs/Kconfig index c19084b0bf..e66f2abcd5 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -129,3 +129,4 @@ source "fs/unionfs/Kconfig" source "fs/userfs/Kconfig" source "fs/hostfs/Kconfig" source "fs/rpmsgfs/Kconfig" +source "fs/zipfs/Kconfig" diff --git a/fs/Makefile b/fs/Makefile index 35465b32ad..2f62d7bea8 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -56,6 +56,7 @@ include userfs/Make.defs include hostfs/Make.defs include littlefs/Make.defs include rpmsgfs/Make.defs +include zipfs/Make.defs endif diff --git a/fs/mount/fs_mount.c b/fs/mount/fs_mount.c index cb68f32678..ac5756854b 100644 --- a/fs/mount/fs_mount.c +++ b/fs/mount/fs_mount.c @@ -181,6 +181,9 @@ extern const struct mountpt_operations g_unionfs_operations; #ifdef CONFIG_FS_RPMSGFS extern const struct mountpt_operations g_rpmsgfs_operations; #endif +#ifdef CONFIG_FS_ZIPFS +extern const struct mountpt_operations g_zipfs_operations; +#endif static const struct fsmap_t g_nonbdfsmap[] = { @@ -213,6 +216,9 @@ static const struct fsmap_t g_nonbdfsmap[] = #endif #ifdef CONFIG_FS_RPMSGFS { "rpmsgfs", &g_rpmsgfs_operations }, +#endif +#ifdef CONFIG_FS_ZIPFS + { "zipfs", &g_zipfs_operations}, #endif { NULL, NULL }, }; diff --git a/fs/zipfs/CMakeLists.txt b/fs/zipfs/CMakeLists.txt new file mode 100644 index 0000000000..c5ac96a06a --- /dev/null +++ b/fs/zipfs/CMakeLists.txt @@ -0,0 +1,28 @@ +# ############################################################################## +# fs/zipfs/CMakeLists.txt +# +# Licensed to the Apache Software Foundation (ASF) under one or more contributor +# license agreements. See the NOTICE file distributed with this work for +# additional information regarding copyright ownership. The ASF licenses this +# file to you under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# +# ############################################################################## + +if(CONFIG_FS_ZIPFS) + + target_sources(fs PRIVATE zip_vfs.c) + + target_include_directories( + fs PRIVATE ${CMAKE_CURRENT_LIST_DIR}/zlib/zlib/contrib/minizip + ${CMAKE_CURRENT_LIST_DIR}/zlib/zlib) +endif() diff --git a/fs/zipfs/Kconfig b/fs/zipfs/Kconfig new file mode 100644 index 0000000000..0a4b2709c7 --- /dev/null +++ b/fs/zipfs/Kconfig @@ -0,0 +1,18 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config FS_ZIPFS + bool "ZIPFS File System" + default n + +if FS_ZIPFS + +config ZIPFS_SEEK_BUFSIZE + int "zipfs seek buffer size" + default 256 + ---help--- + this option will influences seek speed + +endif # FS_ZIPFS diff --git a/fs/zipfs/Make.defs b/fs/zipfs/Make.defs new file mode 100644 index 0000000000..e03aaaa941 --- /dev/null +++ b/fs/zipfs/Make.defs @@ -0,0 +1,32 @@ +############################################################################ +# fs/zipfs/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +ifeq ($(CONFIG_FS_ZIPFS),y) +# Files required for ZIPFS file system support + +CFLAGS += ${INCDIR_PREFIX}zipfs/zlib/zlib/contrib/minizip +CFLAGS += ${INCDIR_PREFIX}zipfs/zlib/zlib +CSRCS += zip_vfs.c +# Include ZIPFS build support + +DEPPATH += --dep-path zipfs +VPATH += :zipfs + +endif diff --git a/fs/zipfs/zip_vfs.c b/fs/zipfs/zip_vfs.c new file mode 100644 index 0000000000..296962878d --- /dev/null +++ b/fs/zipfs/zip_vfs.c @@ -0,0 +1,655 @@ +/**************************************************************************** + * fs/zipfs/zip_vfs.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct zipfs_dir_s +{ + struct fs_dirent_s base; + mutex_t lock; + unzFile uf; + bool last; +}; + +struct zipfs_mountpt_s +{ + char abspath[1]; +}; + +struct zipfs_file_s +{ + unzFile uf; + mutex_t lock; + FAR char *seekbuf; + char relpath[1]; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static voidpf zipfs_real_open(voidpf opaque, FAR const void *filename, + int mode); +static uLong zipfs_real_read(voidpf opaque, voidpf stream, FAR void *buf, + uLong size); +static long zipfs_real_seek(voidpf opaque, voidpf stream, ZPOS64_T offset, + int origin); +static ZPOS64_T zipfs_real_tell(voidpf opaque, voidpf stream); +static int zipfs_real_close(voidpf opaque, voidpf stream); +static int zipfs_real_error(voidpf opaque, voidpf stream); + +static int zipfs_open(FAR struct file *filep, FAR const char *relpath, + int oflags, mode_t mode); +static int zipfs_close(FAR struct file *filep); +static ssize_t zipfs_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +static off_t zipfs_seek(FAR struct file *filep, off_t offset, + int whence); +static int zipfs_dup(FAR const struct file *oldp, + FAR struct file *newp); +static int zipfs_fstat(FAR const struct file *filep, + FAR struct stat *buf); +static int zipfs_opendir(FAR struct inode *mountpt, + FAR const char *relpath, + FAR struct fs_dirent_s **dir); +static int zipfs_closedir(FAR struct inode *mountpt, + FAR struct fs_dirent_s *dir); +static int zipfs_readdir(FAR struct inode *mountpt, + FAR struct fs_dirent_s *dir, + FAR struct dirent *entry); +static int zipfs_rewinddir(FAR struct inode *mountpt, + FAR struct fs_dirent_s *dir); +static int zipfs_bind(FAR struct inode *driver, + FAR const void *data, FAR void **handle); +static int zipfs_unbind(FAR void *handle, FAR struct inode **driver, + unsigned int flags); +static int zipfs_statfs(FAR struct inode *mountpt, + FAR struct statfs *buf); +static int zipfs_stat(FAR struct inode *mountpt, + FAR const char *relpath, FAR struct stat *buf); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static zlib_filefunc64_def zipfs_real_ops = +{ + zipfs_real_open, + zipfs_real_read, + NULL, + zipfs_real_tell, + zipfs_real_seek, + zipfs_real_close, + zipfs_real_error, + NULL +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +const struct mountpt_operations g_zipfs_operations = +{ + zipfs_open, /* open */ + zipfs_close, /* close */ + zipfs_read, /* read */ + NULL, /* write */ + zipfs_seek, /* seek */ + NULL, /* ioctl */ + NULL, /* mmap */ + NULL, /* truncate */ + + NULL, /* sync */ + zipfs_dup, /* dup */ + zipfs_fstat, /* fstat */ + NULL, /* fchstat */ + + zipfs_opendir, /* opendir */ + zipfs_closedir, /* closedir */ + zipfs_readdir, /* readdir */ + zipfs_rewinddir, /* rewinddir */ + + zipfs_bind, /* bind */ + zipfs_unbind, /* unbind */ + zipfs_statfs, /* statfs */ + + NULL, /* unlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* rename */ + zipfs_stat, /* stat */ + NULL /* chstat */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static voidpf zipfs_real_open(voidpf opaque, FAR const void *filename, + int mode) +{ + FAR struct file *filep; + int ret; + + filep = kmm_malloc(sizeof(struct file)); + if (filep == NULL) + { + return NULL; + } + + ret = file_open(filep, filename, O_RDONLY); + if (ret < 0) + { + kmm_free(filep); + return NULL; + } + + return filep; +} + +static uLong zipfs_real_read(voidpf opaque, voidpf stream, + FAR void *buf, uLong size) +{ + return file_read(stream, buf, size); +} + +static ZPOS64_T zipfs_real_tell(voidpf opaque, voidpf stream) +{ + return file_seek(stream, 0, SEEK_CUR); +} + +static long zipfs_real_seek(voidpf opaque, voidpf stream, ZPOS64_T offset, + int origin) +{ + int ret; + + ret = file_seek(stream, offset, origin); + return ret >= 0 ? 0 : ret; +} + +static int zipfs_real_close(voidpf opaque, voidpf stream) +{ + int ret; + + ret = file_close(stream); + kmm_free(stream); + return ret; +} + +static int zipfs_real_error(voidpf opaque, voidpf stream) +{ + return OK; +} + +static int zipfs_convert_result(int ziperr) +{ + switch (ziperr) + { + case UNZ_END_OF_LIST_OF_FILE: + return -ENOENT; + case UNZ_CRCERROR: + return -ESTALE; + case UNZ_INTERNALERROR: + return -EPERM; + case UNZ_BADZIPFILE: + return -EBADF; + case UNZ_PARAMERROR: + return -EINVAL; + default: + return ziperr; + } +} + +static int zipfs_open(FAR struct file *filep, FAR const char *relpath, + int oflags, mode_t mode) +{ + FAR struct zipfs_mountpt_s *fs = filep->f_inode->i_private; + FAR struct zipfs_file_s *fp; + int ret; + + DEBUGASSERT(fs != NULL); + + fp = kmm_malloc(sizeof(*fp) + strlen(relpath)); + if (fp == NULL) + { + return -ENOMEM; + } + + ret = nxmutex_init(&fp->lock); + if (ret < 0) + { + goto err_with_fp; + } + + fp->uf = unzOpen2_64(fs->abspath, &zipfs_real_ops); + if (fp->uf == NULL) + { + ret = -EINVAL; + goto err_with_mutex; + } + + ret = zipfs_convert_result(unzLocateFile(fp->uf, relpath, 0)); + if (ret < 0) + { + goto err_with_zip; + } + + ret = zipfs_convert_result(unzOpenCurrentFile(fp->uf)); + if (ret < 0) + { + goto err_with_zip; + } + + if (ret == OK) + { + fp->seekbuf = NULL; + strcpy(fp->relpath, relpath); + filep->f_priv = fp; + } + else + { +err_with_zip: + unzClose(fp->uf); +err_with_mutex: + nxmutex_destroy(&fp->lock); +err_with_fp: + kmm_free(fp); + } + + return ret; +} + +static int zipfs_close(FAR struct file *filep) +{ + FAR struct zipfs_file_s *fp = filep->f_priv; + int ret; + + ret = zipfs_convert_result(unzClose(fp->uf)); + nxmutex_destroy(&fp->lock); + kmm_free(fp->seekbuf); + kmm_free(fp); + return ret; +} + +static ssize_t zipfs_read(FAR struct file *filep, FAR char *buffer, + size_t buflen) +{ + FAR struct zipfs_file_s *fp = filep->f_priv; + ssize_t ret; + + nxmutex_lock(&fp->lock); + ret = zipfs_convert_result(unzReadCurrentFile(fp->uf, buffer, buflen)); + if (ret > 0) + { + filep->f_pos += ret; + } + + nxmutex_unlock(&fp->lock); + return ret; +} + +static off_t zipfs_skip(FAR struct zipfs_file_s *fp, off_t amount) +{ + off_t next = 0; + + if (fp->seekbuf == NULL) + { + fp->seekbuf = kmm_malloc(CONFIG_ZIPFS_SEEK_BUFSIZE); + if (fp->seekbuf == NULL) + { + return -ENOMEM; + } + } + + while (next < amount) + { + off_t remain = amount - next; + + if (remain > CONFIG_ZIPFS_SEEK_BUFSIZE) + { + remain = CONFIG_ZIPFS_SEEK_BUFSIZE; + } + + remain = unzReadCurrentFile(fp->uf, fp->seekbuf, remain); + remain = zipfs_convert_result(remain); + if (remain <= 0) + { + return next ? next : remain; + } + + next += remain; + } + + return next; +} + +static off_t zipfs_seek(FAR struct file *filep, off_t offset, + int whence) +{ + FAR struct zipfs_mountpt_s *fs = filep->f_inode->i_private; + FAR struct zipfs_file_s *fp = filep->f_priv; + unz_file_info64 file_info; + off_t ret = 0; + + nxmutex_lock(&fp->lock); + switch (whence) + { + case SEEK_SET: + break; + case SEEK_CUR: + offset += filep->f_pos; + break; + case SEEK_END: + ret = unzGetCurrentFileInfo64(fp->uf, &file_info, + NULL, 0, NULL, 0, NULL, 0); + ret = zipfs_convert_result(ret); + if (ret < 0) + { + goto err_with_lock; + } + + offset += file_info.uncompressed_size; + break; + default: + ret = -EINVAL; + goto err_with_lock; + } + + if (filep->f_pos == offset) + { + goto err_with_lock; + } + else if (filep->f_pos > offset) + { + ret = zipfs_convert_result(unzClose(fp->uf)); + if (ret < 0) + { + goto err_with_lock; + } + + fp->uf = unzOpen2_64(fs->abspath, &zipfs_real_ops); + if (fp->uf == NULL) + { + ret = -EINVAL; + goto err_with_lock; + } + + ret = zipfs_convert_result(unzLocateFile(fp->uf, fp->relpath, 0)); + if (ret < 0) + { + goto err_with_lock; + } + + ret = zipfs_convert_result(unzOpenCurrentFile(fp->uf)); + if (ret < 0) + { + goto err_with_lock; + } + + filep->f_pos = 0; + } + + ret = zipfs_skip(fp, offset - filep->f_pos); + if (ret < 0) + { + goto err_with_lock; + } + + if (ret >= 0) + { + filep->f_pos += ret; + } + +err_with_lock: + nxmutex_unlock(&fp->lock); + return ret < 0 ? ret : filep->f_pos; +} + +static int zipfs_dup(FAR const struct file *oldp, FAR struct file *newp) +{ + FAR struct zipfs_file_s *fp; + + fp = oldp->f_priv; + return zipfs_open(newp, fp->relpath, oldp->f_oflags, 0); +} + +static int zipfs_stat_common(unzFile uf, FAR struct stat *buf) +{ + unz_file_info64 file_info; + int ret; + + memset(buf, 0, sizeof(struct stat)); + + ret = unzGetCurrentFileInfo64(uf, &file_info, NULL, 0, + NULL, 0, NULL, 0); + ret = zipfs_convert_result(ret); + if (ret >= 0) + { + buf->st_size = file_info.uncompressed_size; + buf->st_mode = S_IFREG | 0444; + } + + return ret; +} + +static int zipfs_fstat(FAR const struct file *filep, + FAR struct stat *buf) +{ + FAR struct zipfs_file_s *fp = filep->f_priv; + + return zipfs_stat_common(fp->uf, buf); +} + +static int zipfs_opendir(FAR struct inode *mountpt, FAR const char *relpath, + FAR struct fs_dirent_s **dir) +{ + FAR struct zipfs_mountpt_s *fs = mountpt->i_private; + FAR struct zipfs_dir_s *zdir; + int ret; + + DEBUGASSERT(fs != NULL); + + zdir = kmm_malloc(sizeof(*zdir)); + if (zdir == NULL) + { + return -ENOMEM; + } + + ret = nxmutex_init(&zdir->lock); + if (ret < 0) + { + kmm_free(zdir); + return ret; + } + + zdir->uf = unzOpen2_64(fs->abspath, &zipfs_real_ops); + if (zdir->uf == NULL) + { + nxmutex_destroy(&zdir->lock); + kmm_free(zdir); + return -EINVAL; + } + + zdir->last = false; + *dir = &zdir->base; + return ret; +} + +static int zipfs_closedir(FAR struct inode *mountpt, + FAR struct fs_dirent_s *dir) +{ + FAR struct zipfs_dir_s *zdir = (FAR struct zipfs_dir_s *)dir; + int ret; + + zdir = (FAR struct zipfs_dir_s *)dir; + ret = zipfs_convert_result(unzClose(zdir->uf)); + nxmutex_destroy(&zdir->lock); + kmm_free(zdir); + return ret; +} + +static int zipfs_readdir(FAR struct inode *mountpt, + FAR struct fs_dirent_s *dir, + FAR struct dirent *entry) +{ + FAR struct zipfs_dir_s *zdir = (FAR struct zipfs_dir_s *)dir; + unz_file_info64 file_info; + int ret; + + nxmutex_lock(&zdir->lock); + ret = unzGetCurrentFileInfo64(zdir->uf, + &file_info, + entry->d_name, + NAME_MAX, NULL, 0, NULL, 0); + + ret = zipfs_convert_result(ret); + if (ret < 0) + { + goto err_with_lock; + } + + ret = zipfs_convert_result(unzGoToNextFile(zdir->uf)); + if (ret == -ENOENT) + { + if (zdir->last == false) + { + ret = OK; + zdir->last = true; + } + } + +err_with_lock: + nxmutex_unlock(&zdir->lock); + return ret; +} + +static int zipfs_rewinddir(FAR struct inode *mountpt, + FAR struct fs_dirent_s *dir) +{ + FAR struct zipfs_dir_s *zdir = (FAR struct zipfs_dir_s *)dir; + int ret; + + nxmutex_lock(&zdir->lock); + zdir->last = false; + ret = zipfs_convert_result(unzGoToFirstFile(zdir->uf)); + nxmutex_unlock(&zdir->lock); + return ret; +} + +static int zipfs_bind(FAR struct inode *driver, FAR const void *data, + FAR void **handle) +{ + FAR struct zipfs_mountpt_s *fs; + unzFile uf; + + if (data == NULL) + { + return -ENODEV; + } + + fs = kmm_zalloc(sizeof(struct zipfs_mountpt_s) + strlen(data)); + if (fs == NULL) + { + return -ENOMEM; + } + + uf = unzOpen2_64(data, &zipfs_real_ops); + if (uf == NULL) + { + kmm_free(fs); + return -EINVAL; + } + + unzClose(uf); + strcpy(fs->abspath, data); + *handle = fs; + + return OK; +} + +static int zipfs_unbind(FAR void *handle, FAR struct inode **driver, + unsigned int flags) +{ + kmm_free(handle); + return OK; +} + +static int zipfs_statfs(FAR struct inode *mountpt, FAR struct statfs *buf) +{ + buf->f_type = ZIPFS_MAGIC; + buf->f_namelen = NAME_MAX; + return OK; +} + +static int zipfs_stat(FAR struct inode *mountpt, + FAR const char *relpath, FAR struct stat *buf) +{ + FAR struct zipfs_mountpt_s *fs; + unzFile uf; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + if (relpath[0] == 0) + { + buf->st_mode = S_IFDIR; + return OK; + } + + fs = mountpt->i_private; + uf = unzOpen2_64(fs->abspath, &zipfs_real_ops); + if (uf == NULL) + { + return -EINVAL; + } + + ret = zipfs_convert_result(unzLocateFile(uf, relpath, 0)); + if (ret < 0) + { + unzClose(uf); + return ret; + } + + ret = zipfs_stat_common(uf, buf); + + unzClose(uf); + return ret; +} diff --git a/fs/zipfs/zlib b/fs/zipfs/zlib new file mode 120000 index 0000000000..8ab5e15716 --- /dev/null +++ b/fs/zipfs/zlib @@ -0,0 +1 @@ +../../../apps/system/zlib \ No newline at end of file diff --git a/include/sys/statfs.h b/include/sys/statfs.h index bf458b9be8..68c711cde4 100644 --- a/include/sys/statfs.h +++ b/include/sys/statfs.h @@ -94,6 +94,7 @@ #define USERFS_MAGIC 0x52455355 #define CROMFS_MAGIC 0x4d4f5243 #define RPMSGFS_MAGIC 0x54534f47 +#define ZIPFS_MAGIC 0x504b #if defined(CONFIG_FS_LARGEFILE) # define statfs64 statfs diff --git a/tools/nxstyle.c b/tools/nxstyle.c index 08be74f217..4652a3e848 100644 --- a/tools/nxstyle.c +++ b/tools/nxstyle.c @@ -549,6 +549,20 @@ static const char *g_white_content_list[] = "IRQn_Type", + /* Ref: + * fs/zipfs/zip_vfs.c + */ + + "unzFile", + "uLong", + "unzOpen2_64", + "unzLocateFile", + "unzOpenCurrentFile", + "unzClose", + "unzReadCurrentFile", + "unzGetCurrentFileInfo64", + "unzGoToNextFile", + "unzGoToFirstFile", NULL };