summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoão Antônio Cardoso <joao.maker@gmail.com>2020-07-28 17:26:46 -0300
committerFelipe Magno de Almeida <felipe@expertise.dev>2020-12-14 13:41:04 -0300
commitabcb324c2dedb1107f0fd0298f9a8bb41d6d76d2 (patch)
tree097108a9336f2c95e2e42373cd911f474be4388a
parent7c74fc9b5fe14ae6f9abb3efc8889a815312230e (diff)
downloadefl-abcb324c2dedb1107f0fd0298f9a8bb41d6d76d2.tar.gz
evil: Reimplement basename for windows considering possible reentrancy
Use thread local storage (TLS) to enable the usage with multiples threads
-rw-r--r--src/lib/evil/evil_libgen.c44
-rw-r--r--src/lib/evil/evil_libgen.h21
-rw-r--r--src/lib/evil/meson.build1
-rw-r--r--src/tests/evil/evil_test_libgen.c191
4 files changed, 257 insertions, 0 deletions
diff --git a/src/lib/evil/evil_libgen.c b/src/lib/evil/evil_libgen.c
new file mode 100644
index 0000000000..6ae58def47
--- /dev/null
+++ b/src/lib/evil/evil_libgen.c
@@ -0,0 +1,44 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <evil_private.h>
+
+#include <stdlib.h>
+#include <string.h> /* strlen */
+
+EVIL_API char *
+evil_basename(char *path)
+{
+ // Expected from posix
+ if ((path == NULL) || (*path == '\0') ) return ".";
+
+ // Remove trailing '\\'
+ unsigned int len = strlen(path);
+ if ((len > 1) && ((path[len -1] == '/') || (path[len -1] == '\\')))
+ path[len -1] = '\0';
+
+ // Search for the last slash
+ while(--len)
+ if ((path[len] == '/') || (path[len] == '\\'))
+ break;
+
+ if(!len) return path;
+ else return &path[len +1];
+}
+
+EVIL_API char *
+evil_dirname(char *path)
+{
+ // Expected from posix
+ if ((path == NULL) || (*path == '\0') ) return ".";
+
+ // Search for the last slash ignoring trailing '\\'
+ unsigned int len = strlen(path);
+ while(--len)
+ if ((path[len] == '/') || (path[len] == '\\'))
+ break;
+ path[len] = '\0';
+
+ return path;
+}
diff --git a/src/lib/evil/evil_libgen.h b/src/lib/evil/evil_libgen.h
new file mode 100644
index 0000000000..0c0928da7e
--- /dev/null
+++ b/src/lib/evil/evil_libgen.h
@@ -0,0 +1,21 @@
+#ifndef __EVIL_LIBGEN_H__
+#define __EVIL_LIBGEN_H__
+
+#include <evil_private.h>
+
+#ifndef HAVE_BASENAME
+# define HAVE_BASENAME
+# define basename evil_basename
+#endif
+
+#ifndef HAVE_DIRNAME
+# define HAVE_DIRNAME
+# define dirname evil_dirname
+#endif
+
+EVIL_API char* evil_basename (char* path);
+
+EVIL_API char* evil_dirname (char* path);
+
+#endif
+
diff --git a/src/lib/evil/meson.build b/src/lib/evil/meson.build
index dc86e6af0b..3a2c0d5dd4 100644
--- a/src/lib/evil/meson.build
+++ b/src/lib/evil/meson.build
@@ -18,6 +18,7 @@ if target_machine.system() == 'windows'
'evil_unistd.c',
'evil_util.c',
'evil_private.h',
+ 'evil_libgen.c',
])
psapi = cc.find_library('psapi')
diff --git a/src/tests/evil/evil_test_libgen.c b/src/tests/evil/evil_test_libgen.c
new file mode 100644
index 0000000000..80ba19512a
--- /dev/null
+++ b/src/tests/evil/evil_test_libgen.c
@@ -0,0 +1,191 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <evil_private.h>
+
+#include "evil_suite.h"
+
+EFL_START_TEST(evil_libgen_basename_simple)
+{
+ char path[] = "/bin/foo/bar.h";
+ char expected[] = "bar.h";
+ char *res = evil_basename(path);
+
+ fail_if(strcmp(res, expected) != 0);
+}
+EFL_END_TEST
+
+EFL_START_TEST(evil_libgen_basename_short)
+{
+ char path[] = "a";
+ char expected[] = "a";
+ char *res = evil_basename(path);
+
+ fail_if(strcmp(res, expected) != 0);
+}
+EFL_END_TEST
+
+EFL_START_TEST(evil_libgen_basename_root)
+{
+ char path[] = "/";
+ char expected[] = "/";
+ char *res = evil_basename(path);
+
+ fail_if(strcmp(res, expected) != 0);
+}
+EFL_END_TEST
+
+EFL_START_TEST(evil_libgen_basename_trailing)
+{
+ char path[] = "/bin/foo/";
+ char expected[] = "foo";
+
+ char *res = evil_basename(path);
+
+ fail_if(strcmp(res, expected) != 0);
+}
+EFL_END_TEST
+
+EFL_START_TEST(evil_libgen_basename_empty)
+{
+ char path[] = "";
+ char expected[] = ".";
+ char *res = evil_basename(path);
+
+ fail_if(strcmp(res, expected) != 0);
+}
+EFL_END_TEST
+
+EFL_START_TEST(evil_libgen_basename_null)
+{
+ char expected[] = ".";
+ char *res = evil_basename(NULL);
+
+ fail_if(strcmp(res, expected) != 0);
+}
+EFL_END_TEST
+
+EFL_START_TEST(evil_libgen_basename_filename)
+{
+ char path[] = "bar.h";
+ char expected[] = "bar.h";
+ char *res = evil_basename(path);
+
+ fail_if(strcmp(res, expected) != 0);
+}
+EFL_END_TEST
+
+EFL_START_TEST(evil_libgen_basename_windows)
+{
+ char path[] = "C:\\foo\\bar.h";
+ char expected[] = "bar.h";
+ char *res = evil_basename(path);
+
+ fail_if(strcmp(res, expected) != 0);
+}
+EFL_END_TEST
+
+EFL_START_TEST(evil_libgen_dirname_simple)
+{
+ char path[] = "/bin/foo/bar.h";
+ char expected[] = "/bin/foo";
+ char *res = evil_dirname(path);
+
+ fail_if(strcmp(res, expected) != 0);
+}
+EFL_END_TEST
+
+EFL_START_TEST(evil_libgen_dirname_short)
+{
+ char path[] = "a";
+ char expected[] = "";
+ char *res = evil_dirname(path);
+
+ fail_if(strcmp(res, expected) != 0);
+}
+EFL_END_TEST
+
+EFL_START_TEST(evil_libgen_dirname_root)
+{
+ char path[] = "/";
+ char expected[] = "";
+ char *res = evil_dirname(path);
+
+ fail_if(strcmp(res, expected) != 0);
+}
+EFL_END_TEST
+
+EFL_START_TEST(evil_libgen_dirname_trailing)
+{
+ char path[] = "/bin/foo/";
+ char expected[] = "/bin/foo";
+
+ char *res = evil_dirname(path);
+
+ fail_if(strcmp(res, expected) != 0);
+}
+EFL_END_TEST
+
+EFL_START_TEST(evil_libgen_dirname_empty)
+{
+ char path[] = "";
+ char expected[] = ".";
+ char *res = evil_dirname(path);
+
+ fail_if(strcmp(res, expected) != 0);
+}
+EFL_END_TEST
+
+EFL_START_TEST(evil_libgen_dirname_null)
+{
+ char expected[] = ".";
+ char *res = evil_dirname(NULL);
+
+ fail_if(strcmp(res, expected) != 0);
+}
+EFL_END_TEST
+
+EFL_START_TEST(evil_libgen_dirname_filename)
+{
+ char path[] = "bar.h";
+ char expected[] = "";
+ char *res = evil_dirname(path);
+
+ fail_if(strcmp(res, expected) != 0);
+}
+EFL_END_TEST
+
+EFL_START_TEST(evil_libgen_dirname_windows)
+{
+ char path[] = "C:\\foo\\bar.h";
+ char expected[] = "C:\\foo";
+ char *res = evil_dirname(path);
+
+ fail_if(strcmp(res, expected) != 0);
+}
+EFL_END_TEST
+
+void evil_test_libgen(TCase *tc)
+{
+ tcase_add_test(tc, evil_libgen_basename_simple);
+ tcase_add_test(tc, evil_libgen_basename_short);
+ tcase_add_test(tc, evil_libgen_basename_root);
+ tcase_add_test(tc, evil_libgen_basename_trailing);
+ tcase_add_test(tc, evil_libgen_basename_empty);
+ tcase_add_test(tc, evil_libgen_basename_null);
+ tcase_add_test(tc, evil_libgen_basename_filename);
+ tcase_add_test(tc, evil_libgen_basename_windows);
+
+ tcase_add_test(tc, evil_libgen_dirname_simple);
+ tcase_add_test(tc, evil_libgen_dirname_short);
+ tcase_add_test(tc, evil_libgen_dirname_root);
+ tcase_add_test(tc, evil_libgen_dirname_trailing);
+ tcase_add_test(tc, evil_libgen_dirname_empty);
+ tcase_add_test(tc, evil_libgen_dirname_null);
+ tcase_add_test(tc, evil_libgen_dirname_filename);
+ tcase_add_test(tc, evil_libgen_dirname_windows);
+}