b6978178b1
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.
90 lines
2 KiB
C
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);
|
|
}
|