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