diff options
Diffstat (limited to 'src/posix')
-rw-r--r-- | src/posix/environment_posix.c | 134 | ||||
-rw-r--r-- | src/posix/filesystem_posix.c | 35 | ||||
-rw-r--r-- | src/posix/sem_posix.c | 7 | ||||
-rw-r--r-- | src/posix/thread_posix.c | 4 |
4 files changed, 160 insertions, 20 deletions
diff --git a/src/posix/environment_posix.c b/src/posix/environment_posix.c new file mode 100644 index 0000000..8447753 --- /dev/null +++ b/src/posix/environment_posix.c @@ -0,0 +1,134 @@ +// Copyright 2012-2024 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC + +#include <zix/environment.h> + +#include <zix/allocator.h> + +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> + +static bool +is_path_delim(const char c) +{ + return c == '/' || c == ':' || c == '\0'; +} + +static bool +is_var_name_char(const char c) +{ + return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c == '_'); +} + +// Append suffix to dst, update dst_len, and return the realloc'd result +static char* +append_str(ZixAllocator* const allocator, + size_t* const dst_len, + char* const dst, + const size_t suffix_len, + const char* const suffix) +{ + const size_t out_len = *dst_len + suffix_len; + char* const out = (char*)zix_realloc(allocator, dst, out_len + 1U); + if (!out) { + zix_free(allocator, dst); + return NULL; + } + + memcpy(out + *dst_len, suffix, suffix_len); + out[(*dst_len += suffix_len)] = '\0'; + return out; +} + +// Append the value of an environment variable to dst if it's set +static char* +append_var(ZixAllocator* const allocator, + size_t* const dst_len, + char* const dst, + const size_t ref_len, + const char* const ref) +{ + // Get value from environment + const char* const val = getenv(ref + 1U); // NOLINT(concurrency-mt-unsafe) + if (val) { + return append_str(allocator, dst_len, dst, strlen(val), val); + } + + // No value found, append variable reference as-is + return append_str(allocator, dst_len, dst, ref_len, ref); +} + +// Copy a variable reference string like $NAME to a null-terminated string +static char* +set_ref(ZixAllocator* const allocator, + char** const buffer, + const size_t ref_len, + const char* const ref) +{ + char* const out = (char*)zix_realloc(allocator, *buffer, ref_len + 1U); + + if (out) { + memcpy(out, ref, ref_len); + out[ref_len] = '\0'; + } else { + zix_free(allocator, *buffer); + } + + return out; +} + +char* +zix_expand_environment_strings(ZixAllocator* const allocator, + const char* const string) +{ + char* ref = NULL; // Reference string like $NAME + char* out = NULL; // Expanded result + size_t len = 0U; // Length of expanded result + + size_t start = 0U; // Start of current chunk to copy + for (size_t s = 0U; string[s];) { + const char c = string[s]; + if (c == '$' && is_var_name_char(string[s + 1U])) { + // Hit $ (variable reference like $VAR_NAME) + for (size_t t = 1U;; ++t) { + if (!is_var_name_char(string[s + t])) { + const char* const prefix = string + start; + const size_t prefix_len = s - start; + if ((prefix_len && + !(out = append_str(allocator, &len, out, prefix_len, prefix))) || + !(ref = set_ref(allocator, &ref, t, string + s)) || + !(out = append_var(allocator, &len, out, t, ref))) { + zix_free(allocator, ref); + zix_free(allocator, out); + return NULL; + } + start = s = t; + break; + } + } + } else if (c == '~' && is_path_delim(string[s + 1U])) { + // Hit ~ before delimiter or end of string (home directory reference) + const char* const prefix = string + start; + const size_t prefix_len = s - start; + if ((prefix_len && + !(out = append_str(allocator, &len, out, prefix_len, prefix))) || + !(out = append_var(allocator, &len, out, 5U, "$HOME"))) { + zix_free(allocator, ref); + return NULL; + } + start = ++s; + } else { + ++s; + } + } + + if (string[start]) { + const char* const tail = string + start; + const size_t tail_len = strlen(tail); + out = append_str(allocator, &len, out, tail_len, tail); + } + + zix_free(allocator, ref); + return out; +} diff --git a/src/posix/filesystem_posix.c b/src/posix/filesystem_posix.c index c82cdf7..ea091e0 100644 --- a/src/posix/filesystem_posix.c +++ b/src/posix/filesystem_posix.c @@ -1,15 +1,15 @@ // Copyright 2007-2022 David Robillard <d@drobilla.net> // SPDX-License-Identifier: ISC -#include "zix/filesystem.h" +#include <zix/filesystem.h> #include "../errno_status.h" #include "../system.h" #include "../zix_config.h" -#include "zix/allocator.h" -#include "zix/attributes.h" -#include "zix/status.h" +#include <zix/allocator.h> +#include <zix/attributes.h> +#include <zix/status.h> #if USE_FLOCK && USE_FILENO # include <sys/file.h> @@ -90,7 +90,7 @@ copy_path(ZixAllocator* const allocator, #if !defined(PATH_MAX) && USE_PATHCONF static size_t -max_path_size(void) +max_path_size(const char* const path) { const long path_max = pathconf(path, _PC_PATH_MAX); return (path_max > 0) ? (size_t)path_max : zix_system_page_size(); @@ -99,8 +99,10 @@ max_path_size(void) #elif !defined(PATH_MAX) static size_t -max_path_size(void) +max_path_size(const char* const path) { + (void)path; + return zix_system_page_size(); } @@ -298,11 +300,9 @@ zix_remove(const char* const path) } void -zix_dir_for_each(const char* const path, - void* const data, - void (*const f)(const char* path, - const char* name, - void* data)) +zix_dir_for_each(const char* const path, + void* const data, + const ZixDirEntryVisitFunc f) { DIR* dir = opendir(path); if (dir) { @@ -341,6 +341,9 @@ zix_canonical_path(ZixAllocator* const allocator, const char* const path) } zix_free(allocator, buffer); + +#else + (void)allocator; #endif return NULL; @@ -349,7 +352,7 @@ zix_canonical_path(ZixAllocator* const allocator, const char* const path) ZixStatus zix_file_lock(FILE* const file, const ZixFileLockMode mode) { -#if !defined(__EMSCRIPTEN__) && USE_FLOCK && USE_FILENO +#if USE_FLOCK && USE_FILENO return zix_posix_status( flock(fileno(file), (mode == ZIX_FILE_LOCK_BLOCK) ? LOCK_EX : (LOCK_EX | LOCK_NB))); @@ -364,7 +367,7 @@ zix_file_lock(FILE* const file, const ZixFileLockMode mode) ZixStatus zix_file_unlock(FILE* const file, const ZixFileLockMode mode) { -#if !defined(__EMSCRIPTEN__) && USE_FLOCK && USE_FILENO +#if USE_FLOCK && USE_FILENO return zix_posix_status( flock(fileno(file), (mode == ZIX_FILE_LOCK_BLOCK) ? LOCK_UN : (LOCK_UN | LOCK_NB))); @@ -376,8 +379,7 @@ zix_file_unlock(FILE* const file, const ZixFileLockMode mode) #endif } -ZIX_CONST_FUNC -static ZixFileType +ZIX_CONST_FUNC static ZixFileType stat_file_type(const struct stat* sb) { typedef struct { @@ -440,7 +442,7 @@ zix_current_path(ZixAllocator* const allocator) #elif USE_PATHCONF // Others don't so we have to query PATH_MAX at runtime to allocate the result - const size_t size = max_path_size(); + const size_t size = max_path_size("."); char* const buffer = (char*)zix_calloc(allocator, size, 1); char* const current = getcwd(buffer, size); if (!current) { @@ -450,6 +452,7 @@ zix_current_path(ZixAllocator* const allocator) return current; #else + (void)allocator; return NULL; #endif diff --git a/src/posix/sem_posix.c b/src/posix/sem_posix.c index 452830d..5b14e37 100644 --- a/src/posix/sem_posix.c +++ b/src/posix/sem_posix.c @@ -1,12 +1,12 @@ // Copyright 2012-2022 David Robillard <d@drobilla.net> // SPDX-License-Identifier: ISC -#include "zix/sem.h" +#include <zix/sem.h> #include "../errno_status.h" #include "../zix_config.h" -#include "zix/status.h" +#include <zix/status.h> #include <semaphore.h> @@ -61,6 +61,9 @@ zix_sem_timed_wait(ZixSem* sem, { #if !USE_CLOCK_GETTIME || !USE_SEM_TIMEDWAIT + (void)sem; + (void)seconds; + (void)nanoseconds; return ZIX_STATUS_NOT_SUPPORTED; #else diff --git a/src/posix/thread_posix.c b/src/posix/thread_posix.c index 2073448..468fe38 100644 --- a/src/posix/thread_posix.c +++ b/src/posix/thread_posix.c @@ -1,11 +1,11 @@ // Copyright 2012-2020 David Robillard <d@drobilla.net> // SPDX-License-Identifier: ISC -#include "zix/thread.h" +#include <zix/thread.h> #include "../errno_status.h" -#include "zix/status.h" +#include <zix/status.h> #include <pthread.h> |