aboutsummaryrefslogtreecommitdiffstats
path: root/erts/preloaded
diff options
context:
space:
mode:
Diffstat (limited to 'erts/preloaded')
-rw-r--r--erts/preloaded/ebin/erl_prim_loader.beambin50320 -> 52904 bytes
-rw-r--r--erts/preloaded/ebin/erlang.beambin39568 -> 42416 bytes
-rw-r--r--erts/preloaded/ebin/init.beambin45264 -> 48064 bytes
-rw-r--r--erts/preloaded/ebin/otp_ring0.beambin1528 -> 1448 bytes
-rw-r--r--erts/preloaded/ebin/prim_file.beambin32448 -> 39536 bytes
-rw-r--r--erts/preloaded/ebin/prim_inet.beambin65000 -> 69980 bytes
-rw-r--r--erts/preloaded/ebin/prim_zip.beambin22532 -> 23460 bytes
-rw-r--r--erts/preloaded/ebin/zlib.beambin11836 -> 12432 bytes
-rw-r--r--erts/preloaded/src/erl_prim_loader.erl10
-rw-r--r--erts/preloaded/src/erlang.erl36
-rw-r--r--erts/preloaded/src/prim_file.erl254
-rw-r--r--erts/preloaded/src/prim_inet.erl180
-rw-r--r--erts/preloaded/src/prim_zip.erl2
13 files changed, 321 insertions, 161 deletions
diff --git a/erts/preloaded/ebin/erl_prim_loader.beam b/erts/preloaded/ebin/erl_prim_loader.beam
index ffee1f489f..df1831f340 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 dda24d4405..b78747bc84 100644
--- a/erts/preloaded/ebin/erlang.beam
+++ b/erts/preloaded/ebin/erlang.beam
Binary files differ
diff --git a/erts/preloaded/ebin/init.beam b/erts/preloaded/ebin/init.beam
index 37fd8bb832..cc170b86b2 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 e255cc803f..45a409738c 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 6227b562a1..87e80aae9b 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 22c51c79c0..f382236af7 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 7e1a5d1fdb..411fc8d524 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 ebf9f8e6d6..bf88a51502 100644
--- a/erts/preloaded/ebin/zlib.beam
+++ b/erts/preloaded/ebin/zlib.beam
Binary files differ
diff --git a/erts/preloaded/src/erl_prim_loader.erl b/erts/preloaded/src/erl_prim_loader.erl
index 0b4db3d9d0..14a7a2bf20 100644
--- a/erts/preloaded/src/erl_prim_loader.erl
+++ b/erts/preloaded/src/erl_prim_loader.erl
@@ -129,7 +129,7 @@ start(Id, Pgm0, Hosts) ->
{error,Reason}
end.
-%% Hosts must be a list on form ['1.2.3.4' ...]
+%% Hosts must be a list of form ['1.2.3.4' ...]
start_it("inet", Id, Pid, Hosts) ->
process_flag(trap_exit, true),
?dbg(inet, {Id,Pid,Hosts}),
@@ -729,7 +729,7 @@ udp_options() ->
%% INET version IPv4 addresses
%%
ll_tcp_connect(LocalPort, IP, RemotePort) ->
- case ll_open_set_bind(tcp, ?INET_FAMILY, tcp_options(),
+ case ll_open_set_bind(tcp, ?INET_FAMILY, stream, tcp_options(),
?INET_ADDRESS, LocalPort) of
{ok,S} ->
case prim_inet:connect(S, IP, RemotePort, tcp_timeout()) of
@@ -743,11 +743,11 @@ ll_tcp_connect(LocalPort, IP, RemotePort) ->
%% Open and initialize an udp port for broadcast
%%
ll_udp_open(P) ->
- ll_open_set_bind(udp, ?INET_FAMILY, udp_options(), ?INET_ADDRESS, P).
+ ll_open_set_bind(udp, ?INET_FAMILY, dgram, udp_options(), ?INET_ADDRESS, P).
-ll_open_set_bind(Protocol, Family, SOpts, IP, Port) ->
- case prim_inet:open(Protocol, Family) of
+ll_open_set_bind(Protocol, Family, Type, SOpts, IP, Port) ->
+ case prim_inet:open(Protocol, Family, Type) of
{ok, S} ->
case prim_inet:setopts(S, SOpts) of
ok ->
diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index e9a59a7aaf..4cbff3f36e 100644
--- a/erts/preloaded/src/erlang.erl
+++ b/erts/preloaded/src/erlang.erl
@@ -43,6 +43,9 @@
-export([memory/0, memory/1]).
-export([alloc_info/1, alloc_sizes/1]).
+-export([gather_sched_wall_time_result/1,
+ await_sched_wall_time_modifications/2]).
+
-deprecated([hash/2]).
% Get rid of autoimports of spawn to avoid clashes with ourselves.
@@ -1091,8 +1094,6 @@ receive_emd(Ref, EMD, N) ->
receive_emd(Ref) ->
receive_emd(Ref, #memory{}, erlang:system_info(schedulers)).
-aa_mem_data(notsup, _) ->
- notsup;
aa_mem_data(#memory{} = Mem,
[{maximum, Max} | Rest]) ->
aa_mem_data(Mem#memory{maximum = Max},
@@ -1204,3 +1205,34 @@ receive_allocator(Ref, N, Acc) ->
{Ref, _, InfoList} ->
receive_allocator(Ref, N-1, insert_info(InfoList, Acc))
end.
+
+-spec await_sched_wall_time_modifications(Ref, Result) -> boolean() when
+ Ref :: reference(),
+ Result :: boolean().
+
+await_sched_wall_time_modifications(Ref, Result) ->
+ sched_wall_time(Ref, erlang:system_info(schedulers)),
+ Result.
+
+-spec gather_sched_wall_time_result(Ref) -> [{pos_integer(),
+ non_neg_integer(),
+ non_neg_integer()}] when
+ Ref :: reference().
+
+gather_sched_wall_time_result(Ref) when is_reference(Ref) ->
+ sched_wall_time(Ref, erlang:system_info(schedulers), []).
+
+sched_wall_time(_Ref, 0) ->
+ ok;
+sched_wall_time(Ref, N) ->
+ receive Ref -> sched_wall_time(Ref, N-1) end.
+
+sched_wall_time(_Ref, 0, Acc) ->
+ Acc;
+sched_wall_time(Ref, N, undefined) ->
+ receive {Ref, _} -> sched_wall_time(Ref, N-1, undefined) end;
+sched_wall_time(Ref, N, Acc) ->
+ receive
+ {Ref, undefined} -> sched_wall_time(Ref, N-1, undefined);
+ {Ref, SWT} -> sched_wall_time(Ref, N-1, [SWT|Acc])
+ end.
diff --git a/erts/preloaded/src/prim_file.erl b/erts/preloaded/src/prim_file.erl
index 30b7a5246a..36cbe329e8 100644
--- a/erts/preloaded/src/prim_file.erl
+++ b/erts/preloaded/src/prim_file.erl
@@ -26,7 +26,8 @@
%% 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]).
+ write/2, pwrite/2, pwrite/3, read/2, read_line/1, pread/2, pread/3,
+ copy/3, sendfile/10]).
%% Specialized file operations
-export([open/1, open/3]).
@@ -44,13 +45,13 @@
rename/2, rename/3,
make_dir/1, make_dir/2,
del_dir/1, del_dir/2,
- read_file_info/1, read_file_info/2,
+ read_file_info/1, read_file_info/2, read_file_info/3,
altname/1, altname/2,
- write_file_info/2, write_file_info/3,
+ write_file_info/2, write_file_info/3, write_file_info/4,
make_link/2, make_link/3,
make_symlink/2, make_symlink/3,
read_link/1, read_link/2,
- read_link_info/1, read_link_info/2,
+ read_link_info/1, read_link_info/2, read_link_info/3,
list_dir/1, list_dir/2]).
%% How to start and stop the ?DRV port.
-export([start/0, stop/1]).
@@ -98,6 +99,7 @@
-define(FILE_READ_LINE, 29).
-define(FILE_FDATASYNC, 30).
-define(FILE_ADVISE, 31).
+-define(FILE_SENDFILE, 32).
%% Driver responses
-define(FILE_RESP_OK, 0).
@@ -537,7 +539,31 @@ write_file(File, Bin) when (is_list(File) orelse is_binary(File)) ->
end;
write_file(_, _) ->
{error, badarg}.
-
+
+
+%% Returns {error, Reason} | {ok, BytesCopied}
+%sendfile(_,_,_,_,_,_,_,_,_,_) ->
+% {error, enotsup};
+sendfile(#file_descriptor{module = ?MODULE, data = {Port, _}},
+ Dest, Offset, Bytes, _ChunkSize, Headers, Trailers,
+ _Nodiskio, _MNowait, _Sync) ->
+ case erlang:port_get_data(Dest) of
+ Data when Data == inet_tcp; Data == inet6_tcp ->
+ ok = inet:lock_socket(Dest,true),
+ {ok, DestFD} = prim_inet:getfd(Dest),
+ try drv_command(Port, [<<?FILE_SENDFILE, DestFD:32,
+ 0:8,
+ Offset:64/unsigned,
+ Bytes:64/unsigned,
+ (iolist_size(Headers)):32/unsigned,
+ (iolist_size(Trailers)):32/unsigned>>,
+ Headers,Trailers])
+ after
+ ok = inet:lock_socket(Dest,false)
+ end;
+ _Else ->
+ {error,badarg}
+ end.
%%%-----------------------------------------------------------------
@@ -699,16 +725,33 @@ del_dir_int(Port, Dir) ->
-%% read_file_info/{1,2}
+%% read_file_info/{1,2,3}
read_file_info(File) ->
- read_file_info_int({?DRV, [binary]}, File).
+ read_file_info_int({?DRV, [binary]}, File, local).
read_file_info(Port, File) when is_port(Port) ->
- read_file_info_int(Port, File).
+ read_file_info_int(Port, File, local);
+read_file_info(File, Opts) ->
+ read_file_info_int({?DRV, [binary]}, File, plgv(time, Opts, local)).
+
+read_file_info(Port, File, Opts) when is_port(Port) ->
+ read_file_info_int(Port, File, plgv(time, Opts, local)).
+
+read_file_info_int(Port, File, TimeType) ->
+ try
+ case drv_command(Port, [?FILE_FSTAT, pathname(File)]) of
+ {ok, FI} -> {ok, FI#file_info{
+ ctime = from_seconds(FI#file_info.ctime, TimeType),
+ mtime = from_seconds(FI#file_info.mtime, TimeType),
+ atime = from_seconds(FI#file_info.atime, TimeType)
+ }};
+ Error -> Error
+ end
+ catch
+ error:_ -> {error, badarg}
+ end.
-read_file_info_int(Port, File) ->
- drv_command(Port, [?FILE_FSTAT, pathname(File)]).
%% altname/{1,2}
@@ -721,38 +764,61 @@ altname(Port, File) when is_port(Port) ->
altname_int(Port, File) ->
drv_command(Port, [?FILE_ALTNAME, pathname(File)]).
-%% write_file_info/{2,3}
+%% write_file_info/{2,3,4}
write_file_info(File, Info) ->
- write_file_info_int({?DRV, [binary]}, File, Info).
+ write_file_info_int({?DRV, [binary]}, File, Info, local).
write_file_info(Port, File, Info) when is_port(Port) ->
- write_file_info_int(Port, File, Info).
+ write_file_info_int(Port, File, Info, local);
+write_file_info(File, Info, Opts) ->
+ write_file_info_int({?DRV, [binary]}, File, Info, plgv(time, Opts, local)).
+
+write_file_info(Port, File, Info, Opts) when is_port(Port) ->
+ write_file_info_int(Port, File, Info, plgv(time, Opts, local)).
-write_file_info_int(Port,
- File,
+write_file_info_int(Port, File,
#file_info{mode=Mode,
uid=Uid,
gid=Gid,
atime=Atime0,
mtime=Mtime0,
- ctime=Ctime}) ->
- {Atime, Mtime} =
- case {Atime0, Mtime0} of
- {undefined, Mtime0} -> {erlang:localtime(), Mtime0};
- {Atime0, undefined} -> {Atime0, Atime0};
- Complete -> Complete
- end,
- drv_command(Port, [?FILE_WRITE_INFO,
- int_to_bytes(Mode),
- int_to_bytes(Uid),
- int_to_bytes(Gid),
- date_to_bytes(Atime),
- date_to_bytes(Mtime),
- date_to_bytes(Ctime),
- pathname(File)]).
+ ctime=Ctime0},
+ TimeType) ->
+
+ % Atime and/or Mtime might be undefined
+ % - use localtime() for atime, if atime is undefined
+ % - use atime as mtime if mtime is undefined
+ % - use mtime as ctime if ctime is undefined
+
+ try
+ Atime = file_info_validate_atime(Atime0, TimeType),
+ Mtime = file_info_validate_mtime(Mtime0, Atime),
+ Ctime = file_info_validate_ctime(Ctime0, Mtime),
+
+ drv_command(Port, [?FILE_WRITE_INFO,
+ int_to_int32bytes(Mode),
+ int_to_int32bytes(Uid),
+ int_to_int32bytes(Gid),
+ int_to_int64bytes(to_seconds(Atime, TimeType)),
+ int_to_int64bytes(to_seconds(Mtime, TimeType)),
+ int_to_int64bytes(to_seconds(Ctime, TimeType)),
+ pathname(File)])
+ catch
+ error:_ -> {error, badarg}
+ end.
+
+file_info_validate_atime(Atime, _) when Atime =/= undefined -> Atime;
+file_info_validate_atime(undefined, local) -> erlang:localtime();
+file_info_validate_atime(undefined, universal) -> erlang:universaltime();
+file_info_validate_atime(undefined, posix) -> erlang:universaltime_to_posixtime(erlang:universaltime()).
+file_info_validate_mtime(undefined, Atime) -> Atime;
+file_info_validate_mtime(Mtime, _) -> Mtime.
+
+file_info_validate_ctime(undefined, Mtime) -> Mtime;
+file_info_validate_ctime(Ctime, _) -> Ctime.
%% make_link/{2,3}
@@ -796,15 +862,31 @@ read_link_int(Port, Link) ->
%% read_link_info/{2,3}
read_link_info(Link) ->
- read_link_info_int({?DRV, [binary]}, Link).
+ read_link_info_int({?DRV, [binary]}, Link, local).
read_link_info(Port, Link) when is_port(Port) ->
- read_link_info_int(Port, Link).
+ read_link_info_int(Port, Link, local);
+
+read_link_info(Link, Opts) ->
+ read_link_info_int({?DRV, [binary]}, Link, plgv(time, Opts, local)).
-read_link_info_int(Port, Link) ->
- drv_command(Port, [?FILE_LSTAT, pathname(Link)]).
+read_link_info(Port, Link, Opts) when is_port(Port) ->
+ read_link_info_int(Port, Link, plgv(time, Opts, local)).
+read_link_info_int(Port, Link, TimeType) ->
+ try
+ case drv_command(Port, [?FILE_LSTAT, pathname(Link)]) of
+ {ok, FI} -> {ok, FI#file_info{
+ ctime = from_seconds(FI#file_info.ctime, TimeType),
+ mtime = from_seconds(FI#file_info.mtime, TimeType),
+ atime = from_seconds(FI#file_info.atime, TimeType)
+ }};
+ Error -> Error
+ end
+ catch
+ error:_ -> {error, badarg}
+ end.
%% list_dir/{1,2}
@@ -1049,7 +1131,7 @@ translate_response(?FILE_RESP_DATA, List) ->
{_N, _Data} = ND = get_uint64(List),
{ok, ND};
translate_response(?FILE_RESP_INFO, List) when is_list(List) ->
- {ok, transform_info_ints(get_uint32s(List))};
+ {ok, transform_info(List)};
translate_response(?FILE_RESP_NUMERR, L0) ->
{N, L1} = get_uint64(L0),
{error, {N, list_to_atom(L1)}};
@@ -1103,27 +1185,37 @@ translate_response(?FILE_RESP_ALL_DATA, Data) ->
translate_response(X, Data) ->
{error, {bad_response_from_port, [X | Data]}}.
-transform_info_ints(Ints) ->
- [HighSize, LowSize, Type|Tail0] = Ints,
- Size = HighSize * 16#100000000 + LowSize,
- [Ay, Am, Ad, Ah, Ami, As|Tail1] = Tail0,
- [My, Mm, Md, Mh, Mmi, Ms|Tail2] = Tail1,
- [Cy, Cm, Cd, Ch, Cmi, Cs|Tail3] = Tail2,
- [Mode, Links, Major, Minor, Inode, Uid, Gid, Access] = Tail3,
+transform_info([
+ Hsize1, Hsize2, Hsize3, Hsize4,
+ Lsize1, Lsize2, Lsize3, Lsize4,
+ Type1, Type2, Type3, Type4,
+ Atime1, Atime2, Atime3, Atime4, Atime5, Atime6, Atime7, Atime8,
+ Mtime1, Mtime2, Mtime3, Mtime4, Mtime5, Mtime6, Mtime7, Mtime8,
+ Ctime1, Ctime2, Ctime3, Ctime4, Ctime5, Ctime6, Ctime7, Ctime8,
+ Mode1, Mode2, Mode3, Mode4,
+ Links1, Links2, Links3, Links4,
+ Major1, Major2, Major3, Major4,
+ Minor1, Minor2, Minor3, Minor4,
+ Inode1, Inode2, Inode3, Inode4,
+ Uid1, Uid2, Uid3, Uid4,
+ Gid1, Gid2, Gid3, Gid4,
+ Access1,Access2,Access3,Access4]) ->
#file_info {
- size = Size,
- type = file_type(Type),
- access = file_access(Access),
- atime = {{Ay, Am, Ad}, {Ah, Ami, As}},
- mtime = {{My, Mm, Md}, {Mh, Mmi, Ms}},
- ctime = {{Cy, Cm, Cd}, {Ch, Cmi, Cs}},
- mode = Mode,
- links = Links,
- major_device = Major,
- minor_device = Minor,
- inode = Inode,
- uid = Uid,
- gid = Gid}.
+ size = uint32(Hsize1,Hsize2,Hsize3,Hsize4)*16#100000000 + uint32(Lsize1,Lsize2,Lsize3,Lsize4),
+ type = file_type(uint32(Type1,Type2,Type3,Type4)),
+ access = file_access(uint32(Access1,Access2,Access3,Access4)),
+ atime = sint64(Atime1, Atime2, Atime3, Atime4, Atime5, Atime6, Atime7, Atime8),
+ mtime = sint64(Mtime1, Mtime2, Mtime3, Mtime4, Mtime5, Mtime6, Mtime7, Mtime8),
+ ctime = sint64(Ctime1, Ctime2, Ctime3, Ctime4, Ctime5, Ctime6, Ctime7, Ctime8),
+ mode = uint32(Mode1,Mode2,Mode3,Mode4),
+ links = uint32(Links1,Links2,Links3,Links4),
+ major_device = uint32(Major1,Major2,Major3,Major4),
+ minor_device = uint32(Minor1,Minor2,Minor3,Minor4),
+ inode = uint32(Inode1,Inode2,Inode3,Inode4),
+ uid = uint32(Uid1,Uid2,Uid3,Uid4),
+ gid = uint32(Gid1,Gid2,Gid3,Gid4)
+ }.
+
file_type(1) -> device;
file_type(2) -> directory;
@@ -1136,24 +1228,22 @@ file_access(1) -> write;
file_access(2) -> read;
file_access(3) -> read_write.
-int_to_bytes(Int) when is_integer(Int) ->
+int_to_int32bytes(Int) when is_integer(Int) ->
<<Int:32>>;
-int_to_bytes(undefined) ->
+int_to_int32bytes(undefined) ->
<<-1:32>>.
-date_to_bytes(undefined) ->
- <<-1:32, -1:32, -1:32, -1:32, -1:32, -1:32>>;
-date_to_bytes({{Y, Mon, D}, {H, Min, S}}) ->
- <<Y:32, Mon:32, D:32, H:32, Min:32, S:32>>.
+int_to_int64bytes(Int) when is_integer(Int) ->
+ <<Int:64/signed>>.
-%% uint64([[X1, X2, X3, X4] = Y1 | [X5, X6, X7, X8] = Y2]) ->
-%% (uint32(Y1) bsl 32) bor uint32(Y2).
-%% uint64(X1, X2, X3, X4, X5, X6, X7, X8) ->
-%% (uint32(X1, X2, X3, X4) bsl 32) bor uint32(X5, X6, X7, X8).
+sint64(I1,I2,I3,I4,I5,I6,I7,I8) when I1 > 127 ->
+ ((I1 bsl 56) bor (I2 bsl 48) bor (I3 bsl 40) bor (I4 bsl 32) bor
+ (I5 bsl 24) bor (I6 bsl 16) bor (I7 bsl 8) bor I8) - (1 bsl 64);
+sint64(I1,I2,I3,I4,I5,I6,I7,I8) ->
+ ((I1 bsl 56) bor (I2 bsl 48) bor (I3 bsl 40) bor (I4 bsl 32) bor
+ (I5 bsl 24) bor (I6 bsl 16) bor (I7 bsl 8) bor I8).
-%% uint32([X1,X2,X3,X4]) ->
-%% (X1 bsl 24) bor (X2 bsl 16) bor (X3 bsl 8) bor X4.
uint32(X1,X2,X3,X4) ->
(X1 bsl 24) bor (X2 bsl 16) bor (X3 bsl 8) bor X4.
@@ -1166,11 +1256,6 @@ get_uint64(L0) ->
get_uint32([X1,X2,X3,X4|List]) ->
{(((((X1 bsl 8) bor X2) bsl 8) bor X3) bsl 8) bor X4, List}.
-get_uint32s([X1,X2,X3,X4|Tail]) ->
- [uint32(X1,X2,X3,X4) | get_uint32s(Tail)];
-get_uint32s([]) -> [].
-
-
%% Binary mode
transform_ldata(<<0:32, 0:32>>) ->
@@ -1249,3 +1334,28 @@ reverse(L, T) -> lists:reverse(L, T).
% in list_to_binary, which is caught and generates the {error,badarg} return
pathname(File) ->
(catch prim_file:internal_name2native(File)).
+
+
+%% proplist:get_value/3
+plgv(K, [{K, V}|_], _) -> V;
+plgv(K, [_|KVs], D) -> plgv(K, KVs, D);
+plgv(_, [], D) -> D.
+
+%%
+%% We don't actually want this here
+%% We want to use posix time in all prim but erl_prim_loader makes that tricky
+%% It is probably needed to redo the whole erl_prim_loader
+
+from_seconds(Seconds, posix) when is_integer(Seconds) ->
+ Seconds;
+from_seconds(Seconds, universal) when is_integer(Seconds) ->
+ erlang:posixtime_to_universaltime(Seconds);
+from_seconds(Seconds, local) when is_integer(Seconds) ->
+ erlang:universaltime_to_localtime(erlang:posixtime_to_universaltime(Seconds)).
+
+to_seconds(Seconds, posix) when is_integer(Seconds) ->
+ Seconds;
+to_seconds({_,_} = Datetime, universal) ->
+ erlang:universaltime_to_posixtime(Datetime);
+to_seconds({_,_} = Datetime, local) ->
+ erlang:universaltime_to_posixtime(erlang:localtime_to_universaltime(Datetime)).
diff --git a/erts/preloaded/src/prim_inet.erl b/erts/preloaded/src/prim_inet.erl
index 8f2e845b4f..0cedd284db 100644
--- a/erts/preloaded/src/prim_inet.erl
+++ b/erts/preloaded/src/prim_inet.erl
@@ -25,8 +25,8 @@
%% Primitive inet_drv interface
--export([open/1, open/2, fdopen/2, fdopen/3, close/1]).
--export([bind/3, listen/1, listen/2]).
+-export([open/3, fdopen/4, close/1]).
+-export([bind/3, listen/1, listen/2, peeloff/2]).
-export([connect/3, connect/4, async_connect/4]).
-export([accept/1, accept/2, async_accept/2]).
-export([shutdown/2]).
@@ -36,7 +36,8 @@
-export([recvfrom/2, recvfrom/3]).
-export([setopt/3, setopts/2, getopt/2, getopts/2, is_sockopt_val/2]).
-export([chgopt/3, chgopts/2]).
--export([getstat/2, getfd/1, getindex/1, getstatus/1, gettype/1,
+-export([getstat/2, getfd/1, ignorefd/2,
+ getindex/1, getstatus/1, gettype/1,
getifaddrs/1, getiflist/1, ifget/3, ifset/3,
gethostname/1]).
-export([getservbyname/3, getservbyport/3]).
@@ -56,58 +57,46 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
-%% OPEN(tcp | udp | sctp, inet | inet6) ->
+%% OPEN(tcp | udp | sctp, inet | inet6, stream | dgram | seqpacket) ->
%% {ok, insock()} |
%% {error, Reason}
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-open(Protocol) -> open1(Protocol, ?INET_AF_INET).
+open(Protocol, Family, Type) ->
+ open(Protocol, Family, Type, ?INET_REQ_OPEN, []).
-open(Protocol, inet) -> open1(Protocol, ?INET_AF_INET);
-open(Protocol, inet6) -> open1(Protocol, ?INET_AF_INET6);
-open(_, _) -> {error, einval}.
+fdopen(Protocol, Family, Type, Fd) when is_integer(Fd) ->
+ open(Protocol, Family, Type, ?INET_REQ_FDOPEN, ?int32(Fd)).
-fdopen(Protocol, Fd) -> fdopen1(Protocol, ?INET_AF_INET, Fd).
-
-fdopen(Protocol, Fd, inet) -> fdopen1(Protocol, ?INET_AF_INET, Fd);
-fdopen(Protocol, Fd, inet6) -> fdopen1(Protocol, ?INET_AF_INET6, Fd);
-fdopen(_, _, _) -> {error, einval}.
-
-open1(Protocol, Family) ->
- case open0(Protocol) of
- {ok, S} ->
- case ctl_cmd(S, ?INET_REQ_OPEN, [Family]) of
- {ok, _} ->
- {ok,S};
- Error ->
- close(S), Error
- end;
- Error -> Error
+open(Protocol, Family, Type, Req, Data) ->
+ Drv = protocol2drv(Protocol),
+ AF = enc_family(Family),
+ T = enc_type(Type),
+ try erlang:open_port({spawn_driver,Drv}, [binary]) of
+ S ->
+ case ctl_cmd(S, Req, [AF,T,Data]) of
+ {ok,_} -> {ok,S};
+ {error,_}=Error ->
+ close(S),
+ Error
+ end
+ catch
+ %% The only (?) way to get here is to try to open
+ %% the sctp driver when it does not exist
+ error:badarg -> {error,eprotonosupport}
end.
-fdopen1(Protocol, Family, Fd) when is_integer(Fd) ->
- case open0(Protocol) of
- {ok, S} ->
- case ctl_cmd(S,?INET_REQ_FDOPEN,[Family,?int32(Fd)]) of
- {ok, _} -> {ok,S};
- Error -> close(S), Error
- end;
- Error -> Error
- end.
+enc_family(inet) -> ?INET_AF_INET;
+enc_family(inet6) -> ?INET_AF_INET6.
-open0(Protocol) ->
- try erlang:open_port({spawn_driver,protocol2drv(Protocol)}, [binary]) of
- Port -> {ok,Port}
- catch
- error:Reason -> {error,Reason}
- end.
+enc_type(stream) -> ?INET_TYPE_STREAM;
+enc_type(dgram) -> ?INET_TYPE_DGRAM;
+enc_type(seqpacket) -> ?INET_TYPE_SEQPACKET.
protocol2drv(tcp) -> "tcp_inet";
protocol2drv(udp) -> "udp_inet";
-protocol2drv(sctp) -> "sctp_inet";
-protocol2drv(_) ->
- erlang:error(eprotonosupport).
+protocol2drv(sctp) -> "sctp_inet".
drv2protocol("tcp_inet") -> tcp;
drv2protocol("udp_inet") -> udp;
@@ -139,7 +128,7 @@ shutdown_1(S, How) ->
shutdown_2(S, How) ->
case ctl_cmd(S, ?TCP_REQ_SHUTDOWN, [How]) of
{ok, []} -> ok;
- Error -> Error
+ {error,_}=Error -> Error
end.
shutdown_pend_loop(S, N0) ->
@@ -195,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
{ok, [P1,P0]} -> {ok, ?u16(P1, P0)};
- Error -> Error
+ {error,_}=Error -> Error
end;
%% Multi-homed "bind": sctp_bindx(). The Op is 'add' or 'remove'.
@@ -222,7 +211,7 @@ bindx(S, AddFlag, Addrs) ->
{IP, Port} <- Addrs]],
case ctl_cmd(S, ?SCTP_REQ_BINDX, Args) of
{ok,_} -> {ok, S};
- Error -> Error
+ {error,_}=Error -> Error
end;
_ -> {error, einval}
end.
@@ -265,7 +254,7 @@ async_connect(S, IP, Port, Time) ->
case ctl_cmd(S, ?INET_REQ_CONNECT,
[enc_time(Time),?int16(Port),ip_to_bytes(IP)]) of
{ok, [R1,R0]} -> {ok, S, ?u16(R1,R0)};
- Error -> Error
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -318,9 +307,9 @@ accept_opts(L, S) ->
end.
async_accept(L, Time) ->
- case ctl_cmd(L,?TCP_REQ_ACCEPT, [enc_time(Time)]) of
+ case ctl_cmd(L,?INET_REQ_ACCEPT, [enc_time(Time)]) of
{ok, [R1,R0]} -> {ok, ?u16(R1,R0)};
- Error -> Error
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -334,16 +323,30 @@ async_accept(L, Time) ->
%% listening) is also accepted:
listen(S) -> listen(S, ?LISTEN_BACKLOG).
-
+
+listen(S, true) -> listen(S, ?LISTEN_BACKLOG);
+listen(S, false) -> listen(S, 0);
listen(S, BackLog) when is_port(S), is_integer(BackLog) ->
- case ctl_cmd(S, ?TCP_REQ_LISTEN, [?int16(BackLog)]) of
+ case ctl_cmd(S, ?INET_REQ_LISTEN, [?int16(BackLog)]) of
{ok, _} -> ok;
- Error -> Error
- end;
-listen(S, Flag) when is_port(S), is_boolean(Flag) ->
- case ctl_cmd(S, ?SCTP_REQ_LISTEN, enc_value(set, bool8, Flag)) of
- {ok,_} -> ok;
- Error -> Error
+ {error,_}=Error -> Error
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% PEELOFF(insock(), AssocId) -> {ok,outsock()} | {error, Reason}
+%%
+%% SCTP: Peel off one association into a type stream socket
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+peeloff(S, AssocId) ->
+ case ctl_cmd(S, ?SCTP_REQ_PEELOFF, [?int32(AssocId)]) of
+ inet_reply ->
+ receive
+ {inet_reply,S,Res} -> Res
+ end;
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -395,12 +398,12 @@ sendto(S, IP, Port, Data) when is_port(S), Port >= 0, Port =< 65535 ->
true ->
receive
{inet_reply,S,Reply} ->
- ?DBG_FORMAT("prim_inet:send() -> ~p~n", [Reply]),
+ ?DBG_FORMAT("prim_inet:sendto() -> ~p~n", [Reply]),
Reply
end
catch
error:_ ->
- ?DBG_FORMAT("prim_inet:send() -> {error,einval}~n", []),
+ ?DBG_FORMAT("prim_inet:sendto() -> {error,einval}~n", []),
{error,einval}
end.
@@ -455,7 +458,7 @@ recv0(S, Length, Time) when is_port(S), is_integer(Length), Length >= 0 ->
async_recv(S, Length, Time) ->
case ctl_cmd(S, ?TCP_REQ_RECV, [enc_time(Time), ?int32(Length)]) of
{ok,[R1,R0]} -> {ok, ?u16(R1,R0)};
- Error -> Error
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -501,7 +504,7 @@ recvfrom0(S, Length, Time)
{inet_async, S, Ref, Error={error, _}} ->
Error
end;
- Error ->
+ {error,_}=Error ->
Error % Front-end error
end;
recvfrom0(_, _, _) -> {error,einval}.
@@ -517,18 +520,18 @@ peername(S) when is_port(S) ->
{ok, [F, P1,P0 | Addr]} ->
{IP, _} = get_ip(F, Addr),
{ok, { IP, ?u16(P1, P0) }};
- Error -> Error
+ {error,_}=Error -> Error
end.
setpeername(S, {IP,Port}) when is_port(S) ->
case ctl_cmd(S, ?INET_REQ_SETPEER, [?int16(Port),ip_to_bytes(IP)]) of
{ok,[]} -> ok;
- Error -> Error
+ {error,_}=Error -> Error
end;
setpeername(S, undefined) when is_port(S) ->
case ctl_cmd(S, ?INET_REQ_SETPEER, []) of
{ok,[]} -> ok;
- Error -> Error
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -542,18 +545,18 @@ sockname(S) when is_port(S) ->
{ok, [F, P1, P0 | Addr]} ->
{IP, _} = get_ip(F, Addr),
{ok, { IP, ?u16(P1, P0) }};
- Error -> Error
+ {error,_}=Error -> Error
end.
setsockname(S, {IP,Port}) when is_port(S) ->
case ctl_cmd(S, ?INET_REQ_SETNAME, [?int16(Port),ip_to_bytes(IP)]) of
{ok,[]} -> ok;
- Error -> Error
+ {error,_}=Error -> Error
end;
setsockname(S, undefined) when is_port(S) ->
case ctl_cmd(S, ?INET_REQ_SETNAME, []) of
{ok,[]} -> ok;
- Error -> Error
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -573,7 +576,7 @@ setopts(S, Opts) when is_port(S) ->
{ok, Buf} ->
case ctl_cmd(S, ?INET_REQ_SETOPTS, Buf) of
{ok, _} -> ok;
- Error -> Error
+ {error,_}=Error -> Error
end;
Error -> Error
end.
@@ -599,12 +602,12 @@ getopts(S, Opts) when is_port(S), is_list(Opts) ->
{ok,Rep} ->
%% Non-SCTP: "Rep" contains the encoded option vals:
decode_opt_val(Rep);
- {error,sctp_reply} ->
+ inet_reply ->
%% SCTP: Need to receive the full value:
receive
{inet_reply,S,Res} -> Res
end;
- Error -> Error
+ {error,_}=Error -> Error
end;
Error -> Error
end.
@@ -733,7 +736,7 @@ getifaddrs_ifget(S, IFs, IF, FlagsVals, Opts) ->
getiflist(S) when is_port(S) ->
case ctl_cmd(S, ?INET_REQ_GETIFLIST, []) of
{ok, Data} -> {ok, build_iflist(Data)};
- Error -> Error
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -751,7 +754,7 @@ ifget(S, Name, Opts) ->
{ok, Buf2} ->
case ctl_cmd(S, ?INET_REQ_IFGET, [Buf1,Buf2]) of
{ok, Data} -> decode_ifopts(Data,[]);
- Error -> Error
+ {error,_}=Error -> Error
end;
Error -> Error
end;
@@ -773,7 +776,7 @@ ifset(S, Name, Opts) ->
{ok, Buf2} ->
case ctl_cmd(S, ?INET_REQ_IFSET, [Buf1,Buf2]) of
{ok, _} -> ok;
- Error -> Error
+ {error,_}=Error -> Error
end;
Error -> Error
end;
@@ -801,7 +804,7 @@ subscribe(S, Sub) when is_port(S), is_list(Sub) ->
{ok, Bytes} ->
case ctl_cmd(S, ?INET_REQ_SUBSCRIBE, Bytes) of
{ok, Data} -> decode_subs(Data);
- Error -> Error
+ {error,_}=Error -> Error
end;
Error -> Error
end.
@@ -819,7 +822,7 @@ getstat(S, Stats) when is_port(S), is_list(Stats) ->
{ok, Bytes} ->
case ctl_cmd(S, ?INET_REQ_GETSTAT, Bytes) of
{ok, Data} -> decode_stats(Data);
- Error -> Error
+ {error,_}=Error -> Error
end;
Error -> Error
end.
@@ -835,11 +838,26 @@ getstat(S, Stats) when is_port(S), is_list(Stats) ->
getfd(S) when is_port(S) ->
case ctl_cmd(S, ?INET_REQ_GETFD, []) of
{ok, [S3,S2,S1,S0]} -> {ok, ?u32(S3,S2,S1,S0)};
- Error -> Error
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
+%% IGNOREFD(insock(),boolean()) -> {ok,integer()} | {error, Reason}
+%%
+%% steal internal file descriptor
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ignorefd(S,Bool) when is_port(S) ->
+ Val = if Bool -> 1; true -> 0 end,
+ case ctl_cmd(S, ?INET_REQ_IGNOREFD, [Val]) of
+ {ok, _} -> ok;
+ Error -> Error
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
%% GETIX(insock()) -> {ok,integer()} | {error, Reason}
%%
%% get internal socket index
@@ -873,7 +891,7 @@ gettype(S) when is_port(S) ->
_ -> undefined
end,
{ok, {Family, Type}};
- Error -> Error
+ {error,_}=Error -> Error
end.
getprotocol(S) when is_port(S) ->
@@ -901,7 +919,7 @@ getstatus(S) when is_port(S) ->
case ctl_cmd(S, ?INET_REQ_GETSTATUS, []) of
{ok, [S3,S2,S1,S0]} ->
{ok, dec_status(?u32(S3,S2,S1,S0))};
- Error -> Error
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -943,7 +961,7 @@ getservbyname1(S,Name,Proto) ->
case ctl_cmd(S, ?INET_REQ_GETSERVBYNAME, [L1,Name,L2,Proto]) of
{ok, [P1,P0]} ->
{ok, ?u16(P1,P0)};
- Error ->
+ {error,_}=Error ->
Error
end
end.
@@ -971,7 +989,7 @@ getservbyport1(S,Port,Proto) ->
true ->
case ctl_cmd(S, ?INET_REQ_GETSERVBYPORT, [?int16(Port),L,Proto]) of
{ok, Name} -> {ok, Name};
- Error -> Error
+ {error,_}=Error -> Error
end
end.
@@ -985,7 +1003,7 @@ getservbyport1(S,Port,Proto) ->
unrecv(S, Data) ->
case ctl_cmd(S, ?TCP_REQ_UNRECV, Data) of
{ok, _} -> ok;
- Error -> Error
+ {error,_}=Error -> Error
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2163,7 +2181,7 @@ ctl_cmd(Port, Cmd, Args) ->
Result =
try erlang:port_control(Port, Cmd, Args) of
[?INET_REP_OK|Reply] -> {ok,Reply};
- [?INET_REP_SCTP] -> {error,sctp_reply};
+ [?INET_REP] -> inet_reply;
[?INET_REP_ERROR|Err] -> {error,list_to_atom(Err)}
catch
error:_ -> {error,einval}
diff --git a/erts/preloaded/src/prim_zip.erl b/erts/preloaded/src/prim_zip.erl
index 392a9feb45..d29f17ae56 100644
--- a/erts/preloaded/src/prim_zip.erl
+++ b/erts/preloaded/src/prim_zip.erl
@@ -432,7 +432,7 @@ binary_io({file_info, B}, _) ->
is_binary(B) -> {regular, byte_size(B)};
B =:= directory -> {directory, 0}
end,
- Now = calendar:local_time(),
+ Now = erlang:localtime(),
#file_info{size = Size, type = Type, access = read_write,
atime = Now, mtime = Now, ctime = Now,
mode = 0, links = 1, major_device = 0,