aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/preloaded/ebin/prim_file.beambin42004 -> 44092 bytes
-rw-r--r--erts/preloaded/src/prim_file.erl57
-rw-r--r--lib/kernel/test/prim_file_SUITE.erl32
3 files changed, 85 insertions, 4 deletions
diff --git a/erts/preloaded/ebin/prim_file.beam b/erts/preloaded/ebin/prim_file.beam
index b1b54ca050..f7b3aac376 100644
--- a/erts/preloaded/ebin/prim_file.beam
+++ b/erts/preloaded/ebin/prim_file.beam
Binary files differ
diff --git a/erts/preloaded/src/prim_file.erl b/erts/preloaded/src/prim_file.erl
index 305abb8b0a..bf8879c2a0 100644
--- a/erts/preloaded/src/prim_file.erl
+++ b/erts/preloaded/src/prim_file.erl
@@ -50,9 +50,9 @@
write_file_info/2, write_file_info/3, write_file_info/4,
make_link/2, make_link/3,
make_symlink/2, make_symlink/3,
- read_link/1, read_link/2,
+ read_link/1, read_link/2, read_link_all/1, read_link_all/2,
read_link_info/1, read_link_info/2, read_link_info/3,
- list_dir/1, list_dir/2]).
+ list_dir/1, list_dir/2, list_dir_all/1, list_dir_all/2]).
%% How to start and stop the ?DRV port.
-export([start/0, stop/1]).
@@ -877,6 +877,18 @@ read_link_int(Port, Link) ->
drv_command(Port, [?FILE_READLINK, pathname(Link)],
fun handle_fname_response/1).
+%% read_link_all/{2,3}
+
+read_link_all(Link) ->
+ read_link_all_int({?DRV, [binary]}, Link).
+
+read_link_all(Port, Link) when is_port(Port) ->
+ read_link_all_int(Port, Link).
+
+read_link_all_int(Port, Link) ->
+ drv_command(Port, [?FILE_READLINK, pathname(Link)],
+ fun handle_fname_response_all/1).
+
%% read_link_info/{2,3}
@@ -927,6 +939,23 @@ list_dir_int(Port, Dir) ->
end
end).
+list_dir_all(Dir) ->
+ list_dir_all_int({?DRV, [binary]}, Dir).
+
+list_dir_all(Port, Dir) when is_port(Port) ->
+ list_dir_all_int(Port, Dir).
+
+list_dir_all_int(Port, Dir) ->
+ drv_command(Port, [?FILE_READDIR, pathname(Dir)],
+ fun(P) ->
+ case list_dir_response(P, []) of
+ {ok, RawNames} ->
+ {ok, list_dir_convert_all(RawNames)};
+ Error ->
+ Error
+ end
+ end).
+
list_dir_response(Port, Acc0) ->
case drv_get_response(Port) of
{lfname, []} ->
@@ -956,6 +985,17 @@ list_dir_convert([Name|Names]) ->
end;
list_dir_convert([]) -> [].
+list_dir_convert_all([Name|Names]) ->
+ %% If the filename cannot be converted, retain the filename as
+ %% a binary.
+ case prim_file:internal_native2name(Name) of
+ {error, _} ->
+ [Name|list_dir_convert(Names)];
+ Converted when is_list(Converted) ->
+ [Converted|list_dir_convert(Names)]
+ end;
+list_dir_convert_all([]) -> [].
+
%%%-----------------------------------------------------------------
%%% Functions to communicate with the driver
@@ -977,6 +1017,19 @@ handle_fname_response(Port) ->
Error
end.
+handle_fname_response_all(Port) ->
+ case drv_get_response(Port) of
+ {fname, Name} ->
+ case prim_file:internal_native2name(Name) of
+ {error, _} ->
+ {ok, Name};
+ Converted when is_list(Converted) ->
+ {ok, Converted}
+ end;
+ Error ->
+ Error
+ end.
+
%% Opens a driver port and converts any problems into {error, emfile}.
%% Returns {ok, Port} when successful.
diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl
index 9aa0204a16..4550cb1770 100644
--- a/lib/kernel/test/prim_file_SUITE.erl
+++ b/lib/kernel/test/prim_file_SUITE.erl
@@ -50,7 +50,8 @@
read_link_info_for_non_link/1,
symlinks_a/1, symlinks_b/1,
list_dir_limit/1,
- list_dir_error/1]).
+ list_dir_error/1,
+ list_dir/1]).
-export([advise/1]).
-export([large_write/1]).
@@ -82,7 +83,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[read_write_file, {group, dirs}, {group, files},
delete_a, delete_b, rename_a, rename_b, {group, errors},
- {group, compression}, {group, links}, list_dir_limit].
+ {group, compression}, {group, links}, list_dir_limit, list_dir].
groups() ->
[{dirs, [],
@@ -2036,6 +2037,8 @@ symlinks(Config, Handle, Suffix) ->
?line #file_info{links=1, type=symlink} = Info2,
?line {ok, Name} =
?PRIM_FILE_call(read_link, Handle, [Alias]),
+ {ok, Name} =
+ ?PRIM_FILE_call(read_link_all, Handle, [Alias]),
ok
end,
@@ -2151,6 +2154,31 @@ list_dir_error(Config) ->
ok.
%%%
+%%% Test list_dir() and list_dir_all().
+%%%
+
+list_dir(Config) ->
+ RootDir = ?config(priv_dir, Config),
+ TestDir = filename:join(RootDir, ?MODULE_STRING++"_list_dir"),
+ ?PRIM_FILE:make_dir(TestDir),
+ list_dir_1(TestDir, 42, []).
+
+list_dir_1(TestDir, 0, Sorted) ->
+ [ok = ?PRIM_FILE:delete(filename:join(TestDir, F)) ||
+ F <- Sorted],
+ ok = ?PRIM_FILE:del_dir(TestDir);
+list_dir_1(TestDir, Cnt, Sorted0) ->
+ Base = "file" ++ integer_to_list(Cnt),
+ Name = filename:join(TestDir, Base),
+ ok = ?PRIM_FILE:write_file(Name, Base),
+ Sorted = lists:merge([Base], Sorted0),
+ {ok,DirList0} = ?PRIM_FILE:list_dir(TestDir),
+ {ok,DirList1} = ?PRIM_FILE:list_dir_all(TestDir),
+ Sorted = lists:sort(DirList0),
+ Sorted = lists:sort(DirList1),
+ list_dir_1(TestDir, Cnt-1, Sorted).
+
+%%%
%%% Support for testing large files.
%%%