taisei/src/vfs/loadpacks.c
Andrei Alexeyev b6978178b1
memory: use custom memory allocation wrappers
Introduces wrappers around memory allocation functions in `memory.h`
that should be used instead of the standard C ones.

These never return NULL and, with the exception of `mem_realloc()`,
zero-initialize the allocated memory like `calloc()` does.

All allocations made with the memory.h API must be deallocated with
`mem_free()`. Although standard `free()` will work on some platforms,
it's not portable (currently it won't work on Windows). Likewise,
`mem_free()` must not be used to free foreign allocations.

The standard C allocation functions are now diagnosed as deprecated.
They are, however, available with the `libc_` prefix in case interfacing
with foreign APIs is required. So far they are only used to implement
`memory.h`.

Perhaps the most important change is the introduction of the `ALLOC()`,
`ALLOC_ARRAY()`, and `ALLOC_FLEX()` macros. They take a type as a
parameter, and allocate enough memory with the correct alignment for
that type. That includes overaligned types as well. In most
circumstances you should prefer to use these macros. See the `memory.h`
header for some usage examples.
2023-01-18 13:23:22 +01:00

90 lines
2 KiB
C

/*
* This software is licensed under the terms of the MIT License.
* See COPYING for further information.
* ---
* Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>.
* Copyright (c) 2012-2019, Andrei Alexeyev <akari@taisei-project.org>.
*/
#include "taisei.h"
#include "loadpacks.h"
#include "public.h"
#include "setup.h"
#include "error.h"
#include "util.h"
static bool vfs_mount_pkgdir(const char *dst, const char *src) {
VFSInfo stat = vfs_query(src);
if(stat.error) {
return false;
}
if(!stat.exists || !stat.is_dir) {
vfs_set_error("Not a directory");
return false;
}
return vfs_mount_alias(dst, src);
}
static struct pkg_loader_t {
const char *const ext;
bool (*mount)(const char *mp, const char *arg);
} pkg_loaders[] = {
{ ".zip", vfs_mount_zipfile },
{ ".pkgdir", vfs_mount_pkgdir },
{ NULL },
};
static struct pkg_loader_t* find_loader(const char *str) {
char buf[strlen(str) + 1];
memset(buf, 0, sizeof(buf));
for(char *p = buf; *str; ++p, ++str) {
*p = tolower(*str);
}
for(struct pkg_loader_t *l = pkg_loaders; l->ext; ++l) {
if(strendswith(buf, l->ext)) {
return l;
}
}
return NULL;
}
void vfs_load_packages(const char *dir, const char *unionmp) {
// go over the packages in dir in alphapetical order and merge them into unionmp
// e.g. files in 00-aaa.zip will be shadowed by files in 99-zzz.zip
size_t numpaks = 0;
char **paklist = vfs_dir_list_sorted(dir, &numpaks, vfs_dir_list_order_ascending, NULL);
if(!paklist) {
log_fatal("VFS error: %s", vfs_get_error());
}
for(size_t i = 0; i < numpaks; ++i) {
const char *entry = paklist[i];
struct pkg_loader_t *loader = find_loader(entry);
if(loader == NULL) {
continue;
}
log_info("Adding package: %s", entry);
assert(loader->mount != NULL);
char *tmp = strfmt("%s/%s", dir, entry);
if(!loader->mount(unionmp, tmp)) {
log_error("VFS error: %s", vfs_get_error());
}
mem_free(tmp);
}
vfs_dir_list_free(paklist, numpaks);
}