Mercurial > molko
view libmlk-core/mlk/core/vfs-zip.c @ 645:83781cc87fca
core: rework game stack state mechanism
The current model was fundamentally broken as the state could continue its
execution when calling mlk_game_pop from itself (e.g. in update).
The current model uses a sjlj mechanism with mlk_game_push/pop being disallowed
in special state function like end, finish, suspend.
author | David Demelier <markand@malikania.fr> |
---|---|
date | Sun, 04 Feb 2024 15:24:00 +0100 |
parents | fcd124e513ea |
children |
line wrap: on
line source
/* * vfs-zip.c -- VFS subsystem for zip archives * * Copyright (c) 2020-2022 David Demelier <markand@malikania.fr> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "sysconfig.h" #if defined(MLK_WITH_ZIP) #include <assert.h> #include <string.h> #include <zip.h> #include "alloc.h" #include "err.h" #include "util.h" #include "vfs-zip.h" #include "vfs.h" #define MLK_VFS_ZIP_FILE(self) \ MLK_CONTAINER_OF(self, struct mlk_vfs_zip_file, file) #define MLK_VFS_ZIP(self) \ MLK_CONTAINER_OF(self, struct mlk_vfs_zip, vfs) static inline int mkflags(const char *mode) { /* TODO: this should check for mutual exclusions. */ int flags = 0; for (; *mode; ++mode) { switch (*mode) { case 'w': flags |= ZIP_CREATE; break; case 'x': flags |= ZIP_EXCL; break; case '+': flags |= ZIP_TRUNCATE; break; case 'r': flags |= ZIP_RDONLY; break; default: break; } } return flags; } static size_t file_read(struct mlk_vfs_file *self, void *buf, size_t bufsz) { return mlk_vfs_zip_file_read(MLK_VFS_ZIP_FILE(self), buf, bufsz); } static void file_finish(struct mlk_vfs_file *self) { mlk_vfs_zip_file_finish(MLK_VFS_ZIP_FILE(self)); } static struct mlk_vfs_file * vfs_open(struct mlk_vfs *self, const char *entry, const char *mode) { return mlk_vfs_zip_open(MLK_VFS_ZIP(self), entry, mode); } static void vfs_finish(struct mlk_vfs *self) { mlk_vfs_zip_finish(MLK_VFS_ZIP(self)); } int mlk_vfs_zip_init(struct mlk_vfs_zip *zip, const char *file, const char *mode) { assert(zip); assert(file); assert(mode); if (!(zip->handle = zip_open(file, mkflags(mode), NULL))) { mlk_errf("%s: unable to open zip file", file); return -1; } zip->vfs.data = NULL; zip->vfs.open = vfs_open; zip->vfs.finish = vfs_finish; return 0; } struct mlk_vfs_file * mlk_vfs_zip_open(struct mlk_vfs_zip *zip, const char *entry, const char *mode) { (void)mode; struct mlk_vfs_zip_file *file; file = mlk_alloc_new0(1, sizeof (*file)); if (!(file->handle = zip_fopen(zip->handle, entry, 0))) { mlk_errf("unable to open file in archive"); mlk_alloc_free(file); return NULL; } file->file.read = file_read; file->file.finish = file_finish; return &file->file; } void mlk_vfs_zip_finish(struct mlk_vfs_zip *zip) { assert(zip); zip_close(zip->handle); zip->handle = NULL; } size_t mlk_vfs_zip_file_read(struct mlk_vfs_zip_file *file, void *buf, size_t bufsz) { assert(file); assert(buf); zip_int64_t rv; if ((rv = zip_fread(file->handle, buf, bufsz)) < 0) { mlk_errf("%s", zip_file_strerror(file->handle)); return -1; } return rv; } void mlk_vfs_zip_file_finish(struct mlk_vfs_zip_file *file) { assert(file); zip_fclose(file->handle); mlk_alloc_free(file); } #endif /* !MLK_WITH_ZIP */