From 94c01870418373c93744b73d29ebc74986cedd5c Mon Sep 17 00:00:00 2001 From: Mitya Selivanov Date: Fri, 15 Sep 2023 22:09:46 +0200 Subject: file mapping --- TODO | 3 +- source/kit/async_function.h | 14 +-- source/kit/file.c | 234 ++++++++++++++++++++++++++++++++++----- source/kit/file.h | 46 ++++++-- source/kit/kit_test.h | 4 +- source/kit/shared_memory.h | 11 +- source/kit/shared_memory.posix.c | 36 +++++- source/kit/shared_memory.win32.c | 23 ++-- source/kit/status.h | 40 +++---- source/tests/file.test.c | 76 +++++++++++-- source/tests/test_interprocess.c | 2 + 11 files changed, 401 insertions(+), 88 deletions(-) diff --git a/TODO b/TODO index 5571249..5bcfa82 100644 --- a/TODO +++ b/TODO @@ -16,9 +16,8 @@ To-Do - Better atomics support - System call, run process - Terminal - - File and memory mapping - Inter-process transfer - - Sockets tests. + - Sockets tests - System boilerplate (graphics, audio, input) - SDL - X11 (Linux) diff --git a/source/kit/async_function.h b/source/kit/async_function.h index 4e725e7..e94fc31 100644 --- a/source/kit/async_function.h +++ b/source/kit/async_function.h @@ -35,16 +35,16 @@ typedef struct { #define KIT_AF_INTERNAL(coro_) (*((kit_af_type_void *) (coro_))) #ifdef KIT_ENABLE_CUSTOM_ASYNC_FUNCTION_DISPATCH -/* Application should implement this function if custom async - * function dispatch is enabled. - * - * See KIT_ENABLE_CUSTOM_ASYNC_FUNCTION_DISPATCH macro. - */ +// Application should implement this function if custom async +// function dispatch is enabled. +// +// See KIT_ENABLE_CUSTOM_ASYNC_FUNCTION_DISPATCH macro. +// void kit_async_function_dispatch(void *promise); #else static void kit_async_function_dispatch(void *promise) { - /* Dynamic dispatch by default. - */ + // Dynamic dispatch by default. + // KIT_AF_INTERNAL(promise)._state_machine(promise); } #endif diff --git a/source/kit/file.c b/source/kit/file.c index c82ef35..7b80e67 100644 --- a/source/kit/file.c +++ b/source/kit/file.c @@ -7,19 +7,21 @@ enum { PATH_BUF_SIZE = 4096 }; #if defined(_WIN32) && !defined(__CYGWIN__) -# include - # ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN 1 +# define WIN32_LEAN_AND_MEAN # endif - -# include - -# include +# ifndef NOMINMAX +# define NOMINMAX +# endif +# include +# include #else # include +# include # include +# include # include +# include #endif #ifdef __APPLE__ @@ -227,7 +229,7 @@ kit_str_t kit_path_take(kit_str_t path, i64 count) { } #if defined(_WIN32) && !defined(__CYGWIN__) -static void win32_prepare_path_(WCHAR *buf, kit_str_t path) { +static void kit_win32_prepare_path_(WCHAR *buf, kit_str_t path) { assert(path.size == 0 || path.values != NULL); assert(path.size + 5 < PATH_BUF_SIZE); @@ -246,9 +248,9 @@ static void win32_prepare_path_(WCHAR *buf, kit_str_t path) { } # define PREPARE_PATH_BUF_ \ WCHAR buf[PATH_BUF_SIZE]; \ - win32_prepare_path_(buf, path) + kit_win32_prepare_path_(buf, path) #else -static void unix_prepare_path_(char *buf, kit_str_t path) { +static void kit_unix_prepare_path_(char *buf, kit_str_t path) { assert(path.size == 0 || path.values != NULL); assert(path.size + 1 < PATH_BUF_SIZE); @@ -258,20 +260,20 @@ static void unix_prepare_path_(char *buf, kit_str_t path) { } # define PREPARE_PATH_BUF_ \ char buf[PATH_BUF_SIZE]; \ - unix_prepare_path_(buf, path) + kit_unix_prepare_path_(buf, path) #endif -kit_status_t kit_file_create_folder(kit_str_t path) { +kit_status_t kit_folder_create(kit_str_t path) { PREPARE_PATH_BUF_; #if defined(_WIN32) && !defined(__CYGWIN__) return CreateDirectoryW(buf, NULL) ? KIT_OK : KIT_ERROR_MKDIR_FAILED; #else - return mkdir(buf, 0755) == 0 ? KIT_OK : KIT_ERROR_MKDIR_FAILED; + return mkdir(buf, 0775) == 0 ? KIT_OK : KIT_ERROR_MKDIR_FAILED; #endif } -kit_status_t kit_file_create_folder_recursive(kit_str_t path) { +kit_status_t kit_folder_create_recursive(kit_str_t path) { i64 i; for (i = 0;; i++) { @@ -280,7 +282,7 @@ kit_status_t kit_file_create_folder_recursive(kit_str_t path) { if (type == KIT_PATH_FILE) return KIT_ERROR_FILE_ALREADY_EXISTS; if (type == KIT_PATH_NONE) { - kit_status_t s = kit_file_create_folder(part); + kit_status_t s = kit_folder_create(part); if (s != KIT_OK) return s; } @@ -300,7 +302,7 @@ kit_status_t kit_file_remove(kit_str_t path) { #endif } -kit_status_t kit_file_remove_folder(kit_str_t path) { +kit_status_t kit_folder_remove(kit_str_t path) { PREPARE_PATH_BUF_; #if defined(_WIN32) && !defined(__CYGWIN__) return RemoveDirectoryW(buf) ? KIT_OK : KIT_ERROR_RMDIR_FAILED; @@ -315,27 +317,41 @@ kit_status_t kit_file_remove_recursive(kit_str_t path, i64 i; switch (type) { - case KIT_PATH_FILE: return kit_file_remove(path); + case KIT_PATH_FILE: { + kit_status_t s = kit_file_remove(path); + assert(s == KIT_OK); + return s; + } case KIT_PATH_FOLDER: { - kit_path_list_t list = kit_file_enum_folder(path, alloc); + kit_path_list_t list = kit_folder_enum(path, alloc); + + assert(list.status == KIT_OK); if (list.status != KIT_OK) { kit_path_list_destroy(list); return list.status; } + for (i = 0; i < list.files.size; i++) { - str_t s = { .size = list.files.values[i].size, - .values = list.files.values[i].values }; - kit_file_remove_recursive(s, alloc); + str_builder_t full_path = kit_path_join( + path, WRAP_STR(list.files.values[i]), alloc); + kit_status_t s = kit_file_remove_recursive( + WRAP_STR(full_path), alloc); + DA_DESTROY(full_path); + assert(s == KIT_OK); } + kit_path_list_destroy(list); - return kit_file_remove_folder(path); + + kit_status_t s = kit_folder_remove(path); + assert(s == KIT_OK); + return s; } default:; } - return KIT_ERROR_FILE_DO_NOT_EXIST; + return KIT_ERROR_FILE_DOES_NOT_EXIST; } kit_path_type_t kit_path_type(kit_str_t path) { @@ -393,8 +409,8 @@ kit_file_info_t kit_file_info(kit_str_t path) { if (stat(buf, &info) == 0 && S_ISREG(info.st_mode)) { result.size = (i64) info.st_size; # ifndef st_mtime - /* No support for nanosecond timestamps. - */ + // No support for nanosecond timestamps. + // result.time_modified_sec = (i64) info.st_mtime; # else result.time_modified_sec = (i64) info.st_mtim.tv_sec; @@ -405,12 +421,12 @@ kit_file_info_t kit_file_info(kit_str_t path) { } #endif - result.status = KIT_ERROR_FILE_DO_NOT_EXIST; + result.status = KIT_ERROR_FILE_DOES_NOT_EXIST; return result; } -kit_path_list_t kit_file_enum_folder(kit_str_t path, - kit_allocator_t *alloc) { +kit_path_list_t kit_folder_enum(kit_str_t path, + kit_allocator_t *alloc) { PREPARE_PATH_BUF_; kit_path_list_t result = { .status = KIT_OK }; @@ -499,3 +515,165 @@ void kit_path_list_destroy(kit_path_list_t list) { DA_DESTROY(list.files.values[i]); DA_DESTROY(list.files); } + +kit_mapped_file_t kit_file_map(kit_str_t path, i64 size, i32 mode) { + assert(size > 0); + assert(path.size > 0); + assert(path.size <= PATH_MAX); + assert(path.values != NULL); + + kit_mapped_file_t mf; + memset(&mf, 0, sizeof mf); + + if (size <= 0) { + mf.status = KIT_ERROR_INVALID_SIZE; + return mf; + } + + if (path.size <= 0) { + mf.status = KIT_ERROR_INVALID_ARGUMENT; + return mf; + } + + if (path.size > PATH_MAX) { + mf.status = KIT_ERROR_PATH_TOO_LONG; + return mf; + } + +#if defined(_WIN32) && !defined(__CYGWIN__) + char buf[MAX_PATH + 1]; + memcpy(buf, path.values, path.size); + buf[path.size] = '\0'; + + HANDLE file = CreateFileA( + buf, GENERIC_READ | GENERIC_WRITE, + mode == FILE_MAP_SHARED ? FILE_SHARE_READ | FILE_SHARE_WRITE + : 0, + NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + if (file == INVALID_HANDLE_VALUE) { + mf.status = KIT_ERROR_OPEN_FAILED; + return mf; + } + + LONG high = (LONG) (size >> 32); + + if (SetFilePointer(file, (LONG) size, &high, FILE_BEGIN) == + INVALID_SET_FILE_POINTER) { + CloseHandle(file); + assert(0); + mf.status = KIT_ERROR_TRUNCATE_FAILED; + return mf; + } + + if (!SetEndOfFile(file)) { + CloseHandle(file); + assert(0); + mf.status = KIT_ERROR_TRUNCATE_FAILED; + return mf; + } + + HANDLE map = CreateFileMappingA(file, NULL, PAGE_READWRITE, + (DWORD) (size >> 32), (DWORD) size, + NULL); + + if (map == INVALID_HANDLE_VALUE) { + CloseHandle(file); + assert(0); + mf.status = KIT_ERROR_MAP_FAILED; + return mf; + } + + void *p = MapViewOfFile(map, FILE_MAP_ALL_ACCESS, 0, 0, + (SIZE_T) size); + + if (p == NULL) { + CloseHandle(map); + CloseHandle(file); + assert(0); + mf.status = KIT_ERROR_MAP_FAILED; + return mf; + } + + mf.status = KIT_OK; + mf.size = size; + mf.bytes = p; + mf._file = file; + mf._map = map; +#else + char buf[PATH_MAX + 1]; + memcpy(buf, path.values, path.size); + buf[path.size] = '\0'; + + i32 fd = open(buf, O_RDWR | O_CREAT, 0664); + + if (fd == -1) { + mf.status = KIT_ERROR_OPEN_FAILED; + return mf; + } + + if (ftruncate(fd, size) == -1) { + close(fd); + assert(0); + mf.status = KIT_ERROR_TRUNCATE_FAILED; + return mf; + } + + void *p = mmap( + NULL, size, PROT_READ | PROT_WRITE, + mode == KIT_FILE_MAP_SHARED ? MAP_SHARED : MAP_PRIVATE, fd, 0); + + if (p == MAP_FAILED) { + close(fd); + assert(0); + mf.status = KIT_ERROR_MAP_FAILED; + return mf; + } + + mf.status = KIT_OK; + mf.size = size; + mf.bytes = (u8 *) p; + mf._fd = fd; +#endif + + return mf; +} + +kit_status_t kit_file_sync(kit_mapped_file_t *mf) { + assert(mf != NULL); + + if (mf == NULL) + return KIT_ERROR_INVALID_ARGUMENT; + + kit_status_t status = KIT_OK; + +#if !defined(_WIN32) || defined(__CYGWIN__) + if (msync(mf->bytes, mf->size, MS_SYNC) != 0) + status |= KIT_ERROR_SYNC_FAILED; +#endif + + return status; +} + +kit_status_t kit_file_unmap(kit_mapped_file_t *mf) { + assert(mf != NULL); + + if (mf == NULL) + return KIT_ERROR_INVALID_ARGUMENT; + + kit_status_t status = KIT_OK; + +#if defined(_WIN32) && !defined(__CYGWIN__) + if (!UnmapViewOfFile(mf->bytes)) + status |= KIT_ERROR_UNMAP_FAILED; + if (!CloseHandle(mf->_map) || !CloseHandle(mf->_file)) + status |= KIT_ERROR_CLOSE_FAILED; +#else + if (munmap(mf->bytes, mf->size) != 0) + status |= KIT_ERROR_UNMAP_FAILED; + if (close(mf->_fd) != 0) + status |= KIT_ERROR_CLOSE_FAILED; +#endif + + return status; +} diff --git a/source/kit/file.h b/source/kit/file.h index c0a8f23..b2e4f20 100644 --- a/source/kit/file.h +++ b/source/kit/file.h @@ -5,6 +5,8 @@ #include "status.h" #include "string_builder.h" +#include + #ifdef __cplusplus extern "C" { #endif @@ -28,6 +30,20 @@ typedef struct { KIT_DA(kit_str_builder_t) files; } kit_path_list_t; +enum { KIT_FILE_MAP_PRIVATE, KIT_FILE_MAP_SHARED }; + +typedef struct { + kit_status_t status; + i64 size; + u8 *bytes; +#if defined(_WIN32) && !defined(__CYGWIN__) + void *_file; + void *_map; +#else + int _fd; +#endif +} kit_mapped_file_t; + #if defined(_WIN32) && !defined(__CYGWIN__) # define KIT_PATH_DELIM_C '\\' # define KIT_PATH_DELIM "\\" @@ -52,13 +68,13 @@ kit_str_t kit_path_index(kit_str_t path, i64 index); kit_str_t kit_path_take(kit_str_t path, i64 count); -kit_status_t kit_file_create_folder(kit_str_t path); +kit_status_t kit_folder_create(kit_str_t path); -kit_status_t kit_file_create_folder_recursive(kit_str_t path); +kit_status_t kit_folder_create_recursive(kit_str_t path); kit_status_t kit_file_remove(kit_str_t path); -kit_status_t kit_file_remove_folder(kit_str_t path); +kit_status_t kit_folder_remove(kit_str_t path); kit_status_t kit_file_remove_recursive(kit_str_t path, kit_allocator_t *alloc); @@ -67,11 +83,15 @@ kit_path_type_t kit_path_type(kit_str_t path); kit_file_info_t kit_file_info(kit_str_t path); -kit_path_list_t kit_file_enum_folder(kit_str_t path, - kit_allocator_t *alloc); +kit_path_list_t kit_folder_enum(kit_str_t path, + kit_allocator_t *alloc); void kit_path_list_destroy(kit_path_list_t list); +kit_mapped_file_t kit_file_map(kit_str_t path, i64 size, i32 mode); +kit_status_t kit_file_sync(kit_mapped_file_t *mf); +kit_status_t kit_file_unmap(kit_mapped_file_t *mf); + #ifdef __cplusplus } #endif @@ -83,19 +103,25 @@ void kit_path_list_destroy(kit_path_list_t list); # define path_cache kit_path_cache # define path_index kit_path_index # define path_take kit_path_take -# define file_create_folder kit_file_create_folder -# define file_create_folder_recursive \ - kit_file_create_folder_recursive +# define folder_create kit_folder_create +# define folder_create_recursive kit_folder_create_recursive # define file_remove kit_file_remove -# define file_remove_folder kit_file_remove_folder +# define folder_remove kit_folder_remove # define file_remove_recursive kit_file_remove_recursive # define path_type_t kit_path_type_t # define path_type kit_path_type # define file_info_t kit_file_info_t # define file_info kit_file_info # define path_list_t kit_path_list_t -# define file_enum_folder kit_file_enum_folder +# define folder_enum kit_folder_enum # define path_list_destroy kit_path_list_destroy +# define mapped_file_t kit_mapped_file_t +# define file_map kit_file_map +# define file_sync kit_file_sync +# define file_unmap kit_file_unmap + +# define FILE_MAP_PRIVATE KIT_FILE_MAP_PRIVATE +# define FILE_MAP_SHARED KIT_FILE_MAP_SHARED # define PATH_DELIM_C KIT_PATH_DELIM_C # define PATH_DELIM KIT_PATH_DELIM diff --git a/source/kit/kit_test.h b/source/kit/kit_test.h index f51516f..b6f43a6 100644 --- a/source/kit/kit_test.h +++ b/source/kit/kit_test.h @@ -672,7 +672,7 @@ int kit_run_tests(int argc, char **argv) { no_color || kit_print_color_(kit_red_); printf(" -> "); no_color || kit_print_color_(kit_light_); - printf("Got wrong value"); + printf("Got wrong value "); no_color || kit_print_color_(kit_white_); printf("%10lld", (long long) kit_tests_list.v[i].value[j]); @@ -686,7 +686,7 @@ int kit_run_tests(int argc, char **argv) { no_color || kit_print_color_(kit_green_); printf(" -> "); no_color || kit_print_color_(kit_light_); - printf("Expected value "); + printf("Expected value "); no_color || kit_print_color_(kit_white_); printf("%10lld", (long long) kit_tests_list.v[i].expected[j]); diff --git a/source/kit/shared_memory.h b/source/kit/shared_memory.h index fc9a082..594d4a4 100644 --- a/source/kit/shared_memory.h +++ b/source/kit/shared_memory.h @@ -20,7 +20,6 @@ typedef struct { void *_handle; #else i8 _owned; - i32 _fd; char _name[NAME_MAX + 1]; #endif } kit_shared_memory_t; @@ -33,9 +32,19 @@ enum { kit_shared_memory_t kit_shared_memory_open(kit_str_t name, i64 size, i32 mode); kit_status_t kit_shared_memory_close(kit_shared_memory_t *mem); +kit_status_t kit_shared_memory_clean(kit_str_t name); #ifdef __cplusplus } #endif +#ifndef KIT_DISABLE_SHORT_NAMES +# define shared_memory_t kit_shared_memory_t +# define shared_memory_open kit_shared_memory_open +# define shared_memory_close kit_shared_memory_close + +# define SHARED_MEMORY_OPEN KIT_SHARED_MEMORY_OPEN +# define SHARED_MEMORY_CREATE KIT_SHARED_MEMORY_CREATE +#endif + #endif diff --git a/source/kit/shared_memory.posix.c b/source/kit/shared_memory.posix.c index 1695f14..edb8794 100644 --- a/source/kit/shared_memory.posix.c +++ b/source/kit/shared_memory.posix.c @@ -52,24 +52,26 @@ kit_shared_memory_t kit_shared_memory_open(kit_str_t name, i64 size, mode == KIT_SHARED_MEMORY_CREATE ? 0660 : 0); if (fd == -1) { - mem.status = KIT_ERROR_SHM_OPEN_FAILED; + mem.status = KIT_ERROR_OPEN_FAILED; return mem; } if (mode == KIT_SHARED_MEMORY_CREATE && ftruncate(fd, size) == -1) { shm_unlink(mem._name); assert(0); - mem.status = KIT_ERROR_FTRUNCATE_FAILED; + mem.status = KIT_ERROR_TRUNCATE_FAILED; return mem; } void *p = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + close(fd); + if (p == MAP_FAILED) { shm_unlink(mem._name); assert(0); - mem.status = KIT_ERROR_MMAP_FAILED; + mem.status = KIT_ERROR_MAP_FAILED; return mem; } @@ -77,7 +79,6 @@ kit_shared_memory_t kit_shared_memory_open(kit_str_t name, i64 size, mem.size = size; mem.bytes = (u8 *) p; mem._owned = (mode == KIT_SHARED_MEMORY_CREATE); - mem._fd = fd; return mem; } @@ -90,10 +91,35 @@ kit_status_t kit_shared_memory_close(kit_shared_memory_t *mem) { kit_status_t status = KIT_OK; if (munmap(mem->bytes, mem->size) != 0) - status |= KIT_ERROR_MUNMAP_FAILED; + status |= KIT_ERROR_UNMAP_FAILED; if (mem->_owned && shm_unlink(mem->_name) != 0) status |= KIT_ERROR_UNLINK_FAILED; return status; } + +kit_status_t kit_shared_memory_clean(kit_str_t name) { + assert(name.size > 0); + assert(name.size + 1 <= NAME_MAX); + assert(name.values != NULL); + + if (name.size <= 0) + return KIT_ERROR_INVALID_NAME; + + if (name.size + 1 > NAME_MAX) + return KIT_ERROR_NAME_TOO_LONG; + + for (i64 i = 0; i < name.size; i++) + if (name.values[i] == '/' || name.values[i] == '\\') + return KIT_ERROR_INVALID_NAME; + + char buf[NAME_MAX + 1] = "/"; + memcpy(buf + 1, name.values, name.size); + buf[1 + name.size] = '\0'; + + if (shm_unlink(buf) != 0) + return KIT_ERROR_UNLINK_FAILED; + + return KIT_OK; +} #endif diff --git a/source/kit/shared_memory.win32.c b/source/kit/shared_memory.win32.c index 5b5c1b0..73175b1 100644 --- a/source/kit/shared_memory.win32.c +++ b/source/kit/shared_memory.win32.c @@ -41,21 +41,23 @@ kit_shared_memory_t kit_shared_memory_open(kit_str_t name, i64 size, buf[7 + name.size] = '\0'; HANDLE h = mode == KIT_SHARED_MEMORY_CREATE - ? CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, - PAGE_READWRITE, 0, size, buf) + ? CreateFileMappingA( + INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, + (DWORD) (size >> 32), (DWORD) size, buf) : OpenFileMappingA(FILE_MAP_ALL_ACCESS, 0, buf); - if (h == NULL) { - mem.status = KIT_ERROR_SHM_OPEN_FAILED; + if (h == INVALID_HANDLE_VALUE) { + mem.status = KIT_ERROR_OPEN_FAILED; return mem; } - void *p = MapViewOfFile(h, FILE_MAP_ALL_ACCESS, 0, 0, size); + void *p = MapViewOfFile(h, FILE_MAP_ALL_ACCESS, 0, 0, + (SIZE_T) size); assert(p != NULL); if (p == NULL) { CloseHandle(h); - mem.status = KIT_ERROR_MMAP_FAILED; + mem.status = KIT_ERROR_MAP_FAILED; return mem; } @@ -72,10 +74,17 @@ kit_status_t kit_shared_memory_close(kit_shared_memory_t *mem) { i32 status = KIT_OK; if (!UnmapViewOfFile(mem->bytes)) - status |= KIT_ERROR_MUNMAP_FAILED; + status |= KIT_ERROR_UNMAP_FAILED; if (!CloseHandle(mem->_handle)) status |= KIT_ERROR_UNLINK_FAILED; return status; } + +kit_status_t kit_shared_memory_clean(kit_str_t name) { + // Do nothing. + // + + return KIT_OK; +} #endif diff --git a/source/kit/status.h b/source/kit/status.h index 983e263..35139e3 100644 --- a/source/kit/status.h +++ b/source/kit/status.h @@ -5,25 +5,27 @@ enum { KIT_OK = 0, - KIT_ERROR_NOT_IMPLEMENTED = 1, - KIT_ERROR_BAD_ALLOC = (1 << 1), - KIT_ERROR_INVALID_ARGUMENT = (1 << 2), - KIT_ERROR_MKDIR_FAILED = (1 << 3), - KIT_ERROR_RMDIR_FAILED = (1 << 4), - KIT_ERROR_UNLINK_FAILED = (1 << 5), - KIT_ERROR_FILE_ALREADY_EXISTS = (1 << 6), - KIT_ERROR_FILE_DO_NOT_EXIST = (1 << 7), - KIT_ERROR_PATH_TOO_LONG = (1 << 8), - KIT_ERROR_SOCKETS_STARTUP_FAILED = (1 << 9), - KIT_ERROR_SOCKET_CONTROL_FAILED = (1 << 10), - KIT_ERROR_NAME_TOO_LONG = (1 << 11), - KIT_ERROR_INVALID_SIZE = (1 << 12), - KIT_ERROR_INVALID_NAME = (1 << 13), - KIT_ERROR_SHM_OPEN_FAILED = (1 << 14), - KIT_ERROR_SHM_UNLINK_FAILED = (1 << 15), - KIT_ERROR_FTRUNCATE_FAILED = (1 << 16), - KIT_ERROR_MMAP_FAILED = (1 << 17), - KIT_ERROR_MUNMAP_FAILED = (1 << 18), + KIT_ERROR_BAD_ALLOC = 1, + KIT_ERROR_INVALID_ARGUMENT = (1 << 1), + KIT_ERROR_MKDIR_FAILED = (1 << 2), + KIT_ERROR_RMDIR_FAILED = (1 << 3), + KIT_ERROR_UNLINK_FAILED = (1 << 4), + KIT_ERROR_FILE_ALREADY_EXISTS = (1 << 5), + KIT_ERROR_FILE_DOES_NOT_EXIST = (1 << 6), + KIT_ERROR_PATH_TOO_LONG = (1 << 7), + KIT_ERROR_SOCKETS_STARTUP_FAILED = (1 << 8), + KIT_ERROR_SOCKET_CONTROL_FAILED = (1 << 9), + KIT_ERROR_NAME_TOO_LONG = (1 << 10), + KIT_ERROR_INVALID_SIZE = (1 << 11), + KIT_ERROR_INVALID_NAME = (1 << 12), + KIT_ERROR_INVALID_PATH = (1 << 13), + KIT_ERROR_OPEN_FAILED = (1 << 14), + KIT_ERROR_TRUNCATE_FAILED = (1 << 15), + KIT_ERROR_MAP_FAILED = (1 << 16), + KIT_ERROR_UNMAP_FAILED = (1 << 17), + KIT_ERROR_SYNC_FAILED = (1 << 18), + KIT_ERROR_CLOSE_FAILED = (1 << 19), + KIT_ERROR_NOT_IMPLEMENTED = (1 << 30), }; typedef i32 kit_status_t; diff --git a/source/tests/file.test.c b/source/tests/file.test.c index e6071a1..2a37c07 100644 --- a/source/tests/file.test.c +++ b/source/tests/file.test.c @@ -1,6 +1,5 @@ #include "../kit/file.h" #include "../kit/string_ref.h" -#include #define KIT_TEST_FILE file #include "../kit/kit_test.h" @@ -205,16 +204,79 @@ TEST("file path take windows disk name") { REQUIRE(AR_EQUAL(path_take(foobar, 2), bar)); } -TEST("file create folder") { } +TEST("file create folder") { + str_t folder_name = SZ("test_folder"); -TEST("file create folder recursive") { } + REQUIRE_EQ(folder_create(folder_name), KIT_OK); + REQUIRE_EQ(path_type(folder_name), PATH_FOLDER); + REQUIRE_EQ(folder_remove(folder_name), KIT_OK); + REQUIRE_EQ(path_type(folder_name), PATH_NONE); +} + +TEST("file create folder recursive") { + REQUIRE_EQ(folder_create_recursive( + SZ("test_folder" PATH_DELIM "foo" PATH_DELIM "bar")), + KIT_OK); + REQUIRE_EQ(path_type(SZ("test_folder")), PATH_FOLDER); + REQUIRE_EQ(path_type(SZ("test_folder" PATH_DELIM "foo")), + PATH_FOLDER); + REQUIRE_EQ( + path_type(SZ("test_folder" PATH_DELIM "foo" PATH_DELIM "bar")), + PATH_FOLDER); + REQUIRE_EQ(file_remove_recursive(SZ("test_folder"), NULL), KIT_OK); + REQUIRE_EQ(path_type(SZ("test_folder")), PATH_NONE); +} + +TEST("file remove") { + FILE *f = fopen("test_file", "wb"); + fclose(f); + + REQUIRE_EQ(path_type(SZ("test_file")), PATH_FILE); + REQUIRE_EQ(file_remove(SZ("test_file")), KIT_OK); + REQUIRE_EQ(path_type(SZ("test_file")), PATH_NONE); + REQUIRE_EQ(file_remove(SZ("unexisted_file_foo_bar")), + KIT_ERROR_UNLINK_FAILED); +} + +TEST("file map read") { + char buf[] = "bar"; -TEST("file remove") { } + FILE *f = fopen("foo", "wb"); + fwrite(buf, 1, 3, f); + fclose(f); -TEST("file remove folder") { } + mapped_file_t mf = file_map(SZ("foo"), 3, FILE_MAP_PRIVATE); -TEST("file remove recursive") { } + REQUIRE_EQ(mf.status, KIT_OK); + if (mf.status == KIT_OK) { + REQUIRE_EQ(memcmp(buf, mf.bytes, 3), 0); + file_unmap(&mf); + } -TEST("file enum folder") { } + file_remove(SZ("foo")); +} + +TEST("file map write") { + mapped_file_t mf = file_map(SZ("foo"), 3, FILE_MAP_SHARED); + + REQUIRE_EQ(mf.status, KIT_OK); + if (mf.status == KIT_OK) { + memcpy(mf.bytes, "bar", 3); + file_unmap(&mf); + + char buf[3]; + FILE *f = fopen("foo", "rb"); + i64 n = (i64) fread(buf, 1, 3, f); + REQUIRE_EQ(n, 3); + fclose(f); + + if (n == 3) { + printf("READ: %d %d %d \n", buf[0], buf[1], buf[2]); + REQUIRE_EQ(memcmp(buf, "bar", 3), 0); + } + + file_remove(SZ("foo")); + } +} #undef KIT_TEST_FILE diff --git a/source/tests/test_interprocess.c b/source/tests/test_interprocess.c index a69dd02..cf33086 100644 --- a/source/tests/test_interprocess.c +++ b/source/tests/test_interprocess.c @@ -10,6 +10,8 @@ enum { DATA_SIZE = 64 }; enum { STATE_INIT, STATE_READY, STATE_DONE }; int run_writer() { + kit_shared_memory_clean(SZ(NAME)); + kit_shared_memory_t mem = kit_shared_memory_open( SZ(NAME), DATA_SIZE, KIT_SHARED_MEMORY_CREATE); -- cgit v1.2.3