[io] check that file path doesn't escape app's local data folder when opening files
This commit is contained in:
parent
e82225116b
commit
bfc81fd062
|
@ -12,4 +12,4 @@ wasmFlags="--target=wasm32 \
|
||||||
|
|
||||||
/usr/local/opt/llvm/bin/clang $wasmFlags -o ./module.wasm ../../sdk/orca.c src/main.c
|
/usr/local/opt/llvm/bin/clang $wasmFlags -o ./module.wasm ../../sdk/orca.c src/main.c
|
||||||
|
|
||||||
python3 ../../scripts/mkapp.py --orca-dir ../.. --name Pong --icon icon.png module.wasm
|
python3 ../../scripts/mkapp.py --orca-dir ../.. --name Pong --icon icon.png --data-dir dir1 module.wasm
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Hello, ressource file
|
|
@ -41,13 +41,13 @@ void OnInit(void)
|
||||||
surface = mg_surface_main();
|
surface = mg_surface_main();
|
||||||
canvas = mg_canvas_create();
|
canvas = mg_canvas_create();
|
||||||
|
|
||||||
file_handle file = file_open(STR8("test_file.txt") , IO_OPEN_CREATE | IO_OPEN_WRITE);
|
file_handle file = file_open(STR8("/test_write.txt") , IO_OPEN_CREATE | IO_OPEN_WRITE);
|
||||||
|
|
||||||
str8 string = STR8("Hello, file!\n");
|
str8 string = STR8("Hello, file!\n");
|
||||||
file_write(file, string.len, string.ptr);
|
file_write(file, string.len, string.ptr);
|
||||||
file_close(file);
|
file_close(file);
|
||||||
|
|
||||||
file = file_open(STR8("test_file.txt") , IO_OPEN_READ);
|
file = file_open(STR8("/dir1/test_read.txt") , IO_OPEN_READ);
|
||||||
u64 size = file_size(file);
|
u64 size = file_size(file);
|
||||||
char* buffer = mem_arena_alloc(mem_scratch(), size);
|
char* buffer = mem_arena_alloc(mem_scratch(), size);
|
||||||
file_read(file, size, buffer);
|
file_read(file, size, buffer);
|
||||||
|
|
|
@ -18,10 +18,10 @@ from argparse import ArgumentParser
|
||||||
#----------------------------------------------------------------------------------------------
|
#----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
parser = ArgumentParser(prog='mkapp')
|
parser = ArgumentParser(prog='mkapp')
|
||||||
parser.add_argument("-r", "--res-file", nargs='+', action='append', dest='res_files')
|
parser.add_argument("-d", "--data-file", action='append', dest='data_files')
|
||||||
parser.add_argument("-R", "--res-dir", nargs='+', action='append', dest='res_dirs')
|
parser.add_argument("-D", "--data-dir", action='append', dest='data_dirs')
|
||||||
parser.add_argument("-i", "--icon")
|
parser.add_argument("-i", "--icon")
|
||||||
parser.add_argument("-D", "--out-dir", default=os.getcwd())
|
parser.add_argument("-C", "--out-dir", default=os.getcwd())
|
||||||
parser.add_argument("-n", "--name", default='out')
|
parser.add_argument("-n", "--name", default='out')
|
||||||
parser.add_argument("-O", "--orca-dir", default='.')
|
parser.add_argument("-O", "--orca-dir", default='.')
|
||||||
parser.add_argument("--version", default='0.0.0')
|
parser.add_argument("--version", default='0.0.0')
|
||||||
|
@ -38,8 +38,9 @@ bundle_path = args.out_dir + '/' + bundle_name
|
||||||
contents_dir = bundle_path + '/Contents'
|
contents_dir = bundle_path + '/Contents'
|
||||||
exe_dir = contents_dir + '/MacOS'
|
exe_dir = contents_dir + '/MacOS'
|
||||||
res_dir = contents_dir + '/resources'
|
res_dir = contents_dir + '/resources'
|
||||||
wasm_dir = contents_dir + '/wasm'
|
guest_dir = contents_dir + '/app'
|
||||||
data_dir = contents_dir + '/data'
|
wasm_dir = guest_dir + '/wasm'
|
||||||
|
data_dir = guest_dir + '/data'
|
||||||
|
|
||||||
if os.path.exists(bundle_path):
|
if os.path.exists(bundle_path):
|
||||||
shutil.rmtree(bundle_path)
|
shutil.rmtree(bundle_path)
|
||||||
|
@ -47,6 +48,7 @@ os.mkdir(bundle_path)
|
||||||
os.mkdir(contents_dir)
|
os.mkdir(contents_dir)
|
||||||
os.mkdir(exe_dir)
|
os.mkdir(exe_dir)
|
||||||
os.mkdir(res_dir)
|
os.mkdir(res_dir)
|
||||||
|
os.mkdir(guest_dir)
|
||||||
os.mkdir(wasm_dir)
|
os.mkdir(wasm_dir)
|
||||||
os.mkdir(data_dir)
|
os.mkdir(data_dir)
|
||||||
|
|
||||||
|
@ -66,23 +68,27 @@ shutil.copy(egl_lib, exe_dir)
|
||||||
shutil.copy(renderer_lib, exe_dir)
|
shutil.copy(renderer_lib, exe_dir)
|
||||||
|
|
||||||
#-----------------------------------------------------------
|
#-----------------------------------------------------------
|
||||||
#NOTE: copy wasm module and resources
|
#NOTE: copy wasm module and data
|
||||||
#-----------------------------------------------------------
|
#-----------------------------------------------------------
|
||||||
shutil.copy(args.module, wasm_dir + '/module.wasm')
|
shutil.copy(args.module, wasm_dir + '/module.wasm')
|
||||||
|
|
||||||
if args.res_files != None:
|
if args.data_files != None:
|
||||||
for res in args.res_files:
|
for data in args.data_files:
|
||||||
shutil.copy(res, res_dir)
|
shutil.copy(data, data_dir)
|
||||||
|
|
||||||
if args.res_dirs != None:
|
if args.data_dirs != None:
|
||||||
for res in args.res_dirs:
|
for data in args.data_dirs:
|
||||||
shutil.copytree(res, res_dir)
|
shutil.copytree(data, data_dir + '/' + os.path.basename(data), dirs_exist_ok=True)
|
||||||
|
|
||||||
|
#-----------------------------------------------------------
|
||||||
|
#NOTE: copy runtime resources
|
||||||
|
#-----------------------------------------------------------
|
||||||
# default fonts
|
# default fonts
|
||||||
shutil.copy(args.orca_dir + '/resources/OpenSansLatinSubset.ttf', res_dir)
|
shutil.copy(args.orca_dir + '/resources/OpenSansLatinSubset.ttf', res_dir)
|
||||||
shutil.copy(args.orca_dir + '/resources/Menlo.ttf', res_dir)
|
shutil.copy(args.orca_dir + '/resources/Menlo.ttf', res_dir)
|
||||||
shutil.copy(args.orca_dir + '/resources/Menlo Bold.ttf', res_dir)
|
shutil.copy(args.orca_dir + '/resources/Menlo Bold.ttf', res_dir)
|
||||||
shutil.copy(args.orca_dir + '/resources/Menlo Italics.ttf', res_dir)
|
shutil.copy(args.orca_dir + '/resources/Menlo Italics.ttf', res_dir)
|
||||||
|
|
||||||
#-----------------------------------------------------------
|
#-----------------------------------------------------------
|
||||||
#NOTE make icon
|
#NOTE make icon
|
||||||
#-----------------------------------------------------------
|
#-----------------------------------------------------------
|
||||||
|
|
|
@ -76,14 +76,21 @@ enum {
|
||||||
IO_ERR_ARG, // invalid argument or argument combination
|
IO_ERR_ARG, // invalid argument or argument combination
|
||||||
IO_ERR_PERM, // access denied
|
IO_ERR_PERM, // access denied
|
||||||
IO_ERR_SPACE, // no space left
|
IO_ERR_SPACE, // no space left
|
||||||
IO_ERR_NO_FILE, // file does not exist
|
IO_ERR_NO_ENTRY, // file or directory does not exist
|
||||||
IO_ERR_EXISTS, // file already exists
|
IO_ERR_EXISTS, // file already exists
|
||||||
|
IO_ERR_NOT_DIR, // path element is not a directory
|
||||||
|
IO_ERR_DIR, // attempted to write directory
|
||||||
IO_ERR_MAX_FILES, // max open files reached
|
IO_ERR_MAX_FILES, // max open files reached
|
||||||
|
IO_ERR_MAX_LINKS, // too many symbolic links in path
|
||||||
IO_ERR_PATH_LENGTH, // path too long
|
IO_ERR_PATH_LENGTH, // path too long
|
||||||
IO_ERR_FILE_SIZE, // file too big
|
IO_ERR_FILE_SIZE, // file too big
|
||||||
IO_ERR_OVERFLOW, // offset too big
|
IO_ERR_OVERFLOW, // offset too big
|
||||||
IO_ERR_NOT_READY, // no data ready to be read/written
|
IO_ERR_NOT_READY, // no data ready to be read/written
|
||||||
IO_ERR_MEM, // failed to allocate memory
|
IO_ERR_MEM, // failed to allocate memory
|
||||||
|
IO_ERR_INTERRUPT, // operation interrupted by a signal
|
||||||
|
IO_ERR_PHYSICAL, // physical IO error
|
||||||
|
IO_ERR_NO_DEVICE, // device not found
|
||||||
|
IO_ERR_WALKOUT, // attempted to walk out of root directory
|
||||||
|
|
||||||
//...
|
//...
|
||||||
};
|
};
|
||||||
|
|
360
src/io_impl.c
360
src/io_impl.c
|
@ -9,6 +9,7 @@
|
||||||
#include<fcntl.h>
|
#include<fcntl.h>
|
||||||
#include<sys/stat.h>
|
#include<sys/stat.h>
|
||||||
#include<unistd.h>
|
#include<unistd.h>
|
||||||
|
#include<limits.h>
|
||||||
#include"io_common.h"
|
#include"io_common.h"
|
||||||
|
|
||||||
//TODO: - file_handle to FILE* association
|
//TODO: - file_handle to FILE* association
|
||||||
|
@ -84,6 +85,278 @@ file_slot* file_slot_from_handle(file_table* table, file_handle handle)
|
||||||
return(slot);
|
return(slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
io_error io_convert_errno(int e)
|
||||||
|
{
|
||||||
|
io_error error;
|
||||||
|
switch(e)
|
||||||
|
{
|
||||||
|
case EPERM:
|
||||||
|
case EACCES:
|
||||||
|
case EROFS:
|
||||||
|
error = IO_ERR_PERM;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ENOENT:
|
||||||
|
error = IO_ERR_NO_ENTRY;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EINTR:
|
||||||
|
error = IO_ERR_INTERRUPT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EIO:
|
||||||
|
error = IO_ERR_PHYSICAL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ENXIO:
|
||||||
|
error = IO_ERR_NO_DEVICE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EBADF:
|
||||||
|
// this should only happen when user tries to write/read to a file handle
|
||||||
|
// opened with readonly/writeonly access
|
||||||
|
error = IO_ERR_PERM;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ENOMEM:
|
||||||
|
error = IO_ERR_MEM;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EFAULT:
|
||||||
|
case EINVAL:
|
||||||
|
case EDOM:
|
||||||
|
error = IO_ERR_ARG;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EBUSY:
|
||||||
|
case EAGAIN:
|
||||||
|
error = IO_ERR_NOT_READY;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EEXIST:
|
||||||
|
error = IO_ERR_EXISTS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ENOTDIR:
|
||||||
|
error = IO_ERR_NOT_DIR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EISDIR:
|
||||||
|
error = IO_ERR_DIR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ENFILE:
|
||||||
|
case EMFILE:
|
||||||
|
error = IO_ERR_MAX_FILES;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EFBIG:
|
||||||
|
error = IO_ERR_FILE_SIZE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ENOSPC:
|
||||||
|
case EDQUOT:
|
||||||
|
error = IO_ERR_SPACE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ELOOP:
|
||||||
|
error = IO_ERR_MAX_LINKS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ENAMETOOLONG:
|
||||||
|
error = IO_ERR_PATH_LENGTH;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EOVERFLOW:
|
||||||
|
error = IO_ERR_OVERFLOW;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
error = IO_ERR_UNKNOWN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct io_path_walk_result
|
||||||
|
{
|
||||||
|
io_error error;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
} io_path_walk_result;
|
||||||
|
|
||||||
|
io_path_walk_result io_path_walk(str8 path)
|
||||||
|
{
|
||||||
|
io_path_walk_result result = {.fd = -1};
|
||||||
|
|
||||||
|
mem_arena* scratch = mem_scratch();
|
||||||
|
mem_arena_marker mark = mem_arena_mark(scratch);
|
||||||
|
|
||||||
|
str8_list sep = {0};
|
||||||
|
str8_list_push(scratch, &sep, STR8("/"));
|
||||||
|
str8_list pathElements = str8_split(scratch, path, sep);
|
||||||
|
|
||||||
|
str8 execPath = mp_path_directory(mp_app_get_executable_path(scratch));
|
||||||
|
str8_list list = {0};
|
||||||
|
str8_list_push(scratch, &list, execPath);
|
||||||
|
str8_list_push(scratch, &list, STR8("../app/data"));
|
||||||
|
str8 dataPath = str8_list_join(scratch, list);
|
||||||
|
|
||||||
|
result.fd = open(str8_to_cstring(scratch, dataPath), O_RDONLY);
|
||||||
|
if(result.fd < 0)
|
||||||
|
{
|
||||||
|
result.error = io_convert_errno(errno);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
struct stat dirStat;
|
||||||
|
if(fstat(result.fd, &dirStat))
|
||||||
|
{
|
||||||
|
result.error = io_convert_errno(errno);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
ino_t baseInode = dirStat.st_ino;
|
||||||
|
ino_t currentInode = baseInode;
|
||||||
|
|
||||||
|
for_list(&pathElements.list, elt, str8_elt, listElt)
|
||||||
|
{
|
||||||
|
str8 name = elt->string;
|
||||||
|
|
||||||
|
if(!str8_cmp(name, STR8(".")))
|
||||||
|
{
|
||||||
|
//NOTE: skip
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if(!str8_cmp(name, STR8("..")))
|
||||||
|
{
|
||||||
|
//NOTE: check that we don't escape 'root' dir
|
||||||
|
if(currentInode == baseInode)
|
||||||
|
{
|
||||||
|
result.error = IO_ERR_WALKOUT;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// open that dir and continue
|
||||||
|
int nextFd = openat(result.fd, "..", O_RDONLY);
|
||||||
|
if(!nextFd)
|
||||||
|
{
|
||||||
|
result.error = io_convert_errno(errno);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
close(result.fd);
|
||||||
|
result.fd = nextFd;
|
||||||
|
if(fstat(result.fd, &dirStat))
|
||||||
|
{
|
||||||
|
result.error = io_convert_errno(errno);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
currentInode = dirStat.st_ino;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char* nameCStr = str8_to_cstring(scratch, name);
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
if(fstatat(result.fd, nameCStr, &st, AT_SYMLINK_NOFOLLOW))
|
||||||
|
{
|
||||||
|
if(&elt->listElt != list_last(&pathElements.list))
|
||||||
|
{
|
||||||
|
result.error = io_convert_errno(errno);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int type = st.st_mode & S_IFMT;
|
||||||
|
|
||||||
|
if(type == S_IFLNK)
|
||||||
|
{
|
||||||
|
// symlink, check that it's relative, and insert it in elements
|
||||||
|
char buff[PATH_MAX+1];
|
||||||
|
int r = readlinkat(result.fd, nameCStr, buff, PATH_MAX);
|
||||||
|
if(r<0)
|
||||||
|
{
|
||||||
|
result.error = io_convert_errno(errno);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
else if(r == 0)
|
||||||
|
{
|
||||||
|
//NOTE: skip
|
||||||
|
}
|
||||||
|
else if(buff[0] == '/')
|
||||||
|
{
|
||||||
|
result.error = IO_ERR_WALKOUT;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buff[r] = '\0';
|
||||||
|
|
||||||
|
str8_list linkElements = str8_split(scratch, str8_from_buffer(r, buff), sep);
|
||||||
|
if(!list_empty(&linkElements.list))
|
||||||
|
{
|
||||||
|
//NOTE: insert linkElements into pathElements after elt
|
||||||
|
list_elt* tmp = elt->listElt.next;
|
||||||
|
elt->listElt.next = linkElements.list.first;
|
||||||
|
linkElements.list.last->next = tmp;
|
||||||
|
if(!tmp)
|
||||||
|
{
|
||||||
|
pathElements.list.last = linkElements.list.last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(type == S_IFDIR)
|
||||||
|
{
|
||||||
|
// dir, open it and continue
|
||||||
|
int nextFd = openat(result.fd, nameCStr, O_RDONLY);
|
||||||
|
if(!nextFd)
|
||||||
|
{
|
||||||
|
result.error = io_convert_errno(errno);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
close(result.fd);
|
||||||
|
result.fd = nextFd;
|
||||||
|
currentInode = st.st_ino;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(type == S_IFREG)
|
||||||
|
{
|
||||||
|
// regular file, check that we're at the last element
|
||||||
|
if(&elt->listElt != list_last(&pathElements.list))
|
||||||
|
{
|
||||||
|
result.error = IO_ERR_NOT_DIR;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.error = IO_ERR_NOT_DIR;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
error:
|
||||||
|
{
|
||||||
|
close(result.fd);
|
||||||
|
result.fd = -1;
|
||||||
|
}
|
||||||
|
end:
|
||||||
|
mem_arena_clear_to(scratch, mark);
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
io_cmp io_open(io_req* req)
|
io_cmp io_open(io_req* req)
|
||||||
{
|
{
|
||||||
io_cmp cmp = {0};
|
io_cmp cmp = {0};
|
||||||
|
@ -129,6 +402,8 @@ io_cmp io_open(io_req* req)
|
||||||
flags |= O_CREAT;
|
flags |= O_CREAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flags |= O_NOFOLLOW;
|
||||||
|
|
||||||
mode_t mode = S_IRUSR
|
mode_t mode = S_IRUSR
|
||||||
| S_IWUSR
|
| S_IWUSR
|
||||||
| S_IRGRP
|
| S_IRGRP
|
||||||
|
@ -136,28 +411,27 @@ io_cmp io_open(io_req* req)
|
||||||
| S_IROTH
|
| S_IROTH
|
||||||
| S_IWOTH;
|
| S_IWOTH;
|
||||||
|
|
||||||
//NOTE: build path
|
//NOTE: walk path (ensuring it's inside app's data directory subtree)
|
||||||
////////////////////////////////////////////////////////////////////////////////////
|
str8 path = str8_from_buffer(req->size, req->buffer);
|
||||||
//TODO: canonicalize directory path & check that it's inside local app folder
|
io_path_walk_result walkRes = io_path_walk(path);
|
||||||
////////////////////////////////////////////////////////////////////////////////////
|
if(walkRes.error != IO_OK)
|
||||||
|
{
|
||||||
|
slot->fd = -1;
|
||||||
|
slot->fatal = true;
|
||||||
|
slot->error = walkRes.error;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//NOTE: open
|
||||||
mem_arena* scratch = mem_scratch();
|
mem_arena* scratch = mem_scratch();
|
||||||
mem_arena_marker mark = mem_arena_mark(scratch);
|
mem_arena_marker mark = mem_arena_mark(scratch);
|
||||||
|
|
||||||
str8_list list = {0};
|
str8 name = mp_path_base_name(path);
|
||||||
|
char* nameCStr = str8_to_cstring(scratch, name);
|
||||||
|
int fd = openat(walkRes.fd, nameCStr, flags, mode);
|
||||||
|
close(walkRes.fd);
|
||||||
|
|
||||||
str8 execPath = mp_app_get_executable_path(scratch);
|
mem_arena_clear_to(scratch, mark);
|
||||||
str8 execDir = mp_path_directory(execPath);
|
|
||||||
|
|
||||||
str8_list_push(scratch, &list, execDir);
|
|
||||||
str8_list_push(scratch, &list, STR8("/../data/"));
|
|
||||||
str8_list_push(scratch, &list, str8_from_buffer(req->size, req->buffer));
|
|
||||||
|
|
||||||
str8 absPath = str8_list_join(scratch, list);
|
|
||||||
char* absCString = str8_to_cstring(scratch, absPath);
|
|
||||||
|
|
||||||
//NOTE: open
|
|
||||||
int fd = open(absCString, flags, mode);
|
|
||||||
|
|
||||||
if(fd >= 0)
|
if(fd >= 0)
|
||||||
{
|
{
|
||||||
|
@ -169,57 +443,13 @@ io_cmp io_open(io_req* req)
|
||||||
{
|
{
|
||||||
slot->fd = -1;
|
slot->fd = -1;
|
||||||
slot->fatal = true;
|
slot->fatal = true;
|
||||||
|
slot->error = io_convert_errno(errno);
|
||||||
switch(errno)
|
|
||||||
{
|
|
||||||
case EACCES:
|
|
||||||
case EROFS:
|
|
||||||
slot->error = IO_ERR_PERM;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EDQUOT:
|
|
||||||
case ENOSPC:
|
|
||||||
slot->error = IO_ERR_SPACE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EEXIST:
|
|
||||||
slot->error = IO_ERR_EXISTS;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EFAULT:
|
|
||||||
case EINVAL:
|
|
||||||
case EISDIR:
|
|
||||||
slot->error = IO_ERR_ARG;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EMFILE:
|
|
||||||
case ENFILE:
|
|
||||||
slot->error = IO_ERR_MAX_FILES;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ENAMETOOLONG:
|
|
||||||
slot->error = IO_ERR_PATH_LENGTH;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ENOENT:
|
|
||||||
case ENOTDIR:
|
|
||||||
slot->error = IO_ERR_NO_FILE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EOVERFLOW:
|
|
||||||
slot->error = IO_ERR_FILE_SIZE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
slot->error = IO_ERR_UNKNOWN;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cmp.error = slot->error;
|
cmp.error = slot->error;
|
||||||
}
|
}
|
||||||
|
|
||||||
mem_arena_clear_to(scratch, mark);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(cmp);
|
return(cmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -363,7 +363,7 @@ void* orca_runloop(void* user)
|
||||||
|
|
||||||
//NOTE: loads wasm module
|
//NOTE: loads wasm module
|
||||||
const char* bundleNameCString = "module";
|
const char* bundleNameCString = "module";
|
||||||
str8 modulePath = mp_app_get_resource_path(mem_scratch(), "../wasm/module.wasm");
|
str8 modulePath = mp_app_get_resource_path(mem_scratch(), "../app/wasm/module.wasm");
|
||||||
const char* modulePathCString = str8_to_cstring(mem_scratch(), modulePath);
|
const char* modulePathCString = str8_to_cstring(mem_scratch(), modulePath);
|
||||||
|
|
||||||
FILE* file = fopen(modulePathCString, "rb");
|
FILE* file = fopen(modulePathCString, "rb");
|
||||||
|
|
Loading…
Reference in New Issue