Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:24
erlang
5571-ftp-generate-documentation-from-source-cod...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 5571-ftp-generate-documentation-from-source-code.patch of Package erlang
From ce8323bb96c3a3d267cd9acbb6dd6e8dfa99c3b0 Mon Sep 17 00:00:00 2001 From: Kiko Fernandez-Reyes <kiko@erlang.org> Date: Fri, 17 Feb 2023 15:09:41 +0100 Subject: [PATCH 1/2] ftp: generate documentation from source code Generates the types in the documentation of `ftp` from the source code. Before this change, the documentation was hard-coded in `ftp.xml`. --- lib/ftp/doc/specs/.gitignore | 1 + lib/ftp/doc/src/Makefile | 4 + lib/ftp/doc/src/ftp.xml | 736 +++++++++++++---------------------- lib/ftp/doc/src/specs.xml | 4 + lib/ftp/test/ftp_SUITE.erl | 2 +- 5 files changed, 290 insertions(+), 457 deletions(-) create mode 100644 lib/ftp/doc/specs/.gitignore create mode 100644 lib/ftp/doc/src/specs.xml diff --git a/lib/ftp/doc/specs/.gitignore b/lib/ftp/doc/specs/.gitignore new file mode 100644 index 0000000000..322eebcb06 --- /dev/null +++ b/lib/ftp/doc/specs/.gitignore @@ -0,0 +1 @@ +specs_*.xml diff --git a/lib/ftp/doc/src/Makefile b/lib/ftp/doc/src/Makefile index 38ad4f76d0..6223dcc72b 100644 --- a/lib/ftp/doc/src/Makefile +++ b/lib/ftp/doc/src/Makefile @@ -54,6 +54,10 @@ XML_FILES = \ $(XML_REF3_FILES) \ $(XML_APPLICATION_FILES) +SPEC_FILES = $(XML_REF3_FILES:%.xml=$(SPECDIR)/specs_%.xml) +TOP_SPECS_FILE = specs.xml + + # IMAGE_FILES = ftp.gif include $(ERL_TOP)/make/doc.mk diff --git a/lib/ftp/doc/src/ftp.xml b/lib/ftp/doc/src/ftp.xml index a70369a777..7ea8023b24 100644 --- a/lib/ftp/doc/src/ftp.xml +++ b/lib/ftp/doc/src/ftp.xml @@ -81,203 +81,23 @@ <p>The FTP client can be started and stopped dynamically in runtime by calling the <c>ftp</c> application API <c>ftp:open(Host, Options)</c> and - <c>ftp:close(Client)</c>.</p> - - <p>The available configuration options are as follows:</p> - - <taglist> - <tag>{host, Host}</tag> - <item> - <marker id="host"></marker> - <p>Host = <c>string() | ip_address()</c></p> - </item> - - <tag>{port, Port}</tag> - <item> - <marker id="port"></marker> - <p>Port = <c>integer() > 0</c></p> - <p>Default is <c>0</c> which aliases to <c>21</c> or <c>990</c> when used with - <seeerl marker="#open"><c>{tls_sec_method,ftps}</c></seeerl>).</p> - </item> - - <tag>{mode, Mode}</tag> - <item> - <marker id="mode"></marker> - <p>Mode = <c>active | passive</c></p> - <p>Default is <c>passive</c>.</p> - </item> - - <tag>{verbose, Verbose}</tag> - <item> - <marker id="verbose"></marker> - <p>Verbose = <c>boolean()</c> </p> - <p>Determines if the FTP communication is to be - verbose or not.</p> - <p>Default is <c>false</c>.</p> - </item> - - <tag>{debug, Debug}</tag> - <item> - <marker id="debug"></marker> - <p>Debug = <c>trace | debug | disable</c> </p> - <p>Debugging using the dbg toolkit. </p> - <p>Default is <c>disable</c>.</p> - </item> - - <tag>{ipfamily, IpFamily}</tag> - <item> - <marker id="ipfamily"></marker> - <p>IpFamily = <c>inet | inet6 | inet6fb4</c> </p> - <p>With <c>inet6fb4</c> the client behaves as before, that is, - tries to use IPv6, and only if that does not work it - uses IPv4).</p> - <p>Default is <c>inet</c> (IPv4).</p> - </item> - - <tag>{timeout, Timeout}</tag> - <item> - <marker id="timeout"></marker> - <p>Timeout = <c>non_neg_integer()</c></p> - <p>Connection time-out.</p> - <p>Default is <c>60000</c> (milliseconds).</p> - </item> - - <tag>{dtimeout, DTimeout}</tag> - <item> - <marker id="dtimeout"></marker> - <p>DTimeout = <c>non_neg_integer() | infinity</c> </p> - <p>Data connect time-out. - The time the client waits for the server to connect to the - data socket.</p> - <p>Default is <c>infinity</c>. </p> - </item> - - <tag>{progress, Progress}</tag> - <item> - <marker id="progress"></marker> - <p>Progress = <c>ignore | {CBModule, CBFunction, InitProgress}</c></p> - <p><c>CBModule = atom()</c>, <c>CBFunction = atom()</c></p> - <p><c>InitProgress = term()</c></p> - <p>Default is <c>ignore</c>.</p> - </item> - - </taglist> - - <p>Option <c>progress</c> is intended to be used by applications that - want to create some type of progress report, such as a progress bar in - a GUI. Default for the progress option is <c>ignore</c>, - that is, the option is not used. When the progress option is - specified, the following happens when <c>ftp:send/[3,4]</c> or - <c>ftp:recv/[3,4]</c> are called:</p> - - <list type="bulleted"> - <item> - <p>Before a file is transferred, the following call is - made to indicate the start of the file transfer and how large - the file is. The return value of the callback function - is to be a new value for the <c>UserProgressTerm</c> that will - be used as input the next time the callback function is - called.</p> - <p><c> - CBModule:CBFunction(InitProgress, File, {file_size, FileSize}) - </c></p> - </item> - - <item> - <p>Every time a chunk of bytes is transferred the - following call is made:</p> - <p><c> - CBModule:CBFunction(UserProgressTerm, File, {transfer_size, TransferSize}) - </c></p> - </item> - - <item> - <p>At the end of the file the following call is - made to indicate the end of the transfer:</p> - <p><c> - CBModule:CBFunction(UserProgressTerm, File, {transfer_size, 0}) - </c></p> - </item> - </list> - - <p>The callback function is to be defined as follows:</p> - - <p><c> - CBModule:CBFunction(UserProgressTerm, File, Size) -> UserProgressTerm - </c></p> - - <p><c> - CBModule = CBFunction = atom() - </c></p> - - <p><c> - UserProgressTerm = term() - </c></p> - - <p><c> - File = string() - </c></p> - - <p><c> - Size = {transfer_size, integer()} | {file_size, integer()} | {file_size, unknown} - </c></p> - - <p>For remote files, <c>ftp</c> cannot determine the - file size in a platform independent way. In this case the size - becomes <c>unknown</c> and it is left to the application to - determine the size.</p> - - <note> - <p>The callback is made by a middleman process, hence the - file transfer is not affected by the code in the progress - callback function. If the callback crashes, this is - detected by the FTP connection process, which then prints an - info-report and goes on as if the progress option was set - to <c>ignore</c>.</p> - </note> - - <p>The file transfer type is set to the default of the FTP server - when the session is opened. This is usually ASCII mode. - </p> - - <p>The current local working directory (compare <c>lpwd/1</c>) is set - to the value reported by <c>file:get_cwd/1</c>, the wanted - local directory. - </p> - - <p>The return value <c>Pid</c> is used as a reference to the - newly created FTP client in all other functions, and they are to - be called by the process that created the connection. The FTP - client process monitors the process that created it and - terminates if that process terminates.</p> + <c>ftp:close(Client)</c>. </p> </section> <section> - <title>DATA TYPES</title> + <title>Data Types</title> <p>The following type definitions are used by more than one function in the FTP client API:</p> <p><c>pid()</c> = identifier of an FTP connection</p> <p><c>string()</c> = list of ASCII characters</p> - <p><c>shortage_reason()</c> = <c>etnospc | epnospc</c></p> - <p><c>restriction_reason()</c> = <c>epath | efnamena | elogin | enotbinary</c> - - all restrictions are not always relevant to all functions - </p> - <p><c>common_reason()</c> = <c>econn | eclosed | term()</c> - - some explanation of what went wrong</p> - <marker id="account"></marker> </section> <funcs> <func> - <name since="">account(Pid, Account) -> ok | {error, Reason}</name> + <name since="" name="account" arity="2" /> <fsummary>Specifies which account to use.</fsummary> - <type> - <v>Pid = pid()</v> - <v>Account = string()</v> - <v>Reason = eacct | common_reason()</v> - </type> <desc> <p>Sets the account for an operation, if needed.</p> @@ -288,15 +108,10 @@ </func> <func> - <name since="">append(Pid, LocalFile) -> </name> - <name since="">append(Pid, LocalFile, RemoteFile) -> ok | {error, Reason}</name> - <fsummary>Transfers a file to remote server, and appends it to + <name since="" name="append" arity="2"/> + <name since="" name="append" arity="3"/> + <fsummary>Transfers a file to remote server, and appends it to <c>Remotefile</c>.</fsummary> - <type> - <v>Pid = pid()</v> - <v>LocalFile = RemoteFile = string()</v> - <v>Reason = epath | elogin | etnospc | epnospc | efnamena | common_reason</v> - </type> <desc> <p>Transfers the file <c>LocalFile</c> to the remote server. If <c>RemoteFile</c> is specified, the name of the remote file that the @@ -309,17 +124,11 @@ </func> <func> - <name since="">append_bin(Pid, Bin, RemoteFile) -> ok | {error, Reason}</name> + <name since="" name="append_bin" arity="3"/> <fsummary>Transfers a binary into a remote file.</fsummary> - <type> - <v>Pid = pid()</v> - <v>Bin = binary()</v> - <v>RemoteFile = string()</v> - <v>Reason = restriction_reason()| shortage_reason() | common_reason()</v> - </type> <desc> <p>Transfers the binary <c>Bin</c> to the remote server and appends - it to the file <c>RemoteFile</c>. If the file does not exist, it + it to the file <c><anno>RemoteFile</anno></c>. If the file does not exist, it is created.</p> <marker id="append_chunk"></marker> @@ -327,15 +136,10 @@ </func> <func> - <name since="">append_chunk(Pid, Bin) -> ok | {error, Reason}</name> + <name since="" name="append_chunk" arity="2" /> <fsummary>Appends a chunk to the remote file.</fsummary> - <type> - <v>Pid = pid()</v> - <v>Bin = binary()</v> - <v>Reason = echunk | restriction_reason() | common_reason()</v> - </type> <desc> - <p>Transfers the chunk <c>Bin</c> to the remote server, which + <p>Transfers the chunk <c><anno>Bin</anno></c> to the remote server, which appends it to the file specified in the call to <c>append_chunk_start/2</c>.</p> <p>For some errors, for example, file system full, it is @@ -347,16 +151,11 @@ </func> <func> - <name since="">append_chunk_start(Pid, File) -> ok | {error, Reason}</name> + <name since="" name="append_chunk_start" arity="2" /> <fsummary>Starts transfer of file chunks for appending to <c>File</c>.</fsummary> - <type> - <v>Pid = pid()</v> - <v>File = string()</v> - <v>Reason = restriction_reason() | common_reason()</v> - </type> <desc> <p>Starts the transfer of chunks for appending to the file - <c>File</c> at the remote server. If the file does not exist, + <c><anno>RemoteFile</anno></c> at the remote server. If the file does not exist, it is created.</p> <marker id="append_chunk_end"></marker> @@ -364,12 +163,8 @@ </func> <func> - <name since="">append_chunk_end(Pid) -> ok | {error, Reason}</name> + <name since="" name="append_chunk_end" arity="1"/> <fsummary>Stops transfer of chunks for appending.</fsummary> - <type> - <v>Pid = pid()</v> - <v>Reason = echunk | restriction_reason() | shortage_reason() </v> - </type> <desc> <p>Stops transfer of chunks for appending to the remote server. The file at the remote server, specified in the call to @@ -380,27 +175,19 @@ </func> <func> - <name since="">cd(Pid, Dir) -> ok | {error, Reason}</name> + <name since="" name="cd" arity="2" /> <fsummary>Changes remote working directory.</fsummary> - <type> - <v>Pid = pid()</v> - <v>Dir = string()</v> - <v>Reason = restriction_reason() | common_reason() </v> - </type> <desc> <p>Changes the working directory at the remote server to - <c>Dir</c>.</p> + <c><anno>Dir</anno></c>.</p> <marker id="close"></marker> </desc> </func> <func> - <name since="">close(Pid) -> ok</name> + <name since="" name="close" arity="1" /> <fsummary>Ends the FTP session.</fsummary> - <type> - <v>Pid = pid()</v> - </type> <desc> <p>Ends an FTP session, created using function <seeerl marker="#open">open</seeerl>.</p> @@ -410,13 +197,8 @@ </func> <func> - <name since="">delete(Pid, File) -> ok | {error, Reason}</name> + <name since="" name="delete" arity="2"/> <fsummary>Deletes a file at the remote server.</fsummary> - <type> - <v>Pid = pid()</v> - <v>File = string()</v> - <v>Reason = restriction_reason() | common_reason()</v> - </type> <desc> <p>Deletes the file <c>File</c> at the remote server.</p> @@ -425,11 +207,8 @@ </func> <func> - <name since="">formaterror(Tag) -> string()</name> + <name since="" name="formaterror" arity="1"/> <fsummary>Returns error diagnostics.</fsummary> - <type> - <v>Tag = {error, atom()} | atom()</v> - </type> <desc> <p>Given an error return value <c>{error, AtomReason}</c>, this function returns a readable string describing the error.</p> @@ -439,26 +218,18 @@ </func> <func> - <name since="">lcd(Pid, Dir) -> ok | {error, Reason}</name> + <name since="" name="lcd" arity="2" /> <fsummary>Changes local working directory.</fsummary> - <type> - <v>Pid = pid()</v> - <v>Dir = string()</v> - <v>Reason = restriction_reason()</v> - </type> <desc> - <p>Changes the working directory to <c>Dir</c> for the local client.</p> + <p>Changes the working directory to <c><anno>Dir</anno></c> for the local client.</p> <marker id="lpwd"></marker> </desc> </func> <func> - <name since="">lpwd(Pid) -> {ok, Dir}</name> + <name since="" name="lpwd" arity="1" /> <fsummary>Gets local current working directory.</fsummary> - <type> - <v>Pid = pid()</v> - </type> <desc> <p>Returns the current working directory at the local client.</p> @@ -469,21 +240,15 @@ </func> <func> - <name since="">ls(Pid) -> </name> - <name since="">ls(Pid, Pathname) -> {ok, Listing} | {error, Reason}</name> + <name since="" name="ls" arity="1" /> + <name since="" name="ls" arity="2" /> <fsummary>List of files.</fsummary> - <type> - <v>Pid = pid()</v> - <v>Pathname = string()</v> - <v>Listing = string()</v> - <v>Reason = restriction_reason() | common_reason()</v> - </type> <desc> <p>Returns a list of files in long format.</p> - <p><c>Pathname</c> can be a directory, a group of files, or - a file. The <c>Pathname</c> string can contain wildcards.</p> + <p><c><anno>Dir</anno></c> can be a directory or + a file. The <c><anno>Dir</anno></c> string can contain wildcards.</p> <p><c>ls/1</c> implies the current remote directory of the user.</p> - <p>The format of <c>Listing</c> depends on the operating system. + <p>The format of <c><anno>Listing</anno></c> depends on the operating system. On UNIX, it is typically produced from the output of the <c>ls -l</c> shell command.</p> @@ -492,15 +257,10 @@ </func> <func> - <name since="">mkdir(Pid, Dir) -> ok | {error, Reason}</name> + <name since="" name="mkdir" arity="2" /> <fsummary>Creates a remote directory.</fsummary> - <type> - <v>Pid = pid()</v> - <v>Dir = string()</v> - <v>Reason = restriction_reason() | common_reason()</v> - </type> <desc> - <p>Creates the directory <c>Dir</c> at the remote server.</p> + <p>Creates the directory <c><anno>Dir</anno></c> at the remote server.</p> <marker id="nlist"></marker> <marker id="nlist1"></marker> @@ -509,21 +269,15 @@ </func> <func> - <name since="">nlist(Pid) -> </name> - <name since="">nlist(Pid, Pathname) -> {ok, Listing} | {error, Reason}</name> + <name since="" name="nlist" arity="1" /> + <name since="" name="nlist" arity="2" /> <fsummary>List of files.</fsummary> - <type> - <v>Pid = pid()</v> - <v>Pathname = string()</v> - <v>Listing = string()</v> - <v>Reason = restriction_reason() | common_reason()</v> - </type> <desc> <p>Returns a list of files in short format.</p> - <p><c>Pathname</c> can be a directory, a group of files, or - a file. The <c>Pathname</c> string can contain wildcards.</p> + <p><c><anno>Pathname</anno></c> can be a directory or + a file. The <c><anno>Pathname</anno></c> string can contain wildcards.</p> <p><c>nlist/1</c> implies the current remote directory of the user.</p> - <p>The format of <c>Listing</c> is a stream of + <p>The format of <c><anno>Listing</anno></c> is a stream of filenames where each filename is separated by <CRLF> or <NL>. Contrary to function <c>ls</c>, the purpose of <c>nlist</c> is to enable a program to @@ -534,76 +288,229 @@ </func> <func> - <name since="">open(Host) -> {ok, Pid} | {error, Reason}</name> - <name since="">open(Host, Opts) -> {ok, Pid} | {error, Reason}</name> + <name since="" name="open" arity="1" /> + <name since="" name="open" arity="2" /> <fsummary>Starts a FTP client.</fsummary> - <type> - <v>Host = string() | ip_address()</v> - <v>Opts = options()</v> - <v>options() = [option()]</v> - <v>option() = start_option() | open_option()</v> - <v>start_option() = {verbose, verbose()} | {debug, debug()}</v> - <v>verbose() = boolean() (default is false)</v> - <v>debug() = disable | debug | trace (default is disable)</v> - <v>open_option() = {ipfamily, ipfamily()} | {port, port()} | {mode, mode()} | {tls, tls_options()} | {tls_sec_method, tls_sec_method()} | {tls_ctrl_session_reuse, boolean() (default is false)} | {timeout, timeout()} | {dtimeout, dtimeout()} | {progress, progress()} | {sock_ctrl, sock_opts()} | {sock_data_act, sock_opts()} | {sock_data_pass, sock_opts()}</v> - <v>ipfamily() = inet | inet6 | inet6fb4 (default is inet)</v> - <v>port() = non_neg_integer() (default is 0 which aliases to 21 or 990 when used with {tls_sec_method,ftps})</v> - <v>mode() = active | passive (default is passive)</v> - <v>tls_options() = [<seetype marker="ssl:ssl#tls_option">ssl:tls_option()</seetype>]</v> - <v>tls_sec_method() = ftps | ftpes (default is ftpes)</v> - <v>sock_opts() = [<seetype marker="kernel:gen_tcp#option">gen_tcp:option()</seetype> except for ipv6_v6only, active, packet, mode, packet_size and header</v> - <v>timeout() = integer() > 0 (default is 60000 milliseconds)</v> - <v>dtimeout() = integer() > 0 | infinity (default is infinity)</v> - <v>progress() = ignore | {module(), function(), initial_data()} (default is ignore)</v> - <v>module() = atom()</v> - <v>function() = atom()</v> - <v>initial_data() = term()</v> - <v>Reason = ehost | term()</v> - </type> - <desc> <p>Starts a FTP client process and opens a session with the FTP server at <c>Host</c>. </p> + <p>A session opened in this way is closed using function + <seeerl marker="#close">close</seeerl>.</p> + + <p>The available configuration options are as follows:</p> - <p>If option <c>{tls, tls_options()}</c> is present, the FTP session - is transported over <c>tls</c> (<c>ftps</c>, see - <url href="http://www.ietf.org/rfc/rfc4217.txt">RFC 4217</url>). - The list <c>tls_options()</c> can be empty. The function - <seemfa marker="ssl:ssl#connect/3"><c>ssl:connect/3</c></seemfa> + <taglist> + <tag>{host, Host}</tag> + <item> + <marker id="host"></marker> + <p>Host = <c>string() | ip_address()</c></p> + </item> + + <tag>{port, Port}</tag> + <item> + <marker id="port"></marker> + <p>Default is <c>0</c> which aliases to <c>21</c> or <c>990</c> when used with + <seeerl marker="#open"><c>{tls_sec_method,ftps}</c></seeerl>).</p> + </item> + + <tag>{mode, Mode}</tag> + <item> + <marker id="mode"></marker> + <p>Default is <c>passive</c>.</p> + </item> + + <tag>{verbose, Verbose}</tag> + <item> + <marker id="verbose"></marker> + <p>Determines if the FTP communication is to be + verbose or not.</p> + <p>Default is <c>false</c>.</p> + </item> + + <tag>{debug, Debug}</tag> + <item> + <marker id="debug"></marker> + <p>Debugging using the dbg toolkit. </p> + <p>Default is <c>disable</c>.</p> + </item> + + <tag>{ipfamily, IpFamily}</tag> + <item> + <marker id="ipfamily"></marker> + <p>With <c>inet6fb4</c> the client behaves as before, that is, + tries to use IPv6, and only if that does not work it + uses IPv4).</p> + <p>Default is <c>inet</c> (IPv4).</p> + </item> + + <tag>{timeout, Timeout}</tag> + <item> + <marker id="timeout"></marker> + <p>Connection time-out.</p> + <p>Default is <c>60000</c> (milliseconds).</p> + </item> + + <tag>{dtimeout, DTimeout}</tag> + <item> + <marker id="dtimeout"></marker> + <p>Data connect time-out. + The time the client waits for the server to connect to the + data socket.</p> + <p>Default is <c>infinity</c>. </p> + </item> + + <tag>{tls, TLSOptions}</tag> + <item><marker id="tls_options"></marker> + <p>The FTP session is transported over <c>tls</c> (<c>ftps</c>, see + <url href="http://www.ietf.org/rfc/rfc4217.txt">RFC 4217</url>). + The list <c><anno>TLSOptions</anno></c> can be empty. The function + <seemfa marker="ssl:ssl#connect/3"><c>ssl:connect/3</c></seemfa> is used for securing both the control connection and the data sessions. </p> + </item> - <p>The suboption <c>{tls_sec_method, tls_sec_method()}</c> (defaults to - <c>ftpes</c>) when set to <c>ftps</c> will connect immediately with SSL + <tag>{tls_sec_method, TLSSecMethod}</tag> + <item><marker id="tls_sec_method"></marker> + <p>When set to <c>ftps</c> will connect immediately with SSL instead of upgrading with STARTTLS. This suboption is ignored unless - the suboption <c>tls</c> is also set. - </p> + the suboption <c>tls</c> is also set.</p> + <p>Default is <c>ftpes</c></p> + </item> - <p>The option <c>{tls_ctrl_session_reuse, boolean()}</c> (defaults to - <c>false</c>) when set to <c>true</c> the client will re-use the + <tag>{tls_ctrl_session_reuse, boolean()}</tag> + <item><marker id="tls_ctrl_session_reuse"></marker> + <p>When set to <c>true</c> the client will re-use the TLS session from the control channel on the data channel as enforced by many FTP servers as (<url href="https://scarybeastsecurity.blogspot.com/2009/02/vsftpd-210-released.html">proposed and implemented first by vsftpd</url>). </p> + <p>Default is <c>false</c>.</p> + </item> + + <tag>{sock_ctrl, SocketCtrls :: [SocketControl :: gen_tcp:option()]}</tag> + <item> + <p>Passes options from <c>SocketCtrls</c> down to the underlying transport layer (tcp).</p> + <p><seetype marker="kernel:gen_tcp#option">gen_tcp:option()</seetype> except for <c>ipv6_v6only</c>, + <c>active</c>, <c>packet</c>, <c>mode</c>, <c>packet_size</c> and <c>header</c>.</p> + <p>Default value is <c>SocketCtrls = []</c>.</p> + </item> + + <tag>{sock_data_act, [SocketControl]}</tag> + <item> + <p>Passes options from <c>[SocketControl]</c> down to the underlying transport layer (tcp).</p> + <p><c>sock_data_act</c> uses the value of <c>sock_ctrl</c> as default value.</p> + </item> + + <tag>{sock_data_pass, [SocketControl]}</tag> + <item> + <p>Passes options from <c>[SocketControl]</c> down to the underlying transport layer (tcp). + </p> + <p><c>sock_data_pass</c> uses the value of <c>sock_ctrl</c> as default value.</p> + </item> - <p>The options <c>sock_ctrl</c>, <c>sock_data_act</c> and <c>sock_data_pass</c> passes options down to - the underlying transport layer (tcp). The default value for <c>sock_ctrl</c> is <c>[]</c>. Both - <c>sock_data_act</c> and <c>sock_data_pass</c> uses the value of <c>sock_ctrl</c> as default value. - </p> + <tag>{progress, Progress}</tag> + <item> + <marker id="progress"></marker> + <p>Progress = <c>ignore | {Module, Function, InitialData}</c></p> + <p><c>Module = atom()</c>, <c>Function = atom()</c></p> + <p><c>InitialData = term()</c></p> + <p>Default is <c>ignore</c>.</p> + + <p>Option <c>progress</c> is intended to be used by applications that + want to create some type of progress report, such as a progress bar in + a GUI. Default for the progress option is <c>ignore</c>, + that is, the option is not used. When the progress option is + specified, the following happens when <c>ftp:send/[3,4]</c> or + <c>ftp:recv/[3,4]</c> are called:</p> + + <list type="bulleted"> + <item> + <p>Before a file is transferred, the following call is + made to indicate the start of the file transfer and how large + the file is. The return value of the callback function + is to be a new value for the <c>UserProgressTerm</c> that will + be used as input the next time the callback function is + called.</p> + <p><c> + Module:Function(InitialData, File, {file_size, FileSize}) + </c></p> + </item> + + <item> + <p>Every time a chunk of bytes is transferred the + following call is made:</p> + <p><c> + Module:Function(UserProgressTerm, File, {transfer_size, TransferSize}) + </c></p> + </item> + + <item> + <p>At the end of the file the following call is + made to indicate the end of the transfer:</p> + <p><c> + Module:Function(UserProgressTerm, File, {transfer_size, 0}) + </c></p> + </item> + </list> + + <p>The callback function is to be defined as follows:</p> + + <p><c> + Module:Function(UserProgressTerm, File, Size) -> UserProgressTerm + </c></p> + + <p><c> + UserProgressTerm = term() + </c></p> + + <p><c> + File = string() + </c></p> + + <p><c> + Size = {transfer_size, integer()} | {file_size, integer()} | {file_size, unknown} + </c></p> + + <p>For remote files, <c>ftp</c> cannot determine the + file size in a platform independent way. In this case the size + becomes <c>unknown</c> and it is left to the application to + determine the size.</p> + + <note> + <p>The callback is made by a middleman process, hence the + file transfer is not affected by the code in the progress + callback function. If the callback crashes, this is + detected by the FTP connection process, which then prints an + info-report and goes on as if the progress option was set + to <c>ignore</c>.</p> + </note> + + <p>The file transfer type is set to the default of the FTP server + when the session is opened. This is usually ASCII mode. + </p> + + <p>The current local working directory (compare <c>lpwd/1</c>) is set + to the value reported by <c>file:get_cwd/1</c>, the wanted + local directory. + </p> + + <p>The return value <c>Pid</c> is used as a reference to the + newly created FTP client in all other functions, and they are to + be called by the process that created the connection. The FTP + client process monitors the process that created it and + terminates if that process terminates.</p> + + </item> + + </taglist> - <p>A session opened in this way is closed using function - <seeerl marker="#close">close</seeerl>.</p> <marker id="pwd"></marker> </desc> </func> <func> - <name since="">pwd(Pid) -> {ok, Dir} | {error, Reason}</name> + <name since="" name="pwd" arity="1"/> <fsummary>Gets the remote current working directory.</fsummary> - <type> - <v>Pid = pid()</v> - <v>Reason = restriction_reason() | common_reason()</v> - </type> <desc> <p>Returns the current working directory at the remote server.</p> @@ -614,23 +521,17 @@ </func> <func> - <name since="">recv(Pid, RemoteFile) -> </name> - <name since="">recv(Pid, RemoteFile, LocalFile) -> ok | {error, Reason}</name> + <name since="" name="recv" arity="2"/> + <name since="" name="recv" arity="3"/> <fsummary>Transfers a file from remote server.</fsummary> - <type> - <v>Pid = pid()</v> - <v>RemoteFile = LocalFile = string()</v> - <v>Reason = restriction_reason() | common_reason() | file_write_error_reason() </v> - <v>file_write_error_reason() = see file:write/2</v> - </type> - <desc> - <p>Transfers the file <c>RemoteFile</c> from the remote server + <desc> + <p>Transfers the file <c><anno>RemoteFileName</anno></c> from the remote server to the file system of the local client. If - <c>LocalFile</c> is specified, the local file will be - <c>LocalFile</c>, otherwise - <c>RemoteFile</c>.</p> - <p>If the file write fails (for example, <c>enospc</c>), the command is - aborted and <c>{error, file_write_error_reason()}</c> is returned. + <c><anno>LocalFileName</anno></c> is specified, the local file will be + <c><anno>LocalFileName</anno></c>, otherwise + <c><anno>RemoteFileName</anno></c>.</p> + <p>If the file write fails, the command is + aborted and <c>{error, term()}</c> is returned. However, the file is <em>not</em> removed.</p> <marker id="recv_bin"></marker> @@ -638,16 +539,10 @@ </func> <func> - <name since="">recv_bin(Pid, RemoteFile) -> {ok, Bin} | {error, Reason}</name> + <name since="" name="recv_bin" arity="2"/> <fsummary>Transfers a file from remote server as a binary.</fsummary> - <type> - <v>Pid = pid()</v> - <v>Bin = binary()</v> - <v>RemoteFile = string()</v> - <v>Reason = restriction_reason() | common_reason()</v> - </type> - <desc> - <p>Transfers the file <c>RemoteFile</c> from the remote server and + <desc> + <p>Transfers the file <c><anno>RemoteFile</anno></c> from the remote server and receives it as a binary.</p> <marker id="recv_chunk_start"></marker> @@ -655,15 +550,10 @@ </func> <func> - <name since="">recv_chunk_start(Pid, RemoteFile) -> ok | {error, Reason}</name> + <name since="" name="recv_chunk_start" arity="2"/> <fsummary>Starts chunk-reading of the remote file.</fsummary> - <type> - <v>Pid = pid()</v> - <v>RemoteFile = string()</v> - <v>Reason = restriction_reason() | common_reason()</v> - </type> <desc> - <p>Starts transfer of the file <c>RemoteFile</c> from the + <p>Starts transfer of the file <c><anno>RemoteFile</anno></c> from the remote server.</p> <marker id="recv_chunk"></marker> @@ -671,15 +561,10 @@ </func> <func> - <name since="">recv_chunk(Pid) -> ok | {ok, Bin} | {error, Reason}</name> + <name since="" name="recv_chunk" arity="1" /> <fsummary>Receives a chunk of the remote file.</fsummary> - <type> - <v>Pid = pid()</v> - <v>Bin = binary()</v> - <v>Reason = restriction_reason() | common_reason()</v> - </type> <desc> - <p>Receives a chunk of the remote file (<c>RemoteFile</c> of + <p>Receives a chunk of the remote file (<c>RemoteFile</c> of <c>recv_chunk_start</c>). The return values have the following meaning:</p> <list type="bulleted"> @@ -693,30 +578,20 @@ </func> <func> - <name since="">rename(Pid, Old, New) -> ok | {error, Reason}</name> + <name since="" name="rename" arity="3"/> <fsummary>Renames a file at the remote server.</fsummary> - <type> - <v>Pid = pid()</v> - <v>CurrFile = NewFile = string()</v> - <v>Reason = restriction_reason() | common_reason()</v> - </type> <desc> - <p>Renames <c>Old</c> to <c>New</c> at the remote server.</p> + <p>Renames <c><anno>Old</anno></c> to <c><anno>New</anno></c> at the remote server.</p> <marker id="rmdir"></marker> </desc> </func> <func> - <name since="">rmdir(Pid, Dir) -> ok | {error, Reason}</name> + <name since="" name="rmdir" arity="2" /> <fsummary>Removes a remote directory.</fsummary> - <type> - <v>Pid = pid()</v> - <v>Dir = string()</v> - <v>Reason = restriction_reason() | common_reason()</v> - </type> <desc> - <p>Removes directory <c>Dir</c> at the remote server.</p> + <p>Removes directory <c><anno>Dir</anno></c> at the remote server.</p> <marker id="send"></marker> <marker id="send2"></marker> @@ -725,34 +600,23 @@ </func> <func> - <name since="">send(Pid, LocalFile) -></name> - <name since="">send(Pid, LocalFile, RemoteFile) -> ok | {error, Reason}</name> + <name since="" name="send" arity="2"/> + <name since="" name="send" arity="3"/> <fsummary>Transfers a file to the remote server.</fsummary> - <type> - <v>Pid = pid()</v> - <v>LocalFile = RemoteFile = string()</v> - <v>Reason = restriction_reason() | common_reason() | shortage_reason()</v> - </type> <desc> - <p>Transfers the file <c>LocalFile</c> to the remote server. If - <c>RemoteFile</c> is specified, the name of the remote file is set - to <c>RemoteFile</c>, otherwise to <c>LocalFile</c>.</p> + <p>Transfers the file <c><anno>LocalFileName</anno></c> to the remote server. If + <c><anno>RemoteFileName</anno></c> is specified, the name of the remote file is set + to <c><anno>RemoteFileName</anno></c>, otherwise to <c><anno>LocalFileName</anno></c>.</p> <marker id="send_bin"></marker> </desc> </func> <func> - <name since="">send_bin(Pid, Bin, RemoteFile) -> ok | {error, Reason}</name> + <name since="" name="send_bin" arity="3" /> <fsummary>Transfers a binary into a remote file.</fsummary> - <type> - <v>Pid = pid()</v> - <v>Bin = binary()</v> - <v>RemoteFile = string()</v> - <v>Reason = restriction_reason() | common_reason() | shortage_reason()</v> - </type> - <desc> - <p>Transfers the binary <c>Bin</c> into the file <c>RemoteFile</c> + <desc> + <p>Transfers the binary <c><anno>Bin</anno></c> into the file <c><anno>RemoteFile</anno></c> at the remote server.</p> <marker id="send_chunk"></marker> @@ -760,15 +624,10 @@ </func> <func> - <name since="">send_chunk(Pid, Bin) -> ok | {error, Reason}</name> + <name since="" name="send_chunk" arity="2" /> <fsummary>Writes a chunk to the remote file.</fsummary> - <type> - <v>Pid = pid()</v> - <v>Bin = binary()</v> - <v>Reason = echunk | restriction_reason() | common_reason()</v> - </type> <desc> - <p>Transfers the chunk <c>Bin</c> to the remote server, which + <p>Transfers the chunk <c><anno>Bin</anno></c> to the remote server, which writes it into the file specified in the call to <c>send_chunk_start/2</c>.</p> <p>For some errors, for example, file system full, it is @@ -780,15 +639,10 @@ </func> <func> - <name since="">send_chunk_start(Pid, File) -> ok | {error, Reason}</name> + <name since="" name="send_chunk_start" arity="2" /> <fsummary>Starts transfer of file chunks.</fsummary> - <type> - <v>Pid = pid()</v> - <v>File = string()</v> - <v>Reason = restriction_reason() | common_reason()</v> - </type> <desc> - <p>Starts transfer of chunks into the file <c>File</c> at the + <p>Starts transfer of chunks into the file <c><anno>RemoteFile</anno></c> at the remote server.</p> <marker id="send_chunk_end"></marker> @@ -796,12 +650,8 @@ </func> <func> - <name since="">send_chunk_end(Pid) -> ok | {error, Reason}</name> + <name since="" name="send_chunk_end" arity="1" /> <fsummary>Stops transfer of chunks.</fsummary> - <type> - <v>Pid = pid()</v> - <v>Reason = restriction_reason() | common_reason() | shortage_reason()</v> - </type> <desc> <p>Stops transfer of chunks to the remote server. The file at the remote server, specified in the call to <c>send_chunk_start/2</c> @@ -812,14 +662,9 @@ </func> <func> - <name since="OTP 21.0">start_service(ServiceConfig) -> {ok, Pid} | {error, Reason}</name> + <name since="OTP 21.0" name="start_service" arity="1" /> <fsummary>Dynamically starts an <c>FTP</c> session after the <c>ftp</c> application has been started.</fsummary> - <type> - <v>ServiceConfig = [{Option, Value}]</v> - <v>Option = property()</v> - <v>Value = term()</v> - </type> <desc> <p>Dynamically starts an <c>FTP</c> session after the <c>ftp</c> application has been started.</p> @@ -831,25 +676,19 @@ </func> <func> - <name since="OTP 21.0">stop_service(Reference) -> ok | {error, Reason} </name> + <name since="OTP 21.0" name="stop_service" arity="1"/> <fsummary>Stops an FTP session.</fsummary> - <type> - <v>Reference = pid() | term() - service-specified reference</v> - <v>Reason = term()</v> - </type> + <type_desc variable="Pid"> + Service-specified reference + </type_desc> <desc> <p>Stops a started FTP session.</p> </desc> </func> <func> - <name since="">type(Pid, Type) -> ok | {error, Reason}</name> + <name since="" name="type" arity="2" /> <fsummary>Sets transfer type to <c>ascii</c>or <c>binary</c>.</fsummary> - <type> - <v>Pid = pid()</v> - <v>Type = ascii | binary</v> - <v>Reason = etype | restriction_reason() | common_reason()</v> - </type> <desc> <p>Sets the file transfer type to <c>ascii</c> or <c>binary</c>. When an FTP session is opened, the default transfer type of the @@ -860,45 +699,30 @@ </func> <func> - <name since="">user(Pid, User, Password) -> ok | {error, Reason}</name> + <name since="" name="user" arity="3"/> <fsummary>User login.</fsummary> - <type> - <v>Pid = pid()</v> - <v>User = Password = string()</v> - <v>Reason = euser | common_reason()</v> - </type> <desc> - <p>Performs login of <c>User</c> with <c>Password</c>.</p> + <p>Performs login of <c><anno>User</anno></c> with <c><anno>Pass</anno></c>.</p> <marker id="user4"></marker> </desc> </func> <func> - <name since="">user(Pid, User, Password, Account) -> ok | {error, Reason}</name> + <name since="" name="user" arity="4" /> <fsummary>User login.</fsummary> - <type> - <v>Pid = pid()</v> - <v>User = Password = string()</v> - <v>Reason = euser | common_reason() </v> - </type> <desc> - <p>Performs login of <c>User</c> with <c>Password</c> to the account - specified by <c>Account</c>.</p> + <p>Performs login of <c><anno>User</anno></c> with <c><anno>Pass</anno></c> to the account + specified by <c><anno>Account</anno></c>.</p> <marker id="quote"></marker> </desc> </func> <func> - <name since="">quote(Pid, Command) -> [FTPLine]</name> + <name since="" name="quote" arity="2" /> <fsummary>Sends an arbitrary FTP command.</fsummary> - <type> - <v>Pid = pid()</v> - <v>Command = string()</v> - <v>FTPLine = string()</v> - </type> - <desc><note><p>The telnet end of line characters, from the FTP + <desc><note><p>The telnet end of line characters, from the FTP protocol definition, CRLF, for example, "\\r\\n" has been removed.</p></note> <p>Sends an arbitrary FTP command and returns verbatim a list of the lines sent back by the FTP server. This function is diff --git a/lib/ftp/doc/src/specs.xml b/lib/ftp/doc/src/specs.xml new file mode 100644 index 0000000000..a01aa83f78 --- /dev/null +++ b/lib/ftp/doc/src/specs.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" ?> +<specs xmlns:xi="http://www.w3.org/2001/XInclude"> + <xi:include href="../specs/specs_ftp.xml"/> +</specs> diff --git a/lib/ftp/test/ftp_SUITE.erl b/lib/ftp/test/ftp_SUITE.erl index 961b3b5fe1..9239d18f74 100644 --- a/lib/ftp/test/ftp_SUITE.erl +++ b/lib/ftp/test/ftp_SUITE.erl @@ -1069,7 +1069,7 @@ error_ehost(_Config) -> %%%---------------------------------------------------------------- error_datafail() -> [{doc, "Test that failure to open data channel captures " - "error emitted on ctrl chanenel"}]. + "error emitted on ctrl channel"}]. error_datafail(Config) -> Self = self(), -- 2.35.3
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor