aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile54
-rw-r--r--lib/appmon/doc/src/appmon.xml6
-rw-r--r--lib/appmon/doc/src/appmon_chapter.xml6
-rw-r--r--lib/appmon/src/appmon.erl5
-rw-r--r--lib/appmon/src/appmon_a.erl5
-rw-r--r--lib/appmon/src/appmon_lb.erl7
-rw-r--r--lib/appmon/src/appmon_txt.erl5
-rw-r--r--lib/asn1/c_src/asn1_erl_nif.c5
-rw-r--r--lib/asn1/src/asn1ct_check.erl3
-rw-r--r--lib/asn1/src/asn1ct_gen_per.erl4
-rw-r--r--lib/asn1/src/asn1ct_gen_per_rt2ct.erl4
-rw-r--r--lib/asn1/test/asn1_SUITE.erl.src24
-rw-r--r--lib/compiler/doc/src/compile.xml2
-rw-r--r--lib/compiler/src/Makefile1
-rw-r--r--lib/compiler/src/beam_disasm.erl12
-rw-r--r--lib/compiler/src/beam_except.erl149
-rw-r--r--lib/compiler/src/beam_utils.erl11
-rw-r--r--lib/compiler/src/cerl_inline.erl24
-rw-r--r--lib/compiler/src/compile.erl2
-rw-r--r--lib/compiler/src/compiler.app.src1
-rw-r--r--lib/compiler/src/sys_core_fold.erl6
-rw-r--r--lib/compiler/src/v3_codegen.erl37
-rw-r--r--lib/compiler/src/v3_kernel.erl22
-rw-r--r--lib/compiler/src/v3_life.erl34
-rw-r--r--lib/compiler/test/Makefile3
-rw-r--r--lib/compiler/test/beam_disasm_SUITE.erl4
-rw-r--r--lib/compiler/test/beam_expect_SUITE.erl67
-rw-r--r--lib/compiler/test/beam_validator_SUITE.erl27
-rw-r--r--lib/compiler/test/bs_match_SUITE.erl7
-rw-r--r--lib/compiler/test/compilation_SUITE.erl49
-rw-r--r--lib/compiler/test/compilation_SUITE_data/on_load_inline.erl23
-rw-r--r--lib/compiler/test/compile_SUITE.erl37
-rw-r--r--lib/compiler/test/compile_SUITE_data/attributes.erl23
-rw-r--r--lib/compiler/test/compiler.cover2
-rw-r--r--lib/compiler/test/core_SUITE.erl34
-rw-r--r--lib/compiler/test/core_SUITE_data/eval_is_boolean.core22
-rw-r--r--lib/compiler/test/core_SUITE_data/make_effect_seq.core51
-rw-r--r--lib/compiler/test/core_SUITE_data/nomatch_shadow.core28
-rw-r--r--lib/compiler/test/core_SUITE_data/reversed_annos.core49
-rw-r--r--lib/compiler/test/core_SUITE_data/unsafe_case.core25
-rw-r--r--lib/compiler/test/core_fold_SUITE.erl14
-rw-r--r--lib/compiler/test/misc_SUITE.erl20
-rw-r--r--lib/compiler/test/parteval_SUITE.erl66
-rw-r--r--lib/compiler/test/parteval_SUITE_data/t1.erl140
-rw-r--r--lib/compiler/test/test_lib.erl9
-rw-r--r--lib/compiler/test/trycatch_SUITE.erl18
-rw-r--r--lib/debugger/src/dbg_ui_break_win.erl12
-rw-r--r--lib/debugger/src/dbg_ui_edit_win.erl6
-rw-r--r--lib/debugger/src/dbg_ui_filedialog_win.erl7
-rw-r--r--lib/debugger/src/dbg_ui_mon_win.erl13
-rw-r--r--lib/debugger/src/dbg_ui_trace_win.erl19
-rw-r--r--lib/debugger/src/dbg_ui_win.erl9
-rw-r--r--lib/debugger/src/dbg_ui_winman.erl5
-rw-r--r--lib/debugger/src/dbg_wx_trace_win.erl1
-rw-r--r--lib/debugger/test/bs_construct_SUITE.erl2
-rw-r--r--lib/debugger/test/bs_match_misc_SUITE.erl2
-rw-r--r--lib/dialyzer/src/dialyzer_analysis_callgraph.erl13
-rw-r--r--lib/dialyzer/src/dialyzer_gui.erl17
-rw-r--r--lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_12
-rw-r--r--lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_20
-rw-r--r--lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_33
-rw-r--r--lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_1.erl18
-rw-r--r--lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_2.erl18
-rw-r--r--lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_3.erl16
-rw-r--r--lib/diameter/examples/code/GNUmakefile (renamed from lib/diameter/examples/GNUmakefile)10
-rw-r--r--lib/diameter/examples/code/client.erl (renamed from lib/diameter/examples/client.erl)2
-rw-r--r--lib/diameter/examples/code/client_cb.erl (renamed from lib/diameter/examples/client_cb.erl)0
-rw-r--r--lib/diameter/examples/code/peer.erl (renamed from lib/diameter/examples/peer.erl)0
-rw-r--r--lib/diameter/examples/code/redirect.erl (renamed from lib/diameter/examples/redirect.erl)0
-rw-r--r--lib/diameter/examples/code/redirect_cb.erl (renamed from lib/diameter/examples/redirect_cb.erl)0
-rw-r--r--lib/diameter/examples/code/relay.erl (renamed from lib/diameter/examples/relay.erl)0
-rw-r--r--lib/diameter/examples/code/relay_cb.erl (renamed from lib/diameter/examples/relay_cb.erl)0
-rw-r--r--lib/diameter/examples/code/sctp.erl (renamed from lib/diameter/examples/sctp.erl)18
-rw-r--r--lib/diameter/examples/code/server.erl (renamed from lib/diameter/examples/server.erl)0
-rw-r--r--lib/diameter/examples/code/server_cb.erl (renamed from lib/diameter/examples/server_cb.erl)0
-rw-r--r--lib/diameter/examples/dict/rfc4004_mip.dia280
-rw-r--r--lib/diameter/examples/dict/rfc4005_nas.dia740
-rw-r--r--lib/diameter/examples/dict/rfc4006_cc.dia349
-rw-r--r--lib/diameter/examples/dict/rfc4072_eap.dia150
-rw-r--r--lib/diameter/examples/dict/rfc4590_digest.dia45
-rw-r--r--lib/diameter/examples/dict/rfc4740_sip.dia446
-rw-r--r--lib/diameter/src/Makefile16
-rw-r--r--lib/diameter/src/base/diameter_service.erl20
-rw-r--r--lib/diameter/src/base/diameter_watchdog.erl40
-rw-r--r--lib/diameter/src/compiler/diameter_dict_util.erl19
-rw-r--r--lib/diameter/src/modules.mk22
-rw-r--r--lib/diameter/test/Makefile16
-rw-r--r--lib/diameter/test/diameter_capx_SUITE.erl58
-rw-r--r--lib/diameter/test/diameter_codec_SUITE.erl28
-rw-r--r--lib/diameter/test/diameter_codec_SUITE_data/avps.dia25
-rw-r--r--lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl76
-rw-r--r--lib/diameter/test/diameter_codec_SUITE_data/recv.dia51
-rw-r--r--lib/diameter/test/diameter_codec_SUITE_data/send.dia56
-rw-r--r--lib/diameter/test/diameter_compiler_SUITE.erl62
-rw-r--r--lib/diameter/test/diameter_dict_SUITE.erl15
-rw-r--r--lib/diameter/test/diameter_failover_SUITE.erl2
-rw-r--r--lib/diameter/test/diameter_gen_sctp_SUITE.erl354
-rw-r--r--lib/diameter/test/diameter_reg_SUITE.erl13
-rw-r--r--lib/diameter/test/diameter_relay_SUITE.erl28
-rw-r--r--lib/diameter/test/diameter_stats_SUITE.erl13
-rw-r--r--lib/diameter/test/diameter_sync_SUITE.erl13
-rw-r--r--lib/diameter/test/diameter_tls_SUITE.erl22
-rw-r--r--lib/diameter/test/diameter_traffic_SUITE.erl23
-rw-r--r--lib/diameter/test/diameter_transport_SUITE.erl37
-rw-r--r--lib/diameter/test/diameter_util.erl2
-rw-r--r--lib/diameter/test/diameter_watchdog_SUITE.erl11
-rw-r--r--lib/diameter/test/modules.mk7
-rw-r--r--lib/erl_docgen/priv/css/otp_doc.css29
-rw-r--r--lib/erl_docgen/priv/xsl/db_html.xsl154
-rw-r--r--lib/erl_interface/src/misc/ei_format.c3
-rw-r--r--lib/et/src/et_gs_contents_viewer.erl11
-rw-r--r--lib/et/src/et_gs_viewer.erl17
-rw-r--r--lib/gs/contribs/bonk/bonk.erl6
-rw-r--r--lib/gs/contribs/cols/cols.erl6
-rw-r--r--lib/gs/contribs/cols/highscore.erl7
-rw-r--r--lib/gs/contribs/mandel/mandel.erl5
-rw-r--r--lib/gs/contribs/othello/othello_board.erl6
-rw-r--r--lib/gs/doc/src/gs.xml4
-rw-r--r--lib/gs/examples/ball.erl6
-rw-r--r--lib/gs/examples/browser.erl8
-rw-r--r--lib/gs/examples/calc.erl5
-rw-r--r--lib/gs/examples/calc2.erl6
-rw-r--r--lib/gs/examples/color_demo.erl5
-rw-r--r--lib/gs/examples/color_demo2.erl4
-rw-r--r--lib/gs/examples/distrib_draw.erl5
-rw-r--r--lib/gs/examples/entry_demo.erl6
-rw-r--r--lib/gs/examples/event_test.erl3
-rw-r--r--lib/gs/examples/file_dialog.erl5
-rw-r--r--lib/gs/examples/focus_demo.erl5
-rw-r--r--lib/gs/examples/frac.erl3
-rw-r--r--lib/gs/examples/line_demo.erl6
-rw-r--r--lib/gs/examples/man.erl9
-rw-r--r--lib/gs/examples/menu_demo.erl6
-rw-r--r--lib/gs/examples/rubber.erl8
-rw-r--r--lib/gs/src/gs.erl8
-rw-r--r--lib/gs/src/gs_frontend.erl2
-rw-r--r--lib/gs/src/gs_make.erl1
-rw-r--r--lib/gs/src/gse.erl62
-rw-r--r--lib/gs/src/gstk.erl2
-rw-r--r--lib/gs/src/gstk_arc.erl1
-rw-r--r--lib/gs/src/gstk_canvas.erl2
-rw-r--r--lib/gs/src/gstk_editor.erl3
-rw-r--r--lib/gs/src/gstk_entry.erl1
-rw-r--r--lib/gs/src/gstk_generic.erl1
-rw-r--r--lib/gs/src/gstk_grid.erl1
-rw-r--r--lib/gs/src/gstk_gridline.erl2
-rw-r--r--lib/gs/src/gstk_image.erl1
-rw-r--r--lib/gs/src/gstk_menu.erl1
-rw-r--r--lib/gs/src/gstk_menuitem.erl1
-rw-r--r--lib/gs/src/gstk_port_handler.erl1
-rw-r--r--lib/gs/src/gstk_rectangle.erl1
-rw-r--r--lib/gs/src/gstk_window.erl1
-rw-r--r--lib/gs/src/tcl2erl.erl1
-rw-r--r--lib/gs/src/tool_file_dialog.erl10
-rw-r--r--lib/gs/src/tool_utils.erl5
-rw-r--r--lib/hipe/cerl/cerl_hipe_primops.hrl1
-rw-r--r--lib/hipe/cerl/cerl_hipeify.erl1
-rw-r--r--lib/hipe/cerl/cerl_messagean.erl1
-rw-r--r--lib/hipe/cerl/cerl_to_icode.erl3
-rw-r--r--lib/hipe/cerl/erl_bif_types.erl57
-rw-r--r--lib/hipe/flow/Makefile2
-rw-r--r--lib/hipe/icode/Makefile2
-rw-r--r--lib/hipe/icode/hipe_beam_to_icode.erl4
-rw-r--r--lib/hipe/icode/hipe_icode_inline_bifs.erl3
-rw-r--r--lib/hipe/icode/hipe_icode_type.erl6
-rw-r--r--lib/hipe/main/hipe.app.src1
-rw-r--r--lib/hipe/main/hipe.erl6
-rw-r--r--lib/hipe/opt/Makefile2
-rw-r--r--lib/hipe/rtl/Makefile52
-rw-r--r--lib/hipe/tools/hipe_tool.erl12
-rw-r--r--lib/inviso/test/inviso_tool_SUITE.erl7
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangAtom.java2
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangString.java17
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java4
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpNode.java4
-rw-r--r--lib/jinterface/test/nc_SUITE.erl7
-rw-r--r--lib/jinterface/test/nc_SUITE_data/echo_server.java6
-rw-r--r--lib/kernel/src/code_server.erl10
-rw-r--r--lib/kernel/src/gen_sctp.erl6
-rw-r--r--lib/kernel/test/code_SUITE.erl49
-rw-r--r--lib/kernel/test/erl_prim_loader_SUITE.erl8
-rw-r--r--lib/kernel/test/file_SUITE.erl167
-rw-r--r--lib/kernel/test/prim_file_SUITE.erl109
-rw-r--r--lib/kernel/vsn.mk2
-rw-r--r--lib/mnesia/src/mnesia_locker.erl181
-rw-r--r--lib/observer/src/etop_gui.erl7
-rw-r--r--lib/observer/src/observer_lib.erl36
-rw-r--r--lib/observer/src/observer_procinfo.erl101
-rw-r--r--lib/observer/src/observer_tv_table.erl109
-rw-r--r--lib/observer/src/observer_tv_wx.erl4
-rw-r--r--lib/observer/test/etop_SUITE.erl13
-rw-r--r--lib/orber/src/orber_ifr.erl2
-rw-r--r--lib/orber/src/orber_tb.erl2
-rw-r--r--lib/orber/test/orber_SUITE.erl36
-rw-r--r--lib/orber/test/orber_acl_SUITE.erl2
-rw-r--r--lib/os_mon/c_src/memsup.c12
-rw-r--r--lib/os_mon/src/cpu_sup.erl5
-rw-r--r--lib/os_mon/src/memsup.erl3
-rw-r--r--lib/os_mon/src/os_mon.erl20
-rw-r--r--lib/os_mon/src/os_mon_sysinfo.erl6
-rw-r--r--lib/pman/doc/src/pman.xml6
-rw-r--r--lib/pman/doc/src/pman_chapter.xml6
-rw-r--r--lib/pman/src/pman_buf_converter.erl1
-rw-r--r--lib/pman/src/pman_buf_printer.erl2
-rw-r--r--lib/pman/src/pman_main.erl2
-rw-r--r--lib/pman/src/pman_module_info.erl2
-rw-r--r--lib/pman/src/pman_shell.erl4
-rw-r--r--lib/pman/src/pman_tool.erl1
-rw-r--r--lib/pman/src/pman_win.erl10
-rw-r--r--lib/public_key/.gitignore10
-rw-r--r--lib/public_key/doc/src/public_key.xml2
-rw-r--r--lib/public_key/src/pubkey_ssh.erl95
-rw-r--r--lib/runtime_tools/c_src/trace_ip_drv.c22
-rw-r--r--lib/runtime_tools/test/inviso_SUITE.erl17
-rw-r--r--lib/sasl/doc/src/appup.xml2
-rw-r--r--lib/sasl/doc/src/systools.xml4
-rw-r--r--lib/sasl/src/release_handler.erl2
-rw-r--r--lib/sasl/src/systools_make.erl94
-rw-r--r--lib/sasl/test/release_handler_SUITE.erl56
-rw-r--r--lib/sasl/test/systools_SUITE.erl125
-rw-r--r--lib/snmp/doc/src/notes.xml118
-rw-r--r--lib/snmp/doc/src/snmp.xml28
-rw-r--r--lib/snmp/doc/src/snmp_app.xml12
-rw-r--r--lib/snmp/doc/src/snmp_config.xml12
-rw-r--r--lib/snmp/doc/src/snmp_manager_netif.xml43
-rw-r--r--lib/snmp/doc/src/snmpa.xml32
-rw-r--r--lib/snmp/doc/src/snmpm.xml34
-rw-r--r--lib/snmp/doc/src/snmpm_network_interface_filter.xml9
-rw-r--r--lib/snmp/src/agent/snmpa.erl24
-rw-r--r--lib/snmp/src/app/snmp.app.src3
-rw-r--r--lib/snmp/src/app/snmp.appup.src319
-rw-r--r--lib/snmp/src/app/snmp.erl7
-rw-r--r--lib/snmp/src/manager/depend.mk9
-rw-r--r--lib/snmp/src/manager/modules.mk3
-rw-r--r--lib/snmp/src/manager/snmpm.erl25
-rw-r--r--lib/snmp/src/manager/snmpm_config.erl2
-rw-r--r--lib/snmp/src/manager/snmpm_mpd.erl6
-rw-r--r--lib/snmp/src/manager/snmpm_net_if_mt.erl1259
-rw-r--r--lib/snmp/src/misc/snmp_log.erl110
-rw-r--r--lib/snmp/src/misc/snmp_verbosity.erl4
-rw-r--r--lib/snmp/test/exp/.gitignore0
-rw-r--r--lib/snmp/test/exp/snmp_agent_bl_test.erl (renamed from lib/snmp/test/snmp_agent_bl_test.erl)0
-rw-r--r--lib/snmp/test/exp/snmp_agent_ms_test.erl (renamed from lib/snmp/test/snmp_agent_ms_test.erl)0
-rw-r--r--lib/snmp/test/exp/snmp_agent_mt_test.erl (renamed from lib/snmp/test/snmp_agent_mt_test.erl)0
-rw-r--r--lib/snmp/test/exp/snmp_agent_v1_test.erl (renamed from lib/snmp/test/snmp_agent_v1_test.erl)0
-rw-r--r--lib/snmp/test/exp/snmp_agent_v2_test.erl (renamed from lib/snmp/test/snmp_agent_v2_test.erl)0
-rw-r--r--lib/snmp/test/exp/snmp_agent_v3_test.erl (renamed from lib/snmp/test/snmp_agent_v3_test.erl)0
-rw-r--r--lib/snmp/test/snmp_SUITE.erl47
-rw-r--r--lib/snmp/test/snmp_agent_test.erl413
-rw-r--r--lib/snmp/test/snmp_agent_test_lib.erl211
-rw-r--r--lib/snmp/test/snmp_app_test.erl40
-rw-r--r--lib/snmp/test/snmp_compiler_test.erl61
-rw-r--r--lib/snmp/test/snmp_log_test.erl27
-rw-r--r--lib/snmp/test/snmp_manager_test.erl294
-rw-r--r--lib/snmp/test/snmp_test_lib.erl87
-rw-r--r--lib/snmp/vsn.mk6
-rw-r--r--lib/ssh/doc/src/ssh.xml57
-rw-r--r--lib/ssh/src/DSS.asn120
-rw-r--r--lib/ssh/src/Makefile33
-rw-r--r--lib/ssh/src/PKCS-1.asn1116
-rw-r--r--lib/ssh/src/prebuild.skip2
-rw-r--r--lib/ssh/src/ssh.app.src7
-rw-r--r--lib/ssh/src/ssh.erl96
-rw-r--r--lib/ssh/src/ssh.hrl17
-rw-r--r--lib/ssh/src/ssh_auth.erl160
-rw-r--r--lib/ssh/src/ssh_bits.erl6
-rw-r--r--lib/ssh/src/ssh_connection.erl4
-rw-r--r--lib/ssh/src/ssh_connection_handler.erl45
-rw-r--r--lib/ssh/src/ssh_connection_manager.erl6
-rw-r--r--lib/ssh/src/ssh_dsa.erl95
-rw-r--r--lib/ssh/src/ssh_file.erl641
-rw-r--r--lib/ssh/src/ssh_key_api.erl45
-rw-r--r--lib/ssh/src/ssh_rsa.erl298
-rw-r--r--lib/ssh/src/ssh_sftpd.erl22
-rw-r--r--lib/ssh/src/ssh_transport.erl266
-rw-r--r--lib/ssh/src/ssh_xfer.erl16
-rw-r--r--lib/ssh/test/Makefile3
-rw-r--r--lib/ssh/test/ssh_SUITE.erl72
-rw-r--r--lib/ssh/test/ssh_basic_SUITE.erl173
-rw-r--r--lib/ssh/test/ssh_basic_SUITE_data/id_dsa13
-rw-r--r--lib/ssh/test/ssh_basic_SUITE_data/id_rsa15
-rw-r--r--lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key13
-rw-r--r--lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key.pub11
-rw-r--r--lib/ssh/test/ssh_basic_SUITE_data/ssh_host_rsa_key16
-rw-r--r--lib/ssh/test/ssh_basic_SUITE_data/ssh_host_rsa_key.pub5
-rw-r--r--lib/ssh/test/ssh_sftp_SUITE.erl44
-rw-r--r--lib/ssh/test/ssh_sftp_SUITE_data/id_rsa15
-rw-r--r--lib/ssh/test/ssh_sftp_SUITE_data/id_rsa.pub1
-rw-r--r--lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key13
-rw-r--r--lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key.pub11
-rw-r--r--lib/ssh/test/ssh_sftpd_SUITE.erl42
-rw-r--r--lib/ssh/test/ssh_sftpd_SUITE_data/id_dsa13
-rw-r--r--lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key13
-rw-r--r--lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key.pub11
-rw-r--r--lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl57
-rw-r--r--lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/id_dsa13
-rw-r--r--lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key13
-rw-r--r--lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key.pub11
-rw-r--r--lib/ssh/test/ssh_test_lib.erl620
-rw-r--r--lib/ssh/test/ssh_to_openssh_SUITE.erl149
-rw-r--r--lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key13
-rw-r--r--lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key.pub11
-rw-r--r--lib/ssl/src/inet_tls_dist.erl14
-rw-r--r--lib/ssl/src/ssl_handshake.erl17
-rw-r--r--lib/ssl/src/ssl_tls_dist_proxy.erl46
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl105
-rw-r--r--lib/ssl/test/ssl_dist_SUITE.erl10
-rw-r--r--lib/ssl/test/ssl_to_openssl_SUITE.erl6
-rw-r--r--lib/stdlib/doc/src/binary.xml2
-rw-r--r--lib/stdlib/doc/src/gb_trees.xml18
-rw-r--r--lib/stdlib/doc/src/io.xml2
-rw-r--r--lib/stdlib/doc/src/ms_transform.xml4
-rw-r--r--lib/stdlib/doc/src/sofs.xml10
-rw-r--r--lib/stdlib/doc/src/supervisor.xml13
-rw-r--r--lib/stdlib/src/erl_eval.erl1
-rw-r--r--lib/stdlib/src/erl_expand_records.erl17
-rw-r--r--lib/stdlib/src/erl_lint.erl35
-rw-r--r--lib/stdlib/src/error_logger_file_h.erl23
-rw-r--r--lib/stdlib/src/error_logger_tty_h.erl23
-rw-r--r--lib/stdlib/src/gen_fsm.erl2
-rw-r--r--lib/stdlib/src/gen_server.erl2
-rw-r--r--lib/stdlib/src/ms_transform.erl2
-rw-r--r--lib/stdlib/src/otp_internal.erl18
-rw-r--r--lib/stdlib/src/supervisor.erl12
-rw-r--r--lib/stdlib/test/erl_eval_SUITE.erl25
-rw-r--r--lib/stdlib/test/erl_expand_records_SUITE.erl12
-rw-r--r--lib/stdlib/test/erl_lint_SUITE.erl30
-rw-r--r--lib/stdlib/test/ets_SUITE.erl16
-rw-r--r--lib/stdlib/test/ms_transform_SUITE.erl5
-rw-r--r--lib/stdlib/test/re_SUITE.erl54
-rw-r--r--lib/stdlib/test/shell_SUITE.erl29
-rw-r--r--lib/stdlib/test/sofs_SUITE.erl64
-rw-r--r--lib/stdlib/test/supervisor_SUITE.erl65
-rw-r--r--lib/stdlib/vsn.mk2
-rw-r--r--lib/syntax_tools/src/Makefile2
-rw-r--r--lib/syntax_tools/src/erl_syntax.erl3
-rw-r--r--lib/toolbar/doc/src/toolbar.xml5
-rw-r--r--lib/toolbar/doc/src/toolbar_chapter.xml5
-rw-r--r--lib/toolbar/src/canvasbutton.erl3
-rw-r--r--lib/toolbar/src/toolbar.erl1
-rw-r--r--lib/toolbar/src/toolbar_graphics.erl3
-rw-r--r--lib/toolbar/src/toolbar_toolconfig.erl5
-rw-r--r--lib/tools/c_src/Makefile.in27
-rw-r--r--lib/tools/c_src/erl_memory.c7
-rw-r--r--lib/tools/test/fprof_SUITE.erl16
-rw-r--r--lib/tv/doc/src/table_visualizer_chapter.xml6
-rw-r--r--lib/tv/doc/src/tv.xml6
-rw-r--r--lib/tv/src/tv_db.erl4
-rw-r--r--lib/tv/src/tv_db_search.erl12
-rw-r--r--lib/tv/src/tv_etsread.erl3
-rw-r--r--lib/tv/src/tv_info.erl8
-rw-r--r--lib/tv/src/tv_ip.erl6
-rw-r--r--lib/tv/src/tv_main.erl14
-rw-r--r--lib/tv/src/tv_new_table.erl10
-rw-r--r--lib/tv/src/tv_nodewin.erl9
-rw-r--r--lib/tv/src/tv_pb.erl3
-rw-r--r--lib/tv/src/tv_pb_funcs.erl6
-rw-r--r--lib/tv/src/tv_pc.erl1
-rw-r--r--lib/tv/src/tv_pc_menu_handling.erl4
-rw-r--r--lib/tv/src/tv_pd.erl5
-rw-r--r--lib/tv/src/tv_pd_display.erl7
-rw-r--r--lib/tv/src/tv_pd_frames.erl2
-rw-r--r--lib/tv/src/tv_pd_scale.erl2
-rw-r--r--lib/tv/src/tv_pg.erl1
-rw-r--r--lib/tv/src/tv_pg_gridfcns.erl4
-rw-r--r--lib/tv/src/tv_poll_dialog.erl8
-rw-r--r--lib/tv/src/tv_pw.erl1
-rw-r--r--lib/tv/src/tv_pw_window.erl4
-rw-r--r--lib/tv/src/tv_rec_edit.erl10
-rw-r--r--lib/tv/src/tv_utils.erl3
-rw-r--r--lib/wx/doc/src/Makefile2
-rw-r--r--lib/xmerl/doc/src/xmerl_ug.xmlsrc4
-rw-r--r--lib/xmerl/src/xmerl_uri.erl2
373 files changed, 9711 insertions, 4143 deletions
diff --git a/lib/Makefile b/lib/Makefile
index 402e73722a..aa4e074830 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -19,53 +19,21 @@
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
-#
-# Macros
-#
-ifeq ($(findstring vxworks,$(TARGET)),vxworks)
- ERTS_SUB_DIRECTORIES = stdlib sasl kernel compiler
- OTHER_SUB_DIRECTORIES = \
- snmp otp_mibs appmon erl_interface os_mon tools runtime_tools
- ifdef BUILD_ALL
- OTHER_SUB_DIRECTORIES += mnesia jinterface ic asn1 debugger \
- inets mnesia_session diameter orber pman tv observer \
- cosTransactions cosEvent cosTime cosNotification cosProperty
- cosFileTransfer cosEventDomain
- endif
-else
-#
-# unix and win32
-# --------------
-#
- ERTS_SUB_DIRECTORIES = stdlib sasl kernel compiler
- OTHER_SUB_DIRECTORIES = tools test_server common_test runtime_tools
- ifdef BUILD_ALL
- ifeq ($(findstring win32,$(TARGET)),win32) # BUILD_ALL on win32
- OTHER_SUB_DIRECTORIES += \
- snmp otp_mibs appmon erl_interface asn1 jinterface gs wx inets ic \
- mnesia crypto orber os_mon parsetools syntax_tools pman \
- public_key ssl toolbar tv observer debugger reltool odbc \
- diameter \
- cosTransactions cosEvent cosTime cosNotification cosProperty \
- cosFileTransfer cosEventDomain et megaco webtool \
- xmerl edoc eunit ssh inviso typer erl_docgen \
- common_test percept dialyzer
-# dialyzer
- OTHER_SUB_DIRECTORIES += hipe
- else # BUILD_ALL on unix
- OTHER_SUB_DIRECTORIES += \
- snmp otp_mibs appmon erl_interface asn1 jinterface wx debugger reltool gs inets \
+ERTS_SUB_DIRECTORIES = stdlib sasl kernel compiler
+OTHER_SUB_DIRECTORIES = tools test_server common_test runtime_tools
+ifdef BUILD_ALL
+ OTHER_SUB_DIRECTORIES += \
+ snmp otp_mibs appmon erl_interface asn1 jinterface \
+ wx debugger reltool gs inets \
ic mnesia crypto orber os_mon parsetools syntax_tools \
pman public_key ssl toolbar tv observer odbc \
diameter \
cosTransactions cosEvent cosTime cosNotification \
cosProperty cosFileTransfer cosEventDomain et megaco webtool \
xmerl edoc eunit ssh inviso typer erl_docgen \
- common_test percept dialyzer
-# dialyzer
- OTHER_SUB_DIRECTORIES += hipe $(TSP_APP)
- endif
- endif
+ percept dialyzer hipe
+ EXTRA_FILE := $(wildcard EXTRA-APPLICATIONS)
+ EXTRA_APPLICATIONS := $(if $(EXTRA_FILE),$(shell cat $(EXTRA_FILE)))
endif
ifdef BOOTSTRAP
@@ -78,7 +46,9 @@ else
ifdef TERTIARY_BOOTSTRAP
SUB_DIRECTORIES = snmp sasl jinterface ic syntax_tools wx
else # Not bootstrap build
- SUB_DIRECTORIES = $(ERTS_SUB_DIRECTORIES) $(OTHER_SUB_DIRECTORIES)
+ SUB_DIRECTORIES = $(ERTS_SUB_DIRECTORIES) \
+ $(OTHER_SUB_DIRECTORIES) \
+ $(EXTRA_APPLICATIONS)
endif
endif
endif
diff --git a/lib/appmon/doc/src/appmon.xml b/lib/appmon/doc/src/appmon.xml
index ae6147a387..5af50daa53 100644
--- a/lib/appmon/doc/src/appmon.xml
+++ b/lib/appmon/doc/src/appmon.xml
@@ -32,6 +32,12 @@
<module>appmon</module>
<modulesummary>A graphical node and application process tree viewer.</modulesummary>
<description>
+ <warning>
+ <p>
+ The Appmon application has been superseded by the Observer application.
+ Appmon will be removed in R16.
+ </p>
+ </warning>
<p>The application monitor Appmon is a graphical utility used to
supervise applications executing either locally or on remote nodes.
The process tree of an application can furthermore be monitored.</p>
diff --git a/lib/appmon/doc/src/appmon_chapter.xml b/lib/appmon/doc/src/appmon_chapter.xml
index 0dab23b549..3f642ad002 100644
--- a/lib/appmon/doc/src/appmon_chapter.xml
+++ b/lib/appmon/doc/src/appmon_chapter.xml
@@ -31,6 +31,12 @@
<section>
<title>Introduction</title>
+ <warning>
+ <p>
+ The Appmon application has been superseded by the Observer application.
+ Appmon will be removed in R16.
+ </p>
+ </warning>
<p>The application monitor Appmon is a graphical node and application viewer. The tool shows an overview of all applications on all known nodes, and it is possible to view the process tree for an application running on any of the nodes.</p>
<note>
<p>If the Appmon code is not available at a node, for example an
diff --git a/lib/appmon/src/appmon.erl b/lib/appmon/src/appmon.erl
index 2b982cddf0..7a6d86c9ab 100644
--- a/lib/appmon/src/appmon.erl
+++ b/lib/appmon/src/appmon.erl
@@ -17,6 +17,11 @@
%% %CopyrightEnd%
-module(appmon).
-behaviour(gen_server).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,1}}]).
%%%---------------------------------------------------------------------
%%% Appmon main module.
diff --git a/lib/appmon/src/appmon_a.erl b/lib/appmon/src/appmon_a.erl
index b0b5847343..2c8185a85d 100644
--- a/lib/appmon/src/appmon_a.erl
+++ b/lib/appmon/src/appmon_a.erl
@@ -17,6 +17,11 @@
%% %CopyrightEnd%
%%
-module(appmon_a).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,1}}]).
%%----------------------------------------------------------------------
%%
diff --git a/lib/appmon/src/appmon_lb.erl b/lib/appmon/src/appmon_lb.erl
index 4e433f37c5..55fda83027 100644
--- a/lib/appmon/src/appmon_lb.erl
+++ b/lib/appmon/src/appmon_lb.erl
@@ -29,6 +29,13 @@
%%% then pressing the load button, its application window is started.
-module(appmon_lb).
+-compile([{nowarn_deprecated_function,{gs,button,3}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,listbox,3}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
-export ([
start/1,
diff --git a/lib/appmon/src/appmon_txt.erl b/lib/appmon/src/appmon_txt.erl
index 4e1785c53f..8647bc9890 100644
--- a/lib/appmon/src/appmon_txt.erl
+++ b/lib/appmon/src/appmon_txt.erl
@@ -22,6 +22,11 @@
%%------------------------------------------------------------
-module(appmon_txt).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,1}}]).
-export([start/0, start/1, print/1, fprint/1]).
%% gen_server stuff
diff --git a/lib/asn1/c_src/asn1_erl_nif.c b/lib/asn1/c_src/asn1_erl_nif.c
index 9c9f83bc2a..accd368af1 100644
--- a/lib/asn1/c_src/asn1_erl_nif.c
+++ b/lib/asn1/c_src/asn1_erl_nif.c
@@ -580,7 +580,7 @@ int per_insert_bits_as_bits(int desired_no, int no_bytes,
unsigned char **input_ptr, unsigned char **output_ptr, int *unused) {
unsigned char *in_ptr = *input_ptr;
unsigned char val;
- int no_bits, ret, ret2;
+ int no_bits, ret;
if (desired_no == (no_bytes * 8)) {
if (per_insert_octets_unaligned(no_bytes, &in_ptr, output_ptr, *unused)
@@ -606,8 +606,7 @@ int per_insert_bits_as_bits(int desired_no, int no_bytes,
== ASN1_ERROR
)
return ASN1_ERROR;
- ret2 = per_pad_bits(desired_no - (no_bytes * 8), output_ptr, unused);
- /* printf("ret2 = %d\n\r",ret2); */
+ per_pad_bits(desired_no - (no_bytes * 8), output_ptr, unused);
ret = CEIL(desired_no,8);
/* printf("ret = %d\n\r",ret); */
}
diff --git a/lib/asn1/src/asn1ct_check.erl b/lib/asn1/src/asn1ct_check.erl
index e318477234..105fc02819 100644
--- a/lib/asn1/src/asn1ct_check.erl
+++ b/lib/asn1/src/asn1ct_check.erl
@@ -5253,6 +5253,9 @@ check_int(S,[{'NamedNumber',Id,Num}|T],Acc) when is_integer(Num) ->
check_int(S,[{'NamedNumber',Id,{identifier,_,Name}}|T],Acc) ->
Val = dbget_ex(S,S#state.mname,Name),
check_int(S,[{'NamedNumber',Id,Val#valuedef.value}|T],Acc);
+check_int(S,[{'NamedNumber',Id,{'Externalvaluereference',_,Mod,Name}}|T],Acc) ->
+ Val = dbget_ex(S,Mod,Name),
+ check_int(S,[{'NamedNumber',Id,Val#valuedef.value}|T],Acc);
check_int(_S,[],Acc) ->
lists:keysort(2,Acc).
diff --git a/lib/asn1/src/asn1ct_gen_per.erl b/lib/asn1/src/asn1ct_gen_per.erl
index b90a0adf81..8fd7a69a19 100644
--- a/lib/asn1/src/asn1ct_gen_per.erl
+++ b/lib/asn1/src/asn1ct_gen_per.erl
@@ -358,6 +358,10 @@ greatest_common_range2({_,Int},VR={_Lb,_Ub}) when is_integer(Int) ->
greatest_common_range2({_,L},{Lb,Ub}) when is_list(L) ->
Min = least_Lb([Lb|L]),
Max = greatest_Ub([Ub|L]),
+ [{'ValueRange',{Min,Max}}];
+greatest_common_range2({Lb1,Ub1},{Lb2,Ub2}) ->
+ Min = least_Lb([Lb1,Lb2]),
+ Max = greatest_Ub([Ub1,Ub2]),
[{'ValueRange',{Min,Max}}].
mk_vr([{Type,I}]) when is_atom(Type), is_integer(I) ->
diff --git a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl b/lib/asn1/src/asn1ct_gen_per_rt2ct.erl
index 1a0a0e211d..fb9613c18d 100644
--- a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl
+++ b/lib/asn1/src/asn1ct_gen_per_rt2ct.erl
@@ -704,6 +704,10 @@ greatest_common_range([{_,Int}],VR=[{_,{_Lb,_Ub}}]) when is_integer(Int) ->
greatest_common_range([{_,L}],[{_,{Lb,Ub}}]) when is_list(L) ->
Min = least_Lb([Lb|L]),
Max = greatest_Ub([Ub|L]),
+ [{'ValueRange',{Min,Max}}];
+greatest_common_range([{_,{Lb1,Ub1}}],[{_,{Lb2,Ub2}}]) ->
+ Min = least_Lb([Lb1,Lb2]),
+ Max = greatest_Ub([Ub1,Ub2]),
[{'ValueRange',{Min,Max}}].
diff --git a/lib/asn1/test/asn1_SUITE.erl.src b/lib/asn1/test/asn1_SUITE.erl.src
index 124ee2d2bb..3f51b125ec 100644
--- a/lib/asn1/test/asn1_SUITE.erl.src
+++ b/lib/asn1/test/asn1_SUITE.erl.src
@@ -96,7 +96,8 @@ all() -> [{group,compile},parse,default_per,default_ber,default_per_opt,per,
testSSLspecs, testNortel,test_undecoded_rest,
test_inline, testTcapsystem, testNBAPsystem,
test_compile_options,testDoubleEllipses, test_modified_x420,
- testX420, test_x691,ticket_6143, testExtensionAdditionGroup
+ testX420, test_x691,ticket_6143, testExtensionAdditionGroup,
+ test_OTP_9688
] ++ common() ++ particular().
groups() ->
@@ -2369,4 +2370,23 @@ test_modules() ->
"LDAP"
].
-
+test_OTP_9688(Config) ->
+ Asn1Mod = "OTP-9688.asn1",
+ %%DataDir = ?config(data_dir,Config),
+ PrivDir = ?config(priv_dir,Config),
+ Data = "
+OTP-9688 DEFINITIONS ::= BEGIN
+
+ foo INTEGER ::= 1
+ bar INTEGER ::= 42
+
+ Baz ::= INTEGER {x-y-z1(foo), x-y-z2(bar)}
+ Qux ::= SEQUENCE {flerpInfo SEQUENCE {x INTEGER (-10 | -9 | (0..4))} OPTIONAL}
+
+END
+",
+ File = filename:join(PrivDir,Asn1Mod),
+ ok = file:write_file(File, Data),
+ %% Does it compile with changes to asn1ct_check and asn1ct_gen_per_rt2ct?
+ %% (see ticket)
+ ok = asn1ct:compile(File, [{outdir, PrivDir}]).
diff --git a/lib/compiler/doc/src/compile.xml b/lib/compiler/doc/src/compile.xml
index 522c1dc411..0f8abf1ccf 100644
--- a/lib/compiler/doc/src/compile.xml
+++ b/lib/compiler/doc/src/compile.xml
@@ -333,7 +333,7 @@ module.beam: module.erl \
<tag><c>{d,Macro,Value}</c></tag>
<item>
<p>Defines a macro <c>Macro</c> to have the value
- <c>Value</c>. The default is <c>true</c>).</p>
+ <c>Value</c>. The default is <c>true</c>.</p>
</item>
<tag><c>{parse_transform,Module}</c></tag>
diff --git a/lib/compiler/src/Makefile b/lib/compiler/src/Makefile
index 7a237608ad..3415517fff 100644
--- a/lib/compiler/src/Makefile
+++ b/lib/compiler/src/Makefile
@@ -53,6 +53,7 @@ MODULES = \
beam_dead \
beam_dict \
beam_disasm \
+ beam_except \
beam_flatten \
beam_jump \
beam_listing \
diff --git a/lib/compiler/src/beam_disasm.erl b/lib/compiler/src/beam_disasm.erl
index 7103d2390f..62bdc74cc8 100644
--- a/lib/compiler/src/beam_disasm.erl
+++ b/lib/compiler/src/beam_disasm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -182,10 +182,14 @@ process_chunks(F) ->
Literals = beam_disasm_literals(LiteralBin),
Code = beam_disasm_code(CodeBin, Atoms, mk_imports(ImportsList),
StrBin, Lambdas, Literals, Module),
- Attributes = optional_chunk(F, attributes),
+ Attributes =
+ case optional_chunk(F, attributes) of
+ none -> [];
+ Atts when is_list(Atts) -> Atts
+ end,
CompInfo =
case optional_chunk(F, "CInf") of
- none -> none;
+ none -> [];
CompInfoBin when is_binary(CompInfoBin) ->
binary_to_term(CompInfoBin)
end,
@@ -198,7 +202,7 @@ process_chunks(F) ->
end.
%%-----------------------------------------------------------------------
-%% Retrieve an optional chunk or none if the chunk doesn't exist.
+%% Retrieve an optional chunk or return 'none' if the chunk doesn't exist.
%%-----------------------------------------------------------------------
optional_chunk(F, ChunkTag) ->
diff --git a/lib/compiler/src/beam_except.erl b/lib/compiler/src/beam_except.erl
new file mode 100644
index 0000000000..fb1a43cd9e
--- /dev/null
+++ b/lib/compiler/src/beam_except.erl
@@ -0,0 +1,149 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(beam_except).
+-export([module/2]).
+
+%%% Rewrite certain calls to erlang:error/{1,2} to specialized
+%%% instructions:
+%%%
+%%% erlang:error({badmatch,Value}) => badmatch Value
+%%% erlang:error({case_clause,Value}) => case_end Value
+%%% erlang:error({try_clause,Value}) => try_case_end Value
+%%% erlang:error(if_clause) => if_end
+%%% erlang:error(function_clause, Args) => jump FuncInfoLabel
+%%%
+
+-import(lists, [reverse/1]).
+
+module({Mod,Exp,Attr,Fs0,Lc}, _Opt) ->
+ Fs = [function(F) || F <- Fs0],
+ {ok,{Mod,Exp,Attr,Fs,Lc}}.
+
+function({function,Name,Arity,CLabel,Is0}) ->
+ try
+ Is = function_1(Is0),
+ {function,Name,Arity,CLabel,Is}
+ catch
+ Class:Error ->
+ Stack = erlang:get_stacktrace(),
+ io:fwrite("Function: ~w/~w\n", [Name,Arity]),
+ erlang:raise(Class, Error, Stack)
+ end.
+
+-record(st,
+ {lbl, %func_info label
+ loc %location for func_info
+ }).
+
+function_1(Is0) ->
+ case Is0 of
+ [{label,Lbl},{line,Loc}|_] ->
+ St = #st{lbl=Lbl,loc=Loc},
+ translate(Is0, St, []);
+ [{label,_}|_] ->
+ %% No line numbers. The source must be a .S file.
+ %% There is no need to do anything.
+ Is0
+ end.
+
+translate([{call_ext,Ar,{extfunc,erlang,error,Ar}}=I|Is], St, Acc) ->
+ translate_1(Ar, I, Is, St, Acc);
+translate([{call_ext_only,Ar,{extfunc,erlang,error,Ar}}=I|Is], St, Acc) ->
+ translate_1(Ar, I, Is, St, Acc);
+translate([{call_ext_last,Ar,{extfunc,erlang,error,Ar},_}=I|Is], St, Acc) ->
+ translate_1(Ar, I, Is, St, Acc);
+translate([I|Is], St, Acc) ->
+ translate(Is, St, [I|Acc]);
+translate([], _, Acc) ->
+ reverse(Acc).
+
+translate_1(Ar, I, Is, St, [{line,_}=Line|Acc1]=Acc0) ->
+ case dig_out(Ar, Acc1) of
+ no ->
+ translate(Is, St, [I|Acc0]);
+ {yes,function_clause,Acc2} ->
+ case {Line,St} of
+ {{line,Loc},#st{lbl=Fi,loc=Loc}} ->
+ Instr = {jump,{f,Fi}},
+ translate(Is, St, [Instr|Acc2]);
+ {_,_} ->
+ %% This must be "error(function_clause, Args)" in
+ %% the Erlang source code. Don't translate.
+ translate(Is, St, [I|Acc0])
+ end;
+ {yes,Instr,Acc2} ->
+ translate(Is, St, [Instr,Line|Acc2])
+ end.
+
+dig_out(Ar, [{kill,_}|Is]) ->
+ dig_out(Ar, Is);
+dig_out(1, [{block,Bl0}|Is]) ->
+ case dig_out_block(reverse(Bl0)) of
+ no -> no;
+ {yes,What,[]} ->
+ {yes,What,Is};
+ {yes,What,Bl} ->
+ {yes,What,[{block,Bl}|Is]}
+ end;
+dig_out(2, [{block,Bl}|Is]) ->
+ case dig_out_block_fc(Bl) of
+ no -> no;
+ {yes,What} -> {yes,What,Is}
+ end;
+dig_out(_, _) -> no.
+
+dig_out_block([{set,[{x,0}],[{atom,if_clause}],move}]) ->
+ {yes,if_end,[]};
+dig_out_block([{set,[{x,0}],[{literal,{Exc,Value}}],move}|Is]) ->
+ translate_exception(Exc, {literal,Value}, Is, 0);
+dig_out_block([{set,[{x,0}],[Tuple],move},
+ {set,[],[Value],put},
+ {set,[],[{atom,Exc}],put},
+ {set,[Tuple],[],{put_tuple,2}}|Is]) ->
+ translate_exception(Exc, Value, Is, 3);
+dig_out_block([{set,[],[Value],put},
+ {set,[],[{atom,Exc}],put},
+ {set,[{x,0}],[],{put_tuple,2}}|Is]) ->
+ translate_exception(Exc, Value, Is, 3);
+dig_out_block(_) -> no.
+
+translate_exception(badmatch, Val, Is, Words) ->
+ {yes,{badmatch,Val},fix_block(Is, Words)};
+translate_exception(case_clause, Val, Is, Words) ->
+ {yes,{case_end,Val},fix_block(Is, Words)};
+translate_exception(try_clause, Val, Is, Words) ->
+ {yes,{try_case_end,Val},fix_block(Is, Words)};
+translate_exception(_, _, _, _) -> no.
+
+fix_block(Is, 0) ->
+ reverse(Is);
+fix_block(Is0, Words) ->
+ [{set,[],[],{alloc,Live,{F1,F2,Needed,F3}}}|Is] = reverse(Is0),
+ [{set,[],[],{alloc,Live,{F1,F2,Needed-Words,F3}}}|Is].
+
+dig_out_block_fc([{set,[],[],{alloc,Live,_}}|Bl]) ->
+ dig_out_fc(Bl, Live-1, nil);
+dig_out_block_fc(_) -> no.
+
+dig_out_fc([{set,[Dst],[{x,Reg},Dst0],put_list}|Is], Reg, Dst0) ->
+ dig_out_fc(Is, Reg-1, Dst);
+dig_out_fc([{set,[{x,0}],[{atom,function_clause}],move}], -1, {x,1}) ->
+ {yes,function_clause};
+dig_out_fc(_, _, _) -> no.
diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl
index a631b8cd69..116ede0bc9 100644
--- a/lib/compiler/src/beam_utils.erl
+++ b/lib/compiler/src/beam_utils.erl
@@ -474,8 +474,15 @@ check_liveness(R, [{make_fun2,_,_,_,NumFree}|Is], St) ->
end;
check_liveness(R, [{try_end,Y}|Is], St) ->
case R of
- Y -> {killed,St};
- _ -> check_liveness(R, Is, St)
+ Y ->
+ {killed,St};
+ {y,_} ->
+ %% y registers will be used if an exception occurs and
+ %% control transfers to the label given in the previous
+ %% try/2 instruction.
+ {used,St};
+ _ ->
+ check_liveness(R, Is, St)
end;
check_liveness(R, [{catch_end,Y}|Is], St) ->
case R of
diff --git a/lib/compiler/src/cerl_inline.erl b/lib/compiler/src/cerl_inline.erl
index c15103999f..589685d72d 100644
--- a/lib/compiler/src/cerl_inline.erl
+++ b/lib/compiler/src/cerl_inline.erl
@@ -1262,8 +1262,9 @@ i_receive_1(E, Cs, T, B, S) ->
i_module(E, Ctxt, Ren, Env, S) ->
%% Cf. `i_letrec'. Note that we pass a dummy constant value for the
%% "body" parameter.
+ Exps = i_module_exports(E),
{Es, _, Xs1, S1} = i_letrec(module_defs(E), void(),
- module_exports(E), Ctxt, Ren, Env, S),
+ Exps, Ctxt, Ren, Env, S),
%% Sanity check:
case Es of
[] ->
@@ -1276,6 +1277,27 @@ i_module(E, Ctxt, Ren, Env, S) ->
E1 = update_c_module(E, module_name(E), Xs1, module_attrs(E), Es),
{E1, count_size(weight(module), S1)}.
+i_module_exports(E) ->
+ %% If a function is named in an `on_load' attribute, we will
+ %% pretend that it is exported to ensure that it will not be removed.
+ Exps = module_exports(E),
+ Attrs = module_attrs(E),
+ case i_module_on_load(Attrs) of
+ none ->
+ Exps;
+ [{_,_}=FA] ->
+ ordsets:add_element(c_var(FA), Exps)
+ end.
+
+i_module_on_load([{Key,Val}|T]) ->
+ case concrete(Key) of
+ on_load ->
+ concrete(Val);
+ _ ->
+ i_module_on_load(T)
+ end;
+i_module_on_load([]) -> none.
+
%% Binary-syntax expressions are too complicated to do anything
%% interesting with here - that is beyond the scope of this program;
%% also, their construction could have side effects, so even in effect
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index a17a10046e..9b505ad15c 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -629,6 +629,8 @@ asm_passes() ->
[{unless,no_postopt,
[{pass,beam_block},
{iff,dblk,{listing,"block"}},
+ {unless,no_except,{pass,beam_except}},
+ {iff,dexcept,{listing,"except"}},
{unless,no_bopt,{pass,beam_bool}},
{iff,dbool,{listing,"bool"}},
{unless,no_topt,{pass,beam_type}},
diff --git a/lib/compiler/src/compiler.app.src b/lib/compiler/src/compiler.app.src
index fb06f2521c..1133882728 100644
--- a/lib/compiler/src/compiler.app.src
+++ b/lib/compiler/src/compiler.app.src
@@ -28,6 +28,7 @@
beam_dead,
beam_dict,
beam_disasm,
+ beam_except,
beam_flatten,
beam_jump,
beam_listing,
diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index 6ea67741fa..5b155398dc 100644
--- a/lib/compiler/src/sys_core_fold.erl
+++ b/lib/compiler/src/sys_core_fold.erl
@@ -2641,9 +2641,9 @@ bsm_leftmost_2([_|Ps], Cs, N, Pos) ->
bsm_leftmost_2([], Cs, _, Pos) ->
bsm_leftmost_1(Cs, Pos).
-%% bsm_notempty(Cs, Pos) -> true|false
+%% bsm_nonempty(Cs, Pos) -> true|false
%% Check if at least one of the clauses matches a non-empty
-%% binary in the given argumet position.
+%% binary in the given argument position.
%%
bsm_nonempty([#c_clause{pats=Ps}|Cs], Pos) ->
case nth(Pos, Ps) of
@@ -2704,7 +2704,7 @@ bsm_ensure_no_partition_2([P|_], 1, _, Vstate, State) ->
%%
%% But if the clauses can't be freely rearranged, as in
%%
- %% b(Var, <<>>) -> ...
+ %% b(Var, <<X>>) -> ...
%% b(1, 2) -> ...
%%
%% we do have a problem.
diff --git a/lib/compiler/src/v3_codegen.erl b/lib/compiler/src/v3_codegen.erl
index e7dae67085..6623485609 100644
--- a/lib/compiler/src/v3_codegen.erl
+++ b/lib/compiler/src/v3_codegen.erl
@@ -53,7 +53,6 @@
%% Main codegen structure.
-record(cg, {lcount=1, %Label counter
- finfo, %Function info label
bfail, %Fail label for BIFs
break, %Break label
recv, %Receive label
@@ -126,7 +125,6 @@ cg_fun(Les, Hvs, Vdb, AtomMod, NameArity, Anno, St0) ->
stk=[]}, 0, Vdb),
{B,_Aft,St} = cg_list(Les, 0, Vdb, Bef,
St3#cg{bfail=0,
- finfo=Fi,
ultimate_failure=UltimateMatchFail,
is_top_block=true}),
{Name,Arity} = NameArity,
@@ -147,8 +145,6 @@ cg({match,M,Rs}, Le, Vdb, Bef, St) ->
match_cg(M, Rs, Le, Vdb, Bef, St);
cg({guard_match,M,Rs}, Le, Vdb, Bef, St) ->
guard_match_cg(M, Rs, Le, Vdb, Bef, St);
-cg({match_fail,F}, Le, Vdb, Bef, St) ->
- match_fail_cg(F, Le, Vdb, Bef, St);
cg({call,Func,As,Rs}, Le, Vdb, Bef, St) ->
call_cg(Func, As, Rs, Le, Vdb, Bef, St);
cg({enter,Func,As}, Le, Vdb, Bef, St) ->
@@ -294,39 +290,6 @@ match_cg({block,Es}, Le, _Fail, Bef, St) ->
Int = clear_dead(Bef, Le#l.i, Le#l.vdb),
block_cg(Es, Le, Int, St).
-%% match_fail_cg(FailReason, Le, Vdb, StackReg, State) ->
-%% {[Ainstr],StackReg,State}.
-%% Generate code for the match_fail "call". N.B. there is no generic
-%% case for when the fail value has been created elsewhere.
-
-match_fail_cg({function_clause,As}, Le, Vdb, Bef, St) ->
- %% Must have the args in {x,0}, {x,1},...
- {Sis,Int} = cg_setup_call(As, Bef, Le#l.i, Vdb),
- {Sis ++ [{jump,{f,St#cg.finfo}}],
- Int#sr{reg=clear_regs(Int#sr.reg)},St};
-match_fail_cg({badmatch,Term}, Le, Vdb, Bef, St) ->
- R = cg_reg_arg(Term, Bef),
- Int0 = clear_dead(Bef, Le#l.i, Vdb),
- {Sis,Int} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb),
- {Sis ++ [line(Le),{badmatch,R}],
- Int#sr{reg=clear_regs(Int0#sr.reg)},St};
-match_fail_cg({case_clause,Reason}, Le, Vdb, Bef, St) ->
- R = cg_reg_arg(Reason, Bef),
- Int0 = clear_dead(Bef, Le#l.i, Vdb),
- {Sis,Int} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb),
- {Sis++[line(Le),{case_end,R}],
- Int#sr{reg=clear_regs(Bef#sr.reg)},St};
-match_fail_cg(if_clause, Le, Vdb, Bef, St) ->
- Int0 = clear_dead(Bef, Le#l.i, Vdb),
- {Sis,Int1} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb),
- {Sis++[line(Le),if_end],Int1#sr{reg=clear_regs(Int1#sr.reg)},St};
-match_fail_cg({try_clause,Reason}, Le, Vdb, Bef, St) ->
- R = cg_reg_arg(Reason, Bef),
- Int0 = clear_dead(Bef, Le#l.i, Vdb),
- {Sis,Int} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb),
- {Sis ++ [line(Le),{try_case_end,R}],
- Int#sr{reg=clear_regs(Int0#sr.reg)},St}.
-
%% bsm_rename_ctx([Clause], Var) -> [Clause]
%% We know from an annotation that the register for a binary can
%% be reused for the match context because the two are not truly
diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl
index d76291f57f..f2eaa37617 100644
--- a/lib/compiler/src/v3_kernel.erl
+++ b/lib/compiler/src/v3_kernel.erl
@@ -83,6 +83,7 @@
-import(lists, [map/2,foldl/3,foldr/3,mapfoldl/3,splitwith/2,member/2,
keymember/3,keyfind/3]).
-import(ordsets, [add_element/2,del_element/2,union/2,union/1,subtract/2]).
+-import(cerl, [c_tuple/1]).
-include("core_parse.hrl").
-include("v3_kernel.hrl").
@@ -422,10 +423,11 @@ expr(#c_call{anno=A,module=M0,name=F0,args=Cargs}, Sub, St0) ->
end;
expr(#c_primop{anno=A,name=#c_literal{val=match_fail},args=Cargs0}, Sub, St0) ->
Cargs = translate_match_fail(Cargs0, Sub, A, St0),
- %% This special case will disappear.
{Kargs,Ap,St} = atomic_list(Cargs, Sub, St0),
Ar = length(Cargs),
- Call = #k_call{anno=A,op=#k_internal{name=match_fail,arity=Ar},args=Kargs},
+ Call = #k_call{anno=A,op=#k_remote{mod=#k_atom{val=erlang},
+ name=#k_atom{val=error},
+ arity=Ar},args=Kargs},
{Call,Ap,St};
expr(#c_primop{anno=A,name=#c_literal{val=N},args=Cargs}, Sub, St0) ->
{Kargs,Ap,St1} = atomic_list(Cargs, Sub, St0),
@@ -455,14 +457,14 @@ expr(#ireceive_accept{anno=A}, _Sub, St) -> {#k_receive_accept{anno=A},[],St}.
translate_match_fail(Args, Sub, Anno, St) ->
case Args of
[#c_tuple{es=[#c_literal{val=function_clause}|As]}] ->
- translate_match_fail_1(Anno, Args, As, Sub, St);
+ translate_match_fail_1(Anno, As, Sub, St);
[#c_literal{val=Tuple}] when is_tuple(Tuple) ->
%% The inliner may have created a literal out of
%% the original #c_tuple{}.
case tuple_to_list(Tuple) of
[function_clause|As0] ->
As = [#c_literal{val=E} || E <- As0],
- translate_match_fail_1(Anno, Args, As, Sub, St);
+ translate_match_fail_1(Anno, As, Sub, St);
_ ->
Args
end;
@@ -471,7 +473,7 @@ translate_match_fail(Args, Sub, Anno, St) ->
Args
end.
-translate_match_fail_1(Anno, Args, As, Sub, #kern{ff=FF}) ->
+translate_match_fail_1(Anno, As, Sub, #kern{ff=FF}) ->
AnnoFunc = case keyfind(function_name, 1, Anno) of
false ->
none; %Force rewrite.
@@ -481,10 +483,10 @@ translate_match_fail_1(Anno, Args, As, Sub, #kern{ff=FF}) ->
case {AnnoFunc,FF} of
{Same,Same} ->
%% Still in the correct function.
- Args;
+ translate_fc(As);
{{F,_},F} ->
%% Still in the correct function.
- Args;
+ translate_fc(As);
_ ->
%% Wrong function or no function_name annotation.
%%
@@ -493,9 +495,12 @@ translate_match_fail_1(Anno, Args, As, Sub, #kern{ff=FF}) ->
%% the current function). match_fail(function_clause) will
%% only work at the top level of the function it was originally
%% defined in, so we will need to rewrite it to a case_clause.
- [#c_tuple{es=[#c_literal{val=case_clause},#c_tuple{es=As}]}]
+ [c_tuple([#c_literal{val=case_clause},c_tuple(As)])]
end.
+translate_fc(Args) ->
+ [#c_literal{val=function_clause},make_list(Args)].
+
%% call_type(Module, Function, Arity) -> call | bif | apply | error.
%% Classify the call.
call_type(#c_literal{val=M}, #c_literal{val=F}, Ar) when is_atom(M), is_atom(F) ->
@@ -1494,7 +1499,6 @@ iletrec_funs_gen(Fs, FreeVs, St) ->
%% is_exit_expr(Kexpr) -> boolean().
%% Test whether Kexpr always exits and never returns.
-is_exit_expr(#k_call{op=#k_internal{name=match_fail,arity=1}}) -> true;
is_exit_expr(#k_receive_next{}) -> true;
is_exit_expr(_) -> false.
diff --git a/lib/compiler/src/v3_life.erl b/lib/compiler/src/v3_life.erl
index fac9a9843d..93f8034230 100644
--- a/lib/compiler/src/v3_life.erl
+++ b/lib/compiler/src/v3_life.erl
@@ -89,19 +89,8 @@ function(#k_fdef{anno=#k{a=Anno},func=F,arity=Ar,vars=Vs,body=Kb}) ->
end.
%% body(Kbody, I, Vdb) -> {[Expr],MaxI,Vdb}.
-%% Handle a body, need special cases for transforming match_fails.
-%% We KNOW that they only occur last in a body.
-
-body(#k_seq{arg=#k_put{anno=Pa,arg=Arg,ret=[R]},
- body=#k_enter{anno=Ea,op=#k_internal{name=match_fail,arity=1},
- args=[R]}},
- I, Vdb0) ->
- Vdb1 = use_vars(Pa#k.us, I, Vdb0), %All used here
- {[match_fail(Arg, I, Pa#k.a ++ Ea#k.a)],I,Vdb1};
-body(#k_enter{anno=Ea,op=#k_internal{name=match_fail,arity=1},args=[Arg]},
- I, Vdb0) ->
- Vdb1 = use_vars(Ea#k.us, I, Vdb0),
- {[match_fail(Arg, I, Ea#k.a)],I,Vdb1};
+%% Handle a body.
+
body(#k_seq{arg=Ke,body=Kb}, I, Vdb0) ->
%%ok = io:fwrite("life ~w:~p~n", [?LINE,{Ke,I,Vdb0}]),
A = get_kanno(Ke),
@@ -353,25 +342,6 @@ guard_clause(#k_guard_clause{anno=A,guard=Kg,body=Kb}, Ls, I, Ctxt, Vdb0) ->
i=I,vdb=use_vars((get_kanno(Kg))#k.us, I+2, Vdb1),
a=A#k.a}.
-%% match_fail(FailValue, I, Anno) -> Expr.
-%% Generate the correct match_fail instruction. N.B. there is no
-%% generic case for when the fail value has been created elsewhere.
-
-match_fail(#k_literal{anno=Anno,val={Atom,Val}}, I, A) when is_atom(Atom) ->
- match_fail(#k_tuple{anno=Anno,es=[#k_atom{val=Atom},#k_literal{val=Val}]}, I, A);
-match_fail(#k_literal{anno=Anno,val={Atom}}, I, A) when is_atom(Atom) ->
- match_fail(#k_tuple{anno=Anno,es=[#k_atom{val=Atom}]}, I, A);
-match_fail(#k_tuple{es=[#k_atom{val=function_clause}|As]}, I, A) ->
- #l{ke={match_fail,{function_clause,literal_list(As, [])}},i=I,a=A};
-match_fail(#k_tuple{es=[#k_atom{val=badmatch},Val]}, I, A) ->
- #l{ke={match_fail,{badmatch,literal(Val, [])}},i=I,a=A};
-match_fail(#k_tuple{es=[#k_atom{val=case_clause},Val]}, I, A) ->
- #l{ke={match_fail,{case_clause,literal(Val, [])}},i=I,a=A};
-match_fail(#k_atom{val=if_clause}, I, A) ->
- #l{ke={match_fail,if_clause},i=I,a=A};
-match_fail(#k_tuple{es=[#k_atom{val=try_clause},Val]}, I, A) ->
- #l{ke={match_fail,{try_clause,literal(Val, [])}},i=I,a=A}.
-
%% type(Ktype) -> Type.
type(k_literal) -> literal;
diff --git a/lib/compiler/test/Makefile b/lib/compiler/test/Makefile
index b90adaf917..e13ad4ae90 100644
--- a/lib/compiler/test/Makefile
+++ b/lib/compiler/test/Makefile
@@ -10,6 +10,7 @@ MODULES= \
apply_SUITE \
beam_validator_SUITE \
beam_disasm_SUITE \
+ beam_expect_SUITE \
bs_bincomp_SUITE \
bs_bit_binaries_SUITE \
bs_construct_SUITE \
@@ -29,7 +30,6 @@ MODULES= \
misc_SUITE \
num_bif_SUITE \
pmod_SUITE \
- parteval_SUITE \
receive_SUITE \
record_SUITE \
trycatch_SUITE \
@@ -39,6 +39,7 @@ MODULES= \
NO_OPT= \
andor \
apply \
+ beam_expect \
bs_construct \
bs_match \
bs_utf \
diff --git a/lib/compiler/test/beam_disasm_SUITE.erl b/lib/compiler/test/beam_disasm_SUITE.erl
index 44574ae64a..62afc80ca6 100644
--- a/lib/compiler/test/beam_disasm_SUITE.erl
+++ b/lib/compiler/test/beam_disasm_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -60,6 +60,6 @@ stripped(Config) when is_list(Config) ->
?line true = is_list(Attr),
?line true = is_list(CompileInfo),
?line {ok, {tmp, _}} = beam_lib:strip(BeamName),
- ?line {beam_file, tmp, _, none, none, [_|_]} =
+ ?line {beam_file, tmp, _, [], [], [_|_]} =
beam_disasm:file(BeamName),
ok.
diff --git a/lib/compiler/test/beam_expect_SUITE.erl b/lib/compiler/test/beam_expect_SUITE.erl
new file mode 100644
index 0000000000..6f216eac4f
--- /dev/null
+++ b/lib/compiler/test/beam_expect_SUITE.erl
@@ -0,0 +1,67 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(beam_expect_SUITE).
+
+-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+ init_per_group/2,end_per_group/2,
+ coverage/1]).
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [coverage].
+
+groups() ->
+ [].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+coverage(_) ->
+ File = {file,"fake.erl"},
+ ok = fc(a),
+ {'EXIT',{function_clause,
+ [{?MODULE,fc,[[x]],[File,{line,2}]}|_]}} =
+ (catch fc([x])),
+ {'EXIT',{function_clause,
+ [{?MODULE,fc,[y],[File,{line,2}]}|_]}} =
+ (catch fc(y)),
+ {'EXIT',{function_clause,
+ [{?MODULE,fc,[[a,b,c]],[File,{line,6}]}|_]}} =
+ (catch fc([a,b,c])),
+
+ {'EXIT',{undef,[{erlang,error,[a,b,c],_}|_]}} =
+ (catch erlang:error(a, b, c)),
+ ok.
+
+-file("fake.erl", 1).
+fc(a) -> %Line 2
+ ok; %Line 3
+fc(L) when length(L) > 2 -> %Line 4
+ %% Not the same as a "real" function_clause error.
+ error(function_clause, [L]). %Line 6
diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl
index 556dc54a8f..902867bc19 100644
--- a/lib/compiler/test/beam_validator_SUITE.erl
+++ b/lib/compiler/test/beam_validator_SUITE.erl
@@ -79,21 +79,18 @@ beam_files(Config) when is_list(Config) ->
%% a grammatical error in the output of the io:format/2 call below. ;-)
?line [_,_|_] = Fs = filelib:wildcard(Wc),
?line io:format("~p files\n", [length(Fs)]),
- beam_files_1(Fs, 0).
-
-beam_files_1([F|Fs], Errors) ->
- ?line case beam_validator:file(F) of
- ok ->
- beam_files_1(Fs, Errors);
- {error,Es} ->
- io:format("File: ~s", [F]),
- io:format("Error: ~p\n", [Es]),
- beam_files_1(Fs, Errors+1)
- end;
-beam_files_1([], 0) -> ok;
-beam_files_1([], Errors) ->
- ?line io:format("~p error(s)", [Errors]),
- ?line ?t:fail().
+ test_lib:p_run(fun do_beam_file/1, Fs).
+
+
+do_beam_file(F) ->
+ case beam_validator:file(F) of
+ ok ->
+ ok;
+ {error,Es} ->
+ io:format("File: ~s", [F]),
+ io:format("Error: ~p\n", [Es]),
+ error
+ end.
compiler_bug(Config) when is_list(Config) ->
%% Check that the compiler returns an error if we try to
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
index f8c71a0257..01b7568122 100644
--- a/lib/compiler/test/bs_match_SUITE.erl
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -342,6 +342,10 @@ partitioned_bs_match(Config) when is_list(Config) ->
?line fc(partitioned_bs_match_2, [4,<<0:17>>],
catch partitioned_bs_match_2(4, <<0:17>>)),
+
+ anything = partitioned_bs_match_3(anything, <<42>>),
+ ok = partitioned_bs_match_3(1, 2),
+
ok.
partitioned_bs_match(_, <<42:8,T/binary>>) ->
@@ -356,6 +360,9 @@ partitioned_bs_match_2(1, <<B:8,T/binary>>) ->
partitioned_bs_match_2(Len, <<_:8,T/binary>>) ->
{Len,T}.
+partitioned_bs_match_3(Var, <<_>>) -> Var;
+partitioned_bs_match_3(1, 2) -> ok.
+
function_clause(Config) when is_list(Config) ->
?line ok = function_clause_1(<<0,7,0,7,42>>),
?line fc(function_clause_1, [<<0,1,2,3>>],
diff --git a/lib/compiler/test/compilation_SUITE.erl b/lib/compiler/test/compilation_SUITE.erl
index 1343fbd1c9..408fd5ed53 100644
--- a/lib/compiler/test/compilation_SUITE.erl
+++ b/lib/compiler/test/compilation_SUITE.erl
@@ -44,7 +44,7 @@ all() ->
trycatch_4, opt_crash, otp_5404, otp_5436, otp_5481,
otp_5553, otp_5632, otp_5714, otp_5872, otp_6121,
otp_6121a, otp_6121b, otp_7202, otp_7345, on_load,
- string_table,otp_8949_a,otp_8949_a].
+ string_table,otp_8949_a,otp_8949_a,split_cases].
groups() ->
[{vsn, [], [vsn_1, vsn_2, vsn_3]}].
@@ -159,6 +159,7 @@ split({int, N}, <<N:16,B:N/binary,T/binary>>) ->
?comp(convopts).
?comp(otp_7202).
?comp(on_load).
+?comp(on_load_inline).
beam_compiler_7(doc) ->
"Code snippet submitted from Ulf Wiger which fails in R3 Beam.";
@@ -427,9 +428,9 @@ self_compile_1(Config, Prefix, Opts) ->
%% Compile the compiler again using the newly compiled compiler.
%% (In another node because reloading the compiler would disturb cover.)
CompilerB = Prefix++"compiler_b",
- ?line CompB = make_compiler_dir(Priv, Prefix++"compiler_b"),
+ CompB = make_compiler_dir(Priv, CompilerB),
?line VsnB = VsnA ++ ".0",
- ?line self_compile_node(CompilerB, CompA, CompB, VsnB, Opts),
+ self_compile_node(CompA, CompB, VsnB, Opts),
%% Compare compiler directories.
?line compare_compilers(CompA, CompB),
@@ -438,21 +439,26 @@ self_compile_1(Config, Prefix, Opts) ->
?line CompilerC = Prefix++"compiler_c",
?line CompC = make_compiler_dir(Priv, CompilerC),
?line VsnC = VsnB ++ ".0",
- ?line self_compile_node(CompilerC, CompB, CompC, VsnC, Opts),
+ self_compile_node(CompB, CompC, VsnC, Opts),
?line compare_compilers(CompB, CompC),
?line test_server:timetrap_cancel(Dog),
ok.
-self_compile_node(NodeName0, CompilerDir, OutDir, Version, Opts) ->
- ?line NodeName = list_to_atom(NodeName0),
- ?line Dog = test_server:timetrap(test_server:minutes(10)),
+self_compile_node(CompilerDir, OutDir, Version, Opts) ->
+ ?line Dog = test_server:timetrap(test_server:minutes(15)),
?line Pa = "-pa " ++ filename:dirname(code:which(?MODULE)) ++
" -pa " ++ CompilerDir,
- ?line {ok,Node} = start_node(NodeName, Pa),
?line Files = compiler_src(),
- ?line ok = rpc:call(Node, ?MODULE, compile_compiler, [Files,OutDir,Version,Opts]),
- ?line test_server:stop_node(Node),
+
+ %% We don't want the cover server started on the other node,
+ %% because it will load the same cover-compiled code as on this
+ %% node. Use a shielded node to prevent the cover server from
+ %% being started.
+ ?t:run_on_shielded_node(
+ fun() ->
+ compile_compiler(Files, OutDir, Version, Opts)
+ end, Pa),
?line test_server:timetrap_cancel(Dog),
ok.
@@ -465,9 +471,12 @@ compile_compiler(Files, OutDir, Version, InlineOpts) ->
{d,'COMPILER_VSN',"\""++Version++"\""},
nowarn_shadow_vars,
{i,filename:join(code:lib_dir(stdlib), "include")}|InlineOpts],
- lists:foreach(fun(File) ->
- {ok,_} = compile:file(File, Opts)
- end, Files).
+ test_lib:p_run(fun(File) ->
+ case compile:file(File, Opts) of
+ {ok,_} -> ok;
+ _ -> error
+ end
+ end, Files).
compiler_src() ->
filelib:wildcard(filename:join([code:lib_dir(compiler), "src", "*.erl"])).
@@ -657,5 +666,19 @@ otp_8949_b(A, B) ->
id(Var)
end.
+split_cases(_) ->
+ dummy1 = do_split_cases(x),
+ {'EXIT',{{badmatch,b},_}} = (catch do_split_cases(y)),
+ ok.
+
+do_split_cases(A) ->
+ case A of
+ x ->
+ Z = dummy1;
+ _ ->
+ Z = dummy2,
+ a=b
+ end,
+ Z.
id(I) -> I.
diff --git a/lib/compiler/test/compilation_SUITE_data/on_load_inline.erl b/lib/compiler/test/compilation_SUITE_data/on_load_inline.erl
new file mode 100644
index 0000000000..322843b61e
--- /dev/null
+++ b/lib/compiler/test/compilation_SUITE_data/on_load_inline.erl
@@ -0,0 +1,23 @@
+-module(on_load_inline).
+-export([?MODULE/0]).
+-on_load(on_load/0).
+-compile(inline).
+
+?MODULE() ->
+ [{pid,Pid}] = ets:lookup(on_load_executed, pid),
+ exit(Pid, kill),
+ ok.
+
+on_load() ->
+ Parent = self(),
+ spawn(fun() ->
+ T = ets:new(on_load_executed, [named_table]),
+ ets:insert(T, {pid,self()}),
+ Parent ! done,
+ receive
+ wait_forever -> ok
+ end
+ end),
+ receive
+ done -> ok
+ end.
diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl
index fedbd98f71..640849f2ec 100644
--- a/lib/compiler/test/compile_SUITE.erl
+++ b/lib/compiler/test/compile_SUITE.erl
@@ -29,7 +29,8 @@
binary/1, makedep/1, cond_and_ifdef/1, listings/1, listings_big/1,
other_output/1, package_forms/1, encrypted_abstr/1,
bad_record_use1/1, bad_record_use2/1, strict_record/1,
- missing_testheap/1, cover/1, env/1, core/1, asm/1]).
+ missing_testheap/1, cover/1, env/1, core/1, asm/1,
+ sys_pre_attributes/1]).
-export([init/3]).
@@ -45,7 +46,8 @@ all() ->
binary, makedep, cond_and_ifdef, listings, listings_big,
other_output, package_forms, encrypted_abstr,
{group, bad_record_use}, strict_record,
- missing_testheap, cover, env, core, asm].
+ missing_testheap, cover, env, core, asm,
+ sys_pre_attributes].
groups() ->
[{bad_record_use, [],
@@ -785,6 +787,37 @@ do_asm(Beam, Outdir) ->
error
end.
+sys_pre_attributes(Config) ->
+ DataDir = ?config(data_dir, Config),
+ File = filename:join(DataDir, "attributes.erl"),
+ Mod = attributes,
+ CommonOpts = [binary,report,verbose,
+ {parse_transform,sys_pre_attributes}],
+ PreOpts = [{attribute,delete,deleted}],
+ PostOpts = [{attribute,insert,inserted,"value"}],
+ PrePostOpts = [{attribute,replace,replaced,42},
+ {attribute,replace,replace_nonexisting,new}],
+ {ok,Mod,Code} = compile:file(File, PrePostOpts ++ PreOpts ++
+ PostOpts ++ CommonOpts),
+ code:load_binary(Mod, File, Code),
+ Attr = Mod:module_info(attributes),
+ io:format("~p", [Attr]),
+ {inserted,"value"} = lists:keyfind(inserted, 1, Attr),
+ {replaced,[42]} = lists:keyfind(replaced, 1, Attr),
+ {replace_nonexisting,[new]} = lists:keyfind(replace_nonexisting, 1, Attr),
+ false = lists:keymember(deleted, 1, Attr),
+
+ %% Cover more code.
+ {ok,Mod,_} = compile:file(File, PostOpts ++ CommonOpts),
+ {ok,Mod,_} = compile:file(File, CommonOpts -- [verbose]),
+ {ok,Mod,_} = compile:file(File, PreOpts ++ CommonOpts),
+ {ok,Mod,_} = compile:file(File,
+ [{attribute,replace,replaced,42}|CommonOpts]),
+ {ok,Mod,_} = compile:file(File, PrePostOpts ++ PreOpts ++
+ PostOpts ++ CommonOpts --
+ [report,verbose]),
+ ok.
+
%%%
%%% Utilities.
%%%
diff --git a/lib/compiler/test/compile_SUITE_data/attributes.erl b/lib/compiler/test/compile_SUITE_data/attributes.erl
new file mode 100644
index 0000000000..9c3451d272
--- /dev/null
+++ b/lib/compiler/test/compile_SUITE_data/attributes.erl
@@ -0,0 +1,23 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(attributes).
+-deleted(dummy).
+-replaced(dummy).
+
diff --git a/lib/compiler/test/compiler.cover b/lib/compiler/test/compiler.cover
index 9fc4c7dd43..3fd7fc1937 100644
--- a/lib/compiler/test/compiler.cover
+++ b/lib/compiler/test/compiler.cover
@@ -1,5 +1,5 @@
{incl_app,compiler,details}.
%% -*- erlang -*-
-{excl_mods,[sys_pre_attributes,core_scan,core_parse]}.
+{excl_mods,compiler,[core_scan,core_parse]}.
diff --git a/lib/compiler/test/core_SUITE.erl b/lib/compiler/test/core_SUITE.erl
index 26173c62b8..874e02803d 100644
--- a/lib/compiler/test/core_SUITE.erl
+++ b/lib/compiler/test/core_SUITE.erl
@@ -21,7 +21,9 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
init_per_testcase/2,end_per_testcase/2,
- dehydrated_itracer/1,nested_tries/1]).
+ dehydrated_itracer/1,nested_tries/1,
+ make_effect_seq/1,eval_is_boolean/1,
+ unsafe_case/1,nomatch_shadow/1,reversed_annos/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -41,7 +43,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
test_lib:recompile(?MODULE),
- [dehydrated_itracer, nested_tries].
+ [dehydrated_itracer,nested_tries,make_effect_seq,
+ eval_is_boolean,unsafe_case,nomatch_shadow,reversed_annos].
groups() ->
[].
@@ -61,19 +64,18 @@ end_per_group(_GroupName, Config) ->
?comp(dehydrated_itracer).
?comp(nested_tries).
+?comp(make_effect_seq).
+?comp(eval_is_boolean).
+?comp(unsafe_case).
+?comp(nomatch_shadow).
+?comp(reversed_annos).
try_it(Mod, Conf) ->
- ?line Src = filename:join(?config(data_dir, Conf), atom_to_list(Mod)),
- ?line Out = ?config(priv_dir,Conf),
- ?line io:format("Compiling: ~s\n", [Src]),
- ?line CompRc0 = compile:file(Src, [from_core,{outdir,Out},report,time]),
- ?line io:format("Result: ~p\n",[CompRc0]),
- ?line {ok,Mod} = CompRc0,
-
- ?line {module,Mod} = code:load_abs(filename:join(Out, Mod)),
- ?line ok = Mod:Mod(),
- ok.
-
-
-
-
+ Src = filename:join(?config(data_dir, Conf), atom_to_list(Mod)),
+ compile_and_load(Src, []),
+ compile_and_load(Src, [no_copt]).
+
+compile_and_load(Src, Opts) ->
+ {ok,Mod,Bin} = compile:file(Src, [from_core,report,time,binary|Opts]),
+ {module,Mod} = code:load_binary(Mod, Mod, Bin),
+ ok = Mod:Mod().
diff --git a/lib/compiler/test/core_SUITE_data/eval_is_boolean.core b/lib/compiler/test/core_SUITE_data/eval_is_boolean.core
new file mode 100644
index 0000000000..6a68b1414d
--- /dev/null
+++ b/lib/compiler/test/core_SUITE_data/eval_is_boolean.core
@@ -0,0 +1,22 @@
+module 'eval_is_boolean' ['eval_is_boolean'/0]
+ attributes []
+'eval_is_boolean'/0 =
+ %% Line 4
+ fun () ->
+ case <> of
+ <> when 'true' ->
+ case call 'erlang':'is_boolean'(call 'erlang':'make_ref'()) of
+ <'false'> when 'true' ->
+ 'ok'
+ ( <_cor1> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_cor1})
+ -| ['compiler_generated'] )
+ end
+ ( <> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause'})
+ -| [{'function_name',{'eval_is_boolean',0}}] )
+ -| ['compiler_generated'] )
+ end
+end
diff --git a/lib/compiler/test/core_SUITE_data/make_effect_seq.core b/lib/compiler/test/core_SUITE_data/make_effect_seq.core
new file mode 100644
index 0000000000..9941e63b76
--- /dev/null
+++ b/lib/compiler/test/core_SUITE_data/make_effect_seq.core
@@ -0,0 +1,51 @@
+module 'make_effect_seq' ['make_effect_seq'/0]
+ attributes []
+'make_effect_seq'/0 =
+ fun () ->
+ case <> of
+ <> when 'true' ->
+ let <_cor0> =
+ catch
+ apply 't'/1
+ ('a')
+ in
+ case _cor0 of
+ <{'EXIT',{'badarg',_cor3}}> when 'true' ->
+ let <_cor4> =
+ apply 't'/1
+ ({'a','b','c'})
+ in
+ case _cor4 of
+ <'ok'> when 'true' ->
+ ( _cor4
+ -| ['compiler_generated'] )
+ ( <_cor2> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_cor2})
+ -| ['compiler_generated'] )
+ end
+ ( <_cor1> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_cor1})
+ -| ['compiler_generated'] )
+ end
+ ( <> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause'})
+ -| [{'function_name',{'make_effect_seq',0}}] )
+ -| ['compiler_generated'] )
+ end
+'t'/1 =
+ fun (_cor0) ->
+ case _cor0 of
+ <T> when 'true' ->
+ do
+ {'ok',call 'erlang':'element'(2, T)}
+ 'ok'
+ ( <_cor2> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause',_cor2})
+ -| [{'function_name',{'t',1}}] )
+ -| ['compiler_generated'] )
+ end
+end
diff --git a/lib/compiler/test/core_SUITE_data/nomatch_shadow.core b/lib/compiler/test/core_SUITE_data/nomatch_shadow.core
new file mode 100644
index 0000000000..565d9dc0f3
--- /dev/null
+++ b/lib/compiler/test/core_SUITE_data/nomatch_shadow.core
@@ -0,0 +1,28 @@
+module 'nomatch_shadow' ['nomatch_shadow'/0]
+ attributes []
+'nomatch_shadow'/0 =
+ fun () ->
+ case <> of
+ <> when 'true' ->
+ apply 't'/1
+ (42)
+ ( <> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause'})
+ -| [{'function_name',{'nomatch_shadow',0}}] )
+ -| ['compiler_generated'] )
+ end
+'t'/1 =
+ fun (_cor0) ->
+ case _cor0 of
+ <42> when 'true' ->
+ 'ok'
+ <42> when 'true' ->
+ 'ok'
+ ( <_cor1> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause',_cor1})
+ -| [{'function_name',{'t',1}}] )
+ -| ['compiler_generated'] )
+ end
+end
diff --git a/lib/compiler/test/core_SUITE_data/reversed_annos.core b/lib/compiler/test/core_SUITE_data/reversed_annos.core
new file mode 100644
index 0000000000..95b3cd52d6
--- /dev/null
+++ b/lib/compiler/test/core_SUITE_data/reversed_annos.core
@@ -0,0 +1,49 @@
+module 'reversed_annos' ['reversed_annos'/0]
+ attributes []
+'reversed_annos'/0 =
+ fun () ->
+ case <> of
+ <> when 'true' ->
+ case apply 't'/1
+ (['a']) of
+ <'ok'> when 'true' ->
+ let <_cor2> =
+ apply 't'/1
+ (['a'|['b']])
+ in
+ case _cor2 of
+ <'ok'> when 'true' ->
+ ( _cor2
+ -| ['compiler_generated'] )
+ ( <_cor1> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_cor1})
+ -| ['compiler_generated'] )
+ end
+ ( <_cor0> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_cor0})
+ -| ['compiler_generated'] )
+ end
+ ( <> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause'})
+ -| [{'function_name',{'reversed_annos',0}}] )
+ -| ['compiler_generated'] )
+ end
+'t'/1 =
+ fun (_cor0) ->
+ case _cor0 of
+ <[_cor2|_cor3]> when 'true' ->
+ 'ok'
+ %% Cover v3_kernel:get_line/1.
+ ( <['a']> when 'true' ->
+ 'error'
+ -| [{'file',"reversed_annos.erl"},11] )
+ ( <_cor1> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause',_cor1})
+ -| [{'function_name',{'t',1}}] )
+ -| ['compiler_generated'] )
+ end
+end
diff --git a/lib/compiler/test/core_SUITE_data/unsafe_case.core b/lib/compiler/test/core_SUITE_data/unsafe_case.core
new file mode 100644
index 0000000000..84cb2c310a
--- /dev/null
+++ b/lib/compiler/test/core_SUITE_data/unsafe_case.core
@@ -0,0 +1,25 @@
+module 'unsafe_case' ['unsafe_case'/0]
+ attributes []
+'unsafe_case'/0 =
+ fun () ->
+ case apply 't'/1
+ (42) of
+ <{'ok',42}> when 'true' ->
+ 'ok'
+ ( <_cor0> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_cor0})
+ -| ['compiler_generated'] )
+ end
+'t'/1 =
+ fun (_cor0) ->
+ case _cor0 of
+ <X>
+ when call 'erlang':'>'
+ (_cor0,
+ 0) ->
+ {'ok',X}
+ %% The default case is intentionally missing
+ %% to cover v3_kernel:build_match/2.
+ end
+end
diff --git a/lib/compiler/test/core_fold_SUITE.erl b/lib/compiler/test/core_fold_SUITE.erl
index ac14d36e82..fb5ec88c9f 100644
--- a/lib/compiler/test/core_fold_SUITE.erl
+++ b/lib/compiler/test/core_fold_SUITE.erl
@@ -214,6 +214,7 @@ coverage(Config) when is_list(Config) ->
(catch cover_will_match_list_type({a,b,c,d})),
?line a = cover_remove_non_vars_alias({a,b,c}),
?line error = cover_will_match_lit_list(),
+ {ok,[a]} = cover_is_safe_bool_expr(a),
%% Make sure that we don't attempt to make literals
%% out of pids. (Putting a pid into a #c_literal{}
@@ -249,4 +250,17 @@ cover_will_match_lit_list() ->
error
end.
+cover_is_safe_bool_expr(X) ->
+ %% Use a try...catch that looks like a try...catch in a guard.
+ try
+ %% let V = [X] in {ok,V}
+ %% is_safe_simple([X]) ==> true
+ %% is_safe_bool_expr([X]) ==> false
+ V = [X],
+ {ok,V}
+ catch
+ _:_ ->
+ false
+ end.
+
id(I) -> I.
diff --git a/lib/compiler/test/misc_SUITE.erl b/lib/compiler/test/misc_SUITE.erl
index 9b414cade6..5e13a93c52 100644
--- a/lib/compiler/test/misc_SUITE.erl
+++ b/lib/compiler/test/misc_SUITE.erl
@@ -190,6 +190,15 @@ silly_coverage(Config) when is_list(Config) ->
{label,2}|non_proper_list]}],99},
?line expect_error(fun() -> beam_block:module(BlockInput, []) end),
+ %% beam_except
+ ExceptInput = {?MODULE,[{foo,0}],[],
+ [{function,foo,0,2,
+ [{label,1},
+ {line,loc},
+ {func_info,{atom,?MODULE},{atom,foo},0},
+ {label,2}|non_proper_list]}],99},
+ expect_error(fun() -> beam_except:module(ExceptInput, []) end),
+
%% beam_bool
BoolInput = {?MODULE,[{foo,0}],[],
[{function,foo,0,2,
@@ -253,8 +262,15 @@ expect_error(Fun) ->
io:format("~p", [Any]),
?t:fail(call_was_supposed_to_fail)
catch
- _:_ ->
- io:format("~p\n", [erlang:get_stacktrace()])
+ Class:Reason ->
+ Stk = erlang:get_stacktrace(),
+ io:format("~p:~p\n~p\n", [Class,Reason,Stk]),
+ case {Class,Reason} of
+ {error,undef} ->
+ ?t:fail(not_supposed_to_fail_with_undef);
+ {_,_} ->
+ ok
+ end
end.
confused_literals(Config) when is_list(Config) ->
diff --git a/lib/compiler/test/parteval_SUITE.erl b/lib/compiler/test/parteval_SUITE.erl
deleted file mode 100644
index 6b1ae38c1b..0000000000
--- a/lib/compiler/test/parteval_SUITE.erl
+++ /dev/null
@@ -1,66 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
--module(parteval_SUITE).
-
--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, pe2/1]).
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [pe2].
-
-groups() ->
- [].
-
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%% (This is more general than needed, since we once compiled the same
-%% source code with and without a certain option.)
-compile_and_load(Srcname, Outdir, Module, Options) ->
- ?line Objname = filename:join(Outdir, "t1") ++ code:objfile_extension(),
- ?line {ok, Module} =
- compile:file(Srcname,
- [{d, 'M', Module}, {outdir, Outdir}] ++ Options),
- ?line {ok, B} = file:read_file(Objname),
- ?line {module, Module} = code:load_binary(Module, Objname, B),
- B.
-
-pe2(Config) when is_list(Config) ->
- ?line DataDir = ?config(data_dir, Config),
- ?line PrivDir = ?config(priv_dir, Config),
- ?line Srcname = filename:join(DataDir, "t1.erl"),
- ?line compile_and_load(Srcname, PrivDir, t1, []),
-
- ?line {Correct, Actual} = t1:run(),
- ?line Correct = Actual,
- ok.
diff --git a/lib/compiler/test/parteval_SUITE_data/t1.erl b/lib/compiler/test/parteval_SUITE_data/t1.erl
deleted file mode 100644
index 5e4a40f103..0000000000
--- a/lib/compiler/test/parteval_SUITE_data/t1.erl
+++ /dev/null
@@ -1,140 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
--module(?M).
-
--compile(export_all).
-
-%%% The arity-0 functions are all called from the test suite.
-
-f2() ->
- size({1,2}).
-
-i() ->
- case [] of
- [] ->
- ok;
- X ->
- hopp
- end.
-
-e() ->
- case 4+5 of
-% X when X>10 -> kvock; % not removed by BEAM opt.
- {X,X} when list(X) ->
- kvack;
- 9 ->
- ok;
- _ ->
- ko
- end.
-
-f() ->
- element(2,{a,b,c,d}),
- erlang:element(2,{a,b,c,d}),
- "hej" ++ "hopp".
-
-g(X) ->
- if
- float(3.4) ->
- hej;
- X == 5, 4==4 ->
- japp;
- 4 == 4, size({1,2}) == 1 ->
- ok
- end.
-
-g() ->
- {g(3),g(5)}.
-
-bliff() ->
- if
- 3==4 ->
- himm
- end.
-
-fi() ->
- case 4 of
- X when 4==3 ->
- {X};
- 4 ->
- 4;
- _ ->
- ok
- end.
-
-iff() when 3==2 ->
- if
- 3 == 4 ->
- baff;
- 3 == 3 ->
- nipp
- end.
-
-sleep(I) -> receive after I -> ok end.
-
-sleep() ->
- sleep(45).
-
-s() ->
- case 4 of
- 3 ->
- ok
- end.
-
-error_reason(R) when atom(R) ->
- R;
-error_reason(R) when tuple(R) ->
- error_reason(element(1, R)).
-
-plusplus() ->
- ?MODULE ++ " -> mindre snygg felhantering".
-
-call_it(F) ->
- case (catch apply(?MODULE, F, [])) of
- {'EXIT', R0} ->
- {'EXIT', error_reason(R0)};
- V ->
- V
- end.
-
-run() ->
- L = [{f2, 2},
- {i, ok},
- {e, ok},
- {f, "hejhopp"},
- {g, {hej, hej}},
- {bliff, {'EXIT', if_clause}},
- {fi, 4},
- {iff, {'EXIT', function_clause}},
- {sleep, ok},
- {s, {'EXIT', case_clause},
- {plusplus, {'EXIT', badarg}}}],
- Actual = [call_it(F) || {F, _} <- L],
- Correct = [C || {_, C} <- L],
- {Correct, Actual}.
-
-
-%%% Don't call, only compile.
-t(A) ->
- receive
- A when 1==2 ->
- ok;
- B ->
- B
- end.
diff --git a/lib/compiler/test/test_lib.erl b/lib/compiler/test/test_lib.erl
index 53d8c04169..2295592a38 100644
--- a/lib/compiler/test/test_lib.erl
+++ b/lib/compiler/test/test_lib.erl
@@ -77,7 +77,14 @@ get_data_dir(Config) ->
%% Will fail the test case if there were any errors.
p_run(Test, List) ->
- N = erlang:system_info(schedulers) + 1,
+ N = case ?t:is_cover() of
+ false ->
+ erlang:system_info(schedulers);
+ true ->
+ %% Cover is running. Using more than one process
+ %% will probably only slow down compilation.
+ 1
+ end,
p_run_loop(Test, List, N, [], 0, 0).
p_run_loop(_, [], _, [], Errors, Ws) ->
diff --git a/lib/compiler/test/trycatch_SUITE.erl b/lib/compiler/test/trycatch_SUITE.erl
index 760cf17225..09a23724fe 100644
--- a/lib/compiler/test/trycatch_SUITE.erl
+++ b/lib/compiler/test/trycatch_SUITE.erl
@@ -24,7 +24,7 @@
catch_oops/1,after_oops/1,eclectic/1,rethrow/1,
nested_of/1,nested_catch/1,nested_after/1,
nested_horrid/1,last_call_optimization/1,bool/1,
- plain_catch_coverage/1,andalso_orelse/1]).
+ plain_catch_coverage/1,andalso_orelse/1,get_in_try/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -35,7 +35,7 @@ all() ->
[basic, lean_throw, try_of, try_after, catch_oops,
after_oops, eclectic, rethrow, nested_of, nested_catch,
nested_after, nested_horrid, last_call_optimization,
- bool, plain_catch_coverage, andalso_orelse].
+ bool, plain_catch_coverage, andalso_orelse, get_in_try].
groups() ->
[].
@@ -928,3 +928,17 @@ andalso_orelse_2({Type,Keyval}) ->
zero() ->
0.0.
+
+get_in_try(_) ->
+ undefined = get_valid_line([a], []),
+ ok.
+
+get_valid_line([_|T]=Path, Annotations) ->
+ try
+ get(Path)
+ %% beam_dead used to optimize away an assignment to {y,1}
+ %% because it didn't appear to be used.
+ catch
+ _:not_found ->
+ get_valid_line(T, Annotations)
+ end.
diff --git a/lib/debugger/src/dbg_ui_break_win.erl b/lib/debugger/src/dbg_ui_break_win.erl
index abbec158b0..2894e8223b 100644
--- a/lib/debugger/src/dbg_ui_break_win.erl
+++ b/lib/debugger/src/dbg_ui_break_win.erl
@@ -17,6 +17,18 @@
%% %CopyrightEnd%
%%
-module(dbg_ui_break_win).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,entry,2}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,listbox,2}},
+ {nowarn_deprecated_function,{gs,menu,2}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,radiobutton,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
%% External exports
-export([create_win/5,
diff --git a/lib/debugger/src/dbg_ui_edit_win.erl b/lib/debugger/src/dbg_ui_edit_win.erl
index 9b0441b44c..fb40ab3812 100644
--- a/lib/debugger/src/dbg_ui_edit_win.erl
+++ b/lib/debugger/src/dbg_ui_edit_win.erl
@@ -17,6 +17,12 @@
%% %CopyrightEnd%
%%
-module(dbg_ui_edit_win).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,entry,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
%% External exports
-export([create_win/5, get_window/1,
diff --git a/lib/debugger/src/dbg_ui_filedialog_win.erl b/lib/debugger/src/dbg_ui_filedialog_win.erl
index 1eced1104d..50d198f361 100644
--- a/lib/debugger/src/dbg_ui_filedialog_win.erl
+++ b/lib/debugger/src/dbg_ui_filedialog_win.erl
@@ -18,6 +18,13 @@
%%
-module(dbg_ui_filedialog_win).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,entry,3}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,listbox,3}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
%% External exports
-export([create_win/6, create_win/7, get_window/1,
diff --git a/lib/debugger/src/dbg_ui_mon_win.erl b/lib/debugger/src/dbg_ui_mon_win.erl
index 52e8f433ba..f446fb7fcd 100644
--- a/lib/debugger/src/dbg_ui_mon_win.erl
+++ b/lib/debugger/src/dbg_ui_mon_win.erl
@@ -17,6 +17,19 @@
%% %CopyrightEnd%
%%
-module(dbg_ui_mon_win).
+-compile([{nowarn_deprecated_function,{gs,checkbutton,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,grid,2}},
+ {nowarn_deprecated_function,{gs,gridline,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,listbox,2}},
+ {nowarn_deprecated_function,{gs,menu,2}},
+ {nowarn_deprecated_function,{gs,menubar,2}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
%% External exports
-export([init/0]).
diff --git a/lib/debugger/src/dbg_ui_trace_win.erl b/lib/debugger/src/dbg_ui_trace_win.erl
index 82d4199630..f237f30e4a 100644
--- a/lib/debugger/src/dbg_ui_trace_win.erl
+++ b/lib/debugger/src/dbg_ui_trace_win.erl
@@ -17,6 +17,25 @@
%% %CopyrightEnd%
%%
-module(dbg_ui_trace_win).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,button,3}},
+ {nowarn_deprecated_function,{gs,checkbutton,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,editor,2}},
+ {nowarn_deprecated_function,{gs,editor,3}},
+ {nowarn_deprecated_function,{gs,entry,2}},
+ {nowarn_deprecated_function,{gs,entry,3}},
+ {nowarn_deprecated_function,{gs,frame,3}},
+ {nowarn_deprecated_function,{gs,grid,3}},
+ {nowarn_deprecated_function,{gs,gridline,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,label,3}},
+ {nowarn_deprecated_function,{gs,menubar,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,window,2}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
%% External exports
-export([init/0]).
diff --git a/lib/debugger/src/dbg_ui_win.erl b/lib/debugger/src/dbg_ui_win.erl
index 9bed6a1ec5..cef091ee28 100644
--- a/lib/debugger/src/dbg_ui_win.erl
+++ b/lib/debugger/src/dbg_ui_win.erl
@@ -17,6 +17,15 @@
%% %CopyrightEnd%
%%
-module(dbg_ui_win).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,menu,2}},
+ {nowarn_deprecated_function,{gs,menu,3}},
+ {nowarn_deprecated_function,{gs,menubutton,2}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,menuitem,3}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,1}}]).
%% External exports
-export([init/0,
diff --git a/lib/debugger/src/dbg_ui_winman.erl b/lib/debugger/src/dbg_ui_winman.erl
index c7aac0df23..8619be344b 100644
--- a/lib/debugger/src/dbg_ui_winman.erl
+++ b/lib/debugger/src/dbg_ui_winman.erl
@@ -18,6 +18,11 @@
%%
-module(dbg_ui_winman).
-behaviour(gen_server).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,menu,3}},
+ {nowarn_deprecated_function,{gs,menubutton,3}},
+ {nowarn_deprecated_function,{gs,menuitem,3}}]).
%% External exports
-export([start/0]).
diff --git a/lib/debugger/src/dbg_wx_trace_win.erl b/lib/debugger/src/dbg_wx_trace_win.erl
index 79cf87ae62..aab8fddda7 100644
--- a/lib/debugger/src/dbg_wx_trace_win.erl
+++ b/lib/debugger/src/dbg_wx_trace_win.erl
@@ -19,6 +19,7 @@
%%
-module(dbg_wx_trace_win).
+-compile([{nowarn_deprecated_function,{gs,config,2}}]).
%% External exports
-export([init/0, stop/1]).
diff --git a/lib/debugger/test/bs_construct_SUITE.erl b/lib/debugger/test/bs_construct_SUITE.erl
index 187c9f53b0..fa7b40ff1e 100644
--- a/lib/debugger/test/bs_construct_SUITE.erl
+++ b/lib/debugger/test/bs_construct_SUITE.erl
@@ -56,7 +56,7 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(_Case, Config) ->
test_lib:interpret(?MODULE),
- Dog = test_server:timetrap(?t:minutes(1)),
+ Dog = test_server:timetrap(?t:minutes(15)),
[{watchdog,Dog}|Config].
end_per_testcase(_Case, Config) ->
diff --git a/lib/debugger/test/bs_match_misc_SUITE.erl b/lib/debugger/test/bs_match_misc_SUITE.erl
index 89fce263f5..ec3746d76a 100644
--- a/lib/debugger/test/bs_match_misc_SUITE.erl
+++ b/lib/debugger/test/bs_match_misc_SUITE.erl
@@ -57,7 +57,7 @@ end_per_suite(Config) when is_list(Config) ->
init_per_testcase(_Case, Config) ->
test_lib:interpret(?MODULE),
- Dog = test_server:timetrap(?t:minutes(1)),
+ Dog = test_server:timetrap(?t:minutes(15)),
[{watchdog,Dog}|Config].
end_per_testcase(_Case, Config) ->
diff --git a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl
index b42f5e8191..458f3a4c81 100644
--- a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl
+++ b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl
@@ -359,8 +359,17 @@ store_core(Mod, Core, NoWarn, Callgraph, CServer) ->
store_code_and_build_callgraph(Mod, LabeledCore, Callgraph, CServer3, NoWarn).
abs_get_nowarn(Abs, M) ->
- [{M, F, A}
- || {attribute, _, compile, {nowarn_unused_function, {F, A}}} <- Abs].
+ Opts = lists:flatten([C || {attribute, _, compile, C} <- Abs]),
+ Warn = erl_lint:bool_option(warn_unused_function, nowarn_unused_function,
+ true, Opts),
+ case Warn of
+ false ->
+ [{M, F, A} || {function, _, F, A, _} <- Abs]; % all functions
+ true ->
+ [{M, F, A} ||
+ {nowarn_unused_function, FAs} <- Opts,
+ {F, A} <- lists:flatten([FAs])]
+ end.
get_exported_types_from_core(Core) ->
Attrs = cerl:module_attrs(Core),
diff --git a/lib/dialyzer/src/dialyzer_gui.erl b/lib/dialyzer/src/dialyzer_gui.erl
index ccd80a4835..f60194e01f 100644
--- a/lib/dialyzer/src/dialyzer_gui.erl
+++ b/lib/dialyzer/src/dialyzer_gui.erl
@@ -28,6 +28,23 @@
%%%-----------------------------------------------------------------------
-module(dialyzer_gui).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,editor,2}},
+ {nowarn_deprecated_function,{gs,entry,2}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,listbox,2}},
+ {nowarn_deprecated_function,{gs,menu,2}},
+ {nowarn_deprecated_function,{gs,menubar,2}},
+ {nowarn_deprecated_function,{gs,menubutton,2}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,radiobutton,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,stop,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/1]).
diff --git a/lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_1 b/lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_1
new file mode 100644
index 0000000000..de416455e2
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_1
@@ -0,0 +1,2 @@
+
+nowarn_unused_function_1.erl:17: Function f3/1 will never be called
diff --git a/lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_2 b/lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_2
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_2
diff --git a/lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_3 b/lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_3
new file mode 100644
index 0000000000..8ae78673d5
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_3
@@ -0,0 +1,3 @@
+
+nowarn_unused_function_3.erl:12: Function f2/1 will never be called
+nowarn_unused_function_3.erl:9: Function f1/1 will never be called
diff --git a/lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_1.erl b/lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_1.erl
new file mode 100644
index 0000000000..fcce532f73
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_1.erl
@@ -0,0 +1,18 @@
+%% Test that option 'nowarn_unused_funcion' works similarly in
+%% Dialyzer as in the compiler.
+
+-module(nowarn_unused_function_1).
+
+-compile(warn_unused_function).
+
+-compile({nowarn_unused_function,f1/1}).
+f1(_) ->
+ a.
+
+-compile({nowarn_unused_function,[{f2,1}]}).
+f2(_) ->
+ a.
+
+-compile({warn_unused_function,[{f3,1}]}).
+f3(_) ->
+ a.
diff --git a/lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_2.erl b/lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_2.erl
new file mode 100644
index 0000000000..9bc3ab14ea
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_2.erl
@@ -0,0 +1,18 @@
+%% Test that option 'nowarn_unused_funcion' works similarly in
+%% Dialyzer as in the compiler.
+
+-module(nowarn_unused_function_2).
+
+-compile(nowarn_unused_function).
+
+-compile({warn_unused_function,f1/1}).
+f1(_) ->
+ a.
+
+-compile({warn_unused_function,[{f2,1}]}).
+f2(_) ->
+ a.
+
+-compile({nowarn_unused_function,[{f3,1}]}).
+f3(_) ->
+ a.
diff --git a/lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_3.erl b/lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_3.erl
new file mode 100644
index 0000000000..604c5e436b
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_3.erl
@@ -0,0 +1,16 @@
+%% Test that option 'nowarn_unused_funcion' works similarly in
+%% Dialyzer as in the compiler.
+
+-module(nowarn_unused_function_3).
+
+-compile({warn_unused_function,[{f1,1},{f2,1}]}).
+-compile({nowarn_unused_function,[{f3,1}]}).
+
+f1(_) ->
+ a.
+
+f2(_) ->
+ a.
+
+f3(_) ->
+ a.
diff --git a/lib/diameter/examples/GNUmakefile b/lib/diameter/examples/code/GNUmakefile
index 4c3f87939b..a0669119d2 100644
--- a/lib/diameter/examples/GNUmakefile
+++ b/lib/diameter/examples/code/GNUmakefile
@@ -1,19 +1,19 @@
-#
+#
# %CopyrightBegin%
-#
+#
# Copyright Ericsson AB 2010-2011. 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%
#
diff --git a/lib/diameter/examples/client.erl b/lib/diameter/examples/code/client.erl
index 36a77dd524..9e65f98de0 100644
--- a/lib/diameter/examples/client.erl
+++ b/lib/diameter/examples/code/client.erl
@@ -112,7 +112,7 @@ cast(Name) ->
{'Auth-Application-Id', 0},
{'Re-Auth-Request-Type', 1}],
diameter:call(Name, ?APP_ALIAS, RAR, [detach]).
-
+
cast() ->
cast(?SVC_NAME).
diff --git a/lib/diameter/examples/client_cb.erl b/lib/diameter/examples/code/client_cb.erl
index 524a8f94a1..524a8f94a1 100644
--- a/lib/diameter/examples/client_cb.erl
+++ b/lib/diameter/examples/code/client_cb.erl
diff --git a/lib/diameter/examples/peer.erl b/lib/diameter/examples/code/peer.erl
index 89203e15c3..89203e15c3 100644
--- a/lib/diameter/examples/peer.erl
+++ b/lib/diameter/examples/code/peer.erl
diff --git a/lib/diameter/examples/redirect.erl b/lib/diameter/examples/code/redirect.erl
index b54701243f..b54701243f 100644
--- a/lib/diameter/examples/redirect.erl
+++ b/lib/diameter/examples/code/redirect.erl
diff --git a/lib/diameter/examples/redirect_cb.erl b/lib/diameter/examples/code/redirect_cb.erl
index ea7ad38749..ea7ad38749 100644
--- a/lib/diameter/examples/redirect_cb.erl
+++ b/lib/diameter/examples/code/redirect_cb.erl
diff --git a/lib/diameter/examples/relay.erl b/lib/diameter/examples/code/relay.erl
index deecb1cfc0..deecb1cfc0 100644
--- a/lib/diameter/examples/relay.erl
+++ b/lib/diameter/examples/code/relay.erl
diff --git a/lib/diameter/examples/relay_cb.erl b/lib/diameter/examples/code/relay_cb.erl
index 9ed6517d5c..9ed6517d5c 100644
--- a/lib/diameter/examples/relay_cb.erl
+++ b/lib/diameter/examples/code/relay_cb.erl
diff --git a/lib/diameter/examples/sctp.erl b/lib/diameter/examples/code/sctp.erl
index 2e0e9d8b0b..08de023571 100644
--- a/lib/diameter/examples/sctp.erl
+++ b/lib/diameter/examples/code/sctp.erl
@@ -1,3 +1,21 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
-module(sctp).
diff --git a/lib/diameter/examples/server.erl b/lib/diameter/examples/code/server.erl
index ebb408e501..ebb408e501 100644
--- a/lib/diameter/examples/server.erl
+++ b/lib/diameter/examples/code/server.erl
diff --git a/lib/diameter/examples/server_cb.erl b/lib/diameter/examples/code/server_cb.erl
index 43b8e24b5c..43b8e24b5c 100644
--- a/lib/diameter/examples/server_cb.erl
+++ b/lib/diameter/examples/code/server_cb.erl
diff --git a/lib/diameter/examples/dict/rfc4004_mip.dia b/lib/diameter/examples/dict/rfc4004_mip.dia
new file mode 100644
index 0000000000..575ad4394a
--- /dev/null
+++ b/lib/diameter/examples/dict/rfc4004_mip.dia
@@ -0,0 +1,280 @@
+;;
+;; %CopyrightBegin%
+;;
+;; Copyright Ericsson AB 2010-2011. 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%
+;;
+
+;;
+;; RFC 4004, Diameter Mobile IPv4 Application
+;;
+;; Edits:
+;;
+;; - MIP-nonce -> MIP-Nonce
+;; - Session-ID -> Session-Id
+;; - Omit MIP-HA-to-MN-SPI, MIP-MN-FA-SPI and MIP-MN-HA-SPI, none of
+;; which are defined.
+;;
+
+@id 2
+
+@inherits rfc3588_base
+
+;; ===========================================================================
+
+@avp_types
+
+ MIP-Reg-Request 320 OctetString M
+ MIP-Reg-Reply 321 OctetString M
+ MIP-MN-AAA-Auth 322 Grouped M
+ MIP-Mobile-Node-Address 333 Address M
+ MIP-Home-Agent-Address 334 Address M
+ MIP-Candidate-Home-Agent-Host 336 DiamIdent M
+ MIP-Feature-Vector 337 Unsigned32 M
+ MIP-Auth-Input-Data-Length 338 Unsigned32 M
+ MIP-Authenticator-Length 339 Unsigned32 M
+ MIP-Authenticator-Offset 340 Unsigned32 M
+ MIP-MN-AAA-SPI 341 Unsigned32 M
+ MIP-Filter-Rule 342 IPFilterRule M
+ MIP-FA-Challenge 344 OctetString M
+ MIP-Originating-Foreign-AAA 347 Grouped M
+ MIP-Home-Agent-Host 348 Grouped M
+
+ MIP-FA-to-HA-SPI 318 Unsigned32 M
+ MIP-FA-to-MN-SPI 319 Unsigned32 M
+ MIP-HA-to-FA-SPI 323 Unsigned32 M
+ MIP-MN-to-FA-MSA 325 Grouped M
+ MIP-FA-to-MN-MSA 326 Grouped M
+ MIP-FA-to-HA-MSA 328 Grouped M
+ MIP-HA-to-FA-MSA 329 Grouped M
+ MIP-MN-to-HA-MSA 331 Grouped M
+ MIP-HA-to-MN-MSA 332 Grouped M
+ MIP-Nonce 335 OctetString M
+ MIP-Session-Key 343 OctetString M
+ MIP-Algorithm-Type 345 Enumerated M
+ MIP-Replay-Mode 346 Enumerated M
+ MIP-MSA-Lifetime 367 Unsigned32 M
+
+;; ===========================================================================
+
+@messages
+
+ ;; 5.1. AA-Mobile-Node-Request
+
+ AMR ::= < Diameter Header: 260, REQ, PXY >
+
+ < Session-Id >
+ { Auth-Application-Id }
+ { User-Name }
+ { Destination-Realm }
+ { Origin-Host }
+ { Origin-Realm }
+ { MIP-Reg-Request }
+ { MIP-MN-AAA-Auth }
+ [ Acct-Multi-Session-Id ]
+ [ Destination-Host ]
+ [ Origin-State-Id ]
+ [ MIP-Mobile-Node-Address ]
+ [ MIP-Home-Agent-Address ]
+ [ MIP-Feature-Vector ]
+ [ MIP-Originating-Foreign-AAA ]
+ [ Authorization-Lifetime ]
+ [ Auth-Session-State ]
+ [ MIP-FA-Challenge ]
+ [ MIP-Candidate-Home-Agent-Host ]
+ [ MIP-Home-Agent-Host ]
+ [ MIP-HA-to-FA-SPI ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ ;; 5.2. AA-Mobile-Node-Answer
+
+ AMA ::= < Diameter Header: 260, PXY >
+
+ < Session-Id >
+ { Auth-Application-Id }
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ Acct-Multi-Session-Id ]
+ [ User-Name ]
+ [ Authorization-Lifetime ]
+ [ Auth-Session-State ]
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+ [ Re-Auth-Request-Type ]
+ [ MIP-Feature-Vector ]
+ [ MIP-Reg-Reply ]
+ [ MIP-MN-to-FA-MSA ]
+ [ MIP-MN-to-HA-MSA ]
+ [ MIP-FA-to-MN-MSA ]
+ [ MIP-FA-to-HA-MSA ]
+ [ MIP-HA-to-MN-MSA ]
+ [ MIP-MSA-Lifetime ]
+ [ MIP-Home-Agent-Address ]
+ [ MIP-Mobile-Node-Address ]
+ * [ MIP-Filter-Rule ]
+ [ Origin-State-Id ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+ ;; 5.3. Home-Agent-MIP-Request
+
+ HAR ::= < Diameter Header: 262, REQ, PXY >
+
+ < Session-Id >
+ { Auth-Application-Id }
+ { Authorization-Lifetime }
+ { Auth-Session-State }
+ { MIP-Reg-Request }
+ { Origin-Host }
+ { Origin-Realm }
+ { User-Name }
+ { Destination-Realm }
+ { MIP-Feature-Vector }
+ [ Destination-Host ]
+ [ MIP-MN-to-HA-MSA ]
+ [ MIP-MN-to-FA-MSA ]
+ [ MIP-HA-to-MN-MSA ]
+ [ MIP-HA-to-FA-MSA ]
+ [ MIP-MSA-Lifetime ]
+ [ MIP-Originating-Foreign-AAA ]
+ [ MIP-Mobile-Node-Address ]
+ [ MIP-Home-Agent-Address ]
+ * [ MIP-Filter-Rule ]
+ [ Origin-State-Id ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ ;; 5.4. Home-Agent-MIP-Answer
+
+ HAA ::= < Diameter Header: 262, PXY >
+
+ < Session-Id >
+ { Auth-Application-Id }
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ Acct-Multi-Session-Id ]
+ [ User-Name ]
+ [ Error-Reporting-Host ]
+ [ Error-Message ]
+ [ MIP-Reg-Reply ]
+ [ MIP-Home-Agent-Address ]
+ [ MIP-Mobile-Node-Address ]
+ [ MIP-FA-to-HA-SPI ]
+ [ MIP-FA-to-MN-SPI ]
+ [ Origin-State-Id ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+;; ===========================================================================
+
+@grouped
+
+ MIP-MN-AAA-Auth ::= < AVP Header: 322 >
+
+ { MIP-MN-AAA-SPI }
+ { MIP-Auth-Input-Data-Length }
+ { MIP-Authenticator-Length }
+ { MIP-Authenticator-Offset }
+ * [ AVP ]
+
+
+ MIP-Originating-Foreign-AAA ::= < AVP Header: 347 >
+
+ { Origin-Realm }
+ { Origin-Host }
+ * [ AVP ]
+
+ MIP-Home-Agent-Host ::= < AVP Header: 348 >
+
+ { Destination-Realm }
+ { Destination-Host }
+ * [ AVP ]
+
+ MIP-FA-to-MN-MSA ::= < AVP Header: 326 >
+
+ { MIP-FA-to-MN-SPI }
+ { MIP-Algorithm-Type }
+ { MIP-Session-Key }
+ * [ AVP ]
+
+ MIP-FA-to-HA-MSA ::= < AVP Header: 328 >
+
+ { MIP-FA-to-HA-SPI }
+ { MIP-Algorithm-Type }
+ { MIP-Session-Key }
+ * [ AVP ]
+
+ MIP-HA-to-FA-MSA ::= < AVP Header: 329 >
+
+ { MIP-HA-to-FA-SPI }
+ { MIP-Algorithm-Type }
+ { MIP-Session-Key }
+ * [ AVP ]
+
+ MIP-HA-to-MN-MSA ::= < AVP Header: 332 >
+
+ ; { MIP-HA-to-MN-SPI }
+ { MIP-Algorithm-Type }
+ { MIP-Replay-Mode }
+ { MIP-Session-Key }
+ * [ AVP ]
+
+ MIP-MN-to-FA-MSA ::= < AVP Header: 325 >
+
+ ; { MIP-MN-FA-SPI }
+ { MIP-Algorithm-Type }
+ { MIP-Nonce }
+ * [ AVP ]
+
+ MIP-MN-to-HA-MSA ::= < AVP Header: 331 >
+
+ ; { MIP-MN-HA-SPI }
+ { MIP-Algorithm-Type }
+ { MIP-Replay-Mode }
+ { MIP-Nonce }
+ * [ AVP ]
+
+;; ===========================================================================
+
+@enum MIP-Algorithm-Type
+
+ HMAC-SHA-1 2
+
+@enum MIP-Replay-Mode
+
+ NONE 1
+ TIMESTAMPS 2
+ NONCES 3
+
+;; ===========================================================================
+
+@define Result-Code
+
+ ;; 6.1. Transient Failures
+
+ MIP_REPLY_FAILURE 4005
+ HA_NOT_AVAILABLE 4006
+ BAD_KEY 4007
+ MIP_FILTER_NOT_SUPPORTED 4008
+
+ ;; 6.2. Permanent Failures
+
+ NO_FOREIGN_HA_SERVICE 5024
+ END_TO_END_MIP_KEY_ENCRYPTION 5025
diff --git a/lib/diameter/examples/dict/rfc4005_nas.dia b/lib/diameter/examples/dict/rfc4005_nas.dia
new file mode 100644
index 0000000000..a4b44e38bb
--- /dev/null
+++ b/lib/diameter/examples/dict/rfc4005_nas.dia
@@ -0,0 +1,740 @@
+;;
+;; %CopyrightBegin%
+;;
+;; Copyright Ericsson AB 2010-2011. 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%
+;;
+
+;;
+;; RFC 4005, Diameter Network Access Server Application
+;;
+;; Edits:
+;;
+;; - Acounting-Auth-Method -> Accounting-Auth-Method
+;; - Connection-Info -> ConnectInfo
+;; - Framed-Appletalk-Link -> Framed-AppleTalk-Link
+;; - Framed-Appletalk-Network -> Framed-AppleTalk-Network
+;; - Framed-Appletalk-Zone -> Framed-AppleTalk-Zone
+;; - Qos-Filter-Rule -> QoS-Filter-Rule
+;; - Redirect-Host-Usase -> Redirect-Host-Usage
+;; - Redirected-Host -> Redirect-Host
+;; - Redirected-Host-Usage -> Redirect-Host-Usage
+;; - Redirected-Host-Cache-Time -> Redirect-Max-Cache-Time
+;; - Redirected-Max-Cache-Time -> Redirect-Max-Cache-Time
+;;
+
+@id 1
+
+@inherits rfc3588_base
+
+;; ===========================================================================
+
+@avp_types
+
+ ;; 4. NAS Session AVPs
+
+ NAS-Port 5 Unsigned32 M
+ NAS-Port-Id 87 UTF8String M
+ NAS-Port-Type 61 Enumerated M
+ Called-Station-Id 30 UTF8String M
+ Calling-Station-Id 31 UTF8String M
+ Connect-Info 77 UTF8String M
+ Originating-Line-Info 94 OctetString -
+ Reply-Message 18 UTF8String M
+
+ ;; 5. NAS Authentication AVPs
+
+ User-Password 2 OctetString M
+ Password-Retry 75 Unsigned32 M
+ Prompt 76 Enumerated M
+ CHAP-Auth 402 Grouped M
+ CHAP-Algorithm 403 Enumerated M
+ CHAP-Ident 404 OctetString M
+ CHAP-Response 405 OctetString M
+ CHAP-Challenge 60 OctetString M
+ ARAP-Password 70 OctetString M
+ ARAP-Challenge-Response 84 OctetString M
+ ARAP-Security 73 Unsigned32 M
+ ARAP-Security-Data 74 OctetString M
+
+ ;; 6. NAS Authorization AVPs
+
+ Service-Type 6 Enumerated M
+ Callback-Number 19 UTF8String M
+ Callback-Id 20 UTF8String M
+ Idle-Timeout 28 Unsigned32 M
+ Port-Limit 62 Unsigned32 M
+ NAS-Filter-Rule 400 IPFilterRule M
+ Filter-Id 11 UTF8String M
+ Configuration-Token 78 OctetString M
+ QoS-Filter-Rule 407 QoSFilterRule -
+ Framed-Protocol 7 Enumerated M
+ Framed-Routing 10 Enumerated M
+ Framed-MTU 12 Unsigned32 M
+ Framed-Compression 13 Enumerated M
+ Framed-IP-Address 8 OctetString M
+ Framed-IP-Netmask 9 OctetString M
+ Framed-Route 22 UTF8String M
+ Framed-Pool 88 OctetString M
+ Framed-Interface-Id 96 Unsigned64 M
+ Framed-IPv6-Prefix 97 OctetString M
+ Framed-IPv6-Route 99 UTF8String M
+ Framed-IPv6-Pool 100 OctetString M
+ Framed-IPX-Network 23 UTF8String M
+ Framed-AppleTalk-Link 37 Unsigned32 M
+ Framed-AppleTalk-Network 38 Unsigned32 M
+ Framed-AppleTalk-Zone 39 OctetString M
+ ARAP-Features 71 OctetString M
+ ARAP-Zone-Access 72 Enumerated M
+ Login-IP-Host 14 OctetString M
+ Login-IPv6-Host 98 OctetString M
+ Login-Service 15 Enumerated M
+ Login-TCP-Port 16 Unsigned32 M
+ Login-LAT-Service 34 OctetString M
+ Login-LAT-Node 35 OctetString M
+ Login-LAT-Group 36 OctetString M
+ Login-LAT-Port 63 OctetString M
+
+ ;; 7. NAS Tunneling
+
+ Tunneling 401 Grouped M
+ Tunnel-Type 64 Enumerated M
+ Tunnel-Medium-Type 65 Enumerated M
+ Tunnel-Client-Endpoint 66 UTF8String M
+ Tunnel-Server-Endpoint 67 UTF8String M
+ Tunnel-Password 69 OctetString M
+ Tunnel-Private-Group-Id 81 OctetString M
+ Tunnel-Assignment-Id 82 OctetString M
+ Tunnel-Preference 83 Unsigned32 M
+ Tunnel-Client-Auth-Id 90 UTF8String M
+ Tunnel-Server-Auth-Id 91 UTF8String M
+
+ ;; 8. NAS Accounting
+
+ Accounting-Input-Octets 363 Unsigned64 M
+ Accounting-Output-Octets 364 Unsigned64 M
+ Accounting-Input-Packets 365 Unsigned64 M
+ Accounting-Output-Packets 366 Unsigned64 M
+ Acct-Session-Time 46 Unsigned32 M
+ Acct-Authentic 45 Enumerated M
+ Accounting-Auth-Method 406 Enumerated M
+ Acct-Delay-Time 41 Unsigned32 M
+ Acct-Link-Count 51 Unsigned32 M
+ Acct-Tunnel-Connection 68 OctetString M
+ Acct-Tunnel-Packets-Lost 86 Unsigned32 M
+
+ ;; 9.3. AVPs Used Only for Compatibility
+
+ NAS-Identifier 32 UTF8String M
+ NAS-IP-Address 4 OctetString M
+ NAS-IPv6-Address 95 OctetString M
+ State 24 OctetString M
+ ;;Termination-Cause 295 Enumerated M
+ Origin-AAA-Protocol 408 Enumerated M
+
+;; ===========================================================================
+
+@messages
+
+ AAR ::= < Diameter Header: 265, REQ, PXY >
+
+ < Session-Id >
+ { Auth-Application-Id }
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Auth-Request-Type }
+ [ Destination-Host ]
+ [ NAS-Identifier ]
+ [ NAS-IP-Address ]
+ [ NAS-IPv6-Address ]
+ [ NAS-Port ]
+ [ NAS-Port-Id ]
+ [ NAS-Port-Type ]
+ [ Origin-AAA-Protocol ]
+ [ Origin-State-Id ]
+ [ Port-Limit ]
+ [ User-Name ]
+ [ User-Password ]
+ [ Service-Type ]
+ [ State ]
+ [ Authorization-Lifetime ]
+ [ Auth-Grace-Period ]
+ [ Auth-Session-State ]
+ [ Callback-Number ]
+ [ Called-Station-Id ]
+ [ Calling-Station-Id ]
+ [ Originating-Line-Info ]
+ [ Connect-Info ]
+ [ CHAP-Auth ]
+ [ CHAP-Challenge ]
+ * [ Framed-Compression ]
+ [ Framed-Interface-Id ]
+ [ Framed-IP-Address ]
+ * [ Framed-IPv6-Prefix ]
+ [ Framed-IP-Netmask ]
+ [ Framed-MTU ]
+ [ Framed-Protocol ]
+ [ ARAP-Password ]
+ [ ARAP-Security ]
+ * [ ARAP-Security-Data ]
+ * [ Login-IP-Host ]
+ * [ Login-IPv6-Host ]
+ [ Login-LAT-Group ]
+ [ Login-LAT-Node ]
+ [ Login-LAT-Port ]
+ [ Login-LAT-Service ]
+ * [ Tunneling ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ AAA ::= < Diameter Header: 265, PXY >
+
+ < Session-Id >
+ { Auth-Application-Id }
+ { Auth-Request-Type }
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ User-Name ]
+ [ Service-Type ]
+ * [ Class ]
+ * [ Configuration-Token ]
+ [ Acct-Interim-Interval ]
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+ * [ Failed-AVP ]
+ [ Idle-Timeout ]
+ [ Authorization-Lifetime ]
+ [ Auth-Grace-Period ]
+ [ Auth-Session-State ]
+ [ Re-Auth-Request-Type ]
+ [ Multi-Round-Time-Out ]
+ [ Session-Timeout ]
+ [ State ]
+ * [ Reply-Message ]
+ [ Origin-AAA-Protocol ]
+ [ Origin-State-Id ]
+ * [ Filter-Id ]
+ [ Password-Retry ]
+ [ Port-Limit ]
+ [ Prompt ]
+ [ ARAP-Challenge-Response ]
+ [ ARAP-Features ]
+ [ ARAP-Security ]
+ * [ ARAP-Security-Data ]
+ [ ARAP-Zone-Access ]
+ [ Callback-Id ]
+ [ Callback-Number ]
+ [ Framed-AppleTalk-Link ]
+ * [ Framed-AppleTalk-Network ]
+ [ Framed-AppleTalk-Zone ]
+ * [ Framed-Compression ]
+ [ Framed-Interface-Id ]
+ [ Framed-IP-Address ]
+ * [ Framed-IPv6-Prefix ]
+ [ Framed-IPv6-Pool ]
+ * [ Framed-IPv6-Route ]
+ [ Framed-IP-Netmask ]
+ * [ Framed-Route ]
+ [ Framed-Pool ]
+ [ Framed-IPX-Network ]
+ [ Framed-MTU ]
+ [ Framed-Protocol ]
+ [ Framed-Routing ]
+ * [ Login-IP-Host ]
+ * [ Login-IPv6-Host ]
+ [ Login-LAT-Group ]
+ [ Login-LAT-Node ]
+ [ Login-LAT-Port ]
+ [ Login-LAT-Service ]
+ [ Login-Service ]
+ [ Login-TCP-Port ]
+ * [ NAS-Filter-Rule ]
+ * [ QoS-Filter-Rule ]
+ * [ Tunneling ]
+ * [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+ RAR ::= < Diameter Header: 258, REQ, PXY >
+
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Destination-Host }
+ { Auth-Application-Id }
+ { Re-Auth-Request-Type }
+ [ User-Name ]
+ [ Origin-AAA-Protocol ]
+ [ Origin-State-Id ]
+ [ NAS-Identifier ]
+ [ NAS-IP-Address ]
+ [ NAS-IPv6-Address ]
+ [ NAS-Port ]
+ [ NAS-Port-Id ]
+ [ NAS-Port-Type ]
+ [ Service-Type ]
+ [ Framed-IP-Address ]
+ [ Framed-IPv6-Prefix ]
+ [ Framed-Interface-Id ]
+ [ Called-Station-Id ]
+ [ Calling-Station-Id ]
+ [ Originating-Line-Info ]
+ [ Acct-Session-Id ]
+ [ Acct-Multi-Session-Id ]
+ [ State ]
+ * [ Class ]
+ [ Reply-Message ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ RAA ::= < Diameter Header: 258, PXY >
+
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ User-Name ]
+ [ Origin-AAA-Protocol ]
+ [ Origin-State-Id ]
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+ * [ Failed-AVP ]
+ * [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ [ Service-Type ]
+ * [ Configuration-Token ]
+ [ Idle-Timeout ]
+ [ Authorization-Lifetime ]
+ [ Auth-Grace-Period ]
+ [ Re-Auth-Request-Type ]
+ [ State ]
+ * [ Class ]
+ * [ Reply-Message ]
+ [ Prompt ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+ STR ::= < Diameter Header: 275, REQ, PXY >
+
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Auth-Application-Id }
+ { Termination-Cause }
+ [ User-Name ]
+ [ Destination-Host ]
+ * [ Class ]
+ [ Origin-AAA-Protocol ]
+ [ Origin-State-Id ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ STA ::= < Diameter Header: 275, PXY >
+
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ User-Name ]
+ * [ Class ]
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+ * [ Failed-AVP ]
+ [ Origin-AAA-Protocol ]
+ [ Origin-State-Id ]
+ * [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+ ASR ::= < Diameter Header: 274, REQ, PXY >
+
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Destination-Host }
+ { Auth-Application-Id }
+ [ User-Name ]
+ [ Origin-AAA-Protocol ]
+ [ Origin-State-Id ]
+ [ NAS-Identifier ]
+ [ NAS-IP-Address ]
+ [ NAS-IPv6-Address ]
+ [ NAS-Port ]
+ [ NAS-Port-Id ]
+ [ NAS-Port-Type ]
+ [ Service-Type ]
+ [ Framed-IP-Address ]
+ [ Framed-IPv6-Prefix ]
+ [ Framed-Interface-Id ]
+ [ Called-Station-Id ]
+ [ Calling-Station-Id ]
+ [ Originating-Line-Info ]
+ [ Acct-Session-Id ]
+ [ Acct-Multi-Session-Id ]
+ [ State ]
+ * [ Class ]
+ * [ Reply-Message ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ ASA ::= < Diameter Header: 274, PXY >
+
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ User-Name ]
+ [ Origin-AAA-Protocol ]
+ [ Origin-State-Id ]
+ [ State]
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+ * [ Failed-AVP ]
+ * [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ AVP ]
+
+ ACR ::= < Diameter Header: 271, REQ, PXY >
+
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Accounting-Record-Type }
+ { Accounting-Record-Number }
+ [ Acct-Application-Id ]
+ [ Vendor-Specific-Application-Id ]
+ [ User-Name ]
+ [ Accounting-Sub-Session-Id ]
+ [ Acct-Session-Id ]
+ [ Acct-Multi-Session-Id ]
+ [ Origin-AAA-Protocol ]
+ [ Origin-State-Id ]
+ [ Destination-Host ]
+ [ Event-Timestamp ]
+ [ Acct-Delay-Time ]
+ [ NAS-Identifier ]
+ [ NAS-IP-Address ]
+ [ NAS-IPv6-Address ]
+ [ NAS-Port ]
+ [ NAS-Port-Id ]
+ [ NAS-Port-Type ]
+ * [ Class ]
+ [ Service-Type ]
+ [ Termination-Cause ]
+ [ Accounting-Input-Octets ]
+ [ Accounting-Input-Packets ]
+ [ Accounting-Output-Octets ]
+ [ Accounting-Output-Packets ]
+ [ Acct-Authentic ]
+ [ Accounting-Auth-Method ]
+ [ Acct-Link-Count ]
+ [ Acct-Session-Time ]
+ [ Acct-Tunnel-Connection ]
+ [ Acct-Tunnel-Packets-Lost ]
+ [ Callback-Id ]
+ [ Callback-Number ]
+ [ Called-Station-Id ]
+ [ Calling-Station-Id ]
+ * [ Connect-Info ]
+ [ Originating-Line-Info ]
+ [ Authorization-Lifetime ]
+ [ Session-Timeout ]
+ [ Idle-Timeout ]
+ [ Port-Limit ]
+ [ Accounting-Realtime-Required ]
+ [ Acct-Interim-Interval ]
+ * [ Filter-Id ]
+ * [ NAS-Filter-Rule ]
+ * [ QoS-Filter-Rule ]
+ [ Framed-AppleTalk-Link ]
+ [ Framed-AppleTalk-Network ]
+ [ Framed-AppleTalk-Zone ]
+ [ Framed-Compression ]
+ [ Framed-Interface-Id ]
+ [ Framed-IP-Address ]
+ [ Framed-IP-Netmask ]
+ * [ Framed-IPv6-Prefix ]
+ [ Framed-IPv6-Pool ]
+ * [ Framed-IPv6-Route ]
+ [ Framed-IPX-Network ]
+ [ Framed-MTU ]
+ [ Framed-Pool ]
+ [ Framed-Protocol ]
+ * [ Framed-Route ]
+ [ Framed-Routing ]
+ * [ Login-IP-Host ]
+ * [ Login-IPv6-Host ]
+ [ Login-LAT-Group ]
+ [ Login-LAT-Node ]
+ [ Login-LAT-Port ]
+ [ Login-LAT-Service ]
+ [ Login-Service ]
+ [ Login-TCP-Port ]
+ * [ Tunneling ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ ACA ::= < Diameter Header: 271, PXY >
+
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ { Accounting-Record-Type }
+ { Accounting-Record-Number }
+ [ Acct-Application-Id ]
+ [ Vendor-Specific-Application-Id ]
+ [ User-Name ]
+ [ Accounting-Sub-Session-Id ]
+ [ Acct-Session-Id ]
+ [ Acct-Multi-Session-Id ]
+ [ Event-Timestamp ]
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+ * [ Failed-AVP ]
+ [ Origin-AAA-Protocol ]
+ [ Origin-State-Id ]
+ [ NAS-Identifier ]
+ [ NAS-IP-Address ]
+ [ NAS-IPv6-Address ]
+ [ NAS-Port ]
+ [ NAS-Port-Id ]
+ [ NAS-Port-Type ]
+ [ Service-Type ]
+ [ Termination-Cause ]
+ [ Accounting-Realtime-Required ]
+ [ Acct-Interim-Interval ]
+ * [ Class ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+;; ===========================================================================
+
+@grouped
+
+ CHAP-Auth ::= < AVP Header: 402 >
+
+ { CHAP-Algorithm }
+ { CHAP-Ident }
+ [ CHAP-Response ]
+ * [ AVP ]
+
+ Tunneling ::= < AVP Header: 401 >
+
+ { Tunnel-Type }
+ { Tunnel-Medium-Type }
+ { Tunnel-Client-Endpoint }
+ { Tunnel-Server-Endpoint }
+ [ Tunnel-Preference ]
+ [ Tunnel-Client-Auth-Id ]
+ [ Tunnel-Server-Auth-Id ]
+ [ Tunnel-Assignment-Id ]
+ [ Tunnel-Password ]
+ [ Tunnel-Private-Group-Id ]
+
+;; ===========================================================================
+
+@enum NAS-Port-Type
+
+ ASYNC 0
+ SYNC 1
+ ISDN_SYNC 2
+ ISDN_ASYNC_V120 3
+ ISDN_ASYNC_V110 4
+ VIRTUAL 5
+ PIAFS 6
+ HDLC_CLEAR_CHANNEL 7
+ X25 8
+ X75 9
+ G3FAX 10
+ SDSL 11
+ ADSL-CAP 12
+ ADSL-DMT 13
+ IDSL 14
+ ETHERNET 15
+ XDSL 16
+ CABLE 17
+ WIRELESS_OTHER 18
+ 'WIRELESS_802.11' 19
+ TOKEN-RING 20
+ FDDI 21
+ WIRELESS_CDMA2000 22
+ WIRELESS_UMTS 23
+ WIRELESS_1X-EV 24
+ IAPP 25
+
+@enum Prompt
+
+ NO_ECHO 0
+ ECHO 1
+
+@enum CHAP-Algorithm
+
+ WITH_MD5 5
+
+@enum Service-Type
+
+ LOGIN 1
+ FRAMED 2
+ CALLBACK_LOGIN 3
+ CALLBACK_FRAMED 4
+ OUTBOUND 5
+ ADMINISTRATIVE 6
+ NAS_PROMPT 7
+ AUTHENTICATE_ONLY 8
+ CALLBACK_NAS_PROMPT 9
+ CALL_CHECK 10
+ CALLBACK_ADMINISTRATIVE 11
+ VOICE 12
+ FAX 13
+ MODEM_RELAY 14
+ IAPP-REGISTER 15
+ IAPP-AP-CHECK 16
+ AUTHORIZE_ONLY 17
+
+@enum Framed-Protocol
+
+ PPP 1
+ SLIP 2
+ ARAP 3
+ GANDALF 4
+ XYLOGICS 5
+ X75 6
+
+@enum Framed-Routing
+
+ NONE 0
+ SEND 1
+ LISTEN 2
+ SEND_AND_LISTEN 3
+
+@enum Framed-Compression
+
+ NONE 0
+ VJ 1
+ IPX 2
+ STAC-LZS 3
+
+@enum ARAP-Zone-Access
+
+ DEFAULT 1
+ FILTER_INCLUSIVELY 2
+ FILTER_EXCLUSIVELY 4
+
+@enum Login-Service
+
+ TELNET 0
+ RLOGIN 1
+ TCP_CLEAR 2
+ PORTMASTER 3
+ LAT 4
+ X25-PAD 5
+ X25-T3POS 6
+ TCP_CLEAR_QUIET 8
+
+@enum Tunnel-Type
+
+ PPTP 1
+ L2F 2
+ L2TP 3
+ ATMP 4
+ VTP 5
+ AH 6
+ IP-IP 7
+ MIN-IP-IP 8
+ ESP 9
+ GRE 10
+ DVS 11
+ IP-IN-IP 12
+ VLAN 13
+
+@enum Tunnel-Medium-Type
+
+ IPV4 1
+ IPV6 2
+ NSAP 3
+ HDLC 4
+ BBN_1822 5
+ '802' 6
+ E163 7
+ E164 8
+ F69 9
+ X121 10
+ IPX 11
+ APPLETALK 12
+ DECNET_IV 13
+ BANYAN_VINES 14
+ E164_NSAP 15
+
+
+@enum Acct-Authentic
+
+ RADIUS 1
+ LOCAL 2
+ REMOTE 3
+ DIAMETER 4
+
+@enum Accounting-Auth-Method
+
+ PAP 1
+ CHAP 2
+ MS-CHAP-1 3
+ MS-CHAP-2 4
+ EAP 5
+ NONE 7
+
+@enum Termination-Cause
+
+ USER_REQUEST 11
+ LOST_CARRIER 12
+ LOST_SERVICE 13
+ IDLE_TIMEOUT 14
+ SESSION_TIMEOUT 15
+ ADMIN_RESET 16
+ ADMIN_REBOOT 17
+ PORT_ERROR 18
+ NAS_ERROR 19
+ NAS_REQUEST 20
+ NAS_REBOOT 21
+ PORT_UNNEEDED 22
+ PORT_PREEMPTED 23
+ PORT_SUSPENDED 24
+ SERVICE_UNAVAILABLE 25
+ CALLBACK 26
+ USER_ERROR 27
+ HOST_REQUEST 28
+ SUPPLICANT_RESTART 29
+ REAUTHORIZATION_FAILURE 30
+ PORT_REINIT 31
+ PORT_DISABLED 32
diff --git a/lib/diameter/examples/dict/rfc4006_cc.dia b/lib/diameter/examples/dict/rfc4006_cc.dia
new file mode 100644
index 0000000000..b723e4ddbb
--- /dev/null
+++ b/lib/diameter/examples/dict/rfc4006_cc.dia
@@ -0,0 +1,349 @@
+;;
+;; %CopyrightBegin%
+;;
+;; Copyright Ericsson AB 2010-2011. 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%
+;;
+
+;;
+;; RFC 4006, Diameter Credit-Control Application
+;;
+
+@id 4
+
+@inherits rfc3588_base
+@inherits rfc4005_nas Filter-Id
+
+;; ===========================================================================
+
+@avp_types
+
+ CC-Correlation-Id 411 OctetString -
+ CC-Input-Octets 412 Unsigned64 M
+ CC-Money 413 Grouped M
+ CC-Output-Octets 414 Unsigned64 M
+ CC-Request-Number 415 Unsigned32 M
+ CC-Request-Type 416 Enumerated M
+ CC-Service-Specific-Units 417 Unsigned64 M
+ CC-Session-Failover 418 Enumerated M
+ CC-Sub-Session-Id 419 Unsigned64 M
+ CC-Time 420 Unsigned32 M
+ CC-Total-Octets 421 Unsigned64 M
+ CC-Unit-Type 454 Enumerated M
+ Check-Balance-Result 422 Enumerated M
+ Cost-Information 423 Grouped M
+ Cost-Unit 424 UTF8String M
+ Credit-Control 426 Enumerated M
+ Credit-Control-Failure-Handling 427 Enumerated M
+ Currency-Code 425 Unsigned32 M
+ Direct-Debiting-Failure-Handling 428 Enumerated M
+ Exponent 429 Integer32 M
+ Final-Unit-Action 449 Enumerated M
+ Final-Unit-Indication 430 Grouped M
+ Granted-Service-Unit 431 Grouped M
+ G-S-U-Pool-Identifier 453 Unsigned32 M
+ G-S-U-Pool-Reference 457 Grouped M
+ Multiple-Services-Credit-Control 456 Grouped M
+ Multiple-Services-Indicator 455 Enumerated M
+ Rating-Group 432 Unsigned32 M
+ Redirect-Address-Type 433 Enumerated M
+ Redirect-Server 434 Grouped M
+ Redirect-Server-Address 435 UTF8String M
+ Requested-Action 436 Enumerated M
+ Requested-Service-Unit 437 Grouped M
+ Restriction-Filter-Rule 438 IPFilterRule M
+ Service-Context-Id 461 UTF8String M
+ Service-Identifier 439 Unsigned32 M
+ Service-Parameter-Info 440 Grouped -
+ Service-Parameter-Type 441 Unsigned32 -
+ Service-Parameter-Value 442 OctetString -
+ Subscription-Id 443 Grouped M
+ Subscription-Id-Data 444 UTF8String M
+ Subscription-Id-Type 450 Enumerated M
+ Tariff-Change-Usage 452 Enumerated M
+ Tariff-Time-Change 451 Time M
+ Unit-Value 445 Grouped M
+ Used-Service-Unit 446 Grouped M
+ User-Equipment-Info 458 Grouped -
+ User-Equipment-Info-Type 459 Enumerated -
+ User-Equipment-Info-Value 460 OctetString -
+ Value-Digits 447 Integer64 M
+ Validity-Time 448 Unsigned32 M
+
+;; ===========================================================================
+
+@messages
+
+ CCR ::= < Diameter Header: 272, REQ, PXY >
+
+ < Session-Id >
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Auth-Application-Id }
+ { Service-Context-Id }
+ { CC-Request-Type }
+ { CC-Request-Number }
+ [ Destination-Host ]
+ [ User-Name ]
+ [ CC-Sub-Session-Id ]
+ [ Acct-Multi-Session-Id ]
+ [ Origin-State-Id ]
+ [ Event-Timestamp ]
+ * [ Subscription-Id ]
+ [ Service-Identifier ]
+ [ Termination-Cause ]
+ [ Requested-Service-Unit ]
+ [ Requested-Action ]
+ * [ Used-Service-Unit ]
+ [ Multiple-Services-Indicator ]
+ * [ Multiple-Services-Credit-Control ]
+ * [ Service-Parameter-Info ]
+ [ CC-Correlation-Id ]
+ [ User-Equipment-Info ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ CCA ::= < Diameter Header: 272, PXY >
+
+ < Session-Id >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ { Auth-Application-Id }
+ { CC-Request-Type }
+ { CC-Request-Number }
+ [ User-Name ]
+ [ CC-Session-Failover ]
+ [ CC-Sub-Session-Id ]
+ [ Acct-Multi-Session-Id ]
+ [ Origin-State-Id ]
+ [ Event-Timestamp ]
+ [ Granted-Service-Unit ]
+ * [ Multiple-Services-Credit-Control ]
+ [ Cost-Information]
+ [ Final-Unit-Indication ]
+ [ Check-Balance-Result ]
+ [ Credit-Control-Failure-Handling ]
+ [ Direct-Debiting-Failure-Handling ]
+ [ Validity-Time]
+ * [ Redirect-Host]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ Failed-AVP ]
+ * [ AVP ]
+
+;; ===========================================================================
+
+@grouped
+
+ Cost-Information ::= < AVP Header: 423 >
+
+ { Unit-Value }
+ { Currency-Code }
+ [ Cost-Unit ]
+
+ Unit-Value ::= < AVP Header: 445 >
+
+ { Value-Digits }
+ [ Exponent ]
+
+ Multiple-Services-Credit-Control ::= < AVP Header: 456 >
+
+ [ Granted-Service-Unit ]
+ [ Requested-Service-Unit ]
+ * [ Used-Service-Unit ]
+ [ Tariff-Change-Usage ]
+ * [ Service-Identifier ]
+ [ Rating-Group ]
+ * [ G-S-U-Pool-Reference ]
+ [ Validity-Time ]
+ [ Result-Code ]
+ [ Final-Unit-Indication ]
+ * [ AVP ]
+
+ Granted-Service-Unit ::= < AVP Header: 431 >
+
+ [ Tariff-Time-Change ]
+ [ CC-Time ]
+ [ CC-Money ]
+ [ CC-Total-Octets ]
+ [ CC-Input-Octets ]
+ [ CC-Output-Octets ]
+ [ CC-Service-Specific-Units ]
+ * [ AVP ]
+
+ Requested-Service-Unit ::= < AVP Header: 437 >
+
+ [ CC-Time ]
+ [ CC-Money ]
+ [ CC-Total-Octets ]
+ [ CC-Input-Octets ]
+ [ CC-Output-Octets ]
+ [ CC-Service-Specific-Units ]
+ * [ AVP ]
+
+ Used-Service-Unit ::= < AVP Header: 446 >
+
+ [ Tariff-Change-Usage ]
+ [ CC-Time ]
+ [ CC-Money ]
+ [ CC-Total-Octets ]
+ [ CC-Input-Octets ]
+ [ CC-Output-Octets ]
+ [ CC-Service-Specific-Units ]
+ * [ AVP ]
+
+ CC-Money ::= < AVP Header: 413 >
+
+ { Unit-Value }
+ [ Currency-Code ]
+
+ G-S-U-Pool-Reference ::= < AVP Header: 457 >
+
+ { G-S-U-Pool-Identifier }
+ { CC-Unit-Type }
+ { Unit-Value }
+
+ Final-Unit-Indication ::= < AVP Header: 430 >
+
+ { Final-Unit-Action }
+ * [ Restriction-Filter-Rule ]
+ * [ Filter-Id ]
+ [ Redirect-Server ]
+
+ Redirect-Server ::= < AVP Header: 434 >
+
+ { Redirect-Address-Type }
+ { Redirect-Server-Address }
+
+ Service-Parameter-Info ::= < AVP Header: 440 >
+
+ { Service-Parameter-Type }
+ { Service-Parameter-Value }
+
+ Subscription-Id ::= < AVP Header: 443 >
+
+ { Subscription-Id-Type }
+ { Subscription-Id-Data }
+
+ User-Equipment-Info ::= < AVP Header: 458 >
+
+ { User-Equipment-Info-Type }
+ { User-Equipment-Info-Value }
+
+;; ===========================================================================
+
+@enum CC-Request-Type
+
+ INITIAL_REQUEST 1
+ UPDATE_REQUEST 2
+ TERMINATION_REQUEST 3
+ EVENT_REQUEST 4
+
+@enum CC-Session-Failover
+
+ NOT_SUPPORTED 0
+ SUPPORTED 1
+
+@enum Check-Balance-Result
+
+ ENOUGH_CREDIT 0
+ NO_CREDIT 1
+
+@enum Credit-Control
+
+ AUTHORIZATION 0
+ RE_AUTHORIZATION 1
+
+@enum Credit-Control-Failure-Handling
+
+ TERMINATE 0
+ CONTINUE 1
+ RETRY_AND_TERMINATE 2
+
+@enum Direct-Debiting-Failure-Handling
+
+ TERMINATE_OR_BUFFER 0
+ CONTINUE 1
+
+@enum Tariff-Change-Usage
+
+ UNIT_BEFORE_TARIFF_CHANGE 0
+ UNIT_AFTER_TARIFF_CHANGE 1
+ UNIT_INDETERMINATE 2
+
+@enum CC-Unit-Type
+
+ TIME 0
+ MONEY 1
+ TOTAL-OCTETS 2
+ INPUT-OCTETS 3
+ OUTPUT-OCTETS 4
+ SERVICE-SPECIFIC-UNITS 5
+
+@enum Final-Unit-Action
+
+ TERMINATE 0
+ REDIRECT 1
+ RESTRICT_ACCESS 2
+
+@enum Redirect-Address-Type
+
+ IPV4 0
+ IPV6 1
+ URL 2
+ SIP_URI 3
+
+@enum Multiple-Services-Indicator
+
+ NOT_SUPPORTED 0
+ SUPPORTED 1
+
+@enum Requested-Action
+
+ DIRECT_DEBITING 0
+ REFUND_ACCOUNT 1
+ CHECK_BALANCE 2
+ PRICE_ENQUIRY 3
+
+@enum Subscription-Id-Type
+
+ END_USER_E164 0
+ END_USER_IMSI 1
+ END_USER_SIP_URI 2
+ END_USER_NAI 3
+ END_USER_PRIVATE 4
+
+@enum User-Equipment-Info-Type
+
+ IMEISV 0
+ MAC 1
+ EUI64 2
+ MODIFIED_EUI64 3
+
+;; ===========================================================================
+
+@define Result-Code
+
+ END_USER_SERVICE_DENIED 4010
+ CREDIT_CONTROL_NOT_APPLICABLE 4011
+ CREDIT_LIMIT_REACHED 4012
+
+ USER_UNKNOWN 5030
+ RATING_FAILED 5031
diff --git a/lib/diameter/examples/dict/rfc4072_eap.dia b/lib/diameter/examples/dict/rfc4072_eap.dia
new file mode 100644
index 0000000000..111516b347
--- /dev/null
+++ b/lib/diameter/examples/dict/rfc4072_eap.dia
@@ -0,0 +1,150 @@
+;;
+;; %CopyrightBegin%
+;;
+;; Copyright Ericsson AB 2010-2011. 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%
+;;
+
+;;
+;; RFC 4072, Diameter Extensible Authentication Protocol (EAP) Application
+;;
+;; Edits:
+;;
+;; - Move EAP-Payload to not break fixed/required/optional order
+;; - Framed-Appletalk-Link -> Framed-AppleTalk-Link
+;; - Framed-Appletalk-Network -> Framed-AppleTalk-Network
+;; - Framed-Appletalk-Zone -> Framed-AppleTalk-Zone
+;;
+
+@id 5
+
+@inherits rfc3588_base
+@inherits rfc4005_nas
+
+;; ===========================================================================
+
+@avp_types
+
+ EAP-Master-Session-Key 464 OctetString -
+ EAP-Key-Name 102 OctetString -
+ EAP-Payload 462 OctetString -
+ EAP-Reissued-Payload 463 OctetString -
+ Accounting-EAP-Auth-Method 465 Unsigned64 -
+
+;; ===========================================================================
+
+@messages
+
+ DER ::= < Diameter Header: 268, REQ, PXY >
+
+ < Session-Id >
+ { Auth-Application-Id }
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Auth-Request-Type }
+ { EAP-Payload }
+ [ Destination-Host ]
+ [ NAS-Identifier ]
+ [ NAS-IP-Address ]
+ [ NAS-IPv6-Address ]
+ [ NAS-Port ]
+ [ NAS-Port-Id ]
+ [ NAS-Port-Type ]
+ [ Origin-State-Id ]
+ [ Port-Limit ]
+ [ User-Name ]
+ [ EAP-Key-Name ]
+ [ Service-Type ]
+ [ State ]
+ [ Authorization-Lifetime ]
+ [ Auth-Grace-Period ]
+ [ Auth-Session-State ]
+ [ Callback-Number ]
+ [ Called-Station-Id ]
+ [ Calling-Station-Id ]
+ [ Originating-Line-Info ]
+ [ Connect-Info ]
+ * [ Framed-Compression ]
+ [ Framed-Interface-Id ]
+ [ Framed-IP-Address ]
+ * [ Framed-IPv6-Prefix ]
+ [ Framed-IP-Netmask ]
+ [ Framed-MTU ]
+ [ Framed-Protocol ]
+ * [ Tunneling ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ DEA ::= < Diameter Header: 268, PXY >
+
+ < Session-Id >
+ { Auth-Application-Id }
+ { Auth-Request-Type }
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ User-Name ]
+ [ EAP-Payload ]
+ [ EAP-Reissued-Payload ]
+ [ EAP-Master-Session-Key ]
+ [ EAP-Key-Name ]
+ [ Multi-Round-Time-Out ]
+ [ Accounting-EAP-Auth-Method ]
+ [ Service-Type ]
+ * [ Class ]
+ * [ Configuration-Token ]
+ [ Acct-Interim-Interval ]
+ [ Error-Message ]
+ [ Error-Reporting-Host ]
+ * [ Failed-AVP ]
+ [ Idle-Timeout ]
+ [ Authorization-Lifetime ]
+ [ Auth-Grace-Period ]
+ [ Auth-Session-State ]
+ [ Re-Auth-Request-Type ]
+ [ Session-Timeout ]
+ [ State ]
+ * [ Reply-Message ]
+ [ Origin-State-Id ]
+ * [ Filter-Id ]
+ [ Port-Limit ]
+ [ Callback-Id ]
+ [ Callback-Number ]
+ [ Framed-AppleTalk-Link ]
+ * [ Framed-AppleTalk-Network ]
+ [ Framed-AppleTalk-Zone ]
+ * [ Framed-Compression ]
+ [ Framed-Interface-Id ]
+ [ Framed-IP-Address ]
+ * [ Framed-IPv6-Prefix ]
+ [ Framed-IPv6-Pool ]
+ * [ Framed-IPv6-Route ]
+ [ Framed-IP-Netmask ]
+ * [ Framed-Route ]
+ [ Framed-Pool ]
+ [ Framed-IPX-Network ]
+ [ Framed-MTU ]
+ [ Framed-Protocol ]
+ [ Framed-Routing ]
+ * [ NAS-Filter-Rule ]
+ * [ QoS-Filter-Rule ]
+ * [ Tunneling ]
+ * [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ AVP ]
diff --git a/lib/diameter/examples/dict/rfc4590_digest.dia b/lib/diameter/examples/dict/rfc4590_digest.dia
new file mode 100644
index 0000000000..a4ebe0c456
--- /dev/null
+++ b/lib/diameter/examples/dict/rfc4590_digest.dia
@@ -0,0 +1,45 @@
+;;
+;; %CopyrightBegin%
+;;
+;; Copyright Ericsson AB 2010-2011. 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%
+;;
+
+;;
+;; RFC 4590, RADIUS Extension for Digest Authentication
+;;
+
+@avp_types
+
+ Digest-Response 103 OctetString -
+ Digest-Realm 104 OctetString -
+ Digest-Nonce 105 OctetString -
+ Digest-Response-Auth 106 OctetString -
+ Digest-Nextnonce 107 OctetString -
+ Digest-Method 108 OctetString -
+ Digest-URI 109 OctetString -
+ Digest-Qop 110 OctetString -
+ Digest-Algorithm 111 OctetString -
+ Digest-Entity-Body-Hash 112 OctetString -
+ Digest-CNonce 113 OctetString -
+ Digest-Nonce-Count 114 OctetString -
+ Digest-Username 115 OctetString -
+ Digest-Opaque 116 OctetString -
+ Digest-Auth-Param 117 OctetString -
+ Digest-AKA-Auts 118 OctetString -
+ Digest-Domain 119 OctetString -
+ Digest-Stale 120 OctetString -
+ Digest-HA1 121 OctetString -
+ SIP-AOR 122 OctetString -
diff --git a/lib/diameter/examples/dict/rfc4740_sip.dia b/lib/diameter/examples/dict/rfc4740_sip.dia
new file mode 100644
index 0000000000..8c21882649
--- /dev/null
+++ b/lib/diameter/examples/dict/rfc4740_sip.dia
@@ -0,0 +1,446 @@
+;;
+;; %CopyrightBegin%
+;;
+;; Copyright Ericsson AB 2010-2011. 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%
+;;
+
+;;
+;; RFC 4740, Diameter Session Initiation Protocol (SIP) Application
+;;
+
+@id 6
+
+@inherits rfc3588_base
+@inherits rfc4590_digest
+
+;; ===========================================================================
+
+@avp_types
+
+ SIP-Accounting-Information 368 Grouped M
+ SIP-Accounting-Server-URI 369 DiameterURI M
+ SIP-Credit-Control-Server-URI 370 DiameterURI M
+ SIP-Server-URI 371 UTF8String M
+ SIP-Server-Capabilities 372 Grouped M
+ SIP-Mandatory-Capability 373 Unsigned32 M
+ SIP-Optional-Capability 374 Unsigned32 M
+ SIP-Server-Assignment-Type 375 Enumerated M
+ SIP-Auth-Data-Item 376 Grouped M
+ SIP-Authentication-Scheme 377 Enumerated M
+ SIP-Item-Number 378 Unsigned32 M
+ SIP-Authenticate 379 Grouped M
+ SIP-Authorization 380 Grouped M
+ SIP-Authentication-Info 381 Grouped M
+ SIP-Number-Auth-Items 382 Unsigned32 M
+ SIP-Deregistration-Reason 383 Grouped M
+ SIP-Reason-Code 384 Enumerated M
+ SIP-Reason-Info 385 UTF8String M
+ SIP-Visited-Network-Id 386 UTF8String M
+ SIP-User-Authorization-Type 387 Enumerated M
+ SIP-Supported-User-Data-Type 388 UTF8String M
+ SIP-User-Data 389 Grouped M
+ SIP-User-Data-Type 390 UTF8String M
+ SIP-User-Data-Contents 391 OctetString M
+ SIP-User-Data-Already-Available 392 Enumerated M
+ SIP-Method 393 UTF8String M
+
+;; ===========================================================================
+
+@messages
+
+ ;; 8.1. User-Authorization-Request
+
+ UAR ::= < Diameter Header: 283, REQ, PXY >
+
+ < Session-Id >
+ { Auth-Application-Id }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { SIP-AOR }
+ [ Destination-Host ]
+ [ User-Name ]
+ [ SIP-Visited-Network-Id ]
+ [ SIP-User-Authorization-Type ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ ;; 8.2. User-Authorization-Answer
+
+ UAA ::= < Diameter Header: 283, PXY >
+
+ < Session-Id >
+ { Auth-Application-Id }
+ { Auth-Session-State }
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ [ SIP-Server-URI ]
+ [ SIP-Server-Capabilities ]
+ [ Authorization-Lifetime ]
+ [ Auth-Grace-Period ]
+ [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ ;; 8.3. Server-Assignment-Request
+
+ SAR ::= < Diameter Header: 284, REQ, PXY >
+
+ < Session-Id >
+ { Auth-Application-Id }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { SIP-Server-Assignment-Type }
+ { SIP-User-Data-Already-Available }
+ [ Destination-Host ]
+ [ User-Name ]
+ [ SIP-Server-URI ]
+ * [ SIP-Supported-User-Data-Type ]
+ * [ SIP-AOR ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ ;; 8.4. Server-Assignment-Answer
+
+ SAA ::= < Diameter Header: 284, PXY >
+
+ < Session-Id >
+ { Auth-Application-Id }
+ { Result-Code }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ * [ SIP-User-Data ]
+ [ SIP-Accounting-Information ]
+ * [ SIP-Supported-User-Data-Type ]
+ [ User-Name ]
+ [ Auth-Grace-Period ]
+ [ Authorization-Lifetime ]
+ [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ ;; 8.5. Location-Info-Request
+
+ LIR ::= < Diameter Header: 285, REQ, PXY >
+
+ < Session-Id >
+ { Auth-Application-Id }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { SIP-AOR }
+ [ Destination-Host ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ ;; 8.6. Location-Info-Answer
+
+ LIA ::= < Diameter Header: 285, PXY >
+
+ < Session-Id >
+ { Auth-Application-Id }
+ { Result-Code }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ [ SIP-Server-URI ]
+ [ SIP-Server-Capabilities ]
+ [ Auth-Grace-Period ]
+ [ Authorization-Lifetime ]
+ [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ ;; 8.7. Multimedia-Auth-Request
+
+ MAR ::= < Diameter Header: 286, REQ, PXY >
+
+ < Session-Id >
+ { Auth-Application-Id }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { SIP-AOR }
+ { SIP-Method }
+ [ Destination-Host ]
+ [ User-Name ]
+ [ SIP-Server-URI ]
+ [ SIP-Number-Auth-Items ]
+ [ SIP-Auth-Data-Item ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ ;; 8.8. Multimedia-Auth-Answer
+
+ MAA ::= < Diameter Header: 286, PXY >
+
+ < Session-Id >
+ { Auth-Application-Id }
+ { Result-Code }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ [ User-Name ]
+ [ SIP-AOR ]
+ [ SIP-Number-Auth-Items ]
+ * [ SIP-Auth-Data-Item ]
+ [ Authorization-Lifetime ]
+ [ Auth-Grace-Period ]
+ [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ ;; 8.9. Registration-Termination-Request
+
+ RTR ::= < Diameter Header: 287, REQ, PXY >
+
+ < Session-Id >
+ { Auth-Application-Id }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Host }
+ { SIP-Deregistration-Reason }
+ [ Destination-Realm ]
+ [ User-Name ]
+ * [ SIP-AOR ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ ;; 8.10. Registration-Termination-Answer
+
+ RTA ::= < Diameter Header: 287, PXY >
+
+ < Session-Id >
+ { Auth-Application-Id }
+ { Result-Code }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ [ Authorization-Lifetime ]
+ [ Auth-Grace-Period ]
+ [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ ;; 8.11. Push-Profile-Request
+
+ PPR ::= < Diameter Header: 288, REQ, PXY >
+
+ < Session-Id >
+ { Auth-Application-Id }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { User-Name }
+ * [ SIP-User-Data ]
+ [ SIP-Accounting-Information ]
+ [ Destination-Host ]
+ [ Authorization-Lifetime ]
+ [ Auth-Grace-Period ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+ ;; 8.12. Push-Profile-Answer
+
+ PPA ::= < Diameter Header: 288, PXY >
+
+ < Session-Id >
+ { Auth-Application-Id }
+ { Result-Code }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ [ Redirect-Host ]
+ [ Redirect-Host-Usage ]
+ [ Redirect-Max-Cache-Time ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+ * [ AVP ]
+
+;; ===========================================================================
+
+@grouped
+
+ SIP-Accounting-Information ::= < AVP Header: 368 >
+
+ * [ SIP-Accounting-Server-URI ]
+ * [ SIP-Credit-Control-Server-URI ]
+ * [ AVP]
+
+ SIP-Server-Capabilities ::= < AVP Header: 372 >
+
+ * [ SIP-Mandatory-Capability ]
+ * [ SIP-Optional-Capability ]
+ * [ SIP-Server-URI ]
+ * [ AVP ]
+
+ SIP-Auth-Data-Item ::= < AVP Header: 376 >
+
+ { SIP-Authentication-Scheme }
+ [ SIP-Item-Number ]
+ [ SIP-Authenticate ]
+ [ SIP-Authorization ]
+ [ SIP-Authentication-Info ]
+ * [ AVP ]
+
+ SIP-Authenticate ::= < AVP Header: 379 >
+
+ { Digest-Realm }
+ { Digest-Nonce }
+ [ Digest-Domain ]
+ [ Digest-Opaque ]
+ [ Digest-Stale ]
+ [ Digest-Algorithm ]
+ [ Digest-Qop ]
+ [ Digest-HA1]
+ * [ Digest-Auth-Param ]
+ * [ AVP ]
+
+ SIP-Authorization ::= < AVP Header: 380 >
+
+ { Digest-Username }
+ { Digest-Realm }
+ { Digest-Nonce }
+ { Digest-URI }
+ { Digest-Response }
+ [ Digest-Algorithm ]
+ [ Digest-CNonce ]
+ [ Digest-Opaque ]
+ [ Digest-Qop ]
+ [ Digest-Nonce-Count ]
+ [ Digest-Method]
+ [ Digest-Entity-Body-Hash ]
+ * [ Digest-Auth-Param ]
+ * [ AVP ]
+
+ SIP-Authentication-Info ::= < AVP Header: 381 >
+
+ [ Digest-Nextnonce ]
+ [ Digest-Qop ]
+ [ Digest-Response-Auth ]
+ [ Digest-CNonce ]
+ [ Digest-Nonce-Count ]
+ * [ AVP ]
+
+ SIP-Deregistration-Reason ::= < AVP Header: 383 >
+
+ { SIP-Reason-Code }
+ [ SIP-Reason-Info ]
+ * [ AVP ]
+
+ SIP-User-Data ::= < AVP Header: 389 >
+
+ { SIP-User-Data-Type }
+ { SIP-User-Data-Contents }
+ * [ AVP ]
+
+;; ===========================================================================
+
+@enum SIP-Server-Assignment-Type
+
+ NO_ASSIGNMENT 0
+ REGISTRATION 1
+ RE_REGISTRATION 2
+ UNREGISTERED_USER 3
+ TIMEOUT_DEREGISTRATION 4
+ USER_DEREGISTRATION 5
+ TIMEOUT_DEREGISTRATION_STORE 6
+ USER_DEREGISTRATION_STORE 7
+ ADMINISTRATIVE_DEREGISTRATION 8
+ AUTHENTICATION_FAILURE 9
+ AUTHENTICATION_TIMEOUT 10
+ DEREGISTRATION_TOO_MUCH_DATA 11
+
+@enum SIP-Authentication-Scheme
+
+ DIGEST 0
+
+@enum SIP-Reason-Code
+
+ PERMANENT_TERMINATION 0
+ NEW_SIP_SERVER_ASSIGNED 1
+ SIP_SERVER_CHANGE 2
+ REMOVE_SIP_SERVER 3
+
+@enum SIP-User-Authorization-Type
+
+ REGISTRATION 0
+ DEREGISTRATION 1
+ REGISTRATION_AND_CAPABILITIES 2
+
+@enum SIP-User-Data-Already-Available
+
+ USER_DATA_NOT_AVAILABLE 0
+ USER_DATA_ALREADY_AVAILABLE 1
+
+;; ===========================================================================
+
+@define Result-Code
+
+ ;; Success
+
+ FIRST_REGISTRATION 2003
+ SUBSEQUENT_REGISTRATION 2004
+ UNREGISTERED_SERVICE 2005
+ SUCCESS_SERVER_NAME_NOT_STORED 2006
+ SERVER_SELECTION 2007
+ SUCCESS_AUTH_SENT_SERVER_NOT_STORED 2008
+
+ ;; Transient Failures
+
+ USER_NAME_REQUIRED 4013
+
+ ;; Permanent Failures
+
+ USER_UNKNOWN 5032
+ IDENTITIES_DONT_MATCH 5033
+ IDENTITY_NOT_REGISTERED 5034
+ ROAMING_NOT_ALLOWED 5035
+ IDENTITY_ALREADY_REGISTERED 5036
+ AUTH_SCHEME_NOT_SUPPORTED 5037
+ IN_ASSIGNMENT_TYPE 5038
+ TOO_MUCH_DATA 5039
+ NOT_SUPPORTED_USER_DATA 5040
diff --git a/lib/diameter/src/Makefile b/lib/diameter/src/Makefile
index 2ec016ecbc..dbfaa4e140 100644
--- a/lib/diameter/src/Makefile
+++ b/lib/diameter/src/Makefile
@@ -88,6 +88,9 @@ TARGET_FILES = \
# Subdirectories of src to release modules into.
TARGET_DIRS = $(sort $(dir $(TARGET_MODULES)))
+# Ditto for examples.
+EXAMPLE_DIRS = $(sort $(dir $(EXAMPLES)))
+
APP_FILE = diameter.app
APP_SRC = $(APP_FILE).src
APP_TARGET = $(EBIN)/$(APP_FILE)
@@ -169,6 +172,8 @@ info:
@echo
@$(call list,EXAMPLES)
@echo
+ @$(call list,EXAMPLE_DIRS)
+ @echo
@$(call list,BINS)
@echo ========================================
@@ -189,23 +194,29 @@ endif
# Can't $(INSTALL_DIR) more than one directory at a time on Solaris.
release_spec: opt
- for d in bin ebin examples include src/dict $(TARGET_DIRS:%/=src/%); do \
+ for d in bin ebin include src/dict; do \
$(INSTALL_DIR) $(RELSYSDIR)/$$d; \
done
$(INSTALL_SCRIPT) $(BINS:%=../bin/%) $(RELSYSDIR)/bin
$(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(EXAMPLES:%=../examples/%) $(RELSYSDIR)/examples
$(INSTALL_DATA) $(EXTERNAL_HRLS:%=../include/%) $(DICT_HRLS) \
$(RELSYSDIR)/include
$(INSTALL_DATA) $(DICTS:%=dict/%.dia) $(RELSYSDIR)/src/dict
$(MAKE) $(TARGET_DIRS:%/=release_src_%)
+ $(MAKE) $(EXAMPLE_DIRS:%/=release_examples_%)
$(TARGET_DIRS:%/=release_src_%): release_src_%:
+ $(INSTALL_DIR) $(RELSYSDIR)/src/$*
$(INSTALL_DATA) $(filter $*/%, $(TARGET_MODULES:%=%.erl) \
$(INTERNAL_HRLS)) \
$(filter $*/%, compiler/$(DICT_YRL).yrl) \
$(RELSYSDIR)/src/$*
+$(EXAMPLE_DIRS:%/=release_examples_%): release_examples_%:
+ $(INSTALL_DIR) $(RELSYSDIR)/examples/$*
+ $(INSTALL_DATA) $(patsubst %, ../examples/%, $(filter $*/%, $(EXAMPLES))) \
+ $(RELSYSDIR)/examples/$*
+
release_docs_spec:
# ----------------------------------------------------
@@ -237,6 +248,7 @@ depend.mk: depend.sed $(MODULES:%=%.erl) Makefile
.PHONY: app clean depend dict info release_subdir
.PHONY: debug opt release_docs_spec release_spec
.PHONY: $(TARGET_DIRS:%/=%) $(TARGET_DIRS:%/=release_src_%)
+.PHONY: $(EXAMPLE_DIRS:%/=release_examples_%)
# Keep intermediate files.
.SECONDARY: $(DICT_ERLS) $(DICT_HRLS) gen/$(DICT_YRL:%=%.erl)
diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl
index 0893956f97..3dfdcee2b2 100644
--- a/lib/diameter/src/base/diameter_service.erl
+++ b/lib/diameter/src/base/diameter_service.erl
@@ -629,10 +629,6 @@ insert(Tbl, Rec) ->
ets:insert(Tbl, Rec),
Rec.
-monitor(Pid) ->
- erlang:monitor(process, Pid),
- Pid.
-
%% Using the process dictionary for the callback state was initially
%% just a way to make what was horrendous trace (big state record and
%% much else everywhere) somewhat more readable. There's not as much
@@ -814,10 +810,10 @@ start(Ref, Type, Opts, #state{peerT = PeerT,
service = Svc})
when Type == connect;
Type == accept ->
- Pid = monitor(s(Type, Ref, {ConnT,
- Opts,
- SvcName,
- merge_service(Opts, Svc)})),
+ Pid = s(Type, Ref, {ConnT,
+ Opts,
+ SvcName,
+ merge_service(Opts, Svc)}),
insert(PeerT, #peer{pid = Pid,
type = Type,
ref = Ref,
@@ -830,7 +826,13 @@ start(Ref, Type, Opts, #state{peerT = PeerT,
%% callbacks.
s(Type, Ref, T) ->
- diameter_watchdog:start({Type, Ref}, T).
+ case diameter_watchdog:start({Type, Ref}, T) of
+ {_MRef, Pid} ->
+ Pid;
+ Pid when is_pid(Pid) -> %% from old code
+ erlang:monitor(process, Pid),
+ Pid
+ end.
%% merge_service/2
diff --git a/lib/diameter/src/base/diameter_watchdog.erl b/lib/diameter/src/base/diameter_watchdog.erl
index 6dc53d9f31..fb22fd8275 100644
--- a/lib/diameter/src/base/diameter_watchdog.erl
+++ b/lib/diameter/src/base/diameter_watchdog.erl
@@ -59,10 +59,19 @@
message_data}). %% term passed into diameter_service with message
%% start/2
+%%
+%% Start a monitor before the watchdog is allowed to proceed to ensure
+%% that a failed capabilities exchange produces the desired exit
+%% reason.
start({_,_} = Type, T) ->
- {ok, Pid} = diameter_watchdog_sup:start_child({Type, self(), T}),
- Pid.
+ Ref = make_ref(),
+ {ok, Pid} = diameter_watchdog_sup:start_child({Ref, {Type, self(), T}}),
+ try
+ {erlang:monitor(process, Pid), Pid}
+ after
+ Pid ! Ref
+ end.
start_link(T) ->
{ok, _} = proc_lib:start_link(?MODULE,
@@ -80,14 +89,29 @@ init(T) ->
proc_lib:init_ack({ok, self()}),
gen_server:enter_loop(?MODULE, [], i(T)).
-i({T, Pid, {ConnT, Opts, SvcName, #diameter_service{applications = Apps,
- capabilities = Caps}
- = Svc}}) ->
- {M,S,U} = now(),
- random:seed(M,S,U),
+i({Ref, {_, Pid, _} = T}) ->
+ MRef = erlang:monitor(process, Pid),
+ receive
+ Ref ->
+ make_state(T);
+ {'DOWN', MRef, process, _, _} = D ->
+ exit({shutdown, D})
+ end;
+
+i({_, Pid, _} = T) -> %% from old code
+ erlang:monitor(process, Pid),
+ make_state(T).
+
+make_state({T, Pid, {ConnT,
+ Opts,
+ SvcName,
+ #diameter_service{applications = Apps,
+ capabilities = Caps}
+ = Svc}}) ->
+ random:seed(now()),
putr(restart, {T, Opts, Svc}), %% save seeing it in trace
putr(dwr, dwr(Caps)), %%
- #watchdog{parent = monitor(Pid),
+ #watchdog{parent = Pid,
transport = monitor(diameter_peer_fsm:start(T, Opts, Svc)),
tw = proplists:get_value(watchdog_timer,
Opts,
diff --git a/lib/diameter/src/compiler/diameter_dict_util.erl b/lib/diameter/src/compiler/diameter_dict_util.erl
index e4cd29ab7f..36a6efa294 100644
--- a/lib/diameter/src/compiler/diameter_dict_util.erl
+++ b/lib/diameter/src/compiler/diameter_dict_util.erl
@@ -630,13 +630,28 @@ reset(K, Dict, Opts) ->
opt({inherits = Key, "-"}, Dict) ->
dict:erase(Key, Dict);
+
opt({inherits = Key, Mod}, Dict) ->
- dict:append(Key, [0, {word, 0, Mod}], Dict);
+ case lists:splitwith(fun(C) -> C /= $/ end, Mod) of
+ {Mod, ""} ->
+ dict:append(Key, [0, {word, 0, Mod}], Dict);
+ {From, [$/|To]} ->
+ dict:store(Key,
+ [reinherit(From, To, M) || M <- find(Key, Dict)],
+ Dict)
+ end;
+
opt({Key, Val}, Dict) ->
- dict:store(Key, [0, {word, 0, Val}], Dict);
+ dict:store(Key, [[0, {word, 0, Val}]], Dict);
+
opt(_, Dict) ->
Dict.
+reinherit(From, To, [L, {word, _, From} = T | Avps]) ->
+ [L, setelement(3, T, To) | Avps];
+reinherit(_, _, T) ->
+ T.
+
%% ===========================================================================
%% pass1/1
%%
diff --git a/lib/diameter/src/modules.mk b/lib/diameter/src/modules.mk
index 11d354e57e..7a700a6d53 100644
--- a/lib/diameter/src/modules.mk
+++ b/lib/diameter/src/modules.mk
@@ -88,11 +88,17 @@ BINS = \
# Released files relative to ../examples.
EXAMPLES = \
- GNUmakefile \
- peer.erl \
- client.erl \
- client_cb.erl \
- server.erl \
- server_cb.erl \
- relay.erl \
- relay_cb.erl
+ code/GNUmakefile \
+ code/peer.erl \
+ code/client.erl \
+ code/client_cb.erl \
+ code/server.erl \
+ code/server_cb.erl \
+ code/relay.erl \
+ code/relay_cb.erl \
+ dict/rfc4004_mip.dia \
+ dict/rfc4005_nas.dia \
+ dict/rfc4006_cc.dia \
+ dict/rfc4072_eap.dia \
+ dict/rfc4590_digest.dia \
+ dict/rfc4740_sip.dia
diff --git a/lib/diameter/test/Makefile b/lib/diameter/test/Makefile
index 97d9069f4a..ab5b45ff3d 100644
--- a/lib/diameter/test/Makefile
+++ b/lib/diameter/test/Makefile
@@ -50,6 +50,8 @@ TARGET_FILES = $(MODULES:%=%.$(EMULATOR))
SUITE_MODULES = $(filter diameter_%_SUITE, $(MODULES))
SUITES = $(SUITE_MODULES:diameter_%_SUITE=%)
+DATA_DIRS = $(sort $(dir $(DATA)))
+
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -121,12 +123,12 @@ help:
# diameter_ct:run/1 itself can't tell (it seems). The absolute -pa is
# because ct will change directories.
$(SUITES): log opt
- $(ERL) -noshell \
+ $(ERL) -noinput \
-pa $(realpath ../ebin) \
-sname diameter_test_$@ \
-s diameter_ct run diameter_$@_SUITE \
-s init stop \
- | awk '1{rc=0} {print} / FAILED /{rc=1} END{exit rc}'
+ | awk '{print} / FAILED /{rc=1} END{exit rc}' rc=0
# Shorter in sed but requires a GNU extension (ie. Q).
log:
@@ -147,9 +149,7 @@ else
include $(ERL_TOP)/make/otp_release_targets.mk
endif
-release_spec:
-
-release_docs_spec:
+release_spec release_docs_spec:
release_tests_spec:
$(INSTALL_DIR) $(RELSYSDIR)
@@ -157,12 +157,18 @@ release_tests_spec:
$(COVER_SPEC_FILE) \
$(HRL_FILES) \
$(RELSYSDIR)
+ $(MAKE) $(DATA_DIRS:%/=release_data_%)
$(MAKE) $(ERL_FILES:%=/%)
+$(DATA_DIRS:%/=release_data_%): release_data_%:
+ $(INSTALL_DIR) $(RELSYSDIR)/$*
+ $(INSTALL_DATA) $(filter $*/%, $(DATA)) $(RELSYSDIR)/$*
+
force:
.PHONY: release_spec release_docs_spec release_test_specs
.PHONY: force
+.PHONY: $(DATA_DIRS:%/=release_data_%)
# Can't just make $(ERL_FILES:%=/%) phony since then implicit rule
# searching is skipped.
diff --git a/lib/diameter/test/diameter_capx_SUITE.erl b/lib/diameter/test/diameter_capx_SUITE.erl
index e6b1558bf6..54a161d606 100644
--- a/lib/diameter/test/diameter_capx_SUITE.erl
+++ b/lib/diameter/test/diameter_capx_SUITE.erl
@@ -27,8 +27,6 @@
-export([suite/0,
all/0,
groups/0,
- init_per_group/2,
- end_per_group/2,
init_per_testcase/2,
end_per_testcase/2]).
@@ -93,30 +91,26 @@
-define(cea, #diameter_base_CEA).
-define(answer_message, #'diameter_base_answer-message').
+-define(fail(T), erlang:error({T, process_info(self(), messages)})).
+
+-define(TIMEOUT, 2000).
+
%% ===========================================================================
suite() ->
[{timetrap, {seconds, 10}}].
-all() ->
- [start, start_services, add_listeners
- | [{group, N} || {N, _, _} <- groups()]]
- ++ [remove_listeners, stop_services, stop].
+all() -> [start,
+ start_services,
+ add_listeners,
+ {group, all},
+ {group, all, [parallel]},
+ remove_listeners,
+ stop_services,
+ stop].
groups() ->
- Ts = testcases(),
- [{grp(P), P, Ts} || P <- [[], [parallel]]].
-
-grp([]) ->
- sequential;
-grp([parallel = P]) ->
- P.
-
-init_per_group(_Name, Config) ->
- Config.
-
-end_per_group(_, _) ->
- ok.
+ [{all, [], lists:flatmap(fun tc/1, tc())}].
%% Generate a unique hostname for each testcase so that watchdogs
%% don't prevent a connection from being brought up immediately.
@@ -137,9 +131,6 @@ end_per_testcase(Name, Config) ->
ok = diameter:remove_transport(?CLIENT, CRef).
%% Testcases all come in two flavours, client and server.
-testcases() ->
- lists:flatmap(fun tc/1, tc()).
-
tc(Name) ->
[?A([C,$_|?L(Name)]) || C <- "cs"].
@@ -270,8 +261,8 @@ s_client_reject(Config) ->
?packet{}}}
= Info ->
Info
- after 2000 ->
- fail({LRef, OH})
+ after ?TIMEOUT ->
+ ?fail({LRef, OH})
end.
c_client_reject(Config) ->
@@ -307,12 +298,12 @@ server_closed(Config, F, RC) ->
= Reason,
{listen, _}}} ->
Reason
- after 2000 ->
- fail({LRef, OH})
+ after ?TIMEOUT ->
+ ?fail({LRef, OH})
end.
%% server_reject/3
-
+
server_reject(Config, F, RC) ->
true = diameter:subscribe(?SERVER),
OH = host(Config),
@@ -328,8 +319,8 @@ server_reject(Config, F, RC) ->
= Reason,
{listen, _}}} ->
Reason
- after 2000 ->
- fail({LRef, OH})
+ after ?TIMEOUT ->
+ ?fail({LRef, OH})
end.
%% cliient_closed/4
@@ -345,13 +336,13 @@ client_closed(Config, Host, F, RC) ->
%% client_recv/1
-client_recv(CRef) ->
+client_recv(CRef) ->
receive
?event{service = ?CLIENT,
info = {closed, CRef, Reason, {connect, _}}} ->
Reason
- after 2000 ->
- fail(CRef)
+ after ?TIMEOUT ->
+ ?fail(CRef)
end.
%% server_capx/3
@@ -373,9 +364,6 @@ client_capx(_, ?caps{origin_host = {[_,$_|"client_reject." ++ _], _}}) ->
%% ===========================================================================
-fail(T) ->
- erlang:error({T, process_info(self(), messages)}).
-
host(Config) ->
{_, H} = lists:keyfind(host, 1, Config),
?HOST(H).
diff --git a/lib/diameter/test/diameter_codec_SUITE.erl b/lib/diameter/test/diameter_codec_SUITE.erl
index 30c60be8e9..2e219bbb10 100644
--- a/lib/diameter/test/diameter_codec_SUITE.erl
+++ b/lib/diameter/test/diameter_codec_SUITE.erl
@@ -35,7 +35,8 @@
%% testcases
-export([base/1,
gen/1,
- lib/1]).
+ lib/1,
+ unknown/1]).
-include("diameter_ct.hrl").
@@ -47,7 +48,7 @@ suite() ->
[{timetrap, {seconds, 10}}].
all() ->
- [base, gen, lib].
+ [base, gen, lib, unknown].
init_per_testcase(gen, Config) ->
[{application, ?APP, App}] = diameter_util:consult(?APP, app),
@@ -74,3 +75,26 @@ gen([{dicts, Ms} | _]) ->
lib(_Config) ->
diameter_codec_test:lib().
+
+%% Have a separate AVP dictionary just to exercise more code.
+unknown(Config) ->
+ Priv = proplists:get_value(priv_dir, Config),
+ Data = proplists:get_value(data_dir, Config),
+ ok = make(Data, "recv.dia"),
+ ok = make(Data, "avps.dia"),
+ {ok, _, _} = compile("diameter_test_avps.erl"),
+ ok = make(Data, "send.dia"),
+ {ok, _, _} = compile("diameter_test_send.erl"),
+ {ok, _, _} = compile("diameter_test_recv.erl"),
+ {ok, _, _} = compile(filename:join([Data, "diameter_test_unknown.erl"]),
+ [{i, Priv}]),
+ diameter_test_unknown:run().
+
+make(Dir, File) ->
+ diameter_make:codec(filename:join([Dir, File])).
+
+compile(File) ->
+ compile(File, []).
+
+compile(File, Opts) ->
+ compile:file(File, [return | Opts]).
diff --git a/lib/diameter/test/diameter_codec_SUITE_data/avps.dia b/lib/diameter/test/diameter_codec_SUITE_data/avps.dia
new file mode 100644
index 0000000000..c9d80a37a9
--- /dev/null
+++ b/lib/diameter/test/diameter_codec_SUITE_data/avps.dia
@@ -0,0 +1,25 @@
+;;
+;; %CopyrightBegin%
+;;
+;; Copyright Ericsson AB 2010-2011. 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%
+;;
+
+@name diameter_test_avps
+
+@avp_types
+
+ XXX 111 Unsigned32 M
+ YYY 222 Unsigned32 -
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
new file mode 100644
index 0000000000..bce3d78a37
--- /dev/null
+++ b/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl
@@ -0,0 +1,76 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(diameter_test_unknown).
+
+-compile(export_all).
+
+%%
+%% Test reception of unknown AVP's.
+%%
+
+-include_lib("diameter/include/diameter.hrl").
+-include("diameter_test_send.hrl").
+-include("diameter_test_recv.hrl").
+
+-define(HOST, "test.erlang.org").
+-define(REALM, "erlang.org").
+
+%% Patterns to match decoded AVP's.
+-define(MANDATORY_XXX, #diameter_avp{code = 111}).
+-define(NOT_MANDATORY_YYY, #diameter_avp{code = 222}).
+
+%% Ensure that an unknown AVP with an M flag is regarded as an error
+%% while one without an M flag is returned as 'AVP'.
+
+run() ->
+ H = #diameter_header{version = 1,
+ end_to_end_id = 1,
+ hop_by_hop_id = 1},
+ Vs = [{'Origin-Host', ?HOST},
+ {'Origin-Realm', ?REALM},
+ {'XXX', [0]},
+ {'YYY', [1]}],
+ Pkt = #diameter_packet{header = H,
+ msg = Vs},
+
+ [] = diameter_util:run([{?MODULE, [run, M, enc(M, Pkt)]}
+ || M <- ['AR','BR']]).
+
+enc(M, #diameter_packet{msg = Vs} = P) ->
+ diameter_codec:encode(diameter_test_send,
+ P#diameter_packet{msg = [M|Vs]}).
+
+run(M, Pkt) ->
+ dec(M, diameter_codec:decode(diameter_test_recv, Pkt)).
+%% Note that the recv dictionary defines neither XXX nor YYY.
+
+dec('AR', #diameter_packet
+ {msg = #recv_AR{'Origin-Host' = ?HOST,
+ 'Origin-Realm' = ?REALM,
+ 'AVP' = [?NOT_MANDATORY_YYY]},
+ errors = [{5001, ?MANDATORY_XXX}]}) ->
+ ok;
+
+dec('BR', #diameter_packet
+ {msg = #recv_BR{'Origin-Host' = ?HOST,
+ 'Origin-Realm' = ?REALM},
+ errors = [{5008, ?NOT_MANDATORY_YYY},
+ {5001, ?MANDATORY_XXX}]}) ->
+ ok.
diff --git a/lib/diameter/test/diameter_codec_SUITE_data/recv.dia b/lib/diameter/test/diameter_codec_SUITE_data/recv.dia
new file mode 100644
index 0000000000..15fec5a5dd
--- /dev/null
+++ b/lib/diameter/test/diameter_codec_SUITE_data/recv.dia
@@ -0,0 +1,51 @@
+;;
+;; %CopyrightBegin%
+;;
+;; Copyright Ericsson AB 2010-2011. 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%
+;;
+
+@id 17
+@name diameter_test_recv
+@prefix recv
+
+@inherits diameter_gen_base_rfc3588
+
+ Origin-Host
+ Origin-Realm
+ Result-Code
+
+@messages
+
+ AR ::= < Diameter Header: 123, REQ >
+ { Origin-Host }
+ { Origin-Realm }
+ * [ AVP ]
+
+ AA ::= < Diameter Header: 123 >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ * [ AVP ]
+
+ BR ::= < Diameter Header: 124, REQ >
+ { Origin-Host }
+ { Origin-Realm }
+
+ BA ::= < Diameter Header: 124 >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ * [ AVP ]
diff --git a/lib/diameter/test/diameter_codec_SUITE_data/send.dia b/lib/diameter/test/diameter_codec_SUITE_data/send.dia
new file mode 100644
index 0000000000..1472f146ae
--- /dev/null
+++ b/lib/diameter/test/diameter_codec_SUITE_data/send.dia
@@ -0,0 +1,56 @@
+;;
+;; %CopyrightBegin%
+;;
+;; Copyright Ericsson AB 2010-2011. 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%
+;;
+
+@id 17
+@name diameter_test_send
+@prefix send
+
+@inherits diameter_gen_base_rfc3588
+
+ Origin-Host
+ Origin-Realm
+ Result-Code
+
+@inherits diameter_test_avps
+
+@messages
+
+ AR ::= < Diameter Header: 123, REQ >
+ { Origin-Host }
+ { Origin-Realm }
+ [ XXX ]
+ [ YYY ]
+
+ AA ::= < Diameter Header: 123 >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ * [ AVP ]
+
+ BR ::= < Diameter Header: 124, REQ >
+ { Origin-Host }
+ { Origin-Realm }
+ [ XXX ]
+ [ YYY ]
+
+ BA ::= < Diameter Header: 124 >
+ { Result-Code }
+ { Origin-Host }
+ { Origin-Realm }
+ * [ AVP ]
diff --git a/lib/diameter/test/diameter_compiler_SUITE.erl b/lib/diameter/test/diameter_compiler_SUITE.erl
index 66d788f6ec..3b4c9706e0 100644
--- a/lib/diameter/test/diameter_compiler_SUITE.erl
+++ b/lib/diameter/test/diameter_compiler_SUITE.erl
@@ -29,9 +29,10 @@
end_per_suite/1]).
%% testcases
--export([format/1, format/2,
- replace/1, replace/2,
- generate/1, generate/4, generate/0]).
+-export([format/1, format/2,
+ replace/1, replace/2,
+ generate/1, generate/4, generate/0,
+ examples/1, examples/0]).
-export([dict/0]). %% fake dictionary module
@@ -327,6 +328,14 @@
"@codecs mymod "
"Origin-Host Origin-Realm\n&"}]}]).
+%% Standard dictionaries in examples/dict.
+-define(EXAMPLES, [rfc4004_mip,
+ rfc4005_nas,
+ rfc4006_cc,
+ rfc4072_eap,
+ rfc4590_digest,
+ rfc4740_sip]).
+
%% ===========================================================================
suite() ->
@@ -335,7 +344,8 @@ suite() ->
all() ->
[format,
replace,
- generate].
+ generate,
+ examples].
%% Error handling testcases will make an erroneous dictionary out of
%% the base dictionary and check that the expected error results.
@@ -349,8 +359,6 @@ end_per_suite(_Config) ->
ok.
%% ===========================================================================
-%% testcases
-
%% format/1
%%
%% Ensure that parse o format is the identity map.
@@ -367,6 +375,7 @@ format(Mods, Bin) ->
{ok, D} = diameter_dict_util:parse(diameter_dict_util:format(Dict), []),
{Dict, Dict} = {Dict, D}.
+%% ===========================================================================
%% replace/1
%%
%% Ensure the expected success/error when parsing a morphed common
@@ -393,12 +402,13 @@ replace({E, Mods}, Bin) ->
re({RE, Repl}, Bin) ->
re:replace(Bin, RE, Repl, [multiline]).
+%% ===========================================================================
%% generate/1
%%
%% Ensure success when generating code and compiling.
generate() ->
- [{timetrap, {seconds, length(?REPLACE)}}].
+ [{timetrap, {seconds, 2*length(?REPLACE)}}].
generate(Config) ->
Bin = proplists:get_value(base, Config),
@@ -422,6 +432,44 @@ generate(Mods, Bin, N, Mode) ->
andalso ({ok, _} = compile:file(File ++ ".erl", [return_errors])).
%% ===========================================================================
+%% examples/1
+%%
+%% Compile dictionaries extracted from various standards.
+
+examples() ->
+ [{timetrap, {seconds, 3*length(?EXAMPLES)}}].
+
+examples(_Config) ->
+ Dir = filename:join([code:lib_dir(diameter, examples), "dict"]),
+ [D || D <- ?EXAMPLES, _ <- [examples(?S(D), Dir)]].
+
+examples(Dict, Dir) ->
+ {Name, Pre} = make_name(Dict),
+ ok = diameter_make:codec(filename:join([Dir, Dict ++ ".dia"]),
+ [{name, Name},
+ {prefix, Pre},
+ inherits("rfc3588_base")
+ | opts(Dict)]),
+ {ok, _, _} = compile:file(Name ++ ".erl", [return]).
+
+opts(M)
+ when M == "rfc4006_cc";
+ M == "rfc4072_eap" ->
+ [inherits("rfc4005_nas")];
+opts("rfc4740_sip") ->
+ [inherits("rfc4590_digest")];
+opts(_) ->
+ [].
+
+inherits(File) ->
+ {Name, _} = make_name(File),
+ {inherits, File ++ "/" ++ Name}.
+
+make_name(File) ->
+ {R, [$_|N]} = lists:splitwith(fun(C) -> C /= $_ end, File),
+ {string:join(["diameter_gen", N, R], "_"), "diameter_" ++ N}.
+
+%% ===========================================================================
modify(Bin, Mods) ->
lists:foldl(fun re/2, Bin, Mods).
diff --git a/lib/diameter/test/diameter_dict_SUITE.erl b/lib/diameter/test/diameter_dict_SUITE.erl
index 87bb9727fe..5cf8506d3f 100644
--- a/lib/diameter/test/diameter_dict_SUITE.erl
+++ b/lib/diameter/test/diameter_dict_SUITE.erl
@@ -25,9 +25,7 @@
-export([suite/0,
all/0,
- groups/0,
- init_per_group/2,
- end_per_group/2]).
+ groups/0]).
%% testcases
-export([append/1,
@@ -53,10 +51,11 @@ suite() ->
[{timetrap, {seconds, 10}}].
all() ->
- [{group, all} | tc()].
+ [{group, all},
+ {group, all, [parallel]}].
groups() ->
- [{all, [parallel], tc()}].
+ [{all, [], tc()}].
tc() ->
[append,
@@ -71,12 +70,6 @@ tc() ->
update,
update_counter].
-init_per_group(_, Config) ->
- Config.
-
-end_per_group(_, _) ->
- ok.
-
%% ===========================================================================
-define(KV100, [{N,[N]} || N <- lists:seq(1,100)]).
diff --git a/lib/diameter/test/diameter_failover_SUITE.erl b/lib/diameter/test/diameter_failover_SUITE.erl
index 429b6328e6..53398dd93e 100644
--- a/lib/diameter/test/diameter_failover_SUITE.erl
+++ b/lib/diameter/test/diameter_failover_SUITE.erl
@@ -174,7 +174,7 @@ realm(Host) ->
call(Req, Opts) ->
diameter:call(?CLIENT, ?APP_ALIAS, Req, Opts).
-
+
set([H|T], Vs) ->
[H | Vs ++ T].
diff --git a/lib/diameter/test/diameter_gen_sctp_SUITE.erl b/lib/diameter/test/diameter_gen_sctp_SUITE.erl
new file mode 100644
index 0000000000..7f435a6b7a
--- /dev/null
+++ b/lib/diameter/test/diameter_gen_sctp_SUITE.erl
@@ -0,0 +1,354 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. 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%
+%%
+
+%%
+%% Some gen_sctp-specific tests demonstrating problems that were
+%% encountered during diameter development but have nothing
+%% specifically to do with diameter. At least one of them can cause
+%% diameter_transport_SUITE testcases to fail.
+%%
+
+-module(diameter_gen_sctp_SUITE).
+
+-export([suite/0,
+ all/0,
+ init_per_suite/1,
+ end_per_suite/1]).
+
+%% testcases
+-export([send_not_from_controlling_process/1,
+ send_from_multiple_clients/1,
+ receive_what_was_sent/1]).
+
+-include_lib("kernel/include/inet_sctp.hrl").
+
+%% Message from gen_sctp are of this form.
+-define(SCTP(Sock, Data), {sctp, Sock, _, _, Data}).
+
+%% Open sockets on the loopback address.
+-define(ADDR, {127,0,0,1}).
+
+%% Snooze, nap, siesta.
+-define(SLEEP(T), receive after T -> ok end).
+
+%% An indescribably long number of milliseconds after which everthing
+%% that should have happened has.
+-define(FOREVER, 2000).
+
+%% The first byte in each message we send as a simple guard against
+%% not receiving what was sent.
+-define(MAGIC, 42).
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {minutes, 2}}].
+
+all() ->
+ [send_not_from_controlling_process,
+ send_from_multiple_clients,
+ receive_what_was_sent].
+
+init_per_suite(Config) ->
+ case gen_sctp:open() of
+ {ok, Sock} ->
+ gen_sctp:close(Sock),
+ Config;
+ {error, E} when E == eprotonosupport;
+ E == esocktnosupport ->
+ {skip, no_sctp}
+ end.
+
+end_per_suite(_Config) ->
+ ok.
+
+%% ===========================================================================
+
+%% send_not_from_controlling_process/1
+%%
+%% This testcase failing shows gen_sctp:send/4 hanging when called
+%% outside the controlling process of the socket in question.
+
+send_not_from_controlling_process(_) ->
+ Pids = send_not_from_controlling_process(),
+ ?SLEEP(?FOREVER),
+ try
+ [] = [{P,I} || P <- Pids, I <- [process_info(P)], I /= undefined]
+ after
+ lists:foreach(fun(P) -> exit(P, kill) end, Pids)
+ end.
+
+%% send_not_from_controlling_process/0
+%%
+%% Returns the pids of three spawned processes: a listening process, a
+%% connecting process and a sending process.
+%%
+%% The expected behaviour is that all three processes exit:
+%%
+%% - The listening process exits upon receiving an SCTP message
+%% sent by the sending process.
+%% - The connecting process exits upon listening process exit.
+%% - The sending process exits upon gen_sctp:send/4 return.
+%%
+%% The observed behaviour is that all three processes remain alive
+%% indefinitely:
+%%
+%% - The listening process never receives the SCTP message sent
+%% by the sending process.
+%% - The connecting process has an inet_reply message in its mailbox
+%% as a consequence of the call to gen_sctp:send/4 call from the
+%% sending process.
+%% - The call to gen_sctp:send/4 in the sending process doesn't return,
+%% hanging in prim_inet:getopts/2.
+
+send_not_from_controlling_process() ->
+ FPid = self(),
+ {L, MRef} = spawn_monitor(fun() -> listen(FPid) end),%% listening process
+ receive
+ {?MODULE, C, S} ->
+ erlang:demonitor(MRef, [flush]),
+ [L,C,S];
+ {'DOWN', MRef, process, _, _} = T ->
+ error(T)
+ end.
+
+%% listen/1
+
+listen(FPid) ->
+ {ok, Sock} = open(),
+ ok = gen_sctp:listen(Sock, true),
+ {ok, PortNr} = inet:port(Sock),
+ LPid = self(),
+ spawn(fun() -> connect1(PortNr, FPid, LPid) end), %% connecting process
+ Id = assoc(Sock),
+ ?SCTP(Sock, {[#sctp_sndrcvinfo{assoc_id = Id}], _Bin})
+ = recv(). %% Waits with this as current_function.
+
+%% recv/0
+
+recv() ->
+ receive T -> T end.
+
+%% connect1/3
+
+connect1(PortNr, FPid, LPid) ->
+ {ok, Sock} = open(),
+ ok = gen_sctp:connect_init(Sock, ?ADDR, PortNr, []),
+ Id = assoc(Sock),
+ FPid ! {?MODULE,
+ self(),
+ spawn(fun() -> send(Sock, Id) end)}, %% sending process
+ MRef = erlang:monitor(process, LPid),
+ down(MRef). %% Waits with this as current_function.
+
+%% down/1
+
+down(MRef) ->
+ receive {'DOWN', MRef, process, _, Reason} -> Reason end.
+
+%% send/2
+
+send(Sock, Id) ->
+ ok = gen_sctp:send(Sock, Id, 0, <<0:32>>).
+
+%% ===========================================================================
+
+%% send_from_multiple_clients/0
+%%
+%% Demonstrates sluggish delivery of messages.
+
+send_from_multiple_clients(_) ->
+ {S, Rs} = T = send_from_multiple_clients(8, 1024),
+ {false, [], _} = {?FOREVER < S,
+ Rs -- [OI || {O,_} = OI <- Rs, is_integer(O)],
+ T}.
+
+%% send_from_multiple_clients/2
+%%
+%% Opens a listening socket and then spawns a specified number of
+%% processes, each of which connects to the listening socket. Each
+%% connecting process then sends a message, whose size in bytes is
+%% passed as an argument, the listening process sends a reply
+%% containing the time at which the message was received, and the
+%% connecting process then exits upon reception of this reply.
+%%
+%% Returns the elapsed time for all connecting process to exit
+%% together with a list of exit reasons for the connecting processes.
+%% In the successful case a connecting process exits with the
+%% outbound/inbound transit times for the sent/received message as
+%% reason.
+%%
+%% The observed behaviour is that some outbound messages (that is,
+%% from a connecting process to the listening process) can take an
+%% unexpectedly long time to complete their journey. The more
+%% connecting processes, the longer the possible delay it seems.
+%%
+%% eg. (With F = fun send_from_multiple_clients/2.)
+%%
+%% 5> F(2, 1024).
+%% {875,[{128,116},{113,139}]}
+%% 6> F(4, 1024).
+%% {2995290,[{2994022,250},{2994071,80},{200,130},{211,113}]}
+%% 7> F(8, 1024).
+%% {8997461,[{8996161,116},
+%% {2996471,86},
+%% {2996278,116},
+%% {2996360,95},
+%% {246,112},
+%% {213,159},
+%% {373,173},
+%% {376,118}]}
+%% 8> F(8, 1024).
+%% {21001891,[{20999968,128},
+%% {8997891,172},
+%% {8997927,91},
+%% {2995716,164},
+%% {2995860,87},
+%% {134,100},
+%% {117,98},
+%% {149,125}]}
+
+send_from_multiple_clients(N, Sz)
+ when is_integer(N), 0 < N, is_integer(Sz), 0 < Sz ->
+ timer:tc(fun listen/2, [N, <<?MAGIC, 0:Sz/unit:8>>]).
+
+%% listen/2
+
+listen(N, Bin) ->
+ {ok, Sock} = open(),
+ ok = gen_sctp:listen(Sock, true),
+ {ok, PortNr} = inet:port(Sock),
+
+ %% Spawn a middleman that in turn spawns N connecting processes,
+ %% collects a list of exit reasons and then exits with the list as
+ %% reason. loop/3 returns when we receive this list from the
+ %% middleman's 'DOWN'.
+
+ Self = self(),
+ Fun = fun() -> exit(connect2(Self, PortNr, Bin)) end,
+ {_, MRef} = spawn_monitor(fun() -> exit(fold(N, Fun)) end),
+ loop(Sock, MRef, Bin).
+
+%% fold/2
+%%
+%% Spawn N processes and collect their exit reasons in a list.
+
+fold(N, Fun) ->
+ start(N, Fun),
+ acc(N, []).
+
+start(0, _) ->
+ ok;
+start(N, Fun) ->
+ spawn_monitor(Fun),
+ start(N-1, Fun).
+
+acc(0, Acc) ->
+ Acc;
+acc(N, Acc) ->
+ receive
+ {'DOWN', _MRef, process, _, RC} ->
+ acc(N-1, [RC | Acc])
+ end.
+
+%% loop/3
+
+loop(Sock, MRef, Bin) ->
+ receive
+ ?SCTP(Sock, {[#sctp_sndrcvinfo{assoc_id = Id}], B}) ->
+ Sz = size(Bin),
+ {Sz, Bin} = {size(B), B}, %% assert
+ ok = send(Sock, Id, mark(Bin)),
+ loop(Sock, MRef, Bin);
+ ?SCTP(Sock, _) ->
+ loop(Sock, MRef, Bin);
+ {'DOWN', MRef, process, _, Reason} ->
+ Reason
+ end.
+
+%% connect2/3
+
+connect2(Pid, PortNr, Bin) ->
+ erlang:monitor(process, Pid),
+
+ {ok, Sock} = open(),
+ ok = gen_sctp:connect_init(Sock, ?ADDR, PortNr, []),
+ Id = assoc(Sock),
+
+ %% T1 = time before send
+ %% T2 = time after listening process received our message
+ %% T3 = time after reply is received
+
+ T1 = now(),
+ ok = send(Sock, Id, Bin),
+ T2 = unmark(recv(Sock, Id)),
+ T3 = now(),
+ {timer:now_diff(T2, T1), timer:now_diff(T3, T2)}. %% {Outbound, Inbound}
+
+%% recv/2
+
+recv(Sock, Id) ->
+ receive
+ ?SCTP(Sock, {[#sctp_sndrcvinfo{assoc_id = Id}], Bin}) ->
+ Bin;
+ T -> %% eg. 'DOWN'
+ exit(T)
+ end.
+
+%% send/3
+
+send(Sock, Id, Bin) ->
+ gen_sctp:send(Sock, Id, 0, Bin).
+
+%% mark/1
+
+mark(Bin) ->
+ Info = term_to_binary(now()),
+ <<Info/binary, Bin/binary>>.
+
+%% unmark/1
+
+unmark(Bin) ->
+ {_,_,_} = binary_to_term(Bin).
+
+%% ===========================================================================
+
+%% receive_what_was_sent/1
+%%
+%% Demonstrates reception of a message that differs from that sent.
+
+receive_what_was_sent(_Config) ->
+ send_from_multiple_clients(1, 1024*32). %% fails
+
+%% ===========================================================================
+
+%% open/0
+
+open() ->
+ gen_sctp:open([{ip, ?ADDR}, {port, 0}, {active, true}, binary]).
+
+%% assoc/1
+
+assoc(Sock) ->
+ receive
+ ?SCTP(Sock, {[], #sctp_assoc_change{state = S,
+ assoc_id = Id}}) ->
+ comm_up = S, %% assert
+ Id
+ end.
diff --git a/lib/diameter/test/diameter_reg_SUITE.erl b/lib/diameter/test/diameter_reg_SUITE.erl
index ade824c9dd..ec6a0ca731 100644
--- a/lib/diameter/test/diameter_reg_SUITE.erl
+++ b/lib/diameter/test/diameter_reg_SUITE.erl
@@ -26,8 +26,6 @@
-export([suite/0,
all/0,
groups/0,
- init_per_group/2,
- end_per_group/2,
init_per_suite/1,
end_per_suite/1]).
@@ -48,10 +46,11 @@ suite() ->
[{timetrap, {seconds, 10}}].
all() ->
- [{group, all} | tc()].
+ [{group, all},
+ {group, all, [parallel]}].
groups() ->
- [{all, [parallel], tc()}].
+ [{all, [], tc()}].
tc() ->
[add,
@@ -61,12 +60,6 @@ tc() ->
terms,
pids].
-init_per_group(_, Config) ->
- Config.
-
-end_per_group(_, _) ->
- ok.
-
init_per_suite(Config) ->
ok = diameter:start(),
Config.
diff --git a/lib/diameter/test/diameter_relay_SUITE.erl b/lib/diameter/test/diameter_relay_SUITE.erl
index c0351f8cf2..70e1866791 100644
--- a/lib/diameter/test/diameter_relay_SUITE.erl
+++ b/lib/diameter/test/diameter_relay_SUITE.erl
@@ -35,9 +35,7 @@
-export([suite/0,
all/0,
- groups/0,
- init_per_group/2,
- end_per_group/2]).
+ groups/0]).
%% testcases
-export([start/1,
@@ -117,21 +115,17 @@ suite() ->
[{timetrap, {seconds, 10}}].
all() ->
- [start, start_services, connect]
- ++ tc()
- ++ [{group, all},
- disconnect,
- stop_services,
- stop].
+ [start,
+ start_services,
+ connect,
+ {group, all},
+ {group, all, [parallel]},
+ disconnect,
+ stop_services,
+ stop].
groups() ->
- [{all, [parallel], tc()}].
-
-init_per_group(_, Config) ->
- Config.
-
-end_per_group(_, _) ->
- ok.
+ [{all, [], tc()}].
%% Traffic cases run when services are started and connections
%% established.
@@ -248,7 +242,7 @@ call(Server) ->
call(Req, Opts) ->
diameter:call(?CLIENT, ?APP_ALIAS, Req, Opts).
-
+
set([H|T], Vs) ->
[H | Vs ++ T].
diff --git a/lib/diameter/test/diameter_stats_SUITE.erl b/lib/diameter/test/diameter_stats_SUITE.erl
index e50a0050a6..e7807fd360 100644
--- a/lib/diameter/test/diameter_stats_SUITE.erl
+++ b/lib/diameter/test/diameter_stats_SUITE.erl
@@ -26,8 +26,6 @@
-export([suite/0,
all/0,
groups/0,
- init_per_group/2,
- end_per_group/2,
init_per_suite/1,
end_per_suite/1]).
@@ -44,21 +42,16 @@ suite() ->
[{timetrap, {seconds, 10}}].
all() ->
- [{group, all} | tc()].
+ [{group, all},
+ {group, all, [parallel]}].
groups() ->
- [{all, [parallel], tc()}].
+ [{all, [], tc()}].
tc() ->
[an,
twa].
-init_per_group(_, Config) ->
- Config.
-
-end_per_group(_, _) ->
- ok.
-
init_per_suite(Config) ->
ok = diameter:start(),
Config.
diff --git a/lib/diameter/test/diameter_sync_SUITE.erl b/lib/diameter/test/diameter_sync_SUITE.erl
index 84f77b6066..ab629fb1c1 100644
--- a/lib/diameter/test/diameter_sync_SUITE.erl
+++ b/lib/diameter/test/diameter_sync_SUITE.erl
@@ -26,8 +26,6 @@
-export([suite/0,
all/0,
groups/0,
- init_per_group/2,
- end_per_group/2,
init_per_suite/1,
end_per_suite/1]).
@@ -48,10 +46,11 @@ suite() ->
[{timetrap, {seconds, 10}}].
all() ->
- [{group, all} | tc()].
+ [{group, all},
+ {group, all, [parallel]}].
groups() ->
- [{all, [parallel], tc()}].
+ [{all, [], tc()}].
tc() ->
[call,
@@ -59,12 +58,6 @@ tc() ->
timeout,
flush].
-init_per_group(_, Config) ->
- Config.
-
-end_per_group(_, _) ->
- ok.
-
init_per_suite(Config) ->
ok = diameter:start(),
Config.
diff --git a/lib/diameter/test/diameter_tls_SUITE.erl b/lib/diameter/test/diameter_tls_SUITE.erl
index 38282282b8..85b953dc1a 100644
--- a/lib/diameter/test/diameter_tls_SUITE.erl
+++ b/lib/diameter/test/diameter_tls_SUITE.erl
@@ -36,8 +36,6 @@
-export([suite/0,
all/0,
groups/0,
- init_per_group/2,
- end_per_group/2,
init_per_suite/1,
end_per_suite/1]).
@@ -136,20 +134,16 @@ all() ->
start_diameter,
make_certs,
start_services,
- add_transports]
- ++ [{group, N} || {N, _, _} <- groups()]
- ++ [remove_transports, stop_services, stop_diameter, stop_ssl].
+ add_transports,
+ {group, all},
+ {group, all, [parallel]},
+ remove_transports,
+ stop_services,
+ stop_diameter,
+ stop_ssl].
groups() ->
- Ts = tc(),
- [{all, [], Ts},
- {p, [parallel], Ts}].
-
-init_per_group(_, Config) ->
- Config.
-
-end_per_group(_, _) ->
- ok.
+ [{all, [], tc()}].
%% Shouldn't really have to know about crypto here but 'ok' from
%% ssl:start() isn't enough to guarantee that TLS is available.
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index 78131b4ec4..6eed8d3b5d 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -162,27 +162,16 @@ suite() ->
[{timetrap, {seconds, 10}}].
all() ->
- [start, start_services, add_transports, result_codes
- | [{group, N} || {N, _, _} <- groups()]]
+ [start, start_services, add_transports, result_codes]
+ ++ [{group, E, P} || E <- ?ENCODINGS, P <- [[], [parallel]]]
++ [remove_transports, stop_services, stop].
groups() ->
Ts = tc(),
- [{grp(E,P), P, Ts} || E <- ?ENCODINGS, P <- [[], [parallel]]].
-
-grp(E, []) ->
- E;
-grp(E, [parallel]) ->
- ?P(E).
+ [{E, [], Ts} || E <- ?ENCODINGS].
init_per_group(Name, Config) ->
- E = case ?L(Name) of
- "p_" ++ Rest ->
- ?A(Rest);
- _ ->
- Name
- end,
- [{encode, E} | Config].
+ [{encode, Name} | Config].
end_per_group(_, _) ->
ok.
@@ -516,10 +505,10 @@ send_multiple_filters(Config, Fs) ->
%% Ensure that we can pass a request in any form to diameter:call/4,
%% only the return value from the prepare_request callback being
%% significant.
-send_anything(Config) ->
+send_anything(Config) ->
#diameter_base_STA{'Result-Code' = ?SUCCESS}
= call(Config, anything).
-
+
%% ===========================================================================
call(Config, Req) ->
diff --git a/lib/diameter/test/diameter_transport_SUITE.erl b/lib/diameter/test/diameter_transport_SUITE.erl
index df7161fd1e..893b7ba2f9 100644
--- a/lib/diameter/test/diameter_transport_SUITE.erl
+++ b/lib/diameter/test/diameter_transport_SUITE.erl
@@ -27,8 +27,6 @@
-export([suite/0,
all/0,
groups/0,
- init_per_group/2,
- end_per_group/2,
init_per_suite/1,
end_per_suite/1]).
@@ -92,10 +90,13 @@ suite() ->
[{timetrap, {minutes, 2}}].
all() ->
- [start | tc()] ++ [{group, all}, stop].
+ [start,
+ {group, all},
+ {group, all, [parallel]},
+ stop].
groups() ->
- [{all, [parallel], tc()}].
+ [{all, [], tc()}].
tc() ->
[tcp_accept,
@@ -103,12 +104,6 @@ tc() ->
sctp_accept,
sctp_connect].
-init_per_group(_, Config) ->
- Config.
-
-end_per_group(_, _) ->
- ok.
-
init_per_suite(Config) ->
[{sctp, have_sctp()} | Config].
@@ -175,16 +170,13 @@ connect(Prot) ->
%% have_sctp/0
have_sctp() ->
- try gen_sctp:open() of
+ case gen_sctp:open() of
{ok, Sock} ->
gen_sctp:close(Sock),
true;
{error, E} when E == eprotonosupport;
E == esocktnosupport -> %% fail on any other reason
false
- catch
- error: badarg ->
- false
end.
%% if_sctp/2
@@ -220,7 +212,7 @@ init(gen_connect, {Prot, Ref}) ->
[PortNr] = ?util:lport(Prot, Ref, 20),
%% Connect, send a message and receive it back.
- {ok, Sock} = gen_connect(Prot, PortNr, Ref),
+ {ok, Sock} = gen_connect(Prot, PortNr),
Bin = make_msg(),
ok = gen_send(Prot, Sock, Bin),
Bin = gen_recv(Prot, Sock);
@@ -359,20 +351,7 @@ tmod(tcp) ->
%% ===========================================================================
-%% gen_connect/3
-
-gen_connect(Prot, PortNr, Ref) ->
- Pid = sync(connect, Ref),
-
- %% Stagger connect attempts to avoid the situation that no
- %% transport process is accepting yet.
- receive after 250 -> ok end,
-
- try
- gen_connect(Prot, PortNr)
- after
- Pid ! Ref
- end.
+%% gen_connect/2
gen_connect(sctp = P, PortNr) ->
{ok, Sock} = Ok = gen_sctp:open([{ip, ?ADDR}, {port, 0} | ?SCTP_OPTS]),
diff --git a/lib/diameter/test/diameter_util.erl b/lib/diameter/test/diameter_util.erl
index 6b1dc1f0c9..0c42f955ad 100644
--- a/lib/diameter/test/diameter_util.erl
+++ b/lib/diameter/test/diameter_util.erl
@@ -212,7 +212,7 @@ read_priv(Config, Name) ->
read(Path) ->
{ok, Bin} = file:read_file(Path),
binary_to_term(Bin).
-
+
%% map_priv/3
%%
%% Modify a term in a file and return both old and new values.
diff --git a/lib/diameter/test/diameter_watchdog_SUITE.erl b/lib/diameter/test/diameter_watchdog_SUITE.erl
index b40d7c104d..ff40326947 100644
--- a/lib/diameter/test/diameter_watchdog_SUITE.erl
+++ b/lib/diameter/test/diameter_watchdog_SUITE.erl
@@ -306,11 +306,8 @@ watchdog(Type, Ref, TPid, Wd) ->
Opts = [{transport_module, ?MODULE},
{transport_config, TPid},
{watchdog_timer, Wd}],
- monitor(diameter_watchdog:start({Type, Ref},
- {false, Opts, false, ?SERVICE})).
-
-monitor(Pid) ->
- erlang:monitor(process, Pid),
+ {_MRef, Pid} = diameter_watchdog:start({Type, Ref},
+ {false, Opts, false, ?SERVICE}),
Pid.
%% ===========================================================================
@@ -350,6 +347,10 @@ init(_, _, TPid, _) ->
monitor(TPid),
3.
+monitor(Pid) ->
+ erlang:monitor(process, Pid),
+ Pid.
+
%% Generate a unique hostname for the faked peer.
hostname() ->
lists:flatten(io_lib:format("~p-~p-~p", tuple_to_list(now()))).
diff --git a/lib/diameter/test/modules.mk b/lib/diameter/test/modules.mk
index 54978d820c..7f163536fb 100644
--- a/lib/diameter/test/modules.mk
+++ b/lib/diameter/test/modules.mk
@@ -33,6 +33,7 @@ MODULES = \
diameter_sync_SUITE \
diameter_stats_SUITE \
diameter_watchdog_SUITE \
+ diameter_gen_sctp_SUITE \
diameter_transport_SUITE \
diameter_capx_SUITE \
diameter_traffic_SUITE \
@@ -42,3 +43,9 @@ MODULES = \
HRL_FILES = \
diameter_ct.hrl
+
+DATA = \
+ diameter_codec_SUITE_data/avps.dia \
+ diameter_codec_SUITE_data/send.dia \
+ diameter_codec_SUITE_data/recv.dia \
+ diameter_codec_SUITE_data/diameter_test_unknown.erl
diff --git a/lib/erl_docgen/priv/css/otp_doc.css b/lib/erl_docgen/priv/css/otp_doc.css
index 97d8c2df74..c56de378f4 100644
--- a/lib/erl_docgen/priv/css/otp_doc.css
+++ b/lib/erl_docgen/priv/css/otp_doc.css
@@ -1,6 +1,5 @@
-
-
-body {
+/* standard OTP style sheet */
+body {
background: white;
font-family: Verdana, Arial, Helvetica, sans-serif;
margin: 0;
@@ -11,7 +10,6 @@ body {
max-height: 100%;
}
-
th { font-family: Verdana, Arial, Helvetica, sans-serif }
td { font-family: Verdana, Arial, Helvetica, sans-serif }
p { font-family: Verdana, Arial, Helvetica, sans-serif }
@@ -33,8 +31,7 @@ a:visited { color: blue; text-decoration: none }
background-color: #fff;
}
-
-#leftnav {
+#leftnav {
position: fixed;
float: left;
top: 0;
@@ -47,8 +44,7 @@ a:visited { color: blue; text-decoration: none }
border-right: 1px solid red;
}
-
-#content {
+#content {
margin-left: 240px; /* set left value to WidthOfFrameDiv */
}
@@ -57,7 +53,6 @@ a:visited { color: blue; text-decoration: none }
padding-top: 50px; /* Magins for inner DIV inside each DIV (to provide padding) */
}
-
.innertube
{
margin: 15px; /* Magins for inner DIV inside each DIV (to provide padding) */
@@ -66,16 +61,15 @@ a:visited { color: blue; text-decoration: none }
.footer
{
margin: 15px; /* Magins for inner DIV inside each DIV (to provide padding) */
-
}
-span.bold_code { font-family: courier;font-weight: bold}
-span.code { font-family: courier;font-weight: normal}
+
+span.bold_code { font-family: Courier, monospace; font-weight: bold }
+span.code { font-family: Courier, monospace; font-weight: normal }
.note, .warning {
border: solid black 1px;
margin: 1em 3em;
}
-
.note .label {
background: #30d42a;
color: white;
@@ -102,16 +96,15 @@ span.code { font-family: courier;font-weight: normal}
font-size: 90%;
padding: 5px 10px;
}
-
-.example {
+.example {
background-color:#eeeeff;
padding: 0px 10px;
-}
+}
-pre { font-family: courier; font-weight: normal }
+pre { font-family: Courier, monospace; font-weight: normal }
.REFBODY { margin-left: 13mm }
.REFTYPES { margin-left: 8mm }
-footer { }
+footer { }
diff --git a/lib/erl_docgen/priv/xsl/db_html.xsl b/lib/erl_docgen/priv/xsl/db_html.xsl
index bdef7bfd3d..7cf5465f90 100644
--- a/lib/erl_docgen/priv/xsl/db_html.xsl
+++ b/lib/erl_docgen/priv/xsl/db_html.xsl
@@ -3,7 +3,7 @@
#
# %CopyrightBegin%
#
- # Copyright Ericsson AB 2009-2011. All Rights Reserved.
+ # Copyright Ericsson AB 2009-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -40,6 +40,11 @@
<xsl:variable name="m2a" select="document($mod2app_file)"></xsl:variable>
<xsl:key name="mod2app" match="module" use="@name"/>
+ <xsl:key
+ name="mfa"
+ match="func/name[string-length(@arity) > 0 and ancestor::erlref]"
+ use="concat(ancestor::erlref/module,':',@name, '/', @arity)"/>
+
<xsl:template name="err">
<xsl:param name="f"/>
<xsl:param name="m"/>
@@ -101,10 +106,14 @@
</xsl:message>
</xsl:when>
<xsl:when test="ancestor::erlref">
+ <!-- Do not to use preceding since it is very slow! -->
+ <xsl:variable name="curModule" select="ancestor::erlref/module"/>
+ <xsl:variable name="mfas"
+ select="key('mfa',
+ concat($curModule,':',$name,'/',$arity))"/>
<xsl:choose>
- <xsl:when test="preceding-sibling::name[position() = 1
- and @name = $name and @arity = $arity]">
- <!-- Avoid duplicated anchors.-->
+ <xsl:when test="generate-id($mfas[1]) != generate-id(.)">
+ <!-- Avoid duplicated anchors. See also menu.funcs. -->
</xsl:when>
<xsl:otherwise>
<a name="{$name}-{$arity}"></a>
@@ -546,6 +555,23 @@
<!-- End of Dialyzer type/spec tags -->
+ <!-- Cache for each module all the elements used for navigation. -->
+ <xsl:variable name="erlref.nav" select="exsl:node-set($erlref.nav_rtf)"/>
+
+ <xsl:variable name="erlref.nav_rtf">
+ <xsl:for-each select="//erlref">
+ <xsl:variable name="cval" select="module"/>
+ <xsl:variable name="link_cval"><xsl:value-of select="translate($cval, '&#173;', '')"/></xsl:variable>
+ <module name="{$cval}">
+ <xsl:call-template name="menu.funcs">
+ <xsl:with-param name="entries" select="funcs/func/name"/>
+ <xsl:with-param name="cval" select="$cval"/>
+ <xsl:with-param name="basename" select="$link_cval"/>
+ </xsl:call-template>
+ </module>
+ </xsl:for-each>
+ </xsl:variable>
+
<!-- Page layout -->
<xsl:template name="pagelayout">
<xsl:param name="chapnum"/>
@@ -1315,11 +1341,25 @@
Top of manual page
</a>
</li>
- <xsl:call-template name="menu.funcs">
- <xsl:with-param name="entries"
- select="funcs/func/name"/>
- <xsl:with-param name="basename"><xsl:value-of select="$link_cval"/></xsl:with-param>
- </xsl:call-template>
+ <xsl:call-template name="nl"/>
+ <xsl:choose>
+ <xsl:when test="local-name() = 'erlref'">
+ <!-- Use the cached value in order to save time.
+ value-of a string node is _much_ faster than
+ copy-of a rtf -->
+ <xsl:value-of
+ disable-output-escaping="yes"
+ select="$erlref.nav/module[@name = $cval]"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="menu.funcs">
+ <xsl:with-param name="entries"
+ select="funcs/func/name"/>
+ <xsl:with-param name="basename"><xsl:value-of select="$link_cval"/></xsl:with-param>
+ <xsl:with-param name="cval" select="$cval"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
</ul>
</li>
</xsl:when>
@@ -1349,6 +1389,7 @@
<xsl:template name="menu.funcs">
<xsl:param name="entries"/>
<xsl:param name="basename"/>
+ <xsl:param name="cval"/>
<xsl:for-each select="$entries">
@@ -1434,17 +1475,41 @@
</xsl:choose>
</xsl:variable>
+ <!-- Avoid duplicated entries. See also template "spec_name" -->
+ <!-- Do not to use preceding since it is very slow! -->
+ <xsl:variable name="mfas"
+ select="key('mfa',
+ concat($cval,':',$fname,'/',$arity))"/>
<xsl:choose>
- <xsl:when test="preceding-sibling::name[position() = 1
- and @name = $fname and @arity = $arity]">
+ <xsl:when test="string-length(@name) > 0 and
+ generate-id($mfas[1]) != generate-id(.)">
<!-- Skip. Only works for Dialyzer specs. -->
</xsl:when>
<xsl:otherwise>
+<!--
<li title="{$fname}-{$arity}">
<a href="{$basename}.html#{$fname}-{$arity}">
<xsl:value-of select="$fname"/>/<xsl:value-of select="$arity"/>
</a>
</li>
+-->
+ <!-- Generate a text node -->
+ <xsl:text>&lt;li title="</xsl:text>
+ <xsl:value-of select="$fname"/>
+ <xsl:text>-</xsl:text>
+ <xsl:value-of select="$arity"/>
+ <xsl:text>">&lt;a href="</xsl:text>
+ <xsl:value-of select="$basename"/>
+ <xsl:text>.html#</xsl:text>
+ <xsl:value-of select="$fname"/>
+ <xsl:text>-</xsl:text>
+ <xsl:value-of select="$arity"/>
+ <xsl:text>"></xsl:text>
+ <xsl:value-of select="$fname"/>
+ <xsl:text>/</xsl:text>
+ <xsl:value-of select="$arity"/>
+ <xsl:text>&lt;/a>&lt;/li></xsl:text>
+ <xsl:call-template name="nl"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
@@ -1854,18 +1919,24 @@
<xsl:choose>
<xsl:when test="string-length($filepart) > 0">
- <xsl:variable name="modulepart"><xsl:value-of select="substring-before($filepart, ':')"/></xsl:variable>
+ <!-- "Filepart#Linkpart" (or "Filepart#") -->
+ <xsl:variable name="app_part"><xsl:value-of select="substring-before($filepart, ':')"/></xsl:variable>
<xsl:choose>
- <xsl:when test="string-length($modulepart) > 0">
- <xsl:variable name="filepart1"><xsl:value-of select="substring-after($filepart, ':')"/></xsl:variable>
- <span class="bold_code"><a href="javascript:erlhref('{$topdocdir}/../','{$modulepart}','{$filepart1}.html#{$linkpart}');"><xsl:apply-templates/></a></span>
+ <xsl:when test="string-length($app_part) > 0">
+ <!-- "AppPart:ModPart#Linkpart" -->
+ <xsl:variable name="mod_part"><xsl:value-of select="substring-after($filepart, ':')"/></xsl:variable>
+ <span class="bold_code"><a href="javascript:erlhref('{$topdocdir}/../','{$app_part}','{$mod_part}.html#{$linkpart}');"><xsl:apply-templates/></a></span>
</xsl:when>
<xsl:otherwise>
+ <!-- "Filepart#Linkpart (there is no ':' in Filepart) -->
+ <xsl:variable name="minus_prefix"
+ select="substring-before($linkpart, '-')"/>
<xsl:choose>
- <!-- Dialyzer seealso (the application is unknown) -->
- <xsl:when test="string-length($specs_file) > 0
+ <xsl:when test="$minus_prefix = 'type'
+ and string-length($specs_file) > 0
and count($i/specs/module[@name=$filepart]) = 0">
- <!-- Deemed to slow; use key() instead
+ <!-- Dialyzer seealso (the application is unknown) -->
+ <!-- Following code deemed too slow; use key() instead
<xsl:variable name="app"
select="$m2a/mod2app/module[@name=$filepart]"/>
-->
@@ -1877,41 +1948,45 @@
<span class="bold_code"><a href="javascript:erlhref('{$topdocdir}/../','{$app}','{$filepart}.html#{$linkpart}');"><xsl:value-of select="$this"/></a></span>
</xsl:when>
<xsl:otherwise>
- <!-- Unknown application; no link -->
- <xsl:value-of select="$this"/>
+ <!-- Unknown application -->
+ <xsl:message terminate="yes">
+ Error <xsl:value-of select="$filepart"/>: cannot find module exporting type
+ </xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:when>
<xsl:when test="string-length($linkpart) > 0">
+ <!-- Still Filepart#Linkpart (there is no ':' in Filepart -->
<span class="bold_code"><a href="{$filepart}.html#{$linkpart}"><xsl:apply-templates/></a></span>
</xsl:when>
<xsl:otherwise>
+ <!-- "Filepart#" (there is no ':' in Filepart -->
<span class="bold_code"><a href="{$filepart}.html"><xsl:apply-templates/></a></span>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
+ </xsl:when> <!-- string-length($filepart) > 0 -->
+ <xsl:when test="string-length($linkpart) > 0">
+ <!-- "#Linkpart" -->
+ <span class="bold_code"><a href="#{$linkpart}"><xsl:apply-templates/></a></span>
</xsl:when>
<xsl:otherwise>
- <xsl:choose>
- <xsl:when test="string-length($linkpart) > 0">
- <span class="bold_code"><a href="#{$linkpart}"><xsl:apply-templates/></a></span>
- </xsl:when>
- <xsl:otherwise>
- <xsl:variable name="modulepart"><xsl:value-of select="substring-before(@marker, ':')"/></xsl:variable>
+ <!-- "AppPart:Mod" or "Mod" (there is no '#') -->
+ <xsl:variable name="app_part"><xsl:value-of select="substring-before(@marker, ':')"/></xsl:variable>
- <xsl:choose>
- <xsl:when test="string-length($modulepart) > 0">
- <xsl:variable name="filepart1"><xsl:value-of select="substring-after(@marker, ':')"/></xsl:variable>
- <span class="bold_code"><a href="javascript:erlhref('{$topdocdir}/../','{$modulepart}','{$filepart1}.html');"><xsl:apply-templates/></a></span>
- </xsl:when>
- <xsl:otherwise>
- <span class="bold_code"><a href="{@marker}.html"><xsl:apply-templates/></a></span>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:otherwise>
- </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="string-length($app_part) > 0">
+ <!-- "App:Mod" -->
+ <xsl:variable name="mod_part"><xsl:value-of select="substring-after(@marker, ':')"/></xsl:variable>
+ <span class="bold_code"><a href="javascript:erlhref('{$topdocdir}/../','{$app_part}','{$mod_part}.html');"><xsl:apply-templates/></a></span>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- "Mod" -->
+ <span class="bold_code"><a href="{@marker}.html"><xsl:apply-templates/></a></span>
+ </xsl:otherwise>
+ </xsl:choose>
</xsl:otherwise>
</xsl:choose>
@@ -2200,4 +2275,9 @@
</xsl:template>
+ <xsl:template name="nl">
+ <xsl:text>
+</xsl:text>
+ </xsl:template>
+
</xsl:stylesheet>
diff --git a/lib/erl_interface/src/misc/ei_format.c b/lib/erl_interface/src/misc/ei_format.c
index cf50f12451..c1e5d998e4 100644
--- a/lib/erl_interface/src/misc/ei_format.c
+++ b/lib/erl_interface/src/misc/ei_format.c
@@ -149,7 +149,7 @@ static int pdigit(const char** fmt, ei_x_buff* x)
{
const char* start = *fmt;
char c;
- int len, dotp=0;
+ int dotp=0;
double d;
long l;
@@ -166,7 +166,6 @@ static int pdigit(const char** fmt, ei_x_buff* x)
break;
}
--(*fmt);
- len = *fmt - start;
if (dotp) {
sscanf(start, "%lf", &d);
return ei_x_encode_double(x, d);
diff --git a/lib/et/src/et_gs_contents_viewer.erl b/lib/et/src/et_gs_contents_viewer.erl
index f6a87bd608..5331c7697a 100644
--- a/lib/et/src/et_gs_contents_viewer.erl
+++ b/lib/et/src/et_gs_contents_viewer.erl
@@ -21,6 +21,17 @@
%%----------------------------------------------------------------------
-module(et_gs_contents_viewer).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,editor,2}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,menu,2}},
+ {nowarn_deprecated_function,{gs,menubar,2}},
+ {nowarn_deprecated_function,{gs,menubutton,2}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,menuitem,3}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-behaviour(gen_server).
diff --git a/lib/et/src/et_gs_viewer.erl b/lib/et/src/et_gs_viewer.erl
index 0af7814d15..4e6f0e3f64 100644
--- a/lib/et/src/et_gs_viewer.erl
+++ b/lib/et/src/et_gs_viewer.erl
@@ -21,6 +21,23 @@
%%----------------------------------------------------------------------
-module(et_gs_viewer).
+-compile([{nowarn_deprecated_function,{gs,canvas,2}},
+ {nowarn_deprecated_function,{gs,checkbutton,3}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,line,2}},
+ {nowarn_deprecated_function,{gs,menu,2}},
+ {nowarn_deprecated_function,{gs,menu,3}},
+ {nowarn_deprecated_function,{gs,menubar,2}},
+ {nowarn_deprecated_function,{gs,menubutton,2}},
+ {nowarn_deprecated_function,{gs,menubutton,3}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,menuitem,3}},
+ {nowarn_deprecated_function,{gs,scale,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,text,2}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-behaviour(gen_server).
diff --git a/lib/gs/contribs/bonk/bonk.erl b/lib/gs/contribs/bonk/bonk.erl
index 79f01bf659..7e68a4ddc5 100644
--- a/lib/gs/contribs/bonk/bonk.erl
+++ b/lib/gs/contribs/bonk/bonk.erl
@@ -19,6 +19,12 @@
%%
-module(bonk).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
+
-export([run/0, run/1,bonk_dir/0,start/0]).
-record(colors, {miss, x, bomb, face}).
diff --git a/lib/gs/contribs/cols/cols.erl b/lib/gs/contribs/cols/cols.erl
index 111c9a58f1..9c44837f3e 100644
--- a/lib/gs/contribs/cols/cols.erl
+++ b/lib/gs/contribs/cols/cols.erl
@@ -19,6 +19,12 @@
%%
-module(cols).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
-export([start/0, init/0]).
diff --git a/lib/gs/contribs/cols/highscore.erl b/lib/gs/contribs/cols/highscore.erl
index 9ffbea50a7..8f984aaa83 100644
--- a/lib/gs/contribs/cols/highscore.erl
+++ b/lib/gs/contribs/cols/highscore.erl
@@ -19,6 +19,13 @@
%%
-module(highscore).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,grid,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([run/2]).
diff --git a/lib/gs/contribs/mandel/mandel.erl b/lib/gs/contribs/mandel/mandel.erl
index 0f1df5c665..6293f867e2 100644
--- a/lib/gs/contribs/mandel/mandel.erl
+++ b/lib/gs/contribs/mandel/mandel.erl
@@ -18,6 +18,11 @@
%%
-module(mandel).
+-compile([{nowarn_deprecated_function,{gs,assq,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,image,2}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
-author('(mbj,eklas)@erlang.ericsson.se').
%% User's interface
diff --git a/lib/gs/contribs/othello/othello_board.erl b/lib/gs/contribs/othello/othello_board.erl
index 212ba9bfe1..c52211a495 100644
--- a/lib/gs/contribs/othello/othello_board.erl
+++ b/lib/gs/contribs/othello/othello_board.erl
@@ -19,6 +19,12 @@
%%
-module(othello_board).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
+
-export([start/0,stop/0,init/0]).
diff --git a/lib/gs/doc/src/gs.xml b/lib/gs/doc/src/gs.xml
index f2182fc673..c61e8c4938 100644
--- a/lib/gs/doc/src/gs.xml
+++ b/lib/gs/doc/src/gs.xml
@@ -39,9 +39,7 @@
graphical user interface.
</p>
<p>
- GS is not maintained and we plan to deprecate and remove it from
- the distribution as soon as possible, maybe already in the next
- major release (R15).
+ GS is deprecated and will be removed in the R16 release.
</p>
</warning>
<p>The Graphics System, GS, is easy to learn and
diff --git a/lib/gs/examples/ball.erl b/lib/gs/examples/ball.erl
index 3f91a7b379..03fac3b5fc 100644
--- a/lib/gs/examples/ball.erl
+++ b/lib/gs/examples/ball.erl
@@ -24,6 +24,12 @@
%% ------------------------------------------------------------
-module(ball).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,canvas,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,oval,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/0,init/0]).
diff --git a/lib/gs/examples/browser.erl b/lib/gs/examples/browser.erl
index 1dba5a915b..0f8b3fc7e6 100644
--- a/lib/gs/examples/browser.erl
+++ b/lib/gs/examples/browser.erl
@@ -23,6 +23,14 @@
%% ------------------------------------------------------------
-module(browser).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,entry,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,listbox,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/0,start/2,init/3]).
diff --git a/lib/gs/examples/calc.erl b/lib/gs/examples/calc.erl
index 992b8adb4e..ca29ae1cb9 100644
--- a/lib/gs/examples/calc.erl
+++ b/lib/gs/examples/calc.erl
@@ -23,6 +23,11 @@
%% ------------------------------------------------------------
-module(calc).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/0,calc/0]).
diff --git a/lib/gs/examples/calc2.erl b/lib/gs/examples/calc2.erl
index 0e841397f6..83e1870b7a 100644
--- a/lib/gs/examples/calc2.erl
+++ b/lib/gs/examples/calc2.erl
@@ -24,6 +24,12 @@
%% ------------------------------------------------------------
-module(calc2).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
+
-export([start/0,calc/0]).
start() ->
diff --git a/lib/gs/examples/color_demo.erl b/lib/gs/examples/color_demo.erl
index 650f853061..a2f4d0eb87 100644
--- a/lib/gs/examples/color_demo.erl
+++ b/lib/gs/examples/color_demo.erl
@@ -24,6 +24,11 @@
%% ------------------------------------------------------------
-module(color_demo).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,scale,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/0,init/0]).
diff --git a/lib/gs/examples/color_demo2.erl b/lib/gs/examples/color_demo2.erl
index 817cc9ed7d..3b0b36221d 100644
--- a/lib/gs/examples/color_demo2.erl
+++ b/lib/gs/examples/color_demo2.erl
@@ -24,6 +24,10 @@
%% ------------------------------------------------------------
-module(color_demo2).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
-export([start/0,init/0]).
diff --git a/lib/gs/examples/distrib_draw.erl b/lib/gs/examples/distrib_draw.erl
index ecb1386c25..8f76bc6650 100644
--- a/lib/gs/examples/distrib_draw.erl
+++ b/lib/gs/examples/distrib_draw.erl
@@ -43,6 +43,11 @@
%%
-module(distrib_draw).
+-compile([{nowarn_deprecated_function,{gs,canvas,3}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,line,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
-export([start/2,init/0]).
diff --git a/lib/gs/examples/entry_demo.erl b/lib/gs/examples/entry_demo.erl
index a5ecfbc4d3..4bb64e949e 100644
--- a/lib/gs/examples/entry_demo.erl
+++ b/lib/gs/examples/entry_demo.erl
@@ -23,6 +23,12 @@
%% ------------------------------------------------------------
-module(entry_demo).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/0,init/1]).
diff --git a/lib/gs/examples/event_test.erl b/lib/gs/examples/event_test.erl
index f6fcc9b4b9..8c0a109df4 100644
--- a/lib/gs/examples/event_test.erl
+++ b/lib/gs/examples/event_test.erl
@@ -21,6 +21,9 @@
%% Demo for testing some events
-module(event_test).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/0,init/0]).
diff --git a/lib/gs/examples/file_dialog.erl b/lib/gs/examples/file_dialog.erl
index ff20321374..c1ef6ed8b1 100644
--- a/lib/gs/examples/file_dialog.erl
+++ b/lib/gs/examples/file_dialog.erl
@@ -23,6 +23,11 @@
%% ------------------------------------------------------------
-module(file_dialog).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
-export([start/0,start/1,start/2,fs_init/3]).
diff --git a/lib/gs/examples/focus_demo.erl b/lib/gs/examples/focus_demo.erl
index b9d86866e6..71ca9c6ff5 100644
--- a/lib/gs/examples/focus_demo.erl
+++ b/lib/gs/examples/focus_demo.erl
@@ -23,6 +23,11 @@
%% ------------------------------------------------------------
-module(focus_demo).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/0,init/0]).
diff --git a/lib/gs/examples/frac.erl b/lib/gs/examples/frac.erl
index 139a4be310..46af83de8a 100644
--- a/lib/gs/examples/frac.erl
+++ b/lib/gs/examples/frac.erl
@@ -21,6 +21,9 @@
%% Purpose : Fractal trees
-module(frac).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
-export([start/0, go/0, test/0, grow/2, expand/3, subst/2]).
diff --git a/lib/gs/examples/line_demo.erl b/lib/gs/examples/line_demo.erl
index c8a6a69e2e..ba88605118 100644
--- a/lib/gs/examples/line_demo.erl
+++ b/lib/gs/examples/line_demo.erl
@@ -24,6 +24,12 @@
%% ------------------------------------------------------------
-module(line_demo).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,canvas,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,line,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/0,init/0,line/3]).
diff --git a/lib/gs/examples/man.erl b/lib/gs/examples/man.erl
index a0ffd3364e..bddd6930ab 100644
--- a/lib/gs/examples/man.erl
+++ b/lib/gs/examples/man.erl
@@ -23,6 +23,15 @@
%% ------------------------------------------------------------
-module(man).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,entry,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,listbox,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
-export([start/0,init/0]).
-export([man_list/0]).
diff --git a/lib/gs/examples/menu_demo.erl b/lib/gs/examples/menu_demo.erl
index c95fc33152..6b2fc4113a 100644
--- a/lib/gs/examples/menu_demo.erl
+++ b/lib/gs/examples/menu_demo.erl
@@ -19,6 +19,12 @@
%%
-module(menu_demo).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-compile(export_all).
diff --git a/lib/gs/examples/rubber.erl b/lib/gs/examples/rubber.erl
index ba263f07ac..da4aa57391 100644
--- a/lib/gs/examples/rubber.erl
+++ b/lib/gs/examples/rubber.erl
@@ -23,6 +23,14 @@
%% ------------------------------------------------------------
-module(rubber).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,canvas,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,radiobutton,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/0, init/0]).
diff --git a/lib/gs/src/gs.erl b/lib/gs/src/gs.erl
index 3e9a1c4b8b..92dce12580 100644
--- a/lib/gs/src/gs.erl
+++ b/lib/gs/src/gs.erl
@@ -24,7 +24,13 @@
%%
-module(gs).
-
+-deprecated(module).
+-compile([{nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,create_tree,2}},
+ {nowarn_deprecated_function,{gs,foreach,3}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,1}}]).
%% ----- Exports -----
-export([start/0, stop/0, start/1]).
diff --git a/lib/gs/src/gs_frontend.erl b/lib/gs/src/gs_frontend.erl
index 009b264e69..73954baa8d 100644
--- a/lib/gs/src/gs_frontend.erl
+++ b/lib/gs/src/gs_frontend.erl
@@ -24,6 +24,8 @@
%%
-module(gs_frontend).
+-compile([{nowarn_deprecated_function,{gs,assq,2}},
+ {nowarn_deprecated_function,{gs,error,2}}]).
-export([create/2,
config/2,
diff --git a/lib/gs/src/gs_make.erl b/lib/gs/src/gs_make.erl
index e41183f9bf..bf8a66001f 100644
--- a/lib/gs/src/gs_make.erl
+++ b/lib/gs/src/gs_make.erl
@@ -19,6 +19,7 @@
%%
-module(gs_make).
+-compile([{nowarn_deprecated_function,{gs,assq,2}}]).
-export([start/0]).
diff --git a/lib/gs/src/gse.erl b/lib/gs/src/gse.erl
index b3ea2af4d4..c62badcc27 100644
--- a/lib/gs/src/gse.erl
+++ b/lib/gs/src/gse.erl
@@ -23,6 +23,68 @@
%%%----------------------------------------------------------------------
-module(gse).
+-compile([{nowarn_deprecated_function,{gs,arc,2}},
+ {nowarn_deprecated_function,{gs,arc,3}},
+ {nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,button,3}},
+ {nowarn_deprecated_function,{gs,canvas,2}},
+ {nowarn_deprecated_function,{gs,canvas,3}},
+ {nowarn_deprecated_function,{gs,checkbutton,2}},
+ {nowarn_deprecated_function,{gs,checkbutton,3}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,create_tree,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,editor,2}},
+ {nowarn_deprecated_function,{gs,editor,3}},
+ {nowarn_deprecated_function,{gs,entry,2}},
+ {nowarn_deprecated_function,{gs,entry,3}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,frame,3}},
+ {nowarn_deprecated_function,{gs,grid,2}},
+ {nowarn_deprecated_function,{gs,grid,3}},
+ {nowarn_deprecated_function,{gs,gridline,2}},
+ {nowarn_deprecated_function,{gs,gridline,3}},
+ {nowarn_deprecated_function,{gs,image,2}},
+ {nowarn_deprecated_function,{gs,image,3}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,label,3}},
+ {nowarn_deprecated_function,{gs,line,2}},
+ {nowarn_deprecated_function,{gs,line,3}},
+ {nowarn_deprecated_function,{gs,listbox,2}},
+ {nowarn_deprecated_function,{gs,listbox,3}},
+ {nowarn_deprecated_function,{gs,menu,2}},
+ {nowarn_deprecated_function,{gs,menu,3}},
+ {nowarn_deprecated_function,{gs,menubar,2}},
+ {nowarn_deprecated_function,{gs,menubar,3}},
+ {nowarn_deprecated_function,{gs,menubutton,2}},
+ {nowarn_deprecated_function,{gs,menubutton,3}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,menuitem,3}},
+ {nowarn_deprecated_function,{gs,message,2}},
+ {nowarn_deprecated_function,{gs,message,3}},
+ {nowarn_deprecated_function,{gs,oval,2}},
+ {nowarn_deprecated_function,{gs,oval,3}},
+ {nowarn_deprecated_function,{gs,polygon,2}},
+ {nowarn_deprecated_function,{gs,polygon,3}},
+ {nowarn_deprecated_function,{gs,prompter,2}},
+ {nowarn_deprecated_function,{gs,prompter,3}},
+ {nowarn_deprecated_function,{gs,radiobutton,2}},
+ {nowarn_deprecated_function,{gs,radiobutton,3}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,rectangle,2}},
+ {nowarn_deprecated_function,{gs,rectangle,3}},
+ {nowarn_deprecated_function,{gs,scale,2}},
+ {nowarn_deprecated_function,{gs,scale,3}},
+ {nowarn_deprecated_function,{gs,scrollbar,2}},
+ {nowarn_deprecated_function,{gs,scrollbar,3}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,start,1}},
+ {nowarn_deprecated_function,{gs,text,2}},
+ {nowarn_deprecated_function,{gs,text,3}},
+ {nowarn_deprecated_function,{gs,window,2}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
%%-compile(export_all).
-export([
diff --git a/lib/gs/src/gstk.erl b/lib/gs/src/gstk.erl
index 6f83cf8be4..ee974a5f63 100644
--- a/lib/gs/src/gstk.erl
+++ b/lib/gs/src/gstk.erl
@@ -20,6 +20,8 @@
%%
-module(gstk).
+-compile([{nowarn_deprecated_function,{gs,assq,2}},
+ {nowarn_deprecated_function,{gs,creation_error,2}}]).
-export([start_link/4,
stop/1,
diff --git a/lib/gs/src/gstk_arc.erl b/lib/gs/src/gstk_arc.erl
index 8e80ef92b5..3c6fe54d36 100644
--- a/lib/gs/src/gstk_arc.erl
+++ b/lib/gs/src/gstk_arc.erl
@@ -23,6 +23,7 @@
%% ------------------------------------------------------------
-module(gstk_arc).
+-compile([{nowarn_deprecated_function,{gs,creation_error,2}}]).
%%-----------------------------------------------------------------------------
%% ARC OPTIONS
diff --git a/lib/gs/src/gstk_canvas.erl b/lib/gs/src/gstk_canvas.erl
index 868b3020fe..5d15529995 100644
--- a/lib/gs/src/gstk_canvas.erl
+++ b/lib/gs/src/gstk_canvas.erl
@@ -23,6 +23,8 @@
%% ------------------------------------------------------------
-module(gstk_canvas).
+-compile([{nowarn_deprecated_function,{gs,pair,2}},
+ {nowarn_deprecated_function,{gs,val,2}}]).
%%-----------------------------------------------------------------------------
%% CANVAS OPTIONS
diff --git a/lib/gs/src/gstk_editor.erl b/lib/gs/src/gstk_editor.erl
index 6b90cee1d2..2686997036 100644
--- a/lib/gs/src/gstk_editor.erl
+++ b/lib/gs/src/gstk_editor.erl
@@ -23,6 +23,9 @@
%% ------------------------------------------------------------
-module(gstk_editor).
+-compile([{nowarn_deprecated_function,{gs,assq,2}},
+ {nowarn_deprecated_function,{gs,error,2}},
+ {nowarn_deprecated_function,{gs,val,2}}]).
%%------------------------------------------------------------------------------
%% CANVAS OPTIONS
diff --git a/lib/gs/src/gstk_entry.erl b/lib/gs/src/gstk_entry.erl
index 14f7831151..432ccd5fde 100644
--- a/lib/gs/src/gstk_entry.erl
+++ b/lib/gs/src/gstk_entry.erl
@@ -23,6 +23,7 @@
%% ------------------------------------------------------------
-module(gstk_entry).
+-compile([{nowarn_deprecated_function,{gs,error,2}}]).
%%------------------------------------------------------------------------------
%% ENTRY OPTIONS
diff --git a/lib/gs/src/gstk_generic.erl b/lib/gs/src/gstk_generic.erl
index 8fe19b428c..50c3da8dc5 100644
--- a/lib/gs/src/gstk_generic.erl
+++ b/lib/gs/src/gstk_generic.erl
@@ -20,6 +20,7 @@
%%
-module(gstk_generic).
+-compile([{nowarn_deprecated_function,{gs,assq,2}}]).
-export([out_opts/8,
read_option/5,
diff --git a/lib/gs/src/gstk_grid.erl b/lib/gs/src/gstk_grid.erl
index 4189246822..f703dad074 100644
--- a/lib/gs/src/gstk_grid.erl
+++ b/lib/gs/src/gstk_grid.erl
@@ -19,6 +19,7 @@
%%
-module(gstk_grid).
+-compile([{nowarn_deprecated_function,{gs,val,2}}]).
-export([event/5,create/3,config/3,option/5,read/3,delete/2,destroy/2,
mk_create_opts_for_child/4,read_option/5]).
diff --git a/lib/gs/src/gstk_gridline.erl b/lib/gs/src/gstk_gridline.erl
index c1dd5a1443..4585c7e043 100644
--- a/lib/gs/src/gstk_gridline.erl
+++ b/lib/gs/src/gstk_gridline.erl
@@ -19,6 +19,8 @@
%%
-module(gstk_gridline).
+-compile([{nowarn_deprecated_function,{gs,val,2}},
+ {nowarn_deprecated_function,{gs,val,3}}]).
-export([event/5,create/3,config/3,option/5,read/3,delete/2,destroy/3,
read_option/5]).
diff --git a/lib/gs/src/gstk_image.erl b/lib/gs/src/gstk_image.erl
index 53789b312d..2b7a324e28 100644
--- a/lib/gs/src/gstk_image.erl
+++ b/lib/gs/src/gstk_image.erl
@@ -23,6 +23,7 @@
%% ------------------------------------------------------------
-module(gstk_image).
+-compile([{nowarn_deprecated_function,{gs,pair,2}}]).
%%-----------------------------------------------------------------------------
%% BITMAP OPTIONS
diff --git a/lib/gs/src/gstk_menu.erl b/lib/gs/src/gstk_menu.erl
index 3957951a35..e878669de6 100644
--- a/lib/gs/src/gstk_menu.erl
+++ b/lib/gs/src/gstk_menu.erl
@@ -23,6 +23,7 @@
%%------------------------------------------------------------------------------
-module(gstk_menu).
+-compile([{nowarn_deprecated_function,{gs,error,2}}]).
%%------------------------------------------------------------------------------
%% MENU OPTIONS
diff --git a/lib/gs/src/gstk_menuitem.erl b/lib/gs/src/gstk_menuitem.erl
index 36a9253598..8abf5d13aa 100644
--- a/lib/gs/src/gstk_menuitem.erl
+++ b/lib/gs/src/gstk_menuitem.erl
@@ -23,6 +23,7 @@
%% ------------------------------------------------------------
-module(gstk_menuitem).
+-compile([{nowarn_deprecated_function,{gs,error,2}}]).
%%-----------------------------------------------------------------------------
%% MENUITEM OPTIONS
diff --git a/lib/gs/src/gstk_port_handler.erl b/lib/gs/src/gstk_port_handler.erl
index 93f3e58dc2..c6ca2c0f5b 100644
--- a/lib/gs/src/gstk_port_handler.erl
+++ b/lib/gs/src/gstk_port_handler.erl
@@ -34,6 +34,7 @@
%% ------------------------------------------------------------
-module(gstk_port_handler).
+-compile([{nowarn_deprecated_function,{gs,error,2}}]).
-include("gstk.hrl").
diff --git a/lib/gs/src/gstk_rectangle.erl b/lib/gs/src/gstk_rectangle.erl
index 1e02977c9a..14be16c990 100644
--- a/lib/gs/src/gstk_rectangle.erl
+++ b/lib/gs/src/gstk_rectangle.erl
@@ -23,6 +23,7 @@
%% ------------------------------------------------------------
-module(gstk_rectangle).
+-compile([{nowarn_deprecated_function,{gs,pair,2}}]).
%%-----------------------------------------------------------------------------
%% RECTANGLE OPTIONS
diff --git a/lib/gs/src/gstk_window.erl b/lib/gs/src/gstk_window.erl
index acac452ed1..4b4706eb88 100644
--- a/lib/gs/src/gstk_window.erl
+++ b/lib/gs/src/gstk_window.erl
@@ -23,6 +23,7 @@
%% ------------------------------------------------------------
-module(gstk_window).
+-compile([{nowarn_deprecated_function,{gs,destroy,1}}]).
%%------------------------------------------------------------------------------
%% WINDOW OPTIONS
diff --git a/lib/gs/src/tcl2erl.erl b/lib/gs/src/tcl2erl.erl
index 8845cf0b9a..d159681c5c 100644
--- a/lib/gs/src/tcl2erl.erl
+++ b/lib/gs/src/tcl2erl.erl
@@ -25,6 +25,7 @@
%% ------------------------------------------------------------
-module(tcl2erl).
+-compile([{nowarn_deprecated_function,{gs,error,2}}]).
-export([parse_event/1,
ret_int/1,
diff --git a/lib/gs/src/tool_file_dialog.erl b/lib/gs/src/tool_file_dialog.erl
index 6b2c2e8c81..cfcfcd1bf6 100644
--- a/lib/gs/src/tool_file_dialog.erl
+++ b/lib/gs/src/tool_file_dialog.erl
@@ -19,6 +19,16 @@
%%
-module(tool_file_dialog).
+-compile([{nowarn_deprecated_function,{gs,button,3}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,entry,3}},
+ {nowarn_deprecated_function,{gs,frame,3}},
+ {nowarn_deprecated_function,{gs,label,3}},
+ {nowarn_deprecated_function,{gs,listbox,3}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
+
-export([start/1]).
-record(opts, {type, % open | save | multiselect
diff --git a/lib/gs/src/tool_utils.erl b/lib/gs/src/tool_utils.erl
index f1b93c1af8..69919b18bd 100644
--- a/lib/gs/src/tool_utils.erl
+++ b/lib/gs/src/tool_utils.erl
@@ -19,6 +19,11 @@
%%
-module(tool_utils).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}}]).
+
-include_lib("kernel/include/file.hrl").
%%%---------------------------------------------------------------------
diff --git a/lib/hipe/cerl/cerl_hipe_primops.hrl b/lib/hipe/cerl/cerl_hipe_primops.hrl
index 36b1b62901..1d82f7bfc7 100644
--- a/lib/hipe/cerl/cerl_hipe_primops.hrl
+++ b/lib/hipe/cerl/cerl_hipe_primops.hrl
@@ -59,7 +59,6 @@
-define(PRIMOP_IS_ATOM, 'is_atom'). % arity 1
-define(PRIMOP_IS_BIGNUM, 'is_bignum'). % arity 1
-define(PRIMOP_IS_BINARY, 'is_binary'). % arity 1
--define(PRIMOP_IS_CONSTANT, 'is_constant'). % arity 1
-define(PRIMOP_IS_FIXNUM, 'is_fixnum'). % arity 1
-define(PRIMOP_IS_FLOAT, 'is_float'). % arity 1
-define(PRIMOP_IS_FUNCTION, 'is_function'). % arity 1
diff --git a/lib/hipe/cerl/cerl_hipeify.erl b/lib/hipe/cerl/cerl_hipeify.erl
index 8f6c3561c9..89b4ec147d 100644
--- a/lib/hipe/cerl/cerl_hipeify.erl
+++ b/lib/hipe/cerl/cerl_hipeify.erl
@@ -392,7 +392,6 @@ call_to_primop(erlang, '=<', 2) -> {yes, ?PRIMOP_LE};
call_to_primop(erlang, '>=', 2) -> {yes, ?PRIMOP_GE};
call_to_primop(erlang, is_atom, 1) -> {yes, ?PRIMOP_IS_ATOM};
call_to_primop(erlang, is_binary, 1) -> {yes, ?PRIMOP_IS_BINARY};
-call_to_primop(erlang, is_constant, 1) -> {yes, ?PRIMOP_IS_CONSTANT};
call_to_primop(erlang, is_float, 1) -> {yes, ?PRIMOP_IS_FLOAT};
call_to_primop(erlang, is_function, 1) -> {yes, ?PRIMOP_IS_FUNCTION};
call_to_primop(erlang, is_integer, 1) -> {yes, ?PRIMOP_IS_INTEGER};
diff --git a/lib/hipe/cerl/cerl_messagean.erl b/lib/hipe/cerl/cerl_messagean.erl
index 6dd93adaa3..b9f82f2a43 100644
--- a/lib/hipe/cerl/cerl_messagean.erl
+++ b/lib/hipe/cerl/cerl_messagean.erl
@@ -1083,7 +1083,6 @@ is_imm_op(erlang, is_alive, 0) -> true;
is_imm_op(erlang, is_atom, 1) -> true;
is_imm_op(erlang, is_binary, 1) -> true;
is_imm_op(erlang, is_builtin, 3) -> true;
-is_imm_op(erlang, is_constant, 1) -> true;
is_imm_op(erlang, is_float, 1) -> true;
is_imm_op(erlang, is_function, 1) -> true;
is_imm_op(erlang, is_integer, 1) -> true;
diff --git a/lib/hipe/cerl/cerl_to_icode.erl b/lib/hipe/cerl/cerl_to_icode.erl
index 362c427cbe..089e3f021e 100644
--- a/lib/hipe/cerl/cerl_to_icode.erl
+++ b/lib/hipe/cerl/cerl_to_icode.erl
@@ -88,7 +88,6 @@
-define(TYPE_IS_ATOM, atom).
-define(TYPE_IS_BIGNUM, bignum).
-define(TYPE_IS_BINARY, binary).
--define(TYPE_IS_CONSTANT, constant).
-define(TYPE_IS_FIXNUM, fixnum).
-define(TYPE_IS_FLOAT, float).
-define(TYPE_IS_FUNCTION, function).
@@ -2051,7 +2050,6 @@ is_record_test(T, A, N, True, False, Ctxt, Env, S) ->
type_test(?PRIMOP_IS_ATOM) -> ?TYPE_IS_ATOM;
type_test(?PRIMOP_IS_BIGNUM) -> ?TYPE_IS_BIGNUM;
type_test(?PRIMOP_IS_BINARY) -> ?TYPE_IS_BINARY;
-type_test(?PRIMOP_IS_CONSTANT) -> ?TYPE_IS_CONSTANT;
type_test(?PRIMOP_IS_FIXNUM) -> ?TYPE_IS_FIXNUM;
type_test(?PRIMOP_IS_FLOAT) -> ?TYPE_IS_FLOAT;
type_test(?PRIMOP_IS_FUNCTION) -> ?TYPE_IS_FUNCTION;
@@ -2082,7 +2080,6 @@ is_bool_op(Op, A) when is_atom(Op), is_integer(A) -> false.
is_type_test(?PRIMOP_IS_ATOM, 1) -> true;
is_type_test(?PRIMOP_IS_BIGNUM, 1) -> true;
is_type_test(?PRIMOP_IS_BINARY, 1) -> true;
-is_type_test(?PRIMOP_IS_CONSTANT, 1) -> true;
is_type_test(?PRIMOP_IS_FIXNUM, 1) -> true;
is_type_test(?PRIMOP_IS_FLOAT, 1) -> true;
is_type_test(?PRIMOP_IS_FUNCTION, 1) -> true;
diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl
index cee399e861..845df0ca61 100644
--- a/lib/hipe/cerl/erl_bif_types.erl
+++ b/lib/hipe/cerl/erl_bif_types.erl
@@ -54,7 +54,6 @@
t_cons/2,
t_cons_hd/1,
t_cons_tl/1,
- t_constant/0,
t_fixnum/0,
t_non_neg_fixnum/0,
t_pos_fixnum/0,
@@ -81,7 +80,6 @@
t_is_bitstr/1,
t_is_boolean/1,
t_is_cons/1,
- t_is_constant/1,
t_is_float/1,
t_is_float/1,
t_is_fun/1,
@@ -845,11 +843,6 @@ type(erlang, is_boolean, 1, Xs) ->
strict(arg_types(erlang, is_boolean, 1), Xs, Fun);
type(erlang, is_builtin, 3, Xs) ->
strict(arg_types(erlang, is_builtin, 3), Xs, fun (_) -> t_boolean() end);
-type(erlang, is_constant, 1, Xs) ->
- Fun = fun (X) ->
- check_guard(X, fun (Y) -> t_is_constant(Y) end, t_constant())
- end,
- strict(arg_types(erlang, is_constant, 1), Xs, Fun);
type(erlang, is_float, 1, Xs) ->
Fun = fun (X) ->
check_guard(X, fun (Y) -> t_is_float(Y) end, t_float())
@@ -1202,11 +1195,13 @@ type(erlang, process_flag, 2, Xs) ->
case t_atom_vals(Flag) of
['error_handler'] -> t_atom();
['min_heap_size'] -> t_non_neg_integer();
+ ['min_bin_vheap_size'] -> t_non_neg_integer();
['scheduler'] -> t_non_neg_integer();
['monitor_nodes'] -> t_boolean();
['priority'] -> t_process_priority_level();
['save_calls'] -> t_non_neg_integer();
['trap_exit'] -> t_boolean();
+ ['sensitive'] -> t_boolean();
List when is_list(List) ->
T_process_flag_returns;
unknown ->
@@ -1503,6 +1498,8 @@ type(erlang, system_flag, 2, Xs) ->
t_non_neg_fixnum();
['min_heap_size'] ->
t_non_neg_fixnum();
+ ['min_bin_vheap_size'] ->
+ t_non_neg_fixnum();
['multi_scheduling'] ->
t_system_multi_scheduling();
['schedulers_online'] ->
@@ -1546,8 +1543,12 @@ type(erlang, system_info, 1, Xs) ->
t_list(t_tuple([t_atom(),
t_list(t_tuple([t_atom(),
t_any()]))]))]);
+ ['build_type'] ->
+ t_system_build_type_return();
['break_ignored'] ->
t_boolean();
+ ['c_compiler_used'] ->
+ t_tuple([t_atom(), t_any()]);
['cpu_topology'] ->
t_system_cpu_topology();
['compat_rel'] ->
@@ -1560,6 +1561,8 @@ type(erlang, system_info, 1, Xs) ->
t_binary();
['dist_ctrl'] ->
t_list(t_tuple([t_atom(), t_sup([t_pid(), t_port])]));
+ ['driver_version'] ->
+ t_string();
%% elib_malloc is intentionally not included,
%% because it scheduled for removal in R15.
['endian'] ->
@@ -1573,7 +1576,9 @@ type(erlang, system_info, 1, Xs) ->
['heap_sizes'] ->
t_list(t_integer());
['heap_type'] ->
- t_sup([t_atom('private'), t_atom('hybrid')]);
+ t_sup([t_atom('private'),
+ t_atom('shared'),
+ t_atom('hybrid')]);
['hipe_architecture'] ->
t_atoms(['amd64', 'arm', 'powerpc', 'ppc64',
'undefined', 'ultrasparc', 'x86']);
@@ -1581,12 +1586,20 @@ type(erlang, system_info, 1, Xs) ->
t_binary();
['internal_cpu_topology'] -> %% Undocumented internal feature
t_internal_cpu_topology();
+ ['kernel_poll'] ->
+ t_boolean();
['loaded'] ->
t_binary();
['logical_processors'] ->
t_non_neg_fixnum();
['machine'] ->
t_string();
+ ['min_heap_size'] ->
+ t_tuple([t_atom('min_heap_size'),
+ t_non_neg_integer()]);
+ ['min_bin_vheap_size'] ->
+ t_tuple([t_atom('min_bin_vheap_size'),
+ t_non_neg_integer()]);
['multi_scheduling'] ->
t_system_multi_scheduling();
['multi_scheduling_blockers'] ->
@@ -1601,6 +1614,8 @@ type(erlang, system_info, 1, Xs) ->
t_non_neg_fixnum(),
t_non_neg_fixnum()]),
t_string());
+ ['otp_release'] ->
+ t_string();
['process_count'] ->
t_non_neg_fixnum();
['process_limit'] ->
@@ -1630,6 +1645,8 @@ type(erlang, system_info, 1, Xs) ->
t_non_neg_fixnum();
['trace_control_word'] ->
t_integer();
+ ['update_cpu_info'] ->
+ t_sup([t_atom('changed'), t_atom('unchanged')]);
['version'] ->
t_string();
['wordsize'] ->
@@ -3567,8 +3584,6 @@ arg_types(erlang, is_boolean, 1) ->
[t_any()];
arg_types(erlang, is_builtin, 3) ->
[t_atom(), t_atom(), t_arity()];
-arg_types(erlang, is_constant, 1) ->
- [t_any()];
arg_types(erlang, is_float, 1) ->
[t_any()];
arg_types(erlang, is_function, 1) ->
@@ -3747,8 +3762,13 @@ arg_types(erlang, pre_loaded, 0) ->
arg_types(erlang, process_display, 2) ->
[t_pid(), t_atom('backtrace')];
arg_types(erlang, process_flag, 2) ->
- [t_sup([t_atom('trap_exit'), t_atom('error_handler'),
- t_atom('min_heap_size'), t_atom('priority'), t_atom('save_calls'),
+ [t_sup([t_atom('trap_exit'),
+ t_atom('error_handler'),
+ t_atom('min_heap_size'),
+ t_atom('min_bin_vheap_size'),
+ t_atom('priority'),
+ t_atom('save_calls'),
+ t_atom('sensitive'),
t_atom('scheduler'), % undocumented
t_atom('monitor_nodes'), % undocumented
t_tuple([t_atom('monitor_nodes'), t_list()])]), % undocumented
@@ -3861,6 +3881,7 @@ arg_types(erlang, system_flag, 2) ->
t_atom('display_items'), % undocumented
t_atom('fullsweep_after'),
t_atom('min_heap_size'),
+ t_atom('min_bin_vheap_size'),
t_atom('multi_scheduling'),
t_atom('schedulers_online'),
t_atom('scheduler_bind_type'),
@@ -4733,6 +4754,7 @@ t_spawn_options() ->
t_atom('monitor'),
t_tuple([t_atom('priority'), t_process_priority_level()]),
t_tuple([t_atom('min_heap_size'), t_fixnum()]),
+ t_tuple([t_atom('min_bin_vheap_size'), t_fixnum()]),
t_tuple([t_atom('fullsweep_after'), t_fixnum()])]).
t_spawn_opt_return(List) ->
@@ -4821,6 +4843,17 @@ t_system_profile_return() ->
t_sup(t_atom('undefined'),
t_tuple([t_sup(t_pid(), t_port()), t_system_profile_options()])).
+t_system_build_type_return() ->
+ t_sup([t_atom('opt'),
+ t_atom('debug'),
+ t_atom('purify'),
+ t_atom('quantify'),
+ t_atom('purecov'),
+ t_atom('gcov'),
+ t_atom('valgrind'),
+ t_atom('gprof'),
+ t_atom('lcnt')]).
+
%% =====================================================================
%% These are used for the built-in functions of 'ets'
%% =====================================================================
diff --git a/lib/hipe/flow/Makefile b/lib/hipe/flow/Makefile
index 02f610587b..bbe8ef8666 100644
--- a/lib/hipe/flow/Makefile
+++ b/lib/hipe/flow/Makefile
@@ -65,7 +65,7 @@ DOC_FILES= $(MODULES:%=$(DOCS)/%.html)
include ../native.mk
-ERL_COMPILE_FLAGS += +warn_exported_vars +warn_missing_spec +warn_untyped_record
+ERL_COMPILE_FLAGS += +warn_exported_vars +warn_missing_spec # +warn_untyped_record
# ----------------------------------------------------
# Targets
diff --git a/lib/hipe/icode/Makefile b/lib/hipe/icode/Makefile
index eced90b0ec..bd6436c8b3 100644
--- a/lib/hipe/icode/Makefile
+++ b/lib/hipe/icode/Makefile
@@ -83,7 +83,7 @@ DOC_FILES= $(DOC_MODULES:%=$(DOCS)/%.html)
include ../native.mk
-ERL_COMPILE_FLAGS += +warn_unused_import +warn_missing_spec +warn_untyped_record
+ERL_COMPILE_FLAGS += +warn_unused_import +warn_missing_spec # +warn_untyped_record
# ----------------------------------------------------
# Targets
diff --git a/lib/hipe/icode/hipe_beam_to_icode.erl b/lib/hipe/icode/hipe_beam_to_icode.erl
index 992f387bd5..2d2b414a70 100644
--- a/lib/hipe/icode/hipe_beam_to_icode.erl
+++ b/lib/hipe/icode/hipe_beam_to_icode.erl
@@ -465,10 +465,6 @@ trans_fun([{test,is_nil,{f,Lbl},[Arg]}|Instructions], Env) ->
trans_fun([{test,is_binary,{f,Lbl},[Arg]}|Instructions], Env) ->
{Code,Env1} = trans_type_test(binary,Lbl,Arg,Env),
[Code | trans_fun(Instructions,Env1)];
-%%--- is_constant ---
-trans_fun([{test,is_constant,{f,Lbl},[Arg]}|Instructions], Env) ->
- {Code,Env1} = trans_type_test(constant,Lbl,Arg,Env),
- [Code | trans_fun(Instructions,Env1)];
%%--- is_list ---
trans_fun([{test,is_list,{f,Lbl},[Arg]}|Instructions], Env) ->
{Code,Env1} = trans_type_test(list,Lbl,Arg,Env),
diff --git a/lib/hipe/icode/hipe_icode_inline_bifs.erl b/lib/hipe/icode/hipe_icode_inline_bifs.erl
index 27296dcad5..9a2fb7846a 100644
--- a/lib/hipe/icode/hipe_icode_inline_bifs.erl
+++ b/lib/hipe/icode/hipe_icode_inline_bifs.erl
@@ -29,7 +29,7 @@
%% Currently inlined BIFs:
%% and, or, xor, not, <, >, >=, =<, ==, /=, =/=, =:=
-%% is_atom, is_boolean, is_binary, is_constant, is_float, is_function,
+%% is_atom, is_boolean, is_binary, is_float, is_function,
%% is_integer, is_list, is_pid, is_port, is_reference, is_tuple
-module(hipe_icode_inline_bifs).
@@ -131,7 +131,6 @@ is_type_test(Name) ->
is_boolean -> {true, boolean};
is_function -> {true, function};
is_reference -> {true, reference};
- is_constant -> {true, constant};
is_port -> {true, port};
_ -> false
end.
diff --git a/lib/hipe/icode/hipe_icode_type.erl b/lib/hipe/icode/hipe_icode_type.erl
index 3f9488d7c3..cae4325b9e 100644
--- a/lib/hipe/icode/hipe_icode_type.erl
+++ b/lib/hipe/icode/hipe_icode_type.erl
@@ -899,9 +899,7 @@ test_type0(list, T) ->
test_type0(cons, T) ->
t_is_cons(T);
test_type0(nil, T) ->
- t_is_nil(T);
-test_type0(constant, T) ->
- t_is_constant(T).
+ t_is_nil(T).
true_branch_info(integer) ->
@@ -940,8 +938,6 @@ true_branch_info(nil) ->
t_nil();
true_branch_info(boolean) ->
t_boolean();
-true_branch_info(constant) ->
- t_constant();
true_branch_info(T) ->
exit({?MODULE,unknown_typetest,T}).
diff --git a/lib/hipe/main/hipe.app.src b/lib/hipe/main/hipe.app.src
index e5d6d1e540..c05aec4c4a 100644
--- a/lib/hipe/main/hipe.app.src
+++ b/lib/hipe/main/hipe.app.src
@@ -74,7 +74,6 @@
hipe_arm_specific,
hipe_bb,
hipe_beam_to_icode,
- hipe_ceach,
hipe_coalescing_regalloc,
hipe_consttab,
hipe_data_pp,
diff --git a/lib/hipe/main/hipe.erl b/lib/hipe/main/hipe.erl
index 309d847374..1be679a13f 100644
--- a/lib/hipe/main/hipe.erl
+++ b/lib/hipe/main/hipe.erl
@@ -574,12 +574,8 @@ file(File, Options) when is_atom(File) ->
disasm(File) ->
case beam_disasm:file(File) of
#beam_file{labeled_exports = LabeledExports,
- compile_info = CompInfo0,
+ compile_info = CompInfo,
code = BeamCode} ->
- CompInfo = case CompInfo0 of
- none -> [];
- _ -> CompInfo0
- end,
CompOpts = proplists:get_value(options, CompInfo, []),
HCompOpts = case lists:keyfind(hipe, 1, CompOpts) of
{hipe, L} when is_list(L) -> L;
diff --git a/lib/hipe/opt/Makefile b/lib/hipe/opt/Makefile
index 74fde26c0b..4596201801 100644
--- a/lib/hipe/opt/Makefile
+++ b/lib/hipe/opt/Makefile
@@ -63,7 +63,7 @@ DOC_FILES= $(MODULES:%=$(DOCS)/%.html)
include ../native.mk
-ERL_COMPILE_FLAGS += +warn_exported_vars +warn_missing_spec +warn_untyped_record
+ERL_COMPILE_FLAGS += +warn_exported_vars +warn_missing_spec # +warn_untyped_record
# ----------------------------------------------------
# Targets
diff --git a/lib/hipe/rtl/Makefile b/lib/hipe/rtl/Makefile
index 690045b978..48086ec79f 100644
--- a/lib/hipe/rtl/Makefile
+++ b/lib/hipe/rtl/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2011. All Rights Reserved.
+# Copyright Ericsson AB 2001-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -139,27 +139,35 @@ hipe_literals.hrl: $(HIPE_MKLITERALS)
../main/hipe.hrl: ../vsn.mk ../main/hipe.hrl.src
(cd ../main && $(MAKE) hipe.hrl)
-$(EBIN)/hipe_rtl.beam: hipe_rtl.hrl ../main/hipe.hrl
-$(EBIN)/hipe_rtl_arch.beam: hipe_rtl.hrl hipe_literals.hrl
-$(EBIN)/hipe_rtl_binary.beam: hipe_rtl.hrl hipe_literals.hrl
-$(EBIN)/hipe_rtl_bin_util.beam: hipe_rtl.hrl hipe_literals.hrl
-$(EBIN)/hipe_rtl_cfg.beam: hipe_rtl.hrl ../flow/cfg.hrl ../flow/cfg.inc ../main/hipe.hrl
-$(EBIN)/hipe_rtl_cleanup_const.beam: hipe_rtl.hrl
-$(EBIN)/hipe_rtl_liveness.beam: hipe_rtl.hrl ../flow/cfg.hrl ../flow/liveness.inc
-$(EBIN)/hipe_icode2rtl.beam: hipe_literals.hrl ../main/hipe.hrl ../icode/hipe_icode.hrl
-$(EBIN)/hipe_tagscheme.beam: hipe_rtl.hrl hipe_literals.hrl
-$(EBIN)/hipe_rtl_primops.beam: hipe_rtl.hrl ../icode/hipe_icode_primops.hrl hipe_literals.hrl ../main/hipe.hrl
+# 2012-02-24. Please keep these dependencies up to date. They tend to rot.
+# grep ^-include *.erl says a lot, but you need to dig further, e.g:
+# grep ^-include ../flow/*.{hrl,inc}
+$(EBIN)/hipe_icode2rtl.beam: \
+ ../main/hipe.hrl ../icode/hipe_icode.hrl hipe_literals.hrl
+$(EBIN)/hipe_rtl_arch.beam: hipe_literals.hrl
$(EBIN)/hipe_rtl_arith_32.beam: ../main/hipe.hrl hipe_rtl_arith.inc
$(EBIN)/hipe_rtl_arith_64.beam: ../main/hipe.hrl hipe_rtl_arith.inc
-$(EBIN)/hipe_rtl_bs_ops.beam: hipe_literals.hrl ../main/hipe.hrl
-$(EBIN)/hipe_rtl_cerl_bs_ops.beam: ../main/hipe.hrl hipe_literals.hrl hipe_rtl.hrl
-$(EBIN)/hipe_rtl_exceptions.beam: hipe_literals.hrl ../main/hipe.hrl
-$(EBIN)/hipe_rtl_inline_bs_ops.beam: hipe_rtl.hrl hipe_literals.hrl ../main/hipe.hrl
+$(EBIN)/hipe_rtl_binary_construct.beam: \
+ ../main/hipe.hrl hipe_rtl.hrl hipe_literals.hrl
+$(EBIN)/hipe_rtl_binary_match.beam: hipe_literals.hrl
+$(EBIN)/hipe_rtl_cfg.beam: \
+ ../main/hipe.hrl hipe_rtl.hrl ../flow/cfg.hrl ../flow/cfg.inc
+$(EBIN)/hipe_rtl_cleanup_const.beam: hipe_rtl.hrl
+$(EBIN)/hipe_rtl.beam: ../main/hipe.hrl hipe_rtl.hrl
+$(EBIN)/hipe_rtl_exceptions.beam: ../main/hipe.hrl hipe_literals.hrl
+$(EBIN)/hipe_rtl_lcm.beam: ../main/hipe.hrl hipe_rtl.hrl ../flow/cfg.hrl
+$(EBIN)/hipe_rtl_liveness.beam: hipe_rtl.hrl ../flow/cfg.hrl ../flow/liveness.inc
$(EBIN)/hipe_rtl_mk_switch.beam: ../main/hipe.hrl
-$(EBIN)/hipe_rtl_lcm.beam: ../flow/cfg.hrl hipe_rtl.hrl
-$(EBIN)/hipe_rtl_symbolic.beam: hipe_rtl.hrl hipe_literals.hrl ../flow/cfg.hrl ../icode/hipe_icode_primops.hrl
-$(EBIN)/hipe_rtl_varmap.beam: ../main/hipe.hrl ../icode/hipe_icode.hrl
-
-$(EBIN)/hipe_rtl_ssa.beam: ../ssa/hipe_ssa.inc ../main/hipe.hrl ../ssa/hipe_ssa_liveness.inc hipe_rtl.hrl
-$(EBIN)/hipe_rtl_ssa_const_prop.beam: hipe_rtl.hrl ../main/hipe.hrl ../flow/cfg.hrl ../ssa/hipe_ssa_const_prop.inc
-$(EBIN)/hipe_rtl_ssapre.beam: ../main/hipe.hrl ../flow/cfg.hrl hipe_rtl.hrl
+$(EBIN)/hipe_rtl_primops.beam: ../main/hipe.hrl \
+ ../icode/hipe_icode_primops.hrl hipe_rtl.hrl hipe_literals.hrl
+$(EBIN)/hipe_rtl_ssa_avail_expr.beam: ../main/hipe.hrl hipe_rtl.hrl
+$(EBIN)/hipe_rtl_ssa_const_prop.beam: ../main/hipe.hrl hipe_rtl.hrl \
+ ../flow/cfg.hrl ../ssa/hipe_ssa_const_prop.inc
+$(EBIN)/hipe_rtl_ssa.beam: hipe_rtl.hrl \
+ ../main/hipe.hrl ../ssa/hipe_ssa_liveness.inc ../ssa/hipe_ssa.inc
+$(EBIN)/hipe_rtl_ssapre.beam: ../main/hipe.hrl hipe_rtl.hrl
+$(EBIN)/hipe_rtl_symbolic.beam: hipe_rtl.hrl hipe_literals.hrl \
+ ../icode/hipe_icode_primops.hrl
+$(EBIN)/hipe_rtl_varmap.beam: ../main/hipe.hrl \
+ ../misc/hipe_consttab.hrl ../icode/hipe_icode.hrl
+$(EBIN)/hipe_tagscheme.beam: hipe_rtl.hrl hipe_literals.hrl
diff --git a/lib/hipe/tools/hipe_tool.erl b/lib/hipe/tools/hipe_tool.erl
index 990805ceca..190a68ee56 100644
--- a/lib/hipe/tools/hipe_tool.erl
+++ b/lib/hipe/tools/hipe_tool.erl
@@ -30,6 +30,18 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-module(hipe_tool).
+-compile([{nowarn_deprecated_function,{gs,button,3}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,editor,3}},
+ {nowarn_deprecated_function,{gs,label,3}},
+ {nowarn_deprecated_function,{gs,listbox,3}},
+ {nowarn_deprecated_function,{gs,menu,3}},
+ {nowarn_deprecated_function,{gs,menubar,3}},
+ {nowarn_deprecated_function,{gs,menubutton,3}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
-export([start/0]).
diff --git a/lib/inviso/test/inviso_tool_SUITE.erl b/lib/inviso/test/inviso_tool_SUITE.erl
index 6b16e506eb..f8a9cea47f 100644
--- a/lib/inviso/test/inviso_tool_SUITE.erl
+++ b/lib/inviso/test/inviso_tool_SUITE.erl
@@ -52,7 +52,12 @@ end_per_group(_GroupName, Config) ->
%% -----------------------------------------------------------------------------
init_per_suite(Config) ->
- Config.
+ case test_server:is_native(lists) of
+ true ->
+ {skip,"Native libs -- tracing doesn't work"};
+ false ->
+ Config
+ end.
%% -----------------------------------------------------------------------------
end_per_suite(_Config) ->
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangAtom.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangAtom.java
index 4d53447164..60eef7a126 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangAtom.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangAtom.java
@@ -53,7 +53,7 @@ public class OtpErlangAtom extends OtpErlangObject implements Serializable,
if (atom.length() > maxAtomLength) {
throw new java.lang.IllegalArgumentException("Atom may not exceed "
- + maxAtomLength + " characters");
+ + maxAtomLength + " characters: " + atom);
}
this.atom = atom;
}
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangString.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangString.java
index 8cd900aada..be8b7c5c12 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangString.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangString.java
@@ -154,13 +154,16 @@ public class OtpErlangString extends OtpErlangObject implements Serializable,
* Unicode code points
*/
- public static int[] stringToCodePoints(final String s) {
- final int m = s.codePointCount(0, s.length());
- final int [] codePoints = new int[m];
- for (int i = 0, j = 0; j < m; i = s.offsetByCodePoints(i, 1), j++) {
- codePoints[j] = s.codePointAt(i);
- }
- return codePoints;
+ public static int[] stringToCodePoints(final String s) {
+ final int m = s.codePointCount(0, s.length());
+ final int[] codePoints = new int[m];
+ int j = 0;
+ for (int offset = 0; offset < s.length();) {
+ final int codepoint = s.codePointAt(offset);
+ codePoints[j++] = codepoint;
+ offset += Character.charCount(codepoint);
+ }
+ return codePoints;
}
/**
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java
index 71a419497a..b0b64e6953 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java
@@ -31,7 +31,7 @@ package com.ericsson.otp.erlang;
* the recipient of the message. When sending messages to other mailboxes, the
* recipient can only respond if the sender includes the pid as part of the
* message contents. The sender can determine his own pid by calling
- * {@link #self self()}.
+ * {@link #self() self()}.
* </p>
*
* <p>
@@ -141,7 +141,7 @@ public class OtpMbox {
* Get the registered name of this mailbox.
*
* @return the registered name of this mailbox, or null if the mailbox had
- * no registerd name.
+ * no registered name.
*/
public String getName() {
return name;
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpNode.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpNode.java
index d499fae3fb..be7c8e5b1a 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpNode.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpNode.java
@@ -182,7 +182,7 @@ public class OtpNode extends OtpLocalNode {
* Create an unnamed {@link OtpMbox mailbox} that can be used to send and
* receive messages with other, similar mailboxes and with Erlang processes.
* Messages can be sent to this mailbox by using its associated
- * {@link OtpMbox#self pid}.
+ * {@link OtpMbox#self() pid}.
*
* @return a mailbox.
*/
@@ -248,7 +248,7 @@ public class OtpNode extends OtpLocalNode {
* Create an named mailbox that can be used to send and receive messages
* with other, similar mailboxes and with Erlang processes. Messages can be
* sent to this mailbox by using its registered name or the associated
- * {@link OtpMbox#self pid}.
+ * {@link OtpMbox#self() pid}.
*
* @param name
* a name to register for this mailbox. The name must be unique
diff --git a/lib/jinterface/test/nc_SUITE.erl b/lib/jinterface/test/nc_SUITE.erl
index da54f5bf51..9c88400c2a 100644
--- a/lib/jinterface/test/nc_SUITE.erl
+++ b/lib/jinterface/test/nc_SUITE.erl
@@ -296,7 +296,8 @@ lists_roundtrip_2(Config) when is_list(Config) ->
{[z,23|24],tail3},
{[z|25],tail3},
{"abc123",sub3atom},
- {"abc",sub3atom}
+ {"abc",sub3atom},
+ {"abcdefg",codepointBug}
],
Trans =
fun ([_|T], tail) ->
@@ -308,7 +309,9 @@ lists_roundtrip_2(Config) when is_list(Config) ->
(L, tail3) when is_list(L) ->
null;
([_,_,_|L], sub3atom) ->
- list_to_atom(L)
+ list_to_atom(L);
+ (L, codepointBug) ->
+ L
end,
OutTrans =
fun ({L,Twist}) ->
diff --git a/lib/jinterface/test/nc_SUITE_data/echo_server.java b/lib/jinterface/test/nc_SUITE_data/echo_server.java
index 0550e4beb1..5ecb5b72a7 100644
--- a/lib/jinterface/test/nc_SUITE_data/echo_server.java
+++ b/lib/jinterface/test/nc_SUITE_data/echo_server.java
@@ -202,6 +202,12 @@ public class echo_server {
final OtpErlangAtom o = new OtpErlangAtom(s.stringValue()
.substring(3));
return o;
+ } else if (atomValue.equals("codepointBug")
+ && i instanceof OtpErlangString) {
+ final OtpErlangString s = (OtpErlangString) i;
+ final String ss = s.stringValue().substring(3, 6);
+ final int[] cps = OtpErlangString.stringToCodePoints(ss);
+ return s;
} else if (atomValue.equals("utf8")) {
if (i instanceof OtpErlangString) {
final OtpErlangString s = (OtpErlangString) i;
diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl
index 32a12e2b52..5d4f2eb70c 100644
--- a/lib/kernel/src/code_server.erl
+++ b/lib/kernel/src/code_server.erl
@@ -1317,15 +1317,21 @@ int_list([H|T]) when is_integer(H) -> int_list(T);
int_list([_|_]) -> false;
int_list([]) -> true.
+load_file(Mod0, {From,_}=Caller, St0) ->
+ Mod = to_atom(Mod0),
+ case pending_on_load(Mod, From, St0) of
+ no -> load_file_1(Mod, Caller, St0);
+ {yes,St} -> {noreply,St}
+ end.
-load_file(Mod, Caller, #state{path=Path,cache=no_cache}=St) ->
+load_file_1(Mod, Caller, #state{path=Path,cache=no_cache}=St) ->
case mod_to_bin(Path, Mod) of
error ->
{reply,{error,nofile},St};
{Mod,Binary,File} ->
try_load_module(File, Mod, Binary, Caller, St)
end;
-load_file(Mod, Caller, #state{cache=Cache}=St0) ->
+load_file_1(Mod, Caller, #state{cache=Cache}=St0) ->
Key = {obj,Mod},
case ets:lookup(Cache, Key) of
[] ->
diff --git a/lib/kernel/src/gen_sctp.erl b/lib/kernel/src/gen_sctp.erl
index 77ca26b845..d8954f0cf7 100644
--- a/lib/kernel/src/gen_sctp.erl
+++ b/lib/kernel/src/gen_sctp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -314,7 +314,7 @@ eof_or_abort(S, AssocId, Action) ->
-spec send(Socket, SndRcvInfo, Data) -> ok | {error, Reason} when
Socket :: sctp_socket(),
SndRcvInfo :: #sctp_sndrcvinfo{},
- Data :: binary | iolist(),
+ Data :: binary() | iolist(),
Reason :: term().
%% Full-featured send. Rarely needed.
@@ -331,7 +331,7 @@ send(S, SRI, Data) ->
Socket :: sctp_socket(),
Assoc :: #sctp_assoc_change{} | assoc_id(),
Stream :: integer(),
- Data :: binary | iolist(),
+ Data :: binary() | iolist(),
Reason :: term().
send(S, #sctp_assoc_change{assoc_id=AssocId}, Stream, Data)
diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl
index 10ab3e4370..99b0cd2ffb 100644
--- a/lib/kernel/test/code_SUITE.erl
+++ b/lib/kernel/test/code_SUITE.erl
@@ -30,9 +30,9 @@
load_cached/1, start_node_with_cache/1, add_and_rehash/1,
where_is_file_cached/1, where_is_file_no_cache/1,
purge_stacktrace/1, mult_lib_roots/1, bad_erl_libs/1,
- code_archive/1, code_archive2/1, on_load/1,
- big_boot_embedded/1,
- on_load_embedded/1, on_load_errors/1, native_early_modules/1]).
+ code_archive/1, code_archive2/1, on_load/1, on_load_binary/1,
+ on_load_embedded/1, on_load_errors/1, big_boot_embedded/1,
+ native_early_modules/1]).
-export([init_per_testcase/2, end_per_testcase/2,
init_per_suite/1, end_per_suite/1,
@@ -55,8 +55,8 @@ all() ->
add_and_rehash, where_is_file_no_cache,
where_is_file_cached, purge_stacktrace, mult_lib_roots,
bad_erl_libs, code_archive, code_archive2, on_load,
- on_load_embedded, big_boot_embedded, on_load_errors,
- native_early_modules].
+ on_load_binary, on_load_embedded, on_load_errors,
+ big_boot_embedded, native_early_modules].
groups() ->
[].
@@ -1286,6 +1286,45 @@ on_load_wait_for_all([Ref|T]) ->
end;
on_load_wait_for_all([]) -> ok.
+on_load_binary(_) ->
+ Master = on_load_binary_test_case_process,
+ register(Master, self()),
+
+ %% Construct, compile and pretty-print.
+ Mod = on_load_binary,
+ File = atom_to_list(Mod) ++ ".erl",
+ Forms = [{attribute,1,file,{File,1}},
+ {attribute,1,module,Mod},
+ {attribute,2,export,[{ok,0}]},
+ {attribute,3,on_load,{init,0}},
+ {function,5,init,0,
+ [{clause,5,[],[],
+ [{op,6,'!',
+ {atom,6,Master},
+ {tuple,6,[{atom,6,Mod},{call,6,{atom,6,self},[]}]}},
+ {'receive',7,[{clause,8,[{atom,8,go}],[],[{atom,8,ok}]}]}]}]},
+ {function,11,ok,0,[{clause,11,[],[],[{atom,11,true}]}]}],
+ {ok,Mod,Bin} = compile:forms(Forms, [report]),
+ [io:put_chars(erl_pp:form(F)) || F <- Forms],
+
+ {Pid1,Ref1} = spawn_monitor(fun() ->
+ code:load_binary(Mod, File, Bin),
+ true = on_load_binary:ok()
+ end),
+ receive {Mod,OnLoadPid} -> ok end,
+ {Pid2,Ref2} = spawn_monitor(fun() ->
+ true = on_load_binary:ok()
+ end),
+ erlang:yield(),
+ OnLoadPid ! go,
+ receive {'DOWN',Ref1,process,Pid1,Exit1} -> ok end,
+ receive {'DOWN',Ref2,process,Pid2,Exit2} -> ok end,
+ normal = Exit1,
+ normal = Exit2,
+ true = code:delete(on_load_binary),
+ false = code:purge(on_load_binary),
+ ok.
+
on_load_embedded(Config) when is_list(Config) ->
try
on_load_embedded_1(Config)
diff --git a/lib/kernel/test/erl_prim_loader_SUITE.erl b/lib/kernel/test/erl_prim_loader_SUITE.erl
index 7599a89779..d0d52c5ea7 100644
--- a/lib/kernel/test/erl_prim_loader_SUITE.erl
+++ b/lib/kernel/test/erl_prim_loader_SUITE.erl
@@ -175,10 +175,10 @@ wait_really_started(Node, N) ->
inet_disconnects(doc) -> ["Start a node using the 'inet' loading method, ",
"then lose the connection."];
inet_disconnects(Config) when is_list(Config) ->
- case os:type() of
- vxworks ->
- {comment, "VxWorks: tested separately"};
- _ ->
+ case test_server:is_native(erl_boot_server) of
+ true ->
+ {skip,"erl_boot_server is native"};
+ false ->
?line Name = erl_prim_test_inet_disconnects,
?line Host = host(),
?line Cookie = atom_to_list(erlang:get_cookie()),
diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl
index 85346762ac..2b6af7e1fb 100644
--- a/lib/kernel/test/file_SUITE.erl
+++ b/lib/kernel/test/file_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -78,7 +78,7 @@
-export([altname/1]).
--export([large_file/1]).
+-export([large_file/1, large_write/1]).
-export([read_line_1/1, read_line_2/1, read_line_3/1,read_line_4/1]).
@@ -92,6 +92,8 @@
-export([bytes/2, iterate/3]).
+%% System probe functions that might be handy to check from the shell
+-export([disc_free/1, memsize/0]).
-include_lib("test_server/include/test_server.hrl").
-include_lib("kernel/include/file.hrl").
@@ -106,7 +108,7 @@ all() ->
{group, compression}, {group, links}, copy,
delayed_write, read_ahead, segment_read, segment_write,
ipread, pid2name, interleaved_read_write, otp_5814,
- large_file, read_line_1, read_line_2, read_line_3,
+ large_file, large_write, read_line_1, read_line_2, read_line_3,
read_line_4, standard_io].
groups() ->
@@ -143,6 +145,13 @@ end_per_group(_GroupName, Config) ->
init_per_suite(Config) when is_list(Config) ->
+ SaslConfig = case application:start(sasl) of
+ {error, {already_started, sasl}} ->
+ [];
+ ok ->
+ [{sasl,started}]
+ end,
+ ok = application:start(os_mon),
case os:type() of
{win32, _} ->
Priv = ?config(priv_dir, Config),
@@ -154,9 +163,9 @@ init_per_suite(Config) when is_list(Config) ->
{ok, _} ->
[]
end,
- ?FILE_INIT(HasAccessTime++Config);
+ ?FILE_INIT(HasAccessTime++Config++SaslConfig);
_ ->
- ?FILE_INIT(Config)
+ ?FILE_INIT(Config++SaslConfig)
end.
end_per_suite(Config) when is_list(Config) ->
@@ -166,6 +175,13 @@ end_per_suite(Config) when is_list(Config) ->
_ ->
ok
end,
+ application:stop(os_mon),
+ case proplists:get_value(sasl, Config) of
+ started ->
+ application:stop(sasl);
+ _Else ->
+ ok
+ end,
?FILE_FINI(Config).
init_per_testcase(_Func, Config) ->
@@ -394,6 +410,7 @@ make_del_dir(Config) when is_list(Config) ->
%% Don't worry ;-) the parent directory should never be empty, right?
?line case ?FILE_MODULE:del_dir('..') of
{error, eexist} -> ok;
+ {error, eacces} -> ok; %OpenBSD
{error, einval} -> ok %FreeBSD
end,
?line {error, enoent} = ?FILE_MODULE:del_dir(""),
@@ -3287,50 +3304,13 @@ large_file(suite) ->
large_file(doc) ->
["Tests positioning in large files (> 4G)"];
large_file(Config) when is_list(Config) ->
- case {os:type(),os:version()} of
- {{win32,nt},_} ->
- do_large_file(Config);
- {{unix,sunos},{A,B,C}}
- when A == 5, B == 5, C >= 1; A == 5, B >= 6; A >= 6 ->
- do_large_file(Config);
- {{unix,Unix},_} when Unix =/= sunos ->
- N = unix_free(Config),
- io:format("Free: ~w KByte~n", [N]),
- if N < 5 * (1 bsl 20) ->
- %% Less than 5 GByte free
- {skipped,"Less than 5 GByte free"};
- true ->
- do_large_file(Config)
- end;
- _ ->
- {skipped,"Only supported on Win32, Unix or SunOS >= 5.5.1"}
- end.
+ run_large_file_test(Config,
+ fun(Name) -> do_large_file(Name) end,
+ "_large_file").
-unix_free(Config) ->
- Cmd = ["df -k '",?config(priv_dir, Config),"'"],
- DF0 = os:cmd(Cmd),
- io:format("$ ~s~n~s", [Cmd,DF0]),
- [$\n|DF1] = lists:dropwhile(fun ($\n) -> false; (_) -> true end, DF0),
- {ok,[N],_} = io_lib:fread(" ~*s ~d", DF1),
- N.
+do_large_file(Name) ->
+ ?line Watchdog = ?t:timetrap(?t:minutes(20)),
-do_large_file(Config) ->
- ?line Watchdog = ?t:timetrap(?t:minutes(5)),
- %%
- ?line Name = filename:join(?config(priv_dir, Config),
- ?MODULE_STRING ++ "_large_file"),
- ?line Tester = self(),
- Deleter =
- spawn(
- fun() ->
- Mref = erlang:monitor(process, Tester),
- receive
- {'DOWN',Mref,_,_,_} -> ok;
- {Tester,done} -> ok
- end,
- ?FILE_MODULE:delete(Name)
- end),
- %%
?line S = "1234567890",
L = length(S),
R = lists:reverse(S),
@@ -3366,15 +3346,36 @@ do_large_file(Config) ->
?line {ok,R} = ?FILE_MODULE:read(F1, L+1),
?line ok = ?FILE_MODULE:close(F1),
%%
- ?line Mref = erlang:monitor(process, Deleter),
- ?line Deleter ! {Tester,done},
- ?line receive {'DOWN',Mref,_,_,_} -> ok end,
- %%
?line ?t:timetrap_cancel(Watchdog),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+large_write(Config) when is_list(Config) ->
+ run_large_file_test(Config,
+ fun(Name) -> do_large_write(Name) end,
+ "_large_write").
+
+do_large_write(Name) ->
+ Memsize = memsize(),
+ io:format("Memsize = ~w Bytes~n", [Memsize]),
+ case {erlang:system_info(wordsize),Memsize} of
+ {4,_} ->
+ {skip,"Needs a 64-bit emulator"};
+ {8,N} when N < 6 bsl 30 ->
+ {skip,
+ "This machine has < 6 GB memory: "
+ ++integer_to_list(N)};
+ {8,_} ->
+ Size = 4*1024*1024*1024+1,
+ Bin = <<0:Size/unit:8>>,
+ ok = file:write_file(Name, Bin),
+ {ok,#file_info{size=Size}} = file:read_file_info(Name),
+ ok
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
response_analysis(Module, Function, Arguments) ->
@@ -3950,3 +3951,67 @@ flush(Msgs) ->
after 0 ->
lists:reverse(Msgs)
end.
+
+%%%
+%%% Support for testing large files.
+%%%
+
+run_large_file_test(Config, Run, Name) ->
+ case {os:type(),os:version()} of
+ {{win32,nt},_} ->
+ do_run_large_file_test(Config, Run, Name);
+ {{unix,sunos},OsVersion} when OsVersion < {5,5,1} ->
+ {skip,"Only supported on Win32, Unix or SunOS >= 5.5.1"};
+ {{unix,_},_} ->
+ N = disc_free(?config(priv_dir, Config)),
+ io:format("Free disk: ~w KByte~n", [N]),
+ if N < 5 * (1 bsl 20) ->
+ %% Less than 5 GByte free
+ {skip,"Less than 5 GByte free"};
+ true ->
+ do_run_large_file_test(Config, Run, Name)
+ end;
+ _ ->
+ {skip,"Only supported on Win32, Unix or SunOS >= 5.5.1"}
+ end.
+
+
+do_run_large_file_test(Config, Run, Name0) ->
+ Name = filename:join(?config(priv_dir, Config),
+ ?MODULE_STRING ++ Name0),
+
+ %% Set up a process that will delete this file.
+ Tester = self(),
+ Deleter =
+ spawn(
+ fun() ->
+ Mref = erlang:monitor(process, Tester),
+ receive
+ {'DOWN',Mref,_,_,_} -> ok;
+ {Tester,done} -> ok
+ end,
+ ?FILE_MODULE:delete(Name)
+ end),
+
+ %% Run the test case.
+ Res = Run(Name),
+
+ %% Delete file and finish deleter process.
+ Mref = erlang:monitor(process, Deleter),
+ Deleter ! {Tester,done},
+ receive {'DOWN',Mref,_,_,_} -> ok end,
+
+ Res.
+
+disc_free(Path) ->
+ Data = disksup:get_disk_data(),
+ {_,Tot,Perc} = hd(lists:filter(
+ fun({P,_Size,_Full}) ->
+ lists:prefix(filename:nativename(P),
+ filename:nativename(Path))
+ end, lists:reverse(lists:sort(Data)))),
+ round(Tot * (1-(Perc/100))).
+
+memsize() ->
+ {Tot,_Used,_} = memsup:get_memory_data(),
+ Tot.
diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl
index ccf26ee034..3e2202922c 100644
--- a/lib/kernel/test/prim_file_SUITE.erl
+++ b/lib/kernel/test/prim_file_SUITE.erl
@@ -52,6 +52,10 @@
list_dir_limit/1]).
-export([advise/1]).
+-export([large_write/1]).
+
+%% System probe functions that might be handy to check from the shell
+-export([unix_free/1]).
-include_lib("test_server/include/test_server.hrl").
-include_lib("kernel/include/file.hrl").
@@ -83,7 +87,7 @@ groups() ->
cur_dir_1a, cur_dir_1b]},
{files, [],
[{group, open}, {group, pos}, {group, file_info},
- truncate, sync, datasync, advise]},
+ truncate, sync, datasync, advise, large_write]},
{open, [],
[open1, modes, close, access, read_write, pread_write,
append, exclusive]},
@@ -290,6 +294,7 @@ make_del_dir(Config, Handle, Suffix) ->
%% Don't worry ;-) the parent directory should never be empty, right?
?line case ?PRIM_FILE_call(del_dir, Handle, [".."]) of
{error, eexist} -> ok;
+ {error, eacces} -> ok; %OpenBSD
{error, einval} -> ok %FreeBSD
end,
?line {error, enoent} = ?PRIM_FILE_call(del_dir, Handle, [""]),
@@ -1322,6 +1327,41 @@ advise(Config) when is_list(Config) ->
?line test_server:timetrap_cancel(Dog),
ok.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+large_write(Config) when is_list(Config) ->
+ run_large_file_test(Config,
+ fun(Name) -> do_large_write(Name) end,
+ "_large_write").
+
+do_large_write(Name) ->
+ Dog = test_server:timetrap(test_server:minutes(60)),
+ ChunkSize = (256 bsl 20) + 1, % 256 M + 1
+ Chunks = 16, % times 16 -> 4 G + 16
+ Base = 100,
+ Interleave = lists:seq(Base+1, Base+Chunks),
+ Chunk = <<0:ChunkSize/unit:8>>,
+ Data = zip_data(lists:duplicate(Chunks, Chunk), Interleave),
+ Size = Chunks * ChunkSize + Chunks, % 4 G + 32
+ Wordsize = erlang:system_info(wordsize),
+ case prim_file:write_file(Name, Data) of
+ ok when Wordsize =:= 8 ->
+ {ok,#file_info{size=Size}} = file:read_file_info(Name),
+ {ok,Fd} = prim_file:open(Name, [read]),
+ check_large_write(Dog, Fd, ChunkSize, 0, Interleave);
+ {error,einval} when Wordsize =:= 4 ->
+ ok
+ end.
+
+check_large_write(Dog, Fd, ChunkSize, Pos, [X|Interleave]) ->
+ Pos1 = Pos + ChunkSize,
+ {ok,Pos1} = prim_file:position(Fd, {cur,ChunkSize}),
+ {ok,[X]} = prim_file:read(Fd, 1),
+ check_large_write(Dog, Fd, ChunkSize, Pos1+1, Interleave);
+check_large_write(Dog, Fd, _, _, []) ->
+ eof = prim_file:read(Fd, 1),
+ test_server:timetrap_cancel(Dog),
+ ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2044,3 +2084,70 @@ list_dir_limit_cleanup(Dir, Handle, N, Cnt) ->
?PRIM_FILE:delete(Handle, filename:join(Dir, Name)),
list_dir_limit_cleanup(Dir, Handle, N, Cnt+1).
+%%%
+%%% Support for testing large files.
+%%%
+
+run_large_file_test(Config, Run, Name) ->
+ case {os:type(),os:version()} of
+ {{win32,nt},_} ->
+ do_run_large_file_test(Config, Run, Name);
+ {{unix,sunos},OsVersion} when OsVersion < {5,5,1} ->
+ {skip,"Only supported on Win32, Unix or SunOS >= 5.5.1"};
+ {{unix,_},_} ->
+ N = unix_free(?config(priv_dir, Config)),
+ io:format("Free disk: ~w KByte~n", [N]),
+ if N < 5 bsl 20 ->
+ %% Less than 5 GByte free
+ {skip,"Less than 5 GByte free disk"};
+ true ->
+ do_run_large_file_test(Config, Run, Name)
+ end;
+ _ ->
+ {skip,"Only supported on Win32, Unix or SunOS >= 5.5.1"}
+ end.
+
+
+do_run_large_file_test(Config, Run, Name0) ->
+ Name = filename:join(?config(priv_dir, Config),
+ ?MODULE_STRING ++ Name0),
+
+ %% Set up a process that will delete this file.
+ Tester = self(),
+ Deleter =
+ spawn(
+ fun() ->
+ Mref = erlang:monitor(process, Tester),
+ receive
+ {'DOWN',Mref,_,_,_} -> ok;
+ {Tester,done} -> ok
+ end,
+ prim_file:delete(Name)
+ end),
+
+ %% Run the test case.
+ Res = Run(Name),
+
+ %% Delete file and finish deleter process.
+ Mref = erlang:monitor(process, Deleter),
+ Deleter ! {Tester,done},
+ receive {'DOWN',Mref,_,_,_} -> ok end,
+
+ Res.
+
+unix_free(Path) ->
+ Cmd = ["df -k '",Path,"'"],
+ DF0 = os:cmd(Cmd),
+ io:format("$ ~s~n~s", [Cmd,DF0]),
+ Lines = re:split(DF0, "\n", [trim,{return,list}]),
+ Last = lists:last(Lines),
+ RE = "^[^\\s]*\\s+\\d+\\s+\\d+\\s+(\\d+)",
+ {match,[Avail]} = re:run(Last, RE, [{capture,all_but_first,list}]),
+ list_to_integer(Avail).
+
+zip_data([A|As], [B|Bs]) ->
+ [[A,B]|zip_data(As, Bs)];
+zip_data([], Bs) ->
+ Bs;
+zip_data(As, []) ->
+ As.
diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk
index 76c62ece67..76d3003ff4 100644
--- a/lib/kernel/vsn.mk
+++ b/lib/kernel/vsn.mk
@@ -1 +1 @@
-KERNEL_VSN = 2.15
+KERNEL_VSN = 2.15.1
diff --git a/lib/mnesia/src/mnesia_locker.erl b/lib/mnesia/src/mnesia_locker.erl
index de4811f8e4..a22c95d454 100644
--- a/lib/mnesia/src/mnesia_locker.erl
+++ b/lib/mnesia/src/mnesia_locker.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -66,7 +66,7 @@
-record(queue, {oid, tid, op, pid, lucky}).
-%% mnesia_held_locks: contain {Oid, Op, Tid} entries (bag)
+%% mnesia_held_locks: contain {Oid, MaxLock, [{Op, Tid}]} entries
-define(match_oid_held_locks(Oid), {Oid, '_', '_'}).
%% mnesia_tid_locks: contain {Tid, Oid, Op} entries (bag)
-define(match_oid_tid_locks(Tid), {Tid, '_', '_'}).
@@ -83,7 +83,7 @@ start() ->
init(Parent) ->
register(?MODULE, self()),
process_flag(trap_exit, true),
- ?ets_new_table(mnesia_held_locks, [bag, private, named_table]),
+ ?ets_new_table(mnesia_held_locks, [ordered_set, private, named_table]),
?ets_new_table(mnesia_tid_locks, [bag, private, named_table]),
?ets_new_table(mnesia_sticky_locks, [set, private, named_table]),
?ets_new_table(mnesia_lock_queue, [bag, private, named_table, {keypos, 2}]),
@@ -235,10 +235,17 @@ loop(State) ->
loop(State)
end.
-set_lock(Tid, Oid, Op) ->
- ?dbg("Granted ~p ~p ~p~n", [Tid,Oid,Op]),
- ?ets_insert(mnesia_held_locks, {Oid, Op, Tid}),
- ?ets_insert(mnesia_tid_locks, {Tid, Oid, Op}).
+set_lock(Tid, Oid, Op, []) ->
+ ?ets_insert(mnesia_tid_locks, {Tid, Oid, Op}),
+ ?ets_insert(mnesia_held_locks, {Oid, Op, [{Op, Tid}]});
+set_lock(Tid, Oid, read, [{Oid, Prev, Items}]) ->
+ ?ets_insert(mnesia_tid_locks, {Tid, Oid, read}),
+ ?ets_insert(mnesia_held_locks, {Oid, Prev, [{read, Tid}|Items]});
+set_lock(Tid, Oid, write, [{Oid, _Prev, Items}]) ->
+ ?ets_insert(mnesia_tid_locks, {Tid, Oid, write}),
+ ?ets_insert(mnesia_held_locks, {Oid, write, [{write, Tid}|Items]});
+set_lock(Tid, Oid, Op, undefined) ->
+ set_lock(Tid, Oid, Op, ?ets_lookup(mnesia_held_locks, Oid)).
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Acquire locks
@@ -261,14 +268,14 @@ try_lock(Tid, Op, Pid, Oid) ->
try_lock(Tid, Op, SimpleOp, Lock, Pid, Oid) ->
case can_lock(Tid, Lock, Oid, {no, bad_luck}) of
- yes ->
- Reply = grant_lock(Tid, SimpleOp, Lock, Oid),
+ {yes, Default} ->
+ Reply = grant_lock(Tid, SimpleOp, Lock, Oid, Default),
reply(Pid, Reply);
- {no, Lucky} ->
+ {{no, Lucky},_} ->
C = #cyclic{op = SimpleOp, lock = Lock, oid = Oid, lucky = Lucky},
?dbg("Rejected ~p ~p ~p ~p ~n", [Tid, Oid, Lock, Lucky]),
reply(Pid, {not_granted, C});
- {queue, Lucky} ->
+ {{queue, Lucky},_} ->
?dbg("Queued ~p ~p ~p ~p ~n", [Tid, Oid, Lock, Lucky]),
%% Append to queue: Nice place for trace output
?ets_insert(mnesia_lock_queue,
@@ -277,16 +284,16 @@ try_lock(Tid, Op, SimpleOp, Lock, Pid, Oid) ->
?ets_insert(mnesia_tid_locks, {Tid, Oid, {queued, Op}})
end.
-grant_lock(Tid, read, Lock, Oid = {Tab, Key})
+grant_lock(Tid, read, Lock, Oid = {Tab, Key}, Default)
when Key /= ?ALL, Tab /= ?GLOBAL ->
case node(Tid#tid.pid) == node() of
true ->
- set_lock(Tid, Oid, Lock),
+ set_lock(Tid, Oid, Lock, Default),
{granted, lookup_in_client};
false ->
try
Val = mnesia_lib:db_get(Tab, Key), %% lookup as well
- set_lock(Tid, Oid, Lock),
+ set_lock(Tid, Oid, Lock, Default),
{granted, Val}
catch _:_Reason ->
%% Table has been deleted from this node,
@@ -296,19 +303,19 @@ grant_lock(Tid, read, Lock, Oid = {Tab, Key})
{not_granted, C}
end
end;
-grant_lock(Tid, {ix_read,IxKey,Pos}, Lock, Oid = {Tab, _}) ->
+grant_lock(Tid, {ix_read,IxKey,Pos}, Lock, Oid = {Tab, _}, Default) ->
try
Res = ix_read_res(Tab, IxKey,Pos),
- set_lock(Tid, Oid, Lock),
+ set_lock(Tid, Oid, Lock, Default),
{granted, Res, [?ALL]}
catch _:_ ->
{not_granted, {no_exists, Tab, {index, [Pos]}}}
end;
-grant_lock(Tid, read, Lock, Oid) ->
- set_lock(Tid, Oid, Lock),
+grant_lock(Tid, read, Lock, Oid, Default) ->
+ set_lock(Tid, Oid, Lock, Default),
{granted, ok};
-grant_lock(Tid, write, Lock, Oid) ->
- set_lock(Tid, Oid, Lock),
+grant_lock(Tid, write, Lock, Oid, Default) ->
+ set_lock(Tid, Oid, Lock, Default),
granted.
%% 1) Impose an ordering on all transactions favour old (low tid) transactions
@@ -318,55 +325,40 @@ grant_lock(Tid, write, Lock, Oid) ->
%% 3) TabLocks is the problem :-) They should not starve and not deadlock
%% handle tablocks in queue as they had locks on unlocked records.
-can_lock(Tid, read, {Tab, Key}, AlreadyQ) when Key /= ?ALL ->
- %% The key is bound, no need for the other BIF
- Oid = {Tab, Key},
- ObjLocks = ?ets_match_object(mnesia_held_locks, {Oid, write, '_'}),
- TabLocks = ?ets_match_object(mnesia_held_locks, {{Tab, ?ALL}, write, '_'}),
- check_lock(Tid, Oid, ObjLocks, TabLocks, yes, AlreadyQ, read);
+can_lock(Tid, read, Oid = {Tab, Key}, AlreadyQ) when Key /= ?ALL ->
+ ObjLocks = ?ets_lookup(mnesia_held_locks, Oid),
+ TabLocks = ?ets_lookup(mnesia_held_locks, {Tab, ?ALL}),
+ {check_lock(Tid, Oid,
+ filter_write(ObjLocks),
+ filter_write(TabLocks),
+ yes, AlreadyQ, read),
+ ObjLocks};
can_lock(Tid, read, Oid, AlreadyQ) -> % Whole tab
Tab = element(1, Oid),
ObjLocks = ?ets_match_object(mnesia_held_locks, {{Tab, '_'}, write, '_'}),
- check_lock(Tid, Oid, ObjLocks, [], yes, AlreadyQ, read);
+ {check_lock(Tid, Oid, ObjLocks, [], yes, AlreadyQ, read), undefined};
-can_lock(Tid, write, {Tab, Key}, AlreadyQ) when Key /= ?ALL ->
- Oid = {Tab, Key},
+can_lock(Tid, write, Oid = {Tab, Key}, AlreadyQ) when Key /= ?ALL ->
ObjLocks = ?ets_lookup(mnesia_held_locks, Oid),
TabLocks = ?ets_lookup(mnesia_held_locks, {Tab, ?ALL}),
- check_lock(Tid, Oid, ObjLocks, TabLocks, yes, AlreadyQ, write);
+ {check_lock(Tid, Oid, ObjLocks, TabLocks, yes, AlreadyQ, write), ObjLocks};
can_lock(Tid, write, Oid, AlreadyQ) -> % Whole tab
Tab = element(1, Oid),
ObjLocks = ?ets_match_object(mnesia_held_locks, ?match_oid_held_locks({Tab, '_'})),
- check_lock(Tid, Oid, ObjLocks, [], yes, AlreadyQ, write).
+ {check_lock(Tid, Oid, ObjLocks, [], yes, AlreadyQ, write), undefined}.
+
+filter_write([{_, read, _}]) -> [];
+filter_write(Res) -> Res.
%% Check held locks for conflicting locks
-check_lock(Tid, Oid, [Lock | Locks], TabLocks, X, AlreadyQ, Type) ->
- case element(3, Lock) of
- Tid ->
- check_lock(Tid, Oid, Locks, TabLocks, X, AlreadyQ, Type);
- WaitForTid ->
- Queue = allowed_to_be_queued(WaitForTid,Tid),
- if Queue == true ->
- check_lock(Tid, Oid, Locks, TabLocks, {queue, WaitForTid}, AlreadyQ, Type);
- Tid#tid.pid == WaitForTid#tid.pid ->
- dbg_out("Spurious lock conflict ~w ~w: ~w -> ~w~n",
- [Oid, Lock, Tid, WaitForTid]),
- %% Test..
- {Tab, _Key} = Oid,
- HaveQ = (ets:lookup(mnesia_lock_queue, Oid) /= [])
- orelse (ets:lookup(mnesia_lock_queue,{Tab,?ALL}) /= []),
- if
- HaveQ ->
- {no, WaitForTid};
- true ->
- check_lock(Tid,Oid,Locks,TabLocks,{queue,WaitForTid},AlreadyQ,Type)
- end;
- %%{no, WaitForTid}; Safe solution
- true ->
- {no, WaitForTid}
- end
+check_lock(Tid, Oid, [{_, _, Lock} | Locks], TabLocks, _X, AlreadyQ, Type) ->
+ case can_queue(Lock, Tid, Oid, _X) of
+ {no, _} = Res ->
+ Res;
+ Res ->
+ check_lock(Tid, Oid, Locks, TabLocks, Res, AlreadyQ, Type)
end;
check_lock(_, _, [], [], X, {queue, bad_luck}, _) ->
@@ -375,8 +367,7 @@ check_lock(_, _, [], [], X, {queue, bad_luck}, _) ->
check_lock(_, _, [], [], X = {queue, _Tid}, _AlreadyQ, _) ->
X;
-check_lock(Tid, Oid, [], [], X, AlreadyQ, Type) ->
- {Tab, Key} = Oid,
+check_lock(Tid, Oid = {Tab, Key}, [], [], X, AlreadyQ, Type) ->
if
Type == write ->
check_queue(Tid, Tab, X, AlreadyQ);
@@ -403,6 +394,26 @@ check_lock(Tid, Oid, [], [], X, AlreadyQ, Type) ->
check_lock(Tid, Oid, [], TabLocks, X, AlreadyQ, Type) ->
check_lock(Tid, Oid, TabLocks, [], X, AlreadyQ, Type).
+can_queue([{_Op, Tid}|Locks], Tid, Oid, Res) ->
+ can_queue(Locks, Tid, Oid, Res);
+can_queue([{Op, WaitForTid}|Locks], Tid, Oid = {Tab, _}, _) ->
+ case allowed_to_be_queued(WaitForTid,Tid) of
+ true when Tid#tid.pid == WaitForTid#tid.pid ->
+ dbg_out("Spurious lock conflict ~w ~w: ~w -> ~w~n",
+ [Oid, Op, Tid, WaitForTid]),
+ HaveQ = (ets:lookup(mnesia_lock_queue, Oid) /= [])
+ orelse (ets:lookup(mnesia_lock_queue,{Tab,?ALL}) /= []),
+ case HaveQ of
+ true -> {no, WaitForTid};
+ false -> can_queue(Locks, Tid, Oid, {queue, WaitForTid})
+ end;
+ true ->
+ can_queue(Locks, Tid, Oid, {queue, WaitForTid});
+ false ->
+ {no, WaitForTid}
+ end;
+can_queue([], _, _, Res) -> Res.
+
%% True if WaitForTid > Tid -> % Important order
allowed_to_be_queued(WaitForTid, Tid) ->
case get(pid_sort_order) of
@@ -456,14 +467,14 @@ set_read_lock_on_all_keys(Tid, From, Tab, IxKey, Pos) ->
Op = {ix_read,IxKey, Pos},
Lock = read,
case can_lock(Tid, Lock, Oid, {no, bad_luck}) of
- yes ->
- Reply = grant_lock(Tid, Op, Lock, Oid),
+ {yes, Default} ->
+ Reply = grant_lock(Tid, Op, Lock, Oid, Default),
reply(From, Reply);
- {no, Lucky} ->
+ {{no, Lucky},_} ->
C = #cyclic{op = Op, lock = Lock, oid = Oid, lucky = Lucky},
?dbg("Rejected ~p ~p ~p ~p ~n", [Tid, Oid, Lock, Lucky]),
reply(From, {not_granted, C});
- {queue, Lucky} ->
+ {{queue, Lucky},_} ->
?dbg("Queued ~p ~p ~p ~p ~n", [Tid, Oid, Lock, Lucky]),
%% Append to queue: Nice place for trace output
?ets_insert(mnesia_lock_queue,
@@ -520,14 +531,24 @@ release_locks([]) ->
release_lock({Tid, Oid, {queued, _}}) ->
?ets_match_delete(mnesia_lock_queue, #queue{oid=Oid, tid = Tid, op = '_',
pid = '_', lucky = '_'});
-release_lock({Tid, Oid, Op}) ->
- if
- Op == write ->
- ?ets_delete(mnesia_held_locks, Oid);
- Op == read ->
- ets:delete_object(mnesia_held_locks, {Oid, Op, Tid})
+release_lock({_Tid, Oid, write}) ->
+ ?ets_delete(mnesia_held_locks, Oid);
+release_lock({Tid, Oid, read}) ->
+ case ?ets_lookup(mnesia_held_locks, Oid) of
+ [{Oid, Prev, Locks0}] ->
+ case remove_tid(Locks0, Tid, []) of
+ [] -> ?ets_delete(mnesia_held_locks, Oid);
+ Locks -> ?ets_insert(mnesia_held_locks, {Oid, Prev, Locks})
+ end;
+ [] -> ok
end.
+remove_tid([{_Op, Tid}|Ls], Tid, Acc) ->
+ remove_tid(Ls,Tid, Acc);
+remove_tid([Keep|Ls], Tid, Acc) ->
+ remove_tid(Ls,Tid, [Keep|Acc]);
+remove_tid([], _, Acc) -> Acc.
+
rearrange_queue([{_Tid, {Tab, Key}, _} | Locks]) ->
if
Key /= ?ALL->
@@ -592,18 +613,18 @@ try_waiter({queue, Oid, Tid, Op, ReplyTo, _}) ->
try_waiter(Oid, Op, SimpleOp, Lock, ReplyTo, Tid) ->
case can_lock(Tid, Lock, Oid, {queue, bad_luck}) of
- yes ->
+ {yes, Default} ->
%% Delete from queue: Nice place for trace output
?ets_match_delete(mnesia_lock_queue,
#queue{oid=Oid, tid = Tid, op = Op,
pid = ReplyTo, lucky = '_'}),
- Reply = grant_lock(Tid, SimpleOp, Lock, Oid),
+ Reply = grant_lock(Tid, SimpleOp, Lock, Oid, Default),
reply(ReplyTo,Reply),
locked;
- {queue, _Why} ->
+ {{queue, _Why}, _} ->
?dbg("Keep ~p ~p ~p ~p~n", [Tid, Oid, Lock, _Why]),
queued; % Keep waiter in queue
- {no, Lucky} ->
+ {{no, Lucky}, _} ->
C = #cyclic{op = SimpleOp, lock = Lock, oid = Oid, lucky = Lucky},
verbose("** WARNING ** Restarted transaction, possible deadlock in lock queue ~w: cyclic = ~w~n",
[Tid, C]),
@@ -1116,11 +1137,23 @@ rec_requests([], _Oid, _Store) ->
get_held_locks() ->
?MODULE ! {get_table, self(), mnesia_held_locks},
- receive {mnesia_held_locks, Locks} -> Locks end.
+ Locks = receive {mnesia_held_locks, Ls} -> Ls after 5000 -> [] end,
+ rewrite_locks(Locks, []).
+
+rewrite_locks([{Oid, _, Ls}|Locks], Acc0) ->
+ Acc = rewrite_locks(Ls, Oid, Acc0),
+ rewrite_locks(Locks, Acc);
+rewrite_locks([], Acc) ->
+ lists:reverse(Acc).
+
+rewrite_locks([{Op, Tid}|Ls], Oid, Acc) ->
+ rewrite_locks(Ls, Oid, [{Oid, Op, Tid}|Acc]);
+rewrite_locks([], _, Acc) ->
+ Acc.
get_lock_queue() ->
?MODULE ! {get_table, self(), mnesia_lock_queue},
- Q = receive {mnesia_lock_queue, Locks} -> Locks end,
+ Q = receive {mnesia_lock_queue, Locks} -> Locks after 5000 -> [] end,
[{Oid, Op, Pid, Tid, WFT} || {queue, Oid, Tid, Op, Pid, WFT} <- Q].
do_stop() ->
diff --git a/lib/observer/src/etop_gui.erl b/lib/observer/src/etop_gui.erl
index ff1b8078ad..9248d67344 100644
--- a/lib/observer/src/etop_gui.erl
+++ b/lib/observer/src/etop_gui.erl
@@ -17,6 +17,13 @@
%% %CopyrightEnd%
%%
-module(etop_gui).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
+
-author('[email protected]').
-export([init/1,stop/1]).
diff --git a/lib/observer/src/observer_lib.erl b/lib/observer/src/observer_lib.erl
index 967baa5c7a..5260861497 100644
--- a/lib/observer/src/observer_lib.erl
+++ b/lib/observer/src/observer_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -339,17 +339,37 @@ user_term(Parent, Title, Default) ->
?wxID_OK ->
Str = wxTextEntryDialog:getValue(Dialog),
wxTextEntryDialog:destroy(Dialog),
- parse_string(Str);
+ parse_string(ensure_last_is_dot(Str));
?wxID_CANCEL ->
- wxTextEntryDialog:destroy(Dialog)
+ wxTextEntryDialog:destroy(Dialog),
+ cancel
end.
parse_string(Str) ->
try
- {ok, Tokens, _} = erl_scan:string(Str),
- erl_parse:parse_term(Tokens)
- catch _:{badmatch, {error, {_, _, Err}}} ->
- {error, ["Parse error: ", Err]};
- _Err ->
+ Tokens = case erl_scan:string(Str) of
+ {ok, Ts, _} -> Ts;
+ {error, {_SLine, SMod, SError}, _} ->
+ throw(io_lib:format("~s", [SMod:format_error(SError)]))
+ end,
+ case erl_parse:parse_term(Tokens) of
+ {error, {_PLine, PMod, PError}} ->
+ throw(io_lib:format("~s", [PMod:format_error(PError)]));
+ Res -> Res
+ end
+ catch
+ throw:ErrStr ->
+ {error, ErrStr};
+ _:_Err ->
{error, ["Syntax error in: ", Str]}
end.
+
+ensure_last_is_dot([]) ->
+ ".";
+ensure_last_is_dot(String) ->
+ case lists:last(String) =:= $. of
+ true ->
+ String;
+ false ->
+ String ++ "."
+ end.
diff --git a/lib/observer/src/observer_procinfo.erl b/lib/observer/src/observer_procinfo.erl
index a4c5914c49..ec08d3aff1 100644
--- a/lib/observer/src/observer_procinfo.erl
+++ b/lib/observer/src/observer_procinfo.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -124,9 +124,14 @@ code_change(_, _, State) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
init_process_page(Panel, Pid) ->
- Fields = process_info_fields(Pid),
- {FPanel, _, UpFields} = observer_lib:display_info(Panel, Fields),
- {FPanel, fun() -> observer_lib:update_info(UpFields, process_info_fields(Pid)) end}.
+ Fields0 = process_info_fields(Pid),
+ {FPanel, _, UpFields} = observer_lib:display_info(Panel, Fields0),
+ {FPanel, fun() -> case process_info_fields(Pid) of
+ Fields when is_list(Fields) ->
+ observer_lib:update_info(UpFields, Fields);
+ _ -> ok
+ end
+ end}.
init_text_page(Parent) ->
Style = ?wxTE_MULTILINE bor ?wxTE_RICH2 bor ?wxTE_READONLY,
@@ -144,16 +149,20 @@ init_message_page(Parent, Pid) ->
Number+1}
end,
Update = fun() ->
- {messages,RawMessages} =
- observer_wx:try_rpc(node(Pid), erlang, process_info, [Pid, messages]),
- {Messages,_} = lists:mapfoldl(Format, 1, RawMessages),
- Last = wxTextCtrl:getLastPosition(Text),
- wxTextCtrl:remove(Text, 0, Last),
- case Messages =:= [] of
- true ->
- wxTextCtrl:writeText(Text, "No messages");
- false ->
- wxTextCtrl:writeText(Text, Messages)
+ case observer_wx:try_rpc(node(Pid), erlang, process_info,
+ [Pid, messages])
+ of
+ {messages,RawMessages} ->
+ {Messages,_} = lists:mapfoldl(Format, 1, RawMessages),
+ Last = wxTextCtrl:getLastPosition(Text),
+ wxTextCtrl:remove(Text, 0, Last),
+ case Messages =:= [] of
+ true ->
+ wxTextCtrl:writeText(Text, "No messages");
+ false ->
+ wxTextCtrl:writeText(Text, Messages)
+ end;
+ _ -> ok
end
end,
Update(),
@@ -162,12 +171,15 @@ init_message_page(Parent, Pid) ->
init_dict_page(Parent, Pid) ->
Text = init_text_page(Parent),
Update = fun() ->
- {dictionary,RawDict} =
- observer_wx:try_rpc(node(Pid), erlang, process_info, [Pid, dictionary]),
- Dict = [io_lib:format("~-20.w ~p~n", [K, V]) || {K, V} <- RawDict],
- Last = wxTextCtrl:getLastPosition(Text),
- wxTextCtrl:remove(Text, 0, Last),
- wxTextCtrl:writeText(Text, Dict)
+ case observer_wx:try_rpc(node(Pid), erlang, process_info, [Pid, dictionary])
+ of
+ {dictionary,RawDict} ->
+ Dict = [io_lib:format("~-20.w ~p~n", [K, V]) || {K, V} <- RawDict],
+ Last = wxTextCtrl:getLastPosition(Text),
+ wxTextCtrl:remove(Text, 0, Last),
+ wxTextCtrl:writeText(Text, Dict);
+ _ -> ok
+ end
end,
Update(),
{Text, Update}.
@@ -183,24 +195,29 @@ init_stack_page(Parent, Pid) ->
wxListCtrl:setColumnWidth(LCtrl, 1, 300),
wxListItem:destroy(Li),
Update = fun() ->
- {current_stacktrace,RawBt} =
- observer_wx:try_rpc(node(Pid), erlang, process_info,
- [Pid, current_stacktrace]),
- wxListCtrl:deleteAllItems(LCtrl),
- wx:foldl(fun({M, F, A, Info}, Row) ->
- _Item = wxListCtrl:insertItem(LCtrl, Row, ""),
- ?EVEN(Row) andalso
- wxListCtrl:setItemBackgroundColour(LCtrl, Row, ?BG_EVEN),
- wxListCtrl:setItem(LCtrl, Row, 0, observer_lib:to_str({M,F,A})),
- FileLine = case Info of
- [{file,File},{line,Line}] ->
- io_lib:format("~s:~w", [File,Line]);
- _ ->
- []
- end,
- wxListCtrl:setItem(LCtrl, Row, 1, FileLine),
- Row+1
- end, 0, RawBt)
+ case observer_wx:try_rpc(node(Pid), erlang, process_info,
+ [Pid, current_stacktrace])
+ of
+ {current_stacktrace,RawBt} ->
+ observer_wx:try_rpc(node(Pid), erlang, process_info,
+ [Pid, current_stacktrace]),
+ wxListCtrl:deleteAllItems(LCtrl),
+ wx:foldl(fun({M, F, A, Info}, Row) ->
+ _Item = wxListCtrl:insertItem(LCtrl, Row, ""),
+ ?EVEN(Row) andalso
+ wxListCtrl:setItemBackgroundColour(LCtrl, Row, ?BG_EVEN),
+ wxListCtrl:setItem(LCtrl, Row, 0, observer_lib:to_str({M,F,A})),
+ FileLine = case Info of
+ [{file,File},{line,Line}] ->
+ io_lib:format("~s:~w", [File,Line]);
+ _ ->
+ []
+ end,
+ wxListCtrl:setItem(LCtrl, Row, 1, FileLine),
+ Row+1
+ end, 0, RawBt);
+ _ -> ok
+ end
end,
Resize = fun(#wx{event=#wxSize{size={W,_}}},Ev) ->
wxEvent:skip(Ev),
@@ -216,7 +233,6 @@ create_menus(MenuBar) ->
observer_lib:create_menus(Menus, MenuBar, new_window).
process_info_fields(Pid) ->
- RawInfo = observer_wx:try_rpc(node(Pid), erlang, process_info, [Pid, item_list()]),
Struct = [{"Overview",
[{"Initial Call", initial_call},
{"Current Function", current_function},
@@ -246,7 +262,12 @@ process_info_fields(Pid) ->
{"GC Min Heap Size", {bytes, get_gc_info(min_heap_size)}},
{"GC FullSweep After", get_gc_info(fullsweep_after)}
]}],
- observer_lib:fill_info(Struct, RawInfo).
+ case observer_wx:try_rpc(node(Pid), erlang, process_info, [Pid, item_list()]) of
+ RawInfo when is_list(RawInfo) ->
+ observer_lib:fill_info(Struct, RawInfo);
+ _ ->
+ ok
+ end.
item_list() ->
[ %% backtrace,
diff --git a/lib/observer/src/observer_tv_table.erl b/lib/observer/src/observer_tv_table.erl
index 31d5f3d632..f432173f57 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. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -58,7 +58,7 @@
source,
tab,
attrs,
- timer
+ timer={false, 30}
}).
-record(opt,
@@ -268,8 +268,8 @@ handle_event(#wx{id=?ID_DELETE},
handle_event(#wx{id=?wxID_CLOSE}, State) ->
{stop, normal, State};
-handle_event(Help = #wx{id=?wxID_HELP}, State = #state{parent=Parent}) ->
- Parent ! Help,
+handle_event(Help = #wx{id=?wxID_HELP}, State) ->
+ observer ! Help,
{noreply, State};
handle_event(#wx{id=?GOTO_ENTRY, event=#wxCommand{cmdString=Str}},
@@ -374,40 +374,51 @@ handle_event(#wx{id=?ID_REFRESH_INTERVAL},
Timer = observer_lib:interval_dialog(Grid, Timer0, 10, 5*60),
{noreply, State#state{timer=Timer}};
-handle_event(Event, State) ->
- io:format("~p:~p, handle event ~p\n", [?MODULE, ?LINE, Event]),
+handle_event(_Event, State) ->
+ %io:format("~p:~p, handle event ~p\n", [?MODULE, ?LINE, Event]),
{noreply, State}.
-handle_sync_event(Event, _Obj, _State) ->
- io:format("~p:~p, handle sync_event ~p\n", [?MODULE, ?LINE, Event]),
+handle_sync_event(_Event, _Obj, _State) ->
+ %io:format("~p:~p, handle sync_event ~p\n", [?MODULE, ?LINE, Event]),
ok.
-handle_call(Event, From, State) ->
- io:format("~p:~p, handle call (~p) ~p\n", [?MODULE, ?LINE, From, Event]),
+handle_call(_Event, _From, State) ->
+ %io:format("~p:~p, handle call (~p) ~p\n", [?MODULE, ?LINE, From, Event]),
{noreply, State}.
-handle_cast(Event, State) ->
- io:format("~p:~p, handle cast ~p\n", [?MODULE, ?LINE, Event]),
+handle_cast(_Event, State) ->
+ %io:format("~p:~p, handle cast ~p\n", [?MODULE, ?LINE, Event]),
{noreply, State}.
handle_info({no_rows, N}, State = #state{grid=Grid, status=StatusBar}) ->
wxListCtrl:setItemCount(Grid, N),
wxStatusBar:setStatusText(StatusBar, io_lib:format("Objects: ~w",[N])),
{noreply, State};
+
handle_info({new_cols, New}, State = #state{grid=Grid, columns=Cols0}) ->
Cols = add_columns(Grid, Cols0, New),
{noreply, State#state{columns=Cols}};
+
handle_info({refresh, Min, Max}, State = #state{grid=Grid}) ->
wxListCtrl:refreshItems(Grid, Min, Max),
{noreply, State};
+
+handle_info(refresh_interval, State = #state{pid=Pid}) ->
+ Pid ! refresh,
+ {noreply, State};
+
handle_info({error, Error}, State = #state{frame=Frame}) ->
- Dlg = wxMessageDialog:new(Frame, Error),
+ ErrorStr =
+ try io_lib:format("~ts", [Error]), Error
+ catch _:_ -> io_lib:format("~p", [Error])
+ end,
+ Dlg = wxMessageDialog:new(Frame, ErrorStr),
wxMessageDialog:showModal(Dlg),
wxMessageDialog:destroy(Dlg),
{noreply, State};
-handle_info(Event, State) ->
- io:format("~p:~p, handle info ~p\n", [?MODULE, ?LINE, Event]),
+handle_info(_Event, State) ->
+ %% io:format("~p:~p, handle info ~p\n", [?MODULE, ?LINE, _Event]),
{noreply, State}.
terminate(_Event, #state{pid=Pid, attrs=Attrs}) ->
@@ -588,19 +599,22 @@ search([Str, Row, Dir0, CaseSens],
true -> [];
false -> [caseless]
end,
- {ok, Re} = re:compile(Str, Opt),
Dir = case Dir0 of
true -> 1;
false -> -1
end,
- Res = search(Row, Dir, Re, Table),
+ Res = case re:compile(Str, Opt) of
+ {ok, Re} ->
+ search(Row, Dir, Re, Table);
+ {error, _} -> false
+ end,
Parent ! {self(), Res},
S#holder{search=Res}.
search(Row, Dir, Re, Table) ->
Res = try lists:nth(Row+1, Table) of
Term ->
- Str = io_lib:format("~w", [Term]),
+ Str = format(Term),
re:run(Str, Re)
catch _:_ -> no_more
end,
@@ -613,9 +627,9 @@ search(Row, Dir, Re, Table) ->
get_row(From, Row, Col, Table) ->
case lists:nth(Row+1, Table) of
[Object|_] when Col =:= all ->
- From ! {self(), io_lib:format("~w", [Object])};
+ From ! {self(), format(Object)};
[Object|_] when tuple_size(Object) >= Col ->
- From ! {self(), io_lib:format("~w", [element(Col, Object)])};
+ From ! {self(), format(element(Col, Object))};
_ ->
From ! {self(), ""}
end.
@@ -724,3 +738,58 @@ key_pos(Node, ets, TabId) ->
KeyPos = rpc:call(Node, ets, info, [TabId, keypos]),
is_integer(KeyPos) orelse throw(node_or_table_down),
KeyPos.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+format(Tuple) when is_tuple(Tuple) ->
+ [${ |format_tuple(Tuple, 1, tuple_size(Tuple))];
+format(List) when is_list(List) ->
+ format_list(List);
+format(Bin) when is_binary(Bin), byte_size(Bin) > 100 ->
+ io_lib:format("<<#Bin:~w>>", [byte_size(Bin)]);
+format(Float) when is_float(Float) ->
+ io_lib:format("~.3g", [Float]);
+format(Term) ->
+ io_lib:format("~w", [Term]).
+
+format_tuple(Tuple, I, Max) when I < Max ->
+ [format(element(I, Tuple)), $,|format_tuple(Tuple, I+1, Max)];
+format_tuple(Tuple, Max, Max) ->
+ [format(element(Max, Tuple)), $}];
+format_tuple(_Tuple, 1, 0) ->
+ [$}].
+
+format_list([]) -> "[]";
+format_list(List) ->
+ case printable_list(List) of
+ true -> io_lib:format("\"~ts\"", [List]);
+ false -> [$[ | make_list(List)]
+ end.
+
+make_list([Last]) ->
+ [format(Last), $]];
+make_list([Head|Tail]) ->
+ [format(Head), $,|make_list(Tail)].
+
+%% printable_list([Char]) -> bool()
+%% Return true if CharList is a list of printable characters, else
+%% false.
+
+printable_list([C|Cs]) when is_integer(C), C >= $ , C =< 255 ->
+ printable_list(Cs);
+printable_list([$\n|Cs]) ->
+ printable_list(Cs);
+printable_list([$\r|Cs]) ->
+ printable_list(Cs);
+printable_list([$\t|Cs]) ->
+ printable_list(Cs);
+printable_list([$\v|Cs]) ->
+ printable_list(Cs);
+printable_list([$\b|Cs]) ->
+ printable_list(Cs);
+printable_list([$\f|Cs]) ->
+ printable_list(Cs);
+printable_list([$\e|Cs]) ->
+ printable_list(Cs);
+printable_list([]) -> true;
+printable_list(_Other) -> false. %Everything else is false
diff --git a/lib/observer/src/observer_tv_wx.erl b/lib/observer/src/observer_tv_wx.erl
index ad3e8c14ab..b276965f83 100644
--- a/lib/observer/src/observer_tv_wx.erl
+++ b/lib/observer/src/observer_tv_wx.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -313,7 +313,7 @@ display_table_info(Parent0, Node, Source, Table) ->
list_to_strings([]) -> "None";
list_to_strings([A]) -> integer_to_list(A);
-list_to_strings([A,B]) ->
+list_to_strings([A|B]) ->
integer_to_list(A) ++ " ," ++ list_to_strings(B).
handle_error(Foo) ->
diff --git a/lib/observer/test/etop_SUITE.erl b/lib/observer/test/etop_SUITE.erl
index a0782ea809..a277453620 100644
--- a/lib/observer/test/etop_SUITE.erl
+++ b/lib/observer/test/etop_SUITE.erl
@@ -57,11 +57,14 @@ end_per_group(_GroupName, Config) ->
Config.
-text(suite) ->
- [];
-text(doc) ->
- ["Start etop with text presentation"];
-text(Config) when is_list(Config) ->
+%% Start etop with text presentation
+text(_) ->
+ case test_server:is_native(lists) of
+ true -> {skip,"Native libs -- tracing does not work"};
+ false -> text()
+ end.
+
+text() ->
?line {ok,Node} = ?t:start_node(node2,peer,[]),
%% Must spawn this process, else the test case will never end.
diff --git a/lib/orber/src/orber_ifr.erl b/lib/orber/src/orber_ifr.erl
index c23374cd68..6799bc1db4 100644
--- a/lib/orber/src/orber_ifr.erl
+++ b/lib/orber/src/orber_ifr.erl
@@ -478,7 +478,7 @@ get_module(Id, Type) ->
What ->
orber:dbg("[~p] ~p:get_module(~p, ~p).~n"
"Id doesn't exist, mismatch Id vs Type or DB error: ~p",
- [?LINE, ?MODULE, Id, What], ?DEBUG_LEVEL),
+ [?LINE, ?MODULE, Id, Type, What], ?DEBUG_LEVEL),
corba:raise(#'MARSHAL'{completion_status=?COMPLETED_MAYBE})
end.
diff --git a/lib/orber/src/orber_tb.erl b/lib/orber/src/orber_tb.erl
index eee67296d7..d3e3a8497d 100644
--- a/lib/orber/src/orber_tb.erl
+++ b/lib/orber/src/orber_tb.erl
@@ -209,7 +209,7 @@ check_illegal_tcp_options([binary |T], IllegalOpts) ->
check_illegal_tcp_options(T,[binary |IllegalOpts]);
check_illegal_tcp_options([{reuseaddr, V} |T], IllegalOpts) ->
check_illegal_tcp_options(T,[{reuseaddr, V} |IllegalOpts]);
-check_illegal_tcp_options([H|T], IllegalOpts) ->
+check_illegal_tcp_options([_H|T], IllegalOpts) ->
check_illegal_tcp_options(T, IllegalOpts).
%%----------------------------------------------------------------------
diff --git a/lib/orber/test/orber_SUITE.erl b/lib/orber/test/orber_SUITE.erl
index be6ffa201c..72b0db1e0d 100644
--- a/lib/orber/test/orber_SUITE.erl
+++ b/lib/orber/test/orber_SUITE.erl
@@ -20,7 +20,6 @@
-module(orber_SUITE).
-include_lib("test_server/include/test_server.hrl").
-
-define(default_timeout, ?t:minutes(15)).
-define(application, orber).
@@ -31,7 +30,11 @@
% Test cases must be exported.
-export([app_test/1, undefined_functions/1, install_load_order/1,
- install_local_content/1]).
+ install_local_content/1,
+ otp_9887/1]).
+
+%% Exporting error handler callbacks for use in otp_9887
+-export([init/1, handle_event/2]).
%%
%% all/1
@@ -40,7 +43,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[app_test, undefined_functions, install_load_order,
- install_local_content].
+ install_local_content,
+ otp_9887].
groups() ->
[].
@@ -76,6 +80,27 @@ app_test(_Config) ->
?line ok=?t:app_test(orber),
ok.
+otp_9887(_Config) ->
+ orber:jump_stop(),
+ application:set_env(orber, orber_debug_level, 10),
+ orber:jump_start([]),
+
+ mnesia:create_table(orber_light_ifr, []),
+
+ error_logger:add_report_handler(?MODULE,[self()]),
+ catch orber_ifr:get_module(foo, bar),
+
+ receive
+ {stolen,Reason} ->
+ {error,_Pid1, {_Pid2, _ErrorString, ArgumentList}} = Reason,
+ 5 = length(ArgumentList)
+ after 500 ->
+ test_server:fail("OTP_9887 TIMED OUT")
+ end,
+
+ orber:jump_stop(),
+ ok.
+
%% Install Orber using the load_order option.
install_load_order(suite) ->
[];
@@ -192,5 +217,10 @@ key1search(Key, L) ->
fail(Reason) ->
exit({suite_failed, Reason}).
+%% Error handler
+init([Proc]) -> {ok,Proc}.
+handle_event(Event, Proc) ->
+ Proc ! {stolen,Event},
+ {ok,Proc}.
diff --git a/lib/orber/test/orber_acl_SUITE.erl b/lib/orber/test/orber_acl_SUITE.erl
index b43a00be19..49107cde84 100644
--- a/lib/orber/test/orber_acl_SUITE.erl
+++ b/lib/orber/test/orber_acl_SUITE.erl
@@ -80,7 +80,7 @@ end_per_group(_GroupName, Config) ->
%%-----------------------------------------------------------------
init_per_suite(Config) ->
if
- list(Config) ->
+ is_list(Config) ->
Config;
true ->
exit("Config not a list")
diff --git a/lib/os_mon/c_src/memsup.c b/lib/os_mon/c_src/memsup.c
index 241e7718db..b6e417eaa0 100644
--- a/lib/os_mon/c_src/memsup.c
+++ b/lib/os_mon/c_src/memsup.c
@@ -327,27 +327,27 @@ get_mem_procfs(memory_ext *me){
/* Total and free is NEEDED! */
bp = strstr(buffer, "MemTotal:");
- if (sscanf(bp, "MemTotal: %lu kB\n", &(me->total))) me->flag |= F_MEM_TOTAL;
+ if (bp != NULL && sscanf(bp, "MemTotal: %lu kB\n", &(me->total))) me->flag |= F_MEM_TOTAL;
bp = strstr(buffer, "MemFree:");
- if (sscanf(bp, "MemFree: %lu kB\n", &(me->free))) me->flag |= F_MEM_FREE;
+ if (bp != NULL && sscanf(bp, "MemFree: %lu kB\n", &(me->free))) me->flag |= F_MEM_FREE;
/* Extensions */
bp = strstr(buffer, "Buffers:");
- if (sscanf(bp, "Buffers: %lu kB\n", &(me->buffered))) me->flag |= F_MEM_BUFFERS;
+ if (bp != NULL && sscanf(bp, "Buffers: %lu kB\n", &(me->buffered))) me->flag |= F_MEM_BUFFERS;
bp = strstr(buffer, "Cached:");
- if (sscanf(bp, "Cached: %lu kB\n", &(me->cached))) me->flag |= F_MEM_CACHED;
+ if (bp != NULL && sscanf(bp, "Cached: %lu kB\n", &(me->cached))) me->flag |= F_MEM_CACHED;
/* Swap */
bp = strstr(buffer, "SwapTotal:");
- if (sscanf(bp, "SwapTotal: %lu kB\n", &(me->total_swap))) me->flag |= F_SWAP_TOTAL;
+ if (bp != NULL && sscanf(bp, "SwapTotal: %lu kB\n", &(me->total_swap))) me->flag |= F_SWAP_TOTAL;
bp = strstr(buffer, "SwapFree:");
- if (sscanf(bp, "SwapFree: %lu kB\n", &(me->free_swap))) me->flag |= F_SWAP_FREE;
+ if (bp != NULL && sscanf(bp, "SwapFree: %lu kB\n", &(me->free_swap))) me->flag |= F_SWAP_FREE;
me->pagesize = 1024; /* procfs defines its size in kB */
diff --git a/lib/os_mon/src/cpu_sup.erl b/lib/os_mon/src/cpu_sup.erl
index e414e2c10b..34251178ee 100644
--- a/lib/os_mon/src/cpu_sup.erl
+++ b/lib/os_mon/src/cpu_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -764,8 +764,7 @@ port_receive_cpu_util_entries(_, _, Data) ->
exit({data_mismatch, Data}).
start_portprogram() ->
- Command = filename:join([code:priv_dir(os_mon), "bin", "cpu_sup"]),
- Port = open_port({spawn, Command}, [stream]),
+ Port = os_mon:open_port("cpu_sup", [stream]),
port_command(Port, ?ping),
4711 = port_receive_uint32(Port, 5000),
Port.
diff --git a/lib/os_mon/src/memsup.erl b/lib/os_mon/src/memsup.erl
index ba07a529bc..49533da1f7 100644
--- a/lib/os_mon/src/memsup.erl
+++ b/lib/os_mon/src/memsup.erl
@@ -802,8 +802,7 @@ port_init() ->
port_idle(Port).
start_portprogram() ->
- Command = filename:join([code:priv_dir(os_mon), "bin", "memsup"]),
- open_port({spawn, Command}, [{packet, 1}]).
+ os_mon:open_port("memsup",[{packet,1}]).
%% The connected process loops are a bit awkward (several different
%% functions doing almost the same thing) as
diff --git a/lib/os_mon/src/os_mon.erl b/lib/os_mon/src/os_mon.erl
index ef368571db..3098c38808 100644
--- a/lib/os_mon/src/os_mon.erl
+++ b/lib/os_mon/src/os_mon.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -22,7 +22,7 @@
-behaviour(supervisor).
%% API
--export([call/2, call/3, get_env/2]).
+-export([call/2, call/3, get_env/2, open_port/2]).
%% Application callbacks
-export([start/2, stop/1]).
@@ -79,6 +79,22 @@ get_env(Service, Param) ->
Service:param_default(Param)
end.
+open_port(Name, Opts) ->
+ PrivDir = code:priv_dir(os_mon),
+ ReleasedPath = filename:join([PrivDir,"bin",Name]),
+ %% Check os_mon*/priv/bin/Name
+ case filelib:is_regular(ReleasedPath) of
+ true ->
+ erlang:open_port({spawn, ReleasedPath}, Opts);
+ false ->
+ %% Use os_mon*/priv/bin/Arch/Name
+ ArchPath =
+ filename:join(
+ [PrivDir,"bin",erlang:system_info(system_architecture),Name]),
+ erlang:open_port({spawn, ArchPath}, Opts)
+ end.
+
+
%%%-----------------------------------------------------------------
%%% Application callbacks
%%%-----------------------------------------------------------------
diff --git a/lib/os_mon/src/os_mon_sysinfo.erl b/lib/os_mon/src/os_mon_sysinfo.erl
index 5d12bd95d1..080885d5d6 100644
--- a/lib/os_mon/src/os_mon_sysinfo.erl
+++ b/lib/os_mon/src/os_mon_sysinfo.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. 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
@@ -108,9 +108,7 @@ code_change(_OldVsn, State, _Extra) ->
%%----------------------------------------------------------------------
start_portprogram() ->
- Command =
- filename:join([code:priv_dir(os_mon),"bin","win32sysinfo.exe"]),
- Port = open_port({spawn,Command}, [{packet,1}]),
+ Port = os_mon:open_port("win32sysinfo.exe", [{packet,1}]),
receive
{Port, {data, [?OK]}} ->
Port;
diff --git a/lib/pman/doc/src/pman.xml b/lib/pman/doc/src/pman.xml
index 84d5a5772a..5f95aecc04 100644
--- a/lib/pman/doc/src/pman.xml
+++ b/lib/pman/doc/src/pman.xml
@@ -32,6 +32,12 @@
<module>pman</module>
<modulesummary>A graphical process manager.</modulesummary>
<description>
+ <warning>
+ <p>
+ The Pman application has been superseded by the Observer application.
+ Pman will be removed in R16.
+ </p>
+ </warning>
<p>A graphical tool used to inspect the Erlang processes executing either
locally or on remote nodes. It is also possible to trace events in
the individual processes.</p>
diff --git a/lib/pman/doc/src/pman_chapter.xml b/lib/pman/doc/src/pman_chapter.xml
index 141b488415..8668628bfa 100644
--- a/lib/pman/doc/src/pman_chapter.xml
+++ b/lib/pman/doc/src/pman_chapter.xml
@@ -32,6 +32,12 @@
<section>
<title>Introduction</title>
+ <warning>
+ <p>
+ The Pman application has been superseded by the Observer application.
+ Pman will be removed in R16.
+ </p>
+ </warning>
<p>The process manager Pman is a tool for viewing processes executing
locally or on remote nodes. Its main purpose is to locate
erroneous code by inspecting the state of the processes and by tracing
diff --git a/lib/pman/src/pman_buf_converter.erl b/lib/pman/src/pman_buf_converter.erl
index b6f560411c..c6cd8ec9ee 100644
--- a/lib/pman/src/pman_buf_converter.erl
+++ b/lib/pman/src/pman_buf_converter.erl
@@ -29,6 +29,7 @@
%%----------------------------------------------------------------------
-module(pman_buf_converter).
+-compile([{nowarn_deprecated_function,{gs,start,0}}]).
%%-compile(export_all).
-export([init/2]).
diff --git a/lib/pman/src/pman_buf_printer.erl b/lib/pman/src/pman_buf_printer.erl
index 74e935171a..62407648d5 100644
--- a/lib/pman/src/pman_buf_printer.erl
+++ b/lib/pman/src/pman_buf_printer.erl
@@ -18,6 +18,8 @@
%%
-module(pman_buf_printer).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
%%-compile(export_all).
-export([init/2]).
diff --git a/lib/pman/src/pman_main.erl b/lib/pman/src/pman_main.erl
index b68da1d2c3..adb5b65cd4 100644
--- a/lib/pman/src/pman_main.erl
+++ b/lib/pman/src/pman_main.erl
@@ -17,6 +17,8 @@
%% %CopyrightEnd%
%%
-module(pman_main).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,read,2}}]).
%% Main process and window
diff --git a/lib/pman/src/pman_module_info.erl b/lib/pman/src/pman_module_info.erl
index cfd711a6e1..58f956aa42 100644
--- a/lib/pman/src/pman_module_info.erl
+++ b/lib/pman/src/pman_module_info.erl
@@ -17,6 +17,8 @@
%% %CopyrightEnd%
%%
-module(pman_module_info).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,start,1}}]).
%% Window with module information (View->Module Info...)
diff --git a/lib/pman/src/pman_shell.erl b/lib/pman/src/pman_shell.erl
index 0b13890460..393ef5f84d 100644
--- a/lib/pman/src/pman_shell.erl
+++ b/lib/pman/src/pman_shell.erl
@@ -25,6 +25,10 @@
%% ---------------------------------------------------------------
-module(pman_shell).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,start,1}}]).
%% ---------------------------------------------------------------
%% The user interface exports
diff --git a/lib/pman/src/pman_tool.erl b/lib/pman/src/pman_tool.erl
index 1d33fb9764..c548e17d00 100644
--- a/lib/pman/src/pman_tool.erl
+++ b/lib/pman/src/pman_tool.erl
@@ -17,6 +17,7 @@
%% %CopyrightEnd%
%%
-module(pman_tool).
+-compile([{nowarn_deprecated_function,{gs,read,2}}]).
%% Listbox selection window
diff --git a/lib/pman/src/pman_win.erl b/lib/pman/src/pman_win.erl
index 52d5a237cf..9dd446cd81 100644
--- a/lib/pman/src/pman_win.erl
+++ b/lib/pman/src/pman_win.erl
@@ -21,6 +21,16 @@
%% ------------------------------------------------------------
-module(pman_win).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,canvas,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,create,4}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,1}},
+ {nowarn_deprecated_function,{gs,text,2}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
%% ---------------------------------------------------------------
%% The user interface exports
diff --git a/lib/public_key/.gitignore b/lib/public_key/.gitignore
index db24906676..d30fe62c9d 100644
--- a/lib/public_key/.gitignore
+++ b/lib/public_key/.gitignore
@@ -1,7 +1,7 @@
# public_key
-/lib/public_key/asn1/*.asn1db
-/lib/public_key/asn1/*.erl
-/lib/public_key/asn1/*.hrl
-/lib/public_key/include/OTP-PUB-KEY.hrl
-/lib/public_key/include/PKCS-FRAME.hrl
+asn1/*.asn1db
+asn1/*.erl
+asn1/*.hrl
+include/OTP-PUB-KEY.hrl
+include/PKCS-FRAME.hrl
diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml
index 821e7a2300..0b6673e826 100644
--- a/lib/public_key/doc/src/public_key.xml
+++ b/lib/public_key/doc/src/public_key.xml
@@ -453,7 +453,7 @@
<desc>
<p>Encodes a list of ssh file entries (public keys and attributes) to a binary. Possible
attributes depends on the file type, see <seealso
- marker="ssh_decode"> ssh_decode/2 </seealso></p>
+ marker="#ssh_decode-2"> ssh_decode/2 </seealso></p>
</desc>
</func>
diff --git a/lib/public_key/src/pubkey_ssh.erl b/lib/public_key/src/pubkey_ssh.erl
index f342eab159..f0c94e29a5 100644
--- a/lib/public_key/src/pubkey_ssh.erl
+++ b/lib/public_key/src/pubkey_ssh.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -146,16 +146,7 @@ do_openssh_decode(auth_keys = FileType, [Line | Lines], Acc) ->
Split = binary:split(Line, <<" ">>, [global]),
case mend_split(Split, []) of
%% ssh2
- [Options, KeyType, Base64Enc, Comment] when KeyType == <<"ssh-rsa">>;
- KeyType == <<"ssh-dss">> ->
- do_openssh_decode(FileType, Lines,
- [{openssh_pubkey_decode(KeyType, Base64Enc),
- [{comment, string_decode(Comment)},
- {options, comma_list_decode(Options)}]}
- | Acc]);
-
- [KeyType, Base64Enc, Comment] when KeyType == <<"ssh-rsa">>;
- KeyType == <<"ssh-dss">> ->
+ [KeyType, Base64Enc, Comment] ->
do_openssh_decode(FileType, Lines,
[{openssh_pubkey_decode(KeyType, Base64Enc),
[{comment, string_decode(Comment)}]} | Acc]);
@@ -166,44 +157,32 @@ do_openssh_decode(auth_keys = FileType, [Line | Lines], Acc) ->
[{comment, string_decode(Comment)},
{options, comma_list_decode(Options)},
{bits, integer_decode(Bits)}]} | Acc]);
- [Bits, Exponent, Modulus, Comment] ->
- do_openssh_decode(FileType, Lines,
- [{ssh1_rsa_pubkey_decode(Modulus, Exponent),
- [{comment, string_decode(Comment)},
- {bits, integer_decode(Bits)}]} | Acc])
- end;
+ [A, B, C, D] ->
+ ssh_2_or_1(FileType, Lines, Acc, A,B,C,D)
+ end;
do_openssh_decode(known_hosts = FileType, [Line | Lines], Acc) ->
- case binary:split(Line, <<" ">>, [global]) of
+ Split = binary:split(Line, <<" ">>, [global]),
+ case mend_split(Split, []) of
%% ssh 2
- [HostNames, KeyType, Base64Enc] when KeyType == <<"ssh-rsa">>;
- KeyType == <<"ssh-dss">> ->
+ [HostNames, KeyType, Base64Enc] ->
do_openssh_decode(FileType, Lines,
[{openssh_pubkey_decode(KeyType, Base64Enc),
[{hostnames, comma_list_decode(HostNames)}]}| Acc]);
- [HostNames, KeyType, Base64Enc, Comment] when KeyType == <<"ssh-rsa">>;
- KeyType == <<"ssh-dss">> ->
- do_openssh_decode(FileType, Lines,
- [{openssh_pubkey_decode(KeyType, Base64Enc),
- [{comment, string_decode(Comment)},
- {hostnames, comma_list_decode(HostNames)}]} | Acc]);
+ [A, B, C, D] ->
+ ssh_2_or_1(FileType, Lines, Acc, A, B, C, D);
%% ssh 1
[HostNames, Bits, Exponent, Modulus, Comment] ->
do_openssh_decode(FileType, Lines,
[{ssh1_rsa_pubkey_decode(Modulus, Exponent),
[{comment, string_decode(Comment)},
{hostnames, comma_list_decode(HostNames)},
- {bits, integer_decode(Bits)}]} | Acc]);
- [HostNames, Bits, Exponent, Modulus] ->
- do_openssh_decode(FileType, Lines,
- [{ssh1_rsa_pubkey_decode(Modulus, Exponent),
- [{comment, []},
- {hostnames, comma_list_decode(HostNames)},
{bits, integer_decode(Bits)}]} | Acc])
end;
do_openssh_decode(openssh_public_key = FileType, [Line | Lines], Acc) ->
- case binary:split(Line, <<" ">>, [global]) of
+ Split = binary:split(Line, <<" ">>, [global]),
+ case mend_split(Split, []) of
[KeyType, Base64Enc, Comment0] when KeyType == <<"ssh-rsa">>;
KeyType == <<"ssh-dss">> ->
Comment = string:strip(binary_to_list(Comment0), right, $\n),
@@ -212,6 +191,46 @@ do_openssh_decode(openssh_public_key = FileType, [Line | Lines], Acc) ->
[{comment, Comment}]} | Acc])
end.
+ssh_2_or_1(known_hosts = FileType, Lines, Acc, A, B, C, D) ->
+ try integer_decode(B) of
+ Int ->
+ file_type_decode_ssh1(FileType, Lines, Acc, A, Int, C,D)
+ catch
+ error:badarg ->
+ file_type_decode_ssh2(FileType, Lines, Acc, A,B,C,D)
+ end;
+ssh_2_or_1(auth_keys = FileType, Lines, Acc, A, B, C, D) ->
+ try integer_decode(A) of
+ Int ->
+ file_type_decode_ssh1(FileType, Lines, Acc, Int, B, C,D)
+ catch
+ error:badarg ->
+ file_type_decode_ssh2(FileType, Lines, Acc, A,B,C,D)
+ end.
+
+file_type_decode_ssh1(known_hosts = FileType, Lines, Acc, HostNames, Bits, Exponent, Modulus) ->
+ do_openssh_decode(FileType, Lines,
+ [{ssh1_rsa_pubkey_decode(Modulus, Exponent),
+ [{comment, []},
+ {hostnames, comma_list_decode(HostNames)},
+ {bits, Bits}]} | Acc]);
+file_type_decode_ssh1(auth_keys = FileType, Lines, Acc, Bits, Exponent, Modulus, Comment) ->
+ do_openssh_decode(FileType, Lines,
+ [{ssh1_rsa_pubkey_decode(Modulus, Exponent),
+ [{comment, string_decode(Comment)},
+ {bits, Bits}]} | Acc]).
+
+file_type_decode_ssh2(known_hosts = FileType, Lines, Acc, HostNames, KeyType, Base64Enc, Comment) ->
+ do_openssh_decode(FileType, Lines,
+ [{openssh_pubkey_decode(KeyType, Base64Enc),
+ [{comment, string_decode(Comment)},
+ {hostnames, comma_list_decode(HostNames)}]} | Acc]);
+file_type_decode_ssh2(auth_keys = FileType, Lines, Acc, Options, KeyType, Base64Enc, Comment) ->
+ do_openssh_decode(FileType, Lines,
+ [{openssh_pubkey_decode(KeyType, Base64Enc),
+ [{comment, string_decode(Comment)},
+ {options, comma_list_decode(Options)}]}
+ | Acc]).
openssh_pubkey_decode(<<"ssh-rsa">>, Base64Enc) ->
<<?UINT32(StrLen), _:StrLen/binary,
@@ -231,7 +250,9 @@ openssh_pubkey_decode(<<"ssh-dss">>, Base64Enc) ->
{erlint(SizeY, Y),
#'Dss-Parms'{p = erlint(SizeP, P),
q = erlint(SizeQ, Q),
- g = erlint(SizeG, G)}}.
+ g = erlint(SizeG, G)}};
+openssh_pubkey_decode(KeyType, Base64Enc) ->
+ {KeyType, base64:mime_decode(Base64Enc)}.
erlint(MPIntSize, MPIntValue) ->
Bits= MPIntSize * 8,
@@ -412,6 +433,12 @@ is_key_field(<<"ssh-dss">>) ->
true;
is_key_field(<<"ssh-rsa">>) ->
true;
+is_key_field(<<"ecdsa-sha2-nistp256">>) ->
+ true;
+is_key_field(<<"ecdsa-sha2-nistp384">>) ->
+ true;
+is_key_field(<<"ecdsa-sha2-nistp521">>) ->
+ true;
is_key_field(_) ->
false.
diff --git a/lib/runtime_tools/c_src/trace_ip_drv.c b/lib/runtime_tools/c_src/trace_ip_drv.c
index 5396b8afa9..7ae6c1b329 100644
--- a/lib/runtime_tools/c_src/trace_ip_drv.c
+++ b/lib/runtime_tools/c_src/trace_ip_drv.c
@@ -212,11 +212,11 @@ static TraceIpData *lookup_data_by_port(int portno);
static int set_nonblocking(SOCKET sock);
static TraceIpMessage *make_buffer(int datasiz, unsigned char op,
unsigned number);
-static void enque_message(TraceIpData *data, unsigned char *buff, int bufflen,
+static void enque_message(TraceIpData *data, char *buff, int bufflen,
int byteswritten);
static void clean_que(TraceIpData *data);
static void close_client(TraceIpData *data);
-static int trywrite(TraceIpData *data, unsigned char *buff, int bufflen);
+static int trywrite(TraceIpData *data, char *buff, int bufflen);
static SOCKET my_accept(SOCKET sock);
static void close_unlink_port(TraceIpData *data);
enum MySelectOp { SELECT_ON, SELECT_OFF, SELECT_CLOSE };
@@ -518,7 +518,7 @@ static void trace_ip_ready_output(ErlDrvData handle, ErlDrvEvent fd)
tim = data->que[data->questart];
towrite = tim->siz - tim->written;
while((res = write_until_done(data->fd,
- tim->bin + tim->written, towrite))
+ (char *)tim->bin + tim->written, towrite))
== towrite) {
driver_free(tim);
data->que[data->questart] = NULL;
@@ -561,7 +561,7 @@ static ErlDrvSSizeT trace_ip_control(ErlDrvData handle,
TraceIpData *data = (TraceIpData *) handle;
ErlDrvBinary *b = my_alloc_binary(3);
b->orig_bytes[0] = '\0'; /* OK */
- put_be16(data->listen_portno, &(b->orig_bytes[1]));
+ put_be16(data->listen_portno, (unsigned char *)&(b->orig_bytes[1]));
*res = void_ptr = b;
return 0;
}
@@ -696,7 +696,7 @@ static TraceIpMessage *make_buffer(int datasiz, unsigned char op,
** Add message to que, discarding in a politically correct way...
** The FLAG_DROP_OLDEST is currently ingored...
*/
-static void enque_message(TraceIpData *data, unsigned char *buff, int bufflen,
+static void enque_message(TraceIpData *data, char *buff, int bufflen,
int byteswritten)
{
int diff = data->questop - data->questart;
@@ -763,13 +763,13 @@ static void close_client(TraceIpData *data)
** Try to write a message from erlang directly (only called when que is empty
** and client is connected)
*/
-static int trywrite(TraceIpData *data, unsigned char *buff, int bufflen)
+static int trywrite(TraceIpData *data, char *buff, int bufflen)
{
- unsigned char op[5];
+ char op[5];
int res;
op[0] = OP_BINARY;
- put_be32(bufflen, op + 1);
+ put_be32(bufflen, (unsigned char *)op + 1);
if ((res = write_until_done(data->fd, op, 5)) < 0) {
close_client(data);
@@ -793,7 +793,11 @@ static int trywrite(TraceIpData *data, unsigned char *buff, int bufflen)
static SOCKET my_accept(SOCKET sock)
{
struct sockaddr_in sin;
- int sin_size = sizeof(sin);
+#ifdef HAVE_SOCKLEN_T
+ socklen_t sin_size = sizeof(sin);
+#else
+ int sin_size = (int) sizeof(sin);
+#endif
return accept(sock, (struct sockaddr *) &sin, &sin_size);
}
diff --git a/lib/runtime_tools/test/inviso_SUITE.erl b/lib/runtime_tools/test/inviso_SUITE.erl
index 758867cf45..33626ffd9e 100644
--- a/lib/runtime_tools/test/inviso_SUITE.erl
+++ b/lib/runtime_tools/test/inviso_SUITE.erl
@@ -66,13 +66,18 @@ end_per_group(_GroupName, Config) ->
init_per_suite(Config) ->
- %% No never know who skrewed up this node before this suite! :-)
- erlang:trace_pattern({'_','_','_'},[],[local]),
- erlang:trace_pattern({'_','_','_'},[],[global]),
- erlang:trace(all,false,[all]),
+ case test_server:is_native(lists) of
+ true ->
+ {skip,"Native libs -- tracing doesn't work"};
+ false ->
+ %% We never know who messed up this node before this suite! :-)
+ erlang:trace_pattern({'_','_','_'},[],[local]),
+ erlang:trace_pattern({'_','_','_'},[],[global]),
+ erlang:trace(all,false,[all]),
- ?l ok=application:start(runtime_tools),
- Config.
+ ok=application:start(runtime_tools),
+ Config
+ end.
end_per_suite(_Config) ->
?l ok=application:stop(runtime_tools).
diff --git a/lib/sasl/doc/src/appup.xml b/lib/sasl/doc/src/appup.xml
index 195f9fe1d3..770b7c2492 100644
--- a/lib/sasl/doc/src/appup.xml
+++ b/lib/sasl/doc/src/appup.xml
@@ -332,7 +332,7 @@ restart_new_emulator
<p>An info report will be written when the upgrade is
completed. To programatically find out if the upgrade is
complete,
- call <seealso marker="release_handler#which_release/0">
+ call <seealso marker="release_handler#which_releases/0">
release_handler:which_releases</seealso> and check if the
expected release has status <c>current</c>.</p>
<p>The new release must still be made permanent after the upgrade
diff --git a/lib/sasl/doc/src/systools.xml b/lib/sasl/doc/src/systools.xml
index 32c2149a8d..84fed0a25f 100644
--- a/lib/sasl/doc/src/systools.xml
+++ b/lib/sasl/doc/src/systools.xml
@@ -196,6 +196,10 @@
<p>The applications are sorted according to the dependencies
between the applications. Where there are no dependencies,
the order in the <c>.rel</c> file is kept.</p>
+ <p>The function will fail if the mandatory
+ applications <c>kernel</c> and <c>stdlib</c> are not
+ included in the <c>.rel</c> file and have start
+ type <c>permanent</c> (default).</p>
<p>If <c>sasl</c> is not included as an application in
the <c>.rel</c> file, a warning is emitted because such a
release can not be used in an upgrade. To turn off this
diff --git a/lib/sasl/src/release_handler.erl b/lib/sasl/src/release_handler.erl
index 522c7b496b..8d2b9c35d3 100644
--- a/lib/sasl/src/release_handler.erl
+++ b/lib/sasl/src/release_handler.erl
@@ -1572,7 +1572,7 @@ memlib(_Lib, []) -> false.
%% recursively remove file or directory
remove_file(File) ->
- case file:read_file_info(File) of
+ case file:read_link_info(File) of
{ok, Info} when Info#file_info.type==directory ->
case file:list_dir(File) of
{ok, Files} ->
diff --git a/lib/sasl/src/systools_make.erl b/lib/sasl/src/systools_make.erl
index 8fd90c50f9..12ba2a5476 100644
--- a/lib/sasl/src/systools_make.erl
+++ b/lib/sasl/src/systools_make.erl
@@ -463,30 +463,35 @@ check_appl(Appl) ->
end,
Appl) of
[] ->
- {ok,Ws} = mandatory_applications(Appl),
- {split_app_incl(Appl),Ws};
+ {ApplsNoIncls,Incls} = split_app_incl(Appl),
+ {ok,Ws} = mandatory_applications(ApplsNoIncls,undefined,
+ undefined,undefined),
+ {{ApplsNoIncls,Incls},Ws};
Illegal ->
throw({error, {illegal_applications,Illegal}})
end.
-mandatory_applications(Appl) ->
- AppNames = map(fun(AppT) -> element(1, AppT) end,
- Appl),
- Mand = mandatory_applications(),
- case filter(fun(X) -> member(X, AppNames) end, Mand) of
- Mand ->
- case member(sasl,AppNames) of
- true ->
- {ok,[]};
- _ ->
- {ok, [{warning,missing_sasl}]}
- end;
- _ ->
- throw({error, {missing_mandatory_app, Mand}})
- end.
-
-mandatory_applications() ->
- [kernel, stdlib].
+mandatory_applications([{kernel,_,Type}|Apps],undefined,Stdlib,Sasl) ->
+ mandatory_applications(Apps,Type,Stdlib,Sasl);
+mandatory_applications([{stdlib,_,Type}|Apps],Kernel,undefined,Sasl) ->
+ mandatory_applications(Apps,Kernel,Type,Sasl);
+mandatory_applications([{sasl,_,Type}|Apps],Kernel,Stdlib,undefined) ->
+ mandatory_applications(Apps,Kernel,Stdlib,Type);
+mandatory_applications([_|Apps],Kernel,Stdlib,Sasl) ->
+ mandatory_applications(Apps,Kernel,Stdlib,Sasl);
+mandatory_applications([],Type,_,_) when Type=/=permanent ->
+ error_mandatory_application(kernel,Type);
+mandatory_applications([],_,Type,_) when Type=/=permanent ->
+ error_mandatory_application(sasl,Type);
+mandatory_applications([],_,_,undefined) ->
+ {ok, [{warning,missing_sasl}]};
+mandatory_applications([],_,_,_) ->
+ {ok,[]}.
+
+error_mandatory_application(App,undefined) ->
+ throw({error, {missing_mandatory_app, App}});
+error_mandatory_application(App,Type) ->
+ throw({error, {mandatory_app, App, Type}}).
split_app_incl(Appl) -> split_app_incl(Appl, [], []).
@@ -1677,6 +1682,7 @@ add_system_files(Tar, RelName, Release, Path1) ->
false ->
ignore;
Relup ->
+ check_relup(Relup),
add_to_tar(Tar, Relup, filename:join(RelVsnDir, "relup"))
end,
@@ -1684,6 +1690,7 @@ add_system_files(Tar, RelName, Release, Path1) ->
false ->
ignore;
Sys ->
+ check_sys_config(Sys),
add_to_tar(Tar, Sys, filename:join(RelVsnDir, "sys.config"))
end,
@@ -1700,6 +1707,44 @@ lookup_file(Name, [Dir|Path]) ->
lookup_file(_Name, []) ->
false.
+%% Check that relup can be parsed and has expected format
+check_relup(File) ->
+ case file:consult(File) of
+ {ok,[{Vsn,UpFrom,DownTo}]} when is_list(Vsn), is_integer(hd(Vsn)),
+ is_list(UpFrom), is_list(DownTo) ->
+ ok;
+ {ok,_} ->
+ throw({error,{tar_error,{add,"relup",[invalid_format]}}});
+ Other ->
+ throw({error,{tar_error,{add,"relup",[Other]}}})
+ end.
+
+%% Check that sys.config can be parsed and has expected format
+check_sys_config(File) ->
+ case file:consult(File) of
+ {ok,[SysConfig]} ->
+ case lists:all(fun({App,KeyVals}) when is_atom(App),
+ is_list(KeyVals)->
+ true;
+ (OtherConfig) when is_list(OtherConfig),
+ is_integer(hd(OtherConfig)) ->
+ true;
+ (_) ->
+ false
+ end,
+ SysConfig) of
+ true ->
+ ok;
+ false ->
+ throw({error,{tar_error,
+ {add,"sys.config",[invalid_format]}}})
+ end;
+ {ok,_} ->
+ throw({error,{tar_error,{add,"sys.config",[invalid_format]}}});
+ Other ->
+ throw({error,{tar_error,{add,"sys.config",[Other]}}})
+ end.
+
%%______________________________________________________________________
%% Add either a application located under a variable dir or all other
%% applications to a tar file.
@@ -2187,9 +2232,12 @@ format_error({missing_parameter,Par}) ->
format_error({illegal_applications,Names}) ->
io_lib:format("Illegal applications in the release file: ~p~n",
[Names]);
-format_error({missing_mandatory_app,Names}) ->
- io_lib:format("Mandatory applications (~p) must be specified in the release file~n",
- [Names]);
+format_error({missing_mandatory_app,Name}) ->
+ io_lib:format("Mandatory application ~p must be specified in the release file~n",
+ [Name]);
+format_error({mandatory_app,Name,Type}) ->
+ io_lib:format("Mandatory application ~p must be of type 'permanent' in the release file. Is '~p'.~n",
+ [Name,Type]);
format_error({duplicate_register,Dups}) ->
io_lib:format("Duplicated register names: ~n~s",
[map(fun({{Reg,App1,_,_},{Reg,App2,_,_}}) ->
diff --git a/lib/sasl/test/release_handler_SUITE.erl b/lib/sasl/test/release_handler_SUITE.erl
index ac616dab72..467d1226b3 100644
--- a/lib/sasl/test/release_handler_SUITE.erl
+++ b/lib/sasl/test/release_handler_SUITE.erl
@@ -59,7 +59,7 @@ win32_cases() ->
cases() ->
[otp_2740, otp_2760, otp_5761, otp_9402, otp_9417,
otp_9395_check_old_code, otp_9395_check_and_purge,
- otp_9395_update_many_mods, otp_9395_rm_many_mods,
+ otp_9395_update_many_mods, otp_9395_rm_many_mods, otp_9864,
instructions, eval_appup, eval_appup_with_restart,
supervisor_which_children_timeout,
release_handler_which_releases, install_release_syntax_check,
@@ -1205,6 +1205,60 @@ otp_9395_rm_many_mods(Conf) when is_list(Conf) ->
otp_9395_rm_many_mods(cleanup,_Conf) ->
stop_node(node_name(otp_9395_rm_many_mods)).
+otp_9864(Conf) ->
+ %% Set some paths
+ PrivDir = priv_dir(Conf),
+ Dir = filename:join(PrivDir,"otp_9864"),
+ RelDir = filename:join(?config(data_dir, Conf), "app1_app2"),
+ LibDir1 = filename:join(RelDir, "lib1"),
+ LibDir2 = filename:join(RelDir, "lib2"),
+
+ %% Create the releases
+ Rel1 = create_and_install_fake_first_release(Dir,
+ [{app1,"1.0",LibDir1},
+ {app2,"1.0",LibDir1}]),
+ Rel2 = create_fake_upgrade_release(Dir,
+ "2",
+ [{app1,"2.0",LibDir2},
+ {app2,"1.0",LibDir2}],
+ {[Rel1],[Rel1],[LibDir1]}),
+ Rel1Dir = filename:dirname(Rel1),
+ Rel2Dir = filename:dirname(Rel2),
+
+ %% Start a slave node
+ {ok, Node} = t_start_node(otp_9864, Rel1, filename:join(Rel1Dir,"sys.config")),
+
+ %% Unpack rel2 (make sure it does not work if an AppDir is bad)
+ LibDir3 = filename:join(RelDir, "lib3"),
+ {error, {no_such_directory, _}} =
+ rpc:call(Node, release_handler, set_unpacked,
+ [Rel2++".rel", [{app1,"2.0",LibDir2}, {app2,"1.0",LibDir3}]]),
+ {ok, RelVsn2} =
+ rpc:call(Node, release_handler, set_unpacked,
+ [Rel2++".rel", [{app1,"2.0",LibDir2}, {app2,"1.0",LibDir2}]]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "relup")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "start.boot")]),
+ ok = rpc:call(Node, release_handler, install_file,
+ [RelVsn2, filename:join(Rel2Dir, "sys.config")]),
+
+ %% Install RelVsn2 without {update_paths, true} option
+ {ok, RelVsn1, []} =
+ rpc:call(Node, release_handler, install_release, [RelVsn2]),
+
+ %% Install RelVsn1 again
+ {ok, RelVsn1, []} =
+ rpc:call(Node, release_handler, install_release, [RelVsn1]),
+
+ TempRel2Dir = filename:join(Dir,"releases/2"),
+ file:make_symlink(TempRel2Dir, filename:join(TempRel2Dir, "foo_symlink_dir")),
+
+ %% This will fail if symlinks are not handled
+ ok = rpc:call(Node, release_handler, remove_release, [RelVsn2]),
+
+ ok.
+
upgrade_supervisor(Conf) when is_list(Conf) ->
%% Set some paths
diff --git a/lib/sasl/test/systools_SUITE.erl b/lib/sasl/test/systools_SUITE.erl
index 43366d8917..4cf7364d74 100644
--- a/lib/sasl/test/systools_SUITE.erl
+++ b/lib/sasl/test/systools_SUITE.erl
@@ -46,9 +46,11 @@
included_script/1, included_override_script/1,
included_fail_script/1, included_bug_script/1, exref_script/1,
otp_3065_circular_dependenies/1]).
--export([tar_options/1, normal_tar/1, no_mod_vsn_tar/1, variable_tar/1,
- src_tests_tar/1, var_tar/1,
- exref_tar/1, link_tar/1, otp_9507_path_ebin/1]).
+-export([tar_options/1, normal_tar/1, no_mod_vsn_tar/1, system_files_tar/1,
+ system_files_tar/2, invalid_system_files_tar/1,
+ invalid_system_files_tar/2, variable_tar/1,
+ src_tests_tar/1, var_tar/1, exref_tar/1, link_tar/1,
+ otp_9507_path_ebin/1]).
-export([normal_relup/1, restart_relup/1, abnormal_relup/1, no_sasl_relup/1,
no_appup_relup/1, bad_appup_relup/1, app_start_type_relup/1,
regexp_relup/1]).
@@ -80,7 +82,8 @@ groups() ->
included_fail_script, included_bug_script, exref_script,
otp_3065_circular_dependenies]},
{tar, [],
- [tar_options, normal_tar, no_mod_vsn_tar, variable_tar,
+ [tar_options, normal_tar, no_mod_vsn_tar, system_files_tar,
+ invalid_system_files_tar, variable_tar,
src_tests_tar, var_tar, exref_tar, link_tar, otp_9507_path_ebin]},
{relup, [],
[normal_relup, restart_relup, abnormal_relup, no_sasl_relup,
@@ -146,7 +149,10 @@ init_per_testcase(_Case, Config) ->
Dog = test_server:timetrap(?default_timeout),
[{watchdog, Dog}|Config].
-end_per_testcase(_Case, Config) ->
+end_per_testcase(Case, Config) ->
+ try apply(?MODULE,Case,[cleanup,Config])
+ catch error:undef -> ok
+ end,
Dog=?config(watchdog, Config),
test_server:timetrap_cancel(Dog),
case {?config(path,Config),?config(cwd,Config)} of
@@ -483,9 +489,17 @@ crazy_script(Config) when is_list(Config) ->
ok = file:set_cwd(LatestDir2),
error = systools:make_script(LatestName2),
- {error, _, {missing_mandatory_app,[kernel,stdlib]}} =
+ {error, _, {missing_mandatory_app,kernel}} =
systools:make_script(LatestName2, [silent,{path,P}]),
+ %% Run with .rel file with non-permanent kernel
+ {LatestDir3, LatestName3} = create_script(latest_kernel_start_type, Config),
+ ok = file:set_cwd(LatestDir3),
+
+ error = systools:make_script(LatestName3),
+ {error, _, {mandatory_app,kernel,load}} =
+ systools:make_script(LatestName3, [silent,{path,P}]),
+
ok = file:set_cwd(OldDir),
ok.
@@ -756,6 +770,102 @@ no_mod_vsn_tar(Config) when is_list(Config) ->
ok = file:set_cwd(OldDir),
ok.
+
+%% make_tar: Check that relup or sys.config are included if they exist
+system_files_tar(Config) ->
+ {ok, OldDir} = file:get_cwd(),
+
+ {LatestDir, LatestName} = create_script(latest,Config),
+
+ DataDir = filename:absname(?copydir),
+ LibDir = fname([DataDir, d_normal, lib]),
+ P = [fname([LibDir, 'db-2.1', ebin]),
+ fname([LibDir, 'fe-3.1', ebin])],
+
+ ok = file:set_cwd(LatestDir),
+
+ %% Add dummy relup and sys.config
+ ok = file:write_file("sys.config","[].\n"),
+ ok = file:write_file("relup","{\"LATEST\",[],[]}.\n"),
+
+ {ok, _, _} = systools:make_script(LatestName, [silent, {path, P}]),
+ ok = systools:make_tar(LatestName, [{path, P}]),
+ ok = check_tar(fname(["releases","LATEST","sys.config"]), LatestName),
+ ok = check_tar(fname(["releases","LATEST","relup"]), LatestName),
+ {ok, _, _} = systools:make_tar(LatestName, [{path, P}, silent]),
+ ok = check_tar(fname(["releases","LATEST","sys.config"]), LatestName),
+ ok = check_tar(fname(["releases","LATEST","relup"]), LatestName),
+
+ ok = file:set_cwd(OldDir),
+
+ ok.
+
+system_files_tar(cleanup,Config) ->
+ Dir = ?privdir,
+ file:delete(filename:join(Dir,"sys.config")),
+ file:delete(filename:join(Dir,"relup")),
+ ok.
+
+
+%% make_tar: Check that make_tar fails if relup or sys.config exist
+%% but do not have valid content
+invalid_system_files_tar(Config) ->
+ {ok, OldDir} = file:get_cwd(),
+
+ {LatestDir, LatestName} = create_script(latest,Config),
+
+ DataDir = filename:absname(?copydir),
+ LibDir = fname([DataDir, d_normal, lib]),
+ P = [fname([LibDir, 'db-2.1', ebin]),
+ fname([LibDir, 'fe-3.1', ebin])],
+
+ ok = file:set_cwd(LatestDir),
+
+ {ok, _, _} = systools:make_script(LatestName, [silent, {path, P}]),
+
+ %% Add dummy relup and sys.config - faulty sys.config
+ ok = file:write_file("sys.config","[]\n"), %!!! syntax error - missing '.'
+ ok = file:write_file("relup","{\"LATEST\",[],[]}.\n"),
+
+ error = systools:make_tar(LatestName, [{path, P}]),
+ {error,_,{tar_error,{add,"sys.config",[{error,_}]}}} =
+ systools:make_tar(LatestName, [{path, P}, silent]),
+
+ %% Add dummy relup and sys.config - faulty sys.config
+ ok = file:write_file("sys.config","[x,y].\n"), %!!! faulty format
+ ok = file:write_file("relup","{\"LATEST\",[],[]}.\n"),
+
+ error = systools:make_tar(LatestName, [{path, P}]),
+ {error,_,{tar_error,{add,"sys.config",[invalid_format]}}} =
+ systools:make_tar(LatestName, [{path, P}, silent]),
+
+ %% Add dummy relup and sys.config - faulty relup
+ ok = file:write_file("sys.config","[]\n"),
+ ok = file:write_file("relup","{\"LATEST\"\n"), %!!! syntax error - truncated
+
+ error = systools:make_tar(LatestName, [{path, P}]),
+ {error,_,{tar_error,{add,"relup",[{error,_}]}}} =
+ systools:make_tar(LatestName, [{path, P}, silent]),
+
+ %% Add dummy relup and sys.config - faulty relup
+ ok = file:write_file("sys.config","[]\n"),
+ ok = file:write_file("relup","[].\n"), %!!! faulty format
+
+ error = systools:make_tar(LatestName, [{path, P}]),
+ {error,_,{tar_error,{add,"relup",[invalid_format]}}} =
+ systools:make_tar(LatestName, [{path, P}, silent]),
+
+ ok = file:set_cwd(OldDir),
+
+ ok.
+
+invalid_system_files_tar(cleanup,Config) ->
+ Dir = ?privdir,
+ file:delete(filename:join(Dir,"sys.config")),
+ file:delete(filename:join(Dir,"relup")),
+ ok.
+
+
%% make_tar: Use variable and create separate tar (included in generated tar).
variable_tar(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
@@ -1915,6 +2025,9 @@ create_script(latest_small2,Config) ->
create_script(latest_nokernel,Config) ->
Apps = [{db,"2.1"},{fe,"3.1"}],
do_create_script(latest_nokernel,Config,"4.4",Apps);
+create_script(latest_kernel_start_type,Config) ->
+ Apps = [{kernel,"1.0",load},{db,"2.1"},{fe,"3.1"}],
+ do_create_script(latest_kernel_start_type,Config,"4.4",Apps);
create_script(latest_app_start_type1,Config) ->
Apps = core_apps(current),
do_create_script(latest_app_start_type1,Config,current,Apps);
diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml
index 704ff0a20f..f93eb3a128 100644
--- a/lib/snmp/doc/src/notes.xml
+++ b/lib/snmp/doc/src/notes.xml
@@ -34,6 +34,68 @@
<section>
+ <title>SNMP Development Toolkit 4.22</title>
+ <p>Version 4.22 supports code replacement in runtime from/to
+ version 4.21.7 4.21.6 4.21.5, 4.21.4, 4.21.3, 4.21.2, 4.21.1 and 4.21. </p>
+
+ <section>
+ <title>Improvements and new features</title>
+<!--
+ <p>-</p>
+-->
+
+ <list type="bulleted">
+ <item>
+ <p>Added the <c>log_to_io</c> audit-trail-log converter function
+ to the api modules of both the
+ <seealso marker="snmpm#log_to_io">manager</seealso>
+ and
+ <seealso marker="snmpa#log_to_io">agent</seealso>. </p>
+ <p>Own Id: OTP-9940</p>
+ </item>
+
+ <item>
+ <p>[manager] Introduced a new transport module,
+ <c>snmpm_net_if_mt</c>,
+ which handles all incomming and outgoing
+ traffic in newly created processes. The message/request is
+ processed and then the process exits. </p>
+ <p>Own Id: OTP-9876</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+ <p>-</p>
+
+ <!--
+ <list type="bulleted">
+ <item>
+ <p>[agent] Simultaneous
+ <seealso marker="snmpa#backup">snmpa:backup/1,2</seealso>
+ calls can interfere.
+ The master agent did not check if a backup was already in
+ progress when a backup request was accepted. </p>
+ <p>Own Id: OTP-9884</p>
+ <p>Aux Id: Seq 11995</p>
+ </item>
+
+ </list>
+ -->
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+ </section>
+
+ </section> <!-- 4.22 -->
+
+
+ <section>
<title>SNMP Development Toolkit 4.21.7</title>
<p>Version 4.21.7 supports code replacement in runtime from/to
version 4.21.6, 4.21.5, 4.21.4, 4.21.3, 4.21.2, 4.21.1, 4.21, 4.20.1 and
@@ -47,14 +109,14 @@
<list type="bulleted">
<item>
<p>[agent] DoS attack using GET-BULK with large value of
- MaxRepetitions.
- A preventive method has been implementing by simply
- limit the number of varbinds that can be included in
- a Get-BULK response message. This is specified by the
- new config option,
- <seealso marker="snmp_app#agent_gb_max_vbs">gb_max_vbs</seealso>.
- </p>
- <p>Own Id: OTP-9700</p>
+ MaxRepetitions.
+ A preventive method has been implementing by simply
+ limit the number of varbinds that can be included in
+ a Get-BULK response message. This is specified by the
+ new config option,
+ <seealso marker="snmp_app#agent_gb_max_vbs">gb_max_vbs</seealso>.
+ </p>
+ <p>Own Id: OTP-9700</p>
</item>
</list>
@@ -63,7 +125,7 @@
</section>
<section>
- <title>Reported Fixed Bugs and Malfunctions</title>
+ <title>Fixed Bugs and Malfunctions</title>
<!--
<p>-</p>
-->
@@ -71,10 +133,10 @@
<list type="bulleted">
<item>
<p>[agent] Simultaneous
- <seealso marker="snmpa#backup">snmpa:backup/1,2</seealso>
- calls can interfere.
- The master agent did not check if a backup was already in
- progress when a backup request was accepted. </p>
+ <seealso marker="snmpa#backup">snmpa:backup/1,2</seealso>
+ calls can interfere.
+ The master agent did not check if a backup was already in
+ progress when a backup request was accepted. </p>
<p>Own Id: OTP-9884</p>
<p>Aux Id: Seq 11995</p>
</item>
@@ -106,14 +168,14 @@
<list type="bulleted">
<item>
<p>[agent] DoS attack using GET-BULK with large value of
- MaxRepetitions.
- A preventive method has been implementing by simply
- limit the number of varbinds that can be included in
- a Get-BULK response message. This is specified by the
- new config option,
- <seealso marker="snmp_app#agent_gb_max_vbs">gb_max_vbs</seealso>.
- </p>
- <p>Own Id: OTP-9700</p>
+ MaxRepetitions.
+ A preventive method has been implementing by simply
+ limit the number of varbinds that can be included in
+ a Get-BULK response message. This is specified by the
+ new config option,
+ <seealso marker="snmp_app#agent_gb_max_vbs">gb_max_vbs</seealso>.
+ </p>
+ <p>Own Id: OTP-9700</p>
</item>
</list>
@@ -121,7 +183,7 @@
</section>
<section>
- <title>Reported Fixed Bugs and Malfunctions</title>
+ <title>Fixed Bugs and Malfunctions</title>
<!--
<p>-</p>
-->
@@ -129,12 +191,12 @@
<list type="bulleted">
<item>
<p>[agent] Mib server cache gclimit update function incorrectly calls
- age update function.
- The gclimit update function,
- <seealso marker="snmpa#update_mibs_cache_gclimit">update_mibs_cache_gclimit/1</seealso>,
- <em>incorrectly</em> called the age update function,
- <seealso marker="snmpa#update_mibs_cache_age">update_mibs_cache_age/2</seealso>. </p>
- <p>Johan Claesson</p>
+ age update function.
+ The gclimit update function,
+ <seealso marker="snmpa#update_mibs_cache_gclimit">update_mibs_cache_gclimit/1</seealso>,
+ <em>incorrectly</em> called the age update function,
+ <seealso marker="snmpa#update_mibs_cache_age">update_mibs_cache_age/2</seealso>. </p>
+ <p>Johan Claesson</p>
<p>Own Id: OTP-9868</p>
</item>
diff --git a/lib/snmp/doc/src/snmp.xml b/lib/snmp/doc/src/snmp.xml
index af0833f005..3e6610891f 100644
--- a/lib/snmp/doc/src/snmp.xml
+++ b/lib/snmp/doc/src/snmp.xml
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd">
<erlref>
<header>
<copyright>
- <year>1996</year><year>2009</year>
+ <year>1996</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -391,6 +391,30 @@
version of the protocol data unit. There is a new line
between <c>Vsn</c> and <c>PDU</c>.</p>
+ <marker id="log_to_io"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) -> ok | {error, Reason}</name>
+ <fsummary>Convert an Audit Trail Log to text format</fsummary>
+ <type>
+ <v>LogDir = string()</v>
+ <v>Mibs = [MibName]</v>
+ <v>MibName = string()</v>
+ <v>LogName = string()</v>
+ <v>LogFile = string()</v>
+ <v>Start = Stop = null | datetime() | {local_time,datetime()} | {universal_time,datetime()} </v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>Converts an Audit Trail Log to a readable format and
+ prints it on stdio. See
+ <seealso marker="snmp#log_to_txt">log_to_txt</seealso>
+ above for more info.</p>
+
<marker id="change_log_size"></marker>
</desc>
</func>
diff --git a/lib/snmp/doc/src/snmp_app.xml b/lib/snmp/doc/src/snmp_app.xml
index f6abe783b3..d11eaa2771 100644
--- a/lib/snmp/doc/src/snmp_app.xml
+++ b/lib/snmp/doc/src/snmp_app.xml
@@ -35,8 +35,8 @@
<appsummary>The SNMP Application</appsummary>
<description>
<p>This chapter describes the <c>snmp</c>
- application in OTP. The SNMP application provides the following
- services:</p>
+ application in OTP. The SNMP application provides the following
+ services:</p>
<list type="bulleted">
<item>
<p>a multilingual extensible SNMP agent</p>
@@ -589,16 +589,16 @@
{no_reuse, no_reuse()} |
{filter, manager_net_if_filter_options()} </c></p>
<p>These options are actually specific to the used module.
- The ones shown here are applicable to the default
- <c>manager_net_if_module()</c>.</p>
+ The ones shown here are applicable to the default
+ <c>manager_net_if_module()</c>.</p>
<p>For defaults see the options in <c>manager_net_if_option()</c>.</p>
</item>
<marker id="manager_ni_module"></marker>
<tag><c><![CDATA[manager_net_if_module() = atom() <optional>]]></c></tag>
<item>
- <p>Module which handles the network interface part for the
- SNMP manager. Must implement the
+ <p>The module which handles the network interface part for the
+ SNMP manager. It must implement the
<seealso marker="snmpm_network_interface">snmpm_network_interface</seealso> behaviour.</p>
<p>Default is <c>snmpm_net_if</c>.</p>
</item>
diff --git a/lib/snmp/doc/src/snmp_config.xml b/lib/snmp/doc/src/snmp_config.xml
index 0a49b7a62e..b756f3da7d 100644
--- a/lib/snmp/doc/src/snmp_config.xml
+++ b/lib/snmp/doc/src/snmp_config.xml
@@ -586,18 +586,18 @@
{no_reuse, no_reuse()} |
{filter, manager_net_if_filter_options()}</c></p>
<p>These options are actually specific to the used module.
- The ones shown here are applicable to the default
- <c>manager_net_if_module()</c>.</p>
+ The ones shown here are applicable to the default
+ <c>manager_net_if_module()</c>. </p>
<p>For defaults see the options in <c>manager_net_if_option()</c>.</p>
</item>
<marker id="manager_ni_module"></marker>
<tag><c><![CDATA[manager_net_if_module() = atom() <optional>]]></c></tag>
<item>
- <p>Module which handles the network interface part for the
- SNMP manager. Must implement the
- <seealso marker="snmpm_network_interface">snmpm_network_interface</seealso> behaviour.</p>
- <p>Default is <c>snmpm_net_if</c>.</p>
+ <p>The module which handles the network interface part for the
+ SNMP manager. It must implement the
+ <seealso marker="snmpm_network_interface">snmpm_network_interface</seealso> behaviour. </p>
+ <p>Default is <c>snmpm_net_if</c>. </p>
</item>
<marker id="manager_ni_filter_opts"></marker>
diff --git a/lib/snmp/doc/src/snmp_manager_netif.xml b/lib/snmp/doc/src/snmp_manager_netif.xml
index 2738ca76c1..169e20d10b 100644
--- a/lib/snmp/doc/src/snmp_manager_netif.xml
+++ b/lib/snmp/doc/src/snmp_manager_netif.xml
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE chapter SYSTEM "chapter.dtd">
<chapter>
<header>
<copyright>
- <year>2004</year><year>2009</year>
+ <year>2004</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -35,31 +35,34 @@
<image file="snmp_manager_netif_1.gif">
<icaption>The Purpose of Manager Net if</icaption>
</image>
+
<p>The Network Interface (Net if) process delivers SNMP PDUs to the
- manager server, and receives SNMP PDUs from the manager server.
- The most common behaviour of a Net if process is that is receives
- request PDU from the manager server, encodes the PDU into bytes
- and transmits the bytes onto the network to an agent. When the
- reply from the agent is received by the Net if process, which it
- decodes into an SNMP PDU, which it sends to the manager server.
- </p>
+ manager server, and receives SNMP PDUs from the manager server.
+ The most common behaviour of a Net if process is that is receives
+ request PDU from the manager server, encodes the PDU into bytes
+ and transmits the bytes onto the network to an agent. When the
+ reply from the agent is received by the Net if process, which it
+ decodes into an SNMP PDU, which it sends to the manager server. </p>
+
<p>However, that simple behaviour can be modified in numerous
- ways. For example, the Net if process can apply some kind of
- encrypting/decrypting scheme on the bytes.
- </p>
- <p>It is also possible to write your own Net if process. The default
- Net if process is implemented in the module <c>snmpm_net_if</c> and
- it uses UDP as the transport protocol.
- </p>
- <p>This section describes how to write a Net if process.
- </p>
+ ways. For example, the Net if process can apply some kind of
+ encrypting/decrypting scheme on the bytes. </p>
+
+ <p>The snmp application provides two different modules,
+ <c>snmpm_net_if</c> (the default) and <c>snmpm_net_if_mt</c>,
+ both uses the UDP as the transport protocol. The difference
+ between the two modules is that the latter is "multi-threaded",
+ i.e. for each message/request a new process is created that
+ process the message/request and then exits. </p>
+
+ <p>It is also possible to write your own Net if process,
+ this section describes how to write a Net if processdo that.</p>
<section>
<marker id="mandatory_functions"></marker>
<title>Mandatory Functions</title>
<p>A Net if process must implement the SNMP manager
- <seealso marker="snmpm_network_interface">network interface behaviour</seealso>.
- </p>
+ <seealso marker="snmpm_network_interface">network interface behaviour</seealso>. </p>
</section>
<section>
diff --git a/lib/snmp/doc/src/snmpa.xml b/lib/snmp/doc/src/snmpa.xml
index 2322af28cc..86fde03205 100644
--- a/lib/snmp/doc/src/snmpa.xml
+++ b/lib/snmp/doc/src/snmpa.xml
@@ -501,6 +501,7 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
+ <name>log_to_txt(LogDir)</name>
<name>log_to_txt(LogDir, Mibs)</name>
<name>log_to_txt(LogDir, Mibs, OutFile) -> ok | {error, Reason}</name>
<name>log_to_txt(LogDir, Mibs, OutFile, LogName) -> ok | {error, Reason}</name>
@@ -528,6 +529,37 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
See <seealso marker="snmp#log_to_txt">snmp:log_to_txt</seealso>
for more info.</p>
+ <marker id="log_to_io"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>log_to_io(LogDir) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) -> ok | {error, Reason}</name>
+ <fsummary>Convert an Audit Trail Log to text format</fsummary>
+ <type>
+ <v>LogDir = string()</v>
+ <v>Mibs = [MibName]</v>
+ <v>MibName = string()</v>
+ <v>LogName = string()</v>
+ <v>LogFile = string()</v>
+ <v>Start = Stop = null | datetime() | {local_time,datetime()} | {universal_time,datetime()} </v>
+ <v>Reason = disk_log_open_error() | file_open_error() | term()</v>
+ <v>disk_log_open_error() = {LogName, term()}</v>
+ <v>file_open_error() = {OutFile, term()}</v>
+ </type>
+ <desc>
+ <p>Converts an Audit Trail Log to a readable format and
+ prints it on stdio.
+ <c>LogName</c> defaults to "snmpa_log".
+ <c>LogFile</c> defaults to "snmpa.log".
+ See <seealso marker="snmp#log_to_io">snmp:log_to_io</seealso>
+ for more info.</p>
+
<marker id="change_log_size"></marker>
</desc>
</func>
diff --git a/lib/snmp/doc/src/snmpm.xml b/lib/snmp/doc/src/snmpm.xml
index c36a1b2a24..9bbb6cdbdb 100644
--- a/lib/snmp/doc/src/snmpm.xml
+++ b/lib/snmp/doc/src/snmpm.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2004</year><year>2011</year>
+ <year>2004</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -1237,6 +1237,38 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
See <seealso marker="snmp#log_to_txt">snmp:log_to_txt</seealso>
for more info.</p>
+ <marker id="log_to_io"></marker>
+ </desc>
+ </func>
+
+ <func>
+ <name>log_to_io(LogDir) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) -> ok | {error, Reason}</name>
+ <fsummary>Convert an Audit Trail Log to text format</fsummary>
+ <type>
+ <v>LogDir = string()</v>
+ <v>Mibs = [MibName]</v>
+ <v>MibName = string()</v>
+ <v>LogName = string()</v>
+ <v>LogFile = string()</v>
+ <v>Start = Stop = null | datetime() | {local_time,datetime()} | {universal_time,datetime()} </v>
+ <v>Reason = disk_log_open_error() | file_open_error() | term()</v>
+ <v>disk_log_open_error() = {LogName, term()}</v>
+ <v>file_open_error() = {OutFile, term()}</v>
+ </type>
+ <desc>
+ <p>Converts an Audit Trail Log to a readable format and
+ prints it on stdio.
+ <c>LogName</c> defaults to "snmpm_log".
+ <c>LogFile</c> defaults to "snmpm.log".
+ See <seealso marker="snmp#log_to_io">snmp:log_to_io</seealso>
+ for more info.</p>
+
<marker id="change_log_size"></marker>
</desc>
</func>
diff --git a/lib/snmp/doc/src/snmpm_network_interface_filter.xml b/lib/snmp/doc/src/snmpm_network_interface_filter.xml
index ea1e183848..5f80cec94e 100644
--- a/lib/snmp/doc/src/snmpm_network_interface_filter.xml
+++ b/lib/snmp/doc/src/snmpm_network_interface_filter.xml
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd">
<erlref>
<header>
<copyright>
- <year>2007</year><year>2009</year>
+ <year>2007</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -72,9 +72,10 @@
</list>
<p>Note that the network interface filter is something which is used
by the network interface implementation provided by the application
- (<c>snmpm_net_if</c>). The default filter accepts all messages.</p>
+ (<c>snmpm_net_if</c> and <c>snmpm_net_if_mt</c>).
+ The default filter accepts all messages.</p>
<p>A network interface filter can e.g. be used during testing or for load
- regulation. </p>
+ regulation. </p>
</description>
<section>
diff --git a/lib/snmp/src/agent/snmpa.erl b/lib/snmp/src/agent/snmpa.erl
index c400aaddf7..b45a47ec6b 100644
--- a/lib/snmp/src/agent/snmpa.erl
+++ b/lib/snmp/src/agent/snmpa.erl
@@ -83,8 +83,11 @@
-export([add_agent_caps/2, del_agent_caps/1, get_agent_caps/0]).
%% Audit Trail Log functions
--export([log_to_txt/2, log_to_txt/3, log_to_txt/4,
+-export([log_to_txt/1,
+ log_to_txt/2, log_to_txt/3, log_to_txt/4,
log_to_txt/5, log_to_txt/6, log_to_txt/7,
+ log_to_io/1, log_to_io/2, log_to_io/3,
+ log_to_io/4, log_to_io/5, log_to_io/6,
log_info/0,
change_log_size/1,
get_log_type/0, get_log_type/1,
@@ -780,6 +783,8 @@ get_agent_caps() ->
%%% Audit Trail Log functions
%%%-----------------------------------------------------------------
+log_to_txt(LogDir) ->
+ log_to_txt(LogDir, []).
log_to_txt(LogDir, Mibs) ->
OutFile = "snmpa_log.txt",
LogName = ?audit_trail_log_name,
@@ -800,6 +805,23 @@ log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop) ->
snmp:log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop).
+log_to_io(LogDir) ->
+ log_to_io(LogDir, []).
+log_to_io(LogDir, Mibs) ->
+ LogName = ?audit_trail_log_name,
+ LogFile = ?audit_trail_log_file,
+ snmp:log_to_io(LogDir, Mibs, LogName, LogFile).
+log_to_io(LogDir, Mibs, LogName) ->
+ LogFile = ?audit_trail_log_file,
+ snmp:log_to_io(LogDir, Mibs, LogName, LogFile).
+log_to_io(LogDir, Mibs, LogName, LogFile) ->
+ snmp:log_to_io(LogDir, Mibs, LogName, LogFile).
+log_to_io(LogDir, Mibs, LogName, LogFile, Start) ->
+ snmp:log_to_io(LogDir, Mibs, LogName, LogFile, Start).
+log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) ->
+ snmp:log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop).
+
+
log_info() ->
LogName = ?audit_trail_log_name,
snmp_log:info(LogName).
diff --git a/lib/snmp/src/app/snmp.app.src b/lib/snmp/src/app/snmp.app.src
index a880a14696..b11c1ef934 100644
--- a/lib/snmp/src/app/snmp.app.src
+++ b/lib/snmp/src/app/snmp.app.src
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -91,6 +91,7 @@
snmpm_mpd,
snmpm_net_if,
snmpm_net_if_filter,
+ snmpm_net_if_mt,
snmpm_network_interface,
snmpm_network_interface_filter,
snmpm_server,
diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src
index 2f823a5c2d..14b87390c9 100644
--- a/lib/snmp/src/app/snmp.appup.src
+++ b/lib/snmp/src/app/snmp.appup.src
@@ -22,23 +22,47 @@
%% ----- U p g r a d e -------------------------------------------------------
[
- {"4.21.7",
+ {"4.21.7",
[
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
{update, snmpa_local_db, soft, soft_purge, soft_purge, []},
{update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []}
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+
+ {add_module, snmpm_net_if_mt}
]
- },
+ },
{"4.21.6",
[
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
{update, snmpa_local_db, soft, soft_purge, soft_purge, []},
{update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []}
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+
+ {add_module, snmpm_net_if_mt}
]
},
{"4.21.5",
[
- {load_module, snmpa, soft_purge, soft_purge, []},
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
{load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]},
{load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
{load_module, snmpa_trap, soft_purge, soft_purge, []},
@@ -46,12 +70,20 @@
{update, snmpa_local_db, soft, soft_purge, soft_purge, []},
{update, snmpa_mib, soft, soft_purge, soft_purge, []},
{update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []}
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+
+ {add_module, snmpm_net_if_mt}
]
},
{"4.21.4",
[
- {load_module, snmpa, soft_purge, soft_purge, []},
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
{load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]},
{load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
{load_module, snmpa_trap, soft_purge, soft_purge, []},
@@ -62,12 +94,20 @@
{load_module, snmpa_vacm, soft_purge, soft_purge, []},
{update, snmpa_local_db, soft, soft_purge, soft_purge, []},
{update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []}
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+
+ {add_module, snmpm_net_if_mt}
]
},
{"4.21.3",
[
- {load_module, snmpa, soft_purge, soft_purge, []},
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
{load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]},
{load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
{load_module, snmpa_trap, soft_purge, soft_purge, []},
@@ -78,12 +118,20 @@
{load_module, snmpa_vacm, soft_purge, soft_purge, []},
{update, snmpa_local_db, soft, soft_purge, soft_purge, []},
{update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []}
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+
+ {add_module, snmpm_net_if_mt}
]
},
{"4.21.2",
[
- {load_module, snmpa, soft_purge, soft_purge, []},
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
{load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]},
{load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
{update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
@@ -96,12 +144,20 @@
{load_module, snmp_generic_mnesia, soft_purge, soft_purge, []},
{update, snmpa_local_db, soft, soft_purge, soft_purge, []},
{update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []}
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+
+ {add_module, snmpm_net_if_mt}
]
},
{"4.21.1",
[
- {load_module, snmpa, soft_purge, soft_purge, []},
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
{load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]},
{load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
{update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
@@ -115,12 +171,20 @@
{update, snmpa_local_db, soft, soft_purge, soft_purge, []},
{update, snmpa_mib, soft, soft_purge, soft_purge, []},
{update, snmpa_agent, soft, soft_purge, soft_purge, []},
- {update, snmp_note_store, soft, soft_purge, soft_purge, []}
+ {update, snmp_note_store, soft, soft_purge, soft_purge, []},
+
+ {add_module, snmpm_net_if_mt}
]
},
{"4.21",
[
- {load_module, snmpa, soft_purge, soft_purge, []},
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
{load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
{update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
@@ -134,72 +198,9 @@
{update, snmpa_local_db, soft, soft_purge, soft_purge, []},
{update, snmpa_mib, soft, soft_purge, soft_purge, []},
{update, snmpa_agent, soft, soft_purge, soft_purge, []},
- {update, snmp_note_store, soft, soft_purge, soft_purge, []}
- ]
- },
- {"4.20.1",
- [
- {load_module, snmpa, soft_purge, soft_purge, []},
- {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
- {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
+ {update, snmp_note_store, soft, soft_purge, soft_purge, []},
- {load_module, snmpa_vacm, soft_purge, soft_purge, []},
- {load_module, snmpa_set_lib, soft_purge, soft_purge, []},
- {load_module, snmpa_trap, soft_purge, soft_purge, []},
- {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]},
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []},
- {load_module, snmpm, soft_purge, soft_purge,
- [snmpm_server, snmpm_config, snmp_config]},
- {load_module, snmp_conf, soft_purge, soft_purge, []},
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmpm_mpd, soft_purge, soft_purge,
- [snmp_conf, snmp_config, snmpm_config]},
- {load_module, snmpa_mpd, soft_purge, soft_purge,
- [snmp_conf, snmp_config]},
- {load_module, snmpa_conf, soft_purge, soft_purge, [snmp_config]},
- {update, snmp_note_store, soft, soft_purge, soft_purge, []},
- {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []},
- {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mpd]},
- {update, snmpm_config, soft, soft_purge, soft_purge, [snmp_conf]},
- {update, snmpm_server, soft, soft_purge, soft_purge,
- [snmpm_net_if, snmpm_mpd, snmpm_config]},
- {update, snmpm_net_if, soft, soft_purge, soft_purge,
- [snmp_conf, snmpm_mpd, snmpm_config]}
- ]
- },
- {"4.20",
- [
- {load_module, snmpa, soft_purge, soft_purge, []},
- {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
- {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
-
- {load_module, snmpa_vacm, soft_purge, soft_purge, []},
- {load_module, snmpa_set_lib, soft_purge, soft_purge, []},
- {load_module, snmpa_trap, soft_purge, soft_purge, []},
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []},
- {load_module, snmp_target_mib, soft_purge, soft_purge,
- [snmpa_mib_lib, snmp_conf]},
- {load_module, snmpm, soft_purge, soft_purge,
- [snmpm_server, snmpm_config, snmp_config]},
- {load_module, snmp_conf, soft_purge, soft_purge, []},
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmpm_mpd, soft_purge, soft_purge,
- [snmp_conf, snmp_config, snmpm_config]},
- {load_module, snmpa_mpd, soft_purge, soft_purge,
- [snmp_conf, snmp_config]},
- {load_module, snmpa_conf, soft_purge, soft_purge, [snmp_config]},
- {update, snmp_note_store, soft, soft_purge, soft_purge, []},
- {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []},
- {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mpd]},
- {update, snmpm_config, soft, soft_purge, soft_purge, [snmp_conf]},
- {update, snmpm_server, soft, soft_purge, soft_purge,
- [snmpm_net_if, snmpm_mpd, snmpm_config]},
- {update, snmpm_net_if, soft, soft_purge, soft_purge,
- [snmp_conf, snmpm_mpd, snmpm_config]}
+ {add_module, snmpm_net_if_mt}
]
}
],
@@ -207,23 +208,47 @@
%% ------D o w n g r a d e ---------------------------------------------------
[
- {"4.21.7",
+ {"4.21.7",
[
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
{update, snmpa_local_db, soft, soft_purge, soft_purge, []},
{update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []}
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+
+ {remove, {snmpm_net_if_mt, soft_purge, soft_purge}}
]
- },
+ },
{"4.21.6",
[
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
{update, snmpa_local_db, soft, soft_purge, soft_purge, []},
{update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []}
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+
+ {remove, {snmpm_net_if_mt, soft_purge, soft_purge}}
]
},
{"4.21.5",
[
- {load_module, snmpa, soft_purge, soft_purge, []},
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
{load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]},
{load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
{load_module, snmpa_trap, soft_purge, soft_purge, []},
@@ -231,12 +256,20 @@
{update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
{update, snmpa_local_db, soft, soft_purge, soft_purge, []},
{update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []}
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+
+ {remove, {snmpm_net_if_mt, soft_purge, soft_purge}}
]
},
{"4.21.4",
[
- {load_module, snmpa, soft_purge, soft_purge, []},
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
{load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]},
{load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
{load_module, snmpa_trap, soft_purge, soft_purge, []},
@@ -247,12 +280,20 @@
{load_module, snmpa_vacm, soft_purge, soft_purge, []},
{update, snmpa_local_db, soft, soft_purge, soft_purge, []},
{update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []}
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+
+ {remove, {snmpm_net_if_mt, soft_purge, soft_purge}}
]
},
{"4.21.3",
[
- {load_module, snmpa, soft_purge, soft_purge, []},
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
{load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]},
{load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
{load_module, snmpa_trap, soft_purge, soft_purge, []},
@@ -263,12 +304,20 @@
{load_module, snmpa_vacm, soft_purge, soft_purge, []},
{update, snmpa_local_db, soft, soft_purge, soft_purge, []},
{update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []}
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+
+ {remove, {snmpm_net_if_mt, soft_purge, soft_purge}}
]
},
{"4.21.2",
[
- {load_module, snmpa, soft_purge, soft_purge, []},
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
{load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]},
{load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
{update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
@@ -281,12 +330,20 @@
{load_module, snmp_generic_mnesia, soft_purge, soft_purge, []},
{update, snmpa_local_db, soft, soft_purge, soft_purge, []},
{update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, []}
+ {update, snmpa_agent, soft, soft_purge, soft_purge, []},
+
+ {remove, {snmpm_net_if_mt, soft_purge, soft_purge}}
]
},
{"4.21.1",
[
- {load_module, snmpa, soft_purge, soft_purge, []},
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
{load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]},
{load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
{update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
@@ -300,12 +357,20 @@
{update, snmpa_local_db, soft, soft_purge, soft_purge, []},
{update, snmpa_mib, soft, soft_purge, soft_purge, []},
{update, snmpa_agent, soft, soft_purge, soft_purge, []},
- {update, snmp_note_store, soft, soft_purge, soft_purge, []}
+ {update, snmp_note_store, soft, soft_purge, soft_purge, []},
+
+ {remove, {snmpm_net_if_mt, soft_purge, soft_purge}}
]
},
{"4.21",
[
- {load_module, snmpa, soft_purge, soft_purge, []},
+ {load_module, snmp, soft_purge, soft_purge, [snmp_log]},
+ {load_module, snmpm, soft_purge, soft_purge, [snmp]},
+ {load_module, snmp_log, soft_purge, soft_purge, []},
+ {load_module, snmp_verbosity, soft_purge, soft_purge, []},
+ {load_module, snmpm_mpd, soft_purge, soft_purge, []},
+
+ {load_module, snmpa, soft_purge, soft_purge, [snmp]},
{load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
{update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
@@ -319,71 +384,9 @@
{update, snmpa_local_db, soft, soft_purge, soft_purge, []},
{update, snmpa_mib, soft, soft_purge, soft_purge, []},
{update, snmpa_agent, soft, soft_purge, soft_purge, []},
- {update, snmp_note_store, soft, soft_purge, soft_purge, []}
- ]
- },
- {"4.20.1",
- [
- {load_module, snmpa, soft_purge, soft_purge, []},
- {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
- {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
-
- {load_module, snmpa_vacm, soft_purge, soft_purge, []},
- {load_module, snmpa_set_lib, soft_purge, soft_purge, []},
- {load_module, snmpa_trap, soft_purge, soft_purge, []},
- {load_module, snmp_target_mib, soft_purge, soft_purge, []},
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []},
- {load_module, snmpm, soft_purge, soft_purge,
- [snmpm_server, snmpm_config, snmp_config]},
- {load_module, snmp_conf, soft_purge, soft_purge, []},
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmpm_mpd, soft_purge, soft_purge,
- [snmp_conf, snmp_config, snmpm_config]},
- {load_module, snmpa_mpd, soft_purge, soft_purge,
- [snmp_conf, snmp_config]},
- {load_module, snmpa_conf, soft_purge, soft_purge, [snmp_config]},
{update, snmp_note_store, soft, soft_purge, soft_purge, []},
- {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []},
- {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mpd]},
- {update, snmpm_config, soft, soft_purge, soft_purge, [snmp_conf]},
- {update, snmpm_server, soft, soft_purge, soft_purge,
- [snmpm_net_if, snmpm_mpd, snmpm_config]},
- {update, snmpm_net_if, soft, soft_purge, soft_purge,
- [snmp_conf, snmpm_mpd, snmpm_config]}
- ]
- },
- {"4.20",
- [
- {load_module, snmpa, soft_purge, soft_purge, []},
- {load_module, snmpa_mib_lib, soft_purge, soft_purge, []},
- {update, snmpa_supervisor, soft, soft_purge, soft_purge, []},
- {load_module, snmpa_vacm, soft_purge, soft_purge, []},
- {load_module, snmpa_set_lib, soft_purge, soft_purge, []},
- {load_module, snmpa_trap, soft_purge, soft_purge, []},
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []},
- {load_module, snmp_target_mib, soft_purge, soft_purge, [snmp_conf]},
- {load_module, snmpm, soft_purge, soft_purge,
- [snmpm_server, snmpm_config, snmp_config]},
- {load_module, snmp_conf, soft_purge, soft_purge, []},
- {load_module, snmp_config, soft_purge, soft_purge, []},
- {load_module, snmpm_mpd, soft_purge, soft_purge,
- [snmp_conf, snmp_config, snmpm_config]},
- {load_module, snmpa_mpd, soft_purge, soft_purge,
- [snmp_conf, snmp_config]},
- {load_module, snmpa_conf, soft_purge, soft_purge, [snmp_config]},
- {update, snmp_note_store, soft, soft_purge, soft_purge, []},
- {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []},
- {update, snmpa_local_db, soft, soft_purge, soft_purge, []},
- {update, snmpa_mib, soft, soft_purge, soft_purge, []},
- {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mpd]},
- {update, snmpm_config, soft, soft_purge, soft_purge, [snmp_conf]},
- {update, snmpm_server, soft, soft_purge, soft_purge,
- [snmpm_net_if, snmpm_mpd, snmpm_config]},
- {update, snmpm_net_if, soft, soft_purge, soft_purge,
- [snmp_conf, snmpm_mpd, snmpm_config]}
+ {remove, {snmpm_net_if_mt, soft_purge, soft_purge}}
]
}
]
diff --git a/lib/snmp/src/app/snmp.erl b/lib/snmp/src/app/snmp.erl
index 3e0f05e604..fc03757e3f 100644
--- a/lib/snmp/src/app/snmp.erl
+++ b/lib/snmp/src/app/snmp.erl
@@ -50,6 +50,7 @@
read_mib/1,
log_to_txt/5, log_to_txt/6, log_to_txt/7,
+ log_to_io/4, log_to_io/5, log_to_io/6,
change_log_size/2,
octet_string_to_bits/1, bits_to_octet_string/1,
@@ -843,6 +844,12 @@ log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start) ->
log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop) ->
snmp_log:log_to_txt(LogName, LogFile, LogDir, Mibs, OutFile, Start, Stop).
+log_to_io(LogDir, Mibs, LogName, LogFile) ->
+ snmp_log:log_to_io(LogName, LogFile, LogDir, Mibs).
+log_to_io(LogDir, Mibs, LogName, LogFile, Start) ->
+ snmp_log:log_to_io(LogName, LogFile, LogDir, Mibs, Start).
+log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) ->
+ snmp_log:log_to_io(LogName, LogFile, LogDir, Mibs, Start, Stop).
change_log_size(LogName, NewSize) ->
snmp_log:change_size(LogName, NewSize).
diff --git a/lib/snmp/src/manager/depend.mk b/lib/snmp/src/manager/depend.mk
index 0e7e9e3df7..2e7783c8ed 100644
--- a/lib/snmp/src/manager/depend.mk
+++ b/lib/snmp/src/manager/depend.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2009. All Rights Reserved.
+# Copyright Ericsson AB 2004-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -49,6 +49,13 @@ $(EBIN)/snmpm_net_if.$(EMULATOR): \
snmpm_net_if.erl \
snmpm_network_interface.erl
+$(EBIN)/snmpm_net_if_mt.$(EMULATOR): \
+ ../../include/snmp_types.hrl \
+ ../misc/snmp_debug.hrl \
+ ../misc/snmp_verbosity.hrl \
+ snmpm_net_if_mt.erl \
+ snmpm_network_interface.erl
+
$(EBIN)/snmpm_server.$(EMULATOR): \
../../include/snmp_types.hrl \
../../include/STANDARD-MIB.hrl \
diff --git a/lib/snmp/src/manager/modules.mk b/lib/snmp/src/manager/modules.mk
index 79f3dd65d9..d46545ea3f 100644
--- a/lib/snmp/src/manager/modules.mk
+++ b/lib/snmp/src/manager/modules.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2009. All Rights Reserved.
+# Copyright Ericsson AB 2004-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -31,6 +31,7 @@ MODULES = \
snmpm_mpd \
snmpm_misc_sup \
snmpm_net_if \
+ snmpm_net_if_mt \
snmpm_net_if_filter \
snmpm_server \
snmpm_server_sup \
diff --git a/lib/snmp/src/manager/snmpm.erl b/lib/snmp/src/manager/snmpm.erl
index 6d2ac8d747..89eaee9f80 100644
--- a/lib/snmp/src/manager/snmpm.erl
+++ b/lib/snmp/src/manager/snmpm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -75,8 +75,11 @@
%%
%% Logging
+ log_to_txt/1,
log_to_txt/2, log_to_txt/3, log_to_txt/4,
log_to_txt/5, log_to_txt/6, log_to_txt/7,
+ log_to_io/1, log_to_io/2, log_to_io/3,
+ log_to_io/4, log_to_io/5, log_to_io/6,
change_log_size/1,
get_log_type/0,
set_log_type/1,
@@ -1371,6 +1374,9 @@ cancel_async_request(UserId, ReqId) ->
%%%-----------------------------------------------------------------
%%% Audit Trail Log functions (for backward compatibility)
%%%-----------------------------------------------------------------
+
+log_to_txt(LogDir) ->
+ log_to_txt(LogDir, []).
log_to_txt(LogDir, Mibs) ->
OutFile = "snmpm_log.txt",
LogName = ?audit_trail_log_name,
@@ -1391,6 +1397,23 @@ log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop) ->
snmp:log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop).
+log_to_io(LogDir) ->
+ log_to_io(LogDir, []).
+log_to_io(LogDir, Mibs) ->
+ LogName = ?audit_trail_log_name,
+ LogFile = ?audit_trail_log_file,
+ snmp:log_to_io(LogDir, Mibs, LogName, LogFile).
+log_to_io(LogDir, Mibs, LogName) ->
+ LogFile = ?audit_trail_log_file,
+ snmp:log_to_io(LogDir, Mibs, LogName, LogFile).
+log_to_io(LogDir, Mibs, LogName, LogFile) ->
+ snmp:log_to_io(LogDir, Mibs, LogName, LogFile).
+log_to_io(LogDir, Mibs, LogName, LogFile, Start) ->
+ snmp:log_to_io(LogDir, Mibs, LogName, LogFile, Start).
+log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) ->
+ snmp:log_to_io(LogDir, Mibs, LogFile, Start, Stop).
+
+
change_log_size(NewSize) ->
LogName = ?audit_trail_log_name,
snmp:change_log_size(LogName, NewSize).
diff --git a/lib/snmp/src/manager/snmpm_config.erl b/lib/snmp/src/manager/snmpm_config.erl
index c2e57abddb..5bbf9e5542 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/snmp/src/manager/snmpm_mpd.erl b/lib/snmp/src/manager/snmpm_mpd.erl
index 103c87d32b..883224143e 100644
--- a/lib/snmp/src/manager/snmpm_mpd.erl
+++ b/lib/snmp/src/manager/snmpm_mpd.erl
@@ -110,9 +110,9 @@ process_msg(Msg, Domain, Addr, Port, State, NoteStore, Logger) ->
#message{version = 'version-2', vsn_hdr = Community, data = Data}
when State#state.v2c =:= true ->
HS = ?empty_msg_size + length(Community),
- (catch process_v1_v2c_msg('version-2', NoteStore, Msg,
- Domain, Addr, Port,
- Community, Data, HS, Logger));
+ process_v1_v2c_msg('version-2', NoteStore, Msg,
+ Domain, Addr, Port,
+ Community, Data, HS, Logger);
%% Version 3
#message{version = 'version-3', vsn_hdr = H, data = Data}
diff --git a/lib/snmp/src/manager/snmpm_net_if_mt.erl b/lib/snmp/src/manager/snmpm_net_if_mt.erl
new file mode 100644
index 0000000000..3e87f6a7fb
--- /dev/null
+++ b/lib/snmp/src/manager/snmpm_net_if_mt.erl
@@ -0,0 +1,1259 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(snmpm_net_if_mt).
+
+-behaviour(gen_server).
+-behaviour(snmpm_network_interface).
+
+
+%% Network Interface callback functions
+-export([
+ start_link/2,
+ stop/1,
+ send_pdu/6, % Backward compatibillity
+ send_pdu/7, % Backward compatibillity
+ send_pdu/8,
+
+ inform_response/4,
+
+ note_store/2,
+
+ info/1,
+ verbosity/2,
+ %% system_info_updated/2,
+ get_log_type/1, set_log_type/2,
+ filter_reset/1
+ ]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ code_change/3, terminate/2]).
+
+-define(SNMP_USE_V3, true).
+-include("snmp_types.hrl").
+-include("snmpm_internal.hrl").
+-include("snmpm_atl.hrl").
+-include("snmp_debug.hrl").
+
+%% -define(VMODULE,"NET_IF").
+-include("snmp_verbosity.hrl").
+
+-record(state,
+ {
+ server,
+ note_store,
+ sock,
+ mpd_state,
+ log,
+ irb = auto, % auto | {user, integer()}
+ irgc,
+ filter
+ }).
+
+
+-define(DEFAULT_FILTER_MODULE, snmpm_net_if_filter).
+-define(DEFAULT_FILTER_OPTS, [{module, ?DEFAULT_FILTER_MODULE}]).
+
+-ifdef(snmp_debug).
+-define(GS_START_LINK(Args),
+ gen_server:start_link(?MODULE, Args, [{debug,[trace]}])).
+-else.
+-define(GS_START_LINK(Args),
+ gen_server:start_link(?MODULE, Args, [])).
+-endif.
+
+
+-define(IRGC_TIMEOUT, timer:minutes(5)).
+
+-define(ATL_SEQNO_INITIAL, 1).
+-define(ATL_SEQNO_MAX, 2147483647).
+
+
+%%%-------------------------------------------------------------------
+%%% API
+%%%-------------------------------------------------------------------
+start_link(Server, NoteStore) ->
+ ?d("start_link -> entry with"
+ "~n Server: ~p"
+ "~n NoteStore: ~p", [Server, NoteStore]),
+ Args = [Server, NoteStore],
+ ?GS_START_LINK(Args).
+
+stop(Pid) ->
+ call(Pid, stop).
+
+send_pdu(Pid, Pdu, Vsn, MsgData, Addr, Port) ->
+ send_pdu(Pid, Pdu, Vsn, MsgData, Addr, Port, ?DEFAULT_EXTRA_INFO).
+
+send_pdu(Pid, Pdu, Vsn, MsgData, Addr, Port, ExtraInfo) ->
+ Domain = snmpm_config:default_transport_domain(),
+ send_pdu(Pid, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo).
+
+send_pdu(Pid, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo)
+ when is_record(Pdu, pdu) ->
+ ?d("send_pdu -> entry with"
+ "~n Pid: ~p"
+ "~n Pdu: ~p"
+ "~n Vsn: ~p"
+ "~n MsgData: ~p"
+ "~n Domain: ~p"
+ "~n Addr: ~p"
+ "~n Port: ~p", [Pid, Pdu, Vsn, MsgData, Domain, Addr, Port]),
+ cast(Pid, {send_pdu, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo}).
+
+note_store(Pid, NoteStore) ->
+ call(Pid, {note_store, NoteStore}).
+
+inform_response(Pid, Ref, Addr, Port) ->
+ cast(Pid, {inform_response, Ref, Addr, Port}).
+
+info(Pid) ->
+ call(Pid, info).
+
+verbosity(Pid, V) ->
+ call(Pid, {verbosity, V}).
+
+%% system_info_updated(Pid, What) ->
+%% call(Pid, {system_info_updated, What}).
+
+get_log_type(Pid) ->
+ call(Pid, get_log_type).
+
+set_log_type(Pid, NewType) ->
+ call(Pid, {set_log_type, NewType}).
+
+filter_reset(Pid) ->
+ cast(Pid, filter_reset).
+
+
+%%%-------------------------------------------------------------------
+%%% Callback functions from gen_server
+%%%-------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Func: init/1
+%% Returns: {ok, State} |
+%% {ok, State, Timeout} |
+%% ignore |
+%% {stop, Reason}
+%%--------------------------------------------------------------------
+init([Server, NoteStore]) ->
+ ?d("init -> entry with"
+ "~n Server: ~p"
+ "~n NoteStore: ~p", [Server, NoteStore]),
+ case (catch do_init(Server, NoteStore)) of
+ {error, Reason} ->
+ {stop, Reason};
+ {ok, State} ->
+ {ok, State}
+ end.
+
+do_init(Server, NoteStore) ->
+ process_flag(trap_exit, true),
+
+ %% -- Prio --
+ {ok, Prio} = snmpm_config:system_info(prio),
+ process_flag(priority, Prio),
+
+ %% -- Create inform request table --
+ %% This should really be protected, but it also needs to
+ %% be writable for the worker processes, so...
+ ets:new(snmpm_inform_request_table,
+ [set, public, named_table, {keypos, 1}]),
+
+ %% -- Verbosity --
+ {ok, Verbosity} = snmpm_config:system_info(net_if_verbosity),
+ put(sname, mnif),
+ put(verbosity, Verbosity),
+ ?vlog("starting", []),
+
+ %% -- MPD --
+ {ok, Vsns} = snmpm_config:system_info(versions),
+ MpdState = snmpm_mpd:init(Vsns),
+ ?vdebug("MpdState: ~w", [MpdState]),
+
+ %% -- Module dependent options --
+ {ok, Opts} = snmpm_config:system_info(net_if_options),
+
+ %% -- Inform response behaviour --
+ {ok, IRB} = snmpm_config:system_info(net_if_irb),
+ IrGcRef = irgc_start(IRB),
+
+ %% -- Socket --
+ SndBuf = get_opt(Opts, sndbuf, default),
+ RecBuf = get_opt(Opts, recbuf, default),
+ BindTo = get_opt(Opts, bind_to, false),
+ NoReuse = get_opt(Opts, no_reuse, false),
+ {ok, Port} = snmpm_config:system_info(port),
+ {ok, Sock} = do_open_port(Port, SndBuf, RecBuf, BindTo, NoReuse),
+
+ %% Flow control --
+ FilterOpts = get_opt(Opts, filter, []),
+ FilterMod = create_filter(FilterOpts),
+ ?vdebug("FilterMod: ~w", [FilterMod]),
+
+ %% -- Audit trail log ---
+ {ok, ATL} = snmpm_config:system_info(audit_trail_log),
+ Log = do_init_log(ATL),
+ ?vdebug("Log: ~w", [Log]),
+
+ %% -- Initiate counters ---
+ init_counters(),
+
+ %% -- We are done ---
+ State = #state{server = Server,
+ note_store = NoteStore,
+ mpd_state = MpdState,
+ sock = Sock,
+ log = Log,
+ irb = IRB,
+ irgc = IrGcRef,
+ filter = FilterMod},
+ ?vdebug("started", []),
+ {ok, State}.
+
+
+%% Open port
+do_open_port(Port, SendSz, RecvSz, BindTo, NoReuse) ->
+ ?vtrace("do_open_port -> entry with"
+ "~n Port: ~p"
+ "~n SendSz: ~p"
+ "~n RecvSz: ~p"
+ "~n BindTo: ~p"
+ "~n NoReuse: ~p", [Port, SendSz, RecvSz, BindTo, NoReuse]),
+ IpOpts1 = bind_to(BindTo),
+ IpOpts2 = no_reuse(NoReuse),
+ IpOpts3 = recbuf(RecvSz),
+ IpOpts4 = sndbuf(SendSz),
+ IpOpts = [binary | IpOpts1 ++ IpOpts2 ++ IpOpts3 ++ IpOpts4],
+ OpenRes =
+ case init:get_argument(snmpm_fd) of
+ {ok, [[FdStr]]} ->
+ Fd = list_to_integer(FdStr),
+ gen_udp:open(0, [{fd, Fd}|IpOpts]);
+ error ->
+ gen_udp:open(Port, IpOpts)
+ end,
+ case OpenRes of
+ {error, _} = Error ->
+ throw(Error);
+ OK ->
+ OK
+ end.
+
+bind_to(true) ->
+ case snmpm_config:system_info(address) of
+ {ok, Addr} when is_list(Addr) ->
+ [{ip, list_to_tuple(Addr)}];
+ {ok, Addr} ->
+ [{ip, Addr}];
+ _ ->
+ []
+ end;
+bind_to(_) ->
+ [].
+
+no_reuse(false) ->
+ [{reuseaddr, true}];
+no_reuse(_) ->
+ [].
+
+recbuf(default) ->
+ [];
+recbuf(Sz) ->
+ [{recbuf, Sz}].
+
+sndbuf(default) ->
+ [];
+sndbuf(Sz) ->
+ [{sndbuf, Sz}].
+
+
+create_filter(Opts) when is_list(Opts) ->
+ case get_opt(Opts, module, ?DEFAULT_FILTER_MODULE) of
+ ?DEFAULT_FILTER_MODULE = Mod ->
+ Mod;
+ Module ->
+ snmpm_network_interface_filter:verify(Module),
+ Module
+ end;
+create_filter(BadOpts) ->
+ throw({error, {bad_filter_opts, BadOpts}}).
+
+
+%% ----------------------------------------------------------------------
+%% Audit Trail Logger
+%% ----------------------------------------------------------------------
+
+%% Open log
+do_init_log(false) ->
+ ?vtrace("do_init_log(false) -> entry", []),
+ undefined;
+do_init_log(true) ->
+ ?vtrace("do_init_log(true) -> entry", []),
+ {ok, Type} = snmpm_config:system_info(audit_trail_log_type),
+ {ok, Dir} = snmpm_config:system_info(audit_trail_log_dir),
+ {ok, Size} = snmpm_config:system_info(audit_trail_log_size),
+ {ok, Repair} = snmpm_config:system_info(audit_trail_log_repair),
+ Name = ?audit_trail_log_name,
+ File = filename:absname(?audit_trail_log_file, Dir),
+ case snmpm_config:system_info(audit_trail_log_seqno) of
+ {ok, true} ->
+ Initial = ?ATL_SEQNO_INITIAL,
+ Max = ?ATL_SEQNO_MAX,
+ Module = snmpm_config,
+ Function = increment_counter,
+ Args = [atl_seqno, Initial, Max],
+ SeqNoGen = {Module, Function, Args},
+ case snmp_log:create(Name, File, SeqNoGen, Size, Repair, true) of
+ {ok, Log} ->
+ ?vdebug("log created: ~w", [Log]),
+ {Name, Log, Type};
+ {error, Reason} ->
+ throw({error, {failed_create_audit_log, Reason}})
+ end;
+ _ ->
+ case snmp_log:create(Name, File, Size, Repair, true) of
+ {ok, Log} ->
+ ?vdebug("log created: ~w", [Log]),
+ {Name, Log, Type};
+ {error, Reason} ->
+ throw({error, {failed_create_audit_log, Reason}})
+ end
+ end.
+
+
+%% ----------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Func: handle_call/3
+%% Returns: {reply, Reply, State} |
+%% {reply, Reply, State, Timeout} |
+%% {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, Reply, State} | (terminate/2 is called)
+%% {stop, Reason, State} (terminate/2 is called)
+%%--------------------------------------------------------------------
+handle_call({verbosity, Verbosity}, _From, State) ->
+ ?vlog("received verbosity request", []),
+ put(verbosity, Verbosity),
+ {reply, ok, State};
+
+%% handle_call({system_info_updated, What}, _From, State) ->
+%% ?vlog("received system_info_updated request with What = ~p", [What]),
+%% {NewState, Reply} = handle_system_info_updated(State, What),
+%% {reply, Reply, NewState};
+
+handle_call(get_log_type, _From, State) ->
+ ?vlog("received get-log-type request", []),
+ Reply = (catch handle_get_log_type(State)),
+ {reply, Reply, State};
+
+handle_call({set_log_type, NewType}, _From, State) ->
+ ?vlog("received set-log-type request with NewType = ~p", [NewType]),
+ {NewState, Reply} = (catch handle_set_log_type(State, NewType)),
+ {reply, Reply, NewState};
+
+handle_call({note_store, Pid}, _From, State) ->
+ ?vlog("received new note_store: ~w", [Pid]),
+ {reply, ok, State#state{note_store = Pid}};
+
+handle_call(stop, _From, State) ->
+ ?vlog("received stop request", []),
+ Reply = ok,
+ {stop, normal, Reply, State};
+
+handle_call(info, _From, State) ->
+ ?vlog("received info request", []),
+ Reply = get_info(State),
+ {reply, Reply, State};
+
+handle_call(Req, From, State) ->
+ warning_msg("received unknown request (from ~p): ~n~p", [Req, From]),
+ {reply, {error, {invalid_request, Req}}, State}.
+
+
+%%--------------------------------------------------------------------
+%% Func: handle_cast/2
+%% Returns: {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State} (terminate/2 is called)
+%%--------------------------------------------------------------------
+handle_cast({send_pdu, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo},
+ State) ->
+ ?vlog("received send_pdu message with"
+ "~n Pdu: ~p"
+ "~n Vsn: ~p"
+ "~n MsgData: ~p"
+ "~n Domain: ~p"
+ "~n Addr: ~p"
+ "~n Port: ~p", [Pdu, Vsn, MsgData, Domain, Addr, Port]),
+ maybe_process_extra_info(ExtraInfo),
+ handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, Port, State),
+ {noreply, State};
+
+handle_cast({inform_response, Ref, Addr, Port}, State) ->
+ ?vlog("received inform_response message with"
+ "~n Ref: ~p"
+ "~n Addr: ~p"
+ "~n Port: ~p", [Ref, Addr, Port]),
+ handle_inform_response(Ref, Addr, Port, State),
+ {noreply, State};
+
+handle_cast(filter_reset, State) ->
+ ?vlog("received filter_reset message", []),
+ reset_counters(),
+ {noreply, State};
+
+handle_cast(Msg, State) ->
+ warning_msg("received unknown message: ~n~p", [Msg]),
+ {noreply, State}.
+
+
+%%--------------------------------------------------------------------
+%% Func: handle_info/2
+%% Returns: {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State} (terminate/2 is called)
+%%--------------------------------------------------------------------
+handle_info({udp, Sock, Ip, Port, Bytes}, #state{sock = Sock} = State) ->
+ ?vlog("received ~w bytes from ~p:~p", [size(Bytes), Ip, Port]),
+ handle_udp(Ip, Port, Bytes, State),
+ {noreply, State};
+
+handle_info(inform_response_gc, State) ->
+ ?vlog("received inform_response_gc message", []),
+ State2 = handle_inform_response_gc(State),
+ {noreply, State2};
+
+handle_info({disk_log, _Node, Log, Info}, State) ->
+ ?vlog("received disk_log message: "
+ "~n Info: ~p", [Info]),
+ State2 = handle_disk_log(Log, Info, State),
+ {noreply, State2};
+
+handle_info({'DOWN', _MRef, process, Pid, {net_if_worker, ExitStatus}},
+ State) ->
+ ?vdebug("received DOWN message from net_if-worker: "
+ "~n ExitStatus: ~p", [ExitStatus]),
+ handle_worker_exit(Pid, ExitStatus),
+ {noreply, State};
+
+handle_info(Info, State) ->
+ warning_msg("received unknown info: ~n~p", [Info]),
+ {noreply, State}.
+
+
+%%--------------------------------------------------------------------
+%% Func: terminate/2
+%% Purpose: Shutdown the server
+%% Returns: any (ignored by gen_server)
+%%--------------------------------------------------------------------
+terminate(Reason, #state{log = Log, irgc = IrGcRef}) ->
+ ?vdebug("terminate: ~p", [Reason]),
+ irgc_stop(IrGcRef),
+ %% Close logs
+ do_close_log(Log),
+ ok.
+
+
+do_close_log({Log, _Type}) ->
+ (catch snmp_log:sync(Log)),
+ (catch snmp_log:close(Log)),
+ ok;
+do_close_log(_) ->
+ ok.
+
+
+%%----------------------------------------------------------------------
+%% Func: code_change/3
+%% Purpose: Convert process state when code is changed
+%% Returns: {ok, NewState}
+%%----------------------------------------------------------------------
+
+code_change(_Vsn, State, _Extra) ->
+ ?d("code_change -> entry with"
+ "~n Vsn: ~p"
+ "~n State: ~p"
+ "~n Extra: ~p", [_Vsn, State, _Extra]),
+ {ok, State}.
+
+
+%%%-------------------------------------------------------------------
+%%% Internal functions
+%%%-------------------------------------------------------------------
+
+handle_udp(Addr, Port, Bytes, State) ->
+ Verbosity = get(verbosity),
+ spawn_opt(fun() ->
+ Log = worker_init(State, Verbosity),
+ Res = (catch maybe_handle_recv_msg(
+ Addr, Port, Bytes,
+ State#state{log = Log})),
+ worker_exit(udp, {Addr, Port}, Res)
+ end,
+ [monitor]).
+
+
+maybe_handle_recv_msg(Addr, Port, Bytes, #state{filter = FilterMod} = State) ->
+ case (catch FilterMod:accept_recv(Addr, Port)) of
+ false ->
+ %% Drop the received packet
+ inc(netIfMsgInDrops),
+ ok;
+ _ ->
+ handle_recv_msg(Addr, Port, Bytes, State)
+ end.
+
+
+handle_recv_msg(Addr, Port, Bytes, #state{server = Pid})
+ when is_binary(Bytes) andalso (size(Bytes) =:= 0) ->
+ Pid ! {snmp_error, {empty_message, Addr, Port}, Addr, Port},
+ ok;
+
+handle_recv_msg(Addr, Port, Bytes,
+ #state{server = Pid,
+ note_store = NoteStore,
+ mpd_state = MpdState,
+ sock = Sock,
+ log = Log} = State) ->
+ Domain = snmp_conf:which_domain(Addr), % What the ****...
+ Logger = logger(Log, read, Addr, Port),
+ case (catch snmpm_mpd:process_msg(Bytes, Domain, Addr, Port,
+ MpdState, NoteStore, Logger)) of
+
+ {ok, Vsn, Pdu, MS, ACM} ->
+ maybe_handle_recv_pdu(Addr, Port, Vsn, Pdu, MS, ACM,
+ Logger, State);
+
+ {discarded, Reason, Report} ->
+ ?vdebug("discarded: ~p", [Reason]),
+ ErrorInfo = {failed_processing_message, Reason},
+ Pid ! {snmp_error, ErrorInfo, Addr, Port},
+ maybe_udp_send(State#state.filter, Sock, Addr, Port, Report),
+ ok;
+
+ {discarded, Reason} ->
+ ?vdebug("discarded: ~p", [Reason]),
+ ErrorInfo = {failed_processing_message, Reason},
+ Pid ! {snmp_error, ErrorInfo, Addr, Port},
+ ok;
+
+ Error ->
+ error_msg("processing of received message failed: "
+ "~n ~p", [Error]),
+ ok
+ end.
+
+
+maybe_handle_recv_pdu(Addr, Port,
+ Vsn, #pdu{type = Type} = Pdu, PduMS, ACM,
+ Logger,
+ #state{filter = FilterMod} = State) ->
+ case (catch FilterMod:accept_recv_pdu(Addr, Port, Type)) of
+ false ->
+ inc(netIfPduInDrops),
+ ok;
+ _ ->
+ handle_recv_pdu(Addr, Port, Vsn, Pdu, PduMS, ACM, Logger, State)
+ end;
+maybe_handle_recv_pdu(Addr, Port, Vsn, Trap, PduMS, ACM, Logger,
+ #state{filter = FilterMod} = State)
+ when is_record(Trap, trappdu) ->
+ case (catch FilterMod:accept_recv_pdu(Addr, Port, trappdu)) of
+ false ->
+ inc(netIfPduInDrops),
+ ok;
+ _ ->
+ handle_recv_pdu(Addr, Port, Vsn, Trap, PduMS, ACM, Logger, State)
+ end;
+maybe_handle_recv_pdu(Addr, Port, Vsn, Pdu, PduMS, ACM, Logger, State) ->
+ handle_recv_pdu(Addr, Port, Vsn, Pdu, PduMS, ACM, Logger, State).
+
+
+handle_recv_pdu(Addr, Port,
+ Vsn, #pdu{type = 'inform-request'} = Pdu, _PduMS, ACM,
+ Logger, #state{server = Pid, irb = IRB} = State) ->
+ handle_inform_request(IRB, Pid, Vsn, Pdu, ACM,
+ Addr, Port, Logger, State);
+handle_recv_pdu(Addr, Port,
+ _Vsn, #pdu{type = report} = Pdu, _PduMS, ok,
+ _Logger,
+ #state{server = Pid} = _State) ->
+ ?vtrace("received report - ok", []),
+ Pid ! {snmp_report, {ok, Pdu}, Addr, Port},
+ ok;
+handle_recv_pdu(Addr, Port,
+ _Vsn, #pdu{type = report} = Pdu, _PduMS,
+ {error, ReqId, Reason},
+ _Logger,
+ #state{server = Pid} = _State) ->
+ ?vtrace("received report - error", []),
+ Pid ! {snmp_report, {error, ReqId, Reason, Pdu}, Addr, Port},
+ ok;
+handle_recv_pdu(Addr, Port,
+ _Vsn, #pdu{type = 'snmpv2-trap'} = Pdu, _PduMS, _ACM,
+ _Logger,
+ #state{server = Pid} = _State) ->
+ ?vtrace("received snmpv2-trap", []),
+ Pid ! {snmp_trap, Pdu, Addr, Port},
+ ok;
+handle_recv_pdu(Addr, Port,
+ _Vsn, Trap, _PduMS, _ACM,
+ _Logger,
+ #state{server = Pid} = _State) when is_record(Trap, trappdu) ->
+ ?vtrace("received trappdu", []),
+ Pid ! {snmp_trap, Trap, Addr, Port},
+ ok;
+handle_recv_pdu(Addr, Port,
+ _Vsn, Pdu, _PduMS, _ACM,
+ _Logger,
+ #state{server = Pid} = _State) when is_record(Pdu, pdu) ->
+ ?vtrace("received pdu", []),
+ Pid ! {snmp_pdu, Pdu, Addr, Port},
+ ok;
+handle_recv_pdu(_Addr, _Port, _Vsn, Pdu, _PduMS, ACM, _Logger, _State) ->
+ ?vlog("received unexpected pdu: "
+ "~n Pdu: ~p"
+ "~n ACM: ~p", [Pdu, ACM]),
+ ok.
+
+
+handle_inform_request(auto, Pid, Vsn, Pdu, ACM, Addr, Port, Logger, State) ->
+ ?vtrace("received inform-request (true)", []),
+ Pid ! {snmp_inform, ignore, Pdu, Addr, Port},
+ RePdu = make_response_pdu(Pdu),
+ maybe_send_inform_response(RePdu, Vsn, ACM, Addr, Port, Logger, State);
+handle_inform_request({user, To}, Pid, Vsn, #pdu{request_id = ReqId} = Pdu,
+ ACM, Addr, Port, _Logger, _State) ->
+ ?vtrace("received inform-request (false)", []),
+
+ Pid ! {snmp_inform, ReqId, Pdu, Addr, Port},
+
+ %% Before we go any further, we need to check that we have not
+ %% already received this message (possible resend).
+
+ Key = {ReqId, Addr, Port},
+ case ets:lookup(snmpm_inform_request_table, Key) of
+ [_] ->
+ %% OK, we already know about this. We assume this
+ %% is a resend. Either the agent is really eager or
+ %% the user has not answered yet. Bad user!
+ ok;
+ [] ->
+ RePdu = make_response_pdu(Pdu),
+ Expire = t() + To,
+ Rec = {Key, Expire, {Vsn, ACM, RePdu}},
+ ets:insert(snmpm_inform_request_table, Rec)
+ end,
+ ok.
+
+handle_inform_response(Ref, Addr, Port, State) ->
+ Verbosity = get(verbosity),
+ spawn_opt(fun() ->
+ Log = worker_init(State, Verbosity),
+ Res = (catch do_handle_inform_response(
+ Ref,
+ Addr, Port,
+ State#state{log = Log})),
+ worker_exit(inform_reponse, {Addr, Port}, Res)
+ end,
+ [monitor]).
+
+
+
+do_handle_inform_response(Ref, Addr, Port, State) ->
+ Key = {Ref, Addr, Port},
+ case ets:lookup(snmpm_inform_request_table, Key) of
+ [{Key, _, {Vsn, ACM, RePdu}}] ->
+ Logger = logger(State#state.log, read, Addr, Port),
+ ets:delete(snmpm_inform_request_table, Key),
+ maybe_send_inform_response(RePdu, Vsn, ACM, Addr, Port,
+ Logger, State);
+ [] ->
+ %% Already acknowledged, or the user was to slow to reply...
+ ok
+ end,
+ ok.
+
+maybe_send_inform_response(RePdu, Vsn, ACM, Addr, Port, Logger,
+ #state{server = Pid,
+ sock = Sock,
+ filter = FilterMod}) ->
+ case (catch FilterMod:accept_send_pdu(Addr, Port, pdu_type_of(RePdu))) of
+ false ->
+ inc(netIfPduOutDrops),
+ ok;
+ _ ->
+ case snmpm_mpd:generate_response_msg(Vsn, RePdu, ACM, Logger) of
+ {ok, Msg} ->
+ maybe_udp_send(FilterMod, Sock, Addr, Port, Msg);
+ {discarded, Reason} ->
+ ?vlog("failed generating response message:"
+ "~n Reason: ~p", [Reason]),
+ ReqId = RePdu#pdu.request_id,
+ ErrorInfo = {failed_generating_response, {RePdu, Reason}},
+ Pid ! {snmp_error, ReqId, ErrorInfo, Addr, Port},
+ ok
+ end
+ end.
+
+handle_inform_response_gc(#state{irb = IRB} = State) ->
+ ets:safe_fixtable(snmpm_inform_request_table, true),
+ do_irgc(ets:first(snmpm_inform_request_table), t()),
+ ets:safe_fixtable(snmpm_inform_request_table, false),
+ State#state{irgc = irgc_start(IRB)}.
+
+%% We are deleting at the same time as we are traversing the table!!!
+do_irgc('$end_of_table', _) ->
+ ok;
+do_irgc(Key, Now) ->
+ Next = ets:next(snmpm_inform_request_table, Key),
+ case ets:lookup(snmpm_inform_request_table, Key) of
+ [{Key, BestBefore, _}] when BestBefore < Now ->
+ ets:delete(snmpm_inform_request_table, Key);
+ _ ->
+ ok
+ end,
+ do_irgc(Next, Now).
+
+irgc_start(auto) ->
+ undefined;
+irgc_start(_) ->
+ erlang:send_after(?IRGC_TIMEOUT, self(), inform_response_gc).
+
+irgc_stop(undefined) ->
+ ok;
+irgc_stop(Ref) ->
+ (catch erlang:cancel_timer(Ref)).
+
+
+handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, Port, State) ->
+ Verbosity = get(verbosity),
+ spawn_opt(fun() ->
+ Log = worker_init(State, Verbosity),
+ Res = (catch maybe_handle_send_pdu(
+ Pdu, Vsn, MsgData,
+ Domain, Addr, Port,
+ State#state{log = Log})),
+ worker_exit(send_pdu, {Domain, Addr, Port}, Res)
+ end,
+ [monitor]).
+
+maybe_handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, Port,
+ #state{filter = FilterMod} = State) ->
+ case (catch FilterMod:accept_send_pdu(Addr, Port, pdu_type_of(Pdu))) of
+ false ->
+ inc(netIfPduOutDrops),
+ ok;
+ _ ->
+ do_handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, Port, State)
+ end.
+
+do_handle_send_pdu(Pdu, Vsn, MsgData, _Domain, Addr, Port,
+ #state{server = Pid,
+ note_store = NoteStore,
+ sock = Sock,
+ log = Log,
+ filter = FilterMod}) ->
+ Logger = logger(Log, write, Addr, Port),
+ case (catch snmpm_mpd:generate_msg(Vsn, NoteStore,
+ Pdu, MsgData, Logger)) of
+ {ok, Msg} ->
+ ?vtrace("do_handle_send_pdu -> message generated", []),
+ maybe_udp_send(FilterMod, Sock, Addr, Port, Msg);
+ {discarded, Reason} ->
+ ?vlog("PDU not sent: "
+ "~n PDU: ~p"
+ "~n Reason: ~p", [Pdu, Reason]),
+ Pid ! {snmp_error, Pdu, Reason},
+ ok
+ end.
+
+
+maybe_udp_send(FilterMod, Sock, Addr, Port, Msg) ->
+ case (catch FilterMod:accept_send(Addr, Port)) of
+ false ->
+ inc(netIfMsgOutDrops),
+ ok;
+ _ ->
+ udp_send(Sock, Addr, Port, Msg)
+ end.
+
+
+udp_send(Sock, Addr, Port, Msg) ->
+ case (catch gen_udp:send(Sock, Addr, Port, Msg)) of
+ ok ->
+ ?vdebug("sent ~w bytes to ~w:~w [~w]",
+ [sz(Msg), Addr, Port, Sock]),
+ ok;
+ {error, Reason} ->
+ error_msg("failed sending message to ~p:~p: "
+ "~n ~p",[Addr, Port, Reason]),
+ ok;
+ Error ->
+ error_msg("failed sending message to ~p:~p: "
+ "~n ~p",[Addr, Port, Error]),
+ ok
+ end.
+
+sz(B) when is_binary(B) ->
+ size(B);
+sz(L) when is_list(L) ->
+ length(L);
+sz(_) ->
+ undefined.
+
+
+handle_disk_log(_Log, {wrap, NoLostItems}, State) ->
+ ?vlog("Audit Trail Log - wrapped: ~w previously logged items where lost",
+ [NoLostItems]),
+ State;
+handle_disk_log(_Log, {truncated, NoLostItems}, State) ->
+ ?vlog("Audit Trail Log - truncated: ~w items where lost when truncating",
+ [NoLostItems]),
+ State;
+handle_disk_log(_Log, full, State) ->
+ error_msg("Failed to write to Audit Trail Log (full)", []),
+ State;
+handle_disk_log(_Log, {error_status, ok}, State) ->
+ State;
+handle_disk_log(_Log, {error_status, {error, Reason}}, State) ->
+ error_msg("Error status received from Audit Trail Log: "
+ "~n~p", [Reason]),
+ State;
+handle_disk_log(_Log, _Info, State) ->
+ State.
+
+
+%% mk_discovery_msg('version-3', Pdu, _VsnHdr, UserName) ->
+%% ScopedPDU = #scopedPdu{contextEngineID = "",
+%% contextName = "",
+%% data = Pdu},
+%% Bytes = snmp_pdus:enc_scoped_pdu(ScopedPDU),
+%% MsgID = get(msg_id),
+%% put(msg_id,MsgID+1),
+%% UsmSecParams =
+%% #usmSecurityParameters{msgAuthoritativeEngineID = "",
+%% msgAuthoritativeEngineBoots = 0,
+%% msgAuthoritativeEngineTime = 0,
+%% msgUserName = UserName,
+%% msgPrivacyParameters = "",
+%% msgAuthenticationParameters = ""},
+%% SecBytes = snmp_pdus:enc_usm_security_parameters(UsmSecParams),
+%% PduType = Pdu#pdu.type,
+%% Hdr = #v3_hdr{msgID = MsgID,
+%% msgMaxSize = 1000,
+%% msgFlags = snmp_misc:mk_msg_flags(PduType, 0),
+%% msgSecurityModel = ?SEC_USM,
+%% msgSecurityParameters = SecBytes},
+%% Msg = #message{version = 'version-3', vsn_hdr = Hdr, data = Bytes},
+%% case (catch snmp_pdus:enc_message_only(Msg)) of
+%% {'EXIT', Reason} ->
+%% error("Encoding error. Pdu: ~w. Reason: ~w",[Pdu, Reason]),
+%% error;
+%% L when list(L) ->
+%% {Msg, L}
+%% end;
+%% mk_discovery_msg(Version, Pdu, {Com, _, _, _, _}, UserName) ->
+%% Msg = #message{version = Version, vsn_hdr = Com, data = Pdu},
+%% case catch snmp_pdus:enc_message(Msg) of
+%% {'EXIT', Reason} ->
+%% error("Encoding error. Pdu: ~w. Reason: ~w",[Pdu, Reason]),
+%% error;
+%% L when list(L) ->
+%% {Msg, L}
+%% end.
+
+
+%% mk_msg('version-3', Pdu, {Context, User, EngineID, CtxEngineId, SecLevel},
+%% MsgData) ->
+%% %% Code copied from snmp_mpd.erl
+%% {MsgId, SecName, SecData} =
+%% if
+%% tuple(MsgData), Pdu#pdu.type == 'get-response' ->
+%% MsgData;
+%% true ->
+%% Md = get(msg_id),
+%% put(msg_id, Md + 1),
+%% {Md, User, []}
+%% end,
+%% ScopedPDU = #scopedPdu{contextEngineID = CtxEngineId,
+%% contextName = Context,
+%% data = Pdu},
+%% ScopedPDUBytes = snmp_pdus:enc_scoped_pdu(ScopedPDU),
+
+%% PduType = Pdu#pdu.type,
+%% V3Hdr = #v3_hdr{msgID = MsgId,
+%% msgMaxSize = 1000,
+%% msgFlags = snmp_misc:mk_msg_flags(PduType, SecLevel),
+%% msgSecurityModel = ?SEC_USM},
+%% Message = #message{version = 'version-3', vsn_hdr = V3Hdr,
+%% data = ScopedPDUBytes},
+%% SecEngineID = case PduType of
+%% 'get-response' -> snmp_framework_mib:get_engine_id();
+%% _ -> EngineID
+%% end,
+%% case catch snmp_usm:generate_outgoing_msg(Message, SecEngineID,
+%% SecName, SecData, SecLevel) of
+%% {'EXIT', Reason} ->
+%% error("Encoding error. Pdu: ~w. Reason: ~w",[Pdu, Reason]),
+%% error;
+%% {error, Reason} ->
+%% error("Encoding error. Pdu: ~w. Reason: ~w",[Pdu, Reason]),
+%% error;
+%% Packet ->
+%% Packet
+%% end;
+%% mk_msg(Version, Pdu, {Com, _User, _EngineID, _Ctx, _SecLevel}, _SecData) ->
+%% Msg = #message{version = Version, vsn_hdr = Com, data = Pdu},
+%% case catch snmp_pdus:enc_message(Msg) of
+%% {'EXIT', Reason} ->
+%% error("Encoding error. Pdu: ~w. Reason: ~w",[Pdu, Reason]),
+%% error;
+%% B when list(B) ->
+%% B
+%% end.
+
+
+%% handle_system_info_updated(#state{log = {Log, _OldType}} = State,
+%% audit_trail_log_type = _What) ->
+%% %% Just to make sure, check that ATL is actually enabled
+%% case snmpm_config:system_info(audit_trail_log) of
+%% {ok, true} ->
+%% {ok, Type} = snmpm_config:system_info(audit_trail_log_type),
+%% NewState = State#state{log = {Log, Type}},
+%% {NewState, ok};
+%% _ ->
+%% {State, {error, {adt_not_enabled}}}
+%% end;
+%% handle_system_info_updated(_State, _What) ->
+%% ok.
+
+handle_get_log_type(#state{log = {_Log, Value}} = State) ->
+ %% Just to make sure, check that ATL is actually enabled
+ case snmpm_config:system_info(audit_trail_log) of
+ {ok, true} ->
+ Type =
+ case {lists:member(read, Value), lists:member(write, Value)} of
+ {true, true} ->
+ read_write;
+ {true, false} ->
+ read;
+ {false, true} ->
+ write;
+ {false, false} ->
+ throw({State, {error, {bad_atl_type, Value}}})
+ end,
+ {ok, Type};
+ _ ->
+ {error, not_enabled}
+ end;
+handle_get_log_type(_State) ->
+ {error, not_enabled}.
+
+handle_set_log_type(#state{log = {Log, OldValue}} = State, NewType) ->
+ %% Just to make sure, check that ATL is actually enabled
+ case snmpm_config:system_info(audit_trail_log) of
+ {ok, true} ->
+ NewValue =
+ case NewType of
+ read ->
+ [read];
+ write ->
+ [write];
+ read_write ->
+ [read,write];
+ _ ->
+ throw({State, {error, {bad_atl_type, NewType}}})
+ end,
+ NewState = State#state{log = {Log, NewValue}},
+ OldType =
+ case {lists:member(read, OldValue),
+ lists:member(write, OldValue)} of
+ {true, true} ->
+ read_write;
+ {true, false} ->
+ read;
+ {false, true} ->
+ write;
+ {false, false} ->
+ throw({State, {error, {bad_atl_type, OldValue}}})
+ end,
+ {NewState, {ok, OldType}};
+ _ ->
+ {State, {error, not_enabled}}
+ end;
+handle_set_log_type(State, _NewType) ->
+ {State, {error, not_enabled}}.
+
+
+%% -------------------------------------------------------------------
+
+worker_init(#state{log = undefined = Log}, Verbosity) ->
+ worker_init2(Log, Verbosity);
+worker_init(#state{log = {Name, Log, Type}}, Verbosity) ->
+ case snmp_log:open(Name, Log) of
+ {ok, NewLog} ->
+ worker_init2({Name, NewLog, Type}, Verbosity);
+ {error, Reason} ->
+ warning_msg("NetIf worker ~p failed opening ATL: "
+ "~n ~p", [self(), Reason]),
+ NewLog = undefined,
+ worker_init2({Name, NewLog, Type}, Verbosity)
+ end;
+worker_init(State, Verbosity) ->
+ ?vinfo("worker_init -> entry with invalid data: "
+ "~n State: ~p"
+ "~n Verbosity: ~p", [State, Verbosity]),
+ exit({worker_init, State, Verbosity}).
+
+worker_init2(Log, Verbosity) ->
+ put(sname, mnifw),
+ put(verbosity, Verbosity),
+ Log.
+
+
+worker_exit(Tag, Info, Result) ->
+ exit({net_if_worker, {Tag, Info, Result}}).
+
+handle_worker_exit(_, {_, _, ok}) ->
+ ok;
+handle_worker_exit(Pid, {udp, {Addr, Port}, ExitStatus}) ->
+ warning_msg("Worker process (~p) terminated "
+ "while processing (incomming) message from ~w:~w: "
+ "~n~p", [Pid, Addr, Port, ExitStatus]),
+ ok;
+handle_worker_exit(Pid, {send_pdu, {Domain, Addr, Port}, ExitStatus}) ->
+ warning_msg("Worker process (~p) terminated "
+ "while processing (outgoing) pdu for [~w] ~w:~w: "
+ "~n~p", [Pid, Domain, Addr, Port, ExitStatus]),
+ ok;
+handle_worker_exit(Pid, {inform_response, {Addr, Port}, ExitStatus}) ->
+ warning_msg("Worker process (~p) terminated "
+ "while processing (outgoing) inform response for ~w:~w: "
+ "~n~p", [Pid, Addr, Port, ExitStatus]),
+ ok;
+handle_worker_exit(_, _) ->
+ ok.
+
+
+%% -------------------------------------------------------------------
+
+make_response_pdu(#pdu{request_id = ReqId, varbinds = Vbs}) ->
+ #pdu{type = 'get-response',
+ request_id = ReqId,
+ error_status = noError,
+ error_index = 0,
+ varbinds = Vbs}.
+
+
+%% ----------------------------------------------------------------
+
+pdu_type_of(#pdu{type = Type}) ->
+ Type;
+pdu_type_of(TrapPdu) when is_record(TrapPdu, trappdu) ->
+ trap.
+
+
+%% -------------------------------------------------------------------
+
+%% At this point this function is used during testing
+maybe_process_extra_info(?DEFAULT_EXTRA_INFO) ->
+ ok;
+maybe_process_extra_info({?SNMPM_EXTRA_INFO_TAG, Fun})
+ when is_function(Fun, 0) ->
+ (catch Fun()),
+ ok;
+maybe_process_extra_info(_ExtraInfo) ->
+ ok.
+
+
+%% -------------------------------------------------------------------
+
+t() ->
+ {A,B,C} = erlang:now(),
+ A*1000000000+B*1000+(C div 1000).
+
+
+%% -------------------------------------------------------------------
+
+logger(undefined, _Type, _Addr, _Port) ->
+ fun(_) ->
+ ok
+ end;
+logger({_Name, Log, Types}, Type, Addr, Port) ->
+ case lists:member(Type, Types) of
+ true ->
+ fun(Msg) ->
+ snmp_log:log(Log, Msg, Addr, Port)
+ end;
+ false ->
+ fun(_) ->
+ ok
+ end
+ end.
+
+
+%% -------------------------------------------------------------------
+
+%% info_msg(F, A) ->
+%% ?snmpm_info("NET-IF server: " ++ F, A).
+
+warning_msg(F, A) ->
+ ?snmpm_warning("NET-IF server: " ++ F, A).
+
+error_msg(F, A) ->
+ ?snmpm_error("NET-IF server: " ++ F, A).
+
+
+
+%%%-------------------------------------------------------------------
+
+% get_opt(Key, Opts) ->
+% ?vtrace("get option ~w", [Key]),
+% snmp_misc:get_option(Key, Opts).
+
+get_opt(Opts, Key, Def) ->
+ ?vtrace("get option ~w with default ~p", [Key, Def]),
+ snmp_misc:get_option(Key, Opts, Def).
+
+
+%% -------------------------------------------------------------------
+
+get_info(#state{sock = Id}) ->
+ ProcSize = proc_mem(self()),
+ PortInfo = get_port_info(Id),
+ [{process_memory, ProcSize}, {port_info, PortInfo}].
+
+proc_mem(P) when is_pid(P) ->
+ case (catch erlang:process_info(P, memory)) of
+ {memory, Sz} when is_integer(Sz) ->
+ Sz;
+ _ ->
+ undefined
+ end.
+%% proc_mem(_) ->
+%% undefined.
+
+
+get_port_info(Id) ->
+ PortInfo =
+ case (catch erlang:port_info(Id)) of
+ PI when is_list(PI) ->
+ [{port_info, PI}];
+ _ ->
+ []
+ end,
+ PortStatus =
+ case (catch prim_inet:getstatus(Id)) of
+ {ok, PS} ->
+ [{port_status, PS}];
+ _ ->
+ []
+ end,
+ PortAct =
+ case (catch inet:getopts(Id, [active])) of
+ {ok, PA} ->
+ [{port_act, PA}];
+ _ ->
+ []
+ end,
+ PortStats =
+ case (catch inet:getstat(Id)) of
+ {ok, Stat} ->
+ [{port_stats, Stat}];
+ _ ->
+ []
+ end,
+ IfList =
+ case (catch inet:getif(Id)) of
+ {ok, IFs} ->
+ [{interfaces, IFs}];
+ _ ->
+ []
+ end,
+ BufSz =
+ case (catch inet:getopts(Id, [recbuf, sndbuf, buffer])) of
+ {ok, Sz} ->
+ [{buffer_size, Sz}];
+ _ ->
+ []
+ end,
+ [{socket, Id}] ++
+ IfList ++
+ PortStats ++
+ PortInfo ++
+ PortStatus ++
+ PortAct ++
+ BufSz.
+
+
+%%-----------------------------------------------------------------
+%% Counter functions
+%%-----------------------------------------------------------------
+init_counters() ->
+ F = fun(Counter) -> maybe_create_counter(Counter) end,
+ lists:map(F, counters()).
+
+reset_counters() ->
+ F = fun(Counter) -> snmpm_config:reset_stats_counter(Counter) end,
+ lists:map(F, counters()).
+
+maybe_create_counter(Counter) ->
+ snmpm_config:maybe_cre_stats_counter(Counter, 0).
+
+counters() ->
+ [
+ netIfMsgOutDrops,
+ netIfMsgInDrops,
+ netIfPduOutDrops,
+ netIfPduInDrops
+ ].
+
+inc(Name) -> inc(Name, 1).
+inc(Name, N) -> snmpm_config:incr_stats_counter(Name, N).
+
+%% get_counters() ->
+%% Counters = counters(),
+%% get_counters(Counters, []).
+
+%% get_counters([], Acc) ->
+%% lists:reverse(Acc);
+%% get_counters([Counter|Counters], Acc) ->
+%% case snmpm_config:get_stats_counter(Counter) of
+%% {ok, CounterVal} ->
+%% get_counters(Counters, [{Counter, CounterVal}|Acc]);
+%% _ ->
+%% get_counters(Counters, Acc)
+%% end.
+
+
+%% ----------------------------------------------------------------
+
+call(Pid, Req) ->
+ call(Pid, Req, infinity).
+
+call(Pid, Req, Timeout) ->
+ gen_server:call(Pid, Req, Timeout).
+
+cast(Pid, Msg) ->
+ gen_server:cast(Pid, Msg).
+
diff --git a/lib/snmp/src/misc/snmp_log.erl b/lib/snmp/src/misc/snmp_log.erl
index 2c781810ef..a8c5df0b64 100644
--- a/lib/snmp/src/misc/snmp_log.erl
+++ b/lib/snmp/src/misc/snmp_log.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -21,7 +21,7 @@
-export([
- create/4, create/5, create/6,
+ create/4, create/5, create/6, open/1, open/2,
change_size/2, close/1, sync/1, info/1,
log/4,
log_to_txt/5, log_to_txt/6, log_to_txt/7,
@@ -109,6 +109,24 @@ create(Name, File, SeqNoGen, Size, Repair, Notify) ->
{error, {bad_args, Name, File, SeqNoGen, Size, Repair, Notify}}.
+%% -- open ---
+
+%% Open an already existing ( = open ) log
+
+open(Name) ->
+ open(Name, #snmp_log{seqno = disabled}).
+open(Name, #snmp_log{seqno = SeqNoGen} = _OldLog) ->
+ %% We include mode in the opts just to be on the safe side
+ case disk_log:open([{name, Name}, {mode, read_write}]) of
+ {ok, Log} ->
+ %% SeqNo must be proprly initiated also
+ {ok, #snmp_log{id = Log, seqno = SeqNoGen}};
+ {repaired, Log, _RecBytes, _BadBytes} ->
+ {ok, #snmp_log{id = Log, seqno = SeqNoGen}};
+ ERROR ->
+ ERROR
+ end.
+
%% -- close ---
@@ -394,6 +412,14 @@ log_to_io(Log, FileName, Dir, Mibs, Start) ->
log_to_io(Log, FileName, Dir, Mibs, Start, Stop)
when is_list(Mibs) ->
+ ?vtrace("log_to_io -> entry with"
+ "~n Log: ~p"
+ "~n FileName: ~p"
+ "~n Dir: ~p"
+ "~n Mibs: ~p"
+ "~n Start: ~p"
+ "~n Stop: ~p",
+ [Log, FileName, Dir, Mibs, Start, Stop]),
File = filename:join(Dir, FileName),
Converter = fun(L) ->
do_log_to_io(L, Mibs, Start, Stop)
@@ -401,28 +427,10 @@ log_to_io(Log, FileName, Dir, Mibs, Start, Stop)
log_convert(Log, File, Converter).
-%% -- log_to_plain ---
-
-%% log_to_plain(Log, FileName, Dir) ->
-%% log_to_plain(Log, FileName, Dir, null, null).
-
-%% log_to_plain(Log, FileName, Dir, Start) ->
-%% log_to_plain(Log, FileName, Dir, Start, null).
-
-%% log_to_plain(Log, FileName, Dir, Start, Stop)
-%% when is_list(Mibs) ->
-%% File = filename:join(Dir, FileName),
-%% Converter = fun(L) ->
-%% do_log_to_plain(L, Start, Stop)
-%% end,
-%% log_convert(Log, File, Converter).
-
-
%% --------------------------------------------------------------------
%% Internal functions
%% --------------------------------------------------------------------
-
%% -- log_convert ---
log_convert(#snmp_log{id = Log}, File, Converter) ->
@@ -431,6 +439,26 @@ log_convert(Log, File, Converter) ->
do_log_convert(Log, File, Converter).
do_log_convert(Log, File, Converter) ->
+ %% ?vtrace("do_log_converter -> entry with"
+ %% "~n Log: ~p"
+ %% "~n File: ~p"
+ %% "~n disk_log:info(Log): ~p", [Log, File, disk_log:info(Log)]),
+ {Pid, Ref} =
+ erlang:spawn_monitor(
+ fun() ->
+ Result = do_log_convert2(Log, File, Converter),
+ exit(Result)
+ end),
+ receive
+ {'DOWN', Ref, process, Pid, Result} ->
+ %% ?vtrace("do_log_converter -> received result"
+ %% "~n Result: ~p"
+ %% "~n disk_log:info(Log): ~p",
+ %% [Result, disk_log:info(Log)]),
+ Result
+ end.
+
+do_log_convert2(Log, File, Converter) ->
%% First check if the caller process has already opened the
%% log, because if we close an already open log we will cause
%% a runtime error.
@@ -439,29 +467,18 @@ do_log_convert(Log, File, Converter) ->
Converter(Log);
false ->
%% Not yet member of the ruling party, apply for membership...
- %% If a log is opened as read_write it is not possible to
- %% open it as read_only. So, to get around this we open
- %% it under a different name...
- Log2 = convert_name(Log),
- case log_open(Log2, File) of
+ case log_open(Log, File) of
{ok, _} ->
- Res = Converter(Log2),
- disk_log:close(Log2),
+ Res = Converter(Log),
+ disk_log:close(Log),
Res;
{error, {name_already_open, _}} ->
- Converter(Log2);
+ Converter(Log);
{error, Reason} ->
{error, {Log, Reason}}
end
end.
-convert_name(Name) when is_list(Name) ->
- Name ++ "_tmp";
-convert_name(Name) when is_atom(Name) ->
- list_to_atom(atom_to_list(Name) ++ "_tmp");
-convert_name(Name) ->
- lists:flatten(io_lib:format("~w_tmp", [Name])).
-
%% -- do_log_to_text ---
@@ -705,21 +722,21 @@ tsf_ge(_Local,Universal,{universal_time,DateTime}) ->
tsf_ge(Local,_Universal,DateTime) ->
tsf_ge(Local,DateTime).
-tsf_ge(TimeStamp,DateTime) ->
+tsf_ge(TimeStamp, DateTime) ->
T1 = calendar:datetime_to_gregorian_seconds(TimeStamp),
T2 = calendar:datetime_to_gregorian_seconds(DateTime),
T1 >= T2.
-tsf_le(_Local,_Universal,null) ->
+tsf_le(_Local, _Universal, null) ->
true;
-tsf_le(Local,_Universal,{local_time,DateTime}) ->
- tsf_le(Local,DateTime);
-tsf_le(_Local,Universal,{universal_time,DateTime}) ->
- tsf_le(Universal,DateTime);
-tsf_le(Local,_Universal,DateTime) ->
+tsf_le(Local, _Universal, {local_time, DateTime}) ->
+ tsf_le(Local, DateTime);
+tsf_le(_Local, Universal, {universal_time, DateTime}) ->
+ tsf_le(Universal, DateTime);
+tsf_le(Local, _Universal, DateTime) ->
tsf_le(Local,DateTime).
-tsf_le(TimeStamp,DateTime) ->
+tsf_le(TimeStamp, DateTime) ->
T1 = calendar:datetime_to_gregorian_seconds(TimeStamp),
T2 = calendar:datetime_to_gregorian_seconds(DateTime),
T1 =< T2.
@@ -864,11 +881,8 @@ do_std_log_open(Name, File, Size, Repair, Notify) ->
log_open(Name, File) ->
- Opts = [{name, Name},
- {file, File},
- {type, ?LOG_TYPE},
- {format, ?LOG_FORMAT},
- {mode, read_only}],
+ Opts = [{name, Name},
+ {file, File}],
case disk_log:open(Opts) of
{error, {badarg, size}} ->
{error, no_such_log};
diff --git a/lib/snmp/src/misc/snmp_verbosity.erl b/lib/snmp/src/misc/snmp_verbosity.erl
index 85037ba2ae..f2f85ebf79 100644
--- a/lib/snmp/src/misc/snmp_verbosity.erl
+++ b/lib/snmp/src/misc/snmp_verbosity.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -144,6 +144,8 @@ image_of_sname(mse) -> "M-SERVER";
image_of_sname(msew) -> io_lib:format("M-SERVER-worker(~p)", [self()]);
image_of_sname(mns) -> "M-NOTE-STORE";
image_of_sname(mnif) -> "M-NET-IF";
+image_of_sname(mnifl) -> "M-NET-IF-LOGGER";
+image_of_sname(mnifw) -> io_lib:format("M-NET-IF-worker(~p)", [self()]);
image_of_sname(mconf) -> "M-CONF";
image_of_sname(mgr) -> "MGR";
diff --git a/lib/snmp/test/exp/.gitignore b/lib/snmp/test/exp/.gitignore
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/snmp/test/exp/.gitignore
diff --git a/lib/snmp/test/snmp_agent_bl_test.erl b/lib/snmp/test/exp/snmp_agent_bl_test.erl
index b17489a755..b17489a755 100644
--- a/lib/snmp/test/snmp_agent_bl_test.erl
+++ b/lib/snmp/test/exp/snmp_agent_bl_test.erl
diff --git a/lib/snmp/test/snmp_agent_ms_test.erl b/lib/snmp/test/exp/snmp_agent_ms_test.erl
index 1f34f1c8d1..1f34f1c8d1 100644
--- a/lib/snmp/test/snmp_agent_ms_test.erl
+++ b/lib/snmp/test/exp/snmp_agent_ms_test.erl
diff --git a/lib/snmp/test/snmp_agent_mt_test.erl b/lib/snmp/test/exp/snmp_agent_mt_test.erl
index 4f125c0017..4f125c0017 100644
--- a/lib/snmp/test/snmp_agent_mt_test.erl
+++ b/lib/snmp/test/exp/snmp_agent_mt_test.erl
diff --git a/lib/snmp/test/snmp_agent_v1_test.erl b/lib/snmp/test/exp/snmp_agent_v1_test.erl
index 737bb25cc3..737bb25cc3 100644
--- a/lib/snmp/test/snmp_agent_v1_test.erl
+++ b/lib/snmp/test/exp/snmp_agent_v1_test.erl
diff --git a/lib/snmp/test/snmp_agent_v2_test.erl b/lib/snmp/test/exp/snmp_agent_v2_test.erl
index dc94c18ad9..dc94c18ad9 100644
--- a/lib/snmp/test/snmp_agent_v2_test.erl
+++ b/lib/snmp/test/exp/snmp_agent_v2_test.erl
diff --git a/lib/snmp/test/snmp_agent_v3_test.erl b/lib/snmp/test/exp/snmp_agent_v3_test.erl
index 266be72878..266be72878 100644
--- a/lib/snmp/test/snmp_agent_v3_test.erl
+++ b/lib/snmp/test/exp/snmp_agent_v3_test.erl
diff --git a/lib/snmp/test/snmp_SUITE.erl b/lib/snmp/test/snmp_SUITE.erl
index b6d72da2fa..22b9c64588 100644
--- a/lib/snmp/test/snmp_SUITE.erl
+++ b/lib/snmp/test/snmp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,6 +19,8 @@
-module(snmp_SUITE).
+-include("snmp_test_lib.hrl").
+
-export([all/0,
suite/0,
groups/0,
@@ -39,6 +41,21 @@ end_per_testcase(_Case, Config) when is_list(Config) ->
Config.
+init_per_suite(Config) when is_list(Config) ->
+
+ ?DBG("init_per_suite -> entry with"
+ "~n Config: ~p", [Config]),
+
+ Config.
+
+end_per_suite(Config) when is_list(Config) ->
+
+ ?DBG("end_per_suite -> entry with"
+ "~n Config: ~p", [Config]),
+
+ Config.
+
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Top test case
@@ -53,7 +70,8 @@ all() ->
{group, manager}].
groups() ->
- [{app, [], [{group, app_test},
+ [
+ {app, [], [{group, app_test},
{group, appup_test}]},
{compiler, [], [{group, compiler_test}]},
{misc, [], [{group, conf_test},
@@ -66,6 +84,7 @@ groups() ->
{manager, [], [{group, manager_config_test},
{group, manager_user_test},
{group, manager_test}]},
+
{app_test, [], [{snmp_app_test, all}]},
{appup_test, [], [{snmp_appup_test, all}]},
{compiler_test, [], [{snmp_compiler_test, all}]},
@@ -78,17 +97,25 @@ groups() ->
{agent_test, [], [{snmp_agent_test, all}]},
{manager_config_test, [], [{snmp_manager_config_test, all}]},
{manager_user_test, [], [{snmp_manager_user_test, all}]},
- {manager_test, [], [{snmp_manager_test, all}]}].
+ {manager_test, [], [{snmp_manager_test, all}]}
+ ].
-init_per_suite(Config) ->
- Config.
-end_per_suite(_Config) ->
- ok.
+init_per_group(GroupName, Config0) ->
-init_per_group(_GroupName, Config) ->
- Config.
+ ?DBG("init_per_group -> entry with"
+ "~n GroupName: ~p"
+ "~n Config0: ~p", [GroupName, Config0]),
+
+ %% Group name is not really the suite name
+ %% (but it is a good enough approximation),
+ %% but it does not matter since we only need
+ %% it to be unique.
+ snmp_test_lib:init_suite_top_dir(GroupName, Config0).
+
end_per_group(_GroupName, Config) ->
- Config.
+ lists:keydelete(snmp_suite_top_dir, 1, Config).
+
+
diff --git a/lib/snmp/test/snmp_agent_test.erl b/lib/snmp/test/snmp_agent_test.erl
index e968bc65b1..b5acf7cd87 100644
--- a/lib/snmp/test/snmp_agent_test.erl
+++ b/lib/snmp/test/snmp_agent_test.erl
@@ -228,48 +228,79 @@ groups() ->
}
].
-init_per_group(all_tcs, Config) ->
- init_all(Config);
-init_per_group(otp_7157, Config) ->
- init_otp_7157(Config);
-init_per_group(otp_4394, Config) ->
- init_otp_4394(Config);
-init_per_group(v2_inform, Config) ->
- init_v2_inform(Config);
-init_per_group(multiple_reqs_2, Config) ->
- init_mul(Config);
-init_per_group(multiple_reqs, Config) ->
- init_mul(Config);
-init_per_group(test_multi_threaded, Config) ->
- init_mt(Config);
-init_per_group(test_v3, Config) ->
- init_v3(Config);
-init_per_group(test_v1_v2, Config) ->
- init_v1_v2(Config);
-init_per_group(test_v2, Config) ->
- init_v2(Config);
-init_per_group(test_v1, Config) ->
- init_v1(Config);
-init_per_group(misc, Config) ->
- init_misc(Config);
-init_per_group(mib_storage_varm_mnesia, Config) ->
- init_varm_mib_storage_mnesia(Config);
-init_per_group(mib_storage_varm_dets, Config) ->
- init_varm_mib_storage_dets(Config);
-init_per_group(mib_storage_size_check_mnesia, Config) ->
- init_size_check_msm(Config);
-init_per_group(mib_storage_size_check_dets, Config) ->
- init_size_check_msd(Config);
-init_per_group(mib_storage_size_check_ets, Config) ->
- init_size_check_mse(Config);
-init_per_group(mib_storage_mnesia, Config) ->
- init_mib_storage_mnesia(Config);
-init_per_group(mib_storage_dets, Config) ->
- init_mib_storage_dets(Config);
-init_per_group(mib_storage_ets, Config) ->
- init_mib_storage_ets(Config);
-init_per_group(_GroupName, Config) ->
- Config.
+
+init_per_suite(Config0) when is_list(Config0) ->
+
+ ?DBG("init_per_suite -> entry with"
+ "~n Config0: ~p", [Config0]),
+
+ Config1 = snmp_test_lib:init_suite_top_dir(?MODULE, Config0),
+ Config2 = snmp_test_lib:fix_data_dir(Config1),
+
+ %% Mib-dirs
+ MibDir = snmp_test_lib:lookup(data_dir, Config2),
+ StdMibDir = filename:join([code:priv_dir(snmp), "mibs"]),
+
+ Config3 = [{mib_dir, MibDir}, {std_mib_dir, StdMibDir} | Config2],
+
+ ?DBG("init_per_suite -> end with"
+ "~n Config3: ~p", [Config3]),
+
+ Config3.
+
+end_per_suite(Config) when is_list(Config) ->
+
+ ?DBG("end_per_suite -> entry with"
+ "~n Config: ~p", [Config]),
+
+ Config.
+
+
+init_per_group(all_tcs = GroupName, Config) ->
+ init_all(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(otp_7157 = GroupName, Config) ->
+ init_otp_7157(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(otp_4394 = GroupName, Config) ->
+ init_otp_4394(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(v2_inform = GroupName, Config) ->
+ init_v2_inform(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(multiple_reqs_2 = GroupName, Config) ->
+ init_mul(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(multiple_reqs = GroupName, Config) ->
+ init_mul(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(test_multi_threaded = GroupName, Config) ->
+ init_mt(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(test_v3 = GroupName, Config) ->
+ init_v3(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(test_v1_v2 = GroupName, Config) ->
+ init_v1_v2(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(test_v2 = GroupName, Config) ->
+ init_v2(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(test_v1 = GroupName, Config) ->
+ init_v1(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(misc = GroupName, Config) ->
+ init_misc(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(mib_storage_varm_mnesia = GroupName, Config) ->
+ init_varm_mib_storage_mnesia(snmp_test_lib:init_group_top_dir(GroupName,
+ Config));
+init_per_group(mib_storage_varm_dets = GroupName, Config) ->
+ init_varm_mib_storage_dets(snmp_test_lib:init_group_top_dir(GroupName,
+ Config));
+init_per_group(mib_storage_size_check_mnesia = GroupName, Config) ->
+ init_size_check_msm(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(mib_storage_size_check_dets = GroupName, Config) ->
+ init_size_check_msd(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(mib_storage_size_check_ets = GroupName, Config) ->
+ init_size_check_mse(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(mib_storage_mnesia = GroupName, Config) ->
+ init_mib_storage_mnesia(snmp_test_lib:init_group_top_dir(GroupName,
+ Config));
+init_per_group(mib_storage_dets = GroupName, Config) ->
+ init_mib_storage_dets(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(mib_storage_ets = GroupName, Config) ->
+ init_mib_storage_ets(snmp_test_lib:init_group_top_dir(GroupName, Config));
+init_per_group(GroupName, Config) ->
+ snmp_test_lib:init_group_top_dir(GroupName, Config).
end_per_group(all_tcs, Config) ->
finish_all(Config);
@@ -320,38 +351,36 @@ init_per_testcase(otp8395 = Case, Config) when is_list(Config) ->
?DBG("init_per_testcase -> entry with"
"~n Case: ~p"
"~n Config: ~p", [Case, Config]),
- Config2 = init_per_testcase2(Case, init_per_suite(Config)),
- otp8395({init, Config2});
+ otp8395({init, init_per_testcase2(Case, Config)});
init_per_testcase(otp9884 = Case, Config) when is_list(Config) ->
?DBG("init_per_testcase -> entry with"
"~n Case: ~p"
"~n Config: ~p", [Case, Config]),
- Config2 = init_per_testcase2(Case, init_per_suite(Config)),
- otp9884({init, Config2});
+ otp9884({init, init_per_testcase2(Case, Config)});
init_per_testcase(otp_7157_test = _Case, Config) when is_list(Config) ->
?DBG("init_per_testcase -> entry with"
"~n Case: ~p"
"~n Config: ~p", [_Case, Config]),
Dog = ?WD_START(?MINS(1)),
- [{watchdog, Dog}|Config];
+ [{watchdog, Dog} | Config ];
init_per_testcase(v2_inform_i = _Case, Config) when is_list(Config) ->
?DBG("init_per_testcase -> entry with"
"~n Case: ~p"
"~n Config: ~p", [_Case, Config]),
Dog = ?WD_START(?MINS(10)),
- [{watchdog, Dog}|Config];
+ [{watchdog, Dog} | Config ];
init_per_testcase(v3_inform_i = _Case, Config) when is_list(Config) ->
?DBG("init_per_testcase -> entry with"
"~n Case: ~p"
"~n Config: ~p", [_Case, Config]),
Dog = ?WD_START(?MINS(10)),
- [{watchdog, Dog}|Config];
+ [{watchdog, Dog} | Config ];
init_per_testcase(_Case, Config) when is_list(Config) ->
?DBG("init_per_testcase -> entry with"
"~n Case: ~p"
"~n Config: ~p", [_Case, Config]),
Dog = ?WD_START(?MINS(6)),
- [{watchdog, Dog}|Config].
+ [{watchdog, Dog}| Config ].
end_per_testcase(otp8395, Config) when is_list(Config) ->
otp8395({fin, Config});
@@ -366,65 +395,13 @@ end_per_testcase(_Case, Config) when is_list(Config) ->
Config.
-init_per_suite(Config) ->
- ?DBG("init_per_suite -> entry with"
- "~n Config: ~p", [Config]),
-
- %% Suite root dir for test suite
- PrivDir = ?config(priv_dir, Config),
-
- %% Create top-directory for this sub-suite
- SuiteTopDir = filename:join([PrivDir, ?MODULE]),
- case file:make_dir(SuiteTopDir) of
- ok ->
- ok;
- {error, eexist} ->
- %% This can happen since this is not really a
- %% suite-init function.
- ok;
- {error, Reason} ->
- ?FAIL({failed_creating_suite_top_dir, SuiteTopDir, Reason})
- end,
-
-
- %% --
- %% Fix config (data-dir is not correct):
- %%
-
- Config1 = fix_data_dir(Config),
- %% Config1 = Config,
-
- %% Mib-dirs
- MibDir = ?config(data_dir, Config1),
- StdMibDir = filename:join([code:priv_dir(snmp), "mibs"]),
-
- Config2 = [{suite_top_dir, SuiteTopDir},
- {mib_dir, MibDir},
- {std_mib_dir, StdMibDir} | Config1],
-
- ?DBG("init_per_suite -> done when"
- "~n Config2: ~p", [Config2]),
- Config2.
-
-%% end_per_suite(Config) ->
-end_per_suite(Config) ->
- Config.
-
-fix_data_dir(Config) ->
- DataDir0 = ?config(data_dir, Config),
- DataDir1 = filename:split(filename:absname(DataDir0)),
- [_|DataDir2] = lists:reverse(DataDir1),
- DataDir = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]),
- Config1 = lists:keydelete(data_dir, 1, Config),
- [{data_dir, DataDir} | Config1].
+init_per_testcase2(Case, Config) ->
+ ?DBG("end_per_testcase2 -> entry with"
+ "~n Case: ~p"
+ "~n Config: ~p", [Case, Config]),
-init_per_testcase2(Case, Config) ->
- SuiteToDir = ?config(suite_top_dir, Config),
-
- %% Create top-directory for this test-case
- CaseTopDir = filename:join([SuiteToDir, Case]),
- ok = file:make_dir(CaseTopDir),
+ CaseTopDir = snmp_test_lib:init_testcase_top_dir(Case, Config),
%% Create agent top-dir(s)
AgentTopDir = filename:join([CaseTopDir, agent]),
@@ -623,19 +600,19 @@ mib_storage_mnesia_cases() ->
msm_mib_of].
mse_size_check_cases() ->
-[mse_size_check].
+ [mse_size_check].
msd_size_check_cases() ->
-[msd_size_check].
+ [msd_size_check].
msm_size_check_cases() ->
-[msm_size_check].
+ [msm_size_check].
varm_mib_storage_dets_cases() ->
-[msd_varm_mib_start].
+ [msd_varm_mib_start].
varm_mib_storage_mnesia_cases() ->
-[msm_varm_mib_start].
+ [msm_varm_mib_start].
init_mib_storage_ets(Config) when is_list(Config) ->
?LOG("init_mib_storage_ets -> entry", []),
@@ -655,17 +632,18 @@ init_mib_storage_mnesia(Config) when is_list(Config) ->
init_ms(Config, Opts) when is_list(Config) ->
?LOG("init_mib_storage_ets -> entry", []),
- ?line SaNode = ?GCONF(snmp_sa, Config),
+ ?line SaNode = ?GCONF(snmp_sa, Config),
?line create_tables(SaNode),
- ?line AgentDir = ?GCONF(agent_dir, Config),
- ?line MgrDir = ?GCONF(mgr_dir, Config),
- ?line Ip = ?GCONF(ip, Config),
- ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ ?line AgentConfDir = ?GCONF(agent_conf_dir, Config),
+ ?line MgrDir = ?GCONF(mgr_dir, Config),
+ ?line Ip = ?GCONF(ip, Config),
+ ?line config([v1], MgrDir, AgentConfDir,
+ tuple_to_list(Ip), tuple_to_list(Ip)),
MasterAgentVerbosity = {snmp_master_agent_verbosity, trace},
MibsVerbosity = {snmp_mibserver_verbosity, trace},
SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace},
- Opts1 = [MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity|Opts],
- [{vsn, v1} | start_v1_agent(Config,Opts1)].
+ Opts1 = [MasterAgentVerbosity, MibsVerbosity, SymStoreVerbosity | Opts],
+ [{vsn, v1} | start_v1_agent(Config, Opts1)].
init_size_check_mse(Config) when is_list(Config) ->
MibStorage = {snmp_mib_storage, ets},
@@ -1189,10 +1167,11 @@ v1_cases() ->
init_v1(Config) when is_list(Config) ->
?line SaNode = ?config(snmp_sa, Config),
?line create_tables(SaNode),
- ?line AgentDir = ?config(agent_dir, Config),
+ ?line AgentConfDir = ?config(agent_conf_dir, Config),
?line MgrDir = ?config(mgr_dir, Config),
?line Ip = ?config(ip, Config),
- ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ ?line config([v1], MgrDir, AgentConfDir,
+ tuple_to_list(Ip), tuple_to_list(Ip)),
[{vsn, v1} | start_v1_agent(Config)].
finish_v1(Config) when is_list(Config) ->
@@ -1232,10 +1211,11 @@ v2_cases() ->
init_v2(Config) when is_list(Config) ->
SaNode = ?config(snmp_sa, Config),
create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
+ AgentConfDir = ?config(agent_conf_dir, Config),
MgrDir = ?config(mgr_dir, Config),
Ip = ?config(ip, Config),
- config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ config([v2], MgrDir, AgentConfDir,
+ tuple_to_list(Ip), tuple_to_list(Ip)),
[{vsn, v2} | start_v2_agent(Config)].
finish_v2(Config) when is_list(Config) ->
@@ -1251,10 +1231,11 @@ v1_v2_cases() ->
init_v1_v2(Config) when is_list(Config) ->
SaNode = ?config(snmp_sa, Config),
create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
+ AgentConfDir = ?config(agent_conf_dir, Config),
MgrDir = ?config(mgr_dir, Config),
Ip = ?config(ip, Config),
- config([v1,v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ config([v1,v2], MgrDir, AgentConfDir,
+ tuple_to_list(Ip), tuple_to_list(Ip)),
[{vsn, bilingual} | start_bilingual_agent(Config)].
finish_v1_v2(Config) when is_list(Config) ->
@@ -1315,10 +1296,10 @@ init_v3(Config) when is_list(Config) ->
end,
SaNode = ?config(snmp_sa, Config),
create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
+ AgentConfDir = ?config(agent_conf_dir, Config),
MgrDir = ?config(mgr_dir, Config),
Ip = ?config(ip, Config),
- ?line ok = config([v3], MgrDir, AgentDir,
+ ?line ok = config([v3], MgrDir, AgentConfDir,
tuple_to_list(Ip), tuple_to_list(Ip)),
[{vsn, v3} | start_v3_agent(Config)].
@@ -1338,11 +1319,11 @@ mt_cases() ->
init_mt(Config) when is_list(Config) ->
SaNode = ?config(snmp_sa, Config),
create_tables(SaNode),
- AgentDir = ?config(agent_dir, Config),
+ AgentConfDir = ?config(agent_conf_dir, Config),
MgrDir = ?config(mgr_dir, Config),
Ip = ?config(ip, Config),
- ?line ok =
- config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ ?line ok = config([v2], MgrDir, AgentConfDir,
+ tuple_to_list(Ip), tuple_to_list(Ip)),
[{vsn, v2} | start_multi_threaded_agent(Config)].
finish_mt(Config) when is_list(Config) ->
@@ -1421,7 +1402,13 @@ simple(Config) when is_list(Config) ->
?P(simple),
init_case(Config),
- try_test(simple_standard_test).
+ try_test(simple_standard_test),
+
+ p("Display log"),
+ display_log(Config),
+
+ p("done"),
+ ok.
simple_2(X) -> ?P(simple_2), simple(X).
@@ -1601,7 +1588,7 @@ change_target_addr_config(Config) when is_list(Config) ->
try_test(ma_trap1, [MA]),
?LOG("change_target_addr_config -> set silence verbosity for local_db",[]),
- ?line snmpa:verbosity(local_db,silence),
+ ?line snmpa:verbosity(local_db, silence),
%% Start new dummy listener
?LOG("change_target_addr_config -> start dummy manager",[]),
@@ -1609,9 +1596,9 @@ change_target_addr_config(Config) when is_list(Config) ->
%% Reconfigure
?LOG("change_target_addr_config -> reconfigure",[]),
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_addr_conf(AgentDir, NewPort),
- ?line snmp_target_mib:reconfigure(AgentDir),
+ AgentConfDir = ?config(agent_conf_dir, Config),
+ ?line rewrite_target_addr_conf(AgentConfDir, NewPort),
+ ?line snmp_target_mib:reconfigure(AgentConfDir),
%% Send the trap again
?LOG("change_target_addr_config -> send trap again",[]),
@@ -1624,7 +1611,7 @@ change_target_addr_config(Config) when is_list(Config) ->
?line ok = dummy_manager_stop(Pid),
?LOG("change_target_addr_config -> reset target address config",[]),
- ?line reset_target_addr_conf(AgentDir),
+ ?line reset_target_addr_conf(AgentConfDir),
?LOG("change_target_addr_config -> unload TestTrap",[]),
?line unload_master("TestTrap").
@@ -2067,7 +2054,7 @@ v3_inform(_X) ->
{req, [], {conf, init_v3_inform, [v3_inform_i], finish_v3_inform}}.
init_v2_inform(Config) when is_list(Config) ->
- _Dir = ?config(agent_dir, Config),
+ _Dir = ?config(agent_conf_dir, Config),
%% snmp_internal_mib:configure(Dir),
Config.
@@ -2075,7 +2062,7 @@ init_v3_inform(X) ->
init_v2_inform(X).
finish_v2_inform(Config) when is_list(Config) ->
- _Dir = ?config(agent_dir, Config),
+ _Dir = ?config(agent_conf_dir, Config),
%% snmp_internal_mib:configure(Dir),
Config.
@@ -2377,9 +2364,9 @@ v3_md5_auth(Config) when is_list(Config) ->
?P1("Testing MD5 authentication...takes a few seconds..."),
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_params_conf(AgentDir, "authMD5", authNoPriv),
- ?line snmp_target_mib:reconfigure(AgentDir),
+ AgentConfDir = ?config(agent_conf_dir, Config),
+ ?line rewrite_target_params_conf(AgentConfDir, "authMD5", authNoPriv),
+ ?line snmp_target_mib:reconfigure(AgentConfDir),
MA = whereis(snmp_master_agent),
@@ -2388,14 +2375,14 @@ v3_md5_auth(Config) when is_list(Config) ->
?line load_master("TestTrapv2"),
try_test(v3_sync, [[{v2_proc, []},
- {ma_v2_trap1, [MA]},
- {v3_inform_sync, [MA]}]],
- [{sec_level, authNoPriv}, {user, "authMD5"}]),
+ {ma_v2_trap1, [MA]},
+ {v3_inform_sync, [MA]}]],
+ [{sec_level, authNoPriv}, {user, "authMD5"}]),
?line unload_master("TestTrapv2"),
?line unload_master("TestTrap"),
?line unload_master("Test2"),
- ?line reset_target_params_conf(AgentDir).
+ ?line reset_target_params_conf(AgentConfDir).
v3_sha_auth(suite) -> [];
v3_sha_auth(Config) when is_list(Config) ->
@@ -2404,9 +2391,9 @@ v3_sha_auth(Config) when is_list(Config) ->
?P1("Testing SHA authentication...takes a few seconds..."),
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_params_conf(AgentDir, "authSHA", authNoPriv),
- ?line snmp_target_mib:reconfigure(AgentDir),
+ AgentConfDir = ?config(agent_conf_dir, Config),
+ ?line rewrite_target_params_conf(AgentConfDir, "authSHA", authNoPriv),
+ ?line snmp_target_mib:reconfigure(AgentConfDir),
MA = whereis(snmp_master_agent),
@@ -2415,14 +2402,14 @@ v3_sha_auth(Config) when is_list(Config) ->
?line load_master("TestTrapv2"),
try_test(v3_sync, [[{v2_proc, []},
- {ma_v2_trap1, [MA]},
- {v3_inform_sync, [MA]}]],
- [{sec_level, authNoPriv}, {user, "authSHA"}]),
+ {ma_v2_trap1, [MA]},
+ {v3_inform_sync, [MA]}]],
+ [{sec_level, authNoPriv}, {user, "authSHA"}]),
?line unload_master("TestTrapv2"),
?line unload_master("TestTrap"),
?line unload_master("Test2"),
- ?line reset_target_params_conf(AgentDir).
+ ?line reset_target_params_conf(AgentConfDir).
v3_des_priv(suite) -> [];
v3_des_priv(Config) when is_list(Config) ->
@@ -2431,9 +2418,9 @@ v3_des_priv(Config) when is_list(Config) ->
?P1("Testing DES encryption...takes a few seconds..."),
- AgentDir = ?config(agent_dir, Config),
- ?line rewrite_target_params_conf(AgentDir, "privDES", authPriv),
- ?line snmp_target_mib:reconfigure(AgentDir),
+ AgentConfDir = ?config(agent_conf_dir, Config),
+ ?line rewrite_target_params_conf(AgentConfDir, "privDES", authPriv),
+ ?line snmp_target_mib:reconfigure(AgentConfDir),
MA = whereis(snmp_master_agent),
@@ -2444,14 +2431,14 @@ v3_des_priv(Config) when is_list(Config) ->
?line load_master("TestTrapv2"),
try_test(v3_sync, [[{v2_proc, []},
- {ma_v2_trap1, [MA]},
- {v3_inform_sync, [MA]}]],
- [{sec_level, authPriv}, {user, "privDES"}]),
+ {ma_v2_trap1, [MA]},
+ {v3_inform_sync, [MA]}]],
+ [{sec_level, authPriv}, {user, "privDES"}]),
?line unload_master("TestTrapv2"),
?line unload_master("TestTrap"),
?line unload_master("Test2"),
- ?line reset_target_params_conf(AgentDir).
+ ?line reset_target_params_conf(AgentConfDir).
%% -define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]).
@@ -4795,7 +4782,7 @@ snmp_user_based_sm_mib_3(Config) when is_list(Config) ->
?P(snmp_user_based_sm_mib_3),
init_case(Config),
- _AgentDir = ?config(agent_dir, Config),
+ _AgentDir = ?config(agent_conf_dir, Config),
?line load_master_std("SNMP-USER-BASED-SM-MIB"),
%% The newUser used here already has VACM access.
@@ -5727,28 +5714,28 @@ otp_3725_test(MaNode) ->
init_otp_4394(Config) when is_list(Config) ->
?DBG("init_otp_4394 -> entry with"
"~n Config: ~p", [Config]),
- ?line AgentDir = ?config(agent_dir, Config),
- ?line MgrDir = ?config(mgr_dir, Config),
- ?line Ip = ?config(ip, Config),
- ?line otp_4394_config(AgentDir, MgrDir, Ip),
+ ?line AgentConfDir = ?config(agent_conf_dir, Config),
+ ?line MgrDir = ?config(mgr_dir, Config),
+ ?line Ip = ?config(ip, Config),
+ ?line otp_4394_config(AgentConfDir, MgrDir, Ip),
MasterAgentVerbosity = {master_agent_verbosity, trace},
NetIfVerbosity = {net_if_verbosity, trace},
- Opts = [MasterAgentVerbosity,NetIfVerbosity],
- [{vsn, v1} | start_v1_agent(Config,Opts)].
+ Opts = [MasterAgentVerbosity, NetIfVerbosity],
+ [{vsn, v1} | start_v1_agent(Config, Opts)].
-otp_4394_config(AgentDir, MgrDir, Ip0) ->
+otp_4394_config(AgentConfDir, MgrDir, Ip0) ->
?DBG("otp_4394_config -> entry with"
- "~n AgentDir: ~p"
- "~n MgrDir: ~p"
- "~n Ip0: ~p", [AgentDir, MgrDir, Ip0]),
+ "~n AgentConfDir: ~p"
+ "~n MgrDir: ~p"
+ "~n Ip0: ~p", [AgentConfDir, MgrDir, Ip0]),
Vsn = [v1],
Ip = tuple_to_list(Ip0),
- ?line snmp_config:write_agent_snmp_files(AgentDir, Vsn, Ip,
+ ?line snmp_config:write_agent_snmp_files(AgentConfDir, Vsn, Ip,
?TRAP_UDP, Ip, 4000,
"OTP-4394 test"),
- ?line case update_usm(Vsn, AgentDir) of
+ ?line case update_usm(Vsn, AgentConfDir) of
true ->
- ?line copy_file(filename:join(AgentDir, "usm.conf"),
+ ?line copy_file(filename:join(AgentConfDir, "usm.conf"),
filename:join(MgrDir, "usm.conf")),
?line update_usm_mgr(Vsn, MgrDir);
false ->
@@ -5756,8 +5743,8 @@ otp_4394_config(AgentDir, MgrDir, Ip0) ->
end,
C1 = {"a", "all-rights", "initial", "", "pc"},
C2 = {"c", "secret", "secret_name", "", "secret_tag"},
- ?line write_community_conf(AgentDir, [C1, C2]),
- ?line update_vacm(Vsn, AgentDir),
+ ?line write_community_conf(AgentConfDir, [C1, C2]),
+ ?line update_vacm(Vsn, AgentConfDir),
Ta1 = {"shelob v1",
[134,138,177,177], 5000, 1500, 3, %% Anv�nd Ip och modda
"pc1",
@@ -5771,9 +5758,9 @@ otp_4394_config(AgentDir, MgrDir, Ip0) ->
"target_v1", "",
%% [255,255,255,255,0,0],
[], 2048},
- ?line write_target_addr_conf(AgentDir, [Ta1, Ta2]),
- ?line write_target_params_conf(AgentDir, Vsn),
- ?line write_notify_conf(AgentDir),
+ ?line write_target_addr_conf(AgentConfDir, [Ta1, Ta2]),
+ ?line write_target_params_conf(AgentConfDir, Vsn),
+ ?line write_notify_conf(AgentConfDir),
ok.
@@ -5826,10 +5813,11 @@ init_otp_7157(Config) when is_list(Config) ->
?DBG("init_otp_7157 -> entry with"
"~n Config: ~p", [Config]),
- ?line AgentDir = ?config(agent_dir, Config),
+ ?line AgentConfDir = ?config(agent_conf_dir, Config),
?line MgrDir = ?config(mgr_dir, Config),
?line Ip = ?config(ip, Config),
- ?line config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)),
+ ?line config([v2], MgrDir, AgentConfDir,
+ tuple_to_list(Ip), tuple_to_list(Ip)),
MasterAgentVerbosity = {master_agent_verbosity, trace},
NetIfVerbosity = {net_if_verbosity, trace},
Opts = [MasterAgentVerbosity, NetIfVerbosity],
@@ -6562,8 +6550,8 @@ write_community_conf(Dir, Conf) ->
write_target_addr_conf(Dir, Conf) ->
snmp_agent_test_lib:write_target_addr_conf(Dir, Conf).
-write_target_addr_conf(Dir, ManagerIp, UDP, Vsns) ->
- snmp_agent_test_lib:write_target_addr_conf(Dir, ManagerIp, UDP, Vsns).
+%% write_target_addr_conf(Dir, ManagerIp, UDP, Vsns) ->
+%% snmp_agent_test_lib:write_target_addr_conf(Dir, ManagerIp, UDP, Vsns).
rewrite_target_addr_conf(Dir, NewPort) ->
snmp_agent_test_lib:rewrite_target_addr_conf(Dir, NewPort).
@@ -6596,9 +6584,42 @@ copy_file(From, To) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+display_log(Config) ->
+ case lists:keysearch(agent_log_dir, 1, Config) of
+ {value, {_, Dir}} ->
+ case lists:keysearch(snmp_master, 1, Config) of
+ {value, {_, Node}} ->
+ LogDir = Dir,
+ Mibs = [],
+ OutFile = filename:join(LogDir, "snmpa_log.txt"),
+ p("~n"
+ "========================="
+ " < Audit Trail Log > "
+ "========================="
+ "~n"),
+ rcall(Node, snmpa, log_to_txt, [LogDir, Mibs, OutFile]),
+ rcall(Node, snmpa, log_to_io, [LogDir, Mibs]),
+ p("~n"
+ "========================="
+ " < / Audit Trail Log > "
+ "========================="
+ "~n", []);
+ false ->
+ p("display_log -> no agent node found"),
+ ok
+ end;
+ false ->
+ p("display_log -> no agent log dir found: "
+ "~n ~p", [Config]),
+ ok
+ end.
+
+
+%% ------
+
display_memory_usage() ->
Info = snmpa:info(snmp_master_agent),
- AMU = display_agent_memory_uasge(Info),
+ AMU = display_agent_memory_usage(Info),
NIMU = display_net_if_memory_usage(Info),
NSMU = display_note_store_memory_usage(Info),
SSMU = display_symbolic_store_memory_usage(Info),
@@ -6608,7 +6629,7 @@ display_memory_usage() ->
AMU ++ NIMU ++ NSMU ++ SSMU ++ LDBMU ++ MSMU, []),
ok.
-display_agent_memory_uasge(Info) ->
+display_agent_memory_usage(Info) ->
AgentInfo = lists_key1search(agent, Info),
ProcMem =
lists_key1search([process_memory,master_agent], AgentInfo),
@@ -6717,3 +6738,27 @@ lists_key1search(Key, List) when is_atom(Key) ->
regs() ->
lists:sort(registered()).
+
+%% ------
+
+rcall(Node, Mod, Func, Args) ->
+ case rpc:call(Node, Mod, Func, Args) of
+ {badrpc, nodedown} ->
+ ?FAIL({rpc_failure, Node});
+ Else ->
+ Else
+ end.
+
+
+%% ------
+
+p(F) ->
+ p(F, []).
+
+p(F, A) ->
+ io:format("*** [~s] ***"
+ "~n" ++ F ++ "~n", [formated_timestamp()|A]).
+
+formated_timestamp() ->
+ snmp_test_lib:formated_timestamp().
+
diff --git a/lib/snmp/test/snmp_agent_test_lib.erl b/lib/snmp/test/snmp_agent_test_lib.erl
index 084b3ee8da..cd9a87eab8 100644
--- a/lib/snmp/test/snmp_agent_test_lib.erl
+++ b/lib/snmp/test/snmp_agent_test_lib.erl
@@ -119,20 +119,10 @@
%%% didn't undo (since it failed).
%%%-----------------------------------------------------------------
-init_all(Config0) when is_list(Config0) ->
- ?LOG("init_all -> entry with"
- "~n Config0: ~p",[Config0]),
-
- %% --
- %% Fix config:
- %%
+init_all(Config) when is_list(Config) ->
- DataDir0 = ?config(data_dir, Config0),
- DataDir1 = filename:split(filename:absname(DataDir0)),
- [_|DataDir2] = lists:reverse(DataDir1),
- DataDir3 = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]),
- Config1 = lists:keydelete(data_dir, 1, Config0),
- Config = [{data_dir, DataDir3 ++ "/"}|Config1],
+ ?LOG("init_all -> entry with"
+ "~n Config: ~p",[Config]),
%% --
%% Start nodes
@@ -143,34 +133,43 @@ init_all(Config0) when is_list(Config0) ->
%% --
- %% Create necessary files
+ %% Create necessary files ( and dirs )
%%
- PrivDir = ?config(priv_dir, Config),
- ?DBG("init_all -> PrivDir ~p", [PrivDir]),
+ SuiteTopDir = ?config(snmp_suite_top_dir, Config),
+ ?DBG("init_all -> SuiteTopDir ~p", [SuiteTopDir]),
- TopDir = filename:join(PrivDir, snmp_agent_test),
- case file:make_dir(TopDir) of
- ok ->
- ok;
- {error, eexist} ->
- ok;
- Error ->
- ?FAIL({failed_creating_subsuite_top_dir, Error})
- end,
+ AgentDir = filename:join(SuiteTopDir, "agent/"),
+ ?line ok = file:make_dir(AgentDir),
+ ?DBG("init_all -> AgentDir ~p", [AgentDir]),
- DataDir = ?config(data_dir, Config),
- ?DBG("init_all -> DataDir ~p", [DataDir]),
+ AgentDbDir = filename:join(AgentDir, "db/"),
+ ?line ok = file:make_dir(AgentDbDir),
+ ?DBG("init_all -> AgentDbDir ~p", [AgentDbDir]),
- ?line ok = file:make_dir(MgrDir = filename:join(TopDir, "mgr_dir/")),
- ?DBG("init_all -> MgrDir ~p", [MgrDir]),
+ AgentLogDir = filename:join(AgentDir, "log/"),
+ ?line ok = file:make_dir(AgentLogDir),
+ ?DBG("init_all -> AgentLogDir ~p", [AgentLogDir]),
- ?line ok = file:make_dir(AgentDir = filename:join(TopDir, "agent_dir/")),
- ?DBG("init_all -> AgentDir ~p", [AgentDir]),
+ AgentConfDir = filename:join(AgentDir, "conf/"),
+ ?line ok = file:make_dir(AgentConfDir),
+ ?DBG("init_all -> AgentConfDir ~p", [AgentConfDir]),
- ?line ok = file:make_dir(SaDir = filename:join(TopDir, "sa_dir/")),
+ MgrDir = filename:join(SuiteTopDir, "mgr/"),
+ ?line ok = file:make_dir(MgrDir),
+ ?DBG("init_all -> MgrDir ~p", [MgrDir]),
+
+ SaDir = filename:join(SuiteTopDir, "sa/"),
+ ?line ok = file:make_dir(SaDir),
?DBG("init_all -> SaDir ~p", [SaDir]),
+ SaDbDir = filename:join(SaDir, "db/"),
+ ?line ok = file:make_dir(SaDbDir),
+ ?DBG("init_all -> SaDbDir ~p", [SaDbDir]),
+
+ %% MibDir = ?config(mib_dir, Config),
+ %% ?DBG("init_all -> MibDir ~p", [DataDir]),
+
%% --
%% Start and initiate mnesia
@@ -184,11 +183,11 @@ init_all(Config0) when is_list(Config0) ->
?DBG("init_all -> application mnesia: set_env dir",[]),
?line application_controller:set_env(mnesia, dir,
- filename:join(TopDir, "Mnesia1")),
+ filename:join(AgentDbDir, "Mnesia1")),
?DBG("init_all -> application mnesia: set_env dir on node ~p",[SaNode]),
- ?line rpc:call(SaNode, application_controller, set_env,
- [mnesia, dir, filename:join(TopDir, "Mnesia2")]),
+ ?line rpc:call(SaNode, application_controller, set_env,
+ [mnesia, dir, filename:join(SaDir, "Mnesia2")]),
?DBG("init_all -> create mnesia schema",[]),
?line ok = mnesia:create_schema([SaNode, node()]),
@@ -199,13 +198,18 @@ init_all(Config0) when is_list(Config0) ->
?DBG("init_all -> start application mnesia on ~p",[SaNode]),
?line ok = rpc:call(SaNode, application, start, [mnesia]),
Ip = ?LOCALHOST(),
- [{snmp_sa, SaNode},
- {snmp_mgr, MgrNode},
- {agent_dir, AgentDir ++ "/"},
- {mgr_dir, MgrDir ++ "/"},
- {sa_dir, SaDir ++ "/"},
- {mib_dir, DataDir},
- {ip, Ip} |
+ [{snmp_sa, SaNode},
+ {snmp_mgr, MgrNode},
+ {snmp_master, node()},
+ {agent_dir, AgentDir ++ "/"},
+ {agent_db_dir, AgentDbDir ++ "/"},
+ {agent_log_dir, AgentLogDir ++ "/"},
+ {agent_conf_dir, AgentConfDir ++ "/"},
+ {sa_dir, SaDir ++ "/"},
+ {sa_db_dir, SaDbDir ++ "/"},
+ {mgr_dir, MgrDir ++ "/"},
+ %% {mib_dir, DataDir},
+ {ip, Ip} |
Config].
@@ -220,11 +224,14 @@ finish_all(Config) when is_list(Config) ->
%% --- This one *must* be run first in each case ---
init_case(Config) when is_list(Config) ->
+
?DBG("init_case -> entry with"
- "~n Config: ~p", [Config]),
- SaNode = ?config(snmp_sa, Config),
- MgrNode = ?config(snmp_mgr, Config),
- MasterNode = node(),
+ "~n Config: ~p", [Config]),
+
+ SaNode = ?config(snmp_sa, Config),
+ MgrNode = ?config(snmp_mgr, Config),
+ MasterNode = ?config(snmp_master, Config),
+ %% MasterNode = node(),
SaHost = ?HOSTNAME(SaNode),
MgrHost = ?HOSTNAME(MgrNode),
@@ -411,7 +418,8 @@ start_v3_agent(Config, Opts) when is_list(Config) andalso is_list(Opts) ->
start_bilingual_agent(Config) when is_list(Config) ->
start_agent(Config, [v1,v2]).
-start_bilingual_agent(Config, Opts) when is_list(Config) andalso is_list(Opts) ->
+start_bilingual_agent(Config, Opts)
+ when is_list(Config) andalso is_list(Opts) ->
start_agent(Config, [v1,v2], Opts).
start_mt_agent(Config) when is_list(Config) ->
@@ -423,57 +431,33 @@ start_mt_agent(Config, Opts) when is_list(Config) andalso is_list(Opts) ->
start_agent(Config, Vsns) ->
start_agent(Config, Vsns, []).
start_agent(Config, Vsns, Opts) ->
+
?LOG("start_agent -> entry (~p) with"
"~n Config: ~p"
"~n Vsns: ~p"
"~n Opts: ~p", [node(), Config, Vsns, Opts]),
- ?line AgentDir = ?config(agent_dir, Config),
- ?line SaNode = ?config(snmp_sa, Config),
-
-%% AgentConfig =
-%% [{agent_type, master},
-%% %% {multi_threaded, MultiT},
-%% %% {priority, Prio},
-%% %% {error_report_mod, ErrorReportMod},
-%% {versions, Vsns},
-%% {db_dir, AgentDir},
-%% %% {db_init_error, DbInitError},
-%% %% {set_mechanism, SetModule},
-%% %% {authentication_service, AuthModule},
-%% {audit_trail_log, [{type, read_write},
-%% {dir, AgentDir},
-%% {size, {10240, 10}},
-%% {repair, true}]},
-%% {config, [{verbosity, info},
-%% {dir, AgentDir},
-%% {force_load, false}]},
-%% {mibs, Mibs},
-%% %% {mib_storage, MibStorage},
-%% {local_db, []},
-%% {mib_server, []},
-%% {symbolic_store, []},
-%% {note_store, []},
-%% {net_if, []},
-%% %% {supervisor, SupOpts}
-%% ],
-
+ ?line AgentLogDir = ?config(agent_log_dir, Config),
+ ?line AgentConfDir = ?config(agent_conf_dir, Config),
+ ?line AgentDbDir = ?config(agent_db_dir, Config),
+ ?line SaNode = ?config(snmp_sa, Config),
+
app_env_init(vsn_init(Vsns) ++
- [{audit_trail_log, read_write_log},
- {audit_trail_log_dir, AgentDir},
- {audit_trail_log_size, {10240, 10}},
- {force_config_reload, false},
- {snmp_agent_type, master},
- {snmp_config_dir, AgentDir},
- {snmp_db_dir, AgentDir},
- {snmp_local_db_auto_repair, true},
- {snmp_local_db_verbosity, log},
- {snmp_master_agent_verbosity, trace},
- {snmp_supervisor_verbosity, trace},
- {snmp_mibserver_verbosity, log},
+ [{audit_trail_log, read_write_log},
+ {audit_trail_log_dir, AgentLogDir},
+ {audit_trail_log_size, {10240, 10}},
+ {force_config_reload, false},
+ {snmp_agent_type, master},
+ {snmp_config_dir, AgentConfDir},
+ {snmp_db_dir, AgentDbDir},
+ {snmp_local_db_auto_repair, true},
+ {snmp_local_db_verbosity, log},
+ {snmp_master_agent_verbosity, trace},
+ {snmp_supervisor_verbosity, trace},
+ {snmp_mibserver_verbosity, log},
{snmp_symbolic_store_verbosity, log},
- {snmp_note_store_verbosity, log},
- {snmp_net_if_verbosity, trace}],
+ {snmp_note_store_verbosity, log},
+ {snmp_net_if_verbosity, trace}],
Opts),
@@ -1237,30 +1221,44 @@ stop_node(Node) ->
%%% Configuration
%%%-----------------------------------------------------------------
-config(Vsns, MgrDir, AgentDir, MIp, AIp) ->
- ?line snmp_config:write_agent_snmp_files(AgentDir, Vsns, MIp,
- ?TRAP_UDP, AIp, 4000,
+config(Vsns, MgrDir, AgentConfDir, MIp, AIp) ->
+ ?LOG("config -> entry with"
+ "~n Vsns: ~p"
+ "~n MgrDir: ~p"
+ "~n AgentConfDir: ~p"
+ "~n MIp: ~p"
+ "~n AIp: ~p",
+ [Vsns, MgrDir, AgentConfDir, MIp, AIp]),
+ ?line snmp_config:write_agent_snmp_files(AgentConfDir, Vsns,
+ MIp, ?TRAP_UDP, AIp, 4000,
"test"),
- ?line case update_usm(Vsns, AgentDir) of
+ ?line case update_usm(Vsns, AgentConfDir) of
true ->
- ?line copy_file(filename:join(AgentDir, "usm.conf"),
+ ?line copy_file(filename:join(AgentConfDir, "usm.conf"),
filename:join(MgrDir, "usm.conf")),
?line update_usm_mgr(Vsns, MgrDir);
false ->
?line ok
end,
- ?line update_community(Vsns, AgentDir),
- ?line update_vacm(Vsns, AgentDir),
- ?line write_target_addr_conf(AgentDir, MIp, ?TRAP_UDP, Vsns),
- ?line write_target_params_conf(AgentDir, Vsns),
- ?line write_notify_conf(AgentDir),
+ ?line update_community(Vsns, AgentConfDir),
+ ?line update_vacm(Vsns, AgentConfDir),
+ ?line write_target_addr_conf(AgentConfDir, MIp, ?TRAP_UDP, Vsns),
+ ?line write_target_params_conf(AgentConfDir, Vsns),
+ ?line write_notify_conf(AgentConfDir),
ok.
delete_files(Config) ->
- Dir = ?config(agent_dir, Config),
- {ok, List} = file:list_dir(Dir),
+ AgentDir = ?config(agent_dir, Config),
+ delete_files(AgentDir, [db, conf]).
+
+delete_files(_AgentFiles, []) ->
+ ok;
+delete_files(AgentDir, [DirName|DirNames]) ->
+ Dir = filename:join(AgentDir, DirName),
+ {ok, Files} = file:list_dir(Dir),
lists:foreach(fun(FName) -> file:delete(filename:join(Dir, FName)) end,
- List).
+ Files),
+ delete_files(AgentDir, DirNames).
update_usm(Vsns, Dir) ->
case lists:member(v3, Vsns) of
@@ -1418,8 +1416,8 @@ rewrite_target_addr_conf2(_NewPort,O) ->
O.
reset_target_addr_conf(Dir) ->
- ?line ok = file:rename(filename:join(Dir,"target_addr.old"),
- filename:join(Dir,"target_addr.conf")).
+ ?line ok = file:rename(filename:join(Dir, "target_addr.old"),
+ filename:join(Dir, "target_addr.conf")).
write_target_params_conf(Dir, Vsns) ->
F = fun(v1) -> {"target_v1", v1, v1, "all-rights", noAuthNoPriv};
@@ -1458,7 +1456,6 @@ copy_file(From, To) ->
ok = file:write_file(To, Bin).
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
display_memory_usage() ->
diff --git a/lib/snmp/test/snmp_app_test.erl b/lib/snmp/test/snmp_app_test.erl
index bc62c8d530..825a232c99 100644
--- a/lib/snmp/test/snmp_app_test.erl
+++ b/lib/snmp/test/snmp_app_test.erl
@@ -23,8 +23,8 @@
-module(snmp_app_test).
-export([
- all/0,groups/0,init_per_group/2,end_per_group/2, init_per_suite/1,
- end_per_suite/1,
+ all/0, groups/0, init_per_group/2, end_per_group/2,
+ init_per_suite/1, end_per_suite/1,
init_per_testcase/2, end_per_testcase/2,
fields/1,
@@ -52,33 +52,47 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
all() ->
-Cases = [fields, modules, exportall, app_depend,
- undef_funcs, {group, start_and_stop}],
- Cases.
+ Cases =
+ [
+ fields,
+ modules,
+ exportall,
+ app_depend,
+ undef_funcs,
+ {group, start_and_stop}
+ ],
+ Cases.
groups() ->
[{start_and_stop, [],
- [start_and_stop_empty, start_and_stop_with_agent,
- start_and_stop_with_manager,
- start_and_stop_with_agent_and_manager,
- start_epmty_and_then_agent_and_manager_and_stop,
- start_with_agent_and_then_manager_and_stop,
- start_with_manager_and_then_agent_and_stop]}].
+ [start_and_stop_empty,
+ start_and_stop_with_agent,
+ start_and_stop_with_manager,
+ start_and_stop_with_agent_and_manager,
+ start_epmty_and_then_agent_and_manager_and_stop,
+ start_with_agent_and_then_manager_and_stop,
+ start_with_manager_and_then_agent_and_stop]}].
init_per_group(_GroupName, Config) ->
- Config.
+ Config.
end_per_group(_GroupName, Config) ->
- Config.
+ Config.
init_per_suite(Config) when is_list(Config) ->
?DISPLAY_SUITE_INFO(),
+
+ %% Note that part of this stuff (the suite top dir creation)
+ %% may already be done (if we run the entire snmp suite).
+
PrivDir = ?config(priv_dir, Config),
TopDir = filename:join(PrivDir, app),
case file:make_dir(TopDir) of
ok ->
ok;
+ {error, eexist} ->
+ ok;
Error ->
fail({failed_creating_subsuite_top_dir, Error})
end,
diff --git a/lib/snmp/test/snmp_compiler_test.erl b/lib/snmp/test/snmp_compiler_test.erl
index 0a147130b0..f3a1e77322 100644
--- a/lib/snmp/test/snmp_compiler_test.erl
+++ b/lib/snmp/test/snmp_compiler_test.erl
@@ -40,6 +40,7 @@
all/0,
groups/0, init_per_group/2, end_per_group/2,
init_per_testcase/2, end_per_testcase/2,
+ init_per_suite/1, end_per_suite/1,
description/1,
oid_conflicts/1,
@@ -74,19 +75,41 @@
%% External functions
%%======================================================================
-init_per_testcase(_Case, Config) when is_list(Config) ->
- Dir = ?config(priv_dir, Config),
- DataDir = ?config(data_dir, Config),
- [_|RL] = lists:reverse(filename:split(DataDir)),
- MibDir = join(lists:reverse(["snmp_test_data"|RL])),
- CompDir = join(Dir, "comp_dir/"),
- ?line ok = file:make_dir(CompDir),
- [{comp_dir, CompDir}, {mib_dir, MibDir} | Config].
+init_per_suite(Config0) when is_list(Config0) ->
+
+ ?DBG("init_per_suite -> entry with"
+ "~n Config0: ~p", [Config0]),
+
+ Config1 = snmp_test_lib:init_suite_top_dir(?MODULE, Config0),
+ Config2 = snmp_test_lib:fix_data_dir(Config1),
+
+ %% Mib-dirs
+ %% data_dir is trashed by the test-server / common-test
+ %% so there is no point in fixing it...
+ MibDir = snmp_test_lib:lookup(data_dir, Config2),
+ StdMibDir = filename:join([code:priv_dir(snmp), "mibs"]),
+
+ [{mib_dir, MibDir}, {std_mib_dir, StdMibDir} | Config2].
+
+end_per_suite(Config) when is_list(Config) ->
+
+ ?DBG("end_per_suite -> entry with"
+ "~n Config: ~p", [Config]),
+
+ Config.
+
+
+init_per_testcase(Case, Config) when is_list(Config) ->
+
+ ?DBG("init_per_testcase -> entry with"
+ "~n Config: ~p", [Config]),
+
+ CaseTopDir = snmp_test_lib:init_testcase_top_dir(Case, Config),
+
+ [{case_top_dir, CaseTopDir} | Config].
end_per_testcase(_Case, Config) when is_list(Config) ->
- CompDir = ?config(comp_dir, Config),
- ?line ok = ?DEL_DIR(CompDir),
- lists:keydelete(comp_dir, 1, Config).
+ Config.
%%======================================================================
@@ -126,7 +149,7 @@ description(Config) when is_list(Config) ->
put(tname,desc),
p("starting with Config: ~p~n", [Config]),
- Dir = ?config(comp_dir, Config),
+ Dir = ?config(case_top_dir, Config),
Filename = join(Dir,"test"),
MibSrcName = Filename ++ ".mib",
MibBinName = Filename ++ ".bin",
@@ -161,7 +184,7 @@ oid_conflicts(Config) when is_list(Config) ->
put(tname,oid_conflicts),
p("starting with Config: ~p~n", [Config]),
- Dir = ?config(comp_dir, Config),
+ Dir = ?config(case_top_dir, Config),
Mib = join(Dir,"TESTv2.mib"),
?line ok = write_oid_conflict_mib(Mib),
?line {error,compilation_failed} =
@@ -278,7 +301,7 @@ warnings_as_errors(suite) ->
warnings_as_errors(Config) when is_list(Config) ->
put(tname,warnings_as_errors),
p("starting with Config: ~p~n", [Config]),
- Dir = ?config(comp_dir, Config),
+ Dir = ?config(case_top_dir, Config),
MibDir = ?config(mib_dir, Config),
MibFile = join(MibDir, "OTP8574-MIB.mib"),
OutFile = join(Dir, "OTP8574-MIB.bin"),
@@ -303,7 +326,7 @@ otp_6150(Config) when is_list(Config) ->
put(tname,otp_6150),
p("starting with Config: ~p~n", [Config]),
- Dir = ?config(comp_dir, Config),
+ Dir = ?config(case_top_dir, Config),
MibDir = ?config(mib_dir, Config),
MibFile = join(MibDir, "ERICSSON-TOP-MIB.mib"),
?line {ok, Mib} = snmpc:compile(MibFile, [{outdir, Dir}, {verbosity, trace}]),
@@ -319,7 +342,7 @@ otp_8574(Config) when is_list(Config) ->
put(tname,otp_8574),
p("starting with Config: ~p~n", [Config]),
- Dir = ?config(comp_dir, Config),
+ Dir = ?config(case_top_dir, Config),
MibDir = ?config(mib_dir, Config),
MibFile = join(MibDir, "OTP8574-MIB.mib"),
@@ -352,7 +375,7 @@ otp_8595(Config) when is_list(Config) ->
put(tname,otp_8595),
p("starting with Config: ~p~n", [Config]),
- Dir = ?config(comp_dir, Config),
+ Dir = ?config(case_top_dir, Config),
MibDir = ?config(mib_dir, Config),
MibFile = join(MibDir, "OTP8595-MIB.mib"),
?line {ok, Mib} =
@@ -546,8 +569,8 @@ check_desc(Desc1, Desc2) ->
exit({'description not equal', Desc1, Desc2}).
-join(Comp) ->
- filename:join(Comp).
+%% join(Comp) ->
+%% filename:join(Comp).
join(A,B) ->
filename:join(A,B).
diff --git a/lib/snmp/test/snmp_log_test.erl b/lib/snmp/test/snmp_log_test.erl
index b692017407..8478825f59 100644
--- a/lib/snmp/test/snmp_log_test.erl
+++ b/lib/snmp/test/snmp_log_test.erl
@@ -42,7 +42,11 @@
-export([
init_per_testcase/2, end_per_testcase/2,
- all/0,groups/0,init_per_group/2,end_per_group/2,
+ all/0,
+ groups/0,
+ init_per_group/2,
+ end_per_group/2,
+
open_and_close/1,
open_write_and_close1/1,
@@ -109,16 +113,21 @@ end_per_testcase(_Case, Config) when is_list(Config) ->
%%======================================================================
%% ?SKIP(not_yet_implemented).
all() ->
-[open_and_close, {group, open_write_and_close},
- {group, log_to_io}, {group, log_to_txt}].
+ [
+ open_and_close,
+ {group, open_write_and_close},
+ {group, log_to_io},
+ {group, log_to_txt}].
groups() ->
- [{open_write_and_close, [],
- [open_write_and_close1, open_write_and_close2,
- open_write_and_close3, open_write_and_close4]},
- {log_to_io, [], [log_to_io1, log_to_io2]},
- {log_to_txt, [],
- [log_to_txt1, log_to_txt2, log_to_txt3]}].
+ [
+ {open_write_and_close, [],
+ [open_write_and_close1, open_write_and_close2,
+ open_write_and_close3, open_write_and_close4]},
+ {log_to_io, [], [log_to_io1, log_to_io2]},
+ {log_to_txt, [],
+ [log_to_txt1, log_to_txt2, log_to_txt3]}
+ ].
init_per_group(_GroupName, Config) ->
Config.
diff --git a/lib/snmp/test/snmp_manager_test.erl b/lib/snmp/test/snmp_manager_test.erl
index 75c9f7b277..c374a2f0a6 100644
--- a/lib/snmp/test/snmp_manager_test.erl
+++ b/lib/snmp/test/snmp_manager_test.erl
@@ -49,6 +49,8 @@
init_per_group/2, end_per_group/2,
init_per_testcase/2, end_per_testcase/2,
+ init_per_suite/1, end_per_suite/1,
+
simple_start_and_stop1/1,
simple_start_and_stop2/1,
@@ -146,36 +148,43 @@
%% External functions
%%======================================================================
+init_per_suite(Config0) when is_list(Config0) ->
+
+ ?DBG("init_per_suite -> entry with"
+ "~n Config0: ~p", [Config0]),
+
+ Config1 = snmp_test_lib:init_suite_top_dir(?MODULE, Config0),
+ Config2 = snmp_test_lib:fix_data_dir(Config1),
+
+ %% Mib-dirs
+ %% data_dir is trashed by the test-server / common-test
+ %% so there is no point in fixing it...
+ MibDir = snmp_test_lib:lookup(data_dir, Config2),
+ StdMibDir = filename:join([code:priv_dir(snmp), "mibs"]),
+
+ [{mib_dir, MibDir}, {std_mib_dir, StdMibDir} | Config2].
+
+end_per_suite(Config) when is_list(Config) ->
+
+ ?DBG("end_per_suite -> entry with"
+ "~n Config: ~p", [Config]),
+
+ Config.
+
+
init_per_testcase(Case, Config) when is_list(Config) ->
io:format(user, "~n~n*** INIT ~w:~w ***~n~n", [?MODULE,Case]),
init_per_testcase2(Case, Config).
init_per_testcase2(Case, Config) ->
- ?DBG("init [~w] Nodes [1]: ~p", [Case, erlang:nodes()]),
-
- %% Fix a correct data dir (points to the wrong location):
- DataDir0 = ?config(data_dir, Config),
- DataDir1 = filename:split(filename:absname(DataDir0)),
- [_|DataDir2] = lists:reverse(DataDir1),
- DataDir = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]),
+ ?DBG("init_per_testcase2 -> ~p", [erlang:nodes()]),
- PrivDir = ?config(priv_dir, Config),
+ CaseTopDir = snmp_test_lib:init_testcase_top_dir(Case, Config),
- TopDir = filename:join(PrivDir, ?MODULE),
- case file:make_dir(TopDir) of
- ok ->
- ok;
- {error, eexist} ->
- ok;
- Error ->
- ?FAIL({failed_creating_subsuite_top_dir, Error})
- end,
-
- CaseTopDir = filename:join(TopDir, Case),
- ?line ok = file:make_dir(CaseTopDir),
-
%% -- Manager dirs --
- MgrTopDir = filename:join(CaseTopDir, "manager/"),
+ MgrTopDir = filename:join(CaseTopDir, "manager/"),
+ ?DBG("init_per_testcase2 -> try create manager top dir: ~n~p",
+ [MgrTopDir]),
?line ok = file:make_dir(MgrTopDir),
MgrConfDir = filename:join(MgrTopDir, "conf/"),
@@ -200,10 +209,9 @@ init_per_testcase2(Case, Config) ->
AgLogDir = filename:join(AgTopDir, "log/"),
?line ok = file:make_dir(AgLogDir),
- Conf = [{snmp_data_dir, DataDir},
- {watchdog, ?WD_START(?MINS(5))},
+ Conf = [{watchdog, ?WD_START(?MINS(5))},
{ip, ?LOCALHOST()},
- {top_dir, TopDir},
+ {case_top_dir, CaseTopDir},
{agent_dir, AgTopDir},
{agent_conf_dir, AgConfDir},
{agent_db_dir, AgDbDir},
@@ -388,9 +396,11 @@ all() ->
{group, user_tests},
{group, agent_tests},
{group, request_tests},
+ {group, request_tests_mt},
{group, event_tests},
+ {group, event_tests_mt},
discovery,
- {group, tickets}
+ {group, tickets}
].
groups() ->
@@ -431,6 +441,15 @@ groups() ->
{group, misc_request_tests}
]
},
+ {request_tests_mt, [],
+ [
+ {group, get_tests},
+ {group, get_next_tests},
+ {group, set_tests},
+ {group, bulk_tests},
+ {group, misc_request_tests}
+ ]
+ },
{get_tests, [],
[
simple_sync_get1,
@@ -477,18 +496,30 @@ groups() ->
misc_async2
]
},
- {event_tests, [],
- [
- trap1%% ,
- %% trap2,
- %% inform1,
- %% inform2,
- %% inform3,
- %% inform4,
- %% inform_swarm,
- %% report
- ]
- },
+ {event_tests, [],
+ [
+ trap1,
+ trap2,
+ inform1,
+ inform2,
+ inform3,
+ inform4,
+ inform_swarm,
+ report
+ ]
+ },
+ {event_tests_mt, [],
+ [
+ trap1,
+ trap2,
+ inform1,
+ inform2,
+ inform3,
+ inform4,
+ inform_swarm,
+ report
+ ]
+ },
{tickets, [],
[
{group, otp8015},
@@ -507,11 +538,21 @@ groups() ->
}
].
-init_per_group(_GroupName, Config) ->
- Config.
+init_per_group(request_tests_mt = GroupName, Config) ->
+ snmp_test_lib:init_group_top_dir(
+ GroupName,
+ [{manager_net_if_module, snmpm_net_if_mt} | Config]);
+init_per_group(event_tests_mt = GroupName, Config) ->
+ snmp_test_lib:init_group_top_dir(
+ GroupName,
+ [{manager_net_if_module, snmpm_net_if_mt} | Config]);
+init_per_group(GroupName, Config) ->
+ snmp_test_lib:init_group_top_dir(GroupName, Config).
+
end_per_group(_GroupName, Config) ->
- Config.
+ %% Do we really need to do this?
+ lists:keydelete(snmp_group_top_dir, 1, Config).
%%======================================================================
@@ -1571,6 +1612,11 @@ simple_sync_get1(Config) when is_list(Config) ->
?line ok = mgr_user_load_mib(Node, std_mib()),
Oids2 = [[sysObjectID, 0], [sysDescr, 0], [sysUpTime, 0]],
?line ok = do_simple_sync_get(Node, Addr, Port, Oids2),
+
+ p("Display log"),
+ display_log(Config),
+
+ p("done"),
ok.
do_simple_sync_get(Node, Addr, Port, Oids) ->
@@ -1578,7 +1624,7 @@ do_simple_sync_get(Node, Addr, Port, Oids) ->
?DBG("~n Reply: ~p"
"~n Rem: ~w", [Reply, Rem]),
-
+
%% verify that the operation actually worked:
%% The order should be the same, so no need to seach
?line ok = case Reply of
@@ -1612,7 +1658,9 @@ simple_sync_get2(suite) -> [];
simple_sync_get2(Config) when is_list(Config) ->
process_flag(trap_exit, true),
put(tname, ssg2),
- do_simple_sync_get2(Config).
+ do_simple_sync_get2(Config),
+ display_log(Config),
+ ok.
do_simple_sync_get2(Config) ->
Get = fun(Node, TargetName, Oids) ->
@@ -1677,7 +1725,9 @@ simple_sync_get3(suite) -> [];
simple_sync_get3(Config) when is_list(Config) ->
process_flag(trap_exit, true),
put(tname, ssg3),
- do_simple_sync_get3(Config).
+ do_simple_sync_get3(Config),
+ display_log(Config),
+ ok.
do_simple_sync_get3(Config) ->
Self = self(),
@@ -1703,8 +1753,8 @@ do_simple_sync_get3(Config) ->
%%======================================================================
-simple_async_get1(doc) -> ["Simple (async) get-request - "
- "Old style (Addr & Port)"];
+simple_async_get1(doc) ->
+ ["Simple (async) get-request - Old style (Addr & Port)"];
simple_async_get1(suite) -> [];
simple_async_get1(Config) when is_list(Config) ->
process_flag(trap_exit, true),
@@ -1766,6 +1816,7 @@ simple_async_get1(Config) when is_list(Config) ->
p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]),
p("agent info when ending test: ~n~p", [agent_info(AgentNode)]),
+ display_log(Config),
ok.
async_g_exec1(Node, Addr, Port, Oids) ->
@@ -1816,7 +1867,9 @@ simple_async_get2(Config) when is_list(Config) ->
TargetName = ?config(manager_agent_target_name, Config),
Get = fun(Oids) -> async_g_exec2(MgrNode, TargetName, Oids) end,
PostVerify = fun(Res) -> Res end,
- do_simple_async_sync_get2(Config, MgrNode, AgentNode, Get, PostVerify).
+ do_simple_async_sync_get2(Config, MgrNode, AgentNode, Get, PostVerify),
+ display_log(Config),
+ ok.
do_simple_async_sync_get2(Config, MgrNode, AgentNode, Get, PostVerify) ->
?line ok = mgr_user_load_mib(MgrNode, std_mib()),
@@ -1905,7 +1958,9 @@ simple_async_get3(Config) when is_list(Config) ->
PostVerify = fun(ok) -> receive Msg -> ok end;
(Error) -> Error
end,
- do_simple_async_sync_get2(Config, MgrNode, AgentNode, Get, PostVerify).
+ do_simple_async_sync_get2(Config, MgrNode, AgentNode, Get, PostVerify),
+ display_log(Config),
+ ok.
async_g_exec3(Node, TargetName, Oids, SendOpts) ->
mgr_user_async_get2(Node, TargetName, Oids, SendOpts).
@@ -1999,6 +2054,8 @@ simple_sync_get_next1(Config) when is_list(Config) ->
end,
?line ok = do_simple_get_next(8,
MgrNode, Addr, Port, Oids08, VF08),
+
+ display_log(Config),
ok.
@@ -2062,7 +2119,10 @@ simple_sync_get_next2(Config) when is_list(Config) ->
mgr_user_sync_get_next(Node, TargetName, Oids)
end,
PostVerify = fun(Res) -> Res end,
- do_simple_sync_get_next2(Config, GetNext, PostVerify).
+ do_simple_sync_get_next2(Config, GetNext, PostVerify),
+ display_log(Config),
+ ok.
+
do_simple_sync_get_next2(Config, GetNext, PostVerify)
when is_function(GetNext, 3) andalso is_function(PostVerify, 1) ->
@@ -2193,7 +2253,9 @@ simple_sync_get_next3(Config) when is_list(Config) ->
PostVerify = fun(ok) -> receive Msg -> ok end;
(Error) -> Error
end,
- do_simple_sync_get_next2(Config, GetNext, PostVerify).
+ do_simple_sync_get_next2(Config, GetNext, PostVerify),
+ display_log(Config),
+ ok.
%%======================================================================
@@ -2286,6 +2348,7 @@ simple_async_get_next1(Config) when is_list(Config) ->
p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]),
p("agent info when ending test: ~n~p", [agent_info(AgentNode)]),
+ display_log(Config),
ok.
@@ -2315,7 +2378,9 @@ simple_async_get_next2(Config) when is_list(Config) ->
async_gn_exec2(MgrNode, TargetName, Oids)
end,
PostVerify = fun(Res) -> Res end,
- do_simple_async_get_next2(MgrNode, AgentNode, GetNext, PostVerify).
+ do_simple_async_get_next2(MgrNode, AgentNode, GetNext, PostVerify),
+ display_log(Config),
+ ok.
do_simple_async_get_next2(MgrNode, AgentNode, GetNext, PostVerify)
when is_function(GetNext, 1) andalso is_function(PostVerify, 1) ->
@@ -2437,7 +2502,9 @@ simple_async_get_next3(Config) when is_list(Config) ->
(Error) -> Error
end,
- do_simple_async_get_next2(MgrNode, AgentNode, GetNext, PostVerify).
+ do_simple_async_get_next2(MgrNode, AgentNode, GetNext, PostVerify),
+ display_log(Config),
+ ok.
async_gn_exec3(Node, TargetName, Oids, SendOpts) ->
mgr_user_async_get_next2(Node, TargetName, Oids, SendOpts).
@@ -2475,6 +2542,8 @@ simple_sync_set1(Config) when is_list(Config) ->
{[sysLocation, 0], Val22}
],
?line ok = do_simple_set1(Node, Addr, Port, VAVs2),
+
+ display_log(Config),
ok.
do_simple_set1(Node, Addr, Port, VAVs) ->
@@ -2527,7 +2596,9 @@ simple_sync_set2(Config) when is_list(Config) ->
end,
PostVerify = fun() -> ok end,
- do_simple_sync_set2(Config, Set, PostVerify).
+ do_simple_sync_set2(Config, Set, PostVerify),
+ display_log(Config),
+ ok.
do_simple_sync_set2(Config, Set, PostVerify)
when is_function(Set, 3) andalso is_function(PostVerify, 0) ->
@@ -2604,7 +2675,9 @@ simple_sync_set3(Config) when is_list(Config) ->
end,
PostVerify = fun() -> receive Msg -> ok end end,
- do_simple_sync_set2(Config, Set, PostVerify).
+ do_simple_sync_set2(Config, Set, PostVerify),
+ display_log(Config),
+ ok.
%%======================================================================
@@ -2663,6 +2736,7 @@ simple_async_set1(Config) when is_list(Config) ->
p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]),
p("agent info when ending test: ~n~p", [agent_info(AgentNode)]),
+ display_log(Config),
ok.
@@ -2724,7 +2798,9 @@ simple_async_set2(Config) when is_list(Config) ->
end,
PostVerify = fun(Res) -> Res end,
- do_simple_async_set2(MgrNode, AgentNode, Set, PostVerify).
+ do_simple_async_set2(MgrNode, AgentNode, Set, PostVerify),
+ display_log(Config),
+ ok.
do_simple_async_set2(MgrNode, AgentNode, Set, PostVerify) ->
Requests =
@@ -2806,7 +2882,9 @@ simple_async_set3(Config) when is_list(Config) ->
(Res) -> Res
end,
- do_simple_async_set2(MgrNode, AgentNode, Set, PostVerify).
+ do_simple_async_set2(MgrNode, AgentNode, Set, PostVerify),
+ display_log(Config),
+ ok.
async_s_exec3(Node, TargetName, VAVs, SendOpts) ->
mgr_user_async_set2(Node, TargetName, VAVs, SendOpts).
@@ -2932,6 +3010,7 @@ simple_sync_get_bulk1(Config) when is_list(Config) ->
0, 2,
[[TCnt2, 1]], VF11),
+ display_log(Config),
ok.
fl(L) ->
@@ -3004,7 +3083,9 @@ simple_sync_get_bulk2(Config) when is_list(Config) ->
end,
PostVerify = fun(Res) -> Res end,
- do_simple_sync_get_bulk2(Config, MgrNode, AgentNode, GetBulk, PostVerify).
+ do_simple_sync_get_bulk2(Config, MgrNode, AgentNode, GetBulk, PostVerify),
+ display_log(Config),
+ ok.
do_simple_sync_get_bulk2(Config, MgrNode, AgentNode, GetBulk, PostVerify) ->
%% -- 1 --
@@ -3169,7 +3250,9 @@ simple_sync_get_bulk3(Config) when is_list(Config) ->
(Res) -> Res
end,
- do_simple_sync_get_bulk2(Config, MgrNode, AgentNode, GetBulk, PostVerify).
+ do_simple_sync_get_bulk2(Config, MgrNode, AgentNode, GetBulk, PostVerify),
+ display_log(Config),
+ ok.
%%======================================================================
@@ -3308,6 +3391,7 @@ simple_async_get_bulk1(Config) when is_list(Config) ->
p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]),
p("agent info when ending test: ~n~p", [agent_info(AgentNode)]),
+ display_log(Config),
ok.
@@ -3340,7 +3424,9 @@ simple_async_get_bulk2(Config) when is_list(Config) ->
end,
PostVerify = fun(Res) -> Res end,
- do_simple_async_get_bulk2(MgrNode, AgentNode, GetBulk, PostVerify).
+ do_simple_async_get_bulk2(MgrNode, AgentNode, GetBulk, PostVerify),
+ display_log(Config),
+ ok.
do_simple_async_get_bulk2(MgrNode, AgentNode, GetBulk, PostVerify) ->
%% We re-use the verification functions from the ssgb test-case
@@ -3505,7 +3591,9 @@ simple_async_get_bulk3(Config) when is_list(Config) ->
(Res) -> Res
end,
- do_simple_async_get_bulk2(MgrNode, AgentNode, GetBulk, PostVerify).
+ do_simple_async_get_bulk2(MgrNode, AgentNode, GetBulk, PostVerify),
+ display_log(Config),
+ ok.
async_gb_exec3(Node, TargetName, {NR, MR, Oids}, SendOpts) ->
mgr_user_async_get_bulk2(Node, TargetName, NR, MR, Oids, SendOpts).
@@ -3697,6 +3785,7 @@ misc_async1(Config) when is_list(Config) ->
p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]),
p("agent info when ending test: ~n~p", [agent_info(AgentNode)]),
+ display_log(Config),
ok.
@@ -3885,6 +3974,7 @@ misc_async2(Config) when is_list(Config) ->
p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]),
p("agent info when ending test: ~n~p", [agent_info(AgentNode)]),
+ display_log(Config),
ok.
@@ -4099,7 +4189,9 @@ trap1(Config) when is_list(Config) ->
{5, "Manager and agent info after test completion", Cmd1}
],
- command_handler(Commands).
+ command_handler(Commands),
+ display_log(Config),
+ ok.
%%======================================================================
@@ -4290,7 +4382,9 @@ trap2(Config) when is_list(Config) ->
{7, "Manager and agent info after test completion", Cmd1}
],
- command_handler(Commands).
+ command_handler(Commands),
+ display_log(Config),
+ ok.
%%======================================================================
@@ -4415,7 +4509,9 @@ inform1(Config) when is_list(Config) ->
{6, "Manager and agent info after test completion", Cmd1}
],
- command_handler(Commands).
+ command_handler(Commands),
+ display_log(Config),
+ ok.
%%======================================================================
@@ -4423,7 +4519,7 @@ inform1(Config) when is_list(Config) ->
inform2(suite) -> [];
inform2(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- put(tname,i2),
+ put(tname, i2),
p("starting with Config: ~p~n", [Config]),
MgrNode = ?config(manager_node, Config),
@@ -4577,7 +4673,7 @@ inform2(Config) when is_list(Config) ->
[
{1, "Manager and agent info at start of test", Cmd1},
{2, "Send notifcation [no receiver] from agent", Cmd2},
- {3, "await inform-sent acknowledge from agent", Cmd3},
+ {3, "Await inform-sent acknowledge from agent", Cmd3},
{4, "Await first inform to manager - do not reply", Cmd4},
{5, "Await second inform to manager - reply", Cmd5},
{6, "await inform-acknowledge from agent", Cmd6},
@@ -4585,7 +4681,9 @@ inform2(Config) when is_list(Config) ->
{8, "Manager and agent info after test completion", Cmd1}
],
- command_handler(Commands).
+ command_handler(Commands),
+ display_log(Config),
+ ok.
%%======================================================================
@@ -4719,7 +4817,9 @@ inform3(Config) when is_list(Config) ->
{9, "Manager and agent info after test completion", Cmd1}
],
- command_handler(Commands).
+ command_handler(Commands),
+ display_log(Config),
+ ok.
%%======================================================================
@@ -4835,7 +4935,9 @@ inform4(Config) when is_list(Config) ->
{6, "Manager and agent info after test completion", Cmd1}
],
- command_handler(Commands).
+ command_handler(Commands),
+ display_log(Config),
+ ok.
%%======================================================================
@@ -4923,7 +5025,10 @@ inform_swarm(Config) when is_list(Config) ->
{5, "Manager and agent info after test completion", Cmd1}
],
- command_handler(Commands).
+ command_handler(Commands),
+ display_log(Config),
+ ok.
+
inform_swarm_collector(N) ->
inform_swarm_collector(N, 0, 0, 0, 10000).
@@ -5227,8 +5332,8 @@ init_agent(Config) ->
%% --
%% Retrieve some dir's
%%
- Dir = ?config(top_dir, Config),
- DataDir = ?config(data_dir, Config),
+ Dir = ?config(agent_dir, Config),
+ MibDir = ?config(mib_dir, Config),
%% --
%% Start node
@@ -5259,7 +5364,7 @@ init_agent(Config) ->
?line ok = write_agent_config(Vsns, Config),
Conf = [{agent_node, Node},
- {mib_dir, DataDir} | Config],
+ {mib_dir, MibDir} | Config],
%%
%% Start the agent
@@ -5720,6 +5825,15 @@ start_manager(Node, Vsns, Conf0, Opts) ->
AtlSeqNo = get_opt(manager_atl_seqno, Conf0, false),
+ NetIfConf =
+ case get_opt(manager_net_if_module, Conf0, no_module) of
+ no_module ->
+ [{verbosity, NetIfVerbosity}];
+ NetIfModule ->
+ [{module, NetIfModule},
+ {verbosity, NetIfVerbosity}]
+ end,
+
Env = [{versions, Vsns},
{inform_request_behaviour, IRB},
{audit_trail_log, [{type, read_write},
@@ -5732,7 +5846,7 @@ start_manager(Node, Vsns, Conf0, Opts) ->
{verbosity, ConfigVerbosity}]},
{note_store, [{verbosity, NoteStoreVerbosity}]},
{server, [{verbosity, ServerVerbosity}]},
- {net_if, [{verbosity, NetIfVerbosity}]}],
+ {net_if, NetIfConf}],
?line ok = set_mgr_env(Node, Env),
?line ok = start_snmp(Node),
@@ -6018,6 +6132,38 @@ write_conf_file(Dir, File, Str) ->
%% ------
+display_log(Config) ->
+ case lists:keysearch(manager_log_dir, 1, Config) of
+ {value, {_, Dir}} ->
+ case lists:keysearch(manager_node, 1, Config) of
+ {value, {_, Node}} ->
+ LogDir = Dir,
+ Mibs = [],
+ OutFile = j(LogDir, "snmpm_log.txt"),
+ p("~n"
+ "========================="
+ " < Audit Trail Log > "
+ "========================="
+ "~n"),
+ rcall(Node, snmpm, log_to_txt, [LogDir, Mibs, OutFile]),
+ rcall(Node, snmpm, log_to_io, [LogDir, Mibs]),
+ p("~n"
+ "========================="
+ " < / Audit Trail Log > "
+ "========================="
+ "~n");
+ false ->
+ p("display_log -> no manager node found"),
+ ok
+ end;
+ false ->
+ p("display_log -> no manager log dir found"),
+ ok
+ end.
+
+
+%% ------
+
test2_mib(Config) ->
j(test_mib_dir(Config), "Test2.bin").
@@ -6034,7 +6180,7 @@ snmpv2_mib() ->
j(mib_dir(), "SNMPv2-MIB.bin").
test_mib_dir(Config) ->
- ?config(snmp_data_dir, Config).
+ ?config(mib_dir, Config).
mib_dir() ->
j(code:priv_dir(snmp), "mibs").
diff --git a/lib/snmp/test/snmp_test_lib.erl b/lib/snmp/test/snmp_test_lib.erl
index e4d58a1253..bc54361aaf 100644
--- a/lib/snmp/test/snmp_test_lib.erl
+++ b/lib/snmp/test/snmp_test_lib.erl
@@ -25,7 +25,10 @@
-export([hostname/0, hostname/1, localhost/0, os_type/0, sz/1,
display_suite_info/1]).
-export([non_pc_tc_maybe_skip/4, os_based_skip/1]).
--export([replace_config/3, set_config/3, get_config/2, get_config/3]).
+-export([fix_data_dir/1,
+ init_suite_top_dir/2, init_group_top_dir/2, init_testcase_top_dir/2,
+ lookup/2,
+ replace_config/3, set_config/3, get_config/2, get_config/3]).
-export([fail/3, skip/3]).
-export([millis/0, millis_diff/2, hours/1, minutes/1, seconds/1, sleep/1]).
-export([flush_mqueue/0, trap_exit/0, trap_exit/1]).
@@ -198,6 +201,85 @@ os_based_skip(_Crap) ->
%% Test suite utility functions
%%
+fix_data_dir(Config) ->
+ DataDir0 = lookup(data_dir, Config),
+ DataDir1 = filename:split(filename:absname(DataDir0)),
+ [_|DataDir2] = lists:reverse(DataDir1),
+ DataDir = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]),
+ Config1 = lists:keydelete(data_dir, 1, Config),
+ [{data_dir, DataDir ++ "/"} | Config1].
+
+
+init_suite_top_dir(Suite, Config0) ->
+ Dir = lookup(priv_dir, Config0),
+ SuiteTopDir = filename:join(Dir, Suite),
+ case file:make_dir(SuiteTopDir) of
+ ok ->
+ ok;
+ {error, eexist} ->
+ ok;
+ {error, Reason} ->
+ fail({failed_creating_suite_top_dir, SuiteTopDir, Reason},
+ ?MODULE, ?LINE)
+ end,
+
+ %% This is just in case...
+ Config1 = lists:keydelete(snmp_group_top_dir, 1, Config0),
+ Config2 = lists:keydelete(snmp_suite_top_dir, 1, Config1),
+ [{snmp_suite_top_dir, SuiteTopDir} | Config2].
+
+
+init_group_top_dir(GroupName, Config) ->
+ case lists:keysearch(snmp_group_top_dir, 1, Config) of
+ {value, {_Key, Dir}} ->
+ %% This is a sub-group, so create our dir within Dir
+ GroupTopDir = filename:join(Dir, GroupName),
+ case file:make_dir(GroupTopDir) of
+ ok ->
+ ok;
+ {error, Reason} ->
+ fail({failed_creating_group_top_dir, GroupTopDir, Reason},
+ ?MODULE, ?LINE)
+ end,
+ [{snmp_group_top_dir, GroupTopDir} | Config];
+
+ _ ->
+ case lists:keysearch(snmp_suite_top_dir, 1, Config) of
+ {value, {_Key, Dir}} ->
+ GroupTopDir = filename:join(Dir, GroupName),
+ case file:make_dir(GroupTopDir) of
+ ok ->
+ ok;
+ {error, Reason} ->
+ fail({failed_creating_group_top_dir,
+ GroupTopDir, Reason},
+ ?MODULE, ?LINE)
+ end,
+ [{snmp_group_top_dir, GroupTopDir} | Config];
+ _ ->
+ fail(could_not_find_suite_top_dir, ?MODULE, ?LINE)
+ end
+ end.
+
+
+init_testcase_top_dir(Case, Config) ->
+ case lists:keysearch(snmp_group_top_dir, 1, Config) of
+ {value, {_Key, Dir}} ->
+ CaseTopDir = filename:join(Dir, Case),
+ ok = file:make_dir(CaseTopDir),
+ CaseTopDir;
+ false ->
+ case lists:keysearch(snmp_suite_top_dir, 1, Config) of
+ {value, {_Key, Dir}} ->
+ CaseTopDir = filename:join(Dir, Case),
+ ok = file:make_dir(CaseTopDir),
+ CaseTopDir;
+ false ->
+ fail(failed_creating_case_top_dir, ?MODULE, ?LINE)
+ end
+ end.
+
+
replace_config(Key, Config, NewValue) ->
lists:keyreplace(Key, 1, Config, {Key, NewValue}).
@@ -220,6 +302,9 @@ get_config(Key,C,Default) ->
Default
end.
+lookup(Key, Config) ->
+ {value, {Key, Value}} = lists:keysearch(Key, 1, Config),
+ Value.
fail(Reason, Mod, Line) ->
exit({suite_failed, Reason, Mod, Line}).
diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk
index fb1dcb6c41..aea38a4cdb 100644
--- a/lib/snmp/vsn.mk
+++ b/lib/snmp/vsn.mk
@@ -18,6 +18,6 @@
# %CopyrightEnd%
APPLICATION = snmp
-SNMP_VSN = 4.21.7
-PRE_VSN =
-APP_VSN = "$(APPLICATION)-$(SNMP_VSN)$(PRE_VSN)"
+SNMP_VSN = 4.22
+PRE_VSN =
+APP_VSN = "$(APPLICATION)-$(SNMP_VSN)$(PRE_VSN)"
diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml
index 2c5096a25f..ed88b3a1af 100644
--- a/lib/ssh/doc/src/ssh.xml
+++ b/lib/ssh/doc/src/ssh.xml
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd">
<erlref>
<header>
<copyright>
- <year>2004</year><year>2010</year>
+ <year>2004</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -86,7 +86,7 @@
by calling ssh_connect:session_channel/2.</p>
<p>Options are:</p>
<taglist>
- <tag><c><![CDATA[{user_dir, String}]]></c></tag>
+ <tag><c><![CDATA[{user_dir, string()}]]></c></tag>
<item>
<p>Sets the user directory e.i. the directory containing
ssh configuration files for the user such as
@@ -94,6 +94,18 @@
<c><![CDATA[authorized_key]]></c>. Defaults to the directory normally
referred to as <c><![CDATA[~/.ssh]]></c> </p>
</item>
+ <tag><c><![CDATA[{dsa_pass_phrase, string()}]]></c></tag>
+ <item>
+ <p>If the user dsa key is protected by a pass phrase it can be
+ supplied with this option.
+ </p>
+ </item>
+ <tag><c><![CDATA[{rsa_pass_phrase, string()}]]></c></tag>
+ <item>
+ <p>If the user rsa key is protected by a pass phrase it can be
+ supplied with this option.
+ </p>
+ </item>
<tag><c><![CDATA[{silently_accept_hosts, boolean()}]]></c></tag>
<item>
<p>When true hosts are added to the
@@ -222,6 +234,14 @@
option <c>shell</c> which is much less work than implementing
your own cli channel.
</item>
+ <tag><c><![CDATA[{user_dir, String}]]></c></tag>
+ <item>
+ <p>Sets the user directory e.i. the directory containing
+ ssh configuration files for the user such as
+ <c><![CDATA[known_hosts]]></c>, <c><![CDATA[id_rsa, id_dsa]]></c> and
+ <c><![CDATA[authorized_key]]></c>. Defaults to the directory normally
+ referred to as <c><![CDATA[~/.ssh]]></c> </p>
+ </item>
<tag><c><![CDATA[{system_dir, string()}]]></c></tag>
<item>
<p>Sets the system directory, containing the host files
@@ -283,22 +303,6 @@
</func>
<func>
- <name>sign_data(Data, Algorithm) -> Signature | {error, Reason}</name>
- <fsummary> </fsummary>
- <type>
- <v> Data = binary()</v>
- <v> Algorithm = "ssh-rsa"</v>
- <v> Signature = binary()</v>
- <v> Reason = term()</v>
- </type>
- <desc>
- <p>Signs the supplied binary using the SSH key.
- </p>
- </desc>
- </func>
-
-
- <func>
<name>start() -> </name>
<name>start(Type) -> ok | {error, Reason}</name>
<fsummary>Starts the Ssh application. </fsummary>
@@ -356,21 +360,6 @@
</desc>
</func>
- <func>
- <name>verify_data(Data, Signature, Algorithm) -> ok | {error, Reason}</name>
- <fsummary> </fsummary>
- <type>
- <v> Data = binary()</v>
- <v> Algorithm = "ssh-rsa"</v>
- <v> Signature = binary()</v>
- <v> Reason = term()</v>
- </type>
- <desc>
- <p>Verifies the supplied binary against the binary signature.
- </p>
- </desc>
- </func>
-
</funcs>
</erlref>
diff --git a/lib/ssh/src/DSS.asn1 b/lib/ssh/src/DSS.asn1
deleted file mode 100644
index 77aca3808b..0000000000
--- a/lib/ssh/src/DSS.asn1
+++ /dev/null
@@ -1,20 +0,0 @@
-DSS DEFINITIONS EXPLICIT TAGS ::=
-
-BEGIN
-
--- EXPORTS ALL
--- All types and values defined in this module are exported for use
--- in other ASN.1 modules.
-
-DSAPrivateKey ::= SEQUENCE {
- version INTEGER,
- p INTEGER, -- p
- q INTEGER, -- q
- g INTEGER, -- q
- y INTEGER, -- y
- x INTEGER -- x
-}
-
-END
-
-
diff --git a/lib/ssh/src/Makefile b/lib/ssh/src/Makefile
index da31d87369..7be97abf66 100644
--- a/lib/ssh/src/Makefile
+++ b/lib/ssh/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2011. All Rights Reserved.
+# Copyright Ericsson AB 2004-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -36,7 +36,11 @@ RELSYSDIR = $(RELEASE_PATH)/lib/ssh-$(VSN)
# Common Macros
# ----------------------------------------------------
+# Behaviour (api) modules are first so they are compiled when
+# the compiler reaches a callback module using them.
MODULES= \
+ ssh_sftpd_file_api \
+ ssh_key_api \
ssh \
ssh_sup \
sshc_sup \
@@ -56,25 +60,22 @@ MODULES= \
ssh_auth\
ssh_bits \
ssh_cli \
- ssh_dsa \
ssh_file \
ssh_io \
ssh_math \
ssh_no_io \
- ssh_rsa \
ssh_sftp \
ssh_sftpd \
ssh_sftpd_file\
- ssh_sftpd_file_api \
ssh_transport \
ssh_userreg \
ssh_xfer
PUBLIC_HRL_FILES= ssh.hrl ssh_userauth.hrl ssh_xfer.hrl
-ERL_FILES= $(MODULES:%=%.erl) $(ASN_ERLS)
+ERL_FILES= $(MODULES:%=%.erl)
-ALL_MODULES= $(MODULES) $(ASN_MODULES)
+ALL_MODULES= $(MODULES)
TARGET_FILES= $(ALL_MODULES:%=$(EBIN)/%.$(EMULATOR)) $(APP_TARGET) $(APPUP_TARGET)
@@ -87,22 +88,13 @@ APP_TARGET= $(EBIN)/$(APP_FILE)
APPUP_SRC= $(APPUP_FILE).src
APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
-ASN_MODULES = PKCS-1 DSS
-ASN_ASNS = $(ASN_MODULES:%=%.asn1)
-ASN_ERLS = $(ASN_MODULES:%=%.erl)
-ASN_HRLS = $(ASN_MODULES:%=%.hrl)
-ASN_DBS = $(ASN_MODULES:%=%.asn1db)
-ASN_TABLES = $(ASN_MODULES:%=%.table)
-
-ASN_FLAGS = -bber_bin +der +compact_bit_string +optimize +noobj +inline
-
-INTERNAL_HRL_FILES = $(ASN_HRLS) ssh_auth.hrl ssh_connect.hrl ssh_transport.hrl
+INTERNAL_HRL_FILES = ssh_auth.hrl ssh_connect.hrl ssh_transport.hrl
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
-ERL_COMPILE_FLAGS += -pa$(EBIN)
-
+ERL_COMPILE_FLAGS += -pa$(EBIN)\
+ -pz $(ERL_TOP)/lib/public_key/ebin
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
@@ -114,7 +106,6 @@ debug: ERLC_FLAGS += -Ddebug
clean:
rm -f $(TARGET_FILES)
rm -f errs core *~
- rm -f $(ASN_ERLS) $(ASN_HRLS) $(ASN_DBS)
$(TARGET_FILES): ssh.hrl
@@ -127,10 +118,6 @@ $(APP_TARGET): $(APP_SRC) ../vsn.mk
$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
sed -e 's;%VSN%;$(VSN);' $< > $@
-%.erl %.hrl: %.asn1
- $(ERLC) $(ASN_FLAGS) $<
-
-$(EBIN)/ssh_file.$(EMULATOR) $(EBIN)/ssh_rsa.$(EMULATOR): $(ASN_HRLS)
docs:
diff --git a/lib/ssh/src/PKCS-1.asn1 b/lib/ssh/src/PKCS-1.asn1
deleted file mode 100644
index e7d6b18c63..0000000000
--- a/lib/ssh/src/PKCS-1.asn1
+++ /dev/null
@@ -1,116 +0,0 @@
-PKCS-1 {
- iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1)
- modules(0) pkcs-1(1)
-}
-
--- $Revision: 1.1 $
-
-DEFINITIONS EXPLICIT TAGS ::=
-
-BEGIN
-
--- IMPORTS id-sha256, id-sha384, id-sha512
--- FROM NIST-SHA2 {
--- joint-iso-itu-t(2) country(16) us(840) organization(1)
--- gov(101) csor(3) nistalgorithm(4) modules(0) sha2(1)
--- };
-
-pkcs-1 OBJECT IDENTIFIER ::= {
- iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1
-}
-
-rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 }
-
-id-RSAES-OAEP OBJECT IDENTIFIER ::= { pkcs-1 7 }
-
-id-pSpecified OBJECT IDENTIFIER ::= { pkcs-1 9 }
-
-id-RSASSA-PSS OBJECT IDENTIFIER ::= { pkcs-1 10 }
-
-md2WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 2 }
-md5WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 4 }
-sha1WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 5 }
-sha256WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 11 }
-sha384WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 12 }
-sha512WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 13 }
-
-id-sha1 OBJECT IDENTIFIER ::= {
- iso(1) identified-organization(3) oiw(14) secsig(3)
- algorithms(2) 26
-}
-
-id-md2 OBJECT IDENTIFIER ::= {
- iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2
-}
-
-id-md5 OBJECT IDENTIFIER ::= {
- iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5
-}
-
-id-mgf1 OBJECT IDENTIFIER ::= { pkcs-1 8 }
-
-
-RSAPublicKey ::= SEQUENCE {
- modulus INTEGER, -- n
- publicExponent INTEGER -- e
-}
-
-RSAPrivateKey ::= SEQUENCE {
- version Version,
- modulus INTEGER, -- n
- publicExponent INTEGER, -- e
- privateExponent INTEGER, -- d
- prime1 INTEGER, -- p
- prime2 INTEGER, -- q
- exponent1 INTEGER, -- d mod (p-1)
- exponent2 INTEGER, -- d mod (q-1)
- coefficient INTEGER, -- (inverse of q) mod p
- otherPrimeInfos OtherPrimeInfos OPTIONAL
-}
-
-Version ::= INTEGER { two-prime(0), multi(1) }
- (CONSTRAINED BY {
- -- version must be multi if otherPrimeInfos present --
- })
-
-OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo
-
-OtherPrimeInfo ::= SEQUENCE {
- prime INTEGER, -- ri
- exponent INTEGER, -- di
- coefficient INTEGER -- ti
-}
-
-Algorithm ::= SEQUENCE {
- algorithm OBJECT IDENTIFIER,
- parameters ANY DEFINED BY algorithm OPTIONAL
-}
-
-AlgorithmNull ::= SEQUENCE {
- algorithm OBJECT IDENTIFIER,
- parameters NULL
-}
-
-
-RSASSA-PSS-params ::= SEQUENCE {
- hashAlgorithm [0] Algorithm, -- DEFAULT sha1,
- maskGenAlgorithm [1] Algorithm, -- DEFAULT mgf1SHA1,
- saltLength [2] INTEGER DEFAULT 20,
- trailerField [3] TrailerField DEFAULT trailerFieldBC
-}
-
-TrailerField ::= INTEGER { trailerFieldBC(1) }
-
-DigestInfo ::= SEQUENCE {
- digestAlgorithm Algorithm,
- digest OCTET STRING
-}
-
-DigestInfoNull ::= SEQUENCE {
- digestAlgorithm AlgorithmNull,
- digest OCTET STRING
-}
-
-
-END -- PKCS1Definitions
-
diff --git a/lib/ssh/src/prebuild.skip b/lib/ssh/src/prebuild.skip
deleted file mode 100644
index 1d7552d98d..0000000000
--- a/lib/ssh/src/prebuild.skip
+++ /dev/null
@@ -1,2 +0,0 @@
-DSS.asn1db
-PKCS-1.asn1db
diff --git a/lib/ssh/src/ssh.app.src b/lib/ssh/src/ssh.app.src
index 8a3e15841f..7a58dbe54f 100644
--- a/lib/ssh/src/ssh.app.src
+++ b/lib/ssh/src/ssh.app.src
@@ -3,9 +3,7 @@
{application, ssh,
[{description, "SSH-2 for Erlang/OTP"},
{vsn, "%VSN%"},
- {modules, ['DSS',
- 'PKCS-1',
- ssh,
+ {modules, [ssh,
ssh_app,
ssh_acceptor,
ssh_acceptor_sup,
@@ -21,12 +19,11 @@
ssh_shell,
sshc_sup,
sshd_sup,
- ssh_dsa,
ssh_file,
ssh_io,
+ ssh_key_api,
ssh_math,
ssh_no_io,
- ssh_rsa,
ssh_sftp,
ssh_sftpd,
ssh_sftpd_file,
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl
index cada109df0..5751f2eaa0 100644
--- a/lib/ssh/src/ssh.erl
+++ b/lib/ssh/src/ssh.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -23,6 +23,7 @@
-include("ssh.hrl").
-include("ssh_connect.hrl").
+-include_lib("public_key/include/public_key.hrl").
-export([start/0, start/1, stop/0, connect/3, connect/4, close/1, connection_info/2,
channel_info/3,
@@ -30,6 +31,9 @@
stop_listener/1, stop_listener/2, stop_daemon/1, stop_daemon/2,
shell/1, shell/2, shell/3]).
+-deprecated({sign_data, 2, next_major_release}).
+-deprecated({verify_data, 3, next_major_release}).
+
-export([sign_data/2, verify_data/3]).
%%--------------------------------------------------------------------
@@ -89,6 +93,9 @@ connect(Host, Port, Options, Timeout) ->
%% might return undefined as the connection manager
%% could allready have terminated, so we will not
%% match the Manager in this case
+ {_, not_connected, {error, econnrefused}} when DisableIpv6 == false ->
+ do_demonitor(MRef, Manager),
+ connect(Host, Port, [{ip_v6_disabled, true} | Options], Timeout);
{_, not_connected, {error, Reason}} ->
do_demonitor(MRef, Manager),
{error, Reason};
@@ -247,43 +254,6 @@ shell(Host, Port, Options) ->
Error
end.
-
-%%--------------------------------------------------------------------
-%% Function: sign_data(Data, Algorithm) -> binary() |
-%% {error, Reason}
-%%
-%% Data = binary()
-%% Algorithm = "ssh-rsa"
-%%
-%% Description: Use SSH key to sign data.
-%%--------------------------------------------------------------------
-sign_data(Data, Algorithm) when is_binary(Data) ->
- case ssh_file:private_identity_key(Algorithm,[]) of
- {ok, Key} when Algorithm == "ssh-rsa" ->
- ssh_rsa:sign(Key, Data);
- Error ->
- Error
- end.
-
-%%--------------------------------------------------------------------
-%% Function: verify_data(Data, Signature, Algorithm) -> ok |
-%% {error, Reason}
-%%
-%% Data = binary()
-%% Signature = binary()
-%% Algorithm = "ssh-rsa"
-%%
-%% Description: Use SSH signature to verify data.
-%%--------------------------------------------------------------------
-verify_data(Data, Signature, Algorithm) when is_binary(Data), is_binary(Signature) ->
- case ssh_file:public_identity_key(Algorithm, []) of
- {ok, Key} when Algorithm == "ssh-rsa" ->
- ssh_rsa:verify(Key, Data, Signature);
- Error ->
- Error
- end.
-
-
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
@@ -336,6 +306,10 @@ handle_options([{connect_timeout, _} = Opt | Rest], SockOpts, Opts) ->
handle_options(Rest, SockOpts, [Opt | Opts]);
handle_options([{user, _} = Opt | Rest], SockOpts, Opts) ->
handle_options(Rest, SockOpts, [Opt | Opts]);
+handle_options([{dsa_pass_phrase, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, SockOpts, [Opt | Opts]);
+handle_options([{rsa_pass_phrase, _} = Opt | Rest], SockOpts, Opts) ->
+ handle_options(Rest, SockOpts, [Opt | Opts]);
handle_options([{password, _} = Opt | Rest], SockOpts, Opts) ->
handle_options(Rest, SockOpts, [Opt | Opts]);
handle_options([{user_passwords, _} = Opt | Rest], SockOpts, Opts) ->
@@ -379,6 +353,50 @@ handle_options([Opt | Rest], SockOpts, Opts) ->
inetopt(true) ->
inet;
inetopt(false) ->
- inet6.
+ case gen_tcp:listen(0, [inet6, {ip, loopback}]) of
+ {ok, Dummyport} ->
+ gen_tcp:close(Dummyport),
+ inet6;
+ _ ->
+ inet
+ end.
+
+%%%
+%% Deprecated
+%%%
+
+%%--------------------------------------------------------------------
+%% Function: sign_data(Data, Algorithm) -> binary() |
+%% {error, Reason}
+%%
+%% Data = binary()
+%% Algorithm = "ssh-rsa"
+%%
+%% Description: Use SSH key to sign data.
+%%--------------------------------------------------------------------
+sign_data(Data, Algorithm) when is_binary(Data) ->
+ case ssh_file:user_key(Algorithm,[]) of
+ {ok, Key} when Algorithm == "ssh-rsa" ->
+ public_key:sign(Data, sha, Key);
+ Error ->
+ Error
+ end.
+%%--------------------------------------------------------------------
+%% Function: verify_data(Data, Signature, Algorithm) -> ok |
+%% {error, Reason}
+%%
+%% Data = binary()
+%% Signature = binary()
+%% Algorithm = "ssh-rsa"
+%%
+%% Description: Use SSH signature to verify data.
+%%--------------------------------------------------------------------
+verify_data(Data, Signature, Algorithm) when is_binary(Data), is_binary(Signature) ->
+ case ssh_file:user_key(Algorithm, []) of
+ {ok, #'RSAPrivateKey'{publicExponent = E, modulus = N}} when Algorithm == "ssh-rsa" ->
+ public_key:verify(Data, sha, Signature, #'RSAPublicKey'{publicExponent = E, modulus = N});
+ Error ->
+ Error
+ end.
diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl
index ac249b05e3..da5750b6c3 100644
--- a/lib/ssh/src/ssh.hrl
+++ b/lib/ssh/src/ssh.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -54,18 +54,6 @@
-define(string(X), << ?STRING(list_to_binary(X)) >> ).
-define(binary(X), << ?STRING(X) >>).
--ifdef(debug).
--define(dbg(Debug, Fmt, As),
- case (Debug) of
- true ->
- io:format([$# | (Fmt)], (As));
- _ ->
- ok
- end).
--else.
--define(dbg(Debug, Fmt, As), ok).
--endif.
-
-define(SSH_CIPHER_NONE, 0).
-define(SSH_CIPHER_3DES, 3).
-define(SSH_CIPHER_AUTHFILE, ?SSH_CIPHER_3DES).
@@ -138,7 +126,8 @@
userauth_quiet_mode, % boolean()
userauth_supported_methods , %
userauth_methods,
- userauth_preference
+ userauth_preference,
+ available_host_keys
}).
-record(alg,
diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl
index 9dbd95886e..62d684f4dc 100644
--- a/lib/ssh/src/ssh_auth.erl
+++ b/lib/ssh/src/ssh_auth.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -21,8 +21,9 @@
-module(ssh_auth).
--include("ssh.hrl").
+-include_lib("public_key/include/public_key.hrl").
+-include("ssh.hrl").
-include("ssh_auth.hrl").
-include("ssh_transport.hrl").
@@ -36,18 +37,21 @@
%%--------------------------------------------------------------------
%%% Internal application API
%%--------------------------------------------------------------------
-publickey_msg([Cb, #ssh{user = User,
+publickey_msg([Alg, #ssh{user = User,
session_id = SessionId,
service = Service,
opts = Opts} = Ssh]) ->
+
+ Hash = sha, %% Maybe option?!
ssh_bits:install_messages(userauth_pk_messages()),
- Alg = Cb:alg_name(),
- case ssh_file:private_identity_key(Alg, Opts) of
- {ok, PrivKey} ->
- PubKeyBlob = ssh_file:encode_public_key(PrivKey),
+ KeyCb = proplists:get_value(key_cb, Opts, ssh_file),
+
+ case KeyCb:user_key(Alg, Opts) of
+ {ok, Key} ->
+ PubKeyBlob = encode_public_key(Key),
SigData = build_sig_data(SessionId,
- User, Service, Alg, PubKeyBlob),
- Sig = Cb:sign(PrivKey, SigData),
+ User, Service, PubKeyBlob, Alg),
+ Sig = ssh_transport:sign(SigData, Hash, Key),
SigBlob = list_to_binary([?string(Alg), ?binary(Sig)]),
ssh_transport:ssh_packet(
#ssh_msg_userauth_request{user = User,
@@ -58,8 +62,8 @@ publickey_msg([Cb, #ssh{user = User,
?binary(PubKeyBlob),
?binary(SigBlob)]},
Ssh);
- _Error ->
- not_ok
+ _Error ->
+ not_ok
end.
password_msg([#ssh{opts = Opts, io_cb = IoCb,
@@ -67,29 +71,43 @@ password_msg([#ssh{opts = Opts, io_cb = IoCb,
ssh_bits:install_messages(userauth_passwd_messages()),
Password = case proplists:get_value(password, Opts) of
undefined ->
- IoCb:read_password("ssh password: ");
+ user_interaction(Opts, IoCb);
PW ->
PW
end,
- ssh_transport:ssh_packet(
- #ssh_msg_userauth_request{user = User,
- service = Service,
- method = "password",
- data =
- <<?BOOLEAN(?FALSE),
- ?STRING(list_to_binary(Password))>>},
- Ssh).
+ case Password of
+ not_ok ->
+ not_ok;
+ _ ->
+ ssh_transport:ssh_packet(
+ #ssh_msg_userauth_request{user = User,
+ service = Service,
+ method = "password",
+ data =
+ <<?BOOLEAN(?FALSE),
+ ?STRING(list_to_binary(Password))>>},
+ Ssh)
+ end.
+
+user_interaction(Opts, IoCb) ->
+ case proplists:get_value(allow_user_interaction, Opts, true) of
+ true ->
+ IoCb:read_password("ssh password: ");
+ false ->
+ not_ok
+ end.
+
%% See RFC 4256 for info on keyboard-interactive
keyboard_interactive_msg([#ssh{user = User,
- service = Service} = Ssh]) ->
+ service = Service} = Ssh]) ->
ssh_bits:install_messages(userauth_keyboard_interactive_messages()),
ssh_transport:ssh_packet(
#ssh_msg_userauth_request{user = User,
service = Service,
method = "keyboard-interactive",
data = << ?STRING(<<"">>),
- ?STRING(<<>>) >> },
+ ?STRING(<<>>) >> },
Ssh).
service_request_msg(Ssh) ->
@@ -103,12 +121,12 @@ init_userauth_request_msg(#ssh{opts = Opts} = Ssh) ->
service = "ssh-connection",
method = "none",
data = <<>>},
- CbFirst = proplists:get_value(public_key_alg, Opts,
- ?PREFERRED_PK_ALG),
- CbSecond = other_cb(CbFirst),
+ FirstAlg = algorithm(proplists:get_value(public_key_alg, Opts,
+ ?PREFERRED_PK_ALG)),
+ SecondAlg = other_alg(FirstAlg),
AllowUserInt = proplists:get_value(allow_user_interaction, Opts,
true),
- Prefs = method_preference(CbFirst, CbSecond, AllowUserInt),
+ Prefs = method_preference(FirstAlg, SecondAlg, AllowUserInt),
ssh_transport:ssh_packet(Msg, Ssh#ssh{user = User,
userauth_preference = Prefs,
userauth_methods = none,
@@ -192,12 +210,12 @@ handle_userauth_request(#ssh_msg_userauth_request{user = User,
?TRUE ->
case verify_sig(SessionId, User, "ssh-connection", Alg,
KeyBlob, SigWLen, Opts) of
- ok ->
+ true ->
{authorized, User,
ssh_transport:ssh_packet(
#ssh_msg_userauth_success{}, Ssh)};
- {error, Reason} ->
- {not_authorized, {User, {error, Reason}},
+ false ->
+ {not_authorized, {User, {error, "Invalid signature"}},
ssh_transport:ssh_packet(#ssh_msg_userauth_failure{
authentications="publickey,password",
partial_success = false}, Ssh)}
@@ -228,7 +246,6 @@ handle_userauth_info_request(
PromptInfos = decode_keyboard_interactive_prompts(NumPrompts,Data),
Resps = keyboard_interact_get_responses(IoCb, Opts,
Name, Instr, PromptInfos),
- %%?dbg(true, "keyboard_interactive_reply: resps=~n#~p ~n", [Resps]),
RespBin = list_to_binary(
lists:map(fun(S) -> <<?STRING(list_to_binary(S))>> end,
Resps)),
@@ -263,15 +280,15 @@ userauth_messages() ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-method_preference(Callback1, Callback2, true) ->
- [{"publickey", ?MODULE, publickey_msg, [Callback1]},
- {"publickey", ?MODULE, publickey_msg,[Callback2]},
+method_preference(Alg1, Alg2, true) ->
+ [{"publickey", ?MODULE, publickey_msg, [Alg1]},
+ {"publickey", ?MODULE, publickey_msg,[Alg2]},
{"password", ?MODULE, password_msg, []},
{"keyboard-interactive", ?MODULE, keyboard_interactive_msg, []}
];
-method_preference(Callback1, Callback2, false) ->
- [{"publickey", ?MODULE, publickey_msg, [Callback1]},
- {"publickey", ?MODULE, publickey_msg,[Callback2]},
+method_preference(Alg1, Alg2, false) ->
+ [{"publickey", ?MODULE, publickey_msg, [Alg1]},
+ {"publickey", ?MODULE, publickey_msg,[Alg2]},
{"password", ?MODULE, password_msg, []}
].
@@ -295,7 +312,6 @@ user_name(Opts) ->
end.
check_password(User, Password, Opts) ->
- %%?dbg(true, " ~p ~p ~p ~n", [User, Password, Opts]),
case proplists:get_value(pwdfun, Opts) of
undefined ->
Static = get_password_option(Opts, User),
@@ -312,25 +328,22 @@ get_password_option(Opts, User) ->
end.
verify_sig(SessionId, User, Service, Alg, KeyBlob, SigWLen, Opts) ->
- case ssh_file:lookup_user_key(User, Alg, Opts) of
- {ok, OurKey} ->
- {ok, Key} = ssh_file:decode_public_key_v2(KeyBlob, Alg),
- case OurKey of
- Key ->
- NewSig = build_sig_data(SessionId,
- User, Service, Alg, KeyBlob),
- <<?UINT32(AlgSigLen), AlgSig:AlgSigLen/binary>> = SigWLen,
- <<?UINT32(AlgLen), _Alg:AlgLen/binary,
- ?UINT32(SigLen), Sig:SigLen/binary>> = AlgSig,
- M = alg_to_module(Alg),
- M:verify(OurKey, NewSig, Sig);
- _ ->
- {error, key_unacceptable}
- end;
- Error -> Error
+ {ok, Key} = decode_public_key_v2(KeyBlob, Alg),
+ KeyCb = proplists:get_value(key_cb, Opts, ssh_file),
+
+ case KeyCb:is_auth_key(Key, User, Alg, Opts) of
+ true ->
+ PlainText = build_sig_data(SessionId, User,
+ Service, KeyBlob, Alg),
+ <<?UINT32(AlgSigLen), AlgSig:AlgSigLen/binary>> = SigWLen,
+ <<?UINT32(AlgLen), _Alg:AlgLen/binary,
+ ?UINT32(SigLen), Sig:SigLen/binary>> = AlgSig,
+ ssh_transport:verify(PlainText, sha, Sig, Key);
+ false ->
+ {error, key_unacceptable}
end.
-build_sig_data(SessionId, User, Service, Alg, KeyBlob) ->
+build_sig_data(SessionId, User, Service, KeyBlob, Alg) ->
Sig = [?binary(SessionId),
?SSH_MSG_USERAUTH_REQUEST,
?string(User),
@@ -341,6 +354,11 @@ build_sig_data(SessionId, User, Service, Alg, KeyBlob) ->
?binary(KeyBlob)],
list_to_binary(Sig).
+algorithm(ssh_rsa) ->
+ "ssh-rsa";
+algorithm(ssh_dsa) ->
+ "ssh-dss".
+
decode_keyboard_interactive_prompts(NumPrompts, Data) ->
Types = lists:append(lists:duplicate(NumPrompts, [string, boolean])),
pairwise_tuplify(ssh_bits:decode(Data, Types)).
@@ -412,12 +430,28 @@ userauth_pk_messages() ->
binary]} % key blob
].
-alg_to_module("ssh-dss") ->
- ssh_dsa;
-alg_to_module("ssh-rsa") ->
- ssh_rsa.
-
-other_cb(ssh_rsa) ->
- ssh_dsa;
-other_cb(ssh_dsa) ->
- ssh_rsa.
+other_alg("ssh-rsa") ->
+ "ssh-dss";
+other_alg("ssh-dss") ->
+ "ssh-rsa".
+decode_public_key_v2(K_S, "ssh-rsa") ->
+ case ssh_bits:decode(K_S,[string,mpint,mpint]) of
+ ["ssh-rsa", E, N] ->
+ {ok, #'RSAPublicKey'{publicExponent = E, modulus = N}};
+ _ ->
+ {error, bad_format}
+ end;
+decode_public_key_v2(K_S, "ssh-dss") ->
+ case ssh_bits:decode(K_S,[string,mpint,mpint,mpint,mpint]) of
+ ["ssh-dss",P,Q,G,Y] ->
+ {ok, {Y, #'Dss-Parms'{p = P, q = Q, g = G}}};
+ _ ->
+ {error, bad_format}
+ end;
+decode_public_key_v2(_, _) ->
+ {error, bad_format}.
+
+encode_public_key(#'RSAPrivateKey'{publicExponent = E, modulus = N}) ->
+ ssh_bits:encode(["ssh-rsa",E,N], [string,mpint,mpint]);
+encode_public_key(#'DSAPrivateKey'{p = P, q = Q, g = G, y = Y}) ->
+ ssh_bits:encode(["ssh-dss",P,Q,G,Y], [string,mpint,mpint,mpint,mpint]).
diff --git a/lib/ssh/src/ssh_bits.erl b/lib/ssh/src/ssh_bits.erl
index 3f0a06575c..5841f06d70 100644
--- a/lib/ssh/src/ssh_bits.erl
+++ b/lib/ssh/src/ssh_bits.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -105,16 +105,12 @@ bignum(X) ->
install_messages(Codes) ->
foreach(fun({Name, Code, Ts}) ->
- %% ?dbg(true, "install msg: ~s = ~w ~w~n",
-%% [Name,Code,Ts]),
put({msg_name,Code}, {Name,Ts}),
put({msg_code,Name}, {Code,Ts})
end, Codes).
uninstall_messages(Codes) ->
foreach(fun({Name, Code, _Ts}) ->
- %% ?dbg(true, "uninstall msg: ~s = ~w ~w~n",
-%% [Name,Code,_Ts]),
erase({msg_name,Code}),
erase({msg_code,Name})
end, Codes).
diff --git a/lib/ssh/src/ssh_connection.erl b/lib/ssh/src/ssh_connection.erl
index 7b9e9185bf..cb02d7b824 100644
--- a/lib/ssh/src/ssh_connection.erl
+++ b/lib/ssh/src/ssh_connection.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -722,8 +722,6 @@ handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
request_type = _Other,
want_reply = WantReply}, Connection,
ConnectionPid, _) ->
- ?dbg(true, "ssh_msg ssh_msg_channel_request: Other=~p\n",
- [_Other]),
if WantReply == true ->
FailMsg = channel_failure_msg(ChannelId),
{{replies, [{connection_reply, ConnectionPid, FailMsg}]},
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl
index 00b30e5434..9079089d5d 100644
--- a/lib/ssh/src/ssh_connection_handler.erl
+++ b/lib/ssh/src/ssh_connection_handler.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -637,16 +637,18 @@ init_ssh(client = Role, Vsn, Version, Options, Socket) ->
{ok, PeerAddr} = inet:peername(Socket),
PeerName = proplists:get_value(host, Options),
+ KeyCb = proplists:get_value(key_cb, Options, ssh_file),
#ssh{role = Role,
c_vsn = Vsn,
c_version = Version,
- key_cb = proplists:get_value(key_cb, Options, ssh_file),
+ key_cb = KeyCb,
io_cb = IOCb,
userauth_quiet_mode = proplists:get_value(quiet_mode, Options, false),
opts = Options,
userauth_supported_methods = AuthMethods,
- peer = {PeerName, PeerAddr}
+ peer = {PeerName, PeerAddr},
+ available_host_keys = supported_host_keys(Role, KeyCb, Options)
};
init_ssh(server = Role, Vsn, Version, Options, Socket) ->
@@ -654,17 +656,48 @@ init_ssh(server = Role, Vsn, Version, Options, Socket) ->
AuthMethods = proplists:get_value(auth_methods, Options,
?SUPPORTED_AUTH_METHODS),
{ok, PeerAddr} = inet:peername(Socket),
-
+ KeyCb = proplists:get_value(key_cb, Options, ssh_file),
+
#ssh{role = Role,
s_vsn = Vsn,
s_version = Version,
- key_cb = proplists:get_value(key_cb, Options, ssh_file),
+ key_cb = KeyCb,
io_cb = proplists:get_value(io_cb, Options, ssh_io),
opts = Options,
userauth_supported_methods = AuthMethods,
- peer = {undefined, PeerAddr}
+ peer = {undefined, PeerAddr},
+ available_host_keys = supported_host_keys(Role, KeyCb, Options)
}.
+supported_host_keys(client, _, _) ->
+ ["ssh-rsa", "ssh-dss"];
+supported_host_keys(server, KeyCb, Options) ->
+ lists:foldl(fun(Type, Acc) ->
+ case available_host_key(KeyCb, Type, Options) of
+ {error, _} ->
+ Acc;
+ Alg ->
+ [Alg | Acc]
+ end
+ end, [],
+ %% Prefered alg last so no need to reverse
+ ["ssh-dss", "ssh-rsa"]).
+
+available_host_key(KeyCb, "ssh-dss"= Alg, Opts) ->
+ case KeyCb:host_key('ssh-dss', Opts) of
+ {ok, _} ->
+ Alg;
+ Other ->
+ Other
+ end;
+available_host_key(KeyCb, "ssh-rsa" = Alg, Opts) ->
+ case KeyCb:host_key('ssh-rsa', Opts) of
+ {ok, _} ->
+ Alg;
+ Other ->
+ Other
+ end.
+
send_msg(Msg, #state{socket = Socket, transport_cb = Transport}) ->
Transport:send(Socket, Msg).
diff --git a/lib/ssh/src/ssh_connection_manager.erl b/lib/ssh/src/ssh_connection_manager.erl
index 9bfd5270da..f729276e65 100644
--- a/lib/ssh/src/ssh_connection_manager.erl
+++ b/lib/ssh/src/ssh_connection_manager.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. 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
@@ -144,7 +144,7 @@ adjust_window(ConnectionManager, Channel, Bytes) ->
cast(ConnectionManager, {adjust_window, Channel, Bytes}).
close(ConnectionManager, ChannelId) ->
- try call(ConnectionManager, {close, ChannelId}) of
+ try call(ConnectionManager, {close, ChannelId}) of
ok ->
ok;
{error, channel_closed} ->
@@ -604,6 +604,8 @@ call(Pid, Msg, Timeout) ->
exit:{timeout, _} ->
{error, timeout};
exit:{normal, _} ->
+ {error, channel_closed};
+ exit:{noproc,_} ->
{error, channel_closed}
end.
diff --git a/lib/ssh/src/ssh_dsa.erl b/lib/ssh/src/ssh_dsa.erl
deleted file mode 100644
index cb2632beac..0000000000
--- a/lib/ssh/src/ssh_dsa.erl
+++ /dev/null
@@ -1,95 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2011. 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%
-%%
-
-%%
-
-%%% Description: dsa public-key sign and verify
-
--module(ssh_dsa).
-
--export([verify/3]).
--export([sign/2]).
--export([alg_name/0]).
-
--include("ssh.hrl").
-
-%% start() ->
-%% crypto:start().
-
-%% sign_file(File, Opts) ->
-%% start(),
-%% {ok,Bin} = file:read_file(File),
-%% {ok,Key} = ssh_file:private_host_dsa_key(user, Opts),
-%% sign(Key, Bin).
-
-%% verify_file(File, Sig) ->
-%% start(),
-%% {ok,Bin} = file:read_file(File),
-%% {ok,Key} = ssh_file:public_host_key(user, dsa),
-%% verify(Key, Bin, Sig).
-
-sign(_Private=#ssh_key { private={P,Q,G,X} },Mb) ->
- K = ssh_bits:irandom(160) rem Q,
- R = ssh_math:ipow(G, K, P) rem Q,
- Ki = ssh_math:invert(K, Q),
- <<M:160/big-unsigned-integer>> = crypto:sha(Mb),
- S = (Ki * (M + X*R)) rem Q,
- <<R:160/big-unsigned-integer, S:160/big-unsigned-integer>>.
-
-
-%% the paramiko client sends a bad sig sometimes,
-%% instead of crashing, we nicely return error, the
-%% typcally manifests itself as Sb being 39 bytes
-%% instead of 40.
-
-verify(Public, Mb, Sb) ->
- case catch xverify(Public, Mb, Sb) of
- {'EXIT', _Reason} ->
- %store({Public, Mb, Sb, _Reason}),
- {error, inconsistent_key};
- ok ->
- %store({Public, Mb, Sb, ok})
- ok
- end.
-
-%% store(Term) ->
-%% {ok, Fd} = file:open("/tmp/dsa", [append]),
-%% io:format(Fd, "~p~n~n~n", [Term]),
-%% file:close(Fd).
-
-
-xverify(_Public=#ssh_key { public={P,Q,G,Y} },Mb,Sb) ->
- <<R0:160/big-unsigned-integer, S0:160/big-unsigned-integer>> = Sb,
- ?ssh_assert(R0 >= 0 andalso R0 < Q andalso
- S0 >= 0 andalso S0 < Q, out_of_range),
- W = ssh_math:invert(S0,Q),
- <<M0:160/big-unsigned-integer>> = crypto:sha(Mb),
- U1 = (M0*W) rem Q,
- U2 = (R0*W) rem Q,
- T1 = ssh_math:ipow(G,U1,P),
- T2 = ssh_math:ipow(Y,U2,P),
- V = ((T1*T2) rem P) rem Q,
- if V == R0 ->
- ok;
- true ->
- {error, inconsistent_key}
- end.
-
-alg_name() ->
- "ssh-dss".
diff --git a/lib/ssh/src/ssh_file.erl b/lib/ssh/src/ssh_file.erl
index 12180f56bb..d05fa8e09a 100644
--- a/lib/ssh/src/ssh_file.erl
+++ b/lib/ssh/src/ssh_file.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -23,80 +23,98 @@
-module(ssh_file).
--include("ssh.hrl").
--include("PKCS-1.hrl").
--include("DSS.hrl").
+-behaviour(ssh_key_api).
+-include_lib("public_key/include/public_key.hrl").
-include_lib("kernel/include/file.hrl").
--export([public_host_dsa_key/2,private_host_dsa_key/2,
- public_host_rsa_key/2,private_host_rsa_key/2,
- public_host_key/2,private_host_key/2,
- lookup_host_key/3, add_host_key/3, % del_host_key/2,
- lookup_user_key/3, ssh_dir/2, file_name/3]).
-
--export([private_identity_key/2,
- public_identity_key/2]).
-%% identity_keys/2]).
-
--export([encode_public_key/1, decode_public_key_v2/2]).
+-include("ssh.hrl").
--import(lists, [reverse/1, append/1]).
+-export([host_key/2,
+ user_key/2,
+ is_host_key/4,
+ add_host_key/3,
+ is_auth_key/4]).
--define(DBG_PATHS, true).
-define(PERM_700, 8#700).
-define(PERM_644, 8#644).
+
%% API
-public_host_dsa_key(Type, Opts) ->
- File = file_name(Type, "ssh_host_dsa_key.pub", Opts),
- read_public_key_v2(File, "ssh-dss").
-
-private_host_dsa_key(Type, Opts) ->
- File = file_name(Type, "ssh_host_dsa_key", Opts),
- read_private_key_v2(File, "ssh-dss").
-
-public_host_rsa_key(Type, Opts) ->
- File = file_name(Type, "ssh_host_rsa_key.pub", Opts),
- read_public_key_v2(File, "ssh-rsa").
-
-private_host_rsa_key(Type, Opts) ->
- File = file_name(Type, "ssh_host_rsa_key", Opts),
- read_private_key_v2(File, "ssh-rsa").
-
-public_host_key(Type, Opts) ->
- File = file_name(Type, "ssh_host_key", Opts),
- case read_private_key_v1(File,public) of
- {error, enoent} ->
- read_public_key_v1(File++".pub");
- Result ->
- Result
- end.
-
-private_host_key(Type, Opts) ->
- File = file_name(Type, "ssh_host_key", Opts),
- read_private_key_v1(File,private).
+%% Used by server
+host_key(Algorithm, Opts) ->
+ File = file_name(system, file_base_name(Algorithm), Opts),
+ %% We do not expect host keys to have pass phrases
+ %% so probably we could hardcod Password = ignore, but
+ %% we keep it as an undocumented option for now.
+ Password = proplists:get_value(identity_pass_phrase(Algorithm), Opts, ignore),
+ decode(File, Password).
+is_auth_key(Key, User, Alg, Opts) ->
+ case lookup_user_key(Key, User, Alg, Opts) of
+ {ok, Key} ->
+ true;
+ _ ->
+ false
+ end.
-%% in: "host" out: "host,1.2.3.4.
-add_ip(Host) ->
- case inet:getaddr(Host, inet) of
- {ok, Addr} ->
- case ssh_connection:encode_ip(Addr) of
- false -> Host;
- IPString -> Host ++ "," ++ IPString
- end;
- _ -> Host
- end.
-replace_localhost("localhost") ->
- {ok, Hostname} = inet:gethostname(),
- Hostname;
-replace_localhost(Host) ->
- Host.
+%% Used by client
+is_host_key(Key, PeerName, Algorithm, Opts) ->
+ case lookup_host_key(PeerName, Algorithm, Opts) of
+ {ok, Key} ->
+ true;
+ _ ->
+ false
+ end.
+
+user_key(Algorithm, Opts) ->
+ File = file_name(user, identity_key_filename(Algorithm), Opts),
+ Password = proplists:get_value(identity_pass_phrase(Algorithm), Opts, ignore),
+ decode(File, Password).
+
+
+%% Internal functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+file_base_name('ssh-rsa') ->
+ "ssh_host_rsa_key";
+file_base_name('ssh-dss') ->
+ "ssh_host_dsa_key";
+file_base_name(_) ->
+ "ssh_host_key".
+
+decode(File, Password) ->
+ try
+ {ok, decode_ssh_file(read_ssh_file(File), Password)}
+ catch
+ throw:Reason ->
+ {error, Reason};
+ error:Reason ->
+ {error, Reason}
+ end.
+
+read_ssh_file(File) ->
+ {ok, Bin} = file:read_file(File),
+ Bin.
+
+%% Public key
+decode_ssh_file(SshBin, public_key) ->
+ public_key:ssh_decode(SshBin, public_key);
+
+%% Private Key
+decode_ssh_file(Pem, Password) ->
+ case public_key:pem_decode(Pem) of
+ [{_, _, not_encrypted} = Entry] ->
+ public_key:pem_entry_decode(Entry);
+ [Entry] when Password =/= ignore ->
+ public_key:pem_entry_decode(Entry, Password);
+ _ ->
+ throw("No pass phrase provided for private key file")
+ end.
+
%% lookup_host_key
%% return {ok, Key(s)} or {error, not_found}
@@ -106,15 +124,6 @@ lookup_host_key(Host, Alg, Opts) ->
Host1 = replace_localhost(Host),
do_lookup_host_key(Host1, Alg, Opts).
-do_lookup_host_key(Host, Alg, Opts) ->
- case file:open(file_name(user, "known_hosts", Opts), [read]) of
- {ok, Fd} ->
- Res = lookup_host_key_fd(Fd, Host, Alg),
- file:close(Fd),
- Res;
- {error, enoent} -> {error, not_found};
- Error -> Error
- end.
add_host_key(Host, Key, Opts) ->
Host1 = add_ip(replace_localhost(Host)),
@@ -129,383 +138,16 @@ add_host_key(Host, Key, Opts) ->
Error
end.
-%% del_host_key(Host, Opts) ->
-%% Host1 = replace_localhost(Host),
-%% case file:open(file_name(user, "known_hosts", Opts),[write,read]) of
-%% {ok, Fd} ->
-%% Res = del_key_fd(Fd, Host1),
-%% file:close(Fd),
-%% Res;
-%% Error ->
-%% Error
-%% end.
-
-identity_key_filename("ssh-dss") -> "id_dsa";
-identity_key_filename("ssh-rsa") -> "id_rsa".
-
-private_identity_key(Alg, Opts) ->
- Path = file_name(user, identity_key_filename(Alg), Opts),
- read_private_key_v2(Path, Alg).
-
-public_identity_key(Alg, Opts) ->
- Path = file_name(user, identity_key_filename(Alg) ++ ".pub", Opts),
- read_public_key_v2(Path, Alg).
-
-
-read_public_key_v2(File, Type) ->
- case file:read_file(File) of
- {ok,Bin} ->
- List = binary_to_list(Bin),
- case lists:prefix(Type, List) of
- true ->
- List1 = lists:nthtail(length(Type), List),
- K_S = ssh_bits:b64_decode(List1),
- decode_public_key_v2(K_S, Type);
- false ->
- {error, bad_format}
- end;
- Error ->
- Error
- end.
-
-decode_public_key_v2(K_S, "ssh-rsa") ->
- case ssh_bits:decode(K_S,[string,mpint,mpint]) of
- ["ssh-rsa", E, N] ->
- {ok, #ssh_key { type = rsa,
- public = {N,E},
- comment=""}};
- _ ->
- {error, bad_format}
- end;
-decode_public_key_v2(K_S, "ssh-dss") ->
- case ssh_bits:decode(K_S,[string,mpint,mpint,mpint,mpint]) of
- ["ssh-dss",P,Q,G,Y] ->
- {ok,#ssh_key { type = dsa,
- public = {P,Q,G,Y}
- }};
- _A ->
- {error, bad_format}
- end;
-decode_public_key_v2(_, _) ->
- {error, bad_format}.
-
-
-read_public_key_v1(File) ->
- case file:read_file(File) of
- {ok,Bin} ->
- List = binary_to_list(Bin),
- case io_lib:fread("~d ~d ~d ~s", List) of
- {ok,[_Sz,E,N,Comment],_} ->
- {ok,#ssh_key { type = rsa,
- public ={N,E},
- comment = Comment }};
- _Error ->
- {error, bad_format}
- end;
- Error ->
- Error
- end.
-
-%% pem_type("ssh-dss") -> "DSA";
-%% pem_type("ssh-rsa") -> "RSA".
-
-read_private_key_v2(File, Type) ->
- case file:read_file(File) of
- {ok, PemBin} ->
- case catch (public_key:pem_decode(PemBin)) of
- [{_, Bin, not_encrypted}] ->
- decode_private_key_v2(Bin, Type);
- Error -> %% Note we do not handle password encrypted keys at the moment
- {error, Error}
- end;
- {error, Reason} ->
- {error, Reason}
- end.
-%% case file:read_file(File) of
-%% {ok,Bin} ->
-%% case read_pem(binary_to_list(Bin), pem_type(Type)) of
-%% {ok,Bin1} ->
-%% decode_private_key_v2(Bin1, Type);
-%% Error ->
-%% Error
-%% end;
-%% Error ->
-%% Error
-%% end.
-
-decode_private_key_v2(Private,"ssh-rsa") ->
- case 'PKCS-1':decode( 'RSAPrivateKey', Private) of
- {ok,RSA} -> %% FIXME Check for two-prime version
- {ok, #ssh_key { type = rsa,
- public = {RSA#'RSAPrivateKey'.modulus,
- RSA#'RSAPrivateKey'.publicExponent},
- private = {RSA#'RSAPrivateKey'.modulus,
- RSA#'RSAPrivateKey'.privateExponent}
- }};
- Error ->
- Error
- end;
-decode_private_key_v2(Private, "ssh-dss") ->
- case 'DSS':decode('DSAPrivateKey', Private) of
- {ok,DSA} -> %% FIXME Check for two-prime version
- {ok, #ssh_key { type = dsa,
- public = {DSA#'DSAPrivateKey'.p,
- DSA#'DSAPrivateKey'.q,
- DSA#'DSAPrivateKey'.g,
- DSA#'DSAPrivateKey'.y},
- private= {DSA#'DSAPrivateKey'.p,
- DSA#'DSAPrivateKey'.q,
- DSA#'DSAPrivateKey'.g,
- DSA#'DSAPrivateKey'.x}
- }};
- _ ->
- {error,bad_format}
- end.
-
-%% SSH1 private key format
-%% <<"SSH PRIVATE KEY FILE FORMATE 1.1\n" 0:8
-%% CipherNum:8, Reserved:32,
-%% NSz/uint32, N/bignum, E/bignum, Comment/string,
-%%
-%% [ R0:8 R1:8 R0:8 R1:8, D/bignum, IQMP/bignum, Q/bignum, P/bignum, Pad(8)]>>
-%%
-%% where [ ] is encrypted using des3 (ssh1 version) and
-%% a posssibly empty pass phrase using md5(passphase) as key
-%%
-
-read_private_key_v1(File, Type) ->
- case file:read_file(File) of
- {ok,<<"SSH PRIVATE KEY FILE FORMAT 1.1\n",0,
- CipherNum,_Resereved:32,Bin/binary>>} ->
- decode_private_key_v1(Bin, CipherNum,Type);
- {ok,_} ->
- {error, bad_format};
- Error ->
- Error
- end.
-
-decode_private_key_v1(Bin, CipherNum, Type) ->
- case ssh_bits:decode(Bin,0,[uint32, bignum, bignum, string]) of
- {Offset,[_NSz,N,E,Comment]} ->
- if Type == public ->
- {ok,#ssh_key { type=rsa,
- public={N,E},
- comment=Comment}};
- Type == private ->
- <<_:Offset/binary, Encrypted/binary>> = Bin,
- case ssh_bits:decode(decrypt1(Encrypted, CipherNum),0,
- [uint32, bignum, bignum,
- bignum, bignum,{pad,8}]) of
- {_,[_,D,IQMP,Q,P]} ->
- {ok,#ssh_key { type=rsa,
- public={N,E},
- private={D,IQMP,Q,P},
- comment=Comment}};
- _ ->
- {error,bad_format}
- end
- end;
- _ ->
- {error,bad_format}
- end.
-
-
-decrypt1(Bin, CipherNum) ->
- decrypt1(Bin, CipherNum,"").
-
-decrypt1(Bin, CipherNum, Phrase) ->
- if CipherNum == ?SSH_CIPHER_NONE; Phrase == "" ->
- Bin;
- CipherNum == ?SSH_CIPHER_3DES ->
- <<K1:8/binary, K2:8/binary>> = erlang:md5(Phrase),
- K3 = K1,
- IV = <<0,0,0,0,0,0,0,0>>,
- Bin1 = crypto:des_cbc_decrypt(K3,IV,Bin),
- Bin2 = crypto:des_cbc_encrypt(K2,IV,Bin1),
- crypto:des_cbc_decrypt(K1,IV,Bin2)
- end.
-
-%% encrypt1(Bin, CipherNum) ->
-%% encrypt1(Bin, CipherNum,"").
-
-%% encrypt1(Bin, CipherNum, Phrase) ->
-%% if CipherNum == ?SSH_CIPHER_NONE; Phrase == "" ->
-%% Bin;
-%% CipherNum == ?SSH_CIPHER_3DES ->
-%% <<K1:8/binary, K2:8/binary>> = erlang:md5(Phrase),
-%% K3 = K1,
-%% IV = <<0,0,0,0,0,0,0,0>>,
-%% Bin1 = crypto:des_cbc_encrypt(K1,IV,Bin),
-%% Bin2 = crypto:des_cbc_decrypt(K2,IV,Bin1),
-%% crypto:des_cbc_encrypt(K3,IV,Bin2)
-%% end.
-
-lookup_host_key_fd(Fd, Host, Alg) ->
- case io:get_line(Fd, '') of
- eof ->
- {error, not_found};
- Line ->
- case string:tokens(Line, " ") of
- [HostList, Alg, KeyData] ->
-%% io:format(" ~p lookup_host_key_fd: HostList ~p Alg ~p KeyData ~p\n",
-%% [Host, HostList, Alg, KeyData]),
- case lists:member(Host, string:tokens(HostList, ",")) of
- true ->
- decode_public_key_v2(ssh_bits:b64_decode(KeyData), Alg);
- false ->
- lookup_host_key_fd(Fd, Host, Alg)
- end;
- _ ->
- lookup_host_key_fd(Fd, Host, Alg)
- end
- end.
-
-
-
-%% del_key_fd(Fd, Host) ->
-%% del_key_fd(Fd, Host, 0, 0).
-
-%% del_key_fd(Fd, Host, ReadPos0, WritePos0) ->
-%% case io:get_line(Fd, '') of
-%% eof ->
-%% if ReadPos0 == WritePos0 ->
-%% ok;
-%% true ->
-%% file:truncate(Fd)
-%% end;
-%% Line ->
-%% {ok,ReadPos1} = file:position(Fd, cur),
-%% case string:tokens(Line, " ") of
-%% [HostList, _Type, _KeyData] ->
-%% case lists:member(Host, string:tokens(HostList, ",")) of
-%% true ->
-%% del_key_fd(Fd, Host, ReadPos1, WritePos0);
-%% false ->
-%% if ReadPos0 == WritePos0 ->
-%% del_key_fd(Fd, Host, ReadPos1, ReadPos1);
-%% true ->
-%% file:position(Fd, WritePos0),
-%% file:write(Fd, Line),
-%% {ok,WritePos1} = file:position(Fd,cur),
-%% del_key_fd(Fd, Host, ReadPos1, WritePos1)
-%% end
-%% end;
-%% _ ->
-%% if ReadPos0 == WritePos0 ->
-%% del_key_fd(Fd, Host, ReadPos1, ReadPos1);
-%% true ->
-%% file:position(Fd, WritePos0),
-%% file:write(Fd, Line),
-%% {ok,WritePos1} = file:position(Fd,cur),
-%% del_key_fd(Fd, Host, ReadPos1, WritePos1)
-%% end
-%% end
-%% end.
-
-
-add_key_fd(Fd, Host, Key) ->
- case Key#ssh_key.type of
- rsa ->
- {N,E} = Key#ssh_key.public,
- DK = ssh_bits:b64_encode(
- ssh_bits:encode(["ssh-rsa",E,N],
- [string,mpint,mpint])),
- file:write(Fd, [Host, " ssh-rsa ", DK, "\n"]);
- dsa ->
- {P,Q,G,Y} = Key#ssh_key.public,
- DK = ssh_bits:b64_encode(
- ssh_bits:encode(["ssh-dss",P,Q,G,Y],
- [string,mpint,mpint,mpint,mpint])),
- file:write(Fd, [Host, " ssh-dss ", DK, "\n"])
- end.
-
-
-%% read_pem(Cs, Type) ->
-%% case read_line(Cs) of
-%% {"-----BEGIN "++Rest,Cs1} ->
-%% case string:tokens(Rest, " ") of
-%% [Type, "PRIVATE", "KEY-----"] ->
-%% read_pem64(Cs1, [], Type);
-%% _ ->
-%% {error, bad_format}
-%% end;
-%% {"",Cs1} when Cs1 =/= "" ->
-%% read_pem(Cs1,Type);
-%% {_,""} ->
-%% {error, bad_format}
-%% end.
-
-%% read_pem64(Cs, Acc, Type) ->
-%% case read_line(Cs) of
-%% {"-----END "++Rest,_Cs1} ->
-%% case string:tokens(Rest, " ") of
-%% [Type, "PRIVATE", "KEY-----"] ->
-%% {ok,ssh_bits:b64_decode(append(reverse(Acc)))};
-%% Toks ->
-%% error_logger:format("ssh: TOKENS=~p\n", [Toks]),
-%% {error, bad_format}
-%% end;
-%% {B64, Cs1} when Cs1 =/= "" ->
-%% read_pem64(Cs1, [B64|Acc], Type);
-%% _What ->
-%% {error, bad_format}
-%% end.
-
-
-%% read_line(Cs) -> read_line(Cs,[]).
-%% read_line([$\r,$\n|T], Acc) -> {reverse(Acc), T};
-%% read_line([$\n|T], Acc) -> {reverse(Acc), T};
-%% read_line([C|T], Acc) -> read_line(T,[C|Acc]);
-%% read_line([], Acc) -> {reverse(Acc),[]}.
-
-lookup_user_key(User, Alg, Opts) ->
+lookup_user_key(Key, User, Alg, Opts) ->
SshDir = ssh_dir({remoteuser,User}, Opts),
- case lookup_user_key_f(User, SshDir, Alg, "authorized_keys", Opts) of
+ case lookup_user_key_f(Key, User, SshDir, Alg, "authorized_keys", Opts) of
{ok, Key} ->
{ok, Key};
_ ->
- lookup_user_key_f(User, SshDir, Alg, "authorized_keys2", Opts)
- end.
-
-lookup_user_key_f(_User, [], _Alg, _F, _Opts) ->
- {error, nouserdir};
-lookup_user_key_f(_User, nouserdir, _Alg, _F, _Opts) ->
- {error, nouserdir};
-lookup_user_key_f(_User, Dir, Alg, F, _Opts) ->
- FileName = filename:join(Dir, F),
- case file:open(FileName, [read]) of
- {ok, Fd} ->
- Res = lookup_user_key_fd(Fd, Alg),
- file:close(Fd),
- Res;
- {error, Reason} ->
- {error, {{openerr, Reason}, {file, FileName}}}
- end.
-
-lookup_user_key_fd(Fd, Alg) ->
- case io:get_line(Fd, '') of
- eof ->
- {error, not_found};
- Line ->
- case string:tokens(Line, " ") of
- [Alg, KeyData, _] ->
- %% io:format("lookup_user_key_fd: HostList ~p Alg ~p KeyData ~p\n",
- %% [HostList, Alg, KeyData]),
- decode_public_key_v2(ssh_bits:b64_decode(KeyData), Alg);
- _Other ->
- %%?dbg(false, "key_fd Other: ~w ~w\n", [Alg, _Other]),
- lookup_user_key_fd(Fd, Alg)
- end
+ lookup_user_key_f(Key, User, SshDir, Alg, "authorized_keys2", Opts)
end.
-encode_public_key(#ssh_key{type = rsa, public = {N, E}}) ->
- ssh_bits:encode(["ssh-rsa",E,N],
- [string,mpint,mpint]);
-encode_public_key(#ssh_key{type = dsa, public = {P,Q,G,Y}}) ->
- ssh_bits:encode(["ssh-dss",P,Q,G,Y],
- [string,mpint,mpint,mpint,mpint]).
-
%%
%% Utils
%%
@@ -537,11 +179,130 @@ ssh_dir(user, Opts) ->
ssh_dir(system, Opts) ->
proplists:get_value(system_dir, Opts, "/etc/ssh").
+
file_name(Type, Name, Opts) ->
FN = filename:join(ssh_dir(Type, Opts), Name),
- %%?dbg(?DBG_PATHS, "file_name: ~p\n", [FN]),
FN.
+
+
+%% in: "host" out: "host,1.2.3.4.
+add_ip(Host) ->
+ case inet:getaddr(Host, inet) of
+ {ok, Addr} ->
+ case ssh_connection:encode_ip(Addr) of
+ false -> Host;
+ IPString -> Host ++ "," ++ IPString
+ end;
+ _ -> Host
+ end.
+
+replace_localhost("localhost") ->
+ {ok, Hostname} = inet:gethostname(),
+ Hostname;
+replace_localhost(Host) ->
+ Host.
+
+do_lookup_host_key(Host, Alg, Opts) ->
+ case file:open(file_name(user, "known_hosts", Opts), [read, binary]) of
+ {ok, Fd} ->
+ Res = lookup_host_key_fd(Fd, Host, Alg),
+ file:close(Fd),
+ {ok, Res};
+ {error, enoent} -> {error, not_found};
+ Error -> Error
+ end.
+
+identity_key_filename("ssh-dss") ->
+ "id_dsa";
+identity_key_filename("ssh-rsa") ->
+ "id_rsa".
+
+identity_pass_phrase("ssh-dss") ->
+ dsa_pass_phrase;
+identity_pass_phrase('ssh-dss') ->
+ dsa_pass_phrase;
+identity_pass_phrase('ssh-rsa') ->
+ rsa_pass_phrase;
+identity_pass_phrase("ssh-rsa") ->
+ rsa_pass_phrase.
+
+lookup_host_key_fd(Fd, Host, KeyType) ->
+ case io:get_line(Fd, '') of
+ eof ->
+ {error, not_found};
+ Line ->
+ case public_key:ssh_decode(Line, known_hosts) of
+ [{Key, Attributes}] ->
+ handle_host(Fd, Host, proplists:get_value(hostnames, Attributes), Key, KeyType);
+ [] ->
+ lookup_host_key_fd(Fd, Host, KeyType)
+ end
+ end.
+
+handle_host(Fd, Host, HostList, Key, KeyType) ->
+ Host1 = host_name(Host),
+ case lists:member(Host1, HostList) and key_match(Key, KeyType) of
+ true ->
+ Key;
+ false ->
+ lookup_host_key_fd(Fd, Host, KeyType)
+ end.
+
+host_name(Atom) when is_atom(Atom) ->
+ atom_to_list(Atom);
+host_name(List) ->
+ List.
+
+key_match(#'RSAPublicKey'{}, "ssh-rsa") ->
+ true;
+key_match({_, #'Dss-Parms'{}}, "ssh-dss") ->
+ true;
+key_match(_, _) ->
+ false.
+
+add_key_fd(Fd, Host,Key) ->
+ SshBin = public_key:ssh_encode([{Key, [{hostnames, [Host]}]}], known_hosts),
+ file:write(Fd, SshBin).
+
+lookup_user_key_f(_, _User, [], _Alg, _F, _Opts) ->
+ {error, nouserdir};
+lookup_user_key_f(_, _User, nouserdir, _Alg, _F, _Opts) ->
+ {error, nouserdir};
+lookup_user_key_f(Key, _User, Dir, _Alg, F, _Opts) ->
+ FileName = filename:join(Dir, F),
+ case file:open(FileName, [read, binary]) of
+ {ok, Fd} ->
+ Res = lookup_user_key_fd(Fd, Key),
+ file:close(Fd),
+ Res;
+ {error, Reason} ->
+ {error, {{openerr, Reason}, {file, FileName}}}
+ end.
+
+lookup_user_key_fd(Fd, Key) ->
+ case io:get_line(Fd, '') of
+ eof ->
+ {error, not_found};
+ Line ->
+ case public_key:ssh_decode(Line, auth_keys) of
+ [{AuthKey, _}] ->
+ case is_auth_key(Key, AuthKey) of
+ true ->
+ {ok, Key};
+ false ->
+ lookup_user_key_fd(Fd, Key)
+ end;
+ [] ->
+ lookup_user_key_fd(Fd, Key)
+ end
+ end.
+
+is_auth_key(Key, Key) ->
+ true;
+is_auth_key(_,_) ->
+ false.
+
default_user_dir()->
{ok,[[Home|_]]} = init:get_argument(home),
UserDir = filename:join(Home, ".ssh"),
diff --git a/lib/ssh/src/ssh_key_api.erl b/lib/ssh/src/ssh_key_api.erl
new file mode 100644
index 0000000000..8085c12e21
--- /dev/null
+++ b/lib/ssh/src/ssh_key_api.erl
@@ -0,0 +1,45 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(ssh_key_api).
+
+-include_lib("public_key/include/public_key.hrl").
+-include("ssh.hrl").
+
+-type ssh_algorithm() :: string().
+-type file_error() :: file:posix() | badarg | system_limit | terminated.
+
+-callback host_key(Algorithm :: ssh_algorithm(), Options :: list()) ->
+ {ok, [{public_key(), Attributes::list()}]} | public_key()
+ | {error, string()}.
+
+-callback user_key(Algorithm :: ssh_algorithm(), Options :: list()) ->
+ {ok, [{public_key(), Attributes::list()}]} | public_key()
+ | {error, string()}.
+
+-callback is_host_key(Key :: public_key(), PeerName :: string(),
+ Algorithm :: ssh_algorithm(), Options :: list()) ->
+ boolean().
+
+-callback add_host_key(Host :: string(), Key :: public_key(), Options :: list()) ->
+ ok | {error, file_error()}.
+
+-callback is_auth_key(Key :: public_key(), User :: string(),
+ Algorithm :: ssh_algorithm(), Options :: list()) ->
+ boolean().
diff --git a/lib/ssh/src/ssh_rsa.erl b/lib/ssh/src/ssh_rsa.erl
deleted file mode 100644
index 77c411b09f..0000000000
--- a/lib/ssh/src/ssh_rsa.erl
+++ /dev/null
@@ -1,298 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2011. 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%
-%%
-
-%%
-
-%%% Description: rsa public-key sign and verify
-
--module(ssh_rsa).
-
--export([verify/3, sign/2]).
--export([alg_name/0]).
-
--include("ssh.hrl").
--include("PKCS-1.hrl").
-
-
--define(MGF(Seed,Len), mgf1((Seed),(Len))).
--define(HASH(X), crypto:sha((X))).
--define(HLen, 20).
-
-%% start() ->
-%% crypto:start().
-
-%% sign_file(File) ->
-%% start(),
-%% {ok,Bin} = file:read_file(File),
-%% {ok,Key} = ssh_file:private_host_rsa_key(user),
-%% sign(Key, Bin).
-
-%% verify_file(File, Sig) ->
-%% start(),
-%% {ok,Bin} = file:read_file(File),
-%% {ok,Key} = ssh_file:public_host_rsa_key(user),
-%% verify(Key, Bin, Sig).
-
-sign(Private,Mb) ->
- rsassa_pkcs1_v1_5_sign(Private,Mb).
-
-verify(Public,Mb,Sb) ->
- rsassa_pkcs1_v1_5_verify(Public,Mb,Sb).
-
-
-
-%% Integer to octet string
-i2osp(X, XLen) ->
- ssh_bits:i2bin(X, XLen).
-
-%% Octet string to Integer
-os2ip(X) ->
- ssh_bits:bin2i(X).
-
-%% decrypt1, M = message representative
-%% rsaep(#ssh_key { public={N,E}}, M) ->
-%% ?ssh_assert(M >= 0 andalso M =< N-1, out_of_range),
-%% ssh_math:ipow(M, E, N).
-
-%% encrypt1, C = cipher representative
-%% rsadp(#ssh_key { public={N,_}, private={_,D}}, C) ->
-%% ?ssh_assert(C >= 0 andalso C =< N-1, out_of_range),
-%% ssh_math:ipow(C, D, N).
-
-%% sign1, M = message representative
-rsasp1(#ssh_key { public={N,_}, private={_,D}}, M) ->
- ?ssh_assert((M >= 0 andalso M =< N-1), out_of_range),
- ssh_math:ipow(M, D, N).
-
-%% verify1, S =signature representative
-rsavp1(#ssh_key { public={N,E}}, S) ->
- ?ssh_assert(S >= 0 andalso S =< N-1, out_of_range),
- ssh_math:ipow(S, E, N).
-
-
-%% M messaage
-%% rsaes_oaep_encrypt(Public, M) ->
-%% rsaes_oaep_encrypt(Public, M, <<>>).
-
-%% rsaes_oaep_encrypt(Public=#ssh_key { public={N,_E}}, M, L) ->
-%% ?ssh_assert(size(L) =< 16#ffffffffffffffff, label_to_long),
-%% K = (ssh_bits:isize(N)+7) div 8,
-%% MLen = size(M),
-%% %% LLen = size(L),
-%% ?ssh_assert(MLen =< K - 2*?HLen - 2, message_to_long),
-%% LHash = ?HASH(L),
-%% PS = ssh_bits:fill_bits(K - MLen - 2*?HLen - 2, 0),
-%% DB = <<LHash/binary, PS/binary, 16#01, M/binary>>,
-%% Seed = ssh_bits:random(?HLen),
-%% DbMask = ?MGF(Seed, K - ?HLen - 1),
-%% MaskedDB = ssh_bits:xor_bits(DB, DbMask),
-%% SeedMask = ?MGF(MaskedDB, ?HLen),
-%% MaskedSeed = ssh_bits:xor_bits(Seed, SeedMask),
-%% EM = <<16#00, MaskedSeed/binary, MaskedDB/binary>>,
-%% Mc = os2ip(EM),
-%% C = rsaep(Public, Mc),
-%% i2osp(C, K).
-
-%% rsaes_oaep_decrypt(Key, C) ->
-%% rsaes_oaep_decrypt(Key, C, <<>>).
-
-%% rsaes_oaep_decrypt(Private=#ssh_key { public={N,_},private={_,_}},Cb,L) ->
-%% ?ssh_assert(size(L) =< 16#ffffffffffffffff, label_to_long),
-%% K = (ssh_bits:isize(N)+7) div 8,
-%% ?ssh_assert(K == 2*?HLen + 2, decryption_error),
-%% C = os2ip(Cb),
-%% M = rsadp(Private, C),
-%% EM = i2osp(M, K),
-%% LHash = ?HASH(L),
-%% MLen = K - ?HLen -1,
-%% case EM of
-%% <<16#00, MaskedSeed:?HLen/binary, MaskedDB:MLen>> ->
-%% SeedMask = ?MGF(MaskedDB, ?HLen),
-%% Seed = ssh_bits:xor_bits(MaskedSeed, SeedMask),
-%% DbMask = ?MGF(Seed, K - ?HLen - 1),
-%% DB = ssh_bits:xor_bits(MaskedDB, DbMask),
-%% PSLen = K - MLen - 2*?HLen - 2,
-%% case DB of
-%% <<LHash:?HLen, _PS:PSLen/binary, 16#01, M/binary>> ->
-%% M;
-%% _ ->
-%% exit(decryption_error)
-%% end;
-%% _ ->
-%% exit(decryption_error)
-%% end.
-
-
-%% rsaes_pkcs1_v1_5_encrypt(Public=#ssh_key { public={N,_}}, M) ->
-%% K = (ssh_bits:isize(N)+7) div 8,
-%% MLen = size(M),
-%% ?ssh_assert(MLen =< K - 11, message_to_long),
-%% PS = ssh_bits:random(K - MLen - 3),
-%% EM = <<16#00,16#02,PS/binary,16#00,M/binary>>,
-%% Mc = os2ip(EM),
-%% C = rsaep(Public, Mc),
-%% i2osp(C, K).
-
-
-%% rsaes_pkcs1_v1_5_decrypt(Private=#ssh_key { public={N,_},private={_,_}},
-%% Cb) ->
-%% K = (ssh_bits:isize(N)+7) div 8,
-%% CLen = size(Cb),
-%% ?ssh_assert(CLen == K andalso K >= 11, decryption_error),
-%% C = os2ip(Cb),
-%% M = rsadp(Private, C),
-%% EM = i2osp(M, K),
-%% PSLen = K - CLen - 3,
-%% case EM of
-%% <<16#00, 16#02, _PS:PSLen/binary, 16#00, M>> ->
-%% M;
-%% _ ->
-%% exit(decryption_error)
-%% end.
-
-%% rsassa_pss_sign(Private=#ssh_key { public={N,_},private={_,_}},Mb) ->
-%% ModBits = ssh_bits:isize(N),
-%% K = (ModBits+7) div 8,
-%% EM = emsa_pss_encode(Mb, ModBits - 1),
-%% M = os2ip(EM),
-%% S = rsasp1(Private, M),
-%% i2osp(S, K).
-
-%% rsassa_pss_verify(Public=#ssh_key { public={N,_E}},Mb,Sb) ->
-%% ModBits = ssh_bits:isize(N),
-%% K = (ModBits+7) div 8,
-%% ?ssh_assert(size(Sb) == K, invalid_signature),
-%% S = os2ip(Sb),
-%% M = rsavp1(Public,S),
-%% EMLen = (ModBits-1+7) div 8,
-%% EM = i2osp(M, EMLen),
-%% emsa_pss_verify(Mb, EM, ModBits-1).
-
-
-rsassa_pkcs1_v1_5_sign(Private=#ssh_key { public={N,_},private={_,_D}},Mb) ->
- K = (ssh_bits:isize(N)+7) div 8,
- EM = emsa_pkcs1_v1_5_encode(Mb, K),
- M = os2ip(EM),
- S = rsasp1(Private, M),
- i2osp(S, K).
-
-rsassa_pkcs1_v1_5_verify(Public=#ssh_key { public={N,_E}}, Mb, Sb) ->
- K = (ssh_bits:isize(N)+7) div 8,
- ?ssh_assert(size(Sb) == K, invalid_signature),
- S = os2ip(Sb),
- M = rsavp1(Public, S),
- EM = i2osp(M, K),
- %?dbg(true, "verify K=~p S=~w ~n#M=~w~n#EM=~w~n", [K, S, M, EM]),
- case emsa_pkcs1_v1_5_encode(Mb, K) of
- EM -> ok;
- _S ->
- {error, invalid_signature}
- end.
-
-
-emsa_pkcs1_v1_5_encode(M, EMLen) ->
- H = ?HASH(M),
- %% Must use speical xxNull types here!
- Alg = #'AlgorithmNull' { algorithm = ?'id-sha1',
- parameters = <<>> },
- {ok,TCode} = 'PKCS-1':encode('DigestInfoNull',
- #'DigestInfoNull'{ digestAlgorithm = Alg,
- digest = H }),
- T = list_to_binary(TCode),
- TLen = size(T),
- ?ssh_assert(EMLen >= TLen + 11, message_to_short),
- PS = ssh_bits:fill_bits(EMLen - TLen - 3, 16#ff),
- <<16#00, 16#01, PS/binary, 16#00, T/binary>>.
-
-
-%% emsa_pss_encode(M, EMBits) ->
-%% emsa_pss_encode(M, EMBits, 0).
-
-%% emsa_pss_encode(M, EMBits, SLen) ->
-%% ?ssh_assert(size(M) =< 16#ffffffffffffffff, message_to_long),
-%% EMLen = (EMBits + 7) div 8,
-%% MHash = ?HASH(M),
-%% ?ssh_assert(EMLen >= ?HLen + SLen + 2, encoding_error),
-%% Salt = ssh_bits:random(SLen),
-%% M1 = [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
-%% MHash, Salt],
-%% H = ?HASH(M1),
-%% PS = ssh_bits:fill_bits(EMLen-SLen-?HLen-2, 0),
-%% DB = <<PS/binary, 16#01, Salt/binary>>,
-%% DbMask = ?MGF(H, EMLen - ?HLen -1),
-%% MaskedDB = ssh_bits:xor_bits(DB, DbMask),
-%% ZLen = 8*EMLen - EMBits,
-%% NZLen = (8 - (ZLen rem 8)) rem 8,
-%% <<_:ZLen, NZ:NZLen, MaskedDB1/binary>> = MaskedDB,
-%% MaskedDB2 = <<0:ZLen, NZ:NZLen, MaskedDB1/binary>>,
-%% <<MaskedDB2/binary, H/binary, 16#BC>>.
-
-
-%% emsa_pss_verify(M, EM, EMBits) ->
-%% emsa_pss_verify(M, EM, EMBits, 0).
-
-%% emsa_pss_verify(M, EM, EMBits, SLen) ->
-%% ?ssh_assert(size(M) =< 16#ffffffffffffffff, message_to_long),
-%% EMLen = (EMBits + 7) div 8,
-%% MHash = ?HASH(M),
-%% ?ssh_assert(EMLen >= ?HLen + SLen + 2, inconsistent),
-%% MaskLen = (EMLen - ?HLen - 1)-1,
-%% ZLen = 8*EMLen - EMBits,
-%% NZLen = (8 - (ZLen rem 8)) rem 8,
-%% case EM of
-%% <<0:ZLen,Nz:NZLen,MaskedDB1:MaskLen/binary, H:?HLen/binary, 16#BC>> ->
-%% MaskedDB = <<0:ZLen,Nz:NZLen,MaskedDB1/binary>>,
-%% DbMask = ?MGF(H, EMLen - ?HLen - 1),
-%% DB = ssh_bits:xor_bits(MaskedDB, DbMask),
-%% PSLen1 = (EMLen - SLen - ?HLen - 2) - 1,
-%% PS = ssh_bits:fill_bits(PSLen1, 0),
-%% case DB of
-%% <<_:ZLen,0:NZLen,PS:PSLen1/binary,16#01,Salt:SLen/binary>> ->
-%% M1 = [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
-%% MHash, Salt],
-%% case ?HASH(M1) of
-%% H -> ok;
-%% _ -> exit(inconsistent)
-%% end;
-%% _ ->
-%% exit(inconsistent)
-%% end;
-%% _ ->
-%% exit(inconsistent)
-%% end.
-
-
-
-%% Mask generating function MGF1
-%% mgf1(MGFSeed, MaskLen) ->
-%% T = mgf1_loop(0, ((MaskLen + ?HLen -1) div ?HLen) - 1, MGFSeed, ""),
-%% <<R:MaskLen/binary, _/binary>> = T,
-%% R.
-
-%% mgf1_loop(Counter, N, _, T) when Counter > N ->
-%% list_to_binary(T);
-%% mgf1_loop(Counter, N, MGFSeed, T) ->
-%% C = i2osp(Counter, 4),
-%% mgf1_loop(Counter+1, N, MGFSeed, [T, ?HASH([MGFSeed, C])]).
-
-
-
-
-alg_name() ->
- "ssh-rsa".
diff --git a/lib/ssh/src/ssh_sftpd.erl b/lib/ssh/src/ssh_sftpd.erl
index da91817fd7..8cc414f83a 100644
--- a/lib/ssh/src/ssh_sftpd.erl
+++ b/lib/ssh/src/ssh_sftpd.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -231,8 +231,6 @@ handle_op(?SSH_FXP_REALPATH, ReqId,
case Res of
{ok, AbsPath} ->
NewAbsPath = chroot_filename(AbsPath, State),
- ?dbg(true, "handle_op ?SSH_FXP_REALPATH: RelPath=~p AbsPath=~p\n",
- [RelPath, NewAbsPath]),
XF = State#state.xf,
Attr = #ssh_xfer_attr{type=directory},
ssh_xfer:xf_send_name(XF, ReqId, NewAbsPath, Attr),
@@ -463,7 +461,6 @@ get_handle(Handles, BinHandle) ->
read_dir(State0 = #state{file_handler = FileMod, max_files = MaxLength, file_state = FS0},
XF, ReqId, Handle, RelPath, {cache, Files}) ->
AbsPath = relate_file_name(RelPath, State0),
- ?dbg(true, "read_dir: AbsPath=~p\n", [AbsPath]),
if
length(Files) > MaxLength ->
{ToSend, NewCache} = lists:split(MaxLength, Files),
@@ -484,7 +481,6 @@ read_dir(State0 = #state{file_handler = FileMod, max_files = MaxLength, file_sta
read_dir(State0 = #state{file_handler = FileMod, max_files = MaxLength, file_state = FS0},
XF, ReqId, Handle, RelPath, _Status) ->
AbsPath = relate_file_name(RelPath, State0),
- ?dbg(true, "read_dir: AbsPath=~p\n", [AbsPath]),
{Res, FS1} = FileMod:list_dir(AbsPath, FS0),
case Res of
{ok, Files} when MaxLength == 0 orelse MaxLength > length(Files) ->
@@ -516,7 +512,6 @@ get_attrs(_RelPath, [], _FileMod, FS, Acc) ->
{lists:reverse(Acc), FS};
get_attrs(RelPath, [F | Rest], FileMod, FS0, Acc) ->
Path = filename:absname(F, RelPath),
- ?dbg(true, "get_attrs fun: F=~p\n", [F]),
case FileMod:read_link_info(Path, FS0) of
{{ok, Info}, FS1} ->
Attrs = ssh_sftp:info_to_attr(Info),
@@ -560,7 +555,6 @@ stat(ReqId, RelPath, State0=#state{file_handler=FileMod,
file_state=FS0}, F) ->
AbsPath = relate_file_name(RelPath, State0),
XF = State0#state.xf,
- ?dbg(false, "stat: AbsPath=~p\n", [AbsPath]),
{Res, FS1} = FileMod:F(AbsPath, FS0),
State1 = State0#state{file_state = FS1},
case Res of
@@ -605,6 +599,8 @@ decode_4_access_flag(add_subdirectory) ->
[read];
decode_4_access_flag(append_data) ->
[append];
+decode_4_access_flag(write_attributes) ->
+ [write];
decode_4_access_flag(_) ->
[read].
@@ -619,8 +615,7 @@ open(Vsn, ReqId, Data, State) when Vsn =< 3 ->
<<?UINT32(BLen), BPath:BLen/binary, ?UINT32(PFlags),
_Attrs/binary>> = Data,
Path = binary_to_list(BPath),
- Flags = ssh_xfer:decode_open_flags(Vsn, PFlags) -- [creat, excl, trunc],
- ?dbg(true, "open: Flags=~p\n", [Flags]),
+ Flags = ssh_xfer:decode_open_flags(Vsn, PFlags),
do_open(ReqId, State, Path, Flags);
open(Vsn, ReqId, Data, State) when Vsn >= 4 ->
<<?UINT32(BLen), BPath:BLen/binary, ?UINT32(Access),
@@ -628,7 +623,6 @@ open(Vsn, ReqId, Data, State) when Vsn >= 4 ->
Path = binary_to_list(BPath),
FlagBits = ssh_xfer:decode_open_flags(Vsn, PFlags),
AcessBits = ssh_xfer:decode_ace_mask(Access),
- ?dbg(true, "open: Fl=~p\n", [FlagBits]),
%% TODO: This is to make sure the Access flags are not ignored
%% but this should be thought through better. This solution should
%% be considered a hack in order to buy some time. At least
@@ -638,15 +632,12 @@ open(Vsn, ReqId, Data, State) when Vsn >= 4 ->
AcessFlags = decode_4_acess(AcessBits),
Flags = lists:append(lists:umerge(
[[decode_4_flags(FlagBits)] | AcessFlags])),
-
- ?dbg(true, "open: Flags=~p\n", [Flags]),
-
do_open(ReqId, State, Path, Flags).
do_open(ReqId, State0, Path, Flags) ->
#state{file_handler = FileMod, file_state = FS0, root = Root} = State0,
XF = State0#state.xf,
- F = [raw, binary | Flags],
+ F = [binary | Flags],
%% case FileMod:is_dir(Path) of %% This is version 6 we still have 5
%% true ->
%% ssh_xfer:xf_send_status(State#state.xf, ReqId,
@@ -895,14 +886,11 @@ set_stat(Attr, Path,
State0 = #state{file_handler=FileMod, file_state=FS0}) ->
{DecodedAttr, _Rest} =
ssh_xfer:decode_ATTR((State0#state.xf)#ssh_xfer.vsn, Attr),
- ?dbg(true, "set_stat DecodedAttr=~p\n", [DecodedAttr]),
Info = ssh_sftp:attr_to_info(DecodedAttr),
{Res1, FS1} = FileMod:read_link_info(Path, FS0),
case Res1 of
{ok, OldInfo} ->
NewInfo = set_file_info(Info, OldInfo),
- ?dbg(true, "set_stat Path=~p\nInfo=~p\nOldInfo=~p\nNewInfo=~p\n",
- [Path, Info, OldInfo, NewInfo]),
{Res2, FS2} = FileMod:write_file_info(Path, NewInfo, FS1),
State1 = State0#state{file_state = FS2},
{Res2, State1};
diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl
index de3e29e2f1..6140c87f6e 100644
--- a/lib/ssh/src/ssh_transport.erl
+++ b/lib/ssh/src/ssh_transport.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -23,10 +23,11 @@
-module(ssh_transport).
--include("ssh_transport.hrl").
+-include_lib("public_key/include/public_key.hrl").
+-include_lib("kernel/include/inet.hrl").
+-include("ssh_transport.hrl").
-include("ssh.hrl").
--include_lib("kernel/include/inet.hrl").
-export([connect/5, accept/4]).
-export([versions/2, hello_version_msg/1]).
@@ -38,17 +39,8 @@
handle_kex_dh_gex_group/2, handle_kex_dh_gex_reply/2,
handle_new_keys/2, handle_kex_dh_gex_request/2,
handle_kexdh_reply/2,
- unpack/3, decompress/2, ssh_packet/2, pack/2, msg_data/1]).
-
-%% debug flagso
--define(DBG_ALG, true).
--define(DBG_KEX, true).
--define(DBG_CRYPTO, false).
--define(DBG_PACKET, false).
--define(DBG_MESSAGE, true).
--define(DBG_BIN_MESSAGE, true).
--define(DBG_MAC, false).
--define(DBG_ZLIB, true).
+ unpack/3, decompress/2, ssh_packet/2, pack/2, msg_data/1,
+ sign/3, verify/4]).
versions(client, Options)->
Vsn = proplists:get_value(vsn, Options, ?DEFAULT_CLIENT_VERSION),
@@ -212,24 +204,24 @@ key_exchange_init_msg(Ssh0) ->
{SshPacket, Ssh} = ssh_packet(Msg, Ssh0),
{Msg, SshPacket, Ssh}.
-kex_init(#ssh{role = Role, opts = Opts}) ->
+kex_init(#ssh{role = Role, opts = Opts, available_host_keys = HostKeyAlgs}) ->
Random = ssh_bits:random(16),
Compression = case proplists:get_value(compression, Opts, none) of
zlib -> ["zlib", "none"];
none -> ["none", "zlib"]
end,
- kexinit_messsage(Role, Random, Compression).
+ kexinit_messsage(Role, Random, Compression, HostKeyAlgs).
key_init(client, Ssh, Value) ->
Ssh#ssh{c_keyinit = Value};
key_init(server, Ssh, Value) ->
Ssh#ssh{s_keyinit = Value}.
-kexinit_messsage(client, Random, Compression) ->
+kexinit_messsage(client, Random, Compression, HostKeyAlgs) ->
#ssh_msg_kexinit{
cookie = Random,
kex_algorithms = ["diffie-hellman-group1-sha1"],
- server_host_key_algorithms = ["ssh-rsa", "ssh-dss"],
+ server_host_key_algorithms = HostKeyAlgs,
encryption_algorithms_client_to_server = ["aes128-cbc","3des-cbc"],
encryption_algorithms_server_to_client = ["aes128-cbc","3des-cbc"],
mac_algorithms_client_to_server = ["hmac-sha1"],
@@ -240,11 +232,11 @@ kexinit_messsage(client, Random, Compression) ->
languages_server_to_client = []
};
-kexinit_messsage(server, Random, Compression) ->
+kexinit_messsage(server, Random, Compression, HostKeyAlgs) ->
#ssh_msg_kexinit{
cookie = Random,
kex_algorithms = ["diffie-hellman-group1-sha1"],
- server_host_key_algorithms = ["ssh-dss"],
+ server_host_key_algorithms = HostKeyAlgs,
encryption_algorithms_client_to_server = ["aes128-cbc","3des-cbc"],
encryption_algorithms_server_to_client = ["aes128-cbc","3des-cbc"],
mac_algorithms_client_to_server = ["hmac-sha1"],
@@ -300,7 +292,6 @@ install_messages('diffie-hellman-group-exchange-sha1') ->
key_exchange_first_msg('diffie-hellman-group1-sha1', Ssh0) ->
{G, P} = dh_group1(),
{Private, Public} = dh_gen_key(G, P, 1024),
- %%?dbg(?DBG_KEX, "public: ~p~n", [Public]),
{SshPacket, Ssh1} = ssh_packet(#ssh_msg_kexdh_init{e = Public}, Ssh0),
{ok, SshPacket,
Ssh1#ssh{keyex_key = {{Private, Public}, {G, P}}}};
@@ -320,7 +311,6 @@ key_exchange_first_msg('diffie-hellman-group-exchange-sha1', Ssh0) ->
handle_kexdh_init(#ssh_msg_kexdh_init{e = E}, Ssh0) ->
{G, P} = dh_group1(),
{Private, Public} = dh_gen_key(G, P, 1024),
- %%?dbg(?DBG_KEX, "public: ~p~n", [Public]),
K = ssh_math:ipow(E, Private, P),
{Key, K_S} = get_host_key(Ssh0),
H = kex_h(Ssh0, K_S, E, Public, K),
@@ -329,8 +319,7 @@ handle_kexdh_init(#ssh_msg_kexdh_init{e = E}, Ssh0) ->
f = Public,
h_sig = H_SIG
}, Ssh0),
- %%?dbg(?DBG_KEX, "shared_secret: ~s ~n", [fmt_binary(K, 16, 4)]),
- %%?dbg(?DBG_KEX, "hash: ~s ~n", [fmt_binary(H, 16, 4)]),
+
{ok, SshPacket, Ssh1#ssh{keyex_key = {{Private, Public}, {G, P}},
shared_secret = K,
exchanged_hash = H,
@@ -338,7 +327,6 @@ handle_kexdh_init(#ssh_msg_kexdh_init{e = E}, Ssh0) ->
handle_kex_dh_gex_group(#ssh_msg_kex_dh_gex_group{p = P, g = G}, Ssh0) ->
{Private, Public} = dh_gen_key(G,P,1024),
- %%?dbg(?DBG_KEX, "public: ~p ~n", [Public]),
{SshPacket, Ssh1} =
ssh_packet(#ssh_msg_kex_dh_gex_init{e = Public}, Ssh0),
{ok, SshPacket,
@@ -362,8 +350,7 @@ handle_kexdh_reply(#ssh_msg_kexdh_reply{public_host_key = HostKey, f = F,
#ssh{keyex_key = {{Private, Public}, {_G, P}}} = Ssh0) ->
K = ssh_math:ipow(F, Private, P),
H = kex_h(Ssh0, HostKey, Public, F, K),
- %%?dbg(?DBG_KEX, "shared_secret: ~s ~n", [fmt_binary(K, 16, 4)]),
- %%?dbg(?DBG_KEX, "hash: ~s ~n", [fmt_binary(H, 16, 4)]),
+
case verify_host_key(Ssh0, HostKey, H, H_SIG) of
ok ->
{SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0),
@@ -396,8 +383,7 @@ handle_kex_dh_gex_reply(#ssh_msg_kex_dh_gex_reply{public_host_key = HostKey,
Ssh0) ->
K = ssh_math:ipow(F, Private, P),
H = kex_h(Ssh0, HostKey, Min, NBits, Max, P, G, Public, F, K),
- %%?dbg(?DBG_KEX, "shared_secret: ~s ~n", [fmt_binary(K, 16, 4)]),
- %%?dbg(?DBG_KEX, "hash: ~s ~n", [fmt_binary(H, 16, 4)]),
+
case verify_host_key(Ssh0, HostKey, H, H_SIG) of
ok ->
{SshPacket, Ssh} = ssh_packet(#ssh_msg_newkeys{}, Ssh0),
@@ -423,83 +409,68 @@ sid(#ssh{session_id = Id}, _) ->
%%
get_host_key(SSH) ->
#ssh{key_cb = Mod, opts = Opts, algorithms = ALG} = SSH,
- Scope = proplists:get_value(key_scope, Opts, system),
- case ALG#alg.hkey of
- 'ssh-rsa' ->
- case Mod:private_host_rsa_key(Scope, Opts) of
- {ok,Key=#ssh_key { public={N,E}} } ->
- %%?dbg(true, "x~n", []),
- {Key,
- ssh_bits:encode(["ssh-rsa",E,N],[string,mpint,mpint])};
- Error ->
- %%?dbg(true, "y~n", []),
- exit(Error)
- end;
- 'ssh-dss' ->
- case Mod:private_host_dsa_key(Scope, Opts) of
- {ok,Key=#ssh_key { public={P,Q,G,Y}}} ->
- {Key, ssh_bits:encode(["ssh-dss",P,Q,G,Y],
- [string,mpint,mpint,mpint,mpint])};
- Error ->
- exit(Error)
- end;
- _ ->
- exit({error, bad_key_type})
+
+ case Mod:host_key(ALG#alg.hkey, Opts) of
+ {ok, #'RSAPrivateKey'{modulus = N, publicExponent = E} = Key} ->
+ {Key,
+ ssh_bits:encode(["ssh-rsa",E,N],[string,mpint,mpint])};
+ {ok, #'DSAPrivateKey'{y = Y, p = P, q = Q, g = G} = Key} ->
+ {Key, ssh_bits:encode(["ssh-dss",P,Q,G,Y],
+ [string,mpint,mpint,mpint,mpint])};
+ Result ->
+ exit({error, {Result, unsupported_key_type}})
end.
-sign_host_key(Ssh, Private, H) ->
- ALG = Ssh#ssh.algorithms,
- Module = case ALG#alg.hkey of
- 'ssh-rsa' ->
- ssh_rsa;
- 'ssh-dss' ->
- ssh_dsa
- end,
- case catch Module:sign(Private, H) of
- {'EXIT', Reason} ->
- error_logger:format("SIGN FAILED: ~p\n", [Reason]),
- {error, Reason};
- SIG ->
- ssh_bits:encode([Module:alg_name() ,SIG],[string,binary])
- end.
+sign_host_key(_Ssh, #'RSAPrivateKey'{} = Private, H) ->
+ Hash = sha, %% Option ?!
+ Signature = sign(H, Hash, Private),
+ ssh_bits:encode(["ssh-rsa", Signature],[string, binary]);
+sign_host_key(_Ssh, #'DSAPrivateKey'{} = Private, H) ->
+ Hash = sha, %% Option ?!
+ RawSignature = sign(H, Hash, Private),
+ ssh_bits:encode(["ssh-dss", RawSignature],[string, binary]).
verify_host_key(SSH, K_S, H, H_SIG) ->
ALG = SSH#ssh.algorithms,
case ALG#alg.hkey of
'ssh-rsa' ->
- case ssh_bits:decode(K_S,[string,mpint,mpint]) of
- ["ssh-rsa", E, N] ->
- ["ssh-rsa",SIG] = ssh_bits:decode(H_SIG,[string,binary]),
- Public = #ssh_key { type=rsa, public={N,E} },
- case catch ssh_rsa:verify(Public, H, SIG) of
- {'EXIT', Reason} ->
- error_logger:format("VERIFY FAILED: ~p\n", [Reason]),
- {error, bad_signature};
- ok ->
- known_host_key(SSH, Public, "ssh-rsa")
- end;
- _ ->
- {error, bad_format}
- end;
+ verify_host_key_rsa(SSH, K_S, H, H_SIG);
'ssh-dss' ->
- case ssh_bits:decode(K_S,[string,mpint,mpint,mpint,mpint]) of
- ["ssh-dss",P,Q,G,Y] ->
- ["ssh-dss",SIG] = ssh_bits:decode(H_SIG,[string,binary]),
- Public = #ssh_key { type=dsa, public={P,Q,G,Y} },
- case catch ssh_dsa:verify(Public, H, SIG) of
- {'EXIT', Reason} ->
- error_logger:format("VERIFY FAILED: ~p\n", [Reason]),
- {error, bad_signature};
- ok ->
- known_host_key(SSH, Public, "ssh-dss")
- end;
- _ ->
- {error, bad_host_key_format}
- end;
+ verify_host_key_dss(SSH, K_S, H, H_SIG);
_ ->
{error, bad_host_key_algorithm}
end.
+verify_host_key_rsa(SSH, K_S, H, H_SIG) ->
+ case ssh_bits:decode(K_S,[string,mpint,mpint]) of
+ ["ssh-rsa", E, N] ->
+ ["ssh-rsa",SIG] = ssh_bits:decode(H_SIG,[string,binary]),
+ Public = #'RSAPublicKey'{publicExponent = E, modulus = N},
+ case verify(H, sha, SIG, Public) of
+ false ->
+ {error, bad_signature};
+ true ->
+ known_host_key(SSH, Public, "ssh-rsa")
+ end;
+ _ ->
+ {error, bad_format}
+ end.
+
+verify_host_key_dss(SSH, K_S, H, H_SIG) ->
+ case ssh_bits:decode(K_S,[string,mpint,mpint,mpint,mpint]) of
+ ["ssh-dss",P,Q,G,Y] ->
+ ["ssh-dss",SIG] = ssh_bits:decode(H_SIG,[string,binary]),
+ Public = {Y, #'Dss-Parms'{p = P, q = Q, g = G}},
+ case verify(H, sha, SIG, Public) of
+ false ->
+ {error, bad_signature};
+ true ->
+ known_host_key(SSH, Public, "ssh-dss")
+ end;
+ _ ->
+ {error, bad_host_key_format}
+ end.
+
accepted_host(Ssh, PeerName, Opts) ->
case proplists:get_value(silently_accept_hosts, Opts, false) of
true ->
@@ -511,14 +482,10 @@ accepted_host(Ssh, PeerName, Opts) ->
known_host_key(#ssh{opts = Opts, key_cb = Mod, peer = Peer} = Ssh,
Public, Alg) ->
PeerName = peer_name(Peer),
- case Mod:lookup_host_key(PeerName, Alg, Opts) of
- {ok, Public} ->
+ case Mod:is_host_key(Public, PeerName, Alg, Opts) of
+ true ->
ok;
- {ok, BadPublic} ->
- error_logger:format("known_host_key: Public ~p BadPublic ~p\n",
- [Public, BadPublic]),
- {error, bad_public_key};
- {error, not_found} ->
+ false ->
case accepted_host(Ssh, PeerName, Opts) of
yes ->
Mod:add_host_key(PeerName, Public, Opts);
@@ -621,7 +588,6 @@ install_alg(SSH) ->
alg_setup(SSH) ->
ALG = SSH#ssh.algorithms,
- %%?dbg(?DBG_ALG, "ALG: setup ~p ~n", [ALG]),
SSH#ssh{kex = ALG#alg.kex,
hkey = ALG#alg.hkey,
encrypt = ALG#alg.encrypt,
@@ -638,7 +604,6 @@ alg_setup(SSH) ->
}.
alg_init(SSH0) ->
- %%?dbg(?DBG_ALG, "ALG: init~n", []),
{ok,SSH1} = send_mac_init(SSH0),
{ok,SSH2} = recv_mac_init(SSH1),
{ok,SSH3} = encrypt_init(SSH2),
@@ -648,7 +613,6 @@ alg_init(SSH0) ->
SSH6.
alg_final(SSH0) ->
- %%?dbg(?DBG_ALG, "ALG: final ~n", []),
{ok,SSH1} = send_mac_final(SSH0),
{ok,SSH2} = recv_mac_final(SSH1),
{ok,SSH3} = encrypt_final(SSH2),
@@ -669,19 +633,15 @@ select(CL, SL) ->
[] -> undefined;
[ALG|_] -> ALG
end,
- %%?dbg(?DBG_ALG, "ALG: select: ~p ~p = ~p~n", [CL, SL, C]),
C.
ssh_packet(#ssh_msg_kexinit{} = Msg, Ssh0) ->
BinMsg = ssh_bits:encode(Msg),
Ssh = key_init(Ssh0#ssh.role, Ssh0, BinMsg),
- %%?dbg(?DBG_MESSAGE, "SEND_MSG: ~p~n", [Msg]),
pack(BinMsg, Ssh);
ssh_packet(Msg, Ssh) ->
BinMsg = ssh_bits:encode(Msg),
- %%?dbg(?DBG_MESSAGE, "SEND_MSG: ~p~n", [Msg]),
- %%?dbg(?DBG_BIN_MESSAGE, "Encoded: ~p~n", [BinMsg]),
pack(BinMsg, Ssh).
pack(Data0, #ssh{encrypt_block_size = BlockSize,
@@ -732,17 +692,20 @@ msg_data(PacketData) ->
_:PaddingLen/binary>> = PacketData,
Data.
+sign(SigData, Hash, #'DSAPrivateKey'{} = Key) ->
+ DerSignature = public_key:sign(SigData, Hash, Key),
+ #'Dss-Sig-Value'{r = R, s = S} = public_key:der_decode('Dss-Sig-Value', DerSignature),
+ <<R:160/big-unsigned-integer, S:160/big-unsigned-integer>>;
+sign(SigData, Hash, Key) ->
+ public_key:sign(SigData, Hash, Key).
-%% Send a disconnect message
-%% terminate(S, SSH, Code, Message) ->
-%% M = #ssh_msg_disconnect{code=Code,
-%% description = Message,
-%% language = "en"},
-%% send_msg(S, SSH, M),
-%% gen_tcp:close(S),
-%% {error, M}.
+verify(PlainText, Hash, Sig, {_, #'Dss-Parms'{}} = Key) ->
+ <<R:160/big-unsigned-integer, S:160/big-unsigned-integer>> = Sig,
+ Signature = public_key:der_encode('Dss-Sig-Value', #'Dss-Sig-Value'{r = R, s = S}),
+ public_key:verify(PlainText, Hash, Signature, Key);
+verify(PlainText, Hash, Sig, Key) ->
+ public_key:verify(PlainText, Hash, Sig, Key).
-
%% public key algorithms
%%
%% ssh-dss REQUIRED sign Raw DSS Key
@@ -761,9 +724,6 @@ msg_data(PacketData) ->
%%
%%
-
-
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Encryption
%%
@@ -833,19 +793,13 @@ encrypt(#ssh{encrypt = none} = Ssh, Data) ->
encrypt(#ssh{encrypt = '3des-cbc',
encrypt_keys = {K1,K2,K3},
encrypt_ctx = IV0} = Ssh, Data) ->
- %%?dbg(?DBG_CRYPTO, "encrypt: IV=~p K1=~p, K2=~p, K3=~p ~n",
- %% [IV0,K1,K2,K3]),
Enc = crypto:des3_cbc_encrypt(K1,K2,K3,IV0,Data),
- %%?dbg(?DBG_CRYPTO, "encrypt: ~p -> ~p ~n", [Data, Enc]),
IV = crypto:des_cbc_ivec(Enc),
{Ssh#ssh{encrypt_ctx = IV}, Enc};
encrypt(#ssh{encrypt = 'aes128-cbc',
encrypt_keys = K,
encrypt_ctx = IV0} = Ssh, Data) ->
- %%?dbg(?DBG_CRYPTO, "encrypt: IV=~p K=~p ~n",
- %% [IV0,K]),
Enc = crypto:aes_cbc_128_encrypt(K,IV0,Data),
- %%?dbg(?DBG_CRYPTO, "encrypt: ~p -> ~p ~n", [Data, Enc]),
IV = crypto:aes_cbc_ivec(Enc),
{Ssh#ssh{encrypt_ctx = IV}, Enc}.
@@ -893,18 +847,12 @@ decrypt(#ssh{decrypt = none} = Ssh, Data) ->
decrypt(#ssh{decrypt = '3des-cbc', decrypt_keys = Keys,
decrypt_ctx = IV0} = Ssh, Data) ->
{K1, K2, K3} = Keys,
- %%?dbg(?DBG_CRYPTO, "decrypt: IV=~p K1=~p, K2=~p, K3=~p ~n",
- %%[IV0,K1,K2,K3]),
Dec = crypto:des3_cbc_decrypt(K1,K2,K3,IV0,Data),
- %%?dbg(?DBG_CRYPTO, "decrypt: ~p -> ~p ~n", [Data, Dec]),
IV = crypto:des_cbc_ivec(Data),
{Ssh#ssh{decrypt_ctx = IV}, Dec};
decrypt(#ssh{decrypt = 'aes128-cbc', decrypt_keys = Key,
decrypt_ctx = IV0} = Ssh, Data) ->
- %%?dbg(?DBG_CRYPTO, "decrypt: IV=~p Key=~p ~n",
- %% [IV0,Key]),
Dec = crypto:aes_cbc_128_decrypt(Key,IV0,Data),
- %%?dbg(?DBG_CRYPTO, "decrypt: ~p -> ~p ~n", [Data, Dec]),
IV = crypto:aes_cbc_ivec(Data),
{Ssh#ssh{decrypt_ctx = IV}, Dec}.
@@ -936,7 +884,6 @@ compress(#ssh{compress = none} = Ssh, Data) ->
{Ssh, Data};
compress(#ssh{compress = zlib, compress_ctx = Context} = Ssh, Data) ->
Compressed = zlib:deflate(Context, Data, sync),
- %%?dbg(?DBG_ZLIB, "deflate: ~p -> ~p ~n", [Data, Compressed]),
{Ssh, list_to_binary(Compressed)}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -960,7 +907,6 @@ decompress(#ssh{decompress = none} = Ssh, Data) ->
{Ssh, Data};
decompress(#ssh{decompress = zlib, decompress_ctx = Context} = Ssh, Data) ->
Decompressed = zlib:inflate(Context, Data),
- %%?dbg(?DBG_ZLIB, "inflate: ~p -> ~p ~n", [Data, Decompressed]),
{Ssh, list_to_binary(Decompressed)}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1039,7 +985,6 @@ hash(SSH, Char, N, HASH) ->
K1 = HASH([K, H, Char, SessionID]),
Sz = N div 8,
<<Key:Sz/binary, _/binary>> = hash(K, H, K1, N-128, HASH),
- %%?dbg(?DBG_KEX, "Key ~s: ~s ~n", [Char, fmt_binary(Key, 16, 4)]),
Key.
hash(_K, _H, Ki, N, _HASH) when N =< 0 ->
@@ -1055,6 +1000,7 @@ kex_h(SSH, K_S, E, F, K) ->
[string,string,binary,binary,binary,
mpint,mpint,mpint]),
crypto:sha(L).
+
kex_h(SSH, K_S, Min, NBits, Max, Prime, Gen, E, F, K) ->
L = if Min==-1; Max==-1 ->
@@ -1075,7 +1021,7 @@ kex_h(SSH, K_S, Min, NBits, Max, Prime, Gen, E, F, K) ->
Prime, Gen, E,F,K], Ts)
end,
crypto:sha(L).
-
+
mac_key_size('hmac-sha1') -> 20*8;
mac_key_size('hmac-sha1-96') -> 20*8;
mac_key_size('hmac-md5') -> 16*8;
@@ -1105,9 +1051,6 @@ dh_gen_key(G, P, _Bits) ->
Public = ssh_math:ipow(G, Private, P),
{Private,Public}.
-%% trim(Str) ->
-%% lists:reverse(trim_head(lists:reverse(trim_head(Str)))).
-
trim_tail(Str) ->
lists:reverse(trim_head(lists:reverse(Str))).
@@ -1116,48 +1059,3 @@ trim_head([$\t|Cs]) -> trim_head(Cs);
trim_head([$\n|Cs]) -> trim_head(Cs);
trim_head([$\r|Cs]) -> trim_head(Cs);
trim_head(Cs) -> Cs.
-
-%% Retrieve session_id from ssh, needed by public-key auth
-%get_session_id(SSH) ->
-% {ok, SessionID} = call(SSH, get_session_id),
-
-%% DEBUG utils
-%% Format integers and binaries as hex blocks
-%%
-%% -ifdef(debug).
-%% fmt_binary(B, BlockSize, GroupSize) ->
-%% fmt_block(fmt_bin(B), BlockSize, GroupSize).
-
-%% fmt_block(Bin, BlockSize, GroupSize) ->
-%% fmt_block(Bin, BlockSize, 0, GroupSize).
-
-
-%% fmt_block(Bin, 0, _I, _G) ->
-%% binary_to_list(Bin);
-%% fmt_block(Bin, Sz, G, G) when G =/= 0 ->
-%% ["~n#" | fmt_block(Bin, Sz, 0, G)];
-%% fmt_block(Bin, Sz, I, G) ->
-%% case Bin of
-%% <<Block:Sz/binary, Tail/binary>> ->
-%% if Tail == <<>> ->
-%% [binary_to_list(Block)];
-%% true ->
-%% [binary_to_list(Block), " " | fmt_block(Tail, Sz, I+1, G)]
-%% end;
-%% <<>> ->
-%% [];
-%% _ ->
-%% [binary_to_list(Bin)]
-%% end.
-
-%% %% Format integer or binary as hex
-%% fmt_bin(X) when integer(X) ->
-%% list_to_binary(io_lib:format("~p", [X]));
-%% fmt_bin(X) when binary(X) ->
-%% Sz = size(X)*8,
-%% <<Y:Sz/unsigned-big>> = X,
-%% %%Fmt = "~"++integer_to_list(size(X)*2)++"~p",
-%% list_to_binary(io_lib:format("~p", [Y])).
-
-%% -endif.
-
diff --git a/lib/ssh/src/ssh_xfer.erl b/lib/ssh/src/ssh_xfer.erl
index c9631a73b1..d5b6dd03d1 100644
--- a/lib/ssh/src/ssh_xfer.erl
+++ b/lib/ssh/src/ssh_xfer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -298,8 +298,6 @@ xf_send_names(#ssh_xfer{cm = CM, channel = Channel, vsn = Vsn},
Size = 1 + 4 + 4 + Len,
ToSend = [<<?UINT32(Size), ?SSH_FXP_NAME, ?UINT32(ReqId), ?UINT32(Count)>>,
Data],
- %%?dbg(true, "xf_send_names: Size=~p size(ToSend)=~p\n",
- %% [Size, size(list_to_binary(ToSend))]),
ssh_connection:send(CM, Channel, ToSend).
xf_send_status(XF, ReqId, ErrorCode) ->
@@ -353,7 +351,6 @@ xf_reply(_XF, <<?SSH_FXP_DATA, ?UINT32(ReqID),
{data, ReqID, Data};
xf_reply(XF, <<?SSH_FXP_NAME, ?UINT32(ReqID),
?UINT32(Count), AData/binary>>) ->
- %%?dbg(true, "xf_reply ?SSH_FXP_NAME: AData=~p\n", [AData]),
{name, ReqID, decode_names(XF#ssh_xfer.vsn, Count, AData)};
xf_reply(XF, <<?SSH_FXP_ATTRS, ?UINT32(ReqID),
AData/binary>>) ->
@@ -579,7 +576,6 @@ encode_attr_flags(Vsn, Flags) ->
end, Flags).
encode_file_type(Type) ->
- %%?dbg(true, "encode_file_type(~p)\n", [Type]),
case Type of
regular -> ?SSH_FILEXFER_TYPE_REGULAR;
directory -> ?SSH_FILEXFER_TYPE_DIRECTORY;
@@ -660,15 +656,12 @@ encode_ATTR(Vsn, A) ->
{extended, A#ssh_xfer_attr.extensions}],
0, []),
Type = encode_file_type(A#ssh_xfer_attr.type),
- %%?dbg(true, "encode_ATTR: Vsn=~p A=~p As=~p Flags=~p Type=~p",
- %% [Vsn, A, As, Flags, Type]),
Result = list_to_binary([?uint32(Flags),
if Vsn >= 5 ->
?byte(Type);
true ->
(<<>>)
end, As]),
- %% ?dbg(true, " Result=~p\n", [Result]),
Result.
@@ -722,7 +715,6 @@ encode_As(_Vsn, [], Flags, Acc) ->
decode_ATTR(Vsn, <<?UINT32(Flags), Tail/binary>>) ->
- %%?dbg(true, "decode_ATTR: Vsn=~p Flags=~p Tail=~p\n", [Vsn, Flags, Tail]),
{Type,Tail2} =
if Vsn =< 3 ->
{?SSH_FILEXFER_TYPE_UNKNOWN, Tail};
@@ -751,7 +743,6 @@ decode_ATTR(Vsn, <<?UINT32(Flags), Tail/binary>>) ->
Tail2).
decode_As(Vsn, [{AName, AField}|As], R, Flags, Tail) ->
- %%?dbg(false, "decode_As: Vsn=~p AName=~p AField=~p Flags=~p Tail=~p\n", [Vsn, AName, AField, Flags, Tail]),
case AName of
size when ?is_set(?SSH_FILEXFER_ATTR_SIZE, Flags) ->
<<?UINT64(X), Tail2/binary>> = Tail,
@@ -762,7 +753,6 @@ decode_As(Vsn, [{AName, AField}|As], R, Flags, Tail) ->
ownergroup when ?is_set(?SSH_FILEXFER_ATTR_OWNERGROUP, Flags),Vsn>=5 ->
<<?UINT32(Len), Bin:Len/binary, Tail2/binary>> = Tail,
X = binary_to_list(Bin),
- %%?dbg(true, "ownergroup X=~p\n", [X]),
decode_As(Vsn, As, setelement(AField, R, X), Flags, Tail2);
permissions when ?is_set(?SSH_FILEXFER_ATTR_PERMISSIONS,Flags),Vsn>=5->
@@ -824,13 +814,11 @@ decode_names(Vsn, I, <<?UINT32(Len), FileName:Len/binary,
?UINT32(LLen), _LongName:LLen/binary,
Tail/binary>>) when Vsn =< 3 ->
Name = binary_to_list(FileName),
- %%?dbg(true, "decode_names: ~p\n", [Name]),
{A, Tail2} = decode_ATTR(Vsn, Tail),
[{Name, A} | decode_names(Vsn, I-1, Tail2)];
decode_names(Vsn, I, <<?UINT32(Len), FileName:Len/binary,
Tail/binary>>) when Vsn >= 4 ->
Name = binary_to_list(FileName),
- %%?dbg(true, "decode_names: ~p\n", [Name]),
{A, Tail2} = decode_ATTR(Vsn, Tail),
[{Name, A} | decode_names(Vsn, I-1, Tail2)].
@@ -839,8 +827,6 @@ encode_names(Vsn, NamesAndAttrs) ->
encode_name(Vsn, {Name,Attr}, Len) when Vsn =< 3 ->
NLen = length(Name),
- %%?dbg(true, "encode_name: Vsn=~p Name=~p Attr=~p\n",
- %% [Vsn, Name, Attr]),
EncAttr = encode_ATTR(Vsn, Attr),
ALen = size(EncAttr),
NewLen = Len + NLen*2 + 4 + 4 + ALen,
diff --git a/lib/ssh/test/Makefile b/lib/ssh/test/Makefile
index 1820924ed6..145d5d2ad6 100644
--- a/lib/ssh/test/Makefile
+++ b/lib/ssh/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2011. All Rights Reserved.
+# Copyright Ericsson AB 2004-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -32,7 +32,6 @@ VSN=$(GS_VSN)
MODULES= \
ssh_test_lib \
- ssh_SUITE \
ssh_basic_SUITE \
ssh_to_openssh_SUITE \
ssh_sftp_SUITE \
diff --git a/lib/ssh/test/ssh_SUITE.erl b/lib/ssh/test/ssh_SUITE.erl
deleted file mode 100644
index 953c9080f9..0000000000
--- a/lib/ssh/test/ssh_SUITE.erl
+++ /dev/null
@@ -1,72 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2011. 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%
-%%
-
-%%
-%%%----------------------------------------------------------------
-%%% Purpose:ssh application test suite.
-%%%-----------------------------------------------------------------
--module(ssh_SUITE).
--include_lib("common_test/include/ct.hrl").
--include("test_server_line.hrl").
-
-% Default timetrap timeout (set in init_per_testcase).
--define(default_timeout, ?t:minutes(1)).
--define(application, ssh).
-
-% Test server specific exports
--export([all/0,groups/0,init_per_group/2,end_per_group/2]).
--export([init_per_testcase/2, end_per_testcase/2]).
-
-% Test cases must be exported.
--export([app_test/1]).
--define(cases, [app_test]).
-
-%%
-%% all/1
-%%
-all() ->
- [app_test].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_testcase(_Case, Config) ->
- Dog=test_server:timetrap(?default_timeout),
- [{watchdog, Dog}|Config].
-end_per_testcase(_Case, Config) ->
- Dog=?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- ok.
-%
-% Test cases starts here.
-%
-app_test(suite) ->
- [];
-app_test(doc) ->
- ["Application consistency test."];
-app_test(Config) when is_list(Config) ->
- ?t:app_test(?application),
- ok.
diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl
index 5ea0d98980..9c13180159 100644
--- a/lib/ssh/test/ssh_basic_SUITE.erl
+++ b/lib/ssh/test/ssh_basic_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -41,9 +41,6 @@
init_per_suite(Config) ->
case catch crypto:start() of
ok ->
- Dir = ?config(priv_dir, Config),
- {ok, _} = ssh_test_lib:get_id_keys(Dir),
- ssh_test_lib:make_dsa_files(Config),
Config;
_Else ->
{skip, "Crypto could not be started!"}
@@ -55,10 +52,9 @@ init_per_suite(Config) ->
%% A list of key/value pairs, holding the test case configuration.
%% Description: Cleanup after the whole suite
%%--------------------------------------------------------------------
-end_per_suite(Config) ->
- Dir = ?config(priv_dir, Config),
+end_per_suite(_Config) ->
+ ssh:stop(),
crypto:stop(),
- ssh_test_lib:remove_id_keys(Dir),
ok.
%%--------------------------------------------------------------------
@@ -75,7 +71,6 @@ end_per_suite(Config) ->
%% Description: Initialization before each test case
%%--------------------------------------------------------------------
init_per_testcase(_TestCase, Config) ->
- ssh_test_lib:known_hosts(backup),
ssh:start(),
Config.
@@ -87,9 +82,16 @@ init_per_testcase(_TestCase, Config) ->
%% A list of key/value pairs, holding the test case configuration.
%% Description: Cleanup after each test case
%%--------------------------------------------------------------------
-end_per_testcase(_TestCase, _Config) ->
+
+end_per_testcase(TestCase, Config) when TestCase == server_password_option;
+ TestCase == server_userpassword_option ->
+ UserDir = filename:join(?config(priv_dir, Config), nopubkey),
+ ssh_test_lib:del_dirs(UserDir),
+ end_per_testcase(Config);
+end_per_testcase(TestCase, Config) ->
+ end_per_testcase(Config).
+end_per_testcase(_Config) ->
ssh:stop(),
- ssh_test_lib:known_hosts(restore),
ok.
%%--------------------------------------------------------------------
@@ -101,31 +103,72 @@ end_per_testcase(_TestCase, _Config) ->
%% Description: Returns a list of all test cases in this test suite
%%--------------------------------------------------------------------
all() ->
- [exec, exec_compressed, shell, daemon_already_started,
- server_password_option, server_userpassword_option,
- known_hosts].
+ [app_test,
+ {group, dsa_key},
+ {group, rsa_key},
+ {group, dsa_pass_key},
+ {group, rsa_pass_key},
+ daemon_already_started,
+ server_password_option, server_userpassword_option].
groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
+ [{dsa_key, [], [exec, exec_compressed, shell, known_hosts]},
+ {rsa_key, [], [exec, exec_compressed, shell, known_hosts]},
+ {dsa_pass_key, [], [pass_phrase]},
+ {rsa_pass_key, [], [pass_phrase]}
+ ].
+
+init_per_group(dsa_key, Config) ->
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:setup_dsa(DataDir, PrivDir),
+ Config;
+init_per_group(rsa_key, Config) ->
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:setup_rsa(DataDir, PrivDir),
+ Config;
+init_per_group(rsa_pass_key, Config) ->
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:setup_rsa_pass_pharse(DataDir, PrivDir, "Password"),
+ [{pass_phrase, {rsa_pass_phrase, "Password"}}| Config];
+init_per_group(dsa_pass_key, Config) ->
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:setup_dsa_pass_pharse(DataDir, PrivDir, "Password"),
+ [{pass_phrase, {dsa_pass_phrase, "Password"}}| Config];
+init_per_group(_, Config) ->
+ Config.
-end_per_group(_GroupName, Config) ->
- Config.
+end_per_group(dsa_key, Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:clean_dsa(PrivDir),
+ Config;
+end_per_group(rsa_key, Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:clean_rsa(PrivDir),
+ Config;
+end_per_group(dsa_pass_key, Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:clean_dsa(PrivDir),
+ Config;
+end_per_group(rsa_pass_key, Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:clean_rsa(PrivDir),
+ Config;
+end_per_group(_, Config) ->
+ Config.
%% Test cases starts here.
%%--------------------------------------------------------------------
-sign_and_verify_rsa(doc) ->
- ["Test api function ssh:sign_data and ssh:verify_data"];
-
-sign_and_verify_rsa(suite) ->
+app_test(suite) ->
[];
-sign_and_verify_rsa(Config) when is_list(Config) ->
- Data = ssh:sign_data(<<"correct data">>, "ssh-rsa"),
- ok = ssh:verify_data(<<"correct data">>, Data, "ssh-rsa"),
- {error,invalid_signature} = ssh:verify_data(<<"incorrect data">>, Data,"ssh-rsa").
-
+app_test(doc) ->
+ ["Application consistency test."];
+app_test(Config) when is_list(Config) ->
+ ?t:app_test(ssh),
+ ok.
exec(doc) ->
["Test api function ssh_connection:exec"];
@@ -135,11 +178,15 @@ exec(suite) ->
exec(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- SystemDir = ?config(data_dir, Config),
+ SystemDir = filename:join(?config(priv_dir, Config), system),
+ UserDir = ?config(priv_dir, Config),
+
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {user_dir, UserDir},
{failfun, fun ssh_test_lib:failfun/2}]),
ConnectionRef =
ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ {user_dir, UserDir},
{user_interaction, false}]),
{ok, ChannelId0} = ssh_connection:session_channel(ConnectionRef, infinity),
success = ssh_connection:exec(ConnectionRef, ChannelId0,
@@ -177,13 +224,16 @@ exec_compressed(suite) ->
exec_compressed(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- SystemDir = ?config(data_dir, Config),
- {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ SystemDir = filename:join(?config(priv_dir, Config), system),
+ UserDir = ?config(priv_dir, Config),
+
+ {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},{user_dir, UserDir},
{compression, zlib},
{failfun, fun ssh_test_lib:failfun/2}]),
ConnectionRef =
ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ {user_dir, UserDir},
{user_interaction, false}]),
{ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity),
success = ssh_connection:exec(ConnectionRef, ChannelId,
@@ -208,13 +258,15 @@ shell(suite) ->
shell(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- SystemDir = ?config(data_dir, Config),
- {_Pid, _Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ SystemDir = filename:join(?config(priv_dir, Config), system),
+ UserDir = ?config(priv_dir, Config),
+
+ {_Pid, _Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},{user_dir, UserDir},
{failfun, fun ssh_test_lib:failfun/2}]),
test_server:sleep(500),
IO = ssh_test_lib:start_io_server(),
- Shell = ssh_test_lib:start_shell(Port, IO),
+ Shell = ssh_test_lib:start_shell(Port, IO, UserDir),
receive
ErlShellStart ->
test_server:format("Erlang shell start: ~p~n", [ErlShellStart])
@@ -278,9 +330,13 @@ daemon_already_started(suite) ->
daemon_already_started(Config) when is_list(Config) ->
SystemDir = ?config(data_dir, Config),
+ UserDir = ?config(priv_dir, Config),
+
{Pid, _Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {user_dir, UserDir},
{failfun, fun ssh_test_lib:failfun/2}]),
{error, eaddrinuse} = ssh_test_lib:daemon(Port, [{system_dir, SystemDir},
+ {user_dir, UserDir},
{failfun,
fun ssh_test_lib:failfun/2}]),
ssh:stop_daemon(Pid).
@@ -291,9 +347,12 @@ server_password_option(doc) ->
server_password_option(suite) ->
[];
server_password_option(Config) when is_list(Config) ->
- UserDir = ?config(data_dir, Config), % to make sure we don't use
- SysDir = ?config(data_dir, Config), % public-key-auth
+ PrivDir = ?config(priv_dir, Config),
+ UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
+ file:make_dir(UserDir),
+ SysDir = ?config(data_dir, Config),
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
+ {user_dir, UserDir},
{password, "morot"}]),
ConnectionRef =
@@ -321,9 +380,12 @@ server_userpassword_option(doc) ->
server_userpassword_option(suite) ->
[];
server_userpassword_option(Config) when is_list(Config) ->
- UserDir = ?config(data_dir, Config), % to make sure we don't use
- SysDir = ?config(data_dir, Config), % public-key-auth
+ PrivDir = ?config(priv_dir, Config),
+ UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
+ file:make_dir(UserDir),
+ SysDir = ?config(data_dir, Config),
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
+ {user_dir, PrivDir},
{user_passwords, [{"vego", "morot"}]}]),
ConnectionRef =
@@ -362,16 +424,16 @@ known_hosts(suite) ->
[];
known_hosts(Config) when is_list(Config) ->
SystemDir = ?config(data_dir, Config),
- UserDir = ?config(priv_dir, Config),
-
- {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ PrivDir = ?config(priv_dir, Config),
+
+ {Pid, Host, Port} = ssh_test_lib:daemon([{user_dir, PrivDir},{system_dir, SystemDir},
{failfun, fun ssh_test_lib:failfun/2}]),
- KnownHosts = filename:join(UserDir, "known_hosts"),
+ KnownHosts = filename:join(PrivDir, "known_hosts"),
file:delete(KnownHosts),
{error, enoent} = file:read_file(KnownHosts),
ConnectionRef =
- ssh_test_lib:connect(Host, Port, [{user_dir, UserDir},
+ ssh_test_lib:connect(Host, Port, [{user_dir, PrivDir},
{user_interaction, false},
silently_accept_hosts]),
{ok, _Channel} = ssh_connection:session_channel(ConnectionRef, infinity),
@@ -382,7 +444,30 @@ known_hosts(Config) when is_list(Config) ->
[HostAndIp, Alg, _KeyData] = string:tokens(Line, " "),
[Host, _Ip] = string:tokens(HostAndIp, ","),
"ssh-" ++ _ = Alg,
- ssh:stop_daemon(Pid).
+ ssh:stop_daemon(Pid).
+
+pass_phrase(doc) ->
+ ["Test that we can use keyes protected by pass phrases"];
+
+pass_phrase(suite) ->
+ [];
+
+pass_phrase(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ SystemDir = filename:join(?config(priv_dir, Config), system),
+ UserDir = ?config(priv_dir, Config),
+ PhraseArg = ?config(pass_phrase, Config),
+
+ {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {user_dir, UserDir},
+ {failfun, fun ssh_test_lib:failfun/2}]),
+ ConnectionRef =
+ ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ PhraseArg,
+ {user_dir, UserDir},
+ {user_interaction, false}]),
+ {ok, _ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity),
+ ssh:stop_daemon(Pid).
%%--------------------------------------------------------------------
%% Internal functions
diff --git a/lib/ssh/test/ssh_basic_SUITE_data/id_dsa b/lib/ssh/test/ssh_basic_SUITE_data/id_dsa
new file mode 100644
index 0000000000..d306f8b26e
--- /dev/null
+++ b/lib/ssh/test/ssh_basic_SUITE_data/id_dsa
@@ -0,0 +1,13 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBvAIBAAKBgQDfi2flSTZZofwT4yQT0NikX/LGNT7UPeB/XEWe/xovEYCElfaQ
+APFixXvEgXwoojmZ5kiQRKzLM39wBP0jPERLbnZXfOOD0PDnw0haMh7dD7XKVMod
+/EigVgHf/qBdM2M8yz1s/rRF7n1UpLSypziKjkzCm7JoSQ2zbWIPdmBIXwIVAMgP
+kpr7Sq3O7sHdb8D601DRjoExAoGAMOQxDfB2Fd8ouz6G96f/UOzRMI/Kdv8kYYKW
+JIGY+pRYrLPyYzUeJznwZreOJgrczAX+luHnKFWJ2Dnk5CyeXk67Wsr7pJ/4MBMD
+OKeIS0S8qoSBN8+Krp79fgA+yS3IfqbkJLtLu4EBaCX4mKQIX4++k44d4U5lc8pt
++9hlEI8CgYEAznKxx9kyC6bVo7LUYKaGhofRFt0SYFc5PVmT2VUGRs1R6+6DPD+e
+uEO6IhFct7JFSRbP9p0JD4Uk+3zlZF+XX6b2PsZkeV8f/02xlNGUSmEzCSiNg1AX
+Cy/WusYhul0MncWCHMcOZB5rIvU/aP5EJJtn3xrRaz6u0SThF6AnT34CFQC63czE
+ZU8w8Q+H7z0j+a+70x2iAw==
+-----END DSA PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_basic_SUITE_data/id_rsa b/lib/ssh/test/ssh_basic_SUITE_data/id_rsa
new file mode 100644
index 0000000000..9d7e0dd5fb
--- /dev/null
+++ b/lib/ssh/test/ssh_basic_SUITE_data/id_rsa
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQD1OET+3O/Bvj/dtjxDTXmj1oiJt4sIph5kGy0RfjoPrZfaS+CU
+DhakCmS6t2ivxWFgtpKWaoGMZMJqWj6F6ZsumyFl3FPBtujwY/35cgifrI9Ns4Tl
+zR1uuengNBmV+WRQ5cd9F2qS6Z8aDQihzt0r8JUqLcK+VQbrmNzboCCQQwIDAQAB
+AoGAPQEyqPTt8JUT7mRXuaacjFXiweAXhp9NEDpyi9eLOjtFe9lElZCrsUOkq47V
+TGUeRKEm9qSodfTbKPoqc8YaBJGJPhUaTAcha+7QcDdfHBvIsgxvU7ePVnlpXRp3
+CCUEMPhlnx6xBoTYP+fRU0e3+xJIPVyVCqX1jAdUMkzfRoECQQD6ux7B1QJAIWyK
+SGkbDUbBilNmzCFNgIpOP6PA+bwfi5d16diTpra5AX09keQABAo/KaP1PdV8Vg0p
+z4P3A7G3AkEA+l+AKG6m0kQTTBMJDqOdVPYwe+5GxunMaqmhokpEbuGsrZBl5Dvd
+WpcBjR7jmenrhKZRIuA+Fz5HPo/UQJPl1QJBAKxstDkeED8j/S2XoFhPKAJ+6t39
+sUVICVTIZQeXdmzHJXCcUSkw8+WEhakqw/3SyW0oaK2FSWQJFWJUZ+8eJj8CQEh3
+xeduB5kKnS9CvzdeghZqX6QvVosSdtlUmfUYW/BgH5PpHKTP8wTaeld3XldZTpMJ
+dKiMkUw2+XYROVUrubUCQD+Na1LhULlpn4ISEtIEfqpdlUhxDgO15Wg8USmsng+x
+ICliVOSQtwaZjm8kwaFt0W7XnpnDxbRs37vIEbIMWak=
+-----END RSA PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key
new file mode 100644
index 0000000000..51ab6fbd88
--- /dev/null
+++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key
@@ -0,0 +1,13 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBuwIBAAKBgQCClaHzE2ul0gKSUxah5W0W8UiJLy4hXngKEqpaUq9SSdVdY2LK
+wVfKH1gt5iuaf1FfzOhsIC9G/GLnjYttXZc92cv/Gfe3gR+s0ni2++MX+T++mE/Q
+diltXv/Hp27PybS67SmiFW7I+RWnT2OKlMPtw2oUuKeztCe5UWjaj/y5FQIVAPLA
+l9RpiU30Z87NRAHY3NTRaqtrAoGANMRxw8UfdtNVR0CrQj3AgPaXOGE4d+G4Gp4X
+skvnCHycSVAjtYxebUkzUzt5Q6f/IabuLUdge3gXrc8BetvrcKbp+XZgM0/Vj2CF
+Ymmy3in6kzGZq7Fw1sZaku6AOU8vLa5woBT2vAcHLLT1bLAzj7viL048T6MfjrOP
+ef8nHvACgYBhDWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah
+/XcF3DeRF+eEoz48wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+U
+ykSTXYUbtsfTNRFQGBW2/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0CgIVAN4wtL5W
+Lv62jKcdskxNyz2NQoBx
+-----END DSA PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key.pub
new file mode 100644
index 0000000000..4dbb1305b0
--- /dev/null
+++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key.pub
@@ -0,0 +1,11 @@
+---- BEGIN SSH2 PUBLIC KEY ----
+AAAAB3NzaC1kc3MAAACBAIKVofMTa6XSApJTFqHlbRbxSIkvLiFeeAoSqlpSr1JJ1V1j
+YsrBV8ofWC3mK5p/UV/M6GwgL0b8YueNi21dlz3Zy/8Z97eBH6zSeLb74xf5P76YT9B2
+KW1e/8enbs/JtLrtKaIVbsj5FadPY4qUw+3DahS4p7O0J7lRaNqP/LkVAAAAFQDywJfU
+aYlN9GfOzUQB2NzU0WqrawAAAIA0xHHDxR9201VHQKtCPcCA9pc4YTh34bganheyS+cI
+fJxJUCO1jF5tSTNTO3lDp/8hpu4tR2B7eBetzwF62+twpun5dmAzT9WPYIViabLeKfqT
+MZmrsXDWxlqS7oA5Ty8trnCgFPa8BwcstPVssDOPu+IvTjxPox+Os495/yce8AAAAIBh
+DWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah/XcF3DeRF+eEoz48
+wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+UykSTXYUbtsfTNRFQGBW2
+/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0Cg==
+---- END SSH2 PUBLIC KEY ----
diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_rsa_key b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_rsa_key
new file mode 100644
index 0000000000..79968bdd7d
--- /dev/null
+++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_rsa_key
@@ -0,0 +1,16 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8semM4q843337
+zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RWRWzjaxSB
+6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4QIDAQAB
+AoGANmvJzJO5hkLuvyDZHKfAnGTtpifcR1wtSa9DjdKUyn8vhKF0mIimnbnYQEmW
+NUUb3gXCZLi9PvkpRSVRrASDOZwcjoU/Kvww163vBUVb2cOZfFhyn6o2Sk88Tt++
+udH3hdjpf9i7jTtUkUe+QYPsia+wgvvrmn4QrahLAH86+kECQQDx5gFeXTME3cnW
+WMpFz3PPumduzjqgqMMWEccX4FtQkMX/gyGa5UC7OHFyh0N/gSWvPbRHa8A6YgIt
+n8DO+fh5AkEAzbqX4DOn8NY6xJIi42q7l/2jIA0RkB6P7YugW5NblhqBZ0XDnpA5
+sMt+rz+K07u9XZtxgh1xi7mNfwY6lEAMqQJBAJBEauCKmRj35Z6OyeQku59SPsnY
++SJEREVvSNw2lH9SOKQQ4wPsYlTGbvKtNVZgAcen91L5MmYfeckYE/fdIZECQQCt
+64zxsTnM1I8iFxj/gP/OYlJBikrKt8udWmjaghzvLMEw+T2DExJyb9ZNeT53+UMB
+m6O+B/4xzU/djvp+0hbhAkAemIt+rA5kTmYlFndhpvzkSSM8a2EXsO4XIPgGWCTT
+tQKS/tTly0ADMjN/TVy11+9d6zcqadNVuHXHGtR4W0GR
+-----END RSA PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_rsa_key.pub b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_rsa_key.pub
new file mode 100644
index 0000000000..75d2025c71
--- /dev/null
+++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_rsa_key.pub
@@ -0,0 +1,5 @@
+---- BEGIN SSH2 PUBLIC KEY ----
+AAAAB3NzaC1yc2EAAAADAQABAAAAgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8
+semM4q843337zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RW
+RWzjaxSB6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4Q==
+---- END SSH2 PUBLIC KEY ----
diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl
index c96b6de3ea..7644db155d 100644
--- a/lib/ssh/test/ssh_sftp_SUITE.erl
+++ b/lib/ssh/test/ssh_sftp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -24,14 +24,12 @@
-compile(export_all).
-include_lib("common_test/include/ct.hrl").
--include("test_server_line.hrl").
-include_lib("kernel/include/file.hrl").
% Default timetrap timeout
-define(default_timeout, ?t:minutes(1)).
--define(SFPD_PORT, 9999).
-define(USER, "Alladin").
-define(PASSWD, "Sesame").
@@ -46,18 +44,12 @@
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- case {catch crypto:start(),catch ssh:start()} of
- {ok,ok} ->
- Dir = ?config(priv_dir, Config),
- {ok, _} = ssh_test_lib:get_id_keys(Dir),
- ssh_test_lib:make_dsa_files(Config),
+ case (catch crypto:start()) of
+ ok ->
+ ssh:start(),
Config;
- {ok,_} ->
- {skip,"Could not start ssh!"};
- {_,ok} ->
- {skip,"Could not start crypto!"};
- {_,_} ->
- {skip,"Could not start crypto and ssh!"}
+ _ ->
+ {skip,"Could not start crypto!"}
end.
%%--------------------------------------------------------------------
@@ -67,9 +59,8 @@ init_per_suite(Config) ->
%% Description: Cleanup after the whole suite
%%--------------------------------------------------------------------
end_per_suite(Config) ->
+ ssh:stop(),
crypto:stop(),
- Dir = ?config(priv_dir, Config),
- ssh_test_lib:remove_id_keys(Dir),
Config.
%%--------------------------------------------------------------------
@@ -90,27 +81,30 @@ init_per_testcase(_Case, Config) ->
TmpConfig0 = lists:keydelete(watchdog, 1, Config),
TmpConfig = lists:keydelete(sftp, 1, TmpConfig0),
Dog = test_server:timetrap(?default_timeout),
- Dir = ?config(priv_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
SysDir = ?config(data_dir, Config),
Host = ssh_test_lib:hostname(),
- Sftp = case (catch ssh_sftp:start_channel(Host,
- [{user_dir, Dir},
- {user_interaction, false},
+ %% Run test against openssh server if available
+ Sftp = case (catch ssh_sftp:start_channel(Host,
+ [{user_interaction, false},
{silently_accept_hosts, true}])) of
{ok, ChannelPid, Connection} ->
+ test_server:format("Running against openssh"),
{ChannelPid, Connection};
- _Error ->
- {_Sftpd, _Host, _Port} =
- ssh_test_lib:daemon(Host, ?SFPD_PORT,
- [{system_dir, SysDir},
+ _Error -> %% Start own sftp
+ test_server:format("Running against erlang ssh"),
+ {_Sftpd, Host1, Port} =
+ ssh_test_lib:daemon([{system_dir, SysDir},
+ {user_dir, PrivDir},
{user_passwords,
[{?USER, ?PASSWD}]},
{failfun,
fun ssh_test_lib:failfun/2}]),
- Result = (catch ssh_sftp:start_channel(Host, ?SFPD_PORT,
+ Result = (catch ssh_sftp:start_channel(Host1, Port,
[{user, ?USER},
{password, ?PASSWD},
+ {user_dir, PrivDir},
{user_interaction, false},
{silently_accept_hosts, true}])),
{ok, ChannelPid, Connection} = Result,
diff --git a/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa b/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa
deleted file mode 100644
index 7e3f885f5d..0000000000
--- a/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa
+++ /dev/null
@@ -1,15 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIICWwIBAAKBgQDLKYTdRnGzphcN+pF8UuI3sYB7rxZUHbOT87K3vh8XOLkDOsS3
-8VREtNS8Wb3uYXsRtyDoUvrLIDnyllOfJSDupWLr4ibckUZd/nhFAaC6WryVmH6k
-GlQLLp9KU+vcn2DwYeo14gbwHYDB3pmv4CWAlnO1m/BkX4aLz1zC314OkQIBIwKB
-gD/Z2UzboBPjvhpWEHeHw3CW3zzQoJ4X9pw2peH57IOkHOPCA0/A3/hWFvleCH4e
-owWRU3w3ViKVGYbBh/7RJ5rllN+ENUmVn536srJTxLKUtvb5jRGj3W6EWgAGHSUB
-hm83Kt9Lb5hprL7dPrNGvSseBm/LQSfBQ4vUUyiVRKGPAkEA/rPxWoLdBBP+FZtE
-fGzz9izPM6Fe6o8ZGNZIlRBProOhgEvvIqdgzQWObgLVVrw+M/YApPpiYS3PEmWj
-b2b+jwJBAMwyYeL6coKTl8swDu8HvLnshgUFJFTtHhOTXsKtXQNI1b24xhUrB3Sb
-X8fmoByyRNRpOfvg4Jdqi3Z6KfIcsN8CQQDEfC83McBw3DkJWoVKCugVrYnmACSm
-USH9N5cT6AL0VupNB2C0VTwL37cEaJXyc/V4ipLIaWHV8CNl9qKmZWVJAkEAurG4
-lQI8zyfbPW3EgsU+1d+QeZ5NGnJkpC73jWtNudwxIn0M4CdXRgpmMxwAGjyWs5No
-Nr75OfsDKn5SPHIAywJAKrtONlOizgDiG3EvAXZlwFtOb+HkQ7lrFwczrQu9m7yi
-brSAcnTrLKI6CrR33b/QJLvb9C/HTEZojFABGq8M7A==
------END RSA PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa.pub b/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa.pub
deleted file mode 100644
index 77f57de4af..0000000000
--- a/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAyymE3UZxs6YXDfqRfFLiN7GAe68WVB2zk/Oyt74fFzi5AzrEt/FURLTUvFm97mF7Ebcg6FL6yyA58pZTnyUg7qVi6+Im3JFGXf54RQGgulq8lZh+pBpUCy6fSlPr3J9g8GHqNeIG8B2Awd6Zr+AlgJZztZvwZF+Gi89cwt9eDpE= jakob@balin
diff --git a/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key
new file mode 100644
index 0000000000..51ab6fbd88
--- /dev/null
+++ b/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key
@@ -0,0 +1,13 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBuwIBAAKBgQCClaHzE2ul0gKSUxah5W0W8UiJLy4hXngKEqpaUq9SSdVdY2LK
+wVfKH1gt5iuaf1FfzOhsIC9G/GLnjYttXZc92cv/Gfe3gR+s0ni2++MX+T++mE/Q
+diltXv/Hp27PybS67SmiFW7I+RWnT2OKlMPtw2oUuKeztCe5UWjaj/y5FQIVAPLA
+l9RpiU30Z87NRAHY3NTRaqtrAoGANMRxw8UfdtNVR0CrQj3AgPaXOGE4d+G4Gp4X
+skvnCHycSVAjtYxebUkzUzt5Q6f/IabuLUdge3gXrc8BetvrcKbp+XZgM0/Vj2CF
+Ymmy3in6kzGZq7Fw1sZaku6AOU8vLa5woBT2vAcHLLT1bLAzj7viL048T6MfjrOP
+ef8nHvACgYBhDWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah
+/XcF3DeRF+eEoz48wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+U
+ykSTXYUbtsfTNRFQGBW2/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0CgIVAN4wtL5W
+Lv62jKcdskxNyz2NQoBx
+-----END DSA PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key.pub
new file mode 100644
index 0000000000..4dbb1305b0
--- /dev/null
+++ b/lib/ssh/test/ssh_sftp_SUITE_data/ssh_host_dsa_key.pub
@@ -0,0 +1,11 @@
+---- BEGIN SSH2 PUBLIC KEY ----
+AAAAB3NzaC1kc3MAAACBAIKVofMTa6XSApJTFqHlbRbxSIkvLiFeeAoSqlpSr1JJ1V1j
+YsrBV8ofWC3mK5p/UV/M6GwgL0b8YueNi21dlz3Zy/8Z97eBH6zSeLb74xf5P76YT9B2
+KW1e/8enbs/JtLrtKaIVbsj5FadPY4qUw+3DahS4p7O0J7lRaNqP/LkVAAAAFQDywJfU
+aYlN9GfOzUQB2NzU0WqrawAAAIA0xHHDxR9201VHQKtCPcCA9pc4YTh34bganheyS+cI
+fJxJUCO1jF5tSTNTO3lDp/8hpu4tR2B7eBetzwF62+twpun5dmAzT9WPYIViabLeKfqT
+MZmrsXDWxlqS7oA5Ty8trnCgFPa8BwcstPVssDOPu+IvTjxPox+Os495/yce8AAAAIBh
+DWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah/XcF3DeRF+eEoz48
+wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+UykSTXYUbtsfTNRFQGBW2
+/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0Cg==
+---- END SSH2 PUBLIC KEY ----
diff --git a/lib/ssh/test/ssh_sftpd_SUITE.erl b/lib/ssh/test/ssh_sftpd_SUITE.erl
index bfe54a3e75..6e4480ee9d 100644
--- a/lib/ssh/test/ssh_sftpd_SUITE.erl
+++ b/lib/ssh/test/ssh_sftpd_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -53,16 +53,18 @@
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- case {catch ssh:stop(),catch crypto:start()} of
- {ok,ok} ->
- ssh_test_lib:make_dsa_files(Config),
+ case (catch crypto:start()) of
+ ok ->
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ ssh_test_lib:setup_dsa(DataDir, PrivDir),
+ %% to make sure we don't use public-key-auth
+ %% this should be tested by other test suites
+ UserDir = filename:join(?config(priv_dir, Config), nopubkey),
+ file:make_dir(UserDir),
Config;
- {ok,_} ->
- {skip,"Could not start ssh!"};
- {_,ok} ->
- {skip,"Could not start crypto!"};
- {_,_} ->
- {skip,"Could not start crypto and ssh!"}
+ _ ->
+ {skip,"Could not start crypto!"}
end.
%%--------------------------------------------------------------------
@@ -71,7 +73,12 @@ init_per_suite(Config) ->
%% A list of key/value pairs, holding the test case configuration.
%% Description: Cleanup after the whole suite
%%--------------------------------------------------------------------
-end_per_suite(_Config) ->
+end_per_suite(Config) ->
+ SysDir = ?config(priv_dir, Config),
+ ssh_test_lib:clean_dsa(SysDir),
+ UserDir = filename:join(?config(priv_dir, Config), nopubkey),
+ file:del_dir(UserDir),
+ ssh:stop(),
crypto:stop(),
ok.
@@ -91,15 +98,18 @@ end_per_suite(_Config) ->
init_per_testcase(TestCase, Config) ->
ssh:start(),
prep(Config),
- SysDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ ClientUserDir = filename:join(PrivDir, nopubkey),
+ SystemDir = filename:join(?config(priv_dir, Config), system),
+
{ok, Sftpd} =
- ssh_sftpd:listen(?SFPD_PORT, [{system_dir, SysDir},
+ ssh_sftpd:listen(?SFPD_PORT, [{system_dir, SystemDir},
+ {user_dir, PrivDir},
{user_passwords,[{?USER, ?PASSWD}]},
{pwdfun, fun(_,_) -> true end}]),
Cm = ssh_test_lib:connect(?SFPD_PORT,
- [{system_dir, SysDir},
- {user_dir, SysDir},
+ [{user_dir, ClientUserDir},
{user, ?USER}, {password, ?PASSWD},
{user_interaction, false},
{silently_accept_hosts, true},
@@ -542,7 +552,7 @@ set_attributes(Config) when is_list(Config) ->
{ok, FileInfo} = file:read_file_info(FileName),
OrigPermissions = FileInfo#file_info.mode,
- Permissions = 8#400, %% User read-only
+ Permissions = 8#600, %% User read-write-only
Flags = ?SSH_FILEXFER_ATTR_PERMISSIONS,
diff --git a/lib/ssh/test/ssh_sftpd_SUITE_data/id_dsa b/lib/ssh/test/ssh_sftpd_SUITE_data/id_dsa
new file mode 100644
index 0000000000..d306f8b26e
--- /dev/null
+++ b/lib/ssh/test/ssh_sftpd_SUITE_data/id_dsa
@@ -0,0 +1,13 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBvAIBAAKBgQDfi2flSTZZofwT4yQT0NikX/LGNT7UPeB/XEWe/xovEYCElfaQ
+APFixXvEgXwoojmZ5kiQRKzLM39wBP0jPERLbnZXfOOD0PDnw0haMh7dD7XKVMod
+/EigVgHf/qBdM2M8yz1s/rRF7n1UpLSypziKjkzCm7JoSQ2zbWIPdmBIXwIVAMgP
+kpr7Sq3O7sHdb8D601DRjoExAoGAMOQxDfB2Fd8ouz6G96f/UOzRMI/Kdv8kYYKW
+JIGY+pRYrLPyYzUeJznwZreOJgrczAX+luHnKFWJ2Dnk5CyeXk67Wsr7pJ/4MBMD
+OKeIS0S8qoSBN8+Krp79fgA+yS3IfqbkJLtLu4EBaCX4mKQIX4++k44d4U5lc8pt
++9hlEI8CgYEAznKxx9kyC6bVo7LUYKaGhofRFt0SYFc5PVmT2VUGRs1R6+6DPD+e
+uEO6IhFct7JFSRbP9p0JD4Uk+3zlZF+XX6b2PsZkeV8f/02xlNGUSmEzCSiNg1AX
+Cy/WusYhul0MncWCHMcOZB5rIvU/aP5EJJtn3xrRaz6u0SThF6AnT34CFQC63czE
+ZU8w8Q+H7z0j+a+70x2iAw==
+-----END DSA PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key
new file mode 100644
index 0000000000..51ab6fbd88
--- /dev/null
+++ b/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key
@@ -0,0 +1,13 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBuwIBAAKBgQCClaHzE2ul0gKSUxah5W0W8UiJLy4hXngKEqpaUq9SSdVdY2LK
+wVfKH1gt5iuaf1FfzOhsIC9G/GLnjYttXZc92cv/Gfe3gR+s0ni2++MX+T++mE/Q
+diltXv/Hp27PybS67SmiFW7I+RWnT2OKlMPtw2oUuKeztCe5UWjaj/y5FQIVAPLA
+l9RpiU30Z87NRAHY3NTRaqtrAoGANMRxw8UfdtNVR0CrQj3AgPaXOGE4d+G4Gp4X
+skvnCHycSVAjtYxebUkzUzt5Q6f/IabuLUdge3gXrc8BetvrcKbp+XZgM0/Vj2CF
+Ymmy3in6kzGZq7Fw1sZaku6AOU8vLa5woBT2vAcHLLT1bLAzj7viL048T6MfjrOP
+ef8nHvACgYBhDWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah
+/XcF3DeRF+eEoz48wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+U
+ykSTXYUbtsfTNRFQGBW2/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0CgIVAN4wtL5W
+Lv62jKcdskxNyz2NQoBx
+-----END DSA PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key.pub
new file mode 100644
index 0000000000..4dbb1305b0
--- /dev/null
+++ b/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key.pub
@@ -0,0 +1,11 @@
+---- BEGIN SSH2 PUBLIC KEY ----
+AAAAB3NzaC1kc3MAAACBAIKVofMTa6XSApJTFqHlbRbxSIkvLiFeeAoSqlpSr1JJ1V1j
+YsrBV8ofWC3mK5p/UV/M6GwgL0b8YueNi21dlz3Zy/8Z97eBH6zSeLb74xf5P76YT9B2
+KW1e/8enbs/JtLrtKaIVbsj5FadPY4qUw+3DahS4p7O0J7lRaNqP/LkVAAAAFQDywJfU
+aYlN9GfOzUQB2NzU0WqrawAAAIA0xHHDxR9201VHQKtCPcCA9pc4YTh34bganheyS+cI
+fJxJUCO1jF5tSTNTO3lDp/8hpu4tR2B7eBetzwF62+twpun5dmAzT9WPYIViabLeKfqT
+MZmrsXDWxlqS7oA5Ty8trnCgFPa8BwcstPVssDOPu+IvTjxPox+Os495/yce8AAAAIBh
+DWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah/XcF3DeRF+eEoz48
+wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+UykSTXYUbtsfTNRFQGBW2
+/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0Cg==
+---- END SSH2 PUBLIC KEY ----
diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl
index 2209af05d5..4c469ed5f7 100644
--- a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl
+++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -28,7 +28,6 @@
-include_lib("kernel/include/file.hrl").
--define(SSHD_PORT, 9999).
-define(USER, "Alladin").
-define(PASSWD, "Sesame").
-define(SSH_MAX_PACKET_SIZE, 32768).
@@ -48,13 +47,14 @@ init_per_suite(Config) ->
case catch crypto:start() of
ok ->
DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
FileAlt = filename:join(DataDir, "ssh_sftpd_file_alt.erl"),
c:c(FileAlt),
FileName = filename:join(DataDir, "test.txt"),
{ok, FileInfo} = file:read_file_info(FileName),
ok = file:write_file_info(FileName,
FileInfo#file_info{mode = 8#400}),
- ssh_test_lib:make_dsa_files(Config),
+ ssh_test_lib:setup_dsa(DataDir, PrivDir),
Config;
_Else ->
{skip,"Could not start ssh!"}
@@ -66,7 +66,11 @@ init_per_suite(Config) ->
%% A list of key/value pairs, holding the test case configuration.
%% Description: Cleanup after the whole suite
%%--------------------------------------------------------------------
-end_per_suite(_Config) ->
+end_per_suite(Config) ->
+ UserDir = filename:join(?config(priv_dir, Config), nopubkey),
+ file:del_dir(UserDir),
+ SysDir = ?config(priv_dir, Config),
+ ssh_test_lib:clean_dsa(SysDir),
crypto:stop(),
ok.
@@ -85,7 +89,8 @@ end_per_suite(_Config) ->
%%--------------------------------------------------------------------
init_per_testcase(TestCase, Config) ->
ssh:start(),
- DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ SystemDir = filename:join(PrivDir, system),
Options =
case atom_to_list(TestCase) of
@@ -93,50 +98,39 @@ init_per_testcase(TestCase, Config) ->
Spec =
ssh_sftpd:subsystem_spec([{file_handler,
ssh_sftpd_file_alt}]),
- [{user_passwords,[{?USER, ?PASSWD}]},
- {pwdfun, fun(_,_) -> true end},
- {system_dir, DataDir},
- {user_dir, DataDir},
+ [{system_dir, SystemDir},
+ {user_dir, PrivDir},
{subsystems, [Spec]}];
"root_dir" ->
Privdir = ?config(priv_dir, Config),
Root = filename:join(Privdir, root),
file:make_dir(Root),
Spec = ssh_sftpd:subsystem_spec([{root,Root}]),
- [{user_passwords,[{?USER, ?PASSWD}]},
- {pwdfun, fun(_,_) -> true end},
- {system_dir, DataDir},
- {user_dir, DataDir},
+ [{system_dir, SystemDir},
+ {user_dir, PrivDir},
{subsystems, [Spec]}];
"list_dir_limited" ->
Spec =
ssh_sftpd:subsystem_spec([{max_files,1}]),
- [{user_passwords,[{?USER, ?PASSWD}]},
- {pwdfun, fun(_,_) -> true end},
- {system_dir, DataDir},
- {user_dir, DataDir},
+ [{system_dir, SystemDir},
+ {user_dir, PrivDir},
{subsystems, [Spec]}];
_ ->
- [{user_passwords,[{?USER, ?PASSWD}]},
- {pwdfun, fun(_,_) -> true end},
- {user_dir, DataDir},
- {system_dir, DataDir}]
+ [{user_dir, PrivDir},
+ {system_dir, SystemDir}]
end,
- {Sftpd, Host, _Port} = ssh_test_lib:daemon(any, ?SSHD_PORT, Options),
+ {Sftpd, Host, Port} = ssh_test_lib:daemon(Options),
{ok, ChannelPid, Connection} =
- ssh_sftp:start_channel(Host, ?SSHD_PORT,
+ ssh_sftp:start_channel(Host, Port,
[{silently_accept_hosts, true},
- {user, ?USER}, {password, ?PASSWD},
- {pwdfun, fun(_,_) -> true end},
- {system_dir, DataDir},
- {user_dir, DataDir},
+ {user_dir, PrivDir},
{timeout, 30000}]),
TmpConfig = lists:keydelete(sftp, 1, Config),
NewConfig = lists:keydelete(sftpd, 1, TmpConfig),
- [{sftp, {ChannelPid, Connection}}, {sftpd, Sftpd} | NewConfig].
+ [{port, Port}, {sftp, {ChannelPid, Connection}}, {sftpd, Sftpd} | NewConfig].
%%--------------------------------------------------------------------
%% Function: end_per_testcase(TestCase, Config) -> _
@@ -216,6 +210,8 @@ quit_OTP_6349(suite) ->
quit_OTP_6349(Config) when is_list(Config) ->
DataDir = ?config(data_dir, Config),
FileName = filename:join(DataDir, "test.txt"),
+ UserDir = ?config(priv_dir, Config),
+ Port = ?config(port, Config),
{Sftp, _} = ?config(sftp, Config),
@@ -226,11 +222,10 @@ quit_OTP_6349(Config) when is_list(Config) ->
Host = ssh_test_lib:hostname(),
timer:sleep(5000),
- {ok, NewSftp, _Conn} = ssh_sftp:start_channel(Host, ?SSHD_PORT,
+ {ok, NewSftp, _Conn} = ssh_sftp:start_channel(Host, Port,
[{silently_accept_hosts, true},
{pwdfun, fun(_,_) -> true end},
- {system_dir, DataDir},
- {user_dir, DataDir},
+ {user_dir, UserDir},
{user, ?USER}, {password, ?PASSWD}]),
{ok, <<_/binary>>} = ssh_sftp:read_file(NewSftp, FileName),
diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/id_dsa b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/id_dsa
new file mode 100644
index 0000000000..d306f8b26e
--- /dev/null
+++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/id_dsa
@@ -0,0 +1,13 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBvAIBAAKBgQDfi2flSTZZofwT4yQT0NikX/LGNT7UPeB/XEWe/xovEYCElfaQ
+APFixXvEgXwoojmZ5kiQRKzLM39wBP0jPERLbnZXfOOD0PDnw0haMh7dD7XKVMod
+/EigVgHf/qBdM2M8yz1s/rRF7n1UpLSypziKjkzCm7JoSQ2zbWIPdmBIXwIVAMgP
+kpr7Sq3O7sHdb8D601DRjoExAoGAMOQxDfB2Fd8ouz6G96f/UOzRMI/Kdv8kYYKW
+JIGY+pRYrLPyYzUeJznwZreOJgrczAX+luHnKFWJ2Dnk5CyeXk67Wsr7pJ/4MBMD
+OKeIS0S8qoSBN8+Krp79fgA+yS3IfqbkJLtLu4EBaCX4mKQIX4++k44d4U5lc8pt
++9hlEI8CgYEAznKxx9kyC6bVo7LUYKaGhofRFt0SYFc5PVmT2VUGRs1R6+6DPD+e
+uEO6IhFct7JFSRbP9p0JD4Uk+3zlZF+XX6b2PsZkeV8f/02xlNGUSmEzCSiNg1AX
+Cy/WusYhul0MncWCHMcOZB5rIvU/aP5EJJtn3xrRaz6u0SThF6AnT34CFQC63czE
+ZU8w8Q+H7z0j+a+70x2iAw==
+-----END DSA PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key
new file mode 100644
index 0000000000..51ab6fbd88
--- /dev/null
+++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key
@@ -0,0 +1,13 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBuwIBAAKBgQCClaHzE2ul0gKSUxah5W0W8UiJLy4hXngKEqpaUq9SSdVdY2LK
+wVfKH1gt5iuaf1FfzOhsIC9G/GLnjYttXZc92cv/Gfe3gR+s0ni2++MX+T++mE/Q
+diltXv/Hp27PybS67SmiFW7I+RWnT2OKlMPtw2oUuKeztCe5UWjaj/y5FQIVAPLA
+l9RpiU30Z87NRAHY3NTRaqtrAoGANMRxw8UfdtNVR0CrQj3AgPaXOGE4d+G4Gp4X
+skvnCHycSVAjtYxebUkzUzt5Q6f/IabuLUdge3gXrc8BetvrcKbp+XZgM0/Vj2CF
+Ymmy3in6kzGZq7Fw1sZaku6AOU8vLa5woBT2vAcHLLT1bLAzj7viL048T6MfjrOP
+ef8nHvACgYBhDWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah
+/XcF3DeRF+eEoz48wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+U
+ykSTXYUbtsfTNRFQGBW2/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0CgIVAN4wtL5W
+Lv62jKcdskxNyz2NQoBx
+-----END DSA PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key.pub
new file mode 100644
index 0000000000..4dbb1305b0
--- /dev/null
+++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key.pub
@@ -0,0 +1,11 @@
+---- BEGIN SSH2 PUBLIC KEY ----
+AAAAB3NzaC1kc3MAAACBAIKVofMTa6XSApJTFqHlbRbxSIkvLiFeeAoSqlpSr1JJ1V1j
+YsrBV8ofWC3mK5p/UV/M6GwgL0b8YueNi21dlz3Zy/8Z97eBH6zSeLb74xf5P76YT9B2
+KW1e/8enbs/JtLrtKaIVbsj5FadPY4qUw+3DahS4p7O0J7lRaNqP/LkVAAAAFQDywJfU
+aYlN9GfOzUQB2NzU0WqrawAAAIA0xHHDxR9201VHQKtCPcCA9pc4YTh34bganheyS+cI
+fJxJUCO1jF5tSTNTO3lDp/8hpu4tR2B7eBetzwF62+twpun5dmAzT9WPYIViabLeKfqT
+MZmrsXDWxlqS7oA5Ty8trnCgFPa8BwcstPVssDOPu+IvTjxPox+Os495/yce8AAAAIBh
+DWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah/XcF3DeRF+eEoz48
+wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+UykSTXYUbtsfTNRFQGBW2
+/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0Cg==
+---- END SSH2 PUBLIC KEY ----
diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl
index 425fae22c1..26bbdf5c5c 100644
--- a/lib/ssh/test/ssh_test_lib.erl
+++ b/lib/ssh/test/ssh_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -68,15 +68,14 @@ daemon(Host, Port, Options) ->
Error
end.
-
-
+start_shell(Port, IOServer, UserDir) ->
+ spawn_link(?MODULE, init_shell, [Port, IOServer, [{user_dir, UserDir}]]).
start_shell(Port, IOServer) ->
- spawn_link(?MODULE, init_shell, [Port, IOServer]).
+ spawn_link(?MODULE, init_shell, [Port, IOServer, []]).
-init_shell(Port, IOServer) ->
+init_shell(Port, IOServer, UserDir) ->
Host = hostname(),
- UserDir = get_user_dir(),
Options = [{user_interaction, false}, {silently_accept_hosts,
true}] ++ UserDir,
group_leader(IOServer, self()),
@@ -95,13 +94,10 @@ init_io_server(TestCase) ->
loop_io_server(TestCase, Buff0) ->
receive
{input, TestCase, Line} ->
- %io:format("~p~n",[{input, TestCase, Line}]),
loop_io_server(TestCase, Buff0 ++ [Line]);
{io_request, From, ReplyAs, Request} ->
- %io:format("request -> ~p~n",[Request]),
{ok, Reply, Buff} = io_request(Request, TestCase, From,
ReplyAs, Buff0),
- %io:format("reply -> ~p~n",[Reply]),
io_reply(From, ReplyAs, Reply),
loop_io_server(TestCase, Buff);
{'EXIT',_, _} ->
@@ -139,12 +135,18 @@ reply(TestCase, Result) ->
receive_exec_result(Msg) ->
test_server:format("Expect data! ~p", [Msg]),
receive
+ {ssh_cm,_,{data,_,1, Data}} ->
+ test_server:format("StdErr: ~p~n", [Data]),
+ receive_exec_result(Msg);
Msg ->
test_server:format("1: Collected data ~p", [Msg]),
expected;
Other ->
+ test_server:format("Other ~p", [Other]),
{unexpected_msg, Other}
end.
+
+
receive_exec_end(ConnectionRef, ChannelId) ->
Eof = {ssh_cm, ConnectionRef, {eof, ChannelId}},
ExitStatus = {ssh_cm, ConnectionRef, {exit_status, ChannelId, 0}},
@@ -181,27 +183,21 @@ inet_port()->
gen_tcp:close(Socket),
Port.
-
-%% copy private keys to given dir from ~/.ssh
-get_id_keys(DstDir) ->
- SrcDir = filename:join(os:getenv("HOME"), ".ssh"),
- RsaOk = copyfile(SrcDir, DstDir, "id_rsa"),
- DsaOk = copyfile(SrcDir, DstDir, "id_dsa"),
- case {RsaOk, DsaOk} of
- {{ok, _}, {ok, _}} -> {ok, both};
- {{ok, _}, _} -> {ok, rsa};
- {_, {ok, _}} -> {ok, dsa};
- {Error, _} -> Error
- end.
-
-remove_id_keys(Dir) ->
- file:delete(filename:join(Dir, "id_rsa")),
- file:delete(filename:join(Dir, "id_dsa")).
-
-copyfile(SrcDir, DstDir, Fn) ->
- file:copy(filename:join(SrcDir, Fn),
- filename:join(DstDir, Fn)).
-
+setup_ssh_auth_keys(RSAFile, DSAFile, Dir) ->
+ Entries = ssh_file_entry(RSAFile) ++ ssh_file_entry(DSAFile),
+ AuthKeys = public_key:ssh_encode(Entries , auth_keys),
+ AuthKeysFile = filename:join(Dir, "authorized_keys"),
+ file:write_file(AuthKeysFile, AuthKeys).
+
+ssh_file_entry(PubFile) ->
+ case file:read_file(PubFile) of
+ {ok, Ssh} ->
+ [{Key, _}] = public_key:ssh_decode(Ssh, public_key),
+ [{Key, [{comment, "Test"}]}];
+ _ ->
+ []
+ end.
+
failfun(_User, {authmethod,none}) ->
ok;
failfun(User, Reason) ->
@@ -222,463 +218,123 @@ known_hosts(BR) ->
file:rename(B, KnownHosts)
end.
-
-get_user_dir() ->
- case os:type() of
- {win32, _} ->
- [{user_dir, filename:join([os:getenv("HOME"), ".ssh"])}];
- _ ->
- []
- end.
-
-
-make_dsa_cert_files(Config) ->
- make_dsa_cert_files("", Config).
-
-make_dsa_cert_files(RoleStr, Config) ->
-
- CaInfo = {CaCert, _} = make_cert([{key, dsa}]),
- {Cert, CertKey} = make_cert([{key, dsa}, {issuer, CaInfo}]),
- CaCertFile = filename:join([?config(data_dir, Config),
- RoleStr, "dsa_cacerts.pem"]),
- CertFile = filename:join([?config(data_dir, Config),
- RoleStr, "dsa_cert.pem"]),
- KeyFile = filename:join([?config(data_dir, Config),
- RoleStr, "dsa_key.pem"]),
+setup_dsa(DataDir, UserDir) ->
+ file:copy(filename:join(DataDir, "id_dsa"), filename:join(UserDir, "id_dsa")),
+ System = filename:join(UserDir, "system"),
+ file:make_dir(System),
+ file:copy(filename:join(DataDir, "ssh_host_dsa_key"), filename:join(System, "ssh_host_dsa_key")),
+ file:copy(filename:join(DataDir, "ssh_host_dsa_key.pub"), filename:join(System, "ssh_host_dsa_key.pub")),
+ setup_dsa_known_host(DataDir, UserDir),
+ setup_dsa_auth_keys(DataDir, UserDir).
- der_to_pem(CaCertFile, [{'Certificate', CaCert, not_encrypted}]),
- der_to_pem(CertFile, [{'Certificate', Cert, not_encrypted}]),
- der_to_pem(KeyFile, [CertKey]),
- {CaCertFile, CertFile, KeyFile}.
-
-make_dsa_files(Config) ->
- make_dsa_files(Config, rfc4716_public_key).
-make_dsa_files(Config, Type) ->
- {DSA, EncodedKey} = ssh_test_lib:gen_dsa(128, 20),
- PKey = DSA#'DSAPrivateKey'.y,
- P = DSA#'DSAPrivateKey'.p,
- Q = DSA#'DSAPrivateKey'.q,
- G = DSA#'DSAPrivateKey'.g,
- Dss = #'Dss-Parms'{p=P, q=Q, g=G},
+setup_rsa(DataDir, UserDir) ->
+ file:copy(filename:join(DataDir, "id_rsa"), filename:join(UserDir, "id_rsa")),
+ System = filename:join(UserDir, "system"),
+ file:make_dir(System),
+ file:copy(filename:join(DataDir, "ssh_host_rsa_key"), filename:join(System, "ssh_host_rsa_key")),
+ file:copy(filename:join(DataDir, "ssh_host_rsa_key"), filename:join(System, "ssh_host_rsa_key.pub")),
+ setup_rsa_known_host(DataDir, UserDir),
+ setup_rsa_auth_keys(DataDir, UserDir).
+
+clean_dsa(UserDir) ->
+ del_dirs(filename:join(UserDir, "system")),
+ file:delete(filename:join(UserDir,"id_dsa")),
+ file:delete(filename:join(UserDir,"known_hosts")),
+ file:delete(filename:join(UserDir,"authorized_keys")).
+
+clean_rsa(UserDir) ->
+ del_dirs(filename:join(UserDir, "system")),
+ file:delete(filename:join(UserDir,"id_rsa")),
+ file:delete(filename:join(UserDir,"known_hosts")),
+ file:delete(filename:join(UserDir,"authorized_keys")).
+
+setup_dsa_pass_pharse(DataDir, UserDir, Phrase) ->
+ {ok, KeyBin} = file:read_file(filename:join(DataDir, "id_dsa")),
+ setup_pass_pharse(KeyBin, filename:join(UserDir, "id_dsa"), Phrase),
+ System = filename:join(UserDir, "system"),
+ file:make_dir(System),
+ file:copy(filename:join(DataDir, "ssh_host_dsa_key"), filename:join(System, "ssh_host_dsa_key")),
+ file:copy(filename:join(DataDir, "ssh_host_dsa_key.pub"), filename:join(System, "ssh_host_dsa_key.pub")),
+ setup_dsa_known_host(DataDir, UserDir),
+ setup_dsa_auth_keys(DataDir, UserDir).
+
+setup_rsa_pass_pharse(DataDir, UserDir, Phrase) ->
+ {ok, KeyBin} = file:read_file(filename:join(DataDir, "id_rsa")),
+ setup_pass_pharse(KeyBin, filename:join(UserDir, "id_rsa"), Phrase),
+ System = filename:join(UserDir, "system"),
+ file:make_dir(System),
+ file:copy(filename:join(DataDir, "ssh_host_rsa_key"), filename:join(System, "ssh_host_rsa_key")),
+ file:copy(filename:join(DataDir, "ssh_host_rsa_key.pub"), filename:join(System, "ssh_host_rsa_key.pub")),
+ setup_rsa_known_host(DataDir, UserDir),
+ setup_rsa_auth_keys(DataDir, UserDir).
+
+setup_pass_pharse(KeyBin, OutFile, Phrase) ->
+ [{KeyType, _,_} = Entry0] = public_key:pem_decode(KeyBin),
+ Key = public_key:pem_entry_decode(Entry0),
+ Salt = crypto:rand_bytes(8),
+ Entry = public_key:pem_entry_encode(KeyType, Key,
+ {{"DES-CBC", Salt}, Phrase}),
+ Pem = public_key:pem_encode([Entry]),
+ file:write_file(OutFile, Pem).
+
+setup_dsa_known_host(SystemDir, UserDir) ->
+ {ok, SshBin} = file:read_file(filename:join(SystemDir, "ssh_host_dsa_key.pub")),
+ [{Key, _}] = public_key:ssh_decode(SshBin, public_key),
+ setup_known_hosts(Key, UserDir).
+
+setup_rsa_known_host(SystemDir, UserDir) ->
+ {ok, SshBin} = file:read_file(filename:join(SystemDir, "ssh_host_rsa_key.pub")),
+ [{Key, _}] = public_key:ssh_decode(SshBin, public_key),
+ setup_known_hosts(Key, UserDir).
+
+setup_known_hosts(Key, UserDir) ->
{ok, Hostname} = inet:gethostname(),
{ok, {A, B, C, D}} = inet:getaddr(Hostname, inet),
IP = lists:concat([A, ".", B, ".", C, ".", D]),
- Attributes = [], % Could be [{comment,"user@" ++ Hostname}],
- HostNames = [{hostnames,[IP, IP]}],
- PublicKey = [{{PKey, Dss}, Attributes}],
- KnownHosts = [{{PKey, Dss}, HostNames}],
-
+ HostNames = [{hostnames,[Hostname, IP]}],
+ KnownHosts = [{Key, HostNames}],
KnownHostsEnc = public_key:ssh_encode(KnownHosts, known_hosts),
- KnownHosts = public_key:ssh_decode(KnownHostsEnc, known_hosts),
-
- PublicKeyEnc = public_key:ssh_encode(PublicKey, Type),
-% PublicKey = public_key:ssh_decode(PublicKeyEnc, Type),
-
- SystemTmpDir = ?config(data_dir, Config),
- filelib:ensure_dir(SystemTmpDir),
- file:make_dir(SystemTmpDir),
-
- DSAFile = filename:join(SystemTmpDir, "ssh_host_dsa_key.pub"),
- file:delete(DSAFile),
-
- DSAPrivateFile = filename:join(SystemTmpDir, "ssh_host_dsa_key"),
- file:delete(DSAPrivateFile),
+ KHFile = filename:join(UserDir, "known_hosts"),
+ file:write_file(KHFile, KnownHostsEnc).
- KHFile = filename:join(SystemTmpDir, "known_hosts"),
- file:delete(KHFile),
-
- PemBin = public_key:pem_encode([EncodedKey]),
-
- file:write_file(DSAFile, PublicKeyEnc),
- file:write_file(KHFile, KnownHostsEnc),
- file:write_file(DSAPrivateFile, PemBin),
- ok.
-
-%%--------------------------------------------------------------------
-%% Create and return a der encoded certificate
-%% Option Default
-%% -------------------------------------------------------
-%% digest sha1
-%% validity {date(), date() + week()}
-%% version 3
-%% subject [] list of the following content
-%% {name, Name}
-%% {email, Email}
-%% {city, City}
-%% {state, State}
-%% {org, Org}
-%% {org_unit, OrgUnit}
-%% {country, Country}
-%% {serial, Serial}
-%% {title, Title}
-%% {dnQualifer, DnQ}
-%% issuer = {Issuer, IssuerKey} true (i.e. a ca cert is created)
-%% (obs IssuerKey migth be {Key, Password}
-%% key = KeyFile|KeyBin|rsa|dsa Subject PublicKey rsa or dsa generates key
-%%
-%%
-%% (OBS: The generated keys are for testing only)
-%% make_cert([{::atom(), ::term()}]) -> {Cert::binary(), Key::binary()}
-%%--------------------------------------------------------------------
-make_cert(Opts) ->
- SubjectPrivateKey = get_key(Opts),
- {TBSCert, IssuerKey} = make_tbs(SubjectPrivateKey, Opts),
- Cert = public_key:pkix_sign(TBSCert, IssuerKey),
- true = verify_signature(Cert, IssuerKey, undef), %% verify that the keys where ok
- {Cert, encode_key(SubjectPrivateKey)}.
-
-%%--------------------------------------------------------------------
-%% Writes cert files in Dir with FileName and FileName ++ Suffix
-%% write_cert(::string(), ::string(), {Cert,Key}) -> ok
-%%--------------------------------------------------------------------
-write_cert(Dir, FileName, Suffix, {Cert, Key = {_,_,not_encrypted}}) when is_binary(Cert) ->
- ok = der_to_pem(filename:join(Dir, FileName),
- [{'Certificate', Cert, not_encrypted}]),
- ok = der_to_pem(filename:join(Dir, FileName ++ Suffix), [Key]).
-
-%%--------------------------------------------------------------------
-%% Creates a rsa key (OBS: for testing only)
-%% the size are in bytes
-%% gen_rsa(::integer()) -> {::atom(), ::binary(), ::opaque()}
-%%--------------------------------------------------------------------
-gen_rsa(Size) when is_integer(Size) ->
- Key = gen_rsa2(Size),
- {Key, encode_key(Key)}.
-
-%%--------------------------------------------------------------------
-%% Creates a dsa key (OBS: for testing only)
-%% the sizes are in bytes
-%% gen_dsa(::integer()) -> {::atom(), ::binary(), ::opaque()}
-%%--------------------------------------------------------------------
-gen_dsa(LSize,NSize) when is_integer(LSize), is_integer(NSize) ->
- Key = gen_dsa2(LSize, NSize),
- {Key, encode_key(Key)}.
-
-%%--------------------------------------------------------------------
-%% Verifies cert signatures
-%% verify_signature(::binary(), ::tuple()) -> ::boolean()
-%%--------------------------------------------------------------------
-verify_signature(DerEncodedCert, DerKey, _KeyParams) ->
- Key = decode_key(DerKey),
- case Key of
- #'RSAPrivateKey'{modulus=Mod, publicExponent=Exp} ->
- public_key:pkix_verify(DerEncodedCert,
- #'RSAPublicKey'{modulus=Mod, publicExponent=Exp});
- #'DSAPrivateKey'{p=P, q=Q, g=G, y=Y} ->
- public_key:pkix_verify(DerEncodedCert, {Y, #'Dss-Parms'{p=P, q=Q, g=G}})
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%% Implementation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-get_key(Opts) ->
- case proplists:get_value(key, Opts) of
- undefined -> make_key(rsa, Opts);
- rsa -> make_key(rsa, Opts);
- dsa -> make_key(dsa, Opts);
- Key ->
- Password = proplists:get_value(password, Opts, no_passwd),
- decode_key(Key, Password)
- end.
-
-decode_key({Key, Pw}) ->
- decode_key(Key, Pw);
-decode_key(Key) ->
- decode_key(Key, no_passwd).
-
-
-decode_key(#'RSAPublicKey'{} = Key,_) ->
- Key;
-decode_key(#'RSAPrivateKey'{} = Key,_) ->
- Key;
-decode_key(#'DSAPrivateKey'{} = Key,_) ->
- Key;
-decode_key(PemEntry = {_,_,_}, Pw) ->
- public_key:pem_entry_decode(PemEntry, Pw);
-decode_key(PemBin, Pw) ->
- [KeyInfo] = public_key:pem_decode(PemBin),
- decode_key(KeyInfo, Pw).
-
-encode_key(Key = #'RSAPrivateKey'{}) ->
- {ok, Der} = 'OTP-PUB-KEY':encode('RSAPrivateKey', Key),
- {'RSAPrivateKey', list_to_binary(Der), not_encrypted};
-encode_key(Key = #'DSAPrivateKey'{}) ->
- {ok, Der} = 'OTP-PUB-KEY':encode('DSAPrivateKey', Key),
- {'DSAPrivateKey', list_to_binary(Der), not_encrypted}.
-
-make_tbs(SubjectKey, Opts) ->
- Version = list_to_atom("v"++integer_to_list(proplists:get_value(version, Opts, 3))),
-
- IssuerProp = proplists:get_value(issuer, Opts, true),
- {Issuer, IssuerKey} = issuer(IssuerProp, Opts, SubjectKey),
-
- {Algo, Parameters} = sign_algorithm(IssuerKey, Opts),
-
- SignAlgo = #'SignatureAlgorithm'{algorithm = Algo,
- parameters = Parameters},
- Subject = case IssuerProp of
- true -> %% Is a Root Ca
- Issuer;
- _ ->
- subject(proplists:get_value(subject, Opts),false)
- end,
-
- {#'OTPTBSCertificate'{serialNumber = trunc(random:uniform()*100000000)*10000 + 1,
- signature = SignAlgo,
- issuer = Issuer,
- validity = validity(Opts),
- subject = Subject,
- subjectPublicKeyInfo = publickey(SubjectKey),
- version = Version,
- extensions = extensions(Opts)
- }, IssuerKey}.
-
-issuer(true, Opts, SubjectKey) ->
- %% Self signed
- {subject(proplists:get_value(subject, Opts), true), SubjectKey};
-issuer({Issuer, IssuerKey}, _Opts, _SubjectKey) when is_binary(Issuer) ->
- {issuer_der(Issuer), decode_key(IssuerKey)};
-issuer({File, IssuerKey}, _Opts, _SubjectKey) when is_list(File) ->
- {ok, [{cert, Cert, _}|_]} = pem_to_der(File),
- {issuer_der(Cert), decode_key(IssuerKey)}.
-
-issuer_der(Issuer) ->
- Decoded = public_key:pkix_decode_cert(Issuer, otp),
- #'OTPCertificate'{tbsCertificate=Tbs} = Decoded,
- #'OTPTBSCertificate'{subject=Subject} = Tbs,
- Subject.
-
-subject(undefined, IsRootCA) ->
- User = if IsRootCA -> "RootCA"; true -> os:getenv("USER") end,
- Opts = [{email, User ++ "@erlang.org"},
- {name, User},
- {city, "Stockholm"},
- {country, "SE"},
- {org, "erlang"},
- {org_unit, "testing dep"}],
- subject(Opts);
-subject(Opts, _) ->
- subject(Opts).
-
-subject(SubjectOpts) when is_list(SubjectOpts) ->
- Encode = fun(Opt) ->
- {Type,Value} = subject_enc(Opt),
- [#'AttributeTypeAndValue'{type=Type, value=Value}]
- end,
- {rdnSequence, [Encode(Opt) || Opt <- SubjectOpts]}.
-
-%% Fill in the blanks
-subject_enc({name, Name}) -> {?'id-at-commonName', {printableString, Name}};
-subject_enc({email, Email}) -> {?'id-emailAddress', Email};
-subject_enc({city, City}) -> {?'id-at-localityName', {printableString, City}};
-subject_enc({state, State}) -> {?'id-at-stateOrProvinceName', {printableString, State}};
-subject_enc({org, Org}) -> {?'id-at-organizationName', {printableString, Org}};
-subject_enc({org_unit, OrgUnit}) -> {?'id-at-organizationalUnitName', {printableString, OrgUnit}};
-subject_enc({country, Country}) -> {?'id-at-countryName', Country};
-subject_enc({serial, Serial}) -> {?'id-at-serialNumber', Serial};
-subject_enc({title, Title}) -> {?'id-at-title', {printableString, Title}};
-subject_enc({dnQualifer, DnQ}) -> {?'id-at-dnQualifier', DnQ};
-subject_enc(Other) -> Other.
-
-
-extensions(Opts) ->
- case proplists:get_value(extensions, Opts, []) of
- false ->
- asn1_NOVALUE;
- Exts ->
- lists:flatten([extension(Ext) || Ext <- default_extensions(Exts)])
- end.
-
-default_extensions(Exts) ->
- Def = [{key_usage,undefined},
- {subject_altname, undefined},
- {issuer_altname, undefined},
- {basic_constraints, default},
- {name_constraints, undefined},
- {policy_constraints, undefined},
- {ext_key_usage, undefined},
- {inhibit_any, undefined},
- {auth_key_id, undefined},
- {subject_key_id, undefined},
- {policy_mapping, undefined}],
- Filter = fun({Key, _}, D) -> lists:keydelete(Key, 1, D) end,
- Exts ++ lists:foldl(Filter, Def, Exts).
-
-extension({_, undefined}) -> [];
-extension({basic_constraints, Data}) ->
- case Data of
- default ->
- #'Extension'{extnID = ?'id-ce-basicConstraints',
- extnValue = #'BasicConstraints'{cA=true},
- critical=true};
- false ->
- [];
- Len when is_integer(Len) ->
- #'Extension'{extnID = ?'id-ce-basicConstraints',
- extnValue = #'BasicConstraints'{cA=true, pathLenConstraint=Len},
- critical=true};
+setup_dsa_auth_keys(Dir, UserDir) ->
+ {ok, Pem} = file:read_file(filename:join(Dir, "id_dsa")),
+ DSA = public_key:pem_entry_decode(hd(public_key:pem_decode(Pem))),
+ PKey = DSA#'DSAPrivateKey'.y,
+ P = DSA#'DSAPrivateKey'.p,
+ Q = DSA#'DSAPrivateKey'.q,
+ G = DSA#'DSAPrivateKey'.g,
+ Dss = #'Dss-Parms'{p=P, q=Q, g=G},
+ setup_auth_keys([{{PKey, Dss}, [{comment, "Test"}]}], UserDir).
+
+setup_rsa_auth_keys(Dir, UserDir) ->
+ {ok, Pem} = file:read_file(filename:join(Dir, "id_rsa")),
+ RSA = public_key:pem_entry_decode(hd(public_key:pem_decode(Pem))),
+ #'RSAPrivateKey'{publicExponent = E, modulus = N} = RSA,
+ PKey = #'RSAPublicKey'{publicExponent = E, modulus = N},
+ setup_auth_keys([{ PKey, [{comment, "Test"}]}], UserDir).
+
+setup_auth_keys(Keys, Dir) ->
+ AuthKeys = public_key:ssh_encode(Keys, auth_keys),
+ AuthKeysFile = filename:join(Dir, "authorized_keys"),
+ file:write_file(AuthKeysFile, AuthKeys).
+
+
+del_dirs(Dir) ->
+ case file:list_dir(Dir) of
+ {ok, []} ->
+ file:del_dir(Dir);
+ {ok, Files} ->
+ lists:foreach(fun(File) ->
+ FullPath = filename:join(Dir,File),
+ case filelib:is_dir(FullPath) of
+ true ->
+ del_dirs(FullPath),
+ file:del_dir(FullPath);
+ false ->
+ file:delete(FullPath)
+ end
+ end, Files);
_ ->
- #'Extension'{extnID = ?'id-ce-basicConstraints',
- extnValue = Data}
- end;
-extension({Id, Data, Critical}) ->
- #'Extension'{extnID = Id, extnValue = Data, critical = Critical}.
-
-
-publickey(#'RSAPrivateKey'{modulus=N, publicExponent=E}) ->
- Public = #'RSAPublicKey'{modulus=N, publicExponent=E},
- Algo = #'PublicKeyAlgorithm'{algorithm= ?rsaEncryption, parameters='NULL'},
- #'OTPSubjectPublicKeyInfo'{algorithm = Algo,
- subjectPublicKey = Public};
-publickey(#'DSAPrivateKey'{p=P, q=Q, g=G, y=Y}) ->
- Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-dsa',
- parameters={params, #'Dss-Parms'{p=P, q=Q, g=G}}},
- #'OTPSubjectPublicKeyInfo'{algorithm = Algo, subjectPublicKey = Y}.
-
-validity(Opts) ->
- DefFrom0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())-1),
- DefTo0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())+7),
- {DefFrom, DefTo} = proplists:get_value(validity, Opts, {DefFrom0, DefTo0}),
- Format = fun({Y,M,D}) -> lists:flatten(io_lib:format("~w~2..0w~2..0w000000Z",[Y,M,D])) end,
- #'Validity'{notBefore={generalTime, Format(DefFrom)},
- notAfter ={generalTime, Format(DefTo)}}.
-
-sign_algorithm(#'RSAPrivateKey'{}, Opts) ->
- Type = case proplists:get_value(digest, Opts, sha1) of
- sha1 -> ?'sha1WithRSAEncryption';
- sha512 -> ?'sha512WithRSAEncryption';
- sha384 -> ?'sha384WithRSAEncryption';
- sha256 -> ?'sha256WithRSAEncryption';
- md5 -> ?'md5WithRSAEncryption';
- md2 -> ?'md2WithRSAEncryption'
- end,
- {Type, 'NULL'};
-sign_algorithm(#'DSAPrivateKey'{p=P, q=Q, g=G}, _Opts) ->
- {?'id-dsa-with-sha1', {params,#'Dss-Parms'{p=P, q=Q, g=G}}}.
-
-make_key(rsa, _Opts) ->
- %% (OBS: for testing only)
- gen_rsa2(64);
-make_key(dsa, _Opts) ->
- gen_dsa2(128, 20). %% Bytes i.e. {1024, 160}
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% RSA key generation (OBS: for testing only)
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
--define(SMALL_PRIMES, [65537,97,89,83,79,73,71,67,61,59,53,
- 47,43,41,37,31,29,23,19,17,13,11,7,5,3]).
-
-gen_rsa2(Size) ->
- P = prime(Size),
- Q = prime(Size),
- N = P*Q,
- Tot = (P - 1) * (Q - 1),
- [E|_] = lists:dropwhile(fun(Candidate) -> (Tot rem Candidate) == 0 end, ?SMALL_PRIMES),
- {D1,D2} = extended_gcd(E, Tot),
- D = erlang:max(D1,D2),
- case D < E of
- true ->
- gen_rsa2(Size);
- false ->
- {Co1,Co2} = extended_gcd(Q, P),
- Co = erlang:max(Co1,Co2),
- #'RSAPrivateKey'{version = 'two-prime',
- modulus = N,
- publicExponent = E,
- privateExponent = D,
- prime1 = P,
- prime2 = Q,
- exponent1 = D rem (P-1),
- exponent2 = D rem (Q-1),
- coefficient = Co
- }
+ ok
end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% DSA key generation (OBS: for testing only)
-%% See http://en.wikipedia.org/wiki/Digital_Signature_Algorithm
-%% and the fips_186-3.pdf
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-gen_dsa2(LSize, NSize) ->
- Q = prime(NSize), %% Choose N-bit prime Q
- X0 = prime(LSize),
- P0 = prime((LSize div 2) +1),
-
- %% Choose L-bit prime modulus P such that p-1 is a multiple of q.
- case dsa_search(X0 div (2*Q*P0), P0, Q, 1000) of
- error ->
- gen_dsa2(LSize, NSize);
- P ->
- G = crypto:mod_exp(2, (P-1) div Q, P), % Choose G a number whose multiplicative order modulo p is q.
- %% such that This may be done by setting g = h^(p-1)/q mod p, commonly h=2 is used.
-
- X = prime(20), %% Choose x by some random method, where 0 < x < q.
- Y = crypto:mod_exp(G, X, P), %% Calculate y = g^x mod p.
-
- #'DSAPrivateKey'{version=0, p=P, q=Q, g=G, y=Y, x=X}
- end.
-
-%% See fips_186-3.pdf
-dsa_search(T, P0, Q, Iter) when Iter > 0 ->
- P = 2*T*Q*P0 + 1,
- case is_prime(crypto:mpint(P), 50) of
- true -> P;
- false -> dsa_search(T+1, P0, Q, Iter-1)
- end;
-dsa_search(_,_,_,_) ->
- error.
-
-
-%%%%%%% Crypto Math %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-prime(ByteSize) ->
- Rand = odd_rand(ByteSize),
- crypto:erlint(prime_odd(Rand, 0)).
-
-prime_odd(Rand, N) ->
- case is_prime(Rand, 50) of
- true ->
- Rand;
- false ->
- NotPrime = crypto:erlint(Rand),
- prime_odd(crypto:mpint(NotPrime+2), N+1)
- end.
-
-%% see http://en.wikipedia.org/wiki/Fermat_primality_test
-is_prime(_, 0) -> true;
-is_prime(Candidate, Test) ->
- CoPrime = odd_rand(<<0,0,0,4, 10000:32>>, Candidate),
- case crypto:mod_exp(CoPrime, Candidate, Candidate) of
- CoPrime -> is_prime(Candidate, Test-1);
- _ -> false
- end.
-
-odd_rand(Size) ->
- Min = 1 bsl (Size*8-1),
- Max = (1 bsl (Size*8))-1,
- odd_rand(crypto:mpint(Min), crypto:mpint(Max)).
-
-odd_rand(Min,Max) ->
- Rand = <<Sz:32, _/binary>> = crypto:rand_uniform(Min,Max),
- BitSkip = (Sz+4)*8-1,
- case Rand of
- Odd = <<_:BitSkip, 1:1>> -> Odd;
- Even = <<_:BitSkip, 0:1>> ->
- crypto:mpint(crypto:erlint(Even)+1)
- end.
-
-extended_gcd(A, B) ->
- case A rem B of
- 0 ->
- {0, 1};
- N ->
- {X, Y} = extended_gcd(B, N),
- {Y, X-Y*(A div B)}
- end.
-
-pem_to_der(File) ->
- {ok, PemBin} = file:read_file(File),
- public_key:pem_decode(PemBin).
-
-der_to_pem(File, Entries) ->
- PemBin = public_key:pem_encode(Entries),
- file:write_file(File, PemBin).
diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl
index f959d50484..dfe526564d 100644
--- a/lib/ssh/test/ssh_to_openssh_SUITE.erl
+++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -42,8 +42,12 @@
init_per_suite(Config) ->
case catch crypto:start() of
ok ->
- ssh_test_lib:make_dsa_files(Config),
- Config;
+ case gen_tcp:connect("localhost", 22, []) of
+ {error,econnrefused} ->
+ {skip,"No openssh deamon"};
+ _ ->
+ Config
+ end;
_Else ->
{skip,"Could not start crypto!"}
end.
@@ -100,26 +104,38 @@ all() ->
false ->
{skip, "openSSH not installed on host"};
_ ->
- [erlang_shell_client_openssh_server,
- erlang_client_openssh_server_exec,
- erlang_client_openssh_server_exec_compressed,
- erlang_server_openssh_client_exec,
- erlang_server_openssh_client_exec_compressed,
- erlang_client_openssh_server_setenv,
- erlang_client_openssh_server_publickey_rsa,
- erlang_client_openssh_server_publickey_dsa,
- erlang_server_openssh_client_pulic_key_dsa,
- erlang_client_openssh_server_password]
+ [{group, erlang_client},
+ {group, erlang_server}
+ ]
end.
groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
+ [{erlang_client, [], [erlang_shell_client_openssh_server,
+ erlang_client_openssh_server_exec,
+ erlang_client_openssh_server_exec_compressed,
+ erlang_client_openssh_server_setenv,
+ erlang_client_openssh_server_publickey_rsa,
+ erlang_client_openssh_server_publickey_dsa,
+ erlang_client_openssh_server_password]},
+ {erlang_server, [], [erlang_server_openssh_client_exec,
+ erlang_server_openssh_client_exec_compressed,
+ erlang_server_openssh_client_pulic_key_dsa]}
+ ].
+
+init_per_group(erlang_server, Config) ->
+ DataDir = ?config(data_dir, Config),
+ UserDir = ?config(priv_dir, Config),
+ ssh_test_lib:setup_dsa_known_host(DataDir, UserDir),
+ Config;
+init_per_group(_, Config) ->
+ Config.
-end_per_group(_GroupName, Config) ->
- Config.
+end_per_group(erlang_server, Config) ->
+ UserDir = ?config(priv_dir, Config),
+ ssh_test_lib:clean_dsa(UserDir),
+ Config;
+end_per_group(_, Config) ->
+ Config.
%% TEST cases starts here.
%%--------------------------------------------------------------------
@@ -229,7 +245,9 @@ erlang_server_openssh_client_exec(suite) ->
erlang_server_openssh_client_exec(Config) when is_list(Config) ->
SystemDir = ?config(data_dir, Config),
-
+ PrivDir = ?config(priv_dir, Config),
+ KnownHosts = filename:join(PrivDir, "known_hosts"),
+
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
{failfun, fun ssh_test_lib:failfun/2}]),
@@ -237,7 +255,10 @@ erlang_server_openssh_client_exec(Config) when is_list(Config) ->
test_server:sleep(500),
Cmd = "ssh -p " ++ integer_to_list(Port) ++
- " -o StrictHostKeyChecking=no "++ Host ++ " 1+1.",
+ " -o UserKnownHostsFile=" ++ KnownHosts ++ " " ++ Host ++ " 1+1.",
+
+ test_server:format("Cmd: ~p~n", [Cmd]),
+
SshPort = open_port({spawn, Cmd}, [binary]),
receive
@@ -258,6 +279,9 @@ erlang_server_openssh_client_exec_compressed(suite) ->
erlang_server_openssh_client_exec_compressed(Config) when is_list(Config) ->
SystemDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ KnownHosts = filename:join(PrivDir, "known_hosts"),
+
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
{compression, zlib},
{failfun, fun ssh_test_lib:failfun/2}]),
@@ -265,7 +289,7 @@ erlang_server_openssh_client_exec_compressed(Config) when is_list(Config) ->
test_server:sleep(500),
Cmd = "ssh -p " ++ integer_to_list(Port) ++
- " -o StrictHostKeyChecking=no -C "++ Host ++ " 1+1.",
+ " -o UserKnownHostsFile=" ++ KnownHosts ++ " -C "++ Host ++ " 1+1.",
SshPort = open_port({spawn, Cmd}, [binary]),
receive
@@ -330,24 +354,27 @@ erlang_client_openssh_server_publickey_rsa(suite) ->
[];
erlang_client_openssh_server_publickey_rsa(Config) when is_list(Config) ->
{ok,[[Home]]} = init:get_argument(home),
- SrcDir = filename:join(Home, ".ssh"),
- UserDir = ?config(priv_dir, Config),
- case ssh_test_lib:copyfile(SrcDir, UserDir, "id_rsa") of
- {ok, _} ->
- ConnectionRef =
- ssh_test_lib:connect(?SSH_DEFAULT_PORT,
- [{user_dir, UserDir},
- {public_key_alg, ssh_rsa},
- {user_interaction, false},
- silently_accept_hosts]),
- {ok, Channel} =
- ssh_connection:session_channel(ConnectionRef, infinity),
- ok = ssh_connection:close(ConnectionRef, Channel),
- ok = ssh:close(ConnectionRef),
- ok = file:delete(filename:join(UserDir, "id_rsa"));
- {error, enoent} ->
- {skip, "no ~/.ssh/id_rsa"}
+ KeyFile = filename:join(Home, ".ssh/id_rsa"),
+ case file:read_file(KeyFile) of
+ {ok, Pem} ->
+ case public_key:pem_decode(Pem) of
+ [{_,_, not_encrypted}] ->
+ ConnectionRef =
+ ssh_test_lib:connect(?SSH_DEFAULT_PORT,
+ [{public_key_alg, ssh_rsa},
+ {user_interaction, false},
+ silently_accept_hosts]),
+ {ok, Channel} =
+ ssh_connection:session_channel(ConnectionRef, infinity),
+ ok = ssh_connection:close(ConnectionRef, Channel),
+ ok = ssh:close(ConnectionRef);
+ _ ->
+ {skip, {error, "Has pass phrase can not be used by automated test case"}}
+ end;
+ _ ->
+ {skip, "no ~/.ssh/id_rsa"}
end.
+
%%--------------------------------------------------------------------
erlang_client_openssh_server_publickey_dsa(doc) ->
@@ -356,25 +383,26 @@ erlang_client_openssh_server_publickey_dsa(suite) ->
[];
erlang_client_openssh_server_publickey_dsa(Config) when is_list(Config) ->
{ok,[[Home]]} = init:get_argument(home),
- SrcDir = filename:join(Home, ".ssh"),
- UserDir = ?config(priv_dir, Config),
- case ssh_test_lib:copyfile(SrcDir, UserDir, "id_dsa") of
- {ok, _} ->
- ConnectionRef =
- ssh_test_lib:connect(?SSH_DEFAULT_PORT,
- [{user_dir, UserDir},
- {public_key_alg, ssh_dsa},
- {user_interaction, false},
- silently_accept_hosts]),
- {ok, Channel} =
- ssh_connection:session_channel(ConnectionRef, infinity),
- ok = ssh_connection:close(ConnectionRef, Channel),
- ok = ssh:close(ConnectionRef),
- ok = file:delete(filename:join(UserDir, "id_dsa"));
- {error, enoent} ->
- {skip, "no ~/.ssh/id_dsa"}
+ KeyFile = filename:join(Home, ".ssh/id_dsa"),
+ case file:read_file(KeyFile) of
+ {ok, Pem} ->
+ case public_key:pem_decode(Pem) of
+ [{_,_, not_encrypted}] ->
+ ConnectionRef =
+ ssh_test_lib:connect(?SSH_DEFAULT_PORT,
+ [{public_key_alg, ssh_dsa},
+ {user_interaction, false},
+ silently_accept_hosts]),
+ {ok, Channel} =
+ ssh_connection:session_channel(ConnectionRef, infinity),
+ ok = ssh_connection:close(ConnectionRef, Channel),
+ ok = ssh:close(ConnectionRef);
+ _ ->
+ {skip, {error, "Has pass phrase can not be used by automated test case"}}
+ end;
+ _ ->
+ {skip, "no ~/.ssh/id_dsa"}
end.
-
%%--------------------------------------------------------------------
erlang_server_openssh_client_pulic_key_dsa(doc) ->
["Validate using dsa publickey."];
@@ -384,6 +412,9 @@ erlang_server_openssh_client_pulic_key_dsa(suite) ->
erlang_server_openssh_client_pulic_key_dsa(Config) when is_list(Config) ->
SystemDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ KnownHosts = filename:join(PrivDir, "known_hosts"),
+
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
{public_key_alg, ssh_dsa},
{failfun, fun ssh_test_lib:failfun/2}]),
@@ -391,7 +422,8 @@ erlang_server_openssh_client_pulic_key_dsa(Config) when is_list(Config) ->
test_server:sleep(500),
Cmd = "ssh -p " ++ integer_to_list(Port) ++
- " -o StrictHostKeyChecking=no "++ Host ++ " 1+1.",
+ " -o UserKnownHostsFile=" ++ KnownHosts ++
+ " " ++ Host ++ " 1+1.",
SshPort = open_port({spawn, Cmd}, [binary]),
receive
@@ -399,7 +431,6 @@ erlang_server_openssh_client_pulic_key_dsa(Config) when is_list(Config) ->
ok
after ?TIMEOUT ->
test_server:fail("Did not receive answer")
-
end,
ssh:stop_daemon(Pid).
diff --git a/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key
new file mode 100644
index 0000000000..51ab6fbd88
--- /dev/null
+++ b/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key
@@ -0,0 +1,13 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBuwIBAAKBgQCClaHzE2ul0gKSUxah5W0W8UiJLy4hXngKEqpaUq9SSdVdY2LK
+wVfKH1gt5iuaf1FfzOhsIC9G/GLnjYttXZc92cv/Gfe3gR+s0ni2++MX+T++mE/Q
+diltXv/Hp27PybS67SmiFW7I+RWnT2OKlMPtw2oUuKeztCe5UWjaj/y5FQIVAPLA
+l9RpiU30Z87NRAHY3NTRaqtrAoGANMRxw8UfdtNVR0CrQj3AgPaXOGE4d+G4Gp4X
+skvnCHycSVAjtYxebUkzUzt5Q6f/IabuLUdge3gXrc8BetvrcKbp+XZgM0/Vj2CF
+Ymmy3in6kzGZq7Fw1sZaku6AOU8vLa5woBT2vAcHLLT1bLAzj7viL048T6MfjrOP
+ef8nHvACgYBhDWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah
+/XcF3DeRF+eEoz48wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+U
+ykSTXYUbtsfTNRFQGBW2/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0CgIVAN4wtL5W
+Lv62jKcdskxNyz2NQoBx
+-----END DSA PRIVATE KEY-----
+
diff --git a/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key.pub
new file mode 100644
index 0000000000..4dbb1305b0
--- /dev/null
+++ b/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key.pub
@@ -0,0 +1,11 @@
+---- BEGIN SSH2 PUBLIC KEY ----
+AAAAB3NzaC1kc3MAAACBAIKVofMTa6XSApJTFqHlbRbxSIkvLiFeeAoSqlpSr1JJ1V1j
+YsrBV8ofWC3mK5p/UV/M6GwgL0b8YueNi21dlz3Zy/8Z97eBH6zSeLb74xf5P76YT9B2
+KW1e/8enbs/JtLrtKaIVbsj5FadPY4qUw+3DahS4p7O0J7lRaNqP/LkVAAAAFQDywJfU
+aYlN9GfOzUQB2NzU0WqrawAAAIA0xHHDxR9201VHQKtCPcCA9pc4YTh34bganheyS+cI
+fJxJUCO1jF5tSTNTO3lDp/8hpu4tR2B7eBetzwF62+twpun5dmAzT9WPYIViabLeKfqT
+MZmrsXDWxlqS7oA5Ty8trnCgFPa8BwcstPVssDOPu+IvTjxPox+Os495/yce8AAAAIBh
+DWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah/XcF3DeRF+eEoz48
+wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+UykSTXYUbtsfTNRFQGBW2
+/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0Cg==
+---- END SSH2 PUBLIC KEY ----
diff --git a/lib/ssl/src/inet_tls_dist.erl b/lib/ssl/src/inet_tls_dist.erl
index 115527aae0..bc395cb6d5 100644
--- a/lib/ssl/src/inet_tls_dist.erl
+++ b/lib/ssl/src/inet_tls_dist.erl
@@ -57,7 +57,7 @@ accept_connection(AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
setup(Node, Type, MyNode, LongOrShortNames,SetupTime) ->
Kernel = self(),
- spawn(fun() -> do_setup(Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) end).
+ spawn_opt(fun() -> do_setup(Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) end, [link, {priority, max}]).
do_setup(Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) ->
[Name, Address] = splitnode(Node, LongOrShortNames),
@@ -229,9 +229,7 @@ connect_hs_data(Kernel, Node, MyNode, Socket, Timer, Version, Ip, TcpPort, Addre
accept_hs_data(Kernel, MyNode, Socket, Timer, Allowed) ->
common_hs_data(Kernel, MyNode, Socket, Timer, #hs_data{
allowed = Allowed,
- f_address = fun(S, N) ->
- ssl_tls_dist_proxy:get_remote_id(S, N)
- end
+ f_address = fun get_remote_id/2
}).
common_hs_data(Kernel, MyNode, Socket, Timer, HsData) ->
@@ -273,3 +271,11 @@ common_hs_data(Kernel, MyNode, Socket, Timer, HsData) ->
P = proplists:get_value(send_pend, Stats, 0),
{ok, R,W,P}
end}.
+
+get_remote_id(Socket, _Node) ->
+ case ssl_tls_dist_proxy:get_tcp_address(Socket) of
+ {ok, Address} ->
+ Address;
+ {error, _Reason} ->
+ ?shutdown(no_node)
+ end.
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index 371f475c85..542033e6ce 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -188,14 +188,14 @@ certify(#certificate{asn1_certificates = ASN1Certs}, CertDbHandle, CertDbRef,
ValidationFunAndState =
case VerifyFunAndState of
undefined ->
- {fun(OtpCert, ExtensionOrError, SslState) ->
+ {fun(OtpCert, ExtensionOrVerifyResult, SslState) ->
ssl_certificate:validate_extension(OtpCert,
- ExtensionOrError, SslState)
+ ExtensionOrVerifyResult, SslState)
end, Role};
{Fun, UserState0} ->
- {fun(OtpCert, ExtensionOrError, {SslState, UserState}) ->
+ {fun(OtpCert, {extension, _} = Extension, {SslState, UserState}) ->
case ssl_certificate:validate_extension(OtpCert,
- ExtensionOrError,
+ Extension,
SslState) of
{valid, NewSslState} ->
{valid, {NewSslState, UserState}};
@@ -204,8 +204,11 @@ certify(#certificate{asn1_certificates = ASN1Certs}, CertDbHandle, CertDbRef,
SslState);
{unknown, _} ->
apply_user_fun(Fun, OtpCert,
- ExtensionOrError, UserState, SslState)
- end
+ Extension, UserState, SslState)
+ end;
+ (OtpCert, VerifyResult, {SslState, UserState}) ->
+ apply_user_fun(Fun, OtpCert, VerifyResult, UserState,
+ SslState)
end, {Role, UserState0}}
end,
diff --git a/lib/ssl/src/ssl_tls_dist_proxy.erl b/lib/ssl/src/ssl_tls_dist_proxy.erl
index d63eada571..1c61eb7ccc 100644
--- a/lib/ssl/src/ssl_tls_dist_proxy.erl
+++ b/lib/ssl/src/ssl_tls_dist_proxy.erl
@@ -19,7 +19,7 @@
-module(ssl_tls_dist_proxy).
--export([listen/1, accept/1, connect/2, get_remote_id/2]).
+-export([listen/1, accept/1, connect/2, get_tcp_address/1]).
-export([init/1, start_link/0, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3, ssl_options/2]).
@@ -47,9 +47,6 @@ accept(Listen) ->
connect(Ip, Port) ->
gen_server:call(?MODULE, {connect, Ip, Port}, infinity).
-get_remote_id(Socket, Node) ->
- gen_server:call(?MODULE, {get_remote_id, {Socket,Node}}, infinity).
-
%%====================================================================
%% gen_server callbacks
%%====================================================================
@@ -65,8 +62,8 @@ handle_call({listen, Name}, _From, State) ->
case gen_tcp:listen(0, [{active, false}, {packet,?PPRE}]) of
{ok, Socket} ->
{ok, World} = gen_tcp:listen(0, [{active, false}, binary, {packet,?PPRE}]),
- TcpAddress = get_tcp_address(Socket),
- WorldTcpAddress = get_tcp_address(World),
+ {ok, TcpAddress} = get_tcp_address(Socket),
+ {ok, WorldTcpAddress} = get_tcp_address(World),
{_,Port} = WorldTcpAddress#net_address.address,
{ok, Creation} = erl_epmd:register_node(Name, Port),
{reply, {ok, {Socket, TcpAddress, Creation}},
@@ -87,17 +84,16 @@ handle_call({connect, Ip, Port}, {From, _}, State) ->
receive
{Pid, go_ahead, LPort} ->
Res = {ok, Socket} = try_connect(LPort),
- ok = gen_tcp:controlling_process(Socket, From),
- flush_old_controller(From, Socket),
- {reply, Res, State};
+ case gen_tcp:controlling_process(Socket, From) of
+ {error, badarg} = Error -> {reply, Error, State}; % From is dead anyway.
+ ok ->
+ flush_old_controller(From, Socket),
+ {reply, Res, State}
+ end;
{Pid, Error} ->
{reply, Error, State}
end;
-handle_call({get_remote_id, {Socket,_Node}}, _From, State) ->
- Address = get_tcp_address(Socket),
- {reply, Address, State};
-
handle_call(_What, _From, State) ->
{reply, ok, State}.
@@ -117,14 +113,18 @@ code_change(_OldVsn, St, _Extra) ->
%%% Internal functions
%%--------------------------------------------------------------------
get_tcp_address(Socket) ->
- {ok, Address} = inet:sockname(Socket),
- {ok, Host} = inet:gethostname(),
- #net_address{
+ case inet:sockname(Socket) of
+ {ok, Address} ->
+ {ok, Host} = inet:gethostname(),
+ NetAddress = #net_address{
address = Address,
host = Host,
protocol = proxy,
family = inet
- }.
+ },
+ {ok, NetAddress};
+ {error, _} = Error -> Error
+ end.
accept_loop(Proxy, erts = Type, Listen, Extra) ->
process_flag(priority, max),
@@ -178,8 +178,8 @@ setup_proxy(Ip, Port, Parent) ->
Opts = get_ssl_options(client),
case ssl:connect(Ip, Port, [{active, true}, binary, {packet,?PPRE}] ++ Opts) of
{ok, World} ->
- {ok, ErtsL} = gen_tcp:listen(0, [{active, true}, binary, {packet,?PPRE}]),
- #net_address{address={_,LPort}} = get_tcp_address(ErtsL),
+ {ok, ErtsL} = gen_tcp:listen(0, [{active, true}, {ip, {127,0,0,1}}, binary, {packet,?PPRE}]),
+ {ok, #net_address{address={_,LPort}}} = get_tcp_address(ErtsL),
Parent ! {self(), go_ahead, LPort},
case gen_tcp:accept(ErtsL) of
{ok, Erts} ->
@@ -194,7 +194,7 @@ setup_proxy(Ip, Port, Parent) ->
setup_connection(World, ErtsListen) ->
process_flag(trap_exit, true),
- TcpAddress = get_tcp_address(ErtsListen),
+ {ok, TcpAddress} = get_tcp_address(ErtsListen),
{_Addr,Port} = TcpAddress#net_address.address,
{ok, Erts} = gen_tcp:connect({127,0,0,1}, Port, [{active, true}, binary, {packet,?PPRE}]),
ssl:setopts(World, [{active,true}, {packet,?PPRE}]),
@@ -223,7 +223,11 @@ loop_conn_setup(World, Erts) ->
loop_conn_setup(World, Erts);
{tcp, Erts, Data} ->
ssl:send(World, Data),
- loop_conn_setup(World, Erts)
+ loop_conn_setup(World, Erts);
+ {tcp_closed, Erts} ->
+ ssl:close(World);
+ {ssl_closed, World} ->
+ gen_tcp:close(Erts)
end.
loop_conn(World, Erts) ->
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index 527263363c..590ecf33ca 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -250,6 +250,8 @@ all() ->
no_authority_key_identifier, invalid_signature_client,
invalid_signature_server, cert_expired,
client_with_cert_cipher_suites_handshake,
+ verify_fun_always_run_client,
+ verify_fun_always_run_server,
unknown_server_ca_fail, der_input,
unknown_server_ca_accept_verify_none,
unknown_server_ca_accept_verify_peer,
@@ -3217,6 +3219,105 @@ client_with_cert_cipher_suites_handshake(Config) when is_list(Config) ->
ssl_test_lib:check_result(Server, ok, Client, ok),
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
+verify_fun_always_run_client(doc) ->
+ ["Verify that user verify_fun is always run (for valid and valid_peer not only unknown_extension)"];
+verify_fun_always_run_client(suite) ->
+ [];
+verify_fun_always_run_client(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_verification_opts, Config),
+ ServerOpts = ?config(server_verification_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ no_result, []}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ %% If user verify fun is called correctly we fail the connection.
+ %% otherwise we can not tell this case apart form where we miss
+ %% to call users verify fun
+ FunAndState = {fun(_,{extension, _}, UserState) ->
+ {unknown, UserState};
+ (_, valid, [ChainLen]) ->
+ {valid, [ChainLen + 1]};
+ (_, valid_peer, [2]) ->
+ {fail, "verify_fun_was_always_run"};
+ (_, valid_peer, UserState) ->
+ {valid, UserState}
+ end, [0]},
+
+ Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ no_result, []}},
+ {options,
+ [{verify, verify_peer},
+ {verify_fun, FunAndState}
+ | ClientOpts]}]),
+ %% Server error may be esslaccept or closed depending on timing
+ %% this is not a bug it is a circumstance of how tcp works!
+ receive
+ {Server, ServerError} ->
+ test_server:format("Server Error ~p~n", [ServerError])
+ end,
+
+ ssl_test_lib:check_result(Client, {error, esslconnect}).
+
+%%--------------------------------------------------------------------
+verify_fun_always_run_server(doc) ->
+ ["Verify that user verify_fun is always run (for valid and valid_peer not only unknown_extension)"];
+verify_fun_always_run_server(suite) ->
+ [];
+verify_fun_always_run_server(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_verification_opts, Config),
+ ServerOpts = ?config(server_verification_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ %% If user verify fun is called correctly we fail the connection.
+ %% otherwise we can not tell this case apart form where we miss
+ %% to call users verify fun
+ FunAndState = {fun(_,{extension, _}, UserState) ->
+ {unknown, UserState};
+ (_, valid, [ChainLen]) ->
+ {valid, [ChainLen + 1]};
+ (_, valid_peer, [2]) ->
+ {fail, "verify_fun_was_always_run"};
+ (_, valid_peer, UserState) ->
+ {valid, UserState}
+ end, [0]},
+
+ Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ no_result, []}},
+ {options,
+ [{verify, verify_peer},
+ {verify_fun, FunAndState} |
+ ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ no_result, []}},
+ {options,
+ [{verify, verify_peer}
+ | ClientOpts]}]),
+
+ %% Client error may be esslconnect or closed depending on timing
+ %% this is not a bug it is a circumstance of how tcp works!
+ receive
+ {Client, ClientError} ->
+ test_server:format("Client Error ~p~n", [ClientError])
+ end,
+
+ ssl_test_lib:check_result(Server, {error, esslaccept}).
+
%%--------------------------------------------------------------------
unknown_server_ca_fail(doc) ->
["Test that the client fails if the ca is unknown in verify_peer mode"];
@@ -3924,7 +4025,7 @@ renegotiate(Socket, Data) ->
end.
renegotiate_reuse_session(Socket, Data) ->
- %% Make sure session is registerd
+ %% Make sure session is registered
test_server:sleep(?SLEEP),
renegotiate(Socket, Data).
diff --git a/lib/ssl/test/ssl_dist_SUITE.erl b/lib/ssl/test/ssl_dist_SUITE.erl
index 8fe55ee7a4..06182970e3 100644
--- a/lib/ssl/test/ssl_dist_SUITE.erl
+++ b/lib/ssl/test/ssl_dist_SUITE.erl
@@ -26,7 +26,7 @@
-define(DEFAULT_TIMETRAP_SECS, 240).
--define(AWAIT_SLL_NODE_UP_TIMEOUT, 30000).
+-define(AWAIT_SSL_NODE_UP_TIMEOUT, 30000).
-record(node_handle,
{connection_handler,
@@ -120,6 +120,12 @@ basic(Config) when is_list(Config) ->
pang = net_adm:ping(Node1),
pang = net_adm:ping(Node2),
+ %% SSL nodes should not be able to communicate with the test_server node
+ %% either (and ping should return eventually).
+ TestServer = node(),
+ pang = apply_on_ssl_node(NH1, fun () -> net_adm:ping(TestServer) end),
+ pang = apply_on_ssl_node(NH2, fun () -> net_adm:ping(TestServer) end),
+
%%
%% Check that we are able to communicate over the erlang
%% distribution between the ssl nodes.
@@ -380,7 +386,7 @@ mk_node_cmdline(ListenPort, Name, Args) ->
%%
await_ssl_node_up(Name, LSock) ->
- case gen_tcp:accept(LSock, ?AWAIT_SLL_NODE_UP_TIMEOUT) of
+ case gen_tcp:accept(LSock, ?AWAIT_SSL_NODE_UP_TIMEOUT) of
timeout ->
gen_tcp:close(LSock),
?t:format("Timeout waiting for ssl node ~s to come up~n",
diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl
index f04ab9af50..01fca1f166 100644
--- a/lib/ssl/test/ssl_to_openssl_SUITE.erl
+++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1446,8 +1446,8 @@ check_sane_openssl_renegotaite(Config) ->
check_sane_openssl_sslv2(Config) ->
case os:cmd("openssl version") of
- "OpenSSL 1.0.0e" ++ _ ->
- {skip, "Known option bug"};
+ "OpenSSL 1.0.0" ++ _ ->
+ {skip, "sslv2 by default turned of in 1.*"};
_ ->
Config
end.
diff --git a/lib/stdlib/doc/src/binary.xml b/lib/stdlib/doc/src/binary.xml
index 88ce77e0d0..7ce2defb72 100644
--- a/lib/stdlib/doc/src/binary.xml
+++ b/lib/stdlib/doc/src/binary.xml
@@ -505,7 +505,7 @@
<type>
<v>Subject = binary()</v>
<v>Pos = integer() >= 0</v>
- <v>Len = integer() >= 0</v>
+ <v>Len = integer()</v>
</type>
<desc>
<p>The same as <c>part(Subject, {Pos, Len})</c>.</p>
diff --git a/lib/stdlib/doc/src/gb_trees.xml b/lib/stdlib/doc/src/gb_trees.xml
index 65c866efbe..9316d60b1a 100644
--- a/lib/stdlib/doc/src/gb_trees.xml
+++ b/lib/stdlib/doc/src/gb_trees.xml
@@ -132,15 +132,6 @@
</desc>
</func>
<func>
- <name name="lookup" arity="2"/>
- <fsummary>Look up a key in a tree</fsummary>
- <desc>
- <p>Looks up <c><anno>Key</anno></c> in <c><anno>Tree</anno></c>; returns
- <c>{value, <anno>Val</anno>}</c>, or <c>none</c> if <c><anno>Key</anno></c> is not
- present.</p>
- </desc>
- </func>
- <func>
<name name="insert" arity="3"/>
<fsummary>Insert a new key and value in a tree</fsummary>
<desc>
@@ -196,6 +187,15 @@
</desc>
</func>
<func>
+ <name name="lookup" arity="2"/>
+ <fsummary>Look up a key in a tree</fsummary>
+ <desc>
+ <p>Looks up <c><anno>Key</anno></c> in <c><anno>Tree</anno></c>; returns
+ <c>{value, <anno>Val</anno>}</c>, or <c>none</c> if <c><anno>Key</anno></c> is not
+ present.</p>
+ </desc>
+ </func>
+ <func>
<name name="map" arity="2"/>
<fsummary>Return largest key and value</fsummary>
<desc><p>Maps the function F(<anno>K</anno>, <anno>V1</anno>) -> <anno>V2</anno> to all key-value pairs
diff --git a/lib/stdlib/doc/src/io.xml b/lib/stdlib/doc/src/io.xml
index 667d758e29..e6d262466c 100644
--- a/lib/stdlib/doc/src/io.xml
+++ b/lib/stdlib/doc/src/io.xml
@@ -70,7 +70,7 @@
<desc>
<p>Either <c>standard_io</c>, <c>standard_error</c>, a
registered name, or a pid handling IO protocols (returned from
- <seealso marker="file#open/2">file:open/2</seealso>).</p>
+ <seealso marker="kernel:file#open/2">file:open/2</seealso>).</p>
</desc>
</datatype>
<datatype>
diff --git a/lib/stdlib/doc/src/ms_transform.xml b/lib/stdlib/doc/src/ms_transform.xml
index f81f8bda96..ad5f8bd5ac 100644
--- a/lib/stdlib/doc/src/ms_transform.xml
+++ b/lib/stdlib/doc/src/ms_transform.xml
@@ -308,7 +308,7 @@ ets:select(emp_tab, ets:fun2ms(
Erlang code. Also arithmetics is allowed, as well as ordinary guard
bif's. Here's a list of bif's and expressions:</p>
<list type="bulleted">
- <item>The type tests: is_atom, is_constant, is_float, is_integer,
+ <item>The type tests: is_atom, is_float, is_integer,
is_list, is_number, is_pid, is_port, is_reference, is_tuple,
is_binary, is_function, is_record</item>
<item>The boolean operators: not, and, or, andalso, orelse </item>
@@ -318,7 +318,7 @@ ets:select(emp_tab, ets:fun2ms(
<item>The guard bif's: abs, element, hd, length, node, round, size, tl,
trunc, self</item>
<item>The obsolete type test (only in guards):
- atom, constant, float, integer,
+ atom, float, integer,
list, number, pid, port, reference, tuple,
binary, function, record</item>
</list>
diff --git a/lib/stdlib/doc/src/sofs.xml b/lib/stdlib/doc/src/sofs.xml
index 2e7768a1df..37c41501ae 100644
--- a/lib/stdlib/doc/src/sofs.xml
+++ b/lib/stdlib/doc/src/sofs.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2001</year><year>2011</year>
+ <year>2001</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -317,7 +317,7 @@
but is to be preferred since it makes it possible to handle this
case even more efficiently. Examples of SetFuns:</p>
<pre>
-{sofs, union}
+fun sofs:union/1
fun(S) -> sofs:partition(1, S) end
{external, fun(A) -> A end}
{external, fun({A,_,C}) -> {C,A} end}
@@ -711,7 +711,7 @@ fun(S) -> sofs:partition(1, S) end
argument.</p>
<pre>
1> <input>F1 = sofs:from_term([{a,[[1,2],[2,3]]},{b,[[]]}]),</input>
-<input>F2 = sofs:family_projection({sofs, union}, F1),</input>
+<input>F2 = sofs:family_projection(fun sofs:union/1, F1),</input>
<input>sofs:to_external(F2).</input>
[{a,[1,2,3]},{b,[]}]</pre>
</desc>
@@ -821,7 +821,7 @@ fun(S) -> sofs:partition(1, S) end
<input>sofs:to_external(F2).</input>
[{a,[1,2,3]},{b,[]}]</pre>
<p><c>family_union(F)</c> is equivalent to
- <c>family_projection({sofs,union},&nbsp;F)</c>.</p>
+ <c>family_projection(fun sofs:union/1,&nbsp;F)</c>.</p>
</desc>
</func>
<func>
@@ -1438,7 +1438,7 @@ true</pre>
1> <input>R1 = sofs:relation([{a,1},{b,2}]),</input>
<input>R2 = sofs:relation([{x,1},{x,2},{y,3}]),</input>
<input>S1 = sofs:from_sets([R1,R2]),</input>
-<input>S2 = sofs:specification({sofs,is_a_function}, S1),</input>
+<input>S2 = sofs:specification(fun sofs:is_a_function/1, S1),</input>
<input>sofs:to_external(S2).</input>
[[{a,1},{b,2}]]</pre>
</desc>
diff --git a/lib/stdlib/doc/src/supervisor.xml b/lib/stdlib/doc/src/supervisor.xml
index cddb55e5c5..33a7f5bb6a 100644
--- a/lib/stdlib/doc/src/supervisor.xml
+++ b/lib/stdlib/doc/src/supervisor.xml
@@ -127,25 +127,18 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
<p><c>StartFunc</c> defines the function call used to start
the child process. It should be a module-function-arguments
tuple <c>{M,F,A}</c> used as <c>apply(M,F,A)</c>.</p>
- <p> <br></br>
-</p>
<p>The start function <em>must create and link to</em> the child
process, and should return <c>{ok,Child}</c> or
<c>{ok,Child,Info}</c> where <c>Child</c> is the pid of
the child process and <c>Info</c> an arbitrary term which is
ignored by the supervisor.</p>
- <p> <br></br>
-</p>
<p>The start function can also return <c>ignore</c> if the child
process for some reason cannot be started, in which case
- the child specification will be kept by the supervisor but
- the non-existing child process will be ignored.</p>
- <p> <br></br>
-</p>
+ the child specification will be kept by the supervisor
+ (unless it is a temporary child) but the non-existing child
+ process will be ignored.</p>
<p>If something goes wrong, the function may also return an
error tuple <c>{error,Error}</c>.</p>
- <p> <br></br>
-</p>
<p>Note that the <c>start_link</c> functions of the different
behaviour modules fulfill the above requirements.</p>
</item>
diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl
index bf3c7b3504..95ba6b1096 100644
--- a/lib/stdlib/src/erl_eval.erl
+++ b/lib/stdlib/src/erl_eval.erl
@@ -947,7 +947,6 @@ type_test(integer) -> is_integer;
type_test(float) -> is_float;
type_test(number) -> is_number;
type_test(atom) -> is_atom;
-type_test(constant) -> is_constant;
type_test(list) -> is_list;
type_test(tuple) -> is_tuple;
type_test(pid) -> is_pid;
diff --git a/lib/stdlib/src/erl_expand_records.erl b/lib/stdlib/src/erl_expand_records.erl
index 20fd247cea..1c69a131f9 100644
--- a/lib/stdlib/src/erl_expand_records.erl
+++ b/lib/stdlib/src/erl_expand_records.erl
@@ -452,8 +452,10 @@ conj([], _E) ->
conj([{{Name,_Rp},L,R,Sz} | AL], E) ->
NL = neg_line(L),
T1 = {op,NL,'orelse',
- {call,NL,{atom,NL,is_record},[R,{atom,NL,Name},{integer,NL,Sz}]},
- {atom,NL,fail}},
+ {call,NL,
+ {remote,NL,{atom,NL,erlang},{atom,NL,is_record}},
+ [R,{atom,NL,Name},{integer,NL,Sz}]},
+ {atom,NL,fail}},
T2 = case conj(AL, none) of
empty -> T1;
C -> {op,NL,'and',C,T1}
@@ -581,7 +583,9 @@ strict_get_record_field(Line, R, {atom,_,F}=Index, Name, St0) ->
ExpRp = erl_lint:modify_line(ExpR, fun(_L) -> 0 end),
RA = {{Name,ExpRp},Line,ExpR,length(Fs)+1},
St2 = St1#exprec{strict_ra = [RA | St1#exprec.strict_ra]},
- {{call,Line,{atom,Line,element},[I,ExpR]},St2}
+ {{call,Line,
+ {remote,Line,{atom,Line,erlang},{atom,Line,element}},
+ [I,ExpR]},St2}
end.
record_pattern(I, I, Var, Sz, Line, Acc) ->
@@ -593,7 +597,9 @@ record_pattern(_, _, _, _, _, Acc) -> reverse(Acc).
sloppy_get_record_field(Line, R, Index, Name, St) ->
Fs = record_fields(Name, St),
I = index_expr(Line, Index, Name, Fs),
- expr({call,Line,{atom,Line,element},[I,R]}, St).
+ expr({call,Line,
+ {remote,Line,{atom,Line,erlang},{atom,Line,element}},
+ [I,R]}, St).
strict_record_tests([strict_record_tests | _]) -> true;
strict_record_tests([no_strict_record_tests | _]) -> false;
@@ -710,7 +716,8 @@ record_setel(R, Name, Fs, Us0) ->
{'case',Lr,R,
[{clause,Lr,[{tuple,Lr,[{atom,Lr,Name} | Wildcards]}],[],
[foldr(fun ({I,Lf,Val}, Acc) ->
- {call,Lf,{atom,Lf,setelement},[I,Acc,Val]} end,
+ {call,Lf,{remote,Lf,{atom,Lf,erlang},
+ {atom,Lf,setelement}},[I,Acc,Val]} end,
R, Us)]},
{clause,NLr,[{var,NLr,'_'}],[],
[call_error(NLr, {tuple,NLr,[{atom,NLr,badrecord},{atom,NLr,Name}]})]}]}.
diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl
index e5adb84932..a1af0057ca 100644
--- a/lib/stdlib/src/erl_lint.erl
+++ b/lib/stdlib/src/erl_lint.erl
@@ -1804,12 +1804,19 @@ guard_test(G, Vt, St0) ->
%% Specially handle record type test here.
guard_test2({call,Line,{atom,Lr,record},[E,A]}, Vt, St0) ->
gexpr({call,Line,{atom,Lr,is_record},[E,A]}, Vt, St0);
-guard_test2({call,_Line,{atom,_La,F},As}=G, Vt, St0) ->
+guard_test2({call,Line,{atom,_La,F},As}=G, Vt, St0) ->
{Asvt,St1} = gexpr_list(As, Vt, St0), %Always check this.
A = length(As),
case erl_internal:type_test(F, A) of
- true when F =/= is_record -> {Asvt,St1};
- _ -> gexpr(G, Vt, St0)
+ true when F =/= is_record, A =/= 2 ->
+ case no_guard_bif_clash(St1, {F,A}) of
+ false ->
+ {Asvt,add_error(Line, {illegal_guard_local_call,{F,A}}, St1)};
+ true ->
+ {Asvt,St1}
+ end;
+ _ ->
+ gexpr(G, Vt, St0)
end;
guard_test2(G, Vt, St) ->
%% Everything else is a guard expression.
@@ -1865,9 +1872,15 @@ gexpr({call,Line,{atom,_Lr,is_record},[E,R]}, Vt, St0) ->
gexpr({call,Line,{remote,_Lr,{atom,_Lm,erlang},{atom,Lf,is_record}},[E,A]},
Vt, St0) ->
gexpr({call,Line,{atom,Lf,is_record},[E,A]}, Vt, St0);
-gexpr({call,_Line,{atom,_Lr,is_record},[E,{atom,_,_Name},{integer,_,_}]},
+gexpr({call,Line,{atom,_Lr,is_record},[E0,{atom,_,_Name},{integer,_,_}]},
Vt, St0) ->
- gexpr(E, Vt, St0);
+ {E,St1} = gexpr(E0, Vt, St0),
+ case no_guard_bif_clash(St0, {is_record,3}) of
+ true ->
+ {E,St1};
+ false ->
+ {E,add_error(Line, {illegal_guard_local_call,{is_record,3}}, St1)}
+ end;
gexpr({call,Line,{atom,_Lr,is_record},[_,_,_]=Asvt0}, Vt, St0) ->
{Asvt,St1} = gexpr_list(Asvt0, Vt, St0),
{Asvt,add_error(Line, illegal_guard_expr, St1)};
@@ -3423,17 +3436,11 @@ obsolete_guard({call,Line,{atom,Lr,F},As}, St0) ->
false ->
deprecated_function(Line, erlang, F, As, St0);
true ->
- St1 = case F of
- constant ->
- deprecated_function(Lr, erlang, is_constant, As, St0);
- _ ->
- St0
- end,
- case is_warn_enabled(obsolete_guard, St1) of
+ case is_warn_enabled(obsolete_guard, St0) of
true ->
- add_warning(Lr,{obsolete_guard, {F, Arity}}, St1);
+ add_warning(Lr,{obsolete_guard, {F, Arity}}, St0);
false ->
- St1
+ St0
end
end;
obsolete_guard(_G, St) ->
diff --git a/lib/stdlib/src/error_logger_file_h.erl b/lib/stdlib/src/error_logger_file_h.erl
index ee4f0b3a51..08f1873803 100644
--- a/lib/stdlib/src/error_logger_file_h.erl
+++ b/lib/stdlib/src/error_logger_file_h.erl
@@ -104,7 +104,7 @@ code_change(_OldVsn, State, _Extra) ->
%%% ------------------------------------------------------
tag_event(Event) ->
- {erlang:localtime(), Event}.
+ {erlang:universaltime(), Event}.
write_events(Fd, Events) -> write_events1(Fd, lists:reverse(Events)).
@@ -169,23 +169,18 @@ write_event(_, _) ->
maybe_utc(Time) ->
UTC = case application:get_env(sasl, utc_log) of
- {ok, Val} ->
- Val;
+ {ok, Val} -> Val;
undefined ->
%% Backwards compatible:
case application:get_env(stdlib, utc_log) of
- {ok, Val} ->
- Val;
- undefined ->
- false
+ {ok, Val} -> Val;
+ undefined -> false
end
end,
- if
- UTC =:= true ->
- {utc, calendar:local_time_to_universal_time(Time)};
- true ->
- Time
- end.
+ maybe_utc(Time, UTC).
+
+maybe_utc(Time, true) -> {utc, Time};
+maybe_utc(Time, _) -> {local, calendar:universal_time_to_local_time(Time)}.
format_report(Rep) when is_list(Rep) ->
case string_p(Rep) of
@@ -238,7 +233,7 @@ write_time(Time) -> write_time(Time, "ERROR REPORT").
write_time({utc,{{Y,Mo,D},{H,Mi,S}}}, Type) ->
io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s UTC ===~n",
[Type,D,month(Mo),Y,t(H),t(Mi),t(S)]);
-write_time({{Y,Mo,D},{H,Mi,S}}, Type) ->
+write_time({local, {{Y,Mo,D},{H,Mi,S}}}, Type) ->
io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s ===~n",
[Type,D,month(Mo),Y,t(H),t(Mi),t(S)]).
diff --git a/lib/stdlib/src/error_logger_tty_h.erl b/lib/stdlib/src/error_logger_tty_h.erl
index fa13fbb2bd..48e069a407 100644
--- a/lib/stdlib/src/error_logger_tty_h.erl
+++ b/lib/stdlib/src/error_logger_tty_h.erl
@@ -97,7 +97,7 @@ set_group_leader() ->
end.
tag_event(Event) ->
- {erlang:localtime(), Event}.
+ {erlang:universaltime(), Event}.
write_events(Events,IOMod) -> write_events1(lists:reverse(Events),IOMod).
@@ -162,23 +162,18 @@ write_event({_Time, _Error},_IOMod) ->
maybe_utc(Time) ->
UTC = case application:get_env(sasl, utc_log) of
- {ok, Val} ->
- Val;
+ {ok, Val} -> Val;
undefined ->
%% Backwards compatible:
case application:get_env(stdlib, utc_log) of
- {ok, Val} ->
- Val;
- undefined ->
- false
+ {ok, Val} -> Val;
+ undefined -> false
end
end,
- if
- UTC =:= true ->
- {utc, calendar:local_time_to_universal_time(Time)};
- true ->
- Time
- end.
+ maybe_utc(Time, UTC).
+
+maybe_utc(Time, true) -> {utc, Time};
+maybe_utc(Time, _) -> {local, calendar:universal_time_to_local_time(Time)}.
format(IOMod, String) -> format(IOMod, String, []).
format(io_lib, String, Args) -> io_lib:format(String, Args);
@@ -234,7 +229,7 @@ write_time(Time) -> write_time(Time, "ERROR REPORT").
write_time({utc,{{Y,Mo,D},{H,Mi,S}}},Type) ->
io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s UTC ===~n",
[Type,D,month(Mo),Y,t(H),t(Mi),t(S)]);
-write_time({{Y,Mo,D},{H,Mi,S}},Type) ->
+write_time({local, {{Y,Mo,D},{H,Mi,S}}},Type) ->
io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s ===~n",
[Type,D,month(Mo),Y,t(H),t(Mi),t(S)]).
diff --git a/lib/stdlib/src/gen_fsm.erl b/lib/stdlib/src/gen_fsm.erl
index 57734a075c..80866c0806 100644
--- a/lib/stdlib/src/gen_fsm.erl
+++ b/lib/stdlib/src/gen_fsm.erl
@@ -320,7 +320,7 @@ name_to_pid(Name) ->
undefined ->
case global:whereis_name(Name) of
undefined ->
- exit(could_not_find_registerd_name);
+ exit(could_not_find_registered_name);
Pid ->
Pid
end;
diff --git a/lib/stdlib/src/gen_server.erl b/lib/stdlib/src/gen_server.erl
index af07bc988a..f720ec15f5 100644
--- a/lib/stdlib/src/gen_server.erl
+++ b/lib/stdlib/src/gen_server.erl
@@ -844,7 +844,7 @@ name_to_pid(Name) ->
undefined ->
case global:whereis_name(Name) of
undefined ->
- exit(could_not_find_registerd_name);
+ exit(could_not_find_registered_name);
Pid ->
Pid
end;
diff --git a/lib/stdlib/src/ms_transform.erl b/lib/stdlib/src/ms_transform.erl
index 63b397f3a5..4389fd457c 100644
--- a/lib/stdlib/src/ms_transform.erl
+++ b/lib/stdlib/src/ms_transform.erl
@@ -881,7 +881,6 @@ translate_language_element(Atom) ->
end.
old_bool_test(atom,1) -> is_atom;
-old_bool_test(constant,1) -> is_constant;
old_bool_test(float,1) -> is_float;
old_bool_test(integer,1) -> is_integer;
old_bool_test(list,1) -> is_list;
@@ -896,7 +895,6 @@ old_bool_test(record,2) -> is_record;
old_bool_test(_,_) -> undefined.
bool_test(is_atom,1) -> true;
-bool_test(is_constant,1) -> true;
bool_test(is_float,1) -> true;
bool_test(is_integer,1) -> true;
bool_test(is_list,1) -> true;
diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl
index 7bacc05ff2..b9fbef9ed0 100644
--- a/lib/stdlib/src/otp_internal.erl
+++ b/lib/stdlib/src/otp_internal.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -337,11 +337,11 @@ obsolete_1(public_key, decode_private_key, A) when A =:= 1; A =:= 2 ->
%% Added in R14B03.
obsolete_1(docb_gen, _, _) ->
- {deprecated,"the DocBuilder application is deprecated (will be removed in R15B)"};
+ {removed,"the DocBuilder application was removed in R15B"};
obsolete_1(docb_transform, _, _) ->
- {deprecated,"the DocBuilder application is deprecated (will be removed in R15B)"};
+ {removed,"the DocBuilder application was removed in R15B"};
obsolete_1(docb_xml_check, _, _) ->
- {deprecated,"the DocBuilder application is deprecated (will be removed in R15B)"};
+ {removed,"the DocBuilder application was removed in R15B"};
%% Added in R15B
obsolete_1(asn1rt, F, _) when F == load_driver; F == unload_driver ->
@@ -350,10 +350,18 @@ obsolete_1(ssl, pid, 1) ->
{deprecated,"deprecated (will be removed in R17); is no longer needed"};
obsolete_1(inviso, _, _) ->
{deprecated,"the inviso application has been deprecated and will be removed in R16"};
+
+%% Added in R15B01.
+obsolete_1(gs, _, _) ->
+ {deprecated,"the gs application has been deprecated and will be removed in R16; use the wx application instead"};
+obsolete_1(ssh, sign_data, 2) ->
+ {deprecated,"deprecated (will be removed in R16A); use public_key:pem_decode/1, public_key:pem_entry_decode/1 "
+ "and public_key:sign/3 instead"};
+obsolete_1(ssh, verify_data, 3) ->
+ {deprecated,"deprecated (will be removed in R16A); use public_key:ssh_decode/1, and public_key:verify/4 instead"};
obsolete_1(_, _, _) ->
no.
-
-spec is_snmp_agent_function(atom(), byte()) -> boolean().
is_snmp_agent_function(c, 1) -> true;
diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl
index 42ea42f42e..ac5b078c29 100644
--- a/lib/stdlib/src/supervisor.erl
+++ b/lib/stdlib/src/supervisor.erl
@@ -270,6 +270,8 @@ start_children(Children, SupName) -> start_children(Children, [], SupName).
start_children([Child|Chs], NChildren, SupName) ->
case do_start_child(SupName, Child) of
+ {ok, undefined} when Child#child.restart_type =:= temporary ->
+ start_children(Chs, NChildren, SupName);
{ok, Pid} ->
start_children(Chs, [Child#child{pid = Pid}|NChildren], SupName);
{ok, Pid, _Extra} ->
@@ -325,6 +327,8 @@ handle_call({start_child, EArgs}, _From, State) when ?is_simple(State) ->
#child{mfargs = {M, F, A}} = Child,
Args = A ++ EArgs,
case do_start_child_i(M, F, Args) of
+ {ok, undefined} when Child#child.restart_type =:= temporary ->
+ {reply, {ok, undefined}, State};
{ok, Pid} ->
NState = save_dynamic_child(Child#child.restart_type, Pid, Args, State),
{reply, {ok, Pid}, NState};
@@ -611,12 +615,12 @@ handle_start_child(Child, State) ->
case get_child(Child#child.name, State) of
false ->
case do_start_child(State#state.name, Child) of
+ {ok, undefined} when Child#child.restart_type =:= temporary ->
+ {{ok, undefined}, State};
{ok, Pid} ->
- {{ok, Pid},
- save_child(Child#child{pid = Pid}, State)};
+ {{ok, Pid}, save_child(Child#child{pid = Pid}, State)};
{ok, Pid, Extra} ->
- {{ok, Pid, Extra},
- save_child(Child#child{pid = Pid}, State)};
+ {{ok, Pid, Extra}, save_child(Child#child{pid = Pid}, State)};
{error, What} ->
{{error, {What, Child}}, State}
end;
diff --git a/lib/stdlib/test/erl_eval_SUITE.erl b/lib/stdlib/test/erl_eval_SUITE.erl
index 369d8b224e..ca2f18a05a 100644
--- a/lib/stdlib/test/erl_eval_SUITE.erl
+++ b/lib/stdlib/test/erl_eval_SUITE.erl
@@ -1167,15 +1167,22 @@ do_funs(LFH, EFH) ->
[[[0]]], ['F'], LFH, EFH),
%% Tests for a bug found by the Dialyzer - used to crash.
- ?line check(fun() -> Pmod = erl_eval_helper:new(42), Pmod:add(5) end,
- "begin Pmod = erl_eval_helper:new(42), Pmod:add(5) end.",
- 47,
- ['Pmod'], LFH, EFH),
- ?line check(fun() -> Pmod = erl_eval_helper:new(42), B = Pmod:add(7), B end,
- "begin Pmod = erl_eval_helper:new(42), B = Pmod:add(7), B end.",
- 49,
- ['B','Pmod'], LFH, EFH),
-
+ case test_server:is_native(erl_eval) of
+ true ->
+ %% Parameterized modules are not supported by HiPE.
+ ok;
+ false ->
+ check(fun() -> Pmod = erl_eval_helper:new(42), Pmod:add(5) end,
+ "begin Pmod = erl_eval_helper:new(42), Pmod:add(5) end.",
+ 47,
+ ['Pmod'], LFH, EFH),
+ check(fun() -> Pmod = erl_eval_helper:new(42),
+ B = Pmod:add(7), B end,
+ "begin Pmod = erl_eval_helper:new(42), "
+ "B = Pmod:add(7), B end.",
+ 49,
+ ['B','Pmod'], LFH, EFH)
+ end,
ok.
count_down(F, N) when N > 0 ->
diff --git a/lib/stdlib/test/erl_expand_records_SUITE.erl b/lib/stdlib/test/erl_expand_records_SUITE.erl
index f8c1ad783c..8b162cfda0 100644
--- a/lib/stdlib/test/erl_expand_records_SUITE.erl
+++ b/lib/stdlib/test/erl_expand_records_SUITE.erl
@@ -178,6 +178,9 @@ expr(Config) when is_list(Config) ->
true ->
not_ok
end.
+
+ is_record(_, _, _) ->
+ error(wrong_is_record).
">>
],
@@ -366,6 +369,8 @@ strict(Config) when is_list(Config) ->
end
catch error:_ -> ok
end.
+ element(_, _) ->
+ error(wrong_element).
">>
],
?line run(Config, Ts1, [strict_record_tests]),
@@ -380,6 +385,8 @@ strict(Config) when is_list(Config) ->
case foo of
_ when A#r2.a =:= 1 -> ok
end.
+ element(_, _) ->
+ error(wrong_element).
">>
],
?line run(Config, Ts2, [no_strict_record_tests]),
@@ -415,6 +422,11 @@ update(Config) when is_list(Config) ->
t2() ->
R0 = #r{},
#r{_ = R0#r{a = ok}}.
+
+ %% Implicit calls to setelement/3 must go to the BIF,
+ %% not to this function.
+ setelement(_, _, _) ->
+ erlang:error(wrong_setelement_called).
">>
],
?line run(Config, Ts),
diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl
index 9041adbe5c..4e93f056ad 100644
--- a/lib/stdlib/test/erl_lint_SUITE.erl
+++ b/lib/stdlib/test/erl_lint_SUITE.erl
@@ -2631,7 +2631,35 @@ bif_clash(Config) when is_list(Config) ->
binary_part(A,B,C).
">>,
[warn_unused_import],
- {warnings,[{2,erl_lint,{redefine_bif_import,{binary_part,3}}}]}}
+ {warnings,[{2,erl_lint,{redefine_bif_import,{binary_part,3}}}]}},
+ %% Don't accept call to a guard BIF if there is a local definition
+ %% or an import with the same name. Note: is_record/2 is an
+ %% exception, since it is more of syntatic sugar than a real BIF.
+ {clash21,
+ <<"-export([is_list/1]).
+ -import(x, [is_tuple/1]).
+ -record(r, {a,b}).
+ x(T) when is_tuple(T) -> ok;
+ x(T) when is_list(T) -> ok.
+ y(T) when is_tuple(T) =:= true -> ok;
+ y(T) when is_list(T) =:= true -> ok;
+ y(T) when is_record(T, r, 3) -> ok;
+ y(T) when is_record(T, r, 3) =:= true -> ok;
+ y(T) when is_record(T, r) =:= true -> ok.
+ is_list(_) ->
+ ok.
+ is_record(_, _) ->
+ ok.
+ is_record(_, _, _) ->
+ ok.
+ ">>,
+ [{no_auto_import,[{is_tuple,1}]}],
+ {errors,[{4,erl_lint,{illegal_guard_local_call,{is_tuple,1}}},
+ {5,erl_lint,{illegal_guard_local_call,{is_list,1}}},
+ {6,erl_lint,{illegal_guard_local_call,{is_tuple,1}}},
+ {7,erl_lint,{illegal_guard_local_call,{is_list,1}}},
+ {8,erl_lint,{illegal_guard_local_call,{is_record,3}}},
+ {9,erl_lint,{illegal_guard_local_call,{is_record,3}}}],[]}}
],
?line [] = run(Config, Ts),
diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl
index 0e8849b5b3..101828fdef 100644
--- a/lib/stdlib/test/ets_SUITE.erl
+++ b/lib/stdlib/test/ets_SUITE.erl
@@ -74,7 +74,7 @@
-export([bad_table/1, types/1]).
-export([otp_9423/1]).
--export([init_per_testcase/2]).
+-export([init_per_testcase/2, end_per_testcase/2]).
%% Convenience for manual testing
-export([random_test/0]).
@@ -2385,6 +2385,8 @@ setopts_do(Opts) ->
?line {'EXIT',{badarg,_}} = (catch ets:setopts(T,{protection,private,false})),
?line {'EXIT',{badarg,_}} = (catch ets:setopts(T,protection)),
?line ets:delete(T),
+ unlink(Heir),
+ exit(Heir, bang),
ok.
bad_table(doc) -> ["All kinds of operations with bad table argument"];
@@ -5645,7 +5647,8 @@ spawn_logger(Procs) ->
true -> exit(Proc, kill);
_ -> ok
end,
- erlang:display(process_info(Proc)),
+ erlang:display({"Waiting for 'DOWN' from", Proc,
+ process_info(Proc), pid_status(Proc)}),
receive
{'DOWN', Mon, _, _, _} ->
ok
@@ -5656,6 +5659,15 @@ spawn_logger(Procs) ->
spawn_logger([From])
end.
+pid_status(Pid) ->
+ try
+ erts_debug:get_internal_state({process_status, Pid})
+ catch
+ error:undef ->
+ erts_debug:set_internal_state(available_internal_state, true),
+ pid_status(Pid)
+ end.
+
start_spawn_logger() ->
case whereis(ets_test_spawn_logger) of
Pid when is_pid(Pid) -> true;
diff --git a/lib/stdlib/test/ms_transform_SUITE.erl b/lib/stdlib/test/ms_transform_SUITE.erl
index c9688354b1..a17307b07b 100644
--- a/lib/stdlib/test/ms_transform_SUITE.erl
+++ b/lib/stdlib/test/ms_transform_SUITE.erl
@@ -455,7 +455,6 @@ old_guards(Config) when is_list(Config) ->
?line setup(Config),
Tests = [
{atom,is_atom},
- {constant,is_constant},
{float,is_float},
{integer,is_integer},
{list,is_list},
@@ -490,7 +489,6 @@ old_guards(Config) when is_list(Config) ->
?line [{'$1',[{is_integer,'$1'},
{is_float,'$1'},
{is_atom,'$1'},
- {is_constant,'$1'},
{is_list,'$1'},
{is_number,'$1'},
{is_pid,'$1'},
@@ -502,7 +500,7 @@ old_guards(Config) when is_list(Config) ->
[true]}] =
compile_and_run(RD, <<
"ets:fun2ms(fun(X) when integer(X),"
- "float(X), atom(X), constant(X),"
+ "float(X), atom(X),"
"list(X), number(X), pid(X),"
"port(X), reference(X), tuple(X),"
"binary(X), record(X,a) -> true end)"
@@ -530,7 +528,6 @@ autoimported(Config) when is_list(Config) ->
{self,0},
%{float,1}, see float_1_function/1
{is_atom,1},
- {is_constant,1},
{is_float,1},
{is_integer,1},
{is_list,1},
diff --git a/lib/stdlib/test/re_SUITE.erl b/lib/stdlib/test/re_SUITE.erl
index 3b2e637c84..d6d946a28f 100644
--- a/lib/stdlib/test/re_SUITE.erl
+++ b/lib/stdlib/test/re_SUITE.erl
@@ -445,9 +445,17 @@ split_specials(Config) when is_list(Config) ->
ok.
-error_handling(doc) ->
- ["Test that errors are handled correctly by the erlang code."];
-error_handling(Config) when is_list(Config) ->
+%% Test that errors are handled correctly by the erlang code.
+error_handling(_Config) ->
+ case test_server:is_native(re) of
+ true ->
+ %% Exceptions from native code look too different.
+ {skip,"re is native"};
+ false ->
+ error_handling()
+ end.
+
+error_handling() ->
% This test checks the exception tuples manufactured in the erlang
% code to hide the trapping from the user at least when it comes to errors
Dog = ?t:timetrap(?t:minutes(1)),
@@ -455,14 +463,14 @@ error_handling(Config) when is_list(Config) ->
% the trap to re:grun from grun, in the grun function clause
% that handles precompiled expressions
?line {'EXIT',{badarg,[{re,run,["apa",{1,2,3,4},[global]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(catch re:run("apa",{1,2,3,4},[global])),
% An invalid capture list will also cause a badarg late,
% but with a non pre compiled RE, the exception should be thrown by the
% grun function clause that handles RE's compiled implicitly by
% the run/3 BIF before trapping.
?line {'EXIT',{badarg,[{re,run,["apa","p",[{capture,[1,{a}]},global]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(catch re:run("apa","p",[{capture,[1,{a}]},global])),
% And so the case of a precompiled expression together with
% a compile-option (binary and list subject):
@@ -473,88 +481,88 @@ error_handling(Config) when is_list(Config) ->
[<<"apa">>,
{re_pattern,1,0,_},
[global,unicode]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(catch re:run(<<"apa">>,RE,[global,unicode])),
?line {'EXIT',{badarg,[{re,run,
["apa",
{re_pattern,1,0,_},
[global,unicode]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(catch re:run("apa",RE,[global,unicode])),
?line {'EXIT',{badarg,_}} = (catch re:run("apa","(p",[])),
?line {'EXIT',{badarg,_}} = (catch re:run("apa","(p",[global])),
% The replace errors:
?line {'EXIT',{badarg,[{re,replace,["apa",{1,2,3,4},"X",[]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(catch re:replace("apa",{1,2,3,4},"X",[])),
?line {'EXIT',{badarg,[{re,replace,["apa",{1,2,3,4},"X",[global]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(catch re:replace("apa",{1,2,3,4},"X",[global])),
?line {'EXIT',{badarg,[{re,replace,
["apa",
{re_pattern,1,0,_},
"X",
[unicode]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(catch re:replace("apa",RE,"X",[unicode])),
?line <<"aXa">> = iolist_to_binary(re:replace("apa","p","X",[])),
?line {'EXIT',{badarg,[{re,replace,
["apa","p","X",[{capture,all,binary}]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(catch iolist_to_binary(re:replace("apa","p","X",
[{capture,all,binary}]))),
?line {'EXIT',{badarg,[{re,replace,
["apa","p","X",[{capture,all}]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(catch iolist_to_binary(re:replace("apa","p","X",
[{capture,all}]))),
?line {'EXIT',{badarg,[{re,replace,
["apa","p","X",[{return,banana}]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(catch iolist_to_binary(re:replace("apa","p","X",
[{return,banana}]))),
?line {'EXIT',{badarg,_}} = (catch re:replace("apa","(p","X",[])),
% Badarg, not compile error.
?line {'EXIT',{badarg,[{re,replace,
["apa","(p","X",[{return,banana}]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(catch iolist_to_binary(re:replace("apa","(p","X",
[{return,banana}]))),
% And the split errors:
?line [<<"a">>,<<"a">>] = (catch re:split("apa","p",[])),
?line [<<"a">>,<<"p">>,<<"a">>] = (catch re:split("apa",RE,[])),
?line {'EXIT',{badarg,[{re,split,["apa","p",[global]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(catch re:split("apa","p",[global])),
?line {'EXIT',{badarg,[{re,split,["apa","p",[{capture,all}]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(catch re:split("apa","p",[{capture,all}])),
?line {'EXIT',{badarg,[{re,split,["apa","p",[{capture,all,binary}]],_},
- {?MODULE, error_handling,1,_} | _]}} =
+ {?MODULE, error_handling,0,_} | _]}} =
(catch re:split("apa","p",[{capture,all,binary}])),
?line {'EXIT',{badarg,[{re,split,["apa",{1,2,3,4},[]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(catch re:split("apa",{1,2,3,4})),
?line {'EXIT',{badarg,[{re,split,["apa",{1,2,3,4},[]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(catch re:split("apa",{1,2,3,4},[])),
?line {'EXIT',{badarg,[{re,split,
["apa",
RE,
[unicode]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(catch re:split("apa",RE,[unicode])),
?line {'EXIT',{badarg,[{re,split,
["apa",
RE,
[{return,banana}]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(catch re:split("apa",RE,[{return,banana}])),
?line {'EXIT',{badarg,[{re,split,
["apa",
RE,
[banana]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(catch re:split("apa",RE,[banana])),
?line {'EXIT',{badarg,_}} = (catch re:split("apa","(p")),
%Exception on bad argument, not compilation error
@@ -562,7 +570,7 @@ error_handling(Config) when is_list(Config) ->
["apa",
"(p",
[banana]],_},
- {?MODULE,error_handling,1,_} | _]}} =
+ {?MODULE,error_handling,0,_} | _]}} =
(catch re:split("apa","(p",[banana])),
?t:timetrap_cancel(Dog),
ok.
diff --git a/lib/stdlib/test/shell_SUITE.erl b/lib/stdlib/test/shell_SUITE.erl
index b6019b86f0..a881742f13 100644
--- a/lib/stdlib/test/shell_SUITE.erl
+++ b/lib/stdlib/test/shell_SUITE.erl
@@ -2388,13 +2388,28 @@ otp_6554(Config) when is_list(Config) ->
comm_err(<<"V = lists:seq(1, 20), case V of a -> ok end.">>),
?line "exception error: no function clause matching" =
comm_err(<<"fun(P) when is_pid(P) -> true end(a).">>),
- ?line "exception error: {function_clause," =
- comm_err(<<"erlang:error(function_clause, [unproper | list]).">>),
+ case test_server:is_native(erl_eval) of
+ true ->
+ %% Native code has different exit reason. Don't bother
+ %% testing them.
+ ok;
+ false ->
+ "exception error: {function_clause," =
+ comm_err(<<"erlang:error(function_clause, "
+ "[unproper | list]).">>),
+ %% Cheating:
+ "exception error: no function clause matching "
+ "erl_eval:do_apply(4)" ++ _ =
+ comm_err(<<"erlang:error(function_clause, [4]).">>),
+ "exception error: no function clause matching "
+ "lists:reverse(" ++ _ =
+ comm_err(<<"F=fun() -> hello end, lists:reverse(F).">>),
+ "exception error: no function clause matching "
+ "lists:reverse(34) (lists.erl, line " ++ _ =
+ comm_err(<<"lists:reverse(34).">>)
+ end,
?line "exception error: function_clause" =
comm_err(<<"erlang:error(function_clause, 4).">>),
- %% Cheating:
- ?line "exception error: no function clause matching erl_eval:do_apply(4)" ++ _ =
- comm_err(<<"erlang:error(function_clause, [4]).">>),
?line "exception error: no function clause matching" ++ _ =
comm_err(<<"fun(a, b, c, d) -> foo end"
" (lists:seq(1,17),"
@@ -2404,10 +2419,6 @@ otp_6554(Config) when is_list(Config) ->
?line "exception error: no function clause matching" =
comm_err(<<"fun(P, q) when is_pid(P) -> true end(a, b).">>),
- ?line "exception error: no function clause matching lists:reverse(" ++ _ =
- comm_err(<<"F=fun() -> hello end, lists:reverse(F).">>),
- ?line "exception error: no function clause matching lists:reverse(34) (lists.erl, line " ++ _ =
- comm_err(<<"lists:reverse(34).">>),
?line "exception error: no true branch found when evaluating an if expression" =
comm_err(<<"if length([a,b]) > 17 -> a end.">>),
?line "exception error: no such process or port" =
diff --git a/lib/stdlib/test/sofs_SUITE.erl b/lib/stdlib/test/sofs_SUITE.erl
index 73b282149a..f11c6ec4d6 100644
--- a/lib/stdlib/test/sofs_SUITE.erl
+++ b/lib/stdlib/test/sofs_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -536,7 +536,7 @@ projection(Conf) when is_list(Conf) ->
from_term([], [[atom]]))),
?line {'EXIT', {badarg, _}} =
(catch projection({external, fun(X) -> X end}, from_term([[a]]))),
- ?line eval(projection({sofs,union},
+ ?line eval(projection(fun sofs:union/1,
from_term([[[1,2],[2,3]], [[a,b],[b,c]]])),
from_term([[1,2,3], [a,b,c]])),
?line eval(projection(fun(_) -> from_term([a]) end,
@@ -628,7 +628,7 @@ substitution(Conf) when is_list(Conf) ->
?line {'EXIT', {badarg, _}} =
(catch substitution({external, fun(X) -> X end}, from_term([[a]]))),
?line eval(substitution(fun(X) -> X end, from_term([], [[atom]])), E),
- ?line eval(substitution({sofs,union},
+ ?line eval(substitution(fun sofs:union/1,
from_term([[[1,2],[2,3]], [[a,b],[b,c]]])),
from_term([{[[1,2],[2,3]],[1,2,3]}, {[[a,b],[b,c]],[a,b,c]}])),
?line eval(substitution(fun(_) -> from_term([a]) end,
@@ -745,7 +745,7 @@ restriction(Conf) when is_list(Conf) ->
?line eval(restriction(Id, S3, E), E),
?line eval(restriction(Id, from_term([], [[atom]]), set([a])),
from_term([], [[atom]])),
- ?line eval(restriction({sofs,union},
+ ?line eval(restriction(fun sofs:union/1,
from_term([[[a],[b]], [[b],[c]],
[[], [a,b]], [[1],[2]]]),
from_term([[a,b],[1,2,3],[b,c]])),
@@ -862,7 +862,7 @@ drestriction(Conf) when is_list(Conf) ->
?line eval(drestriction(Id, S3, E), S3),
?line eval(drestriction(Id, from_term([], [[atom]]), set([a])),
from_term([], [[atom]])),
- ?line eval(drestriction({sofs,union},
+ ?line eval(drestriction(fun sofs:union/1,
from_term([[[a],[b]], [[b],[c]],
[[], [a,b]], [[1],[2]]]),
from_term([[a,b],[1,2,3],[b,c]])),
@@ -1028,7 +1028,7 @@ specification(Conf) when is_list(Conf) ->
end,
?line eval(specification({external,Fun2x}, S2), from_term([[1],[3]])),
- Fun3 = fun(_) -> neither_true_or_false end,
+ Fun3 = fun(_) -> neither_true_nor_false end,
?line {'EXIT', {badarg, _}} =
(catch specification(Fun3, set([a]))),
?line {'EXIT', {badarg, _}} =
@@ -1810,8 +1810,8 @@ partition_3(Conf) when is_list(Conf) ->
S12a = from_term([[[a],[b]], [[b],[c]], [[], [a,b]], [[1],[2]]]),
S12b = from_term([[a,b],[1,2,3],[b,c]]),
- ?line eval(partition({sofs,union}, S12a, S12b),
- lpartition({sofs,union}, S12a, S12b)),
+ ?line eval(partition(fun sofs:union/1, S12a, S12b),
+ lpartition(fun sofs:union/1, S12a, S12b)),
Fun13 = fun(_) -> from_term([a]) end,
S13a = from_term([], [[atom]]),
@@ -1879,12 +1879,9 @@ digraph(Conf) when is_list(Conf) ->
?line {'EXIT', {badarg, _}} =
(catch family_to_digraph(set([a]))),
- ?line {'EXIT', {badarg, [{sofs,family_to_digraph,[_,_],_}|_]}} =
- (catch family_to_digraph(set([a]), [foo])),
- ?line {'EXIT', {badarg, [{sofs,family_to_digraph,[_,_],_}|_]}} =
- (catch family_to_digraph(F, [foo])),
- ?line {'EXIT', {cyclic, [{sofs,family_to_digraph,[_,_],_}|_]}} =
- (catch family_to_digraph(family([{a,[a]}]),[acyclic])),
+ digraph_fail(badarg, catch family_to_digraph(set([a]), [foo])),
+ digraph_fail(badarg, catch family_to_digraph(F, [foo])),
+ digraph_fail(cyclic, catch family_to_digraph(family([{a,[a]}]),[acyclic])),
?line G1 = family_to_digraph(E),
?line {'EXIT', {badarg, _}} = (catch digraph_to_family(G1, foo)),
@@ -1927,6 +1924,13 @@ digraph(Conf) when is_list(Conf) ->
?line true = T0 == ets:all(),
ok.
+digraph_fail(ExitReason, Fail) ->
+ {'EXIT', {ExitReason, [{sofs,family_to_digraph,A,_}|_]}} = Fail,
+ case {test_server:is_native(sofs),A} of
+ {false,[_,_]} -> ok;
+ {true,2} -> ok
+ end.
+
constant_function(suite) -> [];
constant_function(doc) -> [""];
constant_function(Conf) when is_list(Conf) ->
@@ -1952,10 +1956,8 @@ misc(Conf) when is_list(Conf) ->
% the "functional" part:
?line eval(union(intersection(partition(1,S), partition(Id,S))),
difference(S, RR)),
-
- %% The function external:foo/1 is undefined.
?line {'EXIT', {undef, _}} =
- (catch projection({external,foo}, set([a,b,c]))),
+ (catch projection(fun external:foo/1, set([a,b,c]))),
ok.
relational_restriction(R) ->
@@ -1968,19 +1970,19 @@ family_specification(doc) -> [""];
family_specification(Conf) when is_list(Conf) ->
E = empty_set(),
%% internal
- ?line eval(family_specification({sofs, is_set}, E), E),
+ ?line eval(family_specification(fun sofs:is_set/1, E), E),
?line {'EXIT', {badarg, _}} =
- (catch family_specification({sofs,is_set}, set([]))),
+ (catch family_specification(fun sofs:is_set/1, set([]))),
?line F1 = from_term([{1,[1]}]),
- ?line eval(family_specification({sofs,is_set}, F1), F1),
+ ?line eval(family_specification(fun sofs:is_set/1, F1), F1),
Fun = fun(S) -> is_subset(S, set([0,1,2,3,4])) end,
?line F2 = family([{a,[1,2]},{b,[3,4,5]}]),
?line eval(family_specification(Fun, F2), family([{a,[1,2]}])),
?line F3 = from_term([{a,[]},{b,[]}]),
- ?line eval(family_specification({sofs,is_set}, F3), F3),
+ ?line eval(family_specification(fun sofs:is_set/1, F3), F3),
Fun2 = fun(_) -> throw(fippla) end,
?line fippla = (catch family_specification(Fun2, family([{a,[1]}]))),
- Fun3 = fun(_) -> neither_true_or_false end,
+ Fun3 = fun(_) -> neither_true_nor_false end,
?line {'EXIT', {badarg, _}} =
(catch family_specification(Fun3, F3)),
@@ -2095,22 +2097,22 @@ family_projection(Conf) when is_list(Conf) ->
?line eval(family_projection(fun(X) -> X end, family([])), E),
?line L1 = [{a,[]}],
- ?line eval(family_projection({sofs,union}, E), E),
- ?line eval(family_projection({sofs,union}, from_term(L1, SSType)),
+ ?line eval(family_projection(fun sofs:union/1, E), E),
+ ?line eval(family_projection(fun sofs:union/1, from_term(L1, SSType)),
family(L1)),
?line {'EXIT', {badarg, _}} =
- (catch family_projection({sofs,union}, set([]))),
+ (catch family_projection(fun sofs:union/1, set([]))),
?line {'EXIT', {badarg, _}} =
- (catch family_projection({sofs,union}, from_term([{1,[1]}]))),
+ (catch family_projection(fun sofs:union/1, from_term([{1,[1]}]))),
?line F2 = from_term([{a,[[1],[2]]},{b,[[3,4],[5]]}], SSType),
- ?line eval(family_projection({sofs,union}, F2),
+ ?line eval(family_projection(fun sofs:union/1, F2),
family_union(F2)),
?line F3 = from_term([{1,[{a,b},{b,c},{c,d}]},{3,[]},{5,[{3,5}]}],
SRType),
- ?line eval(family_projection({sofs,domain}, F3), family_domain(F3)),
- ?line eval(family_projection({sofs,range}, F3), family_range(F3)),
+ ?line eval(family_projection(fun sofs:domain/1, F3), family_domain(F3)),
+ ?line eval(family_projection(fun sofs:range/1, F3), family_range(F3)),
?line eval(family_projection(fun(_) -> E end, family([{a,[b,c]}])),
from_term([{a,[]}])),
@@ -2290,7 +2292,7 @@ partition_family(Conf) when is_list(Conf) ->
?line eval(partition_family(1, E), E),
?line eval(partition_family(2, E), E),
- ?line eval(partition_family({sofs,union}, E), E),
+ ?line eval(partition_family(fun sofs:union/1, E), E),
?line eval(partition_family(1, ER), EF),
?line eval(partition_family(2, ER), EF),
?line {'EXIT', {badarg, _}} = (catch partition_family(1, set([]))),
@@ -2354,7 +2356,7 @@ partition_family(Conf) when is_list(Conf) ->
?line {'EXIT', {badarg, _}} =
(catch partition_family({external, fun(X) -> X end},
from_term([[a]]))),
- ?line eval(partition_family({sofs,union},
+ ?line eval(partition_family(fun sofs:union/1,
from_term([[[1],[1,2]], [[1,2]]])),
from_term([{[1,2], [[[1],[1,2]],[[1,2]]]}])),
?line eval(partition_family(fun(X) -> X end,
diff --git a/lib/stdlib/test/supervisor_SUITE.erl b/lib/stdlib/test/supervisor_SUITE.erl
index fa6faa66f2..71b76c093f 100644
--- a/lib/stdlib/test/supervisor_SUITE.erl
+++ b/lib/stdlib/test/supervisor_SUITE.erl
@@ -34,8 +34,10 @@
%% API tests
-export([ sup_start_normal/1, sup_start_ignore_init/1,
- sup_start_ignore_child/1, sup_start_error_return/1,
- sup_start_fail/1, sup_stop_infinity/1,
+ sup_start_ignore_child/1, sup_start_ignore_temporary_child/1,
+ sup_start_ignore_temporary_child_start_child/1,
+ sup_start_ignore_temporary_child_start_child_simple/1,
+ sup_start_error_return/1, sup_start_fail/1, sup_stop_infinity/1,
sup_stop_timeout/1, sup_stop_brutal_kill/1, child_adm/1,
child_adm_simple/1, child_specs/1, extra_return/1]).
@@ -85,8 +87,10 @@ all() ->
groups() ->
[{sup_start, [],
[sup_start_normal, sup_start_ignore_init,
- sup_start_ignore_child, sup_start_error_return,
- sup_start_fail]},
+ sup_start_ignore_child, sup_start_ignore_temporary_child,
+ sup_start_ignore_temporary_child_start_child,
+ sup_start_ignore_temporary_child_start_child_simple,
+ sup_start_error_return, sup_start_fail]},
{sup_stop, [],
[sup_stop_infinity, sup_stop_timeout,
sup_stop_brutal_kill]},
@@ -191,6 +195,59 @@ sup_start_ignore_child(Config) when is_list(Config) ->
[2,1,0,2] = get_child_counts(sup_test).
%%-------------------------------------------------------------------------
+%% Tests what happens if child's init-callback returns ignore for a
+%% temporary child when ChildSpec is returned directly from supervisor
+%% init callback.
+%% Child spec shall NOT be saved!!!
+sup_start_ignore_temporary_child(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ Child1 = {child1, {supervisor_1, start_child, [ignore]},
+ temporary, 1000, worker, []},
+ Child2 = {child2, {supervisor_1, start_child, []}, temporary,
+ 1000, worker, []},
+ {ok, _Pid} = start_link({ok, {{one_for_one, 2, 3600}, [Child1,Child2]}}),
+
+ [{child2, CPid2, worker, []}] = supervisor:which_children(sup_test),
+ true = is_pid(CPid2),
+ [1,1,0,1] = get_child_counts(sup_test).
+
+%%-------------------------------------------------------------------------
+%% Tests what happens if child's init-callback returns ignore for a
+%% temporary child when child is started with start_child/2.
+%% Child spec shall NOT be saved!!!
+sup_start_ignore_temporary_child_start_child(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ {ok, _Pid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
+ Child1 = {child1, {supervisor_1, start_child, [ignore]},
+ temporary, 1000, worker, []},
+ Child2 = {child2, {supervisor_1, start_child, []}, temporary,
+ 1000, worker, []},
+
+ {ok, undefined} = supervisor:start_child(sup_test, Child1),
+ {ok, CPid2} = supervisor:start_child(sup_test, Child2),
+
+ [{child2, CPid2, worker, []}] = supervisor:which_children(sup_test),
+ [1,1,0,1] = get_child_counts(sup_test).
+
+%%-------------------------------------------------------------------------
+%% Tests what happens if child's init-callback returns ignore for a
+%% temporary child when child is started with start_child/2, and the
+%% supervisor is simple_one_for_one.
+%% Child spec shall NOT be saved!!!
+sup_start_ignore_temporary_child_start_child_simple(Config)
+ when is_list(Config) ->
+ process_flag(trap_exit, true),
+ Child1 = {child1, {supervisor_1, start_child, [ignore]},
+ temporary, 1000, worker, []},
+ {ok, _Pid} = start_link({ok, {{simple_one_for_one, 2, 3600}, [Child1]}}),
+
+ {ok, undefined} = supervisor:start_child(sup_test, []),
+ {ok, CPid2} = supervisor:start_child(sup_test, []),
+
+ [{undefined, CPid2, worker, []}] = supervisor:which_children(sup_test),
+ [1,1,0,1] = get_child_counts(sup_test).
+
+%%-------------------------------------------------------------------------
%% Tests what happens if init-callback returns a invalid value.
sup_start_error_return(Config) when is_list(Config) ->
process_flag(trap_exit, true),
diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk
index 2f0ecd3863..694d39ce9c 100644
--- a/lib/stdlib/vsn.mk
+++ b/lib/stdlib/vsn.mk
@@ -1 +1 @@
-STDLIB_VSN = 1.18
+STDLIB_VSN = 1.18.1
diff --git a/lib/syntax_tools/src/Makefile b/lib/syntax_tools/src/Makefile
index 50369e633e..bac138e95a 100644
--- a/lib/syntax_tools/src/Makefile
+++ b/lib/syntax_tools/src/Makefile
@@ -26,7 +26,7 @@ EBIN = ../ebin
ifeq ($(NATIVE_LIBS_ENABLED),yes)
ERL_COMPILE_FLAGS += +native
endif
-ERL_COMPILE_FLAGS += +warn_unused_vars +nowarn_shadow_vars +warn_unused_import +warn_missing_spec +warn_untyped_record
+ERL_COMPILE_FLAGS += +warn_unused_vars +nowarn_shadow_vars +warn_unused_import # +warn_missing_spec +warn_untyped_record
SOURCES=erl_syntax.erl erl_prettypr.erl erl_syntax_lib.erl \
erl_comment_scan.erl erl_recomment.erl erl_tidy.erl \
diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl
index 7f58fda519..32fd3722d6 100644
--- a/lib/syntax_tools/src/erl_syntax.erl
+++ b/lib/syntax_tools/src/erl_syntax.erl
@@ -6100,8 +6100,9 @@ implicit_fun_name(Node) ->
arity_qualifier(
set_pos(atom(Atom), Pos),
set_pos(integer(Arity), Pos)));
- {'fun', Pos, {function, Module, Atom, Arity}} ->
+ {'fun', _Pos, {function, Module, Atom, Arity}} ->
%% New in R15: fun M:F/A.
+ %% XXX: Perhaps set position for this as well?
module_qualifier(Module, arity_qualifier(Atom, Arity));
Node1 ->
data(Node1)
diff --git a/lib/toolbar/doc/src/toolbar.xml b/lib/toolbar/doc/src/toolbar.xml
index ad379438fe..3ad0b4eb78 100644
--- a/lib/toolbar/doc/src/toolbar.xml
+++ b/lib/toolbar/doc/src/toolbar.xml
@@ -33,6 +33,11 @@
<module>toolbar</module>
<modulesummary>GUI for Starting Tools and User Contributions</modulesummary>
<description>
+ <warning>
+ <p>
+ The Toolbar application is deprecated and will be removed in R16.
+ </p>
+ </warning>
<p>Toolbar makes it easier to use
the different Erlang tools - and the user contributions - which are provided.
It has a graphical user interface with an icon for each tool.
diff --git a/lib/toolbar/doc/src/toolbar_chapter.xml b/lib/toolbar/doc/src/toolbar_chapter.xml
index a80dc5bd3e..4ea2101218 100644
--- a/lib/toolbar/doc/src/toolbar_chapter.xml
+++ b/lib/toolbar/doc/src/toolbar_chapter.xml
@@ -28,6 +28,11 @@
<rev>A</rev>
<file>toolbar_chapter.xml</file>
</header>
+ <warning>
+ <p>
+ The Toolbar application is deprecated and will be removed in R16.
+ </p>
+ </warning>
<p>Toolbar provides an interface to the various Erlang tools which are available. Toolbar can also provide access to user supplied tools which are included with the Erlang software release. These tools are called GS Contributions.</p>
<p>All tools included in Toolbar must have a configuration file which contains information about the tool, such as its start function and the location of help information. The name of a configuration file must include the suffix <c>.tool</c>.
</p>
diff --git a/lib/toolbar/src/canvasbutton.erl b/lib/toolbar/src/canvasbutton.erl
index 38fce537bb..7613253efe 100644
--- a/lib/toolbar/src/canvasbutton.erl
+++ b/lib/toolbar/src/canvasbutton.erl
@@ -17,6 +17,9 @@
%% %CopyrightEnd%
%%
-module(canvasbutton).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,read,2}}]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
diff --git a/lib/toolbar/src/toolbar.erl b/lib/toolbar/src/toolbar.erl
index 67967172fe..b78df15700 100644
--- a/lib/toolbar/src/toolbar.erl
+++ b/lib/toolbar/src/toolbar.erl
@@ -17,6 +17,7 @@
%% %CopyrightEnd%
%%
-module(toolbar).
+-compile([{nowarn_deprecated_function,{gs,start,1}}]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
diff --git a/lib/toolbar/src/toolbar_graphics.erl b/lib/toolbar/src/toolbar_graphics.erl
index ad390440e3..b442d7ff06 100644
--- a/lib/toolbar/src/toolbar_graphics.erl
+++ b/lib/toolbar/src/toolbar_graphics.erl
@@ -17,6 +17,9 @@
%% %CopyrightEnd%
%%
-module(toolbar_graphics).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,read,2}}]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
diff --git a/lib/toolbar/src/toolbar_toolconfig.erl b/lib/toolbar/src/toolbar_toolconfig.erl
index 6dccb7ba72..6fb56cb1bd 100644
--- a/lib/toolbar/src/toolbar_toolconfig.erl
+++ b/lib/toolbar/src/toolbar_toolconfig.erl
@@ -17,6 +17,11 @@
%% %CopyrightEnd%
%%
-module(toolbar_toolconfig).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
diff --git a/lib/tools/c_src/Makefile.in b/lib/tools/c_src/Makefile.in
index 604332a91e..b8c4aed6e2 100644
--- a/lib/tools/c_src/Makefile.in
+++ b/lib/tools/c_src/Makefile.in
@@ -1,19 +1,20 @@
-# ``The contents of this file are subject to the Erlang Public License,
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2009-2012. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
# compliance with the License. You should have received a copy of the
# Erlang Public License along with this software. If not, it can be
-# retrieved via the world wide web at http://www.erlang.org/.
-#
+# 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.
-#
-# The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
-# AB. All Rights Reserved.''
-#
-# $Id$
+#
+# %CopyrightEnd%
#
include $(ERL_TOP)/make/target.mk
@@ -138,15 +139,17 @@ EMEM_LIBS = $(LIBS) \
EMEM_OBJS = $(addprefix $(EMEM_OBJ_DIR)/,$(notdir $(EMEM_SRCS:.c=.o)))
+ERTS_LIB = $(ERL_TOP/erts/lib_src/obj/$(TARGET)/$(TYPE)/MADE
+
#
# Misc targets
#
_create_dirs := $(shell mkdir -p $(CREATE_DIRS))
-all: erts_lib $(PROGS) $(DRIVERS)
+all: $(PROGS) $(DRIVERS)
-erts_lib:
+$(ERTS_LIB):
cd $(ERL_TOP)/erts/lib_src && $(MAKE) $(TYPE)
@@ -174,7 +177,7 @@ $(EMEM_OBJ_DIR)/%.o: %.c
# Program targets
#
-$(BIN_DIR)/emem$(TYPEMARKER)@EXEEXT@: $(EMEM_OBJS)
+$(BIN_DIR)/emem$(TYPEMARKER)@EXEEXT@: $(EMEM_OBJS) $(ERTS_LIB)
$(PRE_LD) $(LD) $(EMEM_LDFLAGS) -o $@ $(EMEM_OBJS) $(EMEM_LIBS)
#
diff --git a/lib/tools/c_src/erl_memory.c b/lib/tools/c_src/erl_memory.c
index 872d55e789..5239176d03 100644
--- a/lib/tools/c_src/erl_memory.c
+++ b/lib/tools/c_src/erl_memory.c
@@ -1224,7 +1224,7 @@ print_main_footer(em_state *state)
switch (state->info.stop_reason) {
case EMTP_STOP:
- p += sprintf(p, stop_str);
+ p += sprintf(p, "%s", stop_str);
break;
case EMTP_EXIT:
p += sprintf(p, exit_str, state->info.exit_status);
@@ -2339,7 +2339,7 @@ usage(char *sw, char *error)
if (error)
exit(1);
else {
- char *help_str =
+ fprintf(filep,
"\n"
" [] - switch is allowed any number of times\n"
" {} - switch is allowed at most one time\n"
@@ -2370,8 +2370,7 @@ usage(char *sw, char *error)
" " SW_CHAR "o - display operation count values\n"
" " SW_CHAR "p <P> - set listen port to <P>\n"
" " SW_CHAR "t - display info about total values\n"
- " " SW_CHAR "v - verbose output\n";
- fprintf(filep, help_str);
+ " " SW_CHAR "v - verbose output\n");
exit(0);
}
diff --git a/lib/tools/test/fprof_SUITE.erl b/lib/tools/test/fprof_SUITE.erl
index 0da6d4a9ea..f491c1e227 100644
--- a/lib/tools/test/fprof_SUITE.erl
+++ b/lib/tools/test/fprof_SUITE.erl
@@ -191,11 +191,17 @@ tail_seq(Config) when is_list(Config) ->
%%%---------------------------------------------------------------------
-create_file_slow(doc) ->
- ["Tests the create_file_slow benchmark"];
-create_file_slow(suite) ->
- [];
-create_file_slow(Config) when is_list(Config) ->
+%% Tests the create_file_slow benchmark.
+create_file_slow(Config) ->
+ case test_server:is_native(lists) orelse
+ test_server:is_native(file) of
+ true ->
+ {skip,"Native libs -- tracing does not work"};
+ false ->
+ do_create_file_slow(Config)
+ end.
+
+do_create_file_slow(Config) ->
?line Timetrap = ?t:timetrap(?t:seconds(40)),
?line PrivDir = ?config(priv_dir, Config),
?line TraceFile =
diff --git a/lib/tv/doc/src/table_visualizer_chapter.xml b/lib/tv/doc/src/table_visualizer_chapter.xml
index 12efbe643c..dbfd322945 100644
--- a/lib/tv/doc/src/table_visualizer_chapter.xml
+++ b/lib/tv/doc/src/table_visualizer_chapter.xml
@@ -31,6 +31,12 @@
<rev>C</rev>
<file>table_visualizer.xml</file>
</header>
+ <warning>
+ <p>
+ The TV application has been superseded by the Observer application.
+ TV will be removed in R16.
+ </p>
+ </warning>
<p>The TV, TV, is a tool that enables the user to examine
ETS and Mnesia tables on any (connected) node in the currently running Erlang
system. Once a certain table has been opened in the tool, the content may be
diff --git a/lib/tv/doc/src/tv.xml b/lib/tv/doc/src/tv.xml
index 84b9f8c33d..83bbdfc052 100644
--- a/lib/tv/doc/src/tv.xml
+++ b/lib/tv/doc/src/tv.xml
@@ -36,6 +36,12 @@
<module>tv</module>
<modulesummary>TV graphically examines ETS and Mnesia tables. </modulesummary>
<description>
+ <warning>
+ <p>
+ The TV application has been superseded by the Observer application.
+ TV will be removed in R16.
+ </p>
+ </warning>
<p>TV enables the user to examine ETS and Mnesia tables. Once
a certain table has been opened in the tool, the content may be viewed at
various levels of detail. The content viewed may also be sorted, using any
diff --git a/lib/tv/src/tv_db.erl b/lib/tv/src/tv_db.erl
index 201b4c0e6b..179b75c2e6 100644
--- a/lib/tv/src/tv_db.erl
+++ b/lib/tv/src/tv_db.erl
@@ -22,6 +22,10 @@
%%%*********************************************************************
-module(tv_db).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_db_search.erl b/lib/tv/src/tv_db_search.erl
index 7bf5c4c048..6ae999253a 100644
--- a/lib/tv/src/tv_db_search.erl
+++ b/lib/tv/src/tv_db_search.erl
@@ -21,6 +21,18 @@
%%%
%%%*********************************************************************
-module(tv_db_search).
+-compile([{nowarn_deprecated_function,{gs,button,3}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,entry,3}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,label,3}},
+ {nowarn_deprecated_function,{gs,listbox,3}},
+ {nowarn_deprecated_function,{gs,radiobutton,3}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_etsread.erl b/lib/tv/src/tv_etsread.erl
index d3240ef513..b3e38f9d45 100644
--- a/lib/tv/src/tv_etsread.erl
+++ b/lib/tv/src/tv_etsread.erl
@@ -25,6 +25,9 @@
-module(tv_etsread).
+-compile([{nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_info.erl b/lib/tv/src/tv_info.erl
index 7bc31e35cd..941286362c 100644
--- a/lib/tv/src/tv_info.erl
+++ b/lib/tv/src/tv_info.erl
@@ -16,6 +16,14 @@
%%
%% %CopyrightEnd%
-module(tv_info).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,listbox,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_ip.erl b/lib/tv/src/tv_ip.erl
index aeec4e8f6d..2d3ada878a 100644
--- a/lib/tv/src/tv_ip.erl
+++ b/lib/tv/src/tv_ip.erl
@@ -16,6 +16,12 @@
%%
%% %CopyrightEnd%
-module(tv_ip).
+-compile([{nowarn_deprecated_function,{gs,canvas,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_main.erl b/lib/tv/src/tv_main.erl
index 36cf92bee3..fbf56971f9 100644
--- a/lib/tv/src/tv_main.erl
+++ b/lib/tv/src/tv_main.erl
@@ -16,6 +16,20 @@
%%
%% %CopyrightEnd%
-module(tv_main).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,frame,3}},
+ {nowarn_deprecated_function,{gs,grid,3}},
+ {nowarn_deprecated_function,{gs,gridline,2}},
+ {nowarn_deprecated_function,{gs,label,3}},
+ {nowarn_deprecated_function,{gs,menu,2}},
+ {nowarn_deprecated_function,{gs,menubar,3}},
+ {nowarn_deprecated_function,{gs,menubutton,2}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,menuitem,3}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_new_table.erl b/lib/tv/src/tv_new_table.erl
index 3d62b0548b..d31b9a4ee2 100644
--- a/lib/tv/src/tv_new_table.erl
+++ b/lib/tv/src/tv_new_table.erl
@@ -16,6 +16,16 @@
%%
%% %CopyrightEnd%k
-module(tv_new_table).
+-compile([{nowarn_deprecated_function,{gs,button,3}},
+ {nowarn_deprecated_function,{gs,checkbutton,3}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,entry,3}},
+ {nowarn_deprecated_function,{gs,frame,3}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,radiobutton,3}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_nodewin.erl b/lib/tv/src/tv_nodewin.erl
index 3999d201d8..9030ed930f 100644
--- a/lib/tv/src/tv_nodewin.erl
+++ b/lib/tv/src/tv_nodewin.erl
@@ -16,6 +16,15 @@
%%
%% %CopyrightEnd%
-module(tv_nodewin).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,listbox,3}},
+ {nowarn_deprecated_function,{gs,menu,3}},
+ {nowarn_deprecated_function,{gs,menubar,3}},
+ {nowarn_deprecated_function,{gs,menubutton,3}},
+ {nowarn_deprecated_function,{gs,menuitem,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_pb.erl b/lib/tv/src/tv_pb.erl
index 78a27185dc..fa3dcde919 100644
--- a/lib/tv/src/tv_pb.erl
+++ b/lib/tv/src/tv_pb.erl
@@ -16,6 +16,9 @@
%%
%% %CopyrightEnd%
-module(tv_pb).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,frame,2}}]).
diff --git a/lib/tv/src/tv_pb_funcs.erl b/lib/tv/src/tv_pb_funcs.erl
index 87a4719bbd..0670d2795f 100644
--- a/lib/tv/src/tv_pb_funcs.erl
+++ b/lib/tv/src/tv_pb_funcs.erl
@@ -16,6 +16,12 @@
%%
%% %CopyrightEnd%
-module(tv_pb_funcs).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,canvas,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}}]).
diff --git a/lib/tv/src/tv_pc.erl b/lib/tv/src/tv_pc.erl
index 50214fe06a..fcb7aba3a7 100644
--- a/lib/tv/src/tv_pc.erl
+++ b/lib/tv/src/tv_pc.erl
@@ -25,6 +25,7 @@
-module(tv_pc).
+-compile([{nowarn_deprecated_function,{gs,config,2}}]).
diff --git a/lib/tv/src/tv_pc_menu_handling.erl b/lib/tv/src/tv_pc_menu_handling.erl
index 16195bf91f..5d411b106e 100644
--- a/lib/tv/src/tv_pc_menu_handling.erl
+++ b/lib/tv/src/tv_pc_menu_handling.erl
@@ -25,6 +25,10 @@
-module(tv_pc_menu_handling).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_pd.erl b/lib/tv/src/tv_pd.erl
index ea14bf67b1..6694ea22a3 100644
--- a/lib/tv/src/tv_pd.erl
+++ b/lib/tv/src/tv_pd.erl
@@ -24,6 +24,11 @@
-module(tv_pd).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,destroy,1}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_pd_display.erl b/lib/tv/src/tv_pd_display.erl
index f5a30cb640..dab442e28e 100644
--- a/lib/tv/src/tv_pd_display.erl
+++ b/lib/tv/src/tv_pd_display.erl
@@ -22,6 +22,13 @@
%%%*********************************************************************
-module(tv_pd_display).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,editor,2}},
+ {nowarn_deprecated_function,{gs,entry,3}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,read,2}}]).
diff --git a/lib/tv/src/tv_pd_frames.erl b/lib/tv/src/tv_pd_frames.erl
index 4e091ac9f0..d18dcaf70d 100644
--- a/lib/tv/src/tv_pd_frames.erl
+++ b/lib/tv/src/tv_pd_frames.erl
@@ -16,6 +16,8 @@
%%
%% %CopyrightEnd%
-module(tv_pd_frames).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,frame,2}}]).
diff --git a/lib/tv/src/tv_pd_scale.erl b/lib/tv/src/tv_pd_scale.erl
index c94e57f468..2f98c3183f 100644
--- a/lib/tv/src/tv_pd_scale.erl
+++ b/lib/tv/src/tv_pd_scale.erl
@@ -24,6 +24,8 @@
-module(tv_pd_scale).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,scale,2}}]).
diff --git a/lib/tv/src/tv_pg.erl b/lib/tv/src/tv_pg.erl
index ba8782392b..0b36b18212 100644
--- a/lib/tv/src/tv_pg.erl
+++ b/lib/tv/src/tv_pg.erl
@@ -16,6 +16,7 @@
%%
%% %CopyrightEnd%
-module(tv_pg).
+-compile([{nowarn_deprecated_function,{gs,config,2}}]).
diff --git a/lib/tv/src/tv_pg_gridfcns.erl b/lib/tv/src/tv_pg_gridfcns.erl
index 3d23c8a69f..e47dac28a8 100644
--- a/lib/tv/src/tv_pg_gridfcns.erl
+++ b/lib/tv/src/tv_pg_gridfcns.erl
@@ -16,6 +16,10 @@
%%
%% %CopyrightEnd%
-module(tv_pg_gridfcns).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,read,2}}]).
diff --git a/lib/tv/src/tv_poll_dialog.erl b/lib/tv/src/tv_poll_dialog.erl
index 8d41251266..4bf49f44f1 100644
--- a/lib/tv/src/tv_poll_dialog.erl
+++ b/lib/tv/src/tv_poll_dialog.erl
@@ -22,7 +22,13 @@
%%%*********************************************************************
-module(tv_poll_dialog).
-
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,radiobutton,2}},
+ {nowarn_deprecated_function,{gs,scale,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,2}}]).
-export([start/1, init/2]).
diff --git a/lib/tv/src/tv_pw.erl b/lib/tv/src/tv_pw.erl
index 8b3186e090..bd6d06e241 100644
--- a/lib/tv/src/tv_pw.erl
+++ b/lib/tv/src/tv_pw.erl
@@ -23,6 +23,7 @@
-module(tv_pw).
+-compile([{nowarn_deprecated_function,{gs,config,2}}]).
diff --git a/lib/tv/src/tv_pw_window.erl b/lib/tv/src/tv_pw_window.erl
index 9cb5c879c0..0cd241a031 100644
--- a/lib/tv/src/tv_pw_window.erl
+++ b/lib/tv/src/tv_pw_window.erl
@@ -23,6 +23,10 @@
-module(tv_pw_window).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,menuitem,3}},
+ {nowarn_deprecated_function,{gs,start,0}}]).
diff --git a/lib/tv/src/tv_rec_edit.erl b/lib/tv/src/tv_rec_edit.erl
index e8f663073e..f6c09ebc67 100644
--- a/lib/tv/src/tv_rec_edit.erl
+++ b/lib/tv/src/tv_rec_edit.erl
@@ -16,6 +16,16 @@
%%
%% %CopyrightEnd%
-module(tv_rec_edit).
+-compile([{nowarn_deprecated_function,{gs,button,2}},
+ {nowarn_deprecated_function,{gs,button,3}},
+ {nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,entry,3}},
+ {nowarn_deprecated_function,{gs,frame,2}},
+ {nowarn_deprecated_function,{gs,frame,3}},
+ {nowarn_deprecated_function,{gs,label,2}},
+ {nowarn_deprecated_function,{gs,read,2}},
+ {nowarn_deprecated_function,{gs,start,0}},
+ {nowarn_deprecated_function,{gs,window,3}}]).
diff --git a/lib/tv/src/tv_utils.erl b/lib/tv/src/tv_utils.erl
index fd232bde69..9c7458d302 100644
--- a/lib/tv/src/tv_utils.erl
+++ b/lib/tv/src/tv_utils.erl
@@ -16,6 +16,9 @@
%%
%% %CopyrightEnd%
-module(tv_utils).
+-compile([{nowarn_deprecated_function,{gs,config,2}},
+ {nowarn_deprecated_function,{gs,create,3}},
+ {nowarn_deprecated_function,{gs,destroy,1}}]).
diff --git a/lib/wx/doc/src/Makefile b/lib/wx/doc/src/Makefile
index c8eb6174c4..03e9f1e1bb 100644
--- a/lib/wx/doc/src/Makefile
+++ b/lib/wx/doc/src/Makefile
@@ -22,7 +22,7 @@
# ----------------------------------------------------
include ../../vsn.mk
include ../../config.mk
-APPLICATION=wxErlang
+APPLICATION=wx
ErlMods = wx.erl wx_object.erl
diff --git a/lib/xmerl/doc/src/xmerl_ug.xmlsrc b/lib/xmerl/doc/src/xmerl_ug.xmlsrc
index 6ee6707e53..9ef8fbb0b9 100644
--- a/lib/xmerl/doc/src/xmerl_ug.xmlsrc
+++ b/lib/xmerl/doc/src/xmerl_ug.xmlsrc
@@ -36,9 +36,9 @@
<title>Features</title>
<p>The <em>xmerl</em> XML parser is able to parse XML documents
according to the XML 1.0 standard. As default it performs
- well-formed parsing,(syntax checks and checks of well-formed
+ well-formed parsing, (syntax checks and checks of well-formed
constraints). Optionally one can also use xmerl as a validating
- parser,(validate according to referenced DTD and validating
+ parser, (validate according to referenced DTD and validating
constraints). By means of for example the xmerl_xs module it is
possible to transform the parsed result to other formats,
e.g. text, HTML, XML etc.</p>
diff --git a/lib/xmerl/src/xmerl_uri.erl b/lib/xmerl/src/xmerl_uri.erl
index a0c6f1c2a7..1864651491 100644
--- a/lib/xmerl/src/xmerl_uri.erl
+++ b/lib/xmerl/src/xmerl_uri.erl
@@ -358,7 +358,7 @@ scan_host(C0) ->
%% Hex3=<?HEX;
%% Hex4=<?HEX ->
%% {C1,lists:reverse(lists:append(IPv6address))};
- {C1,Hostname,[A|_HostF]} ->
+ {C1,Hostname,[_A|_HostF]} ->
{C1,lists:reverse(lists:append(Hostname))}
%% _ ->
%% {error,no_host}