evil: Reimplement basename for windows considering possible reentrancy

Use thread local storage (TLS) to enable the usage with multiples threads
This commit is contained in:
João Antônio Cardoso 2020-07-28 17:26:46 -03:00 committed by Felipe Magno de Almeida
parent 7c74fc9b5f
commit abcb324c2d
4 changed files with 257 additions and 0 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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')

View File

@ -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);
}