Replace dynamic allocations with fixed-size buffers and add module extension filtering
- Use fixed STK_PATH_MAX and STK_MOD_ID_BUFFER throughout for predictable memory - Filter by platform-specific extensions (.so/.dll/.dylib) with compile-time length - Add RELOAD event detection and is_module_loaded() helper - Maintain feature parity across all platforms
This commit is contained in:
+4
-2
@@ -4,8 +4,10 @@
|
|||||||
#include "stk_version.h"
|
#include "stk_version.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#define MOD_DIR_BUFFER_SIZE 32
|
#define STK_MOD_DIR_BUFFER 256
|
||||||
#define PATH_BUFFER_SIZE 1024
|
#define STK_MOD_ID_BUFFER 64
|
||||||
|
#define STK_PATH_MAX 256
|
||||||
|
#define STK_PATH_MAX_OS 4096
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|||||||
+44
-43
@@ -8,39 +8,23 @@ void *platform_get_symbol(void *handle, const char *symbol);
|
|||||||
|
|
||||||
typedef void (*stk_module_func)(void);
|
typedef void (*stk_module_func)(void);
|
||||||
|
|
||||||
char **stk_module_ids = NULL;
|
char (*stk_module_ids)[STK_MOD_ID_BUFFER] = NULL;
|
||||||
static void **stk_handles = NULL;
|
void **stk_handles = NULL;
|
||||||
static stk_module_func *stk_inits = NULL;
|
stk_module_func *stk_inits = NULL;
|
||||||
static stk_module_func *stk_shutdowns = NULL;
|
stk_module_func *stk_shutdowns = NULL;
|
||||||
|
|
||||||
size_t module_count = 0;
|
size_t module_count = 0;
|
||||||
|
|
||||||
size_t stk_module_count(void) { return module_count; }
|
size_t stk_module_count(void) { return module_count; }
|
||||||
|
|
||||||
char *extract_module_id(const char *path)
|
int stk_module_load(const char *path, int index)
|
||||||
{
|
|
||||||
char *id, *dot;
|
|
||||||
const char *basename = strrchr(path, '/');
|
|
||||||
if (!basename)
|
|
||||||
basename = path;
|
|
||||||
else
|
|
||||||
basename++;
|
|
||||||
|
|
||||||
id = malloc(strlen(basename) + 1);
|
|
||||||
strcpy(id, basename);
|
|
||||||
|
|
||||||
dot = strrchr(id, '.');
|
|
||||||
if (dot)
|
|
||||||
*dot = '\0';
|
|
||||||
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
int stk_module_load(const char *path)
|
|
||||||
{
|
{
|
||||||
void *handle;
|
void *handle;
|
||||||
stk_module_func init_func;
|
stk_module_func init_func;
|
||||||
stk_module_func shutdown_func;
|
stk_module_func shutdown_func;
|
||||||
|
const char *basename;
|
||||||
|
char *dot;
|
||||||
|
char module_id[STK_MOD_ID_BUFFER];
|
||||||
|
|
||||||
handle = platform_load_library(path);
|
handle = platform_load_library(path);
|
||||||
if (!handle)
|
if (!handle)
|
||||||
@@ -56,32 +40,49 @@ int stk_module_load(const char *path)
|
|||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
stk_module_ids[module_count] = extract_module_id(path);
|
if (index == -1)
|
||||||
stk_handles[module_count] = handle;
|
index = module_count;
|
||||||
stk_inits[module_count] = init_func;
|
|
||||||
stk_shutdowns[module_count] = shutdown_func;
|
|
||||||
|
|
||||||
init_func();
|
basename = strrchr(path, '/');
|
||||||
|
if (!basename)
|
||||||
|
basename = path;
|
||||||
|
else
|
||||||
|
basename++;
|
||||||
|
|
||||||
|
strncpy(module_id, basename, STK_MOD_ID_BUFFER - 1);
|
||||||
|
module_id[STK_MOD_ID_BUFFER - 1] = '\0';
|
||||||
|
|
||||||
|
dot = strrchr(module_id, '.');
|
||||||
|
if (dot)
|
||||||
|
*dot = '\0';
|
||||||
|
|
||||||
|
strncpy(stk_module_ids[index], module_id, STK_MOD_ID_BUFFER - 1);
|
||||||
|
stk_module_ids[index][STK_MOD_ID_BUFFER - 1] = '\0';
|
||||||
|
|
||||||
|
stk_handles[index] = handle;
|
||||||
|
stk_inits[index] = init_func;
|
||||||
|
stk_shutdowns[index] = shutdown_func;
|
||||||
|
|
||||||
|
init_func(); /* TODO eventually, this should have some sort of check */
|
||||||
|
|
||||||
++module_count;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int stk_module_load_init(const char *path, int index)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
result = stk_module_load(path, index);
|
||||||
|
|
||||||
|
if (result == 0)
|
||||||
|
++module_count;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void stk_module_unload(size_t index)
|
void stk_module_unload(size_t index)
|
||||||
{
|
{
|
||||||
size_t i;
|
|
||||||
|
|
||||||
stk_shutdowns[index]();
|
stk_shutdowns[index]();
|
||||||
platform_unload_library(stk_handles[index]);
|
platform_unload_library(stk_handles[index]);
|
||||||
|
|
||||||
for (i = index; i < module_count - 1; ++i) {
|
|
||||||
stk_module_ids[i] = stk_module_ids[i + 1];
|
|
||||||
stk_handles[i] = stk_handles[i + 1];
|
|
||||||
stk_inits[i] = stk_inits[i + 1];
|
|
||||||
stk_shutdowns[i] = stk_shutdowns[i + 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
--module_count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void stk_module_free_memory(void)
|
void stk_module_free_memory(void)
|
||||||
@@ -99,12 +100,12 @@ void stk_module_free_memory(void)
|
|||||||
|
|
||||||
int stk_module_init_memory(size_t capacity)
|
int stk_module_init_memory(size_t capacity)
|
||||||
{
|
{
|
||||||
stk_module_ids = malloc(capacity * sizeof(char *));
|
stk_module_ids = malloc(capacity * sizeof(*stk_module_ids));
|
||||||
stk_handles = malloc(capacity * sizeof(void *));
|
stk_handles = malloc(capacity * sizeof(void *));
|
||||||
stk_inits = malloc(capacity * sizeof(stk_module_func));
|
stk_inits = malloc(capacity * sizeof(stk_module_func));
|
||||||
stk_shutdowns = malloc(capacity * sizeof(stk_module_func));
|
stk_shutdowns = malloc(capacity * sizeof(stk_module_func));
|
||||||
|
|
||||||
if (!stk_handles || !stk_inits || !stk_shutdowns) {
|
if (!stk_module_ids || !stk_handles || !stk_inits || !stk_shutdowns) {
|
||||||
stk_module_free_memory();
|
stk_module_free_memory();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
+275
-238
@@ -22,93 +22,104 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define EVENT_BUFFER_SIZE 4096
|
#if defined(__linux__) || defined(_WIN32)
|
||||||
|
#define STK_EVENT_BUFFER 4096
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
static char **scan_directory(const char *path, size_t *out_count)
|
#define STK_MODULE_EXT ".dll"
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
#define STK_MODULE_EXT ".dylib"
|
||||||
|
#else
|
||||||
|
#define STK_MODULE_EXT ".so"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define STK_MODULE_EXT_LEN (sizeof(STK_MODULE_EXT) - 1)
|
||||||
|
|
||||||
|
static uint8_t is_valid_module_file(const char *filename)
|
||||||
{
|
{
|
||||||
DIR *dir;
|
const char *ext;
|
||||||
struct dirent *entry;
|
size_t name_len;
|
||||||
struct stat file_stat;
|
|
||||||
char full_path[PATH_BUFFER_SIZE];
|
|
||||||
char **file_list = NULL;
|
|
||||||
size_t count = 0, index = 0;
|
|
||||||
|
|
||||||
dir = opendir(path);
|
if (!filename)
|
||||||
if (!dir) {
|
return 0;
|
||||||
mkdir(path, 0755);
|
|
||||||
*out_count = 0;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((entry = readdir(dir)) != NULL) {
|
name_len = strlen(filename);
|
||||||
sprintf(full_path, "%s/%s", path, entry->d_name);
|
|
||||||
if (stat(full_path, &file_stat) == 0 &&
|
|
||||||
S_ISREG(file_stat.st_mode))
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count == 0) {
|
if (name_len <= STK_MODULE_EXT_LEN)
|
||||||
closedir(dir);
|
return 0;
|
||||||
*out_count = 0;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
rewinddir(dir);
|
ext = filename + (name_len - STK_MODULE_EXT_LEN);
|
||||||
|
return strcmp(ext, STK_MODULE_EXT) == 0;
|
||||||
file_list = (char **)malloc(count * sizeof(char *));
|
|
||||||
if (!file_list) {
|
|
||||||
closedir(dir);
|
|
||||||
*out_count = 0;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((entry = readdir(dir)) != NULL && index < count) {
|
|
||||||
sprintf(full_path, "%s/%s", path, entry->d_name);
|
|
||||||
if (stat(full_path, &file_stat) != 0 ||
|
|
||||||
!S_ISREG(file_stat.st_mode))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
file_list[index] = (char *)malloc(strlen(entry->d_name) + 1);
|
|
||||||
if (file_list[index]) {
|
|
||||||
strcpy(file_list[index], entry->d_name);
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
closedir(dir);
|
|
||||||
*out_count = index;
|
|
||||||
return file_list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint8_t is_module_loaded(const char *filename,
|
||||||
|
char (*loaded_module_ids)[STK_MOD_ID_BUFFER],
|
||||||
|
size_t loaded_count)
|
||||||
|
{
|
||||||
|
char module_id[STK_MOD_ID_BUFFER];
|
||||||
|
const char *basename;
|
||||||
|
char *dot;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
basename = strrchr(filename, '/');
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (!basename)
|
||||||
|
basename = strrchr(filename, '\\');
|
||||||
#endif
|
#endif
|
||||||
|
if (!basename)
|
||||||
|
basename = filename;
|
||||||
|
else
|
||||||
|
basename++;
|
||||||
|
|
||||||
|
strncpy(module_id, basename, STK_MOD_ID_BUFFER - 1);
|
||||||
|
module_id[STK_MOD_ID_BUFFER - 1] = '\0';
|
||||||
|
|
||||||
|
dot = strrchr(module_id, '.');
|
||||||
|
if (dot)
|
||||||
|
*dot = '\0';
|
||||||
|
|
||||||
|
for (i = 0; i < loaded_count; i++)
|
||||||
|
if (strcmp(loaded_module_ids[i], module_id) == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#if !defined(__linux__) && !defined(_WIN32)
|
#if !defined(__linux__) && !defined(_WIN32)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char *filename;
|
char filename[STK_PATH_MAX];
|
||||||
time_t mtime;
|
time_t mtime;
|
||||||
} file_snapshot_t;
|
} file_snapshot_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int kq;
|
int kq;
|
||||||
int dir_fd;
|
int dir_fd;
|
||||||
char path[PATH_BUFFER_SIZE];
|
char path[STK_PATH_MAX];
|
||||||
file_snapshot_t *snapshots;
|
file_snapshot_t *snapshots;
|
||||||
size_t snapshot_count;
|
size_t snapshot_count;
|
||||||
|
size_t snapshot_capacity;
|
||||||
} kqueue_watch_context_t;
|
} kqueue_watch_context_t;
|
||||||
|
|
||||||
static file_snapshot_t *create_snapshot(const char *path, size_t *out_count)
|
static file_snapshot_t *create_snapshot(const char *path, size_t *out_count,
|
||||||
|
size_t *out_capacity)
|
||||||
{
|
{
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
struct dirent *entry;
|
struct dirent *entry;
|
||||||
struct stat file_stat;
|
struct stat file_stat;
|
||||||
char full_path[PATH_BUFFER_SIZE];
|
char work_path[STK_PATH_MAX_OS];
|
||||||
file_snapshot_t *snapshots = NULL;
|
file_snapshot_t *snapshots;
|
||||||
size_t count = 0, index = 0;
|
size_t count, capacity, index;
|
||||||
|
|
||||||
|
snapshots = NULL;
|
||||||
|
count = 0;
|
||||||
|
capacity = 0;
|
||||||
|
index = 0;
|
||||||
|
|
||||||
dir = opendir(path);
|
dir = opendir(path);
|
||||||
if (!dir) {
|
if (!dir) {
|
||||||
*out_count = 0;
|
*out_count = 0;
|
||||||
|
*out_capacity = 0;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,9 +127,12 @@ static file_snapshot_t *create_snapshot(const char *path, size_t *out_count)
|
|||||||
if (strcmp(entry->d_name, ".") == 0 ||
|
if (strcmp(entry->d_name, ".") == 0 ||
|
||||||
strcmp(entry->d_name, "..") == 0)
|
strcmp(entry->d_name, "..") == 0)
|
||||||
continue;
|
continue;
|
||||||
snprintf(full_path, sizeof(full_path), "%s/%s", path,
|
|
||||||
entry->d_name);
|
if (!is_valid_module_file(entry->d_name))
|
||||||
if (stat(full_path, &file_stat) == 0 &&
|
continue;
|
||||||
|
|
||||||
|
sprintf(work_path, "%s/%s", path, entry->d_name);
|
||||||
|
if (stat(work_path, &file_stat) == 0 &&
|
||||||
S_ISREG(file_stat.st_mode))
|
S_ISREG(file_stat.st_mode))
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
@@ -126,13 +140,16 @@ static file_snapshot_t *create_snapshot(const char *path, size_t *out_count)
|
|||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
*out_count = 0;
|
*out_count = 0;
|
||||||
|
*out_capacity = 0;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
snapshots = malloc(count * sizeof(file_snapshot_t));
|
capacity = count + 8;
|
||||||
|
snapshots = malloc(capacity * sizeof(file_snapshot_t));
|
||||||
if (!snapshots) {
|
if (!snapshots) {
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
*out_count = 0;
|
*out_count = 0;
|
||||||
|
*out_capacity = 0;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,47 +159,39 @@ static file_snapshot_t *create_snapshot(const char *path, size_t *out_count)
|
|||||||
if (strcmp(entry->d_name, ".") == 0 ||
|
if (strcmp(entry->d_name, ".") == 0 ||
|
||||||
strcmp(entry->d_name, "..") == 0)
|
strcmp(entry->d_name, "..") == 0)
|
||||||
continue;
|
continue;
|
||||||
snprintf(full_path, sizeof(full_path), "%s/%s", path,
|
|
||||||
entry->d_name);
|
if (!is_valid_module_file(entry->d_name))
|
||||||
if (stat(full_path, &file_stat) != 0 ||
|
continue;
|
||||||
|
|
||||||
|
sprintf(work_path, "%s/%s", path, entry->d_name);
|
||||||
|
if (stat(work_path, &file_stat) != 0 ||
|
||||||
!S_ISREG(file_stat.st_mode))
|
!S_ISREG(file_stat.st_mode))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
snapshots[index].filename = malloc(strlen(entry->d_name) + 1);
|
strncpy(snapshots[index].filename, entry->d_name,
|
||||||
if (snapshots[index].filename) {
|
STK_PATH_MAX - 1);
|
||||||
strcpy(snapshots[index].filename, entry->d_name);
|
snapshots[index].filename[STK_PATH_MAX - 1] = '\0';
|
||||||
snapshots[index].mtime = file_stat.st_mtime;
|
snapshots[index].mtime = file_stat.st_mtime;
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
*out_count = index;
|
*out_count = index;
|
||||||
|
*out_capacity = capacity;
|
||||||
return snapshots;
|
return snapshots;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_snapshot(file_snapshot_t *snapshots, size_t count)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
if (!snapshots)
|
|
||||||
return;
|
|
||||||
for (i = 0; i < count; i++) {
|
|
||||||
free(snapshots[i].filename);
|
|
||||||
}
|
|
||||||
free(snapshots);
|
|
||||||
}
|
|
||||||
|
|
||||||
static file_snapshot_t *find_in_snapshot(file_snapshot_t *snapshots,
|
static file_snapshot_t *find_in_snapshot(file_snapshot_t *snapshots,
|
||||||
size_t count, const char *filename)
|
size_t count, const char *filename)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
if (strcmp(snapshots[i].filename, filename) == 0)
|
if (strcmp(snapshots[i].filename, filename) == 0) {
|
||||||
return &snapshots[i];
|
return &snapshots[i];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void *platform_load_library(const char *path)
|
void *platform_load_library(const char *path)
|
||||||
@@ -216,60 +225,50 @@ void *platform_directory_watch_start(const char *path)
|
|||||||
{
|
{
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
int fd, wd;
|
int fd, wd;
|
||||||
|
|
||||||
fd = inotify_init1(IN_NONBLOCK);
|
fd = inotify_init1(IN_NONBLOCK);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
wd = inotify_add_watch(
|
wd = inotify_add_watch(
|
||||||
fd, path, IN_CLOSE_WRITE | IN_DELETE | IN_MOVED_TO | IN_MOVED_FROM);
|
fd, path, IN_CLOSE_WRITE | IN_DELETE | IN_MOVED_TO | IN_MOVED_FROM);
|
||||||
|
|
||||||
if (wd < 0) {
|
if (wd < 0) {
|
||||||
close(fd);
|
close(fd);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (void *)(long)fd;
|
return (void *)(long)fd;
|
||||||
|
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
HANDLE handle =
|
HANDLE handle =
|
||||||
CreateFileA(path, FILE_LIST_DIRECTORY,
|
CreateFileA(path, FILE_LIST_DIRECTORY,
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||||
|
return (handle == INVALID_HANDLE_VALUE) ? NULL : (void *)handle;
|
||||||
if (handle == INVALID_HANDLE_VALUE)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return (void *)handle;
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
struct kevent event;
|
struct kevent event;
|
||||||
kqueue_watch_context_t *ctx = malloc(sizeof(kqueue_watch_context_t));
|
kqueue_watch_context_t *ctx;
|
||||||
|
|
||||||
|
ctx = malloc(sizeof(kqueue_watch_context_t));
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ctx->kq = kqueue();
|
ctx->kq = kqueue();
|
||||||
ctx->dir_fd = open(path, O_RDONLY);
|
ctx->dir_fd = open(path, O_RDONLY);
|
||||||
strncpy(ctx->path, path, PATH_BUFFER_SIZE - 1);
|
strncpy(ctx->path, path, STK_PATH_MAX - 1);
|
||||||
ctx->path[PATH_BUFFER_SIZE - 1] = '\0';
|
ctx->path[STK_PATH_MAX - 1] = '\0';
|
||||||
|
ctx->snapshots = create_snapshot(path, &ctx->snapshot_count,
|
||||||
ctx->snapshots = create_snapshot(path, &ctx->snapshot_count);
|
&ctx->snapshot_capacity);
|
||||||
|
|
||||||
if (ctx->kq < 0 || ctx->dir_fd < 0) {
|
if (ctx->kq < 0 || ctx->dir_fd < 0) {
|
||||||
if (ctx->kq >= 0)
|
if (ctx->kq >= 0)
|
||||||
close(ctx->kq);
|
close(ctx->kq);
|
||||||
if (ctx->dir_fd >= 0)
|
if (ctx->dir_fd >= 0)
|
||||||
close(ctx->dir_fd);
|
close(ctx->dir_fd);
|
||||||
free_snapshot(ctx->snapshots, ctx->snapshot_count);
|
free(ctx->snapshots);
|
||||||
free(ctx);
|
free(ctx);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
EV_SET(&event, ctx->dir_fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR,
|
EV_SET(&event, ctx->dir_fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR,
|
||||||
NOTE_WRITE | NOTE_DELETE | NOTE_RENAME, 0, NULL);
|
NOTE_WRITE | NOTE_DELETE | NOTE_RENAME, 0, NULL);
|
||||||
|
|
||||||
kevent(ctx->kq, &event, 1, NULL, 0, NULL);
|
kevent(ctx->kq, &event, 1, NULL, 0, NULL);
|
||||||
|
|
||||||
return (void *)ctx;
|
return (void *)ctx;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -277,43 +276,42 @@ void *platform_directory_watch_start(const char *path)
|
|||||||
void platform_directory_watch_stop(void *handle)
|
void platform_directory_watch_stop(void *handle)
|
||||||
{
|
{
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
if (!handle)
|
if (handle)
|
||||||
return;
|
|
||||||
close((int)(long)handle);
|
close((int)(long)handle);
|
||||||
|
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
|
if (handle)
|
||||||
CloseHandle((HANDLE)handle);
|
CloseHandle((HANDLE)handle);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
kqueue_watch_context_t *ctx = (kqueue_watch_context_t *)handle;
|
kqueue_watch_context_t *ctx;
|
||||||
|
ctx = (kqueue_watch_context_t *)handle;
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (ctx->dir_fd >= 0)
|
if (ctx->dir_fd >= 0)
|
||||||
close(ctx->dir_fd);
|
close(ctx->dir_fd);
|
||||||
if (ctx->kq >= 0)
|
if (ctx->kq >= 0)
|
||||||
close(ctx->kq);
|
close(ctx->kq);
|
||||||
free_snapshot(ctx->snapshots, ctx->snapshot_count);
|
free(ctx->snapshots);
|
||||||
free(ctx);
|
free(ctx);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
stk_module_event_t *platform_directory_watch_check(void *handle,
|
stk_module_event_t *platform_directory_watch_check(
|
||||||
char ***file_list,
|
void *handle, char (**file_list)[STK_PATH_MAX], size_t *out_count,
|
||||||
size_t *out_count)
|
char (*loaded_module_ids)[STK_MOD_ID_BUFFER], const size_t loaded_count)
|
||||||
{
|
{
|
||||||
#if defined(__linux__) || defined(_WIN32)
|
|
||||||
size_t file_count = 0;
|
|
||||||
#endif
|
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
stk_module_event_t *events = NULL;
|
stk_module_event_t *events = NULL;
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
char buffer[EVENT_BUFFER_SIZE];
|
char buffer[STK_EVENT_BUFFER];
|
||||||
ssize_t bytes_read;
|
ssize_t bytes_read;
|
||||||
struct inotify_event *event;
|
struct inotify_event *event;
|
||||||
char *event_ptr;
|
char *event_ptr;
|
||||||
int fd = (int)(long)handle;
|
int fd;
|
||||||
|
size_t file_count;
|
||||||
|
|
||||||
|
fd = (int)(long)handle;
|
||||||
|
file_count = 0;
|
||||||
|
|
||||||
bytes_read = read(fd, buffer, sizeof(buffer));
|
bytes_read = read(fd, buffer, sizeof(buffer));
|
||||||
if (bytes_read <= 0) {
|
if (bytes_read <= 0) {
|
||||||
@@ -324,7 +322,7 @@ stk_module_event_t *platform_directory_watch_check(void *handle,
|
|||||||
event_ptr = buffer;
|
event_ptr = buffer;
|
||||||
while (event_ptr < buffer + bytes_read) {
|
while (event_ptr < buffer + bytes_read) {
|
||||||
event = (struct inotify_event *)event_ptr;
|
event = (struct inotify_event *)event_ptr;
|
||||||
if (event->len > 0)
|
if (event->len > 0 && is_valid_module_file(event->name))
|
||||||
file_count++;
|
file_count++;
|
||||||
event_ptr += sizeof(struct inotify_event) + event->len;
|
event_ptr += sizeof(struct inotify_event) + event->len;
|
||||||
}
|
}
|
||||||
@@ -335,40 +333,43 @@ stk_module_event_t *platform_directory_watch_check(void *handle,
|
|||||||
}
|
}
|
||||||
|
|
||||||
events = malloc(file_count * sizeof(stk_module_event_t));
|
events = malloc(file_count * sizeof(stk_module_event_t));
|
||||||
*file_list = malloc(file_count * sizeof(char *));
|
*file_list = malloc(file_count * sizeof(**file_list));
|
||||||
if (!events || !*file_list) {
|
|
||||||
free(events);
|
|
||||||
free(*file_list);
|
|
||||||
*out_count = 0;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
index = 0;
|
index = 0;
|
||||||
event_ptr = buffer;
|
event_ptr = buffer;
|
||||||
while (event_ptr < buffer + bytes_read) {
|
while (event_ptr < buffer + bytes_read) {
|
||||||
event = (struct inotify_event *)event_ptr;
|
event = (struct inotify_event *)event_ptr;
|
||||||
if (event->len > 0) {
|
if (event->len > 0 && is_valid_module_file(event->name)) {
|
||||||
events[index] =
|
events[index] =
|
||||||
(event->mask & (IN_CLOSE_WRITE | IN_MOVED_TO))
|
(event->mask & (IN_CLOSE_WRITE | IN_MOVED_TO))
|
||||||
? STK_MOD_LOAD
|
? (is_module_loaded(event->name,
|
||||||
|
loaded_module_ids,
|
||||||
|
loaded_count)
|
||||||
|
? STK_MOD_RELOAD
|
||||||
|
: STK_MOD_LOAD)
|
||||||
: STK_MOD_UNLOAD;
|
: STK_MOD_UNLOAD;
|
||||||
(*file_list)[index] = malloc(strlen(event->name) + 1);
|
strncpy((*file_list)[index], event->name,
|
||||||
if ((*file_list)[index]) {
|
STK_PATH_MAX - 1);
|
||||||
strcpy((*file_list)[index], event->name);
|
(*file_list)[index][STK_PATH_MAX - 1] = '\0';
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
event_ptr += sizeof(struct inotify_event) + event->len;
|
event_ptr += sizeof(struct inotify_event) + event->len;
|
||||||
}
|
}
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
HANDLE h = (HANDLE)handle;
|
HANDLE h;
|
||||||
BYTE buffer[EVENT_BUFFER_SIZE];
|
BYTE buffer[STK_EVENT_BUFFER];
|
||||||
DWORD bytes_returned;
|
DWORD bytes_returned;
|
||||||
FILE_NOTIFY_INFORMATION *info;
|
FILE_NOTIFY_INFORMATION *info;
|
||||||
BYTE *event_ptr;
|
BYTE *event_ptr;
|
||||||
int char_count;
|
size_t file_count;
|
||||||
|
char temp_filename[STK_PATH_MAX];
|
||||||
|
int len;
|
||||||
|
BOOL result;
|
||||||
|
|
||||||
BOOL result = ReadDirectoryChangesW(h, buffer, sizeof(buffer), FALSE,
|
h = (HANDLE)handle;
|
||||||
|
file_count = 0;
|
||||||
|
|
||||||
|
result = ReadDirectoryChangesW(h, buffer, sizeof(buffer), FALSE,
|
||||||
FILE_NOTIFY_CHANGE_FILE_NAME |
|
FILE_NOTIFY_CHANGE_FILE_NAME |
|
||||||
FILE_NOTIFY_CHANGE_LAST_WRITE,
|
FILE_NOTIFY_CHANGE_LAST_WRITE,
|
||||||
&bytes_returned, NULL, NULL);
|
&bytes_returned, NULL, NULL);
|
||||||
@@ -380,7 +381,15 @@ stk_module_event_t *platform_directory_watch_check(void *handle,
|
|||||||
event_ptr = buffer;
|
event_ptr = buffer;
|
||||||
while (1) {
|
while (1) {
|
||||||
info = (FILE_NOTIFY_INFORMATION *)event_ptr;
|
info = (FILE_NOTIFY_INFORMATION *)event_ptr;
|
||||||
|
len = WideCharToMultiByte(CP_UTF8, 0, info->FileName,
|
||||||
|
info->FileNameLength / sizeof(WCHAR),
|
||||||
|
temp_filename, STK_PATH_MAX - 1, NULL,
|
||||||
|
NULL);
|
||||||
|
if (len > 0) {
|
||||||
|
temp_filename[len] = '\0';
|
||||||
|
if (is_valid_module_file(temp_filename))
|
||||||
file_count++;
|
file_count++;
|
||||||
|
}
|
||||||
if (info->NextEntryOffset == 0)
|
if (info->NextEntryOffset == 0)
|
||||||
break;
|
break;
|
||||||
event_ptr += info->NextEntryOffset;
|
event_ptr += info->NextEntryOffset;
|
||||||
@@ -392,67 +401,59 @@ stk_module_event_t *platform_directory_watch_check(void *handle,
|
|||||||
}
|
}
|
||||||
|
|
||||||
events = malloc(file_count * sizeof(stk_module_event_t));
|
events = malloc(file_count * sizeof(stk_module_event_t));
|
||||||
*file_list = malloc(file_count * sizeof(char *));
|
*file_list = malloc(file_count * sizeof(**file_list));
|
||||||
if (!events || !*file_list) {
|
|
||||||
free(events);
|
|
||||||
free(*file_list);
|
|
||||||
*out_count = 0;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
index = 0;
|
index = 0;
|
||||||
event_ptr = buffer;
|
event_ptr = buffer;
|
||||||
while (1) {
|
while (1) {
|
||||||
info = (FILE_NOTIFY_INFORMATION *)event_ptr;
|
info = (FILE_NOTIFY_INFORMATION *)event_ptr;
|
||||||
events[index] = (info->Action == FILE_ACTION_ADDED ||
|
len = WideCharToMultiByte(CP_UTF8, 0, info->FileName,
|
||||||
info->Action == FILE_ACTION_MODIFIED ||
|
info->FileNameLength / sizeof(WCHAR),
|
||||||
info->Action == FILE_ACTION_RENAMED_NEW_NAME)
|
(*file_list)[index], STK_PATH_MAX - 1,
|
||||||
? STK_MOD_LOAD
|
NULL, NULL);
|
||||||
|
if (len > 0) {
|
||||||
|
(*file_list)[index][len] = '\0';
|
||||||
|
if (is_valid_module_file((*file_list)[index])) {
|
||||||
|
events[index] =
|
||||||
|
(info->Action != FILE_ACTION_REMOVED &&
|
||||||
|
info->Action !=
|
||||||
|
FILE_ACTION_RENAMED_OLD_NAME)
|
||||||
|
? (is_module_loaded((*file_list)[index],
|
||||||
|
loaded_module_ids,
|
||||||
|
loaded_count)
|
||||||
|
? STK_MOD_RELOAD
|
||||||
|
: STK_MOD_LOAD)
|
||||||
: STK_MOD_UNLOAD;
|
: STK_MOD_UNLOAD;
|
||||||
char_count = WideCharToMultiByte(
|
|
||||||
CP_UTF8, 0, info->FileName,
|
|
||||||
info->FileNameLength / sizeof(WCHAR), NULL, 0, NULL, NULL);
|
|
||||||
|
|
||||||
if (char_count > 0) {
|
|
||||||
(*file_list)[index] = malloc(char_count + 1);
|
|
||||||
if ((*file_list)[index]) {
|
|
||||||
WideCharToMultiByte(CP_UTF8, 0, info->FileName,
|
|
||||||
info->FileNameLength /
|
|
||||||
sizeof(WCHAR),
|
|
||||||
(*file_list)[index],
|
|
||||||
char_count, NULL, NULL);
|
|
||||||
(*file_list)[index][char_count] = '\0';
|
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->NextEntryOffset == 0)
|
if (info->NextEntryOffset == 0)
|
||||||
break;
|
break;
|
||||||
event_ptr += info->NextEntryOffset;
|
event_ptr += info->NextEntryOffset;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
kqueue_watch_context_t *ctx = (kqueue_watch_context_t *)handle;
|
kqueue_watch_context_t *ctx;
|
||||||
struct kevent event;
|
struct kevent event;
|
||||||
struct timespec timeout = {0, 0};
|
struct timespec timeout;
|
||||||
int nevents;
|
file_snapshot_t *new_snapshots, *old_snap;
|
||||||
file_snapshot_t *new_snapshots, *old_snap, *new_snap;
|
size_t new_count, new_capacity, i, change_count;
|
||||||
size_t new_count, i;
|
|
||||||
size_t change_count = 0;
|
|
||||||
|
|
||||||
nevents = kevent(ctx->kq, NULL, 0, &event, 1, &timeout);
|
ctx = (kqueue_watch_context_t *)handle;
|
||||||
if (nevents <= 0) {
|
timeout.tv_sec = 0;
|
||||||
|
timeout.tv_nsec = 0;
|
||||||
|
change_count = 0;
|
||||||
|
|
||||||
|
if (kevent(ctx->kq, NULL, 0, &event, 1, &timeout) <= 0) {
|
||||||
*out_count = 0;
|
*out_count = 0;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_snapshots = create_snapshot(ctx->path, &new_count);
|
new_snapshots = create_snapshot(ctx->path, &new_count, &new_capacity);
|
||||||
|
|
||||||
for (i = 0; i < ctx->snapshot_count; i++) {
|
for (i = 0; i < ctx->snapshot_count; i++)
|
||||||
new_snap = find_in_snapshot(new_snapshots, new_count,
|
if (!find_in_snapshot(new_snapshots, new_count,
|
||||||
ctx->snapshots[i].filename);
|
ctx->snapshots[i].filename))
|
||||||
if (!new_snap)
|
|
||||||
change_count++;
|
change_count++;
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < new_count; i++) {
|
for (i = 0; i < new_count; i++) {
|
||||||
old_snap = find_in_snapshot(ctx->snapshots, ctx->snapshot_count,
|
old_snap = find_in_snapshot(ctx->snapshots, ctx->snapshot_count,
|
||||||
@@ -462,84 +463,88 @@ stk_module_event_t *platform_directory_watch_check(void *handle,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (change_count == 0) {
|
if (change_count == 0) {
|
||||||
free_snapshot(new_snapshots, new_count);
|
free(new_snapshots);
|
||||||
*out_count = 0;
|
*out_count = 0;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
events = malloc(change_count * sizeof(stk_module_event_t));
|
events = malloc(change_count * sizeof(stk_module_event_t));
|
||||||
*file_list = malloc(change_count * sizeof(char *));
|
*file_list = malloc(change_count * sizeof(**file_list));
|
||||||
if (!events || !*file_list) {
|
|
||||||
free(events);
|
|
||||||
free(*file_list);
|
|
||||||
free_snapshot(new_snapshots, new_count);
|
|
||||||
*out_count = 0;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
index = 0;
|
index = 0;
|
||||||
|
|
||||||
for (i = 0; i < ctx->snapshot_count && index < change_count; i++) {
|
for (i = 0; i < ctx->snapshot_count && index < change_count; i++) {
|
||||||
new_snap = find_in_snapshot(new_snapshots, new_count,
|
if (!find_in_snapshot(new_snapshots, new_count,
|
||||||
ctx->snapshots[i].filename);
|
ctx->snapshots[i].filename)) {
|
||||||
if (!new_snap) {
|
|
||||||
events[index] = STK_MOD_UNLOAD;
|
events[index] = STK_MOD_UNLOAD;
|
||||||
(*file_list)[index] =
|
strncpy((*file_list)[index], ctx->snapshots[i].filename,
|
||||||
malloc(strlen(ctx->snapshots[i].filename) + 1);
|
STK_PATH_MAX - 1);
|
||||||
if ((*file_list)[index]) {
|
(*file_list)[index][STK_PATH_MAX - 1] = '\0';
|
||||||
strcpy((*file_list)[index],
|
|
||||||
ctx->snapshots[i].filename);
|
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < new_count && index < change_count; i++) {
|
for (i = 0; i < new_count && index < change_count; i++) {
|
||||||
old_snap = find_in_snapshot(ctx->snapshots, ctx->snapshot_count,
|
old_snap = find_in_snapshot(ctx->snapshots, ctx->snapshot_count,
|
||||||
new_snapshots[i].filename);
|
new_snapshots[i].filename);
|
||||||
if (!old_snap || old_snap->mtime != new_snapshots[i].mtime) {
|
if (!old_snap || old_snap->mtime != new_snapshots[i].mtime) {
|
||||||
events[index] = STK_MOD_LOAD;
|
events[index] =
|
||||||
(*file_list)[index] =
|
is_module_loaded(new_snapshots[i].filename,
|
||||||
malloc(strlen(new_snapshots[i].filename) + 1);
|
loaded_module_ids, loaded_count)
|
||||||
if ((*file_list)[index]) {
|
? STK_MOD_RELOAD
|
||||||
strcpy((*file_list)[index],
|
: STK_MOD_LOAD;
|
||||||
new_snapshots[i].filename);
|
strncpy((*file_list)[index], new_snapshots[i].filename,
|
||||||
|
STK_PATH_MAX - 1);
|
||||||
|
(*file_list)[index][STK_PATH_MAX - 1] = '\0';
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
free_snapshot(ctx->snapshots, ctx->snapshot_count);
|
free(ctx->snapshots);
|
||||||
ctx->snapshots = new_snapshots;
|
ctx->snapshots = new_snapshots;
|
||||||
ctx->snapshot_count = new_count;
|
ctx->snapshot_count = new_count;
|
||||||
|
ctx->snapshot_capacity = new_capacity;
|
||||||
#endif
|
#endif
|
||||||
*out_count = index;
|
*out_count = index;
|
||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
char **platform_directory_init_scan(const char *path, size_t *out_count)
|
char (*platform_directory_init_scan(const char *mod_dir,
|
||||||
|
size_t *out_count))[STK_PATH_MAX]
|
||||||
{
|
{
|
||||||
|
char(*file_list)[STK_PATH_MAX] = NULL;
|
||||||
|
char work_path[STK_PATH_MAX_OS];
|
||||||
|
size_t count = 0, index = 0;
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
WIN32_FIND_DATAW find_data;
|
WIN32_FIND_DATAW find_data;
|
||||||
HANDLE find_handle;
|
HANDLE find_handle;
|
||||||
WCHAR search_path[PATH_BUFFER_SIZE];
|
WCHAR search_path[STK_PATH_MAX_OS];
|
||||||
char **file_list = NULL;
|
char temp_filename[STK_PATH_MAX];
|
||||||
size_t count = 0, index = 0;
|
int len;
|
||||||
int utf8_len;
|
|
||||||
|
|
||||||
swprintf(search_path, PATH_BUFFER_SIZE, L"%S\\*", path);
|
|
||||||
|
|
||||||
|
swprintf(search_path, STK_PATH_MAX_OS, L"%S\\*", mod_dir);
|
||||||
find_handle = FindFirstFileW(search_path, &find_data);
|
find_handle = FindFirstFileW(search_path, &find_data);
|
||||||
|
|
||||||
if (find_handle == INVALID_HANDLE_VALUE) {
|
if (find_handle == INVALID_HANDLE_VALUE) {
|
||||||
CreateDirectoryA(path, NULL);
|
CreateDirectoryA(mod_dir, NULL);
|
||||||
*out_count = 0;
|
*out_count = 0;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (!(find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
count++;
|
continue;
|
||||||
} while (FindNextFileW(find_handle, &find_data));
|
|
||||||
|
|
||||||
|
len = WideCharToMultiByte(CP_UTF8, 0, find_data.cFileName, -1,
|
||||||
|
temp_filename, STK_PATH_MAX - 1, NULL,
|
||||||
|
NULL);
|
||||||
|
if (len > 0) {
|
||||||
|
temp_filename[len] = '\0';
|
||||||
|
if (is_valid_module_file(temp_filename))
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
} while (FindNextFileW(find_handle, &find_data));
|
||||||
FindClose(find_handle);
|
FindClose(find_handle);
|
||||||
|
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
@@ -548,41 +553,73 @@ char **platform_directory_init_scan(const char *path, size_t *out_count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
find_handle = FindFirstFileW(search_path, &find_data);
|
find_handle = FindFirstFileW(search_path, &find_data);
|
||||||
if (find_handle == INVALID_HANDLE_VALUE) {
|
file_list = malloc(count * sizeof(*file_list));
|
||||||
*out_count = 0;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
file_list = (char **)malloc(count * sizeof(char *));
|
|
||||||
if (!file_list) {
|
|
||||||
FindClose(find_handle);
|
|
||||||
*out_count = 0;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (!(find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
|
if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
index < count) {
|
continue;
|
||||||
utf8_len =
|
|
||||||
WideCharToMultiByte(CP_UTF8, 0, find_data.cFileName,
|
len = WideCharToMultiByte(CP_UTF8, 0, find_data.cFileName, -1,
|
||||||
-1, NULL, 0, NULL, NULL);
|
file_list[index], STK_PATH_MAX - 1,
|
||||||
if (utf8_len > 0) {
|
NULL, NULL);
|
||||||
file_list[index] = (char *)malloc(utf8_len);
|
if (len > 0 && index < count) {
|
||||||
if (file_list[index]) {
|
file_list[index][len] = '\0';
|
||||||
WideCharToMultiByte(
|
if (is_valid_module_file(file_list[index]))
|
||||||
CP_UTF8, 0, find_data.cFileName, -1,
|
|
||||||
file_list[index], utf8_len, NULL,
|
|
||||||
NULL);
|
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (FindNextFileW(find_handle, &find_data) && index < count);
|
} while (FindNextFileW(find_handle, &find_data) && index < count);
|
||||||
|
|
||||||
FindClose(find_handle);
|
FindClose(find_handle);
|
||||||
|
#else
|
||||||
|
DIR *dir;
|
||||||
|
struct dirent *entry;
|
||||||
|
struct stat file_stat;
|
||||||
|
|
||||||
|
dir = opendir(mod_dir);
|
||||||
|
if (!dir) {
|
||||||
|
mkdir(mod_dir, 0755);
|
||||||
|
*out_count = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((entry = readdir(dir)) != NULL) {
|
||||||
|
if (!is_valid_module_file(entry->d_name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sprintf(work_path, "%s/%s", mod_dir, entry->d_name);
|
||||||
|
if (stat(work_path, &file_stat) == 0 &&
|
||||||
|
S_ISREG(file_stat.st_mode))
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == 0) {
|
||||||
|
closedir(dir);
|
||||||
|
*out_count = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rewinddir(dir);
|
||||||
|
file_list = malloc(count * sizeof(*file_list));
|
||||||
|
if (!file_list) {
|
||||||
|
closedir(dir);
|
||||||
|
*out_count = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((entry = readdir(dir)) != NULL && index < count) {
|
||||||
|
if (!is_valid_module_file(entry->d_name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sprintf(work_path, "%s/%s", mod_dir, entry->d_name);
|
||||||
|
if (stat(work_path, &file_stat) != 0 ||
|
||||||
|
!S_ISREG(file_stat.st_mode))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
strncpy(file_list[index], entry->d_name, STK_PATH_MAX - 1);
|
||||||
|
file_list[index][STK_PATH_MAX - 1] = '\0';
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
#endif
|
||||||
*out_count = index;
|
*out_count = index;
|
||||||
return file_list;
|
return file_list;
|
||||||
#else
|
|
||||||
return scan_directory(path, out_count);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,35 +1,45 @@
|
|||||||
#include "stk.h"
|
#include "stk.h"
|
||||||
#include "stk_log.h"
|
#include "stk_log.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
extern char **stk_module_ids;
|
typedef void (*stk_module_func)(void);
|
||||||
|
|
||||||
|
extern void **stk_handles;
|
||||||
|
extern stk_module_func *stk_inits;
|
||||||
|
extern stk_module_func *stk_shutdowns;
|
||||||
|
extern char (*stk_module_ids)[STK_MOD_ID_BUFFER];
|
||||||
|
|
||||||
extern size_t module_count;
|
extern size_t module_count;
|
||||||
|
|
||||||
static char stk_mod_dir[MOD_DIR_BUFFER_SIZE];
|
static char stk_mod_dir[STK_MOD_DIR_BUFFER];
|
||||||
static void *watch_handle = NULL;
|
static void *watch_handle = NULL;
|
||||||
|
|
||||||
char **platform_directory_init_scan(const char *path, size_t *out_count);
|
char *extract_module_id(const char *path);
|
||||||
|
char (*platform_directory_init_scan(const char *path,
|
||||||
|
size_t *out_count))[STK_PATH_MAX];
|
||||||
void *platform_directory_watch_start(const char *path);
|
void *platform_directory_watch_start(const char *path);
|
||||||
void platform_directory_watch_stop(void *handle);
|
void platform_directory_watch_stop(void *handle);
|
||||||
size_t stk_module_count(void);
|
size_t stk_module_count(void);
|
||||||
int stk_module_load(const char *path);
|
int stk_module_load(const char *path, int index);
|
||||||
|
int stk_module_load_init(const char *path, int index);
|
||||||
void stk_module_unload(size_t index);
|
void stk_module_unload(size_t index);
|
||||||
void stk_module_unload_all(void);
|
void stk_module_unload_all(void);
|
||||||
int stk_module_init_memory(size_t capacity);
|
int stk_module_init_memory(size_t capacity);
|
||||||
stk_module_event_t *platform_directory_watch_check(void *handle,
|
stk_module_event_t *platform_directory_watch_check(
|
||||||
char ***file_list,
|
void *handle, char (**file_list)[STK_PATH_MAX], size_t *out_count,
|
||||||
size_t *out_count);
|
char (*loaded_module_ids)[STK_MOD_ID_BUFFER], const size_t loaded_count);
|
||||||
|
|
||||||
int stk_init(const char *mod_dir)
|
int stk_init(const char *mod_dir)
|
||||||
{
|
{
|
||||||
char **files;
|
char(*files)[STK_PATH_MAX] = NULL;
|
||||||
size_t file_count, i;
|
size_t file_count, i;
|
||||||
char full_path[PATH_BUFFER_SIZE];
|
char full_path[STK_PATH_MAX_OS];
|
||||||
|
|
||||||
if (mod_dir) {
|
if (mod_dir) {
|
||||||
strncpy(stk_mod_dir, mod_dir, MOD_DIR_BUFFER_SIZE - 1);
|
strncpy(stk_mod_dir, mod_dir, STK_MOD_DIR_BUFFER - 1);
|
||||||
stk_mod_dir[MOD_DIR_BUFFER_SIZE - 1] = '\0';
|
stk_mod_dir[STK_MOD_DIR_BUFFER - 1] = '\0';
|
||||||
} else {
|
} else {
|
||||||
strcpy(stk_mod_dir, "mods");
|
strcpy(stk_mod_dir, "mods");
|
||||||
}
|
}
|
||||||
@@ -44,8 +54,7 @@ int stk_init(const char *mod_dir)
|
|||||||
|
|
||||||
for (i = 0; i < file_count; ++i) {
|
for (i = 0; i < file_count; ++i) {
|
||||||
sprintf(full_path, "%s/%s", stk_mod_dir, files[i]);
|
sprintf(full_path, "%s/%s", stk_mod_dir, files[i]);
|
||||||
stk_module_load(full_path);
|
stk_module_load_init(full_path, i);
|
||||||
free(files[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free(files);
|
free(files);
|
||||||
@@ -72,34 +81,20 @@ void stk_shutdown(void)
|
|||||||
|
|
||||||
size_t stk_poll(void)
|
size_t stk_poll(void)
|
||||||
{
|
{
|
||||||
char **file_list = NULL;
|
char(*file_list)[STK_PATH_MAX] = NULL;
|
||||||
stk_module_event_t *events = NULL;
|
stk_module_event_t *events = NULL;
|
||||||
size_t file_count;
|
size_t file_count, i;
|
||||||
size_t i;
|
|
||||||
|
|
||||||
events = platform_directory_watch_check(watch_handle, &file_list,
|
events = platform_directory_watch_check(watch_handle, &file_list,
|
||||||
&file_count);
|
&file_count, stk_module_ids,
|
||||||
|
module_count);
|
||||||
if (!events)
|
if (!events)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (i = 0; i < file_count; ++i) {
|
for (i = 0; i < file_count; ++i) {
|
||||||
char full_path[PATH_BUFFER_SIZE];
|
|
||||||
char *module_id;
|
|
||||||
int existing_index = -1;
|
|
||||||
size_t j = 0;
|
|
||||||
|
|
||||||
module_id = file_list[i];
|
|
||||||
sprintf(full_path, "%s/%s", stk_mod_dir, module_id);
|
|
||||||
|
|
||||||
for (j = 0; j < module_count; ++j) {
|
|
||||||
if (strcmp(module_id, stk_module_ids[j]) != 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
existing_index = j;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (events[i]) {
|
switch (events[i]) {
|
||||||
|
case STK_MOD_RELOAD:
|
||||||
|
break;
|
||||||
case STK_MOD_LOAD:
|
case STK_MOD_LOAD:
|
||||||
break;
|
break;
|
||||||
case STK_MOD_UNLOAD:
|
case STK_MOD_UNLOAD:
|
||||||
@@ -107,11 +102,8 @@ size_t stk_poll(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < file_count; i++)
|
|
||||||
free(file_list[i]);
|
|
||||||
|
|
||||||
free(file_list);
|
|
||||||
free(events);
|
free(events);
|
||||||
|
free(file_list);
|
||||||
|
|
||||||
return file_count;
|
return file_count;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user