aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/asn1/doc/src/notes.xml66
-rw-r--r--lib/asn1/src/asn1_db.erl2
-rw-r--r--lib/asn1/src/asn1ct_constructed_per.erl26
-rw-r--r--lib/asn1/src/asn1ct_func.erl2
-rw-r--r--lib/asn1/src/asn1ct_gen_per.erl3
-rw-r--r--lib/asn1/src/asn1ct_imm.erl7
-rw-r--r--lib/asn1/src/asn1ct_name.erl2
-rw-r--r--lib/asn1/src/asn1ct_parser2.erl2
-rw-r--r--lib/asn1/test/asn1_SUITE.erl7
-rw-r--r--lib/asn1/test/asn1_SUITE_data/EnumExt.asn120
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn19
-rw-r--r--lib/asn1/test/asn1_SUITE_data/SeqExtension2.asn1208
-rw-r--r--lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl3
-rw-r--r--lib/asn1/test/asn1_test_lib.erl14
-rw-r--r--lib/asn1/test/testChoExtension.erl2
-rw-r--r--lib/asn1/test/testCompactBitString.erl2
-rw-r--r--lib/asn1/test/testConstraints.erl33
-rw-r--r--lib/asn1/test/testDeepTConstr.erl2
-rw-r--r--lib/asn1/test/testEnumExt.erl28
-rw-r--r--lib/asn1/test/testInfObj.erl2
-rw-r--r--lib/asn1/test/testParameterizedInfObj.erl2
-rw-r--r--lib/asn1/test/testPrim.erl2
-rw-r--r--lib/asn1/test/testSeqExtension.erl35
-rw-r--r--lib/asn1/test/testSeqOf.erl2
-rw-r--r--lib/asn1/vsn.mk2
-rw-r--r--lib/common_test/doc/src/notes.xml152
-rw-r--r--lib/common_test/src/ct_ftp.erl2
-rw-r--r--lib/common_test/src/ct_run.erl6
-rw-r--r--lib/common_test/src/ct_ssh.erl2
-rw-r--r--lib/common_test/src/ct_testspec.erl70
-rw-r--r--lib/common_test/test/ct_gen_conn_SUITE.erl2
-rw-r--r--lib/common_test/test/ct_gen_conn_SUITE_data/conn_SUITE.erl2
-rw-r--r--lib/common_test/test/ct_testspec_3_SUITE.erl928
-rw-r--r--lib/common_test/vsn.mk2
-rw-r--r--lib/compiler/doc/src/notes.xml51
-rw-r--r--lib/compiler/src/beam_a.erl2
-rw-r--r--lib/compiler/src/beam_utils.erl2
-rw-r--r--lib/compiler/src/v3_core.erl2
-rw-r--r--lib/compiler/test/bs_bincomp_SUITE.erl2
-rw-r--r--lib/compiler/vsn.mk2
-rw-r--r--lib/cosEvent/doc/src/notes.xml17
-rw-r--r--lib/cosEvent/vsn.mk2
-rw-r--r--lib/cosFileTransfer/doc/src/notes.xml17
-rw-r--r--lib/cosFileTransfer/vsn.mk2
-rw-r--r--lib/cosNotification/doc/src/notes.xml17
-rw-r--r--lib/cosNotification/vsn.mk2
-rw-r--r--lib/crypto/c_src/crypto.c265
-rw-r--r--lib/crypto/doc/src/crypto.xml113
-rw-r--r--lib/crypto/doc/src/notes.xml59
-rw-r--r--lib/crypto/src/crypto.appup.src14
-rw-r--r--lib/crypto/src/crypto.erl1659
-rw-r--r--lib/crypto/test/crypto_SUITE.erl132
-rw-r--r--lib/crypto/vsn.mk2
-rw-r--r--lib/debugger/doc/src/notes.xml26
-rw-r--r--lib/debugger/src/dbg_istk.erl2
-rw-r--r--lib/debugger/vsn.mk2
-rw-r--r--lib/dialyzer/doc/src/notes.xml71
-rw-r--r--lib/dialyzer/src/dialyzer.erl2
-rw-r--r--lib/dialyzer/src/dialyzer_analysis_callgraph.erl2
-rw-r--r--lib/dialyzer/src/dialyzer_contracts.erl2
-rw-r--r--lib/dialyzer/vsn.mk2
-rw-r--r--lib/diameter/Makefile8
-rw-r--r--lib/diameter/doc/src/Makefile4
-rw-r--r--lib/diameter/doc/src/diameter.xml32
-rw-r--r--lib/diameter/doc/src/diameter_compile.xml6
-rw-r--r--lib/diameter/doc/src/diameter_dict.xml4
-rw-r--r--lib/diameter/doc/src/diameter_intro.xml4
-rw-r--r--lib/diameter/doc/src/diameter_sctp.xml22
-rw-r--r--lib/diameter/doc/src/diameter_tcp.xml15
-rw-r--r--lib/diameter/doc/src/diameter_using.xml4
-rw-r--r--lib/diameter/doc/src/notes.xml223
-rw-r--r--lib/diameter/src/Makefile10
-rw-r--r--lib/diameter/src/base/diameter.erl4
-rw-r--r--lib/diameter/src/base/diameter_capx.erl9
-rw-r--r--lib/diameter/src/base/diameter_codec.erl2
-rw-r--r--lib/diameter/src/base/diameter_config.erl9
-rw-r--r--lib/diameter/src/base/diameter_peer.erl94
-rw-r--r--lib/diameter/src/base/diameter_service.erl24
-rw-r--r--lib/diameter/src/base/diameter_traffic.erl27
-rw-r--r--lib/diameter/src/diameter.app.src (renamed from lib/diameter/src/base/diameter.app.src)0
-rw-r--r--lib/diameter/src/diameter.appup.src (renamed from lib/diameter/src/base/diameter.appup.src)31
-rw-r--r--lib/diameter/src/dict/base_rfc3588.dia6
-rw-r--r--lib/diameter/src/transport/diameter_sctp.erl74
-rw-r--r--lib/diameter/src/transport/diameter_tcp.erl64
-rw-r--r--lib/diameter/test/Makefile6
-rw-r--r--lib/diameter/test/diameter_capx_SUITE.erl82
-rw-r--r--lib/diameter/test/diameter_codec_SUITE.erl2
-rw-r--r--lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl2
-rw-r--r--lib/diameter/test/diameter_examples_SUITE.erl2
-rw-r--r--lib/diameter/test/diameter_traffic_SUITE.erl4
-rw-r--r--lib/diameter/test/diameter_util.erl2
-rw-r--r--lib/diameter/vsn.mk2
-rw-r--r--lib/erl_interface/doc/src/notes.xml16
-rw-r--r--lib/erl_interface/vsn.mk2
-rw-r--r--lib/et/doc/src/notes.xml23
-rw-r--r--lib/et/src/et_collector.erl2
-rw-r--r--lib/et/vsn.mk2
-rw-r--r--lib/hipe/doc/src/notes.xml30
-rw-r--r--lib/hipe/icode/Makefile2
-rw-r--r--lib/hipe/icode/hipe_icode.erl2
-rw-r--r--lib/hipe/icode/hipe_icode.hrl2
-rw-r--r--lib/hipe/icode/hipe_icode_callgraph.erl2
-rw-r--r--lib/hipe/icode/hipe_icode_range.erl2
-rw-r--r--lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl2
-rw-r--r--lib/hipe/regalloc/hipe_ls_regalloc.erl2
-rw-r--r--lib/hipe/rtl/Makefile2
-rw-r--r--lib/hipe/vsn.mk2
-rw-r--r--lib/ic/doc/src/notes.xml18
-rw-r--r--lib/ic/src/icparse.yrl2
-rw-r--r--lib/ic/vsn.mk2
-rw-r--r--lib/inets/doc/src/notes.xml61
-rw-r--r--lib/inets/src/http_client/httpc.erl2
-rw-r--r--lib/inets/src/http_lib/http_chunk.erl2
-rw-r--r--lib/inets/src/http_lib/http_request.erl2
-rw-r--r--lib/inets/test/http_format_SUITE.erl2
-rw-r--r--lib/inets/vsn.mk2
-rw-r--r--lib/kernel/doc/src/heart.xml9
-rw-r--r--lib/kernel/doc/src/notes.xml85
-rw-r--r--lib/kernel/src/gen_udp.erl2
-rw-r--r--lib/kernel/src/heart.erl20
-rw-r--r--lib/kernel/src/inet.erl39
-rw-r--r--lib/kernel/src/inet_db.erl64
-rw-r--r--lib/kernel/src/inet_hosts.erl9
-rw-r--r--lib/kernel/src/inet_int.hrl2
-rw-r--r--lib/kernel/src/inet_res.erl4
-rw-r--r--lib/kernel/test/gen_sctp_SUITE.erl2
-rw-r--r--lib/kernel/test/gen_tcp_misc_SUITE.erl2
-rw-r--r--lib/kernel/test/global_SUITE_data/global_trace.erl2
-rw-r--r--lib/kernel/test/inet_SUITE.erl197
-rw-r--r--lib/kernel/test/inet_res_SUITE.erl198
-rw-r--r--lib/kernel/test/inet_res_SUITE_data/otptest/named_inc.conf6
-rw-r--r--lib/kernel/test/inet_res_SUITE_data/otptest/root.zone6
-rw-r--r--lib/kernel/test/inet_sockopt_SUITE.erl2
-rw-r--r--lib/megaco/doc/src/notes.xml17
-rw-r--r--lib/megaco/vsn.mk2
-rw-r--r--lib/mnesia/doc/src/notes.xml32
-rw-r--r--lib/mnesia/src/mnesia_index.erl2
-rw-r--r--lib/mnesia/src/mnesia_subscr.erl10
-rw-r--r--lib/mnesia/test/mnesia_durability_test.erl2
-rw-r--r--lib/mnesia/test/mnesia_evil_coverage_test.erl4
-rw-r--r--lib/mnesia/test/mnesia_isolation_test.erl10
-rw-r--r--lib/mnesia/vsn.mk2
-rw-r--r--lib/observer/doc/src/notes.xml63
-rw-r--r--lib/observer/src/observer_procinfo.erl2
-rw-r--r--lib/observer/src/observer_tv_table.erl2
-rw-r--r--lib/observer/vsn.mk2
-rw-r--r--lib/odbc/doc/src/notes.xml31
-rw-r--r--lib/odbc/test/oracle.erl2
-rw-r--r--lib/odbc/test/postgres.erl2
-rw-r--r--lib/odbc/vsn.mk2
-rw-r--r--lib/orber/COSS/CosNaming/orber_cosnaming_utils.erl2
-rw-r--r--lib/orber/doc/src/notes.xml17
-rw-r--r--lib/orber/src/orber_env.erl2
-rw-r--r--lib/orber/src/orber_iiop_outproxy.erl2
-rw-r--r--lib/orber/vsn.mk2
-rw-r--r--lib/os_mon/c_src/memsup.c2
-rw-r--r--lib/os_mon/doc/src/notes.xml28
-rw-r--r--lib/os_mon/src/disksup.erl2
-rw-r--r--lib/os_mon/src/nteventlog.erl5
-rw-r--r--lib/os_mon/src/os_sup.erl6
-rw-r--r--lib/os_mon/vsn.mk2
-rw-r--r--lib/percept/doc/src/notes.xml15
-rw-r--r--lib/percept/vsn.mk2
-rw-r--r--lib/public_key/doc/src/notes.xml44
-rw-r--r--lib/public_key/doc/src/public_key.xml20
-rw-r--r--lib/public_key/src/public_key.app.src2
-rw-r--r--lib/public_key/src/public_key.erl3
-rw-r--r--lib/public_key/test/pbe_SUITE.erl1
-rw-r--r--lib/public_key/test/pkits_SUITE.erl3
-rw-r--r--lib/public_key/test/public_key_SUITE.erl3
-rw-r--r--lib/public_key/vsn.mk2
-rw-r--r--lib/reltool/doc/src/notes.xml43
-rw-r--r--lib/reltool/src/reltool_target.erl9
-rw-r--r--lib/reltool/test/reltool_server_SUITE.erl11
-rw-r--r--lib/reltool/vsn.mk2
-rw-r--r--lib/runtime_tools/doc/src/notes.xml31
-rw-r--r--lib/runtime_tools/vsn.mk2
-rw-r--r--lib/sasl/doc/src/notes.xml16
-rw-r--r--lib/sasl/examples/src/target_system.erl35
-rw-r--r--lib/sasl/src/erlsrv.erl6
-rw-r--r--lib/sasl/src/release_handler.erl101
-rw-r--r--lib/sasl/test/installer.erl15
-rw-r--r--lib/sasl/test/release_handler_SUITE.erl205
-rw-r--r--lib/sasl/test/rh_test_lib.erl64
-rw-r--r--lib/sasl/test/systools_SUITE.erl6
-rw-r--r--lib/snmp/doc/src/files.mk2
-rw-r--r--lib/snmp/src/agent/depend.mk2
-rw-r--r--lib/snmp/src/agent/snmpa_agent_sup.erl2
-rw-r--r--lib/snmp/src/agent/snmpa_target_cache.erl2
-rw-r--r--lib/snmp/src/app/snmp_app.erl2
-rw-r--r--lib/snmp/src/manager/snmpm_config.erl2
-rw-r--r--lib/snmp/src/misc/snmp_config.erl2
-rw-r--r--lib/snmp/src/misc/snmp_misc.erl2
-rw-r--r--lib/snmp/test/snmp_agent_test_lib.erl2
-rw-r--r--lib/snmp/test/snmp_test_lib.erl2
-rw-r--r--lib/ssh/doc/src/notes.xml52
-rw-r--r--lib/ssh/src/ssh.appup.src14
-rw-r--r--lib/ssh/src/ssh.erl2
-rw-r--r--lib/ssh/src/ssh_xfer.erl2
-rw-r--r--lib/ssh/vsn.mk2
-rw-r--r--lib/ssl/doc/src/notes.xml75
-rw-r--r--lib/ssl/src/ssl.appup.src4
-rw-r--r--lib/ssl/src/ssl.erl4
-rw-r--r--lib/ssl/src/ssl_cipher.erl12
-rw-r--r--lib/ssl/src/ssl_manager.erl1
-rw-r--r--lib/ssl/src/tls.erl2
-rw-r--r--lib/ssl/src/tls_connection.erl3
-rw-r--r--lib/ssl/src/tls_handshake.erl2
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl3
-rw-r--r--lib/ssl/test/ssl_certificate_verify_SUITE.erl3
-rw-r--r--lib/ssl/test/ssl_npn_handshake_SUITE.erl1
-rw-r--r--lib/ssl/test/ssl_packet_SUITE.erl2
-rw-r--r--lib/ssl/test/ssl_payload_SUITE.erl1
-rw-r--r--lib/ssl/test/ssl_session_cache_SUITE.erl2
-rw-r--r--lib/ssl/test/ssl_to_openssl_SUITE.erl1
-rw-r--r--lib/ssl/vsn.mk2
-rw-r--r--lib/stdlib/doc/src/notes.xml173
-rw-r--r--lib/stdlib/src/gen.erl2
-rw-r--r--lib/stdlib/src/gen_event.erl2
-rw-r--r--lib/stdlib/src/lists.erl2
-rw-r--r--lib/stdlib/src/slave.erl28
-rw-r--r--lib/stdlib/test/c_SUITE.erl2
-rw-r--r--lib/stdlib/test/gen_event_SUITE.erl2
-rw-r--r--lib/stdlib/test/lists_SUITE.erl2
-rw-r--r--lib/stdlib/test/supervisor_3.erl2
-rw-r--r--lib/stdlib/test/supervisor_SUITE.erl2
-rw-r--r--lib/stdlib/test/unicode_SUITE.erl149
-rw-r--r--lib/test_server/doc/src/notes.xml52
-rw-r--r--lib/test_server/src/configure.in3
-rw-r--r--lib/test_server/src/test_server_node.erl31
-rw-r--r--lib/test_server/src/ts_install_cth.erl2
-rw-r--r--lib/test_server/vsn.mk2
-rw-r--r--lib/tools/doc/src/eprof.xml25
-rw-r--r--lib/tools/doc/src/notes.xml66
-rw-r--r--lib/tools/src/eprof.erl219
-rw-r--r--lib/tools/src/fprof.erl2
-rw-r--r--lib/tools/test/eprof_SUITE.erl245
-rw-r--r--lib/tools/test/eprof_SUITE_data/eprof_test.erl15
-rw-r--r--lib/tools/vsn.mk2
239 files changed, 5930 insertions, 1951 deletions
diff --git a/lib/asn1/doc/src/notes.xml b/lib/asn1/doc/src/notes.xml
index 5faf4fd48c..f3c1ef862c 100644
--- a/lib/asn1/doc/src/notes.xml
+++ b/lib/asn1/doc/src/notes.xml
@@ -31,6 +31,72 @@
<p>This document describes the changes made to the asn1 application.</p>
+<section><title>Asn1 2.0.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix some Makefile rules that didn't support silent rules.
+ Thanks to Anthony Ramine.</p>
+ <p>
+ Own Id: OTP-11111</p>
+ </item>
+ <item>
+ <p>PER/UPER: A semi-constrained INTEGER with a non-zero
+ lower bound would be incorrectly decoded. This bug was
+ introduced in R16.</p>
+ <p>PER/UPER: Given <c>INTEGER (10..MAX, ...)</c>,
+ attempting to decode any integer below 10 would cause the
+ encoder to enter an infinite loop.</p>
+ <p>PER/UPER: For a type with an extensible SIZE
+ constraint, sizes outside of the root range were
+ incorrectly encoded.</p>
+ <p>Given a constraint such as <c>(SIZE (5, ...))</c>,
+ encoding a size less than 5 would fail (PER/UPER).
+ Similarly, for BER decoding would fail.</p>
+ <p>PER: The encoder did not align a known multiplier
+ string (such as IA5String) of length 16 bits (exactly) to
+ an octet boundary.</p>
+ <p>In rare circumstances, DEFAULT values for the UPER
+ backend could be wrongly encoded.</p>
+ <p>
+ Own Id: OTP-11134</p>
+ </item>
+ <item>
+ <p>UPER: The compiler would crash when compiling an
+ ENUMERATED having more than 63 extended values.</p>
+ <p>PER/UPER: A SEQUENCE with more 64 extended values
+ could not be decoded.</p>
+ <p>
+ Own Id: OTP-11153</p>
+ </item>
+ <item>
+ <p>
+ When decoding a SEQUENCE defined inline inside a an
+ extension addition group, the record named generated by
+ the decoding code would not match the name in the
+ generated .hrl file.</p>
+ <p>
+ Own Id: OTP-11154 Aux Id: seq12339 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Postscript files no longer needed for the generation
+ of PDF files have been removed. </p>
+ <p>
+ Own Id: OTP-11016</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Asn1 2.0.1.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/asn1/src/asn1_db.erl b/lib/asn1/src/asn1_db.erl
index e96ca9ae25..869b36ddbd 100644
--- a/lib/asn1/src/asn1_db.erl
+++ b/lib/asn1/src/asn1_db.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/asn1/src/asn1ct_constructed_per.erl b/lib/asn1/src/asn1ct_constructed_per.erl
index efb55cf015..d279e9697f 100644
--- a/lib/asn1/src/asn1ct_constructed_per.erl
+++ b/lib/asn1/src/asn1ct_constructed_per.erl
@@ -354,8 +354,7 @@ gen_dec_constructed_imm_2(Typename, CompList,
%% we don't return named lists any more Cnames = mkcnamelist(CompList),
demit({"Result = "}), %dbg
%% return value as record
- RecordName = lists:concat([get_record_name_prefix(),
- asn1ct_gen:list2rname(Typename)]),
+ RecordName = record_name(Typename),
case Typename of
['EXTERNAL'] ->
emit({" OldFormat={'",RecordName,
@@ -377,6 +376,29 @@ gen_dec_constructed_imm_2(Typename, CompList,
end,
emit({{curr,bytes},"}"}).
+%% record_name([TypeName]) -> RecordNameString
+%% Construct a record name for the constructed type, ignoring any
+%% fake sequences that are used to represent an extension addition
+%% group. Such fake sequences never appear as a top type, and their
+%% name always start with "ExtAddGroup".
+
+record_name(Typename0) ->
+ [TopType|Typename1] = lists:reverse(Typename0),
+ Typename = filter_ext_add_groups(Typename1, [TopType]),
+ lists:concat([get_record_name_prefix(),
+ asn1ct_gen:list2rname(Typename)]).
+
+filter_ext_add_groups([H|T], Acc) when is_atom(H) ->
+ case atom_to_list(H) of
+ "ExtAddGroup"++_ ->
+ filter_ext_add_groups(T, Acc);
+ _ ->
+ filter_ext_add_groups(T, [H|Acc])
+ end;
+filter_ext_add_groups([H|T], Acc) ->
+ filter_ext_add_groups(T, [H|Acc]);
+filter_ext_add_groups([], Acc) -> Acc.
+
textual_order([#'ComponentType'{textual_order=undefined}|_],TermList) ->
TermList;
textual_order(CompList,TermList) when is_list(CompList) ->
diff --git a/lib/asn1/src/asn1ct_func.erl b/lib/asn1/src/asn1ct_func.erl
index 262bef6862..ab0dbcce8f 100644
--- a/lib/asn1/src/asn1ct_func.erl
+++ b/lib/asn1/src/asn1ct_func.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/asn1/src/asn1ct_gen_per.erl b/lib/asn1/src/asn1ct_gen_per.erl
index 30c9ab9365..69d9d51bf1 100644
--- a/lib/asn1/src/asn1ct_gen_per.erl
+++ b/lib/asn1/src/asn1ct_gen_per.erl
@@ -250,7 +250,8 @@ emit_enc_enumerated_case(Erules, C, EnumName, Count) ->
enc_ext_and_val(per, E, F, Args) ->
[E|apply(asn1ct_eval_per, F, Args)];
enc_ext_and_val(uper, E, F, Args) ->
- <<E:1,(apply(asn1ct_eval_uper, F, Args))/bitstring>>.
+ Bs = list_to_bitstring([apply(asn1ct_eval_uper, F, Args)]),
+ <<E:1,Bs/bitstring>>.
%% Object code generating for encoding and decoding
diff --git a/lib/asn1/src/asn1ct_imm.erl b/lib/asn1/src/asn1ct_imm.erl
index c6803a0f96..bf362db843 100644
--- a/lib/asn1/src/asn1ct_imm.erl
+++ b/lib/asn1/src/asn1ct_imm.erl
@@ -86,7 +86,7 @@ per_dec_enumerated(BaseNamedList, NamedListExt0, Aligned) ->
bit_case(Base, Ext).
per_dec_extension_map(Aligned) ->
- Len = {add,per_dec_normally_small_number(Aligned),1},
+ Len = per_dec_normally_small_length(Aligned),
{get_bits,Len,[1,bitstring]}.
per_dec_integer(Constraint0, Aligned) ->
@@ -240,6 +240,11 @@ per_dec_normally_small_number(Aligned) ->
Unlimited = per_decode_semi_constrained(0, Aligned),
bit_case(Small, Unlimited).
+per_dec_normally_small_length(Aligned) ->
+ Small = {add,{get_bits,6,[1]},1},
+ Unlimited = decode_unconstrained_length(false, Aligned),
+ bit_case(Small, Unlimited).
+
per_decode_semi_constrained(Lb, Aligned) ->
add_lb(Lb, {get_bits,decode_unconstrained_length(false, Aligned),[8]}).
diff --git a/lib/asn1/src/asn1ct_name.erl b/lib/asn1/src/asn1ct_name.erl
index c0c2ed302c..ba52e66ce3 100644
--- a/lib/asn1/src/asn1ct_name.erl
+++ b/lib/asn1/src/asn1ct_name.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/asn1/src/asn1ct_parser2.erl b/lib/asn1/src/asn1ct_parser2.erl
index 344fdf44dd..1abccc8626 100644
--- a/lib/asn1/src/asn1ct_parser2.erl
+++ b/lib/asn1/src/asn1ct_parser2.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/asn1/test/asn1_SUITE.erl b/lib/asn1/test/asn1_SUITE.erl
index 6be493320c..f00b23a8b2 100644
--- a/lib/asn1/test/asn1_SUITE.erl
+++ b/lib/asn1/test/asn1_SUITE.erl
@@ -454,10 +454,13 @@ testSeqDefault(Config, Rule, Opts) ->
testSeqExtension(Config) -> test(Config, fun testSeqExtension/3).
testSeqExtension(Config, Rule, Opts) ->
- asn1_test_lib:compile_all(["External", "SeqExtension"], Config,
+ asn1_test_lib:compile_all(["External",
+ "SeqExtension",
+ "SeqExtension2"],
+ Config,
[Rule|Opts]),
DataDir = ?config(data_dir, Config),
- testSeqExtension:main(DataDir, [Rule|Opts]).
+ testSeqExtension:main(Rule, DataDir, [Rule|Opts]).
testSeqExternal(Config) -> test(Config, fun testSeqExternal/3).
testSeqExternal(Config, Rule, Opts) ->
diff --git a/lib/asn1/test/asn1_SUITE_data/EnumExt.asn1 b/lib/asn1/test/asn1_SUITE_data/EnumExt.asn1
index 3a727e46bb..8dc5f3d7e1 100644
--- a/lib/asn1/test/asn1_SUITE_data/EnumExt.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/EnumExt.asn1
@@ -31,5 +31,25 @@ Seq ::= SEQUENCE {
i INTEGER
}
+EnumExtBig ::= ENUMERATED {
+ base,
+ ...,
+ e00,e01,e02,e03,e04,e05,e06,e07,e08,e09,e0a,e0b,e0c,e0d,e0e,e0f,
+ e10,e11,e12,e13,e14,e15,e16,e17,e18,e19,e1a,e1b,e1c,e1d,e1e,e1f,
+ e20,e21,e22,e23,e24,e25,e26,e27,e28,e29,e2a,e2b,e2c,e2d,e2e,e2f,
+ e30,e31,e32,e33,e34,e35,e36,e37,e38,e39,e3a,e3b,e3c,e3d,e3e,e3f,
+ e40,e41,e42,e43,e44,e45,e46,e47,e48,e49,e4a,e4b,e4c,e4d,e4e,e4f,
+ e50,e51,e52,e53,e54,e55,e56,e57,e58,e59,e5a,e5b,e5c,e5d,e5e,e5f,
+ e60,e61,e62,e63,e64,e65,e66,e67,e68,e69,e6a,e6b,e6c,e6d,e6e,e6f,
+ e70,e71,e72,e73,e74,e75,e76,e77,e78,e79,e7a,e7b,e7c,e7d,e7e,e7f,
+ e80
+}
+
+SeqBig ::= SEQUENCE {
+ b BOOLEAN,
+ e EnumExtBig,
+ i INTEGER
+}
+
END
diff --git a/lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn b/lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn
index b07dcd8baa..0e905d8839 100644
--- a/lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn
+++ b/lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn
@@ -118,4 +118,23 @@ AC-BarringConfig ::= SEQUENCE {
ac-BarringForSpecialAC BIT STRING (SIZE(5))
}
+InlinedSeq ::= SEQUENCE {
+ ...,
+ [[
+ s SEQUENCE {
+ a INTEGER,
+ b BOOLEAN
+ }
+ ]]
+}
+
+-- 'ExtAddGroup1' is used internally to represent fake sequences for
+-- extension addition groups. Make sure that a real sequence with that
+-- name at the top-level doesn't cause a problem.
+
+ExtAddGroup1 ::= SEQUENCE {
+ x INTEGER,
+ y INTEGER
+}
+
END
diff --git a/lib/asn1/test/asn1_SUITE_data/SeqExtension2.asn1 b/lib/asn1/test/asn1_SUITE_data/SeqExtension2.asn1
new file mode 100644
index 0000000000..44900d9d39
--- /dev/null
+++ b/lib/asn1/test/asn1_SUITE_data/SeqExtension2.asn1
@@ -0,0 +1,208 @@
+SeqExtension2 DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
+
+SeqExt66 ::= SEQUENCE {
+ ...,
+ i0 INTEGER (0..127) OPTIONAL,
+ i1 INTEGER (0..127) OPTIONAL,
+ i2 INTEGER (0..127) OPTIONAL,
+ i3 INTEGER (0..127) OPTIONAL,
+ i4 INTEGER (0..127) OPTIONAL,
+ i5 INTEGER (0..127) OPTIONAL,
+ i6 INTEGER (0..127) OPTIONAL,
+ i7 INTEGER (0..127) OPTIONAL,
+ i8 INTEGER (0..127) OPTIONAL,
+ i9 INTEGER (0..127) OPTIONAL,
+ i10 INTEGER (0..127) OPTIONAL,
+ i11 INTEGER (0..127) OPTIONAL,
+ i12 INTEGER (0..127) OPTIONAL,
+ i13 INTEGER (0..127) OPTIONAL,
+ i14 INTEGER (0..127) OPTIONAL,
+ i15 INTEGER (0..127) OPTIONAL,
+ i16 INTEGER (0..127) OPTIONAL,
+ i17 INTEGER (0..127) OPTIONAL,
+ i18 INTEGER (0..127) OPTIONAL,
+ i19 INTEGER (0..127) OPTIONAL,
+ i20 INTEGER (0..127) OPTIONAL,
+ i21 INTEGER (0..127) OPTIONAL,
+ i22 INTEGER (0..127) OPTIONAL,
+ i23 INTEGER (0..127) OPTIONAL,
+ i24 INTEGER (0..127) OPTIONAL,
+ i25 INTEGER (0..127) OPTIONAL,
+ i26 INTEGER (0..127) OPTIONAL,
+ i27 INTEGER (0..127) OPTIONAL,
+ i28 INTEGER (0..127) OPTIONAL,
+ i29 INTEGER (0..127) OPTIONAL,
+ i30 INTEGER (0..127) OPTIONAL,
+ i31 INTEGER (0..127) OPTIONAL,
+ i32 INTEGER (0..127) OPTIONAL,
+ i33 INTEGER (0..127) OPTIONAL,
+ i34 INTEGER (0..127) OPTIONAL,
+ i35 INTEGER (0..127) OPTIONAL,
+ i36 INTEGER (0..127) OPTIONAL,
+ i37 INTEGER (0..127) OPTIONAL,
+ i38 INTEGER (0..127) OPTIONAL,
+ i39 INTEGER (0..127) OPTIONAL,
+ i40 INTEGER (0..127) OPTIONAL,
+ i41 INTEGER (0..127) OPTIONAL,
+ i42 INTEGER (0..127) OPTIONAL,
+ i43 INTEGER (0..127) OPTIONAL,
+ i44 INTEGER (0..127) OPTIONAL,
+ i45 INTEGER (0..127) OPTIONAL,
+ i46 INTEGER (0..127) OPTIONAL,
+ i47 INTEGER (0..127) OPTIONAL,
+ i48 INTEGER (0..127) OPTIONAL,
+ i49 INTEGER (0..127) OPTIONAL,
+ i50 INTEGER (0..127) OPTIONAL,
+ i51 INTEGER (0..127) OPTIONAL,
+ i52 INTEGER (0..127) OPTIONAL,
+ i53 INTEGER (0..127) OPTIONAL,
+ i54 INTEGER (0..127) OPTIONAL,
+ i55 INTEGER (0..127) OPTIONAL,
+ i56 INTEGER (0..127) OPTIONAL,
+ i57 INTEGER (0..127) OPTIONAL,
+ i58 INTEGER (0..127) OPTIONAL,
+ i59 INTEGER (0..127) OPTIONAL,
+ i60 INTEGER (0..127) OPTIONAL,
+ i61 INTEGER (0..127) OPTIONAL,
+ i62 INTEGER (0..127) OPTIONAL,
+ i63 INTEGER (0..127) OPTIONAL,
+ i64 INTEGER (0..127) OPTIONAL,
+ i65 INTEGER (0..127) OPTIONAL
+}
+
+SeqExt130 ::= SEQUENCE {
+ ...,
+ i0 INTEGER (0..255) OPTIONAL,
+ i1 INTEGER (0..255) OPTIONAL,
+ i2 INTEGER (0..255) OPTIONAL,
+ i3 INTEGER (0..255) OPTIONAL,
+ i4 INTEGER (0..255) OPTIONAL,
+ i5 INTEGER (0..255) OPTIONAL,
+ i6 INTEGER (0..255) OPTIONAL,
+ i7 INTEGER (0..255) OPTIONAL,
+ i8 INTEGER (0..255) OPTIONAL,
+ i9 INTEGER (0..255) OPTIONAL,
+ i10 INTEGER (0..255) OPTIONAL,
+ i11 INTEGER (0..255) OPTIONAL,
+ i12 INTEGER (0..255) OPTIONAL,
+ i13 INTEGER (0..255) OPTIONAL,
+ i14 INTEGER (0..255) OPTIONAL,
+ i15 INTEGER (0..255) OPTIONAL,
+ i16 INTEGER (0..255) OPTIONAL,
+ i17 INTEGER (0..255) OPTIONAL,
+ i18 INTEGER (0..255) OPTIONAL,
+ i19 INTEGER (0..255) OPTIONAL,
+ i20 INTEGER (0..255) OPTIONAL,
+ i21 INTEGER (0..255) OPTIONAL,
+ i22 INTEGER (0..255) OPTIONAL,
+ i23 INTEGER (0..255) OPTIONAL,
+ i24 INTEGER (0..255) OPTIONAL,
+ i25 INTEGER (0..255) OPTIONAL,
+ i26 INTEGER (0..255) OPTIONAL,
+ i27 INTEGER (0..255) OPTIONAL,
+ i28 INTEGER (0..255) OPTIONAL,
+ i29 INTEGER (0..255) OPTIONAL,
+ i30 INTEGER (0..255) OPTIONAL,
+ i31 INTEGER (0..255) OPTIONAL,
+ i32 INTEGER (0..255) OPTIONAL,
+ i33 INTEGER (0..255) OPTIONAL,
+ i34 INTEGER (0..255) OPTIONAL,
+ i35 INTEGER (0..255) OPTIONAL,
+ i36 INTEGER (0..255) OPTIONAL,
+ i37 INTEGER (0..255) OPTIONAL,
+ i38 INTEGER (0..255) OPTIONAL,
+ i39 INTEGER (0..255) OPTIONAL,
+ i40 INTEGER (0..255) OPTIONAL,
+ i41 INTEGER (0..255) OPTIONAL,
+ i42 INTEGER (0..255) OPTIONAL,
+ i43 INTEGER (0..255) OPTIONAL,
+ i44 INTEGER (0..255) OPTIONAL,
+ i45 INTEGER (0..255) OPTIONAL,
+ i46 INTEGER (0..255) OPTIONAL,
+ i47 INTEGER (0..255) OPTIONAL,
+ i48 INTEGER (0..255) OPTIONAL,
+ i49 INTEGER (0..255) OPTIONAL,
+ i50 INTEGER (0..255) OPTIONAL,
+ i51 INTEGER (0..255) OPTIONAL,
+ i52 INTEGER (0..255) OPTIONAL,
+ i53 INTEGER (0..255) OPTIONAL,
+ i54 INTEGER (0..255) OPTIONAL,
+ i55 INTEGER (0..255) OPTIONAL,
+ i56 INTEGER (0..255) OPTIONAL,
+ i57 INTEGER (0..255) OPTIONAL,
+ i58 INTEGER (0..255) OPTIONAL,
+ i59 INTEGER (0..255) OPTIONAL,
+ i60 INTEGER (0..255) OPTIONAL,
+ i61 INTEGER (0..255) OPTIONAL,
+ i62 INTEGER (0..255) OPTIONAL,
+ i63 INTEGER (0..255) OPTIONAL,
+ i64 INTEGER (0..255) OPTIONAL,
+ i65 INTEGER (0..255) OPTIONAL,
+ i66 INTEGER (0..255) OPTIONAL,
+ i67 INTEGER (0..255) OPTIONAL,
+ i68 INTEGER (0..255) OPTIONAL,
+ i69 INTEGER (0..255) OPTIONAL,
+ i70 INTEGER (0..255) OPTIONAL,
+ i71 INTEGER (0..255) OPTIONAL,
+ i72 INTEGER (0..255) OPTIONAL,
+ i73 INTEGER (0..255) OPTIONAL,
+ i74 INTEGER (0..255) OPTIONAL,
+ i75 INTEGER (0..255) OPTIONAL,
+ i76 INTEGER (0..255) OPTIONAL,
+ i77 INTEGER (0..255) OPTIONAL,
+ i78 INTEGER (0..255) OPTIONAL,
+ i79 INTEGER (0..255) OPTIONAL,
+ i80 INTEGER (0..255) OPTIONAL,
+ i81 INTEGER (0..255) OPTIONAL,
+ i82 INTEGER (0..255) OPTIONAL,
+ i83 INTEGER (0..255) OPTIONAL,
+ i84 INTEGER (0..255) OPTIONAL,
+ i85 INTEGER (0..255) OPTIONAL,
+ i86 INTEGER (0..255) OPTIONAL,
+ i87 INTEGER (0..255) OPTIONAL,
+ i88 INTEGER (0..255) OPTIONAL,
+ i89 INTEGER (0..255) OPTIONAL,
+ i90 INTEGER (0..255) OPTIONAL,
+ i91 INTEGER (0..255) OPTIONAL,
+ i92 INTEGER (0..255) OPTIONAL,
+ i93 INTEGER (0..255) OPTIONAL,
+ i94 INTEGER (0..255) OPTIONAL,
+ i95 INTEGER (0..255) OPTIONAL,
+ i96 INTEGER (0..255) OPTIONAL,
+ i97 INTEGER (0..255) OPTIONAL,
+ i98 INTEGER (0..255) OPTIONAL,
+ i99 INTEGER (0..255) OPTIONAL,
+ i100 INTEGER (0..255) OPTIONAL,
+ i101 INTEGER (0..255) OPTIONAL,
+ i102 INTEGER (0..255) OPTIONAL,
+ i103 INTEGER (0..255) OPTIONAL,
+ i104 INTEGER (0..255) OPTIONAL,
+ i105 INTEGER (0..255) OPTIONAL,
+ i106 INTEGER (0..255) OPTIONAL,
+ i107 INTEGER (0..255) OPTIONAL,
+ i108 INTEGER (0..255) OPTIONAL,
+ i109 INTEGER (0..255) OPTIONAL,
+ i110 INTEGER (0..255) OPTIONAL,
+ i111 INTEGER (0..255) OPTIONAL,
+ i112 INTEGER (0..255) OPTIONAL,
+ i113 INTEGER (0..255) OPTIONAL,
+ i114 INTEGER (0..255) OPTIONAL,
+ i115 INTEGER (0..255) OPTIONAL,
+ i116 INTEGER (0..255) OPTIONAL,
+ i117 INTEGER (0..255) OPTIONAL,
+ i118 INTEGER (0..255) OPTIONAL,
+ i119 INTEGER (0..255) OPTIONAL,
+ i120 INTEGER (0..255) OPTIONAL,
+ i121 INTEGER (0..255) OPTIONAL,
+ i122 INTEGER (0..255) OPTIONAL,
+ i123 INTEGER (0..255) OPTIONAL,
+ i124 INTEGER (0..255) OPTIONAL,
+ i125 INTEGER (0..255) OPTIONAL,
+ i126 INTEGER (0..255) OPTIONAL,
+ i127 INTEGER (0..255) OPTIONAL,
+ i128 INTEGER (0..255) OPTIONAL,
+ i129 INTEGER (0..255) OPTIONAL
+}
+
+END
diff --git a/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl b/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl
index 00e4c707dd..8e21e6ca84 100644
--- a/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl
+++ b/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl
@@ -34,6 +34,9 @@ run(Erule) ->
run3(),
run3(Erule),
+ roundtrip('InlinedSeq', #'InlinedSeq'{s=#'InlinedSeq_s'{a=42,b=true}}),
+ roundtrip('ExtAddGroup1', #'ExtAddGroup1'{x=42,y=1023}),
+
ok.
%% From X.691 (07/2002) A.4.
diff --git a/lib/asn1/test/asn1_test_lib.erl b/lib/asn1/test/asn1_test_lib.erl
index b839dfcf2a..60b2b2b42e 100644
--- a/lib/asn1/test/asn1_test_lib.erl
+++ b/lib/asn1/test/asn1_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -22,6 +22,7 @@
-export([compile/3]).
-export([compile_all/3]).
-export([compile_erlang/3]).
+-export([hex_to_bin/1]).
-export([ticket_7407_compile/2,ticket_7407_code/1, ticket_7678/2,
ticket_7708/2, ticket_7763/1, ticket_7876/3]).
@@ -61,6 +62,13 @@ compile_erlang(Mod, Config, Options) ->
{ok, M} = compile:file(filename:join(DataDir, Mod),
[report,{i,CaseDir},{outdir,CaseDir}|Options]).
+hex_to_bin(S) ->
+ << <<(hex2num(C)):4>> || C <- S, C =/= $\s >>.
+
+%%%
+%%% Internal functions.
+%%%
+
should_load(File, Options) ->
case lists:member(abs, Options) of
true ->
@@ -79,6 +87,10 @@ strip_extension(File, Ext) when Ext == ".asn"; Ext == ".set"; Ext == ".asn1"->
strip_extension(File, _Ext) ->
File.
+hex2num(C) when $0 =< C, C =< $9 -> C - $0;
+hex2num(C) when $A =< C, C =< $F -> C - $A + 10;
+hex2num(C) when $a =< C, C =< $f -> C - $a + 10.
+
ticket_7407_compile(Config,Option) ->
?line DataDir = ?config(data_dir,Config),
diff --git a/lib/asn1/test/testChoExtension.erl b/lib/asn1/test/testChoExtension.erl
index 5c67ff62ce..c6a07646c2 100644
--- a/lib/asn1/test/testChoExtension.erl
+++ b/lib/asn1/test/testChoExtension.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/asn1/test/testCompactBitString.erl b/lib/asn1/test/testCompactBitString.erl
index 28ab2464e9..f74992a79e 100644
--- a/lib/asn1/test/testCompactBitString.erl
+++ b/lib/asn1/test/testCompactBitString.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/asn1/test/testConstraints.erl b/lib/asn1/test/testConstraints.erl
index e825302629..03a09492af 100644
--- a/lib/asn1/test/testConstraints.erl
+++ b/lib/asn1/test/testConstraints.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -126,19 +126,29 @@ int_constraints(Rules) ->
%%==========================================================
roundtrip('SemiConstrained', 100),
+ v_roundtrip(Rules, 'SemiConstrained', 100+128),
roundtrip('SemiConstrained', 397249742397243),
+ roundtrip('SemiConstrained', 100 + 1 bsl 128*8),
+ roundtrip('SemiConstrained', 100 + 1 bsl 256*8),
+
roundtrip('NegSemiConstrained', -128),
+ v_roundtrip(Rules, 'NegSemiConstrained', 0),
roundtrip('NegSemiConstrained', -1),
roundtrip('NegSemiConstrained', 500),
roundtrip('SemiConstrainedExt', -65536),
roundtrip('SemiConstrainedExt', 0),
roundtrip('SemiConstrainedExt', 42),
+ v_roundtrip(Rules, 'SemiConstrainedExt', 42+128),
roundtrip('SemiConstrainedExt', 100),
roundtrip('SemiConstrainedExt', 47777789),
+ roundtrip('SemiConstrainedExt', 42 + 1 bsl 128*8),
+ roundtrip('SemiConstrainedExt', 42 + 1 bsl 256*8),
+
roundtrip('NegSemiConstrainedExt', -1023),
roundtrip('NegSemiConstrainedExt', -128),
roundtrip('NegSemiConstrainedExt', -1),
+ v_roundtrip(Rules, 'NegSemiConstrainedExt', 0),
roundtrip('NegSemiConstrainedExt', 500),
%%==========================================================
@@ -174,6 +184,21 @@ int_constraints(Rules) ->
ok.
+%% PER: Ensure that if the lower bound is Lb, Lb+16#80 is encoded
+%% in two bytes as 16#0180. (Not in three bytes as 16#010080.)
+v(ber, 'SemiConstrained', 100+128) -> "020200E4";
+v(per, 'SemiConstrained', 100+128) -> "0180";
+v(uper, 'SemiConstrained', 100+128) -> "0180";
+v(ber, 'NegSemiConstrained', 0) -> "020100";
+v(per, 'NegSemiConstrained', 0) -> "0180";
+v(uper, 'NegSemiConstrained', 0) -> "0180";
+v(ber, 'SemiConstrainedExt', 42+128) -> "020200AA";
+v(per, 'SemiConstrainedExt', 42+128) -> "000180";
+v(uper, 'SemiConstrainedExt', 42+128) -> "00C000";
+v(ber, 'NegSemiConstrainedExt', 0) -> "020100";
+v(per, 'NegSemiConstrainedExt', 0) -> "000180";
+v(uper, 'NegSemiConstrainedExt', 0) -> "00C000".
+
shorter_ext(per, "a") -> <<16#80,16#01,16#61>>;
shorter_ext(uper, "a") -> <<16#80,16#E1>>;
shorter_ext(ber, _) -> none.
@@ -183,13 +208,17 @@ refed_NNL_name(_Erule) ->
?line {error,_Reason} =
asn1_wrapper:encode('Constraints','AnotherThing',fred3).
+v_roundtrip(Erule, Type, Value) ->
+ Encoded = asn1_test_lib:hex_to_bin(v(Erule, Type, Value)),
+ Encoded = roundtrip('Constraints', Type, Value).
+
roundtrip(Type, Value) ->
roundtrip('Constraints', Type, Value).
roundtrip(Module, Type, Value) ->
{ok,Encoded} = Module:encode(Type, Value),
{ok,Value} = Module:decode(Type, Encoded),
- ok.
+ Encoded.
roundtrip_enc(Type, Value, Enc) ->
Module = 'Constraints',
diff --git a/lib/asn1/test/testDeepTConstr.erl b/lib/asn1/test/testDeepTConstr.erl
index e826cafa0c..f17dedc043 100644
--- a/lib/asn1/test/testDeepTConstr.erl
+++ b/lib/asn1/test/testDeepTConstr.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/asn1/test/testEnumExt.erl b/lib/asn1/test/testEnumExt.erl
index 8840ed6d2f..cbc13ee6da 100644
--- a/lib/asn1/test/testEnumExt.erl
+++ b/lib/asn1/test/testEnumExt.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -38,7 +38,7 @@ main(Rule) when Rule =:= per; Rule =:= uper ->
%% ENUMERATED no extensionmark
B64 = <<64>>,
B64 = roundtrip('Noext', red),
- common();
+ common(Rule);
main(ber) ->
io:format("main(ber)~n",[]),
%% ENUMERATED with extensionmark (value is in root set)
@@ -56,18 +56,38 @@ main(ber) ->
roundtrip('Globalstate', preop),
roundtrip('Globalstate', com),
- common().
+ common(ber).
-common() ->
+common(Erule) ->
roundtrip('Seq', {'Seq',blue,42}),
roundtrip('Seq', {'Seq',red,42}),
roundtrip('Seq', {'Seq',green,42}),
roundtrip('Seq', {'Seq',orange,47}),
roundtrip('Seq', {'Seq',black,4711}),
roundtrip('Seq', {'Seq',magenta,4712}),
+
+ [begin
+ S = io_lib:format("e~2.016.0b", [I]),
+ E = list_to_atom(lists:flatten(S)),
+ roundtrip('SeqBig', {'SeqBig',true,E,9357})
+ end || I <- lists:seq(0, 128)],
+
+ v_roundtrip(Erule, 'SeqBig', {'SeqBig',true,e40,9357}),
+ v_roundtrip(Erule, 'SeqBig', {'SeqBig',true,e80,9357}),
ok.
roundtrip(Type, Value) ->
{ok,Encoded} = 'EnumExt':encode(Type, Value),
{ok,Value} = 'EnumExt':decode(Type, Encoded),
Encoded.
+
+v_roundtrip(Erule, Type, Value) ->
+ Encoded = roundtrip(Type, Value),
+ Encoded = asn1_test_lib:hex_to_bin(v(Erule, Value)).
+
+v(ber, {'SeqBig',true,e40,9357}) -> "300A8001 FF810141 8202248D";
+v(ber, {'SeqBig',true,e80,9357}) -> "300B8001 FF810200 81820224 8D";
+v(per, {'SeqBig',true,e40,9357}) -> "E0014002 248D";
+v(per, {'SeqBig',true,e80,9357}) -> "E0018002 248D";
+v(uper, {'SeqBig',true,e40,9357}) -> "E0280044 91A0";
+v(uper, {'SeqBig',true,e80,9357}) -> "E0300044 91A0".
diff --git a/lib/asn1/test/testInfObj.erl b/lib/asn1/test/testInfObj.erl
index 75f4dae310..c7b19a0cbb 100644
--- a/lib/asn1/test/testInfObj.erl
+++ b/lib/asn1/test/testInfObj.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/asn1/test/testParameterizedInfObj.erl b/lib/asn1/test/testParameterizedInfObj.erl
index 212df79fd4..1dfa52f401 100644
--- a/lib/asn1/test/testParameterizedInfObj.erl
+++ b/lib/asn1/test/testParameterizedInfObj.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/asn1/test/testPrim.erl b/lib/asn1/test/testPrim.erl
index 990e7adcd9..a6e68a9fe0 100644
--- a/lib/asn1/test/testPrim.erl
+++ b/lib/asn1/test/testPrim.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/asn1/test/testSeqExtension.erl b/lib/asn1/test/testSeqExtension.erl
index 1128d9a7c3..b996634996 100644
--- a/lib/asn1/test/testSeqExtension.erl
+++ b/lib/asn1/test/testSeqExtension.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -20,7 +20,7 @@
-module(testSeqExtension).
-include("External.hrl").
--export([main/2]).
+-export([main/3]).
-include_lib("test_server/include/test_server.hrl").
@@ -32,7 +32,7 @@
-record('SeqExt6',{i1,i2,i3,i4,i5,i6,i7}).
-record('SuperSeq',{s1,s2,s3,s4,s5,s6,i}).
-main(DataDir, Opts) ->
+main(Erule, DataDir, Opts) ->
roundtrip('SeqExt1', #'SeqExt1'{}),
roundtrip('SeqExt2', #'SeqExt2'{bool=true,int=99}),
@@ -92,9 +92,38 @@ main(DataDir, Opts) ->
s5={'SeqExt5'},
s6={'SeqExt6',531,601,999,777,11953},
i=BigInt} = DecodedSuperSeq,
+
+
+ %% Test more than 64 extensions.
+ roundtrip2('SeqExt66',
+ list_to_tuple(['SeqExt66'|lists:seq(0, 65)])),
+ v_roundtrip2(Erule, 'SeqExt66',
+ list_to_tuple(['SeqExt66'|
+ lists:duplicate(65, asn1_NOVALUE)++[125]])),
+ roundtrip2('SeqExt130',
+ list_to_tuple(['SeqExt130'|lists:seq(0, 129)])),
+ v_roundtrip2(Erule, 'SeqExt130',
+ list_to_tuple(['SeqExt130'|
+ lists:duplicate(129, asn1_NOVALUE)++[199]])),
ok.
roundtrip(Type, Value) ->
{ok,Encoded} = 'SeqExtension':encode(Type, Value),
{ok,Value} = 'SeqExtension':decode(Type, Encoded),
ok.
+
+v_roundtrip2(Erule, Type, Value) ->
+ Encoded = asn1_test_lib:hex_to_bin(v(Erule, Type)),
+ Encoded = roundtrip2(Type, Value).
+
+roundtrip2(Type, Value) ->
+ {ok,Encoded} = 'SeqExtension2':encode(Type, Value),
+ {ok,Value} = 'SeqExtension2':decode(Type, Encoded),
+ Encoded.
+
+v(ber, 'SeqExt66') -> "30049F41 017D";
+v(per, 'SeqExt66') -> "C0420000 00000000 00004001 FA";
+v(uper, 'SeqExt66') -> "D0800000 00000000 00101FA0";
+v(ber, 'SeqExt130') -> "30069F81 010200C7";
+v(per, 'SeqExt130') -> "C0808200 00000000 00000000 00000000 00000040 01C7";
+v(uper, 'SeqExt130') -> "E0208000 00000000 00000000 00000000 0000101C 70".
diff --git a/lib/asn1/test/testSeqOf.erl b/lib/asn1/test/testSeqOf.erl
index c1af0d7a32..db537b1478 100644
--- a/lib/asn1/test/testSeqOf.erl
+++ b/lib/asn1/test/testSeqOf.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/asn1/vsn.mk b/lib/asn1/vsn.mk
index 9245f83280..b75de179dc 100644
--- a/lib/asn1/vsn.mk
+++ b/lib/asn1/vsn.mk
@@ -1,2 +1,2 @@
#next version number to use is 2.0
-ASN1_VSN = 2.0.1.2
+ASN1_VSN = 2.0.2
diff --git a/lib/common_test/doc/src/notes.xml b/lib/common_test/doc/src/notes.xml
index da9e201f84..cc3c5231a5 100644
--- a/lib/common_test/doc/src/notes.xml
+++ b/lib/common_test/doc/src/notes.xml
@@ -32,6 +32,158 @@
<file>notes.xml</file>
</header>
+<section><title>Common_Test 1.7.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ A design flaw in the generic connection handling in
+ Common Test made it impossible to implement a connection
+ handler that could map multiple connection names (i.e.
+ configuration variable aliases) to single connection
+ pids. This problem has been solved.</p>
+ <p>
+ Own Id: OTP-10126 Aux Id: kunagi-178 [89] </p>
+ </item>
+ <item>
+ <p>
+ If a telnet connection is hanging, then a call to
+ ct_telnet:close/1 will time out after 5 seconds and the
+ connection process is brutally killed. In some cases the
+ connection would not be unregistered and attempts at
+ opening a new connection with the same name would make
+ common_test try to reuse the same connection since it
+ believed that it was still alive. This has been corrected
+ - a killed connection is now always unregistered.</p>
+ <p>
+ Own Id: OTP-10648 Aux Id: seq12212 </p>
+ </item>
+ <item>
+ <p>
+ Test performance has been improved by means of a cache
+ for the top level HTML index logs (all_runs.html and
+ index.html, in the logdir directory). This solves
+ problems with slow start up times and test execution
+ times increasing with the number of ct_run directories
+ stored in logdir. The cached index entries are stored in
+ RAM during test execution and are saved to file in logdir
+ (for faster start up times) whenever a test run finishes.</p>
+ <p>
+ Own Id: OTP-10855</p>
+ </item>
+ <item>
+ <p>
+ Testing of the test specification functionality has been
+ improved and a couple of minor bugs have been discovered
+ and corrected.</p>
+ <p>
+ Own Id: OTP-10857</p>
+ </item>
+ <item>
+ <p>
+ Links to the top level index files in some HTML footers
+ had disappeared. This error has been corrected. Also, a
+ problem with the suite overview log file not being closed
+ properly has been solved.</p>
+ <p>
+ Own Id: OTP-11046</p>
+ </item>
+ <item>
+ <p>
+ Common Test would, in case of timetrap error, print a
+ warning in the log if end_per_testcase wasn't implemented
+ in the suite, even though it's an optional function. This
+ printout has been removed.</p>
+ <p>
+ Own Id: OTP-11052</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ If it could not be decided which test case a certain log
+ printout belonged to, the common test framework log was
+ earlier used. Such printouts are now instead sent to
+ unexpected_io.log.html in test_server so that there is
+ only one place to look for "missing" printouts.</p>
+ <p>
+ Own Id: OTP-10494 Aux Id: kunagi-319 [230] </p>
+ </item>
+ <item>
+ <p>
+ Make cover smarter about finding source from beam.</p>
+ <p>
+ In particular, search using the source path in
+ module_info if the current heuristic fails.</p>
+ <p>
+ Own Id: OTP-10902</p>
+ </item>
+ <item>
+ <p>
+ Add a variant of ct_slave:start/2 that starts a node with
+ specified options on the local host.</p>
+ <p>
+ Own Id: OTP-10920</p>
+ </item>
+ <item>
+ <p>
+ Integrate elliptic curve contribution from Andreas
+ Schultz </p>
+ <p>
+ In order to be able to support elliptic curve cipher
+ suites in SSL/TLS, additions to handle elliptic curve
+ infrastructure has been added to public_key and crypto.</p>
+ <p>
+ This also has resulted in a rewrite of the crypto API to
+ gain consistency and remove unnecessary overhead. All OTP
+ applications using crypto has been updated to use the new
+ API.</p>
+ <p>
+ Impact: Elliptic curve cryptography (ECC) offers
+ equivalent security with smaller key sizes than other
+ public key algorithms. Smaller key sizes result in
+ savings for power, memory, bandwidth, and computational
+ cost that make ECC especially attractive for constrained
+ environments.</p>
+ <p>
+ Own Id: OTP-11009</p>
+ </item>
+ <item>
+ <p> Postscript files no longer needed for the generation
+ of PDF files have been removed. </p>
+ <p>
+ Own Id: OTP-11016</p>
+ </item>
+ <item>
+ <p>
+ A link is added from the red error printout in a test
+ case log (for a failed test case) to the full error
+ description at the end of the log. The reason for this is
+ that the error description in the red field is sometimes
+ truncated at 50 characters in order to keep the log as
+ short and easy to read as possible.</p>
+ <p>
+ Own Id: OTP-11044 Aux Id: seq12304 </p>
+ </item>
+ <item>
+ <p>
+ A new option 'no_prompt_check' is added to
+ ct_telnet:expect/3. If this option is used, ct_telnet
+ will not wait for a prompt or a newline before attempting
+ to match the given pattern.</p>
+ <p>
+ Own Id: OTP-11095</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Common_Test 1.7.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/common_test/src/ct_ftp.erl b/lib/common_test/src/ct_ftp.erl
index b91a521bd4..71fd8754ff 100644
--- a/lib/common_test/src/ct_ftp.erl
+++ b/lib/common_test/src/ct_ftp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl
index 41d53c7b43..266ca73417 100644
--- a/lib/common_test/src/ct_run.erl
+++ b/lib/common_test/src/ct_run.erl
@@ -402,7 +402,8 @@ script_start2(Opts = #opts{vts = undefined,
Relaxed = get_start_opt(allow_user_terms, true, false, Args),
case catch ct_testspec:collect_tests_from_file(Specs1, Relaxed) of
{E,Reason} when E == error ; E == 'EXIT' ->
- {error,Reason};
+ StackTrace = erlang:get_stacktrace(),
+ {error,{invalid_testspec,{Reason,StackTrace}}};
TestSpecData ->
execute_all_specs(TestSpecData, Opts, Args, [])
end;
@@ -1101,7 +1102,8 @@ run_spec_file(Relaxed,
AbsSpecs1 = get_start_opt(join_specs, [AbsSpecs], AbsSpecs, StartOpts),
case catch ct_testspec:collect_tests_from_file(AbsSpecs1, Relaxed) of
{Error,CTReason} when Error == error ; Error == 'EXIT' ->
- exit({error,CTReason});
+ StackTrace = erlang:get_stacktrace(),
+ exit({error,{invalid_testspec,{CTReason,StackTrace}}});
TestSpecData ->
run_all_specs(TestSpecData, Opts, StartOpts, [])
end.
diff --git a/lib/common_test/src/ct_ssh.erl b/lib/common_test/src/ct_ssh.erl
index 1adc79d358..974791bd70 100644
--- a/lib/common_test/src/ct_ssh.erl
+++ b/lib/common_test/src/ct_ssh.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/common_test/src/ct_testspec.erl b/lib/common_test/src/ct_testspec.erl
index 71b03c0ea6..c07ea323e6 100644
--- a/lib/common_test/src/ct_testspec.erl
+++ b/lib/common_test/src/ct_testspec.erl
@@ -253,7 +253,7 @@ collect_tests_from_file(Specs,Nodes,Relaxed) when is_list(Nodes) ->
Specs2 = [filename:absname(S) || S <- Specs1],
TS0 = #testspec{nodes=NodeRefs},
- try create_specs(Specs2,TS0,Relaxed,Join) of
+ try create_testspecs(Specs2,TS0,Relaxed,Join) of
{{[],_},SeparateTestSpecs} ->
filter_and_convert(SeparateTestSpecs);
{{_,#testspec{tests=[]}},SeparateTestSpecs} ->
@@ -262,8 +262,10 @@ collect_tests_from_file(Specs,Nodes,Relaxed) when is_list(Nodes) ->
[filter_and_convert(Joined) |
filter_and_convert(SeparateTestSpecs)]
catch
+ _:Error={error,_} ->
+ Error;
_:Error ->
- Error
+ {error,Error}
end.
filter_and_convert(Joined) when is_tuple(Joined) ->
@@ -293,9 +295,12 @@ delete_dups1([E|Es],Keep) ->
delete_dups1([],Keep) ->
Keep.
-create_specs(Specs,TestSpec,Relaxed,Join) ->
- SpecsTree = create_spec_tree(Specs,TestSpec,Join,[]),
- create_specs(SpecsTree,TestSpec,Relaxed).
+create_testspecs(Specs,TestSpec,Relaxed,Join) ->
+ %% SpecsTree = {SpecAbsName, TermsInSpec,
+ %% IncludedJoinTree, IncludedSeparateTree,
+ %% JoinSpecWithRest, RestSpecsTree}
+ SpecsTree = create_spec_tree(Specs,TestSpec,Join,[]),
+ create_specs(SpecsTree,TestSpec,TestSpec,Relaxed).
create_spec_tree([Spec|Specs],TS,JoinWithNext,Known) ->
SpecDir = filename:dirname(filename:absname(Spec)),
@@ -325,27 +330,31 @@ create_spec_tree([],_TS,_JoinWithNext,_Known) ->
[].
create_specs({Spec,Terms,InclJoin,InclSep,JoinWithNext,NextSpec},
- TestSpec,Relaxed) ->
+ TestSpec,TestSpec0,Relaxed) ->
SpecDir = filename:dirname(filename:absname(Spec)),
TestSpec1 = create_spec(Terms,TestSpec#testspec{spec_dir=SpecDir},
JoinWithNext,Relaxed),
- {{JoinSpecs1,JoinTS1},Separate1} = create_specs(InclJoin,TestSpec1,Relaxed),
+ {{JoinSpecs1,JoinTS1},Separate1} = create_specs(InclJoin,TestSpec1,
+ TestSpec0,Relaxed),
{{JoinSpecs2,JoinTS2},Separate2} =
case JoinWithNext of
true ->
- create_specs(NextSpec,JoinTS1,Relaxed);
+ create_specs(NextSpec,JoinTS1,
+ TestSpec0,Relaxed);
false ->
{{[],JoinTS1},[]}
end,
- {SepJoinSpecs,Separate3} = create_specs(InclSep,TestSpec,Relaxed),
+ {SepJoinSpecs,Separate3} = create_specs(InclSep,TestSpec0,
+ TestSpec0,Relaxed),
{SepJoinSpecs1,Separate4} =
case JoinWithNext of
true ->
{{[],TestSpec},[]};
false ->
- create_specs(NextSpec,TestSpec,Relaxed)
+ create_specs(NextSpec,TestSpec0,
+ TestSpec0,Relaxed)
end,
SpecInfo = {Spec,TestSpec1#testspec.merge_tests},
@@ -354,7 +363,6 @@ create_specs({Spec,Terms,InclJoin,InclSep,JoinWithNext,NextSpec},
[SepJoinSpecs]++Separate2++
[SepJoinSpecs1]++Separate4,
Ss /= []],
-
case {JoinWithNext,JoinSpecs1} of
{true,_} ->
{{[SpecInfo|(JoinSpecs1++JoinSpecs2)],JoinTS2},
@@ -366,7 +374,7 @@ create_specs({Spec,Terms,InclJoin,InclSep,JoinWithNext,NextSpec},
{{[SpecInfo|(JoinSpecs1++JoinSpecs2)],JoinTS2},
AllSeparate}
end;
-create_specs([],TestSpec,_Relaxed) ->
+create_specs([],TestSpec,_,_Relaxed) ->
{{[],TestSpec},[]}.
create_spec(Terms,TestSpec,JoinedByPrev,Relaxed) ->
@@ -842,7 +850,8 @@ add_tests([{cases,Node,Dir,Suite,Cs}|Ts],Spec) ->
Tests = Spec#testspec.tests,
Tests1 = insert_cases(ref2node(Node,Spec#testspec.nodes),
ref2dir(Dir,Spec),
- Suite,Cs,Tests, Spec#testspec.merge_tests),
+ Suite,Cs,Tests,
+ Spec#testspec.merge_tests),
add_tests(Ts,Spec#testspec{tests=Tests1});
%% --- skip_suites ---
@@ -1246,17 +1255,22 @@ insert_cases(Node,Dir,Suite,Cases,Tests,false) when is_list(Cases) ->
append({{Node,Dir},[{Suite,Cases}]},Tests);
insert_cases(Node,Dir,Suite,Cases,Tests,true) when is_list(Cases) ->
{Tests1,Done} =
- lists:foldr(fun(All={{N,D},[{all,_}]},{Replaced,_}) when N == Node,
+ lists:foldr(fun(All={{N,D},[{all,_}]},{Merged,_}) when N == Node,
D == Dir ->
- {[All|Replaced],true};
- ({{N,D},Suites0},{Replaced,_}) when N == Node,
+ {[All|Merged],true};
+ ({{N,D},Suites0},{Merged,_}) when N == Node,
D == Dir ->
Suites1 = insert_cases1(Suite,Cases,Suites0),
- {[{{N,D},Suites1}|Replaced],true};
- (T,{Replaced,Match}) ->
- {[T|Replaced],Match}
+ {[{{N,D},Suites1}|Merged],true};
+ (T,{Merged,Match}) ->
+ {[T|Merged],Match}
end, {[],false}, Tests),
- if not Done ->
+ if Tests == [] ->
+ %% initial case with length(Cases) > 1, we need to do this
+ %% to merge possible duplicate cases in Cases
+ [{{Node,Dir},insert_cases1(Suite,Cases,[{Suite,[]}])}];
+ not Done ->
+ %% no merging done, simply add these cases to Tests
Tests ++ [{{Node,Dir},[{Suite,Cases}]}];
true ->
Tests1
@@ -1301,14 +1315,14 @@ skip_groups(Node,Dir,Suite,Groups,Cases,Cmt,Tests,false) when
skip_groups(Node,Dir,Suite,Groups,Cases,Cmt,Tests,true) when
((Cases == all) or is_list(Cases)) and is_list(Groups) ->
{Tests1,Done} =
- lists:foldr(fun({{N,D},Suites0},{Replaced,_}) when N == Node,
+ lists:foldr(fun({{N,D},Suites0},{Merged,_}) when N == Node,
D == Dir ->
Suites1 = skip_groups1(Suite,
[{Gr,Cases} || Gr <- Groups],
Cmt,Suites0),
- {[{{N,D},Suites1}|Replaced],true};
- (T,{Replaced,Match}) ->
- {[T|Replaced],Match}
+ {[{{N,D},Suites1}|Merged],true};
+ (T,{Merged,Match}) ->
+ {[T|Merged],Match}
end, {[],false}, Tests),
if not Done ->
Tests ++ [{{Node,Dir},skip_groups1(Suite,
@@ -1339,12 +1353,12 @@ skip_cases(Node,Dir,Suite,Cases,Cmt,Tests,false) when is_list(Cases) ->
append({{Node,Dir},Suites1},Tests);
skip_cases(Node,Dir,Suite,Cases,Cmt,Tests,true) when is_list(Cases) ->
{Tests1,Done} =
- lists:foldr(fun({{N,D},Suites0},{Replaced,_}) when N == Node,
+ lists:foldr(fun({{N,D},Suites0},{Merged,_}) when N == Node,
D == Dir ->
Suites1 = skip_cases1(Suite,Cases,Cmt,Suites0),
- {[{{N,D},Suites1}|Replaced],true};
- (T,{Replaced,Match}) ->
- {[T|Replaced],Match}
+ {[{{N,D},Suites1}|Merged],true};
+ (T,{Merged,Match}) ->
+ {[T|Merged],Match}
end, {[],false}, Tests),
if not Done ->
Tests ++ [{{Node,Dir},skip_cases1(Suite,Cases,Cmt,[])}];
diff --git a/lib/common_test/test/ct_gen_conn_SUITE.erl b/lib/common_test/test/ct_gen_conn_SUITE.erl
index 2a2183854e..49d6edca86 100644
--- a/lib/common_test/test/ct_gen_conn_SUITE.erl
+++ b/lib/common_test/test/ct_gen_conn_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/common_test/test/ct_gen_conn_SUITE_data/conn_SUITE.erl b/lib/common_test/test/ct_gen_conn_SUITE_data/conn_SUITE.erl
index 6877e0c2d2..1344878675 100644
--- a/lib/common_test/test/ct_gen_conn_SUITE_data/conn_SUITE.erl
+++ b/lib/common_test/test/ct_gen_conn_SUITE_data/conn_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/common_test/test/ct_testspec_3_SUITE.erl b/lib/common_test/test/ct_testspec_3_SUITE.erl
index 6b4b729552..5fa187e5b4 100644
--- a/lib/common_test/test/ct_testspec_3_SUITE.erl
+++ b/lib/common_test/test/ct_testspec_3_SUITE.erl
@@ -284,6 +284,24 @@ events_to_check(_, 0) ->
events_to_check(Test, N) ->
test_events(Test) ++ events_to_check(Test, N-1).
+
+%%%!
+%%%! IMPORTANT NOTE ABOUT THE TEST ORDER:
+%%%!
+%%%! When merging testspec terms, CT will group the tests by TestDir and
+%%%! Suite, before term order (in testspec). That means that if tests
+%%%! are ordered like e.g:
+%%%! {Dir1,Suite11}, {Dir2,Suite21}, {Dir1,Suite12},
+%%%! the execution order after merge (even if no merge takes place),
+%%%! will be:
+%%%! {Dir1,[Suite11,Suite12]}, {Dir2,Suite21}
+%%%!
+%%%! Also, tests in a tree of included testspecs are always collected
+%%%! and merged in depth-first manner, meaning even if a particular test is
+%%%! on a higher level in the tree, it may be executed later than a test on a
+%%%! lower level.
+%%%!
+
test_events(start_separate) ->
[{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
@@ -300,6 +318,7 @@ test_events(start_separate) ->
{?eh,tc_done,{t21_SUITE,end_per_suite,ok}},
{?eh,test_done,{'DEF','STOP_TIME'}},
{?eh,stop_logging,[]},
+
{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
{?eh,start_info,{3,2,15}},
@@ -415,6 +434,7 @@ test_events(incl_separate1) ->
{?eh,test_done,{'DEF','STOP_TIME'}},
{?eh,stop_logging,[]},
+
{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
{?eh,start_info,{3,2,15}},
@@ -448,6 +468,7 @@ test_events(incl_separate2) ->
{?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
{?eh,test_done,{'DEF','STOP_TIME'}},
{?eh,stop_logging,[]},
+
{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
{?eh,start_info,{3,2,15}},
@@ -468,6 +489,7 @@ test_events(incl_separate2) ->
{?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
{?eh,test_done,{'DEF','STOP_TIME'}},
{?eh,stop_logging,[]},
+
{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
{?eh,start_info,{2,2,10}},
@@ -483,6 +505,7 @@ test_events(incl_separate2) ->
{?eh,tc_done,{t21_SUITE,end_per_suite,ok}},
{?eh,test_done,{'DEF','STOP_TIME'}},
{?eh,stop_logging,[]},
+
{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
{?eh,start_info,{2,2,10}},
@@ -498,6 +521,7 @@ test_events(incl_separate2) ->
{?eh,tc_done,{t21_SUITE,end_per_suite,ok}},
{?eh,test_done,{'DEF','STOP_TIME'}},
{?eh,stop_logging,[]},
+
{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
{?eh,start_info,{3,2,15}},
@@ -545,6 +569,7 @@ test_events(incl_join1) ->
{?eh,tc_done,{t21_SUITE,end_per_suite,ok}},
{?eh,test_done,{'DEF','STOP_TIME'}},
{?eh,stop_logging,[]},
+
{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
{?eh,start_info,{4,4,20}},
@@ -614,6 +639,7 @@ test_events(incl_both1) ->
{?eh,tc_done,{t21_SUITE,end_per_suite,ok}},
{?eh,test_done,{'DEF','STOP_TIME'}},
{?eh,stop_logging,[]},
+
{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
{?eh,start_info,{3,2,15}},
@@ -634,6 +660,7 @@ test_events(incl_both1) ->
{?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
{?eh,test_done,{'DEF','STOP_TIME'}},
{?eh,stop_logging,[]},
+
{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
{?eh,start_info,{2,2,10}},
@@ -649,6 +676,7 @@ test_events(incl_both1) ->
{?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
{?eh,test_done,{'DEF','STOP_TIME'}},
{?eh,stop_logging,[]},
+
{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
{?eh,start_info,{2,2,10}},
@@ -692,6 +720,7 @@ test_events(incl_both2) ->
{?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
{?eh,test_done,{'DEF','STOP_TIME'}},
{?eh,stop_logging,[]},
+
{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
{?eh,start_info,{3,2,15}},
@@ -712,6 +741,7 @@ test_events(incl_both2) ->
{?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
{?eh,test_done,{'DEF','STOP_TIME'}},
{?eh,stop_logging,[]},
+
{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
{?eh,start_info,{2,2,10}},
@@ -728,18 +758,890 @@ test_events(incl_both2) ->
{?eh,test_done,{'DEF','STOP_TIME'}},
{?eh,stop_logging,[]}];
-test_events(incl_both_and_join1) -> [];
-test_events(incl_both_and_join2) -> [];
-test_events(rec_incl_separate1) -> [];
-test_events(rec_incl_separate2) -> [];
-test_events(rec_incl_join1) -> [];
-test_events(rec_incl_join2) -> [];
-test_events(rec_incl_separate_join1) -> [];
-test_events(rec_incl_separate_join2) -> [];
-test_events(rec_incl_join_separate1) -> [];
-test_events(rec_incl_join_separate2) -> [];
-
-test_events(_) ->
- [].
+test_events(incl_both_and_join1) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{5,3,25}},
+ {?eh,tc_start,{t11_SUITE,init_per_suite}},
+ {?eh,tc_done,{t11_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{1,2,{1,1}}},
+ {?eh,tc_start,{t11_SUITE,end_per_suite}},
+ {?eh,tc_done,{t11_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t21_SUITE,init_per_suite}},
+ {?eh,tc_done,{t21_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{2,4,{2,2}}},
+ {?eh,tc_start,{t21_SUITE,end_per_suite}},
+ {?eh,tc_done,{t21_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t11_SUITE,init_per_suite}},
+ {?eh,tc_done,{t11_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{3,6,{3,3}}},
+ {?eh,tc_start,{t11_SUITE,end_per_suite}},
+ {?eh,tc_done,{t11_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t11_SUITE,init_per_suite}},
+ {?eh,tc_done,{t11_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{4,8,{4,4}}},
+ {?eh,tc_start,{t11_SUITE,end_per_suite}},
+ {?eh,tc_done,{t11_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t21_SUITE,init_per_suite}},
+ {?eh,tc_done,{t21_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{5,10,{5,5}}},
+ {?eh,tc_start,{t21_SUITE,end_per_suite}},
+ {?eh,tc_done,{t21_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{3,2,15}},
+ {?eh,tc_start,{t12_SUITE,init_per_suite}},
+ {?eh,tc_done,{t12_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{1,2,{1,1}}},
+ {?eh,tc_start,{t12_SUITE,end_per_suite}},
+ {?eh,tc_done,{t12_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t12_SUITE,init_per_suite}},
+ {?eh,tc_done,{t12_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{2,4,{2,2}}},
+ {?eh,tc_start,{t12_SUITE,end_per_suite}},
+ {?eh,tc_done,{t12_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,init_per_suite}},
+ {?eh,tc_done,{t22_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{3,6,{3,3}}},
+ {?eh,tc_start,{t22_SUITE,end_per_suite}},
+ {?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{4,4,20}},
+ {?eh,tc_start,{t11_SUITE,init_per_suite}},
+ {?eh,tc_done,{t11_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{1,2,{1,1}}},
+ {?eh,tc_start,{t11_SUITE,end_per_suite}},
+ {?eh,tc_done,{t11_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t12_SUITE,init_per_suite}},
+ {?eh,tc_done,{t12_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{2,4,{2,2}}},
+ {?eh,tc_start,{t12_SUITE,end_per_suite}},
+ {?eh,tc_done,{t12_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t21_SUITE,init_per_suite}},
+ {?eh,tc_done,{t21_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{3,6,{3,3}}},
+ {?eh,tc_start,{t21_SUITE,end_per_suite}},
+ {?eh,tc_done,{t21_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,init_per_suite}},
+ {?eh,tc_done,{t22_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{4,8,{4,4}}},
+ {?eh,tc_start,{t22_SUITE,end_per_suite}},
+ {?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{2,2,10}},
+ {?eh,tc_start,{t11_SUITE,init_per_suite}},
+ {?eh,tc_done,{t11_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{1,2,{1,1}}},
+ {?eh,tc_start,{t11_SUITE,end_per_suite}},
+ {?eh,tc_done,{t11_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t21_SUITE,init_per_suite}},
+ {?eh,tc_done,{t21_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{2,4,{2,2}}},
+ {?eh,tc_start,{t21_SUITE,end_per_suite}},
+ {?eh,tc_done,{t21_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(incl_both_and_join2) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{4,4,20}},
+ {?eh,tc_start,{t11_SUITE,init_per_suite}},
+ {?eh,tc_done,{t11_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{1,2,{1,1}}},
+ {?eh,tc_start,{t11_SUITE,end_per_suite}},
+ {?eh,tc_done,{t11_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t12_SUITE,init_per_suite}},
+ {?eh,tc_done,{t12_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{2,4,{2,2}}},
+ {?eh,tc_start,{t12_SUITE,end_per_suite}},
+ {?eh,tc_done,{t12_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t21_SUITE,init_per_suite}},
+ {?eh,tc_done,{t21_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{3,6,{3,3}}},
+ {?eh,tc_start,{t21_SUITE,end_per_suite}},
+ {?eh,tc_done,{t21_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,init_per_suite}},
+ {?eh,tc_done,{t22_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{4,8,{4,4}}},
+ {?eh,tc_start,{t22_SUITE,end_per_suite}},
+ {?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{3,2,15}},
+ {?eh,tc_start,{t12_SUITE,init_per_suite}},
+ {?eh,tc_done,{t12_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{1,2,{1,1}}},
+ {?eh,tc_start,{t12_SUITE,end_per_suite}},
+ {?eh,tc_done,{t12_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t12_SUITE,init_per_suite}},
+ {?eh,tc_done,{t12_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{2,4,{2,2}}},
+ {?eh,tc_start,{t12_SUITE,end_per_suite}},
+ {?eh,tc_done,{t12_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,init_per_suite}},
+ {?eh,tc_done,{t22_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{3,6,{3,3}}},
+ {?eh,tc_start,{t22_SUITE,end_per_suite}},
+ {?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{2,2,10}},
+ {?eh,tc_start,{t11_SUITE,init_per_suite}},
+ {?eh,tc_done,{t11_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{1,2,{1,1}}},
+ {?eh,tc_start,{t11_SUITE,end_per_suite}},
+ {?eh,tc_done,{t11_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t21_SUITE,init_per_suite}},
+ {?eh,tc_done,{t21_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{2,4,{2,2}}},
+ {?eh,tc_start,{t21_SUITE,end_per_suite}},
+ {?eh,tc_done,{t21_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(rec_incl_separate1) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec2_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec1_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,5}},
+ {?eh,tc_start,{t22_SUITE,init_per_suite}},
+ {?eh,tc_done,{t22_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{1,2,{1,1}}},
+ {?eh,tc_start,{t22_SUITE,end_per_suite}},
+ {?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec1_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec2_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,5}},
+ {?eh,tc_start,{t23_SUITE,init_per_suite}},
+ {?eh,tc_done,{t23_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{1,2,{1,1}}},
+ {?eh,tc_start,{t23_SUITE,end_per_suite}},
+ {?eh,tc_done,{t23_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,5}},
+ {?eh,tc_start,{t22_SUITE,init_per_suite}},
+ {?eh,tc_done,{t22_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,end_per_suite}},
+ {?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec1_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec2_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec2_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec1_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(rec_incl_separate2) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,5}},
+ {?eh,tc_start,{t23_SUITE,init_per_suite}},
+ {?eh,tc_done,{t23_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{1,2,{1,1}}},
+ {?eh,tc_start,{t23_SUITE,end_per_suite}},
+ {?eh,tc_done,{t23_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec2_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec1_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,5}},
+ {?eh,tc_start,{t22_SUITE,init_per_suite}},
+ {?eh,tc_done,{t22_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{1,2,{1,1}}},
+ {?eh,tc_start,{t22_SUITE,end_per_suite}},
+ {?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec1_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec2_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,5}},
+ {?eh,tc_start,{t22_SUITE,init_per_suite}},
+ {?eh,tc_done,{t22_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{1,2,{1,1}}},
+ {?eh,tc_start,{t22_SUITE,end_per_suite}},
+ {?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec1_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec2_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec2_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec1_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(rec_incl_join1) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{4,4,20}},
+ {?eh,tc_start,{t12_SUITE,init_per_suite}},
+ {?eh,tc_done,{t12_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t12_SUITE,end_per_suite}},
+ {?eh,tc_done,{t12_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t11_SUITE,init_per_suite}},
+ {?eh,tc_done,{t11_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t11_SUITE,end_per_suite}},
+ {?eh,tc_done,{t11_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,init_per_suite}},
+ {?eh,tc_done,{t22_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,end_per_suite}},
+ {?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t21_SUITE,init_per_suite}},
+ {?eh,tc_done,{t21_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{4,8,{4,4}}},
+ {?eh,tc_start,{t21_SUITE,end_per_suite}},
+ {?eh,tc_done,{t21_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{5,5,25}},
+ {?eh,tc_start,{t23_SUITE,init_per_suite}},
+ {?eh,tc_done,{t23_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t23_SUITE,end_per_suite}},
+ {?eh,tc_done,{t23_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,init_per_suite}},
+ {?eh,tc_done,{t22_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,end_per_suite}},
+ {?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t21_SUITE,init_per_suite}},
+ {?eh,tc_done,{t21_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t21_SUITE,end_per_suite}},
+ {?eh,tc_done,{t21_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t11_SUITE,init_per_suite}},
+ {?eh,tc_done,{t11_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t11_SUITE,end_per_suite}},
+ {?eh,tc_done,{t11_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t12_SUITE,init_per_suite}},
+ {?eh,tc_done,{t12_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{5,10,{5,5}}},
+ {?eh,tc_start,{t12_SUITE,end_per_suite}},
+ {?eh,tc_done,{t12_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+test_events(rec_incl_join2) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{5,5,25}},
+ {?eh,tc_start,{t12_SUITE,init_per_suite}},
+ {?eh,tc_done,{t12_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t12_SUITE,end_per_suite}},
+ {?eh,tc_done,{t12_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t11_SUITE,init_per_suite}},
+ {?eh,tc_done,{t11_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t11_SUITE,end_per_suite}},
+ {?eh,tc_done,{t11_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,init_per_suite}},
+ {?eh,tc_done,{t22_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,end_per_suite}},
+ {?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t21_SUITE,init_per_suite}},
+ {?eh,tc_done,{t21_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t21_SUITE,end_per_suite}},
+ {?eh,tc_done,{t21_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t23_SUITE,init_per_suite}},
+ {?eh,tc_done,{t23_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{5,10,{5,5}}},
+ {?eh,tc_start,{t23_SUITE,end_per_suite}},
+ {?eh,tc_done,{t23_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(rec_incl_separate_join1) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{4,4,20}},
+ {?eh,tc_start,{t22_SUITE,init_per_suite}},
+ {?eh,tc_done,{t22_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,end_per_suite}},
+ {?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t21_SUITE,init_per_suite}},
+ {?eh,tc_done,{t21_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t21_SUITE,end_per_suite}},
+ {?eh,tc_done,{t21_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t11_SUITE,init_per_suite}},
+ {?eh,tc_done,{t11_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t11_SUITE,end_per_suite}},
+ {?eh,tc_done,{t11_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t12_SUITE,init_per_suite}},
+ {?eh,tc_done,{t12_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{4,8,{4,4}}},
+ {?eh,tc_start,{t12_SUITE,end_per_suite}},
+ {?eh,tc_done,{t12_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{4,4,20}},
+ {?eh,tc_start,{t12_SUITE,init_per_suite}},
+ {?eh,tc_done,{t12_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t12_SUITE,end_per_suite}},
+ {?eh,tc_done,{t12_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t11_SUITE,init_per_suite}},
+ {?eh,tc_done,{t11_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t11_SUITE,end_per_suite}},
+ {?eh,tc_done,{t11_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,init_per_suite}},
+ {?eh,tc_done,{t22_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,end_per_suite}},
+ {?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t21_SUITE,init_per_suite}},
+ {?eh,tc_done,{t21_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{4,8,{4,4}}},
+ {?eh,tc_start,{t21_SUITE,end_per_suite}},
+ {?eh,tc_done,{t21_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,5}},
+ {?eh,tc_start,{t23_SUITE,init_per_suite}},
+ {?eh,tc_done,{t23_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{1,2,{1,1}}},
+ {?eh,tc_start,{t23_SUITE,end_per_suite}},
+ {?eh,tc_done,{t23_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{4,4,20}},
+ {?eh,tc_start,{t12_SUITE,init_per_suite}},
+ {?eh,tc_done,{t12_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t12_SUITE,end_per_suite}},
+ {?eh,tc_done,{t12_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t11_SUITE,init_per_suite}},
+ {?eh,tc_done,{t11_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t11_SUITE,end_per_suite}},
+ {?eh,tc_done,{t11_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,init_per_suite}},
+ {?eh,tc_done,{t22_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,end_per_suite}},
+ {?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t21_SUITE,init_per_suite}},
+ {?eh,tc_done,{t21_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{4,8,{4,4}}},
+ {?eh,tc_start,{t21_SUITE,end_per_suite}},
+ {?eh,tc_done,{t21_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{4,4,20}},
+ {?eh,tc_start,{t22_SUITE,init_per_suite}},
+ {?eh,tc_done,{t22_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,end_per_suite}},
+ {?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t21_SUITE,init_per_suite}},
+ {?eh,tc_done,{t21_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t21_SUITE,end_per_suite}},
+ {?eh,tc_done,{t21_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t11_SUITE,init_per_suite}},
+ {?eh,tc_done,{t11_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t11_SUITE,end_per_suite}},
+ {?eh,tc_done,{t11_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t12_SUITE,init_per_suite}},
+ {?eh,tc_done,{t12_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{4,8,{4,4}}},
+ {?eh,tc_start,{t12_SUITE,end_per_suite}},
+ {?eh,tc_done,{t12_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(rec_incl_separate_join2) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,5}},
+ {?eh,tc_start,{t23_SUITE,init_per_suite}},
+ {?eh,tc_done,{t23_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{1,2,{1,1}}},
+ {?eh,tc_start,{t23_SUITE,end_per_suite}},
+ {?eh,tc_done,{t23_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{4,4,20}},
+ {?eh,tc_start,{t22_SUITE,init_per_suite}},
+ {?eh,tc_done,{t22_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,end_per_suite}},
+ {?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t21_SUITE,init_per_suite}},
+ {?eh,tc_done,{t21_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t21_SUITE,end_per_suite}},
+ {?eh,tc_done,{t21_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t11_SUITE,init_per_suite}},
+ {?eh,tc_done,{t11_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t11_SUITE,end_per_suite}},
+ {?eh,tc_done,{t11_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t12_SUITE,init_per_suite}},
+ {?eh,tc_done,{t12_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{4,8,{4,4}}},
+ {?eh,tc_start,{t12_SUITE,end_per_suite}},
+ {?eh,tc_done,{t12_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{4,4,20}},
+ {?eh,tc_start,{t12_SUITE,init_per_suite}},
+ {?eh,tc_done,{t12_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t12_SUITE,end_per_suite}},
+ {?eh,tc_done,{t12_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t11_SUITE,init_per_suite}},
+ {?eh,tc_done,{t11_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t11_SUITE,end_per_suite}},
+ {?eh,tc_done,{t11_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,init_per_suite}},
+ {?eh,tc_done,{t22_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,end_per_suite}},
+ {?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t21_SUITE,init_per_suite}},
+ {?eh,tc_done,{t21_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{4,8,{4,4}}},
+ {?eh,tc_start,{t21_SUITE,end_per_suite}},
+ {?eh,tc_done,{t21_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+
+ {?eh,stop_logging,[]},
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{4,4,20}},
+ {?eh,tc_start,{t12_SUITE,init_per_suite}},
+ {?eh,tc_done,{t12_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t12_SUITE,end_per_suite}},
+ {?eh,tc_done,{t12_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t11_SUITE,init_per_suite}},
+ {?eh,tc_done,{t11_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t11_SUITE,end_per_suite}},
+ {?eh,tc_done,{t11_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,init_per_suite}},
+ {?eh,tc_done,{t22_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,end_per_suite}},
+ {?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t21_SUITE,init_per_suite}},
+ {?eh,tc_done,{t21_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{4,8,{4,4}}},
+ {?eh,tc_start,{t21_SUITE,end_per_suite}},
+ {?eh,tc_done,{t21_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{4,4,20}},
+ {?eh,tc_start,{t22_SUITE,init_per_suite}},
+ {?eh,tc_done,{t22_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,end_per_suite}},
+ {?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t21_SUITE,init_per_suite}},
+ {?eh,tc_done,{t21_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t21_SUITE,end_per_suite}},
+ {?eh,tc_done,{t21_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t11_SUITE,init_per_suite}},
+ {?eh,tc_done,{t11_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t11_SUITE,end_per_suite}},
+ {?eh,tc_done,{t11_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t12_SUITE,init_per_suite}},
+ {?eh,tc_done,{t12_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{4,8,{4,4}}},
+ {?eh,tc_start,{t12_SUITE,end_per_suite}},
+ {?eh,tc_done,{t12_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(rec_incl_join_separate1) ->
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{2,2,10}},
+ {?eh,tc_start,{t23_SUITE,init_per_suite}},
+ {?eh,tc_done,{t23_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{1,2,{1,1}}},
+ {?eh,tc_start,{t23_SUITE,end_per_suite}},
+ {?eh,tc_done,{t23_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,init_per_suite}},
+ {?eh,tc_done,{t22_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{2,4,{2,2}}},
+ {?eh,tc_start,{t22_SUITE,end_per_suite}},
+ {?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec2_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec1_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec1_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec2_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{2,2,10}},
+ {?eh,tc_start,{t23_SUITE,init_per_suite}},
+ {?eh,tc_done,{t23_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{1,2,{1,1}}},
+ {?eh,tc_start,{t23_SUITE,end_per_suite}},
+ {?eh,tc_done,{t23_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,init_per_suite}},
+ {?eh,tc_done,{t22_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{2,4,{2,2}}},
+ {?eh,tc_start,{t22_SUITE,end_per_suite}},
+ {?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec1_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec2_events() ++
+
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec2_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec1_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(rec_incl_join_separate2) ->
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{2,2,10}},
+ {?eh,tc_start,{t23_SUITE,init_per_suite}},
+ {?eh,tc_done,{t23_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{1,2,{1,1}}},
+ {?eh,tc_start,{t23_SUITE,end_per_suite}},
+ {?eh,tc_done,{t23_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,init_per_suite}},
+ {?eh,tc_done,{t22_SUITE,init_per_suite,ok}},
+ {?eh,test_stats,{2,4,{2,2}}},
+ {?eh,tc_start,{t22_SUITE,end_per_suite}},
+ {?eh,tc_done,{t22_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec2_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec1_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec1_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec2_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec1_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec2_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec2_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]},
+
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}]
+ ++ flat_spec1_events() ++
+ [{?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}].
+
+%%%-----------------------------------------------------------------
+
+flat_spec1_events() ->
+ [
+ {?eh,start_info,{2,2,10}},
+ {?eh,tc_start,{t11_SUITE,init_per_suite}},
+ {?eh,tc_done,{t11_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t11_SUITE,ok_tc}},
+ {?eh,tc_done,{t11_SUITE,ok_tc,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ {?eh,tc_start,{t11_SUITE,exit_tc}},
+ {?eh,tc_done,{t11_SUITE,exit_tc,{failed,{error,kaboom}}}},
+ {?eh,test_stats,{1,1,{0,0}}},
+ {?eh,tc_start,{t11_SUITE,to_tc}},
+ {?eh,tc_done,{t11_SUITE,to_tc,{failed,{timetrap_timeout,1}}}},
+ {?eh,test_stats,{1,2,{0,0}}},
+ {?eh,tc_start,{t11_SUITE,autoskip_tc}},
+ {?eh,tc_done,
+ {t11_SUITE,autoskip_tc,{skipped,
+ {failed,
+ {t11_SUITE,init_per_testcase,
+ {kaboom,'_'}}}}}},
+ {?eh,test_stats,{1,2,{0,1}}},
+ {?eh,tc_start,{t11_SUITE,userskip_tc}},
+ {?eh,tc_done,{t11_SUITE,userskip_tc,{skipped,"user skipped"}}},
+ {?eh,test_stats,{1,2,{1,1}}},
+ {?eh,tc_start,{t11_SUITE,end_per_suite}},
+ {?eh,tc_done,{t11_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t21_SUITE,init_per_suite}},
+ {?eh,tc_done,{t21_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t21_SUITE,ok_tc}},
+ {?eh,tc_done,{t21_SUITE,ok_tc,ok}},
+ {?eh,test_stats,{2,2,{1,1}}},
+ {?eh,tc_start,{t21_SUITE,exit_tc}},
+ {?eh,tc_done,{t21_SUITE,exit_tc,{failed,{error,kaboom}}}},
+ {?eh,test_stats,{2,3,{1,1}}},
+ {?eh,tc_start,{t21_SUITE,to_tc}},
+ {?eh,tc_done,{t21_SUITE,to_tc,{failed,{timetrap_timeout,1}}}},
+ {?eh,test_stats,{2,4,{1,1}}},
+ {?eh,tc_start,{t21_SUITE,autoskip_tc}},
+ {?eh,tc_done,
+ {t21_SUITE,autoskip_tc,{skipped,
+ {failed,
+ {t21_SUITE,init_per_testcase,
+ {kaboom,'_'}}}}}},
+ {?eh,test_stats,{2,4,{1,2}}},
+ {?eh,tc_start,{t21_SUITE,userskip_tc}},
+ {?eh,tc_done,{t21_SUITE,userskip_tc,{skipped,"user skipped"}}},
+ {?eh,test_stats,{2,4,{2,2}}},
+ {?eh,tc_start,{t21_SUITE,end_per_suite}},
+ {?eh,tc_done,{t21_SUITE,end_per_suite,ok}}].
+
+flat_spec2_events() ->
+ [
+ {?eh,start_info,{3,2,15}},
+ {?eh,tc_start,{t12_SUITE,init_per_suite}},
+ {?eh,tc_done,{t12_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t12_SUITE,ok_tc}},
+ {?eh,tc_done,{t12_SUITE,ok_tc,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ {?eh,tc_start,{t12_SUITE,exit_tc}},
+ {?eh,tc_done,{t12_SUITE,exit_tc,{failed,{error,kaboom}}}},
+ {?eh,test_stats,{1,1,{0,0}}},
+ {?eh,tc_start,{t12_SUITE,to_tc}},
+ {?eh,tc_done,{t12_SUITE,to_tc,{failed,{timetrap_timeout,1}}}},
+ {?eh,test_stats,{1,2,{0,0}}},
+ {?eh,tc_start,{t12_SUITE,autoskip_tc}},
+ {?eh,tc_done,
+ {t12_SUITE,autoskip_tc,{skipped,
+ {failed,
+ {t12_SUITE,init_per_testcase,
+ {kaboom,'_'}}}}}},
+ {?eh,test_stats,{1,2,{0,1}}},
+ {?eh,tc_start,{t12_SUITE,userskip_tc}},
+ {?eh,tc_done,{t12_SUITE,userskip_tc,{skipped,"user skipped"}}},
+ {?eh,test_stats,{1,2,{1,1}}},
+ {?eh,tc_start,{t12_SUITE,end_per_suite}},
+ {?eh,tc_done,{t12_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t12_SUITE,init_per_suite}},
+ {?eh,tc_done,{t12_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t12_SUITE,ok_tc}},
+ {?eh,tc_done,{t12_SUITE,ok_tc,ok}},
+ {?eh,test_stats,{2,2,{1,1}}},
+ {?eh,tc_start,{t12_SUITE,exit_tc}},
+ {?eh,tc_done,{t12_SUITE,exit_tc,{failed,{error,kaboom}}}},
+ {?eh,test_stats,{2,3,{1,1}}},
+ {?eh,tc_start,{t12_SUITE,to_tc}},
+ {?eh,tc_done,{t12_SUITE,to_tc,{failed,{timetrap_timeout,1}}}},
+ {?eh,test_stats,{2,4,{1,1}}},
+ {?eh,tc_start,{t12_SUITE,autoskip_tc}},
+ {?eh,tc_done,
+ {t12_SUITE,autoskip_tc,{skipped,
+ {failed,
+ {t12_SUITE,init_per_testcase,
+ {kaboom,'_'}}}}}},
+ {?eh,test_stats,{2,4,{1,2}}},
+ {?eh,tc_start,{t12_SUITE,userskip_tc}},
+ {?eh,tc_done,{t12_SUITE,userskip_tc,{skipped,"user skipped"}}},
+ {?eh,test_stats,{2,4,{2,2}}},
+ {?eh,tc_start,{t12_SUITE,end_per_suite}},
+ {?eh,tc_done,{t12_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,init_per_suite}},
+ {?eh,tc_done,{t22_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{t22_SUITE,ok_tc}},
+ {?eh,tc_done,{t22_SUITE,ok_tc,ok}},
+ {?eh,test_stats,{3,4,{2,2}}},
+ {?eh,tc_start,{t22_SUITE,exit_tc}},
+ {?eh,tc_done,{t22_SUITE,exit_tc,{failed,{error,kaboom}}}},
+ {?eh,test_stats,{3,5,{2,2}}},
+ {?eh,tc_start,{t22_SUITE,to_tc}},
+ {?eh,tc_done,{t22_SUITE,to_tc,{failed,{timetrap_timeout,1}}}},
+ {?eh,test_stats,{3,6,{2,2}}},
+ {?eh,tc_start,{t22_SUITE,autoskip_tc}},
+ {?eh,tc_done,
+ {t22_SUITE,autoskip_tc,{skipped,
+ {failed,
+ {t22_SUITE,init_per_testcase,
+ {kaboom,'_'}}}}}},
+ {?eh,test_stats,{3,6,{2,3}}},
+ {?eh,tc_start,{t22_SUITE,userskip_tc}},
+ {?eh,tc_done,{t22_SUITE,userskip_tc,{skipped,"user skipped"}}},
+ {?eh,test_stats,{3,6,{3,3}}},
+ {?eh,tc_start,{t22_SUITE,end_per_suite}},
+ {?eh,tc_done,{t22_SUITE,end_per_suite,ok}}].
diff --git a/lib/common_test/vsn.mk b/lib/common_test/vsn.mk
index 87d762b697..d60b4ba675 100644
--- a/lib/common_test/vsn.mk
+++ b/lib/common_test/vsn.mk
@@ -1 +1 @@
-COMMON_TEST_VSN = 1.7.1
+COMMON_TEST_VSN = 1.7.2
diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml
index 352bb0d7ac..837fcf4368 100644
--- a/lib/compiler/doc/src/notes.xml
+++ b/lib/compiler/doc/src/notes.xml
@@ -31,6 +31,57 @@
<p>This document describes the changes made to the Compiler
application.</p>
+<section><title>Compiler 4.9.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Compiling functions with complex boolean operations in
+ guards could be very slow. (Thanks to Magnus Muller for
+ reporting this issue.)</p>
+ <p>
+ Own Id: OTP-10939</p>
+ </item>
+ <item>
+ <p>
+ Certain guard expressions used in a receive statement
+ could cause the compiler to crash.</p>
+ <p>
+ Own Id: OTP-11119 Aux Id: seq12342 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Fix optimization of some binary comprehensions. Thanks to
+ Anthony Ramine.</p>
+ <p>
+ Own Id: OTP-11005</p>
+ </item>
+ <item>
+ <p>
+ Use a set to store ref registers in beam_receive. Thanks
+ to Anthony Ramine.</p>
+ <p>
+ Own Id: OTP-11069</p>
+ </item>
+ <item>
+ <p>
+ Fix renaming of bs_put_string instructions. Thanks to
+ Anthony Ramine.</p>
+ <p>
+ Own Id: OTP-11129</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Compiler 4.9.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/compiler/src/beam_a.erl b/lib/compiler/src/beam_a.erl
index b348e854a0..c590c5e35b 100644
--- a/lib/compiler/src/beam_a.erl
+++ b/lib/compiler/src/beam_a.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl
index e623bcc6a5..e9911fefd9 100644
--- a/lib/compiler/src/beam_utils.erl
+++ b/lib/compiler/src/beam_utils.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl
index 2af7166c86..8159b42f2f 100644
--- a/lib/compiler/src/v3_core.erl
+++ b/lib/compiler/src/v3_core.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/compiler/test/bs_bincomp_SUITE.erl b/lib/compiler/test/bs_bincomp_SUITE.erl
index 6140320728..4450405695 100644
--- a/lib/compiler/test/bs_bincomp_SUITE.erl
+++ b/lib/compiler/test/bs_bincomp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk
index 90d2bff0ad..1c6f49d89b 100644
--- a/lib/compiler/vsn.mk
+++ b/lib/compiler/vsn.mk
@@ -1 +1 @@
-COMPILER_VSN = 4.9.1
+COMPILER_VSN = 4.9.2
diff --git a/lib/cosEvent/doc/src/notes.xml b/lib/cosEvent/doc/src/notes.xml
index ef25ceb374..df05f5634e 100644
--- a/lib/cosEvent/doc/src/notes.xml
+++ b/lib/cosEvent/doc/src/notes.xml
@@ -32,7 +32,22 @@
<file>notes.xml</file>
</header>
- <section><title>cosEvent 2.1.13</title>
+ <section><title>cosEvent 2.1.14</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Postscript files no longer needed for the generation
+ of PDF files have been removed. </p>
+ <p>
+ Own Id: OTP-11016</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>cosEvent 2.1.13</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/cosEvent/vsn.mk b/lib/cosEvent/vsn.mk
index 85c5c6aadd..6745bee079 100644
--- a/lib/cosEvent/vsn.mk
+++ b/lib/cosEvent/vsn.mk
@@ -1,3 +1,3 @@
-COSEVENT_VSN = 2.1.13
+COSEVENT_VSN = 2.1.14
diff --git a/lib/cosFileTransfer/doc/src/notes.xml b/lib/cosFileTransfer/doc/src/notes.xml
index 385336bffc..5cca5e307b 100644
--- a/lib/cosFileTransfer/doc/src/notes.xml
+++ b/lib/cosFileTransfer/doc/src/notes.xml
@@ -30,7 +30,22 @@
<file>notes.xml</file>
</header>
- <section><title>cosFileTransfer 1.1.14</title>
+ <section><title>cosFileTransfer 1.1.15</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Postscript files no longer needed for the generation
+ of PDF files have been removed. </p>
+ <p>
+ Own Id: OTP-11016</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>cosFileTransfer 1.1.14</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/cosFileTransfer/vsn.mk b/lib/cosFileTransfer/vsn.mk
index 58545be931..cf33926334 100644
--- a/lib/cosFileTransfer/vsn.mk
+++ b/lib/cosFileTransfer/vsn.mk
@@ -1 +1 @@
-COSFILETRANSFER_VSN = 1.1.14
+COSFILETRANSFER_VSN = 1.1.15
diff --git a/lib/cosNotification/doc/src/notes.xml b/lib/cosNotification/doc/src/notes.xml
index 88c9d38062..b700e0984c 100644
--- a/lib/cosNotification/doc/src/notes.xml
+++ b/lib/cosNotification/doc/src/notes.xml
@@ -31,7 +31,22 @@
<file>notes.xml</file>
</header>
- <section><title>cosNotification 1.1.19</title>
+ <section><title>cosNotification 1.1.20</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Postscript files no longer needed for the generation
+ of PDF files have been removed. </p>
+ <p>
+ Own Id: OTP-11016</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>cosNotification 1.1.19</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/cosNotification/vsn.mk b/lib/cosNotification/vsn.mk
index 20eb6167ac..ea59800164 100644
--- a/lib/cosNotification/vsn.mk
+++ b/lib/cosNotification/vsn.mk
@@ -1,2 +1,2 @@
-COSNOTIFICATION_VSN = 1.1.19
+COSNOTIFICATION_VSN = 1.1.20
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 98ebb21f29..c28ff8136c 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -142,6 +142,19 @@
(s)[3] = (char)((i) & 0xff);\
}
+/* This shall correspond to the similar macro in crypto.erl */
+/* Current value is: erlang:system_info(context_reductions) * 10 */
+#define MAX_BYTES_TO_NIF 20000
+
+#define CONSUME_REDS(NifEnv, Ibin) \
+do { \
+ int _cost = ((Ibin).size * 100) / MAX_BYTES_TO_NIF;\
+ if (_cost) { \
+ (void) enif_consume_timeslice((NifEnv), \
+ (_cost > 100) ? 100 : _cost); \
+ } \
+ } while (0)
+
/* NIF interface declarations */
static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info);
static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info);
@@ -208,7 +221,7 @@ static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
static ERL_NIF_TERM dss_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_set_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -229,8 +242,6 @@ static ERL_NIF_TERM bf_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
static ERL_NIF_TERM bf_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM blowfish_ofb64_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM ec_key_to_term_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM term_to_ec_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -338,7 +349,7 @@ static ErlNifFunc nif_funcs[] = {
{"dss_verify_nif", 4, dss_verify_nif},
{"rsa_verify_nif", 4, rsa_verify_nif},
{"aes_cbc_crypt", 4, aes_cbc_crypt},
- {"exor", 2, exor},
+ {"do_exor", 2, do_exor},
{"rc4_encrypt", 2, rc4_encrypt},
{"rc4_set_key", 1, rc4_set_key},
{"rc4_encrypt_with_state", 2, rc4_encrypt_with_state},
@@ -359,12 +370,10 @@ static ErlNifFunc nif_funcs[] = {
{"bf_ecb_crypt", 3, bf_ecb_crypt},
{"blowfish_ofb64_encrypt", 3, blowfish_ofb64_encrypt},
- {"ec_key_to_term_nif", 1, ec_key_to_term_nif},
- {"term_to_ec_key_nif", 3, term_to_ec_key_nif},
{"ec_key_generate", 1, ec_key_generate},
- {"ecdsa_sign_nif", 3, ecdsa_sign_nif},
- {"ecdsa_verify_nif", 4, ecdsa_verify_nif},
- {"ecdh_compute_key_nif", 2, ecdh_compute_key_nif}
+ {"ecdsa_sign_nif", 4, ecdsa_sign_nif},
+ {"ecdsa_verify_nif", 5, ecdsa_verify_nif},
+ {"ecdh_compute_key_nif", 3, ecdh_compute_key_nif}
};
#if defined(HAVE_EC)
@@ -459,10 +468,7 @@ static struct nid_map ec_curves[] = {
#define EC_CURVES_CNT (sizeof(ec_curves)/sizeof(struct nid_map))
-struct nif_ec_key {
- EC_KEY *key;
-};
-#endif
+#endif /* HAVE_EC */
ERL_NIF_INIT(crypto,nif_funcs,load,NULL,upgrade,unload)
@@ -515,17 +521,13 @@ static ERL_NIF_TERM atom_none;
static ERL_NIF_TERM atom_notsup;
static ERL_NIF_TERM atom_digest;
-static ERL_NIF_TERM atom_ec;
-
#if defined(HAVE_EC)
+static ERL_NIF_TERM atom_ec;
static ERL_NIF_TERM atom_prime_field;
static ERL_NIF_TERM atom_characteristic_two_field;
static ERL_NIF_TERM atom_tpbasis;
static ERL_NIF_TERM atom_ppbasis;
static ERL_NIF_TERM atom_onbasis;
-
-static ErlNifResourceType* res_type_ec_key;
-static void ec_key_dtor(ErlNifEnv* env, void* obj);
#endif
/*
@@ -557,7 +559,6 @@ static void error_handler(void* null, const char* errstr)
static int init(ErlNifEnv* env, ERL_NIF_TERM load_info)
{
- int i;
ErlNifSysInfo sys_info;
get_crypto_callbacks_t* funcp;
struct crypto_callbacks* ccb;
@@ -577,6 +578,7 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info)
PRINTF_ERR1("CRYPTO: Invalid load_info '%T'", load_info);
return 0;
}
+
if (library_refc > 0) {
/* Repeated loading of this library (module upgrade).
* Atoms and callbacks are already set, we are done.
@@ -618,13 +620,11 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info)
atom_ppbasis = enif_make_atom(env,"ppbasis");
atom_onbasis = enif_make_atom(env,"onbasis");
- for (i = 0; i < EC_CURVES_CNT; i++)
+ {
+ int i;
+ for (i = 0; i < EC_CURVES_CNT; i++)
ec_curves[i].atom = enif_make_atom(env,ec_curves[i].name);
-
- res_type_ec_key = enif_open_resource_type(env,NULL,"crypto.EC_KEY",
- ec_key_dtor,
- ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER,
- NULL);
+ }
#endif
init_digest_types(env);
@@ -778,6 +778,7 @@ static ERL_NIF_TERM md5(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
}
MD5((unsigned char *) ibin.data, ibin.size,
enif_make_new_binary(env,MD5_LEN, &ret));
+ CONSUME_REDS(env,ibin);
return ret;
}
static ERL_NIF_TERM md5_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -799,6 +800,7 @@ static ERL_NIF_TERM md5_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
new_ctx = (MD5_CTX*) enif_make_new_binary(env,MD5_CTX_LEN, &ret);
memcpy(new_ctx, ctx_bin.data, MD5_CTX_LEN);
MD5_Update(new_ctx, data_bin.data, data_bin.size);
+ CONSUME_REDS(env,data_bin);
return ret;
}
static ERL_NIF_TERM md5_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -820,10 +822,11 @@ static ERL_NIF_TERM ripemd160(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
ERL_NIF_TERM ret;
if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
- return enif_make_badarg(env);
+ return enif_make_badarg(env);
}
RIPEMD160((unsigned char *) ibin.data, ibin.size,
- enif_make_new_binary(env,RIPEMD160_LEN, &ret));
+ enif_make_new_binary(env,RIPEMD160_LEN, &ret));
+ CONSUME_REDS(env,ibin);
return ret;
}
static ERL_NIF_TERM ripemd160_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -838,13 +841,14 @@ static ERL_NIF_TERM ripemd160_update(ErlNifEnv* env, int argc, const ERL_NIF_TER
ErlNifBinary ctx_bin, data_bin;
ERL_NIF_TERM ret;
if (!enif_inspect_binary(env, argv[0], &ctx_bin)
- || ctx_bin.size != RIPEMD160_CTX_LEN
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
- return enif_make_badarg(env);
+ || ctx_bin.size != RIPEMD160_CTX_LEN
+ || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
+ return enif_make_badarg(env);
}
new_ctx = (RIPEMD160_CTX*) enif_make_new_binary(env,RIPEMD160_CTX_LEN, &ret);
memcpy(new_ctx, ctx_bin.data, RIPEMD160_CTX_LEN);
RIPEMD160_Update(new_ctx, data_bin.data, data_bin.size);
+ CONSUME_REDS(env, data_bin);
return ret;
}
static ERL_NIF_TERM ripemd160_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -853,7 +857,7 @@ static ERL_NIF_TERM ripemd160_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM
RIPEMD160_CTX ctx_clone;
ERL_NIF_TERM ret;
if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != RIPEMD160_CTX_LEN) {
- return enif_make_badarg(env);
+ return enif_make_badarg(env);
}
memcpy(&ctx_clone, ctx_bin.data, RIPEMD160_CTX_LEN); /* writable */
RIPEMD160_Final(enif_make_new_binary(env, RIPEMD160_LEN, &ret), &ctx_clone);
@@ -871,6 +875,7 @@ static ERL_NIF_TERM sha(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
}
SHA1((unsigned char *) ibin.data, ibin.size,
enif_make_new_binary(env,SHA_LEN, &ret));
+ CONSUME_REDS(env,ibin);
return ret;
}
static ERL_NIF_TERM sha_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -891,6 +896,7 @@ static ERL_NIF_TERM sha_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
new_ctx = (SHA_CTX*) enif_make_new_binary(env,SHA_CTX_LEN, &ret);
memcpy(new_ctx, ctx_bin.data, SHA_CTX_LEN);
SHA1_Update(new_ctx, data_bin.data, data_bin.size);
+ CONSUME_REDS(env,data_bin);
return ret;
}
static ERL_NIF_TERM sha_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -917,6 +923,7 @@ static ERL_NIF_TERM sha224_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
}
SHA224((unsigned char *) ibin.data, ibin.size,
enif_make_new_binary(env,SHA224_LEN, &ret));
+ CONSUME_REDS(env,ibin);
return ret;
#else
return atom_notsup;
@@ -945,6 +952,7 @@ static ERL_NIF_TERM sha224_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
new_ctx = (SHA256_CTX*) enif_make_new_binary(env,sizeof(SHA256_CTX), &ret);
memcpy(new_ctx, ctx_bin.data, sizeof(SHA256_CTX));
SHA224_Update(new_ctx, data_bin.data, data_bin.size);
+ CONSUME_REDS(env,data_bin);
return ret;
#else
return atom_notsup;
@@ -978,6 +986,7 @@ static ERL_NIF_TERM sha256_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
}
SHA256((unsigned char *) ibin.data, ibin.size,
enif_make_new_binary(env,SHA256_LEN, &ret));
+ CONSUME_REDS(env,ibin);
return ret;
#else
return atom_notsup;
@@ -1006,6 +1015,7 @@ static ERL_NIF_TERM sha256_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
new_ctx = (SHA256_CTX*) enif_make_new_binary(env,sizeof(SHA256_CTX), &ret);
memcpy(new_ctx, ctx_bin.data, sizeof(SHA256_CTX));
SHA256_Update(new_ctx, data_bin.data, data_bin.size);
+ CONSUME_REDS(env,data_bin);
return ret;
#else
return atom_notsup;
@@ -1039,6 +1049,7 @@ static ERL_NIF_TERM sha384_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
}
SHA384((unsigned char *) ibin.data, ibin.size,
enif_make_new_binary(env,SHA384_LEN, &ret));
+ CONSUME_REDS(env,ibin);
return ret;
#else
return atom_notsup;
@@ -1067,6 +1078,7 @@ static ERL_NIF_TERM sha384_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
new_ctx = (SHA512_CTX*) enif_make_new_binary(env,sizeof(SHA512_CTX), &ret);
memcpy(new_ctx, ctx_bin.data, sizeof(SHA512_CTX));
SHA384_Update(new_ctx, data_bin.data, data_bin.size);
+ CONSUME_REDS(env,data_bin);
return ret;
#else
return atom_notsup;
@@ -1100,6 +1112,7 @@ static ERL_NIF_TERM sha512_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
}
SHA512((unsigned char *) ibin.data, ibin.size,
enif_make_new_binary(env,SHA512_LEN, &ret));
+ CONSUME_REDS(env,ibin);
return ret;
#else
return atom_notsup;
@@ -1128,6 +1141,7 @@ static ERL_NIF_TERM sha512_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
new_ctx = (SHA512_CTX*) enif_make_new_binary(env,sizeof(SHA512_CTX), &ret);
memcpy(new_ctx, ctx_bin.data, sizeof(SHA512_CTX));
SHA512_Update(new_ctx, data_bin.data, data_bin.size);
+ CONSUME_REDS(env,data_bin);
return ret;
#else
return atom_notsup;
@@ -1161,6 +1175,7 @@ static ERL_NIF_TERM md4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
}
MD4((unsigned char *) ibin.data, ibin.size,
enif_make_new_binary(env,MD4_LEN, &ret));
+ CONSUME_REDS(env,ibin);
return ret;
}
static ERL_NIF_TERM md4_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -1181,6 +1196,7 @@ static ERL_NIF_TERM md4_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
new_ctx = (MD4_CTX*) enif_make_new_binary(env,MD4_CTX_LEN, &ret);
memcpy(new_ctx, ctx_bin.data, MD4_CTX_LEN);
MD4_Update(new_ctx, data_bin.data, data_bin.size);
+ CONSUME_REDS(env,data_bin);
return ret;
}
static ERL_NIF_TERM md4_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -1210,6 +1226,7 @@ static ERL_NIF_TERM md5_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
}
hmac_md5(key.data, key.size, data.data, data.size, hmacbuf);
memcpy(enif_make_new_binary(env, mac_sz, &ret), hmacbuf, mac_sz);
+ CONSUME_REDS(env,data);
return ret;
}
@@ -1228,6 +1245,7 @@ static ERL_NIF_TERM sha_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
hmac_sha1(key.data, key.size, data.data, data.size, hmacbuf);
memcpy(enif_make_new_binary(env, mac_sz, &ret),
hmacbuf, mac_sz);
+ CONSUME_REDS(env,data);
return ret;
}
@@ -1247,6 +1265,7 @@ static ERL_NIF_TERM sha224_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
hmac_sha224(key.data, key.size, data.data, data.size, hmacbuf);
memcpy(enif_make_new_binary(env, mac_sz, &ret),
hmacbuf, mac_sz);
+ CONSUME_REDS(env,data);
return ret;
#else
return atom_notsup;
@@ -1269,6 +1288,7 @@ static ERL_NIF_TERM sha256_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
hmac_sha256(key.data, key.size, data.data, data.size, hmacbuf);
memcpy(enif_make_new_binary(env, mac_sz, &ret),
hmacbuf, mac_sz);
+ CONSUME_REDS(env,data);
return ret;
#else
return atom_notsup;
@@ -1291,6 +1311,7 @@ static ERL_NIF_TERM sha384_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
hmac_sha384(key.data, key.size, data.data, data.size, hmacbuf);
memcpy(enif_make_new_binary(env, mac_sz, &ret),
hmacbuf, mac_sz);
+ CONSUME_REDS(env,data);
return ret;
#else
return atom_notsup;
@@ -1314,6 +1335,7 @@ static ERL_NIF_TERM sha512_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
hmac_sha512(key.data, key.size, data.data, data.size, hmacbuf);
memcpy(enif_make_new_binary(env, mac_sz, &ret),
hmacbuf, mac_sz);
+ CONSUME_REDS(env,data);
return ret;
#else
return atom_notsup;
@@ -1371,6 +1393,7 @@ static ERL_NIF_TERM hmac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
ctx_buf = enif_make_new_binary(env, sizeof(HMAC_CTX), &ret);
memcpy(ctx_buf, context.data, context.size);
HMAC_Update((HMAC_CTX *)ctx_buf, data.data, data.size);
+ CONSUME_REDS(env,data);
return ret;
}
@@ -1401,7 +1424,7 @@ static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
HMAC_CTX_cleanup(&ctx);
if (argc == 2 && req_len < mac_len) {
- // Only truncate to req_len bytes if asked.
+ /* Only truncate to req_len bytes if asked. */
mac_len = req_len;
}
mac_bin = enif_make_new_binary(env, mac_len, &ret);
@@ -1427,6 +1450,7 @@ static ERL_NIF_TERM des_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
DES_set_key((const_DES_cblock*)key.data, &schedule);
DES_ncbc_encrypt(text.data, enif_make_new_binary(env, text.size, &ret),
text.size, &schedule, &ivec_clone, (argv[3] == atom_true));
+ CONSUME_REDS(env,text);
return ret;
}
@@ -1446,6 +1470,7 @@ static ERL_NIF_TERM des_cfb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
DES_set_key((const_DES_cblock*)key.data, &schedule);
DES_cfb_encrypt(text.data, enif_make_new_binary(env, text.size, &ret),
8, text.size, &schedule, &ivec_clone, (argv[3] == atom_true));
+ CONSUME_REDS(env,text);
return ret;
}
@@ -1462,6 +1487,7 @@ static ERL_NIF_TERM des_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
DES_ecb_encrypt((const_DES_cblock*)text.data,
(DES_cblock*)enif_make_new_binary(env, 8, &ret),
&schedule, (argv[2] == atom_true));
+ CONSUME_REDS(env,text);
return ret;
}
@@ -1488,6 +1514,7 @@ static ERL_NIF_TERM des_ede3_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_T
DES_ede3_cbc_encrypt(text.data, enif_make_new_binary(env,text.size,&ret),
text.size, &schedule1, &schedule2, &schedule3,
&ivec_clone, (argv[5] == atom_true));
+ CONSUME_REDS(env,text);
return ret;
}
@@ -1514,6 +1541,7 @@ static ERL_NIF_TERM des_ede3_cfb_crypt_nif(ErlNifEnv* env, int argc, const ERL_N
DES_ede3_cfb_encrypt(text.data, enif_make_new_binary(env,text.size,&ret),
8, text.size, &schedule1, &schedule2, &schedule3,
&ivec_clone, (argv[5] == atom_true));
+ CONSUME_REDS(env,text);
return ret;
#else
return atom_notsup;
@@ -1540,6 +1568,7 @@ static ERL_NIF_TERM aes_cfb_128_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TE
enif_make_new_binary(env, text.size, &ret),
text.size, &aes_key, ivec_clone, &new_ivlen,
(argv[3] == atom_true));
+ CONSUME_REDS(env,text);
return ret;
}
@@ -1565,6 +1594,7 @@ static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM
AES_ctr128_encrypt((unsigned char *) text.data,
enif_make_new_binary(env, text.size, &ret),
text.size, &aes_key, ivec_clone, ecount_buf, &num);
+ CONSUME_REDS(env,text);
/* To do an incremental {en|de}cryption, the state to to keep between calls
must include ivec_clone, ecount_buf and num. */
@@ -1608,6 +1638,7 @@ static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_N
num2_term = enif_make_uint(env, num);
new_state_term = enif_make_tuple4(env, state_term[0], ivec2_term, ecount2_term, num2_term);
ret = enif_make_tuple2(env, new_state_term, cipher_term);
+ CONSUME_REDS(env,text_bin);
return ret;
}
@@ -2055,10 +2086,11 @@ static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
ret_ptr = enif_make_new_binary(env, data_bin.size, &ret);
memcpy(ivec, ivec_bin.data, 16); /* writable copy */
AES_cbc_encrypt(data_bin.data, ret_ptr, data_bin.size, &aes_key, ivec, i);
+ CONSUME_REDS(env,data_bin);
return ret;
}
-static ERL_NIF_TERM exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Data1, Data2) */
ErlNifBinary d1, d2;
unsigned char* ret_ptr;
@@ -2075,6 +2107,7 @@ static ERL_NIF_TERM exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
for (i=0; i<d1.size; i++) {
ret_ptr[i] = d1.data[i] ^ d2.data[i];
}
+ CONSUME_REDS(env,d1);
return ret;
}
@@ -2091,6 +2124,7 @@ static ERL_NIF_TERM rc4_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
RC4_set_key(&rc4_key, key.size, key.data);
RC4(&rc4_key, data.size, data.data,
enif_make_new_binary(env, data.size, &ret));
+ CONSUME_REDS(env,data);
return ret;
}
@@ -2123,7 +2157,7 @@ static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_N
memcpy(rc4_key, state.data, sizeof(RC4_KEY));
RC4(rc4_key, data.size, data.data,
enif_make_new_binary(env, data.size, &new_data));
-
+ CONSUME_REDS(env,data);
return enif_make_tuple2(env,new_state,new_data);
}
@@ -2150,6 +2184,7 @@ static ERL_NIF_TERM rc2_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
data_bin.size, &rc2_key,
iv_copy,
(argv[3] == atom_true));
+ CONSUME_REDS(env,data_bin);
return ret;
}
@@ -2781,6 +2816,7 @@ static ERL_NIF_TERM bf_cfb64_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM
BF_cfb64_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret),
data_bin.size, &bf_key, bf_tkey, &bf_n,
(argv[3] == atom_true ? BF_ENCRYPT : BF_DECRYPT));
+ CONSUME_REDS(env,data_bin);
return ret;
}
@@ -2804,6 +2840,7 @@ static ERL_NIF_TERM bf_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
BF_cbc_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret),
data_bin.size, &bf_key, bf_tkey,
(argv[3] == atom_true ? BF_ENCRYPT : BF_DECRYPT));
+ CONSUME_REDS(env,data_bin);
return ret;
}
@@ -2821,6 +2858,7 @@ static ERL_NIF_TERM bf_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
BF_set_key(&bf_key, key_bin.size, key_bin.data);
BF_ecb_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret),
&bf_key, (argv[2] == atom_true ? BF_ENCRYPT : BF_DECRYPT));
+ CONSUME_REDS(env,data_bin);
return ret;
}
@@ -2843,6 +2881,7 @@ static ERL_NIF_TERM blowfish_ofb64_encrypt(ErlNifEnv* env, int argc, const ERL_N
memcpy(bf_tkey, ivec_bin.data, 8);
BF_ofb64_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret),
data_bin.size, &bf_key, bf_tkey, &bf_n);
+ CONSUME_REDS(env,data_bin);
return ret;
}
@@ -2884,7 +2923,7 @@ static EC_KEY* ec_key_new(ErlNifEnv* env, ERL_NIF_TERM curve_arg)
&& c_arity == 5
&& get_bn_from_bin(env, curve[3], &bn_order)
&& (curve[4] != atom_none && get_bn_from_bin(env, curve[4], &cofactor))) {
- //* {Field, Prime, Point, Order, CoFactor} = Curve */
+ /* {Field, Prime, Point, Order, CoFactor} = Curve */
int f_arity = -1;
const ERL_NIF_TERM* field;
@@ -3038,7 +3077,7 @@ static ERL_NIF_TERM bn2term(ErlNifEnv* env, const BIGNUM *bn)
dlen = BN_num_bytes(bn);
ptr = enif_make_new_binary(env, dlen, &ret);
BN_bn2bin(bn, ptr);
-
+ ERL_VALGRIND_MAKE_MEM_DEFINED(ptr, dlen);
return ret;
}
@@ -3061,39 +3100,10 @@ static ERL_NIF_TERM point2term(ErlNifEnv* env,
enif_release_binary(&bin);
return enif_make_badarg(env);
}
-
+ ERL_VALGRIND_MAKE_MEM_DEFINED(bin.data, bin.size);
return enif_make_binary(env, &bin);
}
-#endif
-
-static ERL_NIF_TERM ec_key_to_term_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{
-#if defined(HAVE_EC)
- struct nif_ec_key *obj;
- const EC_GROUP *group;
- const EC_POINT *public_key;
- const BIGNUM *priv_key = NULL;
- ERL_NIF_TERM pub_key = atom_undefined;
-
- if (!enif_get_resource(env, argv[0], res_type_ec_key, (void **)&obj))
- return enif_make_badarg(env);
-
- group = EC_KEY_get0_group(obj->key);
- public_key = EC_KEY_get0_public_key(obj->key);
- priv_key = EC_KEY_get0_private_key(obj->key);
- if (group) {
- if (public_key)
- pub_key = point2term(env, group, public_key, EC_KEY_get_conv_form(obj->key));
- }
-
- return enif_make_tuple2(env, pub_key, bn2term(env, priv_key));
-#else
- return atom_notsup;
-#endif
-}
-
-#if defined(HAVE_EC)
static int term2point(ErlNifEnv* env, ERL_NIF_TERM term,
EC_GROUP *group, EC_POINT **pptr)
{
@@ -3121,24 +3131,22 @@ static int term2point(ErlNifEnv* env, ERL_NIF_TERM term,
return ret;
}
-#endif
-static ERL_NIF_TERM term_to_ec_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+static int get_ec_key(ErlNifEnv* env,
+ ERL_NIF_TERM curve, ERL_NIF_TERM priv, ERL_NIF_TERM pub,
+ EC_KEY** res)
{
-#if defined(HAVE_EC)
- ERL_NIF_TERM ret;
EC_KEY *key = NULL;
BIGNUM *priv_key = NULL;
EC_POINT *pub_key = NULL;
- struct nif_ec_key *obj;
EC_GROUP *group = NULL;
- if (!(argv[1] == atom_undefined || get_bn_from_bin(env, argv[1], &priv_key))
- || !(argv[2] == atom_undefined || enif_is_binary(env, argv[2]))) {
+ if (!(priv == atom_undefined || get_bn_from_bin(env, priv, &priv_key))
+ || !(pub == atom_undefined || enif_is_binary(env, pub))) {
goto out_err;
}
- key = ec_key_new(env, argv[0]);
+ key = ec_key_new(env, curve);
if (!key) {
goto out_err;
@@ -3147,12 +3155,12 @@ static ERL_NIF_TERM term_to_ec_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T
if (!group)
group = EC_GROUP_dup(EC_KEY_get0_group(key));
- if (term2point(env, argv[2], group, &pub_key)) {
+ if (term2point(env, pub, group, &pub_key)) {
if (!EC_KEY_set_public_key(key, pub_key)) {
goto out_err;
}
}
- if (argv[1] != atom_undefined
+ if (priv != atom_undefined
&& !BN_is_zero(priv_key)) {
if (!EC_KEY_set_private_key(key, priv_key))
goto out_err;
@@ -3171,19 +3179,11 @@ static ERL_NIF_TERM term_to_ec_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T
}
}
- obj = enif_alloc_resource(res_type_ec_key, sizeof(struct nif_ec_key));
- if (!obj)
- goto out_err;
-
- obj->key = key;
- ret = enif_make_resource(env, obj);
- enif_release_resource(obj);
-
goto out;
out_err:
if (key) EC_KEY_free(key);
- ret = enif_make_badarg(env);
+ key = NULL;
out:
/* some OpenSSL structures are mem-dup'ed into the key,
@@ -3191,11 +3191,12 @@ out:
if (priv_key) BN_clear_free(priv_key);
if (pub_key) EC_POINT_free(pub_key);
if (group) EC_GROUP_free(group);
- return ret;
-#else
- return atom_notsup;
-#endif
+ if (!key)
+ return 0;
+ *res = key;
+ return 1;
}
+#endif /* HAVE_EC */
static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
@@ -3203,14 +3204,21 @@ static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM
EC_KEY *key = ec_key_new(env, argv[0]);
if (key && EC_KEY_generate_key(key)) {
- ERL_NIF_TERM term;
- struct nif_ec_key *obj = enif_alloc_resource(res_type_ec_key, sizeof(struct nif_ec_key));
- if (!obj)
- return atom_error;
- obj->key = key;
- term = enif_make_resource(env, obj);
- enif_release_resource(obj);
- return term;
+ const EC_GROUP *group;
+ const EC_POINT *public_key;
+ ERL_NIF_TERM priv_key;
+ ERL_NIF_TERM pub_key = atom_undefined;
+
+ group = EC_KEY_get0_group(key);
+ public_key = EC_KEY_get0_public_key(key);
+
+ if (group && public_key) {
+ pub_key = point2term(env, group, public_key,
+ EC_KEY_get_conv_form(key));
+ }
+ priv_key = bn2term(env, EC_KEY_get0_private_key(key));
+ EC_KEY_free(key);
+ return enif_make_tuple2(env, pub_key, priv_key);
}
else
return enif_make_badarg(env);
@@ -3219,21 +3227,13 @@ static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM
#endif
}
-#if defined(HAVE_EC)
-static void ec_key_dtor(ErlNifEnv* env, void* obj)
-{
- struct nif_ec_key *key = (struct nif_ec_key*) obj;
- EC_KEY_free(key->key);
-}
-#endif
-
static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Type, Data|{digest,Digest}, Key) */
+{/* (Type, Data|{digest,Digest}, Curve, Key) */
#if defined(HAVE_EC)
ErlNifBinary data_bin, ret_bin;
unsigned char hmacbuf[SHA_DIGEST_LENGTH];
unsigned int dsa_s_len;
- struct nif_ec_key *obj;
+ EC_KEY* key = NULL;
int i;
const ERL_NIF_TERM* tpl_terms;
int tpl_arity;
@@ -3248,30 +3248,32 @@ static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
return atom_notsup;
}
- if (!enif_get_resource(env, argv[2], res_type_ec_key, (void **)&obj))
- return enif_make_badarg(env);
+ if (!get_ec_key(env, argv[2], argv[3], atom_undefined, &key))
+ goto badarg;
if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
if (tpl_arity != 2 || tpl_terms[0] != atom_digest
|| !enif_inspect_binary(env, tpl_terms[1], &data_bin)
|| data_bin.size != digp->len) {
- return enif_make_badarg(env);
+ goto badarg;
}
digest = data_bin.data;
}
else {
if (!enif_inspect_binary(env,argv[1],&data_bin)) {
- return enif_make_badarg(env);
+ goto badarg;
}
digest = hmacbuf;
digp->funcp(data_bin.data, data_bin.size, digest);
}
- enif_alloc_binary(ECDSA_size(obj->key), &ret_bin);
+ enif_alloc_binary(ECDSA_size(key), &ret_bin);
i = ECDSA_sign(digp->NID_type, digest, digp->len,
- ret_bin.data, &dsa_s_len, obj->key);
+ ret_bin.data, &dsa_s_len, key);
+
+ EC_KEY_free(key);
if (i) {
if (dsa_s_len != ret_bin.size) {
enif_realloc_binary(&ret_bin, dsa_s_len);
@@ -3282,18 +3284,23 @@ static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
enif_release_binary(&ret_bin);
return atom_error;
}
+
+badarg:
+ if (key)
+ EC_KEY_free(key);
+ return enif_make_badarg(env);
#else
return atom_notsup;
#endif
}
static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Type, Data|{digest,Digest}, Signature, Key) */
+{/* (Type, Data|{digest,Digest}, Signature, Curve, Key) */
#if defined(HAVE_EC)
ErlNifBinary data_bin, sign_bin;
unsigned char hmacbuf[SHA512_LEN];
int i;
- struct nif_ec_key *obj;
+ EC_KEY* key = NULL;
const ERL_NIF_TERM type = argv[0];
const ERL_NIF_TERM* tpl_terms;
int tpl_arity;
@@ -3309,15 +3316,15 @@ static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER
}
if (!enif_inspect_binary(env, argv[2], &sign_bin)
- || !enif_get_resource(env, argv[3], res_type_ec_key, (void **)&obj))
- return enif_make_badarg(env);
+ || !get_ec_key(env, argv[3], atom_undefined, argv[4], &key))
+ goto badarg;
if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
if (tpl_arity != 2 || tpl_terms[0] != atom_digest
|| !enif_inspect_binary(env, tpl_terms[1], &data_bin)
|| data_bin.size != digp->len) {
- return enif_make_badarg(env);
+ goto badarg;
}
digest = data_bin.data;
}
@@ -3326,13 +3333,20 @@ static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER
digp->funcp(data_bin.data, data_bin.size, digest);
}
else {
- return enif_make_badarg(env);
+ goto badarg;
}
i = ECDSA_verify(digp->NID_type, digest, digp->len,
- sign_bin.data, sign_bin.size, obj->key);
+ sign_bin.data, sign_bin.size, key);
+
+ EC_KEY_free(key);
return (i==1 ? atom_true : atom_false);
+
+badarg:
+ if (key)
+ EC_KEY_free(key);
+ return enif_make_badarg(env);
#else
return atom_notsup;
#endif
@@ -3343,24 +3357,24 @@ static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER
(_OthersPublicKey, _MyEC_Point)
*/
static ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+/* (OtherPublicKey, Curve, My) */
{
#if defined(HAVE_EC)
ERL_NIF_TERM ret;
unsigned char *p;
- struct nif_ec_key *other_key;
+ EC_KEY* key = NULL;
int field_size = 0;
int i;
-
EC_GROUP *group;
const BIGNUM *priv_key;
EC_POINT *my_ecpoint;
EC_KEY *other_ecdh = NULL;
- if (!enif_get_resource(env, argv[1], res_type_ec_key, (void **)&other_key))
+ if (!get_ec_key(env, argv[1], argv[2], atom_undefined, &key))
return enif_make_badarg(env);
- group = EC_GROUP_dup(EC_KEY_get0_group(other_key->key));
- priv_key = EC_KEY_get0_private_key(other_key->key);
+ group = EC_GROUP_dup(EC_KEY_get0_group(key));
+ priv_key = EC_KEY_get0_private_key(key);
if (!term2point(env, argv[0], group, &my_ecpoint)) {
goto out_err;
@@ -3384,6 +3398,7 @@ out:
if (group) EC_GROUP_free(group);
if (my_ecpoint) EC_POINT_free(my_ecpoint);
if (other_ecdh) EC_KEY_free(other_ecdh);
+ if (key) EC_KEY_free(key);
return ret;
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 9e64c8e377..5bb2365109 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -208,7 +208,7 @@
</type>
<desc>
<p>Computes the shared secret from the private key and the other party's public key.
- See also <seealso marker="public_key:public_key#compute_key/2">public_key:compute_key/2</seealso>
+ See also <seealso marker="public_key:public_key#compute_key-2">public_key:compute_key/2</seealso>
</p>
</desc>
</func>
@@ -240,7 +240,7 @@
</type>
<desc>
<p>Generates public keys of type <c>Type</c>.
- See also <seealso marker="public_key:public_key#generate_key/1">public_key:generate_key/1</seealso>
+ See also <seealso marker="public_key:public_key#generate_key-1">public_key:generate_key/1</seealso>
</p>
</desc>
</func>
@@ -269,7 +269,7 @@
<desc>
<p>Initializes the context for streaming hash operations. <c>Type</c> determines
which digest to use. The returned context should be used as argument
- to <seealso marker="#hash_update/2">hash_update</seealso>.</p>
+ to <seealso marker="#hash_update-2">hash_update</seealso>.</p>
<p>May throw exception <c>notsup</c> in case the chosen <c>Type</c>
is not supported by the underlying OpenSSL implementation.</p>
</desc>
@@ -283,10 +283,10 @@
</type>
<desc>
<p>Updates the digest represented by <c>Context</c> using the given <c>Data</c>. <c>Context</c>
- must have been generated using <seealso marker="#hash_init/1">hash_init</seealso>
+ must have been generated using <seealso marker="#hash_init-1">hash_init</seealso>
or a previous call to this function. <c>Data</c> can be any length. <c>NewContext</c>
must be passed into the next call to <c>hash_update</c>
- or <seealso marker="#hash_final/1">hash_final</seealso>.</p>
+ or <seealso marker="#hash_final-1">hash_final</seealso>.</p>
</desc>
</func>
<func>
@@ -297,7 +297,7 @@
</type>
<desc>
<p>Finalizes the hash operation referenced by <c>Context</c> returned
- from a previous call to <seealso marker="#hash_update/2">hash_update</seealso>.
+ from a previous call to <seealso marker="#hash_update-2">hash_update</seealso>.
The size of <c>Digest</c> is determined by the type of hash
function used to generate it.</p>
</desc>
@@ -346,10 +346,10 @@
<desc>
<p>Updates the HMAC represented by <c>Context</c> using the given <c>Data</c>. <c>Context</c>
must have been generated using an HMAC init function (such as
- <seealso marker="#hmac_init/2">hmac_init</seealso>). <c>Data</c> can be any length. <c>NewContext</c>
+ <seealso marker="#hmac_init-2">hmac_init</seealso>). <c>Data</c> can be any length. <c>NewContext</c>
must be passed into the next call to <c>hmac_update</c>
- or to one of the functions <seealso marker="#hmac_final/1">hmac_final</seealso> and
- <seealso marker="#hmac_final_n/1">hmac_final_n</seealso>
+ or to one of the functions <seealso marker="#hmac_final-1">hmac_final</seealso> and
+ <seealso marker="#hmac_final_n-2">hmac_final_n</seealso>
</p>
</desc>
@@ -447,36 +447,36 @@
<v>PlainText = binary()</v>
</type>
<desc>
- <p>Decrypts the <c>ChipherText</c> (usually a session key encrypted with
- <seealso marker="#public_encrypt/3">public_encrypt/3</seealso>)
- using the <c>PrivateKey</c> and returns the
- message. The <c>Padding</c> is the padding mode that was
- used to encrypt the data,
- see <seealso marker="#public_encrypt/3">public_encrypt/3</seealso>.
- See also <seealso marker="public_key:public_key#decrypt_private/2">public_key:decrypt_private/[2,3]</seealso>
+ <p>Decrypts the <c>ChipherText</c>, encrypted with
+ <seealso marker="#public_encrypt-4">public_encrypt/4</seealso> (or equivalent function)
+ using the <c>PrivateKey</c>, and returns the
+ plaintext (message digest). This is a low level signature verification operation
+ used for instance by older versions of the SSL protocol.
+ See also <seealso marker="public_key:public_key#decrypt_private-2">public_key:decrypt_private/[2,3]</seealso>
</p>
</desc>
</func>
-
+
<func>
<name>private_encrypt(Type, PlainText, PrivateKey, Padding) -> ChipherText</name>
- <fsummary>Encrypts Msg using the private Key.</fsummary>
+ <fsummary>Encrypts PlainText using the private Key.</fsummary>
<type>
<v>Type = rsa</v>
<v>PlainText = binary()</v>
+ <d> The size of the <c>PlainText</c> must be less
+ than <c>byte_size(N)-11</c> if <c>rsa_pkcs1_padding</c> is
+ used, and <c>byte_size(N)</c> if <c>rsa_no_padding</c> is
+ used, where N is public modulus of the RSA key.</d>
<v>PrivateKey = rsa_private()</v>
<v>Padding = rsa_pkcs1_padding | rsa_no_padding</v>
<v>ChipherText = binary()</v>
</type>
<desc>
<p>Encrypts the <c>PlainText</c> using the <c>PrivateKey</c>
- and returns the cipher. The <c>Padding</c> decides what padding mode is used,
- <c>rsa_pkcs1_padding</c> is PKCS #1 v1.5 currently the most
- used mode.
- The size of the <c>Msg</c> must be less than <c>byte_size(N)-11</c> if
- <c>rsa_pkcs1_padding</c> is used, and <c>byte_size(N)</c> if <c>rsa_no_padding</c>
- is used, where N is public modulus of the RSA key.
- See also <seealso marker="public_key:public_key#encrypt_private/2">public_key:encrypt_private/[2,3]</seealso>
+ and returns the ciphertext. This is a low level signature operation
+ used for instance by older versions of the SSL protocol. See
+ also <seealso
+ marker="public_key:public_key#encrypt_private-2">public_key:encrypt_private/[2,3]</seealso>
</p>
</desc>
</func>
@@ -491,42 +491,35 @@
<v>PlainText = binary()</v>
</type>
<desc>
- <p>Decrypts the <c>ChipherText</c> (encrypted with
- <seealso marker="#private_encrypt/3">private_encrypt/3</seealso>)
- using the <c>PrivateKey</c> and returns the
- message. The <c>Padding</c> is the padding mode that was
- used to encrypt the data,
- see <seealso marker="#private_encrypt/3">private_encrypt/3</seealso>.
- See also <seealso marker="public_key:public_key#decrypt_public/2">public_key:decrypt_public/[2,3]</seealso>
+ <p>Decrypts the <c>ChipherText</c>, encrypted with
+ <seealso marker="#private_encrypt-4">private_encrypt/4</seealso>(or equivalent function)
+ using the <c>PrivateKey</c>, and returns the
+ plaintext (message digest). This is a low level signature verification operation
+ used for instance by older versions of the SSL protocol.
+ See also <seealso marker="public_key:public_key#decrypt_public-2">public_key:decrypt_public/[2,3]</seealso>
</p>
</desc>
</func>
<func>
<name>public_encrypt(Type, PlainText, PublicKey, Padding) -> ChipherText</name>
- <fsummary>Encrypts Msg using the public Key.</fsummary>
+ <fsummary>Encrypts PlainText using the public Key.</fsummary>
<type>
<v>Type = rsa</v>
<v>PlainText = binary()</v>
+ <d> The size of the <c>PlainText</c> must be less
+ than <c>byte_size(N)-11</c> if <c>rsa_pkcs1_padding</c> is
+ used, and <c>byte_size(N)</c> if <c>rsa_no_padding</c> is
+ used, where N is public modulus of the RSA key.</d>
<v>PublicKey = rsa_public()</v>
<v>Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding | rsa_no_padding</v>
<v>ChipherText = binary()</v>
</type>
<desc>
- <p>Encrypts the <c>PlainText</c> (usually a session key) using
- the <c>PublicKey</c> and returns the <c>CipherText</c>. The
- <c>Padding</c> decides what padding mode is used,
- <c>rsa_pkcs1_padding</c> is PKCS #1 v1.5 currently the most
- used mode and <c>rsa_pkcs1_oaep_padding</c> is EME-OAEP as
- defined in PKCS #1 v2.0 with SHA-1, MGF1 and an empty encoding
- parameter. This mode is recommended for all new
- applications. The size of the <c>Msg</c> must be less than
- <c>byte_size(N)-11</c> if <c>rsa_pkcs1_padding</c> is
- used, <c>byte_size(N)-41</c> if
- <c>rsa_pkcs1_oaep_padding</c> is used and
- <c>byte_size(N)</c> if <c>rsa_no_padding</c> is used, where N is public modulus of the RSA key.
- See also <seealso
- marker="public_key:public_key#encrypt_public/2">public_key:encrypt_public/[2,3]</seealso>
+ <p>Encrypts the <c>PlainText</c> (message digest) using the <c>PublicKey</c>
+ and returns the <c>CipherText</c>. This is a low level signature operation
+ used for instance by older versions of the SSL protocol. See also <seealso
+ marker="public_key:public_key#encrypt_public-2">public_key:encrypt_public/[2,3]</seealso>
</p>
</desc>
</func>
@@ -563,9 +556,9 @@
<type>
<v>Algorithm = rsa | dss | ecdsa </v>
<v>Msg = binary() | {digest,binary()}</v>
- <d>The msg is either the binary "plain text" data to be
- signed or it is the hashed value of "plain text" i.e. the
- digest.</d>
+ <d>The msg is either the binary "cleartext" data to be
+ signed or it is the hashed value of "cleartext" i.e. the
+ digest (plaintext).</d>
<v>DigestType = digest_type()</v>
<v>Key = rsa_private() | dss_private() | [ecdh_private(),ecdh_params()]</v>
</type>
@@ -573,7 +566,7 @@
<p>Creates a digital signature.</p>
<p>Algorithm <c>dss</c> can only be used together with digest type
<c>sha</c>.</p>
- See also <seealso marker="public_key:public_key#sign/3">public_key:sign/3</seealso>
+ See also <seealso marker="public_key:public_key#sign-3">public_key:sign/3</seealso>
</desc>
</func>
@@ -617,8 +610,8 @@
</type>
<desc>
<p>Initializes the state for use in RC4 stream encryption
- <seealso marker="#stream_encrypt/2">stream_encrypt</seealso> and
- <seealso marker="#stream_decrypt/2">stream_decrypt</seealso></p>
+ <seealso marker="#stream_encrypt-2">stream_encrypt</seealso> and
+ <seealso marker="#stream_decrypt-2">stream_decrypt</seealso></p>
</desc>
</func>
@@ -635,8 +628,8 @@
<p>Initializes the state for use in streaming AES encryption using Counter mode (CTR).
<c>Key</c> is the AES key and must be either 128, 192, or 256 bts long. <c>IVec</c> is
an arbitrary initializing vector of 128 bits (16 bytes). This state is for use with
- <seealso marker="#stream_encrypt/2">stream_encrypt</seealso> and
- <seealso marker="#stream_decrypt/2">stream_decrypt</seealso>.</p>
+ <seealso marker="#stream_encrypt-2">stream_encrypt</seealso> and
+ <seealso marker="#stream_decrypt-2">stream_decrypt</seealso>.</p>
</desc>
</func>
@@ -650,7 +643,7 @@
<desc>
<p>Encrypts <c>PlainText</c> according to the stream cipher <c>Type</c> specified in stream_init/3.
<c>Text</c> can be any number of bytes. The initial <c>State</c> is created using
- <seealso marker="#stream_init/2">stream_init</seealso>.
+ <seealso marker="#stream_init-2">stream_init</seealso>.
<c>NewState</c> must be passed into the next call to <c>stream_encrypt</c>.</p>
</desc>
</func>
@@ -665,7 +658,7 @@
<desc>
<p>Decrypts <c>CipherText</c> according to the stream cipher <c>Type</c> specified in stream_init/3.
<c>PlainText</c> can be any number of bytes. The initial <c>State</c> is created using
- <seealso marker="#stream_init/2">stream_init</seealso>.
+ <seealso marker="#stream_init-2">stream_init</seealso>.
<c>NewState</c> must be passed into the next call to <c>stream_encrypt</c>.</p>
</desc>
</func>
@@ -692,8 +685,8 @@
<type>
<v> Algorithm = rsa | dss | ecdsa </v>
<v>Msg = binary() | {digest,binary()}</v>
- <d>The msg is either the binary "plain text" data
- or it is the hashed value of "plain text" i.e. the digest.</d>
+ <d>The msg is either the binary "cleartext" data
+ or it is the hashed value of "cleartext" i.e. the digest (plaintext).</d>
<v>DigestType = digest_type()</v>
<v>Signature = binary()</v>
<v>Key = rsa_public() | dss_public() | [ecdh_public(),ecdh_params()]</v>
@@ -703,7 +696,7 @@
<p>Algorithm <c>dss</c> can only be used together with digest type
<c>sha</c>.</p>
- See also <seealso marker="public_key:public_key#sign/3">public_key:verify/3</seealso>
+ See also <seealso marker="public_key:public_key#verify-4">public_key:verify/4</seealso>
</desc>
</func>
diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml
index 64cb6d143a..6abe19eac5 100644
--- a/lib/crypto/doc/src/notes.xml
+++ b/lib/crypto/doc/src/notes.xml
@@ -30,6 +30,65 @@
</header>
<p>This document describes the changes made to the Crypto application.</p>
+<section><title>Crypto 3.0</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Integrate elliptic curve contribution from Andreas
+ Schultz </p>
+ <p>
+ In order to be able to support elliptic curve cipher
+ suites in SSL/TLS, additions to handle elliptic curve
+ infrastructure has been added to public_key and crypto.</p>
+ <p>
+ This also has resulted in a rewrite of the crypto API to
+ gain consistency and remove unnecessary overhead. All OTP
+ applications using crypto has been updated to use the new
+ API.</p>
+ <p>
+ Impact: Elliptic curve cryptography (ECC) offers
+ equivalent security with smaller key sizes than other
+ public key algorithms. Smaller key sizes result in
+ savings for power, memory, bandwidth, and computational
+ cost that make ECC especially attractive for constrained
+ environments.</p>
+ <p>
+ Own Id: OTP-11009</p>
+ </item>
+ <item>
+ <p>
+ Fixed a spelling mistake in crypto docs. Thanks to Klaus
+ Trainer</p>
+ <p>
+ Own Id: OTP-11058</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Known Bugs and Problems</title>
+ <list>
+ <item>
+ <p>
+ Make the crypto functions interruptible by chunking input
+ when it is very large and bumping reductions in the nifs.</p>
+ <p>
+ Not yet implemented for block_encrypt|decrypt/4</p>
+ <p>
+ Impact: Individual calls to crypto functions may take
+ longer time but over all system performance should
+ improve as crypto calls will not become throughput
+ bottlenecks.</p>
+ <p>
+ Own Id: OTP-11142</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Crypto 2.3</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/crypto/src/crypto.appup.src b/lib/crypto/src/crypto.appup.src
index b39ef734eb..5b4ce5acee 100644
--- a/lib/crypto/src/crypto.appup.src
+++ b/lib/crypto/src/crypto.appup.src
@@ -1,7 +1,8 @@
+%% -*- erlang -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -17,6 +18,11 @@
%% %CopyrightEnd%
%%
{"%VSN%",
- [],
- []
-}.
+ [
+ {<<"2\\.*">>, [{restart_application, crypto}]}
+ {<<"1\\.*">>, [{restart_application, crypto}]}
+ ],
+ [
+ {<<"2\\.*">>, [{restart_application, crypto}]}
+ {<<"1\\.*">>, [{restart_application, crypto}]}
+ ]}.
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index e042545094..8e8370f3b0 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -35,7 +35,6 @@
-export([private_encrypt/4, public_decrypt/4]).
-export([dh_generate_parameters/2, dh_check/1]). %% Testing see
-
%% DEPRECATED
%% Replaced by hash_*
-export([md4/1, md4_init/0, md4_update/2, md4_final/1]).
@@ -165,60 +164,8 @@
-export([info/0]).
-deprecated({info, 0, next_major_release}).
--define(FUNC_LIST, [hash, hash_init, hash_update, hash_final,
- hmac, hmac_init, hmac_update, hmac_final, hmac_final_n,
- %% deprecated
- md4, md4_init, md4_update, md4_final,
- md5, md5_init, md5_update, md5_final,
- sha, sha_init, sha_update, sha_final,
- md5_mac, md5_mac_96,
- sha_mac, sha_mac_96,
- %%
- block_encrypt, block_decrypt,
- %% deprecated
- des_cbc_encrypt, des_cbc_decrypt,
- des_cfb_encrypt, des_cfb_decrypt,
- des_ecb_encrypt, des_ecb_decrypt,
- des3_cbc_encrypt, des3_cbc_decrypt,
- des3_cfb_encrypt, des3_cfb_decrypt,
- aes_cfb_128_encrypt, aes_cfb_128_decrypt,
- rc2_cbc_encrypt, rc2_cbc_decrypt,
- rc2_40_cbc_encrypt, rc2_40_cbc_decrypt,
- aes_cbc_128_encrypt, aes_cbc_128_decrypt,
- aes_cbc_256_encrypt, aes_cbc_256_decrypt,
- blowfish_cbc_encrypt, blowfish_cbc_decrypt,
- blowfish_cfb64_encrypt, blowfish_cfb64_decrypt,
- blowfish_ecb_encrypt, blowfish_ecb_decrypt, blowfish_ofb64_encrypt,
- %%
- rand_bytes,
- strong_rand_bytes,
- rand_uniform,
- mod_pow,
- exor,
- %% deprecated
- mod_exp,strong_rand_mpint,erlint, mpint,
- %%
- sign, verify, generate_key, compute_key,
- %% deprecated
- dss_verify,dss_sign,
- rsa_verify,rsa_sign,
- rsa_public_encrypt,rsa_private_decrypt,
- rsa_private_encrypt,rsa_public_decrypt,
- dh_generate_key, dh_compute_key,
- %%
- stream_init, stream_encrypt, stream_decrypt,
- %% deprecated
- rc4_encrypt, rc4_set_key, rc4_encrypt_with_state,
- aes_ctr_encrypt, aes_ctr_decrypt,
- aes_ctr_stream_init, aes_ctr_stream_encrypt, aes_ctr_stream_decrypt,
- %%
- next_iv,
- %% deprecated
- aes_cbc_ivec,
- des_cbc_ivec, des_cfb_ivec,
- info,
- %%
- info_lib, supports]).
+%% This should correspond to the similar macro in crypto.c
+-define(MAX_BYTES_TO_NIF, 20000). %% Current value is: erlang:system_info(context_reductions) * 10
-type mpint() :: binary().
-type rsa_digest_type() :: 'md5' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'.
@@ -235,76 +182,27 @@
%%-type ec_curve() :: ec_named_curve() | ec_curve_spec().
%%-type ec_key() :: {Curve :: ec_curve(), PrivKey :: binary() | undefined, PubKey :: ec_point() | undefined}.
--define(nif_stub,nif_stub_error(?LINE)).
-
-on_load(on_load/0).
-
-define(CRYPTO_NIF_VSN,201).
-on_load() ->
- LibBaseName = "crypto",
- PrivDir = code:priv_dir(crypto),
- LibName = case erlang:system_info(build_type) of
- opt ->
- LibBaseName;
- Type ->
- LibTypeName = LibBaseName ++ "." ++ atom_to_list(Type),
- case (filelib:wildcard(
- filename:join(
- [PrivDir,
- "lib",
- LibTypeName ++ "*"])) /= []) orelse
- (filelib:wildcard(
- filename:join(
- [PrivDir,
- "lib",
- erlang:system_info(system_architecture),
- LibTypeName ++ "*"])) /= []) of
- true -> LibTypeName;
- false -> LibBaseName
- end
- end,
- Lib = filename:join([PrivDir, "lib", LibName]),
- Status = case erlang:load_nif(Lib, {?CRYPTO_NIF_VSN,Lib}) of
- ok -> ok;
- {error, {load_failed, _}}=Error1 ->
- ArchLibDir =
- filename:join([PrivDir, "lib",
- erlang:system_info(system_architecture)]),
- Candidate =
- filelib:wildcard(filename:join([ArchLibDir,LibName ++ "*" ])),
- case Candidate of
- [] -> Error1;
- _ ->
- ArchLib = filename:join([ArchLibDir, LibName]),
- erlang:load_nif(ArchLib, {?CRYPTO_NIF_VSN,ArchLib})
- end;
- Error1 -> Error1
- end,
- case Status of
- ok -> ok;
- {error, {E, Str}} ->
- error_logger:error_msg("Unable to load crypto library. Failed with error:~n\"~p, ~s\"~n"
- "OpenSSL might not be installed on this system.~n",[E,Str]),
- Status
- end.
-
+-define(nif_stub,nif_stub_error(?LINE)).
nif_stub_error(Line) ->
erlang:nif_error({nif_not_loaded,module,?MODULE,line,Line}).
+%%--------------------------------------------------------------------
+%%% API
+%%--------------------------------------------------------------------
+%% Crypto app version history:
+%% (no version): Driver implementation
+%% 2.0 : NIF implementation, requires OTP R14
+version() -> ?CRYPTO_VSN.
+
start() ->
application:start(crypto).
stop() ->
application:stop(crypto).
-info() ->
- ?FUNC_LIST.
-
-info_lib() -> ?nif_stub.
-
-algorithms() -> ?nif_stub.
-
supports()->
Algs = algorithms(),
PubKeyAlgs =
@@ -316,32 +214,20 @@ supports()->
end,
[{hashs, Algs -- [ec]},
{ciphers, [des_cbc, des_cfb, des3_cbc, des3_cbf, des_ede3, blowfish_cbc,
- blowfish_cfb64, blowfish_ofb64, blowfish_ecb, aes_cbc128, aes_cfb128, aes_cbc256, rc2_cbc, aes_ctr, rc4
+ blowfish_cfb64, blowfish_ofb64, blowfish_ecb, aes_cbc128, aes_cfb128,
+ aes_cbc256, rc2_cbc, aes_ctr, rc4
]},
PubKeyAlgs
].
-%% Crypto app version history:
-%% (no version): Driver implementation
-%% 2.0 : NIF implementation, requires OTP R14
-version() -> ?CRYPTO_VSN.
-
-%% Below Key and Data are binaries or IO-lists. IVec is a binary.
-%% Output is always a binary. Context is a binary.
-
-%%
-%% MESSAGE DIGESTS
-%%
+info_lib() -> ?nif_stub.
-spec hash(_, iodata()) -> binary().
-hash(md5, Data) -> md5(Data);
-hash(md4, Data) -> md4(Data);
-hash(sha, Data) -> sha(Data);
-hash(ripemd160, Data) -> ripemd160(Data);
-hash(sha224, Data) -> sha224(Data);
-hash(sha256, Data) -> sha256(Data);
-hash(sha384, Data) -> sha384(Data);
-hash(sha512, Data) -> sha512(Data).
+
+hash(Hash, Data0) ->
+ Data = iolist_to_binary(Data0),
+ MaxByts = max_bytes(),
+ hash(Hash, Data, erlang:byte_size(Data), MaxByts, initial).
-spec hash_init('md5'|'md4'|'ripemd160'|
'sha'|'sha224'|'sha256'|'sha384'|'sha512') -> any().
@@ -357,14 +243,10 @@ hash_init(sha512) -> {sha512, sha512_init()}.
-spec hash_update(_, iodata()) -> any().
-hash_update({md5,Context}, Data) -> {md5, md5_update(Context,Data)};
-hash_update({md4,Context}, Data) -> {md4, md4_update(Context,Data)};
-hash_update({sha,Context}, Data) -> {sha, sha_update(Context,Data)};
-hash_update({ripemd160,Context}, Data) -> {ripemd160, ripemd160_update(Context,Data)};
-hash_update({sha224,Context}, Data) -> {sha224, sha224_update(Context,Data)};
-hash_update({sha256,Context}, Data) -> {sha256, sha256_update(Context,Data)};
-hash_update({sha384,Context}, Data) -> {sha384, sha384_update(Context,Data)};
-hash_update({sha512,Context}, Data) -> {sha512, sha512_update(Context,Data)}.
+hash_update(State, Data0) ->
+ Data = iolist_to_binary(Data0),
+ MaxBytes = max_bytes(),
+ hash_update(State, Data, erlang:byte_size(Data), MaxBytes).
-spec hash_final(_) -> binary().
@@ -377,6 +259,458 @@ hash_final({sha256,Context}) -> sha256_final(Context);
hash_final({sha384,Context}) -> sha384_final(Context);
hash_final({sha512,Context}) -> sha512_final(Context).
+
+-spec hmac(_, iodata(), iodata()) -> binary().
+-spec hmac(_, iodata(), iodata(), integer()) -> binary().
+-spec hmac_init(atom(), iodata()) -> binary().
+-spec hmac_update(binary(), iodata()) -> binary().
+-spec hmac_final(binary()) -> binary().
+-spec hmac_final_n(binary(), integer()) -> binary().
+
+hmac(Type, Key, Data0) ->
+ Data = iolist_to_binary(Data0),
+ hmac(Type, Key, Data, undefined, erlang:byte_size(Data), max_bytes(), initial).
+hmac(Type, Key, Data0, MacSize) ->
+ Data = iolist_to_binary(Data0),
+ hmac(Type, Key, Data, MacSize, erlang:byte_size(Data), max_bytes(), initial).
+
+
+hmac_init(_Type, _Key) -> ?nif_stub.
+
+hmac_update(State, Data0) ->
+ Data = iolist_to_binary(Data0),
+ hmac_update(State, Data, erlang:byte_size(Data), max_bytes()).
+hmac_final(_Context) -> ? nif_stub.
+hmac_final_n(_Context, _HashLen) -> ? nif_stub.
+
+%% Ecrypt/decrypt %%%
+
+-spec block_encrypt(des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 | blowfish_cbc |
+ blowfish_cfb64 | aes_cbc128 | aes_cfb128 | aes_cbc256 | rc2_cbc,
+ Key::iodata(), Ivec::binary(), Data::iodata()) -> binary().
+
+block_encrypt(des_cbc, Key, Ivec, Data) ->
+ des_cbc_encrypt(Key, Ivec, Data);
+block_encrypt(des_cfb, Key, Ivec, Data) ->
+ des_cfb_encrypt(Key, Ivec, Data);
+block_encrypt(des3_cbc, [Key1, Key2, Key3], Ivec, Data) ->
+ des3_cbc_encrypt(Key1, Key2, Key3, Ivec, Data);
+block_encrypt(des3_cbf, [Key1, Key2, Key3], Ivec, Data) ->
+ des3_cfb_encrypt(Key1, Key2, Key3, Ivec, Data);
+block_encrypt(des_ede3, [Key1, Key2, Key3], Ivec, Data) ->
+ des_ede3_cbc_encrypt(Key1, Key2, Key3, Ivec, Data);
+block_encrypt(blowfish_cbc, Key, Ivec, Data) ->
+ blowfish_cbc_encrypt(Key, Ivec, Data);
+block_encrypt(blowfish_cfb64, Key, Ivec, Data) ->
+ blowfish_cfb64_encrypt(Key, Ivec, Data);
+block_encrypt(blowfish_ofb64, Key, Ivec, Data) ->
+ blowfish_ofb64_encrypt(Key, Ivec, Data);
+block_encrypt(aes_cbc128, Key, Ivec, Data) ->
+ aes_cbc_128_encrypt(Key, Ivec, Data);
+block_encrypt(aes_cbc256, Key, Ivec, Data) ->
+ aes_cbc_256_encrypt(Key, Ivec, Data);
+block_encrypt(aes_cfb128, Key, Ivec, Data) ->
+ aes_cfb_128_encrypt(Key, Ivec, Data);
+block_encrypt(rc2_cbc, Key, Ivec, Data) ->
+ rc2_cbc_encrypt(Key, Ivec, Data).
+
+-spec block_decrypt(des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 | blowfish_cbc |
+ blowfish_cfb64 | blowfish_ofb64 | aes_cbc128 | aes_cbc256 | aes_cfb128 | rc2_cbc,
+ Key::iodata(), Ivec::binary(), Data::iodata()) -> binary().
+
+block_decrypt(des_cbc, Key, Ivec, Data) ->
+ des_cbc_decrypt(Key, Ivec, Data);
+block_decrypt(des_cfb, Key, Ivec, Data) ->
+ des_cfb_decrypt(Key, Ivec, Data);
+block_decrypt(des3_cbc, [Key1, Key2, Key3], Ivec, Data) ->
+ des3_cbc_decrypt(Key1, Key2, Key3, Ivec, Data);
+block_decrypt(des3_cbf, [Key1, Key2, Key3], Ivec, Data) ->
+ des3_cfb_decrypt(Key1, Key2, Key3, Ivec, Data);
+block_decrypt(des_ede3, [Key1, Key2, Key3], Ivec, Data) ->
+ des_ede3_cbc_decrypt(Key1, Key2, Key3, Ivec, Data);
+block_decrypt(blowfish_cbc, Key, Ivec, Data) ->
+ blowfish_cbc_decrypt(Key, Ivec, Data);
+block_decrypt(blowfish_cfb64, Key, Ivec, Data) ->
+ blowfish_cfb64_decrypt(Key, Ivec, Data);
+block_decrypt(blowfish_ofb64, Key, Ivec, Data) ->
+ blowfish_ofb64_decrypt(Key, Ivec, Data);
+block_decrypt(aes_cbc128, Key, Ivec, Data) ->
+ aes_cbc_128_decrypt(Key, Ivec, Data);
+block_decrypt(aes_cbc256, Key, Ivec, Data) ->
+ aes_cbc_256_decrypt(Key, Ivec, Data);
+block_decrypt(aes_cfb128, Key, Ivec, Data) ->
+ aes_cfb_128_decrypt(Key, Ivec, Data);
+block_decrypt(rc2_cbc, Key, Ivec, Data) ->
+ rc2_cbc_decrypt(Key, Ivec, Data).
+
+-spec block_encrypt(des_ecb | blowfish_ecb, Key::iodata(), Data::iodata()) -> binary().
+
+block_encrypt(des_ecb, Key, Data) ->
+ des_ecb_encrypt(Key, Data);
+block_encrypt(blowfish_ecb, Key, Data) ->
+ blowfish_ecb_encrypt(Key, Data).
+
+-spec block_decrypt(des_ecb | blowfish_ecb, Key::iodata(), Data::iodata()) -> binary().
+
+block_decrypt(des_ecb, Key, Data) ->
+ des_ecb_decrypt(Key, Data);
+block_decrypt(blowfish_ecb, Key, Data) ->
+ blowfish_ecb_decrypt(Key, Data).
+
+-spec next_iv(des_cbc | des3_cbc | aes_cbc, Data::iodata()) -> binary().
+
+next_iv(des_cbc, Data) ->
+ des_cbc_ivec(Data);
+next_iv(des3_cbc, Data) ->
+ des_cbc_ivec(Data);
+next_iv(aes_cbc, Data) ->
+ aes_cbc_ivec(Data).
+
+-spec next_iv(des_cfb, Data::iodata(), Ivec::binary()) -> binary().
+
+next_iv(des_cfb, Data, Ivec) ->
+ des_cfb_ivec(Ivec, Data);
+next_iv(Type, Data, _Ivec) ->
+ next_iv(Type, Data).
+
+stream_init(aes_ctr, Key, Ivec) ->
+ {aes_ctr, aes_ctr_stream_init(Key, Ivec)}.
+stream_init(rc4, Key) ->
+ {rc4, rc4_set_key(Key)}.
+
+stream_encrypt(State, Data0) ->
+ Data = iolist_to_binary(Data0),
+ MaxByts = max_bytes(),
+ stream_crypt(fun do_stream_encrypt/2, State, Data, erlang:byte_size(Data), MaxByts, []).
+
+stream_decrypt(State, Data0) ->
+ Data = iolist_to_binary(Data0),
+ MaxByts = max_bytes(),
+ stream_crypt(fun do_stream_decrypt/2, State, Data, erlang:byte_size(Data), MaxByts, []).
+
+%%
+%% RAND - pseudo random numbers using RN_ functions in crypto lib
+%%
+-spec rand_bytes(non_neg_integer()) -> binary().
+-spec strong_rand_bytes(non_neg_integer()) -> binary().
+-spec rand_uniform(crypto_integer(), crypto_integer()) ->
+ crypto_integer().
+
+rand_bytes(_Bytes) -> ?nif_stub.
+
+strong_rand_bytes(Bytes) ->
+ case strong_rand_bytes_nif(Bytes) of
+ false -> erlang:error(low_entropy);
+ Bin -> Bin
+ end.
+strong_rand_bytes_nif(_Bytes) -> ?nif_stub.
+
+rand_bytes(_Bytes, _Topmask, _Bottommask) -> ?nif_stub.
+
+
+rand_uniform(From,To) when is_binary(From), is_binary(To) ->
+ case rand_uniform_nif(From,To) of
+ <<Len:32/integer, MSB, Rest/binary>> when MSB > 127 ->
+ <<(Len + 1):32/integer, 0, MSB, Rest/binary>>;
+ Whatever ->
+ Whatever
+ end;
+rand_uniform(From,To) when is_integer(From),is_integer(To) ->
+ if From < 0 ->
+ rand_uniform_pos(0, To - From) + From;
+ true ->
+ rand_uniform_pos(From, To)
+ end.
+
+rand_uniform_pos(From,To) when From < To ->
+ BinFrom = mpint(From),
+ BinTo = mpint(To),
+ case rand_uniform(BinFrom, BinTo) of
+ Result when is_binary(Result) ->
+ erlint(Result);
+ Other ->
+ Other
+ end;
+rand_uniform_pos(_,_) ->
+ error(badarg).
+
+rand_uniform_nif(_From,_To) -> ?nif_stub.
+
+
+-spec mod_pow(binary()|integer(), binary()|integer(), binary()|integer()) -> binary() | error.
+mod_pow(Base, Exponent, Prime) ->
+ case mod_exp_nif(ensure_int_as_bin(Base), ensure_int_as_bin(Exponent), ensure_int_as_bin(Prime), 0) of
+ <<0>> -> error;
+ R -> R
+ end.
+verify(dss, none, Data, Signature, Key) when is_binary(Data) ->
+ verify(dss, sha, {digest, Data}, Signature, Key);
+verify(Alg, Type, Data, Signature, Key) when is_binary(Data) ->
+ verify(Alg, Type, {digest, hash(Type, Data)}, Signature, Key);
+verify(dss, Type, Data, Signature, Key) ->
+ dss_verify_nif(Type, Data, Signature, map_ensure_int_as_bin(Key));
+verify(rsa, Type, DataOrDigest, Signature, Key) ->
+ case rsa_verify_nif(Type, DataOrDigest, Signature, map_ensure_int_as_bin(Key)) of
+ notsup -> erlang:error(notsup);
+ Bool -> Bool
+ end;
+verify(ecdsa, Type, DataOrDigest, Signature, [Key, Curve]) ->
+ case ecdsa_verify_nif(Type, DataOrDigest, Signature, nif_curve_params(Curve), ensure_int_as_bin(Key)) of
+ notsup -> erlang:error(notsup);
+ Bool -> Bool
+ end.
+sign(dss, none, Data, Key) when is_binary(Data) ->
+ sign(dss, sha, {digest, Data}, Key);
+sign(Alg, Type, Data, Key) when is_binary(Data) ->
+ sign(Alg, Type, {digest, hash(Type, Data)}, Key);
+sign(rsa, Type, DataOrDigest, Key) ->
+ case rsa_sign_nif(Type, DataOrDigest, map_ensure_int_as_bin(Key)) of
+ error -> erlang:error(badkey, [Type,DataOrDigest,Key]);
+ Sign -> Sign
+ end;
+sign(dss, Type, DataOrDigest, Key) ->
+ case dss_sign_nif(Type, DataOrDigest, map_ensure_int_as_bin(Key)) of
+ error -> erlang:error(badkey, [DataOrDigest, Key]);
+ Sign -> Sign
+ end;
+sign(ecdsa, Type, DataOrDigest, [Key, Curve]) ->
+ case ecdsa_sign_nif(Type, DataOrDigest, nif_curve_params(Curve), ensure_int_as_bin(Key)) of
+ error -> erlang:error(badkey, [Type,DataOrDigest,Key]);
+ Sign -> Sign
+ end.
+
+-spec public_encrypt(rsa, binary(), [binary()], rsa_padding()) ->
+ binary().
+-spec public_decrypt(rsa, binary(), [integer() | binary()], rsa_padding()) ->
+ binary().
+-spec private_encrypt(rsa, binary(), [integer() | binary()], rsa_padding()) ->
+ binary().
+-spec private_decrypt(rsa, binary(), [integer() | binary()], rsa_padding()) ->
+ binary().
+
+public_encrypt(rsa, BinMesg, Key, Padding) ->
+ case rsa_public_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, true) of
+ error ->
+ erlang:error(encrypt_failed, [BinMesg,Key, Padding]);
+ Sign -> Sign
+ end.
+
+%% Binary, Key = [E,N,D]
+private_decrypt(rsa, BinMesg, Key, Padding) ->
+ case rsa_private_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, false) of
+ error ->
+ erlang:error(decrypt_failed, [BinMesg,Key, Padding]);
+ Sign -> Sign
+ end.
+
+
+%% Binary, Key = [E,N,D]
+private_encrypt(rsa, BinMesg, Key, Padding) ->
+ case rsa_private_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, true) of
+ error ->
+ erlang:error(encrypt_failed, [BinMesg,Key, Padding]);
+ Sign -> Sign
+ end.
+
+%% Binary, Key = [E,N]
+public_decrypt(rsa, BinMesg, Key, Padding) ->
+ case rsa_public_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, false) of
+ error ->
+ erlang:error(decrypt_failed, [BinMesg,Key, Padding]);
+ Sign -> Sign
+ end.
+
+%%
+%% XOR - xor to iolists and return a binary
+%% NB doesn't check that they are the same size, just concatenates
+%% them and sends them to the driver
+%%
+-spec exor(iodata(), iodata()) -> binary().
+
+exor(Bin1, Bin2) ->
+ Data1 = iolist_to_binary(Bin1),
+ Data2 = iolist_to_binary(Bin2),
+ MaxBytes = max_bytes(),
+ exor(Data1, Data2, erlang:byte_size(Data1), MaxBytes, []).
+
+generate_key(Type, Params) ->
+ generate_key(Type, Params, undefined).
+
+generate_key(dh, DHParameters, PrivateKey) ->
+ dh_generate_key_nif(ensure_int_as_bin(PrivateKey),
+ map_ensure_int_as_bin(DHParameters), 0);
+
+generate_key(srp, {host, [Verifier, Generator, Prime, Version]}, PrivArg)
+ when is_binary(Verifier), is_binary(Generator), is_binary(Prime), is_atom(Version) ->
+ Private = case PrivArg of
+ undefined -> random_bytes(32);
+ _ -> ensure_int_as_bin(PrivArg)
+ end,
+ host_srp_gen_key(Private, Verifier, Generator, Prime, Version);
+
+generate_key(srp, {user, [Generator, Prime, Version]}, PrivateArg)
+ when is_binary(Generator), is_binary(Prime), is_atom(Version) ->
+ Private = case PrivateArg of
+ undefined -> random_bytes(32);
+ _ -> PrivateArg
+ end,
+ user_srp_gen_key(Private, Generator, Prime);
+
+generate_key(ecdh, Curve, undefined) ->
+ ec_key_generate(Curve).
+
+
+compute_key(dh, OthersPublicKey, MyPrivateKey, DHParameters) ->
+ case dh_compute_key_nif(ensure_int_as_bin(OthersPublicKey),
+ ensure_int_as_bin(MyPrivateKey),
+ map_ensure_int_as_bin(DHParameters)) of
+ error -> erlang:error(computation_failed,
+ [OthersPublicKey,MyPrivateKey,DHParameters]);
+ Ret -> Ret
+ end;
+
+compute_key(srp, HostPublic, {UserPublic, UserPrivate},
+ {user, [DerivedKey, Prime, Generator, Version | ScramblerArg]}) when
+ is_binary(Prime),
+ is_binary(Generator),
+ is_atom(Version) ->
+ HostPubBin = ensure_int_as_bin(HostPublic),
+ Multiplier = srp_multiplier(Version, Generator, Prime),
+ Scrambler = case ScramblerArg of
+ [] -> srp_scrambler(Version, ensure_int_as_bin(UserPublic),
+ HostPubBin, Prime);
+ [S] -> S
+ end,
+ srp_user_secret_nif(ensure_int_as_bin(UserPrivate), Scrambler, HostPubBin,
+ Multiplier, Generator, DerivedKey, Prime);
+
+compute_key(srp, UserPublic, {HostPublic, HostPrivate},
+ {host,[Verifier, Prime, Version | ScramblerArg]}) when
+ is_binary(Verifier),
+ is_binary(Prime),
+ is_atom(Version) ->
+ UserPubBin = ensure_int_as_bin(UserPublic),
+ Scrambler = case ScramblerArg of
+ [] -> srp_scrambler(Version, UserPubBin, ensure_int_as_bin(HostPublic), Prime);
+ [S] -> S
+ end,
+ srp_host_secret_nif(Verifier, ensure_int_as_bin(HostPrivate), Scrambler,
+ UserPubBin, Prime);
+
+compute_key(ecdh, Others, My, Curve) ->
+ ecdh_compute_key_nif(ensure_int_as_bin(Others),
+ nif_curve_params(Curve),
+ ensure_int_as_bin(My)).
+
+
+random_bytes(N) ->
+ try strong_rand_bytes(N) of
+ RandBytes ->
+ RandBytes
+ catch
+ error:low_entropy ->
+ rand_bytes(N)
+ end.
+
+%%--------------------------------------------------------------------
+%%% On load
+%%--------------------------------------------------------------------
+
+on_load() ->
+ LibBaseName = "crypto",
+ PrivDir = code:priv_dir(crypto),
+ LibName = case erlang:system_info(build_type) of
+ opt ->
+ LibBaseName;
+ Type ->
+ LibTypeName = LibBaseName ++ "." ++ atom_to_list(Type),
+ case (filelib:wildcard(
+ filename:join(
+ [PrivDir,
+ "lib",
+ LibTypeName ++ "*"])) /= []) orelse
+ (filelib:wildcard(
+ filename:join(
+ [PrivDir,
+ "lib",
+ erlang:system_info(system_architecture),
+ LibTypeName ++ "*"])) /= []) of
+ true -> LibTypeName;
+ false -> LibBaseName
+ end
+ end,
+ Lib = filename:join([PrivDir, "lib", LibName]),
+ Status = case erlang:load_nif(Lib, {?CRYPTO_NIF_VSN,Lib}) of
+ ok -> ok;
+ {error, {load_failed, _}}=Error1 ->
+ ArchLibDir =
+ filename:join([PrivDir, "lib",
+ erlang:system_info(system_architecture)]),
+ Candidate =
+ filelib:wildcard(filename:join([ArchLibDir,LibName ++ "*" ])),
+ case Candidate of
+ [] -> Error1;
+ _ ->
+ ArchLib = filename:join([ArchLibDir, LibName]),
+ erlang:load_nif(ArchLib, {?CRYPTO_NIF_VSN,ArchLib})
+ end;
+ Error1 -> Error1
+ end,
+ case Status of
+ ok -> ok;
+ {error, {E, Str}} ->
+ error_logger:error_msg("Unable to load crypto library. Failed with error:~n\"~p, ~s\"~n"
+ "OpenSSL might not be installed on this system.~n",[E,Str]),
+ Status
+ end.
+%%--------------------------------------------------------------------
+%%% Internal functions (some internal API functions are part of the deprecated API)
+%%--------------------------------------------------------------------
+max_bytes() ->
+ ?MAX_BYTES_TO_NIF.
+
+%% HASH --------------------------------------------------------------------
+hash(Hash, Data, Size, Max, initial) when Size =< Max ->
+ do_hash(Hash, Data);
+hash(State0, Data, Size, Max, continue) when Size =< Max ->
+ State = do_hash_update(State0, Data),
+ hash_final(State);
+hash(Hash, Data, _Size, Max, initial) ->
+ <<Increment:Max/binary, Rest/binary>> = Data,
+ State0 = hash_init(Hash),
+ State = do_hash_update(State0, Increment),
+ hash(State, Rest, erlang:byte_size(Rest), max_bytes(), continue);
+hash(State0, Data, _Size, MaxByts, continue) ->
+ <<Increment:MaxByts/binary, Rest/binary>> = Data,
+ State = do_hash_update(State0, Increment),
+ hash(State, Rest, erlang:byte_size(Rest), max_bytes(), continue).
+
+do_hash(md5, Data) -> md5(Data);
+do_hash(md4, Data) -> md4(Data);
+do_hash(sha, Data) -> sha(Data);
+do_hash(ripemd160, Data) -> ripemd160(Data);
+do_hash(sha224, Data) -> sha224(Data);
+do_hash(sha256, Data) -> sha256(Data);
+do_hash(sha384, Data) -> sha384(Data);
+do_hash(sha512, Data) -> sha512(Data).
+
+hash_update(State, Data, Size, MaxBytes) when Size =< MaxBytes ->
+ do_hash_update(State, Data);
+hash_update(State0, Data, _, MaxBytes) ->
+ <<Increment:MaxBytes/binary, Rest/binary>> = Data,
+ State = do_hash_update(State0, Increment),
+ hash_update(State, Rest, erlang:byte_size(Rest), MaxBytes).
+
+do_hash_update({md5,Context}, Data) -> {md5, md5_update(Context,Data)};
+do_hash_update({md4,Context}, Data) -> {md4, md4_update(Context,Data)};
+do_hash_update({sha,Context}, Data) -> {sha, sha_update(Context,Data)};
+do_hash_update({ripemd160,Context}, Data) -> {ripemd160, ripemd160_update(Context,Data)};
+do_hash_update({sha224,Context}, Data) -> {sha224, sha224_update(Context,Data)};
+do_hash_update({sha256,Context}, Data) -> {sha256, sha256_update(Context,Data)};
+do_hash_update({sha384,Context}, Data) -> {sha384, sha384_update(Context,Data)};
+do_hash_update({sha512,Context}, Data) -> {sha512, sha512_update(Context,Data)}.
+
+
%%
%% MD5
%%
@@ -567,40 +901,56 @@ sha512_init_nif() -> ?nif_stub.
sha512_update_nif(_Context, _Data) -> ?nif_stub.
sha512_final_nif(_Context) -> ?nif_stub.
-%%
-%% MESSAGE AUTHENTICATION CODES
-%%
-
-%%
-%% HMAC (multiple hash options)
-%%
+%% HMAC --------------------------------------------------------------------
--spec hmac(_, iodata(), iodata()) -> binary().
--spec hmac(_, iodata(), iodata(), integer()) -> binary().
--spec hmac_init(atom(), iodata()) -> binary().
--spec hmac_update(binary(), iodata()) -> binary().
--spec hmac_final(binary()) -> binary().
--spec hmac_final_n(binary(), integer()) -> binary().
-
-hmac(md5, Key, Data) -> md5_mac(Key, Data);
-hmac(sha, Key, Data) -> sha_mac(Key, Data);
-hmac(sha224, Key, Data) -> sha224_mac(Key, Data);
-hmac(sha256, Key, Data) -> sha256_mac(Key, Data);
-hmac(sha384, Key, Data) -> sha384_mac(Key, Data);
-hmac(sha512, Key, Data) -> sha512_mac(Key, Data).
-
-hmac(md5, Key, Data, Size) -> md5_mac_n(Key, Data, Size);
-hmac(sha, Key, Data, Size) -> sha_mac_n(Key, Data, Size);
-hmac(sha224, Key, Data, Size) -> sha224_mac(Key, Data, Size);
-hmac(sha256, Key, Data, Size) -> sha256_mac(Key, Data, Size);
-hmac(sha384, Key, Data, Size) -> sha384_mac(Key, Data, Size);
-hmac(sha512, Key, Data, Size) -> sha512_mac(Key, Data, Size).
+hmac(Type, Key, Data, MacSize, Size, MaxBytes, initial) when Size =< MaxBytes ->
+ case MacSize of
+ undefined ->
+ do_hmac(Type, Key, Data);
+ _ ->
+ do_hmac(Type, Key, Data, MacSize)
+ end;
+hmac(Type, Key, Data, MacSize, _, MaxBytes, initial) ->
+ <<Increment:MaxBytes/binary, Rest/binary>> = Data,
+ State0 = hmac_init(Type, Key),
+ State = hmac_update(State0, Increment),
+ hmac(State, Rest, MacSize, erlang:byte_size(Rest), max_bytes(), continue).
+hmac(State0, Data, MacSize, Size, MaxBytes, continue) when Size =< MaxBytes ->
+ State = hmac_update(State0, Data),
+ case MacSize of
+ undefined ->
+ hmac_final(State);
+ _ ->
+ hmac_final_n(State, MacSize)
+ end;
+hmac(State0, Data, MacSize, _Size, MaxBytes, continue) ->
+ <<Increment:MaxBytes/binary, Rest/binary>> = Data,
+ State = hmac_update(State0, Increment),
+ hmac(State, Rest, MacSize, erlang:byte_size(Rest), max_bytes(), continue).
+
+hmac_update(State, Data, Size, MaxBytes) when Size =< MaxBytes ->
+ do_hmac_update(State, Data);
+hmac_update(State0, Data, _, MaxBytes) ->
+ <<Increment:MaxBytes/binary, Rest/binary>> = Data,
+ State = do_hmac_update(State0, Increment),
+ hmac_update(State, Rest, erlang:byte_size(Rest), MaxBytes).
+
+do_hmac(md5, Key, Data) -> md5_mac(Key, Data);
+do_hmac(sha, Key, Data) -> sha_mac(Key, Data);
+do_hmac(sha224, Key, Data) -> sha224_mac(Key, Data);
+do_hmac(sha256, Key, Data) -> sha256_mac(Key, Data);
+do_hmac(sha384, Key, Data) -> sha384_mac(Key, Data);
+do_hmac(sha512, Key, Data) -> sha512_mac(Key, Data).
+
+do_hmac(md5, Key, Data, Size) -> md5_mac_n(Key, Data, Size);
+do_hmac(sha, Key, Data, Size) -> sha_mac_n(Key, Data, Size);
+do_hmac(sha224, Key, Data, Size) -> sha224_mac(Key, Data, Size);
+do_hmac(sha256, Key, Data, Size) -> sha256_mac(Key, Data, Size);
+do_hmac(sha384, Key, Data, Size) -> sha384_mac(Key, Data, Size);
+do_hmac(sha512, Key, Data, Size) -> sha512_mac(Key, Data, Size).
+
+do_hmac_update(_Context, _Data) -> ? nif_stub.
-hmac_init(_Type, _Key) -> ?nif_stub.
-hmac_update(_Context, _Data) -> ? nif_stub.
-hmac_final(_Context) -> ? nif_stub.
-hmac_final_n(_Context, _HashLen) -> ? nif_stub.
-
%%
%% MD5_MAC
%%
@@ -696,172 +1046,7 @@ sha512_mac(Key, Data, MacSz) ->
sha512_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub.
-
-%% Ecrypt/decrypt %%%
-
--spec block_encrypt(des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 | blowfish_cbc |
- blowfish_cfb64 | aes_cbc128 | aes_cfb128 | aes_cbc256 | rc2_cbc,
- Key::iodata(), Ivec::binary(), Data::iodata()) -> binary().
-
-block_encrypt(des_cbc, Key, Ivec, Data) ->
- des_cbc_encrypt(Key, Ivec, Data);
-block_encrypt(des_cfb, Key, Ivec, Data) ->
- des_cfb_encrypt(Key, Ivec, Data);
-block_encrypt(des3_cbc, [Key1, Key2, Key3], Ivec, Data) ->
- des3_cbc_encrypt(Key1, Key2, Key3, Ivec, Data);
-block_encrypt(des3_cbf, [Key1, Key2, Key3], Ivec, Data) ->
- des3_cfb_encrypt(Key1, Key2, Key3, Ivec, Data);
-block_encrypt(des_ede3, [Key1, Key2, Key3], Ivec, Data) ->
- des_ede3_cbc_encrypt(Key1, Key2, Key3, Ivec, Data);
-block_encrypt(blowfish_cbc, Key, Ivec, Data) ->
- blowfish_cbc_encrypt(Key, Ivec, Data);
-block_encrypt(blowfish_cfb64, Key, Ivec, Data) ->
- blowfish_cfb64_encrypt(Key, Ivec, Data);
-block_encrypt(blowfish_ofb64, Key, Ivec, Data) ->
- blowfish_ofb64_encrypt(Key, Ivec, Data);
-block_encrypt(aes_cbc128, Key, Ivec, Data) ->
- aes_cbc_128_encrypt(Key, Ivec, Data);
-block_encrypt(aes_cbc256, Key, Ivec, Data) ->
- aes_cbc_256_encrypt(Key, Ivec, Data);
-block_encrypt(aes_cfb128, Key, Ivec, Data) ->
- aes_cfb_128_encrypt(Key, Ivec, Data);
-block_encrypt(rc2_cbc, Key, Ivec, Data) ->
- rc2_cbc_encrypt(Key, Ivec, Data).
-
--spec block_decrypt(des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 | blowfish_cbc |
- blowfish_cfb64 | blowfish_ofb64 | aes_cbc128 | aes_cbc256 | aes_cfb128 | rc2_cbc,
- Key::iodata(), Ivec::binary(), Data::iodata()) -> binary().
-
-block_decrypt(des_cbc, Key, Ivec, Data) ->
- des_cbc_decrypt(Key, Ivec, Data);
-block_decrypt(des_cfb, Key, Ivec, Data) ->
- des_cfb_decrypt(Key, Ivec, Data);
-block_decrypt(des3_cbc, [Key1, Key2, Key3], Ivec, Data) ->
- des3_cbc_decrypt(Key1, Key2, Key3, Ivec, Data);
-block_decrypt(des3_cbf, [Key1, Key2, Key3], Ivec, Data) ->
- des3_cfb_decrypt(Key1, Key2, Key3, Ivec, Data);
-block_decrypt(des_ede3, [Key1, Key2, Key3], Ivec, Data) ->
- des_ede3_cbc_decrypt(Key1, Key2, Key3, Ivec, Data);
-block_decrypt(blowfish_cbc, Key, Ivec, Data) ->
- blowfish_cbc_decrypt(Key, Ivec, Data);
-block_decrypt(blowfish_cfb64, Key, Ivec, Data) ->
- blowfish_cfb64_decrypt(Key, Ivec, Data);
-block_decrypt(blowfish_ofb64, Key, Ivec, Data) ->
- blowfish_ofb64_decrypt(Key, Ivec, Data);
-block_decrypt(aes_cbc128, Key, Ivec, Data) ->
- aes_cbc_128_decrypt(Key, Ivec, Data);
-block_decrypt(aes_cbc256, Key, Ivec, Data) ->
- aes_cbc_256_decrypt(Key, Ivec, Data);
-block_decrypt(aes_cfb128, Key, Ivec, Data) ->
- aes_cfb_128_decrypt(Key, Ivec, Data);
-block_decrypt(rc2_cbc, Key, Ivec, Data) ->
- rc2_cbc_decrypt(Key, Ivec, Data).
-
--spec block_encrypt(des_ecb | blowfish_ecb, Key::iodata(), Data::iodata()) -> binary().
-
-block_encrypt(des_ecb, Key, Data) ->
- des_ecb_encrypt(Key, Data);
-block_encrypt(blowfish_ecb, Key, Data) ->
- blowfish_ecb_encrypt(Key, Data).
-
--spec block_decrypt(des_ecb | blowfish_ecb, Key::iodata(), Data::iodata()) -> binary().
-
-block_decrypt(des_ecb, Key, Data) ->
- des_ecb_decrypt(Key, Data);
-block_decrypt(blowfish_ecb, Key, Data) ->
- blowfish_ecb_decrypt(Key, Data).
-
--spec next_iv(des_cbc | des3_cbc | aes_cbc, Data::iodata()) -> binary().
-
-next_iv(des_cbc, Data) ->
- des_cbc_ivec(Data);
-next_iv(des3_cbc, Data) ->
- des_cbc_ivec(Data);
-next_iv(aes_cbc, Data) ->
- aes_cbc_ivec(Data).
-
--spec next_iv(des_cfb, Data::iodata(), Ivec::binary()) -> binary().
-
-next_iv(des_cfb, Data, Ivec) ->
- des_cfb_ivec(Ivec, Data);
-next_iv(Type, Data, _Ivec) ->
- next_iv(Type, Data).
-
-stream_init(aes_ctr, Key, Ivec) ->
- {aes_ctr, aes_ctr_stream_init(Key, Ivec)}.
-stream_init(rc4, Key) ->
- {rc4, rc4_set_key(Key)}.
-stream_encrypt({aes_ctr, State0}, Data) ->
- {State, Cipher} = aes_ctr_stream_encrypt(State0, Data),
- {{aes_ctr, State}, Cipher};
-stream_encrypt({rc4, State0}, Data) ->
- {State, Cipher} = rc4_encrypt_with_state(State0, Data),
- {{rc4, State}, Cipher}.
-stream_decrypt({aes_ctr, State0}, Data) ->
- {State, Text} = aes_ctr_stream_decrypt(State0, Data),
- {{aes_ctr, State}, Text};
-stream_decrypt({rc4, State0}, Data) ->
- {State, Text} = rc4_encrypt_with_state (State0, Data),
- {{rc4, State}, Text}.
-
-%%
-%% CRYPTO FUNCTIONS
-%%
-
-%%
-%% DES - in cipher block chaining mode (CBC)
-%%
--spec des_cbc_encrypt(iodata(), binary(), iodata()) -> binary().
--spec des_cbc_decrypt(iodata(), binary(), iodata()) -> binary().
-
-des_cbc_encrypt(Key, IVec, Data) ->
- des_cbc_crypt(Key, IVec, Data, true).
-
-des_cbc_decrypt(Key, IVec, Data) ->
- des_cbc_crypt(Key, IVec, Data, false).
-
-des_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
-
-%%
-%% dec_cbc_ivec(Data) -> binary()
-%%
-%% Returns the IVec to be used in the next iteration of
-%% des_cbc_[encrypt|decrypt].
-%%
--spec des_cbc_ivec(iodata()) -> binary().
-
-des_cbc_ivec(Data) when is_binary(Data) ->
- {_, IVec} = split_binary(Data, size(Data) - 8),
- IVec;
-des_cbc_ivec(Data) when is_list(Data) ->
- des_cbc_ivec(list_to_binary(Data)).
-
-%%
-%% DES - in 8-bits cipher feedback mode (CFB)
-%%
--spec des_cfb_encrypt(iodata(), binary(), iodata()) -> binary().
--spec des_cfb_decrypt(iodata(), binary(), iodata()) -> binary().
-
-des_cfb_encrypt(Key, IVec, Data) ->
- des_cfb_crypt(Key, IVec, Data, true).
-
-des_cfb_decrypt(Key, IVec, Data) ->
- des_cfb_crypt(Key, IVec, Data, false).
-
-des_cfb_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
-
-%%
-%% dec_cfb_ivec(IVec, Data) -> binary()
-%%
-%% Returns the IVec to be used in the next iteration of
-%% des_cfb_[encrypt|decrypt].
-%%
--spec des_cfb_ivec(iodata(), iodata()) -> binary().
-
-des_cfb_ivec(IVec, Data) ->
- IVecAndData = list_to_binary([IVec, Data]),
- {_, NewIVec} = split_binary(IVecAndData, byte_size(IVecAndData) - 8),
- NewIVec.
+%% CIPHERS --------------------------------------------------------------------
%%
%% DES - in electronic codebook mode (ECB)
@@ -973,292 +1158,63 @@ aes_cfb_128_decrypt(Key, IVec, Data) ->
aes_cfb_128_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
-%%
-%% RAND - pseudo random numbers using RN_ functions in crypto lib
%%
--spec rand_bytes(non_neg_integer()) -> binary().
--spec strong_rand_bytes(non_neg_integer()) -> binary().
--spec rand_uniform(crypto_integer(), crypto_integer()) ->
- crypto_integer().
--spec strong_rand_mpint(Bits::non_neg_integer(),
- Top::-1..1,
- Bottom::0..1) -> binary().
-
-rand_bytes(_Bytes) -> ?nif_stub.
-
-strong_rand_bytes(Bytes) ->
- case strong_rand_bytes_nif(Bytes) of
- false -> erlang:error(low_entropy);
- Bin -> Bin
- end.
-strong_rand_bytes_nif(_Bytes) -> ?nif_stub.
-
-rand_bytes(_Bytes, _Topmask, _Bottommask) -> ?nif_stub.
-
-strong_rand_mpint(Bits, Top, Bottom) ->
- case strong_rand_mpint_nif(Bits,Top,Bottom) of
- false -> erlang:error(low_entropy);
- Bin -> Bin
- end.
-strong_rand_mpint_nif(_Bits, _Top, _Bottom) -> ?nif_stub.
-
+%% DES - in cipher block chaining mode (CBC)
+%%
+-spec des_cbc_encrypt(iodata(), binary(), iodata()) -> binary().
+-spec des_cbc_decrypt(iodata(), binary(), iodata()) -> binary().
-rand_uniform(From,To) when is_binary(From), is_binary(To) ->
- case rand_uniform_nif(From,To) of
- <<Len:32/integer, MSB, Rest/binary>> when MSB > 127 ->
- <<(Len + 1):32/integer, 0, MSB, Rest/binary>>;
- Whatever ->
- Whatever
- end;
-rand_uniform(From,To) when is_integer(From),is_integer(To) ->
- if From < 0 ->
- rand_uniform_pos(0, To - From) + From;
- true ->
- rand_uniform_pos(From, To)
- end.
+des_cbc_encrypt(Key, IVec, Data) ->
+ des_cbc_crypt(Key, IVec, Data, true).
-rand_uniform_pos(From,To) when From < To ->
- BinFrom = mpint(From),
- BinTo = mpint(To),
- case rand_uniform(BinFrom, BinTo) of
- Result when is_binary(Result) ->
- erlint(Result);
- Other ->
- Other
- end;
-rand_uniform_pos(_,_) ->
- error(badarg).
+des_cbc_decrypt(Key, IVec, Data) ->
+ des_cbc_crypt(Key, IVec, Data, false).
-rand_uniform_nif(_From,_To) -> ?nif_stub.
+des_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
%%
-%% mod_exp - utility for rsa generation and SRP
+%% dec_cbc_ivec(Data) -> binary()
%%
-mod_exp(Base, Exponent, Modulo)
- when is_integer(Base), is_integer(Exponent), is_integer(Modulo) ->
- bin_to_int(mod_exp_nif(int_to_bin(Base), int_to_bin(Exponent), int_to_bin(Modulo), 0));
-
-mod_exp(Base, Exponent, Modulo) ->
- mod_exp_nif(mpint_to_bin(Base),mpint_to_bin(Exponent),mpint_to_bin(Modulo), 4).
-
--spec mod_pow(binary()|integer(), binary()|integer(), binary()|integer()) -> binary() | error.
-mod_pow(Base, Exponent, Prime) ->
- case mod_exp_nif(ensure_int_as_bin(Base), ensure_int_as_bin(Exponent), ensure_int_as_bin(Prime), 0) of
- <<0>> -> error;
- R -> R
- end.
-
+%% Returns the IVec to be used in the next iteration of
+%% des_cbc_[encrypt|decrypt].
+%%
+-spec des_cbc_ivec(iodata()) -> binary().
-mod_exp_nif(_Base,_Exp,_Mod,_bin_hdr) -> ?nif_stub.
+des_cbc_ivec(Data) when is_binary(Data) ->
+ {_, IVec} = split_binary(Data, size(Data) - 8),
+ IVec;
+des_cbc_ivec(Data) when is_list(Data) ->
+ des_cbc_ivec(list_to_binary(Data)).
%%
-%% DSS, RSA - verify
+%% DES - in 8-bits cipher feedback mode (CFB)
%%
--spec dss_verify(data_or_digest(), binary(), [binary()]) -> boolean().
--spec dss_verify(dss_digest_type(), data_or_digest(), binary(), [binary()]) -> boolean().
--spec rsa_verify(data_or_digest(), binary(), [binary()]) -> boolean().
--spec rsa_verify(rsa_digest_type(), data_or_digest(), binary(), [binary()]) ->
- boolean().
-
-%% Key = [P,Q,G,Y] P,Q,G=DSSParams Y=PublicKey
-dss_verify(Data,Signature,Key) ->
- dss_verify(sha, Data, Signature, Key).
-
-dss_verify(Type,Data,Signature,Key) when is_binary(Data), Type=/=none ->
- verify(dss,Type,mpint_to_bin(Data),mpint_to_bin(Signature),map_mpint_to_bin(Key));
-dss_verify(Type,Digest,Signature,Key) ->
- verify(dss,Type,Digest,mpint_to_bin(Signature),map_mpint_to_bin(Key)).
-
-% Key = [E,N] E=PublicExponent N=PublicModulus
-rsa_verify(Data,Signature,Key) ->
- rsa_verify(sha, Data,Signature,Key).
-rsa_verify(Type, Data, Signature, Key) when is_binary(Data) ->
- verify(rsa, Type, mpint_to_bin(Data), mpint_to_bin(Signature), map_mpint_to_bin(Key));
-rsa_verify(Type, Digest, Signature, Key) ->
- verify(rsa, Type, Digest, mpint_to_bin(Signature), map_mpint_to_bin(Key)).
-
-
-verify(dss, Type, Data, Signature, Key) ->
- dss_verify_nif(Type, Data, Signature, map_ensure_int_as_bin(Key));
-
-verify(rsa, Type, DataOrDigest, Signature, Key) ->
- case rsa_verify_nif(Type, DataOrDigest, Signature, map_ensure_int_as_bin(Key)) of
- notsup -> erlang:error(notsup);
- Bool -> Bool
- end;
-verify(ecdsa, Type, DataOrDigest, Signature, [Key, Curve]) ->
- case ecdsa_verify_nif(Type, DataOrDigest, Signature, term_to_ec_key(Curve, undefined, Key)) of
- notsup -> erlang:error(notsup);
- Bool -> Bool
- end.
+-spec des_cfb_encrypt(iodata(), binary(), iodata()) -> binary().
+-spec des_cfb_decrypt(iodata(), binary(), iodata()) -> binary().
+des_cfb_encrypt(Key, IVec, Data) ->
+ des_cfb_crypt(Key, IVec, Data, true).
-dss_verify_nif(_Type, _Data, _Signature, _Key) -> ?nif_stub.
-rsa_verify_nif(_Type, _Data, _Signature, _Key) -> ?nif_stub.
-ecdsa_verify_nif(_Type, _DataOrDigest, _Signature, _Key) -> ?nif_stub.
+des_cfb_decrypt(Key, IVec, Data) ->
+ des_cfb_crypt(Key, IVec, Data, false).
+des_cfb_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
%%
-%% DSS, RSA - sign
+%% dec_cfb_ivec(IVec, Data) -> binary()
%%
-%% Key = [P,Q,G,X] P,Q,G=DSSParams X=PrivateKey
--spec dss_sign(data_or_digest(), [binary()]) -> binary().
--spec dss_sign(dss_digest_type(), data_or_digest(), [binary()]) -> binary().
--spec rsa_sign(data_or_digest(), [binary()]) -> binary().
--spec rsa_sign(rsa_digest_type(), data_or_digest(), [binary()]) -> binary().
-
-dss_sign(DataOrDigest,Key) ->
- dss_sign(sha,DataOrDigest,Key).
-dss_sign(Type, Data, Key) when is_binary(Data), Type=/=none ->
- sign(dss, Type, mpint_to_bin(Data), map_mpint_to_bin(Key));
-dss_sign(Type, Digest, Key) ->
- sign(dss, Type, Digest, map_mpint_to_bin(Key)).
-
-
-%% Key = [E,N,D] E=PublicExponent N=PublicModulus D=PrivateExponent
-rsa_sign(DataOrDigest,Key) ->
- rsa_sign(sha, DataOrDigest, Key).
-
-rsa_sign(Type, Data, Key) when is_binary(Data) ->
- sign(rsa, Type, mpint_to_bin(Data), map_mpint_to_bin(Key));
-rsa_sign(Type, Digest, Key) ->
- sign(rsa, Type, Digest, map_mpint_to_bin(Key)).
-
-map_mpint_to_bin(List) ->
- lists:map(fun(E) -> mpint_to_bin(E) end, List ).
-
-map_ensure_int_as_bin([H|_]=List) when is_integer(H) ->
- lists:map(fun(E) -> int_to_bin(E) end, List);
-map_ensure_int_as_bin(List) ->
- List.
-
-ensure_int_as_bin(Int) when is_integer(Int) ->
- int_to_bin(Int);
-ensure_int_as_bin(Bin) ->
- Bin.
-
-map_to_norm_bin([H|_]=List) when is_integer(H) ->
- lists:map(fun(E) -> int_to_bin(E) end, List);
-map_to_norm_bin(List) ->
- lists:map(fun(E) -> mpint_to_bin(E) end, List).
-
-
-sign(rsa, Type, DataOrDigest, Key) ->
- case rsa_sign_nif(Type, DataOrDigest, map_ensure_int_as_bin(Key)) of
- error -> erlang:error(badkey, [Type,DataOrDigest,Key]);
- Sign -> Sign
- end;
-sign(dss, Type, DataOrDigest, Key) ->
- case dss_sign_nif(Type, DataOrDigest, map_ensure_int_as_bin(Key)) of
- error -> erlang:error(badkey, [DataOrDigest, Key]);
- Sign -> Sign
- end;
-sign(ecdsa, Type, DataOrDigest, [Key, Curve]) ->
- case ecdsa_sign_nif(Type, DataOrDigest, term_to_ec_key(Curve, Key, undefined)) of
- error -> erlang:error(badkey, [Type,DataOrDigest,Key]);
- Sign -> Sign
- end.
-
-rsa_sign_nif(_Type,_Data,_Key) -> ?nif_stub.
-dss_sign_nif(_Type,_Data,_Key) -> ?nif_stub.
-ecdsa_sign_nif(_Type, _DataOrDigest, _Key) -> ?nif_stub.
-
-
-
-
--spec public_encrypt(rsa, binary(), [binary()], rsa_padding()) ->
- binary().
--spec public_decrypt(rsa, binary(), [integer() | binary()], rsa_padding()) ->
- binary().
--spec private_encrypt(rsa, binary(), [integer() | binary()], rsa_padding()) ->
- binary().
--spec private_decrypt(rsa, binary(), [integer() | binary()], rsa_padding()) ->
- binary().
-
-public_encrypt(rsa, BinMesg, Key, Padding) ->
- case rsa_public_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, true) of
- error ->
- erlang:error(encrypt_failed, [BinMesg,Key, Padding]);
- Sign -> Sign
- end.
-
-%% Binary, Key = [E,N,D]
-private_decrypt(rsa, BinMesg, Key, Padding) ->
- case rsa_private_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, false) of
- error ->
- erlang:error(decrypt_failed, [BinMesg,Key, Padding]);
- Sign -> Sign
- end.
-
-
-%% Binary, Key = [E,N,D]
-private_encrypt(rsa, BinMesg, Key, Padding) ->
- case rsa_private_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, true) of
- error ->
- erlang:error(encrypt_failed, [BinMesg,Key, Padding]);
- Sign -> Sign
- end.
-
-%% Binary, Key = [E,N]
-public_decrypt(rsa, BinMesg, Key, Padding) ->
- case rsa_public_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, false) of
- error ->
- erlang:error(decrypt_failed, [BinMesg,Key, Padding]);
- Sign -> Sign
- end.
-
-
+%% Returns the IVec to be used in the next iteration of
+%% des_cfb_[encrypt|decrypt].
%%
-%% rsa_public_encrypt
-%% rsa_private_decrypt
--type rsa_padding() :: 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding' | 'rsa_no_padding'.
--spec rsa_public_encrypt(binary(), [binary()], rsa_padding()) ->
- binary().
--spec rsa_public_decrypt(binary(), [integer() | mpint()], rsa_padding()) ->
- binary().
--spec rsa_private_encrypt(binary(), [integer() | mpint()], rsa_padding()) ->
- binary().
--spec rsa_private_decrypt(binary(), [integer() | mpint()], rsa_padding()) ->
- binary().
-
-%% Binary, Key = [E,N]
-rsa_public_encrypt(BinMesg, Key, Padding) ->
- case rsa_public_crypt(BinMesg, map_to_norm_bin(Key), Padding, true) of
- error ->
- erlang:error(encrypt_failed, [BinMesg,Key, Padding]);
- Sign -> Sign
- end.
-
-rsa_public_crypt(_BinMsg, _Key, _Padding, _IsEncrypt) -> ?nif_stub.
+-spec des_cfb_ivec(iodata(), iodata()) -> binary().
-%% Binary, Key = [E,N,D]
-rsa_private_decrypt(BinMesg, Key, Padding) ->
- case rsa_private_crypt(BinMesg, map_to_norm_bin(Key), Padding, false) of
- error ->
- erlang:error(decrypt_failed, [BinMesg,Key, Padding]);
- Sign -> Sign
- end.
+des_cfb_ivec(IVec, Data) ->
+ IVecAndData = list_to_binary([IVec, Data]),
+ {_, NewIVec} = split_binary(IVecAndData, byte_size(IVecAndData) - 8),
+ NewIVec.
-rsa_private_crypt(_BinMsg, _Key, _Padding, _IsEncrypt) -> ?nif_stub.
-
-%% Binary, Key = [E,N,D]
-rsa_private_encrypt(BinMesg, Key, Padding) ->
- case rsa_private_crypt(BinMesg, map_to_norm_bin(Key), Padding, true) of
- error ->
- erlang:error(encrypt_failed, [BinMesg,Key, Padding]);
- Sign -> Sign
- end.
-
-%% Binary, Key = [E,N]
-rsa_public_decrypt(BinMesg, Key, Padding) ->
- case rsa_public_crypt(BinMesg, map_to_norm_bin(Key), Padding, false) of
- error ->
- erlang:error(decrypt_failed, [BinMesg,Key, Padding]);
- Sign -> Sign
- end.
-
%%
%% AES - with 128 or 256 bit key in cipher block chaining mode (CBC)
%%
@@ -1298,6 +1254,33 @@ aes_cbc_ivec(Data) when is_binary(Data) ->
aes_cbc_ivec(Data) when is_list(Data) ->
aes_cbc_ivec(list_to_binary(Data)).
+
+%% Stream ciphers --------------------------------------------------------------------
+
+stream_crypt(Fun, State, Data, Size, MaxByts, []) when Size =< MaxByts ->
+ Fun(State, Data);
+stream_crypt(Fun, State0, Data, Size, MaxByts, Acc) when Size =< MaxByts ->
+ {State, Cipher} = Fun(State0, Data),
+ {State, list_to_binary(lists:reverse([Cipher | Acc]))};
+stream_crypt(Fun, State0, Data, _, MaxByts, Acc) ->
+ <<Increment:MaxByts/binary, Rest/binary>> = Data,
+ {State, CipherText} = Fun(State0, Increment),
+ stream_crypt(Fun, State, Rest, erlang:byte_size(Rest), MaxByts, [CipherText | Acc]).
+
+do_stream_encrypt({aes_ctr, State0}, Data) ->
+ {State, Cipher} = aes_ctr_stream_encrypt(State0, Data),
+ {{aes_ctr, State}, Cipher};
+do_stream_encrypt({rc4, State0}, Data) ->
+ {State, Cipher} = rc4_encrypt_with_state(State0, Data),
+ {{rc4, State}, Cipher}.
+
+do_stream_decrypt({aes_ctr, State0}, Data) ->
+ {State, Text} = aes_ctr_stream_decrypt(State0, Data),
+ {{aes_ctr, State}, Text};
+do_stream_decrypt({rc4, State0}, Data) ->
+ {State, Text} = rc4_encrypt_with_state(State0, Data),
+ {{rc4, State}, Text}.
+
%%
%% AES - in counter mode (CTR)
%%
@@ -1305,7 +1288,7 @@ aes_cbc_ivec(Data) when is_list(Data) ->
binary().
-spec aes_ctr_decrypt(iodata(), binary(), iodata()) ->
binary().
-
+
aes_ctr_encrypt(_Key, _IVec, _Data) -> ?nif_stub.
aes_ctr_decrypt(_Key, _IVec, _Cipher) -> ?nif_stub.
@@ -1326,15 +1309,6 @@ aes_ctr_stream_encrypt({_Key, _IVec, _ECount, _Num}=_State, _Data) -> ?nif_stub.
aes_ctr_stream_decrypt({_Key, _IVec, _ECount, _Num}=_State, _Cipher) -> ?nif_stub.
%%
-%% XOR - xor to iolists and return a binary
-%% NB doesn't check that they are the same size, just concatenates
-%% them and sends them to the driver
-%%
--spec exor(iodata(), iodata()) -> binary().
-
-exor(_A, _B) -> ?nif_stub.
-
-%%
%% RC4 - symmetric stream cipher
%%
-spec rc4_encrypt(iodata(), iodata()) -> binary().
@@ -1363,7 +1337,76 @@ rc2_40_cbc_encrypt(Key, IVec, Data) when erlang:byte_size(Key) == 5 ->
rc2_40_cbc_decrypt(Key, IVec, Data) when erlang:byte_size(Key) == 5 ->
rc2_cbc_crypt(Key,IVec,Data,false).
-%%
+
+%% Secure remote password -------------------------------------------------------------------
+
+user_srp_gen_key(Private, Generator, Prime) ->
+ case mod_pow(Generator, Private, Prime) of
+ error ->
+ error;
+ Public ->
+ {Public, Private}
+ end.
+
+host_srp_gen_key(Private, Verifier, Generator, Prime, Version) ->
+ Multiplier = srp_multiplier(Version, Generator, Prime),
+ case srp_value_B_nif(Multiplier, Verifier, Generator, Private, Prime) of
+ error ->
+ error;
+ Public ->
+ {Public, Private}
+ end.
+
+srp_multiplier('6a', Generator, Prime) ->
+ %% k = SHA1(N | PAD(g)) from http://srp.stanford.edu/design.html
+ C0 = sha_init(),
+ C1 = sha_update(C0, Prime),
+ C2 = sha_update(C1, srp_pad_to(erlang:byte_size(Prime), Generator)),
+ sha_final(C2);
+srp_multiplier('6', _, _) ->
+ <<3/integer>>;
+srp_multiplier('3', _, _) ->
+ <<1/integer>>.
+
+srp_scrambler(Version, UserPublic, HostPublic, Prime) when Version == '6'; Version == '6a'->
+ %% SHA1(PAD(A) | PAD(B)) from http://srp.stanford.edu/design.html
+ PadLength = erlang:byte_size(Prime),
+ C0 = sha_init(),
+ C1 = sha_update(C0, srp_pad_to(PadLength, UserPublic)),
+ C2 = sha_update(C1, srp_pad_to(PadLength, HostPublic)),
+ sha_final(C2);
+srp_scrambler('3', _, HostPublic, _Prime) ->
+ %% The parameter u is a 32-bit unsigned integer which takes its value
+ %% from the first 32 bits of the SHA1 hash of B, MSB first.
+ <<U:32/bits, _/binary>> = sha(HostPublic),
+ U.
+
+srp_pad_length(Width, Length) ->
+ (Width - Length rem Width) rem Width.
+
+srp_pad_to(Width, Binary) ->
+ case srp_pad_length(Width, size(Binary)) of
+ 0 -> Binary;
+ N -> << 0:(N*8), Binary/binary>>
+ end.
+
+srp_host_secret_nif(_Verifier, _B, _U, _A, _Prime) -> ?nif_stub.
+
+srp_user_secret_nif(_A, _U, _B, _Multiplier, _Generator, _Exponent, _Prime) -> ?nif_stub.
+
+srp_value_B_nif(_Multiplier, _Verifier, _Generator, _Exponent, _Prime) -> ?nif_stub.
+
+
+%% Digital signatures --------------------------------------------------------------------
+rsa_sign_nif(_Type,_Data,_Key) -> ?nif_stub.
+dss_sign_nif(_Type,_Data,_Key) -> ?nif_stub.
+ecdsa_sign_nif(_Type, _DataOrDigest, _Curve, _Key) -> ?nif_stub.
+
+dss_verify_nif(_Type, _Data, _Signature, _Key) -> ?nif_stub.
+rsa_verify_nif(_Type, _Data, _Signature, _Key) -> ?nif_stub.
+ecdsa_verify_nif(_Type, _DataOrDigest, _Signature, _Curve, _Key) -> ?nif_stub.
+
+%% Public Keys --------------------------------------------------------------------
%% DH Diffie-Hellman functions
%%
@@ -1412,84 +1455,13 @@ dh_compute_key(OthersPublicKey, MyPrivateKey, DHParameters) ->
dh_compute_key_nif(_OthersPublicKey, _MyPrivateKey, _DHParameters) -> ?nif_stub.
-generate_key(Type, Params) ->
- generate_key(Type, Params, undefined).
-
-generate_key(dh, DHParameters, PrivateKey) ->
- dh_generate_key_nif(ensure_int_as_bin(PrivateKey),
- map_ensure_int_as_bin(DHParameters), 0);
-
-generate_key(srp, {host, [Verifier, Generator, Prime, Version]}, PrivArg)
- when is_binary(Verifier), is_binary(Generator), is_binary(Prime), is_atom(Version) ->
- Private = case PrivArg of
- undefined -> random_bytes(32);
- _ -> ensure_int_as_bin(PrivArg)
- end,
- host_srp_gen_key(Private, Verifier, Generator, Prime, Version);
-
-generate_key(srp, {user, [Generator, Prime, Version]}, PrivateArg)
- when is_binary(Generator), is_binary(Prime), is_atom(Version) ->
- Private = case PrivateArg of
- undefined -> random_bytes(32);
- _ -> PrivateArg
- end,
- user_srp_gen_key(Private, Generator, Prime);
-
-generate_key(ecdh, Curve, undefined) ->
- ec_key_to_term_nif(ec_key_generate(Curve)).
-
-
ec_key_generate(_Key) -> ?nif_stub.
-
-compute_key(dh, OthersPublicKey, MyPrivateKey, DHParameters) ->
- case dh_compute_key_nif(ensure_int_as_bin(OthersPublicKey),
- ensure_int_as_bin(MyPrivateKey),
- map_ensure_int_as_bin(DHParameters)) of
- error -> erlang:error(computation_failed,
- [OthersPublicKey,MyPrivateKey,DHParameters]);
- Ret -> Ret
- end;
-
-compute_key(srp, HostPublic, {UserPublic, UserPrivate},
- {user, [DerivedKey, Prime, Generator, Version | ScramblerArg]}) when
- is_binary(Prime),
- is_binary(Generator),
- is_atom(Version) ->
- HostPubBin = ensure_int_as_bin(HostPublic),
- Multiplier = srp_multiplier(Version, Generator, Prime),
- Scrambler = case ScramblerArg of
- [] -> srp_scrambler(Version, ensure_int_as_bin(UserPublic),
- HostPubBin, Prime);
- [S] -> S
- end,
- srp_user_secret_nif(ensure_int_as_bin(UserPrivate), Scrambler, HostPubBin,
- Multiplier, Generator, DerivedKey, Prime);
-
-compute_key(srp, UserPublic, {HostPublic, HostPrivate},
- {host,[Verifier, Prime, Version | ScramblerArg]}) when
- is_binary(Verifier),
- is_binary(Prime),
- is_atom(Version) ->
- UserPubBin = ensure_int_as_bin(UserPublic),
- Scrambler = case ScramblerArg of
- [] -> srp_scrambler(Version, UserPubBin, ensure_int_as_bin(HostPublic), Prime);
- [S] -> S
- end,
- srp_host_secret_nif(Verifier, ensure_int_as_bin(HostPrivate), Scrambler,
- UserPubBin, Prime);
-
-compute_key(ecdh, Others, My, Curve) ->
- ecdh_compute_key_nif(ensure_int_as_bin(Others),
- term_to_ec_key(Curve,My,undefined)).
-
-ecdh_compute_key_nif(_Others, _My) -> ?nif_stub.
-
+ecdh_compute_key_nif(_Others, _Curve, _My) -> ?nif_stub.
%%
%% EC
%%
-ec_key_to_term_nif(_Key) -> ?nif_stub.
term_to_nif_prime({prime_field, Prime}) ->
{prime_field, int_to_bin(Prime)};
@@ -1497,79 +1469,188 @@ term_to_nif_prime(PrimeField) ->
PrimeField.
term_to_nif_curve({A, B, Seed}) ->
{ensure_int_as_bin(A), ensure_int_as_bin(B), Seed}.
-term_to_nif_curve_parameters({PrimeField, Curve, BasePoint, Order, CoFactor}) ->
+nif_curve_params({PrimeField, Curve, BasePoint, Order, CoFactor}) ->
{term_to_nif_prime(PrimeField), term_to_nif_curve(Curve), ensure_int_as_bin(BasePoint), int_to_bin(Order), int_to_bin(CoFactor)};
-term_to_nif_curve_parameters(Curve) when is_atom(Curve) ->
+nif_curve_params(Curve) when is_atom(Curve) ->
%% named curve
Curve.
-term_to_ec_key(Curve, PrivKey, PubKey) ->
- term_to_ec_key_nif(term_to_nif_curve_parameters(Curve),
- ensure_int_as_bin(PrivKey),
- ensure_int_as_bin(PubKey)).
-term_to_ec_key_nif(_Curve, _PrivKey, _PubKey) -> ?nif_stub.
+%% MISC --------------------------------------------------------------------
+
+exor(Data1, Data2, Size, MaxByts, []) when Size =< MaxByts ->
+ do_exor(Data1, Data2);
+exor(Data1, Data2, Size, MaxByts, Acc) when Size =< MaxByts ->
+ Result = do_exor(Data1, Data2),
+ list_to_binary(lists:reverse([Result | Acc]));
+exor(Data1, Data2, _Size, MaxByts, Acc) ->
+ <<Increment1:MaxByts/binary, Rest1/binary>> = Data1,
+ <<Increment2:MaxByts/binary, Rest2/binary>> = Data2,
+ Result = do_exor(Increment1, Increment2),
+ exor(Rest1, Rest2, erlang:byte_size(Rest1), MaxByts, [Result | Acc]).
+do_exor(_A, _B) -> ?nif_stub.
+algorithms() -> ?nif_stub.
+
+int_to_bin(X) when X < 0 -> int_to_bin_neg(X, []);
+int_to_bin(X) -> int_to_bin_pos(X, []).
+
+int_to_bin_pos(0,Ds=[_|_]) ->
+ list_to_binary(Ds);
+int_to_bin_pos(X,Ds) ->
+ int_to_bin_pos(X bsr 8, [(X band 255)|Ds]).
+
+int_to_bin_neg(-1, Ds=[MSB|_]) when MSB >= 16#80 ->
+ list_to_binary(Ds);
+int_to_bin_neg(X,Ds) ->
+ int_to_bin_neg(X bsr 8, [(X band 255)|Ds]).
+
+bytes_to_integer(Bin) ->
+ bin_to_int(Bin).
+
+bin_to_int(Bin) when is_binary(Bin) ->
+ Bits = bit_size(Bin),
+ <<Integer:Bits/integer>> = Bin,
+ Integer;
+bin_to_int(undefined) ->
+ undefined.
-%% LOCAL FUNCTIONS
+map_ensure_int_as_bin([H|_]=List) when is_integer(H) ->
+ lists:map(fun(E) -> int_to_bin(E) end, List);
+map_ensure_int_as_bin(List) ->
+ List.
+
+ensure_int_as_bin(Int) when is_integer(Int) ->
+ int_to_bin(Int);
+ensure_int_as_bin(Bin) ->
+ Bin.
+
+map_to_norm_bin([H|_]=List) when is_integer(H) ->
+ lists:map(fun(E) -> int_to_bin(E) end, List);
+map_to_norm_bin(List) ->
+ lists:map(fun(E) -> mpint_to_bin(E) end, List).
+
+%%--------------------------------------------------------------------
+%%% Deprecated
+%%--------------------------------------------------------------------
%%
+%% rsa_public_encrypt
+%% rsa_private_decrypt
+-type rsa_padding() :: 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding' | 'rsa_no_padding'.
-user_srp_gen_key(Private, Generator, Prime) ->
- case mod_pow(Generator, Private, Prime) of
+-spec rsa_public_encrypt(binary(), [binary()], rsa_padding()) ->
+ binary().
+-spec rsa_public_decrypt(binary(), [integer() | mpint()], rsa_padding()) ->
+ binary().
+-spec rsa_private_encrypt(binary(), [integer() | mpint()], rsa_padding()) ->
+ binary().
+-spec rsa_private_decrypt(binary(), [integer() | mpint()], rsa_padding()) ->
+ binary().
+
+%% Binary, Key = [E,N]
+rsa_public_encrypt(BinMesg, Key, Padding) ->
+ case rsa_public_crypt(BinMesg, map_to_norm_bin(Key), Padding, true) of
error ->
- error;
- Public ->
- {Public, Private}
+ erlang:error(encrypt_failed, [BinMesg,Key, Padding]);
+ Sign -> Sign
end.
-host_srp_gen_key(Private, Verifier, Generator, Prime, Version) ->
- Multiplier = srp_multiplier(Version, Generator, Prime),
- case srp_value_B_nif(Multiplier, Verifier, Generator, Private, Prime) of
- error ->
- error;
- Public ->
- {Public, Private}
- end.
+rsa_public_crypt(_BinMsg, _Key, _Padding, _IsEncrypt) -> ?nif_stub.
-srp_multiplier('6a', Generator, Prime) ->
- %% k = SHA1(N | PAD(g)) from http://srp.stanford.edu/design.html
- C0 = sha_init(),
- C1 = sha_update(C0, Prime),
- C2 = sha_update(C1, srp_pad_to(erlang:byte_size(Prime), Generator)),
- sha_final(C2);
-srp_multiplier('6', _, _) ->
- <<3/integer>>;
-srp_multiplier('3', _, _) ->
- <<1/integer>>.
+%% Binary, Key = [E,N,D]
+rsa_private_decrypt(BinMesg, Key, Padding) ->
+ case rsa_private_crypt(BinMesg, map_to_norm_bin(Key), Padding, false) of
+ error ->
+ erlang:error(decrypt_failed, [BinMesg,Key, Padding]);
+ Sign -> Sign
+ end.
-srp_scrambler(Version, UserPublic, HostPublic, Prime) when Version == '6'; Version == '6a'->
- %% SHA1(PAD(A) | PAD(B)) from http://srp.stanford.edu/design.html
- PadLength = erlang:byte_size(Prime),
- C0 = sha_init(),
- C1 = sha_update(C0, srp_pad_to(PadLength, UserPublic)),
- C2 = sha_update(C1, srp_pad_to(PadLength, HostPublic)),
- sha_final(C2);
-srp_scrambler('3', _, HostPublic, _Prime) ->
- %% The parameter u is a 32-bit unsigned integer which takes its value
- %% from the first 32 bits of the SHA1 hash of B, MSB first.
- <<U:32/bits, _/binary>> = sha(HostPublic),
- U.
+rsa_private_crypt(_BinMsg, _Key, _Padding, _IsEncrypt) -> ?nif_stub.
-srp_pad_length(Width, Length) ->
- (Width - Length rem Width) rem Width.
-srp_pad_to(Width, Binary) ->
- case srp_pad_length(Width, size(Binary)) of
- 0 -> Binary;
- N -> << 0:(N*8), Binary/binary>>
+%% Binary, Key = [E,N,D]
+rsa_private_encrypt(BinMesg, Key, Padding) ->
+ case rsa_private_crypt(BinMesg, map_to_norm_bin(Key), Padding, true) of
+ error ->
+ erlang:error(encrypt_failed, [BinMesg,Key, Padding]);
+ Sign -> Sign
end.
-srp_host_secret_nif(_Verifier, _B, _U, _A, _Prime) -> ?nif_stub.
+%% Binary, Key = [E,N]
+rsa_public_decrypt(BinMesg, Key, Padding) ->
+ case rsa_public_crypt(BinMesg, map_to_norm_bin(Key), Padding, false) of
+ error ->
+ erlang:error(decrypt_failed, [BinMesg,Key, Padding]);
+ Sign -> Sign
+ end.
-srp_user_secret_nif(_A, _U, _B, _Multiplier, _Generator, _Exponent, _Prime) -> ?nif_stub.
+map_mpint_to_bin(List) ->
+ lists:map(fun(E) -> mpint_to_bin(E) end, List ).
+
+%%
+%% DSS, RSA - sign
+%%
+%% Key = [P,Q,G,X] P,Q,G=DSSParams X=PrivateKey
+-spec dss_sign(data_or_digest(), [binary()]) -> binary().
+-spec dss_sign(dss_digest_type(), data_or_digest(), [binary()]) -> binary().
+-spec rsa_sign(data_or_digest(), [binary()]) -> binary().
+-spec rsa_sign(rsa_digest_type(), data_or_digest(), [binary()]) -> binary().
+
+dss_sign(DataOrDigest,Key) ->
+ dss_sign(sha,DataOrDigest,Key).
+dss_sign(Type, Data, Key) when is_binary(Data), Type=/=none ->
+ sign(dss, Type, mpint_to_bin(Data), map_mpint_to_bin(Key));
+dss_sign(Type, Digest, Key) ->
+ sign(dss, Type, Digest, map_mpint_to_bin(Key)).
+
+
+%% Key = [E,N,D] E=PublicExponent N=PublicModulus D=PrivateExponent
+rsa_sign(DataOrDigest,Key) ->
+ rsa_sign(sha, DataOrDigest, Key).
+
+rsa_sign(Type, Data, Key) when is_binary(Data) ->
+ sign(rsa, Type, mpint_to_bin(Data), map_mpint_to_bin(Key));
+rsa_sign(Type, Digest, Key) ->
+ sign(rsa, Type, Digest, map_mpint_to_bin(Key)).
+
+%%
+%% DSS, RSA - verify
+%%
+-spec dss_verify(data_or_digest(), binary(), [binary()]) -> boolean().
+-spec dss_verify(dss_digest_type(), data_or_digest(), binary(), [binary()]) -> boolean().
+-spec rsa_verify(data_or_digest(), binary(), [binary()]) -> boolean().
+-spec rsa_verify(rsa_digest_type(), data_or_digest(), binary(), [binary()]) ->
+ boolean().
+
+%% Key = [P,Q,G,Y] P,Q,G=DSSParams Y=PublicKey
+dss_verify(Data,Signature,Key) ->
+ dss_verify(sha, Data, Signature, Key).
+
+dss_verify(Type,Data,Signature,Key) when is_binary(Data), Type=/=none ->
+ verify(dss,Type,mpint_to_bin(Data),mpint_to_bin(Signature),map_mpint_to_bin(Key));
+dss_verify(Type,Digest,Signature,Key) ->
+ verify(dss,Type,Digest,mpint_to_bin(Signature),map_mpint_to_bin(Key)).
+
+% Key = [E,N] E=PublicExponent N=PublicModulus
+rsa_verify(Data,Signature,Key) ->
+ rsa_verify(sha, Data,Signature,Key).
+rsa_verify(Type, Data, Signature, Key) when is_binary(Data) ->
+ verify(rsa, Type, mpint_to_bin(Data), mpint_to_bin(Signature), map_mpint_to_bin(Key));
+rsa_verify(Type, Digest, Signature, Key) ->
+ verify(rsa, Type, Digest, mpint_to_bin(Signature), map_mpint_to_bin(Key)).
+
+-spec strong_rand_mpint(Bits::non_neg_integer(),
+ Top::-1..1,
+ Bottom::0..1) -> binary().
+
+strong_rand_mpint(Bits, Top, Bottom) ->
+ case strong_rand_mpint_nif(Bits,Top,Bottom) of
+ false -> erlang:error(low_entropy);
+ Bin -> Bin
+ end.
+strong_rand_mpint_nif(_Bits, _Top, _Bottom) -> ?nif_stub.
-srp_value_B_nif(_Multiplier, _Verifier, _Generator, _Exponent, _Prime) -> ?nif_stub.
%% large integer in a binary with 32bit length
%% MP representaion (SSH2)
@@ -1594,32 +1675,6 @@ mpint_pos(X) ->
<<?UINT32(Sz), Bin/binary>>
end.
-int_to_bin(X) when X < 0 -> int_to_bin_neg(X, []);
-int_to_bin(X) -> int_to_bin_pos(X, []).
-
-%%int_to_bin_pos(X) when X >= 0 ->
-%% int_to_bin_pos(X, []).
-
-int_to_bin_pos(0,Ds=[_|_]) ->
- list_to_binary(Ds);
-int_to_bin_pos(X,Ds) ->
- int_to_bin_pos(X bsr 8, [(X band 255)|Ds]).
-
-int_to_bin_neg(-1, Ds=[MSB|_]) when MSB >= 16#80 ->
- list_to_binary(Ds);
-int_to_bin_neg(X,Ds) ->
- int_to_bin_neg(X bsr 8, [(X band 255)|Ds]).
-
-bytes_to_integer(Bin) ->
- bin_to_int(Bin).
-
-bin_to_int(Bin) when is_binary(Bin) ->
- Bits = bit_size(Bin),
- <<Integer:Bits/integer>> = Bin,
- Integer;
-bin_to_int(undefined) ->
- undefined.
-
%% int from integer in a binary with 32bit length
erlint(<<MPIntSize:32/integer,MPIntValue/binary>>) ->
Bits= MPIntSize * 8,
@@ -1629,11 +1684,71 @@ erlint(<<MPIntSize:32/integer,MPIntValue/binary>>) ->
mpint_to_bin(<<Len:32, Bin:Len/binary>>) ->
Bin.
-random_bytes(N) ->
- try strong_rand_bytes(N) of
- RandBytes ->
- RandBytes
- catch
- error:low_entropy ->
- rand_bytes(N)
- end.
+%%
+%% mod_exp - utility for rsa generation and SRP
+%%
+mod_exp(Base, Exponent, Modulo)
+ when is_integer(Base), is_integer(Exponent), is_integer(Modulo) ->
+ bin_to_int(mod_exp_nif(int_to_bin(Base), int_to_bin(Exponent), int_to_bin(Modulo), 0));
+
+mod_exp(Base, Exponent, Modulo) ->
+ mod_exp_nif(mpint_to_bin(Base),mpint_to_bin(Exponent),mpint_to_bin(Modulo), 4).
+
+mod_exp_nif(_Base,_Exp,_Mod,_bin_hdr) -> ?nif_stub.
+
+-define(FUNC_LIST, [hash, hash_init, hash_update, hash_final,
+ hmac, hmac_init, hmac_update, hmac_final, hmac_final_n,
+ %% deprecated
+ md4, md4_init, md4_update, md4_final,
+ md5, md5_init, md5_update, md5_final,
+ sha, sha_init, sha_update, sha_final,
+ md5_mac, md5_mac_96,
+ sha_mac, sha_mac_96,
+ %%
+ block_encrypt, block_decrypt,
+ %% deprecated
+ des_cbc_encrypt, des_cbc_decrypt,
+ des_cfb_encrypt, des_cfb_decrypt,
+ des_ecb_encrypt, des_ecb_decrypt,
+ des3_cbc_encrypt, des3_cbc_decrypt,
+ des3_cfb_encrypt, des3_cfb_decrypt,
+ aes_cfb_128_encrypt, aes_cfb_128_decrypt,
+ rc2_cbc_encrypt, rc2_cbc_decrypt,
+ rc2_40_cbc_encrypt, rc2_40_cbc_decrypt,
+ aes_cbc_128_encrypt, aes_cbc_128_decrypt,
+ aes_cbc_256_encrypt, aes_cbc_256_decrypt,
+ blowfish_cbc_encrypt, blowfish_cbc_decrypt,
+ blowfish_cfb64_encrypt, blowfish_cfb64_decrypt,
+ blowfish_ecb_encrypt, blowfish_ecb_decrypt, blowfish_ofb64_encrypt,
+ %%
+ rand_bytes,
+ strong_rand_bytes,
+ rand_uniform,
+ mod_pow,
+ exor,
+ %% deprecated
+ mod_exp,strong_rand_mpint,erlint, mpint,
+ %%
+ sign, verify, generate_key, compute_key,
+ %% deprecated
+ dss_verify,dss_sign,
+ rsa_verify,rsa_sign,
+ rsa_public_encrypt,rsa_private_decrypt,
+ rsa_private_encrypt,rsa_public_decrypt,
+ dh_generate_key, dh_compute_key,
+ %%
+ stream_init, stream_encrypt, stream_decrypt,
+ %% deprecated
+ rc4_encrypt, rc4_set_key, rc4_encrypt_with_state,
+ aes_ctr_encrypt, aes_ctr_decrypt,
+ aes_ctr_stream_init, aes_ctr_stream_encrypt, aes_ctr_stream_decrypt,
+ %%
+ next_iv,
+ %% deprecated
+ aes_cbc_ivec,
+ des_cbc_ivec, des_cfb_ivec,
+ info,
+ %%
+ info_lib, supports]).
+info() ->
+ ?FUNC_LIST.
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index b3bb5dbd17..58aaa78d28 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -212,16 +212,8 @@ mod_pow(Config) when is_list(Config) ->
exor() ->
[{doc, "Test the exor function"}].
exor(Config) when is_list(Config) ->
- B = <<1, 2, 3, 4, 5, 6, 7, 8, 9, 10>>,
- Z1 = zero_bin(B),
- Z1 = crypto:exor(B, B),
- B1 = crypto:rand_bytes(100),
- B2 = crypto:rand_bytes(100),
- Z2 = zero_bin(B1),
- Z2 = crypto:exor(B1, B1),
- Z2 = crypto:exor(B2, B2),
- R = xor_bytes(B1, B2),
- R = crypto:exor(B1, B2).
+ do_exor(<<1, 2, 3, 4, 5, 6, 7, 8, 9, 10>>),
+ do_exor(term_to_binary(lists:seq(1, 1000000))).
%%--------------------------------------------------------------------
rand_uniform() ->
[{doc, "rand_uniform and random_bytes testing"}].
@@ -229,10 +221,10 @@ rand_uniform(Config) when is_list(Config) ->
rand_uniform_aux_test(10),
10 = byte_size(crypto:rand_bytes(10)),
10 = byte_size(crypto:strong_rand_bytes(10)).
+
%%--------------------------------------------------------------------
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
-
hash(_, [], []) ->
ok;
hash(Type, [Msg | RestMsg], [Digest| RestDigest]) ->
@@ -491,7 +483,7 @@ do_block_iolistify({Type, Key, IV, PlainText}) ->
iolistify(<<"Test With Truncation">>)->
%% Do not iolistify as it spoils this special case
<<"Test With Truncation">>;
-iolistify(Msg)->
+iolistify(Msg) when is_binary(Msg) ->
Length = erlang:byte_size(Msg),
Split = Length div 2,
List0 = binary_to_list(Msg),
@@ -500,7 +492,9 @@ iolistify(Msg)->
[[Element], List1, List2];
{List1, List2}->
[List1, List2]
- end.
+ end;
+iolistify(Msg) ->
+ iolistify(list_to_binary(Msg)).
des_iolistify(Msg) ->
des_iolist(erlang:byte_size(Msg) div 8, Msg, []).
@@ -540,6 +534,17 @@ ipow(A, B, M, Prod) ->
ipow(A1, B1, M, (A*Prod) rem M)
end.
+do_exor(B) ->
+ Z1 = zero_bin(B),
+ Z1 = crypto:exor(B, B),
+ B1 = crypto:rand_bytes(100),
+ B2 = crypto:rand_bytes(100),
+ Z2 = zero_bin(B1),
+ Z2 = crypto:exor(B1, B1),
+ Z2 = crypto:exor(B2, B2),
+ R = xor_bytes(B1, B2),
+ R = crypto:exor(B1, B2).
+
zero_bin(N) when is_integer(N) ->
N8 = N * 8,
<<0:N8/integer>>;
@@ -586,20 +591,20 @@ group_config(md4 = Type, Config) ->
group_config(md5 = Type, Config) ->
Msgs = rfc_1321_msgs(),
Digests = rfc_1321_md5_digests(),
- Keys = rfc_2202_md5_keys(),
- Data = rfc_2202_msgs(),
- Hmac = rfc_2202_hmac_md5(),
+ Keys = rfc_2202_md5_keys() ++ [long_hmac_key(md5)],
+ Data = rfc_2202_msgs() ++ [long_msg()],
+ Hmac = rfc_2202_hmac_md5() ++ [long_hmac(md5)],
[{hash, {Type, Msgs, Digests}}, {hmac, {Type, Keys, Data, Hmac}} | Config];
group_config(ripemd160 = Type, Config) ->
Msgs = ripemd160_msgs(),
Digests = ripemd160_digests(),
[{hash, {Type, Msgs, Digests}} | Config];
group_config(sha = Type, Config) ->
- Msgs = [rfc_4634_test1(), rfc_4634_test2_1()],
- Digests = rfc_4634_sha_digests(),
- Keys = rfc_2202_sha_keys(),
- Data = rfc_2202_msgs(),
- Hmac = rfc_2202_hmac_sha(),
+ Msgs = [rfc_4634_test1(), rfc_4634_test2_1(),long_msg()],
+ Digests = rfc_4634_sha_digests() ++ [long_sha_digest()],
+ Keys = rfc_2202_sha_keys() ++ [long_hmac_key(sha)],
+ Data = rfc_2202_msgs() ++ [long_msg()],
+ Hmac = rfc_2202_hmac_sha() ++ [long_hmac(sha)],
[{hash, {Type, Msgs, Digests}}, {hmac, {Type, Keys, Data, Hmac}} | Config];
group_config(sha224 = Type, Config) ->
Msgs = [rfc_4634_test1(), rfc_4634_test2_1()],
@@ -609,25 +614,25 @@ group_config(sha224 = Type, Config) ->
Hmac = rfc4231_hmac_sha224(),
[{hash, {Type, Msgs, Digests}}, {hmac, {Type, Keys, Data, Hmac}} | Config];
group_config(sha256 = Type, Config) ->
- Msgs = [rfc_4634_test1(), rfc_4634_test2_1()],
- Digests = rfc_4634_sha256_digests(),
- Keys = rfc_4231_keys(),
- Data = rfc_4231_msgs(),
- Hmac = rfc4231_hmac_sha256(),
+ Msgs = [rfc_4634_test1(), rfc_4634_test2_1(), long_msg()],
+ Digests = rfc_4634_sha256_digests() ++ [long_sha256_digest()],
+ Keys = rfc_4231_keys() ++ [long_hmac_key(sha256)],
+ Data = rfc_4231_msgs() ++ [long_msg()],
+ Hmac = rfc4231_hmac_sha256() ++ [long_hmac(sha256)],
[{hash, {Type, Msgs, Digests}}, {hmac, {Type, Keys, Data, Hmac}} | Config];
group_config(sha384 = Type, Config) ->
- Msgs = [rfc_4634_test1(), rfc_4634_test2()],
- Digests = rfc_4634_sha384_digests(),
- Keys = rfc_4231_keys(),
- Data = rfc_4231_msgs(),
- Hmac = rfc4231_hmac_sha384(),
+ Msgs = [rfc_4634_test1(), rfc_4634_test2(), long_msg()],
+ Digests = rfc_4634_sha384_digests() ++ [long_sha384_digest()],
+ Keys = rfc_4231_keys() ++ [long_hmac_key(sha384)],
+ Data = rfc_4231_msgs() ++ [long_msg()],
+ Hmac = rfc4231_hmac_sha384() ++ [long_hmac(sha384)],
[{hash, {Type, Msgs, Digests}}, {hmac, {Type, Keys, Data, Hmac}} | Config];
group_config(sha512 = Type, Config) ->
- Msgs = [rfc_4634_test1(), rfc_4634_test2()],
- Digests = rfc_4634_sha512_digests(),
- Keys = rfc_4231_keys(),
- Data = rfc_4231_msgs(),
- Hmac = rfc4231_hmac_sha512(),
+ Msgs = [rfc_4634_test1(), rfc_4634_test2(), long_msg()],
+ Digests = rfc_4634_sha512_digests() ++ [long_sha512_digest()],
+ Keys = rfc_4231_keys() ++ [long_hmac_key(sha512)],
+ Data = rfc_4231_msgs() ++ [long_msg()],
+ Hmac = rfc4231_hmac_sha512() ++ [long_hmac(sha512)],
[{hash, {Type, Msgs, Digests}}, {hmac, {Type, Keys, Data, Hmac}} | Config];
group_config(rsa = Type, Config) ->
Msg = rsa_plain(),
@@ -789,6 +794,23 @@ rfc_4634_sha512_digests() ->
"454D4423643CE80E2A9AC94FA54CA49F"),
hexstr2bin("8E959B75DAE313DA8CF4F72814FC143F8F7779C6EB9F7FA17299AEADB6889018501D289E4900F7E4331B99DEC4B5433AC7D329EEB6DD26545E96E55B874BE909")].
+long_msg() ->
+ lists:duplicate(1000000, $a).
+
+long_sha_digest() ->
+ hexstr2bin("34aa973c" "d4c4daa4" "f61eeb2b" "dbad2731" "6534016f").
+
+long_sha256_digest() ->
+ hexstr2bin("cdc76e5c" "9914fb92" "81a1c7e2" "84d73e67" "f1809a48" "a497200e" "046d39cc" "c7112cd0").
+
+long_sha384_digest() ->
+ hexstr2bin("9d0e1809716474cb" "086e834e310a4a1c" "ed149e9c00f24852" "7972cec5704c2a5b"
+ "07b8b3dc38ecc4eb" "ae97ddd87f3d8985").
+
+long_sha512_digest() ->
+ hexstr2bin("e718483d0ce76964" "4e2e42c7bc15b463" "8e1f98b13b204428" "5632a803afa973eb"
+ "de0ff244877ea60a" "4cb0432ce577c31b" "eb009c5c2c49aa2e" "4eadb217ad8cc09b").
+
ripemd160_msgs() ->
[<<"">>,
<<"a">>,
@@ -852,6 +874,35 @@ hmac_key(_) ->
hmac_inc(_) ->
[<<"Sampl">>, <<"e #1">>].
+%% https://www.cosic.esat.kuleuven.be/nessie/testvectors/
+long_hmac_key(Type) when Type == sha384;
+ Type == sha512 ->
+ hexstr2bin("00112233445566778899AABBCCDDEEFF"
+ "0123456789ABCDEF0011223344556677"
+ "8899AABBCCDDEEFF0123456789ABCDEF"
+ "00112233445566778899AABBCCDDEEFF");
+long_hmac_key(_) ->
+ hexstr2bin("0123456789ABCDEF0123456789ABCDEF"
+ "0123456789ABCDEF0123456789ABCDEF"
+ "0123456789ABCDEF0123456789ABCDEF"
+ "0123456789ABCDEF0123456789ABCDEF").
+long_hmac(md5) ->
+ hexstr2bin("82FDDA30202CB6ACC6F24D4F8A50EB7A");
+long_hmac(sha) ->
+ hexstr2bin("61D1D0B6459860755FDA892938C23DD401E54A7E");
+long_hmac(sha256) ->
+ hexstr2bin("50008B8DC7ED3926936347FDC1A01E9D"
+ "5220C6CC4B038B482C0F28A4CD88CA37");
+long_hmac(sha384) ->
+ hexstr2bin("C1EB08DAFA015833D3FC6B29A387558B"
+ "3F6FA1524AA1A8EB64798D5A76A39D6E"
+ "A1465525342E060EE996277B4FFCDDC9");
+long_hmac(sha512) ->
+ hexstr2bin("D116BF471AAE1264854F1906025E846A"
+ "61618A965FCA30B695220EA2D6E547E3"
+ "F3B5A4B54E6778928C26D5D3D810498E"
+ "8DF86CB3CC1E9F66A00419B13B6B0C9A").
+
rfc_2202_hmac_md5() ->
[
hexstr2bin("9294727a3638bb1c13f48ef8158bfc9d"),
@@ -1193,7 +1244,8 @@ blowfish_ofb64() ->
rc4() ->
[{rc4, <<"apaapa">>, <<"Yo baby yo">>},
- {rc4, <<"apaapa">>, list_to_binary(lists:seq(0, 255))}
+ {rc4, <<"apaapa">>, list_to_binary(lists:seq(0, 255))},
+ {rc4, <<"apaapa">>, lists:duplicate(1000000, $a)}
].
aes_ctr() ->
@@ -1237,7 +1289,11 @@ aes_ctr() ->
hexstr2bin("30c81c46a35ce411e5fbc1191a0a52ef")},
{aes_ctr, hexstr2bin("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"),
hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdff02"),
- hexstr2bin("f69f2445df4f9b17ad2b417be66c3710")}
+ hexstr2bin("f69f2445df4f9b17ad2b417be66c3710")},
+
+ {aes_ctr, hexstr2bin("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"),
+ hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"),
+ lists:duplicate(1000000, $a)}
].
rsa_plain() ->
diff --git a/lib/crypto/vsn.mk b/lib/crypto/vsn.mk
index 2a0cb57aa9..d5d7c8a128 100644
--- a/lib/crypto/vsn.mk
+++ b/lib/crypto/vsn.mk
@@ -1 +1 @@
-CRYPTO_VSN = 2.3
+CRYPTO_VSN = 3.0
diff --git a/lib/debugger/doc/src/notes.xml b/lib/debugger/doc/src/notes.xml
index 19b8560041..5f1d411db2 100644
--- a/lib/debugger/doc/src/notes.xml
+++ b/lib/debugger/doc/src/notes.xml
@@ -32,6 +32,32 @@
<p>This document describes the changes made to the Debugger
application.</p>
+<section><title>Debugger 3.2.11</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> A new checkbox has been added. When it is checked,
+ the range set by the <c>erl</c> flag <c>+pc</c> is used
+ for determining when to print lists of integers as
+ strings. When it is unchecked, integer lists are never
+ printed as strings. </p> <p>A minor incompatibility:
+ settings saved by Erlang R16B01 or later cannot be read
+ by Erlang R16B or earlier.</p>
+ <p>
+ Own Id: OTP-10899</p>
+ </item>
+ <item>
+ <p>Erlang source files with non-ASCII characters are now
+ encoded in UTF-8 (instead of latin1).</p>
+ <p>
+ Own Id: OTP-11041 Aux Id: OTP-10907 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Debugger 3.2.10</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/debugger/src/dbg_istk.erl b/lib/debugger/src/dbg_istk.erl
index ced42a5f9f..d8f83eef3d 100644
--- a/lib/debugger/src/dbg_istk.erl
+++ b/lib/debugger/src/dbg_istk.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/debugger/vsn.mk b/lib/debugger/vsn.mk
index 58d462f409..c3e3579e2c 100644
--- a/lib/debugger/vsn.mk
+++ b/lib/debugger/vsn.mk
@@ -1 +1 @@
-DEBUGGER_VSN = 3.2.10
+DEBUGGER_VSN = 3.2.11
diff --git a/lib/dialyzer/doc/src/notes.xml b/lib/dialyzer/doc/src/notes.xml
index 4c701c5acf..b61b1af1b0 100644
--- a/lib/dialyzer/doc/src/notes.xml
+++ b/lib/dialyzer/doc/src/notes.xml
@@ -31,6 +31,77 @@
<p>This document describes the changes made to the Dialyzer
application.</p>
+<section><title>Dialyzer 2.6.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> A bug that made it impossible to do any analyses from
+ the GUI has been fixed. </p>
+ <p>
+ Own Id: OTP-11057 Aux Id: seq12313 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Include module, function and arity in Dialyzer's
+ "overlapping domain" warnings. Thanks to Magnus Henoch.</p>
+ <p>
+ Own Id: OTP-10918</p>
+ </item>
+ <item>
+ <p>
+ Improve Dialyzer output for scan errors. Thanks to Magnus
+ Henoch.</p>
+ <p>
+ Own Id: OTP-10996</p>
+ </item>
+ <item>
+ <p>
+ Integrate elliptic curve contribution from Andreas
+ Schultz </p>
+ <p>
+ In order to be able to support elliptic curve cipher
+ suites in SSL/TLS, additions to handle elliptic curve
+ infrastructure has been added to public_key and crypto.</p>
+ <p>
+ This also has resulted in a rewrite of the crypto API to
+ gain consistency and remove unnecessary overhead. All OTP
+ applications using crypto has been updated to use the new
+ API.</p>
+ <p>
+ Impact: Elliptic curve cryptography (ECC) offers
+ equivalent security with smaller key sizes than other
+ public key algorithms. Smaller key sizes result in
+ savings for power, memory, bandwidth, and computational
+ cost that make ECC especially attractive for constrained
+ environments.</p>
+ <p>
+ Own Id: OTP-11009</p>
+ </item>
+ <item>
+ <p>
+ Bitstring type inference and duplicate module error
+ message fixes. Thanks to Stavros Aronis.</p>
+ <p>
+ Own Id: OTP-11027</p>
+ </item>
+ <item>
+ <p>Erlang source files with non-ASCII characters are now
+ encoded in UTF-8 (instead of latin1).</p>
+ <p>
+ Own Id: OTP-11041 Aux Id: OTP-10907 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Dialyzer 2.6</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/dialyzer/src/dialyzer.erl b/lib/dialyzer/src/dialyzer.erl
index be4b9b6e12..822aa0826a 100644
--- a/lib/dialyzer/src/dialyzer.erl
+++ b/lib/dialyzer/src/dialyzer.erl
@@ -2,7 +2,7 @@
%%-----------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl
index affb89385e..0fbaf1d47c 100644
--- a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl
+++ b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl
@@ -2,7 +2,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/dialyzer/src/dialyzer_contracts.erl b/lib/dialyzer/src/dialyzer_contracts.erl
index 410be8586e..332a326b0d 100644
--- a/lib/dialyzer/src/dialyzer_contracts.erl
+++ b/lib/dialyzer/src/dialyzer_contracts.erl
@@ -2,7 +2,7 @@
%%-----------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/dialyzer/vsn.mk b/lib/dialyzer/vsn.mk
index bdb8692f8a..af32c5b901 100644
--- a/lib/dialyzer/vsn.mk
+++ b/lib/dialyzer/vsn.mk
@@ -1 +1 @@
-DIALYZER_VSN = 2.6
+DIALYZER_VSN = 2.6.1
diff --git a/lib/diameter/Makefile b/lib/diameter/Makefile
index 9961d627cf..aa1c9f7f20 100644
--- a/lib/diameter/Makefile
+++ b/lib/diameter/Makefile
@@ -1,7 +1,7 @@
-#
+#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010-2012. All Rights Reserved.
+# Copyright Ericsson AB 2010-2013. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -22,11 +22,11 @@ include vsn.mk
include subdirs.mk
SUB_DIRECTORIES = $(SUB_DIRS) doc/src
-SPECIAL_TARGETS =
+SPECIAL_TARGETS =
include $(ERL_TOP)/make/otp_subdir.mk
-info:
+info:
@echo "APP_VSN = $(APP_VSN)"
.PHONY: info
diff --git a/lib/diameter/doc/src/Makefile b/lib/diameter/doc/src/Makefile
index 99a6680f12..bd2b6b103a 100644
--- a/lib/diameter/doc/src/Makefile
+++ b/lib/diameter/doc/src/Makefile
@@ -1,4 +1,4 @@
-#
+#
# %CopyrightBegin%
#
# Copyright Ericsson AB 2010-2013. All Rights Reserved.
@@ -117,7 +117,7 @@ info:
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
diff --git a/lib/diameter/doc/src/diameter.xml b/lib/diameter/doc/src/diameter.xml
index 77d2381d2e..f6b1f75230 100644
--- a/lib/diameter/doc/src/diameter.xml
+++ b/lib/diameter/doc/src/diameter.xml
@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd" [
+ <!ENTITY spawn_opt
+ '<seealso marker="erts:erlang#spawn_opt-2">erlang:spawn_opt/2</seealso>'>
<!ENTITY nodes
'<seealso marker="erts:erlang#nodes-0">erlang:nodes/0</seealso>'>
<!ENTITY make_ref
@@ -27,12 +29,12 @@ 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.
-
+
</legalnotice>
<title>diameter(3)</title>
@@ -871,6 +873,18 @@ of a single Diameter node across multiple Erlang nodes.</p>
</note>
</item>
+<tag><c>{spawn_opt, [term()]}</c></tag>
+<item>
+<p>
+An options list passed to &spawn_opt; when spawning a process for an
+incoming Diameter request, unless the transport in question
+specifies another value.
+Options <c>monitor</c> and <c>link</c> are ignored.</p>
+
+<p>
+Defaults to the empty list.</p>
+</item>
+
<tag><c>{use_shared_peers, boolean() | [node()] | evaluable()}</c></tag>
<item>
<p>
@@ -1161,6 +1175,18 @@ Defaults to 30000 for a connecting transport and 60000 for a listening
transport.</p>
</item>
+<marker id="spawn_opt"/>
+<tag><c>{spawn_opt, [term()]}</c></tag>
+<item>
+<p>
+An options list passed to &spawn_opt; when spawning a process for an
+incoming Diameter request.
+Options <c>monitor</c> and <c>link</c> are ignored.</p>
+
+<p>
+Defaults to the list configured on the service if not specified.</p>
+</item>
+
<marker id="transport_config"/>
<tag><c>{transport_config, term()}</c></tag>
<tag><c>{transport_config, term(), &dict_Unsigned32; | infinity}</c></tag>
@@ -1626,7 +1652,7 @@ The <c>caps</c> entry identifies the capabilities sent by the local
node and received from the peer during capabilities exchange.
The <c>port</c> entry displays socket-level information about the
transport connection.
-The <c>statistics</c> entry presents Diameter-level counters,
+The <c>statistics</c> entry presents Diameter-level counters,
an entry like <c>{{{0,280,1},recv},2}</c> saying that the client has
received 2 DWR messages: <c>{0,280,1} = {Application_Id, Command_Code,
R_Flag}</c>.</p>
diff --git a/lib/diameter/doc/src/diameter_compile.xml b/lib/diameter/doc/src/diameter_compile.xml
index 65228c7c7a..512070dfd0 100644
--- a/lib/diameter/doc/src/diameter_compile.xml
+++ b/lib/diameter/doc/src/diameter_compile.xml
@@ -16,9 +16,9 @@
</copyright>
<legalnotice>
-The program may be used and/or copied only with the written permission
-from Ericsson AB, or in accordance with the terms and conditions
-stipulated in the agreement/contract under which the program has been
+The program may be used and/or copied only with the written permission
+from Ericsson AB, or in accordance with the terms and conditions
+stipulated in the agreement/contract under which the program has been
supplied.
</legalnotice>
diff --git a/lib/diameter/doc/src/diameter_dict.xml b/lib/diameter/doc/src/diameter_dict.xml
index becac23278..7b27046352 100644
--- a/lib/diameter/doc/src/diameter_dict.xml
+++ b/lib/diameter/doc/src/diameter_dict.xml
@@ -25,12 +25,12 @@ 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.
-
+
</legalnotice>
<title>diameter_dict(4)</title>
diff --git a/lib/diameter/doc/src/diameter_intro.xml b/lib/diameter/doc/src/diameter_intro.xml
index 4788fcc7b8..7764cb6133 100644
--- a/lib/diameter/doc/src/diameter_intro.xml
+++ b/lib/diameter/doc/src/diameter_intro.xml
@@ -17,12 +17,12 @@ 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.
-
+
</legalnotice>
<title>Introduction</title>
diff --git a/lib/diameter/doc/src/diameter_sctp.xml b/lib/diameter/doc/src/diameter_sctp.xml
index 5e65e8dad7..c0040f6198 100644
--- a/lib/diameter/doc/src/diameter_sctp.xml
+++ b/lib/diameter/doc/src/diameter_sctp.xml
@@ -70,10 +70,15 @@ and implements the behaviour documented in
<v>Type = connect | accept</v>
<v>Ref = &mod_transport_ref;</v>
<v>Svc = #diameter_service{}</v>
-<v>Opt = {raddr, &ip_address;} | {rport, integer()} | term()</v>
+<v>Opt = OwnOpt | SctpOpt</v>
<v>Pid = pid()</v>
<v>LAddr = &ip_address;</v>
<v>Reason = term()</v>
+<v>OwnOpt = {raddr, &ip_address;}
+ | {rport, integer()}
+ | {accept, Match}</v>
+<v>SctpOpt = term()</v>
+<v>Match = &ip_address; | string() | [Match]</v>
</type>
<desc>
@@ -85,9 +90,20 @@ Options <c>raddr</c> and <c>rport</c> specify the remote address
and port for a connecting transport and not valid for a listening
transport: the former is required while latter defaults to 3868 if
unspecified.
-More than one <c>raddr</c> option can be specified, in which case the
+Mupltiple <c>raddr</c> options can be specified, in which case the
connecting transport in question attempts each in sequence until
-an association is established.
+an association is established.</p>
+
+<p>
+Option <c>accept</c> specifies remote addresses for a listening
+transport and is not valid for a connecting transport.
+If specified, a remote address that does not match one of the
+specified addresses causes the association to be aborted.
+Multiple <c>accept</c> options can be specified.
+A string-valued <c>Match</c> that does not parse as an address is
+interpreted as a regular expression.</p>
+
+<p>
Remaining options are any accepted by &gen_sctp_open1;, with the exception
of options <c>mode</c>, <c>binary</c>, <c>list</c>, <c>active</c>
and <c>sctp_events</c>.
diff --git a/lib/diameter/doc/src/diameter_tcp.xml b/lib/diameter/doc/src/diameter_tcp.xml
index dd6d60df07..f6bbe7dd23 100644
--- a/lib/diameter/doc/src/diameter_tcp.xml
+++ b/lib/diameter/doc/src/diameter_tcp.xml
@@ -96,10 +96,12 @@ before configuring TLS capability on diameter transports.</p>
<v>Reason = term()</v>
<v>OwnOpt = {raddr, &ip_address;}
| {rport, integer()}
+ | {accept, Match}
| {port, integer()}
| {fragment_timer, infinity | 0..16#FFFFFFFF}</v>
<v>SslOpt = {ssl_options, true | list()}</v>
<v>TcpOpt = term()</v>
+<v>Match = &ip_address; | string() | [Match]</v>
</type>
<desc>
@@ -109,7 +111,18 @@ The start function required by &man_transport;.</p>
<p>
Options <c>raddr</c> and <c>rport</c> specify the remote address
and port for a connecting transport and are not valid for a listening
-transport.
+transport.</p>
+
+<p>
+Option <c>accept</c> specifies remote addresses for a listening
+transport and is not valid for a connecting transport.
+If specified, a remote address that does not match one of the
+specified addresses causes the connection to be aborted.
+Multiple <c>accept</c> options can be specified.
+A string-valued <c>Match</c> that does not parse as an address is
+interpreted as a regular expression.</p>
+
+<p>
Option <c>ssl_options</c> must be specified for a transport
that should support TLS: a value of <c>true</c> results in a
TLS handshake immediately upon connection establishment while
diff --git a/lib/diameter/doc/src/diameter_using.xml b/lib/diameter/doc/src/diameter_using.xml
index 02250bdef8..4427d29c3c 100644
--- a/lib/diameter/doc/src/diameter_using.xml
+++ b/lib/diameter/doc/src/diameter_using.xml
@@ -15,12 +15,12 @@ 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.
-
+
</legalnotice>
<title>Usage</title>
diff --git a/lib/diameter/doc/src/notes.xml b/lib/diameter/doc/src/notes.xml
index 02f9217957..6e79a9589a 100644
--- a/lib/diameter/doc/src/notes.xml
+++ b/lib/diameter/doc/src/notes.xml
@@ -42,6 +42,229 @@ first.</p>
<!-- ===================================================================== -->
+<section><title>diameter 1.4.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix handling of 5014 (INVALID_AVP_LENGTH) errors.</p>
+ <p>
+ This was in some cases reported as 3009
+ (INVALID_AVP_BITS).</p>
+ <p>
+ Note that the correction is partially implemented in
+ modules generated by diameterc(1): a dictionary file must
+ be recompiled for the correction to apply to any messages
+ it defines.</p>
+ <p>
+ Own Id: OTP-11007</p>
+ </item>
+ <item>
+ <p>
+ Fix faulty capitalization in release notes.</p>
+ <p>
+ Diameter = the protocol.<br/> diameter = the Erlang
+ application.</p>
+ <p>
+ Own Id: OTP-11014</p>
+ </item>
+ <item>
+ <p>
+ Fix watchdog memory leak.</p>
+ <p>
+ Entries were not removed from a service-specific ets
+ table, causing them to be orphaned at connection
+ reestablishment for listening transports, and
+ diameter:remove_transport/2 for both listening and
+ connecting transports.</p>
+ <p>
+ The fault was introduced by OTP-10692 in diameter-1.4.1
+ (R16B).</p>
+ <p>
+ Own Id: OTP-11019 Aux Id: OTP-10692 </p>
+ </item>
+ <item>
+ <p>
+ Fix decode failure on AVP Length &lt; 8.</p>
+ <p>
+ The failure caused the message in question to be
+ discarded.</p>
+ <p>
+ Own Id: OTP-11026</p>
+ </item>
+ <item>
+ <p>
+ Respect Host-IP-Address configuration.</p>
+ <p>
+ Addresses returned from a transport module were always
+ used to populate Host-IP-Address AVP's in an outgoing
+ CER/CEA, which precluded the sending of a VIP address.
+ Transport addresses are now only used if Host-IP-Address
+ is unspecified.</p>
+ <p>
+ Own Id: OTP-11045</p>
+ </item>
+ <item>
+ <p>
+ Fix mkdir race.</p>
+ <p>
+ Install could fail if examples/code and examples/dict
+ were created in parallel. Noticed on FreeBSD.</p>
+ <p>
+ Own Id: OTP-11051</p>
+ </item>
+ <item>
+ <p>
+ Fix recognition of 5001 on mandatory AVP's.</p>
+ <p>
+ An AVP setting the M-bit was not regarded as erroneous if
+ it was defined in the dictionary in question and its
+ container (message or Grouped AVP) had an 'AVP' field.
+ It's now regarded as a 5001 error (AVP_UNSUPPORTED), as
+ in the case that the AVP is not defined.</p>
+ <p>
+ Note that the correction is partially implemented in
+ modules generated by diameterc(1): a dictionary file must
+ be recompiled for the correction to apply to any messages
+ it defines.</p>
+ <p>
+ Own Id: OTP-11087</p>
+ </item>
+ <item>
+ <p>
+ Fix setting of Failed-AVP on handle_request
+ {answer_message, 5xxx} return.</p>
+ <p>
+ Failed-AVP was never in the outgoing answer-message. It
+ is now set with the AVP from the first entry with the
+ specified Result-Code in the errors field of the incoming
+ diameter_packet, if found.</p>
+ <p>
+ Own Id: OTP-11092</p>
+ </item>
+ <item>
+ <p>
+ Fix watchdog function_clause</p>
+ <p>
+ A listening transport on a service that allowed multiple
+ connections to the same peer could result in a
+ function_clause error in module diameter_watchdog. The
+ resulting crash was harmless but unseemly.</p>
+ <p>
+ Thanks to Aleksander Nycz.</p>
+ <p>
+ Own Id: OTP-11115</p>
+ </item>
+ <item>
+ <p>
+ Fix population of Failed-AVP.</p>
+ <p>
+ In cases in which diameter populated this AVP, many
+ values were sent instead of one as suggested by RFC 6733.
+ This was partially corrected by OTP-11007.</p>
+ <p>
+ Own Id: OTP-11127 Aux Id: OTP-11007 </p>
+ </item>
+ <item>
+ <p>
+ Fix list-valued Vendor-Specific-Application-Id config</p>
+ <p>
+ R16B (specifically, OTP-10760) broke the handling of such
+ configuration, resulting in a function clause error if
+ the list was not of length 3, and faulty interpretation
+ of the list's contents otherwise. Only record-valued
+ configuration was properly interpreted.</p>
+ <p>
+ Own Id: OTP-11165</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Allow peer connections to be shared between Erlang nodes
+ for the purpose of sending outgoing requests.</p>
+ <p>
+ A diameter_app(3) pick_peer/4 callback gets a list of
+ remote candidates as argument, allowing a callback on one
+ node to select a transport connection established on
+ another node. The service_opt() share_peers controls the
+ extent to which local connections are shared with remote
+ nodes. The service_opt() use_shared_peers controls the
+ extent to which connections shared from remote nodes are
+ utilized on the local node.</p>
+ <p>
+ Own Id: OTP-9610</p>
+ </item>
+ <item>
+ <p>
+ Allow listening diameter_{tcp,sctp} transports to be
+ configured with remote addresses.</p>
+ <p>
+ Option 'accept' allows remote addresses to be configured
+ as tuples or regular expressions. Remote addresses are
+ matched against the configured values at connection
+ establishment, any non-matching address causing the
+ connection to be aborted.</p>
+ <p>
+ Own Id: OTP-10893</p>
+ </item>
+ <item>
+ <p>
+ Detect more transport_opt() configuration errors at
+ diameter:add_transport/2.</p>
+ <p>
+ Many errors would previously not be detected until
+ transport start, diameter:add_transport/2 returning 'ok'
+ but transport connections failing to be established. An
+ error tuple is now returned.</p>
+ <p>
+ Own Id: OTP-10972</p>
+ </item>
+ <item>
+ <p>
+ Make explicit local address configuration optional in
+ diameter_tcp:start/3.</p>
+ <p>
+ The default address (as determined by gen_tcp) is now
+ used when a local address is not explicitly configured.</p>
+ <p>
+ Own Id: OTP-10986</p>
+ </item>
+ <item>
+ <p>
+ Improve handling of unrecognized service options.</p>
+ <p>
+ Such options were silently ignored by
+ diameter:start_service/2. An error tuple is now returned.</p>
+ <p>
+ Own Id: OTP-11017</p>
+ </item>
+ <item>
+ <p>
+ Don't send default Inband-Security-Id in CER/CEA.</p>
+ <p>
+ RFC 6733 recommends against the use of
+ Inband-Security-Id. Only send a value that differs from
+ the default, NO_INBAND_SECURITY = 0.</p>
+ <p>
+ Own Id: OTP-11050</p>
+ </item>
+ <item>
+ <p>
+ Make spawn options for request processes configurable.</p>
+ <p>
+ Own Id: OTP-11060</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>diameter 1.4.1.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/diameter/src/Makefile b/lib/diameter/src/Makefile
index c0cf418f06..578bbaee2e 100644
--- a/lib/diameter/src/Makefile
+++ b/lib/diameter/src/Makefile
@@ -1,19 +1,19 @@
-#
+#
# %CopyrightBegin%
-#
+#
# Copyright Ericsson AB 2010-2013. All Rights Reserved.
-#
+#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
# 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%
include $(ERL_TOP)/make/target.mk
diff --git a/lib/diameter/src/base/diameter.erl b/lib/diameter/src/base/diameter.erl
index 57730cad61..77200cc7d0 100644
--- a/lib/diameter/src/base/diameter.erl
+++ b/lib/diameter/src/base/diameter.erl
@@ -306,7 +306,8 @@ call(SvcName, App, Message) ->
| {restrict_connections, restriction()}
| {sequence, sequence() | evaluable()}
| {share_peers, remotes()}
- | {use_shared_peers, remotes()}.
+ | {use_shared_peers, remotes()}
+ | {spawn_opt, list()}.
-type application_opt()
:: {alias, app_alias()}
@@ -345,6 +346,7 @@ call(SvcName, App, Message) ->
| {reconnect_timer, 'Unsigned32'()}
| {watchdog_timer, 'Unsigned32'() | {module(), atom(), list()}}
| {watchdog_config, [{okay|suspect, non_neg_integer()}]}
+ | {spawn_opt, list()}
| {private, any()}.
%% Predicate passed to remove_transport/2
diff --git a/lib/diameter/src/base/diameter_capx.erl b/lib/diameter/src/base/diameter_capx.erl
index 4b821f5139..1a931a9854 100644
--- a/lib/diameter/src/base/diameter_capx.erl
+++ b/lib/diameter/src/base/diameter_capx.erl
@@ -419,12 +419,13 @@ app_union(#diameter_caps{auth_application_id = U,
vendor_specific_application_id = V}) ->
set_list(U ++ C ++ lists:flatmap(fun vsa_apps/1, V)).
-vsa_apps([_ | [_,_] = Ids]) ->
- lists:append(Ids);
+vsa_apps(Vals)
+ when is_list(Vals) ->
+ lists:flatmap(fun({'Vendor-Id', _}) -> []; ({_, Ids}) -> Ids end, Vals);
vsa_apps(Rec)
when is_tuple(Rec) ->
- [_|T] = tuple_to_list(Rec),
- vsa_apps(T).
+ [_Name, _VendorId | Idss] = tuple_to_list(Rec),
+ lists:append(Idss).
%% It's a configuration error for a locally advertised application not
%% to be represented in Apps. Don't just match on lists:keyfind/3 in
diff --git a/lib/diameter/src/base/diameter_codec.erl b/lib/diameter/src/base/diameter_codec.erl
index 6c0e73de36..1d647b8c87 100644
--- a/lib/diameter/src/base/diameter_codec.erl
+++ b/lib/diameter/src/base/diameter_codec.erl
@@ -204,7 +204,7 @@ msg_header(Mod, 'answer-message' = MsgName, Header) ->
#diameter_header{application_id = Aid,
cmd_code = Code}
= Header,
- {-1, Flags, ?DIAMETER_APP_ID_COMMON} = Mod:msg_header(MsgName),
+ {-1, Flags, ?APP_ID_COMMON} = Mod:msg_header(MsgName),
{Code, Flags, Aid};
msg_header(Mod, MsgName, _) ->
diff --git a/lib/diameter/src/base/diameter_config.erl b/lib/diameter/src/base/diameter_config.erl
index 2a145c874b..fc5c284bf2 100644
--- a/lib/diameter/src/base/diameter_config.erl
+++ b/lib/diameter/src/base/diameter_config.erl
@@ -549,6 +549,9 @@ opt({watchdog_timer, Tmo}) ->
opt({watchdog_config, L}) ->
is_list(L) andalso lists:all(fun wdopt/1, L);
+opt({spawn_opt, Opts}) ->
+ is_list(Opts);
+
%% Options that we can't validate.
opt({K, _})
when K == transport_config;
@@ -632,7 +635,8 @@ make_config(SvcName, Opts) ->
{false, use_shared_peers},
{false, monitor},
{?NOMASK, sequence},
- {nodes, restrict_connections}]),
+ {nodes, restrict_connections},
+ {[], spawn_opt}]),
#service{name = SvcName,
rec = #diameter_service{applications = Apps,
@@ -647,6 +651,9 @@ make_opts(Opts, Defs) ->
[{K, opt(K,V)} || {K,V} <- Known].
+opt(spawn_opt, L) ->
+ is_list(L);
+
opt(K, false = B)
when K /= sequence ->
B;
diff --git a/lib/diameter/src/base/diameter_peer.erl b/lib/diameter/src/base/diameter_peer.erl
index 0d2efd4d1f..e5d4b28766 100644
--- a/lib/diameter/src/base/diameter_peer.erl
+++ b/lib/diameter/src/base/diameter_peer.erl
@@ -25,7 +25,8 @@
-export([recv/2,
up/1,
up/2,
- up/3]).
+ up/3,
+ match/2]).
%% ... and the stack.
-export([start/1,
@@ -63,16 +64,16 @@
-define(DEFAULT_TCFG, []).
-define(DEFAULT_TTMO, infinity).
-%%% ---------------------------------------------------------------------------
-%%% # notify/3
-%%% ---------------------------------------------------------------------------
+%% ---------------------------------------------------------------------------
+%% # notify/3
+%% ---------------------------------------------------------------------------
notify(Nodes, SvcName, T) ->
rpc:abcast(Nodes, ?SERVER, {notify, SvcName, T}).
-%%% ---------------------------------------------------------------------------
-%%% # start/1
-%%% ---------------------------------------------------------------------------
+%% ---------------------------------------------------------------------------
+%% # start/1
+%% ---------------------------------------------------------------------------
-spec start({T, [Opt], #diameter_service{}})
-> {TPid, [Addr], Tmo, Data}
@@ -180,9 +181,34 @@ start(T, [M|Ms], Cfg, Svc, Tmo, Rest, Errs) ->
start(Mod, Args) ->
apply(Mod, start, Args).
-%%% ---------------------------------------------------------------------------
-%%% # up/1-3
-%%% ---------------------------------------------------------------------------
+%% ---------------------------------------------------------------------------
+%% # match/2
+%% ---------------------------------------------------------------------------
+
+match(Addrs, Matches)
+ when is_list(Addrs) ->
+ lists:all(fun(A) -> match1(A, Matches) end, Addrs).
+
+match1(Addr, Matches)
+ when not is_integer(hd(Matches)) ->
+ lists:any(fun(M) -> match1(Addr, M) end, Matches);
+
+match1(Addr, Match) ->
+ match(Addr, addr(Match), Match).
+
+match(Addr, {ok, A}, _) ->
+ Addr == A;
+match(Addr, {error, _}, RE) ->
+ match == re:run(inet_parse:ntoa(Addr), RE, [{capture, none}]).
+
+addr([_|_] = A) ->
+ inet_parse:address(A);
+addr(A) ->
+ {ok, A}.
+
+%% ---------------------------------------------------------------------------
+%% # up/1-3
+%% ---------------------------------------------------------------------------
up(Pid) -> %% accepting transport
ifc_send(Pid, {self(), connected}).
@@ -193,16 +219,16 @@ up(Pid, Remote) -> %% connecting transport
up(Pid, Remote, LAddrs) -> %% connecting transport
ifc_send(Pid, {self(), connected, Remote, LAddrs}).
-%%% ---------------------------------------------------------------------------
-%%% # recv/2
-%%% ---------------------------------------------------------------------------
+%% ---------------------------------------------------------------------------
+%% # recv/2
+%% ---------------------------------------------------------------------------
recv(Pid, Pkt) ->
ifc_send(Pid, {recv, Pkt}).
-%%% ---------------------------------------------------------------------------
-%%% # send/2
-%%% ---------------------------------------------------------------------------
+%% ---------------------------------------------------------------------------
+%% # send/2
+%% ---------------------------------------------------------------------------
send(Pid, #diameter_packet{transport_data = undefined,
bin = Bin}) ->
@@ -211,16 +237,16 @@ send(Pid, #diameter_packet{transport_data = undefined,
send(Pid, Pkt) ->
ifc_send(Pid, {send, Pkt}).
-%%% ---------------------------------------------------------------------------
-%%% # close/1
-%%% ---------------------------------------------------------------------------
+%% ---------------------------------------------------------------------------
+%% # close/1
+%% ---------------------------------------------------------------------------
close(Pid) ->
ifc_send(Pid, {close, self()}).
-%%% ---------------------------------------------------------------------------
-%%% # abort/1
-%%% ---------------------------------------------------------------------------
+%% ---------------------------------------------------------------------------
+%% # abort/1
+%% ---------------------------------------------------------------------------
abort(Pid) ->
exit(Pid, shutdown).
@@ -241,16 +267,16 @@ state() ->
uptime() ->
call(uptime).
-%%% ----------------------------------------------------------
-%%% # init(Role)
-%%% ----------------------------------------------------------
+%% ----------------------------------------------------------
+%% # init(Role)
+%% ----------------------------------------------------------
init([]) ->
{ok, #state{}}.
-%%% ----------------------------------------------------------
-%%% # handle_call(Request, From, State)
-%%% ----------------------------------------------------------
+%% ----------------------------------------------------------
+%% # handle_call(Request, From, State)
+%% ----------------------------------------------------------
handle_call(state, _, State) ->
{reply, State, State};
@@ -262,17 +288,17 @@ handle_call(Req, From, State) ->
?UNEXPECTED([Req, From]),
{reply, nok, State}.
-%%% ----------------------------------------------------------
-%%% # handle_cast(Request, State)
-%%% ----------------------------------------------------------
+%% ----------------------------------------------------------
+%% # handle_cast(Request, State)
+%% ----------------------------------------------------------
handle_cast(Msg, State) ->
?UNEXPECTED([Msg]),
{noreply, State}.
-%%% ----------------------------------------------------------
-%%% # handle_info(Request, State)
-%%% ----------------------------------------------------------
+%% ----------------------------------------------------------
+%% # handle_info(Request, State)
+%% ----------------------------------------------------------
%% Remote service is distributing a message.
handle_info({notify, SvcName, T}, S) ->
diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl
index 112e83476d..9dd8aafc61 100644
--- a/lib/diameter/src/base/diameter_service.erl
+++ b/lib/diameter/src/base/diameter_service.erl
@@ -770,10 +770,8 @@ start(Ref, Type, Opts, #state{watchdogT = WatchdogT,
= Svc
= merge_service(Opts, Svc0),
{_,_} = Mask = proplists:get_value(sequence, SvcOpts),
- Pid = s(Type, Ref, {diameter_traffic:make_recvdata([SvcName,
- PeerT,
- Apps,
- Mask]),
+ RecvData = diameter_traffic:make_recvdata([SvcName, PeerT, Apps, Mask]),
+ Pid = s(Type, Ref, {{spawn_opts([Opts, SvcOpts]), RecvData},
Opts,
SvcOpts,
Svc}),
@@ -787,6 +785,12 @@ start(Ref, Type, Opts, #state{watchdogT = WatchdogT,
%% record so that each watchdog may get a different record. This
%% record is what is passed back into application callbacks.
+spawn_opts(Optss) ->
+ SpawnOpts = get_value(spawn_opt, Optss, []),
+ [T || T <- SpawnOpts,
+ T /= link,
+ T /= monitor].
+
s(Type, Ref, T) ->
{_MRef, Pid} = diameter_watchdog:start({Type, Ref}, T),
Pid.
@@ -986,6 +990,18 @@ keyfind([Key | Rest], Pos, L) ->
T
end.
+%% get_value/3
+
+get_value(_, [], Def) ->
+ Def;
+get_value(Key, [L | Rest], Def) ->
+ case lists:keyfind(Key, 1, L) of
+ {_,V} ->
+ V;
+ _ ->
+ get_value(Key, Rest, Def)
+ end.
+
%% find_outgoing_app/2
find_outgoing_app(Alias, Apps) ->
diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl
index 0b15e68ec7..8b6f026b34 100644
--- a/lib/diameter/src/base/diameter_traffic.erl
+++ b/lib/diameter/src/base/diameter_traffic.erl
@@ -48,6 +48,7 @@
-define(BASE, ?DIAMETER_DICT_COMMON). %% Note: the RFC 3588 dictionary
-define(DEFAULT_TIMEOUT, 5000). %% for outgoing requests
+-define(DEFAULT_SPAWN_OPTS, []).
%% Table containing outgoing requests for which a reply has yet to be
%% received.
@@ -153,13 +154,8 @@ receive_message(TPid, Pkt, Dict0, RecvData)
RecvData).
%% Incoming request ...
-recv(true, false, TPid, Pkt, Dict0, RecvData) ->
- try
- spawn(fun() -> recv_request(TPid, Pkt, Dict0, RecvData) end)
- catch
- error: system_limit = E -> %% discard
- ?LOG({error, E}, now())
- end;
+recv(true, false, TPid, Pkt, Dict0, T) ->
+ spawn_request(TPid, Pkt, Dict0, T);
%% ... answer to known request ...
recv(false, #request{ref = Ref, handler = Pid} = Req, _, Pkt, Dict0, _) ->
@@ -177,6 +173,21 @@ recv(false, #request{ref = Ref, handler = Pid} = Req, _, Pkt, Dict0, _) ->
recv(false, false, _, _, _, _) ->
ok.
+%% spawn_request/4
+
+spawn_request(TPid, Pkt, Dict0, {Opts, RecvData}) ->
+ spawn_request(TPid, Pkt, Dict0, Opts, RecvData);
+spawn_request(TPid, Pkt, Dict0, RecvData) ->
+ spawn_request(TPid, Pkt, Dict0, ?DEFAULT_SPAWN_OPTS, RecvData).
+
+spawn_request(TPid, Pkt, Dict0, Opts, RecvData) ->
+ try
+ spawn_opt(fun() -> recv_request(TPid, Pkt, Dict0, RecvData) end, Opts)
+ catch
+ error: system_limit = E -> %% discard
+ ?LOG({error, E}, now())
+ end.
+
%% ---------------------------------------------------------------------------
%% recv_request/4
%% ---------------------------------------------------------------------------
@@ -780,7 +791,7 @@ failed([MsgName | Values], FailedAvp, Dict) ->
%% ... or record.
failed(Rec, FailedAvp, Dict) ->
try
- RecName = element(1, Rec),
+ RecName = element(1, Rec),
Dict:'#info-'(RecName, {index, 'Failed-AVP'}),
{'Failed-AVP', [FailedAvp]}
catch
diff --git a/lib/diameter/src/base/diameter.app.src b/lib/diameter/src/diameter.app.src
index ceefb9b398..ceefb9b398 100644
--- a/lib/diameter/src/base/diameter.app.src
+++ b/lib/diameter/src/diameter.app.src
diff --git a/lib/diameter/src/base/diameter.appup.src b/lib/diameter/src/diameter.appup.src
index 359f434941..62ace16faa 100644
--- a/lib/diameter/src/base/diameter.appup.src
+++ b/lib/diameter/src/diameter.appup.src
@@ -31,10 +31,36 @@
{"1.4", [{restart_application, diameter}]}, %% R16A
{"1.4.1", [{load_module, diameter_reg}, %% R16B
{load_module, diameter_stats},
+ {load_module, diameter_traffic},
{load_module, diameter_service},
+ {load_module, diameter_config},
+ {load_module, diameter_peer},
+ {load_module, diameter_peer_fsm},
{load_module, diameter_watchdog},
{load_module, diameter_capx},
- {load_module, diameter}]}
+ {load_module, diameter_codec},
+ {load_module, diameter_gen_base_rfc3588},
+ {load_module, diameter_gen_base_accounting},
+ {load_module, diameter_gen_base_rfc6733},
+ {load_module, diameter_gen_base_acct6733},
+ {load_module, diameter_tcp},
+ {load_module, diameter_lib},
+ {load_module, diameter}]},
+ {"1.4.1.1", [{load_module, diameter_traffic},
+ {load_module, diameter_service},
+ {load_module, diameter_config},
+ {load_module, diameter_peer},
+ {load_module, diameter_peer_fsm},
+ {load_module, diameter_watchdog},
+ {load_module, diameter_capx},
+ {load_module, diameter_codec},
+ {load_module, diameter_gen_base_rfc3588},
+ {load_module, diameter_gen_base_accounting},
+ {load_module, diameter_gen_base_rfc6733},
+ {load_module, diameter_gen_base_acct6733},
+ {load_module, diameter_tcp},
+ {load_module, diameter_lib},
+ {load_module, diameter}]}
],
[
{"0.9", [{restart_application, diameter}]},
@@ -46,6 +72,7 @@
{"1.3", [{restart_application, diameter}]},
{"1.3.1", [{restart_application, diameter}]},
{"1.4", [{restart_application, diameter}]},
- {"1.4.1", [{restart_application, diameter}]}
+ {"1.4.1", [{restart_application, diameter}]},
+ {"1.4.1.1", [{restart_application, diameter}]}
]
}.
diff --git a/lib/diameter/src/dict/base_rfc3588.dia b/lib/diameter/src/dict/base_rfc3588.dia
index acd7fffd00..43a417b8dc 100644
--- a/lib/diameter/src/dict/base_rfc3588.dia
+++ b/lib/diameter/src/dict/base_rfc3588.dia
@@ -1,7 +1,7 @@
;;
;; %CopyrightBegin%
;;
-;; Copyright Ericsson AB 2010-2011. All Rights Reserved.
+;; Copyright Ericsson AB 2010-2013. All Rights Reserved.
;;
;; The contents of this file are subject to the Erlang Public License,
;; Version 1.1, (the "License"); you may not use this file except in
@@ -421,7 +421,7 @@
DIAMETER_INVALID_AVP_BIT_COMBO 5016
DIAMETER_NO_COMMON_SECURITY 5017
-@grouped
+@grouped
Proxy-Info ::= < AVP Header: 284 >
{ Proxy-Host }
@@ -440,7 +440,7 @@
[ Auth-Application-Id ]
[ Acct-Application-Id ]
-;; The E2E-Sequence AVP is defined in RFC 3588 as Grouped, but
+;; The E2E-Sequence AVP is defined in RFC 3588 as Grouped, but
;; there is no definition of the group - only an informal text stating
;; that there should be a nonce (an OctetString) and a counter
;; (integer)
diff --git a/lib/diameter/src/transport/diameter_sctp.erl b/lib/diameter/src/transport/diameter_sctp.erl
index 8b8c2a6694..49a530b4eb 100644
--- a/lib/diameter/src/transport/diameter_sctp.erl
+++ b/lib/diameter/src/transport/diameter_sctp.erl
@@ -42,6 +42,9 @@
-export([ports/0,
ports/1]).
+-export_type([listen_option/0,
+ connect_option/0]).
+
-include_lib("kernel/include/inet_sctp.hrl").
-include_lib("diameter/include/diameter.hrl").
@@ -54,6 +57,9 @@
%% The default port for a listener.
-define(DEFAULT_PORT, 3868). %% RFC 3588, ch 2.1
+%% Remote addresses to accept connections from.
+-define(DEFAULT_ACCEPT, []). %% any
+
%% How long a listener with no associations lives before offing
%% itself.
-define(LISTENER_TIMEOUT, 30000).
@@ -62,6 +68,17 @@
%% association establishment.
-define(ACCEPT_TIMEOUT, 5000).
+-type connect_option() :: {raddr, inet:ip_address()}
+ | {rport, inet:port_number()}
+ | gen_sctp:open_option().
+
+-type match() :: inet:ip_address()
+ | string()
+ | [match()].
+
+-type listen_option() :: {accept, match()}
+ | gen_sctp:open_option().
+
-type uint() :: non_neg_integer().
%% Accepting/connecting transport process state.
@@ -69,7 +86,7 @@
{parent :: pid(),
mode :: {accept, pid()}
| accept
- | {connect, {list(inet:ip_address()), uint(), list()}}
+ | {connect, {[inet:ip_address()], uint(), list()}}
%% {RAs, RP, Errors}
| connect,
socket :: gen_sctp:sctp_socket(),
@@ -86,7 +103,8 @@
tmap = ets:new(?MODULE, []) :: ets:tid(),
%% {MRef, Pid|AssocId}, {AssocId, Pid}
pending = {0, ets:new(?MODULE, [ordered_set])},
- tref :: reference()}).
+ tref :: reference(),
+ accept :: [match()]}).
%% Field tmap is used to map an incoming message or event to the
%% relevent transport process. Field pending implements a queue of
%% transport processes to which an association has been assigned (at
@@ -102,6 +120,13 @@
%% # start/3
%% ---------------------------------------------------------------------------
+-spec start({accept, Ref}, #diameter_service{}, [listen_option()])
+ -> {ok, pid(), [inet:ip_address()]}
+ when Ref :: diameter:transport_ref();
+ ({connect, Ref}, #diameter_service{}, [connect_option()])
+ -> {ok, pid(), [inet:ip_address()]}
+ when Ref :: diameter:transport_ref().
+
start(T, #diameter_service{capabilities = Caps}, Opts)
when is_list(Opts) ->
diameter_sctp_sup:start(), %% start supervisors on demand
@@ -169,12 +194,14 @@ init(T) ->
%% A process owning a listening socket.
i({listen, Ref, {Opts, Addrs}}) ->
- {LAs, Sock} = AS = open(Addrs, Opts, ?DEFAULT_PORT),
+ {[Matches], Rest} = proplists:split(Opts, [accept]),
+ {LAs, Sock} = AS = open(Addrs, Rest, ?DEFAULT_PORT),
proc_lib:init_ack({ok, self(), LAs}),
ok = gen_sctp:listen(Sock, true),
true = diameter_reg:add_new({?MODULE, listener, {Ref, AS}}),
start_timer(#listener{ref = Ref,
- socket = Sock});
+ socket = Sock,
+ accept = accept(Matches)});
%% A connecting transport.
i({connect, Pid, Opts, Addrs, Ref}) ->
@@ -311,6 +338,9 @@ handle_call({{accept, Ref}, Pid}, _, #listener{ref = Ref,
{TPid, NewS} = accept(Ref, Pid, S),
{reply, {ok, TPid}, NewS#listener{count = N+1}};
+handle_call(T, From, {listener,_,_,_,_,_,_} = S) -> % started in old code
+ handle_call(T, From, upgrade(S));
+
handle_call(_, _, State) ->
{reply, nok, State}.
@@ -329,7 +359,10 @@ handle_info(T, #transport{} = S) ->
{noreply, #transport{} = t(T,S)};
handle_info(T, #listener{} = S) ->
- {noreply, #listener{} = l(T,S)}.
+ {noreply, #listener{} = l(T,S)};
+
+handle_info(T, {listener,_,_,_,_,_,_} = S) -> % started in old code
+ handle_info(T, upgrade(S)).
%% ---------------------------------------------------------------------------
%% # code_change/3
@@ -363,6 +396,9 @@ terminate(_, #listener{socket = Sock}) ->
%% ---------------------------------------------------------------------------
+upgrade(S) ->
+ #listener{} = erlang:append_element(S, ?DEFAULT_ACCEPT).
+
putr(Key, Val) ->
put({?MODULE, Key}, Val).
@@ -386,7 +422,7 @@ l({sctp, Sock, _RA, _RP, Data} = Msg, #listener{socket = Sock} = S) ->
try find(Id, Data, S) of
{TPid, NewS} ->
- TPid ! {peeloff, peeloff(Sock, Id, TPid), Msg},
+ TPid ! {peeloff, peeloff(Sock, Id, TPid), Msg, S#listener.accept},
NewS;
false ->
S
@@ -460,11 +496,14 @@ t(T,S) ->
%% transition/2
%% Listening process is transfering ownership of an association.
-transition({peeloff, Sock, {sctp, LSock, _RA, _RP, _Data} = Msg},
+transition({peeloff, Sock, {sctp, LSock, _RA, _RP, _Data} = Msg, Matches},
#transport{mode = {accept, _},
socket = LSock}
= S) ->
+ ok = accept_peer(Sock, Matches),
transition(Msg, S#transport{socket = Sock});
+transition({peeloff = T, _Sock, _Msg} = T, #transport{} = S) ->% from old code
+ transition(erlang:append_element(T, ?DEFAULT_ACCEPT), S);
%% Incoming message.
transition({sctp, _Sock, _RA, _RP, Data}, #transport{socket = Sock} = S) ->
@@ -510,6 +549,27 @@ transition({resolve_port, Pid}, #transport{socket = Sock})
%% Crash on anything unexpected.
+ok({ok, T}) ->
+ T;
+ok(T) ->
+ x(T).
+
+%% accept_peer/2
+
+accept_peer(_, []) ->
+ ok;
+
+accept_peer(Sock, Matches) ->
+ {RAddrs, _} = ok(inet:peername(Sock)),
+ diameter_peer:match(RAddrs, Matches)
+ orelse x({accept, RAddrs, Matches}),
+ ok.
+
+%% accept/1
+
+accept(Opts) ->
+ [[M] || {accept, M} <- Opts].
+
%% accept/3
%%
%% Start a new transport process or use one that's already been
diff --git a/lib/diameter/src/transport/diameter_tcp.erl b/lib/diameter/src/transport/diameter_tcp.erl
index cbbba714ac..4d1b8bec51 100644
--- a/lib/diameter/src/transport/diameter_tcp.erl
+++ b/lib/diameter/src/transport/diameter_tcp.erl
@@ -42,6 +42,9 @@
-export([ports/0,
ports/1]).
+-export_type([connect_option/0,
+ listen_option/0]).
+
-include_lib("diameter/include/diameter.hrl").
%% Keys into process dictionary.
@@ -80,6 +83,25 @@
-type frag() :: {length(), size(), binary(), list(binary())}
| binary().
+-type connect_option() :: {raddr, inet:ip_address()}
+ | {rport, pos_integer()}
+ | {ssl_options, true | [ssl:connect_option()]}
+ | option()
+ | ssl:connect_option()
+ | gen_tcp:connect_option().
+
+-type match() :: inet:ip_address()
+ | string()
+ | [match()].
+
+-type listen_option() :: {accept, match()}
+ | {ssl_options, true | [ssl:listen_option()]}
+ | ssl:listen_option()
+ | gen_tcp:listen_option().
+
+-type option() :: {port, non_neg_integer()}
+ | {fragment_timer, 0..16#FFFFFFFF}.
+
%% Accepting/connecting transport process state.
-record(transport,
{socket :: inet:socket() | ssl:sslsocket(), %% accept/connect socket
@@ -100,18 +122,14 @@
%% # start/3
%% ---------------------------------------------------------------------------
--spec start({accept, Ref}, Svc, [Opt])
+-spec start({accept, Ref}, #diameter_service{}, [listen_option()])
-> {ok, pid(), [inet:ip_address()]}
- when Ref :: diameter:transport_ref(),
- Svc :: #diameter_service{},
- Opt :: diameter:transport_opt();
- ({connect, Ref}, Svc, [Opt])
+ when Ref :: diameter:transport_ref();
+ ({connect, Ref}, #diameter_service{}, [connect_option()])
-> {ok, pid(), [inet:ip_address()]}
| {ok, pid()}
- when Ref :: diameter:transport_ref(),
- Svc :: #diameter_service{},
- Opt :: diameter:transport_opt().
-
+ when Ref :: diameter:transport_ref().
+
start({T, Ref}, #diameter_service{capabilities = Caps}, Opts) ->
diameter_tcp_sup:start(), %% start tcp supervisors on demand
{Mod, Rest} = split(Opts),
@@ -225,10 +243,10 @@ laddr([], Mod, Sock) ->
Addr;
laddr([{ip, Addr}], _, _) ->
Addr.
-
+
own(Opts) ->
- {Own, Rest} = proplists:split(Opts, [fragment_timer]),
- {lists:append(Own), Rest}.
+ {[Own], Rest} = proplists:split(Opts, [fragment_timer]),
+ {Own, Rest}.
ssl(Opts) ->
{[SslOpts], Rest} = proplists:split(Opts, [ssl_options]),
@@ -257,9 +275,11 @@ init(Type, Ref, Mod, Pid, _, Opts, Addrs) ->
%% init/6
init(accept = T, Ref, Mod, Pid, Opts, Addrs) ->
- {LAddr, LSock} = listener(Ref, {Mod, Opts, Addrs}),
+ {[Matches], Rest} = proplists:split(Opts, [accept]),
+ {LAddr, LSock} = listener(Ref, {Mod, Rest, Addrs}),
proc_lib:init_ack({ok, self(), [LAddr]}),
Sock = ok(accept(Mod, LSock)),
+ ok = accept_peer(Mod, Sock, accept(Matches)),
publish(Mod, T, Ref, Sock),
diameter_peer:up(Pid),
Sock;
@@ -282,7 +302,7 @@ init_rc([]) ->
up(Pid, Remote, [{ip, _Addr}], _, _) ->
diameter_peer:up(Pid, Remote);
-up(Pid, Remote, [], Mod, Sock) ->
+up(Pid, Remote, [], Mod, Sock) ->
{Addr, _Port} = ok(sockname(Mod, Sock)),
diameter_peer:up(Pid, Remote, [Addr]).
@@ -298,6 +318,22 @@ ok(No) ->
x(Reason) ->
exit({shutdown, Reason}).
+%% accept_peer/3
+
+accept_peer(_Mod, _Sock, []) ->
+ ok;
+
+accept_peer(Mod, Sock, Matches) ->
+ {RAddr, _} = ok(peername(Mod, Sock)),
+ diameter_peer:match([RAddr], Matches)
+ orelse x({accept, RAddr, Matches}),
+ ok.
+
+%% accept/1
+
+accept(Opts) ->
+ [[M] || {accept, M} <- Opts].
+
%% listener/2
listener(LRef, T) ->
diff --git a/lib/diameter/test/Makefile b/lib/diameter/test/Makefile
index 9719c67b32..aff1b18cf8 100644
--- a/lib/diameter/test/Makefile
+++ b/lib/diameter/test/Makefile
@@ -1,4 +1,4 @@
-#
+#
# %CopyrightBegin%
#
# Copyright Ericsson AB 2010-2013. All Rights Reserved.
@@ -76,7 +76,7 @@ any: opt
$(MAKE) -i $(SUITES)
clean:
- rm -f $(TARGET_FILES)
+ rm -f $(TARGET_FILES)
rm -f depend.mk coverspec
realclean: clean
@@ -159,7 +159,7 @@ log:
# ----------------------------------------------------
# Release Targets
-# ----------------------------------------------------
+# ----------------------------------------------------
/%: % force
sed -f release.sed $< > "$(RELSYSDIR)$@"
diff --git a/lib/diameter/test/diameter_capx_SUITE.erl b/lib/diameter/test/diameter_capx_SUITE.erl
index 8c9bb67e61..deabdd720b 100644
--- a/lib/diameter/test/diameter_capx_SUITE.erl
+++ b/lib/diameter/test/diameter_capx_SUITE.erl
@@ -27,6 +27,8 @@
-export([suite/0,
all/0,
groups/0,
+ init_per_suite/1,
+ end_per_suite/1,
init_per_group/2,
end_per_group/2,
init_per_testcase/2,
@@ -56,6 +58,11 @@
peer_down/4]).
-include("diameter.hrl").
+-include("diameter_gen_base_rfc3588.hrl").
+%% Use only the Vendor-Specific-Application-Id record from the base
+%% include, to test the independence of capabilities configuration
+%% from the different definitions of Vendor-Id in RFC's 3588 and RFC
+%% 6733.
%% ===========================================================================
@@ -69,6 +76,11 @@
-define(REALM, "erlang.org").
-define(HOST(Name), Name ++ "." ++ ?REALM).
+%% Application id's that are never agreed upon at capabilities
+%% exchange. Testcase no_common_application references them in order
+%% to exercise Vendor-Specific-Application-Id handling.
+-define(NOAPPS, [1111, 2222, 3333, 4444]).
+
%% Config for diameter:start_service/2.
-define(SERVICE,
[{'Origin-Realm', ?REALM},
@@ -83,7 +95,10 @@
|| {A,D} <- [{base3588, diameter_gen_base_rfc3588},
{acct3588, diameter_gen_base_accounting},
{base6733, diameter_gen_base_rfc6733},
- {acct6733, diameter_gen_acct_rfc6733}]]]).
+ {acct6733, diameter_gen_acct_rfc6733}]]]
+ ++ [{application, [{dictionary, dict(N)},
+ {module, not_really}]}
+ || N <- ?NOAPPS]).
-define(A, list_to_atom).
-define(L, atom_to_list).
@@ -116,6 +131,16 @@ groups() ->
Tc = lists:flatmap(fun tc/1, tc()),
[{D, [], Tc} || D <- ?DICTS].
+init_per_suite(Config) ->
+ lists:foreach(fun load_dict/1, ?NOAPPS),
+ Config.
+
+end_per_suite(_Config) ->
+ [] = [Mod || N <- ?NOAPPS,
+ Mod <- [dict(N)],
+ false <- [code:delete(Mod)]],
+ ok.
+
%% Generate a unique hostname for each testcase so that watchdogs
%% don't prevent a connection from being brought up immediately.
init_per_testcase(Name, Config) ->
@@ -160,7 +185,7 @@ start(_Config) ->
ok = diameter:start().
%% Ensure that both integer and list-valued vendor id's can be
-%% configured in a 'Vendor-Specific-Application-Id, the arity having
+%% configured in a Vendor-Specific-Application-Id, the arity having
%% changed between RFC 3588 and RFC 6733.
vendor_id(_Config) ->
[] = ?util:run([[fun vid/1, V] || V <- [1, [1], [1,2], x]]).
@@ -188,13 +213,13 @@ add_listeners(Config) ->
Acct = [listen(?SERVER,
[{capabilities, [{'Origin-Host', ?HOST(H)},
{'Auth-Application-Id', []}]},
- {applications, [A]},
+ {applications, [A | noapps()]},
{capabilities_cb, [fun server_capx/3, acct]}])
|| {A,H} <- [{acct3588, "acct3588-srv"},
{acct6733, "acct6733-srv"}]],
Base = [listen(?SERVER,
[{capabilities, [{'Origin-Host', ?HOST(H)}]},
- {applications, A},
+ {applications, A ++ noapps()},
{capabilities_cb, [fun server_capx/3, base]}])
|| {A,H} <- [{[base3588, acct3588], "base3588-srv"},
{[base6733, acct6733], "base6733-srv"}]],
@@ -224,15 +249,33 @@ stop(_Config) ->
%% DIAMETER_NO_COMMON_APPLICATION = 5010.
s_no_common_application(Config) ->
- server_closed(Config, fun no_common_application/1, 5010).
+ Vs = [[{'Vendor-Id', 111},
+ {'Auth-Application-Id', [1111]}],
+ #'diameter_base_Vendor-Specific-Application-Id'
+ {'Vendor-Id' = [222],
+ 'Acct-Application-Id' = [2222]}],
+ server_closed(Config,
+ fun(C) -> no_common_application(C,Vs) end,
+ 5010).
c_no_common_application(Config) ->
- client_closed(Config, "acct-srv", fun no_common_application/1, 5010).
-
-no_common_application(Config) ->
+ Vs = [#'diameter_base_Vendor-Specific-Application-Id'
+ {'Vendor-Id' = 333,
+ 'Auth-Application-Id' = [3333]},
+ [{'Vendor-Id', [444]},
+ {'Acct-Application-Id', [4444]}]],
+ client_closed(Config,
+ "acct-srv",
+ fun(C) -> no_common_application(C,Vs) end,
+ 5010).
+
+no_common_application(Config, Vs) ->
[Common, _Acct] = apps(Config),
- connect(Config, acct, [{capabilities, [{'Acct-Application-Id', []}]},
- {applications, [Common]}]).
+ connect(Config,
+ acct,
+ [{capabilities, [{'Acct-Application-Id', []},
+ {'Vendor-Specific-Application-Id', Vs}]},
+ {applications, [Common | noapps()]}]).
%% ====================
%% Ask the base server to speak accounting with an unknown security
@@ -324,6 +367,25 @@ client_reject(Config) ->
%% ===========================================================================
+noapps() ->
+ lists:map(fun dict/1, ?NOAPPS).
+
+dict(N) ->
+ ?A(?L(?MODULE) ++ "_" ++ integer_to_list(N)).
+
+%% Compile and load minimal dictionary modules. These actually have to
+%% exists since diameter will call their id/0 to extract application
+%% id's, failing with app_not_configured if it can't.
+load_dict(N) ->
+ Mod = dict(N),
+ Forms = [{attribute, 1, module, Mod},
+ {attribute, 2, compile, [export_all]},
+ {function, 3, id, 0,
+ [{clause, 4, [], [], [{integer, 4, N}]}]}],
+ {ok, Mod, Bin, []} = compile:forms(Forms, [return]),
+ {module, Mod} = code:load_binary(Mod, Mod, Bin),
+ N = Mod:id().
+
%% server_closed/3
server_closed(Config, F, RC) ->
diff --git a/lib/diameter/test/diameter_codec_SUITE.erl b/lib/diameter/test/diameter_codec_SUITE.erl
index 2e219bbb10..cd8ca41f66 100644
--- a/lib/diameter/test/diameter_codec_SUITE.erl
+++ b/lib/diameter/test/diameter_codec_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl b/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl
index 49f2158b1a..cdf0cf55e1 100644
--- a/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl
+++ b/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/diameter/test/diameter_examples_SUITE.erl b/lib/diameter/test/diameter_examples_SUITE.erl
index 1954bc319b..75b542b679 100644
--- a/lib/diameter/test/diameter_examples_SUITE.erl
+++ b/lib/diameter/test/diameter_examples_SUITE.erl
@@ -149,7 +149,7 @@ to_erl(File, Opts) ->
No ->
throw({make, No})
end.
-
+
to_beam(Name) ->
case compile:file(Name ++ ".erl", [return]) of
{ok, _, _} ->
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index 38bdf55af8..a97c54fc04 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -171,7 +171,8 @@
{'Product-Name', "OTP/diameter"},
{'Auth-Application-Id', [?DIAMETER_APP_ID_COMMON]},
{'Acct-Application-Id', [?DIAMETER_APP_ID_ACCOUNTING]},
- {restrict_connections, false}
+ {restrict_connections, false},
+ {spawn_opt, [{min_heap_size, 5000}]}
| [{application, [{dictionary, D},
{module, ?MODULE},
{answer_errors, callback}]}
@@ -321,6 +322,7 @@ add_transports(Config) ->
LRef = ?util:listen(?SERVER,
tcp,
[{capabilities_cb, fun capx/2},
+ {spawn_opt, [{min_heap_size, 8096}]},
{applications, apps(rfc3588)}]),
Cs = [?util:connect(?CLIENT,
tcp,
diff --git a/lib/diameter/test/diameter_util.erl b/lib/diameter/test/diameter_util.erl
index aa489fef5f..92c72c84e7 100644
--- a/lib/diameter/test/diameter_util.erl
+++ b/lib/diameter/test/diameter_util.erl
@@ -336,7 +336,7 @@ opts(Prot, T) ->
{transport_config, [{ip, ?ADDR}, {port, 0} | opts(T)]}].
opts(listen) ->
- [];
+ [{accept, M} || M <- [{256,0,0,1}, ["256.0.0.1", ["^.+$"]]]];
opts(PortNr) ->
[{raddr, ?ADDR}, {rport, PortNr}].
diff --git a/lib/diameter/vsn.mk b/lib/diameter/vsn.mk
index 757f29a32e..f7462c3916 100644
--- a/lib/diameter/vsn.mk
+++ b/lib/diameter/vsn.mk
@@ -18,5 +18,5 @@
# %CopyrightEnd%
APPLICATION = diameter
-DIAMETER_VSN = 1.4.1.1
+DIAMETER_VSN = 1.4.2
APP_VSN = $(APPLICATION)-$(DIAMETER_VSN)$(PRE_VSN)
diff --git a/lib/erl_interface/doc/src/notes.xml b/lib/erl_interface/doc/src/notes.xml
index 327adb4034..930b24c26a 100644
--- a/lib/erl_interface/doc/src/notes.xml
+++ b/lib/erl_interface/doc/src/notes.xml
@@ -30,6 +30,22 @@
</header>
<p>This document describes the changes made to the Erl_interface application.</p>
+<section><title>Erl_Interface 3.7.13</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ A guard was added to check if file descriptor is valid
+ before closing it.</p>
+ <p>
+ Own Id: OTP-11167</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erl_Interface 3.7.12</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/erl_interface/vsn.mk b/lib/erl_interface/vsn.mk
index 9287e105df..6f08d380ca 100644
--- a/lib/erl_interface/vsn.mk
+++ b/lib/erl_interface/vsn.mk
@@ -1 +1 @@
-EI_VSN = 3.7.12
+EI_VSN = 3.7.13
diff --git a/lib/et/doc/src/notes.xml b/lib/et/doc/src/notes.xml
index 7557c31851..7b9d3fcf81 100644
--- a/lib/et/doc/src/notes.xml
+++ b/lib/et/doc/src/notes.xml
@@ -36,6 +36,29 @@
one section in this document. The title of each section is the
version number of <c>Event Tracer (ET)</c>.</p>
+<section><title>ET 1.4.4.4</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Use erlang:demonitor(Ref, [flush]) where applicable.
+ Thanks to Lo�c Hoguin.</p>
+ <p>
+ Own Id: OTP-11039</p>
+ </item>
+ <item>
+ <p>
+ Rename and document lists:zf/2 as lists:filtermap/2.
+ Thanks to Anthony Ramine.</p>
+ <p>
+ Own Id: OTP-11078</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>ET 1.4.4.3</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/et/src/et_collector.erl b/lib/et/src/et_collector.erl
index ce8cf6d4e0..a78b30c419 100644
--- a/lib/et/src/et_collector.erl
+++ b/lib/et/src/et_collector.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/et/vsn.mk b/lib/et/vsn.mk
index 99532ee3f3..40cdc2b298 100644
--- a/lib/et/vsn.mk
+++ b/lib/et/vsn.mk
@@ -1 +1 @@
-ET_VSN = 1.4.4.3
+ET_VSN = 1.4.4.4
diff --git a/lib/hipe/doc/src/notes.xml b/lib/hipe/doc/src/notes.xml
index 77a6f92f31..52c5e068e1 100644
--- a/lib/hipe/doc/src/notes.xml
+++ b/lib/hipe/doc/src/notes.xml
@@ -30,6 +30,36 @@
</header>
<p>This document describes the changes made to HiPE.</p>
+<section><title>Hipe 3.10.2</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Fix the title of hipe_app documentation page. Thanks to
+ Lo�c Hoguin.</p>
+ <p>
+ Own Id: OTP-10904</p>
+ </item>
+ <item>
+ <p>
+ Fix native code compiler crash involving bs_match_string.
+ Thanks to Kostis Sagonas.</p>
+ <p>
+ Own Id: OTP-10985</p>
+ </item>
+ <item>
+ <p>
+ Loosen the assumptions of code that handles escaping
+ functions. Thanks to Kostis Sagonas</p>
+ <p>
+ Own Id: OTP-11031</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Hipe 3.10.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/hipe/icode/Makefile b/lib/hipe/icode/Makefile
index 238f70cf59..87015aa51c 100644
--- a/lib/hipe/icode/Makefile
+++ b/lib/hipe/icode/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2012. All Rights Reserved.
+# Copyright Ericsson AB 2001-2013. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/hipe/icode/hipe_icode.erl b/lib/hipe/icode/hipe_icode.erl
index dfea092af2..6d4758bbf1 100644
--- a/lib/hipe/icode/hipe_icode.erl
+++ b/lib/hipe/icode/hipe_icode.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/hipe/icode/hipe_icode.hrl b/lib/hipe/icode/hipe_icode.hrl
index 89d297ef01..060493e61e 100644
--- a/lib/hipe/icode/hipe_icode.hrl
+++ b/lib/hipe/icode/hipe_icode.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/hipe/icode/hipe_icode_callgraph.erl b/lib/hipe/icode/hipe_icode_callgraph.erl
index 6d004823e2..5789328f47 100644
--- a/lib/hipe/icode/hipe_icode_callgraph.erl
+++ b/lib/hipe/icode/hipe_icode_callgraph.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/hipe/icode/hipe_icode_range.erl b/lib/hipe/icode/hipe_icode_range.erl
index 46c5a39f2c..1a2cbfae31 100644
--- a/lib/hipe/icode/hipe_icode_range.erl
+++ b/lib/hipe/icode/hipe_icode_range.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl b/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl
index 718d5d442b..2337ef9323 100644
--- a/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl
+++ b/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/hipe/regalloc/hipe_ls_regalloc.erl b/lib/hipe/regalloc/hipe_ls_regalloc.erl
index 7fb65be6a0..4276b8f968 100644
--- a/lib/hipe/regalloc/hipe_ls_regalloc.erl
+++ b/lib/hipe/regalloc/hipe_ls_regalloc.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/hipe/rtl/Makefile b/lib/hipe/rtl/Makefile
index 0312e67822..751e87636a 100644
--- a/lib/hipe/rtl/Makefile
+++ b/lib/hipe/rtl/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2012. All Rights Reserved.
+# Copyright Ericsson AB 2001-2013. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/hipe/vsn.mk b/lib/hipe/vsn.mk
index 6cd87708ef..deb16b02fd 100644
--- a/lib/hipe/vsn.mk
+++ b/lib/hipe/vsn.mk
@@ -1 +1 @@
-HIPE_VSN = 3.10.1
+HIPE_VSN = 3.10.2
diff --git a/lib/ic/doc/src/notes.xml b/lib/ic/doc/src/notes.xml
index 4789b1e0c7..7169a58543 100644
--- a/lib/ic/doc/src/notes.xml
+++ b/lib/ic/doc/src/notes.xml
@@ -30,7 +30,23 @@
<file>notes.xml</file>
</header>
- <section><title>IC 4.3.1</title>
+ <section><title>IC 4.3.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed some compilation warnings on miscellaneous
+ platforms. Thanks to Anthony Ramine.</p>
+ <p>
+ Own Id: OTP-11086</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>IC 4.3.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/ic/src/icparse.yrl b/lib/ic/src/icparse.yrl
index b0286d57f4..420067fa09 100644
--- a/lib/ic/src/icparse.yrl
+++ b/lib/ic/src/icparse.yrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/ic/vsn.mk b/lib/ic/vsn.mk
index 9fd8aedb63..53b81ad731 100644
--- a/lib/ic/vsn.mk
+++ b/lib/ic/vsn.mk
@@ -1 +1 @@
-IC_VSN = 4.3.1
+IC_VSN = 4.3.2
diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml
index f1702aa00d..c456c59b47 100644
--- a/lib/inets/doc/src/notes.xml
+++ b/lib/inets/doc/src/notes.xml
@@ -33,7 +33,66 @@
</header>
- <section><title>Inets 5.9.4</title>
+ <section><title>Inets 5.9.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Reverted incorrect commit that broke cookie handling when
+ using httpc-profiles.</p>
+ <p>
+ Own Id: OTP-10956</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Fix http_request:http_headers/1 to send content-length
+ when length is zero. Thanks to CA Meijer.</p>
+ <p>
+ Own Id: OTP-10934</p>
+ </item>
+ <item>
+ <p>
+ Integrate elliptic curve contribution from Andreas
+ Schultz </p>
+ <p>
+ In order to be able to support elliptic curve cipher
+ suites in SSL/TLS, additions to handle elliptic curve
+ infrastructure has been added to public_key and crypto.</p>
+ <p>
+ This also has resulted in a rewrite of the crypto API to
+ gain consistency and remove unnecessary overhead. All OTP
+ applications using crypto has been updated to use the new
+ API.</p>
+ <p>
+ Impact: Elliptic curve cryptography (ECC) offers
+ equivalent security with smaller key sizes than other
+ public key algorithms. Smaller key sizes result in
+ savings for power, memory, bandwidth, and computational
+ cost that make ECC especially attractive for constrained
+ environments.</p>
+ <p>
+ Own Id: OTP-11009</p>
+ </item>
+ <item>
+ <p>
+ Fix {stream, {self, once}} in httpc to work as expected.
+ Thanks to Masatake Daimon</p>
+ <p>
+ Own Id: OTP-11122</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 5.9.4</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/inets/src/http_client/httpc.erl b/lib/inets/src/http_client/httpc.erl
index 64a60b82aa..41bba7995e 100644
--- a/lib/inets/src/http_client/httpc.erl
+++ b/lib/inets/src/http_client/httpc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/inets/src/http_lib/http_chunk.erl b/lib/inets/src/http_lib/http_chunk.erl
index 24c939e80c..d15d7ba49a 100644
--- a/lib/inets/src/http_lib/http_chunk.erl
+++ b/lib/inets/src/http_lib/http_chunk.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/inets/src/http_lib/http_request.erl b/lib/inets/src/http_lib/http_request.erl
index fbfbe7c632..aa9f9f6774 100644
--- a/lib/inets/src/http_lib/http_request.erl
+++ b/lib/inets/src/http_lib/http_request.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/inets/test/http_format_SUITE.erl b/lib/inets/test/http_format_SUITE.erl
index c913964094..c5920a3968 100644
--- a/lib/inets/test/http_format_SUITE.erl
+++ b/lib/inets/test/http_format_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk
index f5abaf9764..3f464c8684 100644
--- a/lib/inets/vsn.mk
+++ b/lib/inets/vsn.mk
@@ -18,7 +18,7 @@
# %CopyrightEnd%
APPLICATION = inets
-INETS_VSN = 5.9.4
+INETS_VSN = 5.9.5
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)"
diff --git a/lib/kernel/doc/src/heart.xml b/lib/kernel/doc/src/heart.xml
index f5028a5559..3ec33d2f18 100644
--- a/lib/kernel/doc/src/heart.xml
+++ b/lib/kernel/doc/src/heart.xml
@@ -118,8 +118,13 @@
the system. The new Erlang runtime system will (if it
misbehaves) use the environment variable
<c>HEART_COMMAND</c> to reboot.</p>
- <p>Limitations: The length of the <c><anno>Cmd</anno></c> command string
- must be less than 2047 characters.</p>
+
+ <p>Limitations: The <c><anno>Cmd</anno></c> command string
+ will be sent to the heart program as a ISO-latin-1 or UTF-8
+ encoded binary depending on the file name encoding mode of the
+ emulator (see
+ <seealso marker="kernel:file#native_name_encoding/0"><c>file:native_name_encoding/0</c></seealso>).
+ The size of the encoded binary must be less than 2047 bytes.</p>
</desc>
</func>
<func>
diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml
index 1b14d11e62..6b703b7c2b 100644
--- a/lib/kernel/doc/src/notes.xml
+++ b/lib/kernel/doc/src/notes.xml
@@ -30,6 +30,91 @@
</header>
<p>This document describes the changes made to the Kernel application.</p>
+<section><title>Kernel 2.16.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ A bug in prim_inet has been corrected. If the port owner
+ was killed at a bad time while closing the socket port
+ the port could become orphaned hence causing port and
+ socket leaking. Reported by Fred Herbert, Dmitry Belyaev
+ and others.</p>
+ <p>
+ Own Id: OTP-10497 Aux Id: OTP-10562 </p>
+ </item>
+ <item>
+ <p>
+ A few bugs regarding case sensitivity for hostname
+ resolution while using e.g the internal lookup types
+ 'file' and 'dns' has been corrected. When looking up
+ hostnames ASCII letters a-z are to be regarded as the
+ same as A-Z according to RFC 4343 "Domain Name System
+ (DNS) Case Insensitivity Clarification", and this was not
+ always the case.</p>
+ <p>
+ Own Id: OTP-10689 Aux Id: seq12227 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add <c>application:ensure_started/1,2</c>. It is
+ equivavlent to <c>application:start/1,2</c> except it
+ returns <c>ok</c> for already started applications.</p>
+ <p>
+ Own Id: OTP-10910</p>
+ </item>
+ <item>
+ <p>
+ Optimize communication with file io server. Thanks to
+ Anthony Ramine.</p>
+ <p>
+ Own Id: OTP-11040</p>
+ </item>
+ <item>
+ <p>Erlang source files with non-ASCII characters are now
+ encoded in UTF-8 (instead of latin1).</p>
+ <p>
+ Own Id: OTP-11041 Aux Id: OTP-10907 </p>
+ </item>
+ <item>
+ <p>
+ Optimization of simultaneous <c>inet_db</c> operations on
+ the same socket by using a lock free implementation.</p>
+ <p>
+ Impact on the characteristics of the system: Improved
+ performance.</p>
+ <p>
+ Own Id: OTP-11074</p>
+ </item>
+ <item>
+ <p>
+ The <c>high_msgq_watermark</c> and
+ <c>low_msgq_watermark</c> <c>inet</c> socket options
+ introduced in OTP-R16A could only be set on TCP sockets.
+ These options are now generic and can be set on all types
+ of sockets.</p>
+ <p>
+ Own Id: OTP-11075 Aux Id: OTP-10336 </p>
+ </item>
+ <item>
+ <p>
+ Fix deep list argument error under Windows in os:cmd/1.
+ Thanks to Aleksandr Vinokurov .</p>
+ <p>
+ Own Id: OTP-11104</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Kernel 2.16.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/kernel/src/gen_udp.erl b/lib/kernel/src/gen_udp.erl
index fb5737f82e..e82b11d2ef 100644
--- a/lib/kernel/src/gen_udp.erl
+++ b/lib/kernel/src/gen_udp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/kernel/src/heart.erl b/lib/kernel/src/heart.erl
index aa65c3a474..daed6dd488 100644
--- a/lib/kernel/src/heart.erl
+++ b/lib/kernel/src/heart.erl
@@ -184,14 +184,18 @@ wait_ack(Port) ->
loop(Parent, Port, Cmd) ->
_ = send_heart_beat(Port),
receive
- {From, set_cmd, NewCmd} when length(NewCmd) < 2047 ->
- _ = send_heart_cmd(Port, NewCmd),
- _ = wait_ack(Port),
- From ! {heart, ok},
- loop(Parent, Port, NewCmd);
- {From, set_cmd, NewCmd} ->
- From ! {heart, {error, {bad_cmd, NewCmd}}},
- loop(Parent, Port, Cmd);
+ {From, set_cmd, NewCmd0} ->
+ Enc = file:native_name_encoding(),
+ case catch unicode:characters_to_binary(NewCmd0,Enc,Enc) of
+ NewCmd when is_binary(NewCmd), byte_size(NewCmd) < 2047 ->
+ _ = send_heart_cmd(Port, NewCmd),
+ _ = wait_ack(Port),
+ From ! {heart, ok},
+ loop(Parent, Port, NewCmd);
+ _ ->
+ From ! {heart, {error, {bad_cmd, NewCmd0}}},
+ loop(Parent, Port, Cmd)
+ end;
{From, clear_cmd} ->
From ! {heart, ok},
_ = send_heart_cmd(Port, ""),
diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl
index 1a1f7b8cbc..6f65968fc2 100644
--- a/lib/kernel/src/inet.erl
+++ b/lib/kernel/src/inet.erl
@@ -947,21 +947,34 @@ gethostbyname_self(Name, Type) when is_atom(Name) ->
gethostbyname_self(Name, Type)
when is_list(Name), Type =:= inet;
is_list(Name), Type =:= inet6 ->
- case inet_db:gethostname() of
- Name ->
- {ok,make_hostent(Name,
- [translate_ip(loopback, Type)],
- [], Type)};
- Self ->
+ N = inet_db:tolower(Name),
+ Self = inet_db:gethostname(),
+ %%
+ %% This is the final fallback that pretends /etc/hosts has got
+ %% a line for the hostname on the loopback address.
+ %% Lookups into /etc/hosts are case insensitive and return
+ %% what is in the file. Therefore the letter case may differ between
+ %% the returned hostent record and the hostname that was asked for.
+ %%
+ case inet_db:tolower(Self) of
+ N ->
+ {ok,
+ make_hostent(
+ Self, [translate_ip(loopback, Type)], [], Type)};
+ _ ->
case inet_db:res_option(domain) of
- "" -> {error,nxdomain};
+ "" ->
+ {error,nxdomain};
Domain ->
- case lists:append([Self,".",Domain]) of
- Name ->
- {ok,make_hostent(Name,
- [translate_ip(loopback, Type)],
- [], Type)};
- _ -> {error,nxdomain}
+ FQDN = lists:append([Self,".",Domain]),
+ case inet_db:tolower(FQDN) of
+ N ->
+ {ok,
+ make_hostent(
+ FQDN,
+ [translate_ip(loopback, Type)], [], Type)};
+ _ ->
+ {error,nxdomain}
end
end
end;
diff --git a/lib/kernel/src/inet_db.erl b/lib/kernel/src/inet_db.erl
index 8a2994579b..2ebdc0f554 100644
--- a/lib/kernel/src/inet_db.erl
+++ b/lib/kernel/src/inet_db.erl
@@ -845,7 +845,8 @@ init([]) ->
process_flag(trap_exit, true),
Db = ets:new(inet_db, [public, named_table]),
reset_db(Db),
- Cache = ets:new(inet_cache, [public, bag, {keypos,2}, named_table]),
+ CacheOpts = [public, bag, {keypos,#dns_rr.domain}, named_table],
+ Cache = ets:new(inet_cache, CacheOpts),
BynameOpts = [protected, bag, named_table, {keypos,1}],
ByaddrOpts = [protected, bag, named_table, {keypos,3}],
HostsByname = ets:new(inet_hosts_byname, BynameOpts),
@@ -901,15 +902,21 @@ reset_db(Db) ->
handle_call(Request, From, #state{db=Db}=State) ->
case Request of
{load_hosts_file,IPNmAs} when is_list(IPNmAs) ->
- NIPs = lists:flatten([ [{N,if tuple_size(IP) =:= 4 -> inet;
- tuple_size(IP) =:= 8 -> inet6
- end,IP} || N <- [Nm|As]]
- || {IP,Nm,As} <- IPNmAs]),
+ NIPs =
+ lists:flatten(
+ [ [{N,
+ if tuple_size(IP) =:= 4 -> inet;
+ tuple_size(IP) =:= 8 -> inet6
+ end,IP} || N <- [Nm|As]]
+ || {IP,Nm,As} <- IPNmAs]),
Byname = State#state.hosts_file_byname,
Byaddr = State#state.hosts_file_byaddr,
ets:delete_all_objects(Byname),
ets:delete_all_objects(Byaddr),
- ets:insert(Byname, NIPs),
+ %% Byname has lowercased names while Byaddr keep the name casing.
+ %% This is to be able to reconstruct the original
+ %% /etc/hosts entry.
+ ets:insert(Byname, [{tolower(N),Type,IP} || {N,Type,IP} <- NIPs]),
ets:insert(Byaddr, NIPs),
{reply, ok, State};
@@ -938,16 +945,14 @@ handle_call(Request, From, #state{db=Db}=State) ->
{reply, ok, State};
{add_rr, RR} when is_record(RR, dns_rr) ->
- RR1 = lower_rr(RR),
- ?dbg("add_rr: ~p~n", [RR1]),
- do_add_rr(RR1, Db, State),
+ ?dbg("add_rr: ~p~n", [RR]),
+ do_add_rr(RR, Db, State),
{reply, ok, State};
{del_rr, RR} when is_record(RR, dns_rr) ->
- RR1 = lower_rr(RR),
%% note. del_rr will handle wildcards !!!
Cache = State#state.cache,
- ets:match_delete(Cache, RR1),
+ ets:match_delete(Cache, RR),
{reply, ok, State};
{lookup_rr, Domain, Class, Type} ->
@@ -1225,15 +1230,19 @@ handle_set_file(ParseFun, Bin, From, State) ->
handle_rc_list(Opts, From, State)
end.
+%% Byname has lowercased names while Byaddr keep the name casing.
+%% This is to be able to reconstruct the original /etc/hosts entry.
+
do_add_host(Byname, Byaddr, Names, Type, IP) ->
do_del_host(Byname, Byaddr, IP),
- NIPs = [{tolower(N),Type,IP} || N <- Names],
- ets:insert(Byname, NIPs),
- ets:insert(Byaddr, NIPs),
+ ets:insert(Byname, [{tolower(N),Type,IP} || N <- Names]),
+ ets:insert(Byaddr, [{N,Type,IP} || N <- Names]),
ok.
do_del_host(Byname, Byaddr, IP) ->
- _ = [ets:delete_object(Byname, NIP) || NIP <- ets:lookup(Byaddr, IP)],
+ _ =
+ [ets:delete_object(Byname, {tolower(Name),Type,Addr}) ||
+ {Name,Type,Addr} <- ets:lookup(Byaddr, IP)],
ets:delete(Byaddr, IP),
ok.
@@ -1369,7 +1378,7 @@ times() ->
%% lookup and remove old entries
do_lookup_rr(Domain, Class, Type) ->
- match_rr(#dns_rr{domain = tolower(Domain), class = Class,type = Type,
+ match_rr(#dns_rr{domain = Domain, class = Class,type = Type,
cnt = '_', tm = '_', ttl = '_',
bm = '_', func = '_', data = '_'}).
@@ -1393,23 +1402,20 @@ filter_rr([], _Time) -> [].
%%
-%% Lower case the domain name before storage
-%%
-lower_rr(RR) ->
- Dn = RR#dns_rr.domain,
- if is_list(Dn) ->
- RR#dns_rr { domain = tolower(Dn) };
- true -> RR
- end.
-
+%% Case fold upper-case to lower-case according to RFC 4343
+%% "Domain Name System (DNS) Case Insensitivity Clarification".
%%
-%% Map upper-case to lower-case
%% NOTE: this code is in kernel and we don't want to relay
-%% to much on stdlib
+%% to much on stdlib. Furthermore string:to_lower/1
+%% does not follow RFC 4343.
%%
tolower([]) -> [];
-tolower([C|Cs]) when C >= $A, C =< $Z -> [(C-$A)+$a|tolower(Cs)];
-tolower([C|Cs]) -> [C|tolower(Cs)].
+tolower([C|Cs]) when is_integer(C) ->
+ if C >= $A, C =< $Z ->
+ [(C-$A)+$a|tolower(Cs)];
+ true ->
+ [C|tolower(Cs)]
+ end.
dn_ip6_int(A,B,C,D,E,F,G,H) ->
dnib(H) ++ dnib(G) ++ dnib(F) ++ dnib(E) ++
diff --git a/lib/kernel/src/inet_hosts.erl b/lib/kernel/src/inet_hosts.erl
index df1d4fc0be..6e9719b4aa 100644
--- a/lib/kernel/src/inet_hosts.erl
+++ b/lib/kernel/src/inet_hosts.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -38,9 +38,12 @@ gethostbyname(_) -> {error, formerr}.
gethostbyname(Name, Type) when is_list(Name), is_atom(Type) ->
- case gethostbyname(Name, Type, inet_hosts_byname, inet_hosts_byaddr) of
+ %% Byname has lowercased names while Byaddr keep the name casing.
+ %% This is to be able to reconstruct the original /etc/hosts entry.
+ N = inet_db:tolower(Name),
+ case gethostbyname(N, Type, inet_hosts_byname, inet_hosts_byaddr) of
false ->
- case gethostbyname(Name, Type,
+ case gethostbyname(N, Type,
inet_hosts_file_byname,
inet_hosts_file_byaddr) of
false -> {error,nxdomain};
diff --git a/lib/kernel/src/inet_int.hrl b/lib/kernel/src/inet_int.hrl
index a01c733d81..67a99913a1 100644
--- a/lib/kernel/src/inet_int.hrl
+++ b/lib/kernel/src/inet_int.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/kernel/src/inet_res.erl b/lib/kernel/src/inet_res.erl
index ab9cbf0617..6037da1d22 100644
--- a/lib/kernel/src/inet_res.erl
+++ b/lib/kernel/src/inet_res.erl
@@ -181,8 +181,8 @@ lookup(Name, Class, Type, Opts, Timeout) ->
lookup_filter({ok,#dns_rec{anlist=Answers}}, Class, Type) ->
[A#dns_rr.data || A <- Answers,
- A#dns_rr.class =:= Class,
- A#dns_rr.type =:= Type];
+ Class =:= any orelse A#dns_rr.class =:= Class,
+ Type =:= any orelse A#dns_rr.type =:= Type];
lookup_filter({error,_}, _, _) -> [].
%% --------------------------------------------------------------------------
diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl
index c5d8becfd3..e89cb44797 100644
--- a/lib/kernel/test/gen_sctp_SUITE.erl
+++ b/lib/kernel/test/gen_sctp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/kernel/test/gen_tcp_misc_SUITE.erl b/lib/kernel/test/gen_tcp_misc_SUITE.erl
index 2d5827282f..ee271fbdfa 100644
--- a/lib/kernel/test/gen_tcp_misc_SUITE.erl
+++ b/lib/kernel/test/gen_tcp_misc_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/kernel/test/global_SUITE_data/global_trace.erl b/lib/kernel/test/global_SUITE_data/global_trace.erl
index 7da4980263..1396d86c79 100644
--- a/lib/kernel/test/global_SUITE_data/global_trace.erl
+++ b/lib/kernel/test/global_SUITE_data/global_trace.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl
index 1f7724d0dc..62ba95e1a3 100644
--- a/lib/kernel/test/inet_SUITE.erl
+++ b/lib/kernel/test/inet_SUITE.erl
@@ -183,80 +183,74 @@ t_gethostbyname(Config) when is_list(Config) ->
h_addr_list = [IP]},
?line HEntF_ = HEntF,
?line check_elems([{HEnt#hostent.h_aliases,[[],Aliases]}]),
+ %%
+ ?line FullNameU = toupper(FullName),
+ ?line {ok,HEntU} = inet:gethostbyname(FullNameU),
+ ?line FullNameU = toupper(HEntU#hostent.h_name),
+ ?line #hostent{
+ h_addrtype = inet,
+ h_length = 4,
+ h_addr_list = [IP]} = HEntU,
+ ?line check_elems(
+ [{[toupper(H) || H <- HEntU#hostent.h_aliases],
+ [[],[toupper(A) || A <- Aliases]]}]),
?line {DName, _DFullName, _DIPStr, _DIP, _, _, _} =
ct:get_config(test_dummy_host),
?line {error,nxdomain} = inet:gethostbyname(DName),
- ?line {error,nxdomain} = inet:gethostbyname(IP_46_Str).
+ ?line {error,nxdomain} = inet:gethostbyname(IP_46_Str),
+ ok.
t_gethostbyname_v6() -> required(v6).
t_gethostbyname_v6(doc) -> "Test the inet:gethostbyname/1 inet6 function.";
t_gethostbyname_v6(suite) -> [];
t_gethostbyname_v6(Config) when is_list(Config) ->
- ?line {Name, _, _, _,Aliases,IP_46_Str,IP_46} =
- ct:get_config(test_host_ipv4_only),
+ {Name, FullName, IPStr, IP, Aliases} =
+ ct:get_config(test_host_ipv6_only),
- case {inet:gethostbyname(IP_46_Str, inet6),
- inet:gethostbyname(Name, inet6)} of
- {{ok,HEnt46},{ok,_}} ->
- ?line HEnt46_ = HEnt46#hostent{h_name = IP_46_Str,
- h_addrtype = inet6,
- h_length = 16,
- h_addr_list = [IP_46]},
- ?line HEnt46_ = HEnt46,
- ?line check_elems([{HEnt46#hostent.h_aliases,[[],Aliases]}]),
-
- ?line {Name6, FullName6, IPStr6, IP6, Aliases6} =
- ct:get_config(test_host_ipv6_only),
- ?line {ok,_} = inet:gethostbyname(IPStr6, inet6),
- ?line {ok,HEnt6} = inet:gethostbyname(Name6, inet6),
- ?line {ok,HEnt6} = inet:gethostbyname(list_to_atom(Name6), inet6),
- ?line case HEnt6#hostent.h_addr_list of
- [IP6] -> % ipv6 ok
- ?line HEnt6_ = HEnt6#hostent{h_addrtype = inet6,
- h_length = 16,
- h_addr_list = [IP6]},
- ?line HEnt6_ = HEnt6,
- ?line check_elems([{HEnt6#hostent.h_name,[Name6,FullName6]},
- {HEnt6#hostent.h_aliases,[[],Aliases6]}]);
- _ -> % ipv4 compatible addr
- ?line {ok,HEnt4} = inet:gethostbyname(Name6, inet),
- ?line [IP4] = HEnt4#hostent.h_addr_list,
- ?line {ok,IP46_2} =
- inet_parse:ipv6_address("::ffff:"++inet_parse:ntoa(IP4)),
- ?line HEnt6_ = HEnt6#hostent{h_addrtype = inet6,
- h_length = 16,
- h_addr_list = [IP46_2]},
- ?line HEnt6_ = HEnt6,
- ?line check_elems([{HEnt6#hostent.h_name,[Name6,FullName6]}])
- end,
-
- ?line {ok,HEntF6} = inet:gethostbyname(FullName6, inet6),
- ?line case HEntF6#hostent.h_addr_list of
- [IP6] -> % ipv6 ok
- ?line HEntF6_ = HEntF6#hostent{h_name = FullName6,
- h_addrtype = inet6,
- h_length = 16,
- h_addr_list = [IP6]},
- ?line HEntF6_ = HEntF6,
- ?line check_elems([{HEntF6#hostent.h_aliases,[[],Aliases6]}]);
- _ -> % ipv4 compatible addr
- ?line {ok,HEntF4} = inet:gethostbyname(FullName6, inet),
- ?line [IPF4] = HEntF4#hostent.h_addr_list,
- ?line {ok,IPF46_2} =
- inet_parse:ipv6_address("::ffff:"++inet_parse:ntoa(IPF4)),
- ?line HEntF6_ = HEntF6#hostent{h_addrtype = inet6,
- h_length = 16,
- h_addr_list = [IPF46_2]},
- ?line HEntF6_ = HEntF6,
- ?line check_elems([{HEntF6#hostent.h_name,[Name6,FullName6]}])
- end,
-
- ?line {DName6, _DFullName6, _DIPStr6, _DIP6, _} =
- ct:get_config(test_dummy_ipv6_host),
- ?line {error,nxdomain} = inet:gethostbyname(DName6, inet6),
- ok;
- {_,_} ->
+ case inet:gethostbyname(Name, inet6) of
+ {ok,HEnt} ->
+ {ok,_} = inet:gethostbyname(IPStr, inet6),
+ {ok,HEnt} = inet:gethostbyname(list_to_atom(Name), inet6),
+ case HEnt#hostent.h_addr_list of
+ [IP] -> % IPv6 address
+ #hostent{h_addrtype = inet6,
+ h_length = 16} = HEnt,
+ check_elems(
+ [{HEnt#hostent.h_name,[Name,FullName]},
+ {HEnt#hostent.h_aliases,[[],Aliases]}]);
+ [IP46] -> % IPv4 compatible address
+ {ok,HEnt4} = inet:gethostbyname(Name, inet),
+ #hostent{h_addrtype = inet,
+ h_length = 4,
+ h_addr_list = [IP4]} = HEnt4,
+ {ok,IP46} =
+ inet_parse:ipv6_address(
+ "::ffff:" ++ inet_parse:ntoa(IP4)),
+ check_elems(
+ [{HEnt#hostent.h_name,[Name,FullName]}])
+ end,
+
+ {ok,HEntF} = inet:gethostbyname(FullName, inet6),
+ case HEntF#hostent.h_addr_list of
+ [IP] -> % IPv6 address
+ #hostent{h_name = FullName,
+ h_addrtype = inet6,
+ h_length = 16} = HEntF,
+ check_elems(
+ [{HEnt#hostent.h_aliases,[[],Aliases]}]);
+ [IP46F] -> % IPv4 compatible address
+ {ok,HEnt4F} = inet:gethostbyname(FullName, inet),
+ #hostent{h_addrtype = inet,
+ h_length = 4,
+ h_addr_list = [IP4F]} = HEnt4F,
+ {ok,IP46F} =
+ inet_parse:ipv6_address(
+ "::ffff:" ++ inet_parse:ntoa(IP4F)),
+ check_elems(
+ [{HEntF#hostent.h_name,[Name,FullName]}])
+ end;
+ _ ->
{skip, "IPv6 is not supported on this host"}
end.
@@ -290,47 +284,35 @@ t_getaddr(Config) when is_list(Config) ->
?line {error,nxdomain} = inet:getaddr(DName, inet),
?line {error,nxdomain} = inet:getaddr(DFullName, inet),
?line {ok,DIP} = inet:getaddr(DIPStr, inet),
- ?line {ok,DIP} = inet:getaddr(DIP, inet).
+ ?line {ok,DIP} = inet:getaddr(DIP, inet),
+ ok.
t_getaddr_v6() -> required(v4) ++ required(v6).
t_getaddr_v6(doc) -> "Test the inet:getaddr/2 function.";
t_getaddr_v6(suite) -> [];
t_getaddr_v6(Config) when is_list(Config) ->
- ?line {Name,FullName,IPStr,_IP,_,IP_46_Str,IP46} =
- ct:get_config(test_host_ipv4_only),
- case {inet:getaddr(IP_46_Str, inet6),inet:getaddr(Name, inet6)} of
- {{ok,IP46},{ok,V4Addr}} when V4Addr /= {0,0,0,0,0,0,0,1} ->
- %% Since we suceeded in parsing an IPv6 address string and
- %% look up the name, this computer fully supports IPv6.
- ?line {ok,IP46} = inet:getaddr(IP46, inet6),
- ?line {ok,IP46} = inet:getaddr(Name, inet6),
- ?line {ok,IP46} = inet:getaddr(FullName, inet6),
- ?line {ok,IP46} = inet:getaddr(IPStr, inet6),
-%% ?line IP4toIP6 = inet:getaddr(IPStr, inet6),
-%% ?line case IP4toIP6 of
-%% {ok,IP46} ->
-%% ?line ok;
-%% {error,nxdomain} ->
-%% ?line false =
-%% lists:member(native,
-%% inet_db:res_option(lookup))
-%% end,
- ?line {Name6, FullName6, IPStr6, IP6, _} =
- ct:get_config(test_host_ipv6_only),
- ?line {ok,_} = inet:getaddr(list_to_atom(Name6), inet6),
- ?line {ok,_} = inet:getaddr(Name6, inet6),
- ?line {ok,_} = inet:getaddr(FullName6, inet6),
- ?line {ok,IP6} = inet:getaddr(IP6, inet6),
- ?line {ok,IP6} = inet:getaddr(IPStr6, inet6),
-
- ?line {DName6, DFullName6, DIPStr6, DIP6, _} =
+ {Name,FullName,IPStr,IP,_} =
+ ct:get_config(test_host_ipv6_only),
+
+ case inet:getaddr(Name, inet6) of
+ {ok,Addr} ->
+ IP = Addr,
+ {ok,IP} = inet:getaddr(toupper(Name), inet6),
+ {ok,IP} = inet:getaddr(list_to_atom(Name), inet6),
+ {ok,IP} = inet:getaddr(list_to_atom(toupper(Name)), inet6),
+ {ok,IP} = inet:getaddr(FullName, inet6),
+ {ok,IP} = inet:getaddr(toupper(FullName), inet6),
+ {ok,IP} = inet:getaddr(IP, inet6),
+ {ok,IP} = inet:getaddr(IPStr, inet6),
+ %%
+ {DName,DFullName,DIPStr,DIP,_} =
ct:get_config(test_dummy_ipv6_host),
- ?line {error,nxdomain} = inet:getaddr(DName6, inet6),
- ?line {error,nxdomain} = inet:getaddr(DFullName6, inet6),
- ?line {ok,DIP6} = inet:getaddr(DIPStr6, inet6),
- ?line {ok,DIP6} = inet:getaddr(DIP6, inet6),
+ {error,nxdomain} = inet:getaddr(DName, inet6),
+ {error,nxdomain} = inet:getaddr(DFullName, inet6),
+ {ok,DIP} = inet:getaddr(DIPStr, inet6),
+ {ok,DIP} = inet:getaddr(DIP, inet6),
ok;
- {_,_} ->
+ _ ->
{skip, "IPv6 is not supported on this host"}
end.
@@ -608,8 +590,12 @@ t_parse_address(Func, [String|L]) ->
t_parse_address(Func, L).
parse_strict_address(Config) when is_list(Config) ->
- {ok, Ipv4} = inet:parse_strict_address("127.0.0.1"),
- {ok, Ipv6} = inet:parse_strict_address("c11:0c22:5c33:c440:55c0:c66c:77:0088").
+ {ok, {127,0,0,1}} =
+ inet:parse_strict_address("127.0.0.1"),
+ {ok, {3089,3106,23603,50240,21952,50796,119,136}} =
+ inet:parse_strict_address("c11:0c22:5c33:c440:55c0:c66c:77:0088"),
+ {ok, {3089,3106,23603,50240,0,0,119,136}} =
+ inet:parse_strict_address("c11:0c22:5c33:c440::077:0088").
t_gethostnative(suite) ->[];
t_gethostnative(doc) ->[];
@@ -1102,3 +1088,14 @@ ip_member({127,_,_,_}, [{127,_,_,_}|_]) -> true;
ip_member(K, [K|_]) -> true;
ip_member(K, [_|T]) -> ip_member(K, T);
ip_member(_, []) -> false.
+
+%% Case fold to upper case according to RFC 4343
+%%
+toupper([C|Cs]) when is_integer(C) ->
+ if $a =< C, C =< $z ->
+ [(C - $a + $A)|toupper(Cs)];
+ true ->
+ [C|toupper(Cs)]
+ end;
+toupper([]) ->
+ [].
diff --git a/lib/kernel/test/inet_res_SUITE.erl b/lib/kernel/test/inet_res_SUITE.erl
index f3ba28e4f9..1bc93e3138 100644
--- a/lib/kernel/test/inet_res_SUITE.erl
+++ b/lib/kernel/test/inet_res_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -282,6 +282,7 @@ basic(doc) ->
basic(Config) when is_list(Config) ->
NS = ns(Config),
Name = "ns.otptest",
+ NameC = caseflip(Name),
IP = {127,0,0,254},
%%
%% nslookup
@@ -292,6 +293,17 @@ basic(Config) when is_list(Config) ->
Bin1 = inet_dns:encode(Msg1),
%%io:format("Bin1 = ~w~n", [Bin1]),
{ok,Msg1} = inet_dns:decode(Bin1),
+ %% Now with scrambled case
+ {ok,Msg1b} = inet_res:nslookup(NameC, in, a, [NS]),
+ io:format("~p~n", [Msg1b]),
+ [RR1b] = inet_dns:msg(Msg1b, anlist),
+ IP = inet_dns:rr(RR1b, data),
+ Bin1b = inet_dns:encode(Msg1b),
+ %%io:format("Bin1b = ~w~n", [Bin1b]),
+ {ok,Msg1b} = inet_dns:decode(Bin1b),
+ true =
+ (tolower(inet_dns:rr(RR1, domain))
+ =:= tolower(inet_dns:rr(RR1b, domain))),
%%
%% resolve
{ok,Msg2} = inet_res:resolve(Name, in, a, [{nameservers,[NS]},verbose]),
@@ -301,15 +313,29 @@ basic(Config) when is_list(Config) ->
Bin2 = inet_dns:encode(Msg2),
%%io:format("Bin2 = ~w~n", [Bin2]),
{ok,Msg2} = inet_dns:decode(Bin2),
+ %% Now with scrambled case
+ {ok,Msg2b} = inet_res:resolve(NameC, in, a, [{nameservers,[NS]},verbose]),
+ io:format("~p~n", [Msg2b]),
+ [RR2b] = inet_dns:msg(Msg2b, anlist),
+ IP = inet_dns:rr(RR2b, data),
+ Bin2b = inet_dns:encode(Msg2b),
+ %%io:format("Bin2b = ~w~n", [Bin2b]),
+ {ok,Msg2b} = inet_dns:decode(Bin2b),
+ true =
+ (tolower(inet_dns:rr(RR2, domain))
+ =:= tolower(inet_dns:rr(RR2b, domain))),
%%
%% lookup
[IP] = inet_res:lookup(Name, in, a, [{nameservers,[NS]},verbose]),
+ [IP] = inet_res:lookup(NameC, in, a, [{nameservers,[NS]},verbose]),
%%
%% gethostbyname
{ok,#hostent{h_addr_list=[IP]}} = inet_res:gethostbyname(Name),
+ {ok,#hostent{h_addr_list=[IP]}} = inet_res:gethostbyname(NameC),
%%
%% getbyname
{ok,#hostent{h_addr_list=[IP]}} = inet_res:getbyname(Name, a),
+ {ok,#hostent{h_addr_list=[IP]}} = inet_res:getbyname(NameC, a),
ok.
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -317,63 +343,115 @@ basic(Config) when is_list(Config) ->
resolve(doc) ->
["Lookup different records using resolve/2..4"];
resolve(Config) when is_list(Config) ->
+ Class = in,
NS = ns(Config),
Domain = "otptest",
RDomain4 = "0.0.127.in-addr.arpa",
RDomain6 = "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa",
Name = "resolve."++Domain,
- L = [{in,a,Name,[{127,0,0,28}],undefined},
- {in,aaaa,Name,[{0,0,0,0,0,0,32512,28}],undefined},
- {in,cname,"cname."++Name,[Name],undefined},
- {in,a,"cname."++Name,[Name,{127,0,0,28}],undefined},
- {in,ns,"ns."++Name,[],[Name]},
- {in,soa,Domain,[],[{"ns.otptest","lsa.otptest",1,60,10,300,30}]},
+ L = [{a,Name,[{a,{127,0,0,28}}],undefined},
+ {aaaa,Name,[{aaaa,{0,0,0,0,0,0,32512,28}}],undefined},
+ {cname,"cname."++Name,[{cname,Name}],undefined},
+ {a,"cname."++Name,[{cname,Name},{a,{127,0,0,28}}],undefined},
+ {ns,"ns."++Name,[],[{ns,Name}]},
+ {soa,Domain,[],[{soa,{"ns.otptest","lsa.otptest",1,60,10,300,30}}]},
%% WKS: protocol TCP (6), services (bits) TELNET (23) and SMTP (25)
- {in,wks,"wks."++Name,[{{127,0,0,28},6,<<0,0,1,64>>}],undefined},
- {in,ptr,"28."++RDomain4,[Name],undefined},
- {in,ptr,"c.1.0.0.0.0.f.7."++RDomain6,[Name],undefined},
- {in,hinfo,Name,[{"BEAM","Erlang/OTP"}],undefined},
- {in,mx,RDomain4,[{10,"mx."++Domain}],undefined},
- {in,srv,"_srv._tcp."++Name,[{10,3,4711,Name}],undefined},
- {in,naptr,"naptr."++Name,
- [{10,5,"s","http","","_srv._tcp."++Name}],undefined},
- {in,txt,"txt."++Name,
- [["Hej ","du ","glade "],["ta ","en ","spade!"]],undefined},
- {in,mb,"mb."++Name,["mx."++Name],undefined},
- {in,mg,"mg."++Name,["lsa."++Domain],undefined},
- {in,mr,"mr."++Name,["lsa."++Domain],undefined},
- {in,minfo,"minfo."++Name,
- [{"minfo-owner."++Name,"minfo-bounce."++Name}],undefined},
- {in,any,"cname."++Name,[Name],undefined},
- {in,any,Name,[{127,0,0,28},
- {0,0,0,0,0,0,32512,28},
- {"BEAM","Erlang/OTP"}],undefined}
+ {wks,"wks."++Name,[{wks,{{127,0,0,28},6,<<0,0,1,64>>}}],undefined},
+ {ptr,"28."++RDomain4,[{ptr,Name}],undefined},
+ {ptr,"c.1.0.0.0.0.f.7."++RDomain6,[{ptr,Name}],undefined},
+ {hinfo,Name,[{hinfo,{"BEAM","Erlang/OTP"}}],undefined},
+ {mx,RDomain4,[{mx,{10,"mx."++Domain}}],undefined},
+ {srv,"_srv._tcp."++Name,[{srv,{10,3,4711,Name}}],undefined},
+ {naptr,"naptr."++Name,
+ [{naptr,{10,5,"s","http","","_srv._tcp."++Name}}],
+ undefined},
+ {txt,"txt."++Name,
+ [{txt,["Hej ","du ","glade "]},{txt,["ta ","en ","spade!"]}],
+ undefined},
+ {mb,"mb."++Name,[{mb,"mx."++Name}],undefined},
+ {mg,"mg."++Name,[{mg,"Lsa."++Domain}],undefined},
+ {mr,"mr."++Name,[{mr,"LSA."++Domain}],undefined},
+ {minfo,"minfo."++Name,
+ [{minfo,{"minfo-OWNER."++Name,"MinfoBounce."++Name}}],
+ undefined},
+ {any,"cname."++Name,[{cname,Name}],undefined},
+ {any,Name,
+ [{a,{127,0,0,28}},
+ {aaaa,{0,0,0,0,0,0,32512,28}},
+ {hinfo,{"BEAM","Erlang/OTP"}}],
+ undefined}
],
- resolve([{edns,false},{nameservers,[NS]}], L),
- resolve([{edns,0},{nameservers,[NS]}], L).
-
-resolve(_Opts, []) -> ok;
-resolve(Opts, [{Class,Type,Name,Answers,Authority}=Q|Qs]) ->
+ resolve(Class, [{edns,0},{nameservers,[NS]}], L),
+ resolve(Class, [{edns,false},{nameservers,[NS]}], L),
+ %% Again, to see ensure the cache does not mess things up
+ resolve(Class, [{edns,0},{nameservers,[NS]}], L),
+ resolve(Class, [{edns,false},{nameservers,[NS]}], L).
+
+resolve(_Class, _Opts, []) ->
+ ok;
+resolve(Class, Opts, [{Type,Nm,Answers,Authority}=Q|Qs]) ->
io:format("Query: ~p~nOptions: ~p~n", [Q,Opts]),
- {ok,Msg} = inet_res:resolve(Name, Class, Type, Opts),
+ {Name,NameC} =
+ case erlang:phash2(Q) band 4 of
+ 0 ->
+ {Nm,caseflip(Nm)};
+ _ ->
+ {caseflip(Nm),Nm}
+ end,
AnList =
if
Answers =/= undefined ->
- lists:sort(Answers);
+ normalize_answers(Answers);
true ->
undefined
end,
NsList =
if
Authority =/= undefined ->
- lists:sort(Authority);
+ normalize_answers(Authority);
true ->
undefined
end,
- case {lists:sort
- ([inet_dns:rr(RR, data) || RR <- inet_dns:msg(Msg, anlist)]),
- lists:sort
- ([inet_dns:rr(RR, data) || RR <- inet_dns:msg(Msg, nslist)])} of
+ {ok,Msg} = inet_res:resolve(Name, Class, Type, Opts),
+ check_msg(Class, Type, Msg, AnList, NsList),
+ {ok,MsgC} = inet_res:resolve(NameC, Class, Type, Opts),
+ check_msg(Class, Type, MsgC, AnList, NsList),
+ resolve(Class, Opts, Qs).
+
+
+
+normalize_answers(AnList) ->
+ lists:sort([normalize_answer(Answer) || Answer <- AnList]).
+
+normalize_answer({soa,{NS,HM,Ser,Ref,Ret,Exp,Min}}) ->
+ {tolower(NS),tolower_email(HM),Ser,Ref,Ret,Exp,Min};
+normalize_answer({mx,{Prio,DN}}) ->
+ {Prio,tolower(DN)};
+normalize_answer({srv,{Prio,Weight,Port,DN}}) ->
+ {Prio,Weight,Port,tolower(DN)};
+normalize_answer({naptr,{Order,Pref,Flags,Service,RE,Repl}}) ->
+ {Order,Pref,Flags,Service,RE,tolower(Repl)};
+normalize_answer({minfo,{RespM,ErrM}}) ->
+ {tolower_email(RespM),tolower_email(ErrM)};
+normalize_answer({T,MN}) when T =:= mg; T =:= mr ->
+ tolower_email(MN);
+normalize_answer({T,DN}) when T =:= cname; T =:= ns; T =:= ptr; T =:= mb ->
+ tolower(DN);
+normalize_answer(Answer) ->
+ Answer.
+
+check_msg(Class, Type, Msg, AnList, NsList) ->
+ io:format("check_msg Type: ~p, Msg: ~p~n.", [Type,Msg]),
+ case {normalize_answers(
+ [begin
+ Class = inet_dns:rr(RR, class),
+ {inet_dns:rr(RR, type),inet_dns:rr(RR, data)}
+ end || RR <- inet_dns:msg(Msg, anlist)]),
+ normalize_answers(
+ [begin
+ Class = inet_dns:rr(RR, class),
+ {inet_dns:rr(RR, type),inet_dns:rr(RR, data)}
+ end || RR <- inet_dns:msg(Msg, nslist)])} of
{AnList,NsList} ->
ok;
{NsList,AnList} when Type =:= ns ->
@@ -389,7 +467,7 @@ resolve(Opts, [{Class,Type,Name,Answers,Authority}=Q|Qs]) ->
end,
Buf = inet_dns:encode(Msg),
{ok,Msg} = inet_dns:decode(Buf),
- resolve(Opts, Qs).
+ ok.
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -497,6 +575,7 @@ files_monitor(Config) when is_list(Config) ->
do_files_monitor(Config) ->
Dir = ?config(priv_dir, Config),
{ok,Hostname} = inet:gethostname(),
+ io:format("Hostname = ~p.~n", [Hostname]),
FQDN =
case inet_db:res_option(domain) of
"" ->
@@ -504,11 +583,13 @@ do_files_monitor(Config) ->
_ ->
Hostname++"."++inet_db:res_option(domain)
end,
+ io:format("FQDN = ~p.~n", [FQDN]),
HostsFile = filename:join(Dir, "files_monitor_hosts"),
ResolvConf = filename:join(Dir, "files_monitor_resolv.conf"),
ok = inet_db:res_option(resolv_conf, ResolvConf),
ok = inet_db:res_option(hosts_file, HostsFile),
[] = inet_db:res_option(search),
+ %% The inet function will use its final fallback to find this host
{ok,#hostent{h_name = Hostname,
h_addrtype = inet,
h_length = 4,
@@ -521,6 +602,7 @@ do_files_monitor(Config) ->
{error,nxdomain} = inet_res:gethostbyname(FQDN),
{ok,{127,0,0,10}} = inet:getaddr("mx.otptest", inet),
{ok,{0,0,0,0,0,0,32512,28}} = inet:getaddr("resolve.otptest", inet6),
+ %% The inet function will use its final fallback to find this host
{ok,#hostent{h_name = Hostname,
h_addrtype = inet6,
h_length = 16,
@@ -603,3 +685,41 @@ ipv4_to_ipv6() -> inet_SUITE:ipv4_to_ipv6().
ipv4_to_ipv6(Config) -> inet_SUITE:ipv4_to_ipv6(Config).
host_and_addr() -> inet_SUITE:host_and_addr().
host_and_addr(Config) -> inet_SUITE:host_and_addr(Config).
+
+
+
+%% Case flip helper
+
+caseflip([C|Cs]) when is_integer(C), $a =< C, C =< $z ->
+ [(C - $a + $A)|caseflip_skip(Cs)];
+caseflip([C|Cs]) when is_integer(C), $A =< C, C =< $Z ->
+ [(C - $A + $a)|caseflip_skip(Cs)];
+caseflip([C|Cs]) ->
+ [C|caseflip(Cs)];
+caseflip([]) ->
+ [].
+
+caseflip_skip([C|Cs]) when is_integer(C), $a =< C, C =< $z ->
+ [C|caseflip(Cs)];
+caseflip_skip([C|Cs]) when is_integer(C), $A =< C, C =< $Z ->
+ [C|caseflip(Cs)];
+caseflip_skip([C|Cs]) ->
+ [C|caseflip_skip(Cs)];
+caseflip_skip([]) ->
+ [].
+
+tolower_email([$.|Cs]) ->
+ [$.|tolower(Cs)];
+tolower_email([C|Cs]) ->
+ [C|tolower_email(Cs)].
+
+%% Case fold to lower case according to RFC 4343
+%%
+tolower([C|Cs]) when is_integer(C) ->
+ if $A =< C, C =< $Z ->
+ [(C - $A + $a)|tolower(Cs)];
+ true ->
+ [C|tolower(Cs)]
+ end;
+tolower([]) ->
+ [].
diff --git a/lib/kernel/test/inet_res_SUITE_data/otptest/named_inc.conf b/lib/kernel/test/inet_res_SUITE_data/otptest/named_inc.conf
index 0b01b25204..2d68f6e59c 100644
--- a/lib/kernel/test/inet_res_SUITE_data/otptest/named_inc.conf
+++ b/lib/kernel/test/inet_res_SUITE_data/otptest/named_inc.conf
@@ -2,11 +2,11 @@ zone "." in {
type master;
file "root.zone";
};
-zone "0.0.127.in-addr.arpa" in {
+zone "0.0.127.in-addr.arpa." in {
type master;
file "0.0.127.in-addr.arpa.zone";
};
-zone "0.0.0.0.f.7.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa" in {
+zone "0.0.0.0.f.7.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa." in {
type master;
file "0.0.0.0.f.7.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.zone";
-}; \ No newline at end of file
+};
diff --git a/lib/kernel/test/inet_res_SUITE_data/otptest/root.zone b/lib/kernel/test/inet_res_SUITE_data/otptest/root.zone
index 11cba18d45..5a56eac95c 100644
--- a/lib/kernel/test/inet_res_SUITE_data/otptest/root.zone
+++ b/lib/kernel/test/inet_res_SUITE_data/otptest/root.zone
@@ -43,8 +43,8 @@ naptr.resolve.otptest IN NAPTR 10 5 "S" "HTTP" "" _srv._tcp.resolve.otptest
txt.resolve.otptest IN TXT "Hej " "du " "glade "
txt.resolve.otptest IN TXT "ta " "en " "spade!"
mb.resolve.otptest IN MB mx.resolve.otptest
-mg.resolve.otptest IN MG lsa.otptest
-mr.resolve.otptest IN MR lsa.otptest
-minfo.resolve.otptest IN MINFO minfo-owner.resolve.otptest minfo-bounce.resolve.otptest
+mg.resolve.otptest IN MG Lsa.otptest
+mr.resolve.otptest IN MR LSA.otptest
+minfo.resolve.otptest IN MINFO minfo-OWNER.resolve.otptest MinfoBounce.resolve.otptest
ns.otptest IN A 127.0.0.254
diff --git a/lib/kernel/test/inet_sockopt_SUITE.erl b/lib/kernel/test/inet_sockopt_SUITE.erl
index 185751fead..9d236a8a0a 100644
--- a/lib/kernel/test/inet_sockopt_SUITE.erl
+++ b/lib/kernel/test/inet_sockopt_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/megaco/doc/src/notes.xml b/lib/megaco/doc/src/notes.xml
index df886823fc..50b2661c57 100644
--- a/lib/megaco/doc/src/notes.xml
+++ b/lib/megaco/doc/src/notes.xml
@@ -36,7 +36,22 @@
section is the version number of Megaco.</p>
- <section><title>Megaco 3.17</title>
+ <section><title>Megaco 3.17.0.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Postscript files no longer needed for the generation
+ of PDF files have been removed. </p>
+ <p>
+ Own Id: OTP-11016</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Megaco 3.17</title>
<p>Version 3.17 supports code replacement in runtime from/to
version 3.16.0.3 and and 3.16.0.2. </p>
diff --git a/lib/megaco/vsn.mk b/lib/megaco/vsn.mk
index 68b12c0286..db956102a6 100644
--- a/lib/megaco/vsn.mk
+++ b/lib/megaco/vsn.mk
@@ -18,6 +18,6 @@
# %CopyrightEnd%
APPLICATION = megaco
-MEGACO_VSN = 3.17
+MEGACO_VSN = 3.17.0.1
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(MEGACO_VSN)$(PRE_VSN)"
diff --git a/lib/mnesia/doc/src/notes.xml b/lib/mnesia/doc/src/notes.xml
index 74061ea8b2..99a26dd281 100644
--- a/lib/mnesia/doc/src/notes.xml
+++ b/lib/mnesia/doc/src/notes.xml
@@ -38,7 +38,37 @@
thus constitutes one section in this document. The title of each
section is the version number of Mnesia.</p>
- <section><title>Mnesia 4.8</title>
+ <section><title>Mnesia 4.9</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ If mnesia:clear_table/2 was called during a table load on
+ that table, the schema record was written to the table
+ instead of clearing table.</p>
+ <p>
+ Own Id: OTP-11030 Aux Id: seq12267 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Optimize index creation for Mnesia set tables. Thanks to
+ Nick Marino.</p>
+ <p>
+ Own Id: OTP-11103</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.8</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/mnesia/src/mnesia_index.erl b/lib/mnesia/src/mnesia_index.erl
index 6f9f575d93..54db45e3ba 100644
--- a/lib/mnesia/src/mnesia_index.erl
+++ b/lib/mnesia/src/mnesia_index.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/mnesia/src/mnesia_subscr.erl b/lib/mnesia/src/mnesia_subscr.erl
index 415c69d508..8f78dc55e8 100644
--- a/lib/mnesia/src/mnesia_subscr.erl
+++ b/lib/mnesia/src/mnesia_subscr.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -447,8 +447,12 @@ deactivate(ClientPid, What, Var, SubscrTab) ->
{'EXIT', _} ->
unlink(ClientPid)
end,
- del_subscr(Var, What, ClientPid),
- {ok, node()}.
+ try
+ del_subscr(Var, What, ClientPid),
+ {ok, node()}
+ catch _:_ ->
+ {error, badarg}
+ end.
del_subscr(subscribers, _What, Pid) ->
mnesia_lib:del(subscribers, Pid);
diff --git a/lib/mnesia/test/mnesia_durability_test.erl b/lib/mnesia/test/mnesia_durability_test.erl
index 1de62a7d25..4434abaa1e 100644
--- a/lib/mnesia/test/mnesia_durability_test.erl
+++ b/lib/mnesia/test/mnesia_durability_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/mnesia/test/mnesia_evil_coverage_test.erl b/lib/mnesia/test/mnesia_evil_coverage_test.erl
index 0df245b75d..db23a39943 100644
--- a/lib/mnesia/test/mnesia_evil_coverage_test.erl
+++ b/lib/mnesia/test/mnesia_evil_coverage_test.erl
@@ -1985,6 +1985,10 @@ subscribe_standard(Config) when is_list(Config)->
?match({atomic, ok}, mnesia:create_table(Tab, Def)),
%% Check system events
+ ?match({error, {badarg, foo}}, mnesia:unsubscribe(foo)),
+ ?match({error, badarg}, mnesia:unsubscribe({table, foo})),
+ ?match(_, mnesia:unsubscribe(activity)),
+
?match({ok, N1}, mnesia:subscribe(system)),
?match({ok, N1}, mnesia:subscribe(activity)),
diff --git a/lib/mnesia/test/mnesia_isolation_test.erl b/lib/mnesia/test/mnesia_isolation_test.erl
index 3273bc4d40..d57f976d1f 100644
--- a/lib/mnesia/test/mnesia_isolation_test.erl
+++ b/lib/mnesia/test/mnesia_isolation_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -613,11 +613,11 @@ unbound2(Config) when is_list(Config) ->
?match_receive({B, continuing}),
%% B should now be in lock queue.
- A ! continue,
- ?match_receive({A, {atomic, ok}}),
- ?match_receive({B, {atomic, [{ul,{key,{17,42}},val}]}}),
+ A ! continue,
+ ?match_multi_receive([{A, {atomic, ok}},
+ {B, {atomic, [{ul,{key,{17,42}},val}]}}]),
ok.
-
+
receiver() ->
receive
{_Pid, begin_trans} ->
diff --git a/lib/mnesia/vsn.mk b/lib/mnesia/vsn.mk
index 8cd97342af..d7a132bc1a 100644
--- a/lib/mnesia/vsn.mk
+++ b/lib/mnesia/vsn.mk
@@ -1 +1 @@
-MNESIA_VSN = 4.8
+MNESIA_VSN = 4.9
diff --git a/lib/observer/doc/src/notes.xml b/lib/observer/doc/src/notes.xml
index b344ee40cf..998a4e4f9f 100644
--- a/lib/observer/doc/src/notes.xml
+++ b/lib/observer/doc/src/notes.xml
@@ -31,6 +31,69 @@
<p>This document describes the changes made to the Observer
application.</p>
+<section><title>Observer 1.3.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Some bugs related to calculation of CPU/scheduler
+ utilization in observer are corrected.</p>
+ <p>
+ Current function for a process is accepted to be
+ 'undefined' when running hipe.</p>
+ <p>
+ Own Id: OTP-10894</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ <list> <item> The new Memory field from a crash dump is
+ now presented by crashdump viewer, both in the process
+ overview and in the process detail page. </item> <item> A
+ summary of blocks- and carriers sizes is added to the
+ allocator information page in the crashdump viewer.
+ </item> </list></p>
+ <p>
+ Own Id: OTP-10604 Aux Id: kunagi-336 [247] </p>
+ </item>
+ <item>
+ <p>
+ Use "open" as default browser for crashdump viewer on Mac
+ OS X. Thanks to Magnus Henoch.</p>
+ <p>
+ Own Id: OTP-10929</p>
+ </item>
+ <item>
+ <p>
+ Fix observer table viewer crash on formatting improper
+ lists. Thanks to Andrey Tsirulev</p>
+ <p>
+ Own Id: OTP-10931</p>
+ </item>
+ <item>
+ <p> Postscript files no longer needed for the generation
+ of PDF files have been removed. </p>
+ <p>
+ Own Id: OTP-11016</p>
+ </item>
+ <item>
+ <p>
+ Add processes state view in observer. Thanks to Eric
+ Pailleau.</p>
+ <p>
+ Own Id: OTP-11136</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Observer 1.3</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/observer/src/observer_procinfo.erl b/lib/observer/src/observer_procinfo.erl
index f234218017..98d0403139 100644
--- a/lib/observer/src/observer_procinfo.erl
+++ b/lib/observer/src/observer_procinfo.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/observer/src/observer_tv_table.erl b/lib/observer/src/observer_tv_table.erl
index 83619414ad..b4832d9599 100644
--- a/lib/observer/src/observer_tv_table.erl
+++ b/lib/observer/src/observer_tv_table.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/observer/vsn.mk b/lib/observer/vsn.mk
index 1ff1b3ec52..96d9d885da 100644
--- a/lib/observer/vsn.mk
+++ b/lib/observer/vsn.mk
@@ -1 +1 @@
-OBSERVER_VSN = 1.3
+OBSERVER_VSN = 1.3.1
diff --git a/lib/odbc/doc/src/notes.xml b/lib/odbc/doc/src/notes.xml
index 9acf9f1310..a1c6f999e0 100644
--- a/lib/odbc/doc/src/notes.xml
+++ b/lib/odbc/doc/src/notes.xml
@@ -31,7 +31,36 @@
<p>This document describes the changes made to the odbc application.
</p>
- <section><title>ODBC 2.10.15</title>
+ <section><title>ODBC 2.10.16</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Fix a 64bit related bug in odbcserver. Thanks to Satoshi
+ Kinoshita.</p>
+ <p>
+ Own Id: OTP-10993</p>
+ </item>
+ <item>
+ <p> Postscript files no longer needed for the generation
+ of PDF files have been removed. </p>
+ <p>
+ Own Id: OTP-11016</p>
+ </item>
+ <item>
+ <p>
+ Fix checking for odbc in standard locations when
+ "with-odbc" flag present. Thanks to Alexey Saltanov.</p>
+ <p>
+ Own Id: OTP-11126</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>ODBC 2.10.15</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/odbc/test/oracle.erl b/lib/odbc/test/oracle.erl
index 95cf7155dc..3e49a1b64d 100644
--- a/lib/odbc/test/oracle.erl
+++ b/lib/odbc/test/oracle.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/odbc/test/postgres.erl b/lib/odbc/test/postgres.erl
index 0c1761b835..99a191c46a 100644
--- a/lib/odbc/test/postgres.erl
+++ b/lib/odbc/test/postgres.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/odbc/vsn.mk b/lib/odbc/vsn.mk
index b3ffff2cf8..98a9f4ab4a 100644
--- a/lib/odbc/vsn.mk
+++ b/lib/odbc/vsn.mk
@@ -1 +1 @@
-ODBC_VSN = 2.10.15
+ODBC_VSN = 2.10.16
diff --git a/lib/orber/COSS/CosNaming/orber_cosnaming_utils.erl b/lib/orber/COSS/CosNaming/orber_cosnaming_utils.erl
index aa582d1d4e..5ec0c084e3 100644
--- a/lib/orber/COSS/CosNaming/orber_cosnaming_utils.erl
+++ b/lib/orber/COSS/CosNaming/orber_cosnaming_utils.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/orber/doc/src/notes.xml b/lib/orber/doc/src/notes.xml
index eea479717d..c4d13a5a2f 100644
--- a/lib/orber/doc/src/notes.xml
+++ b/lib/orber/doc/src/notes.xml
@@ -33,7 +33,22 @@
</header>
- <section><title>Orber 3.6.26</title>
+ <section><title>Orber 3.6.26.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Postscript files no longer needed for the generation
+ of PDF files have been removed. </p>
+ <p>
+ Own Id: OTP-11016</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Orber 3.6.26</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/orber/src/orber_env.erl b/lib/orber/src/orber_env.erl
index 67d31018ff..1c8a90bc81 100644
--- a/lib/orber/src/orber_env.erl
+++ b/lib/orber/src/orber_env.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/orber/src/orber_iiop_outproxy.erl b/lib/orber/src/orber_iiop_outproxy.erl
index 9c4e603753..8319d89088 100644
--- a/lib/orber/src/orber_iiop_outproxy.erl
+++ b/lib/orber/src/orber_iiop_outproxy.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/orber/vsn.mk b/lib/orber/vsn.mk
index 4e09532f88..7bbebc65dc 100644
--- a/lib/orber/vsn.mk
+++ b/lib/orber/vsn.mk
@@ -1,2 +1,2 @@
-ORBER_VSN = 3.6.26
+ORBER_VSN = 3.6.26.1
diff --git a/lib/os_mon/c_src/memsup.c b/lib/os_mon/c_src/memsup.c
index 8e610f951b..b5114d10ed 100644
--- a/lib/os_mon/c_src/memsup.c
+++ b/lib/os_mon/c_src/memsup.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2012. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2013. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/os_mon/doc/src/notes.xml b/lib/os_mon/doc/src/notes.xml
index 880826b270..a5099a0829 100644
--- a/lib/os_mon/doc/src/notes.xml
+++ b/lib/os_mon/doc/src/notes.xml
@@ -30,6 +30,34 @@
</header>
<p>This document describes the changes made to the OS_Mon application.</p>
+<section><title>Os_Mon 2.2.12</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Compilation fixes for NetBSD. Thanks to YAMAMOTO Takashi.</p>
+ <p>
+ Own Id: OTP-10941</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Fixed disksup:get_disk_data for SUSv3, specifically OS X
+ ML. Thanks to Sriram Melkote.</p>
+ <p>
+ Own Id: OTP-10945</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Os_Mon 2.2.11</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/os_mon/src/disksup.erl b/lib/os_mon/src/disksup.erl
index f906f33d32..8c8bbe843a 100644
--- a/lib/os_mon/src/disksup.erl
+++ b/lib/os_mon/src/disksup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/os_mon/src/nteventlog.erl b/lib/os_mon/src/nteventlog.erl
index 1fdc0f2025..97eaf07179 100644
--- a/lib/os_mon/src/nteventlog.erl
+++ b/lib/os_mon/src/nteventlog.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -121,7 +121,8 @@ code_change(_OldVsn, State, _Extra) ->
%%----------------------------------------------------------------------
start_portprogram(Identifier) ->
- Command = "\"" ++ filename:join([code:priv_dir(os_mon),"bin","nteventlog.exe"]) ++
+ Command =
+ "\"" ++ filename:join([code:priv_dir(os_mon),"bin","nteventlog.exe"]) ++
"\" " ++ make_list(Identifier),
open_port({spawn,Command},[{packet,2}]).
diff --git a/lib/os_mon/src/os_sup.erl b/lib/os_mon/src/os_sup.erl
index f5c6c138ba..3ad8b6e990 100644
--- a/lib/os_mon/src/os_sup.erl
+++ b/lib/os_mon/src/os_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -228,8 +228,8 @@ code_change(_OldVsn, State, _Extra) ->
start_portprogram() ->
OwnPath = os_mon:get_env(os_sup, os_sup_own),
Command =
- filename:join([code:priv_dir(os_mon), "bin", "ferrule"]) ++
- " " ++ OwnPath,
+ "\"" ++ filename:join([code:priv_dir(os_mon), "bin", "ferrule"]) ++
+ "\" " ++ OwnPath,
open_port({spawn, Command}, [{packet, 2}]).
%% os:cmd(cmd_str(enable)) should be done BEFORE starting os_sup
diff --git a/lib/os_mon/vsn.mk b/lib/os_mon/vsn.mk
index 7d6c5484a7..e3acea0258 100644
--- a/lib/os_mon/vsn.mk
+++ b/lib/os_mon/vsn.mk
@@ -1 +1 @@
-OS_MON_VSN = 2.2.11
+OS_MON_VSN = 2.2.12
diff --git a/lib/percept/doc/src/notes.xml b/lib/percept/doc/src/notes.xml
index 5933ed1c13..391f4d6d47 100644
--- a/lib/percept/doc/src/notes.xml
+++ b/lib/percept/doc/src/notes.xml
@@ -32,6 +32,21 @@
</header>
<p>This document describes the changes made to the Percept application.</p>
+<section><title>Percept 0.8.8.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Postscript files no longer needed for the generation
+ of PDF files have been removed. </p>
+ <p>
+ Own Id: OTP-11016</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Percept 0.8.8</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/percept/vsn.mk b/lib/percept/vsn.mk
index 07e9ac5085..2ea0341ddf 100644
--- a/lib/percept/vsn.mk
+++ b/lib/percept/vsn.mk
@@ -1 +1 @@
-PERCEPT_VSN = 0.8.8
+PERCEPT_VSN = 0.8.8.1
diff --git a/lib/public_key/doc/src/notes.xml b/lib/public_key/doc/src/notes.xml
index c72fac1a5e..e18d350dc5 100644
--- a/lib/public_key/doc/src/notes.xml
+++ b/lib/public_key/doc/src/notes.xml
@@ -34,6 +34,50 @@
<file>notes.xml</file>
</header>
+<section><title>Public_Key 0.19</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add support for ISO oids 1.3.14.3.2.29 and 1.3.14.3.2.27
+ that are somtimes used instead of the PKCS defined oids
+ 1.2.840.113549.1.1.5 and 1.2.840.10040.4.3. Add function
+ pkix_sign_types:/1 that translates oids to to algorithm
+ atoms ex:</p>
+ <p>
+ > public_key:pkix_sign_types({1,3,14,3,2,29}). {sha,rsa}</p>
+ <p>
+ Own Id: OTP-10873</p>
+ </item>
+ <item>
+ <p>
+ Integrate elliptic curve contribution from Andreas
+ Schultz </p>
+ <p>
+ In order to be able to support elliptic curve cipher
+ suites in SSL/TLS, additions to handle elliptic curve
+ infrastructure has been added to public_key and crypto.</p>
+ <p>
+ This also has resulted in a rewrite of the crypto API to
+ gain consistency and remove unnecessary overhead. All OTP
+ applications using crypto has been updated to use the new
+ API.</p>
+ <p>
+ Impact: Elliptic curve cryptography (ECC) offers
+ equivalent security with smaller key sizes than other
+ public key algorithms. Smaller key sizes result in
+ savings for power, memory, bandwidth, and computational
+ cost that make ECC especially attractive for constrained
+ environments.</p>
+ <p>
+ Own Id: OTP-11009</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Public_Key 0.18</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml
index c8bbbdfdd2..002f641f1d 100644
--- a/lib/public_key/doc/src/public_key.xml
+++ b/lib/public_key/doc/src/public_key.xml
@@ -43,7 +43,8 @@
<title>public_key</title>
<list type="bulleted">
- <item>public_key requires the crypto application.</item>
+ <item>public_key requires the crypto and asn1 applications, the latter since R16 (hopefully the runtime dependency on asn1 will
+ be removed again in the future).</item>
<item>Supports <url href="http://www.ietf.org/rfc/rfc5280.txt">RFC 5280 </url> -
Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile </item>
@@ -154,8 +155,8 @@
<funcs>
<func>
- <name> compute_key(OthersKey, MyKey)-></name>
- <name> compute_key(OthersKey, MyKey, Params)-></name>
+ <name>compute_key(OthersKey, MyKey)-></name>
+ <name>compute_key(OthersKey, MyKey, Params)-></name>
<fsummary> Compute shared secret</fsummary>
<type>
<v>OthersKey = #'ECPoint'{} | binary(), MyKey = #'ECPrivateKey'{} | binary()</v>
@@ -176,7 +177,8 @@
<v>Options = public_crypt_options()</v>
</type>
<desc>
- <p>Public key decryption using the private key.</p>
+ <p>Public key decryption using the private key. See also <seealso
+ marker="crypto:crypto#private_decrypt/4">crypto:private_decrypt/4</seealso></p>
</desc>
</func>
@@ -190,7 +192,8 @@
<v>Options = public_crypt_options()</v>
</type>
<desc>
- <p> Public key decryption using the public key.</p>
+ <p> Public key decryption using the public key. See also <seealso
+ marker="crypto:crypto#public_decrypt/4">crypto:public_decrypt/4</seealso></p>
</desc>
</func>
@@ -304,7 +307,9 @@
<v>Key = rsa_private_key()</v>
</type>
<desc>
- <p> Public key encryption using the private key.</p>
+ <p> Public key encryption using the private key.
+ See also <seealso
+ marker="crypto:crypto#private_encrypt/4">crypto:private_encrypt/4</seealso></p>
</desc>
</func>
@@ -316,7 +321,8 @@
<v>Key = rsa_public_key()</v>
</type>
<desc>
- <p> Public key encryption using the public key.</p>
+ <p> Public key encryption using the public key. See also <seealso
+ marker="crypto:crypto#public_encrypt/4">crypto:public_encrypt/4</seealso></p>
</desc>
</func>
diff --git a/lib/public_key/src/public_key.app.src b/lib/public_key/src/public_key.app.src
index 9f0677606d..736a778a4b 100644
--- a/lib/public_key/src/public_key.app.src
+++ b/lib/public_key/src/public_key.app.src
@@ -11,7 +11,7 @@
'OTP-PUB-KEY',
'PKCS-FRAME'
]},
- {applications, [crypto, kernel, stdlib]},
+ {applications, [asn1, crypto, kernel, stdlib]},
{registered, []},
{env, []}
]
diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl
index 3eea6f6ec4..cdbfe6e07c 100644
--- a/lib/public_key/src/public_key.erl
+++ b/lib/public_key/src/public_key.erl
@@ -252,8 +252,7 @@ decrypt_private(CipherText, Key) ->
decrypt_private(CipherText, Key, []).
decrypt_private(CipherText,
- #'RSAPrivateKey'{modulus = N, publicExponent = E,
- privateExponent = D} = Key,
+ #'RSAPrivateKey'{} = Key,
Options)
when is_binary(CipherText),
is_list(Options) ->
diff --git a/lib/public_key/test/pbe_SUITE.erl b/lib/public_key/test/pbe_SUITE.erl
index 254601b107..2c9b17478d 100644
--- a/lib/public_key/test/pbe_SUITE.erl
+++ b/lib/public_key/test/pbe_SUITE.erl
@@ -42,6 +42,7 @@ groups() ->
%%--------------------------------------------------------------------
init_per_suite(Config) ->
+ application:stop(crypto),
try crypto:start() of
ok ->
Config
diff --git a/lib/public_key/test/pkits_SUITE.erl b/lib/public_key/test/pkits_SUITE.erl
index c490493e13..699481b20f 100644
--- a/lib/public_key/test/pkits_SUITE.erl
+++ b/lib/public_key/test/pkits_SUITE.erl
@@ -111,14 +111,17 @@ groups() ->
%%--------------------------------------------------------------------
init_per_suite(Config) ->
+ application:stop(crypto),
try crypto:start() of
ok ->
+ application:start(asn1),
crypto_support_check(Config)
catch _:_ ->
{skip, "Crypto did not start"}
end.
end_per_suite(_Config) ->
+ application:stop(asn1),
application:stop(crypto).
%%--------------------------------------------------------------------
diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl
index 5a64140c67..c3aa2e2366 100644
--- a/lib/public_key/test/public_key_SUITE.erl
+++ b/lib/public_key/test/public_key_SUITE.erl
@@ -56,14 +56,17 @@ groups() ->
].
%%-------------------------------------------------------------------
init_per_suite(Config) ->
+ application:stop(crypto),
try crypto:start() of
ok ->
+ application:start(asn1),
Config
catch _:_ ->
{skip, "Crypto did not start"}
end.
end_per_suite(_Config) ->
+ application:stop(asn1),
application:stop(crypto).
%%-------------------------------------------------------------------
diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk
index bd20a5546b..b820f24d2a 100644
--- a/lib/public_key/vsn.mk
+++ b/lib/public_key/vsn.mk
@@ -1 +1 @@
-PUBLIC_KEY_VSN = 0.18
+PUBLIC_KEY_VSN = 0.19
diff --git a/lib/reltool/doc/src/notes.xml b/lib/reltool/doc/src/notes.xml
index 9dc2ce0e5f..8aaf4cc5d3 100644
--- a/lib/reltool/doc/src/notes.xml
+++ b/lib/reltool/doc/src/notes.xml
@@ -37,7 +37,48 @@
thus constitutes one section in this document. The title of each
section is the version number of Reltool.</p>
- <section><title>Reltool 0.6.3</title>
+ <section><title>Reltool 0.6.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix receive support in erl_eval with a BEAM module.
+ Thanks to Anthony Ramine.</p>
+ <p>
+ Own Id: OTP-11137</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Reltool used to fail if an application was mentioned in
+ the config file which was not found in the file system,
+ even if the application was explicitly excluded in the
+ config. This has been changed and will only produce a
+ warning. If the application is not explicitly excluded it
+ will still cause reltool to fail. Thanks to H�kan
+ Mattsson!</p>
+ <p>
+ Own Id: OTP-10988</p>
+ </item>
+ <item>
+ <p>
+ Fix possibly "not owner" error while file copy with
+ reltool. Thanks to Alexey Saltanov.</p>
+ <p>
+ Own Id: OTP-11099</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Reltool 0.6.3</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/reltool/src/reltool_target.erl b/lib/reltool/src/reltool_target.erl
index 9cda5dabd3..b59108d8dd 100644
--- a/lib/reltool/src/reltool_target.erl
+++ b/lib/reltool/src/reltool_target.erl
@@ -1455,10 +1455,11 @@ do_install(RelName, TargetDir) ->
{win32, _} ->
NativeRootDir = nativename(TargetDir2),
NativeErtsBinDir = nativename(ErtsBinDir),
- IniData = ["[erlang]\r\n",
- "Bindir=", NativeErtsBinDir, "\r\n",
- "Progname=erl\r\n",
- "Rootdir=", NativeRootDir, "\r\n"],
+ IniData0 = ["[erlang]\r\n",
+ "Bindir=", NativeErtsBinDir, "\r\n",
+ "Progname=erl\r\n",
+ "Rootdir=", NativeRootDir, "\r\n"],
+ IniData = unicode:characters_to_binary(IniData0),
IniFile = filename:join([BinDir, "erl.ini"]),
ok = file:write_file(IniFile, IniData);
_ ->
diff --git a/lib/reltool/test/reltool_server_SUITE.erl b/lib/reltool/test/reltool_server_SUITE.erl
index 61d8ced7fc..feeac9e099 100644
--- a/lib/reltool/test/reltool_server_SUITE.erl
+++ b/lib/reltool/test/reltool_server_SUITE.erl
@@ -807,13 +807,14 @@ create_target_unicode(Config) ->
%% If file name translation mode is unicode, then use unicode
%% characters release name (which will be used as file name for
- %% .rel, .script and .boot)
- RelNamePrefix =
+ %% .rel, .script and .boot), and install the release under a path
+ %% which icludes unicode characters.
+ {RelNamePrefix,TargetDirName} =
case file:native_name_encoding() of
utf8 ->
- "Unicode test αβ";
+ {"Unicode test αβ","target_unicode_αβ"} ;
latin1 ->
- "Unicode test"
+ {"Unicode test","target_unicode"}
end,
%% Configure the server
@@ -837,7 +838,7 @@ create_target_unicode(Config) ->
]},
%% Generate target file
- TargetDir = filename:join([?WORK_DIR, "target_unicode"]),
+ TargetDir = filename:join([?WORK_DIR, TargetDirName]),
?m(ok, reltool_utils:recursive_delete(TargetDir)),
?m(ok, file:make_dir(TargetDir)),
?log("SPEC: ~p\n", [reltool:get_target_spec([{config, Sys}])]),
diff --git a/lib/reltool/vsn.mk b/lib/reltool/vsn.mk
index 9df2fc8406..412e78f49f 100644
--- a/lib/reltool/vsn.mk
+++ b/lib/reltool/vsn.mk
@@ -1 +1 @@
-RELTOOL_VSN = 0.6.3
+RELTOOL_VSN = 0.6.4
diff --git a/lib/runtime_tools/doc/src/notes.xml b/lib/runtime_tools/doc/src/notes.xml
index 84d49cfa99..db35eba436 100644
--- a/lib/runtime_tools/doc/src/notes.xml
+++ b/lib/runtime_tools/doc/src/notes.xml
@@ -31,6 +31,37 @@
<p>This document describes the changes made to the Runtime_Tools
application.</p>
+<section><title>Runtime_Tools 1.8.11</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Some bugs related to calculation of CPU/scheduler
+ utilization in observer are corrected.</p>
+ <p>
+ Current function for a process is accepted to be
+ 'undefined' when running hipe.</p>
+ <p>
+ Own Id: OTP-10894</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Erlang source files with non-ASCII characters are now
+ encoded in UTF-8 (instead of latin1).</p>
+ <p>
+ Own Id: OTP-11041 Aux Id: OTP-10907 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Runtime_Tools 1.8.10</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/runtime_tools/vsn.mk b/lib/runtime_tools/vsn.mk
index d9c03b7e25..5faae06b53 100644
--- a/lib/runtime_tools/vsn.mk
+++ b/lib/runtime_tools/vsn.mk
@@ -1 +1 @@
-RUNTIME_TOOLS_VSN = 1.8.10
+RUNTIME_TOOLS_VSN = 1.8.11
diff --git a/lib/sasl/doc/src/notes.xml b/lib/sasl/doc/src/notes.xml
index dfc6e9949d..373d732e53 100644
--- a/lib/sasl/doc/src/notes.xml
+++ b/lib/sasl/doc/src/notes.xml
@@ -30,6 +30,22 @@
</header>
<p>This document describes the changes made to the SASL application.</p>
+<section><title>SASL 2.3.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix receive support in erl_eval with a BEAM module.
+ Thanks to Anthony Ramine.</p>
+ <p>
+ Own Id: OTP-11137</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>SASL 2.3.1</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/sasl/examples/src/target_system.erl b/lib/sasl/examples/src/target_system.erl
index ffc0fcf443..fb9e9aaaaf 100644
--- a/lib/sasl/examples/src/target_system.erl
+++ b/lib/sasl/examples/src/target_system.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -34,9 +34,9 @@ create(RelFileName,SystoolsOpts) ->
Dir = filename:dirname(RelFileName),
PlainRelFileName = filename:join(Dir,"plain"),
PlainRelFile = PlainRelFileName ++ ".rel",
- io:fwrite("Reading file: ~p ...~n", [RelFile]),
+ io:fwrite("Reading file: ~tp ...~n", [RelFile]),
{ok, [RelSpec]} = file:consult(RelFile),
- io:fwrite("Creating file: ~p from ~p ...~n",
+ io:fwrite("Creating file: ~tp from ~tp ...~n",
[PlainRelFile, RelFile]),
{release,
{RelName, RelVsn},
@@ -57,41 +57,41 @@ create(RelFileName,SystoolsOpts) ->
io:fwrite(Fd, "~p.~n", [PlainRelSpec]),
file:close(Fd),
- io:fwrite("Making \"~s.script\" and \"~s.boot\" files ...~n",
+ io:fwrite("Making \"~ts.script\" and \"~ts.boot\" files ...~n",
[PlainRelFileName,PlainRelFileName]),
make_script(PlainRelFileName,SystoolsOpts),
- io:fwrite("Making \"~s.script\" and \"~s.boot\" files ...~n",
+ io:fwrite("Making \"~ts.script\" and \"~ts.boot\" files ...~n",
[RelFileName, RelFileName]),
make_script(RelFileName,SystoolsOpts),
TarFileName = filename:join(Dir,RelFileName ++ ".tar.gz"),
- io:fwrite("Creating tar file ~p ...~n", [TarFileName]),
+ io:fwrite("Creating tar file ~tp ...~n", [TarFileName]),
make_tar(RelFileName,SystoolsOpts),
TmpDir = filename:join(Dir,"tmp"),
- io:fwrite("Creating directory ~p ...~n",[TmpDir]),
+ io:fwrite("Creating directory ~tp ...~n",[TmpDir]),
file:make_dir(TmpDir),
- io:fwrite("Extracting ~p into directory ~p ...~n", [TarFileName,TmpDir]),
+ io:fwrite("Extracting ~tp into directory ~tp ...~n", [TarFileName,TmpDir]),
extract_tar(TarFileName, TmpDir),
TmpBinDir = filename:join([TmpDir, "bin"]),
ErtsBinDir = filename:join([TmpDir, "erts-" ++ ErtsVsn, "bin"]),
- io:fwrite("Deleting \"erl\" and \"start\" in directory ~p ...~n",
+ io:fwrite("Deleting \"erl\" and \"start\" in directory ~tp ...~n",
[ErtsBinDir]),
file:delete(filename:join([ErtsBinDir, "erl"])),
file:delete(filename:join([ErtsBinDir, "start"])),
- io:fwrite("Creating temporary directory ~p ...~n", [TmpBinDir]),
+ io:fwrite("Creating temporary directory ~tp ...~n", [TmpBinDir]),
file:make_dir(TmpBinDir),
- io:fwrite("Copying file \"~s.boot\" to ~p ...~n",
+ io:fwrite("Copying file \"~ts.boot\" to ~tp ...~n",
[PlainRelFileName, filename:join([TmpBinDir, "start.boot"])]),
copy_file(PlainRelFileName++".boot",filename:join([TmpBinDir, "start.boot"])),
io:fwrite("Copying files \"epmd\", \"run_erl\" and \"to_erl\" from \n"
- "~p to ~p ...~n",
+ "~tp to ~tp ...~n",
[ErtsBinDir, TmpBinDir]),
copy_file(filename:join([ErtsBinDir, "epmd"]),
filename:join([TmpBinDir, "epmd"]), [preserve]),
@@ -101,11 +101,11 @@ create(RelFileName,SystoolsOpts) ->
filename:join([TmpBinDir, "to_erl"]), [preserve]),
StartErlDataFile = filename:join([TmpDir, "releases", "start_erl.data"]),
- io:fwrite("Creating ~p ...~n", [StartErlDataFile]),
+ io:fwrite("Creating ~tp ...~n", [StartErlDataFile]),
StartErlData = io_lib:fwrite("~s ~s~n", [ErtsVsn, RelVsn]),
write_file(StartErlDataFile, StartErlData),
- io:fwrite("Recreating tar file ~p from contents in directory ~p ...~n",
+ io:fwrite("Recreating tar file ~tp from contents in directory ~tp ...~n",
[TarFileName,TmpDir]),
{ok, Tar} = erl_tar:open(TarFileName, [write, compressed]),
%% {ok, Cwd} = file:get_cwd(),
@@ -117,14 +117,14 @@ create(RelFileName,SystoolsOpts) ->
erl_tar:add(Tar, filename:join(TmpDir,"lib"), "lib", []),
erl_tar:close(Tar),
%% file:set_cwd(Cwd),
- io:fwrite("Removing directory ~p ...~n",[TmpDir]),
+ io:fwrite("Removing directory ~tp ...~n",[TmpDir]),
remove_dir_tree(TmpDir),
ok.
install(RelFileName, RootDir) ->
TarFile = RelFileName ++ ".tar.gz",
- io:fwrite("Extracting ~p ...~n", [TarFile]),
+ io:fwrite("Extracting ~tp ...~n", [TarFile]),
extract_tar(TarFile, RootDir),
StartErlDataFile = filename:join([RootDir, "releases", "start_erl.data"]),
{ok, StartErlData} = read_txt_file(StartErlDataFile),
@@ -235,8 +235,9 @@ copy_file(Src, Dest, Opts) ->
end.
write_file(FName, Conts) ->
+ Enc = file:native_name_encoding(),
{ok, Fd} = file:open(FName, [write]),
- file:write(Fd, Conts),
+ file:write(Fd, unicode:characters_to_binary(Conts,Enc,Enc)),
file:close(Fd).
read_txt_file(File) ->
diff --git a/lib/sasl/src/erlsrv.erl b/lib/sasl/src/erlsrv.erl
index 711c1c6f1c..0d931f1779 100644
--- a/lib/sasl/src/erlsrv.erl
+++ b/lib/sasl/src/erlsrv.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -39,7 +39,7 @@ current_version() ->
run_erlsrv(Command) ->
run_erlsrv(current_version(),Command).
run_erlsrv(EVer, Command) ->
- case catch(open_port({spawn, erlsrv(EVer) ++ " " ++ Command},
+ case catch(open_port({spawn, "\"" ++ erlsrv(EVer) ++ "\" " ++ Command},
[{line,1000}, in, eof])) of
{'EXIT',{Reason,_}} ->
{port_error, Reason};
@@ -53,7 +53,7 @@ run_erlsrv(EVer, Command) ->
end.
run_erlsrv_interactive(EVer, Commands) ->
- case catch(open_port({spawn, erlsrv(EVer) ++ " readargs"},
+ case catch(open_port({spawn, "\""++ erlsrv(EVer) ++ "\" readargs"},
[{line,1000}, eof])) of
{'EXIT',{Reason,_}} ->
{port_error, Reason};
diff --git a/lib/sasl/src/release_handler.erl b/lib/sasl/src/release_handler.erl
index c1b715b970..1ad60af7c2 100644
--- a/lib/sasl/src/release_handler.erl
+++ b/lib/sasl/src/release_handler.erl
@@ -585,11 +585,9 @@ init([]) ->
handle_call({unpack_release, ReleaseName}, _From, S)
when S#state.masters == false ->
- RelDir = S#state.rel_dir,
- case catch do_unpack_release(S#state.root, RelDir,
+ case catch do_unpack_release(S#state.root, S#state.rel_dir,
ReleaseName, S#state.releases) of
{ok, NewReleases, Vsn} ->
- clean_release(RelDir, ReleaseName),
{reply, {ok, Vsn}, S#state{releases = NewReleases}};
{error, Reason} ->
{reply, {error, Reason}, S};
@@ -739,7 +737,7 @@ mk_lib_name([]) -> [].
handle_info(timeout, S) ->
case soft_purge(S#state.unpurged) of
[] ->
- timer:cancel(S#state.timer),
+ _ = timer:cancel(S#state.timer),
{noreply, S#state{unpurged = [], timer = undefined}};
Unpurged ->
{noreply, S#state{unpurged = Unpurged}}
@@ -850,15 +848,11 @@ do_unpack_release(Root, RelDir, ReleaseName, Releases) ->
Dir = filename:join([RelDir, Vsn]),
copy_file(RelFile, Dir, false),
- {ok, NewReleases, Vsn}.
+ %% Clean release
+ _ = file:delete(Tar),
+ _ = file:delete(RelFile),
-%% Note that this function is not executed by a client
-%% release_handler.
-clean_release(RelDir, ReleaseName) ->
- Tar = filename:join(RelDir, ReleaseName ++ ".tar.gz"),
- Rel = filename:join(RelDir, ReleaseName ++ ".rel"),
- file:delete(Tar),
- file:delete(Rel).
+ {ok, NewReleases, Vsn}.
check_rel(Root, RelFile, Masters) ->
check_rel(Root, RelFile, [], Masters).
@@ -1184,7 +1178,8 @@ rename_tmp_service(EVsn,TmpVsn,NewVsn) ->
{error, _Error} ->
ok;
_Data ->
- erlsrv:remove_service(ToName)
+ {ok,_} = erlsrv:remove_service(ToName),
+ ok
end,
rename_service(EVsn,FromName,ToName).
@@ -1237,13 +1232,12 @@ do_make_services_permanent(PermanentVsn,Vsn, PermanentEVsn, EVsn) ->
UpdData = erlsrv:new_service(Name, Data, []),
case erlsrv:store_service(EVsn,UpdData) of
ok ->
- erlsrv:disable_service(PermanentEVsn, PermName),
- erlsrv:enable_service(EVsn, Name),
- erlsrv:remove_service(PermName),
+ {ok,_} = erlsrv:disable_service(PermanentEVsn, PermName),
+ {ok,_} = erlsrv:enable_service(EVsn, Name),
+ {ok,_} = erlsrv:remove_service(PermName),
%%% Read comments about these above...
os:putenv("ERLSRV_SERVICE_NAME", Name),
- heart:cycle(),
- ok;
+ ok = heart:cycle();
Error4 ->
throw(Error4)
end
@@ -1288,7 +1282,7 @@ do_make_permanent(#state{releases = Releases,
_ ->
ok
end,
- init:make_permanent(filename:join(Dir, "start"), Sys),
+ ok = init:make_permanent(filename:join(Dir, "start"), Sys),
{ok, NewReleases, brutal_purge(Unpurged)};
{value, #release{status = permanent}} ->
{ok, Releases, Unpurged};
@@ -1309,13 +1303,13 @@ do_back_service(OldVersion, CurrentVersion,OldEVsn,CurrentEVsn) ->
Data ->
erlsrv:new_service(OldName, Data, [])
end,
- case erlsrv:store_service(OldEVsn,UpdData) of
- ok ->
- erlsrv:disable_service(CurrentEVsn,CurrentName),
- erlsrv:enable_service(OldEVsn,OldName);
- Error2 ->
- throw(Error2)
- end,
+ _ = case erlsrv:store_service(OldEVsn,UpdData) of
+ ok ->
+ {ok,_} = erlsrv:disable_service(CurrentEVsn,CurrentName),
+ {ok,_} = erlsrv:enable_service(OldEVsn,OldName);
+ Error2 ->
+ throw(Error2)
+ end,
OldErlSrv = filename:nativename(erlsrv:erlsrv(OldEVsn)),
CurrentErlSrv = filename:nativename(erlsrv:erlsrv(CurrentEVsn)),
case heart:set_cmd(CurrentErlSrv ++ " remove " ++ CurrentName ++
@@ -1386,10 +1380,18 @@ set_permanent_files(RelDir, _EVsn, Vsn, Masters, _Static) ->
do_remove_service(Vsn) ->
- %%% Very unconditionally remove the service.
+ %% Very unconditionally remove the service.
+ %% Note that the service could already have been removed when
+ %% making another release permanent.
ServiceName = hd(string:tokens(atom_to_list(node()),"@"))
++ "_" ++ Vsn,
- erlsrv:remove_service(ServiceName).
+ case erlsrv:get_service(ServiceName) of
+ {error, _Error} ->
+ ok;
+ _Data ->
+ {ok,_} = erlsrv:remove_service(ServiceName),
+ ok
+ end.
do_remove_release(Root, RelDir, Vsn, Releases) ->
% Decide which libs should be removed
@@ -1603,8 +1605,7 @@ do_write_file(File, Str, FileOpts) ->
case file:open(File, [write | FileOpts]) of
{ok, Fd} ->
io:put_chars(Fd, Str),
- file:close(Fd),
- ok;
+ ok = file:close(Fd);
{error, Reason} ->
{error, {Reason, File}}
end.
@@ -1651,9 +1652,9 @@ get_appls([], Res) ->
mon_nodes(true) ->
- net_kernel:monitor_nodes(true);
+ ok = net_kernel:monitor_nodes(true);
mon_nodes(false) ->
- net_kernel:monitor_nodes(false),
+ ok = net_kernel:monitor_nodes(false),
flush().
flush() ->
@@ -1691,7 +1692,7 @@ prepare_restart_nt(#release{erts_vsn = EVsn, vsn = Vsn},
{error, _} = Error2 ->
throw(Error2);
_X ->
- erlsrv:disable_service(EVsn, FutureServiceName),
+ {ok,_} = erlsrv:disable_service(EVsn, FutureServiceName),
ErlSrv = filename:nativename(erlsrv:erlsrv(EVsn)),
StartDisabled = ErlSrv ++ " start_disabled " ++ FutureServiceName,
case heart:set_cmd(StartDisabled) of
@@ -1877,8 +1878,7 @@ do_write_release(Dir, RELEASES, NewReleases) ->
case file:open(filename:join(Dir, RELEASES), [write]) of
{ok, Fd} ->
ok = io:format(Fd, "~p.~n", [NewReleases]),
- file:close(Fd),
- ok;
+ ok = file:close(Fd);
{error, Reason} ->
{error, Reason}
end.
@@ -2010,7 +2010,7 @@ do_rename_files([]) ->
%% Remove a list of files. Ignore failure.
%%-----------------------------------------------------------------
do_remove_files([File|Files]) ->
- file:delete(File),
+ _ = file:delete(File),
do_remove_files(Files);
do_remove_files([]) ->
ok.
@@ -2030,7 +2030,8 @@ do_ensure_RELEASES(RelFile) ->
%% Make a directory, ignore failures (captured later).
%%-----------------------------------------------------------------
make_dir(Dir, false) ->
- file:make_dir(Dir);
+ _ = file:make_dir(Dir),
+ ok;
make_dir(Dir, Masters) ->
lists:foreach(fun(Master) -> rpc:call(Master, file, make_dir, [Dir]) end,
Masters).
@@ -2062,12 +2063,12 @@ at_all_masters([], _, _, _) ->
%% Ignore {M,F,A} return value.
%%-----------------------------------------------------------------
takewhile(Master, Masters, M, F, A) ->
- lists:takewhile(fun(Ma) when Ma == Master ->
- false;
- (Ma) ->
- rpc:call(Ma, M, F, A),
- true
- end, Masters),
+ _ = lists:takewhile(fun(Ma) when Ma == Master ->
+ false;
+ (Ma) ->
+ rpc:call(Ma, M, F, A),
+ true
+ end, Masters),
ok.
consult(File, false) -> file:consult(File);
@@ -2205,23 +2206,23 @@ set_static_files(SrcDir, DestDir, Masters) ->
write_ini_file(RootDir,EVsn,Masters) ->
BinDir = filename:join([RootDir,"erts-"++EVsn,"bin"]),
Str0 = io_lib:format("[erlang]~n"
- "Bindir=~s~n"
+ "Bindir=~ts~n"
"Progname=erl~n"
- "Rootdir=~s~n",
+ "Rootdir=~ts~n",
[filename:nativename(BinDir),
filename:nativename(RootDir)]),
- Str = re:replace(Str0,"\\\\","\\\\\\\\",[{return,list},global]),
+ Str = re:replace(Str0,"\\\\","\\\\\\\\",[{return,list},global,unicode]),
IniFile = filename:join(BinDir,"erl.ini"),
do_write_ini_file(IniFile,Str,Masters).
do_write_ini_file(File,Data,false) ->
- case do_write_file(File, Data) of
+ case do_write_file(File, Data, [{encoding,utf8}]) of
ok -> ok;
Error -> throw(Error)
end;
do_write_ini_file(File,Data,Masters) ->
all_masters(Masters),
- safe_write_file_m(File, Data, Masters).
+ safe_write_file_m(File, Data, [{encoding,utf8}], Masters).
%%-----------------------------------------------------------------
@@ -2235,13 +2236,15 @@ do_write_ini_file(File,Data,Masters) ->
%% (as long as possible), except for 4 which is allowed to fail.
%%-----------------------------------------------------------------
safe_write_file_m(File, Data, Masters) ->
+ safe_write_file_m(File, Data, [], Masters).
+safe_write_file_m(File, Data, FileOpts, Masters) ->
Backup = File ++ ".backup",
Change = File ++ ".change",
case at_all_masters(Masters, ?MODULE, do_copy_files,
[File, [Backup]]) of
ok ->
case at_all_masters(Masters, ?MODULE, do_write_file,
- [Change, Data]) of
+ [Change, Data, FileOpts]) of
ok ->
case at_all_masters(Masters, file, rename,
[Change, File]) of
diff --git a/lib/sasl/test/installer.erl b/lib/sasl/test/installer.erl
index 709269a73c..fa404c8b7b 100644
--- a/lib/sasl/test/installer.erl
+++ b/lib/sasl/test/installer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -54,8 +54,12 @@
-export([reg_proc/1]).
-export([registered_loop/1]).
--define(print(List), {rh_print, TestNode} ! {print, {?MODULE, ?LINE}, List}).
--define(print_line(Line,List), {rh_print, TestNode} ! {print, {?MODULE, Line}, List}).
+-define(print(List),
+ io:format(user,"(~w:~w) ~tp~n",[?MODULE,?LINE,List]),
+ {rh_print, TestNode} ! {print, {?MODULE, ?LINE}, List}).
+-define(print_line(Line,List),
+ io:format(user,"(~w:~w) ~tp~n",[?MODULE,Line,List]),
+ {rh_print, TestNode} ! {print, {?MODULE, Line}, List}).
-define(fail(Term), exit({?MODULE, ?LINE, Term})).
-define(fail_line(Line,Term), exit({?MODULE, Line, Term})).
@@ -905,10 +909,9 @@ start_client(TestNode,Client,Sname) ->
start_client_unix(TestNode,Sname,Node) ->
Start = filename:join(["clients", "type1", Node, "bin", "start"]),
- Cmd = lists:concat(["env NODENAME=",Sname," ",
- filename:join(code:root_dir(), Start)]),
+ Cmd = filename:join(code:root_dir(), Start),
?print([{start_client,Sname},Cmd]),
- Res = os:cmd(Cmd),
+ Res = rh_test_lib:cmd(Cmd,[],[{"NODENAME",atom_to_list(Sname)}]),
?print([{start_client,result},Res]).
start_client_win32(TestNode,Client,ClientSname) ->
diff --git a/lib/sasl/test/release_handler_SUITE.erl b/lib/sasl/test/release_handler_SUITE.erl
index a56924d5ca..cb82fdd060 100644
--- a/lib/sasl/test/release_handler_SUITE.erl
+++ b/lib/sasl/test/release_handler_SUITE.erl
@@ -35,7 +35,8 @@ init_per_suite(Config) ->
application:start(sasl),
Config.
-end_per_suite(_Config) ->
+end_per_suite(Config) ->
+ clean_priv_dir(Config,true),
ok.
all() ->
@@ -50,7 +51,7 @@ unix_cases() ->
true -> [{group, release}];
false -> [no_run_erl]
end,
- [target_system] ++ RunErlCases ++ cases().
+ [target_system, target_system_unicode] ++ RunErlCases ++ cases().
win32_cases() ->
[{group,release} | cases()].
@@ -163,7 +164,6 @@ end_per_group(release, Config) ->
{win32,_} -> delete_all_services();
_ -> ok
end,
- clean_priv_dir(Config,true),
?t:timetrap_cancel(Dog),
Config;
end_per_group(_GroupName, Config) ->
@@ -1559,6 +1559,9 @@ eval_appup_with_restart(Conf) when is_list(Conf) ->
%% Test the example/target_system.erl module
target_system(Conf) when is_list(Conf) ->
PrivDir = priv_dir(Conf),
+ target_system1(Conf,PrivDir).
+
+target_system1(Conf,PrivDir) ->
DataDir = ?config(data_dir,Conf),
TargetCreateDir = filename:join([PrivDir,"target_system","create"]),
@@ -1567,7 +1570,6 @@ target_system(Conf) when is_list(Conf) ->
ok = filelib:ensure_dir(filename:join(TargetCreateDir,"xx")),
ok = filelib:ensure_dir(filename:join(TargetInstallDir,"xx")),
-
%% Create the .rel file
RelName = filename:join(TargetCreateDir,"ts-1.0"),
RelFile = RelName++".rel",
@@ -1607,7 +1609,8 @@ target_system(Conf) when is_list(Conf) ->
StdlibVsn = vsn(stdlib,current),
SaslVsn = vsn(sasl,current),
RelFileBasename = filename:basename(RelFile),
- true = filelib:is_dir(filename:join(LibDir,"kernel-"++KernelVsn)),
+ KernelLibDir = filename:join(LibDir,"kernel-"++KernelVsn),
+ true = filelib:is_dir(KernelLibDir),
true = filelib:is_dir(filename:join(LibDir,"stdlib-"++StdlibVsn)),
true = filelib:is_dir(filename:join(LibDir,"sasl-"++SaslVsn)),
true = filelib:is_dir(filename:join(LibDir,"a-1.0")),
@@ -1616,11 +1619,13 @@ target_system(Conf) when is_list(Conf) ->
true = filelib:is_regular(filename:join(RelDir,"start_erl.data")),
true = filelib:is_regular(filename:join(RelDir,RelFileBasename)),
true = filelib:is_dir(filename:join(RelDir,RelVsn)),
- true = filelib:is_regular(filename:join([RelDir,RelVsn,"start.boot"])),
+ StartBoot = filename:join([RelDir,RelVsn,"start.boot"]),
+ true = filelib:is_regular(StartBoot),
true = filelib:is_regular(filename:join([RelDir,RelVsn,RelFileBasename])),
BinDir = filename:join(TargetInstallDir,bin),
+ Erl = filename:join(BinDir,erl),
+ true = filelib:is_regular(Erl),
true = filelib:is_regular(filename:join(BinDir,"start.boot")),
- true = filelib:is_regular(filename:join(BinDir,erl)),
true = filelib:is_regular(filename:join(BinDir,start_erl)),
true = filelib:is_regular(filename:join(BinDir,start)),
true = filelib:is_regular(filename:join(BinDir,epmd)),
@@ -1631,9 +1636,75 @@ target_system(Conf) when is_list(Conf) ->
ErtsVsn = vsn(erts,current),
{ok,SED} = file:read_file(filename:join(RelDir,"start_erl.data")),
[ErtsVsn,RelVsn] = string:tokens(binary_to_list(SED),"\s\n"),
+
+ %% Check that installation can be started
+ Sname = list_to_atom(atom_to_list(?MODULE) ++ "-target_system"),
+ {ok,Node} = start_target_node_with_erl(Erl,Sname,StartBoot),
+
+ TargetInstallDir = rpc:call(Node,code,root_dir,[]),
+ KernelLibDir = rpc:call(Node,code,lib_dir,[kernel]),
+ [{RelName,RelVsn,_Apps,permanent}] =
+ rpc:call(Node,release_handler,which_releases,[]),
+
+ ?t:format("Target node ok:~nRootDir: ~ts~nKernelLibDir: ~ts~nRelease: ~ts",
+ [TargetInstallDir,KernelLibDir,RelName]),
+
ok.
+target_system(cleanup,_Conf) ->
+ Sname = list_to_atom(atom_to_list(?MODULE) ++ "-target_system"),
+ stop_target_node(node_name(Sname)),
+ ok.
+
+start_target_node_with_erl(Erl,Sname,Boot) ->
+ FullName = node_name(Sname),
+ FilenameMode = case file:native_name_encoding() of
+ latin1 -> "+fnl";
+ utf8 -> "+fnui"
+ end,
+ Args = [FilenameMode,"-detached", "-noinput","-sname",atom_to_list(Sname),
+ "-boot",filename:rootname(Boot)],
+ ?t:format("Starting node ~p: ~ts~n",
+ [FullName, lists:flatten([[X," "] || X <- [Erl|Args]])]),
+ case rh_test_lib:cmd(Erl,Args,[]) of
+ ok ->
+ ok = wait_nodes_up([FullName],"target_system test node"),
+ {ok,FullName};
+ Error ->
+ ?t:fail({failed_to_start_node, FullName, Error})
+ end.
+
+stop_target_node(Node) ->
+ monitor_node(Node, true),
+ _ = rpc:call(Node,erlang,halt,[]),
+ receive {nodedown, Node} -> ok end.
+%% Test that the example/target_system.erl module can create and
+%% install under a path which includes unicode characters
+target_system_unicode(Conf) when is_list(Conf) ->
+ PrivDir = priv_dir(Conf),
+ UnicodePrivDir = filename:join(PrivDir,"αβ"),
+
+ PA = filename:dirname(code:which(?MODULE)),
+
+ %% Make sure this runs on a node with unicode file name mode
+ Sname = list_to_atom(atom_to_list(?MODULE) ++ "-target_system_unicode"),
+ {ok,Node} = ?t:start_node(Sname,peer,[{args,"+fnui -pa " ++ PA}]),
+ ok = rpc:call(Node,file,make_dir,[UnicodePrivDir]),
+ case rpc:call(Node,application,start,[sasl]) of
+ ok -> ok;
+ {error,{already_started,sasl}} -> ok;
+ Error -> ?t:fail({failed_to_start_sasl_on_test_node,Node,Error})
+ end,
+ ok = rpc:call(Node,?MODULE,target_system1,[Conf,UnicodePrivDir]),
+ ok.
+
+target_system_unicode(cleanup,Conf) ->
+ Sname = list_to_atom(atom_to_list(?MODULE) ++ "-target_system_unicode"),
+ Node = node_name(Sname),
+ _ = rpc:call(Node,?MODULE,target_system,[cleanup,Conf]),
+ _ = stop_node(Node),
+ ok.
%%%=================================================================
%%% Testing global groups.
@@ -1852,7 +1923,7 @@ stop_node(Node) ->
copy_client(Conf,Master,Sname,Client) ->
- io:format("copy_client(Conf)"),
+ ?t:format("copy_client(Conf)"),
DataDir = ?config(data_dir, Conf),
MasterDir = filename:join(priv_dir(Conf),Master),
@@ -1891,82 +1962,12 @@ copy_client(Conf,Master,Sname,Client) ->
clean_priv_dir(Conf,Save) ->
PrivDir = priv_dir(Conf),
-
- {ok, OrigWd} = file:get_cwd(),
-
- ok = file:set_cwd(PrivDir),
- ?t:format("======== current dir ~p~n",[PrivDir]),
- {ok, Dirs} = file:list_dir(PrivDir),
- ?t:format("======== deleting ~p~n",[Dirs]),
-
- ok = clean_dirs_os(Dirs,Save),
- {ok,Remaining} = file:list_dir(PrivDir),
- ?t:format("======== remaining ~p~n",[Remaining]),
-
- case Remaining of
- [] ->
- ok;
- _ ->
- clean_dirs_os(Remaining,Save),
- Remaining2 = file:list_dir(PrivDir),
- ?t:format("======== remaining after second try ~p~n",[Remaining2])
- end,
-
- ok = file:set_cwd(OrigWd),
- ok.
-
-
-clean_dirs_os(Dirs,Save) ->
- case os:type() of
- {unix, _} ->
- clean_dirs_unix(Dirs,Save);
- {win32, _} ->
- clean_dirs_win32(Dirs,Save);
- Os ->
- test_server:fail({error, {not_yet_implemented_os, Os}})
+ rh_test_lib:clean_dir(PrivDir,Save),
+ case file:list_dir(PrivDir) of
+ {ok,[]} -> _ = file:del_dir(PrivDir);
+ _ -> ok
end.
-
-clean_dirs_unix([],_) ->
- ok;
-clean_dirs_unix(["save"|Dirs],Save) when Save ->
- clean_dirs_unix(Dirs,Save);
-clean_dirs_unix([Dir|Dirs],Save) ->
- Rm = string:concat("rm -rf ", Dir),
- ?t:format("============== COMMAND ~p~n",[Rm]),
- case file:list_dir(Dir) of
- {error, enotdir} ->
- ok;
- X ->
- ?t:format("------- Dir ~p~n ~p~n",[Dir, X])
- end,
- case os:cmd(Rm) of
- [] ->
- ?t:format("------- Result of COMMAND ~p~n",[ok]);
- Y ->
- ?t:format("!!!!!!! delete ERROR Dir ~p Error ~p~n",[Dir, Y]),
- ?t:format("------- ls -al ~p~n",[os:cmd("ls -al " ++ Dir)])
- end,
-
- clean_dirs_unix(Dirs,Save).
-
-clean_dirs_win32([],_) ->
- ok;
-clean_dirs_win32(["save"|Dirs],Save) when Save ->
- clean_dirs_win32(Dirs,Save);
-clean_dirs_win32([Dir|Dirs],Save) ->
- Rm =
- case filelib:is_dir(Dir) of
- true ->
- string:concat("rmdir /s /q ", Dir);
- false ->
- string:concat("del /q ", Dir)
- end,
- ?t:format("============== COMMAND ~p~n",[Rm]),
- [] = os:cmd(Rm),
- clean_dirs_win32(Dirs,Save).
-
-
node_name(Sname) when is_atom(Sname) ->
{ok,Host} = inet:gethostname(),
list_to_atom(atom_to_list(Sname) ++ "@" ++ Host).
@@ -2012,7 +2013,7 @@ chmod(Dest,Opts) ->
copy_error(Src, Dest, Reason) ->
- io:format("Copy ~s to ~s failed: ~s\n",
+ ?t:format("Copy ~ts to ~ts failed: ~ts\n",
[Src,Dest,file:format_error(Reason)]),
?t:fail(file_copy_failed).
@@ -2052,9 +2053,11 @@ subst_file(Src, Dest, Vars) ->
subst_file(Src, Dest, Vars, []).
subst_file(Src, Dest, Vars, Opts) ->
{ok, Bin} = file:read_file(Src),
- Conts = binary_to_list(Bin),
+ Conts = binary_to_list(Bin), % The source will always be latin1
NConts = subst(Conts, Vars),
- ok = file:write_file(Dest, NConts),
+ %% The destination must be utf8 if file name encoding is unicode
+ Enc = file:native_name_encoding(),
+ ok = file:write_file(Dest, unicode:characters_to_binary(NConts,Enc,Enc)),
preserve(Src,Dest,Opts),
chmod(Dest,Opts).
@@ -2087,13 +2090,22 @@ subst_var([], Vars, Result, VarAcc) ->
priv_dir(Conf) ->
-%% filename:absname(?config(priv_dir, Conf)). % Get rid of trailing slash
%% Due to problem with long paths on windows => creating a new
%% priv_dir under data_dir
- filename:absname(filename:join(?config(data_dir, Conf),priv_dir)).
+ %% And get rid of trailing slash (absname does that)
+ %% And if file name translation mode is utf8, use a path with
+ %% unicode characters
+ PrivDir =
+ case file:native_name_encoding() of
+ utf8 ->
+ "priv_dir_αβ";
+ _ ->
+ "priv_dir"
+ end,
+ filename:absname(filename:join([?config(data_dir, Conf),PrivDir])).
init_priv_dir(Conf) ->
- Dir = filename:absname(filename:join(?config(data_dir, Conf),priv_dir)),
+ Dir = priv_dir(Conf),
case filelib:is_dir(Dir) of
true ->
clean_priv_dir(Conf,false);
@@ -2118,7 +2130,7 @@ rh_print() ->
receive
{print, {Module,Line}, [H|T]} ->
?t:format("=== ~p:~p - ~p",[Module,Line,H]),
- lists:foreach(fun(Term) -> ?t:format(" ~p",[Term]) end, T),
+ lists:foreach(fun(Term) -> ?t:format(" ~tp",[Term]) end, T),
?t:format("",[]),
rh_print();
kill ->
@@ -2511,11 +2523,14 @@ start_nodes(Conf,Snames,Tag) ->
start_node_unix(Sname,NodeDir) ->
Script = filename:join([NodeDir,"bin","start"]),
- Cmd = "env NODENAME="++atom_to_list(Sname) ++ " " ++ Script,
- %% {ok,StartFile} = file:read_file(Cmd),
- %% io:format("~s:\n~s~n~n",[Start,binary_to_list(StartFile)]),
- Res = os:cmd(Cmd),
- io:format("Start ~p: ~p~n=>\t~p~n", [Sname,Cmd,Res]).
+ ?t:format("Starting ~p: ~tp~n", [Sname,Script]),
+ case rh_test_lib:cmd(Script,[],[{"NODENAME",atom_to_list(Sname)}]) of
+ ok ->
+ {ok,node_name(Sname)};
+ Error ->
+ ?t:fail({failed_to_start_node, Sname, Error})
+ end.
+
start_node_win32(Sname,NodeDir) ->
Name = atom_to_list(Sname) ++ "_P1G",
@@ -2676,7 +2691,7 @@ rpc_inst(Node,Func,Args) ->
delete_all_services() ->
ErlSrv = erlsrv:erlsrv(erlang:system_info(version)),
- [_|Serviceinfo] = string:tokens(os:cmd(ErlSrv ++ " list"),"\n"),
+ [_|Serviceinfo] = string:tokens(os:cmd("\"" ++ ErlSrv ++ "\" list"),"\n"),
Services =
[lists:takewhile(fun($\t) -> false; (_) -> true end,S)
|| S <- Serviceinfo],
diff --git a/lib/sasl/test/rh_test_lib.erl b/lib/sasl/test/rh_test_lib.erl
index 99a7f919a7..11935496d8 100644
--- a/lib/sasl/test/rh_test_lib.erl
+++ b/lib/sasl/test/rh_test_lib.erl
@@ -1,5 +1,6 @@
-module(rh_test_lib).
+-export([cmd/3]).
-export([erlsrv/3,
erlsrv/4]).
-export([get_service_args/3,
@@ -8,12 +9,26 @@
get_start_erl_args/3,
get_client_args/3,
get_client_args/4]).
+-export([clean_dir/1,
+ clean_dir/2]).
+-include_lib("kernel/include/file.hrl").
+
+cmd(Cmd,Args,Env) ->
+ case open_port({spawn_executable, Cmd}, [{args,Args},{env,Env}]) of
+ Port when is_port(Port) ->
+ unlink(Port),
+ erlang:port_close(Port),
+ ok;
+ Error ->
+ Error
+ end.
erlsrv(Erlsrv,Action,Name) ->
erlsrv(Erlsrv,Action,Name,"").
erlsrv(Erlsrv,Action,Name,Rest) ->
- Cmd = Erlsrv ++ " " ++ atom_to_list(Action) ++ " " ++ Name ++ " " ++ Rest,
+ Cmd = "\"" ++ Erlsrv ++ "\" " ++ atom_to_list(Action) ++ " " ++
+ Name ++ " " ++ Rest,
io:format("erlsrv cmd: ~p~n",[Cmd]),
Port = open_port({spawn, Cmd}, [stream, {line, 100}, eof, in]),
Res = recv_prog_output(Port),
@@ -98,3 +113,50 @@ single_quote() ->
_ ->
"\\'"
end.
+
+clean_dir(Dir) ->
+ clean_dir(Dir,false).
+clean_dir(Dir,Save) ->
+ test_server:format("======== current dir ~tp~n",[Dir]),
+ Dirs = filelib:wildcard(filename:join(Dir,"*")),
+ test_server:format("======== deleting ~tp~n",[Dirs]),
+
+ ok = rm_rf(Dirs,Save),
+ Remaining = filelib:wildcard(filename:join(Dir,"*")),
+ test_server:format("======== remaining ~tp~n",[Remaining]),
+
+ case Remaining of
+ [] ->
+ ok;
+ _ ->
+ rm_rf(Remaining,Save),
+ Remaining2 = filelib:wildcard(filename:join(Dir,"*")),
+ test_server:format("======== remaining after second try ~tp~n",
+ [Remaining2])
+ end,
+
+ ok.
+
+
+rm_rf([File|Files],Save) ->
+ case Save andalso filename:basename(File)=="save" of
+ true ->
+ rm_rf(Files,Save);
+ false ->
+ case file:read_link_info(File) of
+ {ok,#file_info{type=directory}} ->
+ MoreFiles = filelib:wildcard(filename:join(File,"*")),
+ rm_rf(MoreFiles,Save),
+ file:del_dir(File),
+ rm_rf(Files,Save);
+ {ok,#file_info{}} ->
+ file:delete(File),
+ rm_rf(Files,Save);
+ Other ->
+ test_server:format("======== could not delete file ~p~n"
+ "read_link_info -> ~p~n",[File,Other]),
+ rm_rf(Files,Save)
+ end
+ end;
+rm_rf([],_) ->
+ ok.
diff --git a/lib/sasl/test/systools_SUITE.erl b/lib/sasl/test/systools_SUITE.erl
index 5e95b13077..1cc9eb6986 100644
--- a/lib/sasl/test/systools_SUITE.erl
+++ b/lib/sasl/test/systools_SUITE.erl
@@ -137,9 +137,9 @@ compile_source(File) ->
ok = file:write_file(OutFileTemp, Code),
file:rename(OutFileTemp, OutFile).
-end_per_suite(Conf) when is_list(Conf) ->
- %% Nothing.
- Conf.
+end_per_suite(Config) when is_list(Config) ->
+ rh_test_lib:clean_dir(?privdir),
+ Config.
init_per_testcase(link_tar, Config) ->
case os:type() of
diff --git a/lib/snmp/doc/src/files.mk b/lib/snmp/doc/src/files.mk
index 494c550fff..91fd18ca85 100644
--- a/lib/snmp/doc/src/files.mk
+++ b/lib/snmp/doc/src/files.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2011. All Rights Reserved.
+# Copyright Ericsson AB 2001-2013. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/snmp/src/agent/depend.mk b/lib/snmp/src/agent/depend.mk
index 4b12b66e3b..b4ca8a2d9f 100644
--- a/lib/snmp/src/agent/depend.mk
+++ b/lib/snmp/src/agent/depend.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2012. All Rights Reserved.
+# Copyright Ericsson AB 2004-2013. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/snmp/src/agent/snmpa_agent_sup.erl b/lib/snmp/src/agent/snmpa_agent_sup.erl
index 2805e2dc0d..1c6632e065 100644
--- a/lib/snmp/src/agent/snmpa_agent_sup.erl
+++ b/lib/snmp/src/agent/snmpa_agent_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/snmp/src/agent/snmpa_target_cache.erl b/lib/snmp/src/agent/snmpa_target_cache.erl
index 1fcaf82373..391d711dc5 100644
--- a/lib/snmp/src/agent/snmpa_target_cache.erl
+++ b/lib/snmp/src/agent/snmpa_target_cache.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/snmp/src/app/snmp_app.erl b/lib/snmp/src/app/snmp_app.erl
index 0cfbb22a5a..28a6fef7e9 100644
--- a/lib/snmp/src/app/snmp_app.erl
+++ b/lib/snmp/src/app/snmp_app.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/snmp/src/manager/snmpm_config.erl b/lib/snmp/src/manager/snmpm_config.erl
index 9d687f1d31..736debe544 100644
--- a/lib/snmp/src/manager/snmpm_config.erl
+++ b/lib/snmp/src/manager/snmpm_config.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/snmp/src/misc/snmp_config.erl b/lib/snmp/src/misc/snmp_config.erl
index 22fe25941c..945b8719fc 100644
--- a/lib/snmp/src/misc/snmp_config.erl
+++ b/lib/snmp/src/misc/snmp_config.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/snmp/src/misc/snmp_misc.erl b/lib/snmp/src/misc/snmp_misc.erl
index 293b22991b..c36cee2a53 100644
--- a/lib/snmp/src/misc/snmp_misc.erl
+++ b/lib/snmp/src/misc/snmp_misc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/snmp/test/snmp_agent_test_lib.erl b/lib/snmp/test/snmp_agent_test_lib.erl
index 11c05fc1db..7e4b713e56 100644
--- a/lib/snmp/test/snmp_agent_test_lib.erl
+++ b/lib/snmp/test/snmp_agent_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/snmp/test/snmp_test_lib.erl b/lib/snmp/test/snmp_test_lib.erl
index 505332b586..fbb891e40d 100644
--- a/lib/snmp/test/snmp_test_lib.erl
+++ b/lib/snmp/test/snmp_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml
index 3505b8087f..e2dbfa04f7 100644
--- a/lib/ssh/doc/src/notes.xml
+++ b/lib/ssh/doc/src/notes.xml
@@ -29,6 +29,58 @@
<file>notes.xml</file>
</header>
+<section><title>Ssh 2.1.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ ssh:daemon will get feeded with an argument even if it is
+ not a valid expression.</p>
+ <p>
+ Own Id: OTP-10975</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Properly ignore everything in lib/ssh/doc/html/. Thanks
+ to Anthony Ramine.</p>
+ <p>
+ Own Id: OTP-10983</p>
+ </item>
+ <item>
+ <p>
+ Integrate elliptic curve contribution from Andreas
+ Schultz </p>
+ <p>
+ In order to be able to support elliptic curve cipher
+ suites in SSL/TLS, additions to handle elliptic curve
+ infrastructure has been added to public_key and crypto.</p>
+ <p>
+ This also has resulted in a rewrite of the crypto API to
+ gain consistency and remove unnecessary overhead. All OTP
+ applications using crypto has been updated to use the new
+ API.</p>
+ <p>
+ Impact: Elliptic curve cryptography (ECC) offers
+ equivalent security with smaller key sizes than other
+ public key algorithms. Smaller key sizes result in
+ savings for power, memory, bandwidth, and computational
+ cost that make ECC especially attractive for constrained
+ environments.</p>
+ <p>
+ Own Id: OTP-11009</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Ssh 2.1.6</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/ssh/src/ssh.appup.src b/lib/ssh/src/ssh.appup.src
index b25e0c9e37..32f7cc470b 100644
--- a/lib/ssh/src/ssh.appup.src
+++ b/lib/ssh/src/ssh.appup.src
@@ -19,22 +19,12 @@
{"%VSN%",
[
- {<<"2.1.4">>, [{load_module, ssh_sftp, soft_purge, soft_purge, []},
- {load_module, ssh_connection_handler, soft_purge, soft_purge, []}]},
- {<<"2.1.3">>, [{restart_application, ssh}]},
- {<<"2.1.2">>, [{restart_application, ssh}]},
- {<<"2.1.1">>, [{restart_application, ssh}]},
- {<<"2.1">>, [{restart_application, ssh}]},
+ {<<"2.1\\.*">>, [{restart_application, ssh}]},
{<<"2.0\\.*">>, [{restart_application, ssh}]},
{<<"1\\.*">>, [{restart_application, ssh}]}
],
[
- {<<"2.1.4">>, [{load_module, ssh_sftp, soft_purge, soft_purge, []},
- {load_module, ssh_connection_handler, soft_purge, soft_purge, []}]},
- {<<"2.1.3">>, [{restart_application, ssh}]},
- {<<"2.1.2">>, [{restart_application, ssh}]},
- {<<"2.1.1">>, [{restart_application, ssh}]},
- {<<"2.1">>,[{restart_application, ssh}]},
+ {<<"2.1\\.*">>,[{restart_application, ssh}]},
{<<"2.0\\.*">>, [{restart_application, ssh}]},
{<<"1\\.*">>, [{restart_application, ssh}]}
]
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl
index 3a7aa79d16..7d5478c3f6 100644
--- a/lib/ssh/src/ssh.erl
+++ b/lib/ssh/src/ssh.erl
@@ -41,11 +41,13 @@
%%--------------------------------------------------------------------
start() ->
application:start(crypto),
+ application:start(asn1),
application:start(public_key),
application:start(ssh).
start(Type) ->
application:start(crypto, Type),
+ application:start(asn1),
application:start(public_key, Type),
application:start(ssh, Type).
diff --git a/lib/ssh/src/ssh_xfer.erl b/lib/ssh/src/ssh_xfer.erl
index 93f9e20663..b299868d41 100644
--- a/lib/ssh/src/ssh_xfer.erl
+++ b/lib/ssh/src/ssh_xfer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk
index d5ca1cb3fe..231779b75a 100644
--- a/lib/ssh/vsn.mk
+++ b/lib/ssh/vsn.mk
@@ -1,5 +1,5 @@
#-*-makefile-*- ; force emacs to enter makefile-mode
-SSH_VSN = 2.1.6
+SSH_VSN = 2.1.7
APP_VSN = "ssh-$(SSH_VSN)"
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml
index d5b7bdf8b8..5db4bea654 100644
--- a/lib/ssl/doc/src/notes.xml
+++ b/lib/ssl/doc/src/notes.xml
@@ -26,7 +26,80 @@
</header>
<p>This document describes the changes made to the SSL application.</p>
- <section><title>SSL 5.2.1</title>
+ <section><title>SSL 5.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Honor the versions option to ssl:connect and ssl:listen.</p>
+ <p>
+ Own Id: OTP-10905</p>
+ </item>
+ <item>
+ <p>
+ Next protocol negotiation with reused sessions will now
+ succeed</p>
+ <p>
+ Own Id: OTP-10909</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add support for PSK (Pre Shared Key) and SRP (Secure
+ Remote Password) chipher suits, thanks to Andreas
+ Schultz.</p>
+ <p>
+ Own Id: OTP-10450 Aux Id: kunagi-269 [180] </p>
+ </item>
+ <item>
+ <p>
+ Fix SSL Next Protocol Negotiation documentation. Thanks
+ to Julien Barbot.</p>
+ <p>
+ Own Id: OTP-10955</p>
+ </item>
+ <item>
+ <p>
+ Fix ssl_connection to support reading proxy/chain
+ certificates. Thanks to Valentin Kuznetsov.</p>
+ <p>
+ Own Id: OTP-10980</p>
+ </item>
+ <item>
+ <p>
+ Integrate elliptic curve contribution from Andreas
+ Schultz </p>
+ <p>
+ In order to be able to support elliptic curve cipher
+ suites in SSL/TLS, additions to handle elliptic curve
+ infrastructure has been added to public_key and crypto.</p>
+ <p>
+ This also has resulted in a rewrite of the crypto API to
+ gain consistency and remove unnecessary overhead. All OTP
+ applications using crypto has been updated to use the new
+ API.</p>
+ <p>
+ Impact: Elliptic curve cryptography (ECC) offers
+ equivalent security with smaller key sizes than other
+ public key algorithms. Smaller key sizes result in
+ savings for power, memory, bandwidth, and computational
+ cost that make ECC especially attractive for constrained
+ environments.</p>
+ <p>
+ Own Id: OTP-11009</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 5.2.1</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/ssl/src/ssl.appup.src b/lib/ssl/src/ssl.appup.src
index a8a494b2fc..9e5bec26f1 100644
--- a/lib/ssl/src/ssl.appup.src
+++ b/lib/ssl/src/ssl.appup.src
@@ -1,14 +1,14 @@
%% -*- erlang -*-
{"%VSN%",
[
- {<<"5.2">>, [{restart_application, ssl}]},
+ {<<"5.2\\*">>, [{restart_application, ssl}]},
{<<"5.1\\*">>, [{restart_application, ssl}]},
{<<"5.0\\*">>, [{restart_application, ssl}]},
{<<"4\\.*">>, [{restart_application, ssl}]},
{<<"3\\.*">>, [{restart_application, ssl}]}
],
[
- {<<"5.2">>, [{restart_application, ssl}]},
+ {<<"5.2\\*">>, [{restart_application, ssl}]},
{<<"5.1\\*">>, [{restart_application, ssl}]},
{<<"5.0\\*">>, [{restart_application, ssl}]},
{<<"4\\.*">>, [{restart_application, ssl}]},
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index 75c17b14db..0c1e47311d 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -214,8 +214,8 @@ prf(Socket, Secret, Label, Seed, WantedLength) ->
clear_pem_cache() ->
tls:clear_pem_cache().
-format_error(Reason) when is_list(Reason) ->
- tls:format_error(Reason).
+format_error(Error) ->
+ tls:format_error(Error).
random_bytes(N) ->
tls:random_bytes(N).
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl
index 898b421dff..ec5d793d65 100644
--- a/lib/ssl/src/ssl_cipher.erl
+++ b/lib/ssl/src/ssl_cipher.erl
@@ -1190,14 +1190,16 @@ hash_size(md5) ->
16;
hash_size(sha) ->
20;
-hash_size(sha224) ->
- 28;
+%% Uncomment when adding cipher suite that needs it
+%% hash_size(sha224) ->
+%% 28;
hash_size(sha256) ->
32;
hash_size(sha384) ->
- 48;
-hash_size(sha512) ->
- 64.
+ 48.
+%% Uncomment when adding cipher suite that needs it
+%% hash_size(sha512) ->
+%% 64.
%% RFC 5246: 6.2.3.2. CBC Block Cipher
%%
diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl
index 1b06e351cf..7af4a68461 100644
--- a/lib/ssl/src/ssl_manager.erl
+++ b/lib/ssl/src/ssl_manager.erl
@@ -104,7 +104,6 @@ connection_init(Trustedcerts, Role) ->
%%--------------------------------------------------------------------
cache_pem_file(File, DbHandle) ->
MD5 = crypto:hash(md5, File),
- MD5 = crypto:md5(File),
case ssl_pkix_db:lookup_cached_pem(DbHandle, MD5) of
[{Content,_}] ->
{ok, Content};
diff --git a/lib/ssl/src/tls.erl b/lib/ssl/src/tls.erl
index fcecf8196f..bb02695c12 100644
--- a/lib/ssl/src/tls.erl
+++ b/lib/ssl/src/tls.erl
@@ -94,11 +94,13 @@
%%--------------------------------------------------------------------
start() ->
application:start(crypto),
+ application:start(asn1),
application:start(public_key),
application:start(ssl).
start(Type) ->
application:start(crypto, Type),
+ application:start(asn1),
application:start(public_key, Type),
application:start(ssl, Type).
diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl
index 6a0461e805..246fecf34a 100644
--- a/lib/ssl/src/tls_connection.erl
+++ b/lib/ssl/src/tls_connection.erl
@@ -673,8 +673,7 @@ certify_client_key_exchange(#encrypted_premaster_secret{premaster_secret= EncPMS
certify_client_key_exchange(#client_diffie_hellman_public{dh_public = ClientPublicDhKey},
#state{negotiated_version = Version,
- diffie_hellman_params = #'DHParameter'{prime = P,
- base = G} = Params,
+ diffie_hellman_params = #'DHParameter'{} = Params,
diffie_hellman_keys = {_, ServerDhPrivateKey}} = State0) ->
case dh_master_secret(Params, ClientPublicDhKey, ServerDhPrivateKey, State0) of
#state{} = State1 ->
diff --git a/lib/ssl/src/tls_handshake.erl b/lib/ssl/src/tls_handshake.erl
index fea75736f7..51fd2e1dc9 100644
--- a/lib/ssl/src/tls_handshake.erl
+++ b/lib/ssl/src/tls_handshake.erl
@@ -866,7 +866,7 @@ handle_ecc_point_fmt_extension(undefined) ->
handle_ecc_point_fmt_extension(_) ->
#ec_point_formats{ec_point_format_list = [?ECPOINT_UNCOMPRESSED]}.
-handle_ecc_curves_extension(Version, undefined) ->
+handle_ecc_curves_extension(_Version, undefined) ->
undefined;
handle_ecc_curves_extension(Version, _) ->
#elliptic_curves{elliptic_curve_list = ssl_tls1:ecc_curves(Version)}.
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index fed590f0ef..b5cf6d1212 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -190,8 +190,7 @@ init_per_suite(Config0) ->
catch crypto:stop(),
try crypto:start() of
ok ->
- application:start(public_key),
-
+ ssl:start(),
%% make rsa certs using oppenssl
Result =
(catch make_certs:all(?config(data_dir, Config0),
diff --git a/lib/ssl/test/ssl_certificate_verify_SUITE.erl b/lib/ssl/test/ssl_certificate_verify_SUITE.erl
index 4e095dc184..f76c55f670 100644
--- a/lib/ssl/test/ssl_certificate_verify_SUITE.erl
+++ b/lib/ssl/test/ssl_certificate_verify_SUITE.erl
@@ -80,8 +80,7 @@ init_per_suite(Config0) ->
catch crypto:stop(),
try crypto:start() of
ok ->
- application:start(public_key),
- application:start(ssl),
+ ssl:start(),
%% make rsa certs using oppenssl
Result =
(catch make_certs:all(?config(data_dir, Config0),
diff --git a/lib/ssl/test/ssl_npn_handshake_SUITE.erl b/lib/ssl/test/ssl_npn_handshake_SUITE.erl
index 7b271c4d5d..30c0a67a36 100644
--- a/lib/ssl/test/ssl_npn_handshake_SUITE.erl
+++ b/lib/ssl/test/ssl_npn_handshake_SUITE.erl
@@ -69,7 +69,6 @@ init_per_suite(Config) ->
catch crypto:stop(),
try crypto:start() of
ok ->
- application:start(public_key),
ssl:start(),
Result =
(catch make_certs:all(?config(data_dir, Config),
diff --git a/lib/ssl/test/ssl_packet_SUITE.erl b/lib/ssl/test/ssl_packet_SUITE.erl
index 5a374e234d..36f7af784d 100644
--- a/lib/ssl/test/ssl_packet_SUITE.erl
+++ b/lib/ssl/test/ssl_packet_SUITE.erl
@@ -139,7 +139,7 @@ init_per_suite(Config) ->
catch crypto:stop(),
try crypto:start() of
ok ->
- application:start(public_key),
+ ssl:start(),
Result =
(catch make_certs:all(?config(data_dir, Config),
?config(priv_dir, Config))),
diff --git a/lib/ssl/test/ssl_payload_SUITE.erl b/lib/ssl/test/ssl_payload_SUITE.erl
index 5f5166391f..f95eae51b7 100644
--- a/lib/ssl/test/ssl_payload_SUITE.erl
+++ b/lib/ssl/test/ssl_payload_SUITE.erl
@@ -71,7 +71,6 @@ init_per_suite(Config) ->
catch crypto:stop(),
try crypto:start() of
ok ->
- application:start(public_key),
ssl:start(),
make_certs:all(?config(data_dir, Config), ?config(priv_dir, Config)),
ssl_test_lib:cert_options(Config)
diff --git a/lib/ssl/test/ssl_session_cache_SUITE.erl b/lib/ssl/test/ssl_session_cache_SUITE.erl
index 6cc6c4bdb2..c31f6c2d7d 100644
--- a/lib/ssl/test/ssl_session_cache_SUITE.erl
+++ b/lib/ssl/test/ssl_session_cache_SUITE.erl
@@ -56,9 +56,7 @@ init_per_suite(Config0) ->
catch crypto:stop(),
try crypto:start() of
ok ->
- application:start(public_key),
ssl:start(),
-
%% make rsa certs using oppenssl
Result =
(catch make_certs:all(?config(data_dir, Config0),
diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl
index 0564b37f1c..019ed58b1b 100644
--- a/lib/ssl/test/ssl_to_openssl_SUITE.erl
+++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl
@@ -99,7 +99,6 @@ init_per_suite(Config0) ->
catch crypto:stop(),
try crypto:start() of
ok ->
- application:start(public_key),
ssl:start(),
Result =
(catch make_certs:all(?config(data_dir, Config0),
diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk
index 1f3bef83c8..9dd151553c 100644
--- a/lib/ssl/vsn.mk
+++ b/lib/ssl/vsn.mk
@@ -1 +1 @@
-SSL_VSN = 5.2.1
+SSL_VSN = 5.3
diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml
index c36cc310aa..c0f236cd71 100644
--- a/lib/stdlib/doc/src/notes.xml
+++ b/lib/stdlib/doc/src/notes.xml
@@ -30,6 +30,179 @@
</header>
<p>This document describes the changes made to the STDLIB application.</p>
+<section><title>STDLIB 1.19.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> The Erlang scanner no longer accepts floating point
+ numbers in the input string. </p>
+ <p>
+ Own Id: OTP-10990</p>
+ </item>
+ <item>
+ <p>
+ When converting a faulty binary to a list with
+ unicode:characters_to_list, the error return value could
+ contain a faulty "rest", i.e. the io_list of characters
+ that could not be converted was wrong. This happened only
+ if input was a sub binary and conversion was from utf8.
+ This is now corrected.</p>
+ <p>
+ Own Id: OTP-11080</p>
+ </item>
+ <item>
+ <p>The type <c>hook_function()</c> has been corrected in
+ <c>erl_pp</c>, the Erlang Pretty Printer. </p>
+ <p>The printing of invalid forms, e.g. record field
+ types, has also been fixed. It has been broken since
+ R16B. </p>
+ <p> (Thanks to Tom&#225;&#353; Janou&#353;ek.) </p>
+ <p>
+ Own Id: OTP-11100</p>
+ </item>
+ <item>
+ <p>
+ Fix receive support in erl_eval with a BEAM module.
+ Thanks to Anthony Ramine.</p>
+ <p>
+ Own Id: OTP-11137</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Delete obsolete note about simple-one-for-one supervisor.
+ Thanks to Magnus Henoch.</p>
+ <p>
+ Own Id: OTP-10938</p>
+ </item>
+ <item>
+ <p> When selecting encoding of a script written in Erlang
+ (<c>escript</c>) the optional directive on the second
+ line is now recognized. </p>
+ <p>
+ Own Id: OTP-10951</p>
+ </item>
+ <item>
+ <p> The function <c>erl_parse:abstract/2</c> has been
+ documented. </p>
+ <p>
+ Own Id: OTP-10992</p>
+ </item>
+ <item>
+ <p>
+ Integrate elliptic curve contribution from Andreas
+ Schultz </p>
+ <p>
+ In order to be able to support elliptic curve cipher
+ suites in SSL/TLS, additions to handle elliptic curve
+ infrastructure has been added to public_key and crypto.</p>
+ <p>
+ This also has resulted in a rewrite of the crypto API to
+ gain consistency and remove unnecessary overhead. All OTP
+ applications using crypto has been updated to use the new
+ API.</p>
+ <p>
+ Impact: Elliptic curve cryptography (ECC) offers
+ equivalent security with smaller key sizes than other
+ public key algorithms. Smaller key sizes result in
+ savings for power, memory, bandwidth, and computational
+ cost that make ECC especially attractive for constrained
+ environments.</p>
+ <p>
+ Own Id: OTP-11009</p>
+ </item>
+ <item>
+ <p>
+ Added sys:get_state/1,2 and sys:replace_state/2,3. Thanks
+ to Steve Vinoski.</p>
+ <p>
+ Own Id: OTP-11013</p>
+ </item>
+ <item>
+ <p>
+ Optimizations to gen mechanism. Thanks to Lo�c Hoguin.</p>
+ <p>
+ Own Id: OTP-11025</p>
+ </item>
+ <item>
+ <p>
+ Optimizations to gen.erl. Thanks to Lo�c Hoguin.</p>
+ <p>
+ Own Id: OTP-11035</p>
+ </item>
+ <item>
+ <p>
+ Use erlang:demonitor(Ref, [flush]) where applicable.
+ Thanks to Lo�c Hoguin.</p>
+ <p>
+ Own Id: OTP-11039</p>
+ </item>
+ <item>
+ <p>Erlang source files with non-ASCII characters are now
+ encoded in UTF-8 (instead of latin1).</p>
+ <p>
+ Own Id: OTP-11041 Aux Id: OTP-10907 </p>
+ </item>
+ <item>
+ <p>
+ Fix rest_for_one and one_for_all restarting a child not
+ terminated. Thanks to James Fish.</p>
+ <p>
+ Own Id: OTP-11042</p>
+ </item>
+ <item>
+ <p>
+ Fix excessive CPU consumption of timer_server. Thanks to
+ Aliaksey Kandratsenka.</p>
+ <p>
+ Own Id: OTP-11053</p>
+ </item>
+ <item>
+ <p>
+ Rename and document lists:zf/2 as lists:filtermap/2.
+ Thanks to Anthony Ramine.</p>
+ <p>
+ Own Id: OTP-11078</p>
+ </item>
+ <item>
+ <p>
+ Fixed an inconsistent state in epp. Thanks to Anthony
+ Ramine</p>
+ <p>
+ Own Id: OTP-11079</p>
+ </item>
+ <item>
+ <p>
+ c:ls(File) will now print File, similar to ls(1) in Unix.
+ The error messages have also been improved. (Thanks to
+ Bengt Kleberg.)</p>
+ <p>
+ Own Id: OTP-11108</p>
+ </item>
+ <item>
+ <p>
+ Support callback attributes in erl_pp. Thanks to Anthony
+ Ramine.</p>
+ <p>
+ Own Id: OTP-11140</p>
+ </item>
+ <item>
+ <p>
+ Improve erl_lint performance. Thanks to Jos� Valim.</p>
+ <p>
+ Own Id: OTP-11143</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>STDLIB 1.19.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/stdlib/src/gen.erl b/lib/stdlib/src/gen.erl
index 5df5530ba1..7281549ea7 100644
--- a/lib/stdlib/src/gen.erl
+++ b/lib/stdlib/src/gen.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/stdlib/src/gen_event.erl b/lib/stdlib/src/gen_event.erl
index bfebf29080..7629e88fbf 100644
--- a/lib/stdlib/src/gen_event.erl
+++ b/lib/stdlib/src/gen_event.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/stdlib/src/lists.erl b/lib/stdlib/src/lists.erl
index 0c033acd88..b5577165f4 100644
--- a/lib/stdlib/src/lists.erl
+++ b/lib/stdlib/src/lists.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/stdlib/src/slave.erl b/lib/stdlib/src/slave.erl
index 9c74041f56..3e647635bc 100644
--- a/lib/stdlib/src/slave.erl
+++ b/lib/stdlib/src/slave.erl
@@ -289,7 +289,8 @@ register_unique_name(Number) ->
%% If the node should run on the local host, there is
%% no need to use rsh.
-mk_cmd(Host, Name, Args, Waiter, Prog) ->
+mk_cmd(Host, Name, Args, Waiter, Prog0) ->
+ Prog = quote_progname(Prog0),
BasicCmd = lists:concat([Prog,
" -detached -noinput -master ", node(),
" ", long_or_short(), Name, "@", Host,
@@ -309,6 +310,31 @@ mk_cmd(Host, Name, Args, Waiter, Prog) ->
end
end.
+%% This is an attempt to distinguish between spaces in the program
+%% path and spaces that separate arguments. The program is quoted to
+%% allow spaces in the path.
+%%
+%% Arguments could exist either if the executable is excplicitly given
+%% (through start/5) or if the -program switch to beam is used and
+%% includes arguments (typically done by cerl in OTP test environment
+%% in order to ensure that slave/peer nodes are started with the same
+%% emulator and flags as the test node. The return from lib:progname()
+%% could then typically be '/<full_path_to>/cerl -gcov').
+quote_progname(Progname) ->
+ do_quote_progname(string:tokens(to_list(Progname)," ")).
+
+do_quote_progname([Prog]) ->
+ "\""++Prog++"\"";
+do_quote_progname([Prog,Arg|Args]) ->
+ case os:find_executable(Prog) of
+ false ->
+ do_quote_progname([Prog++" "++Arg | Args]);
+ _ ->
+ %% this one has an executable - we assume the rest are arguments
+ "\""++Prog++"\""++
+ lists:flatten(lists:map(fun(X) -> [" ",X] end, [Arg|Args]))
+ end.
+
%% Give the user an opportunity to run another program,
%% than the "rsh". On HP-UX rsh is called remsh; thus HP users
%% must start erlang as erl -rsh remsh.
diff --git a/lib/stdlib/test/c_SUITE.erl b/lib/stdlib/test/c_SUITE.erl
index 8c55b616b9..a018db9c91 100644
--- a/lib/stdlib/test/c_SUITE.erl
+++ b/lib/stdlib/test/c_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/stdlib/test/gen_event_SUITE.erl b/lib/stdlib/test/gen_event_SUITE.erl
index 6be5a299b6..5819ef3890 100644
--- a/lib/stdlib/test/gen_event_SUITE.erl
+++ b/lib/stdlib/test/gen_event_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/stdlib/test/lists_SUITE.erl b/lib/stdlib/test/lists_SUITE.erl
index cd7210f8ec..92253ef5b9 100644
--- a/lib/stdlib/test/lists_SUITE.erl
+++ b/lib/stdlib/test/lists_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/stdlib/test/supervisor_3.erl b/lib/stdlib/test/supervisor_3.erl
index 31b3037d6f..0023219ff3 100644
--- a/lib/stdlib/test/supervisor_3.erl
+++ b/lib/stdlib/test/supervisor_3.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/stdlib/test/supervisor_SUITE.erl b/lib/stdlib/test/supervisor_SUITE.erl
index ff5be6bb95..ac5a34c3bc 100644
--- a/lib/stdlib/test/supervisor_SUITE.erl
+++ b/lib/stdlib/test/supervisor_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/stdlib/test/unicode_SUITE.erl b/lib/stdlib/test/unicode_SUITE.erl
index 4055af2741..e2d789bbe6 100644
--- a/lib/stdlib/test/unicode_SUITE.erl
+++ b/lib/stdlib/test/unicode_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -29,7 +29,7 @@
random_lists/1,
roundtrips/1,
latin1/1,
- exceptions/1]).
+ exceptions/1, binaries_errors/1]).
init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
Dog=?t:timetrap(?t:minutes(20)),
@@ -44,7 +44,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[utf8_illegal_sequences_bif,
utf16_illegal_sequences_bif, random_lists, roundtrips,
- latin1, exceptions].
+ latin1, exceptions, binaries_errors].
groups() ->
[].
@@ -61,6 +61,149 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
+binaries_errors(Config) when is_list(Config) ->
+ setlimit(10),
+ ex_binaries_errors_utf8(Config),
+ setlimit(default),
+ ex_binaries_errors_utf8(Config),
+ ex_binaries_errors_utf16_little(Config),
+ ex_binaries_errors_utf16_big(Config),
+ ex_binaries_errors_utf32_little(Config),
+ ex_binaries_errors_utf32_big(Config).
+
+ex_binaries_errors_utf8(Config) when is_list(Config) ->
+ %% Original smoke test, we should not forget the original offset...
+ <<_:8,_:8,RR2/binary>> = <<$a,$b,164,165,$c>>,
+ {error,[],<<164,165,$c>>} = unicode:characters_to_list(RR2),
+ %% Now, try with longer binary (trapping)
+ BrokenPart = list_to_binary(lists:seq(128,255)),
+ BrokenSz = byte_size(BrokenPart),
+ [ begin
+ OKList = lists:flatten(lists:duplicate(N,lists:seq(1,255))),
+ OKBin = unicode:characters_to_binary(OKList),
+ OKLen = length(OKList),
+ %% Copy to avoid that the binary get's writable
+ PartlyBroken = binary:copy(<<OKBin/binary, BrokenPart/binary>>),
+ PBSz = byte_size(PartlyBroken),
+ {error,OKList,DeepBrokenPart} =
+ unicode:characters_to_list(PartlyBroken),
+ BrokenPart = iolist_to_binary(DeepBrokenPart),
+ [ begin
+ NewList = lists:nthtail(X, OKList),
+ NewSz = byte_size(unicode:characters_to_binary(NewList)) +
+ BrokenSz,
+ Chomped = binary:part(PartlyBroken,PBSz - NewSz, NewSz),
+ true = (binary:referenced_byte_size(Chomped) =:= PBSz),
+ {error,NewList,DeepBrokenPart2} =
+ unicode:characters_to_list(Chomped),
+ BrokenPart = iolist_to_binary(DeepBrokenPart2)
+ end || X <- lists:seq(1,OKLen) ]
+ end || N <- lists:seq(1,20) ],
+ ok.
+
+ex_binaries_errors_utf16_little(Config) when is_list(Config) ->
+ BrokenPart = << <<X:16/little>> || X <- lists:seq(16#DC00,16#DFFF) >>,
+ BrokenSz = byte_size(BrokenPart),
+ [ begin
+ OKList = lists:flatten(lists:duplicate(N,lists:seq(1,255))),
+ OKBin = unicode:characters_to_binary(OKList,unicode,{utf16,little}),
+ OKLen = length(OKList),
+ %% Copy to avoid that the binary get's writable
+ PartlyBroken = binary:copy(<<OKBin/binary, BrokenPart/binary>>),
+ PBSz = byte_size(PartlyBroken),
+ {error,OKList,DeepBrokenPart} =
+ unicode:characters_to_list(PartlyBroken,{utf16,little}),
+ BrokenPart = iolist_to_binary(DeepBrokenPart),
+ [ begin
+ NewList = lists:nthtail(X, OKList),
+ NewSz = byte_size(unicode:characters_to_binary(NewList,unicode,{utf16,little})) +
+ BrokenSz,
+ Chomped = binary:part(PartlyBroken,PBSz - NewSz, NewSz),
+ true = (binary:referenced_byte_size(Chomped) =:= PBSz),
+ {error,NewList,DeepBrokenPart2} =
+ unicode:characters_to_list(Chomped,{utf16,little}),
+ BrokenPart = iolist_to_binary(DeepBrokenPart2)
+ end || X <- lists:seq(1,OKLen) ]
+ end || N <- lists:seq(1,15) ],
+ ok.
+ex_binaries_errors_utf16_big(Config) when is_list(Config) ->
+ BrokenPart = << <<X:16/big>> || X <- lists:seq(16#DC00,16#DFFF) >>,
+ BrokenSz = byte_size(BrokenPart),
+ [ begin
+ OKList = lists:flatten(lists:duplicate(N,lists:seq(1,255))),
+ OKBin = unicode:characters_to_binary(OKList,unicode,{utf16,big}),
+ OKLen = length(OKList),
+ %% Copy to avoid that the binary get's writable
+ PartlyBroken = binary:copy(<<OKBin/binary, BrokenPart/binary>>),
+ PBSz = byte_size(PartlyBroken),
+ {error,OKList,DeepBrokenPart} =
+ unicode:characters_to_list(PartlyBroken,{utf16,big}),
+ BrokenPart = iolist_to_binary(DeepBrokenPart),
+ [ begin
+ NewList = lists:nthtail(X, OKList),
+ NewSz = byte_size(unicode:characters_to_binary(NewList,unicode,{utf16,big})) +
+ BrokenSz,
+ Chomped = binary:part(PartlyBroken,PBSz - NewSz, NewSz),
+ true = (binary:referenced_byte_size(Chomped) =:= PBSz),
+ {error,NewList,DeepBrokenPart2} =
+ unicode:characters_to_list(Chomped,{utf16,big}),
+ BrokenPart = iolist_to_binary(DeepBrokenPart2)
+ end || X <- lists:seq(1,OKLen) ]
+ end || N <- lists:seq(1,15) ],
+ ok.
+
+ex_binaries_errors_utf32_big(Config) when is_list(Config) ->
+ BrokenPart = << <<X:32/big>> || X <- lists:seq(16#DC00,16#DFFF) >>,
+ BrokenSz = byte_size(BrokenPart),
+ [ begin
+ OKList = lists:flatten(lists:duplicate(N,lists:seq(1,255))),
+ OKBin = unicode:characters_to_binary(OKList,unicode,{utf32,big}),
+ OKLen = length(OKList),
+ %% Copy to avoid that the binary get's writable
+ PartlyBroken = binary:copy(<<OKBin/binary, BrokenPart/binary>>),
+ PBSz = byte_size(PartlyBroken),
+ {error,OKList,DeepBrokenPart} =
+ unicode:characters_to_list(PartlyBroken,{utf32,big}),
+ BrokenPart = iolist_to_binary(DeepBrokenPart),
+ [ begin
+ NewList = lists:nthtail(X, OKList),
+ NewSz = byte_size(unicode:characters_to_binary(NewList,unicode,{utf32,big})) +
+ BrokenSz,
+ Chomped = binary:part(PartlyBroken,PBSz - NewSz, NewSz),
+ true = (binary:referenced_byte_size(Chomped) =:= PBSz),
+ {error,NewList,DeepBrokenPart2} =
+ unicode:characters_to_list(Chomped,{utf32,big}),
+ BrokenPart = iolist_to_binary(DeepBrokenPart2)
+ end || X <- lists:seq(1,OKLen) ]
+ end || N <- lists:seq(1,15) ],
+ ok.
+
+ex_binaries_errors_utf32_little(Config) when is_list(Config) ->
+ BrokenPart = << <<X:32/little>> || X <- lists:seq(16#DC00,16#DFFF) >>,
+ BrokenSz = byte_size(BrokenPart),
+ [ begin
+ OKList = lists:flatten(lists:duplicate(N,lists:seq(1,255))),
+ OKBin = unicode:characters_to_binary(OKList,unicode,{utf32,little}),
+ OKLen = length(OKList),
+ %% Copy to avoid that the binary get's writable
+ PartlyBroken = binary:copy(<<OKBin/binary, BrokenPart/binary>>),
+ PBSz = byte_size(PartlyBroken),
+ {error,OKList,DeepBrokenPart} =
+ unicode:characters_to_list(PartlyBroken,{utf32,little}),
+ BrokenPart = iolist_to_binary(DeepBrokenPart),
+ [ begin
+ NewList = lists:nthtail(X, OKList),
+ NewSz = byte_size(unicode:characters_to_binary(NewList,unicode,{utf32,little})) +
+ BrokenSz,
+ Chomped = binary:part(PartlyBroken,PBSz - NewSz, NewSz),
+ true = (binary:referenced_byte_size(Chomped) =:= PBSz),
+ {error,NewList,DeepBrokenPart2} =
+ unicode:characters_to_list(Chomped,{utf32,little}),
+ BrokenPart = iolist_to_binary(DeepBrokenPart2)
+ end || X <- lists:seq(1,OKLen) ]
+ end || N <- lists:seq(1,15) ],
+ ok.
+
exceptions(Config) when is_list(Config) ->
diff --git a/lib/test_server/doc/src/notes.xml b/lib/test_server/doc/src/notes.xml
index a151bfbda0..f3d4bc201a 100644
--- a/lib/test_server/doc/src/notes.xml
+++ b/lib/test_server/doc/src/notes.xml
@@ -32,6 +32,56 @@
<file>notes.xml</file>
</header>
+<section><title>Test_Server 3.6.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Some unused code related to remote targets is removed,
+ and documentation is updated.</p>
+ <p>
+ Own Id: OTP-10607 Aux Id: kunagi-338 [249] </p>
+ </item>
+ <item>
+ <p>
+ A bug in test_server_gl caused io requests containing
+ invalid data (i.e. not unicode:chardata()) to hang, since
+ no io reply was sent. This has been corrected.</p>
+ <p>
+ Own Id: OTP-10991</p>
+ </item>
+ <item>
+ <p>
+ Common Test would, in case of timetrap error, print a
+ warning in the log if end_per_testcase wasn't implemented
+ in the suite, even though it's an optional function. This
+ printout has been removed.</p>
+ <p>
+ Own Id: OTP-11052</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The '-force_stop' flag to use with time-limited repeats
+ of test runs can now be used with a new 'skip_rest'
+ option which causes the rest of the test cases in the
+ ongoing test job to be skipped when the time limit is
+ reached. E.g. 'ct_run -spec xxx -duration 010000
+ -force_stop skip_rest'</p>
+ <p>
+ Own Id: OTP-10856 Aux Id: OTP-10832 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Test_Server 3.6.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -226,8 +276,6 @@
unicode:characters_to_binary for conversion between
binaries and strings instead of binary_to_list and
list_to_binary. </item> </list></p>
- <p>
- Own Id: OTP-10783</p>
</item>
</list>
</section>
diff --git a/lib/test_server/src/configure.in b/lib/test_server/src/configure.in
index 785bab395c..3815027721 100644
--- a/lib/test_server/src/configure.in
+++ b/lib/test_server/src/configure.in
@@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script for Erlang.
dnl
dnl %CopyrightBegin%
dnl
-dnl Copyright Ericsson AB 1997-2012. All Rights Reserved.
+dnl Copyright Ericsson AB 1997-2013. All Rights Reserved.
dnl
dnl The contents of this file are subject to the Erlang Public License,
dnl Version 1.1, (the "License"); you may not use this file except in
@@ -276,6 +276,7 @@ AC_CHECK_FUNC(gethostbyname, , AC_CHECK_LIB(nsl, main, [LIBS="$LIBS -lnsl"]))
dnl Checks for library functions.
AC_CHECK_FUNCS(strerror)
AC_CHECK_FUNCS(vsnprintf)
+AC_CHECK_FUNCS(usleep)
# First check if the library is available, then if we can choose between
# two versions of gethostbyname
diff --git a/lib/test_server/src/test_server_node.erl b/lib/test_server/src/test_server_node.erl
index 619fd463de..582abb2153 100644
--- a/lib/test_server/src/test_server_node.erl
+++ b/lib/test_server/src/test_server_node.erl
@@ -82,7 +82,7 @@ start_tracer_node(TraceFile,TI) ->
Cookie = TI#target_info.cookie,
{ok,LSock} = gen_tcp:listen(0,[binary,{reuseaddr,true},{packet,2}]),
{ok,TracePort} = inet:port(LSock),
- Prog = pick_erl_program(default),
+ Prog = quote_progname(pick_erl_program(default)),
Cmd = lists:concat([Prog, " -sname tracer -hidden -setcookie ", Cookie,
" -s ", ?MODULE, " trc ", TraceFile, " ",
TracePort, " ", TI#target_info.os_family]),
@@ -312,7 +312,7 @@ start_node_peer(SlaveName, OptList, From, TI) ->
FailOnError = start_node_get_option_value(fail_on_error, OptList, true),
Pa = TI#target_info.test_server_dir,
Prog0 = start_node_get_option_value(erl, OptList, default),
- Prog = pick_erl_program(Prog0),
+ Prog = quote_progname(pick_erl_program(Prog0)),
Args =
case string:str(SuppliedArgs,"-setcookie") of
0 -> "-setcookie " ++ TI#target_info.cookie ++ " " ++ SuppliedArgs;
@@ -589,7 +589,32 @@ pick_erl_program(L) ->
{release, S} ->
find_release(S);
this ->
- lib:progname()
+ cast_to_list(lib:progname())
+ end.
+
+%% This is an attempt to distinguish between spaces in the program
+%% path and spaces that separate arguments. The program is quoted to
+%% allow spaces in the path.
+%%
+%% Arguments could exist either if the executable is excplicitly given
+%% ({prog,String}) or if the -program switch to beam is used and
+%% includes arguments (typically done by cerl in OTP test environment
+%% in order to ensure that slave/peer nodes are started with the same
+%% emulator and flags as the test node. The return from lib:progname()
+%% could then typically be '/<full_path_to>/cerl -gcov').
+quote_progname(Progname) ->
+ do_quote_progname(string:tokens(Progname," ")).
+
+do_quote_progname([Prog]) ->
+ "\""++Prog++"\"";
+do_quote_progname([Prog,Arg|Args]) ->
+ case os:find_executable(Prog) of
+ false ->
+ do_quote_progname([Prog++" "++Arg | Args]);
+ _ ->
+ %% this one has an executable - we assume the rest are arguments
+ "\""++Prog++"\""++
+ lists:flatten(lists:map(fun(X) -> [" ",X] end, [Arg|Args]))
end.
random_element(L) ->
diff --git a/lib/test_server/src/ts_install_cth.erl b/lib/test_server/src/ts_install_cth.erl
index a75cae3c9d..7746bbed6f 100644
--- a/lib/test_server/src/ts_install_cth.erl
+++ b/lib/test_server/src/ts_install_cth.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/test_server/vsn.mk b/lib/test_server/vsn.mk
index 0a5c4246f1..1753bbb913 100644
--- a/lib/test_server/vsn.mk
+++ b/lib/test_server/vsn.mk
@@ -1 +1 @@
-TEST_SERVER_VSN = 3.6.1
+TEST_SERVER_VSN = 3.6.2
diff --git a/lib/tools/doc/src/eprof.xml b/lib/tools/doc/src/eprof.xml
index 6c740fec1a..3ebacf5546 100644
--- a/lib/tools/doc/src/eprof.xml
+++ b/lib/tools/doc/src/eprof.xml
@@ -52,12 +52,14 @@
<func>
<name>start_profiling(Rootset) -> profiling | {error, Reason}</name>
<name>start_profiling(Rootset,Pattern) -> profiling | {error, Reason}</name>
+ <name>start_profiling(Rootset,Pattern,Options) -> profiling | {error, Reason}</name>
<fsummary>Start profiling.</fsummary>
<type>
<v>Rootset = [atom() | pid()]</v>
- <v>Pattern = {Module, Function, Arity}</v>
- <v>Module = Function = atom()</v>
- <v>Arity = integer()</v>
+ <v>Pattern = {Module, Function, Arity}</v>
+ <v>Module = Function = atom()</v>
+ <v>Arity = integer()</v>
+ <v>Options = [set_on_spawn]</v>
<v>Reason = term()</v>
</type>
<desc>
@@ -70,6 +72,9 @@
<p>A pattern can be selected to narrow the profiling. For instance a
specific module can be selected, and only the code executed in that
module will be profiled.</p>
+ <p>The <c>set_on_spawn</c> option will active call time tracing for
+ all processes spawned by processes in the rootset. This is
+ the default behaviour.</p>
</desc>
</func>
<func>
@@ -82,19 +87,22 @@
</func>
<func>
<name>profile(Fun) -> profiling | {error, Reason}</name>
+ <name>profile(Fun, Options) -> profiling | {error, Reason}</name>
<name>profile(Rootset) -> profiling | {error, Reason}</name>
<name>profile(Rootset,Fun) -> {ok, Value} | {error,Reason}</name>
<name>profile(Rootset,Fun,Pattern) -> {ok, Value} | {error, Reason}</name>
<name>profile(Rootset,Module,Function,Args) -> {ok, Value} | {error, Reason}</name>
<name>profile(Rootset,Module,Function,Args,Pattern) -> {ok, Value} | {error, Reason}</name>
+ <name>profile(Rootset,Module,Function,Args,Pattern,Options) -> {ok, Value} | {error, Reason}</name>
<fsummary>Start profiling.</fsummary>
<type>
<v>Rootset = [atom() | pid()]</v>
- <v>Fun = fun() -> term()</v>
- <v>Pattern = {Module, Function, Arity}</v>
+ <v>Fun = fun() -> term() end</v>
+ <v>Pattern = {Module, Function, Arity}</v>
<v>Module = Function = atom()</v>
<v>Args = [term()]</v>
- <v>Arity = integer()</v>
+ <v>Arity = integer()</v>
+ <v>Options = [set_on_spawn]</v>
<v>Value = Reason = term()</v>
</type>
<desc>
@@ -108,8 +116,11 @@
<c>Rootset</c>, the function returns <c>{ok,Value}</c> when
<c>Fun()</c>/<c>apply</c> returns with the value <c>Value</c>, or
<c>{error,Reason}</c> if <c>Fun()</c>/<c>apply</c> fails with
- exit reason <c>Reason</c>. Otherwise it returns <c>{error, Reason}</c>
+ exit reason <c>Reason</c>. Otherwise it returns <c>{error, Reason}</c>
immediately.</p>
+ <p>The <c>set_on_spawn</c> option will active call time tracing for
+ all processes spawned by processes in the rootset. This is
+ the default behaviour.</p>
<p>The programmer must ensure that the function given as argument
is truly synchronous and that no work continues after
the function has returned a value.</p>
diff --git a/lib/tools/doc/src/notes.xml b/lib/tools/doc/src/notes.xml
index 63ee59c168..422d4538a6 100644
--- a/lib/tools/doc/src/notes.xml
+++ b/lib/tools/doc/src/notes.xml
@@ -30,6 +30,72 @@
</header>
<p>This document describes the changes made to the Tools application.</p>
+<section><title>Tools 2.6.11</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ When cover:stop(Node) was called on a non-existing node,
+ a process waiting for cover data from the node would hang
+ forever. This has been corrected.</p>
+ <p>
+ Own Id: OTP-10979</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Make cover smarter about finding source from beam.</p>
+ <p>
+ In particular, search using the source path in
+ module_info if the current heuristic fails.</p>
+ <p>
+ Own Id: OTP-10902</p>
+ </item>
+ <item>
+ <p>
+ Remove Flymake dependency in erlang-pkg.el. Thanks to
+ Magnus Henoch.</p>
+ <p>
+ Own Id: OTP-10930</p>
+ </item>
+ <item>
+ <p>
+ Erlang-mode: Add autoload cookies for file extension
+ associations. Thanks to Magnus Henoch.</p>
+ <p>
+ Own Id: OTP-10999</p>
+ </item>
+ <item>
+ <p> Postscript files no longer needed for the generation
+ of PDF files have been removed. </p>
+ <p>
+ Own Id: OTP-11016</p>
+ </item>
+ <item>
+ <p>
+ Fix a race condition when there're several applications
+ in apps directory. Thanks to Manuel Rubio.</p>
+ <p>
+ Own Id: OTP-11028</p>
+ </item>
+ <item>
+ <p>
+ New option for eprof, 'set_on_spawn'. This option was
+ previously always on and is also the default.</p>
+ <p>
+ Own Id: OTP-11144</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Tools 2.6.10</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/tools/src/eprof.erl b/lib/tools/src/eprof.erl
index 87fdc1fa34..bfbbefb473 100644
--- a/lib/tools/src/eprof.erl
+++ b/lib/tools/src/eprof.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -26,7 +26,7 @@
-export([start/0,
stop/0,
dump/0,
- start_profiling/1, start_profiling/2,
+ start_profiling/1, start_profiling/2, start_profiling/3,
profile/1, profile/2, profile/3, profile/4, profile/5,
stop_profiling/0,
analyze/0, analyze/1, analyze/2,
@@ -39,6 +39,8 @@
handle_info/2,
terminate/2,
code_change/3]).
+
+
-record(bpd, {
n = 0, % number of total calls
us = 0, % sum of uS for all calls
@@ -46,14 +48,18 @@
mfa = [] % list of {Mfa, {Count, Us}}
}).
+-define(default_options, [{set_on_spawn, true}]).
+-define(default_pattern, {'_','_','_'}).
+
-record(state, {
- profiling = false,
- pattern = {'_','_','_'},
- rootset = [],
- fd = undefined,
- start_ts = undefined,
- reply = undefined,
- bpd = #bpd{}
+ profiling = false,
+ pattern = ?default_pattern,
+ rootset = [],
+ trace_opts = [],
+ fd = undefined,
+ start_ts = undefined,
+ reply = undefined,
+ bpd = #bpd{}
}).
@@ -67,26 +73,6 @@
start() -> gen_server:start({local, ?MODULE}, ?MODULE, [], []).
stop() -> gen_server:call(?MODULE, stop, infinity).
-profile(Fun) when is_function(Fun) ->
- profile([], Fun);
-profile(Rs) when is_list(Rs) ->
- start_profiling(Rs).
-
-profile(Pids, Fun) ->
- profile(Pids, Fun, {'_','_','_'}).
-
-profile(Pids, Fun, Pattern) ->
- profile(Pids, erlang, apply, [Fun,[]], Pattern).
-
-profile(Pids, M, F, A) ->
- profile(Pids, M, F, A, {'_','_','_'}).
-
-profile(Pids, M, F, A, Pattern) ->
- start(),
- gen_server:call(?MODULE, {profile,Pids,Pattern,M,F,A},infinity).
-
-dump() ->
- gen_server:call(?MODULE, dump, infinity).
analyze() ->
analyze(procs).
@@ -98,17 +84,53 @@ analyze(Opts) when is_list(Opts) ->
analyze(Type, Opts) when is_list(Opts) ->
gen_server:call(?MODULE, {analyze, Type, Opts}, infinity).
+%% odd duck, should only been start_profiling/1
+profile(Rootset) when is_list(Rootset) ->
+ start_profiling(Rootset);
+
+profile(Fun) when is_function(Fun) ->
+ profile([], Fun).
+
+profile(Fun, Opts) when is_function(Fun), is_list(Opts) ->
+ profile([], erlang, apply, [Fun, []], ?default_pattern, Opts);
+
+profile(Rootset, Fun) when is_list(Rootset), is_function(Fun) ->
+ profile(Rootset, Fun, ?default_pattern).
+
+profile(Rootset, Fun, Pattern) when is_list(Rootset), is_function(Fun) ->
+ profile(Rootset, Fun, Pattern, ?default_options).
+
+profile(Rootset, Fun, Pattern, Options) when is_list(Rootset), is_function(Fun), is_list(Options) ->
+ profile(Rootset, erlang, apply, [Fun,[]], Pattern, Options);
+
+profile(Rootset, M, F, A) when is_list(Rootset), is_atom(M), is_atom(F), is_list(A) ->
+ profile(Rootset, M, F, A, ?default_pattern).
+
+profile(Rootset, M, F, A, Pattern) when is_list(Rootset), is_atom(M), is_atom(F), is_list(A) ->
+ profile(Rootset, M, F, A, Pattern, ?default_options).
+
+%% Returns when M:F/A has terminated
+profile(Rootset, M, F, A, Pattern, Options) ->
+ start(),
+ gen_server:call(?MODULE, {profile_start, Rootset, Pattern, {M,F,A}, Options}, infinity).
+
+dump() ->
+ gen_server:call(?MODULE, dump, infinity).
+
log(File) ->
gen_server:call(?MODULE, {logfile, File}, infinity).
+%% Does not block
start_profiling(Rootset) ->
- start_profiling(Rootset, {'_','_','_'}).
+ start_profiling(Rootset, ?default_pattern).
start_profiling(Rootset, Pattern) ->
+ start_profiling(Rootset, Pattern, ?default_options).
+start_profiling(Rootset, Pattern, Options) ->
start(),
- gen_server:call(?MODULE, {profile, Rootset, Pattern}, infinity).
+ gen_server:call(?MODULE, {profile_start, Rootset, Pattern, undefined, Options}, infinity).
stop_profiling() ->
- gen_server:call(?MODULE, stop_profiling, infinity).
+ gen_server:call(?MODULE, profile_stop, infinity).
%% -------------------------------------------------------------------- %%
@@ -151,74 +173,75 @@ handle_call({analyze, Type, _Opts}, _, S) ->
%% profile
-handle_call({profile, _Rootset, _Pattern, _M,_F,_A}, _From, #state{ profiling = true } = S) ->
+handle_call({profile_start, _Rootset, _Pattern, _MFA, _Opts}, _From, #state{ profiling = true } = S) ->
{reply, {error, already_profiling}, S};
-handle_call({profile, Rootset, Pattern, M,F,A}, From, #state{fd = Fd } = S) ->
+handle_call({profile_start, Rootset, Pattern, {M,F,A}, Opts}, From, #state{fd = Fd } = S) ->
+
+ ok = set_pattern_trace(false, S#state.pattern),
+ _ = set_process_trace(false, S#state.rootset, S#state.trace_opts),
- set_pattern_trace(false, S#state.pattern),
- set_process_trace(false, S#state.rootset),
+ Topts = get_trace_options(Opts),
+ Pid = setup_profiling(M,F,A),
- Pid = setup_profiling(M,F,A),
- case set_process_trace(true, [Pid|Rootset]) of
+ case set_process_trace(true, [Pid|Rootset], Topts) of
true ->
- set_pattern_trace(true, Pattern),
+ ok = set_pattern_trace(true, Pattern),
T0 = now(),
- execute_profiling(Pid),
+ ok = execute_profiling(Pid),
{noreply, #state{
- profiling = true,
- rootset = [Pid|Rootset],
- start_ts = T0,
- reply = From,
- fd = Fd,
- pattern = Pattern
+ profiling = true,
+ rootset = [Pid|Rootset],
+ start_ts = T0,
+ reply = From,
+ fd = Fd,
+ trace_opts = Topts,
+ pattern = Pattern
}};
false ->
exit(Pid, eprof_kill),
{reply, error, #state{ fd = Fd}}
end;
-handle_call({profile, _Rootset, _Pattern}, _From, #state{ profiling = true } = S) ->
- {reply, {error, already_profiling}, S};
-
-handle_call({profile, Rootset, Pattern}, From, #state{ fd = Fd } = S) ->
+handle_call({profile_start, Rootset, Pattern, undefined, Opts}, From, #state{ fd = Fd } = S) ->
- set_pattern_trace(false, S#state.pattern),
- set_process_trace(false, S#state.rootset),
+ ok = set_pattern_trace(false, S#state.pattern),
+ true = set_process_trace(false, S#state.rootset, S#state.trace_opts),
+ Topts = get_trace_options(Opts),
- case set_process_trace(true, Rootset) of
+ case set_process_trace(true, Rootset, Topts) of
true ->
T0 = now(),
- set_pattern_trace(true, Pattern),
+ ok = set_pattern_trace(true, Pattern),
{reply, profiling, #state{
- profiling = true,
- rootset = Rootset,
- start_ts = T0,
- reply = From,
- fd = Fd,
- pattern = Pattern
+ profiling = true,
+ rootset = Rootset,
+ start_ts = T0,
+ reply = From,
+ fd = Fd,
+ trace_opts = Topts,
+ pattern = Pattern
}};
false ->
{reply, error, #state{ fd = Fd }}
end;
-handle_call(stop_profiling, _From, #state{ profiling = false } = S) ->
+handle_call(profile_stop, _From, #state{ profiling = false } = S) ->
{reply, profiling_already_stopped, S};
-handle_call(stop_profiling, _From, #state{ profiling = true } = S) ->
-
- set_pattern_trace(pause, S#state.pattern),
+handle_call(profile_stop, _From, #state{ profiling = true } = S) ->
+ ok = set_pattern_trace(pause, S#state.pattern),
Bpd = collect_bpd(),
-
- set_process_trace(false, S#state.rootset),
- set_pattern_trace(false, S#state.pattern),
+ _ = set_process_trace(false, S#state.rootset, S#state.trace_opts),
+ ok = set_pattern_trace(false, S#state.pattern),
{reply, profiling_stopped, S#state{
- profiling = false,
- rootset = [],
- pattern = {'_','_','_'},
- bpd = Bpd
+ profiling = false,
+ rootset = [],
+ trace_opts = [],
+ pattern = ?default_pattern,
+ bpd = Bpd
}};
%% logfile
@@ -261,33 +284,33 @@ handle_info({'EXIT', _, eprof_kill}, S) ->
{noreply, S};
handle_info({'EXIT', _, Reason}, #state{ reply = FromTag } = S) ->
- set_process_trace(false, S#state.rootset),
- set_pattern_trace(false, S#state.pattern),
+ _ = set_process_trace(false, S#state.rootset, S#state.trace_opts),
+ ok = set_pattern_trace(false, S#state.pattern),
gen_server:reply(FromTag, {error, Reason}),
{noreply, S#state{
- profiling = false,
- rootset = [],
- pattern = {'_','_','_'}
+ profiling = false,
+ rootset = [],
+ trace_opts = [],
+ pattern = ?default_pattern
}};
% check if Pid is spawned process?
handle_info({_Pid, {answer, Result}}, #state{ reply = {From,_} = FromTag} = S) ->
- set_pattern_trace(pause, S#state.pattern),
-
- Bpd = collect_bpd(),
-
- set_process_trace(false, S#state.rootset),
- set_pattern_trace(false, S#state.pattern),
+ ok = set_pattern_trace(pause, S#state.pattern),
+ Bpd = collect_bpd(),
+ _ = set_process_trace(false, S#state.rootset, S#state.trace_opts),
+ ok = set_pattern_trace(false, S#state.pattern),
catch unlink(From),
gen_server:reply(FromTag, {ok, Result}),
{noreply, S#state{
- profiling = false,
- rootset = [],
- pattern = {'_','_','_'},
- bpd = Bpd
+ profiling = false,
+ rootset = [],
+ trace_opts = [],
+ pattern = ?default_pattern,
+ bpd = Bpd
}}.
%% -------------------------------------------------------------------- %%
@@ -297,11 +320,11 @@ handle_info({_Pid, {answer, Result}}, #state{ reply = {From,_} = FromTag} = S) -
%% -------------------------------------------------------------------- %%
terminate(_Reason, #state{ fd = undefined }) ->
- set_pattern_trace(false, {'_','_','_'}),
+ ok = set_pattern_trace(false, ?default_pattern),
ok;
terminate(_Reason, #state{ fd = Fd }) ->
- file:close(Fd),
- set_pattern_trace(false, {'_','_','_'}),
+ ok = file:close(Fd),
+ ok = set_pattern_trace(false, ?default_pattern),
ok.
%% -------------------------------------------------------------------- %%
@@ -330,7 +353,19 @@ spin_profile(M, F, A) ->
end.
execute_profiling(Pid) ->
- Pid ! {self(), execute}.
+ Pid ! {self(), execute},
+ ok.
+
+
+get_trace_options([]) ->
+ [call];
+get_trace_options([{set_on_spawn, true}|Opts]) ->
+ [set_on_spawn | get_trace_options(Opts)];
+get_trace_options([set_on_spawn|Opts]) ->
+ [set_on_spawn | get_trace_options(Opts)];
+get_trace_options([_|Opts]) ->
+ get_trace_options(Opts).
+
set_pattern_trace(Flag, Pattern) ->
erlang:system_flag(multi_scheduling, block),
@@ -339,10 +374,6 @@ set_pattern_trace(Flag, Pattern) ->
erlang:system_flag(multi_scheduling, unblock),
ok.
-set_process_trace(Flag, Pids) ->
- % do we need procs for meta info?
- % could be useful
- set_process_trace(Flag, Pids, [call, set_on_spawn]).
set_process_trace(_, [], _) -> true;
set_process_trace(Flag, [Pid|Pids], Options) when is_pid(Pid) ->
try
diff --git a/lib/tools/src/fprof.erl b/lib/tools/src/fprof.erl
index 877218bda0..75840e54ff 100644
--- a/lib/tools/src/fprof.erl
+++ b/lib/tools/src/fprof.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/tools/test/eprof_SUITE.erl b/lib/tools/test/eprof_SUITE.erl
index 3283fa571f..26685a6a84 100644
--- a/lib/tools/test/eprof_SUITE.erl
+++ b/lib/tools/test/eprof_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -21,12 +21,14 @@
-include_lib("test_server/include/test_server.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,tiny/1,eed/1,basic/1]).
+ init_per_group/2,end_per_group/2]).
+
+-export([tiny/1,eed/1,basic/1,basic_option/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [basic, tiny, eed].
+ [basic, basic_option, tiny, eed].
groups() ->
[].
@@ -49,140 +51,185 @@ basic(Config) when is_list(Config) ->
%% load eprof_test and change directory
- ?line {ok, OldCurDir} = file:get_cwd(),
+ {ok, OldCurDir} = file:get_cwd(),
Datadir = ?config(data_dir, Config),
Privdir = ?config(priv_dir, Config),
- ?line {ok,eprof_test} = compile:file(filename:join(Datadir, "eprof_test"),
+ {ok,eprof_test} = compile:file(filename:join(Datadir, "eprof_test"),
[trace,{outdir, Privdir}]),
- ?line ok = file:set_cwd(Privdir),
- ?line code:purge(eprof_test),
- ?line {module,eprof_test} = code:load_file(eprof_test),
+ ok = file:set_cwd(Privdir),
+ code:purge(eprof_test),
+ {module,eprof_test} = code:load_file(eprof_test),
%% rootset profiling
- ?line ensure_eprof_stopped(),
- ?line profiling = eprof:profile([self()]),
- ?line {error, already_profiling} = eprof:profile([self()]),
- ?line profiling_stopped = eprof:stop_profiling(),
- ?line profiling_already_stopped = eprof:stop_profiling(),
- ?line profiling = eprof:start_profiling([self(),self(),self()]),
- ?line profiling_stopped = eprof:stop_profiling(),
+ ensure_eprof_stopped(),
+ profiling = eprof:profile([self()]),
+ {error, already_profiling} = eprof:profile([self()]),
+ profiling_stopped = eprof:stop_profiling(),
+ profiling_already_stopped = eprof:stop_profiling(),
+ profiling = eprof:start_profiling([self(),self(),self()]),
+ profiling_stopped = eprof:stop_profiling(),
%% with patterns
- ?line profiling = eprof:start_profiling([self()], {?MODULE, '_', '_'}),
- ?line {error, already_profiling} = eprof:start_profiling([self()], {?MODULE, '_', '_'}),
- ?line profiling_stopped = eprof:stop_profiling(),
- ?line profiling = eprof:start_profiling([self()], {?MODULE, start_stop, '_'}),
- ?line profiling_stopped = eprof:stop_profiling(),
- ?line profiling = eprof:start_profiling([self()], {?MODULE, start_stop, 1}),
- ?line profiling_stopped = eprof:stop_profiling(),
+ profiling = eprof:start_profiling([self()], {?MODULE, '_', '_'}),
+ {error, already_profiling} = eprof:start_profiling([self()], {?MODULE, '_', '_'}),
+ profiling_stopped = eprof:stop_profiling(),
+ profiling = eprof:start_profiling([self()], {?MODULE, start_stop, '_'}),
+ profiling_stopped = eprof:stop_profiling(),
+ profiling = eprof:start_profiling([self()], {?MODULE, start_stop, 1}),
+ profiling_stopped = eprof:stop_profiling(),
%% with fun
- ?line {ok, _} = eprof:profile(fun() -> eprof_test:go(10) end),
- ?line profiling = eprof:profile([self()]),
- ?line {error, already_profiling} = eprof:profile(fun() -> eprof_test:go(10) end),
- ?line profiling_stopped = eprof:stop_profiling(),
- ?line {ok, _} = eprof:profile(fun() -> eprof_test:go(10) end),
- ?line {ok, _} = eprof:profile([], fun() -> eprof_test:go(10) end),
- ?line Pid = whereis(eprof),
- ?line {ok, _} = eprof:profile(erlang:processes() -- [Pid], fun() -> eprof_test:go(10) end),
- ?line {ok, _} = eprof:profile([], fun() -> eprof_test:go(10) end, {eprof_test, '_', '_'}),
- ?line {ok, _} = eprof:profile([], fun() -> eprof_test:go(10) end, {eprof_test, go, '_'}),
- ?line {ok, _} = eprof:profile([], fun() -> eprof_test:go(10) end, {eprof_test, go, 1}),
- ?line {ok, _} = eprof:profile([], fun() -> eprof_test:go(10) end, {eprof_test, dec, 1}),
+ {ok, _} = eprof:profile(fun() -> eprof_test:go(10) end),
+ profiling = eprof:profile([self()]),
+ {error, already_profiling} = eprof:profile(fun() -> eprof_test:go(10) end),
+ profiling_stopped = eprof:stop_profiling(),
+ {ok, _} = eprof:profile(fun() -> eprof_test:go(10) end),
+ {ok, _} = eprof:profile([], fun() -> eprof_test:go(10) end),
+ Pid = whereis(eprof),
+ {ok, _} = eprof:profile(erlang:processes() -- [Pid], fun() -> eprof_test:go(10) end),
+ {ok, _} = eprof:profile([], fun() -> eprof_test:go(10) end, {eprof_test, '_', '_'}),
+ {ok, _} = eprof:profile([], fun() -> eprof_test:go(10) end, {eprof_test, go, '_'}),
+ {ok, _} = eprof:profile([], fun() -> eprof_test:go(10) end, {eprof_test, go, 1}),
+ {ok, _} = eprof:profile([], fun() -> eprof_test:go(10) end, {eprof_test, dec, 1}),
%% error case
- ?line error = eprof:profile([Pid], fun() -> eprof_test:go(10) end),
- ?line Pid = whereis(eprof),
- ?line error = eprof:profile([Pid], fun() -> eprof_test:go(10) end),
- ?line A = spawn(fun() -> receive _ -> ok end end),
- ?line profiling = eprof:profile([A]),
- ?line true = exit(A, kill_it),
- ?line profiling_stopped = eprof:stop_profiling(),
- ?line {error,_} = eprof:profile(fun() -> a = b end),
+ error = eprof:profile([Pid], fun() -> eprof_test:go(10) end),
+ Pid = whereis(eprof),
+ error = eprof:profile([Pid], fun() -> eprof_test:go(10) end),
+ A = spawn(fun() -> receive _ -> ok end end),
+ profiling = eprof:profile([A]),
+ true = exit(A, kill_it),
+ profiling_stopped = eprof:stop_profiling(),
+ {error,_} = eprof:profile(fun() -> a = b end),
%% with mfa
- ?line {ok, _} = eprof:profile([], eprof_test, go, [10]),
- ?line {ok, _} = eprof:profile([], eprof_test, go, [10], {eprof_test, dec, 1}),
+ {ok, _} = eprof:profile([], eprof_test, go, [10]),
+ {ok, _} = eprof:profile([], eprof_test, go, [10], {eprof_test, dec, 1}),
%% dump
- ?line {ok, _} = eprof:profile([], fun() -> eprof_test:go(10) end, {eprof_test, '_', '_'}),
- ?line [{_, Mfas}] = eprof:dump(),
- ?line Dec_mfa = {eprof_test, dec, 1},
- ?line Go_mfa = {eprof_test, go, 1},
- ?line {value, {Go_mfa, { 1, _Time1}}} = lists:keysearch(Go_mfa, 1, Mfas),
- ?line {value, {Dec_mfa, {11, _Time2}}} = lists:keysearch(Dec_mfa, 1, Mfas),
+ {ok, _} = eprof:profile([], fun() -> eprof_test:go(10) end, {eprof_test, '_', '_'}),
+ [{_, Mfas}] = eprof:dump(),
+ Dec_mfa = {eprof_test, dec, 1},
+ Go_mfa = {eprof_test, go, 1},
+ {value, {Go_mfa, { 1, _Time1}}} = lists:keysearch(Go_mfa, 1, Mfas),
+ {value, {Dec_mfa, {11, _Time2}}} = lists:keysearch(Dec_mfa, 1, Mfas),
%% change current working directory
- ?line ok = file:set_cwd(OldCurDir),
- ?line stopped = eprof:stop(),
+ ok = file:set_cwd(OldCurDir),
+ stopped = eprof:stop(),
+ ok.
+
+basic_option(Config) when is_list(Config) ->
+ %% load eprof_test and change directory
+
+ {ok, OldCurDir} = file:get_cwd(),
+ Datadir = ?config(data_dir, Config),
+ Privdir = ?config(priv_dir, Config),
+ {ok,eprof_test} = compile:file(filename:join(Datadir, "eprof_test"),
+ [trace,{outdir, Privdir}]),
+ ok = file:set_cwd(Privdir),
+ code:purge(eprof_test),
+ {module,eprof_test} = code:load_file(eprof_test),
+
+ % vanilla
+ {ok, _} = eprof:profile(fun() -> eprof_test:do(10) end, [{set_on_spawn, true}]),
+
+ [{_, MfasDo1},{_, MfasLists1}] = eprof:dump(),
+ Mfas1 = MfasDo1 ++ MfasLists1,
+
+ {value, {_, {11, _}}} = lists:keysearch({eprof_test,dec,1}, 1, Mfas1),
+ {value, {_, { 1, _}}} = lists:keysearch({eprof_test, go,1}, 1, Mfas1),
+ {value, {_, { 9, _}}} = lists:keysearch({lists, split_2,5}, 1, Mfas1),
+ {value, {_, { 4, _}}} = lists:keysearch({lists, seq_loop,3}, 1, Mfas1),
+
+ {ok, _} = eprof:profile(fun() -> eprof_test:do(10) end, [set_on_spawn]),
+
+ [{_, MfasDo2},{_, MfasLists2}] = eprof:dump(),
+ Mfas2 = MfasDo2 ++ MfasLists2,
+ {value, {_, {11, _}}} = lists:keysearch({eprof_test,dec,1}, 1, Mfas2),
+ {value, {_, { 1, _}}} = lists:keysearch({eprof_test, go,1}, 1, Mfas2),
+ {value, {_, { 9, _}}} = lists:keysearch({lists, split_2,5}, 1, Mfas2),
+ {value, {_, { 4, _}}} = lists:keysearch({lists, seq_loop,3}, 1, Mfas2),
+
+ % disable trace set_on_spawn
+ {ok, _} = eprof:profile(fun() -> eprof_test:do(10) end, []),
+ [{_, Mfas3}] = eprof:dump(),
+ {value, {_, {11, _}}} = lists:keysearch({eprof_test,dec,1}, 1, Mfas3),
+ {value, {_, { 1, _}}} = lists:keysearch({eprof_test, go,1}, 1, Mfas3),
+ false = lists:keysearch({lists, split_2,5}, 1, Mfas3),
+ false = lists:keysearch({lists, seq_loop,3}, 1, Mfas3),
+
+ %% change current working directory
+ ok = file:set_cwd(OldCurDir),
+ stopped = eprof:stop(),
ok.
tiny(suite) -> [];
tiny(Config) when is_list(Config) ->
- ?line ensure_eprof_stopped(),
- ?line {ok, OldCurDir} = file:get_cwd(),
+ ensure_eprof_stopped(),
+ {ok, OldCurDir} = file:get_cwd(),
Datadir = ?config(data_dir, Config),
Privdir = ?config(priv_dir, Config),
- ?line TTrap=?t:timetrap(60*1000),
+ TTrap=?t:timetrap(60*1000),
% (Trace)Compile to priv_dir and make sure the correct version is loaded.
- ?line {ok,eprof_suite_test} = compile:file(filename:join(Datadir,
+ {ok,eprof_suite_test} = compile:file(filename:join(Datadir,
"eprof_suite_test"),
[trace,{outdir, Privdir}]),
- ?line ok = file:set_cwd(Privdir),
- ?line code:purge(eprof_suite_test),
- ?line {module,eprof_suite_test} = code:load_file(eprof_suite_test),
- ?line {ok,_Pid} = eprof:start(),
- ?line nothing_to_analyze = eprof:analyze(),
- ?line nothing_to_analyze = eprof:analyze(total),
- ?line eprof:profile([], eprof_suite_test, test, [Config]),
- ?line ok = eprof:analyze(),
- ?line ok = eprof:analyze(total),
- ?line ok = eprof:log("eprof_SUITE_logfile"),
- ?line stopped = eprof:stop(),
- ?line ?t:timetrap_cancel(TTrap),
- ?line ok = file:set_cwd(OldCurDir),
+ ok = file:set_cwd(Privdir),
+ code:purge(eprof_suite_test),
+ {module,eprof_suite_test} = code:load_file(eprof_suite_test),
+ {ok,_Pid} = eprof:start(),
+ nothing_to_analyze = eprof:analyze(),
+ nothing_to_analyze = eprof:analyze(total),
+ eprof:profile([], eprof_suite_test, test, [Config]),
+ ok = eprof:analyze(),
+ ok = eprof:analyze(total),
+ ok = eprof:log("eprof_SUITE_logfile"),
+ stopped = eprof:stop(),
+ ?t:timetrap_cancel(TTrap),
+ ok = file:set_cwd(OldCurDir),
ok.
eed(suite) -> [];
eed(Config) when is_list(Config) ->
- ?line ensure_eprof_stopped(),
- ?line Datadir = ?config(data_dir, Config),
- ?line Privdir = ?config(priv_dir, Config),
- ?line TTrap=?t:timetrap(5*60*1000),
+ ensure_eprof_stopped(),
+ Datadir = ?config(data_dir, Config),
+ Privdir = ?config(priv_dir, Config),
+ TTrap=?t:timetrap(5*60*1000),
%% (Trace)Compile to priv_dir and make sure the correct version is loaded.
- ?line code:purge(eed),
- ?line {ok,eed} = c:c(filename:join(Datadir, "eed"), [trace,{outdir,Privdir}]),
- ?line {ok,_Pid} = eprof:start(),
- ?line Script = filename:join(Datadir, "ed.script"),
- ?line ok = file:set_cwd(Datadir),
- ?line {T1,_} = statistics(runtime),
- ?line ok = eed:file(Script),
- ?line ok = eed:file(Script),
- ?line ok = eed:file(Script),
- ?line ok = eed:file(Script),
- ?line ok = eed:file(Script),
- ?line ok = eed:file(Script),
- ?line ok = eed:file(Script),
- ?line ok = eed:file(Script),
- ?line ok = eed:file(Script),
- ?line ok = eed:file(Script),
- ?line {T2,_} = statistics(runtime),
- ?line {ok,ok} = eprof:profile([], eed, file, [Script]),
- ?line {T3,_} = statistics(runtime),
- ?line profiling_already_stopped = eprof:stop_profiling(),
- ?line ok = eprof:analyze(),
- ?line ok = eprof:analyze(total),
- ?line ok = eprof:log("eprof_SUITE_logfile"),
- ?line stopped = eprof:stop(),
- ?line ?t:timetrap_cancel(TTrap),
+ code:purge(eed),
+ {ok,eed} = c:c(filename:join(Datadir, "eed"), [trace,{outdir,Privdir}]),
+ {ok,_Pid} = eprof:start(),
+ Script = filename:join(Datadir, "ed.script"),
+ ok = file:set_cwd(Datadir),
+ {T1,_} = statistics(runtime),
+ ok = eed:file(Script),
+ ok = eed:file(Script),
+ ok = eed:file(Script),
+ ok = eed:file(Script),
+ ok = eed:file(Script),
+ ok = eed:file(Script),
+ ok = eed:file(Script),
+ ok = eed:file(Script),
+ ok = eed:file(Script),
+ ok = eed:file(Script),
+ {T2,_} = statistics(runtime),
+ {ok,ok} = eprof:profile([], eed, file, [Script]),
+ {T3,_} = statistics(runtime),
+ profiling_already_stopped = eprof:stop_profiling(),
+ ok = eprof:analyze(),
+ ok = eprof:analyze(total),
+ ok = eprof:log("eprof_SUITE_logfile"),
+ stopped = eprof:stop(),
+ ?t:timetrap_cancel(TTrap),
try
S = lists:flatten(io_lib:format("~p times slower",
[10*(T3-T2)/(T2-T1)])),
@@ -198,5 +245,5 @@ ensure_eprof_stopped() ->
undefined ->
ok;
Pid ->
- ?line stopped=eprof:stop()
+ stopped=eprof:stop()
end.
diff --git a/lib/tools/test/eprof_SUITE_data/eprof_test.erl b/lib/tools/test/eprof_SUITE_data/eprof_test.erl
index 33c428e893..2d9e4c2945 100644
--- a/lib/tools/test/eprof_SUITE_data/eprof_test.erl
+++ b/lib/tools/test/eprof_SUITE_data/eprof_test.erl
@@ -1,5 +1,5 @@
-module(eprof_test).
--export([go/1]).
+-export([go/1, do/1]).
go(N) ->
0 = dec(N),
@@ -7,3 +7,16 @@ go(N) ->
dec(0) -> 0;
dec(N) -> dec(N - 1).
+
+
+
+load(N, Pid) ->
+ _ = lists:sort(lists:reverse(lists:seq(1, N))),
+ Pid ! {self(), ok}.
+
+
+do(N) ->
+ Me = self(),
+ Pid = spawn_link(fun() -> load(N, Me) end),
+ ok = go(N),
+ receive {Pid, ok} -> ok end.
diff --git a/lib/tools/vsn.mk b/lib/tools/vsn.mk
index 4fb2f30e4f..a30b16fc49 100644
--- a/lib/tools/vsn.mk
+++ b/lib/tools/vsn.mk
@@ -1 +1 @@
-TOOLS_VSN = 2.6.10
+TOOLS_VSN = 2.6.11