ftp.erl

来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,598 行 · 第 1/4 页

ERL
1,598
字号
%% ``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/.%% %% 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$%%%% Description: This module implements an ftp client, RFC 959. %% It also supports ipv6 RFC 2428.-module(ftp).-behaviour(gen_server).%%  API - Client interface-export([cd/2, close/1, delete/2, formaterror/1, 	 lcd/2, lpwd/1, ls/1, ls/2, 	 mkdir/2, nlist/1, nlist/2, 	 open/1, open/2, open/3, force_active/1,	 pwd/1, quote/2,	 recv/2, recv/3, recv_bin/2, 	 recv_chunk_start/2, recv_chunk/1, 	 rename/3, rmdir/2, 	 send/2, send/3, send_bin/3, 	 send_chunk_start/2, send_chunk/2, send_chunk_end/1, 	 type/2, user/3, user/4, account/2,	 append/3, append/2, append_bin/3,	 append_chunk/2, append_chunk_end/1, append_chunk_start/2]).%% gen_server callbacks-export([init/1, handle_call/3, handle_cast/2, 	 handle_info/2, terminate/2, code_change/3]).%% supervisor callbacks-export([start_link_sup/1]).-include("ftp_internal.hrl").%% Constante used in internal state definition-define(CONNECTION_TIMEOUT, 60*1000).-define(DEFAULT_MODE, passive).%% Internal Constants-define(FTP_PORT, 21).-define(FILE_BUFSIZE, 4096).%% Internal state-record(state, {	  csock = undefined, % socket() - Control connection socket 	  dsock = undefined, % socket() - Data connection socket 	  verbose = false,   % boolean() 	  ldir = undefined,  % string() - Current local directory	  type = ftp_server_default,  % atom() - binary | ascii 	  chunk = false,     % boolean() - Receiving data chunks 	  mode = ?DEFAULT_MODE,    % passive | active	  timeout = ?CONNECTION_TIMEOUT, % integer()	  %% Data received so far on the data connection	  data = <<>>,   % binary()	  %% Data received so far on the control connection	  %% {BinStream, AccLines}. If a binary sequence	  %% ends with ?CR then keep it in the binary to	  %% be able to detect if the next received byte is ?LF	  %% and hence the end of the response is reached!	  ctrl_data = {<<>>, [], start},  % {binary(), [bytes()], LineStatus}	  %% pid() - Client pid (note not the same as "From")	  owner = undefined,   	  client = undefined,  % "From" to be used in gen_server:reply/2	  %% Function that activated a connection and maybe some	  %% data needed further on.	  caller = undefined, % term()     	  ip_v6_disabled,     % boolean()	  progress = ignore   % ignore | pid()	    	 }).%%%=========================================================================%%%  API - CLIENT FUNCTIONS%%%=========================================================================%%--------------------------------------------------------------------------%% open(Host, <Port>, <Flags>) -> {ok, Pid} | {error, ehost}%%	Host = string(), %%      Port = integer(), %%      Flags = [Flag], %%      Flag = verbose | debug | trace%%%% Description:  Start an ftp client and connect to a host.%%--------------------------------------------------------------------------%% The only option was the host in textual formopen({option_list, Options})->    ensure_started(),    Flags = key_search(flags, Options, []),    {ok, Pid} =  ftp_sup:start_child([[[{client, self()}, Flags], []]]),    call(Pid, {open, ip_comm, Options}, pid);	 %% The only option was the tuple form of the ip-numberopen(Host) when tuple(Host) ->    open(Host, ?FTP_PORT, []);%% Host is the string form of the hostname open(Host)->    open(Host, ?FTP_PORT, []).open(Host, Port) when integer(Port) ->    open(Host, Port, []);open(Host, Flags) when list(Flags) ->    open(Host, ?FTP_PORT, Flags).open(Host, Port, Flags) when integer(Port), list(Flags) ->    ensure_started(),    {ok, Pid} = ftp_sup:start_child([[[{client, self()}, Flags], []]]),     Opts = [{host, Host}, {port, Port}| Flags],     call(Pid, {open, ip_comm, Opts}, pid).%%--------------------------------------------------------------------------%% user(Pid, User, Pass, <Acc>) -> ok | {error, euser} | {error, econn} %%                                    | {error, eacct}%%	Pid = pid(), %%      User = Pass =  Acc = string()%%%% Description:  Login with or without a supplied account name.%%--------------------------------------------------------------------------user(Pid, User, Pass) ->    call(Pid, {user, User, Pass}, atom).user(Pid, User, Pass, Acc) ->    call(Pid, {user, User, Pass, Acc}, atom).%%--------------------------------------------------------------------------%% account(Pid, Acc)  -> ok | {error, eacct}%%	Pid = pid()%%	Acc= string()%%%% Description:  Set a user Account.%%--------------------------------------------------------------------------account(Pid, Acc) ->    call(Pid, {account, Acc}, atom).%%--------------------------------------------------------------------------%% pwd(Pid) -> {ok, Dir} | {error, elogin} | {error, econn} %%	Pid = pid()%%      Dir = string()%%%% Description:  Get the current working directory at remote server.%%--------------------------------------------------------------------------pwd(Pid) ->    call(Pid, pwd, ctrl).%%--------------------------------------------------------------------------%% lpwd(Pid) ->  {ok, Dir} | {error, elogin} %%	Pid = pid()%%      Dir = string()%%%% Description:  Get the current working directory at local server.%%--------------------------------------------------------------------------lpwd(Pid) ->    call(Pid, lpwd, string).%%--------------------------------------------------------------------------%% cd(Pid, Dir) ->  ok | {error, epath} | {error, elogin} | {error, econn}%%	Pid = pid()%%	Dir = string()%%%% Description:  Change current working directory at remote server.%%--------------------------------------------------------------------------cd(Pid, Dir) ->    call(Pid, {cd, Dir}, atom).%%--------------------------------------------------------------------------%% lcd(Pid, Dir) ->  ok | {error, epath}%%	Pid = pid()%%	Dir = string()%%%% Description:  Change current working directory for the local client.%%--------------------------------------------------------------------------lcd(Pid, Dir) ->    call(Pid, {lcd, Dir}, string).%%--------------------------------------------------------------------------%% ls(Pid, <Dir>) -> {ok, Listing} | {error, epath} | {error, elogin} | %%                   {error, econn}%%	Pid = pid()%%	Dir = string()%%      Listing = string()%%%% Description: List the contents of current directory (ls/1) or%% directory Dir (ls/2) at remote server.%%--------------------------------------------------------------------------ls(Pid) ->  ls(Pid, "").ls(Pid, Dir) ->    call(Pid, {dir, long, Dir}, string).%%--------------------------------------------------------------------------%% nlist(Pid, <Dir>) -> {ok, Listing} | {error, epath} | {error, elogin} | %%                      {error, econn}%%	Pid = pid()%%	Dir = string()%%%% Description:  List the contents of current directory (ls/1) or directory%%           Dir (ls/2) at remote server. The returned list is a stream%%           of file names.%%--------------------------------------------------------------------------nlist(Pid) ->  nlist(Pid, "").nlist(Pid, Dir) ->    call(Pid, {dir, short, Dir}, string).%%--------------------------------------------------------------------------%% rename(Pid, CurrFile, NewFile) ->  ok | {error, epath} | {error, elogin} %%                                    | {error, econn}%%	Pid = pid()%%	CurrFile = NewFile = string()%%%% Description:  Rename a file at remote server.%%--------------------------------------------------------------------------rename(Pid, CurrFile, NewFile) ->    call(Pid, {rename, CurrFile, NewFile}, string).%%--------------------------------------------------------------------------%% delete(Pid, File) ->  ok | {error, epath} | {error, elogin} | %%                       {error, econn}%%	Pid = pid()%%	File = string()%%%% Description:  Remove file at remote server.%%--------------------------------------------------------------------------delete(Pid, File) ->    call(Pid, {delete, File}, string).%%--------------------------------------------------------------------------%% mkdir(Pid, Dir) -> ok | {error, epath} | {error, elogin} | {error, econn}%%	Pid = pid(), %%	Dir = string()%%%% Description:  Make directory at remote server.%%--------------------------------------------------------------------------mkdir(Pid, Dir) ->    call(Pid, {mkdir, Dir}, atom).%%--------------------------------------------------------------------------%% rmdir(Pid, Dir) -> ok | {error, epath} | {error, elogin} | {error, econn}%%	Pid = pid(), %%	Dir = string()%%%% Description:  Remove directory at remote server.%%--------------------------------------------------------------------------rmdir(Pid, Dir) ->    call(Pid, {rmdir, Dir}, atom).%%--------------------------------------------------------------------------%% type(Pid, Type) -> ok | {error, etype} | {error, elogin} | {error, econn}%%	Pid = pid() %%	Type = ascii | binary%%%% Description:  Set transfer type.%%--------------------------------------------------------------------------type(Pid, Type) ->    call(Pid, {type, Type}, atom).%%--------------------------------------------------------------------------%% recv(Pid, RemoteFileName <LocalFileName>) -> ok | {error, epath} |%%                                          {error, elogin} | {error, econn}%%	Pid = pid()%%	RemoteFileName = LocalFileName = string()%%%% Description:  Transfer file from remote server.%%--------------------------------------------------------------------------recv(Pid, RemotFileName) ->  recv(Pid, RemotFileName, RemotFileName).recv(Pid, RemotFileName, LocalFileName) ->    call(Pid, {recv, RemotFileName, LocalFileName}, atom).%%--------------------------------------------------------------------------%% recv_bin(Pid, RemoteFile) -> {ok, Bin} | {error, epath} | {error, elogin} %%			   | {error, econn}%%	Pid = pid()%%	RemoteFile = string()%%      Bin = binary()%%%% Description:  Transfer file from remote server into binary.%%--------------------------------------------------------------------------recv_bin(Pid, RemoteFile) ->    call(Pid, {recv_bin, RemoteFile}, bin).%%--------------------------------------------------------------------------%% recv_chunk_start(Pid, RemoteFile) -> ok | {error, elogin} | {error, epath} %%                                 | {error, econn}%%	Pid = pid()%%	RemoteFile = string()%%%% Description:  Start receive of chunks of remote file.%%--------------------------------------------------------------------------recv_chunk_start(Pid, RemoteFile) ->    call(Pid, {recv_chunk_start, RemoteFile}, atom).%%--------------------------------------------------------------------------%% recv_chunk(Pid, RemoteFile) ->  ok | {ok, Bin} | {error, Reason}%%	Pid = pid()%%	RemoteFile = string()%%%% Description:  Transfer file from remote server into binary in chunks%%--------------------------------------------------------------------------recv_chunk(Pid) ->    call(Pid, recv_chunk, atom).%%--------------------------------------------------------------------------%% send(Pid, LocalFileName <RemotFileName>) -> ok | {error, epath} %%                                                | {error, elogin} %%                             | {error, econn}%%	Pid = pid()%%	LocalFileName = RemotFileName = string()%%%% Description:  Transfer file to remote server.%%--------------------------------------------------------------------------send(Pid, LocalFileName) ->  send(Pid, LocalFileName, LocalFileName).send(Pid, LocalFileName, RemotFileName) ->    call(Pid, {send, LocalFileName, RemotFileName}, atom).%%--------------------------------------------------------------------------%% send_bin(Pid, Bin, RemoteFile) -> ok | {error, epath} | {error, elogin} %%                             | {error, enotbinary} | {error, econn}%%	Pid = pid()%%	Bin = binary()%%	RemoteFile = string()%%%% Description:  Transfer a binary to a remote file.%%--------------------------------------------------------------------------send_bin(Pid, Bin, RemoteFile) when binary(Bin) ->    call(Pid, {send_bin, Bin, RemoteFile}, atom);send_bin(_Pid, _Bin, _RemoteFile) ->  {error, enotbinary}.%%--------------------------------------------------------------------------%% send_chunk_start(Pid, RemoteFile) -> ok | {error, elogin} | {error, epath} %%                                 | {error, econn}%%	Pid = pid()%%	RemoteFile = string()%%%% Description:  Start transfer of chunks to remote file.%%--------------------------------------------------------------------------send_chunk_start(Pid, RemoteFile) ->    call(Pid, {send_chunk_start, RemoteFile}, atom).%%--------------------------------------------------------------------------%% append_chunk_start(Pid, RemoteFile) -> ok | {error, elogin} | %%                                        {error, epath} | {error, econn}%%	Pid = pid()%%	RemoteFile = string()%%%% Description:  Start append chunks of data to remote file.%%--------------------------------------------------------------------------append_chunk_start(Pid, RemoteFile) ->    call(Pid, {append_chunk_start, RemoteFile}, atom).%%--------------------------------------------------------------------------%% send_chunk(Pid, Bin) -> ok | {error, elogin} | {error, enotbinary} %%                       | {error, echunk} | {error, econn}%%      Pid = pid()%%	Bin = binary().%%%% Purpose:  Send chunk to remote file.%%--------------------------------------------------------------------------send_chunk(Pid, Bin) when binary(Bin) ->    call(Pid, {transfer_chunk, Bin}, atom);send_chunk(_Pid, _Bin) ->  {error, enotbinary}.%%--------------------------------------------------------------------------%% append_chunk(Pid, Bin) -> ok | {error, elogin} | {error, enotbinary} %%			     | {error, echunk} | {error, econn}%%	Pid = pid()%%	Bin = binary()%%%% Description:  Append chunk to remote file.%%--------------------------------------------------------------------------append_chunk(Pid, Bin) when binary(Bin) ->    call(Pid, {transfer_chunk, Bin}, atom);append_chunk(_Pid, _Bin) ->  {error, enotbinary}.%%--------------------------------------------------------------------------%% send_chunk_end(Pid) -> ok | {error, elogin} | {error, echunk} %%			  | {error, econn}%%	Pid = pid()%%%% Description:  End sending of chunks to remote file.%%--------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?