.TH ftp 3erl "inets 6.3.4" "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 As from \fIInets\fR\& 4\&.4\&.1, 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 \fBmode\fR\&\&. .LP An FTP client can be started in two ways\&. One is using the \fBInets service framework\fR\&, the other is to start it directly as a standalone process using function \fBopen\fR\&\&. .LP For a simple example of an FTP session, see \fBInets User\&'s Guide\fR\&\&. .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 provvided 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 SERVICE START/STOP" .LP The FTP client can be started and stopped dynamically in runtime by calling the \fIInets\fR\& application API \fIinets:start(ftpc, ServiceConfig)\fR\&, or \fIinets:start(ftpc, ServiceConfig, How)\fR\&, and \fIinets:stop(ftpc, Pid)\fR\&\&. For details, see \fBinets(3erl)\fR\&\&. .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 Port = \fIinteger() > 0\fR\& .RE .RS 2 .LP Default is \fI21\fR\&\&. .RE .TP 2 .B {mode, Mode}: .RS 2 .LP Mode = \fIactive | passive\fR\& .RE .RS 2 .LP Default is \fIpassive\fR\&\&. .RE .TP 2 .B {verbose, Verbose}: .RS 2 .LP Verbose = \fIboolean()\fR\& .RE .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 Debug = \fItrace | debug | disable\fR\& .RE .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 IpFamily = \fIinet | inet6 | inet6fb4\fR\& .RE .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 Timeout = \fInon_neg_integer()\fR\& .RE .RS 2 .LP Connection time-out\&. .RE .RS 2 .LP Default is \fI60000\fR\& (milliseconds)\&. .RE .TP 2 .B {dtimeout, DTimeout}: .RS 2 .LP DTimeout = \fInon_neg_integer() | infinity\fR\& .RE .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 {progress, Progress}: .RS 2 .LP Progress = \fIignore | {CBModule, CBFunction, InitProgress}\fR\& .RE .RS 2 .LP \fICBModule = atom()\fR\&, \fICBFunction = atom()\fR\& .RE .RS 2 .LP \fIInitProgress = term()\fR\& .RE .RS 2 .LP Default is \fIignore\fR\&\&. .RE .RE .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: .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 CBModule:CBFunction(InitProgress, 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 CBModule:CBFunction(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 CBModule:CBFunction(UserProgressTerm, File, {transfer_size, 0}) \fR\& .RE .LP .RE .LP The callback function is to be defined as follows: .LP \fI CBModule:CBFunction(UserProgressTerm, File, Size) -> UserProgressTerm \fR\& .LP \fI CBModule = CBFunction = atom() \fR\& .LP \fI UserProgressTerm = term() \fR\& .LP \fI File = string() \fR\& .LP \fI Size = {transfer_size, integer()} | {file_size, integer()} | {file_size, unknown} \fR\& .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\&. .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\&\&. .LP The file transfer type is set to the default of the FTP server when the session is opened\&. This is usually ASCCI mode\&. .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\&. .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\&. .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 .LP \fIshortage_reason()\fR\& = \fIetnospc | epnospc\fR\& .LP \fIrestriction_reason()\fR\& = \fIepath | efnamena | elogin | enotbinary\fR\& - all restrictions are not always relevant to all functions .LP \fIcommon_reason()\fR\& = \fIeconn | eclosed | term()\fR\& - some explanation of what went wrong .SH EXPORTS .LP .B account(Pid, Account) -> ok | {error, Reason} .br .RS .LP Types: .RS 3 Pid = pid() .br Account = string() .br Reason = eacct | common_reason() .br .RE .RE .RS .LP Sets the account for an operation, if needed\&. .RE .LP .B append(Pid, LocalFile) -> .br .B append(Pid, LocalFile, RemoteFile) -> ok | {error, Reason} .br .RS .LP Types: .RS 3 Pid = pid() .br LocalFile = RemoteFile = string() .br Reason = epath | elogin | etnospc | epnospc | efnamena | common_reason .br .RE .RE .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 .B append_bin(Pid, Bin, RemoteFile) -> ok | {error, Reason} .br .RS .LP Types: .RS 3 Pid = pid() .br Bin = binary()() .br RemoteFile = string() .br Reason = restriction_reason()| shortage_reason() | common_reason() .br .RE .RE .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 .B append_chunk(Pid, Bin) -> ok | {error, Reason} .br .RS .LP Types: .RS 3 Pid = pid() .br Bin = binary() .br Reason = echunk | restriction_reason() | common_reason() .br .RE .RE .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 .B append_chunk_start(Pid, File) -> ok | {error, Reason} .br .RS .LP Types: .RS 3 Pid = pid() .br File = string() .br Reason = restriction_reason() | common_reason() .br .RE .RE .RS .LP Starts the transfer of chunks for appending to the file \fIFile\fR\& at the remote server\&. If the file does not exist, it is created\&. .RE .LP .B append_chunk_end(Pid) -> ok | {error, Reason} .br .RS .LP Types: .RS 3 Pid = pid() .br Reason = echunk | restriction_reason() | shortage_reason() .br .RE .RE .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 .B cd(Pid, Dir) -> ok | {error, Reason} .br .RS .LP Types: .RS 3 Pid = pid() .br Dir = string() .br Reason = restriction_reason() | common_reason() .br .RE .RE .RS .LP Changes the working directory at the remote server to \fIDir\fR\&\&. .RE .LP .B close(Pid) -> ok .br .RS .LP Types: .RS 3 Pid = pid() .br .RE .RE .RS .LP Ends an FTP session, created using function \fBopen\fR\&\&. .RE .LP .B delete(Pid, File) -> ok | {error, Reason} .br .RS .LP Types: .RS 3 Pid = pid() .br File = string() .br Reason = restriction_reason() | common_reason() .br .RE .RE .RS .LP Deletes the file \fIFile\fR\& at the remote server\&. .RE .LP .B formaterror(Tag) -> string() .br .RS .LP Types: .RS 3 Tag = {error, atom()} | atom() .br .RE .RE .RS .LP Given an error return value \fI{error, AtomReason}\fR\&, this function returns a readable string describing the error\&. .RE .LP .B lcd(Pid, Dir) -> ok | {error, Reason} .br .RS .LP Types: .RS 3 Pid = pid() .br Dir = string() .br Reason = restriction_reason() .br .RE .RE .RS .LP Changes the working directory to \fIDir\fR\& for the local client\&. .RE .LP .B lpwd(Pid) -> {ok, Dir} .br .RS .LP Types: .RS 3 Pid = pid() .br .RE .RE .RS .LP Returns the current working directory at the local client\&. .RE .LP .B ls(Pid) -> .br .B ls(Pid, Pathname) -> {ok, Listing} | {error, Reason} .br .RS .LP Types: .RS 3 Pid = pid() .br Pathname = string() .br Listing = string() .br Reason = restriction_reason() | common_reason() .br .RE .RE .RS .LP Returns a list of files in long format\&. .LP \fIPathname\fR\& can be a directory, a group of files, or a file\&. The \fIPathname\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 .B mkdir(Pid, Dir) -> ok | {error, Reason} .br .RS .LP Types: .RS 3 Pid = pid() .br Dir = string() .br Reason = restriction_reason() | common_reason() .br .RE .RE .RS .LP Creates the directory \fIDir\fR\& at the remote server\&. .RE .LP .B nlist(Pid) -> .br .B nlist(Pid, Pathname) -> {ok, Listing} | {error, Reason} .br .RS .LP Types: .RS 3 Pid = pid() .br Pathname = string() .br Listing = string() .br Reason = restriction_reason() | common_reason() .br .RE .RE .RS .LP Returns a list of files in short format\&. .LP \fIPathname\fR\& can be a directory, a group of files, 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 .B open(Host) -> {ok, Pid} | {error, Reason} .br .B open(Host, Opts) -> {ok, Pid} | {error, Reason} .br .RS .LP Types: .RS 3 Host = string() | ip_address() .br Opts = options() .br options() = [option()] .br option() = start_option() | open_option() .br start_option() = {verbose, verbose()} | {debug, debug()} .br verbose() = boolean() (default is false) .br debug() = disable | debug | trace (default is disable) .br open_option() = {ipfamily, ipfamily()} | {port, port()} | {mode, mode()} | {tls, tls_options()} | {timeout, timeout()} | {dtimeout, dtimeout()} | {progress, progress()} .br ipfamily() = inet | inet6 | inet6fb4 (default is inet) .br port() = integer() > 0 (default is 21) .br mode() = active | passive (default is passive) .br tls_options() = [\fBssl:ssloption()\fR\&] .br timeout() = integer() > 0 (default is 60000 milliseconds) .br dtimeout() = integer() > 0 | infinity (default is infinity) .br pogress() = ignore | {module(), function(), initial_data()} (default is ignore) .br module() = atom() .br function() = atom() .br initial_data() = term() .br Reason = ehost | term() .br .RE .RE .RS .LP Starts a standalone FTP client process (without the \fIInets\fR\& service framework) and opens a session with the FTP server at \fIHost\fR\&\&. .LP If option \fI{tls, tls_options()}\fR\& is present, the FTP session is transported over \fItls\fR\& (\fIftps\fR\&, see RFC 4217)\&. The list \fItls_options()\fR\& can be empty\&. The function \fB\fIssl:connect/3\fR\&\fR\& is used for securing both the control connection and the data sessions\&. .LP A session opened in this way is closed using function \fBclose\fR\&\&. .RE .LP .B pwd(Pid) -> {ok, Dir} | {error, Reason} .br .RS .LP Types: .RS 3 Pid = pid() .br Reason = restriction_reason() | common_reason() .br .RE .RE .RS .LP Returns the current working directory at the remote server\&. .RE .LP .B recv(Pid, RemoteFile) -> .br .B recv(Pid, RemoteFile, LocalFile) -> ok | {error, Reason} .br .RS .LP Types: .RS 3 Pid = pid() .br RemoteFile = LocalFile = string() .br Reason = restriction_reason() | common_reason() | file_write_error_reason() .br file_write_error_reason() = see file:write/2 .br .RE .RE .RS .LP Transfers the file \fIRemoteFile\fR\& from the remote server to the file system of the local client\&. If \fILocalFile\fR\& is specified, the local file will be \fILocalFile\fR\&, otherwise \fIRemoteFile\fR\&\&. .LP If the file write fails (for example, \fIenospc\fR\&), the command is aborted and \fI{error, file_write_error_reason()}\fR\& is returned\&. However, the file is \fInot\fR\& removed\&. .RE .LP .B recv_bin(Pid, RemoteFile) -> {ok, Bin} | {error, Reason} .br .RS .LP Types: .RS 3 Pid = pid() .br Bin = binary() .br RemoteFile = string() .br Reason = restriction_reason() | common_reason() .br .RE .RE .RS .LP Transfers the file \fIRemoteFile\fR\& from the remote server and receives it as a binary\&. .RE .LP .B recv_chunk_start(Pid, RemoteFile) -> ok | {error, Reason} .br .RS .LP Types: .RS 3 Pid = pid() .br RemoteFile = string() .br Reason = restriction_reason() | common_reason() .br .RE .RE .RS .LP Starts transfer of the file \fIRemoteFile\fR\& from the remote server\&. .RE .LP .B recv_chunk(Pid) -> ok | {ok, Bin} | {error, Reason} .br .RS .LP Types: .RS 3 Pid = pid() .br Bin = binary() .br Reason = restriction_reason() | common_reason() .br .RE .RE .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 .B rename(Pid, Old, New) -> ok | {error, Reason} .br .RS .LP Types: .RS 3 Pid = pid() .br CurrFile = NewFile = string() .br Reason = restriction_reason() | common_reason() .br .RE .RE .RS .LP Renames \fIOld\fR\& to \fINew\fR\& at the remote server\&. .RE .LP .B rmdir(Pid, Dir) -> ok | {error, Reason} .br .RS .LP Types: .RS 3 Pid = pid() .br Dir = string() .br Reason = restriction_reason() | common_reason() .br .RE .RE .RS .LP Removes directory \fIDir\fR\& at the remote server\&. .RE .LP .B send(Pid, LocalFile) -> .br .B send(Pid, LocalFile, RemoteFile) -> ok | {error, Reason} .br .RS .LP Types: .RS 3 Pid = pid() .br LocalFile = RemoteFile = string() .br Reason = restriction_reason() | common_reason() | shortage_reason() .br .RE .RE .RS .LP Transfers the file \fILocalFile\fR\& to the remote server\&. If \fIRemoteFile\fR\& is specified, the name of the remote file is set to \fIRemoteFile\fR\&, otherwise to \fILocalFile\fR\&\&. .RE .LP .B send_bin(Pid, Bin, RemoteFile) -> ok | {error, Reason} .br .RS .LP Types: .RS 3 Pid = pid() .br Bin = binary()() .br RemoteFile = string() .br Reason = restriction_reason() | common_reason() | shortage_reason() .br .RE .RE .RS .LP Transfers the binary \fIBin\fR\& into the file \fIRemoteFile\fR\& at the remote server\&. .RE .LP .B send_chunk(Pid, Bin) -> ok | {error, Reason} .br .RS .LP Types: .RS 3 Pid = pid() .br Bin = binary() .br Reason = echunk | restriction_reason() | common_reason() .br .RE .RE .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 .B send_chunk_start(Pid, File) -> ok | {error, Reason} .br .RS .LP Types: .RS 3 Pid = pid() .br File = string() .br Reason = restriction_reason() | common_reason() .br .RE .RE .RS .LP Starts transfer of chunks into the file \fIFile\fR\& at the remote server\&. .RE .LP .B send_chunk_end(Pid) -> ok | {error, Reason} .br .RS .LP Types: .RS 3 Pid = pid() .br Reason = restriction_reason() | common_reason() | shortage_reason() .br .RE .RE .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 .B type(Pid, Type) -> ok | {error, Reason} .br .RS .LP Types: .RS 3 Pid = pid() .br Type = ascii | binary .br Reason = etype | restriction_reason() | common_reason() .br .RE .RE .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 .B user(Pid, User, Password) -> ok | {error, Reason} .br .RS .LP Types: .RS 3 Pid = pid() .br User = Password = string() .br Reason = euser | common_reason() .br .RE .RE .RS .LP Performs login of \fIUser\fR\& with \fIPassword\fR\&\&. .RE .LP .B user(Pid, User, Password, Account) -> ok | {error, Reason} .br .RS .LP Types: .RS 3 Pid = pid() .br User = Password = string() .br Reason = euser | common_reason() .br .RE .RE .RS .LP Performs login of \fIUser\fR\& with \fIPassword\fR\& to the account specified by \fIAccount\fR\&\&. .RE .LP .B quote(Pid, Command) -> [FTPLine] .br .RS .LP Types: .RS 3 Pid = pid() .br Command = string() .br FTPLine = string( .br .RE .RE .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 \fBfile(3erl)\fR\& \fBfilename(3erl)\fR\& and J\&. Postel and J\&. Reynolds: File Transfer Protocol (RFC 959)\&.