summaryrefslogtreecommitdiffstats
path: root/src/posix
diff options
context:
space:
mode:
Diffstat (limited to 'src/posix')
-rw-r--r--src/posix/environment_posix.c134
-rw-r--r--src/posix/filesystem_posix.c35
-rw-r--r--src/posix/sem_posix.c7
-rw-r--r--src/posix/thread_posix.c4
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>