.TH ftp 3erl "ftp 1.2.1" "Ericsson AB" "Erlang Module Definition" .SH NAME ftp \- A File Transfer Protocol client. .SH DESCRIPTION .LP This module implements a client for file transfer according to a subset of the File Transfer Protocol (FTP), see RFC 959\&. .LP The FTP client always tries to use passive FTP mode and only resort to active FTP mode if this fails\&. This default behavior can be changed by start option mode\&. .LP For a simple example of an FTP session, see FTP User\&'s Guide\&. .LP In addition to the ordinary functions for receiving and sending files (see \fIrecv/2\fR\&, \fIrecv/3\fR\&, \fIsend/2\fR\&, and \fIsend/3\fR\&) there are functions for receiving remote files as binaries (see \fIrecv_bin/2\fR\&) and for sending binaries to be stored as remote files (see \fIsend_bin/3\fR\&)\&. .LP A set of functions is provided for sending and receiving contiguous parts of a file to be stored in a remote file\&. For send, see \fIsend_chunk_start/2\fR\&, \fIsend_chunk/2\fR\&, and \fIsend_chunk_end/1\fR\&\&. For receive, see \fIrecv_chunk_start/2\fR\& and \fIrecv_chunk/\fR\&)\&. .LP The return values of the following functions depend much on the implementation of the FTP server at the remote host\&. In particular, the results from \fIls\fR\& and \fInlist\fR\& varies\&. Often real errors are not reported as errors by \fIls\fR\&, even if, for example, a file or directory does not exist\&. \fInlist\fR\& is usually more strict, but some implementations have the peculiar behaviour of responding with an error if the request is a listing of the contents of a directory that exists but is empty\&. .SH "FTP CLIENT START/STOP" .LP The FTP client can be started and stopped dynamically in runtime by calling the \fIftp\fR\& application API \fIftp:open(Host, Options)\fR\& and \fIftp:close(Client)\fR\&\&. .SH "DATA TYPES" .LP The following type definitions are used by more than one function in the FTP client API: .LP \fIpid()\fR\& = identifier of an FTP connection .LP \fIstring()\fR\& = list of ASCII characters .SH EXPORTS .LP .nf .B account(Pid :: pid(), Acc :: string()) -> .B ok | {error, Reason :: term()} .br .fi .br .RS .LP Sets the account for an operation, if needed\&. .RE .LP .nf .B append(Pid :: pid(), LocalFileName :: string()) -> .B ok | {error, Reason :: term()} .br .fi .br .nf .B append(Pid :: pid(), .B LocalFileName :: string(), .B RemoteFileName :: string()) -> .B ok | {error, Reason :: term()} .br .fi .br .RS .LP Transfers the file \fILocalFile\fR\& to the remote server\&. If \fIRemoteFile\fR\& is specified, the name of the remote file that the file is appended to is set to \fIRemoteFile\fR\&, otherwise to \fILocalFile\fR\&\&. If the file does not exists, it is created\&. .RE .LP .nf .B append_bin(Pid :: pid(), Bin :: binary(), RemoteFile :: string()) -> .B ok | {error, Reason :: term()} .br .fi .br .RS .LP Transfers the binary \fIBin\fR\& to the remote server and appends it to the file \fIRemoteFile\fR\&\&. If the file does not exist, it is created\&. .RE .LP .nf .B append_chunk(Pid :: pid(), Bin :: binary()) -> .B ok | {error, Reason :: term()} .br .fi .br .RS .LP Transfers the chunk \fIBin\fR\& to the remote server, which appends it to the file specified in the call to \fIappend_chunk_start/2\fR\&\&. .LP For some errors, for example, file system full, it is necessary to call \fIappend_chunk_end\fR\& to get the proper reason\&. .RE .LP .nf .B append_chunk_start(Pid :: pid(), RemoteFile :: string()) -> .B ok | {error, Reason :: term()} .br .fi .br .RS .LP Starts the transfer of chunks for appending to the file \fIRemoteFile\fR\& at the remote server\&. If the file does not exist, it is created\&. .RE .LP .nf .B append_chunk_end(Pid :: pid()) -> ok | {error, Reason :: term()} .br .fi .br .RS .LP Stops transfer of chunks for appending to the remote server\&. The file at the remote server, specified in the call to \fIappend_chunk_start/2\fR\&, is closed by the server\&. .RE .LP .nf .B cd(Pid :: pid(), Dir :: string()) -> .B ok | {error, Reason :: term()} .br .fi .br .RS .LP Changes the working directory at the remote server to \fIDir\fR\&\&. .RE .LP .nf .B close(Pid :: pid()) -> ok .br .fi .br .RS .LP Ends an FTP session, created using function open\&. .RE .LP .nf .B delete(Pid :: pid(), File :: string()) -> .B ok | {error, Reason :: term()} .br .fi .br .RS .LP Deletes the file \fIFile\fR\& at the remote server\&. .RE .LP .nf .B formaterror(Tag :: atom() | {error, atom()}) -> string() .br .fi .br .RS .LP Given an error return value \fI{error, AtomReason}\fR\&, this function returns a readable string describing the error\&. .RE .LP .nf .B lcd(Pid :: pid(), Dir :: string()) -> .B ok | {error, Reason :: term()} .br .fi .br .RS .LP Changes the working directory to \fIDir\fR\& for the local client\&. .RE .LP .nf .B lpwd(Pid :: pid()) -> {ok, Dir :: string()} .br .fi .br .RS .LP Returns the current working directory at the local client\&. .RE .LP .nf .B ls(Pid :: pid()) -> .B {ok, Listing :: string()} | {error, Reason :: term()} .br .fi .br .nf .B ls(Pid :: pid(), Dir :: string()) -> .B {ok, Listing :: string()} | {error, Reason :: term()} .br .fi .br .RS .LP Returns a list of files in long format\&. .LP \fIDir\fR\& can be a directory or a file\&. The \fIDir\fR\& string can contain wildcards\&. .LP \fIls/1\fR\& implies the current remote directory of the user\&. .LP The format of \fIListing\fR\& depends on the operating system\&. On UNIX, it is typically produced from the output of the \fIls -l\fR\& shell command\&. .RE .LP .nf .B mkdir(Pid :: pid(), Dir :: string()) -> .B ok | {error, Reason :: term()} .br .fi .br .RS .LP Creates the directory \fIDir\fR\& at the remote server\&. .RE .LP .nf .B nlist(Pid :: pid()) -> .B {ok, Listing :: string()} | {error, Reason :: term()} .br .fi .br .nf .B nlist(Pid :: pid(), Pathname :: string()) -> .B {ok, Listing :: string()} | {error, Reason :: term()} .br .fi .br .RS .LP Returns a list of files in short format\&. .LP \fIPathname\fR\& can be a directory or a file\&. The \fIPathname\fR\& string can contain wildcards\&. .LP \fInlist/1\fR\& implies the current remote directory of the user\&. .LP The format of \fIListing\fR\& is a stream of filenames where each filename is separated by or \&. Contrary to function \fIls\fR\&, the purpose of \fInlist\fR\& is to enable a program to process filename information automatically\&. .RE .LP .nf .B open(Host :: string() | inet:ip_address()) -> .B {ok, Pid :: pid()} | {error, Reason :: term()} .br .fi .br .nf .B open(Host :: string() | inet:ip_address(), Opts) -> .B {ok, Pid :: pid()} | {error, Reason :: term()} .br .fi .br .RS .LP Types: .RS 3 Opts = [Opt] .br Opt = StartOption | OpenOption .br StartOption = {verbose, Verbose} | {debug, Debug} .br Verbose = boolean() .br Debug = disable | debug | trace .br OpenOption = .br {ipfamily, IpFamily} | .br {port, Port :: port()} | .br {mode, Mode} | .br {tls, TLSOptions :: [ssl:tls_option()]} | .br {tls_sec_method, TLSSecMethod :: ftps | ftpes} | .br {tls_ctrl_session_reuse, TLSSessionReuse :: boolean()} | .br {timeout, Timeout :: timeout()} | .br {dtimeout, DTimeout :: timeout()} | .br {progress, Progress} | .br {sock_ctrl, SocketCtrls} | .br {sock_data_act, [SocketControl]} | .br {sock_data_pass, [SocketControl]} .br SocketCtrls = [SocketControl] .br IpFamily = inet | inet6 | inet6fb4 .br Mode = active | passive .br Module = Function = atom() .br InitialData = term() .br Progress = ignore | {Module, Function, InitialData} .br SocketControl = gen_tcp:option() .br .RE .RE .RS .LP Starts a FTP client process and opens a session with the FTP server at \fIHost\fR\&\&. .LP A session opened in this way is closed using function close\&. .LP The available configuration options are as follows: .RS 2 .TP 2 .B {host, Host}: .RS 2 .LP Host = \fIstring() | ip_address()\fR\& .RE .TP 2 .B {port, Port}: .RS 2 .LP Default is \fI0\fR\& which aliases to \fI21\fR\& or \fI990\fR\& when used with \fI{tls_sec_method,ftps}\fR\&)\&. .RE .TP 2 .B {mode, Mode}: .RS 2 .LP Default is \fIpassive\fR\&\&. .RE .TP 2 .B {verbose, Verbose}: .RS 2 .LP Determines if the FTP communication is to be verbose or not\&. .RE .RS 2 .LP Default is \fIfalse\fR\&\&. .RE .TP 2 .B {debug, Debug}: .RS 2 .LP Debugging using the dbg toolkit\&. .RE .RS 2 .LP Default is \fIdisable\fR\&\&. .RE .TP 2 .B {ipfamily, IpFamily}: .RS 2 .LP With \fIinet6fb4\fR\& the client behaves as before, that is, tries to use IPv6, and only if that does not work it uses IPv4)\&. .RE .RS 2 .LP Default is \fIinet\fR\& (IPv4)\&. .RE .TP 2 .B {timeout, Timeout}: .RS 2 .LP Connection time-out\&. .RE .RS 2 .LP Default is \fI60000\fR\& (milliseconds)\&. .RE .TP 2 .B {dtimeout, DTimeout}: .RS 2 .LP Data connect time-out\&. The time the client waits for the server to connect to the data socket\&. .RE .RS 2 .LP Default is \fIinfinity\fR\&\&. .RE .TP 2 .B {tls, TLSOptions}: .RS 2 .LP The FTP session is transported over \fItls\fR\& (\fIftps\fR\&, see RFC 4217)\&. The list \fITLSOptions\fR\& can be empty\&. The function \fIssl:connect/3\fR\& is used for securing both the control connection and the data sessions\&. .RE .TP 2 .B {tls_sec_method, TLSSecMethod}: .RS 2 .LP When set to \fIftps\fR\& will connect immediately with SSL instead of upgrading with STARTTLS\&. This suboption is ignored unless the suboption \fItls\fR\& is also set\&. .RE .RS 2 .LP Default is \fIftpes\fR\& .RE .TP 2 .B {tls_ctrl_session_reuse, boolean()}: .RS 2 .LP When set to \fItrue\fR\& the client will re-use the TLS session from the control channel on the data channel as enforced by many FTP servers as (proposed and implemented first by vsftpd)\&. .RE .RS 2 .LP Default is \fIfalse\fR\&\&. .RE .TP 2 .B {sock_ctrl, SocketCtrls :: [SocketControl :: gen_tcp:option()]}: Passes options from \fISocketCtrls\fR\& down to the underlying transport layer (tcp)\&. .RS 2 .LP gen_tcp:option() except for \fIipv6_v6only\fR\&, \fIactive\fR\&, \fIpacket\fR\&, \fImode\fR\&, \fIpacket_size\fR\& and \fIheader\fR\&\&. .RE .RS 2 .LP Default value is \fISocketCtrls = []\fR\&\&. .RE .TP 2 .B {sock_data_act, [SocketControl]}: Passes options from \fI[SocketControl]\fR\& down to the underlying transport layer (tcp)\&. .RS 2 .LP \fIsock_data_act\fR\& uses the value of \fIsock_ctrl\fR\& as default value\&. .RE .TP 2 .B {sock_data_pass, [SocketControl]}: Passes options from \fI[SocketControl]\fR\& down to the underlying transport layer (tcp)\&. .RS 2 .LP \fIsock_data_pass\fR\& uses the value of \fIsock_ctrl\fR\& as default value\&. .RE .TP 2 .B {progress, Progress}: .RS 2 .LP Progress = \fIignore | {Module, Function, InitialData}\fR\& .RE .RS 2 .LP \fIModule = atom()\fR\&, \fIFunction = atom()\fR\& .RE .RS 2 .LP \fIInitialData = term()\fR\& .RE .RS 2 .LP Default is \fIignore\fR\&\&. .RE .RS 2 .LP Option \fIprogress\fR\& 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 \fIignore\fR\&, that is, the option is not used\&. When the progress option is specified, the following happens when \fIftp:send/[3,4]\fR\& or \fIftp:recv/[3,4]\fR\& are called: .RE .RS 2 .TP 2 * 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 \fIUserProgressTerm\fR\& that will be used as input the next time the callback function is called\&. .RS 2 .LP \fI Module:Function(InitialData, File, {file_size, FileSize}) \fR\& .RE .LP .TP 2 * Every time a chunk of bytes is transferred the following call is made: .RS 2 .LP \fI Module:Function(UserProgressTerm, File, {transfer_size, TransferSize}) \fR\& .RE .LP .TP 2 * At the end of the file the following call is made to indicate the end of the transfer: .RS 2 .LP \fI Module:Function(UserProgressTerm, File, {transfer_size, 0}) \fR\& .RE .LP .RE .RS 2 .LP The callback function is to be defined as follows: .RE .RS 2 .LP \fI Module:Function(UserProgressTerm, File, Size) -> UserProgressTerm \fR\& .RE .RS 2 .LP \fI UserProgressTerm = term() \fR\& .RE .RS 2 .LP \fI File = string() \fR\& .RE .RS 2 .LP \fI Size = {transfer_size, integer()} | {file_size, integer()} | {file_size, unknown} \fR\& .RE .RS 2 .LP For remote files, \fIftp\fR\& cannot determine the file size in a platform independent way\&. In this case the size becomes \fIunknown\fR\& and it is left to the application to determine the size\&. .RE .LP .RS -4 .B Note: .RE 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 \fIignore\fR\&\&. .RS 2 .LP The file transfer type is set to the default of the FTP server when the session is opened\&. This is usually ASCII mode\&. .RE .RS 2 .LP The current local working directory (compare \fIlpwd/1\fR\&) is set to the value reported by \fIfile:get_cwd/1\fR\&, the wanted local directory\&. .RE .RS 2 .LP The return value \fIPid\fR\& 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\&. .RE .RE .RE .LP .nf .B pwd(Pid :: pid()) -> .B {ok, Dir :: string()} | {error, Reason :: term()} .br .fi .br .RS .LP Returns the current working directory at the remote server\&. .RE .LP .nf .B recv(Pid :: pid(), RemoteFileName :: string()) -> .B ok | {error, Reason :: term()} .br .fi .br .nf .B recv(Pid :: pid(), .B RemoteFileName :: string(), .B LocalFileName :: string()) -> .B ok | {error, Reason :: term()} .br .fi .br .RS .LP Transfers the file \fIRemoteFileName\fR\& from the remote server to the file system of the local client\&. If \fILocalFileName\fR\& is specified, the local file will be \fILocalFileName\fR\&, otherwise \fIRemoteFileName\fR\&\&. .LP If the file write fails, the command is aborted and \fI{error, term()}\fR\& is returned\&. However, the file is \fInot\fR\& removed\&. .RE .LP .nf .B recv_bin(Pid :: pid(), RemoteFile :: string()) -> .B {ok, Bin :: binary()} | {error, Reason :: term()} .br .fi .br .RS .LP Transfers the file \fIRemoteFile\fR\& from the remote server and receives it as a binary\&. .RE .LP .nf .B recv_chunk_start(Pid :: pid(), RemoteFile :: string()) -> .B ok | {error, Reason :: term()} .br .fi .br .RS .LP Starts transfer of the file \fIRemoteFile\fR\& from the remote server\&. .RE .LP .nf .B recv_chunk(Pid :: pid()) -> .B ok | .B {ok, Bin :: binary()} | .B {error, Reason :: term()} .br .fi .br .RS .LP Receives a chunk of the remote file (\fIRemoteFile\fR\& of \fIrecv_chunk_start\fR\&)\&. The return values have the following meaning: .RS 2 .TP 2 * \fIok\fR\& = the transfer is complete\&. .LP .TP 2 * \fI{ok, Bin}\fR\& = just another chunk of the file\&. .LP .TP 2 * \fI{error, Reason}\fR\& = transfer failed\&. .LP .RE .RE .LP .nf .B rename(Pid :: pid(), Old :: string(), New :: string()) -> .B ok | {error, Reason :: term()} .br .fi .br .RS .LP Renames \fIOld\fR\& to \fINew\fR\& at the remote server\&. .RE .LP .nf .B rmdir(Pid :: pid(), Dir :: string()) -> .B ok | {error, Reason :: term()} .br .fi .br .RS .LP Removes directory \fIDir\fR\& at the remote server\&. .RE .LP .nf .B send(Pid :: pid(), LocalFileName :: string()) -> .B ok | {error, Reason :: term()} .br .fi .br .nf .B send(Pid :: pid(), .B LocalFileName :: string(), .B RemoteFileName :: string()) -> .B ok | {error, Reason :: term()} .br .fi .br .RS .LP Transfers the file \fILocalFileName\fR\& to the remote server\&. If \fIRemoteFileName\fR\& is specified, the name of the remote file is set to \fIRemoteFileName\fR\&, otherwise to \fILocalFileName\fR\&\&. .RE .LP .nf .B send_bin(Pid :: pid(), Bin :: binary(), RemoteFile :: string()) -> .B ok | {error, Reason :: term()} .br .fi .br .RS .LP Transfers the binary \fIBin\fR\& into the file \fIRemoteFile\fR\& at the remote server\&. .RE .LP .nf .B send_chunk(Pid :: pid(), Bin :: binary()) -> .B ok | {error, Reason :: term()} .br .fi .br .RS .LP Transfers the chunk \fIBin\fR\& to the remote server, which writes it into the file specified in the call to \fIsend_chunk_start/2\fR\&\&. .LP For some errors, for example, file system full, it is necessary to to call \fIsend_chunk_end\fR\& to get the proper reason\&. .RE .LP .nf .B send_chunk_start(Pid :: pid(), RemoteFile :: string()) -> .B ok | {error, Reason :: term()} .br .fi .br .RS .LP Starts transfer of chunks into the file \fIRemoteFile\fR\& at the remote server\&. .RE .LP .nf .B send_chunk_end(Pid :: pid()) -> ok | {error, Reason :: term()} .br .fi .br .RS .LP Stops transfer of chunks to the remote server\&. The file at the remote server, specified in the call to \fIsend_chunk_start/2\fR\& is closed by the server\&. .RE .LP .nf .B type(Pid :: pid(), Type :: ascii | binary) -> .B ok | {error, Reason :: term()} .br .fi .br .RS .LP Sets the file transfer type to \fIascii\fR\& or \fIbinary\fR\&\&. When an FTP session is opened, the default transfer type of the server is used, most often \fIascii\fR\&, which is default according to RFC 959\&. .RE .LP .nf .B user(Pid :: pid(), User :: string(), Pass :: string()) -> .B ok | {error, Reason :: term()} .br .fi .br .RS .LP Performs login of \fIUser\fR\& with \fIPass\fR\&\&. .RE .LP .nf .B user(Pid :: pid(), .B User :: string(), .B Pass :: string(), .B Account :: string()) -> .B ok | {error, Reason :: term()} .br .fi .br .RS .LP Performs login of \fIUser\fR\& with \fIPass\fR\& to the account specified by \fIAccount\fR\&\&. .RE .LP .nf .B quote(Pid :: pid(), Cmd :: string()) -> [FTPLine :: string()] .br .fi .br .RS .LP .RS -4 .B Note: .RE The telnet end of line characters, from the FTP protocol definition, CRLF, for example, "\\\\r\\\\n" has been removed\&. .LP Sends an arbitrary FTP command and returns verbatim a list of the lines sent back by the FTP server\&. This function is intended to give application accesses to FTP commands that are server-specific or that cannot be provided by this FTP client\&. .LP .RS -4 .B Note: .RE FTP commands requiring a data connection cannot be successfully issued with this function\&. .RE .SH "ERRORS" .LP The possible error reasons and the corresponding diagnostic strings returned by \fIformaterror/1\fR\& are as follows: .RS 2 .TP 2 .B \fIechunk\fR\&: Synchronization error during chunk sending according to one of the following: .RS 2 .TP 2 * A call is made to \fIsend_chunk/2\fR\& or \fIsend_chunk_end/1\fR\& before a call to \fIsend_chunk_start/2\fR\&\&. .LP .TP 2 * A call has been made to another transfer function during chunk sending, that is, before a call to \fIsend_chunk_end/1\fR\&\&. .LP .RE .TP 2 .B \fIeclosed\fR\&: The session is closed\&. .TP 2 .B \fIeconn\fR\&: Connection to the remote server is prematurely closed\&. .TP 2 .B \fIehost\fR\&: Host is not found, FTP server is not found, or connection is rejected by FTP server\&. .TP 2 .B \fIelogin\fR\&: User is not logged in\&. .TP 2 .B \fIenotbinary\fR\&: Term is not a binary\&. .TP 2 .B \fIepath\fR\&: No such file or directory, or directory already exists, or permission denied\&. .TP 2 .B \fIetype\fR\&: No such type\&. .TP 2 .B \fIeuser\fR\&: Invalid username or password\&. .TP 2 .B \fIetnospc\fR\&: Insufficient storage space in system [452]\&. .TP 2 .B \fIepnospc\fR\&: Exceeded storage allocation (for current directory or dataset) [552]\&. .TP 2 .B \fIefnamena\fR\&: Filename not allowed [553]\&. .RE .SH "SEE ALSO" .LP file(3erl) filename(3erl) and J\&. Postel and J\&. Reynolds: File Transfer Protocol (RFC 959)\&.