diff options
Diffstat (limited to 'erts/preloaded/src')
-rw-r--r-- | erts/preloaded/src/erl_prim_loader.erl | 269 | ||||
-rw-r--r-- | erts/preloaded/src/erlang.erl | 62 | ||||
-rw-r--r-- | erts/preloaded/src/init.erl | 19 | ||||
-rw-r--r-- | erts/preloaded/src/otp_ring0.erl | 11 | ||||
-rw-r--r-- | erts/preloaded/src/prim_zip.erl | 57 | ||||
-rw-r--r-- | erts/preloaded/src/zlib.erl | 11 |
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 |