aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2013-09-19 19:13:13 +0200
committerSverker Eriksson <[email protected]>2013-09-19 19:13:13 +0200
commit6fea2c436a6f4a501be632e9bb7453570c09fb8e (patch)
tree9f21aca3d6136647553d6fedbe4cb0fdcc737d2f
parentf7c9b020f21d57bceddc8596faa275be20625557 (diff)
downloadotp-6fea2c436a6f4a501be632e9bb7453570c09fb8e.tar.gz
otp-6fea2c436a6f4a501be632e9bb7453570c09fb8e.tar.bz2
otp-6fea2c436a6f4a501be632e9bb7453570c09fb8e.zip
erts, crypto: Support NIF library with unicode filename on windows
-rw-r--r--erts/emulator/beam/erl_nif.c12
-rw-r--r--erts/emulator/sys/win32/erl_win32_sys_ddll.c24
-rw-r--r--lib/crypto/c_src/crypto.c20
-rw-r--r--lib/crypto/src/crypto.erl14
4 files changed, 51 insertions, 19 deletions
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index 9e2e588161..e87959f0ab 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -1568,7 +1568,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
void* init_func = NULL;
ErlNifEntry* entry = NULL;
ErlNifEnv env;
- int i, err;
+ int i, err, encoding;
Module* mod;
Eterm mod_atom;
const Atom* mod_atomp;
@@ -1580,8 +1580,14 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
struct erl_module_nif* lib = NULL;
int reload_warning = 0;
- lib_name = erts_convert_filename_to_native(BIF_ARG_1, NULL, 0,
- ERTS_ALC_T_TMP, 1, 0, NULL);
+ encoding = erts_get_native_filename_encoding();
+ if (encoding == ERL_FILENAME_WIN_WCHAR) {
+ /* Do not convert the lib name to utf-16le yet, do that in win32 specific code */
+ /* since lib_name is used in error messages */
+ encoding = ERL_FILENAME_UTF8;
+ }
+ lib_name = erts_convert_filename_to_encoding(BIF_ARG_1, NULL, 0,
+ ERTS_ALC_T_TMP, 1, 0, encoding, NULL);
if (!lib_name) {
BIF_ERROR(BIF_P, BADARG);
}
diff --git a/erts/emulator/sys/win32/erl_win32_sys_ddll.c b/erts/emulator/sys/win32/erl_win32_sys_ddll.c
index 4c8d83ab16..553d3b0983 100644
--- a/erts/emulator/sys/win32/erl_win32_sys_ddll.c
+++ b/erts/emulator/sys/win32/erl_win32_sys_ddll.c
@@ -38,7 +38,7 @@
#include "erl_nif.h"
#define EXT_LEN 4
-#define FILE_EXT ".dll"
+#define FILE_EXT_WCHAR L".dll"
static DWORD tls_index = 0;
static TWinDynDriverCallbacks wddc;
@@ -57,11 +57,14 @@ void erl_sys_ddll_init(void) {
/*
* Open a shared object
+ * Expecting 'full_name' as an UTF-8 string.
*/
int erts_sys_ddll_open2(const char *full_name, void **handle, ErtsSysDdllError* err)
{
+ HINSTANCE hinstance;
int len;
char dlname[MAXPATHLEN + 1];
+ char* wcp;
if ((len = sys_strlen(full_name)) >= MAXPATHLEN - EXT_LEN) {
if (err != NULL) {
@@ -69,10 +72,23 @@ int erts_sys_ddll_open2(const char *full_name, void **handle, ErtsSysDdllError*
}
return ERL_DE_LOAD_ERROR_NAME_TO_LONG;
}
- sys_strcpy(dlname, full_name);
- sys_strcpy(dlname+len, FILE_EXT);
- return erts_sys_ddll_open_noext(dlname, handle, err);
+
+ wcp = erts_convert_filename_to_wchar(full_name, len, dlname, sizeof(dlname),
+ ERTS_ALC_T_TMP, &used, EXT_LEN);
+ wcscpy(&wcp[used], FILE_EXT_WCHAR);
+
+ if ((hinstance = LoadLibraryW(wcp)) == NULL) {
+ int code = ERL_DE_DYNAMIC_ERROR_OFFSET - GetLastError();
+ if (err != NULL) {
+ err->str = erts_sys_ddll_error(code);
+ }
+ return code;
+ }
+
+ *handle = (void *) hinstance;
+ return ERL_DE_NO_ERROR;
}
+
int erts_sys_ddll_open_noext(char *dlname, void **handle, ErtsSysDdllError* err)
{
HINSTANCE hinstance;
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index c28ff8136c..30c8c2554d 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -538,16 +538,17 @@ static ERL_NIF_TERM atom_onbasis;
#define PRINTF_ERR1(FMT,A1)
#ifdef HAVE_DYNAMIC_CRYPTO_LIB
-static int change_basename(char* buf, int bufsz, const char* newfile)
+static int change_basename(ErlNifBinary* bin, char* buf, int bufsz, const char* newfile)
{
- char* p = strrchr(buf, '/');
- p = (p == NULL) ? buf : p + 1;
+ const unsigned char* p = (unsigned char*)strrchr((char*)bin->data, '/');
+ int i = (p == NULL) ? 0 : (p+1) - bin->data;
- if ((p - buf) + strlen(newfile) >= bufsz) {
+ if (i + strlen(newfile) >= bufsz) {
PRINTF_ERR0("CRYPTO: lib name too long");
return 0;
}
- strcpy(p, newfile);
+ memcpy(buf, bin->data, i);
+ strcpy(buf+i, newfile);
return 1;
}
@@ -566,14 +567,15 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info)
int tpl_arity;
const ERL_NIF_TERM* tpl_array;
int vernum;
+ ErlNifBinary lib_bin;
char lib_buf[1000];
- /* load_info: {201, "/full/path/of/this/library"} */
+ /* load_info: {301, <<"/full/path/of/this/library">>} */
if (!enif_get_tuple(env, load_info, &tpl_arity, &tpl_array)
|| tpl_arity != 2
|| !enif_get_int(env, tpl_array[0], &vernum)
- || vernum != 201
- || enif_get_string(env, tpl_array[1], lib_buf, sizeof(lib_buf), ERL_NIF_LATIN1) <= 0) {
+ || vernum != 301
+ || !enif_inspect_binary(env, tpl_array[1], &lib_bin)) {
PRINTF_ERR1("CRYPTO: Invalid load_info '%T'", load_info);
return 0;
@@ -633,7 +635,7 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info)
#ifdef HAVE_DYNAMIC_CRYPTO_LIB
{
void* handle;
- if (!change_basename(lib_buf, sizeof(lib_buf), "crypto_callback")) {
+ if (!change_basename(&lib_bin, lib_buf, sizeof(lib_buf), "crypto_callback")) {
return 0;
}
if (!(handle = enif_dlopen(lib_buf, &error_handler, NULL))) {
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 8e8370f3b0..784fcc0119 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -183,7 +183,7 @@
%%-type ec_key() :: {Curve :: ec_curve(), PrivKey :: binary() | undefined, PubKey :: ec_point() | undefined}.
-on_load(on_load/0).
--define(CRYPTO_NIF_VSN,201).
+-define(CRYPTO_NIF_VSN,301).
-define(nif_stub,nif_stub_error(?LINE)).
nif_stub_error(Line) ->
@@ -640,7 +640,7 @@ on_load() ->
end
end,
Lib = filename:join([PrivDir, "lib", LibName]),
- Status = case erlang:load_nif(Lib, {?CRYPTO_NIF_VSN,Lib}) of
+ Status = case erlang:load_nif(Lib, {?CRYPTO_NIF_VSN,path2bin(Lib)}) of
ok -> ok;
{error, {load_failed, _}}=Error1 ->
ArchLibDir =
@@ -652,7 +652,7 @@ on_load() ->
[] -> Error1;
_ ->
ArchLib = filename:join([ArchLibDir, LibName]),
- erlang:load_nif(ArchLib, {?CRYPTO_NIF_VSN,ArchLib})
+ erlang:load_nif(ArchLib, {?CRYPTO_NIF_VSN,path2bin(ArchLib)})
end;
Error1 -> Error1
end,
@@ -663,6 +663,14 @@ on_load() ->
"OpenSSL might not be installed on this system.~n",[E,Str]),
Status
end.
+
+path2bin(Path) when is_list(Path) ->
+ Encoding = file:native_name_encoding(),
+ case unicode:characters_to_binary(Path,Encoding,Encoding) of
+ Bin when is_binary(Bin) ->
+ Bin
+ end.
+
%%--------------------------------------------------------------------
%%% Internal functions (some internal API functions are part of the deprecated API)
%%--------------------------------------------------------------------