summaryrefslogtreecommitdiff
path: root/source/kit/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/kit/file.c')
-rw-r--r--source/kit/file.c691
1 files changed, 0 insertions, 691 deletions
diff --git a/source/kit/file.c b/source/kit/file.c
deleted file mode 100644
index 3eafc70..0000000
--- a/source/kit/file.c
+++ /dev/null
@@ -1,691 +0,0 @@
-#include "file.h"
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-enum { PATH_BUF_SIZE = 4096 };
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-# ifndef WIN32_LEAN_AND_MEAN
-# define WIN32_LEAN_AND_MEAN
-# endif
-# ifndef NOMINMAX
-# define NOMINMAX
-# endif
-# include <windows.h>
-# include <shlwapi.h>
-#else
-# include <dirent.h>
-# include <sys/mman.h>
-# include <sys/stat.h>
-# include <fcntl.h>
-# include <unistd.h>
-# include <limits.h>
-#endif
-
-#ifdef __APPLE__
-# define st_mtim st_mtimespec
-#endif
-
-#ifndef PATH_MAX
-# define PATH_MAX MAX_PATH
-#endif
-
-static i32 is_delim(char c) {
- return c == '/' || c == '\\';
-}
-
-kit_str_builder_t kit_get_env(kit_str_t name,
- kit_allocator_t *alloc) {
- char *val = getenv(BS(name));
- i64 size = val != NULL ? (i64) strlen(val) : 0;
-
- str_builder_t result;
- DA_INIT(result, size, alloc);
- assert(result.size == size);
-
- if (result.size == size && size > 0)
- memcpy(result.values, val, result.size);
- else
- DA_RESIZE(result, 0);
-
- return result;
-}
-
-kit_str_builder_t kit_path_norm(kit_str_t path,
- kit_allocator_t *alloc) {
- str_t parent = SZ("..");
- i64 i, i1, j;
-
- str_builder_t norm;
- DA_INIT(norm, path.size, alloc);
- assert(norm.size == path.size);
-
- if (norm.size != path.size)
- return norm;
-
- memcpy(norm.values, path.values, path.size);
-
- for (i1 = 0, i = 0; i < path.size; i++) {
- if (!is_delim(path.values[i]))
- continue;
-
- str_t s = { .size = i - i1 - 1, .values = path.values + i1 + 1 };
- if (AR_EQUAL(s, parent)) {
- i32 have_parent = 0;
- i64 i0 = 0;
-
- for (j = 0; j < i1; j++) {
- if (norm.values[j] != '\0')
- have_parent = 1;
- if (is_delim(norm.values[j]))
- i0 = j;
- }
-
- if (have_parent) {
- memset(norm.values + i0, '\0', i - i0);
-
- if (!is_delim(path.values[i0]))
- norm.values[i] = '\0';
- }
- }
-
- i1 = i;
- }
-
- i64 size = 0;
-
- for (i = 0; i < norm.size; i++) {
- if (norm.values[i] != '\0') {
- if (is_delim(norm.values[i]))
- norm.values[size] = KIT_PATH_DELIM_C;
- else
- norm.values[size] = norm.values[i];
- size++;
- }
- }
-
- norm.size = size;
- return norm;
-}
-
-kit_str_builder_t kit_path_join(kit_str_t left, kit_str_t right,
- kit_allocator_t *alloc) {
- i64 left_size = left.size;
- i64 right_size = right.size;
- char *right_values = right.values;
-
- if (left_size > 0 && is_delim(left.values[left_size - 1]))
- left_size--;
- if (right_size > 0 && is_delim(right.values[0])) {
- right_size--;
- right_values++;
- }
-
- kit_str_builder_t joined;
- DA_INIT(joined, left_size + right_size + 1, alloc);
- assert(joined.size == left_size + right_size + 1);
-
- if (joined.size != left_size + right_size + 1)
- return joined;
-
- memcpy(joined.values, left.values, left_size);
- joined.values[left_size] = KIT_PATH_DELIM_C;
- memcpy(joined.values + left_size + 1, right_values, right_size);
-
- return joined;
-}
-
-kit_str_builder_t kit_path_user(kit_allocator_t *alloc) {
- kit_str_builder_t user = kit_get_env(SZ(KIT_ENV_HOME), alloc);
- if (user.size == 0) {
- DA_RESIZE(user, 1);
- if (user.size == 1)
- user.values[0] = '.';
- }
- return user;
-}
-
-kit_str_builder_t kit_path_cache(kit_allocator_t *alloc) {
- kit_str_builder_t cache, user;
-
- cache = kit_get_env(SZ("XDG_CACHE_HOME"), alloc);
- if (cache.size != 0)
- return cache;
- DA_DESTROY(cache);
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
- cache = kit_get_env(SZ("TEMP"), alloc);
- if (cache.size != 0)
- return cache;
- DA_DESTROY(cache);
-#endif
-
- user = kit_path_user(alloc);
- cache =
-#ifdef __APPLE__
- kit_path_join(WRAP_STR(user), SZ("Library" PATH_DELIM "Caches"),
- alloc);
-#else
- kit_path_join(WRAP_STR(user), SZ(".cache"), alloc);
-#endif
- DA_DESTROY(user);
-
- return cache;
-}
-
-kit_str_builder_t kit_path_data(kit_allocator_t *alloc) {
- kit_str_builder_t data, user;
-
- data = kit_get_env(SZ("XDG_DATA_HOME"), alloc);
- if (data.size != 0)
- return data;
- DA_DESTROY(data);
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
- data = kit_get_env(SZ("LOCALAPPDATA"), alloc);
- if (data.size != 0)
- return data;
- DA_DESTROY(data);
-#endif
-
- user = kit_path_user(alloc);
- data =
-#ifdef __APPLE__
- kit_path_join(WRAP_STR(user), SZ("Library"), alloc);
-#else
- kit_path_join(WRAP_STR(user), SZ(".local" PATH_DELIM "share"),
- alloc);
-#endif
- DA_DESTROY(user);
-
- return data;
-}
-
-kit_str_t kit_path_index(kit_str_t path, i64 index) {
- str_t s = { .size = 0, .values = NULL };
-
- i64 i0 = 0;
- i64 i = 0;
- i64 n = 0;
-
- for (; i < path.size; i++) {
- if (!is_delim(path.values[i]))
- continue;
-
- if (i0 < i) {
- if (n++ == index) {
- s.values = path.values + i0;
- s.size = i - i0;
- return s;
- }
- }
-
- i0 = i + 1;
- }
-
- if (n == index) {
- s.values = path.values + i0;
- s.size = i - i0;
- }
-
- return s;
-}
-
-kit_str_t kit_path_take(kit_str_t path, i64 count) {
- str_t s = { .size = 0, .values = path.values };
-
- i64 i0 = 0;
- i64 i = 0;
- i64 n = 0;
-
- for (; i < path.size; i++) {
- if (!is_delim(path.values[i]))
- continue;
-
- if (i0 < i) {
- if (n++ == count) {
- s.size = i;
- return s;
- }
- }
-
- i0 = i + 1;
- }
-
- if (n == count)
- s.size = i;
-
- return s;
-}
-
-// TODO
-// Long path support for Windows
-//
-static void kit_prepare_path_(char *buf, kit_str_t path) {
- assert(path.size == 0 || path.values != NULL);
- assert(path.size + 1 < PATH_BUF_SIZE);
-
- memset(buf, 0, PATH_BUF_SIZE);
- if (path.size > 0 && path.size + 1 < PATH_BUF_SIZE)
- memcpy(buf, path.values, path.size);
-}
-
-#define PREPARE_PATH_BUF_ \
- char buf[PATH_BUF_SIZE]; \
- kit_prepare_path_(buf, path)
-
-s32 kit_folder_create(kit_str_t path) {
- PREPARE_PATH_BUF_;
-#if defined(_WIN32) && !defined(__CYGWIN__)
- return CreateDirectoryA(buf, NULL) ? KIT_OK
- : KIT_ERROR_MKDIR_FAILED;
-#else
- return mkdir(buf, 0775) == 0 ? KIT_OK : KIT_ERROR_MKDIR_FAILED;
-#endif
-}
-
-s32 kit_folder_create_recursive(kit_str_t path) {
- for (i32 i = 0;; i++) {
- str_t part = kit_path_take(path, i);
- i32 type = kit_path_type(part);
- if (type == KIT_PATH_FILE)
- return KIT_ERROR_FILE_ALREADY_EXISTS;
- if (type == KIT_PATH_NONE) {
- s32 s = kit_folder_create(part);
- if (s != KIT_OK)
- return s;
- }
- if (part.size == path.size)
- break;
- }
-
- return KIT_OK;
-}
-
-s32 kit_file_remove(kit_str_t path) {
- PREPARE_PATH_BUF_;
-#if defined(_WIN32) && !defined(__CYGWIN__)
- return DeleteFileA(buf) ? KIT_OK : KIT_ERROR_UNLINK_FAILED;
-#else
- return unlink(buf) == 0 ? KIT_OK : KIT_ERROR_UNLINK_FAILED;
-#endif
-}
-
-s32 kit_folder_remove(kit_str_t path) {
- PREPARE_PATH_BUF_;
-#if defined(_WIN32) && !defined(__CYGWIN__)
- return RemoveDirectoryA(buf) ? KIT_OK : KIT_ERROR_RMDIR_FAILED;
-#else
- return rmdir(buf) == 0 ? KIT_OK : KIT_ERROR_RMDIR_FAILED;
-#endif
-}
-
-s32 kit_file_remove_recursive(kit_str_t path,
- kit_allocator_t *alloc) {
- i32 type = kit_path_type(path);
- i64 i;
-
- switch (type) {
- case KIT_PATH_FILE: {
- s32 s = kit_file_remove(path);
- assert(s == KIT_OK);
- return s;
- }
-
- case KIT_PATH_FOLDER: {
- 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_builder_t full_path = kit_path_join(
- path, WRAP_STR(list.files.values[i]), alloc);
- s32 s = kit_file_remove_recursive(WRAP_STR(full_path), alloc);
- DA_DESTROY(full_path);
- assert(s == KIT_OK);
- }
-
- kit_path_list_destroy(list);
-
- s32 s = kit_folder_remove(path);
- assert(s == KIT_OK);
- return s;
- }
-
- default:;
- }
-
- return KIT_ERROR_FILE_DOES_NOT_EXIST;
-}
-
-kit_path_type_t kit_path_type(kit_str_t path) {
- PREPARE_PATH_BUF_;
-#if defined(_WIN32) && !defined(__CYGWIN__)
- if (PathFileExistsA(buf)) {
- if ((GetFileAttributesA(buf) & FILE_ATTRIBUTE_DIRECTORY) != 0)
- return KIT_PATH_FOLDER;
- else
- return KIT_PATH_FILE;
- }
-#else
- struct stat info;
- if (stat(buf, &info) == 0) {
- if (S_ISREG(info.st_mode))
- return KIT_PATH_FILE;
- if (S_ISDIR(info.st_mode))
- return KIT_PATH_FOLDER;
- }
-#endif
- return KIT_PATH_NONE;
-}
-
-kit_file_info_t kit_file_info(kit_str_t path) {
- kit_file_info_t result;
- memset(&result, 0, sizeof result);
-
- PREPARE_PATH_BUF_;
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
- HANDLE f = CreateFileA(buf, GENERIC_READ, FILE_SHARE_READ, NULL,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (f != INVALID_HANDLE_VALUE) {
- FILETIME ft;
- if (GetFileTime(f, NULL, NULL, &ft) != 0) {
- i64 nsec100 = (((u64) ft.dwHighDateTime) << 32) |
- (u64) ft.dwLowDateTime;
- result.time_modified_sec = (i64) (nsec100 / 10000000);
- result.time_modified_nsec = (i32) (100 * (nsec100 % 10000000));
- } else {
- assert(0);
- }
-
- DWORD high;
- DWORD low = GetFileSize(f, &high);
-
- result.size = (i64) ((((u64) high) << 32) | (u64) low);
- result.status = KIT_OK;
-
- CloseHandle(f);
- return result;
- }
-#else
- struct stat info;
- if (stat(buf, &info) == 0 && S_ISREG(info.st_mode)) {
- result.size = (i64) info.st_size;
-# ifndef st_mtime
- // No support for nanosecond timestamps.
- //
- result.time_modified_sec = (i64) info.st_mtime;
-# else
- result.time_modified_sec = (i64) info.st_mtim.tv_sec;
- result.time_modified_nsec = (i32) info.st_mtim.tv_nsec;
-# endif
- result.status = KIT_OK;
- return result;
- }
-#endif
-
- result.status = KIT_ERROR_FILE_DOES_NOT_EXIST;
- return result;
-}
-
-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 };
- DA_INIT(result.files, 0, alloc);
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
- if (path.size + 3 >= PATH_BUF_SIZE) {
- result.status = KIT_ERROR_PATH_TOO_LONG;
- return result;
- }
-
- buf[path.size] = '\\';
- buf[path.size + 1] = '*';
-
- WIN32_FIND_DATAA data;
- HANDLE find = FindFirstFileA(buf, &data);
-
- if (find == INVALID_HANDLE_VALUE)
- return result;
-
- do {
- if (strcmp(data.cFileName, ".") == 0 ||
- strcmp(data.cFileName, "..") == 0)
- continue;
-
- i64 n = result.files.size;
- DA_RESIZE(result.files, n + 1);
- if (result.files.size != n + 1) {
- result.status = KIT_ERROR_OUT_OF_MEMORY;
- break;
- }
-
- i64 size = (i64) strlen(data.cFileName);
- DA_INIT(result.files.values[n], size, alloc);
- if (result.files.values[n].size != size) {
- DA_RESIZE(result.files, n);
- result.status = KIT_ERROR_OUT_OF_MEMORY;
- break;
- }
-
- memcpy(result.files.values[n].values, data.cFileName, size);
- } while (FindNextFileA(find, &data) != 0);
-
- FindClose(find);
-#else
- DIR *directory = opendir(buf);
-
- if (directory == NULL)
- return result;
-
- for (;;) {
- struct dirent *entry = readdir(directory);
-
- if (entry == NULL)
- break;
-
- if (entry->d_name[0] == '.')
- continue;
-
- i64 n = result.files.size;
- DA_RESIZE(result.files, n + 1);
- if (result.files.size != n + 1) {
- result.status = KIT_ERROR_OUT_OF_MEMORY;
- break;
- }
-
- i64 size = (i64) strlen(entry->d_name);
- DA_INIT(result.files.values[n], size, alloc);
- if (result.files.values[n].size != size) {
- DA_RESIZE(result.files, n);
- result.status = KIT_ERROR_OUT_OF_MEMORY;
- break;
- }
-
- if (size > 0)
- memcpy(result.files.values[n].values, entry->d_name, size);
- }
-
- closedir(directory);
-#endif
-
- return result;
-}
-
-void kit_path_list_destroy(kit_path_list_t list) {
- i64 i;
- for (i = 0; i < list.files.size; i++)
- 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;
-}
-
-s32 kit_file_sync(kit_mapped_file_t *mf) {
- assert(mf != NULL);
-
- if (mf == NULL)
- return KIT_ERROR_INVALID_ARGUMENT;
-
- s32 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;
-}
-
-s32 kit_file_unmap(kit_mapped_file_t *mf) {
- assert(mf != NULL);
-
- if (mf == NULL)
- return KIT_ERROR_INVALID_ARGUMENT;
-
- s32 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;
-}