aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile10
-rw-r--r--compat/compat.h6
-rw-r--r--include/moslib/safe.h16
-rw-r--r--src/safe.c15
-rw-r--r--src/tester.c41
-rw-r--r--tests/safe_tests.c43
-rw-r--r--tests/string_tests.c3
7 files changed, 104 insertions, 30 deletions
diff --git a/Makefile b/Makefile
index ae8a59e..044e2b4 100644
--- a/Makefile
+++ b/Makefile
@@ -29,12 +29,18 @@ endef
PROBED:= \
$(call probe_fun,string.h,memmem) \
- $(call probe_fun,string.h,strdup) \
- $(call probe_fun,stdio.h,fileno)
+ $(call probe_fun,string.h,strdup)
CFLAGS+=$(PROBED)
TESTS_CFLAGS+=$(PROBED)
+FS_FLAG:=$(shell printf '#include "compat.h"\n#include <stdio.h>\nint main(void){\n#ifdef _WIN32\n_fileno;\n#else\nfileno;\n#endif\nreturn 0;}' \
+ | $(CC) $(CFLAGS) -x c - -o /dev/null 2>/dev/null \
+ || echo -DNO_FS)
+
+CFLAGS+=$(FS_FLAG)
+TESTS_CFLAGS+=$(FS_FLAG)
+
both: CLEANUP=true
both: clean shared static
@$(MAKE) clean --no-print-directory
diff --git a/compat/compat.h b/compat/compat.h
index 314ffcf..367ec47 100644
--- a/compat/compat.h
+++ b/compat/compat.h
@@ -27,10 +27,4 @@ extern char *mos_strdup(const char *s);
extern void *mos_memmem(const void *h, size_t h_size, const void *n, size_t n_size);
#endif // NO_MEMMEM
-#ifndef NO_FILENO
-#define mos_fileno fileno
-#else
-#error fileno fallback not implemented
-#endif // NO_MEMMEM
-
#endif // MOSLIB_COMPAT_H
diff --git a/include/moslib/safe.h b/include/moslib/safe.h
index a606f17..e9fb7bb 100644
--- a/include/moslib/safe.h
+++ b/include/moslib/safe.h
@@ -4,9 +4,14 @@
#include <stddef.h>
#include <stdio.h>
-#include <unistd.h>
#include <sys/types.h>
+#ifndef _WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+
#ifndef MOSLIB_SAFE_H
#define MOSLIB_SAFE_H
@@ -19,8 +24,11 @@
#define safe_tmpfile mos_safe_tmpfile
#define safe_dup mos_safe_dup
#define safe_dup2 mos_safe_dup2
+
+#ifndef _WIN32
#define safe_fork mos_safe_fork
#define safe_pipe mos_safe_pipe
+#endif
#endif // MOS_FORCE_PREFIXES
@@ -41,8 +49,11 @@ typedef struct {
#define mos_safe_tmpfile() mos_safe_tmpfile_fn(mos_err_info)
#define mos_safe_dup(fd) mos_safe_dup_fn(fd, mos_err_info)
#define mos_safe_dup2(fd, fd2) mos_safe_dup2_fn(fd, fd2, mos_err_info)
+
+#ifndef _WIN32
#define mos_safe_fork() mos_safe_fork_fn(mos_err_info)
#define mos_safe_pipe(fd) mos_safe_pipe_fn(fd, mos_err_info)
+#endif
// Function prototypes for macros
extern void *mos_safe_malloc_fn(size_t size, MosSafeErrInfo info);
@@ -52,7 +63,10 @@ extern FILE *mos_safe_fopen_fn(const char *path, const char *mode, MosSafeErrInf
extern FILE *mos_safe_tmpfile_fn(MosSafeErrInfo info);
extern int mos_safe_dup_fn(int fd, MosSafeErrInfo info);
extern int mos_safe_dup2_fn(int fd, int fd2, MosSafeErrInfo info);
+
+#ifndef _WIN32
extern pid_t mos_safe_fork_fn(MosSafeErrInfo info);
extern int mos_safe_pipe_fn(int fd[2], MosSafeErrInfo info);
+#endif
#endif // MOSLIB_SAFE_H
diff --git a/src/safe.c b/src/safe.c
index fd7a1af..e72dbff 100644
--- a/src/safe.c
+++ b/src/safe.c
@@ -4,7 +4,12 @@
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
+
+#ifndef _WIN32
#include <unistd.h>
+#else
+#include <io.h>
+#endif
#define ERR_MESS(...) err_mess(info, __VA_ARGS__)
@@ -58,7 +63,11 @@ FILE *mos_safe_tmpfile_fn(MosSafeErrInfo info) {
}
int mos_safe_dup_fn(int fd, MosSafeErrInfo info) {
+#ifndef _WIN32
int res = dup(fd);
+#else
+ int res = _dup(fd);
+#endif
if (res != -1)
return res;
ERR_MESS("failed to dup %d", fd);
@@ -66,13 +75,18 @@ int mos_safe_dup_fn(int fd, MosSafeErrInfo info) {
}
int mos_safe_dup2_fn(int fd, int fd2, MosSafeErrInfo info) {
+#ifndef _WIN32
int res = dup2(fd, fd2);
+#else
+ int res = _dup2(fd, fd2);
+#endif
if (res != -1)
return res;
ERR_MESS("failed to dup %d 2 %d", fd, fd2);
exit(EXIT_FAILURE);
}
+#ifndef _WIN32
pid_t mos_safe_fork_fn(MosSafeErrInfo info) {
pid_t pid = fork();
if (pid != -1)
@@ -88,3 +102,4 @@ int mos_safe_pipe_fn(int fd[2], MosSafeErrInfo info) {
ERR_MESS("failed to pipe");
exit(EXIT_FAILURE);
}
+#endif
diff --git a/src/tester.c b/src/tester.c
index 05bc3d1..f6df372 100644
--- a/src/tester.c
+++ b/src/tester.c
@@ -8,7 +8,16 @@
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
+
+#ifndef _WIN32
#include <unistd.h>
+#define mos_close close
+#define mos_isatty isatty
+#else
+#include <io.h>
+#define mos_close _close
+#define mos_isatty _isatty
+#endif
#include "moslib/safe.h"
@@ -39,8 +48,9 @@ static Outputs suppressed = {
};
#define print_color(color, ...) \
- (isatty(STDOUT_FILENO) ? (printf("\033[%dm", color), printf(__VA_ARGS__), printf("\033[0m")) \
- : printf(__VA_ARGS__))
+ (mos_isatty(STDOUT_FILENO) \
+ ? (printf("\033[%dm", color), printf(__VA_ARGS__), printf("\033[0m")) \
+ : printf(__VA_ARGS__))
#define nl printf("\n")
static void print_center(const char *text, int color, char padding_char) {
@@ -111,6 +121,10 @@ void mos_test_assert(int expression, const char *fail_message) {
}
void mos_test_assert_exit_fn(MosTestFn function, int code, const char *name) {
+#ifdef _WIN32
+ fprintf(stderr, "test_assert_exit is not supported on windows\n");
+ exit(1);
+#else
int fd[2];
mos_safe_pipe(fd);
pid_t pid = mos_safe_fork();
@@ -145,6 +159,7 @@ void mos_test_assert_exit_fn(MosTestFn function, int code, const char *name) {
print_color(RED, "ASSERT FAILED: ");
printf("exit code was %d, expected %d (in function %s)\n", exit_code, code, name);
}
+#endif
}
void mos_test_assert_out_fn(
@@ -154,15 +169,19 @@ void mos_test_assert_out_fn(
const char *fn_name,
const char *stream_name
) {
+#ifdef NO_FS
+ fprintf(stderr, "FATAL: test_assert_out is not supported on your system\n");
+ exit(1);
+#else
size_t n = strlen(output);
char *out = mos_safe_calloc(n + 2, 1);
FILE *tmp = mos_safe_tmpfile();
- int fd = mos_fileno(stream);
+ int fd = fileno(stream);
int og = mos_safe_dup(fd);
fflush(stream);
- mos_safe_dup2(mos_fileno(tmp), fd);
+ mos_safe_dup2(fileno(tmp), fd);
function();
fflush(stream);
@@ -171,7 +190,7 @@ void mos_test_assert_out_fn(
fclose(tmp);
mos_safe_dup2(og, fd);
- close(og);
+ mos_close(og);
if (strcmp(out, output)) {
failed = 1;
@@ -181,16 +200,21 @@ void mos_test_assert_out_fn(
printf(" expected: %s\n", output);
}
free(out);
+#endif
}
void mos_suppress_output_fn(FILE *stream) {
+#ifdef NO_FS
+ fprintf(stderr, "FATAL: suppress_output is not supported on your system\n");
+ exit(1);
+#else
if (!suppressed.outs || suppressed.n_outs >= suppressed.out_cap) {
while (suppressed.n_outs >= suppressed.out_cap)
suppressed.out_cap *= 2;
suppressed.outs = mos_safe_realloc(suppressed.outs, suppressed.out_cap * sizeof(int));
suppressed.ogs = mos_safe_realloc(suppressed.ogs, suppressed.out_cap * sizeof(int));
}
- int fd = mos_fileno(stream);
+ int fd = fileno(stream);
suppressed.outs[suppressed.n_outs] = fd;
suppressed.ogs[suppressed.n_outs++] = mos_safe_dup(fd);
@@ -198,7 +222,8 @@ void mos_suppress_output_fn(FILE *stream) {
dev_null = mos_safe_tmpfile();
fflush(stream);
- mos_safe_dup2(mos_fileno(dev_null), fd);
+ mos_safe_dup2(fileno(dev_null), fd);
+#endif
}
void mos_unsuppress_outputs(void) {
@@ -210,7 +235,7 @@ void mos_unsuppress_outputs(void) {
for (size_t i = suppressed.n_outs; i-- > 0;) {
mos_safe_dup2(suppressed.ogs[i], suppressed.outs[i]);
- close(suppressed.ogs[i]);
+ mos_close(suppressed.ogs[i]);
}
suppressed.n_outs = 0;
diff --git a/tests/safe_tests.c b/tests/safe_tests.c
index 0915550..fd45603 100644
--- a/tests/safe_tests.c
+++ b/tests/safe_tests.c
@@ -4,7 +4,12 @@
#include <limits.h>
#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
+
+#ifndef _WIN32
+#define mos_close close
+#else
+#define mos_close _close
+#endif
TEST_HELPER(malloc_exit) {
safe_malloc(ULLONG_MAX);
@@ -14,7 +19,9 @@ TEST(test_safe_malloc) {
void *p = safe_malloc(1024);
test_assert(p != NULL, "Failed to malloc 1KiB");
+#ifndef NO_FS
suppress_output(stderr);
+#endif
test_assert_exit(malloc_exit, EXIT_FAILURE);
unsuppress_outputs();
}
@@ -27,7 +34,9 @@ TEST(test_safe_calloc) {
void *p = safe_calloc(16, 16);
test_assert(p != NULL, "Failed to calloc 16 items of 16 bytes");
+#ifndef NO_FS
suppress_output(stderr);
+#endif
test_assert_exit(calloc_exit, EXIT_FAILURE);
unsuppress_outputs();
}
@@ -45,7 +54,9 @@ TEST(test_safe_realloc) {
p = safe_realloc(p, 4096);
test_assert(p != NULL, "Failed to realloc 1KiB to 4KiB");
+#ifndef NO_FS
suppress_output(stderr);
+#endif
test_assert_exit(realloc_exit, EXIT_FAILURE);
unsuppress_outputs();
}
@@ -58,7 +69,9 @@ TEST(test_safe_fopen) {
FILE *fp = safe_fopen(__FILE__, "r");
test_assert(fp != NULL, "Failed to fopen current file");
+#ifndef NO_FS
suppress_output(stderr);
+#endif
test_assert_exit(fopen_exit, EXIT_FAILURE);
unsuppress_outputs();
}
@@ -75,9 +88,11 @@ TEST_HELPER(dup_exit) {
TEST(test_safe_dup) {
int fd = safe_dup(STDOUT_FILENO);
test_assert(fd != -1, "Failed to dup stdout");
- close(fd);
+ mos_close(fd);
+#ifndef NO_FS
suppress_output(stderr);
+#endif
test_assert_exit(dup_exit, EXIT_FAILURE);
unsuppress_outputs();
}
@@ -87,21 +102,24 @@ TEST_HELPER(dup2_exit) {
}
TEST(test_safe_dup2) {
- int res = dup2(STDOUT_FILENO, STDOUT_FILENO);
+ int res = safe_dup2(STDOUT_FILENO, STDOUT_FILENO);
test_assert(res != -1, "Failed to dup stdout 2 itself");
- int fd = dup(STDOUT_FILENO);
- res = dup2(STDERR_FILENO, STDOUT_FILENO);
+ int fd = safe_dup(STDOUT_FILENO);
+ res = safe_dup2(STDERR_FILENO, STDOUT_FILENO);
test_assert(res != -1, "Failed to dup stderr 2 stdout");
- res = dup2(fd, STDOUT_FILENO);
+ res = safe_dup2(fd, STDOUT_FILENO);
test_assert(res != -1, "Failed to restore stdout");
- close(fd);
+ mos_close(fd);
+#ifndef NO_FS
suppress_output(stderr);
+#endif
test_assert_exit(dup2_exit, EXIT_FAILURE);
unsuppress_outputs();
}
+#ifndef _WIN32
TEST(test_safe_fork) {
pid_t pid = safe_fork();
test_assert(pid != -1, "Failed to create a child process");
@@ -113,12 +131,10 @@ TEST(test_safe_pipe) {
int fd[2];
int res = safe_pipe(fd);
test_assert(res != -1, "Failed to create a pipe");
- close(fd[0]);
- close(fd[1]);
+ mos_close(fd[0]);
+ mos_close(fd[1]);
}
-
-#define mos_safe_fork() mos_safe_fork_fn(mos_err_info)
-#define mos_safe_pipe(fd) mos_safe_pipe_fn(fd, mos_err_info)
+#endif
void safe_tests(Tester *tester) {
TestGroup *group = add_test_group(tester, "moslib/safe.h");
@@ -129,6 +145,9 @@ void safe_tests(Tester *tester) {
add_test(group, test_safe_tmpfile);
add_test(group, test_safe_dup);
add_test(group, test_safe_dup2);
+
+#ifndef _WIN32
add_test(group, test_safe_fork);
add_test(group, test_safe_pipe);
+#endif
}
diff --git a/tests/string_tests.c b/tests/string_tests.c
index 7638f9b..41c6cd8 100644
--- a/tests/string_tests.c
+++ b/tests/string_tests.c
@@ -6,7 +6,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
#include "moslib/ds/array.h"
@@ -43,7 +42,9 @@ TEST(ss_print_helper) {
}
TEST(printing) {
+#ifndef NO_FS
test_assert_out(ss_print_helper, stdout, "test");
+#endif
StringSlice ss = ss_from_str("slice");
char buf[16];