#include <fcntl.h>
#include <stdbool.h>
#include <string.h>
#include <subsystem.h>
#include <sys/errno.h>
#include <sys/syslimits.h>
#include <_simple.h>
#define SUBSYSTEM_ROOT_PATH_KEY "subsystem_root_path"
void _subsystem_init(const char *apple[]);
static char * subsystem_root_path = NULL;
static size_t subsystem_root_path_len = 0;
void
_subsystem_init(const char **apple)
{
char * subsystem_root_path_string = _simple_getenv(apple, SUBSYSTEM_ROOT_PATH_KEY);
if (subsystem_root_path_string) {
subsystem_root_path = subsystem_root_path_string;
subsystem_root_path_len = strnlen(subsystem_root_path, PATH_MAX);
}
}
static bool
construct_subsystem_path(char * buf, size_t buf_size, const char * subsystem_root_path, const char * file_path)
{
size_t return_a = strlcpy(buf, subsystem_root_path, buf_size);
size_t return_b = strlcat(buf, file_path, buf_size);
if ((return_a >= buf_size) || (return_b >= buf_size)) {
return false;
}
return true;
}
int
open_with_subsystem(const char * path, int oflag)
{
if (oflag & O_CREAT){
errno = EINVAL;
return -1;
}
int result;
result = open(path, oflag);
if ((result < 0) && (errno == ENOENT) && (subsystem_root_path)) {
char subsystem_path[PATH_MAX];
if (construct_subsystem_path(subsystem_path, sizeof(subsystem_path), subsystem_root_path, path)) {
result = open(subsystem_path, oflag);
} else {
errno = ENAMETOOLONG;
}
}
return result;
}
int
stat_with_subsystem(const char *restrict path, struct stat *restrict buf)
{
int result;
result = stat(path, buf);
if ((result < 0) && (errno == ENOENT) && (subsystem_root_path)) {
char subsystem_path[PATH_MAX];
if (construct_subsystem_path(subsystem_path, sizeof(subsystem_path), subsystem_root_path, path)) {
result = stat(subsystem_path, buf);
} else {
errno = ENAMETOOLONG;
}
}
return result;
}