aboutsummaryrefslogtreecommitdiffstats
path: root/erts/preloaded
diff options
context:
space:
mode:
Diffstat (limited to 'erts/preloaded')
-rw-r--r--erts/preloaded/ebin/erl_prim_loader.beambin52904 -> 54136 bytes
-rw-r--r--erts/preloaded/ebin/erlang.beambin88536 -> 92996 bytes
-rw-r--r--erts/preloaded/ebin/erts_internal.beambin0 -> 3616 bytes
-rw-r--r--erts/preloaded/ebin/init.beambin48060 -> 48556 bytes
-rw-r--r--erts/preloaded/ebin/otp_ring0.beambin1444 -> 1448 bytes
-rw-r--r--erts/preloaded/ebin/prim_file.beambin41124 -> 41176 bytes
-rw-r--r--erts/preloaded/ebin/prim_inet.beambin69896 -> 70016 bytes
-rw-r--r--erts/preloaded/ebin/prim_zip.beambin23456 -> 23408 bytes
-rw-r--r--erts/preloaded/ebin/zlib.beambin12804 -> 12784 bytes
-rw-r--r--erts/preloaded/src/Makefile5
-rw-r--r--erts/preloaded/src/erl_prim_loader.erl361
-rw-r--r--erts/preloaded/src/erlang.erl351
-rw-r--r--erts/preloaded/src/erts_internal.erl155
-rw-r--r--erts/preloaded/src/init.erl16
-rw-r--r--erts/preloaded/src/prim_file.erl30
-rw-r--r--erts/preloaded/src/prim_inet.erl15
16 files changed, 649 insertions, 284 deletions
diff --git a/erts/preloaded/ebin/erl_prim_loader.beam b/erts/preloaded/ebin/erl_prim_loader.beam
index 62d161850c..344fa3ecc0 100644
--- a/erts/preloaded/ebin/erl_prim_loader.beam
+++ b/erts/preloaded/ebin/erl_prim_loader.beam
Binary files differ
diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam
index 5e485948c6..4ff729e06c 100644
--- a/erts/preloaded/ebin/erlang.beam
+++ b/erts/preloaded/ebin/erlang.beam
Binary files differ
diff --git a/erts/preloaded/ebin/erts_internal.beam b/erts/preloaded/ebin/erts_internal.beam
new file mode 100644
index 0000000000..af06c2a1cb
--- /dev/null
+++ b/erts/preloaded/ebin/erts_internal.beam
Binary files differ
diff --git a/erts/preloaded/ebin/init.beam b/erts/preloaded/ebin/init.beam
index 3bf5777b19..9710204552 100644
--- a/erts/preloaded/ebin/init.beam
+++ b/erts/preloaded/ebin/init.beam
Binary files differ
diff --git a/erts/preloaded/ebin/otp_ring0.beam b/erts/preloaded/ebin/otp_ring0.beam
index ab86e0eab4..0ba1cb8f73 100644
--- a/erts/preloaded/ebin/otp_ring0.beam
+++ b/erts/preloaded/ebin/otp_ring0.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_file.beam b/erts/preloaded/ebin/prim_file.beam
index 538aa264d3..b8f71b0c1e 100644
--- a/erts/preloaded/ebin/prim_file.beam
+++ b/erts/preloaded/ebin/prim_file.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_inet.beam b/erts/preloaded/ebin/prim_inet.beam
index 941ce02467..a1aca09d1d 100644
--- a/erts/preloaded/ebin/prim_inet.beam
+++ b/erts/preloaded/ebin/prim_inet.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_zip.beam b/erts/preloaded/ebin/prim_zip.beam
index bff09897d9..bec1f2cc21 100644
--- a/erts/preloaded/ebin/prim_zip.beam
+++ b/erts/preloaded/ebin/prim_zip.beam
Binary files differ
diff --git a/erts/preloaded/ebin/zlib.beam b/erts/preloaded/ebin/zlib.beam
index 620b495ad4..1ac89dd42a 100644
--- a/erts/preloaded/ebin/zlib.beam
+++ b/erts/preloaded/ebin/zlib.beam
Binary files differ
diff --git a/erts/preloaded/src/Makefile b/erts/preloaded/src/Makefile
index d5f5ba3c37..a224b6a5d4 100644
--- a/erts/preloaded/src/Makefile
+++ b/erts/preloaded/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2010. All Rights Reserved.
+# Copyright Ericsson AB 2008-2012. 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
@@ -40,7 +40,8 @@ PRE_LOADED_MODULES = \
zlib \
prim_zip \
otp_ring0 \
- erlang
+ erlang \
+ erts_internal
RELSYSDIR = $(RELEASE_PATH)/lib/erts-$(VSN)
# not $(RELEASE_PATH)/erts-$(VSN)/preloaded
diff --git a/erts/preloaded/src/erl_prim_loader.erl b/erts/preloaded/src/erl_prim_loader.erl
index 14a7a2bf20..d36fdeba3f 100644
--- a/erts/preloaded/src/erl_prim_loader.erl
+++ b/erts/preloaded/src/erl_prim_loader.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. 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,7 @@
prim_read_file_info/2, prim_get_cwd/2]).
%% Used by escript and code
--export([set_primary_archive/3, release_archives/0]).
+-export([set_primary_archive/4, release_archives/0]).
-include_lib("kernel/include/file.hrl").
@@ -222,15 +222,16 @@ get_cwd(Drive) ->
check_file_result(get_cwd, Drive, request({get_cwd,[Drive]})).
-spec set_primary_archive(File :: string() | 'undefined',
- ArchiveBin :: binary() | 'undefined',
- FileInfo :: #file_info{} | 'undefined')
+ ArchiveBin :: binary() | 'undefined',
+ FileInfo :: #file_info{} | 'undefined',
+ ParserFun :: fun())
-> {ok, [string()]} | {error,_}.
-set_primary_archive(undefined, undefined, undefined) ->
- request({set_primary_archive, undefined, undefined, undefined});
-set_primary_archive(File, ArchiveBin, FileInfo)
+set_primary_archive(undefined, undefined, undefined, ParserFun) ->
+ request({set_primary_archive, undefined, undefined, undefined, ParserFun});
+set_primary_archive(File, ArchiveBin, FileInfo, ParserFun)
when is_list(File), is_binary(ArchiveBin), is_record(FileInfo, file_info) ->
- request({set_primary_archive, File, ArchiveBin, FileInfo}).
+ request({set_primary_archive, File, ArchiveBin, FileInfo, ParserFun}).
-spec release_archives() -> 'ok' | {'error', _}.
@@ -318,8 +319,11 @@ loop(State, Parent, Paths) ->
{get_cwd,[_]=Args} ->
{Res,State1} = handle_get_cwd(State, Args),
{Res,State1,Paths};
- {set_primary_archive,File,Bin,FileInfo} ->
- {Res,State1} = handle_set_primary_archive(State, File, Bin, FileInfo),
+ {set_primary_archive,File,ArchiveBin,FileInfo,ParserFun} ->
+ {Res,State1} =
+ handle_set_primary_archive(State, File,
+ ArchiveBin, FileInfo,
+ ParserFun),
{Res,State1,Paths};
release_archives ->
{Res,State1} = handle_release_archives(State),
@@ -359,8 +363,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, FileInfo) ->
- ?SAFE2(efile_set_primary_archive(State, File, Bin, FileInfo), State).
+handle_set_primary_archive(State= #state{loader = efile}, File, ArchiveBin, FileInfo, ParserFun) ->
+ ?SAFE2(efile_set_primary_archive(State, File, ArchiveBin, FileInfo, ParserFun), State).
handle_release_archives(State= #state{loader = efile}) ->
?SAFE2(efile_release_archives(State), State).
@@ -484,8 +488,10 @@ 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, FileInfo) ->
- {Res, PS2} = prim_set_primary_archive(PS, File, Bin, FileInfo),
+efile_set_primary_archive(#state{prim_state = PS} = State, File,
+ ArchiveBin, FileInfo, ParserFun) ->
+ {Res, PS2} = prim_set_primary_archive(PS, File, ArchiveBin,
+ FileInfo, ParserFun),
{Res,State#state{prim_state = PS2}}.
efile_release_archives(#state{prim_state = PS} = State) ->
@@ -791,7 +797,7 @@ prim_release_archives(PS) ->
prim_do_release_archives(PS, [{ArchiveFile, DictVal} | KeyVals], Acc) ->
Res =
case DictVal of
- {primary, _PrimZip, _FI} ->
+ {primary, _PrimZip, _FI, _ParserFun} ->
ok; % Keep primary archive
{Cache, _FI} ->
debug(PS, {release, cache, ArchiveFile}),
@@ -809,7 +815,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, undefined) ->
+prim_set_primary_archive(PS, undefined, undefined, undefined, _ParserFun) ->
debug(PS, {set_primary_archive, clean}),
case PS#prim_state.primary_archive of
undefined ->
@@ -817,48 +823,40 @@ prim_set_primary_archive(PS, undefined, undefined, undefined) ->
debug(PS, {return, Res}),
{Res, PS};
ArchiveFile ->
- {primary, PrimZip, _FI} = erase(ArchiveFile),
+ {primary, PrimZip, _FI, _ParserFun2} = 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, #file_info{} = FileInfo)
- when is_list(ArchiveFile), is_binary(ArchiveBin) ->
+
+prim_set_primary_archive(PS, ArchiveFile0, ArchiveBin,
+ #file_info{} = FileInfo, ParserFun)
+ when is_list(ArchiveFile0), is_binary(ArchiveBin) ->
%% Try the archive file
- debug(PS, {set_primary_archive, ArchiveFile, byte_size(ArchiveBin)}),
+ debug(PS, {set_primary_archive, ArchiveFile0, byte_size(ArchiveBin)}),
+ ArchiveFile = real_path(absname(ArchiveFile0)),
{Res3, PS3} =
case PS#prim_state.primary_archive of
undefined ->
- Fun =
- fun({Funny, _GI, _GB}, A) ->
- case Funny of
- ["", "nibe", RevApp] -> % Reverse ebin
- %% Collect ebin directories in archive
- Ebin = reverse(RevApp) ++ "/ebin",
- {true, [Ebin | A]};
- _ ->
- {true, A}
- end
- end,
- Ebins0 = [ArchiveFile],
- case open_archive({ArchiveFile, ArchiveBin}, FileInfo, Ebins0, Fun) of
- {ok, PrimZip, {RevEbins, FI, _}} ->
- Ebins = reverse(RevEbins),
+ case load_prim_archive(ArchiveFile, ArchiveBin, FileInfo) of
+ {ok, PrimZip, FI, Ebins} ->
debug(PS, {set_primary_archive, Ebins}),
- put(ArchiveFile, {primary, PrimZip, FI}),
- {{ok, Ebins}, PS#prim_state{primary_archive = ArchiveFile}};
+ put(ArchiveFile, {primary, PrimZip, FI, ParserFun}),
+ {{ok, Ebins},
+ PS#prim_state{primary_archive = ArchiveFile}};
Error ->
debug(PS, {set_primary_archive, Error}),
{Error, PS}
end;
OldArchiveFile ->
debug(PS, {set_primary_archive, clean}),
- {primary, PrimZip, _FI} = erase(OldArchiveFile),
+ {primary, PrimZip, _FI, _ParserFun} = erase(OldArchiveFile),
ok = prim_zip:close(PrimZip),
PS2 = PS#prim_state{primary_archive = undefined},
- prim_set_primary_archive(PS2, ArchiveFile, ArchiveBin, FileInfo)
+ prim_set_primary_archive(PS2, ArchiveFile, ArchiveBin,
+ FileInfo, ParserFun)
end,
debug(PS3, {return, Res3}),
{Res3, PS3}.
@@ -873,11 +871,11 @@ prim_get_file(PS, File) ->
{Res, PS};
{archive, ArchiveFile, FileInArchive} ->
debug(PS, {archive_get_file, ArchiveFile, FileInArchive}),
- FunnyFile = funny_split(FileInArchive, $/),
+ FileComponents = path_split(FileInArchive),
Fun =
- fun({Funny, _GetInfo, GetBin}, Acc) ->
+ fun({Components, _GetInfo, GetBin}, Acc) ->
if
- Funny =:= FunnyFile ->
+ Components =:= FileComponents ->
{false, {ok, GetBin()}};
true ->
{true, Acc}
@@ -900,11 +898,11 @@ prim_list_dir(PS, Dir) ->
{Res, PS};
{archive, ArchiveFile, FileInArchive} ->
debug(PS, {archive_list_dir, ArchiveFile, FileInArchive}),
- FunnyDir = funny_split(FileInArchive, $/),
+ DirComponents = path_split(FileInArchive),
Fun =
- fun({Funny, _GetInfo, _GetBin}, {Status, Names} = Acc) ->
- case Funny of
- [RevName | FD] when FD =:= FunnyDir ->
+ fun({Components, _GetInfo, _GetBin}, {Status, Names} = Acc) ->
+ case Components of
+ [RevName | DC] when DC =:= DirComponents ->
case RevName of
"" ->
%% The listed directory
@@ -914,16 +912,16 @@ prim_list_dir(PS, Dir) ->
Name = reverse(RevName),
{true, {Status, [Name | Names]}}
end;
- ["", RevName | FD] when FD =:= FunnyDir ->
+ ["", RevName | DC] when DC =:= DirComponents ->
%% Directory
Name = reverse(RevName),
{true, {Status, [Name | Names]}};
- [RevName] when FunnyDir =:= [""] ->
- %% Top file
+ [RevName] when DirComponents =:= [""] ->
+ %% File in top directory
Name = reverse(RevName),
{true, {ok, [Name | Names]}};
- ["", RevName] when FunnyDir =:= [""] ->
- %% Top file
+ ["", RevName] when DirComponents =:= [""] ->
+ %% Directory in top directory
Name = reverse(RevName),
{true, {ok, [Name | Names]}};
_ ->
@@ -962,15 +960,14 @@ prim_read_file_info(PS, File) ->
end;
{archive, ArchiveFile, FileInArchive} ->
debug(PS, {archive_read_file_info, File}),
- FunnyFile = funny_split(FileInArchive, $/),
+ FileComponents = path_split(FileInArchive),
Fun =
- fun({Funny, GetInfo, _GetBin}, Acc) ->
- case Funny of
- [H | T] when H =:= "",
- T =:= FunnyFile ->
+ fun({Components, GetInfo, _GetBin}, Acc) ->
+ case Components of
+ ["" | F] when F =:= FileComponents ->
%% Directory
{false, {ok, GetInfo()}};
- F when F =:= FunnyFile ->
+ F when F =:= FileComponents ->
%% Plain file
{false, {ok, GetInfo()}};
_ ->
@@ -1011,7 +1008,7 @@ apply_archive(PS, Fun, Acc, Archive) ->
%% put(Archive, {Error, FI}),
{Error, PS}
end;
- {primary, PrimZip, FI} ->
+ {primary, PrimZip, FI, ParserFun} ->
case prim_file:read_file_info(Archive) of
{ok, FI2}
when FI#file_info.mtime =:= FI2#file_info.mtime ->
@@ -1022,6 +1019,16 @@ apply_archive(PS, Fun, Acc, Archive) ->
debug(PS, {primary, Error}),
{Error, PS}
end;
+ {ok, FI2} ->
+ ok = clear_cache(Archive, {ok, PrimZip}),
+ case load_prim_archive(Archive, FI2, ParserFun) of
+ {ok, PrimZip2, FI3, _Ebins} ->
+ debug(PS, {cache, {update, Archive}}),
+ put(Archive, {primary, PrimZip2, FI3, ParserFun});
+ Error2 ->
+ debug(PS, {cache, {clear, Error2}})
+ end,
+ apply_archive(PS, Fun, Acc, Archive);
Error ->
debug(PS, {cache, {clear, Error}}),
clear_cache(Archive, {ok, PrimZip}),
@@ -1063,50 +1070,69 @@ open_archive(Archive, Acc, Fun) ->
{error, Reason}
end.
+%% Open the given archive and iterate through all files with an own
+%% wrapper fun in order to identify each file as a component list as
+%% returned from path_split/1.
+%%
+%% In the archive (zip) file, directory elements might or might not be
+%% present. To ensure consistency, a directory element is added if it
+%% does not already exist (ensure_virtual_dirs/6). NOTE that there will
+%% be no such directory element for the top directory of the archive.
open_archive(Archive, FileInfo, Acc, Fun) ->
FakeFI = FileInfo#file_info{type = directory},
Wrapper =
- fun({N, GI, GB}, {A, I, FunnyDirs}) -> % Full iteration at open
- Funny = funny_split(N, $/),
- FunnyDirs2 =
- case Funny of
- ["" | FunnyDir] ->
- [FunnyDir | FunnyDirs];
+ fun({N, GI, GB}, {A, I, Dirs}) ->
+ Components = path_split(N),
+ Dirs2 =
+ case Components of
+ ["" | Dir] ->
+ %% This is a directory
+ [Dir | Dirs];
_ ->
- FunnyDirs
+ %% This is a regular file
+ Dirs
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}}
+ {Includes, Dirs3, A2} =
+ ensure_virtual_dirs(Components, Fun, FakeFI,
+ [{true, Components}], Dirs2, A),
+ {_Continue, A3} = Fun({Components, GI, GB}, A2),
+ {true, Includes, {A3, I, Dirs3}}
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
+ensure_virtual_dirs(Components, Fun, FakeFI, Includes, Dirs, Acc) ->
+ case Components of
+ [_] ->
+ %% Don't add virtual dir for top directory
+ {Includes, Dirs, Acc};
+ [_ | Dir] ->
+ case lists:member(Dir, Dirs) of % BIF
false ->
+ %% The directory does not yet exist - add it
GetInfo = fun() -> FakeFI end,
GetBin = fun() -> <<>> end,
- VirtualDir = ["" | FunnyDir],
+ VirtualDir = ["" | Dir],
Includes2 = [{true, VirtualDir, GetInfo, GetBin} | Includes],
- FunnyDirs2 = [FunnyDir | FunnyDirs],
- {I, F, Acc2} = ensure_virtual_dirs(FunnyDir, Fun, FakeFI, Includes2, FunnyDirs2, Acc),
+ Dirs2 = [Dir | Dirs],
+
+ %% Recursively ensure dir elements on all levels
+ {I, F, Acc2} = ensure_virtual_dirs(Dir, Fun, FakeFI,
+ Includes2, Dirs2, Acc),
+
{_Continue, Acc3} = Fun({VirtualDir, GetInfo, GetBin}, Acc2),
{I, F, Acc3};
true ->
- {reverse(Includes), FunnyDirs, Acc}
- end;
- [] ->
- {reverse(Includes), FunnyDirs, Acc}
+ %% The directory element does already exist
+ %% Recursivly ensure dir elements on all levels
+ ensure_virtual_dirs(Dir,Fun,FakeFI,Includes,Dirs,Acc)
+ end
end.
foldl_archive(PrimZip, Acc, Fun) ->
Wrapper =
- fun({Funny, GI, GB}, A) ->
+ fun({Components, GI, GB}, A) ->
%% Allow partial iteration at foldl
- {Continue, A2} = Fun({Funny, GI, GB}, A),
+ {Continue, A2} = Fun({Components, GI, GB}, A),
{Continue, true, A2}
end,
prim_zip:foldl(Wrapper, Acc, PrimZip).
@@ -1202,17 +1228,32 @@ reverse([A, B]) ->
reverse([A, B | L]) ->
lists:reverse(L, [B, A]). % BIF
-%% Returns all lists in reverse order
-funny_split(List, Sep) ->
- funny_split(List, Sep, [], []).
-
-funny_split([Sep | Tail], Sep, Path, Paths) ->
- funny_split(Tail, Sep, [], [Path | Paths]);
-funny_split([Head | Tail], Sep, Path, Paths) ->
- funny_split(Tail, Sep, [Head | Path], Paths);
-funny_split([], _Sep, Path, Paths) ->
+%% Returns a reversed list of path components, each component itself a
+%% reversed list (string), e.g.
+%% /path/to/file -> ["elif","ot","htap",""]
+%% /path/to/dir/ -> ["","rid","ot","htap",""]
+%% Note the "" marking leading and trailing / (slash).
+path_split(List) ->
+ path_split(List, [], []).
+
+path_split([$/ | Tail], Path, Paths) ->
+ path_split(Tail, [], [Path | Paths]);
+path_split([Head | Tail], Path, Paths) ->
+ path_split(Tail, [Head | Path], Paths);
+path_split([], Path, Paths) ->
[Path | Paths].
+%% The opposite of path_split/1
+path_join(Paths) ->
+ path_join(Paths,[]).
+
+path_join([""],Acc) ->
+ Acc;
+path_join([Path],Acc) ->
+ reverse(Path) ++ Acc;
+path_join([Path|Paths],Acc) ->
+ path_join(Paths,"/" ++ reverse(Path) ++ Acc).
+
name_split(ArchiveFile, File0) ->
File = absname(File0),
do_name_split(ArchiveFile, File).
@@ -1235,26 +1276,22 @@ do_name_split(undefined, File) ->
%% False match. Assume plain file
{file, File}
end;
-do_name_split(ArchiveFile0, File) ->
+do_name_split(ArchiveFile, File) ->
%% Look first in primary archive
- ArchiveFile = absname(ArchiveFile0),
- case string_match(File, ArchiveFile, []) of
+ case string_match(real_path(File), ArchiveFile, []) of
no_match ->
%% Archive or plain file
do_name_split(undefined, File);
{match, _RevPrimArchiveFile, FileInArchive} ->
%% Primary archive
- case FileInArchive of
- [$/ | FileInArchive2] ->
- {archive, ArchiveFile, FileInArchive2};
- _ ->
- {archive, ArchiveFile, FileInArchive}
- end
+ {archive, ArchiveFile, FileInArchive}
end.
string_match([Char | File], [Char | Archive], RevTop) ->
string_match(File, Archive, [Char | RevTop]);
-string_match(File, [], RevTop) ->
+string_match([] = File, [], RevTop) ->
+ {match, RevTop, File};
+string_match([$/ | File], [], RevTop) ->
{match, RevTop, File};
string_match(_File, _Archive, _RevTop) ->
no_match.
@@ -1314,14 +1351,14 @@ absname(Name) ->
case prim_file:get_cwd() of
{ok, Cwd} ->
Cwd ++ "/" ++ Name2;
- {error, _} ->
+ {error, _} ->
Name2
end;
volumerelative ->
case prim_file:get_cwd() of
{ok, Cwd} ->
absname_vr(Name2, Cwd);
- {error, _} ->
+ {error, _} ->
Name2
end
end.
@@ -1348,14 +1385,7 @@ pathtype(Name) when is_list(Name) ->
{unix, _} ->
unix_pathtype(Name);
{win32, _} ->
- win32_pathtype(Name);
- {vxworks, _} ->
- case vxworks_first(Name) of
- {device, _Rest, _Dev} ->
- absolute;
- _ ->
- relative
- end
+ win32_pathtype(Name)
end.
unix_pathtype(Name) ->
@@ -1380,58 +1410,18 @@ win32_pathtype(Name) ->
win32_pathtype([Char | List++Rest]);
[$/, $/|_] ->
absolute;
- [$\\, $/|_] ->
- absolute;
- [$/, $\\|_] ->
- absolute;
- [$\\, $\\|_] ->
- absolute;
[$/|_] ->
volumerelative;
- [$\\|_] ->
- volumerelative;
[C1, C2, List | Rest] when is_list(List) ->
- pathtype([C1, C2|List ++ Rest]);
+ win32_pathtype([C1, C2|List ++ Rest]);
[_Letter, $:, $/|_] ->
absolute;
- [_Letter, $:, $\\|_] ->
- absolute;
[_Letter, $:|_] ->
volumerelative;
_ ->
relative
end.
-vxworks_first(Name) ->
- case Name of
- [] ->
- {not_device, [], []};
- [$/ | T] ->
- vxworks_first2(device, T, [$/]);
- [$\\ | T] ->
- vxworks_first2(device, T, [$/]);
- [H | T] when is_list(H) ->
- vxworks_first(H ++ T);
- [H | T] ->
- vxworks_first2(not_device, T, [H])
- end.
-
-vxworks_first2(Devicep, Name, FirstComp) ->
- case Name of
- [] ->
- {Devicep, [], FirstComp};
- [$/ |T ] ->
- {Devicep, [$/ | T], FirstComp};
- [$\\ | T] ->
- {Devicep, [$/ | T], FirstComp};
- [$: | T]->
- {device, T, [$: | FirstComp]};
- [H | T] when is_list(H) ->
- vxworks_first2(Devicep, H ++ T, FirstComp);
- [H | T] ->
- vxworks_first2(Devicep, T, [H | FirstComp])
- end.
-
normalize(Name, Acc) ->
case Name of
[List | Rest] when is_list(List) ->
@@ -1445,3 +1435,70 @@ normalize(Name, Acc) ->
[] ->
reverse(Acc)
end.
+
+%% Remove .. and . from the path, e.g.
+%% /path/./to/this/../file -> /path/to/file
+%% This includes resolving symlinks.
+%%
+%% This is done to ensure that paths are totally normalized before
+%% comparing to find out if a file is inside the primary archive or
+%% not.
+real_path(Name) ->
+ real_path(Name,reverse(path_split(Name)),[],[]).
+
+real_path(_Name,[],Acc,_Links) ->
+ path_join(Acc);
+real_path(Name,["."|Paths],Acc,Links) ->
+ real_path(Name,Paths,Acc,Links);
+real_path(Name,[".."|Paths],[""]=Acc,Links) ->
+ %% /.. -> / (can't get higher than root)
+ real_path(Name,Paths,Acc,Links);
+real_path(Name,[".."|Paths],[Prev|Acc],Links) when Prev=/=".." ->
+ real_path(Name,Paths,Acc,Links);
+real_path(Name,[Path|Paths],Acc,Links) ->
+ This = [Path|Acc],
+ ThisFile = path_join(This),
+ case lists:member(ThisFile,Links) of
+ true -> % circular!!
+ Name;
+ false ->
+ case prim_file:read_link(ThisFile) of
+ {ok,Link} ->
+ case reverse(path_split(Link)) of
+ [""|_] = LinkPaths ->
+ real_path(Name,LinkPaths++Paths,[],[ThisFile|Links]);
+ LinkPaths ->
+ real_path(Name,LinkPaths++Paths,Acc,[ThisFile|Links])
+ end;
+ _ ->
+ real_path(Name,Paths,This,Links)
+ end
+ end.
+
+load_prim_archive(ArchiveFile, ArchiveBin, #file_info{}=FileInfo) ->
+ Fun = fun({Components, _GI, _GB}, A) ->
+ case Components of
+ ["", "nibe", RevApp] -> % Reverse ebin
+ %% Collect ebin directories in archive
+ Ebin = lists:reverse(RevApp, "/ebin"),
+ {true, [Ebin | A]};
+ _ ->
+ {true, A}
+ end
+ end,
+ Ebins0 = [ArchiveFile],
+ case open_archive({ArchiveFile, ArchiveBin}, FileInfo,
+ Ebins0, Fun) of
+ {ok, PrimZip, {RevEbins, FI, _}} ->
+ Ebins = reverse(RevEbins),
+ {ok, PrimZip, FI, Ebins};
+ Error ->
+ Error
+ end;
+load_prim_archive(ArchiveFile, FileInfo, ParserFun) ->
+ case ParserFun(ArchiveFile) of
+ {ok, ArchiveBin} ->
+ load_prim_archive(ArchiveFile, ArchiveBin, FileInfo);
+ Error ->
+ Error
+ end.
diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index 646acf5798..50546b1856 100644
--- a/erts/preloaded/src/erlang.erl
+++ b/erts/preloaded/src/erlang.erl
@@ -79,15 +79,18 @@
-export([bump_reductions/1, byte_size/1, call_on_load_function/1]).
-export([cancel_timer/1, check_old_code/1, check_process_code/2, crc32/1]).
-export([crc32/2, crc32_combine/3, date/0, decode_packet/3]).
+-export([delete_element/2]).
-export([delete_module/1, demonitor/1, demonitor/2, display/1]).
-export([display_nl/0, display_string/1, dist_exit/3, erase/0, erase/1]).
-export([error/1, error/2, exit/1, exit/2, external_size/1]).
-export([external_size/2, finish_after_on_load/2, finish_loading/1, float/1]).
--export([float_to_list/1, fun_info/2, fun_to_list/1, function_exported/3]).
+-export([float_to_list/1, float_to_list/2]).
+-export([fun_info/2, fun_to_list/1, function_exported/3]).
-export([garbage_collect/0, garbage_collect/1]).
-export([garbage_collect_message_area/0, get/0, get/1, get_keys/1]).
-export([get_module_info/1, get_stacktrace/0, group_leader/0]).
-export([group_leader/2, halt/0, halt/1, halt/2, hash/2, hibernate/3]).
+-export([insert_element/3]).
-export([integer_to_list/1, iolist_size/1, iolist_to_binary/1]).
-export([is_alive/0, is_builtin/3, is_process_alive/1, length/1, link/1]).
-export([list_to_atom/1, list_to_binary/1, list_to_bitstr/1]).
@@ -529,6 +532,14 @@ date() ->
decode_packet(_Type, _Bin, _Options) ->
erlang:nif_error(undefined).
+%% delete_element/2
+-spec erlang:delete_element(Index, Tuple1) -> Tuple2 when
+ Index :: pos_integer(),
+ Tuple1 :: tuple(),
+ Tuple2 :: tuple().
+delete_element(_Index, _Tuple1) ->
+ erlang:nif_error(undefined).
+
%% delete_module/1
-spec delete_module(Module) -> true | undefined when
Module :: module().
@@ -701,6 +712,16 @@ float(_Number) ->
float_to_list(_Float) ->
erlang:nif_error(undefined).
+%% float_to_list/2
+-spec float_to_list(Float, Options) -> string() when
+ Float :: float(),
+ Options :: [Option],
+ Option :: {decimals, non_neg_integer()} |
+ {scientific, non_neg_integer()} |
+ compact.
+float_to_list(_Float, _Options) ->
+ erlang:nif_error(undefined).
+
%% fun_info/2
-spec erlang:fun_info(Fun, Item) -> {Item, Info} when
Fun :: function(),
@@ -820,6 +841,15 @@ hash(_Term, _Range) ->
hibernate(_Module, _Function, _Args) ->
erlang:nif_error(undefined).
+%% insert_element/3
+-spec erlang:insert_element(Index, Tuple1, Term) -> Tuple2 when
+ Index :: pos_integer(),
+ Tuple1 :: tuple(),
+ Tuple2 :: tuple(),
+ Term :: term().
+insert_element(_Index, _Tuple1, _Term) ->
+ erlang:nif_error(undefined).
+
%% integer_to_list/1
-spec integer_to_list(Integer) -> string() when
Integer :: integer().
@@ -1075,57 +1105,6 @@ phash2(_Term, _Range) ->
pid_to_list(_Pid) ->
erlang:nif_error(undefined).
-%% port_close/1
--spec port_close(Port) -> true when
- Port :: port() | atom().
-port_close(_Port) ->
- erlang:nif_error(undefined).
-
-%% port_command/2
--spec port_command(Port, Data) -> true when
- Port :: port() | atom(),
- Data :: iodata().
-port_command(_Port, _Data) ->
- erlang:nif_error(undefined).
-
-%% port_command/3
--spec port_command(Port, Data, OptionList) -> boolean() when
- Port :: port() | atom(),
- Data :: iodata(),
- OptionList :: [Option],
- Option :: force | nosuspend.
-port_command(_Port, _Data, _OptionList) ->
- erlang:nif_error(undefined).
-
-%% port_connect/2
--spec port_connect(Port, Pid) -> true when
- Port :: port() | atom(),
- Pid :: pid().
-port_connect(_Port, _Pid) ->
- erlang:nif_error(undefined).
-
-%% port_control/3
--spec port_control(Port, Operation, Data) -> Res when
- Port :: port() | atom(),
- Operation :: integer(),
- Data :: iodata(),
- Res :: string() | binary().
-port_control(_Port, _Operation, _Data) ->
- erlang:nif_error(undefined).
-
-%% port_get_data/1
--spec erlang:port_get_data(P1) -> term() when
- P1 :: port() | atom().
-port_get_data(_P1) ->
- erlang:nif_error(undefined).
-
-%% port_set_data/2
--spec erlang:port_set_data(P1, P2) -> true when
- P1 :: port() | atom(),
- P2 :: term().
-port_set_data(_P1, _P2) ->
- erlang:nif_error(undefined).
-
%% port_to_list/1
-spec erlang:port_to_list(Port) -> string() when
Port :: port().
@@ -1699,60 +1678,12 @@ nodes(_Arg) ->
| in
| out
| binary
- | eof.
+ | eof
+ | {parallelism, Boolean :: boolean()}
+ | hide.
open_port(_PortName,_PortSettings) ->
erlang:nif_error(undefined).
-%% Shadowed by erl_bif_types: erlang:port_call/2
--spec erlang:port_call(Port, Data) -> term() when
- Port :: port() | atom(),
- Data :: term().
-port_call(_Port, _Data) ->
- erlang:nif_error(undefined).
-
-%% Shadowed by erl_bif_types: erlang:port_call/3
--spec erlang:port_call(Port, Operation, Data) -> term() when
- Port :: port() | atom(),
- Operation :: integer(),
- Data :: term().
-port_call(_Port, _Operation, _Data) ->
- erlang:nif_error(undefined).
-
--type port_info_item() ::
- registered_name |
- id |
- connected |
- links |
- name |
- input |
- output |
- os_pid.
-
--type port_info_result_item() ::
- {registered_name, RegName :: atom()} |
- {id, Index :: non_neg_integer()} |
- {connected, Pid :: pid()} |
- {links, Pids :: [pid()]} |
- {name, String :: string()} |
- {input, Bytes :: non_neg_integer()} |
- {output, Bytes :: non_neg_integer()} |
- {os_pid, OsPid :: non_neg_integer() | 'undefined'}.
-
-%% Shadowed by erl_bif_types: erlang:port_info/1
--spec erlang:port_info(Port) -> Result when
- Port :: port() | atom(),
- Result :: [port_info_result_item()] | undefined.
-port_info(_Result) ->
- erlang:nif_error(undefined).
-
-%% Shadowed by erl_bif_types: erlang:port_info/2
--spec erlang:port_info(Port, Item) -> Result when
- Port :: port() | atom(),
- Item :: port_info_item(),
- Result :: port_info_result_item() | undefined.
-port_info(_Result, _Item) ->
- erlang:nif_error(undefined).
-
-type priority_level() ::
low | normal | high | max.
@@ -1836,7 +1767,7 @@ process_flag(_Flag, _Value) ->
{group_leader, GroupLeader :: pid()} |
{heap_size, Size :: non_neg_integer()} |
{initial_call, mfa()} |
- {links, Pids :: [pid()]} |
+ {links, PidsAndPorts :: [pid() | port()]} |
{last_calls, false | (Calls :: [mfa()])} |
{memory, Size :: non_neg_integer()} |
{message_que_len, MessageQueueLen :: non_neg_integer()} |
@@ -2137,6 +2068,8 @@ tuple_to_list(_Tuple) ->
(multi_scheduling) -> disabled | blocked | enabled;
(multi_scheduling_blockers) -> [PID :: pid()];
(otp_release) -> string();
+ (port_count) -> non_neg_integer();
+ (port_limit) -> pos_integer();
(process_count) -> pos_integer();
(process_limit) -> pos_integer();
(procs) -> binary();
@@ -2530,6 +2463,216 @@ suspend_process(P) ->
end.
%%
+%% Port BIFs
+%%
+%% Currently all port BIFs calls the corresponding
+%% erts_internal:port_*() native function which perform
+%% most of the actual work. These native functions should
+%% *never* be called directly by other functionality. The
+%% native functions may be changed, or removed without any
+%% notice whatsoever!
+%%
+%% IMPORTANT NOTE:
+%% When the erts_internal:port_*() native functions return
+%% a reference, they have also internally prepared the
+%% message queue of the caller for a receive that will
+%% unconditionally wait for a message containing this
+%% reference. If the erlang code calling these native
+%% functions do not do this, subsequent receives will not
+%% work as expected! That is, it is of *vital importance*
+%% that the receive is performed as described above!
+%%
+
+-spec port_command(Port, Data) -> 'true' when
+ Port :: port() | atom(),
+ Data :: iodata().
+
+port_command(Port, Data) ->
+ case case erts_internal:port_command(Port, Data, []) of
+ Ref when erlang:is_reference(Ref) -> receive {Ref, Res} -> Res end;
+ Res -> Res
+ end of
+ true -> true;
+ Error -> erlang:error(Error, [Port, Data])
+ end.
+
+-spec port_command(Port, Data, OptionList) -> boolean() when
+ Port :: port() | atom(),
+ Data :: iodata(),
+ Option :: force | nosuspend,
+ OptionList :: [Option].
+
+port_command(Port, Data, Flags) ->
+ case case erts_internal:port_command(Port, Data, Flags) of
+ Ref when erlang:is_reference(Ref) -> receive {Ref, Res} -> Res end;
+ Res -> Res
+ end of
+ Bool when Bool == true; Bool == false -> Bool;
+ Error -> erlang:error(Error, [Port, Data, Flags])
+ end.
+
+-spec port_connect(Port, Pid) -> 'true' when
+ Port :: port() | atom(),
+ Pid :: pid().
+
+port_connect(Port, Pid) ->
+ case case erts_internal:port_connect(Port, Pid) of
+ Ref when erlang:is_reference(Ref) -> receive {Ref, Res} -> Res end;
+ Res -> Res
+ end of
+ true -> true;
+ Error -> erlang:error(Error, [Port, Pid])
+ end.
+
+-spec port_close(Port) -> 'true' when
+ Port :: port() | atom().
+
+port_close(Port) ->
+ case case erts_internal:port_close(Port) of
+ Ref when erlang:is_reference(Ref) -> receive {Ref, Res} -> Res end;
+ Res -> Res
+ end of
+ true -> true;
+ Error -> erlang:error(Error, [Port])
+ end.
+
+-spec port_control(Port, Operation, Data) -> iodata() | binary() when
+ Port :: port() | atom(),
+ Operation :: integer(),
+ Data :: iodata().
+
+port_control(Port, Operation, Data) ->
+ case case erts_internal:port_control(Port, Operation, Data) of
+ Ref when erlang:is_reference(Ref) -> receive {Ref, Res} -> Res end;
+ Res -> Res
+ end of
+ badarg -> erlang:error(badarg, [Port, Operation, Data]);
+ Result -> Result
+ end.
+
+-spec erlang:port_call(Port, Data) -> term() when
+ Port :: port() | atom(),
+ Data :: term().
+
+port_call(Port, Data) ->
+ case case erts_internal:port_call(Port, 0, Data) of
+ Ref when erlang:is_reference(Ref) -> receive {Ref, Res} -> Res end;
+ Res -> Res
+ end of
+ {ok, Result} -> Result;
+ Error -> erlang:error(Error, [Port, Data])
+ end.
+
+-spec erlang:port_call(Port, Operation, Data) -> term() when
+ Port :: port() | atom(),
+ Operation :: integer(),
+ Data :: term().
+
+port_call(Port, Operation, Data) ->
+ case case erts_internal:port_call(Port, Operation, Data) of
+ Ref when erlang:is_reference(Ref) -> receive {Ref, Res} -> Res end;
+ Res -> Res
+ end of
+ {ok, Result} -> Result;
+ Error -> erlang:error(Error, [Port, Operation, Data])
+ end.
+
+-spec erlang:port_info(Port) -> Result when
+ Port :: port() | atom(),
+ ResultItem :: {registered_name, RegisteredName :: atom()}
+ | {id, Index :: non_neg_integer()}
+ | {connected, Pid :: pid()}
+ | {links, Pids :: [pid()]}
+ | {name, String :: string()}
+ | {input, Bytes :: non_neg_integer()}
+ | {output, Bytes :: non_neg_integer()}
+ | {os_pid, OsPid :: non_neg_integer() | 'undefined'},
+ Result :: [ResultItem] | 'undefined'.
+
+port_info(Port) ->
+ case case erts_internal:port_info(Port) of
+ Ref when erlang:is_reference(Ref) -> receive {Ref, Res} -> Res end;
+ Res -> Res
+ end of
+ badarg -> erlang:error(badarg, [Port]);
+ Result -> Result
+ end.
+
+-spec erlang:port_info(Port, connected) -> {connected, Pid} | 'undefined' when
+ Port :: port() | atom(),
+ Pid :: pid();
+ (Port, id) -> {id, Index} | 'undefined' when
+ Port :: port() | atom(),
+ Index :: non_neg_integer();
+ (Port, input) -> {input, Bytes} | 'undefined' when
+ Port :: port() | atom(),
+ Bytes :: non_neg_integer();
+ (Port, links) -> {links, Pids} | 'undefined' when
+ Port :: port() | atom(),
+ Pids :: [pid()];
+ (Port, locking) -> {locking, Locking} | 'undefined' when
+ Port :: port() | atom(),
+ Locking :: 'false' | 'port_level' | 'driver_level';
+ (Port, memory) -> {memory, Bytes} | 'undefined' when
+ Port :: port() | atom(),
+ Bytes :: non_neg_integer();
+ (Port, monitors) -> {monitors, Monitors} | 'undefined' when
+ Port :: port() | atom(),
+ Monitors :: [{process, pid()}];
+ (Port, name) -> {name, Name} | 'undefined' when
+ Port :: port() | atom(),
+ Name :: string();
+ (Port, os_pid) -> {os_pid, OsPid} | 'undefined' when
+ Port :: port() | atom(),
+ OsPid :: non_neg_integer() | 'undefined';
+ (Port, output) -> {output, Bytes} | 'undefined' when
+ Port :: port() | atom(),
+ Bytes :: non_neg_integer();
+ (Port, parallelism) -> {parallelism, Boolean} | 'undefined' when
+ Port :: port() | atom(),
+ Boolean :: boolean();
+ (Port, queue_size) -> {queue_size, Bytes} | 'undefined' when
+ Port :: port() | atom(),
+ Bytes :: non_neg_integer();
+ (Port, registered_name) -> {registered_name, RegisteredName} | [] | 'undefined' when
+ Port :: port() | atom(),
+ RegisteredName :: atom().
+
+port_info(Port, Item) ->
+ case case erts_internal:port_info(Port, Item) of
+ Ref when erlang:is_reference(Ref) -> receive {Ref, Res} -> Res end;
+ Res -> Res
+ end of
+ badarg -> erlang:error(badarg, [Port, Item]);
+ Result -> Result
+ end.
+
+-spec erlang:port_set_data(Port, Data) -> 'true' when
+ Port :: port() | atom(),
+ Data :: term().
+
+port_set_data(Port, Data) ->
+ case case erts_internal:port_set_data(Port, Data) of
+ Ref when erlang:is_reference(Ref) -> receive {Ref, Res} -> Res end;
+ Res -> Res
+ end of
+ badarg -> erlang:error(badarg, [Port, Data]);
+ Result -> Result
+ end.
+
+-spec erlang:port_get_data(Port) -> term() when
+ Port :: port() | atom().
+
+port_get_data(Port) ->
+ case case erts_internal:port_get_data(Port) of
+ Ref when erlang:is_reference(Ref) -> receive {Ref, Res} -> Res end;
+ Res -> Res
+ end of
+ {ok, Data} -> Data;
+ Error -> erlang:error(Error, [Port])
+ end.
+
+%%
%% If the emulator wants to perform a distributed command and
%% a connection is not established to the actual node the following
%% functions are called in order to set up the connection and then
diff --git a/erts/preloaded/src/erts_internal.erl b/erts/preloaded/src/erts_internal.erl
new file mode 100644
index 0000000000..f1c83f4518
--- /dev/null
+++ b/erts/preloaded/src/erts_internal.erl
@@ -0,0 +1,155 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. 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%
+%%
+
+%%
+%% As the module name imply, this module is here for ERTS internal
+%% functionality. As an application programmer you should *never*
+%% call anything in this module directly. Functions exported by
+%% this module may change behaviour or be removed at any time
+%% without any notice whatsoever. Everything in this module is
+%% intentionally left undocumented, and should remain so.
+%%
+
+-module(erts_internal).
+
+-export([await_port_send_result/3]).
+
+-export([port_command/3, port_connect/2, port_close/1,
+ port_control/3, port_call/3, port_set_data/2, port_get_data/1,
+ port_info/1, port_info/2]).
+
+%%
+%% Await result of send to port
+%%
+
+await_port_send_result(Ref, Busy, Ok) ->
+ receive
+ {Ref, false} -> Busy;
+ {Ref, _} -> Ok
+ end.
+
+%%
+%% Statically linked port NIFs
+%%
+
+-spec erts_internal:port_command(Port, Data, OptionList) -> Result when
+ Port :: port() | atom(),
+ Data :: iodata(),
+ OptionList :: [Option],
+ Option :: force | nosuspend,
+ Result :: boolean() | reference() | badarg | notsup.
+port_command(_Port, _Data, _OptionList) ->
+ erlang:nif_error(undefined).
+
+-spec erts_internal:port_connect(Port, Pid) -> Result when
+ Port :: port() | atom(),
+ Pid :: pid(),
+ Result :: true | reference() | badarg.
+port_connect(_Port, _Pid) ->
+ erlang:nif_error(undefined).
+
+-spec erts_internal:port_close(Port) -> Result when
+ Port :: port() | atom(),
+ Result :: true | reference() | badarg.
+port_close(_Port) ->
+ erlang:nif_error(undefined).
+
+-spec erts_internal:port_control(Port, Operation, Data) -> Result when
+ Port :: port() | atom(),
+ Operation :: integer(),
+ Data :: iodata(),
+ Result :: string() | binary() | reference() | badarg.
+port_control(_Port, _Operation, _Data) ->
+ erlang:nif_error(undefined).
+
+-spec erts_internal:port_call(Port, Operation, Data) -> Result when
+ Port :: port() | atom(),
+ Operation :: integer(),
+ Data :: term(),
+ Result :: {ok, term()} | reference() | badarg.
+port_call(_Port, _Operation, _Data) ->
+ erlang:nif_error(undefined).
+
+-spec erts_internal:port_get_data(P1) -> Result when
+ P1 :: port() | atom(),
+ Result :: {ok, term()} | reference() | badarg.
+port_get_data(_P1) ->
+ erlang:nif_error(undefined).
+
+-spec erts_internal:port_set_data(P1, P2) -> Result when
+ P1 :: port() | atom(),
+ P2 :: term(),
+ Result :: true | reference() | badarg.
+port_set_data(_P1, _P2) ->
+ erlang:nif_error(undefined).
+
+-type port_info_1_result_item() ::
+ {registered_name, RegName :: atom()} |
+ {id, Index :: non_neg_integer()} |
+ {connected, Pid :: pid()} |
+ {links, Pids :: [pid()]} |
+ {name, String :: string()} |
+ {input, Bytes :: non_neg_integer()} |
+ {output, Bytes :: non_neg_integer()} |
+ {os_pid, OsPid :: non_neg_integer() | 'undefined'}.
+
+-spec erts_internal:port_info(Port) -> Result when
+ Port :: port() | atom(),
+ Result :: [port_info_1_result_item()] | undefined | reference() | badarg | [].
+port_info(_Result) ->
+ erlang:nif_error(undefined).
+
+-type port_info_2_item() ::
+ registered_name |
+ id |
+ connected |
+ links |
+ name |
+ input |
+ output |
+ os_pid |
+ monitors |
+ memory |
+ parallelism |
+ queue_size |
+ locking.
+
+-type port_info_2_result_item() ::
+ {registered_name, RegName :: atom()} |
+ [] | % No registered name
+ {id, Index :: non_neg_integer()} |
+ {connected, Pid :: pid()} |
+ {links, Pids :: [pid()]} |
+ {name, String :: string()} |
+ {input, Bytes :: non_neg_integer()} |
+ {output, Bytes :: non_neg_integer()} |
+ {os_pid, OsPid :: non_neg_integer() | 'undefined'} |
+ {monitors, Monitors :: [{process, pid()}]} |
+ {memory, MemSz :: non_neg_integer()} |
+ {parallelism, Boolean :: boolean()} |
+ {queue_size, QSz :: non_neg_integer()} |
+ {locking, Locking :: 'false' | 'port_level' | 'driver_level'}.
+
+-spec erts_internal:port_info(Port, Item) -> Result when
+ Port :: port() | atom(),
+ Item :: port_info_2_item(),
+ Result :: port_info_2_result_item() | undefined | reference() | badarg.
+
+port_info(_Result, _Item) ->
+ erlang:nif_error(undefined).
diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl
index c9c434dea0..1d1087c7f2 100644
--- a/erts/preloaded/src/init.erl
+++ b/erts/preloaded/src/init.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. 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
@@ -635,8 +635,16 @@ do_unload([M|Mods]) ->
catch erlang:purge_module(M),
do_unload(Mods);
do_unload([]) ->
+ purge_all_hipe_refs(),
ok.
+purge_all_hipe_refs() ->
+ case erlang:system_info(hipe_architecture) of
+ undefined -> ok;
+ _ -> hipe_bifs:remove_refs_from(all)
+ end.
+
+
sub([H|T],L) -> sub(T,del(H,L));
sub([],L) -> L.
@@ -1252,7 +1260,11 @@ get_arguments([]) ->
[].
to_strings([H|T]) when is_atom(H) -> [atom_to_list(H)|to_strings(T)];
-to_strings([H|T]) when is_binary(H) -> [binary_to_list(H)|to_strings(T)];
+to_strings([H|T]) when is_binary(H) -> [try
+ unicode:characters_to_list(H,file:native_name_encoding())
+ catch
+ _:_ -> binary_to_list(H)
+ end|to_strings(T)];
to_strings([]) -> [].
get_argument(Arg,Flags) ->
diff --git a/erts/preloaded/src/prim_file.erl b/erts/preloaded/src/prim_file.erl
index d66f0e09cc..c412b7faf2 100644
--- a/erts/preloaded/src/prim_file.erl
+++ b/erts/preloaded/src/prim_file.erl
@@ -27,7 +27,7 @@
%% Generic file contents operations
-export([open/2, close/1, datasync/1, sync/1, advise/4, position/2, truncate/1,
write/2, pwrite/2, pwrite/3, read/2, read_line/1, pread/2, pread/3,
- copy/3, sendfile/10]).
+ copy/3, sendfile/10, allocate/3]).
%% Specialized file operations
-export([open/1, open/3]).
@@ -100,6 +100,7 @@
-define(FILE_FDATASYNC, 30).
-define(FILE_ADVISE, 31).
-define(FILE_SENDFILE, 32).
+-define(FILE_ALLOCATE, 33).
%% Driver responses
-define(FILE_RESP_OK, 0).
@@ -293,6 +294,11 @@ advise(#file_descriptor{module = ?MODULE, data = {Port, _}},
end.
%% Returns {error, Reason} | ok.
+allocate(#file_descriptor{module = ?MODULE, data = {Port, _}}, Offset, Length) ->
+ Cmd = <<?FILE_ALLOCATE, Offset:64/signed, Length:64/signed>>,
+ drv_command(Port, Cmd).
+
+%% Returns {error, Reason} | ok.
write(#file_descriptor{module = ?MODULE, data = {Port, _}}, Bytes) ->
case drv_command_nt(Port, [?FILE_WRITE,erlang:dt_prepend_vm_tag_data(Bytes)],undefined) of
{ok, _Size} ->
@@ -479,7 +485,7 @@ position(#file_descriptor{module = ?MODULE, data = {Port, _}}, At) ->
{error, Reason}
end.
-%% Returns {error, Reaseon} | ok.
+%% Returns {error, Reason} | ok.
truncate(#file_descriptor{module = ?MODULE, data = {Port, _}}) ->
drv_command(Port, <<?FILE_TRUNCATE>>).
@@ -674,25 +680,7 @@ set_cwd(Dir) ->
set_cwd(Port, Dir) when is_port(Port) ->
set_cwd_int(Port, Dir).
-set_cwd_int(Port, Dir0) ->
- Dir =
- (catch
- case os:type() of
- vxworks ->
- %% chdir on vxworks doesn't support
- %% relative paths
- %% must call get_cwd from here and use
- %% absname/2, since
- %% absname/1 uses file:get_cwd ...
- case get_cwd_int(Port, 0) of
- {ok, AbsPath} ->
- filename:absname(Dir0, AbsPath);
- _Badcwd ->
- Dir0
- end;
- _Else ->
- Dir0
- end),
+set_cwd_int(Port, Dir) ->
%% Dir is now either a string or an EXIT tuple.
%% An EXIT tuple will fail in the following catch.
drv_command(Port, [?FILE_CHDIR, pathname(Dir)]).
diff --git a/erts/preloaded/src/prim_inet.erl b/erts/preloaded/src/prim_inet.erl
index 3c8a059269..21d23159f0 100644
--- a/erts/preloaded/src/prim_inet.erl
+++ b/erts/preloaded/src/prim_inet.erl
@@ -184,7 +184,7 @@ close_pend_loop(S, N) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bind(S,IP,Port) when is_port(S), is_integer(Port), Port >= 0, Port =< 65535 ->
- case ctl_cmd(S,?INET_REQ_BIND,[?int16(Port),ip_to_bytes(IP)]) of
+ case ctl_cmd(S,?INET_REQ_BIND,enc_value(set, addr, {IP,Port})) of
{ok, [P1,P0]} -> {ok, ?u16(P1, P0)};
{error,_}=Error -> Error
end;
@@ -206,10 +206,10 @@ bindx(S, AddFlag, Addrs) ->
case getprotocol(S) of
sctp ->
%% Really multi-homed "bindx". Stringified args:
- %% [AddFlag, (Port, IP)+]:
+ %% [AddFlag, (AddrBytes see enc_value_2(addr,X))+]:
Args =
[?int8(AddFlag)|
- [[?int16(Port)|ip_to_bytes(IP)] ||
+ [enc_value(set, addr, {IP,Port}) ||
{IP, Port} <- Addrs]],
case ctl_cmd(S, ?SCTP_REQ_BINDX, Args) of
{ok,_} -> {ok, S};
@@ -1062,6 +1062,7 @@ enc_opt(multicast_ttl) -> ?UDP_OPT_MULTICAST_TTL;
enc_opt(multicast_loop) -> ?UDP_OPT_MULTICAST_LOOP;
enc_opt(add_membership) -> ?UDP_OPT_ADD_MEMBERSHIP;
enc_opt(drop_membership) -> ?UDP_OPT_DROP_MEMBERSHIP;
+enc_opt(ipv6_v6only) -> ?INET_OPT_IPV6_V6ONLY;
enc_opt(buffer) -> ?INET_LOPT_BUFFER;
enc_opt(header) -> ?INET_LOPT_HEADER;
enc_opt(active) -> ?INET_LOPT_ACTIVE;
@@ -1071,6 +1072,8 @@ enc_opt(deliver) -> ?INET_LOPT_DELIVER;
enc_opt(exit_on_close) -> ?INET_LOPT_EXITONCLOSE;
enc_opt(high_watermark) -> ?INET_LOPT_TCP_HIWTRMRK;
enc_opt(low_watermark) -> ?INET_LOPT_TCP_LOWTRMRK;
+enc_opt(high_msgq_watermark) -> ?INET_LOPT_TCP_MSGQ_HIWTRMRK;
+enc_opt(low_msgq_watermark) -> ?INET_LOPT_TCP_MSGQ_LOWTRMRK;
enc_opt(send_timeout) -> ?INET_LOPT_TCP_SEND_TIMEOUT;
enc_opt(send_timeout_close) -> ?INET_LOPT_TCP_SEND_TIMEOUT_CLOSE;
enc_opt(delay_send) -> ?INET_LOPT_TCP_DELAY_SEND;
@@ -1115,6 +1118,7 @@ dec_opt(?UDP_OPT_MULTICAST_TTL) -> multicast_ttl;
dec_opt(?UDP_OPT_MULTICAST_LOOP) -> multicast_loop;
dec_opt(?UDP_OPT_ADD_MEMBERSHIP) -> add_membership;
dec_opt(?UDP_OPT_DROP_MEMBERSHIP) -> drop_membership;
+dec_opt(?INET_OPT_IPV6_V6ONLY) -> ipv6_v6only;
dec_opt(?INET_LOPT_BUFFER) -> buffer;
dec_opt(?INET_LOPT_HEADER) -> header;
dec_opt(?INET_LOPT_ACTIVE) -> active;
@@ -1124,6 +1128,8 @@ dec_opt(?INET_LOPT_DELIVER) -> deliver;
dec_opt(?INET_LOPT_EXITONCLOSE) -> exit_on_close;
dec_opt(?INET_LOPT_TCP_HIWTRMRK) -> high_watermark;
dec_opt(?INET_LOPT_TCP_LOWTRMRK) -> low_watermark;
+dec_opt(?INET_LOPT_TCP_MSGQ_HIWTRMRK) -> high_msgq_watermark;
+dec_opt(?INET_LOPT_TCP_MSGQ_LOWTRMRK) -> low_msgq_watermark;
dec_opt(?INET_LOPT_TCP_SEND_TIMEOUT) -> send_timeout;
dec_opt(?INET_LOPT_TCP_SEND_TIMEOUT_CLOSE) -> send_timeout_close;
dec_opt(?INET_LOPT_TCP_DELAY_SEND) -> delay_send;
@@ -1178,6 +1184,7 @@ type_opt_1(recbuf) -> int;
type_opt_1(priority) -> int;
type_opt_1(tos) -> int;
type_opt_1(nodelay) -> bool;
+type_opt_1(ipv6_v6only) -> bool;
%% multicast
type_opt_1(multicast_ttl) -> int;
type_opt_1(multicast_loop) -> bool;
@@ -1218,6 +1225,8 @@ type_opt_1(deliver) ->
type_opt_1(exit_on_close) -> bool;
type_opt_1(low_watermark) -> int;
type_opt_1(high_watermark) -> int;
+type_opt_1(low_msgq_watermark) -> int;
+type_opt_1(high_msgq_watermark) -> int;
type_opt_1(send_timeout) -> time;
type_opt_1(send_timeout_close) -> bool;
type_opt_1(delay_send) -> bool;