diff options
Diffstat (limited to 'erts')
-rw-r--r-- | erts/emulator/beam/atom.names | 1 | ||||
-rw-r--r-- | erts/emulator/beam/erl_init.c | 53 | ||||
-rw-r--r-- | erts/emulator/beam/erl_unicode.c | 17 | ||||
-rw-r--r-- | erts/emulator/beam/sys.h | 14 | ||||
-rw-r--r-- | erts/emulator/sys/common/erl_sys_common_misc.c | 9 | ||||
-rw-r--r-- | erts/preloaded/ebin/erl_prim_loader.beam | bin | 54120 -> 54360 bytes | |||
-rw-r--r-- | erts/preloaded/ebin/prim_file.beam | bin | 41128 -> 42004 bytes | |||
-rw-r--r-- | erts/preloaded/src/erl_prim_loader.erl | 12 | ||||
-rw-r--r-- | erts/preloaded/src/prim_file.erl | 32 |
9 files changed, 125 insertions, 13 deletions
diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names index f138324e1f..ce60bb9bbc 100644 --- a/erts/emulator/beam/atom.names +++ b/erts/emulator/beam/atom.names @@ -269,6 +269,7 @@ atom hipe_architecture atom http httph https http_response http_request http_header http_eoh http_error http_bin httph_bin atom id atom if_clause +atom ignore atom imports atom in atom in_exiting diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c index 223c9c4d7e..ec3e0d54cb 100644 --- a/erts/emulator/beam/erl_init.c +++ b/erts/emulator/beam/erl_init.c @@ -981,19 +981,64 @@ erl_start(int argc, char **argv) break; case 'f': if (!strncmp(argv[i],"-fn",3)) { + int warning_type = ERL_FILENAME_WARNING_WARNING; arg = get_arg(argv[i]+3, argv[i+1], &i); switch (*arg) { case 'u': - erts_set_user_requested_filename_encoding(ERL_FILENAME_UTF8); + switch (*(argv[i]+4)) { + case 'w': + case 0: + break; + case 'i': + warning_type = ERL_FILENAME_WARNING_IGNORE; + break; + case 'e': + warning_type = ERL_FILENAME_WARNING_ERROR; + break; + default: + erts_fprintf(stderr, "bad type of warnings for " + "wrongly coded filename: %s\n", argv[i]+4); + erts_usage(); + } + erts_set_user_requested_filename_encoding + ( + ERL_FILENAME_UTF8, + warning_type + ); break; case 'l': - erts_set_user_requested_filename_encoding(ERL_FILENAME_LATIN1); + erts_set_user_requested_filename_encoding + ( + ERL_FILENAME_LATIN1, + warning_type + ); break; case 'a': - erts_set_user_requested_filename_encoding(ERL_FILENAME_UNKNOWN); + switch (*(argv[i]+4)) { + case 'w': + case 0: + break; + case 'i': + warning_type = ERL_FILENAME_WARNING_IGNORE; + break; + case 'e': + warning_type = ERL_FILENAME_WARNING_ERROR; + break; + default: + erts_fprintf(stderr, "bad type of warnings for " + "wrongly coded filename: %s\n", argv[i]+4); + erts_usage(); + } + erts_set_user_requested_filename_encoding + ( + ERL_FILENAME_UNKNOWN, + warning_type + ); break; default: - erts_fprintf(stderr, "bad filename encoding %s, can be (l,u or a)\n", arg); + erts_fprintf(stderr, "bad filename encoding %s, can be " + "(l,u or a, optionally followed by w, " + "i or e)\n", arg); erts_usage(); } break; diff --git a/erts/emulator/beam/erl_unicode.c b/erts/emulator/beam/erl_unicode.c index 99108af937..8d7930e5fa 100644 --- a/erts/emulator/beam/erl_unicode.c +++ b/erts/emulator/beam/erl_unicode.c @@ -2573,8 +2573,20 @@ BIF_RETTYPE prim_file_internal_native2name_1(BIF_ALIST_1) case ERL_FILENAME_UTF8: bytes = erts_get_aligned_binary_bytes(BIF_ARG_1, &temp_alloc); if (erts_analyze_utf8(bytes,size,&err_pos,&num_chars,NULL) != ERTS_UTF8_OK) { + Eterm *hp = HAlloc(BIF_P,3); + Eterm warn_type = NIL; erts_free_aligned_binary_bytes(temp_alloc); - goto noconvert; + switch (erts_get_filename_warning_type()) { + case ERL_FILENAME_WARNING_IGNORE: + warn_type = am_ignore; + break; + case ERL_FILENAME_WARNING_ERROR: + warn_type = am_error; + break; + default: + warn_type = am_warning; + } + BIF_RET(TUPLE2(hp,am_error,warn_type)); } num_built = 0; num_eaten = 0; @@ -2607,9 +2619,8 @@ BIF_RETTYPE prim_file_internal_native2name_1(BIF_ALIST_1) erts_free_aligned_binary_bytes(temp_alloc); BIF_RET(ret); default: - goto noconvert; + break; } - noconvert: BIF_RET(BIF_ARG_1); } diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h index 249a9c05c2..9416a91480 100644 --- a/erts/emulator/beam/sys.h +++ b/erts/emulator/beam/sys.h @@ -1029,10 +1029,22 @@ char* win32_errorstr(int); #define ERL_FILENAME_UTF8_MAC (3) #define ERL_FILENAME_WIN_WCHAR (4) +/************************************************************************ + * If a filename in for example list_dir is not in the right encoding, it + * will be skipped in the resulting list, but depending on a startup setting + * we will inform the user in different ways. These macros define the + * different reactions to wrongly coded filenames. In the error case an + * exception will be thrown by prim_file. + ************************************************************************/ +#define ERL_FILENAME_WARNING_WARNING (0) +#define ERL_FILENAME_WARNING_IGNORE (1) +#define ERL_FILENAME_WARNING_ERROR (2) + int erts_get_native_filename_encoding(void); /* The set function is only to be used by erl_init! */ -void erts_set_user_requested_filename_encoding(int encoding); +void erts_set_user_requested_filename_encoding(int encoding, int warning); int erts_get_user_requested_filename_encoding(void); +int erts_get_filename_warning_type(void); void erts_init_sys_common_misc(void); diff --git a/erts/emulator/sys/common/erl_sys_common_misc.c b/erts/emulator/sys/common/erl_sys_common_misc.c index 1bf5fa89f4..a0cd4cd10a 100644 --- a/erts/emulator/sys/common/erl_sys_common_misc.c +++ b/erts/emulator/sys/common/erl_sys_common_misc.c @@ -47,14 +47,16 @@ /* Written once and only once */ static int filename_encoding = ERL_FILENAME_UNKNOWN; +static int filename_warning = ERL_FILENAME_WARNING_WARNING; #if defined(__WIN32__) || defined(__DARWIN__) static int user_filename_encoding = ERL_FILENAME_UTF8; /* Default unicode on windows */ #else static int user_filename_encoding = ERL_FILENAME_LATIN1; #endif -void erts_set_user_requested_filename_encoding(int encoding) +void erts_set_user_requested_filename_encoding(int encoding, int warning) { user_filename_encoding = encoding; + filename_warning = warning; } int erts_get_user_requested_filename_encoding(void) @@ -62,6 +64,11 @@ int erts_get_user_requested_filename_encoding(void) return user_filename_encoding; } +int erts_get_filename_warning_type(void) +{ + return filename_warning; +} + void erts_init_sys_common_misc(void) { #if defined(__WIN32__) diff --git a/erts/preloaded/ebin/erl_prim_loader.beam b/erts/preloaded/ebin/erl_prim_loader.beam Binary files differindex f8c2df3a5a..4a3af265c1 100644 --- a/erts/preloaded/ebin/erl_prim_loader.beam +++ b/erts/preloaded/ebin/erl_prim_loader.beam diff --git a/erts/preloaded/ebin/prim_file.beam b/erts/preloaded/ebin/prim_file.beam Binary files differindex ca93edbe25..b1b54ca050 100644 --- a/erts/preloaded/ebin/prim_file.beam +++ b/erts/preloaded/ebin/prim_file.beam diff --git a/erts/preloaded/src/erl_prim_loader.erl b/erts/preloaded/src/erl_prim_loader.erl index c2fac8c0fc..7490954f2d 100644 --- a/erts/preloaded/src/erl_prim_loader.erl +++ b/erts/preloaded/src/erl_prim_loader.erl @@ -150,7 +150,17 @@ start_it("inet", Id, Pid, Hosts) -> start_it("efile", Id, Pid, _Hosts) -> process_flag(trap_exit, true), {ok, Port} = prim_file:start(), - init_ack(Pid), + %% Check that we started in a valid directory. + case prim_file:get_cwd(Port) of + {error, _} -> + %% At this point in the startup, we have no error_logger at all. + Report = "Invalid current directory or invalid filename " + "mode: loader cannot read current directory\n", + erlang:display(Report), + exit({error, invalid_current_directory}); + _ -> + init_ack(Pid) + end, MultiGet = case erlang:system_info(thread_pool_size) of 0 -> false; _ -> true diff --git a/erts/preloaded/src/prim_file.erl b/erts/preloaded/src/prim_file.erl index af1a6127c9..27e7640b7e 100644 --- a/erts/preloaded/src/prim_file.erl +++ b/erts/preloaded/src/prim_file.erl @@ -155,13 +155,15 @@ internal_normalize_utf8/1]). -type prim_file_name() :: string() | unicode:unicode_binary(). +-type prim_file_name_error() :: 'error' | 'ignore' | 'warning'. -spec internal_name2native(prim_file_name()) -> binary(). internal_name2native(_) -> erlang:nif_error(undefined). --spec internal_native2name(binary()) -> prim_file_name(). +-spec internal_native2name(binary()) -> + prim_file_name() | {'error',prim_file_name_error()}. internal_native2name(_) -> erlang:nif_error(undefined). @@ -924,7 +926,21 @@ list_dir_response(Port, Acc0) -> end. list_dir_convert([Name|Names]) -> - [prim_file:internal_native2name(Name)|list_dir_convert(Names)]; + %% If the filename cannot be converted, return error or ignore + %% with optional error logger warning, depending on +fn{u|a}{i|e|w} + %% emulator switches. + case prim_file:internal_native2name(Name) of + {error, warning} -> + error_logger:warning_msg("Non-unicode filename ~p ignored\n", + [Name]), + list_dir_convert(Names); + {error, ignore} -> + list_dir_convert(Names); + {error, error} -> + {error, {no_translation, Name}}; + Converted when is_list(Converted) -> + [Converted|list_dir_convert(Names)] + end; list_dir_convert([]) -> []. %%%----------------------------------------------------------------- @@ -933,7 +949,17 @@ list_dir_convert([]) -> []. handle_fname_response(Port) -> case drv_get_response(Port) of {fname, Name} -> - {ok, prim_file:internal_native2name(Name)}; + case prim_file:internal_native2name(Name) of + {error, warning} -> + error_logger:warning_msg("Non-unicode filename ~p " + "ignored when reading link\n", + [Name]), + {error, einval}; + {error, _} -> + {error, einval}; + Converted when is_list(Converted) -> + {ok, Converted} + end; Error -> Error end. |