diff options
Diffstat (limited to 'lib/kernel')
-rw-r--r-- | lib/kernel/doc/src/code.xml | 15 | ||||
-rw-r--r-- | lib/kernel/doc/src/file.xml | 94 | ||||
-rw-r--r-- | lib/kernel/doc/src/notes.xml | 2 | ||||
-rw-r--r-- | lib/kernel/doc/src/specs.xml | 1 | ||||
-rw-r--r-- | lib/kernel/src/application_controller.erl | 6 | ||||
-rw-r--r-- | lib/kernel/src/auth.erl | 2 | ||||
-rw-r--r-- | lib/kernel/src/code.erl | 6 | ||||
-rw-r--r-- | lib/kernel/src/code_server.erl | 3 | ||||
-rw-r--r-- | lib/kernel/src/file.erl | 162 | ||||
-rw-r--r-- | lib/kernel/src/file_server.erl | 6 | ||||
-rw-r--r-- | lib/kernel/src/gen_tcp.erl | 4 | ||||
-rw-r--r-- | lib/kernel/src/hipe_unified_loader.erl | 25 | ||||
-rw-r--r-- | lib/kernel/src/inet6_tcp_dist.erl | 10 | ||||
-rw-r--r-- | lib/kernel/src/inet_tcp_dist.erl | 10 | ||||
-rw-r--r-- | lib/kernel/test/code_SUITE.erl | 19 | ||||
-rw-r--r-- | lib/kernel/test/file_SUITE.erl | 197 | ||||
-rw-r--r-- | lib/kernel/test/file_name_SUITE.erl | 59 | ||||
-rw-r--r-- | lib/kernel/test/prim_file_SUITE.erl | 47 | ||||
-rw-r--r-- | lib/kernel/vsn.mk | 2 |
19 files changed, 498 insertions, 172 deletions
diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml index 279c7558bc..6f04741f85 100644 --- a/lib/kernel/doc/src/code.xml +++ b/lib/kernel/doc/src/code.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2012</year> + <year>1996</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -738,6 +738,19 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]), <c>undefined</c>.</p> </desc> </func> + + <func> + <name name="get_mode" arity="0"/> + <fsummary>The code_server's mode.</fsummary> + <desc> + <p>This function returns an atom describing the code_server's mode: + <c>interactive</c> or <c>embedded</c>. </p> + <p>This information is useful when an external entity (for example, + an IDE) provides additional code for a running node. If in interactive + mode, it only needs to add to the code path. If in embedded mode, + the code has to be loaded with <c>load_binary/3</c></p> + </desc> + </func> </funcs> </erlref> diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml index 4a9b7d2ceb..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 @@ -110,6 +102,9 @@ <name name="filename"/> </datatype> <datatype> + <name name="filename_all"/> + </datatype> + <datatype> <name name="io_device"/> <desc> <p>As returned by @@ -122,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 @@ -156,9 +159,6 @@ <datatype> <name name="file_info_option"/> </datatype> - <datatype> - <name name="sendfile_option"/> - </datatype> </datatypes> <funcs> @@ -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 @@ -1648,6 +1717,7 @@ <func> <name name="sendfile" arity="5"/> <fsummary>send a file to a socket</fsummary> + <type name="sendfile_option"/> <desc> <p>Sends <c>Bytes</c> from the file referenced by <c>RawFile</c> beginning at <c>Offset</c> to diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index 6968b36eac..14bcfc3c4d 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2004</year><year>2012</year> + <year>2004</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/kernel/doc/src/specs.xml b/lib/kernel/doc/src/specs.xml index b41addaa0c..813bb06e1f 100644 --- a/lib/kernel/doc/src/specs.xml +++ b/lib/kernel/doc/src/specs.xml @@ -29,5 +29,4 @@ <xi:include href="../specs/specs_user.xml"/> <xi:include href="../specs/specs_wrap_log_reader.xml"/> <xi:include href="../specs/specs_zlib_stub.xml"/> - <xi:include href="../specs/specs_packages.xml"/> </specs> diff --git a/lib/kernel/src/application_controller.erl b/lib/kernel/src/application_controller.erl index 3c860af48e..9ed2c7a7d9 100644 --- a/lib/kernel/src/application_controller.erl +++ b/lib/kernel/src/application_controller.erl @@ -495,6 +495,8 @@ init(Init, Kernel) -> {'EXIT', LoadError} -> Reason = {'load error', LoadError}, Init ! {ack, self(), {error, to_string(Reason)}}; + {error, Error} -> + Init ! {ack, self(), {error, to_string(Error)}}; {ok, NewS} -> Init ! {ack, self(), ok}, gen_server:enter_loop(?MODULE, [], NewS, @@ -1447,7 +1449,7 @@ prim_consult(FullName) -> {ok, Bin, _} -> case file_binary_to_list(Bin) of {ok, String} -> - case erl_scan:string(String, 1, [unicode]) of + case erl_scan:string(String) of {ok, Tokens, _EndLine} -> prim_parse(Tokens, []); {error, Reason, _EndLine} -> @@ -1600,7 +1602,7 @@ conv(_) -> []. %%% Fix some day: eliminate the duplicated code here make_term(Str) -> - case erl_scan:string(Str, 1, [unicode]) of + case erl_scan:string(Str) of {ok, Tokens, _} -> case erl_parse:parse_term(Tokens ++ [{dot, 1}]) of {ok, Term} -> 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/code.erl b/lib/kernel/src/code.erl index 8a543abd6f..03fba96d4b 100644 --- a/lib/kernel/src/code.erl +++ b/lib/kernel/src/code.erl @@ -64,7 +64,8 @@ where_is_file/1, where_is_file/2, set_primary_archive/4, - clash/0]). + clash/0, + get_mode/0]). -export_type([load_error_rsn/0, load_ret/0]). @@ -293,6 +294,9 @@ replace_path(Name, Dir) when (is_atom(Name) orelse is_list(Name)), -spec rehash() -> 'ok'. rehash() -> call(rehash). +-spec get_mode() -> 'embedded' | 'interactive'. +get_mode() -> call(get_mode). + %%----------------------------------------------------------------- call(Req) -> diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl index b770fce887..5d74e8620b 100644 --- a/lib/kernel/src/code_server.erl +++ b/lib/kernel/src/code_server.erl @@ -422,6 +422,9 @@ handle_call({is_cached,File}, {_From,_Tag}, S=#state{cache=Cache}) -> end end; +handle_call(get_mode, {_From,_Tag}, S=#state{mode=Mode}) -> + {reply, Mode, S}; + handle_call(Other,{_From,_Tag}, S) -> error_msg(" ** Codeserver*** ignoring ~w~n ",[Other]), {noreply,S}. diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl index 70c4583ad2..a4c56b346f 100644 --- a/lib/kernel/src/file.erl +++ b/lib/kernel/src/file.erl @@ -27,12 +27,12 @@ -export([format_error/1]). %% File system and metadata. -export([get_cwd/0, get_cwd/1, set_cwd/1, delete/1, rename/2, - make_dir/1, del_dir/1, list_dir/1, + make_dir/1, del_dir/1, list_dir/1, list_dir_all/1, read_file_info/1, read_file_info/2, write_file_info/2, write_file_info/3, altname/1, read_link_info/1, read_link_info/2, - read_link/1, + read_link/1, read_link_all/1, make_link/2, make_symlink/2, read_file/1, write_file/2, write_file/3]). %% Specialized @@ -67,8 +67,8 @@ -export([ipread_s32bu_p32bu_int/3]). %% Types that can be used from other modules -- alphabetically ordered. --export_type([date_time/0, fd/0, file_info/0, filename/0, io_device/0, - name/0, posix/0]). +-export_type([date_time/0, fd/0, file_info/0, filename/0, filename_all/0, + io_device/0, name/0, name_all/0, posix/0]). %%% Includes and defines -include("file.hrl"). @@ -80,7 +80,8 @@ -define(RAM_FILE, ram_file). % Module %% data types --type filename() :: string() | binary(). +-type filename() :: string(). +-type filename_all() :: string() | binary(). -type file_info() :: #file_info{}. -type fd() :: #file_descriptor{}. -type io_device() :: pid() | fd(). @@ -96,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' @@ -116,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. @@ -159,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) -> @@ -196,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. @@ -239,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. @@ -247,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. @@ -261,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. @@ -271,15 +273,23 @@ 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. read_link(Name) -> check_and_call(read_link, [file_name(Name)]). +-spec read_link_all(Name) -> {ok, Filename} | {error, Reason} when + Name :: name_all(), + Filename :: filename_all(), + Reason :: posix() | badarg. + +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. @@ -287,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. @@ -296,15 +306,25 @@ 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_all(), + Filenames :: [filename_all()], + Reason :: posix() | badarg. + +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. @@ -312,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. @@ -340,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. @@ -399,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. @@ -506,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 @@ -524,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 @@ -692,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. @@ -704,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(), @@ -931,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()}. @@ -948,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()}. @@ -971,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()}. @@ -979,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()}. @@ -995,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()}. @@ -1006,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()}. @@ -1029,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()}. @@ -1038,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 @@ -1056,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()}. @@ -1068,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()}. @@ -1101,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) -> @@ -1127,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. @@ -1136,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. @@ -1145,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. @@ -1155,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. @@ -1164,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. @@ -1174,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. @@ -1196,7 +1222,7 @@ change_time(Name, {{AY, AM, AD}, {AH, AMin, ASec}}=Atime, -spec sendfile(RawFile, Socket, Offset, Bytes, Opts) -> {'ok', non_neg_integer()} | {'error', inet:posix() | closed | badarg | not_owner} when - RawFile :: file:fd(), + RawFile :: fd(), Socket :: inet:socket(), Offset :: non_neg_integer(), Bytes :: non_neg_integer(), @@ -1222,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 :: file:name(), + when Filename :: name_all(), Socket :: inet:socket(). sendfile(Filename, Sock) -> case file:open(Filename, [read, raw, binary]) of @@ -1345,7 +1371,7 @@ eval_stream(Fd, Handling, Bs) -> eval_stream(Fd, Handling, 1, undefined, [], Bs). eval_stream(Fd, H, Line, Last, E, Bs) -> - eval_stream2(io:parse_erl_exprs(Fd, '', Line, [unicode]), Fd, H, Last, E, Bs). + eval_stream2(io:parse_erl_exprs(Fd, '', Line), Fd, H, Last, E, Bs). eval_stream2({ok,Form,EndLine}, Fd, H, Last, E, Bs0) -> try erl_eval:exprs(Form, Bs0) of diff --git a/lib/kernel/src/file_server.erl b/lib/kernel/src/file_server.erl index fc6cd823c9..49ec6f96cc 100644 --- a/lib/kernel/src/file_server.erl +++ b/lib/kernel/src/file_server.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2011. All Rights Reserved. +%% Copyright Ericsson AB 2000-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -136,6 +136,8 @@ handle_call({del_dir, Name}, _From, Handle) -> handle_call({list_dir, Name}, _From, Handle) -> {reply, ?PRIM_FILE:list_dir(Handle, Name), Handle}; +handle_call({list_dir_all, Name}, _From, Handle) -> + {reply, ?PRIM_FILE:list_dir_all(Handle, Name), Handle}; handle_call(get_cwd, _From, Handle) -> {reply, ?PRIM_FILE:get_cwd(Handle), Handle}; @@ -167,6 +169,8 @@ 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_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..a98ed4c238 100644 --- a/lib/kernel/src/gen_tcp.erl +++ b/lib/kernel/src/gen_tcp.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2012. All Rights Reserved. +%% Copyright Ericsson AB 1997-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -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/src/inet6_tcp_dist.erl b/lib/kernel/src/inet6_tcp_dist.erl index b9c4fa607c..2cb0e10c87 100644 --- a/lib/kernel/src/inet6_tcp_dist.erl +++ b/lib/kernel/src/inet6_tcp_dist.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2011. All Rights Reserved. +%% Copyright Ericsson AB 1997-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -71,8 +71,12 @@ listen(Name) -> {ok, Socket} -> TcpAddress = get_tcp_address(Socket), {_,Port} = TcpAddress#net_address.address, - {ok, Creation} = erl_epmd:register_node(Name, Port), - {ok, {Socket, TcpAddress, Creation}}; + case erl_epmd:register_node(Name, Port) of + {ok, Creation} -> + {ok, {Socket, TcpAddress, Creation}}; + Error -> + Error + end; Error -> Error end. diff --git a/lib/kernel/src/inet_tcp_dist.erl b/lib/kernel/src/inet_tcp_dist.erl index 7f935c2b36..8005eff58c 100644 --- a/lib/kernel/src/inet_tcp_dist.erl +++ b/lib/kernel/src/inet_tcp_dist.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% Copyright Ericsson AB 1997-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -67,8 +67,12 @@ listen(Name) -> {ok, Socket} -> TcpAddress = get_tcp_address(Socket), {_,Port} = TcpAddress#net_address.address, - {ok, Creation} = erl_epmd:register_node(Name, Port), - {ok, {Socket, TcpAddress, Creation}}; + case erl_epmd:register_node(Name, Port) of + {ok, Creation} -> + {ok, {Socket, TcpAddress, Creation}}; + Error -> + Error + end; Error -> Error end. diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index d7424c0c9a..fc17db2745 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2012. All Rights Reserved. +%% Copyright Ericsson AB 1996-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -33,7 +33,7 @@ purge_stacktrace/1, mult_lib_roots/1, bad_erl_libs/1, code_archive/1, code_archive2/1, on_load/1, on_load_binary/1, on_load_embedded/1, on_load_errors/1, big_boot_embedded/1, - native_early_modules/1]). + native_early_modules/1, get_mode/1]). -export([init_per_testcase/2, end_per_testcase/2, init_per_suite/1, end_per_suite/1, @@ -60,7 +60,7 @@ all() -> where_is_file_cached, purge_stacktrace, mult_lib_roots, bad_erl_libs, code_archive, code_archive2, on_load, on_load_binary, on_load_embedded, on_load_errors, - big_boot_embedded, native_early_modules]. + big_boot_embedded, native_early_modules, get_mode]. groups() -> []. @@ -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,10 +1594,15 @@ 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. +get_mode(suite) -> []; +get_mode(doc) -> ["Test that the mode of the code server is properly retrieved"]; +get_mode(Config) when is_list(Config) -> + interactive = code:get_mode(). + %%----------------------------------------------------------------- %% error_logger handler. %% (Copied from stdlib/test/proc_lib_SUITE.erl.) diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl index ac991b1111..c604e7073f 100644 --- a/lib/kernel/test/file_SUITE.erl +++ b/lib/kernel/test/file_SUITE.erl @@ -45,6 +45,8 @@ init_per_testcase/2, end_per_testcase/2, 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, @@ -55,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, @@ -110,12 +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]}, + [{dirs, [], [make_del_dir, cur_dir_0, cur_dir_1, + list_dir, list_dir_error, untranslatable_names, + untranslatable_names_error]}, {files, [], [{group, open}, {group, pos}, {group, file_info}, {group, consult}, {group, eval}, {group, script}, @@ -519,6 +523,148 @@ win_cur_dir_1(_Config) -> ok. + +%%% +%%% Test list_dir() on a non-existing pathname. +%%% + +list_dir_error(Config) -> + Priv = ?config(priv_dir, Config), + NonExisting = filename:join(Priv, "non-existing-dir"), + {error,enoent} = ?FILE_MODULE:list_dir(NonExisting), + ok. + +%%% +%%% Test list_dir() and list_dir_all(). +%%% + +list_dir(Config) -> + RootDir = ?config(priv_dir, Config), + TestDir = filename:join(RootDir, ?MODULE_STRING++"_list_dir"), + ?FILE_MODULE:make_dir(TestDir), + list_dir_1(TestDir, 42, []). + +list_dir_1(TestDir, 0, Sorted) -> + [ok = ?FILE_MODULE:delete(filename:join(TestDir, F)) || + F <- Sorted], + ok = ?FILE_MODULE:del_dir(TestDir); +list_dir_1(TestDir, Cnt, Sorted0) -> + Base = "file" ++ integer_to_list(Cnt), + Name = filename:join(TestDir, Base), + ok = ?FILE_MODULE:write_file(Name, Base), + Sorted = lists:merge([Base], Sorted0), + {ok,DirList0} = ?FILE_MODULE:list_dir(TestDir), + {ok,DirList1} = ?FILE_MODULE:list_dir_all(TestDir), + Sorted = lists:sort(DirList0), + 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. + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -2453,6 +2599,7 @@ symlinks(suite) -> []; symlinks(Config) when is_list(Config) -> ?line Dog = test_server:timetrap(test_server:seconds(10)), ?line {error, _} = ?FILE_MODULE:read_link(lists:duplicate(10000,$a)), + {error, _} = ?FILE_MODULE:read_link_all(lists:duplicate(10000,$a)), ?line RootDir = ?config(priv_dir, Config), ?line NewDir = filename:join(RootDir, atom_to_list(?MODULE) @@ -2476,6 +2623,7 @@ symlinks(Config) when is_list(Config) -> ?line {ok, Info2} = ?FILE_MODULE:read_link_info(Alias), ?line #file_info{links=1, type=symlink} = Info2, ?line {ok, Name} = ?FILE_MODULE:read_link(Alias), + {ok, Name} = ?FILE_MODULE:read_link_all(Alias), ok end, @@ -3370,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 40bde8a736..a6728564e4 100644 --- a/lib/kernel/test/file_name_SUITE.erl +++ b/lib/kernel/test/file_name_SUITE.erl @@ -3,7 +3,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2012. All Rights Reserved. +%% Copyright Ericsson AB 1996-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -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,33 +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), - ?line SF3 = unicode:characters_to_binary("åäösubfil3", - file:native_name_encoding()), - ?line SF2 = case treat_icky(<<"åäösubfil2">>) of - LF2 when is_list(LF2) -> - unicode:characters_to_binary(LF2, - file:native_name_encoding()); - BF2 -> - BF2 - end, - ?line Sorted = lists:sort([SF3,SF2]), - ?line Sorted = lists:sort(filelib:wildcard("*",<<"åäösubdir2">>)), ok catch throw:need_unicode_mode -> @@ -604,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; @@ -619,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 ], @@ -637,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 ], diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl index 4e93a593b3..ac75037536 100644 --- a/lib/kernel/test/prim_file_SUITE.erl +++ b/lib/kernel/test/prim_file_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2011. All Rights Reserved. +%% Copyright Ericsson AB 2000-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -49,7 +49,9 @@ make_link_a/1, make_link_b/1, read_link_info_for_non_link/1, symlinks_a/1, symlinks_b/1, - list_dir_limit/1]). + list_dir_limit/1, + list_dir_error/1, + list_dir/1]). -export([advise/1]). -export([large_write/1]). @@ -81,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, [], @@ -110,7 +112,7 @@ groups() -> write_compressed, compress_errors]}, {links, [], [make_link_a, make_link_b, read_link_info_for_non_link, - symlinks_a, symlinks_b]}]. + symlinks_a, symlinks_b, list_dir_error]}]. init_per_group(_GroupName, Config) -> Config. @@ -2035,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, @@ -2140,6 +2144,41 @@ list_dir_limit_cleanup(Dir, Handle, N, Cnt) -> list_dir_limit_cleanup(Dir, Handle, N, Cnt+1). %%% +%%% Test list_dir() on a non-existing pathname. +%%% + +list_dir_error(Config) -> + Priv = ?config(priv_dir, Config), + NonExisting = filename:join(Priv, "non-existing-dir"), + {error,enoent} = prim_file:list_dir(NonExisting), + 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. %%% diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk index 46a991eb38..b6cf4407d2 100644 --- a/lib/kernel/vsn.mk +++ b/lib/kernel/vsn.mk @@ -1 +1 @@ -KERNEL_VSN = 2.16 +KERNEL_VSN = 2.16.1 |