aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kernel')
-rw-r--r--lib/kernel/doc/src/heart.xml9
-rw-r--r--lib/kernel/doc/src/inet.xml4
-rw-r--r--lib/kernel/src/gen_sctp.erl4
-rw-r--r--lib/kernel/src/gen_udp.erl4
-rw-r--r--lib/kernel/src/heart.erl20
-rw-r--r--lib/kernel/src/inet.erl5
-rw-r--r--lib/kernel/src/inet_int.hrl4
-rw-r--r--lib/kernel/src/os.erl52
-rw-r--r--lib/kernel/test/file_SUITE.erl17
-rw-r--r--lib/kernel/test/file_name_SUITE.erl16
-rw-r--r--lib/kernel/test/gen_tcp_misc_SUITE.erl2
-rw-r--r--lib/kernel/test/inet_sockopt_SUITE.erl8
-rw-r--r--lib/kernel/test/interactive_shell_SUITE.erl6
-rw-r--r--lib/kernel/test/os_SUITE.erl67
-rw-r--r--lib/kernel/test/os_SUITE_data/my_echo.c28
-rw-r--r--lib/kernel/test/prim_file_SUITE.erl17
16 files changed, 197 insertions, 66 deletions
diff --git a/lib/kernel/doc/src/heart.xml b/lib/kernel/doc/src/heart.xml
index f5028a5559..3ec33d2f18 100644
--- a/lib/kernel/doc/src/heart.xml
+++ b/lib/kernel/doc/src/heart.xml
@@ -118,8 +118,13 @@
the system. The new Erlang runtime system will (if it
misbehaves) use the environment variable
<c>HEART_COMMAND</c> to reboot.</p>
- <p>Limitations: The length of the <c><anno>Cmd</anno></c> command string
- must be less than 2047 characters.</p>
+
+ <p>Limitations: The <c><anno>Cmd</anno></c> command string
+ will be sent to the heart program as a ISO-latin-1 or UTF-8
+ encoded binary depending on the file name encoding mode of the
+ emulator (see
+ <seealso marker="kernel:file#native_name_encoding/0"><c>file:native_name_encoding/0</c></seealso>).
+ The size of the encoded binary must be less than 2047 bytes.</p>
</desc>
</func>
<func>
diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml
index f99aef57b7..119d7d8df9 100644
--- a/lib/kernel/doc/src/inet.xml
+++ b/lib/kernel/doc/src/inet.xml
@@ -559,7 +559,7 @@ fe80::204:acff:fe17:bf38
<c>[Byte1,Byte2|Binary]</c>.</p>
</item>
- <tag><c>{high_msgq_watermark, Size}</c> (TCP/IP sockets)</tag>
+ <tag><c>{high_msgq_watermark, Size}</c></tag>
<item>
<p>The socket message queue will be set into a busy
state when the amount of data queued on the message
@@ -674,7 +674,7 @@ fe80::204:acff:fe17:bf38
the flushing time-out in seconds.</p>
</item>
- <tag><c>{low_msgq_watermark, Size}</c> (TCP/IP sockets)</tag>
+ <tag><c>{low_msgq_watermark, Size}</c></tag>
<item>
<p>If the socket message queue is in a busy state, the
socket message queue will be set in a not busy state when
diff --git a/lib/kernel/src/gen_sctp.erl b/lib/kernel/src/gen_sctp.erl
index 81c9fbe55f..0d005eb651 100644
--- a/lib/kernel/src/gen_sctp.erl
+++ b/lib/kernel/src/gen_sctp.erl
@@ -39,7 +39,9 @@
{active, true | false | once} |
{buffer, non_neg_integer()} |
{dontroute, boolean()} |
+ {high_msgq_watermark, pos_integer()} |
{linger, {boolean(), non_neg_integer()}} |
+ {low_msgq_watermark, pos_integer()} |
{mode, list | binary} | list | binary |
{priority, non_neg_integer()} |
{recbuf, non_neg_integer()} |
@@ -68,7 +70,9 @@
active |
buffer |
dontroute |
+ high_msgq_watermark |
linger |
+ low_msgq_watermark |
mode |
priority |
recbuf |
diff --git a/lib/kernel/src/gen_udp.erl b/lib/kernel/src/gen_udp.erl
index c5a1173575..fb5737f82e 100644
--- a/lib/kernel/src/gen_udp.erl
+++ b/lib/kernel/src/gen_udp.erl
@@ -34,6 +34,8 @@
{dontroute, boolean()} |
{drop_membership, {inet:ip_address(), inet:ip_address()}} |
{header, non_neg_integer()} |
+ {high_msgq_watermark, pos_integer()} |
+ {low_msgq_watermark, pos_integer()} |
{mode, list | binary} | list | binary |
{multicast_if, inet:ip_address()} |
{multicast_loop, boolean()} |
@@ -56,6 +58,8 @@
deliver |
dontroute |
header |
+ high_msgq_watermark |
+ low_msgq_watermark |
mode |
multicast_if |
multicast_loop |
diff --git a/lib/kernel/src/heart.erl b/lib/kernel/src/heart.erl
index aa65c3a474..daed6dd488 100644
--- a/lib/kernel/src/heart.erl
+++ b/lib/kernel/src/heart.erl
@@ -184,14 +184,18 @@ wait_ack(Port) ->
loop(Parent, Port, Cmd) ->
_ = send_heart_beat(Port),
receive
- {From, set_cmd, NewCmd} when length(NewCmd) < 2047 ->
- _ = send_heart_cmd(Port, NewCmd),
- _ = wait_ack(Port),
- From ! {heart, ok},
- loop(Parent, Port, NewCmd);
- {From, set_cmd, NewCmd} ->
- From ! {heart, {error, {bad_cmd, NewCmd}}},
- loop(Parent, Port, Cmd);
+ {From, set_cmd, NewCmd0} ->
+ Enc = file:native_name_encoding(),
+ case catch unicode:characters_to_binary(NewCmd0,Enc,Enc) of
+ NewCmd when is_binary(NewCmd), byte_size(NewCmd) < 2047 ->
+ _ = send_heart_cmd(Port, NewCmd),
+ _ = wait_ack(Port),
+ From ! {heart, ok},
+ loop(Parent, Port, NewCmd);
+ _ ->
+ From ! {heart, {error, {bad_cmd, NewCmd0}}},
+ loop(Parent, Port, Cmd)
+ end;
{From, clear_cmd} ->
From ! {heart, ok},
_ = send_heart_cmd(Port, ""),
diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl
index ad6b265b83..1a1f7b8cbc 100644
--- a/lib/kernel/src/inet.erl
+++ b/lib/kernel/src/inet.erl
@@ -712,7 +712,8 @@ udp_options() ->
[tos, priority, reuseaddr, sndbuf, recbuf, header, active, buffer, mode,
deliver, ipv6_v6only,
broadcast, dontroute, multicast_if, multicast_ttl, multicast_loop,
- add_membership, drop_membership, read_packets,raw].
+ add_membership, drop_membership, read_packets,raw,
+ high_msgq_watermark, low_msgq_watermark].
udp_options(Opts, Family) ->
@@ -766,7 +767,7 @@ udp_add(Name, Val, R, Opts, As) ->
sctp_options() ->
[ % The following are generic inet options supported for SCTP sockets:
mode, active, buffer, tos, priority, dontroute, reuseaddr, linger, sndbuf,
- recbuf, ipv6_v6only,
+ recbuf, ipv6_v6only, high_msgq_watermark, low_msgq_watermark,
% Other options are SCTP-specific (though they may be similar to their
% TCP and UDP counter-parts):
diff --git a/lib/kernel/src/inet_int.hrl b/lib/kernel/src/inet_int.hrl
index 000119bc74..a01c733d81 100644
--- a/lib/kernel/src/inet_int.hrl
+++ b/lib/kernel/src/inet_int.hrl
@@ -141,8 +141,8 @@
-define(INET_LOPT_READ_PACKETS, 33).
-define(INET_OPT_RAW, 34).
-define(INET_LOPT_TCP_SEND_TIMEOUT_CLOSE, 35).
--define(INET_LOPT_TCP_MSGQ_HIWTRMRK, 36).
--define(INET_LOPT_TCP_MSGQ_LOWTRMRK, 37).
+-define(INET_LOPT_MSGQ_HIWTRMRK, 36).
+-define(INET_LOPT_MSGQ_LOWTRMRK, 37).
% Specific SCTP options: separate range:
-define(SCTP_OPT_RTOINFO, 100).
-define(SCTP_OPT_ASSOCINFO, 101).
diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl
index 1f96e5c3c0..c92bb463c1 100644
--- a/lib/kernel/src/os.erl
+++ b/lib/kernel/src/os.erl
@@ -126,7 +126,7 @@ verify_executable(Name0, [Ext|Rest], OrigExtensions) ->
end;
verify_executable(Name, [], OrigExtensions) when OrigExtensions =/= [""] -> %% Windows
%% Will only happen on windows, hence case insensitivity
- case can_be_full_name(string:to_lower(Name),OrigExtensions) of
+ case can_be_full_name(string:to_lower(Name),OrigExtensions) of
true ->
verify_executable(Name,[""],[""]);
_ ->
@@ -150,7 +150,7 @@ split_path(Path) ->
{win32, _} ->
{ok,Curr} = file:get_cwd(),
split_path(Path, $;, [], [Curr]);
- _ ->
+ _ ->
split_path(Path, $:, [], [])
end.
@@ -183,17 +183,25 @@ extensions() ->
Command :: atom() | io_lib:chars().
cmd(Cmd) ->
validate(Cmd),
- case type() of
- {unix, _} ->
- unix_cmd(Cmd);
- {win32, Wtype} ->
- Command = case {os:getenv("COMSPEC"),Wtype} of
- {false,windows} -> lists:concat(["command.com /c", Cmd]);
- {false,_} -> lists:concat(["cmd /c", Cmd]);
- {Cspec,_} -> lists:concat([Cspec," /c",Cmd])
- end,
- Port = open_port({spawn, Command}, [stream, in, eof, hide]),
- get_data(Port, [])
+ Bytes = case type() of
+ {unix, _} ->
+ unix_cmd(Cmd);
+ {win32, Wtype} ->
+ Command0 = case {os:getenv("COMSPEC"),Wtype} of
+ {false,windows} -> lists:concat(["command.com /c", Cmd]);
+ {false,_} -> lists:concat(["cmd /c", Cmd]);
+ {Cspec,_} -> lists:concat([Cspec," /c",Cmd])
+ end,
+ %% open_port/2 awaits string() in Command, but io_lib:chars() can be
+ %% deep lists according to io_lib module description.
+ Command = lists:flatten(Command0),
+ Port = open_port({spawn, Command}, [stream, in, eof, hide]),
+ get_data(Port, [])
+ end,
+ String = unicode:characters_to_list(list_to_binary(Bytes)),
+ if %% Convert to unicode list if possible otherwise return bytes
+ is_list(String) -> String;
+ true -> Bytes
end.
unix_cmd(Cmd) ->
@@ -213,7 +221,7 @@ unix_cmd(Cmd) ->
end.
%% The -s flag implies that only the positional parameters are set,
-%% and the commands are read from standard input. We set the
+%% and the commands are read from standard input. We set the
%% $1 parameter for easy identification of the resident shell.
%%
-define(SHELL, "/bin/sh -s unix:cmd 2>&1").
@@ -226,7 +234,7 @@ unix_cmd(Cmd) ->
-spec start_port() -> port().
start_port() ->
Ref = make_ref(),
- Request = {Ref,self()},
+ Request = {Ref,self()},
{Pid, Mon} = case whereis(?PORT_CREATOR_NAME) of
undefined ->
spawn_monitor(fun() ->
@@ -273,7 +281,7 @@ start_port_srv_handle({Ref,Client}) ->
Port
catch
error:Reason ->
- {Reason,erlang:get_stacktrace()}
+ {Reason,erlang:get_stacktrace()}
end,
Client ! {Ref,Reply},
ok.
@@ -334,7 +342,7 @@ mk_cmd(Cmd) when is_atom(Cmd) -> % backward comp.
mk_cmd(Cmd) ->
%% We insert a new line after the command, in case the command
%% contains a comment character.
- io_lib:format("(~ts\n) </dev/null; echo \"\^D\"\n", [Cmd]).
+ [$(, unicode:characters_to_binary(Cmd), "\n) </dev/null; echo \"\^D\"\n"].
validate(Atom) when is_atom(Atom) ->
@@ -342,7 +350,7 @@ validate(Atom) when is_atom(Atom) ->
validate(List) when is_list(List) ->
validate1(List).
-validate1([C|Rest]) when is_integer(C), 0 =< C, C < 256 ->
+validate1([C|Rest]) when is_integer(C) ->
validate1(Rest);
validate1([List|Rest]) when is_list(List) ->
validate1(List),
@@ -355,16 +363,16 @@ get_data(Port, Sofar) ->
{Port, {data, Bytes}} ->
get_data(Port, [Sofar|Bytes]);
{Port, eof} ->
- Port ! {self(), close},
+ Port ! {self(), close},
receive
{Port, closed} ->
true
- end,
+ end,
receive
- {'EXIT', Port, _} ->
+ {'EXIT', Port, _} ->
ok
after 1 -> % force context switch
ok
- end,
+ end,
lists:flatten(Sofar)
end.
diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl
index 4218cfa646..e4c8f0ffaf 100644
--- a/lib/kernel/test/file_SUITE.erl
+++ b/lib/kernel/test/file_SUITE.erl
@@ -2651,6 +2651,8 @@ symlinks(Config) when is_list(Config) ->
?line #file_info{links=1, type=symlink} = Info2,
?line {ok, Name} = ?FILE_MODULE:read_link(Alias),
{ok, Name} = ?FILE_MODULE:read_link_all(Alias),
+ %% If all is good, delete dir again (avoid hanging dir on windows)
+ rm_rf(?FILE_MODULE,NewDir),
ok
end,
@@ -4304,3 +4306,18 @@ disc_free(Path) ->
memsize() ->
{Tot,_Used,_} = memsup:get_memory_data(),
Tot.
+
+%%%-----------------------------------------------------------------
+%%% Utilities
+rm_rf(Mod,Dir) ->
+ case Mod:read_link_info(Dir) of
+ {ok, #file_info{type = directory}} ->
+ {ok, Content} = Mod:list_dir_all(Dir),
+ [ rm_rf(Mod,filename:join(Dir,C)) || C <- Content ],
+ Mod:del_dir(Dir),
+ ok;
+ {ok, #file_info{}} ->
+ Mod:delete(Dir);
+ _ ->
+ ok
+ end.
diff --git a/lib/kernel/test/file_name_SUITE.erl b/lib/kernel/test/file_name_SUITE.erl
index 93a1678cb4..9354af2e41 100644
--- a/lib/kernel/test/file_name_SUITE.erl
+++ b/lib/kernel/test/file_name_SUITE.erl
@@ -196,7 +196,10 @@ normal(Config) when is_list(Config) ->
put(file_module,prim_file),
ok = check_normal(prim_file),
put(file_module,file),
- ok = check_normal(file)
+ ok = check_normal(file),
+ %% If all is good, delete dir again (avoid hanging dir on windows)
+ rm_rf(file,"normal_dir"),
+ ok
after
file:set_cwd(Dir)
end.
@@ -218,7 +221,10 @@ icky(Config) when is_list(Config) ->
put(file_module,prim_file),
ok = check_icky(prim_file),
put(file_module,file),
- ok = check_icky(file)
+ ok = check_icky(file),
+ %% If all is good, delete dir again (avoid hanging dir on windows)
+ rm_rf(file,"icky_dir"),
+ ok
after
file:set_cwd(Dir)
end
@@ -242,7 +248,11 @@ very_icky(Config) when is_list(Config) ->
{skipped,"VM needs to be started in Unicode filename mode"};
ok ->
put(file_module,file),
- ok = check_very_icky(file)
+ ok = check_very_icky(file),
+ %% If all is good, delete dir again
+ %% (avoid hanging dir on windows)
+ rm_rf(file,"very_icky_dir"),
+ ok
end
after
file:set_cwd(Dir)
diff --git a/lib/kernel/test/gen_tcp_misc_SUITE.erl b/lib/kernel/test/gen_tcp_misc_SUITE.erl
index 6b672004ec..2d5827282f 100644
--- a/lib/kernel/test/gen_tcp_misc_SUITE.erl
+++ b/lib/kernel/test/gen_tcp_misc_SUITE.erl
@@ -602,7 +602,7 @@ iter_max_socks(Config) when is_list(Config) ->
%% Run on a different node in order to limit the effect if this test fails.
Dir = filename:dirname(code:which(?MODULE)),
{ok,Node} = test_server:start_node(test_iter_max_socks,slave,
- [{args,"-pa " ++ Dir}]),
+ [{args,"+Q 2048 -pa " ++ Dir}]),
L = rpc:call(Node,?MODULE,do_iter_max_socks,[N, initalize]),
test_server:stop_node(Node),
diff --git a/lib/kernel/test/inet_sockopt_SUITE.erl b/lib/kernel/test/inet_sockopt_SUITE.erl
index 75496ce745..185751fead 100644
--- a/lib/kernel/test/inet_sockopt_SUITE.erl
+++ b/lib/kernel/test/inet_sockopt_SUITE.erl
@@ -772,8 +772,10 @@ all_listen_options() ->
{mode,list,binary,true,true},
{deliver,term,port,true,true},
{exit_on_close, true, false, true, true},
- %{high_watermark,4096,8192,true,true},
- %{low_watermark,2048,4096,true,true},
+ {high_watermark,4096,8192,true,true},
+ {low_watermark,2048,4096,true,true},
+ {high_msgq_watermark,4096,8192,true,true},
+ {low_msgq_watermark,2048,4096,true,true},
{send_timeout,infinity,1000,true,true},
{send_timeout_close,false,true,true,true},
{delay_send,false,true,true,true},
@@ -797,6 +799,8 @@ all_connect_options() ->
{exit_on_close, true, false, true, true},
{high_watermark,4096,8192,false,true},
{low_watermark,2048,4096,false,true},
+ {high_msgq_watermark,4096,8192,true,true},
+ {low_msgq_watermark,2048,4096,true,true},
{send_timeout,infinity,1000,true,true},
{send_timeout_close,false,true,true,true},
{delay_send,false,true,true,true},
diff --git a/lib/kernel/test/interactive_shell_SUITE.erl b/lib/kernel/test/interactive_shell_SUITE.erl
index dac021c6c6..d7d9434b1f 100644
--- a/lib/kernel/test/interactive_shell_SUITE.erl
+++ b/lib/kernel/test/interactive_shell_SUITE.erl
@@ -211,7 +211,7 @@ job_control_remote(Config) when is_list(Config) ->
{sleep,timeout(short)},
{putline,""},
{getline," -->"},
- {putline,"r "++MyNode},
+ {putline,"r '"++MyNode++"'"},
{putline,"c"},
{putline_raw,""},
{getline,"Eshell"},
@@ -265,7 +265,7 @@ job_control_remote_noshell(Config) when is_list(Config) ->
{sleep,timeout(short)},
{putline,""},
{getline," -->"},
- {putline,"r "++NSNodeStr},
+ {putline,"r '"++NSNodeStr++"'"},
{putline,"c"},
{putline_raw,""},
{getline,"Eshell"},
@@ -721,4 +721,4 @@ get_default_shell() ->
end.
atom2list(A) ->
- lists:flatten(io_lib:format("~w", [A])).
+ lists:flatten(io_lib:format("~s", [A])).
diff --git a/lib/kernel/test/os_SUITE.erl b/lib/kernel/test/os_SUITE.erl
index 382fd6f6a9..9b474c4cdf 100644
--- a/lib/kernel/test/os_SUITE.erl
+++ b/lib/kernel/test/os_SUITE.erl
@@ -18,20 +18,20 @@
%%
-module(os_SUITE).
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
--export([space_in_cwd/1, quoting/1, space_in_name/1, bad_command/1,
- find_executable/1, unix_comment_in_command/1, evil/1]).
+-export([space_in_cwd/1, quoting/1, cmd_unicode/1, space_in_name/1, bad_command/1,
+ find_executable/1, unix_comment_in_command/1, deep_list_command/1, evil/1]).
-include_lib("test_server/include/test_server.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
-all() ->
- [space_in_cwd, quoting, space_in_name, bad_command,
- find_executable, unix_comment_in_command, evil].
+all() ->
+ [space_in_cwd, quoting, cmd_unicode, space_in_name, bad_command,
+ find_executable, unix_comment_in_command, deep_list_command, evil].
-groups() ->
+groups() ->
[].
init_per_suite(Config) ->
@@ -94,6 +94,21 @@ quoting(Config) when is_list(Config) ->
?line [] = receive_all(),
ok.
+
+cmd_unicode(doc) -> "Test that unicode arguments work.";
+cmd_unicode(suite) -> [];
+cmd_unicode(Config) when is_list(Config) ->
+ ?line DataDir = ?config(data_dir, Config),
+ ?line Echo = filename:join(DataDir, "my_echo"),
+
+ ?line comp("one", os:cmd(Echo ++ " one")),
+ ?line comp("one::two", os:cmd(Echo ++ " one two")),
+ ?line comp("åäö::ϼΩ", os:cmd(Echo ++ " åäö " ++ [1020, 937])),
+ ?t:sleep(5),
+ ?line [] = receive_all(),
+ ok.
+
+
space_in_name(doc) ->
"Test that program with a space in its name can be executed.";
space_in_name(suite) -> [];
@@ -117,9 +132,9 @@ space_in_name(Config) when is_list(Config) ->
?line ok = file:change_mode(Echo, 8#777), % Make it executable on Unix.
%% Run the echo program.
- %% Quoting on windows depends on if the full path of the executable
+ %% Quoting on windows depends on if the full path of the executable
%% contains special characters. Paths when running common_tests always
- %% include @, why Windows would always fail if we do not double the
+ %% include @, why Windows would always fail if we do not double the
%% quotes (this is the behaviour of cmd.exe, not Erlang's idea).
Quote = case os:type() of
{win32,_} ->
@@ -135,7 +150,7 @@ space_in_name(Config) when is_list(Config) ->
?t:sleep(5),
?line [] = receive_all(),
ok.
-
+
bad_command(doc) ->
"Check that a bad command doesn't crasch the server or the emulator (it used to).";
bad_command(suite) -> [];
@@ -153,17 +168,17 @@ find_executable(suite) -> [];
find_executable(doc) -> [];
find_executable(Config) when is_list(Config) ->
case os:type() of
- {win32, _} ->
+ {win32, _} ->
?line DataDir = filename:join(?config(data_dir, Config), "win32"),
?line ok = file:set_cwd(filename:join([DataDir, "current"])),
?line Bin = filename:join(DataDir, "bin"),
?line Abin = filename:join(DataDir, "abin"),
?line UsrBin = filename:join([DataDir, "usr", "bin"]),
?line {ok, Current} = file:get_cwd(),
-
+
?line Path = lists:concat([Bin, ";", Abin, ";", UsrBin]),
?line io:format("Path = ~s", [Path]),
-
+
%% Search for programs in Bin (second element in PATH).
?line find_exe(Abin, "my_ar", ".exe", Path),
?line find_exe(Abin, "my_ascii", ".com", Path),
@@ -175,18 +190,18 @@ find_executable(Config) when is_list(Config) ->
?line find_exe(Abin, "my_ar.EXE", "", Path),
?line find_exe(Abin, "my_ascii.COM", "", Path),
?line find_exe(Abin, "MY_ADB.BAT", "", Path),
-
+
%% Search for programs in Abin (second element in PATH).
?line find_exe(Abin, "my_ar", ".exe", Path),
?line find_exe(Abin, "my_ascii", ".com", Path),
?line find_exe(Abin, "my_adb", ".bat", Path),
-
+
%% Search for programs in the current working directory.
?line find_exe(Current, "my_program", ".exe", Path),
?line find_exe(Current, "my_command", ".com", Path),
?line find_exe(Current, "my_batch", ".bat", Path),
ok;
- {unix, _} ->
+ {unix, _} ->
DataDir = ?config(data_dir, Config),
%% Smoke test.
@@ -237,6 +252,21 @@ unix_comment_in_command(Config) when is_list(Config) ->
?line test_server:timetrap_cancel(Dog),
ok.
+deep_list_command(doc) ->
+ "Check that a deep list in command works equally on unix and on windows.";
+deep_list_command(suite) -> [];
+deep_list_command(Config) when is_list(Config) ->
+ %% As a 'io_lib' module description says: "There is no guarantee that the
+ %% character lists returned from some of the functions are flat, they can
+ %% be deep lists."
+ %% That's why os:cmd/1 can have arguments that are deep lists.
+ %% It is not a problem for unix, but for windows it is (in R15B02 for ex.).
+ Echo = os:cmd([$e, $c, "ho"]),
+ true = erlang:is_list(Echo),
+ %% FYI: [$e, $c, "ho"] =:= io_lib:format("ec~s", ["ho"])
+ ok.
+
+
-define(EVIL_PROCS, 100).
-define(EVIL_LOOPS, 100).
-define(PORT_CREATOR, os_cmd_port_creator).
@@ -286,8 +316,8 @@ comp(Expected, Got) ->
Expected ->
ok;
Other ->
- ok = io:format("Expected: ~s\n", [Expected]),
- ok = io:format("Got: ~s\n", [Other]),
+ ok = io:format("Expected: ~ts\n", [Expected]),
+ ok = io:format("Got: ~ts\n", [Other]),
test_server:fail()
end.
@@ -303,4 +333,3 @@ receive_all() ->
X -> [X|receive_all()]
after 0 -> []
end.
-
diff --git a/lib/kernel/test/os_SUITE_data/my_echo.c b/lib/kernel/test/os_SUITE_data/my_echo.c
index 2127511dd1..712c828bb5 100644
--- a/lib/kernel/test/os_SUITE_data/my_echo.c
+++ b/lib/kernel/test/os_SUITE_data/my_echo.c
@@ -1,3 +1,30 @@
+#ifdef __WIN32__
+#include <windows.h>
+
+int wmain(int argc, wchar_t **argv)
+{
+ char* sep = "";
+ int len;
+
+ /*
+ * Echo all arguments separated with '::', so that we can check that
+ * quotes are interpreted correctly.
+ */
+
+ while (argc-- > 1) {
+ char *utf8;
+ len = WideCharToMultiByte(CP_UTF8, 0, argv[1], -1, NULL, 0, NULL, NULL);
+ utf8 = malloc(len*sizeof(char));
+ WideCharToMultiByte(CP_UTF8, 0, argv++[1], -1, utf8, len, NULL, NULL);
+ printf("%s%s", sep, utf8);
+ free(utf8);
+ sep = "::";
+ }
+ putchar('\n');
+ return 0;
+}
+#else
+
#include <stdio.h>
int
@@ -17,3 +44,4 @@ main(int argc, char** argv)
putchar('\n');
return 0;
}
+#endif
diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl
index ac75037536..199e597e78 100644
--- a/lib/kernel/test/prim_file_SUITE.erl
+++ b/lib/kernel/test/prim_file_SUITE.erl
@@ -2039,6 +2039,8 @@ symlinks(Config, Handle, Suffix) ->
?PRIM_FILE_call(read_link, Handle, [Alias]),
{ok, Name} =
?PRIM_FILE_call(read_link_all, Handle, [Alias]),
+ %% If all is good, delete dir again (avoid hanging dir on windows)
+ rm_rf(?PRIM_FILE,NewDir),
ok
end,
@@ -2245,3 +2247,18 @@ zip_data([], Bs) ->
Bs;
zip_data(As, []) ->
As.
+
+%%%-----------------------------------------------------------------
+%%% Utilities
+rm_rf(Mod,Dir) ->
+ case Mod:read_link_info(Dir) of
+ {ok, #file_info{type = directory}} ->
+ {ok, Content} = Mod:list_dir_all(Dir),
+ [ rm_rf(Mod,filename:join(Dir,C)) || C <- Content ],
+ Mod:del_dir(Dir),
+ ok;
+ {ok, #file_info{}} ->
+ Mod:delete(Dir);
+ _ ->
+ ok
+ end.