diff options
author | Sverker Eriksson <[email protected]> | 2013-09-19 19:13:13 +0200 |
---|---|---|
committer | Sverker Eriksson <[email protected]> | 2013-09-19 19:13:13 +0200 |
commit | 6fea2c436a6f4a501be632e9bb7453570c09fb8e (patch) | |
tree | 9f21aca3d6136647553d6fedbe4cb0fdcc737d2f | |
parent | f7c9b020f21d57bceddc8596faa275be20625557 (diff) | |
download | otp-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.c | 12 | ||||
-rw-r--r-- | erts/emulator/sys/win32/erl_win32_sys_ddll.c | 24 | ||||
-rw-r--r-- | lib/crypto/c_src/crypto.c | 20 | ||||
-rw-r--r-- | lib/crypto/src/crypto.erl | 14 |
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) %%-------------------------------------------------------------------- |