aboutsummaryrefslogtreecommitdiffstats
path: root/erts/preloaded/src
diff options
context:
space:
mode:
Diffstat (limited to 'erts/preloaded/src')
-rw-r--r--erts/preloaded/src/erl_prim_loader.erl269
-rw-r--r--erts/preloaded/src/erlang.erl62
-rw-r--r--erts/preloaded/src/init.erl19
-rw-r--r--erts/preloaded/src/otp_ring0.erl11
-rw-r--r--erts/preloaded/src/prim_zip.erl57
-rw-r--r--erts/preloaded/src/zlib.erl11
6 files changed, 260 insertions, 169 deletions
diff --git a/erts/preloaded/src/erl_prim_loader.erl b/erts/preloaded/src/erl_prim_loader.erl
index 399c2bb55d..a13292d5ab 100644
--- a/erts/preloaded/src/erl_prim_loader.erl
+++ b/erts/preloaded/src/erl_prim_loader.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1996-2010. 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
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -49,24 +49,27 @@
prim_read_file_info/2, prim_get_cwd/2]).
%% Used by escript and code
--export([set_primary_archive/2, release_archives/0]).
-
-%% Internal function. Exported to avoid dialyzer warnings
--export([concat/1]).
+-export([set_primary_archive/3, release_archives/0]).
-include_lib("kernel/include/file.hrl").
-type host() :: atom().
+-record(prim_state, {debug :: boolean(),
+ cache,
+ primary_archive}).
+-type prim_state() :: #prim_state{}.
+
-record(state,
- {loader :: 'efile' | 'inet',
- hosts = [] :: [host()], % hosts list (to boot from)
+ {loader :: 'efile' | 'inet',
+ hosts = [] :: [host()], % hosts list (to boot from)
id, % not used any more?
- data, % data port etc
- timeout, % idle timeout
- n_timeouts, % Number of timeouts before archives are released
- multi_get = false :: boolean(),
- prim_state}). % state for efile code loader
+ data :: 'noport' | port(), % data port etc
+ timeout :: timeout(), % idle timeout
+ %% Number of timeouts before archives are released
+ n_timeouts :: non_neg_integer(),
+ multi_get = false :: boolean(),
+ prim_state :: prim_state()}). % state for efile code loader
-define(IDLE_TIMEOUT, 60000). %% tear inet connection after 1 minutes
-define(N_TIMEOUTS, 6). %% release efile archive after 6 minutes
@@ -89,8 +92,6 @@
end
end()).
--record(prim_state, {debug, cache, primary_archive}).
-
debug(#prim_state{debug = Deb}, Term) ->
case Deb of
false -> ok;
@@ -124,7 +125,7 @@ start(Id, Pgm0, Hosts) ->
start_it("ose_inet"=Cmd, Id, Pid, Hosts) ->
%% Setup reserved port for ose_inet driver (only OSE)
- case catch erlang:open_port({spawn,Cmd},[binary]) of
+ case catch erlang:open_port({spawn,Cmd}, [binary]) of
{'EXIT',Why} ->
?dbg(ose_inet_port_open_fail, Why),
Why;
@@ -220,14 +221,15 @@ get_cwd(Drive) ->
check_file_result(get_cwd, Drive, request({get_cwd,[Drive]})).
-spec set_primary_archive(File :: string() | 'undefined',
- ArchiveBin :: binary() | 'undefined')
- -> {ok, [string()]} | {error,_}.
+ ArchiveBin :: binary() | 'undefined',
+ FileInfo :: #file_info{} | 'undefined')
+ -> {ok, [string()]} | {error,_}.
-set_primary_archive(undefined, undefined) ->
- request({set_primary_archive, undefined, undefined});
-set_primary_archive(File, ArchiveBin)
- when is_list(File), is_binary(ArchiveBin) ->
- request({set_primary_archive, File, ArchiveBin}).
+set_primary_archive(undefined, undefined, undefined) ->
+ request({set_primary_archive, undefined, undefined, undefined});
+set_primary_archive(File, ArchiveBin, FileInfo)
+ when is_list(File), is_binary(ArchiveBin), is_record(FileInfo, file_info) ->
+ request({set_primary_archive, File, ArchiveBin, FileInfo}).
-spec release_archives() -> 'ok' | {'error', _}.
@@ -315,8 +317,8 @@ loop(State, Parent, Paths) ->
{get_cwd,[_]=Args} ->
{Res,State1} = handle_get_cwd(State, Args),
{Res,State1,Paths};
- {set_primary_archive,File,Bin} ->
- {Res,State1} = handle_set_primary_archive(State, File, Bin),
+ {set_primary_archive,File,Bin,FileInfo} ->
+ {Res,State1} = handle_set_primary_archive(State, File, Bin, FileInfo),
{Res,State1,Paths};
release_archives ->
{Res,State1} = handle_release_archives(State),
@@ -325,7 +327,7 @@ loop(State, Parent, Paths) ->
{ignore,State,Paths}
end,
if Resp =:= ignore -> ok;
- true -> Pid ! {self(),Resp}
+ true -> Pid ! {self(),Resp}, ok
end,
if
is_record(State2, state) ->
@@ -334,7 +336,7 @@ loop(State, Parent, Paths) ->
exit({bad_state, Req, State2})
end;
{'EXIT',Parent,W} ->
- handle_stop(State),
+ _State1 = handle_stop(State),
exit(W);
{'EXIT',P,W} ->
State1 = handle_exit(State, P, W),
@@ -356,8 +358,8 @@ handle_get_file(State = #state{loader = efile}, Paths, File) ->
handle_get_file(State = #state{loader = inet}, Paths, File) ->
?SAFE2(inet_get_file_from_port(State, File, Paths), State).
-handle_set_primary_archive(State= #state{loader = efile}, File, Bin) ->
- ?SAFE2(efile_set_primary_archive(State, File, Bin), State).
+handle_set_primary_archive(State= #state{loader = efile}, File, Bin, FileInfo) ->
+ ?SAFE2(efile_set_primary_archive(State, File, Bin, FileInfo), State).
handle_release_archives(State= #state{loader = efile}) ->
?SAFE2(efile_release_archives(State), State).
@@ -481,8 +483,8 @@ efile_get_file_from_port3(State, File, [P | Paths]) ->
efile_get_file_from_port3(State, _File, []) ->
{{error,enoent},State}.
-efile_set_primary_archive(#state{prim_state = PS} = State, File, Bin) ->
- {Res, PS2} = prim_set_primary_archive(PS, File, Bin),
+efile_set_primary_archive(#state{prim_state = PS} = State, File, Bin, FileInfo) ->
+ {Res, PS2} = prim_set_primary_archive(PS, File, Bin, FileInfo),
{Res,State#state{prim_state = PS2}}.
efile_release_archives(#state{prim_state = PS} = State) ->
@@ -572,13 +574,14 @@ find_loop(U, Retry, AL, ReqDelay, SReSleep, Ignore, Tries, LReSleep) ->
case find_loop(U, Retry, AL, ReqDelay, []) of
[] -> % no response from any server
erlang:display({erl_prim_loader,'no server found'}), % lifesign
- Tries1 = if Tries > 0 ->
- sleep(SReSleep),
- Tries - 1;
- true ->
- sleep(LReSleep),
- 0
- end,
+ Tries1 =
+ if Tries > 0 ->
+ sleep(SReSleep),
+ Tries - 1;
+ true ->
+ sleep(LReSleep),
+ 0
+ end,
find_loop(U, Retry, AL, ReqDelay, SReSleep, Ignore, Tries1, LReSleep);
Servers ->
keysort(1, Servers -- Ignore)
@@ -603,7 +606,6 @@ find_collect(U,Retry,AL,Delay,Acc) ->
_Garbage ->
?dbg(collect_garbage, _Garbage),
find_collect(U, Retry, AL, Delay, Acc)
-
after Delay ->
?dbg(collected, Acc),
case keymember(0, 1, Acc) of %% got high priority server?
@@ -617,7 +619,7 @@ sleep(Time) ->
receive after Time -> ok end.
inet_exit_port(State, Port, _Reason) when State#state.data =:= Port ->
- State#state { data = noport, timeout = infinity };
+ State#state{data = noport, timeout = infinity};
inet_exit_port(State, _, _) ->
State.
@@ -627,7 +629,7 @@ inet_timeout_handler(State, _Parent) ->
if is_port(Tcp) -> ll_close(Tcp);
true -> ok
end,
- State#state { timeout = infinity, data = noport }.
+ State#state{timeout = infinity, data = noport}.
%% -> {{ok,BinFile,Tag},State} | {{error,Reason},State}
inet_get_file_from_port(State, File, Paths) ->
@@ -657,9 +659,9 @@ inet_get_file_from_port1(_File, [], State) ->
inet_send_and_rcv(Msg, Tag, State) when State#state.data =:= noport ->
{ok,Tcp} = find_master(State#state.hosts), %% reconnect
- inet_send_and_rcv(Msg, Tag, State#state { data = Tcp,
- timeout = ?IDLE_TIMEOUT });
-inet_send_and_rcv(Msg, Tag, #state{data=Tcp,timeout=Timeout}=State) ->
+ inet_send_and_rcv(Msg, Tag, State#state{data = Tcp,
+ timeout = ?IDLE_TIMEOUT});
+inet_send_and_rcv(Msg, Tag, #state{data = Tcp, timeout = Timeout} = State) ->
prim_inet:send(Tcp, term_to_binary(Msg)),
receive
{tcp,Tcp,BinMsg} ->
@@ -677,13 +679,13 @@ inet_send_and_rcv(Msg, Tag, #state{data=Tcp,timeout=Timeout}=State) ->
end;
{tcp_closed,Tcp} ->
%% Ok we must reconnect
- inet_send_and_rcv(Msg, Tag, State#state { data = noport });
+ inet_send_and_rcv(Msg, Tag, State#state{data = noport});
{tcp_error,Tcp,_Reason} ->
%% Ok we must reconnect
inet_send_and_rcv(Msg, Tag, inet_stop_port(State));
{'EXIT', Tcp, _} ->
%% Ok we must reconnect
- inet_send_and_rcv(Msg, Tag, State#state { data = noport })
+ inet_send_and_rcv(Msg, Tag, State#state{data = noport})
after Timeout ->
%% Ok we must reconnect
inet_send_and_rcv(Msg, Tag, inet_stop_port(State))
@@ -770,6 +772,7 @@ port_error(S, Error) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-spec prim_init() -> prim_state().
prim_init() ->
Deb =
case init:get_argument(loader_debug) of
@@ -777,19 +780,19 @@ prim_init() ->
error -> false
end,
cache_new(#prim_state{debug = Deb}).
-
+
prim_release_archives(PS) ->
debug(PS, release_archives),
- {Res, PS2}= prim_do_release_archives(PS, get(), []),
+ {Res, PS2} = prim_do_release_archives(PS, get(), []),
debug(PS2, {return, Res}),
{Res, PS2}.
prim_do_release_archives(PS, [{ArchiveFile, DictVal} | KeyVals], Acc) ->
Res =
case DictVal of
- {primary, _PrimZip} ->
+ {primary, _PrimZip, _FI} ->
ok; % Keep primary archive
- {_Mtime, Cache} ->
+ {Cache, _FI} ->
debug(PS, {release, cache, ArchiveFile}),
erase(ArchiveFile),
clear_cache(ArchiveFile, Cache)
@@ -805,7 +808,7 @@ prim_do_release_archives(PS, [], []) ->
prim_do_release_archives(PS, [], Errors) ->
{{error, Errors}, PS#prim_state{primary_archive = undefined}}.
-prim_set_primary_archive(PS, undefined, undefined) ->
+prim_set_primary_archive(PS, undefined, undefined, undefined) ->
debug(PS, {set_primary_archive, clean}),
case PS#prim_state.primary_archive of
undefined ->
@@ -813,14 +816,14 @@ prim_set_primary_archive(PS, undefined, undefined) ->
debug(PS, {return, Res}),
{Res, PS};
ArchiveFile ->
- {primary, PrimZip} = erase(ArchiveFile),
+ {primary, PrimZip, _FI} = erase(ArchiveFile),
ok = prim_zip:close(PrimZip),
PS2 = PS#prim_state{primary_archive = undefined},
Res = {ok, []},
debug(PS2, {return, Res}),
{Res, PS2}
end;
-prim_set_primary_archive(PS, ArchiveFile, ArchiveBin)
+prim_set_primary_archive(PS, ArchiveFile, ArchiveBin, #file_info{} = FileInfo)
when is_list(ArchiveFile), is_binary(ArchiveBin) ->
%% Try the archive file
debug(PS, {set_primary_archive, ArchiveFile, byte_size(ArchiveBin)}),
@@ -833,17 +836,17 @@ prim_set_primary_archive(PS, ArchiveFile, ArchiveBin)
["", "nibe", RevApp] -> % Reverse ebin
%% Collect ebin directories in archive
Ebin = reverse(RevApp) ++ "/ebin",
- {true, [Ebin | A]};
+ {true, [Ebin | A]};
_ ->
{true, A}
end
end,
Ebins0 = [ArchiveFile],
- case open_archive({ArchiveFile, ArchiveBin}, Ebins0, Fun) of
- {ok, PrimZip, RevEbins} ->
+ case open_archive({ArchiveFile, ArchiveBin}, FileInfo, Ebins0, Fun) of
+ {ok, PrimZip, {RevEbins, FI, _}} ->
Ebins = reverse(RevEbins),
debug(PS, {set_primary_archive, Ebins}),
- put(ArchiveFile, {primary, PrimZip}),
+ put(ArchiveFile, {primary, PrimZip, FI}),
{{ok, Ebins}, PS#prim_state{primary_archive = ArchiveFile}};
Error ->
debug(PS, {set_primary_archive, Error}),
@@ -851,14 +854,15 @@ prim_set_primary_archive(PS, ArchiveFile, ArchiveBin)
end;
OldArchiveFile ->
debug(PS, {set_primary_archive, clean}),
- PrimZip = erase(OldArchiveFile),
+ {primary, PrimZip, _FI} = erase(OldArchiveFile),
ok = prim_zip:close(PrimZip),
PS2 = PS#prim_state{primary_archive = undefined},
- prim_set_primary_archive(PS2, ArchiveFile, ArchiveBin)
+ prim_set_primary_archive(PS2, ArchiveFile, ArchiveBin, FileInfo)
end,
debug(PS3, {return, Res3}),
{Res3, PS3}.
+-spec prim_get_file(prim_state(), file:filename()) -> {_, prim_state()}.
prim_get_file(PS, File) ->
debug(PS, {get_file, File}),
{Res2, PS2} =
@@ -883,7 +887,9 @@ prim_get_file(PS, File) ->
debug(PS, {return, Res2}),
{Res2, PS2}.
-%% -> {{ok,List},State} | {{error,Reason},State}
+-spec prim_list_dir(prim_state(), file:filename()) ->
+ {{'ok', [file:filename()]}, prim_state()}
+ | {{'error', term()}, prim_state()}.
prim_list_dir(PS, Dir) ->
debug(PS, {list_dir, Dir}),
{Res2, PS3} =
@@ -934,7 +940,9 @@ prim_list_dir(PS, Dir) ->
debug(PS, {return, Res2}),
{Res2, PS3}.
-%% -> {{ok,Info},State} | {{error,Reason},State}
+-spec prim_read_file_info(prim_state(), file:filename()) ->
+ {{'ok', #file_info{}}, prim_state()}
+ | {{'error', term()}, prim_state()}.
prim_read_file_info(PS, File) ->
debug(PS, {read_file_info, File}),
{Res2, PS2} =
@@ -956,15 +964,15 @@ prim_read_file_info(PS, File) ->
FunnyFile = funny_split(FileInArchive, $/),
Fun =
fun({Funny, GetInfo, _GetBin}, Acc) ->
- if
- hd(Funny) =:= "",
- tl(Funny) =:= FunnyFile ->
+ case Funny of
+ [H | T] when H =:= "",
+ T =:= FunnyFile ->
%% Directory
{false, {ok, GetInfo()}};
- Funny =:= FunnyFile ->
+ F when F =:= FunnyFile ->
%% Plain file
{false, {ok, GetInfo()}};
- true ->
+ _ ->
%% No match
{true, Acc}
end
@@ -974,6 +982,8 @@ prim_read_file_info(PS, File) ->
debug(PS2, {return, Res2}),
{Res2, PS2}.
+-spec prim_get_cwd(prim_state(), [file:filename()]) ->
+ {{'error', term()} | {'ok', _}, prim_state()}.
prim_get_cwd(PS, []) ->
debug(PS, {get_cwd, []}),
Res = prim_file:get_cwd(),
@@ -990,33 +1000,36 @@ prim_get_cwd(PS, [Drive]) ->
apply_archive(PS, Fun, Acc, Archive) ->
case get(Archive) of
undefined ->
+ case open_archive(Archive, Acc, Fun) of
+ {ok, PrimZip, {Acc2, FI, _}} ->
+ debug(PS, {cache, ok}),
+ put(Archive, {{ok, PrimZip}, FI}),
+ {Acc2, PS};
+ Error ->
+ debug(PS, {cache, Error}),
+ %% put(Archive, {Error, FI}),
+ {Error, PS}
+ end;
+ {primary, PrimZip, FI} ->
+ case prim_file:read_file_info(Archive) of
+ {ok, FI2}
+ when FI#file_info.mtime =:= FI2#file_info.mtime ->
+ case foldl_archive(PrimZip, Acc, Fun) of
+ {ok, _PrimZip2, Acc2} ->
+ {Acc2, PS};
+ Error ->
+ debug(PS, {primary, Error}),
+ {Error, PS}
+ end;
+ Error ->
+ debug(PS, {cache, {clear, Error}}),
+ clear_cache(Archive, {ok, PrimZip}),
+ apply_archive(PS, Fun, Acc, Archive)
+ end;
+ {Cache, FI} ->
case prim_file:read_file_info(Archive) of
- {ok, #file_info{mtime = Mtime}} ->
- case open_archive(Archive, Acc, Fun) of
- {ok, PrimZip, Acc2} ->
- debug(PS, {cache, ok}),
- put(Archive, {Mtime, {ok, PrimZip}}),
- {Acc2, PS};
- Error ->
- debug(PS, {cache, Error}),
- put(Archive, {Mtime, Error}),
- {Error, PS}
- end;
- Error ->
- debug(PS, {cache, Error}),
- {Error, PS}
- end;
- {primary, PrimZip} ->
- case foldl_archive(PrimZip, Acc, Fun) of
- {ok, _PrimZip2, Acc2} ->
- {Acc2, PS};
- Error ->
- debug(PS, {primary, Error}),
- {Error, PS}
- end;
- {Mtime, Cache} ->
- case prim_file:read_file_info(Archive) of
- {ok, #file_info{mtime = Mtime2}} when Mtime2 =:= Mtime ->
+ {ok, FI2}
+ when FI#file_info.mtime =:= FI2#file_info.mtime ->
case Cache of
{ok, PrimZip} ->
case foldl_archive(PrimZip, Acc, Fun) of
@@ -1024,9 +1037,10 @@ apply_archive(PS, Fun, Acc, Archive) ->
{Acc2, PS};
Error ->
debug(PS, {cache, {clear, Error}}),
- clear_cache(Archive, Cache),
+ ok = clear_cache(Archive, Cache),
debug(PS, {cache, Error}),
- put(Archive, {Mtime, Error}),
+ erase(Archive),
+ %% put(Archive, {Error, FI}),
{Error, PS}
end;
Error ->
@@ -1035,26 +1049,63 @@ apply_archive(PS, Fun, Acc, Archive) ->
end;
Error ->
debug(PS, {cache, {clear, Error}}),
- clear_cache(Archive, Cache),
+ ok = clear_cache(Archive, Cache),
apply_archive(PS, Fun, Acc, Archive)
end
end.
open_archive(Archive, Acc, Fun) ->
+ case prim_file:read_file_info(Archive) of
+ {ok, FileInfo} ->
+ open_archive(Archive, FileInfo, Acc, Fun);
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+open_archive(Archive, FileInfo, Acc, Fun) ->
+ FakeFI = FileInfo#file_info{type = directory},
Wrapper =
- fun({N, GI, GB}, A) ->
- %% Ensure full iteration at open
- Funny = funny_split(N, $/),
- {_Continue, A2} = Fun({Funny, GI, GB}, A),
- {true, {true, Funny}, A2}
- end,
- prim_zip:open(Wrapper, Acc, Archive).
+ fun({N, GI, GB}, {A, I, FunnyDirs}) -> % Full iteration at open
+ Funny = funny_split(N, $/),
+ FunnyDirs2 =
+ case Funny of
+ ["" | FunnyDir] ->
+ [FunnyDir | FunnyDirs];
+ _ ->
+ FunnyDirs
+ end,
+ {Includes, FunnyDirs3, A2} =
+ ensure_virtual_dirs(Funny, Fun, FakeFI, [{true, Funny}], FunnyDirs2, A),
+ {_Continue, A3} = Fun({Funny, GI, GB}, A2),
+ {true, Includes, {A3, I, FunnyDirs3}}
+ end,
+ prim_zip:open(Wrapper, {Acc, FakeFI, []}, Archive).
+
+ensure_virtual_dirs(Funny, Fun, FakeFI, Includes, FunnyDirs, Acc) ->
+ case Funny of
+ [_ | FunnyDir] ->
+ case lists:member(FunnyDir, FunnyDirs) of % BIF
+ false ->
+ GetInfo = fun() -> FakeFI end,
+ GetBin = fun() -> <<>> end,
+ VirtualDir = ["" | FunnyDir],
+ Includes2 = [{true, VirtualDir, GetInfo, GetBin} | Includes],
+ FunnyDirs2 = [FunnyDir | FunnyDirs],
+ {I, F, Acc2} = ensure_virtual_dirs(FunnyDir, Fun, FakeFI, Includes2, FunnyDirs2, Acc),
+ {_Continue, Acc3} = Fun({VirtualDir, GetInfo, GetBin}, Acc2),
+ {I, F, Acc3};
+ true ->
+ {reverse(Includes), FunnyDirs, Acc}
+ end;
+ [] ->
+ {reverse(Includes), FunnyDirs, Acc}
+ end.
foldl_archive(PrimZip, Acc, Fun) ->
Wrapper =
- fun({N, GI, GB}, A) ->
+ fun({Funny, GI, GB}, A) ->
%% Allow partial iteration at foldl
- {Continue, A2} = Fun({N, GI, GB}, A),
+ {Continue, A2} = Fun({Funny, GI, GB}, A),
{Continue, true, A2}
end,
prim_zip:foldl(Wrapper, Acc, PrimZip).
@@ -1100,8 +1151,8 @@ send_all(U, [IP | AL], Cmd) ->
send_all(U, AL, Cmd);
send_all(_U, [], _) -> ok.
-concat([A|T]) when is_atom(A) -> %Atom
- atom_to_list(A) ++ concat(T);
+%%concat([A|T]) when is_atom(A) -> %Atom
+%% atom_to_list(A) ++ concat(T);
concat([C|T]) when C >= 0, C =< 255 ->
[C|concat(T)];
concat([S|T]) -> %String
diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index 6f92b319b7..1edb5e72db 100644
--- a/erts/preloaded/src/erlang.erl
+++ b/erts/preloaded/src/erlang.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1996-2010. 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
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
-module(erlang).
@@ -29,39 +29,39 @@
-export([send_nosuspend/2, send_nosuspend/3]).
-export([localtime_to_universaltime/1]).
-export([suspend_process/1]).
--export([min/2,max/2]).
-
+-export([min/2, max/2]).
-export([dlink/1, dunlink/1, dsend/2, dsend/3, dgroup_leader/2,
dexit/2, dmonitor_node/3, dmonitor_p/2]).
-
-export([delay_trap/2]).
-
-export([set_cookie/2, get_cookie/0]).
-
-export([nodes/0]).
-
-export([concat_binary/1]).
-
-export([list_to_integer/2,integer_to_list/2]).
-
-export([flush_monitor_message/2]).
-
-export([set_cpu_topology/1, format_cpu_topology/1]).
-
-export([await_proc_exit/3]).
-deprecated([hash/2]).
+-deprecated([concat_binary/1]).
-compile(nowarn_bif_clash).
+%%--------------------------------------------------------------------------
+
+-type date() :: {pos_integer(), pos_integer(), pos_integer()}.
+-type time() :: {non_neg_integer(), non_neg_integer(), non_neg_integer()}.
+-type date_time() :: {date(), time()}.
+
+%%--------------------------------------------------------------------------
+
apply(Fun, Args) ->
apply(Fun, Args).
apply(Mod, Name, Args) ->
apply(Mod, Name, Args).
+%% Spawns with a fun
-% Spawns with a fun
spawn(F) when is_function(F) ->
spawn(erlang, apply, [F, []]);
spawn({M,F}=MF) when is_atom(M), is_atom(F) ->
@@ -124,7 +124,7 @@ spawn_opt(N, {M,F}=MF, O) when is_atom(M), is_atom(F) ->
spawn_opt(N, F, O) ->
erlang:error(badarg, [N, F, O]).
-% Spawns with MFA
+%% Spawns with MFA
spawn(N,M,F,A) when N =:= node(), is_atom(M), is_atom(F), is_list(A) ->
spawn(M,F,A);
@@ -253,12 +253,17 @@ crasher(Node,Mod,Fun,Args,Opts,Reason) ->
[Mod,Fun,Args,Opts,Node]),
exit(Reason).
+-spec yield() -> 'true'.
yield() ->
erlang:yield().
-nodes() -> erlang:nodes(visible).
+-spec nodes() -> [node()].
+nodes() ->
+ erlang:nodes(visible).
-disconnect_node(Node) -> net_kernel:disconnect(Node).
+-spec disconnect_node(node()) -> boolean().
+disconnect_node(Node) ->
+ net_kernel:disconnect(Node).
fun_info(Fun) when is_function(Fun) ->
Keys = [type,env,arity,name,uniq,index,new_uniq,new_index,module,pid],
@@ -284,9 +289,11 @@ send_nosuspend(Pid, Msg, Opts) ->
_ -> false
end.
+-spec localtime_to_universaltime(date_time()) -> date_time().
localtime_to_universaltime(Localtime) ->
erlang:localtime_to_universaltime(Localtime, undefined).
+-spec suspend_process(pid()) -> 'true'.
suspend_process(P) ->
case catch erlang:suspend_process(P, []) of
{'EXIT', {Reason, _}} -> erlang:error(Reason, [P]);
@@ -297,10 +304,11 @@ suspend_process(P) ->
%%
%% If the emulator wants to perform a distributed command and
%% a connection is not established to the actual node the following
-%% functions is called in order to set up the connection and then
+%% functions are called in order to set up the connection and then
%% reactivate the command.
%%
+-spec dlink(pid() | port()) -> 'true'.
dlink(Pid) ->
case net_kernel:connect(node(Pid)) of
true -> link(Pid);
@@ -308,6 +316,7 @@ dlink(Pid) ->
end.
%% Can this ever happen?
+-spec dunlink(identifier()) -> 'true'.
dunlink(Pid) ->
case net_kernel:connect(node(Pid)) of
true -> unlink(Pid);
@@ -321,7 +330,7 @@ dmonitor_node(Node, Flag, []) ->
end;
dmonitor_node(Node, Flag, Opts) ->
- case lists:member(allow_passive_connect,Opts) of
+ case lists:member(allow_passive_connect, Opts) of
true ->
case net_kernel:passive_cnct(Node) of
true -> erlang:monitor_node(Node, Flag, Opts);
@@ -377,11 +386,11 @@ dsend({Name, Node}, Msg, Opts) ->
ignored -> ok % Not distributed.
end.
+-spec dmonitor_p('process', pid() | {atom(),atom()}) -> reference().
dmonitor_p(process, ProcSpec) ->
%% ProcSpec = pid() | {atom(),atom()}
%% ProcSpec CANNOT be an atom because a locally registered process
%% is never handled here.
-
Node = case ProcSpec of
{S,N} when is_atom(S), is_atom(N), N =/= node() -> N;
_ when is_pid(ProcSpec) -> node(ProcSpec)
@@ -399,6 +408,7 @@ dmonitor_p(process, ProcSpec) ->
%% Trap function used when modified timing has been enabled.
%%
+-spec delay_trap(Result, timeout()) -> Result.
delay_trap(Result, 0) -> erlang:yield(), Result;
delay_trap(Result, Timeout) -> receive after Timeout -> Result end.
@@ -422,13 +432,15 @@ set_cookie(Node, C) when Node =/= nonode@nohost, is_atom(Node) ->
error -> exit(badarg);
Other -> Other
end.
-
+
+-spec get_cookie() -> atom().
get_cookie() ->
auth:get_cookie().
concat_binary(List) ->
list_to_binary(List).
+-spec integer_to_list(integer(), 1..255) -> string().
integer_to_list(I, 10) ->
erlang:integer_to_list(I);
integer_to_list(I, Base)
@@ -456,7 +468,6 @@ integer_to_list(I0, Base, R0) ->
end.
-
list_to_integer(L, 10) ->
erlang:list_to_integer(L);
list_to_integer(L, Base)
@@ -661,6 +672,7 @@ rvrs([X|Xs],Ys) -> rvrs(Xs, [X|Ys]).
%% functions in bif.c. Do not make
%% any changes to it without reading
%% the comment about them in bif.c!
+-spec await_proc_exit(dst(), 'apply' | 'data' | 'reason', term()) -> term().
await_proc_exit(Proc, Op, Data) ->
Mon = erlang:monitor(process, Proc),
receive
@@ -676,8 +688,10 @@ await_proc_exit(Proc, Op, Data) ->
end
end.
+-spec min(term(), term()) -> term().
min(A, B) when A > B -> B;
min(A, _) -> A.
+-spec max(term(), term()) -> term().
max(A, B) when A < B -> B;
max(A, _) -> A.
diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl
index c6f4c62f63..3b98b9cddc 100644
--- a/erts/preloaded/src/init.erl
+++ b/erts/preloaded/src/init.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1996-2010. 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
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
%%
@@ -51,7 +51,7 @@
get_status/0,boot/1,get_arguments/0,get_plain_arguments/0,
get_argument/1,script_id/0]).
-% internal exports
+%% internal exports
-export([fetch_loaded/0,ensure_loaded/1,make_permanent/2,
notify_when_started/1,wait_until_started/0,
objfile_extension/0, archive_extension/0,code_path_choice/0]).
@@ -115,6 +115,8 @@ fetch_loaded() ->
ensure_loaded(Module) ->
request({ensure_loaded, Module}).
+-spec make_permanent(file:filename(), 'false' | file:filename()) ->
+ 'ok' | {'error', term()}.
make_permanent(Boot,Config) ->
request({make_permanent,Boot,Config}).
@@ -1357,10 +1359,7 @@ run_on_load_handlers([M|Ms]) ->
{Pid,Ref} = spawn_monitor(Fun),
receive
{'DOWN',Ref,process,Pid,OnLoadRes} ->
- Keep = if
- is_boolean(OnLoadRes) -> OnLoadRes;
- true -> false
- end,
+ Keep = OnLoadRes =:= ok,
erlang:finish_after_on_load(M, Keep),
case Keep of
false ->
diff --git a/erts/preloaded/src/otp_ring0.erl b/erts/preloaded/src/otp_ring0.erl
index 3b0d562d1f..2ccf142f30 100644
--- a/erts/preloaded/src/otp_ring0.erl
+++ b/erts/preloaded/src/otp_ring0.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2000-2010. 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
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
-module(otp_ring0).
@@ -22,6 +22,7 @@
-export([start/2]).
+-spec start(_, term()) -> term().
start(_Env, Argv) ->
run(init, boot, Argv).
diff --git a/erts/preloaded/src/prim_zip.erl b/erts/preloaded/src/prim_zip.erl
index 17ef8c6c43..3f5a5b9721 100644
--- a/erts/preloaded/src/prim_zip.erl
+++ b/erts/preloaded/src/prim_zip.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2008-2010. 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
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -94,12 +94,7 @@ do_foldl(FilterFun, FilterAcc, [PF | Tail], Acc0, PrimZip, PrimZipOrig) ->
#primzip_file{name = F, get_info = GetInfo, get_bin = GetBin} = PF,
case FilterFun({F, GetInfo, GetBin}, FilterAcc) of
{Continue, Include, FilterAcc2} ->
- Acc1 =
- case Include of
- false -> Acc0;
- true -> [PF | Acc0];
- {true, Nick} -> [PF#primzip_file{name = Nick} | Acc0]
- end,
+ Acc1 = include_acc(Include, PF, Acc0),
case Continue of
true ->
do_foldl(FilterFun, FilterAcc2, Tail, Acc1, PrimZip, PrimZipOrig);
@@ -112,6 +107,28 @@ do_foldl(FilterFun, FilterAcc, [PF | Tail], Acc0, PrimZip, PrimZipOrig) ->
do_foldl(_FilterFun, FilterAcc, [], Acc, PrimZip, _PrimZipOrig) ->
{ok, FilterAcc, PrimZip#primzip{files = reverse(Acc)}}.
+include_acc(Include, PF, Acc) ->
+ case Include of
+ false ->
+ Acc;
+ true ->
+ [PF | Acc];
+ {true, Nick} ->
+ [PF#primzip_file{name = Nick} | Acc];
+ {true, Nick, GetInfo, GetBin} ->
+ PF2 = #primzip_file{name = Nick, get_info = GetInfo, get_bin = GetBin},
+ [PF2 | Acc];
+ List when is_list(List) ->
+ %% Add new entries
+ Fun = fun(I, A) -> include_acc(I, PF, A) end,
+ lists_foldl(Fun, Acc, List)
+ end.
+
+lists_foldl(F, Accu, [Hd|Tail]) ->
+ lists_foldl(F, F(Hd, Accu), Tail);
+lists_foldl(F, Accu, []) when is_function(F, 2) ->
+ Accu.
+
%% close a zip archive
close(#primzip{in = In0, input = Input, zlib = Z}) ->
Input(close, In0),
@@ -199,15 +216,25 @@ get_cd_loop(N, BCD, Acc0, PrimZip, FileName, Offset, CFH, EndOffset, FilterFun,
end,
%% erlang:display({FileName, N, Offset, Size, NextPF}),
GetInfo = fun() -> cd_file_header_to_file_info(FileName, CFH, <<>>) end,
- GetBin = fun() -> get_z_file(FileName, Offset, Size, PrimZip) end,
+ GetBin = fun() -> get_z_file(FileName, Offset, Size, PrimZip) end,
PF = #primzip_file{name = FileName, get_info = GetInfo, get_bin = GetBin},
case FilterFun({FileName, GetInfo, GetBin}, FilterAcc) of
{Continue, Include, FilterAcc2} ->
Acc1 =
case Include of
- false -> Acc0;
- true -> [PF | Acc0];
- {true, Nick} -> [PF#primzip_file{name = Nick} | Acc0]
+ false ->
+ Acc0;
+ true ->
+ [PF | Acc0];
+ {true, Nick} ->
+ [PF#primzip_file{name = Nick} | Acc0];
+ {true, Nick, GI, GB} ->
+ PF2 = #primzip_file{name = Nick, get_info = GI, get_bin = GB},
+ [PF2 | Acc0];
+ List when is_list(List) ->
+ %% Add new entries
+ Fun = fun(I, A) -> include_acc(I, PF, A) end,
+ lists_foldl(Fun, Acc0, List)
end,
case Continue of
true when N > 1 ->
diff --git a/erts/preloaded/src/zlib.erl b/erts/preloaded/src/zlib.erl
index 21971a75cf..51d6cd0a0b 100644
--- a/erts/preloaded/src/zlib.erl
+++ b/erts/preloaded/src/zlib.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2003-2010. 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
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -115,7 +115,6 @@
%%------------------------------------------------------------------------
%% Main data types of the file
--type(iodata() :: iolist() | binary()). %XXX To be removed in R13B.
-type zstream() :: port().
%% Auxiliary data types of the file