aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kernel')
-rw-r--r--lib/kernel/doc/src/file.xml87
-rw-r--r--lib/kernel/src/auth.erl2
-rw-r--r--lib/kernel/src/file.erl137
-rw-r--r--lib/kernel/src/file_server.erl2
-rw-r--r--lib/kernel/src/gen_tcp.erl2
-rw-r--r--lib/kernel/src/hipe_unified_loader.erl25
-rw-r--r--lib/kernel/test/code_SUITE.erl8
-rw-r--r--lib/kernel/test/file_SUITE.erl157
-rw-r--r--lib/kernel/test/file_name_SUITE.erl46
9 files changed, 334 insertions, 132 deletions
diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml
index 069b13eacf..66ecba1bf2 100644
--- a/lib/kernel/doc/src/file.xml
+++ b/lib/kernel/doc/src/file.xml
@@ -60,14 +60,6 @@
converted, why the Unicode mode for file names is not default on
systems having completely transparent file naming.</p>
- <note>
- <p>As of R14B01, the most basic file handling modules
- (<c>file</c>, <c>prim_file</c>, <c>filelib</c> and
- <c>filename</c>) accept raw file names, but the rest of OTP is not
- guaranteed to handle them, why Unicode file naming on systems
- where it is not default is still considered experimental.</p>
- </note>
-
<p>Raw file names is a new feature in OTP R14B01, which allows the
user to supply completely uninterpreted file names to the
underlying OS/filesystem. They are supplied as binaries, where it
@@ -125,6 +117,14 @@
<desc>
<p>If VM is in Unicode filename mode, <c>string()</c> and <c>char()</c>
are allowed to be > 255.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="name_all"/>
+ <desc>
+ <p>If VM is in Unicode filename mode, <c>string()</c> and <c>char()</c>
+ are allowed to be > 255.
<c><anno>RawFilename</anno></c> is a filename not subject to
Unicode translation,
meaning that it can contain characters not conforming to
@@ -504,7 +504,8 @@
<name name="list_dir" arity="1"/>
<fsummary>List files in a directory</fsummary>
<desc>
- <p>Lists all the files in a directory. Returns
+ <p>Lists all files in a directory, <b>except</b> files
+ with "raw" names. Returns
<c>{ok, <anno>Filenames</anno>}</c> if successful.
Otherwise, it returns <c>{error, <anno>Reason</anno>}</c>.
<c><anno>Filenames</anno></c> is a list of
@@ -521,6 +522,37 @@
<item>
<p>The directory does not exist.</p>
</item>
+ <tag><c>{no_translation, <anno>Filename</anno>}</c></tag>
+ <item>
+ <p><c><anno>Filename</anno></c> is a <c>binary()</c> with
+ characters coded in ISO-latin-1 and the VM was started
+ with the parameter <c>+fnue</c>.</p>
+ </item>
+ </taglist>
+ </desc>
+ </func>
+ <func>
+ <name name="list_dir_all" arity="1"/>
+ <fsummary>List all files in a directory</fsummary>
+ <desc>
+ <p>Lists all the files in a directory, including files with
+ "raw" names.
+ Returns <c>{ok, <anno>Filenames</anno>}</c> if successful.
+ Otherwise, it returns <c>{error, <anno>Reason</anno>}</c>.
+ <c><anno>Filenames</anno></c> is a list of
+ the names of all the files in the directory. The names are
+ not sorted.</p>
+ <p>Typical error reasons are:</p>
+ <taglist>
+ <tag><c>eacces</c></tag>
+ <item>
+ <p>Missing search or write permissions for <c><anno>Dir</anno></c>
+ or one of its parent directories.</p>
+ </item>
+ <tag><c>enoent</c></tag>
+ <item>
+ <p>The directory does not exist.</p>
+ </item>
</taglist>
</desc>
</func>
@@ -1409,10 +1441,41 @@
<fsummary>See what a link is pointing to</fsummary>
<desc>
<p>This function returns <c>{ok, <anno>Filename</anno>}</c> if
+ <c><anno>Name</anno></c> refers to a symbolic link that is
+ not a "raw" file name, or <c>{error, <anno>Reason</anno>}</c>
+ otherwise.
+ On platforms that do not support symbolic links, the return
+ value will be <c>{error,enotsup}</c>.</p>
+ <p>Typical error reasons:</p>
+ <taglist>
+ <tag><c>einval</c></tag>
+ <item>
+ <p><c><anno>Name</anno></c> does not refer to a symbolic link
+ or the name of the file that it refers to does not conform
+ to the expected encoding.</p>
+ </item>
+ <tag><c>enoent</c></tag>
+ <item>
+ <p>The file does not exist.</p>
+ </item>
+ <tag><c>enotsup</c></tag>
+ <item>
+ <p>Symbolic links are not supported on this platform.</p>
+ </item>
+ </taglist>
+ </desc>
+ </func>
+ <func>
+ <name name="read_link_all" arity="1"/>
+ <fsummary>See what a link is pointing to</fsummary>
+ <desc>
+ <p>This function returns <c>{ok, <anno>Filename</anno>}</c> if
<c><anno>Name</anno></c> refers to a symbolic link or
<c>{error, <anno>Reason</anno>}</c> otherwise.
On platforms that do not support symbolic links, the return
value will be <c>{error,enotsup}</c>.</p>
+ <p>Note that <c><anno>Filename</anno></c> can be either a list
+ or a binary.</p>
<p>Typical error reasons:</p>
<taglist>
<tag><c>einval</c></tag>
@@ -1580,6 +1643,12 @@
<p><c><anno>Dir</anno></c> had an improper type,
such as tuple.</p>
</item>
+ <tag><c>no_translation</c></tag>
+ <item>
+ <p><c><anno>Dir</anno></c> is a <c>binary()</c> with
+ characters coded in ISO-latin-1 and the VM was started
+ with the parameter <c>+fnue</c>.</p>
+ </item>
</taglist>
<warning>
<p>In a future release, a bad type for the
diff --git a/lib/kernel/src/auth.erl b/lib/kernel/src/auth.erl
index 1e12a647d7..7d463103e3 100644
--- a/lib/kernel/src/auth.erl
+++ b/lib/kernel/src/auth.erl
@@ -391,7 +391,7 @@ create_cookie(Name) ->
{error,Reason} ->
{error,
lists:flatten(
- io_lib:format("Failed to create cookie file '~s': ~p", [Name, Reason]))}
+ io_lib:format("Failed to create cookie file '~ts': ~p", [Name, Reason]))}
end.
random_cookie(0, _, Result) ->
diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl
index 5f52f94270..a4c56b346f 100644
--- a/lib/kernel/src/file.erl
+++ b/lib/kernel/src/file.erl
@@ -68,7 +68,7 @@
%% Types that can be used from other modules -- alphabetically ordered.
-export_type([date_time/0, fd/0, file_info/0, filename/0, filename_all/0,
- io_device/0, name/0, posix/0]).
+ io_device/0, name/0, name_all/0, posix/0]).
%%% Includes and defines
-include("file.hrl").
@@ -97,7 +97,8 @@
| 'read_ahead' | 'compressed'
| {'encoding', unicode:encoding()}.
-type deep_list() :: [char() | atom() | deep_list()].
--type name() :: string() | atom() | deep_list() | (RawFilename :: binary()).
+-type name() :: string() | atom() | deep_list().
+-type name_all() :: string() | atom() | deep_list() | (RawFilename :: binary()).
-type posix() :: 'eacces' | 'eagain' | 'ebadf' | 'ebusy' | 'edquot'
| 'eexist' | 'efault' | 'efbig' | 'eintr' | 'einval'
| 'eio' | 'eisdir' | 'eloop' | 'emfile' | 'emlink'
@@ -117,7 +118,7 @@
-export([file_info/1, native_name_encoding/0]).
-spec file_info(Filename) -> {ok, FileInfo} | {error, Reason} when
- Filename :: name(),
+ Filename :: name_all(),
FileInfo :: file_info(),
Reason :: posix() | badarg.
@@ -160,7 +161,7 @@ format_error(ErrorId) ->
erl_posix_msg:message(ErrorId).
-spec pid2name(Pid) -> {ok, Filename} | undefined when
- Filename :: filename(),
+ Filename :: filename_all(),
Pid :: pid().
pid2name(Pid) when is_pid(Pid) ->
@@ -197,42 +198,42 @@ get_cwd(Drive) ->
-spec set_cwd(Dir) -> ok | {error, Reason} when
Dir :: name(),
- Reason :: posix() | badarg.
+ Reason :: posix() | badarg | no_translation.
set_cwd(Dirname) ->
check_and_call(set_cwd, [file_name(Dirname)]).
-spec delete(Filename) -> ok | {error, Reason} when
- Filename :: name(),
+ Filename :: name_all(),
Reason :: posix() | badarg.
delete(Name) ->
check_and_call(delete, [file_name(Name)]).
-spec rename(Source, Destination) -> ok | {error, Reason} when
- Source :: name(),
- Destination :: name(),
+ Source :: name_all(),
+ Destination :: name_all(),
Reason :: posix() | badarg.
rename(From, To) ->
check_and_call(rename, [file_name(From), file_name(To)]).
-spec make_dir(Dir) -> ok | {error, Reason} when
- Dir :: name(),
+ Dir :: name_all(),
Reason :: posix() | badarg.
make_dir(Name) ->
check_and_call(make_dir, [file_name(Name)]).
-spec del_dir(Dir) -> ok | {error, Reason} when
- Dir :: name(),
+ Dir :: name_all(),
Reason :: posix() | badarg.
del_dir(Name) ->
check_and_call(del_dir, [file_name(Name)]).
-spec read_file_info(Filename) -> {ok, FileInfo} | {error, Reason} when
- Filename :: name(),
+ Filename :: name_all(),
FileInfo :: file_info(),
Reason :: posix() | badarg.
@@ -240,7 +241,7 @@ read_file_info(Name) ->
check_and_call(read_file_info, [file_name(Name)]).
-spec read_file_info(Filename, Opts) -> {ok, FileInfo} | {error, Reason} when
- Filename :: name(),
+ Filename :: name_all(),
Opts :: [file_info_option()],
FileInfo :: file_info(),
Reason :: posix() | badarg.
@@ -248,13 +249,13 @@ read_file_info(Name) ->
read_file_info(Name, Opts) when is_list(Opts) ->
check_and_call(read_file_info, [file_name(Name), Opts]).
--spec altname(Name :: name()) -> any().
+-spec altname(Name :: name_all()) -> any().
altname(Name) ->
check_and_call(altname, [file_name(Name)]).
-spec read_link_info(Name) -> {ok, FileInfo} | {error, Reason} when
- Name :: name(),
+ Name :: name_all(),
FileInfo :: file_info(),
Reason :: posix() | badarg.
@@ -262,7 +263,7 @@ read_link_info(Name) ->
check_and_call(read_link_info, [file_name(Name)]).
-spec read_link_info(Name, Opts) -> {ok, FileInfo} | {error, Reason} when
- Name :: name(),
+ Name :: name_all(),
Opts :: [file_info_option()],
FileInfo :: file_info(),
Reason :: posix() | badarg.
@@ -272,7 +273,7 @@ read_link_info(Name, Opts) when is_list(Opts) ->
-spec read_link(Name) -> {ok, Filename} | {error, Reason} when
- Name :: name(),
+ Name :: name_all(),
Filename :: filename(),
Reason :: posix() | badarg.
@@ -280,7 +281,7 @@ read_link(Name) ->
check_and_call(read_link, [file_name(Name)]).
-spec read_link_all(Name) -> {ok, Filename} | {error, Reason} when
- Name :: name(),
+ Name :: name_all(),
Filename :: filename_all(),
Reason :: posix() | badarg.
@@ -288,7 +289,7 @@ read_link_all(Name) ->
check_and_call(read_link_all, [file_name(Name)]).
-spec write_file_info(Filename, FileInfo) -> ok | {error, Reason} when
- Filename :: name(),
+ Filename :: name_all(),
FileInfo :: file_info(),
Reason :: posix() | badarg.
@@ -296,7 +297,7 @@ write_file_info(Name, Info = #file_info{}) ->
check_and_call(write_file_info, [file_name(Name), Info]).
-spec write_file_info(Filename, FileInfo, Opts) -> ok | {error, Reason} when
- Filename :: name(),
+ Filename :: name_all(),
Opts :: [file_info_option()],
FileInfo :: file_info(),
Reason :: posix() | badarg.
@@ -305,15 +306,17 @@ write_file_info(Name, Info = #file_info{}, Opts) when is_list(Opts) ->
check_and_call(write_file_info, [file_name(Name), Info, Opts]).
-spec list_dir(Dir) -> {ok, Filenames} | {error, Reason} when
- Dir :: name(),
+ Dir :: name_all(),
Filenames :: [filename()],
- Reason :: posix() | badarg.
+ Reason :: posix()
+ | badarg
+ | {no_translation, Filename :: unicode:latin1_binary()}.
list_dir(Name) ->
check_and_call(list_dir, [file_name(Name)]).
-spec list_dir_all(Dir) -> {ok, Filenames} | {error, Reason} when
- Dir :: name(),
+ Dir :: name_all(),
Filenames :: [filename_all()],
Reason :: posix() | badarg.
@@ -321,7 +324,7 @@ list_dir_all(Name) ->
check_and_call(list_dir_all, [file_name(Name)]).
-spec read_file(Filename) -> {ok, Binary} | {error, Reason} when
- Filename :: name(),
+ Filename :: name_all(),
Binary :: binary(),
Reason :: posix() | badarg | terminated | system_limit.
@@ -329,23 +332,23 @@ read_file(Name) ->
check_and_call(read_file, [file_name(Name)]).
-spec make_link(Existing, New) -> ok | {error, Reason} when
- Existing :: name(),
- New :: name(),
+ Existing :: name_all(),
+ New :: name_all(),
Reason :: posix() | badarg.
make_link(Old, New) ->
check_and_call(make_link, [file_name(Old), file_name(New)]).
-spec make_symlink(Existing, New) -> ok | {error, Reason} when
- Existing :: name(),
- New :: name(),
+ Existing :: name_all(),
+ New :: name_all(),
Reason :: posix() | badarg.
make_symlink(Old, New) ->
check_and_call(make_symlink, [file_name(Old), file_name(New)]).
-spec write_file(Filename, Bytes) -> ok | {error, Reason} when
- Filename :: name(),
+ Filename :: name_all(),
Bytes :: iodata(),
Reason :: posix() | badarg | terminated | system_limit.
@@ -357,7 +360,7 @@ write_file(Name, Bin) ->
%% Meanwhile, it is implemented here, slightly less efficient.
-spec write_file(Filename, Bytes, Modes) -> ok | {error, Reason} when
- Filename :: name(),
+ Filename :: name_all(),
Bytes :: iodata(),
Modes :: [mode()],
Reason :: posix() | badarg | terminated | system_limit.
@@ -416,7 +419,7 @@ raw_write_file_info(Name, #file_info{} = Info) ->
-spec open(File, Modes) -> {ok, IoDevice} | {error, Reason} when
File :: Filename | iodata(),
- Filename :: name(),
+ Filename :: name_all(),
Modes :: [mode() | ram],
IoDevice :: io_device(),
Reason :: posix() | badarg | system_limit.
@@ -523,7 +526,10 @@ allocate(#file_descriptor{module = Module} = Handle, Offset, Length) ->
IoDevice :: io_device() | atom(),
Number :: non_neg_integer(),
Data :: string() | binary(),
- Reason :: posix() | badarg | terminated.
+ Reason :: posix()
+ | badarg
+ | terminated
+ | {no_translation, unicode, latin1}.
read(File, Sz) when (is_pid(File) orelse is_atom(File)), is_integer(Sz), Sz >= 0 ->
case io:request(File, {get_chars, '', Sz}) of
@@ -541,7 +547,10 @@ read(_, _) ->
-spec read_line(IoDevice) -> {ok, Data} | eof | {error, Reason} when
IoDevice :: io_device() | atom(),
Data :: string() | binary(),
- Reason :: posix() | badarg | terminated.
+ Reason :: posix()
+ | badarg
+ | terminated
+ | {no_translation, unicode, latin1}.
read_line(File) when (is_pid(File) orelse is_atom(File)) ->
case io:request(File, {get_line, ''}) of
@@ -709,7 +718,7 @@ truncate(_) ->
-spec copy(Source, Destination) -> {ok, BytesCopied} | {error, Reason} when
Source :: io_device() | Filename | {Filename, Modes},
Destination :: io_device() | Filename | {Filename, Modes},
- Filename :: name(),
+ Filename :: name_all(),
Modes :: [mode()],
BytesCopied :: non_neg_integer(),
Reason :: posix() | badarg | terminated.
@@ -721,7 +730,7 @@ copy(Source, Dest) ->
{ok, BytesCopied} | {error, Reason} when
Source :: io_device() | Filename | {Filename, Modes},
Destination :: io_device() | Filename | {Filename, Modes},
- Filename :: name(),
+ Filename :: name_all(),
Modes :: [mode()],
ByteCount :: non_neg_integer() | infinity,
BytesCopied :: non_neg_integer(),
@@ -948,7 +957,7 @@ ipread_s32bu_p32bu_2(File,
%%% provide a higher-lever interface to files.
-spec consult(Filename) -> {ok, Terms} | {error, Reason} when
- Filename :: name(),
+ Filename :: name_all(),
Terms :: [term()],
Reason :: posix() | badarg | terminated | system_limit
| {Line :: integer(), Mod :: module(), Term :: term()}.
@@ -965,10 +974,10 @@ consult(File) ->
-spec path_consult(Path, Filename) -> {ok, Terms, FullName} | {error, Reason} when
Path :: [Dir],
- Dir :: name(),
- Filename :: name(),
+ Dir :: name_all(),
+ Filename :: name_all(),
Terms :: [term()],
- FullName :: filename(),
+ FullName :: filename_all(),
Reason :: posix() | badarg | terminated | system_limit
| {Line :: integer(), Mod :: module(), Term :: term()}.
@@ -988,7 +997,7 @@ path_consult(Path, File) ->
end.
-spec eval(Filename) -> ok | {error, Reason} when
- Filename :: name(),
+ Filename :: name_all(),
Reason :: posix() | badarg | terminated | system_limit
| {Line :: integer(), Mod :: module(), Term :: term()}.
@@ -996,7 +1005,7 @@ eval(File) ->
eval(File, erl_eval:new_bindings()).
-spec eval(Filename, Bindings) -> ok | {error, Reason} when
- Filename :: name(),
+ Filename :: name_all(),
Bindings :: erl_eval:binding_struct(),
Reason :: posix() | badarg | terminated | system_limit
| {Line :: integer(), Mod :: module(), Term :: term()}.
@@ -1012,9 +1021,9 @@ eval(File, Bs) ->
end.
-spec path_eval(Path, Filename) -> {ok, FullName} | {error, Reason} when
- Path :: [Dir :: name()],
- Filename :: name(),
- FullName :: filename(),
+ Path :: [Dir :: name_all()],
+ Filename :: name_all(),
+ FullName :: filename_all(),
Reason :: posix() | badarg | terminated | system_limit
| {Line :: integer(), Mod :: module(), Term :: term()}.
@@ -1023,10 +1032,10 @@ path_eval(Path, File) ->
-spec path_eval(Path, Filename, Bindings) ->
{ok, FullName} | {error, Reason} when
- Path :: [Dir :: name()],
- Filename :: name(),
+ Path :: [Dir :: name_all()],
+ Filename :: name_all(),
Bindings :: erl_eval:binding_struct(),
- FullName :: filename(),
+ FullName :: filename_all(),
Reason :: posix() | badarg | terminated | system_limit
| {Line :: integer(), Mod :: module(), Term :: term()}.
@@ -1046,7 +1055,7 @@ path_eval(Path, File, Bs) ->
end.
-spec script(Filename) -> {ok, Value} | {error, Reason} when
- Filename :: name(),
+ Filename :: name_all(),
Value :: term(),
Reason :: posix() | badarg | terminated | system_limit
| {Line :: integer(), Mod :: module(), Term :: term()}.
@@ -1055,7 +1064,7 @@ script(File) ->
script(File, erl_eval:new_bindings()).
-spec script(Filename, Bindings) -> {ok, Value} | {error, Reason} when
- Filename :: name(),
+ Filename :: name_all(),
Bindings :: erl_eval:binding_struct(),
Value :: term(),
Reason :: posix() | badarg | terminated | system_limit
@@ -1073,10 +1082,10 @@ script(File, Bs) ->
-spec path_script(Path, Filename) ->
{ok, Value, FullName} | {error, Reason} when
- Path :: [Dir :: name()],
- Filename :: name(),
+ Path :: [Dir :: name_all()],
+ Filename :: name_all(),
Value :: term(),
- FullName :: filename(),
+ FullName :: filename_all(),
Reason :: posix() | badarg | terminated | system_limit
| {Line :: integer(), Mod :: module(), Term :: term()}.
@@ -1085,11 +1094,11 @@ path_script(Path, File) ->
-spec path_script(Path, Filename, Bindings) ->
{ok, Value, FullName} | {error, Reason} when
- Path :: [Dir :: name()],
- Filename :: name(),
+ Path :: [Dir :: name_all()],
+ Filename :: name_all(),
Bindings :: erl_eval:binding_struct(),
Value :: term(),
- FullName :: filename(),
+ FullName :: filename_all(),
Reason :: posix() | badarg | terminated | system_limit
| {Line :: integer(), Mod :: module(), Term :: term()}.
@@ -1118,11 +1127,11 @@ path_script(Path, File, Bs) ->
-spec path_open(Path, Filename, Modes) ->
{ok, IoDevice, FullName} | {error, Reason} when
- Path :: [Dir :: name()],
- Filename :: name(),
+ Path :: [Dir :: name_all()],
+ Filename :: name_all(),
Modes :: [mode()],
IoDevice :: io_device(),
- FullName :: filename(),
+ FullName :: filename_all(),
Reason :: posix() | badarg | system_limit.
path_open(PathList, Name, Mode) ->
@@ -1144,7 +1153,7 @@ path_open(PathList, Name, Mode) ->
end.
-spec change_mode(Filename, Mode) -> ok | {error, Reason} when
- Filename :: name(),
+ Filename :: name_all(),
Mode :: integer(),
Reason :: posix() | badarg.
@@ -1153,7 +1162,7 @@ change_mode(Name, Mode)
write_file_info(Name, #file_info{mode=Mode}).
-spec change_owner(Filename, Uid) -> ok | {error, Reason} when
- Filename :: name(),
+ Filename :: name_all(),
Uid :: integer(),
Reason :: posix() | badarg.
@@ -1162,7 +1171,7 @@ change_owner(Name, OwnerId)
write_file_info(Name, #file_info{uid=OwnerId}).
-spec change_owner(Filename, Uid, Gid) -> ok | {error, Reason} when
- Filename :: name(),
+ Filename :: name_all(),
Uid :: integer(),
Gid :: integer(),
Reason :: posix() | badarg.
@@ -1172,7 +1181,7 @@ change_owner(Name, OwnerId, GroupId)
write_file_info(Name, #file_info{uid=OwnerId, gid=GroupId}).
-spec change_group(Filename, Gid) -> ok | {error, Reason} when
- Filename :: name(),
+ Filename :: name_all(),
Gid :: integer(),
Reason :: posix() | badarg.
@@ -1181,7 +1190,7 @@ change_group(Name, GroupId)
write_file_info(Name, #file_info{gid=GroupId}).
-spec change_time(Filename, Mtime) -> ok | {error, Reason} when
- Filename :: name(),
+ Filename :: name_all(),
Mtime :: date_time(),
Reason :: posix() | badarg.
@@ -1191,7 +1200,7 @@ change_time(Name, {{Y, M, D}, {H, Min, Sec}}=Time)
write_file_info(Name, #file_info{mtime=Time}).
-spec change_time(Filename, Atime, Mtime) -> ok | {error, Reason} when
- Filename :: name(),
+ Filename :: name_all(),
Atime :: date_time(),
Mtime :: date_time(),
Reason :: posix() | badarg.
@@ -1239,7 +1248,7 @@ sendfile(File, Sock, Offset, Bytes, Opts) ->
-spec sendfile(Filename, Socket) ->
{'ok', non_neg_integer()} | {'error', inet:posix() |
closed | badarg | not_owner}
- when Filename :: name(),
+ when Filename :: name_all(),
Socket :: inet:socket().
sendfile(Filename, Sock) ->
case file:open(Filename, [read, raw, binary]) of
diff --git a/lib/kernel/src/file_server.erl b/lib/kernel/src/file_server.erl
index 73202319b9..6b413ff630 100644
--- a/lib/kernel/src/file_server.erl
+++ b/lib/kernel/src/file_server.erl
@@ -170,7 +170,7 @@ handle_call({read_link_info, Name, Opts}, _From, Handle) ->
handle_call({read_link, Name}, _From, Handle) ->
{reply, ?PRIM_FILE:read_link(Handle, Name), Handle};
handle_call({read_link_all, Name}, _From, Handle) ->
- {reply, ?PRIM_FILE:read_link(Handle, Name), Handle};
+ {reply, ?PRIM_FILE:read_link_all(Handle, Name), Handle};
handle_call({make_link, Old, New}, _From, Handle) ->
{reply, ?PRIM_FILE:make_link(Handle, Old, New), Handle};
diff --git a/lib/kernel/src/gen_tcp.erl b/lib/kernel/src/gen_tcp.erl
index ec13ab6d2e..23867300a5 100644
--- a/lib/kernel/src/gen_tcp.erl
+++ b/lib/kernel/src/gen_tcp.erl
@@ -256,7 +256,7 @@ close(S) ->
-spec send(Socket, Packet) -> ok | {error, Reason} when
Socket :: socket(),
Packet :: iodata(),
- Reason :: inet:posix().
+ Reason :: closed | inet:posix().
send(S, Packet) when is_port(S) ->
case inet_db:lookup_socket(S) of
diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl
index 06d404905d..e676ca997d 100644
--- a/lib/kernel/src/hipe_unified_loader.erl
+++ b/lib/kernel/src/hipe_unified_loader.erl
@@ -218,7 +218,7 @@ load_common(Mod, Bin, Beam, OldReferencesToPatch) ->
{MFAs,Addresses} = exports(ExportMap, CodeAddress),
%% Remove references to old versions of the module.
ReferencesToPatch = get_refs_from(MFAs, []),
- remove_refs_from(MFAs),
+ ok = remove_refs_from(MFAs),
%% Patch all dynamic references in the code.
%% Function calls, Atoms, Constants, System calls
patch(Refs, CodeAddress, ConstMap2, Addresses, TrampolineMap),
@@ -802,7 +802,7 @@ patch_to_emu_step1(Mod) ->
%% Find all call sites that call these MFAs. As a side-effect,
%% create native stubs for any MFAs that are referred.
ReferencesToPatch = get_refs_from(MFAs, []),
- remove_refs_from(MFAs),
+ ok = remove_refs_from(MFAs),
ReferencesToPatch;
false ->
%% The first time we load the module, no redirection needs to be done.
@@ -846,11 +846,8 @@ get_refs_from(MFAs, []) ->
mark_referred_from(MFAs),
MFAs.
-mark_referred_from([MFA|MFAs]) ->
- hipe_bifs:mark_referred_from(MFA),
- mark_referred_from(MFAs);
-mark_referred_from([]) ->
- [].
+mark_referred_from(MFAs) ->
+ lists:foreach(fun(MFA) -> hipe_bifs:mark_referred_from(MFA) end, MFAs).
%%--------------------------------------------------------------------
%% Given a list of MFAs with referred_from references, update their
@@ -858,11 +855,8 @@ mark_referred_from([]) ->
%%
%% The {MFA,Refs} list must come from get_refs_from/2.
%%
-redirect([MFA|Rest]) ->
- hipe_bifs:redirect_referred_from(MFA),
- redirect(Rest);
-redirect([]) ->
- ok.
+redirect(MFAs) ->
+ lists:foreach(fun(MFA) -> hipe_bifs:redirect_referred_from(MFA) end, MFAs).
%%--------------------------------------------------------------------
%% Given a list of MFAs, remove all referred_from references having
@@ -874,11 +868,8 @@ redirect([]) ->
%% list. The refers_to list is used here to find the CalleeMFAs whose
%% referred_from lists should be updated.
%%
-remove_refs_from([CallerMFA|CallerMFAs]) ->
- hipe_bifs:remove_refs_from(CallerMFA),
- remove_refs_from(CallerMFAs);
-remove_refs_from([]) ->
- [].
+remove_refs_from(MFAs) ->
+ lists:foreach(fun(MFA) -> hipe_bifs:remove_refs_from(MFA) end, MFAs).
%%--------------------------------------------------------------------
diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl
index 4c040f0a0e..79d11c155c 100644
--- a/lib/kernel/test/code_SUITE.erl
+++ b/lib/kernel/test/code_SUITE.erl
@@ -716,7 +716,7 @@ analyse([], [This={M,F,A}|Path], Visited, ErrCnt0) ->
%% These modules should be loaded by code.erl before
%% the code_server is started.
OK = [erlang, os, prim_file, erl_prim_loader, init, ets,
- code_server, lists, lists_sort, unicode, binary, filename, packages,
+ code_server, lists, lists_sort, unicode, binary, filename,
gb_sets, gb_trees, hipe_unified_loader, hipe_bifs,
prim_zip, zlib],
ErrCnt1 =
@@ -822,6 +822,10 @@ check_funs({'$M_EXPR','$F_EXPR',2},
check_funs({'$M_EXPR','$F_EXPR',1},
[{lists,foreach,2},
{hipe_unified_loader,patch_consts,3} | _]) -> 0;
+check_funs({'$M_EXPR','$F_EXPR',1},
+ [{lists,foreach,2},
+ {hipe_unified_loader,mark_referred_from,1},
+ {hipe_unified_loader,get_refs_from,2}| _]) -> 0;
check_funs({'$M_EXPR',warning_msg,2},
[{code_server,finish_on_load_report,2} | _]) -> 0;
%% This is cheating! /raimo
@@ -1590,7 +1594,7 @@ native_early_modules_1(Architecture) ->
?line true = lists:all(fun code:is_module_native/1,
[ets,file,filename,gb_sets,gb_trees,
%%hipe_unified_loader, no_native as workaround
- lists,os,packages]),
+ lists,os]),
ok
end.
diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl
index fd4d5bd24e..c604e7073f 100644
--- a/lib/kernel/test/file_SUITE.erl
+++ b/lib/kernel/test/file_SUITE.erl
@@ -46,6 +46,7 @@
read_write_file/1, names/1]).
-export([cur_dir_0/1, cur_dir_1/1, make_del_dir/1,
list_dir/1,list_dir_error/1,
+ untranslatable_names/1, untranslatable_names_error/1,
pos1/1, pos2/1]).
-export([close/1, consult1/1, path_consult/1, delete/1]).
-export([ eval1/1, path_eval/1, script1/1, path_script/1,
@@ -56,7 +57,7 @@
-export([rename/1, access/1, truncate/1, datasync/1, sync/1,
read_write/1, pread_write/1, append/1, exclusive/1]).
-export([ e_delete/1, e_rename/1, e_make_dir/1, e_del_dir/1]).
--export([otp_5814/1]).
+-export([otp_5814/1, otp_10852/1]).
-export([ read_not_really_compressed/1,
read_compressed_cooked/1, read_compressed_cooked_binary/1,
@@ -111,13 +112,14 @@ all() ->
{group, files}, delete, rename, names, {group, errors},
{group, compression}, {group, links}, copy,
delayed_write, read_ahead, segment_read, segment_write,
- ipread, pid2name, interleaved_read_write, otp_5814,
+ ipread, pid2name, interleaved_read_write, otp_5814, otp_10852,
large_file, large_write, read_line_1, read_line_2, read_line_3,
read_line_4, standard_io].
groups() ->
[{dirs, [], [make_del_dir, cur_dir_0, cur_dir_1,
- list_dir, list_dir_error]},
+ list_dir, list_dir_error, untranslatable_names,
+ untranslatable_names_error]},
{files, [],
[{group, open}, {group, pos}, {group, file_info},
{group, consult}, {group, eval}, {group, script},
@@ -557,6 +559,112 @@ list_dir_1(TestDir, Cnt, Sorted0) ->
Sorted = lists:sort(DirList1),
list_dir_1(TestDir, Cnt-1, Sorted).
+untranslatable_names(Config) ->
+ case no_untranslatable_names() of
+ true ->
+ {skip,"Not a problem on this OS"};
+ false ->
+ untranslatable_names_1(Config)
+ end.
+
+untranslatable_names_1(Config) ->
+ {ok,OldCwd} = file:get_cwd(),
+ PrivDir = ?config(priv_dir, Config),
+ Dir = filename:join(PrivDir, "untranslatable_names"),
+ ok = file:make_dir(Dir),
+ Node = start_node(untranslatable_names, "+fnu"),
+ try
+ ok = file:set_cwd(Dir),
+ [ok = file:write_file(F, F) || {_,F} <- untranslatable_names()],
+
+ ExpectedListDir0 = [unicode:characters_to_list(N, utf8) ||
+ {utf8,N} <- untranslatable_names()],
+ ExpectedListDir = lists:sort(ExpectedListDir0),
+ io:format("ExpectedListDir: ~p\n", [ExpectedListDir]),
+ ExpectedListDir = call_and_sort(Node, file, list_dir, [Dir]),
+
+ ExpectedListDirAll0 = [case Enc of
+ utf8 ->
+ unicode:characters_to_list(N, utf8);
+ latin1 ->
+ N
+ end || {Enc,N} <- untranslatable_names()],
+ ExpectedListDirAll = lists:sort(ExpectedListDirAll0),
+ io:format("ExpectedListDirAll: ~p\n", [ExpectedListDirAll]),
+ ExpectedListDirAll = call_and_sort(Node, file, list_dir_all, [Dir])
+ after
+ catch test_server:stop_node(Node),
+ file:set_cwd(OldCwd),
+ [file:delete(F) || {_,F} <- untranslatable_names()],
+ file:del_dir(Dir)
+ end,
+ ok.
+
+untranslatable_names_error(Config) ->
+ case no_untranslatable_names() of
+ true ->
+ {skip,"Not a problem on this OS"};
+ false ->
+ untranslatable_names_error_1(Config)
+ end.
+
+untranslatable_names_error_1(Config) ->
+ {ok,OldCwd} = file:get_cwd(),
+ PrivDir = ?config(priv_dir, Config),
+ Dir = filename:join(PrivDir, "untranslatable_names_error"),
+ ok = file:make_dir(Dir),
+ Node = start_node(untranslatable_names, "+fnue"),
+ try
+ ok = file:set_cwd(Dir),
+ [ok = file:write_file(F, F) || {_,F} <- untranslatable_names()],
+
+ ExpectedListDir0 = [unicode:characters_to_list(N, utf8) ||
+ {utf8,N} <- untranslatable_names()],
+ ExpectedListDir = lists:sort(ExpectedListDir0),
+ io:format("ExpectedListDir: ~p\n", [ExpectedListDir]),
+ {error,{no_translation,BadFile}} =
+ rpc:call(Node, file, list_dir, [Dir]),
+ true = lists:keymember(BadFile, 2, untranslatable_names())
+
+ after
+ catch test_server:stop_node(Node),
+ file:set_cwd(OldCwd),
+ [file:delete(F) || {_,F} <- untranslatable_names()],
+ file:del_dir(Dir)
+ end,
+ ok.
+
+untranslatable_names() ->
+ [{utf8,<<"abc">>},
+ {utf8,<<"def">>},
+ {utf8,<<"Lagerl",195,182,"f">>},
+ {utf8,<<195,150,"stra Emterwik">>},
+ {latin1,<<"M",229,"rbacka">>},
+ {latin1,<<"V",228,"rmland">>}].
+
+call_and_sort(Node, M, F, A) ->
+ {ok,Res} = rpc:call(Node, M, F, A),
+ lists:sort(Res).
+
+no_untranslatable_names() ->
+ case os:type() of
+ {unix,darwin} -> true;
+ {win32,_} -> true;
+ _ -> false
+ end.
+
+start_node(Name, Args) ->
+ [_,Host] = string:tokens(atom_to_list(node()), "@"),
+ ct:log("Trying to start ~w@~s~n", [Name,Host]),
+ case test_server:start_node(Name, peer, [{args,Args}]) of
+ {error,Reason} ->
+ test_server:fail(Reason);
+ {ok,Node} ->
+ ct:log("Node ~p started~n", [Node]),
+ Node
+ end.
+
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -3410,6 +3518,49 @@ otp_5814(Config) when is_list(Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+otp_10852(suite) ->
+ [];
+otp_10852(doc) ->
+ ["OTP-10852. +fnu and latin1 filenames"];
+otp_10852(Config) when is_list(Config) ->
+ Node = start_node(erl_pp_helper, "+fnu"),
+ Dir = ?config(priv_dir, Config),
+ B = filename:join(Dir, <<"\xE4">>),
+ ok = rpc_call(Node, get_cwd, [B]),
+ {error, no_translation} = rpc_call(Node, set_cwd, [B]),
+ ok = rpc_call(Node, delete, [B]),
+ ok = rpc_call(Node, rename, [B, B]),
+ ok = rpc_call(Node, read_file_info, [B]),
+ ok = rpc_call(Node, read_link_info, [B]),
+ ok = rpc_call(Node, read_link, [B]),
+ ok = rpc_call(Node, write_file_info, [B,#file_info{}]),
+ ok = rpc_call(Node, list_dir, [B]),
+ ok = rpc_call(Node, list_dir_all, [B]),
+ ok = rpc_call(Node, read_file, [B]),
+ ok = rpc_call(Node, make_link, [B,B]),
+ ok = rpc_call(Node, make_symlink, [B,B]),
+ ok = rpc_call(Node, delete, [B]),
+ ok = rpc_call(Node, make_dir, [B]),
+ ok = rpc_call(Node, del_dir, [B]),
+ ok = rpc_call(Node, write_file, [B,B]),
+ {ok, Fd} = rpc_call(Node, open, [B,[read]]),
+ ok = rpc_call(Node, close, [Fd]),
+ {ok,0} = rpc_call(Node, copy, [B,B]),
+ {ok, Fd2, B} = rpc_call(Node, path_open, [["."], B, [read]]),
+ ok = rpc_call(Node, close, [Fd2]),
+ true = test_server:stop_node(Node),
+ ok.
+
+rpc_call(N, F, As) ->
+ case rpc:call(N, ?FILE_MODULE, F, As) of
+ {error, enotsup} -> ok;
+ {error, enoent} -> ok;
+ {error, badarg} -> ok;
+ Else -> Else
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
large_file(suite) ->
[];
large_file(doc) ->
diff --git a/lib/kernel/test/file_name_SUITE.erl b/lib/kernel/test/file_name_SUITE.erl
index e8529db1dc..808a10ee27 100644
--- a/lib/kernel/test/file_name_SUITE.erl
+++ b/lib/kernel/test/file_name_SUITE.erl
@@ -340,9 +340,9 @@ check_icky(Mod) ->
?line true=(length("åäö") =:= 3),
?line UniMode = file:native_name_encoding() =/= latin1,
?line make_icky_dir(Mod),
- ?line {ok, L0} = Mod:list_dir("."),
+ {ok, L0} = Mod:list_dir_all("."),
?line L1 = lists:sort(L0),
- io:format("~p ~p~n",[L1,list(icky_dir())]),
+ io:format("~p~n~p~n~n",[L1,lists:sort(list(icky_dir()))]),
?line L1 = lists:sort(convlist(list(icky_dir()))),
?line {ok,D2} = Mod:get_cwd(),
?line true = is_list(D2),
@@ -357,7 +357,8 @@ check_icky(Mod) ->
?line Syms = [ {S,conv(Targ),list_to_binary(get_data(Targ,icky_dir()))}
|| {T,S,Targ} <- icky_dir(), T =:= symlink ],
?line [ {ok, Cont} = Mod:read_file(SymL) || {SymL,_,Cont} <- Syms ],
- ?line [ {ok, Targ} = fixlink(Mod:read_link(SymL)) || {SymL,Targ,_} <- Syms ],
+ [ {ok, Targ} = fixlink(Mod:read_link_all(SymL)) ||
+ {SymL,Targ,_} <- Syms ],
?line chk_cre_dir(Mod,[{directory,"åäö_dir",icky_dir()}]),
?line {ok,BeginAt} = Mod:get_cwd(),
?line true = is_list(BeginAt),
@@ -369,7 +370,7 @@ check_icky(Mod) ->
?line ok = Mod:set_cwd(".."),
?line {ok,BeginAt} = Mod:get_cwd(),
?line rm_r2(Mod,"åäö_dir"),
- {OS,TYPE} = os:type(),
+ {OS,_} = os:type(),
% Check that treat_icky really converts to the same as the OS
case UniMode of
true ->
@@ -377,7 +378,7 @@ check_icky(Mod) ->
?line ok = Mod:set_cwd("åäö_dir"),
?line ok = Mod:write_file(<<"ååå">>,<<"hello">>),
?line Treated = treat_icky(<<"ååå">>),
- ?line {ok,[Treated]} = Mod:list_dir("."),
+ {ok,[Treated]} = Mod:list_dir_all("."),
?line ok = Mod:delete(<<"ååå">>),
?line {ok,[]} = Mod:list_dir("."),
?line ok = Mod:set_cwd(".."),
@@ -393,15 +394,7 @@ check_icky(Mod) ->
true ->
ok
end,
- ?line ok = Mod:set_cwd(treat_icky(<<"åäö_dir">>)),
- ?line {ok, NowAt2} = Mod:get_cwd(),
- io:format("~p~n",[NowAt2]),
- % Cannot create raw unicode-breaking filenames on windows or macos
- ?line true = ((((not UniMode) or (OS =:= win32) or (TYPE=:=darwin)) and is_list(NowAt2)) orelse ((UniMode) and is_binary(NowAt2))),
- ?line true = BeginAt =/= NowAt2,
- ?line ok = Mod:set_cwd(".."),
?line {ok,BeginAt} = Mod:get_cwd(),
- ?line rm_r2(Mod,conv(treat_icky(<<"åäö_dir">>))),
case has_links() of
true ->
?line ok = Mod:make_link("fil1","nisseö"),
@@ -485,7 +478,7 @@ check_very_icky(Mod) ->
ok
end,
?line make_very_icky_dir(Mod),
- ?line {ok, L0} = Mod:list_dir("."),
+ {ok, L0} = Mod:list_dir_all("."),
?line L1 = lists:sort(L0),
?line L1 = lists:sort(convlist(list(very_icky_dir()))),
?line {ok,D2} = Mod:get_cwd(),
@@ -494,7 +487,8 @@ check_very_icky(Mod) ->
?line Syms = [ {S,conv(Targ),list_to_binary(get_data(Targ,very_icky_dir()))}
|| {T,S,Targ} <- very_icky_dir(), T =:= symlink ],
?line [ {ok, Cont} = Mod:read_file(SymL) || {SymL,_,Cont} <- Syms ],
- ?line [ {ok, Targ} = fixlink(Mod:read_link(SymL)) || {SymL,Targ,_} <- Syms ],
+ ?line [ {ok, Targ} = fixlink(Mod:read_link_all(SymL)) ||
+ {SymL,Targ,_} <- Syms ],
?line chk_cre_dir(Mod,[{directory,[1088,1079,1091]++"_dir",very_icky_dir()}]),
?line {ok,BeginAt} = Mod:get_cwd(),
?line true = is_list(BeginAt),
@@ -559,22 +553,6 @@ check_very_icky(Mod) ->
FI#file_info{mode = NewMode2}),
?line {ok,#file_info{mode = NewMode2}} =
Mod:read_file_info([956,965,963,954,959,49]),
- ?line NumOK0 = case has_links() of
- true -> 5;
- false -> 3
- end,
- ?line NumNOK0 = case has_links() of
- true -> 4;
- false -> 3
- end,
- ?line {NumOK,NumNOK} = case is_binary(treat_icky(<<"foo">>)) of
- false ->
- {NumOK0+NumNOK0,0};
- true ->
- {NumOK0,NumNOK0}
- end,
- ?line {NumOK,NumNOK} = filelib:fold_files(".",".*",true,fun(_F,{N,M}) when is_list(_F) -> io:format("~ts~n",[_F]),{N+1,M}; (_F,{N,M}) -> io:format("~p~n",[_F]),{N,M+1} end,{0,0}),
- ?line ok = filelib:fold_files(".",[1076,1089,1072,124,46,42],true,fun(_F,_) -> ok end,false),
ok
catch
throw:need_unicode_mode ->
@@ -593,7 +571,7 @@ check_very_icky(Mod) ->
rm_rf(Mod,Dir) ->
case Mod:read_link_info(Dir) of
{ok, #file_info{type = directory}} ->
- {ok, Content} = Mod:list_dir(Dir),
+ {ok, Content} = Mod:list_dir_all(Dir),
[ rm_rf(Mod,filename:join(Dir,C)) || C <- Content ],
Mod:del_dir(Dir),
ok;
@@ -608,7 +586,7 @@ rm_r(Mod,Dir) ->
case Mod:read_link_info(Dir) of
{ok, #file_info{type = directory}} ->
{ok,#file_info{type = directory}} = Mod:read_file_info(Dir),
- {ok, Content} = Mod:list_dir(Dir),
+ {ok, Content} = Mod:list_dir_all(Dir),
[ true = is_list(Part) || Part <- Content ],
[ true = is_list(filename:join(Dir,Part)) || Part <- Content ],
[ rm_r(Mod,filename:join(Dir,C)) || C <- Content ],
@@ -626,7 +604,7 @@ rm_r2(Mod,Dir) ->
case Mod:read_link_info(Dir) of
{ok, #file_info{type = directory}} ->
{ok,#file_info{type = directory}} = Mod:read_file_info(Dir),
- {ok, Content} = Mod:list_dir(Dir),
+ {ok, Content} = Mod:list_dir_all(Dir),
UniMode = file:native_name_encoding() =/= latin1,
[ true = (is_list(Part) orelse UniMode) || Part <- Content ],
[ true = (is_list(filename:join(Dir,Part)) orelse UniMode) || Part <- Content ],