File 1060-ftp-whitespace-fixes.patch of Package erlang
From 0254ebb3a53c2984f4b7b81bb9d2935ec28701a1 Mon Sep 17 00:00:00 2001
From: Alexander Clouter <alex@digriz.org.uk>
Date: Sun, 24 May 2020 13:59:20 +0100
Subject: [PATCH] ftp: whitespace fixes
---
lib/ftp/src/ftp.erl | 2304 ++++++++++++++++++------------------
lib/ftp/test/ftp_SUITE.erl | 690 +++++------
2 files changed, 1497 insertions(+), 1497 deletions(-)
diff --git a/lib/ftp/src/ftp.erl b/lib/ftp/src/ftp.erl
index b94c535467..fb52c4b2e8 100644
--- a/lib/ftp/src/ftp.erl
+++ b/lib/ftp/src/ftp.erl
@@ -37,24 +37,24 @@
-export([start_link/1, start_link/2]).
%% 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,
- 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,
- info/1, latest_ctrl_response/1]).
+-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,
+ 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,
+ info/1, latest_ctrl_response/1]).
%% gen_server callbacks
--export([init/1, handle_call/3, handle_cast/2,
- handle_info/2, terminate/2, code_change/3]).
+-export([init/1, handle_call/3, handle_cast/2,
+ handle_info/2, terminate/2, code_change/3]).
-include("ftp_internal.hrl").
@@ -63,7 +63,7 @@
-define(DATA_ACCEPT_TIMEOUT, infinity).
-define(DEFAULT_MODE, passive).
-define(PROGRESS_DEFAULT, ignore).
--define(FTP_EXT_DEFAULT, false).
+-define(FTP_EXT_DEFAULT, false).
%% Internal Constants
-define(FTP_PORT, 21).
@@ -76,39 +76,39 @@
%% Internal state
-record(state, {
- csock = undefined, % socket() - Control connection socket
- dsock = undefined, % socket() - Data connection socket
- tls_options = undefined, % list()
- 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")
- latest_ctrl_response = "",
- 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()
- ipfamily, % inet | inet6 | inet6fb4
+ csock = undefined, % socket() - Control connection socket
+ dsock = undefined, % socket() - Data connection socket
+ tls_options = undefined, % list()
+ 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")
+ latest_ctrl_response = "",
+ 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()
+ ipfamily, % inet | inet6 | inet6fb4
sockopts_ctrl = [],
sockopts_data_passive = [],
sockopts_data_active = [],
- progress = ignore, % ignore | pid()
- dtimeout = ?DATA_ACCEPT_TIMEOUT, % non_neg_integer() | infinity
- tls_upgrading_data_connection = false,
- ftp_extension = ?FTP_EXT_DEFAULT
- }).
+ progress = ignore, % ignore | pid()
+ dtimeout = ?DATA_ACCEPT_TIMEOUT, % non_neg_integer() | infinity
+ tls_upgrading_data_connection = false,
+ ftp_extension = ?FTP_EXT_DEFAULT
+ }).
-record(recv_chunk_closing, {
dconn_closed = false,
@@ -136,34 +136,34 @@ start() ->
start_standalone(Options) ->
try
- {ok, StartOptions} = start_options(Options),
- {ok, OpenOptions} = open_options(Options),
- {ok, SocketOptions} = socket_options(Options),
- case start_link(StartOptions, []) of
- {ok, Pid} ->
- call(Pid, {open, ip_comm, OpenOptions, SocketOptions}, plain);
- Error1 ->
- Error1
- end
+ {ok, StartOptions} = start_options(Options),
+ {ok, OpenOptions} = open_options(Options),
+ {ok, SocketOptions} = socket_options(Options),
+ case start_link(StartOptions, []) of
+ {ok, Pid} ->
+ call(Pid, {open, ip_comm, OpenOptions, SocketOptions}, plain);
+ Error1 ->
+ Error1
+ end
catch
- throw:Error2 ->
- Error2
+ throw:Error2 ->
+ Error2
end.
start_service(Options) ->
try
- {ok, StartOptions} = start_options(Options),
- {ok, OpenOptions} = open_options(Options),
- {ok, SocketOptions} = socket_options(Options),
- case ftp_sup:start_child([[[{client, self()} | StartOptions], []]]) of
- {ok, Pid} ->
- call(Pid, {open, ip_comm, OpenOptions, SocketOptions}, plain);
- Error1 ->
- Error1
- end
- catch
- throw:Error2 ->
- Error2
+ {ok, StartOptions} = start_options(Options),
+ {ok, OpenOptions} = open_options(Options),
+ {ok, SocketOptions} = socket_options(Options),
+ case ftp_sup:start_child([[[{client, self()} | StartOptions], []]]) of
+ {ok, Pid} ->
+ call(Pid, {open, ip_comm, OpenOptions, SocketOptions}, plain);
+ Error1 ->
+ Error1
+ end
+ catch
+ throw:Error2 ->
+ Error2
end.
stop() ->
@@ -173,14 +173,14 @@ stop_service(Pid) ->
close(Pid).
services() ->
- [{ftpc, Pid} || {_, Pid, _, _} <-
- supervisor:which_children(ftp_sup)].
+ [{ftpc, Pid} || {_, Pid, _, _} <-
+ supervisor:which_children(ftp_sup)].
service_info(Pid) ->
{ok, Info} = call(Pid, info, list),
- {ok, [proplists:lookup(mode, Info),
- proplists:lookup(local_port, Info),
- proplists:lookup(peer, Info),
- proplists:lookup(peer_port, Info)]}.
+ {ok, [proplists:lookup(mode, Info),
+ proplists:lookup(local_port, Info),
+ proplists:lookup(peer, Info),
+ proplists:lookup(peer_port, Info)]}.
%%%=========================================================================
@@ -189,9 +189,9 @@ service_info(Pid) ->
%%--------------------------------------------------------------------------
%% open(HostOrOtpList, <Port>, <Flags>) -> {ok, Pid} | {error, ehost}
-%% HostOrOtpList = string() | [{option_list, Options}]
-%% Port = integer(),
-%% Flags = [Flag],
+%% HostOrOtpList = string() | [{option_list, Options}]
+%% Port = integer(),
+%% Flags = [Flag],
%% Flag = verbose | debug | trace
%%
%% Description: Start an ftp client and connect to a host.
@@ -203,18 +203,18 @@ service_info(Pid) ->
%% <BACKWARD-COMPATIBILLITY>
open({option_list, Options}) when is_list(Options) ->
try
- {ok, StartOptions} = start_options(Options),
- {ok, OpenOptions} = open_options(Options),
- {ok, SockOpts} = socket_options(Options),
- case ftp_sup:start_child([[[{client, self()} | StartOptions], []]]) of
- {ok, Pid} ->
- call(Pid, {open, ip_comm, OpenOptions, SockOpts}, plain);
- Error1 ->
- Error1
- end
- catch
- throw:Error2 ->
- Error2
+ {ok, StartOptions} = start_options(Options),
+ {ok, OpenOptions} = open_options(Options),
+ {ok, SockOpts} = socket_options(Options),
+ case ftp_sup:start_child([[[{client, self()} | StartOptions], []]]) of
+ {ok, Pid} ->
+ call(Pid, {open, ip_comm, OpenOptions, SockOpts}, plain);
+ Error1 ->
+ Error1
+ end
+ catch
+ throw:Error2 ->
+ Error2
end;
%% </BACKWARD-COMPATIBILLITY>
@@ -231,67 +231,67 @@ open(Host, Port) when is_integer(Port) ->
open(Host, Opts) when is_list(Opts) ->
try
- {ok, StartOptions} = start_options(Opts),
- {ok, OpenOptions} = open_options([{host, Host}|Opts]),
- {ok, SocketOptions} = socket_options(Opts),
- case start_link(StartOptions, []) of
- {ok, Pid} ->
- do_open(Pid, OpenOptions, SocketOptions, tls_options(Opts));
- Error1 ->
- Error1
- end
+ {ok, StartOptions} = start_options(Opts),
+ {ok, OpenOptions} = open_options([{host, Host}|Opts]),
+ {ok, SocketOptions} = socket_options(Opts),
+ case start_link(StartOptions, []) of
+ {ok, Pid} ->
+ do_open(Pid, OpenOptions, SocketOptions, tls_options(Opts));
+ Error1 ->
+ Error1
+ end
catch
- throw:Error2 ->
- Error2
+ throw:Error2 ->
+ Error2
end.
do_open(Pid, OpenOptions, SocketOptions, TLSOpts) ->
case call(Pid, {open, ip_comm, OpenOptions, SocketOptions}, plain) of
- {ok, Pid} ->
- maybe_tls_upgrade(Pid, TLSOpts);
- Error ->
- Error
+ {ok, Pid} ->
+ maybe_tls_upgrade(Pid, TLSOpts);
+ Error ->
+ Error
end.
%%--------------------------------------------------------------------------
-%% user(Pid, User, Pass, <Acc>) -> ok | {error, euser} | {error, econn}
+%% user(Pid, User, Pass, <Acc>) -> ok | {error, euser} | {error, econn}
%% | {error, eacct}
-%% Pid = pid(),
+%% Pid = pid(),
%% User = Pass = Acc = string()
%%
%% Description: Login with or without a supplied account name.
%%--------------------------------------------------------------------------
--spec user(Pid :: pid(),
- User :: string(),
- Pass :: string()) ->
+-spec user(Pid :: pid(),
+ User :: string(),
+ Pass :: string()) ->
'ok' | {'error', Reason :: 'euser' | common_reason()}.
user(Pid, User, Pass) ->
case {is_name_sane(User), is_name_sane(Pass)} of
- {true, true} ->
- call(Pid, {user, User, Pass}, atom);
- _ ->
- {error, euser}
+ {true, true} ->
+ call(Pid, {user, User, Pass}, atom);
+ _ ->
+ {error, euser}
end.
--spec user(Pid :: pid(),
- User :: string(),
- Pass :: string(),
- Acc :: string()) ->
+-spec user(Pid :: pid(),
+ User :: string(),
+ Pass :: string(),
+ Acc :: string()) ->
'ok' | {'error', Reason :: 'euser' | common_reason()}.
user(Pid, User, Pass, Acc) ->
case {is_name_sane(User), is_name_sane(Pass), is_name_sane(Acc)} of
- {true, true, true} ->
- call(Pid, {user, User, Pass, Acc}, atom);
- _ ->
- {error, euser}
+ {true, true, true} ->
+ call(Pid, {user, User, Pass, Acc}, atom);
+ _ ->
+ {error, euser}
end.
%%--------------------------------------------------------------------------
%% account(Pid, Acc) -> ok | {error, eacct}
-%% Pid = pid()
-%% Acc= string()
+%% Pid = pid()
+%% Acc= string()
%%
%% Description: Set a user Account.
%%--------------------------------------------------------------------------
@@ -301,32 +301,32 @@ user(Pid, User, Pass, Acc) ->
account(Pid, Acc) ->
case is_name_sane(Acc) of
- true ->
- call(Pid, {account, Acc}, atom);
- _ ->
- {error, eacct}
+ true ->
+ call(Pid, {account, Acc}, atom);
+ _ ->
+ {error, eacct}
end.
%%--------------------------------------------------------------------------
-%% pwd(Pid) -> {ok, Dir} | {error, elogin} | {error, econn}
-%% Pid = pid()
+%% pwd(Pid) -> {ok, Dir} | {error, elogin} | {error, econn}
+%% Pid = pid()
%% Dir = string()
%%
%% Description: Get the current working directory at remote server.
%%--------------------------------------------------------------------------
-spec pwd(Pid :: pid()) ->
- {'ok', Dir :: string()} |
- {'error', Reason :: restriction_reason() | common_reason()}.
+ {'ok', Dir :: string()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
pwd(Pid) ->
call(Pid, pwd, ctrl).
%%--------------------------------------------------------------------------
-%% lpwd(Pid) -> {ok, Dir}
-%% Pid = pid()
+%% lpwd(Pid) -> {ok, Dir}
+%% Pid = pid()
%% Dir = string()
%%
%% Description: Get the current working directory at local server.
@@ -341,8 +341,8 @@ lpwd(Pid) ->
%%--------------------------------------------------------------------------
%% cd(Pid, Dir) -> ok | {error, epath} | {error, elogin} | {error, econn}
-%% Pid = pid()
-%% Dir = string()
+%% Pid = pid()
+%% Dir = string()
%%
%% Description: Change current working directory at remote server.
%%--------------------------------------------------------------------------
@@ -352,17 +352,17 @@ lpwd(Pid) ->
cd(Pid, Dir) ->
case is_name_sane(Dir) of
- true ->
- call(Pid, {cd, Dir}, atom);
- _ ->
- {error, efnamena}
+ true ->
+ call(Pid, {cd, Dir}, atom);
+ _ ->
+ {error, efnamena}
end.
%%--------------------------------------------------------------------------
%% lcd(Pid, Dir) -> ok | {error, epath}
-%% Pid = pid()
-%% Dir = string()
+%% Pid = pid()
+%% Dir = string()
%%
%% Description: Change current working directory for the local client.
%%--------------------------------------------------------------------------
@@ -377,9 +377,9 @@ lcd(Pid, Dir) ->
%%--------------------------------------------------------------------------
%% ls(Pid) -> Result
%% ls(Pid, <Dir>) -> Result
-%%
-%% Pid = pid()
-%% Dir = string()
+%%
+%% Pid = pid()
+%% Dir = string()
%% Result = {ok, Listing} | {error, Reason}
%% Listing = string()
%% Reason = epath | elogin | econn
@@ -388,31 +388,31 @@ lcd(Pid, Dir) ->
%%--------------------------------------------------------------------------
-spec ls(Pid :: pid()) ->
- {'ok', Listing :: string()} |
- {'error', Reason :: restriction_reason() | common_reason()}.
+ {'ok', Listing :: string()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
ls(Pid) ->
ls(Pid, "").
-spec ls(Pid :: pid(), Dir :: string()) ->
- {'ok', Listing :: string()} |
- {'error', Reason :: restriction_reason() | common_reason()}.
+ {'ok', Listing :: string()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
ls(Pid, Dir) ->
case is_name_sane(Dir) of
- true ->
- call(Pid, {dir, long, Dir}, string);
- _ ->
- {error, efnamena}
+ true ->
+ call(Pid, {dir, long, Dir}, string);
+ _ ->
+ {error, efnamena}
end.
%%--------------------------------------------------------------------------
%% nlist(Pid) -> Result
%% nlist(Pid, Pathname) -> Result
-%%
-%% Pid = pid()
-%% Pathname = string()
+%%
+%% Pid = pid()
+%% Pathname = string()
%% Result = {ok, Listing} | {error, Reason}
%% Listing = string()
%% Reason = epath | elogin | econn
@@ -421,30 +421,30 @@ ls(Pid, Dir) ->
%%--------------------------------------------------------------------------
-spec nlist(Pid :: pid()) ->
- {'ok', Listing :: string()} |
- {'error', Reason :: restriction_reason() | common_reason()}.
+ {'ok', Listing :: string()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
nlist(Pid) ->
nlist(Pid, "").
-spec nlist(Pid :: pid(), Pathname :: string()) ->
- {'ok', Listing :: string()} |
- {'error', Reason :: restriction_reason() | common_reason()}.
+ {'ok', Listing :: string()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
nlist(Pid, Dir) ->
case is_name_sane(Dir) of
- true ->
- call(Pid, {dir, short, Dir}, string);
- _ ->
- {error, efnamena}
+ true ->
+ call(Pid, {dir, short, Dir}, string);
+ _ ->
+ {error, efnamena}
end.
%%--------------------------------------------------------------------------
-%% rename(Pid, Old, New) -> ok | {error, epath} | {error, elogin}
+%% rename(Pid, Old, New) -> ok | {error, epath} | {error, elogin}
%% | {error, econn}
-%% Pid = pid()
-%% CurrFile = NewFile = string()
+%% Pid = pid()
+%% CurrFile = NewFile = string()
%%
%% Description: Rename a file at remote server.
%%--------------------------------------------------------------------------
@@ -454,18 +454,18 @@ nlist(Pid, Dir) ->
rename(Pid, Old, New) ->
case {is_name_sane(Old), is_name_sane(New)} of
- {true, true} ->
- call(Pid, {rename, Old, New}, string);
- _ ->
- {error, efnamena}
+ {true, true} ->
+ call(Pid, {rename, Old, New}, string);
+ _ ->
+ {error, efnamena}
end.
%%--------------------------------------------------------------------------
-%% delete(Pid, File) -> ok | {error, epath} | {error, elogin} |
+%% delete(Pid, File) -> ok | {error, epath} | {error, elogin} |
%% {error, econn}
-%% Pid = pid()
-%% File = string()
+%% Pid = pid()
+%% File = string()
%%
%% Description: Remove file at remote server.
%%--------------------------------------------------------------------------
@@ -475,17 +475,17 @@ rename(Pid, Old, New) ->
delete(Pid, File) ->
case is_name_sane(File) of
- true ->
- call(Pid, {delete, File}, string);
- _ ->
- {error, efnamena}
+ true ->
+ call(Pid, {delete, File}, string);
+ _ ->
+ {error, efnamena}
end.
%%--------------------------------------------------------------------------
%% mkdir(Pid, Dir) -> ok | {error, epath} | {error, elogin} | {error, econn}
-%% Pid = pid(),
-%% Dir = string()
+%% Pid = pid(),
+%% Dir = string()
%%
%% Description: Make directory at remote server.
%%--------------------------------------------------------------------------
@@ -495,17 +495,17 @@ delete(Pid, File) ->
mkdir(Pid, Dir) ->
case is_name_sane(Dir) of
- true ->
- call(Pid, {mkdir, Dir}, atom);
- _ ->
- {error, efnamena}
+ true ->
+ call(Pid, {mkdir, Dir}, atom);
+ _ ->
+ {error, efnamena}
end.
%%--------------------------------------------------------------------------
%% rmdir(Pid, Dir) -> ok | {error, epath} | {error, elogin} | {error, econn}
-%% Pid = pid(),
-%% Dir = string()
+%% Pid = pid(),
+%% Dir = string()
%%
%% Description: Remove directory at remote server.
%%--------------------------------------------------------------------------
@@ -515,24 +515,24 @@ mkdir(Pid, Dir) ->
rmdir(Pid, Dir) ->
case is_name_sane(Dir) of
- true ->
- call(Pid, {rmdir, Dir}, atom);
- _ ->
- {error, efnamena}
+ true ->
+ call(Pid, {rmdir, Dir}, atom);
+ _ ->
+ {error, efnamena}
end.
%%--------------------------------------------------------------------------
%% type(Pid, Type) -> ok | {error, etype} | {error, elogin} | {error, econn}
-%% Pid = pid()
-%% Type = ascii | binary
+%% Pid = pid()
+%% Type = ascii | binary
%%
%% Description: Set transfer type.
%%--------------------------------------------------------------------------
-spec type(Pid :: pid(), Type :: ascii | binary) ->
- 'ok' |
- {'error', Reason :: 'etype' | restriction_reason() | common_reason()}.
+ 'ok' |
+ {'error', Reason :: 'etype' | restriction_reason() | common_reason()}.
type(Pid, Type) ->
call(Pid, {type, Type}, atom).
@@ -541,165 +541,165 @@ type(Pid, Type) ->
%%--------------------------------------------------------------------------
%% recv(Pid, RemoteFileName [, LocalFileName]) -> ok | {error, epath} |
%% {error, elogin} | {error, econn}
-%% Pid = pid()
-%% RemoteFileName = LocalFileName = string()
+%% Pid = pid()
+%% RemoteFileName = LocalFileName = string()
%%
%% Description: Transfer file from remote server.
%%--------------------------------------------------------------------------
-spec recv(Pid :: pid(), RemoteFileName :: string()) ->
- 'ok' | {'error', Reason :: restriction_reason() |
- common_reason() |
+ 'ok' | {'error', Reason :: restriction_reason() |
+ common_reason() |
file_write_error_reason()}.
recv(Pid, RemotFileName) ->
recv(Pid, RemotFileName, RemotFileName).
--spec recv(Pid :: pid(),
- RemoteFileName :: string(),
- LocalFileName :: string()) ->
+-spec recv(Pid :: pid(),
+ RemoteFileName :: string(),
+ LocalFileName :: string()) ->
'ok' | {'error', Reason :: term()}.
recv(Pid, RemotFileName, LocalFileName) ->
case is_name_sane(RemotFileName) of
- true ->
- call(Pid, {recv, RemotFileName, LocalFileName}, atom);
- _ ->
- {error, efnamena}
+ true ->
+ call(Pid, {recv, RemotFileName, LocalFileName}, atom);
+ _ ->
+ {error, efnamena}
end.
%%--------------------------------------------------------------------------
-%% recv_bin(Pid, RemoteFile) -> {ok, Bin} | {error, epath} | {error, elogin}
-%% | {error, econn}
-%% Pid = pid()
-%% RemoteFile = string()
+%% 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.
%%--------------------------------------------------------------------------
--spec recv_bin(Pid :: pid(),
- RemoteFile :: string()) ->
- {'ok', Bin :: binary()} |
- {'error', Reason :: restriction_reason() | common_reason()}.
+-spec recv_bin(Pid :: pid(),
+ RemoteFile :: string()) ->
+ {'ok', Bin :: binary()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
recv_bin(Pid, RemoteFile) ->
case is_name_sane(RemoteFile) of
- true ->
- call(Pid, {recv_bin, RemoteFile}, bin);
- _ ->
- {error, efnamena}
+ true ->
+ call(Pid, {recv_bin, RemoteFile}, bin);
+ _ ->
+ {error, efnamena}
end.
%%--------------------------------------------------------------------------
-%% recv_chunk_start(Pid, RemoteFile) -> ok | {error, elogin} | {error, epath}
+%% recv_chunk_start(Pid, RemoteFile) -> ok | {error, elogin} | {error, epath}
%% | {error, econn}
-%% Pid = pid()
-%% RemoteFile = string()
+%% Pid = pid()
+%% RemoteFile = string()
%%
%% Description: Start receive of chunks of remote file.
%%--------------------------------------------------------------------------
--spec recv_chunk_start(Pid :: pid(),
- RemoteFile :: string()) ->
+-spec recv_chunk_start(Pid :: pid(),
+ RemoteFile :: string()) ->
'ok' | {'error', Reason :: restriction_reason() | common_reason()}.
recv_chunk_start(Pid, RemoteFile) ->
case is_name_sane(RemoteFile) of
- true ->
- call(Pid, {recv_chunk_start, RemoteFile}, atom);
- _ ->
- {error, efnamena}
+ true ->
+ call(Pid, {recv_chunk_start, RemoteFile}, atom);
+ _ ->
+ {error, efnamena}
end.
%%--------------------------------------------------------------------------
%% recv_chunk(Pid, RemoteFile) -> ok | {ok, Bin} | {error, Reason}
-%% Pid = pid()
-%% RemoteFile = string()
+%% Pid = pid()
+%% RemoteFile = string()
%%
%% Description: Transfer file from remote server into binary in chunks
%%--------------------------------------------------------------------------
-spec recv_chunk(Pid :: pid()) ->
- 'ok' |
- {'ok', Bin :: binary()} |
- {'error', Reason :: restriction_reason() | common_reason()}.
+ 'ok' |
+ {'ok', Bin :: binary()} |
+ {'error', Reason :: restriction_reason() | common_reason()}.
recv_chunk(Pid) ->
call(Pid, recv_chunk, atom).
%%--------------------------------------------------------------------------
-%% send(Pid, LocalFileName [, RemotFileName]) -> ok | {error, epath}
-%% | {error, elogin}
+%% send(Pid, LocalFileName [, RemotFileName]) -> ok | {error, epath}
+%% | {error, elogin}
%% | {error, econn}
-%% Pid = pid()
-%% LocalFileName = RemotFileName = string()
+%% Pid = pid()
+%% LocalFileName = RemotFileName = string()
%%
%% Description: Transfer file to remote server.
%%--------------------------------------------------------------------------
-spec send(Pid :: pid(), LocalFileName :: string()) ->
- 'ok' |
- {'error', Reason :: restriction_reason() |
- common_reason() |
+ 'ok' |
+ {'error', Reason :: restriction_reason() |
+ common_reason() |
shortage_reason()}.
send(Pid, LocalFileName) ->
send(Pid, LocalFileName, LocalFileName).
--spec send(Pid :: pid(),
- LocalFileName :: string(),
- RemoteFileName :: string()) ->
- 'ok' |
- {'error', Reason :: restriction_reason() |
- common_reason() |
+-spec send(Pid :: pid(),
+ LocalFileName :: string(),
+ RemoteFileName :: string()) ->
+ 'ok' |
+ {'error', Reason :: restriction_reason() |
+ common_reason() |
shortage_reason()}.
send(Pid, LocalFileName, RemotFileName) ->
case is_name_sane(RemotFileName) of
- true ->
- call(Pid, {send, LocalFileName, RemotFileName}, atom);
- _ ->
- {error, efnamena}
+ true ->
+ call(Pid, {send, LocalFileName, RemotFileName}, atom);
+ _ ->
+ {error, efnamena}
end.
%%--------------------------------------------------------------------------
-%% send_bin(Pid, Bin, RemoteFile) -> ok | {error, epath} | {error, elogin}
+%% send_bin(Pid, Bin, RemoteFile) -> ok | {error, epath} | {error, elogin}
%% | {error, enotbinary} | {error, econn}
-%% Pid = pid()
-%% Bin = binary()
-%% RemoteFile = string()
+%% Pid = pid()
+%% Bin = binary()
+%% RemoteFile = string()
%%
%% Description: Transfer a binary to a remote file.
%%--------------------------------------------------------------------------
-spec send_bin(Pid :: pid(), Bin :: binary(), RemoteFile :: string()) ->
- 'ok' |
- {'error', Reason :: restriction_reason() |
- common_reason() |
+ 'ok' |
+ {'error', Reason :: restriction_reason() |
+ common_reason() |
shortage_reason()}.
send_bin(Pid, Bin, RemoteFile) when is_binary(Bin) ->
case is_name_sane(RemoteFile) of
- true ->
- call(Pid, {send_bin, Bin, RemoteFile}, atom);
- _ ->
- {error, efnamena}
+ true ->
+ call(Pid, {send_bin, Bin, RemoteFile}, atom);
+ _ ->
+ {error, efnamena}
end;
send_bin(_Pid, _Bin, _RemoteFile) ->
{error, enotbinary}.
%%--------------------------------------------------------------------------
-%% send_chunk_start(Pid, RemoteFile) -> ok | {error, elogin} | {error, epath}
+%% send_chunk_start(Pid, RemoteFile) -> ok | {error, elogin} | {error, epath}
%% | {error, econn}
-%% Pid = pid()
-%% RemoteFile = string()
+%% Pid = pid()
+%% RemoteFile = string()
%%
%% Description: Start transfer of chunks to remote file.
%%--------------------------------------------------------------------------
@@ -709,18 +709,18 @@ send_bin(_Pid, _Bin, _RemoteFile) ->
send_chunk_start(Pid, RemoteFile) ->
case is_name_sane(RemoteFile) of
- true ->
- call(Pid, {send_chunk_start, RemoteFile}, atom);
- _ ->
- {error, efnamena}
+ true ->
+ call(Pid, {send_chunk_start, RemoteFile}, atom);
+ _ ->
+ {error, efnamena}
end.
%%--------------------------------------------------------------------------
-%% append_chunk_start(Pid, RemoteFile) -> ok | {error, elogin} |
+%% append_chunk_start(Pid, RemoteFile) -> ok | {error, elogin} |
%% {error, epath} | {error, econn}
-%% Pid = pid()
-%% RemoteFile = string()
+%% Pid = pid()
+%% RemoteFile = string()
%%
%% Description: Start append chunks of data to remote file.
%%--------------------------------------------------------------------------
@@ -730,26 +730,26 @@ send_chunk_start(Pid, RemoteFile) ->
append_chunk_start(Pid, RemoteFile) ->
case is_name_sane(RemoteFile) of
- true ->
- call(Pid, {append_chunk_start, RemoteFile}, atom);
- _ ->
- {error, efnamena}
+ true ->
+ call(Pid, {append_chunk_start, RemoteFile}, atom);
+ _ ->
+ {error, efnamena}
end.
%%--------------------------------------------------------------------------
-%% send_chunk(Pid, Bin) -> ok | {error, elogin} | {error, enotbinary}
+%% send_chunk(Pid, Bin) -> ok | {error, elogin} | {error, enotbinary}
%% | {error, echunk} | {error, econn}
%% Pid = pid()
-%% Bin = binary().
+%% Bin = binary().
%%
%% Purpose: Send chunk to remote file.
%%--------------------------------------------------------------------------
-spec send_chunk(Pid :: pid(), Bin :: binary()) ->
- 'ok' |
- {'error', Reason :: 'echunk' |
- restriction_reason() |
+ 'ok' |
+ {'error', Reason :: 'echunk' |
+ restriction_reason() |
common_reason()}.
send_chunk(Pid, Bin) when is_binary(Bin) ->
@@ -759,18 +759,18 @@ send_chunk(_Pid, _Bin) ->
%%--------------------------------------------------------------------------
-%% append_chunk(Pid, Bin) -> ok | {error, elogin} | {error, enotbinary}
-%% | {error, echunk} | {error, econn}
-%% Pid = pid()
-%% Bin = binary()
+%% append_chunk(Pid, Bin) -> ok | {error, elogin} | {error, enotbinary}
+%% | {error, echunk} | {error, econn}
+%% Pid = pid()
+%% Bin = binary()
%%
%% Description: Append chunk to remote file.
%%--------------------------------------------------------------------------
-spec append_chunk(Pid :: pid(), Bin :: binary()) ->
- 'ok' |
- {'error', Reason :: 'echunk' |
- restriction_reason() |
+ 'ok' |
+ {'error', Reason :: 'echunk' |
+ restriction_reason() |
common_reason()}.
append_chunk(Pid, Bin) when is_binary(Bin) ->
@@ -780,17 +780,17 @@ append_chunk(_Pid, _Bin) ->
%%--------------------------------------------------------------------------
-%% send_chunk_end(Pid) -> ok | {error, elogin} | {error, echunk}
-%% | {error, econn}
-%% Pid = pid()
+%% send_chunk_end(Pid) -> ok | {error, elogin} | {error, echunk}
+%% | {error, econn}
+%% Pid = pid()
%%
%% Description: End sending of chunks to remote file.
%%--------------------------------------------------------------------------
-spec send_chunk_end(Pid :: pid()) ->
- 'ok' |
- {'error', Reason :: restriction_reason() |
- common_reason() |
+ 'ok' |
+ {'error', Reason :: restriction_reason() |
+ common_reason() |
shortage_reason()}.
send_chunk_end(Pid) ->
@@ -798,17 +798,17 @@ send_chunk_end(Pid) ->
%%--------------------------------------------------------------------------
-%% append_chunk_end(Pid) -> ok | {error, elogin} | {error, echunk}
-%% | {error, econn}
-%% Pid = pid()
+%% append_chunk_end(Pid) -> ok | {error, elogin} | {error, echunk}
+%% | {error, econn}
+%% Pid = pid()
%%
%% Description: End appending of chunks to remote file.
%%--------------------------------------------------------------------------
-spec append_chunk_end(Pid :: pid()) ->
- 'ok' |
- {'error', Reason :: restriction_reason() |
- common_reason() |
+ 'ok' |
+ {'error', Reason :: restriction_reason() |
+ common_reason() |
shortage_reason()}.
append_chunk_end(Pid) ->
@@ -816,64 +816,64 @@ append_chunk_end(Pid) ->
%%--------------------------------------------------------------------------
-%% append(Pid, LocalFileName [, RemotFileName]) -> ok | {error, epath}
-%% | {error, elogin}
+%% append(Pid, LocalFileName [, RemotFileName]) -> ok | {error, epath}
+%% | {error, elogin}
%% | {error, econn}
-%% Pid = pid()
-%% LocalFileName = RemotFileName = string()
+%% Pid = pid()
+%% LocalFileName = RemotFileName = string()
%%
%% Description: Append the local file to the remote file
%%--------------------------------------------------------------------------
-spec append(Pid :: pid(), LocalFileName :: string()) ->
- 'ok' |
- {'error', Reason :: 'epath' |
- 'elogin' |
- 'etnospc' |
- 'epnospc' |
+ 'ok' |
+ {'error', Reason :: 'epath' |
+ 'elogin' |
+ 'etnospc' |
+ 'epnospc' |
'efnamena' | common_reason()}.
append(Pid, LocalFileName) ->
append(Pid, LocalFileName, LocalFileName).
--spec append(Pid :: pid(),
- LocalFileName :: string(),
- RemoteFileName :: string()) ->
+-spec append(Pid :: pid(),
+ LocalFileName :: string(),
+ RemoteFileName :: string()) ->
'ok' | {'error', Reason :: term()}.
append(Pid, LocalFileName, RemotFileName) ->
case is_name_sane(RemotFileName) of
- true ->
- call(Pid, {append, LocalFileName, RemotFileName}, atom);
- _ ->
- {error, efnamena}
+ true ->
+ call(Pid, {append, LocalFileName, RemotFileName}, atom);
+ _ ->
+ {error, efnamena}
end.
%%--------------------------------------------------------------------------
-%% append_bin(Pid, Bin, RemoteFile) -> ok | {error, epath} | {error, elogin}
-%% | {error, enotbinary} | {error, econn}
-%% Pid = pid()
-%% Bin = binary()
-%% RemoteFile = string()
+%% append_bin(Pid, Bin, RemoteFile) -> ok | {error, epath} | {error, elogin}
+%% | {error, enotbinary} | {error, econn}
+%% Pid = pid()
+%% Bin = binary()
+%% RemoteFile = string()
%%
%% Purpose: Append a binary to a remote file.
%%--------------------------------------------------------------------------
--spec append_bin(Pid :: pid(),
- Bin :: binary(),
- RemoteFile :: string()) ->
- 'ok' |
- {'error', Reason :: restriction_reason() |
- common_reason() |
+-spec append_bin(Pid :: pid(),
+ Bin :: binary(),
+ RemoteFile :: string()) ->
+ 'ok' |
+ {'error', Reason :: restriction_reason() |
+ common_reason() |
shortage_reason()}.
append_bin(Pid, Bin, RemoteFile) when is_binary(Bin) ->
case is_name_sane(RemoteFile) of
- true ->
- call(Pid, {append_bin, Bin, RemoteFile}, atom);
- _ ->
- {error, efnamena}
+ true ->
+ call(Pid, {append_bin, Bin, RemoteFile}, atom);
+ _ ->
+ {error, efnamena}
end;
append_bin(_Pid, _Bin, _RemoteFile) ->
{error, enotbinary}.
@@ -881,8 +881,8 @@ append_bin(_Pid, _Bin, _RemoteFile) ->
%%--------------------------------------------------------------------------
%% quote(Pid, Cmd) -> list()
-%% Pid = pid()
-%% Cmd = string()
+%% Pid = pid()
+%% Cmd = string()
%%
%% Description: Send arbitrary ftp command.
%%--------------------------------------------------------------------------
@@ -895,7 +895,7 @@ quote(Pid, Cmd) when is_list(Cmd) ->
%%--------------------------------------------------------------------------
%% close(Pid) -> ok
-%% Pid = pid()
+%% Pid = pid()
%%
%% Description: End the ftp session.
%%--------------------------------------------------------------------------
@@ -909,7 +909,7 @@ close(Pid) ->
%%--------------------------------------------------------------------------
%% formaterror(Tag) -> string()
-%% Tag = atom() | {error, atom()}
+%% Tag = atom() | {error, atom()}
%%
%% Description: Return diagnostics.
%%--------------------------------------------------------------------------
@@ -926,7 +926,7 @@ info(Pid) ->
%%--------------------------------------------------------------------------
%% latest_ctrl_response(Pid) -> string()
-%% Pid = pid()
+%% Pid = pid()
%%
%% Description: The latest received response from the server
%%--------------------------------------------------------------------------
@@ -938,7 +938,7 @@ latest_ctrl_response(Pid) ->
%%%========================================================================
-%%% gen_server callback functions
+%%% gen_server callback functions
%%%========================================================================
%%-------------------------------------------------------------------------
@@ -949,34 +949,34 @@ init(Options) ->
process_flag(trap_exit, true),
%% Keep track of the client
- {value, {client, Client}} = lists:keysearch(client, 1, Options),
+ {value, {client, Client}} = lists:keysearch(client, 1, Options),
erlang:monitor(process, Client),
%% Make sure inet is started
_ = inet_db:start(),
-
+
%% Where are we
{ok, Dir} = file:get_cwd(),
%% Maybe activate dbg
case key_search(debug, Options, disable) of
- trace ->
- dbg:tracer(),
- dbg:p(all, [call]),
- {ok, _} = dbg:tpl(ftp, [{'_', [], [{return_trace}]}]),
- {ok, _} = dbg:tpl(ftp_response, [{'_', [], [{return_trace}]}]),
- {ok, _} = dbg:tpl(ftp_progress, [{'_', [], [{return_trace}]}]),
- ok;
- debug ->
- dbg:tracer(),
- dbg:p(all, [call]),
- {ok, _} = dbg:tp(ftp, [{'_', [], [{return_trace}]}]),
- {ok, _} = dbg:tp(ftp_response, [{'_', [], [{return_trace}]}]),
- {ok, _} = dbg:tp(ftp_progress, [{'_', [], [{return_trace}]}]),
- ok;
- _ ->
- %% Keep silent
- ok
+ trace ->
+ dbg:tracer(),
+ dbg:p(all, [call]),
+ {ok, _} = dbg:tpl(ftp, [{'_', [], [{return_trace}]}]),
+ {ok, _} = dbg:tpl(ftp_response, [{'_', [], [{return_trace}]}]),
+ {ok, _} = dbg:tpl(ftp_progress, [{'_', [], [{return_trace}]}]),
+ ok;
+ debug ->
+ dbg:tracer(),
+ dbg:p(all, [call]),
+ {ok, _} = dbg:tp(ftp, [{'_', [], [{return_trace}]}]),
+ {ok, _} = dbg:tp(ftp_response, [{'_', [], [{return_trace}]}]),
+ {ok, _} = dbg:tp(ftp_progress, [{'_', [], [{return_trace}]}]),
+ ok;
+ _ ->
+ %% Keep silent
+ ok
end,
%% Verbose?
@@ -985,11 +985,11 @@ init(Options) ->
%% IpFamily?
IpFamily = key_search(ipfamily, Options, inet),
- State = #state{owner = Client,
- verbose = Verbose,
- ipfamily = IpFamily,
- ldir = Dir},
-
+ State = #state{owner = Client,
+ verbose = Verbose,
+ ipfamily = IpFamily,
+ ldir = Dir},
+
%% Set process prio
Priority = key_search(priority, Options, low),
process_flag(priority, Priority),
@@ -1004,26 +1004,26 @@ init(Options) ->
%% {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, Reply, State} |
-%% Description: Handle incoming requests.
+%% Description: Handle incoming requests.
%%-------------------------------------------------------------------------
%% Anyone can ask this question
handle_call({_, info}, _, #state{verbose = Verbose,
- mode = Mode,
- timeout = Timeout,
- ipfamily = IpFamily,
- csock = Socket,
- progress = Progress} = State) ->
+ mode = Mode,
+ timeout = Timeout,
+ ipfamily = IpFamily,
+ csock = Socket,
+ progress = Progress} = State) ->
{ok, {_, LocalPort}} = sockname(Socket),
{ok, {Address, Port}} = peername(Socket),
- Options = [{verbose, Verbose},
- {ipfamily, IpFamily},
- {mode, Mode},
- {peer, Address},
- {peer_port, Port},
- {local_port, LocalPort},
- {timeout, Timeout},
- {progress, Progress}],
+ Options = [{verbose, Verbose},
+ {ipfamily, IpFamily},
+ {mode, Mode},
+ {peer, Address},
+ {peer_port, Port},
+ {local_port, LocalPort},
+ {timeout, Timeout},
+ {progress, Progress}],
{reply, {ok, Options}, State};
handle_call({_,latest_ctrl_response}, _, #state{latest_ctrl_response=Resp} = State) ->
@@ -1035,91 +1035,91 @@ handle_call({Pid, _}, _, #state{owner = Owner} = State) when Owner =/= Pid ->
handle_call({_, {open, ip_comm, Opts, {CtrlOpts, DataPassOpts, DataActOpts}}}, From, State) ->
case key_search(host, Opts, undefined) of
- undefined ->
- {stop, normal, {error, ehost}, State};
- Host ->
- Mode = key_search(mode, Opts, ?DEFAULT_MODE),
- Port = key_search(port, Opts, ?FTP_PORT),
- Timeout = key_search(timeout, Opts, ?CONNECTION_TIMEOUT),
- DTimeout = key_search(dtimeout, Opts, ?DATA_ACCEPT_TIMEOUT),
- Progress = key_search(progress, Opts, ignore),
- IpFamily = key_search(ipfamily, Opts, inet),
- FtpExt = key_search(ftp_extension, Opts, ?FTP_EXT_DEFAULT),
-
- State2 = State#state{client = From,
- mode = Mode,
- progress = progress(Progress),
- ipfamily = IpFamily,
+ undefined ->
+ {stop, normal, {error, ehost}, State};
+ Host ->
+ Mode = key_search(mode, Opts, ?DEFAULT_MODE),
+ Port = key_search(port, Opts, ?FTP_PORT),
+ Timeout = key_search(timeout, Opts, ?CONNECTION_TIMEOUT),
+ DTimeout = key_search(dtimeout, Opts, ?DATA_ACCEPT_TIMEOUT),
+ Progress = key_search(progress, Opts, ignore),
+ IpFamily = key_search(ipfamily, Opts, inet),
+ FtpExt = key_search(ftp_extension, Opts, ?FTP_EXT_DEFAULT),
+
+ State2 = State#state{client = From,
+ mode = Mode,
+ progress = progress(Progress),
+ ipfamily = IpFamily,
sockopts_ctrl = CtrlOpts,
sockopts_data_passive = DataPassOpts,
sockopts_data_active = DataActOpts,
- dtimeout = DTimeout,
- ftp_extension = FtpExt},
-
- case setup_ctrl_connection(Host, Port, Timeout, State2) of
- {ok, State3, WaitTimeout} ->
- {noreply, State3, WaitTimeout};
- {error, _Reason} ->
- gen_server:reply(From, {error, ehost}),
- {stop, normal, State2#state{client = undefined}}
- end
- end;
+ dtimeout = DTimeout,
+ ftp_extension = FtpExt},
+
+ case setup_ctrl_connection(Host, Port, Timeout, State2) of
+ {ok, State3, WaitTimeout} ->
+ {noreply, State3, WaitTimeout};
+ {error, _Reason} ->
+ gen_server:reply(From, {error, ehost}),
+ {stop, normal, State2#state{client = undefined}}
+ end
+ end;
handle_call({_, {open, tls_upgrade, TLSOptions}}, From, State0) ->
- _ = send_ctrl_message(State0, mk_cmd("AUTH TLS", [])),
+ _ = send_ctrl_message(State0, mk_cmd("AUTH TLS", [])),
State = activate_ctrl_connection(State0),
{noreply, State#state{client = From, caller = open, tls_options = TLSOptions}};
-handle_call({_, {user, User, Password}}, From,
- #state{csock = CSock} = State) when (CSock =/= undefined) ->
+handle_call({_, {user, User, Password}}, From,
+ #state{csock = CSock} = State) when (CSock =/= undefined) ->
handle_user(User, Password, "", State#state{client = From});
-handle_call({_, {user, User, Password, Acc}}, From,
- #state{csock = CSock} = State) when (CSock =/= undefined) ->
+handle_call({_, {user, User, Password, Acc}}, From,
+ #state{csock = CSock} = State) when (CSock =/= undefined) ->
handle_user(User, Password, Acc, State#state{client = From});
-
+
handle_call({_, {account, Acc}}, From, State)->
handle_user_account(Acc, State#state{client = From});
handle_call({_, pwd}, From, #state{chunk = false} = State0) ->
- _ = send_ctrl_message(State0, mk_cmd("PWD", [])),
+ _ = send_ctrl_message(State0, mk_cmd("PWD", [])),
State = activate_ctrl_connection(State0),
{noreply, State#state{client = From, caller = pwd}};
-handle_call({_, lpwd}, From, #state{ldir = LDir} = State) ->
+handle_call({_, lpwd}, From, #state{ldir = LDir} = State) ->
{reply, {ok, LDir}, State#state{client = From}};
-handle_call({_, {cd, Dir}}, From, #state{chunk = false} = State0) ->
- _ = send_ctrl_message(State0, mk_cmd("CWD ~s", [Dir])),
+handle_call({_, {cd, Dir}}, From, #state{chunk = false} = State0) ->
+ _ = send_ctrl_message(State0, mk_cmd("CWD ~s", [Dir])),
State = activate_ctrl_connection(State0),
{noreply, State#state{client = From, caller = cd}};
handle_call({_,{lcd, Dir}}, _From, #state{ldir = LDir0} = State) ->
LDir = filename:absname(Dir, LDir0),
case file:read_file_info(LDir) of %% FIX better check that LDir is a dir.
- {ok, _ } ->
- {reply, ok, State#state{ldir = LDir}};
- _ ->
- {reply, {error, epath}, State}
+ {ok, _ } ->
+ {reply, ok, State#state{ldir = LDir}};
+ _ ->
+ {reply, {error, epath}, State}
end;
-handle_call({_, {dir, Len, Dir}}, {_Pid, _} = From,
- #state{chunk = false} = State) ->
+handle_call({_, {dir, Len, Dir}}, {_Pid, _} = From,
+ #state{chunk = false} = State) ->
setup_data_connection(State#state{caller = {dir, Dir, Len},
- client = From});
+ client = From});
handle_call({_, {rename, CurrFile, NewFile}}, From,
- #state{chunk = false} = State0) ->
+ #state{chunk = false} = State0) ->
_ = send_ctrl_message(State0, mk_cmd("RNFR ~s", [CurrFile])),
State = activate_ctrl_connection(State0),
{noreply, State#state{caller = {rename, NewFile}, client = From}};
-handle_call({_, {delete, File}}, {_Pid, _} = From,
- #state{chunk = false} = State0) ->
+handle_call({_, {delete, File}}, {_Pid, _} = From,
+ #state{chunk = false} = State0) ->
_ = send_ctrl_message(State0, mk_cmd("DELE ~s", [File])),
State = activate_ctrl_connection(State0),
{noreply, State#state{client = From}};
-handle_call({_, {mkdir, Dir}}, From, #state{chunk = false} = State0) ->
+handle_call({_, {mkdir, Dir}}, From, #state{chunk = false} = State0) ->
_ = send_ctrl_message(State0, mk_cmd("MKD ~s", [Dir])),
State = activate_ctrl_connection(State0),
{noreply, State#state{client = From}};
@@ -1129,50 +1129,50 @@ handle_call({_,{rmdir, Dir}}, From, #state{chunk = false} = State0) ->
State = activate_ctrl_connection(State0),
{noreply, State#state{client = From}};
-handle_call({_,{type, Type}}, From, #state{chunk = false} = State0) ->
+handle_call({_,{type, Type}}, From, #state{chunk = false} = State0) ->
case Type of
- ascii ->
- _ = send_ctrl_message(State0, mk_cmd("TYPE A", [])),
- State = activate_ctrl_connection(State0),
- {noreply, State#state{caller = type, type = ascii,
- client = From}};
- binary ->
- _ = send_ctrl_message(State0, mk_cmd("TYPE I", [])),
- State = activate_ctrl_connection(State0),
- {noreply, State#state{caller = type, type = binary,
- client = From}};
- _ ->
- {reply, {error, etype}, State0}
+ ascii ->
+ _ = send_ctrl_message(State0, mk_cmd("TYPE A", [])),
+ State = activate_ctrl_connection(State0),
+ {noreply, State#state{caller = type, type = ascii,
+ client = From}};
+ binary ->
+ _ = send_ctrl_message(State0, mk_cmd("TYPE I", [])),
+ State = activate_ctrl_connection(State0),
+ {noreply, State#state{caller = type, type = binary,
+ client = From}};
+ _ ->
+ {reply, {error, etype}, State0}
end;
-handle_call({_,{recv, RemoteFile, LocalFile}}, From,
- #state{chunk = false, ldir = LocalDir} = State) ->
+handle_call({_,{recv, RemoteFile, LocalFile}}, From,
+ #state{chunk = false, ldir = LocalDir} = State) ->
progress_report({remote_file, RemoteFile}, State),
NewLocalFile = filename:absname(LocalFile, LocalDir),
case file_open(NewLocalFile, write) of
- {ok, Fd} ->
- setup_data_connection(State#state{client = From,
- caller =
- {recv_file,
- RemoteFile, Fd}});
- {error, _What} ->
- {reply, {error, epath}, State}
+ {ok, Fd} ->
+ setup_data_connection(State#state{client = From,
+ caller =
+ {recv_file,
+ RemoteFile, Fd}});
+ {error, _What} ->
+ {reply, {error, epath}, State}
end;
-handle_call({_, {recv_bin, RemoteFile}}, From, #state{chunk = false} =
- State) ->
+handle_call({_, {recv_bin, RemoteFile}}, From, #state{chunk = false} =
+ State) ->
setup_data_connection(State#state{caller = {recv_bin, RemoteFile},
- client = From});
+ client = From});
-handle_call({_,{recv_chunk_start, RemoteFile}}, From, #state{chunk = false}
- = State) ->
+handle_call({_,{recv_chunk_start, RemoteFile}}, From, #state{chunk = false}
+ = State) ->
setup_data_connection(State#state{caller = {start_chunk_transfer,
- "RETR", RemoteFile},
- client = From});
+ "RETR", RemoteFile},
+ client = From});
handle_call({_, recv_chunk}, _, #state{chunk = false} = State) ->
- {reply, {error, "ftp:recv_chunk_start/2 not called"}, State};
+ {reply, {error, "ftp:recv_chunk_start/2 not called"}, State};
handle_call({_, recv_chunk}, _From, #state{chunk = true,
caller = #recv_chunk_closing{dconn_closed = true,
@@ -1185,7 +1185,7 @@ handle_call({_, recv_chunk}, _From, #state{chunk = true,
{reply, ok, State#state{caller = undefined,
chunk = false,
client = undefined}};
-
+
handle_call({_, recv_chunk}, From, #state{chunk = true,
caller = #recv_chunk_closing{} = R
} = State) ->
@@ -1196,41 +1196,41 @@ handle_call({_, recv_chunk}, From, #state{chunk = true,
handle_call({_, recv_chunk}, From, #state{chunk = true} = State0) ->
State = activate_data_connection(State0),
{noreply, State#state{client = From, caller = recv_chunk}};
-
-handle_call({_, {send, LocalFile, RemoteFile}}, From,
- #state{chunk = false, ldir = LocalDir} = State) ->
- progress_report({local_file, filename:absname(LocalFile, LocalDir)},
- State),
+
+handle_call({_, {send, LocalFile, RemoteFile}}, From,
+ #state{chunk = false, ldir = LocalDir} = State) ->
+ progress_report({local_file, filename:absname(LocalFile, LocalDir)},
+ State),
setup_data_connection(State#state{caller = {transfer_file,
- {"STOR",
- LocalFile, RemoteFile}},
- client = From});
-handle_call({_, {append, LocalFile, RemoteFile}}, From,
- #state{chunk = false} = State) ->
+ {"STOR",
+ LocalFile, RemoteFile}},
+ client = From});
+handle_call({_, {append, LocalFile, RemoteFile}}, From,
+ #state{chunk = false} = State) ->
setup_data_connection(State#state{caller = {transfer_file,
- {"APPE",
- LocalFile, RemoteFile}},
- client = From});
-handle_call({_, {send_bin, Bin, RemoteFile}}, From,
- #state{chunk = false} = State) ->
+ {"APPE",
+ LocalFile, RemoteFile}},
+ client = From});
+handle_call({_, {send_bin, Bin, RemoteFile}}, From,
+ #state{chunk = false} = State) ->
setup_data_connection(State#state{caller = {transfer_data,
- {"STOR", Bin, RemoteFile}},
- client = From});
-handle_call({_,{append_bin, Bin, RemoteFile}}, From,
- #state{chunk = false} = State) ->
+ {"STOR", Bin, RemoteFile}},
+ client = From});
+handle_call({_,{append_bin, Bin, RemoteFile}}, From,
+ #state{chunk = false} = State) ->
setup_data_connection(State#state{caller = {transfer_data,
- {"APPE", Bin, RemoteFile}},
- client = From});
-handle_call({_, {send_chunk_start, RemoteFile}}, From, #state{chunk = false}
- = State) ->
+ {"APPE", Bin, RemoteFile}},
+ client = From});
+handle_call({_, {send_chunk_start, RemoteFile}}, From, #state{chunk = false}
+ = State) ->
setup_data_connection(State#state{caller = {start_chunk_transfer,
- "STOR", RemoteFile},
- client = From});
-handle_call({_, {append_chunk_start, RemoteFile}}, From, #state{chunk = false}
- = State) ->
+ "STOR", RemoteFile},
+ client = From});
+handle_call({_, {append_chunk_start, RemoteFile}}, From, #state{chunk = false}
+ = State) ->
setup_data_connection(State#state{caller = {start_chunk_transfer,
- "APPE", RemoteFile},
- client = From});
+ "APPE", RemoteFile},
+ client = From});
handle_call({_, {transfer_chunk, Bin}}, _, #state{chunk = true} = State) ->
send_data_message(State, Bin),
{reply, ok, State};
@@ -1241,8 +1241,8 @@ handle_call({_, {transfer_chunk, _}}, _, #state{chunk = false} = State) ->
handle_call({_, chunk_end}, From, #state{chunk = true} = State0) ->
close_data_connection(State0),
State = activate_ctrl_connection(State0),
- {noreply, State#state{client = From, dsock = undefined,
- caller = end_chunk_transfer, chunk = false}};
+ {noreply, State#state{client = From, dsock = undefined,
+ caller = end_chunk_transfer, chunk = false}};
handle_call({_, chunk_end}, _, #state{chunk = false} = State) ->
{reply, {error, echunk}, State};
@@ -1252,24 +1252,24 @@ handle_call({_, {quote, Cmd}}, From, #state{chunk = false} = State0) ->
State = activate_ctrl_connection(State0),
{noreply, State#state{client = From, caller = quote}};
-handle_call({_, _Req}, _From, #state{csock = CSock} = State)
+handle_call({_, _Req}, _From, #state{csock = CSock} = State)
when (CSock =:= undefined) ->
{reply, {error, not_connected}, State};
handle_call(_, _, #state{chunk = true} = State) ->
{reply, {error, echunk}, State};
-%% Catch all - This can only happen if the application programmer writes
+%% Catch all - This can only happen if the application programmer writes
%% really bad code that violates the API.
handle_call(Request, _Timeout, State) ->
{stop, {'API_violation_connection_closed', Request},
{error, {connection_terminated, 'API_violation'}}, State}.
%%--------------------------------------------------------------------------
-%% handle_cast(Request, State) -> {noreply, State} |
+%% handle_cast(Request, State) -> {noreply, State} |
%% {noreply, State, Timeout} |
-%% {stop, Reason, State}
-%% Description: Handles cast messages.
+%% {stop, Reason, State}
+%% Description: Handles cast messages.
%%-------------------------------------------------------------------------
handle_cast({Pid, close}, #state{owner = Pid} = State) ->
_ = send_ctrl_message(State, mk_cmd("QUIT", [])),
@@ -1279,18 +1279,18 @@ handle_cast({Pid, close}, #state{owner = Pid} = State) ->
handle_cast({Pid, close}, State) ->
Report = io_lib:format("A none owner process ~p tried to close an "
- "ftp connection: ~n", [Pid]),
+ "ftp connection: ~n", [Pid]),
error_logger:info_report(Report),
{noreply, State};
-%% Catch all - This can oly happen if the application programmer writes
+%% Catch all - This can oly happen if the application programmer writes
%% really bad code that violates the API.
handle_cast(Msg, State) ->
{stop, {'API_violation_connection_closed', Msg}, State}.
%%--------------------------------------------------------------------------
%% handle_info(Msg, State) -> {noreply, State} | {noreply, State, Timeout} |
-%% {stop, Reason, State}
+%% {stop, Reason, State}
%% Description: Handles tcp messages from the ftp-server.
%% Note: The order of the function clauses is significant.
%%--------------------------------------------------------------------------
@@ -1302,18 +1302,18 @@ handle_info(timeout, State) ->
{noreply, State};
%%% Data socket messages %%%
-handle_info({Trpt, Socket, Data},
- #state{dsock = {Trpt,Socket},
- caller = {recv_file, Fd}} = State0) when Trpt==tcp;Trpt==ssl ->
+handle_info({Trpt, Socket, Data},
+ #state{dsock = {Trpt,Socket},
+ caller = {recv_file, Fd}} = State0) when Trpt==tcp;Trpt==ssl ->
?DBG('L~p --data ~p ----> ~s~p~n',[?LINE,Socket,Data,State0]),
ok = file_write(binary_to_list(Data), Fd),
progress_report({binary, Data}, State0),
State = activate_data_connection(State0),
{noreply, State};
-handle_info({Trpt, Socket, Data}, #state{dsock = {Trpt,Socket}, client = From,
- caller = recv_chunk}
- = State) when Trpt==tcp;Trpt==ssl ->
+handle_info({Trpt, Socket, Data}, #state{dsock = {Trpt,Socket}, client = From,
+ caller = recv_chunk}
+ = State) when Trpt==tcp;Trpt==ssl ->
?DBG('L~p --data ~p ----> ~s~p~n',[?LINE,Socket,Data,State]),
gen_server:reply(From, {ok, Data}),
{noreply, State#state{client = undefined, data = <<>>}};
@@ -1322,10 +1322,10 @@ handle_info({Trpt, Socket, Data}, #state{dsock = {Trpt,Socket}} = State0) when T
?DBG('L~p --data ~p ----> ~s~p~n',[?LINE,Socket,Data,State0]),
State = activate_data_connection(State0),
{noreply, State#state{data = <<(State#state.data)/binary,
- Data/binary>>}};
+ Data/binary>>}};
handle_info({Cls, Socket}, #state{dsock = {Trpt,Socket},
- caller = {recv_file, Fd}} = State0)
+ caller = {recv_file, Fd}} = State0)
when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
file_close(Fd),
progress_report({transfer_size, 0}, State0),
@@ -1335,7 +1335,7 @@ handle_info({Cls, Socket}, #state{dsock = {Trpt,Socket},
handle_info({Cls, Socket}, #state{dsock = {Trpt,Socket},
client = Client,
- caller = recv_chunk} = State0)
+ caller = recv_chunk} = State0)
when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
?DBG("Data channel close recv_chunk",[]),
State = activate_ctrl_connection(State0),
@@ -1344,81 +1344,81 @@ handle_info({Cls, Socket}, #state{dsock = {Trpt,Socket},
client_called_us = Client =/= undefined}
}};
-handle_info({Cls, Socket}, #state{dsock = {Trpt,Socket}, caller = recv_bin,
- data = Data} = State0)
+handle_info({Cls, Socket}, #state{dsock = {Trpt,Socket}, caller = recv_bin,
+ data = Data} = State0)
when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
?DBG("Data channel close",[]),
State = activate_ctrl_connection(State0),
- {noreply, State#state{dsock = undefined, data = <<>>,
- caller = {recv_bin, Data}}};
+ {noreply, State#state{dsock = undefined, data = <<>>,
+ caller = {recv_bin, Data}}};
handle_info({Cls, Socket}, #state{dsock = {Trpt,Socket}, data = Data,
- caller = {handle_dir_result, Dir}}
- = State0) when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
+ caller = {handle_dir_result, Dir}}
+ = State0) when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
?DBG("Data channel close",[]),
State = activate_ctrl_connection(State0),
- {noreply, State#state{dsock = undefined,
- caller = {handle_dir_result, Dir, Data},
-% data = <<?CR,?LF>>}};
- data = <<>>}};
+ {noreply, State#state{dsock = undefined,
+ caller = {handle_dir_result, Dir, Data},
+% data = <<?CR,?LF>>}};
+ data = <<>>}};
handle_info({Err, Socket, Reason}, #state{dsock = {Trpt,Socket},
- client = From} = State)
+ client = From} = State)
when {Err,Trpt}=={tcp_error,tcp} ; {Err,Trpt}=={ssl_error,ssl} ->
gen_server:reply(From, {error, Reason}),
close_data_connection(State),
{noreply, State#state{dsock = undefined, client = undefined,
- data = <<>>, caller = undefined, chunk = false}};
+ data = <<>>, caller = undefined, chunk = false}};
%%% Ctrl socket messages %%%
-handle_info({Transport, Socket, Data}, #state{csock = {Transport, Socket},
- verbose = Verbose,
- caller = Caller,
- client = From,
- ctrl_data = {BinCtrlData, AccLines,
- LineStatus}}
- = State0) ->
+handle_info({Transport, Socket, Data}, #state{csock = {Transport, Socket},
+ verbose = Verbose,
+ caller = Caller,
+ client = From,
+ ctrl_data = {BinCtrlData, AccLines,
+ LineStatus}}
+ = State0) ->
?DBG('--ctrl ~p ----> ~s~p~n',[Socket,<<BinCtrlData/binary, Data/binary>>,State]),
case ftp_response:parse_lines(<<BinCtrlData/binary, Data/binary>>,
- AccLines, LineStatus) of
- {ok, Lines, NextMsgData} ->
- verbose(Lines, Verbose, 'receive'),
- CtrlResult = ftp_response:interpret(Lines),
- case Caller of
- quote ->
- gen_server:reply(From, string:tokens(Lines, [?CR, ?LF])),
- {noreply, State0#state{client = undefined,
+ AccLines, LineStatus) of
+ {ok, Lines, NextMsgData} ->
+ verbose(Lines, Verbose, 'receive'),
+ CtrlResult = ftp_response:interpret(Lines),
+ case Caller of
+ quote ->
+ gen_server:reply(From, string:tokens(Lines, [?CR, ?LF])),
+ {noreply, State0#state{client = undefined,
caller = undefined,
latest_ctrl_response = Lines,
- ctrl_data = {NextMsgData, [],
+ ctrl_data = {NextMsgData, [],
start}}};
- _ ->
- ?DBG(' ...handle_ctrl_result(~p,...) ctrl_data=~p~n',[CtrlResult,{NextMsgData, [], start}]),
- handle_ctrl_result(CtrlResult,
- State0#state{latest_ctrl_response = Lines,
- ctrl_data =
+ _ ->
+ ?DBG(' ...handle_ctrl_result(~p,...) ctrl_data=~p~n',[CtrlResult,{NextMsgData, [], start}]),
+ handle_ctrl_result(CtrlResult,
+ State0#state{latest_ctrl_response = Lines,
+ ctrl_data =
{NextMsgData, [], start}})
- end;
- {continue, CtrlData} when CtrlData =/= State0#state.ctrl_data ->
- ?DBG(' ...Continue... ctrl_data=~p~n',[CtrlData]),
- State1 = State0#state{ctrl_data = CtrlData},
- State = activate_ctrl_connection(State1),
- {noreply, State};
- {continue, _CtrlData} ->
- ?DBG(' ...Continue... ctrl_data=~p~n',[_CtrlData]),
- {noreply, State0}
+ end;
+ {continue, CtrlData} when CtrlData =/= State0#state.ctrl_data ->
+ ?DBG(' ...Continue... ctrl_data=~p~n',[CtrlData]),
+ State1 = State0#state{ctrl_data = CtrlData},
+ State = activate_ctrl_connection(State1),
+ {noreply, State};
+ {continue, _CtrlData} ->
+ ?DBG(' ...Continue... ctrl_data=~p~n',[_CtrlData]),
+ {noreply, State0}
end;
-%% If the server closes the control channel it is
+%% If the server closes the control channel it is
%% the expected behavior that connection process terminates.
-handle_info({Cls, Socket}, #state{csock = {Trpt, Socket}})
- when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
+handle_info({Cls, Socket}, #state{csock = {Trpt, Socket}})
+ when {Cls,Trpt}=={tcp_closed,tcp} ; {Cls,Trpt}=={ssl_closed,ssl} ->
exit(normal); %% User will get error message from terminate/2
handle_info({Err, Socket, Reason}, _) when Err==tcp_error ; Err==ssl_error ->
- Report =
- io_lib:format("~p on socket: ~p for reason: ~p~n",
- [Err, Socket, Reason]),
+ Report =
+ io_lib:format("~p on socket: ~p for reason: ~p~n",
+ [Err, Socket, Reason]),
error_logger:error_report(Report),
%% If tcp does not work the only option is to terminate,
%% this is the expected behavior under these circumstances.
@@ -1431,26 +1431,26 @@ handle_info({'DOWN', _Ref, _Type, _Process, normal}, State) ->
handle_info({'DOWN', _Ref, _Type, _Process, shutdown}, State) ->
{stop, normal, State#state{client = undefined}};
-
+
handle_info({'DOWN', _Ref, _Type, _Process, timeout}, State) ->
{stop, normal, State#state{client = undefined}};
-
+
handle_info({'DOWN', _Ref, _Type, Process, Reason}, State) ->
{stop, {stopped, {'EXIT', Process, Reason}},
State#state{client = undefined}};
handle_info({'EXIT', Pid, Reason}, #state{progress = Pid} = State) ->
Report = io_lib:format("Progress reporting stopped for reason ~p~n",
- [Reason]),
+ [Reason]),
error_logger:info_report(Report),
{noreply, State#state{progress = ignore}};
-
+
%% Catch all - throws away unknown messages (This could happen by "accident"
%% so we do not want to crash, but we make a log entry as it is an
-%% unwanted behaviour.)
+%% unwanted behaviour.)
handle_info(Info, State) ->
Report = io_lib:format("ftp : ~p : Unexpected message: ~p~nState: ~p~n",
- [self(), Info, State]),
+ [self(), Info, State]),
error_logger:info_report(Report),
{noreply, State}.
@@ -1460,9 +1460,9 @@ handle_info(Info, State) ->
terminate(normal, State) ->
%% If terminate reason =/= normal the progress reporting process will
%% be killed by the exit signal.
- progress_report(stop, State),
+ progress_report(stop, State),
do_terminate({error, econn}, State);
-terminate(Reason, State) ->
+terminate(Reason, State) ->
Report = io_lib:format("Ftp connection closed due to: ~p~n", [Reason]),
error_logger:error_report(Report),
do_terminate({error, eclosed}, State).
@@ -1471,66 +1471,66 @@ do_terminate(ErrorMsg, State) ->
close_data_connection(State),
close_ctrl_connection(State),
case State#state.client of
- undefined ->
- ok;
- From ->
- gen_server:reply(From, ErrorMsg)
+ undefined ->
+ ok;
+ From ->
+ gen_server:reply(From, ErrorMsg)
end,
- ok.
+ ok.
code_change(_Vsn, State1, upgrade_from_pre_5_12) ->
- {state, CSock, DSock, Verbose, LDir, Type, Chunk, Mode, Timeout,
- Data, CtrlData, Owner, Client, Caller, IPv6Disable, Progress} = State1,
- IpFamily =
- if
- (IPv6Disable =:= true) ->
- inet;
- true ->
- inet6fb4
- end,
+ {state, CSock, DSock, Verbose, LDir, Type, Chunk, Mode, Timeout,
+ Data, CtrlData, Owner, Client, Caller, IPv6Disable, Progress} = State1,
+ IpFamily =
+ if
+ (IPv6Disable =:= true) ->
+ inet;
+ true ->
+ inet6fb4
+ end,
State2 = #state{csock = CSock,
- dsock = DSock,
- verbose = Verbose,
- ldir = LDir,
- type = Type,
- chunk = Chunk,
- mode = Mode,
- timeout = Timeout,
- data = Data,
- ctrl_data = CtrlData,
- owner = Owner,
- client = Client,
- caller = Caller,
- ipfamily = IpFamily,
- progress = Progress},
+ dsock = DSock,
+ verbose = Verbose,
+ ldir = LDir,
+ type = Type,
+ chunk = Chunk,
+ mode = Mode,
+ timeout = Timeout,
+ data = Data,
+ ctrl_data = CtrlData,
+ owner = Owner,
+ client = Client,
+ caller = Caller,
+ ipfamily = IpFamily,
+ progress = Progress},
{ok, State2};
code_change(_Vsn, State1, downgrade_to_pre_5_12) ->
#state{csock = CSock,
- dsock = DSock,
- verbose = Verbose,
- ldir = LDir,
- type = Type,
- chunk = Chunk,
- mode = Mode,
- timeout = Timeout,
- data = Data,
- ctrl_data = CtrlData,
- owner = Owner,
- client = Client,
- caller = Caller,
- ipfamily = IpFamily,
- progress = Progress} = State1,
- IPv6Disable =
- if
- (IpFamily =:= inet) ->
- true;
- true ->
- false
- end,
- State2 =
- {state, CSock, DSock, Verbose, LDir, Type, Chunk, Mode, Timeout,
- Data, CtrlData, Owner, Client, Caller, IPv6Disable, Progress},
+ dsock = DSock,
+ verbose = Verbose,
+ ldir = LDir,
+ type = Type,
+ chunk = Chunk,
+ mode = Mode,
+ timeout = Timeout,
+ data = Data,
+ ctrl_data = CtrlData,
+ owner = Owner,
+ client = Client,
+ caller = Caller,
+ ipfamily = IpFamily,
+ progress = Progress} = State1,
+ IPv6Disable =
+ if
+ (IpFamily =:= inet) ->
+ true;
+ true ->
+ false
+ end,
+ State2 =
+ {state, CSock, DSock, Verbose, LDir, Type, Chunk, Mode, Timeout,
+ Data, CtrlData, Owner, Client, Caller, IPv6Disable, Progress},
{ok, State2};
code_change(_Vsn, State, _Extra) ->
@@ -1541,10 +1541,10 @@ code_change(_Vsn, State, _Extra) ->
%% Start/stop
%%%=========================================================================
%%--------------------------------------------------------------------------
-%% start_link([Opts, GenServerOptions]) -> {ok, Pid} | {error, Reason}
-%%
-%% Description: Callback function for the ftp supervisor. It is called
-%% : when start_service/1 calls ftp_sup:start_child/1 to start an
+%% start_link([Opts, GenServerOptions]) -> {ok, Pid} | {error, Reason}
+%%
+%% Description: Callback function for the ftp supervisor. It is called
+%% : when start_service/1 calls ftp_sup:start_child/1 to start an
%% : instance of the ftp process. Also called by start_standalone/1
%%--------------------------------------------------------------------------
start_link([Opts, GenServerOptions]) ->
@@ -1552,12 +1552,12 @@ start_link([Opts, GenServerOptions]) ->
start_link(Opts, GenServerOptions) ->
case lists:keysearch(client, 1, Opts) of
- {value, _} ->
- %% Via the supervisor
- gen_server:start_link(?MODULE, Opts, GenServerOptions);
- false ->
- Opts2 = [{client, self()} | Opts],
- gen_server:start_link(?MODULE, Opts2, GenServerOptions)
+ {value, _} ->
+ %% Via the supervisor
+ gen_server:start_link(?MODULE, Opts, GenServerOptions);
+ false ->
+ Opts2 = [{client, self()} | Opts],
+ gen_server:start_link(?MODULE, Opts2, GenServerOptions)
end.
@@ -1570,7 +1570,7 @@ start_link(Opts, GenServerOptions) ->
%%--------------------------------------------------------------------------
%%% Help functions to handle_call and/or handle_ctrl_result
%%--------------------------------------------------------------------------
-%% User handling
+%% User handling
handle_user(User, Password, Acc, State0) ->
_ = send_ctrl_message(State0, mk_cmd("USER ~s", [User])),
State = activate_ctrl_connection(State0),
@@ -1588,26 +1588,26 @@ handle_user_account(Acc, State0) ->
%%--------------------------------------------------------------------------
-%% handle_ctrl_result
+%% handle_ctrl_result
%%--------------------------------------------------------------------------
handle_ctrl_result({tls_upgrade, _}, #state{csock = {tcp, Socket},
- tls_options = TLSOptions,
- timeout = Timeout,
- caller = open, client = From}
- = State0) ->
+ tls_options = TLSOptions,
+ timeout = Timeout,
+ caller = open, client = From}
+ = State0) ->
?DBG('<--ctrl ssl:connect(~p, ~p)~n~p~n',[Socket,TLSOptions,State0]),
case ssl:connect(Socket, TLSOptions, Timeout) of
- {ok, TLSSocket} ->
- State1 = State0#state{csock = {ssl,TLSSocket}},
- _ = send_ctrl_message(State1, mk_cmd("PBSZ 0", [])),
- State = activate_ctrl_connection(State1),
- {noreply, State#state{tls_upgrading_data_connection = {true, pbsz}} };
- {error, _} = Error ->
- gen_server:reply(From, {Error, self()}),
- {stop, normal, State0#state{client = undefined,
- caller = undefined,
- tls_upgrading_data_connection = false}}
- end;
+ {ok, TLSSocket} ->
+ State1 = State0#state{csock = {ssl,TLSSocket}},
+ _ = send_ctrl_message(State1, mk_cmd("PBSZ 0", [])),
+ State = activate_ctrl_connection(State1),
+ {noreply, State#state{tls_upgrading_data_connection = {true, pbsz}} };
+ {error, _} = Error ->
+ gen_server:reply(From, {Error, self()}),
+ {stop, normal, State0#state{client = undefined,
+ caller = undefined,
+ tls_upgrading_data_connection = false}}
+ end;
handle_ctrl_result({pos_compl, _}, #state{tls_upgrading_data_connection = {true, pbsz}} = State0) ->
_ = send_ctrl_message(State0, mk_cmd("PROT P", [])),
@@ -1615,223 +1615,223 @@ handle_ctrl_result({pos_compl, _}, #state{tls_upgrading_data_connection = {true,
{noreply, State#state{tls_upgrading_data_connection = {true, prot}}};
handle_ctrl_result({pos_compl, _}, #state{tls_upgrading_data_connection = {true, prot},
- client = From} = State) ->
- gen_server:reply(From, {ok, self()}),
+ client = From} = State) ->
+ gen_server:reply(From, {ok, self()}),
+ {noreply, State#state{client = undefined,
+ caller = undefined,
+ tls_upgrading_data_connection = false}};
+
+handle_ctrl_result({pos_compl, _}, #state{caller = open, client = From}
+ = State) ->
+ gen_server:reply(From, {ok, self()}),
{noreply, State#state{client = undefined,
- caller = undefined,
- tls_upgrading_data_connection = false}};
-
-handle_ctrl_result({pos_compl, _}, #state{caller = open, client = From}
- = State) ->
- gen_server:reply(From, {ok, self()}),
- {noreply, State#state{client = undefined,
- caller = undefined }};
+ caller = undefined }};
handle_ctrl_result({_, Lines}, #state{caller = open} = State) ->
ctrl_result_response(econn, State, {error, Lines});
%%--------------------------------------------------------------------------
-%% Data connection setup active mode
-handle_ctrl_result({pos_compl, _Lines},
- #state{mode = active,
- caller = {setup_data_connection,
- {LSock, Caller}}} = State) ->
+%% Data connection setup active mode
+handle_ctrl_result({pos_compl, _Lines},
+ #state{mode = active,
+ caller = {setup_data_connection,
+ {LSock, Caller}}} = State) ->
handle_caller(State#state{caller = Caller, dsock = {lsock, LSock}});
-handle_ctrl_result({Status, _Lines},
- #state{mode = active,
- caller = {setup_data_connection, {LSock, _}}}
- = State) ->
+handle_ctrl_result({Status, _Lines},
+ #state{mode = active,
+ caller = {setup_data_connection, {LSock, _}}}
+ = State) ->
close_connection({tcp,LSock}),
ctrl_result_response(Status, State, {error, Status});
-%% Data connection setup passive mode
-handle_ctrl_result({pos_compl, Lines},
- #state{mode = passive,
- ipfamily = inet6,
- client = From,
- caller = {setup_data_connection, Caller},
- csock = CSock,
+%% Data connection setup passive mode
+handle_ctrl_result({pos_compl, Lines},
+ #state{mode = passive,
+ ipfamily = inet6,
+ client = From,
+ caller = {setup_data_connection, Caller},
+ csock = CSock,
sockopts_data_passive = SockOpts,
- timeout = Timeout}
- = State) ->
+ timeout = Timeout}
+ = State) ->
[_, PortStr | _] = lists:reverse(string:tokens(Lines, "|")),
{ok, {IP, _}} = peername(CSock),
case connect(IP, list_to_integer(PortStr), SockOpts, Timeout, State) of
- {ok, _, Socket} ->
- handle_caller(State#state{caller = Caller, dsock = {tcp, Socket}});
- {error, _Reason} = Error ->
- gen_server:reply(From, Error),
- {noreply, State#state{client = undefined, caller = undefined}}
+ {ok, _, Socket} ->
+ handle_caller(State#state{caller = Caller, dsock = {tcp, Socket}});
+ {error, _Reason} = Error ->
+ gen_server:reply(From, Error),
+ {noreply, State#state{client = undefined, caller = undefined}}
end;
-handle_ctrl_result({pos_compl, Lines},
- #state{mode = passive,
- ipfamily = inet,
- client = From,
- caller = {setup_data_connection, Caller},
- timeout = Timeout,
+handle_ctrl_result({pos_compl, Lines},
+ #state{mode = passive,
+ ipfamily = inet,
+ client = From,
+ caller = {setup_data_connection, Caller},
+ timeout = Timeout,
sockopts_data_passive = SockOpts,
- ftp_extension = false} = State) ->
-
- {_, [?LEFT_PAREN | Rest]} =
- lists:splitwith(fun(?LEFT_PAREN) -> false; (_) -> true end, Lines),
+ ftp_extension = false} = State) ->
+
+ {_, [?LEFT_PAREN | Rest]} =
+ lists:splitwith(fun(?LEFT_PAREN) -> false; (_) -> true end, Lines),
{NewPortAddr, _} =
- lists:splitwith(fun(?RIGHT_PAREN) -> false; (_) -> true end, Rest),
- [A1, A2, A3, A4, P1, P2] =
- lists:map(fun(X) -> list_to_integer(X) end,
- string:tokens(NewPortAddr, [$,])),
- IP = {A1, A2, A3, A4},
- Port = (P1 * 256) + P2,
+ lists:splitwith(fun(?RIGHT_PAREN) -> false; (_) -> true end, Rest),
+ [A1, A2, A3, A4, P1, P2] =
+ lists:map(fun(X) -> list_to_integer(X) end,
+ string:tokens(NewPortAddr, [$,])),
+ IP = {A1, A2, A3, A4},
+ Port = (P1 * 256) + P2,
?DBG('<--data tcp connect to ~p:~p, Caller=~p~n',[IP,Port,Caller]),
case connect(IP, Port, SockOpts, Timeout, State) of
- {ok, _, Socket} ->
- handle_caller(State#state{caller = Caller, dsock = {tcp,Socket}});
- {error, _Reason} = Error ->
- gen_server:reply(From, Error),
- {noreply,State#state{client = undefined, caller = undefined}}
+ {ok, _, Socket} ->
+ handle_caller(State#state{caller = Caller, dsock = {tcp,Socket}});
+ {error, _Reason} = Error ->
+ gen_server:reply(From, Error),
+ {noreply,State#state{client = undefined, caller = undefined}}
end;
-handle_ctrl_result({pos_compl, Lines},
- #state{mode = passive,
- ipfamily = inet,
- client = From,
- caller = {setup_data_connection, Caller},
- csock = CSock,
- timeout = Timeout,
+handle_ctrl_result({pos_compl, Lines},
+ #state{mode = passive,
+ ipfamily = inet,
+ client = From,
+ caller = {setup_data_connection, Caller},
+ csock = CSock,
+ timeout = Timeout,
sockopts_data_passive = SockOpts,
- ftp_extension = true} = State) ->
-
+ ftp_extension = true} = State) ->
+
[_, PortStr | _] = lists:reverse(string:tokens(Lines, "|")),
{ok, {IP, _}} = peername(CSock),
?DBG('<--data tcp connect to ~p:~p, Caller=~p~n',[IP,PortStr,Caller]),
- case connect(IP, list_to_integer(PortStr), SockOpts, Timeout, State) of
- {ok, _, Socket} ->
- handle_caller(State#state{caller = Caller, dsock = {tcp, Socket}});
- {error, _Reason} = Error ->
- gen_server:reply(From, Error),
- {noreply, State#state{client = undefined, caller = undefined}}
+ case connect(IP, list_to_integer(PortStr), SockOpts, Timeout, State) of
+ {ok, _, Socket} ->
+ handle_caller(State#state{caller = Caller, dsock = {tcp, Socket}});
+ {error, _Reason} = Error ->
+ gen_server:reply(From, Error),
+ {noreply, State#state{client = undefined, caller = undefined}}
end;
-
+
%% FTP server does not support passive mode: try to fallback on active mode
-handle_ctrl_result(_,
- #state{mode = passive,
- caller = {setup_data_connection, Caller}} = State) ->
+handle_ctrl_result(_,
+ #state{mode = passive,
+ caller = {setup_data_connection, Caller}} = State) ->
setup_data_connection(State#state{mode = active, caller = Caller});
-
+
%%--------------------------------------------------------------------------
-%% User handling
-handle_ctrl_result({pos_interm, _},
- #state{caller = {handle_user, PassWord, Acc}} = State) ->
+%% User handling
+handle_ctrl_result({pos_interm, _},
+ #state{caller = {handle_user, PassWord, Acc}} = State) ->
handle_user_passwd(PassWord, Acc, State);
-handle_ctrl_result({Status, _},
- #state{caller = {handle_user, _, _}} = State) ->
+handle_ctrl_result({Status, _},
+ #state{caller = {handle_user, _, _}} = State) ->
ctrl_result_response(Status, State, {error, euser});
-%% Accounts
-handle_ctrl_result({pos_interm_acct, _},
- #state{caller = {handle_user_passwd, Acc}} = State)
+%% Accounts
+handle_ctrl_result({pos_interm_acct, _},
+ #state{caller = {handle_user_passwd, Acc}} = State)
when Acc =/= "" ->
handle_user_account(Acc, State);
handle_ctrl_result({Status, _},
- #state{caller = {handle_user_passwd, _}} = State) ->
+ #state{caller = {handle_user_passwd, _}} = State) ->
ctrl_result_response(Status, State, {error, euser});
%%--------------------------------------------------------------------------
%% Print current working directory
-handle_ctrl_result({pos_compl, Lines},
- #state{caller = pwd, client = From} = State) ->
+handle_ctrl_result({pos_compl, Lines},
+ #state{caller = pwd, client = From} = State) ->
Dir = pwd_result(Lines),
gen_server:reply(From, {ok, Dir}),
{noreply, State#state{client = undefined, caller = undefined}};
%%--------------------------------------------------------------------------
-%% Directory listing
+%% Directory listing
handle_ctrl_result({pos_prel, _}, #state{caller = {dir, Dir}} = State0) ->
case accept_data_connection(State0) of
- {ok, State1} ->
- State = activate_data_connection(State1),
- {noreply, State#state{caller = {handle_dir_result, Dir}}};
- {error, _Reason} = ERROR ->
- case State0#state.client of
- undefined ->
- {stop, ERROR, State0};
- From ->
- gen_server:reply(From, ERROR),
- {stop, normal, State0#state{client = undefined}}
- end
+ {ok, State1} ->
+ State = activate_data_connection(State1),
+ {noreply, State#state{caller = {handle_dir_result, Dir}}};
+ {error, _Reason} = ERROR ->
+ case State0#state.client of
+ undefined ->
+ {stop, ERROR, State0};
+ From ->
+ gen_server:reply(From, ERROR),
+ {stop, normal, State0#state{client = undefined}}
+ end
end;
handle_ctrl_result({pos_compl, _}, #state{caller = {handle_dir_result, Dir,
- Data}, client = From}
- = State) ->
+ Data}, client = From}
+ = State) ->
case Dir of
- "" -> % Current directory
- gen_server:reply(From, {ok, Data}),
- {noreply, State#state{client = undefined,
- caller = undefined}};
- _ ->
- %% <WTF>
- %% Dir cannot be assumed to be a dir. It is a string that
- %% could be a dir, but could also be a file or even a string
- %% containing wildcards (*).
- %%
- %% %% If there is only one line it might be a directory with one
- %% %% file but it might be an error message that the directory
- %% %% was not found. So in this case we have to endure a little
- %% %% overhead to be able to give a good return value. Alas not
- %% %% all ftp implementations behave the same and returning
- %% %% an error string is allowed by the FTP RFC.
- %% case lists:dropwhile(fun(?CR) -> false;(_) -> true end,
- %% binary_to_list(Data)) of
- %% L when (L =:= [?CR, ?LF]) orelse (L =:= []) ->
- %% send_ctrl_message(State, mk_cmd("PWD", [])),
- %% activate_ctrl_connection(State),
- %% {noreply,
- %% State#state{caller = {handle_dir_data, Dir, Data}}};
- %% _ ->
- %% gen_server:reply(From, {ok, Data}),
- %% {noreply, State#state{client = undefined,
- %% caller = undefined}}
- %% end
- %% </WTF>
- gen_server:reply(From, {ok, Data}),
- {noreply, State#state{client = undefined,
- caller = undefined}}
+ "" -> % Current directory
+ gen_server:reply(From, {ok, Data}),
+ {noreply, State#state{client = undefined,
+ caller = undefined}};
+ _ ->
+ %% <WTF>
+ %% Dir cannot be assumed to be a dir. It is a string that
+ %% could be a dir, but could also be a file or even a string
+ %% containing wildcards (*).
+ %%
+ %% %% If there is only one line it might be a directory with one
+ %% %% file but it might be an error message that the directory
+ %% %% was not found. So in this case we have to endure a little
+ %% %% overhead to be able to give a good return value. Alas not
+ %% %% all ftp implementations behave the same and returning
+ %% %% an error string is allowed by the FTP RFC.
+ %% case lists:dropwhile(fun(?CR) -> false;(_) -> true end,
+ %% binary_to_list(Data)) of
+ %% L when (L =:= [?CR, ?LF]) orelse (L =:= []) ->
+ %% send_ctrl_message(State, mk_cmd("PWD", [])),
+ %% activate_ctrl_connection(State),
+ %% {noreply,
+ %% State#state{caller = {handle_dir_data, Dir, Data}}};
+ %% _ ->
+ %% gen_server:reply(From, {ok, Data}),
+ %% {noreply, State#state{client = undefined,
+ %% caller = undefined}}
+ %% end
+ %% </WTF>
+ gen_server:reply(From, {ok, Data}),
+ {noreply, State#state{client = undefined,
+ caller = undefined}}
end;
-handle_ctrl_result({pos_compl, Lines},
- #state{caller = {handle_dir_data, Dir, DirData}} =
- State0) ->
- OldDir = pwd_result(Lines),
+handle_ctrl_result({pos_compl, Lines},
+ #state{caller = {handle_dir_data, Dir, DirData}} =
+ State0) ->
+ OldDir = pwd_result(Lines),
_ = send_ctrl_message(State0, mk_cmd("CWD ~s", [Dir])),
State = activate_ctrl_connection(State0),
{noreply, State#state{caller = {handle_dir_data_second_phase, OldDir,
- DirData}}};
+ DirData}}};
handle_ctrl_result({Status, _},
- #state{caller = {handle_dir_data, _, _}} = State) ->
+ #state{caller = {handle_dir_data, _, _}} = State) ->
ctrl_result_response(Status, State, {error, epath});
handle_ctrl_result(S={_Status, _},
- #state{caller = {handle_dir_result, _, _}} = State) ->
+ #state{caller = {handle_dir_result, _, _}} = State) ->
%% OTP-5731, macosx
ctrl_result_response(S, State, {error, epath});
handle_ctrl_result({pos_compl, _},
- #state{caller = {handle_dir_data_second_phase, OldDir,
- DirData}} = State0) ->
+ #state{caller = {handle_dir_data_second_phase, OldDir,
+ DirData}} = State0) ->
_ = send_ctrl_message(State0, mk_cmd("CWD ~s", [OldDir])),
State = activate_ctrl_connection(State0),
{noreply, State#state{caller = {handle_dir_data_third_phase, DirData}}};
-handle_ctrl_result({Status, _},
- #state{caller = {handle_dir_data_second_phase, _, _}}
- = State) ->
+handle_ctrl_result({Status, _},
+ #state{caller = {handle_dir_data_second_phase, _, _}}
+ = State) ->
ctrl_result_response(Status, State, {error, epath});
handle_ctrl_result(_, #state{caller = {handle_dir_data_third_phase, DirData},
- client = From} = State) ->
+ client = From} = State) ->
gen_server:reply(From, {ok, DirData}),
{noreply, State#state{client = undefined, caller = undefined}};
@@ -1843,69 +1843,69 @@ handle_ctrl_result(Status={epath, _}, #state{caller = {dir,_}} = State) ->
%%--------------------------------------------------------------------------
%% File renaming
-handle_ctrl_result({pos_interm, _}, #state{caller = {rename, NewFile}}
- = State0) ->
+handle_ctrl_result({pos_interm, _}, #state{caller = {rename, NewFile}}
+ = State0) ->
_ = send_ctrl_message(State0, mk_cmd("RNTO ~s", [NewFile])),
State = activate_ctrl_connection(State0),
- {noreply, State#state{caller = rename_second_phase}};
+ {noreply, State#state{caller = rename_second_phase}};
-handle_ctrl_result({Status, _},
- #state{caller = {rename, _}} = State) ->
+handle_ctrl_result({Status, _},
+ #state{caller = {rename, _}} = State) ->
ctrl_result_response(Status, State, {error, Status});
handle_ctrl_result({Status, _},
- #state{caller = rename_second_phase} = State) ->
+ #state{caller = rename_second_phase} = State) ->
ctrl_result_response(Status, State, {error, Status});
%%--------------------------------------------------------------------------
%% File handling - recv_bin
handle_ctrl_result({pos_prel, _}, #state{caller = recv_bin} = State0) ->
case accept_data_connection(State0) of
- {ok, State1} ->
- State = activate_data_connection(State1),
- {noreply, State};
- {error, _Reason} = ERROR ->
- case State0#state.client of
- undefined ->
- {stop, ERROR, State0};
- From ->
- gen_server:reply(From, ERROR),
- {stop, normal, State0#state{client = undefined}}
- end
+ {ok, State1} ->
+ State = activate_data_connection(State1),
+ {noreply, State};
+ {error, _Reason} = ERROR ->
+ case State0#state.client of
+ undefined ->
+ {stop, ERROR, State0};
+ From ->
+ gen_server:reply(From, ERROR),
+ {stop, normal, State0#state{client = undefined}}
+ end
end;
handle_ctrl_result({pos_compl, _}, #state{caller = {recv_bin, Data},
- client = From} = State) ->
+ client = From} = State) ->
gen_server:reply(From, {ok, Data}),
close_data_connection(State),
{noreply, State#state{client = undefined, caller = undefined}};
handle_ctrl_result({Status, _}, #state{caller = recv_bin} = State) ->
close_data_connection(State),
- ctrl_result_response(Status, State#state{dsock = undefined},
- {error, epath});
+ ctrl_result_response(Status, State#state{dsock = undefined},
+ {error, epath});
handle_ctrl_result({Status, _}, #state{caller = {recv_bin, _}} = State) ->
close_data_connection(State),
- ctrl_result_response(Status, State#state{dsock = undefined},
- {error, epath});
+ ctrl_result_response(Status, State#state{dsock = undefined},
+ {error, epath});
%%--------------------------------------------------------------------------
%% File handling - start_chunk_transfer
handle_ctrl_result({pos_prel, _}, #state{client = From,
- caller = start_chunk_transfer}
- = State0) ->
+ caller = start_chunk_transfer}
+ = State0) ->
case accept_data_connection(State0) of
- {ok, State1} ->
- State = start_chunk(State1),
- {noreply, State};
- {error, _Reason} = ERROR ->
- case State0#state.client of
- undefined ->
- {stop, ERROR, State0};
- From ->
- gen_server:reply(From, ERROR),
- {stop, normal, State0#state{client = undefined}}
- end
+ {ok, State1} ->
+ State = start_chunk(State1),
+ {noreply, State};
+ {error, _Reason} = ERROR ->
+ case State0#state.client of
+ undefined ->
+ {stop, ERROR, State0};
+ From ->
+ gen_server:reply(From, ERROR),
+ {stop, normal, State0#state{client = undefined}}
+ end
end;
%%--------------------------------------------------------------------------
@@ -1916,7 +1916,7 @@ handle_ctrl_result({pos_compl, _}, #state{client = From,
client_called_us = true,
pos_compl_received = false
}}
- = State0) when From =/= undefined ->
+ = State0) when From =/= undefined ->
%% The pos_compl was the last event we waited for, finnish and clean up
?DBG("recv_chunk_closing pos_compl, last event",[]),
gen_server:reply(From, ok),
@@ -1926,7 +1926,7 @@ handle_ctrl_result({pos_compl, _}, #state{client = From,
client = undefined}};
handle_ctrl_result({pos_compl, _}, #state{caller = #recv_chunk_closing{}=R}
- = State0) ->
+ = State0) ->
%% Waiting for more, don't care what
?DBG("recv_chunk_closing pos_compl, wait more",[]),
{noreply, State0#state{caller = R#recv_chunk_closing{pos_compl_received=true}}};
@@ -1936,59 +1936,59 @@ handle_ctrl_result({pos_compl, _}, #state{caller = #recv_chunk_closing{}=R}
%% File handling - recv_file
handle_ctrl_result({pos_prel, _}, #state{caller = {recv_file, _}} = State0) ->
case accept_data_connection(State0) of
- {ok, State1} ->
- State = activate_data_connection(State1),
- {noreply, State};
- {error, _Reason} = ERROR ->
- case State0#state.client of
- undefined ->
- {stop, ERROR, State0};
- From ->
- gen_server:reply(From, ERROR),
- {stop, normal, State0#state{client = undefined}}
- end
+ {ok, State1} ->
+ State = activate_data_connection(State1),
+ {noreply, State};
+ {error, _Reason} = ERROR ->
+ case State0#state.client of
+ undefined ->
+ {stop, ERROR, State0};
+ From ->
+ gen_server:reply(From, ERROR),
+ {stop, normal, State0#state{client = undefined}}
+ end
end;
handle_ctrl_result({Status, _}, #state{caller = {recv_file, Fd}} = State) ->
file_close(Fd),
close_data_connection(State),
- ctrl_result_response(Status, State#state{dsock = undefined},
- {error, epath});
+ ctrl_result_response(Status, State#state{dsock = undefined},
+ {error, epath});
%%--------------------------------------------------------------------------
%% File handling - transfer_*
-handle_ctrl_result({pos_prel, _}, #state{caller = {transfer_file, Fd}}
- = State0) ->
+handle_ctrl_result({pos_prel, _}, #state{caller = {transfer_file, Fd}}
+ = State0) ->
case accept_data_connection(State0) of
- {ok, State1} ->
- send_file(State1, Fd);
- {error, _Reason} = ERROR ->
- case State0#state.client of
- undefined ->
- {stop, ERROR, State0};
- From ->
- gen_server:reply(From, ERROR),
- {stop, normal, State0#state{client = undefined}}
- end
+ {ok, State1} ->
+ send_file(State1, Fd);
+ {error, _Reason} = ERROR ->
+ case State0#state.client of
+ undefined ->
+ {stop, ERROR, State0};
+ From ->
+ gen_server:reply(From, ERROR),
+ {stop, normal, State0#state{client = undefined}}
+ end
end;
-handle_ctrl_result({pos_prel, _}, #state{caller = {transfer_data, Bin}}
- = State0) ->
+handle_ctrl_result({pos_prel, _}, #state{caller = {transfer_data, Bin}}
+ = State0) ->
case accept_data_connection(State0) of
- {ok, State} ->
- send_bin(State, Bin);
- {error, _Reason} = ERROR ->
- case State0#state.client of
- undefined ->
- {stop, ERROR, State0};
- From ->
- gen_server:reply(From, ERROR),
- {stop, normal, State0#state{client = undefined}}
- end
+ {ok, State} ->
+ send_bin(State, Bin);
+ {error, _Reason} = ERROR ->
+ case State0#state.client of
+ undefined ->
+ {stop, ERROR, State0};
+ From ->
+ gen_server:reply(From, ERROR),
+ {stop, normal, State0#state{client = undefined}}
+ end
end;
%%--------------------------------------------------------------------------
%% Default
-handle_ctrl_result({Status, _Lines}, #state{client = From} = State)
+handle_ctrl_result({Status, _Lines}, #state{client = From} = State)
when From =/= undefined ->
ctrl_result_response(Status, State, {error, Status}).
@@ -2003,10 +2003,10 @@ ctrl_result_response(enofile, #state{client = From} = State, _) ->
gen_server:reply(From, {error, enofile}),
{noreply, State#state{client = undefined, caller = undefined}};
-ctrl_result_response(Status, #state{client = From} = State, _)
- when (Status =:= etnospc) orelse
- (Status =:= epnospc) orelse
- (Status =:= efnamena) orelse
+ctrl_result_response(Status, #state{client = From} = State, _)
+ when (Status =:= etnospc) orelse
+ (Status =:= epnospc) orelse
+ (Status =:= efnamena) orelse
(Status =:= econn) ->
gen_server:reply(From, {error, Status}),
%% {stop, normal, {error, Status}, State#state{client = undefined}};
@@ -2019,9 +2019,9 @@ ctrl_result_response(_, #state{client = From} = State, ErrorMsg) ->
%%--------------------------------------------------------------------------
handle_caller(#state{caller = {dir, Dir, Len}} = State0) ->
Cmd = case Len of
- short -> "NLST";
- long -> "LIST"
- end,
+ short -> "NLST";
+ long -> "LIST"
+ end,
_ = case Dir of
"" ->
send_ctrl_message(State0, mk_cmd(Cmd, ""));
@@ -2030,89 +2030,89 @@ handle_caller(#state{caller = {dir, Dir, Len}} = State0) ->
end,
State = activate_ctrl_connection(State0),
{noreply, State#state{caller = {dir, Dir}}};
-
+
handle_caller(#state{caller = {recv_bin, RemoteFile}} = State0) ->
_ = send_ctrl_message(State0, mk_cmd("RETR ~s", [RemoteFile])),
State = activate_ctrl_connection(State0),
{noreply, State#state{caller = recv_bin}};
-handle_caller(#state{caller = {start_chunk_transfer, Cmd, RemoteFile}} =
- State0) ->
+handle_caller(#state{caller = {start_chunk_transfer, Cmd, RemoteFile}} =
+ State0) ->
_ = send_ctrl_message(State0, mk_cmd("~s ~s", [Cmd, RemoteFile])),
State = activate_ctrl_connection(State0),
{noreply, State#state{caller = start_chunk_transfer}};
handle_caller(#state{caller = {recv_file, RemoteFile, Fd}} = State0) ->
- _ = send_ctrl_message(State0, mk_cmd("RETR ~s", [RemoteFile])),
+ _ = send_ctrl_message(State0, mk_cmd("RETR ~s", [RemoteFile])),
State = activate_ctrl_connection(State0),
{noreply, State#state{caller = {recv_file, Fd}}};
handle_caller(#state{caller = {transfer_file, {Cmd, LocalFile, RemoteFile}},
- ldir = LocalDir, client = From} = State0) ->
+ ldir = LocalDir, client = From} = State0) ->
case file_open(filename:absname(LocalFile, LocalDir), read) of
- {ok, Fd} ->
- _ = send_ctrl_message(State0, mk_cmd("~s ~s", [Cmd, RemoteFile])),
- State = activate_ctrl_connection(State0),
- {noreply, State#state{caller = {transfer_file, Fd}}};
- {error, _} ->
- gen_server:reply(From, {error, epath}),
- {noreply, State0#state{client = undefined, caller = undefined,
- dsock = undefined}}
+ {ok, Fd} ->
+ _ = send_ctrl_message(State0, mk_cmd("~s ~s", [Cmd, RemoteFile])),
+ State = activate_ctrl_connection(State0),
+ {noreply, State#state{caller = {transfer_file, Fd}}};
+ {error, _} ->
+ gen_server:reply(From, {error, epath}),
+ {noreply, State0#state{client = undefined, caller = undefined,
+ dsock = undefined}}
end;
-handle_caller(#state{caller = {transfer_data, {Cmd, Bin, RemoteFile}}} =
- State0) ->
+handle_caller(#state{caller = {transfer_data, {Cmd, Bin, RemoteFile}}} =
+ State0) ->
_ = send_ctrl_message(State0, mk_cmd("~s ~s", [Cmd, RemoteFile])),
State = activate_ctrl_connection(State0),
{noreply, State#state{caller = {transfer_data, Bin}}}.
-%% ----------- FTP SERVER COMMUNICATION -------------------------
+%% ----------- FTP SERVER COMMUNICATION -------------------------
-%% Connect to FTP server at Host (default is TCP port 21)
+%% Connect to FTP server at Host (default is TCP port 21)
%% in order to establish a control connection.
setup_ctrl_connection(Host, Port, Timeout, #state{sockopts_ctrl = SockOpts} = State0) ->
MsTime = erlang:monotonic_time(),
case connect(Host, Port, SockOpts, Timeout, State0) of
- {ok, IpFam, CSock} ->
- State1 = State0#state{csock = {tcp, CSock}, ipfamily = IpFam},
- State = activate_ctrl_connection(State1),
- case Timeout - millisec_passed(MsTime) of
- Timeout2 when (Timeout2 >= 0) ->
- {ok, State#state{caller = open}, Timeout2};
- _ ->
+ {ok, IpFam, CSock} ->
+ State1 = State0#state{csock = {tcp, CSock}, ipfamily = IpFam},
+ State = activate_ctrl_connection(State1),
+ case Timeout - millisec_passed(MsTime) of
+ Timeout2 when (Timeout2 >= 0) ->
+ {ok, State#state{caller = open}, Timeout2};
+ _ ->
%% Oups: Simulate timeout
- {ok, State#state{caller = open}, 0}
- end;
- Error ->
- Error
+ {ok, State#state{caller = open}, 0}
+ end;
+ Error ->
+ Error
end.
-setup_data_connection(#state{mode = active,
- caller = Caller,
- csock = CSock,
+setup_data_connection(#state{mode = active,
+ caller = Caller,
+ csock = CSock,
sockopts_data_active = SockOpts,
- ftp_extension = FtpExt} = State0) ->
+ ftp_extension = FtpExt} = State0) ->
case (catch sockname(CSock)) of
- {ok, {{_, _, _, _, _, _, _, _} = IP0, _}} ->
+ {ok, {{_, _, _, _, _, _, _, _} = IP0, _}} ->
IP = proplists:get_value(ip, SockOpts, IP0),
- {ok, LSock} =
- gen_tcp:listen(0, [{ip, IP}, {active, false},
- inet6, binary, {packet, 0} |
+ {ok, LSock} =
+ gen_tcp:listen(0, [{ip, IP}, {active, false},
+ inet6, binary, {packet, 0} |
lists:keydelete(ip,1,SockOpts)]),
- {ok, {_, Port}} = sockname({tcp,LSock}),
- IpAddress = inet_parse:ntoa(IP),
- Cmd = mk_cmd("EPRT |2|~s|~p|", [IpAddress, Port]),
- _ = send_ctrl_message(State0, Cmd),
- State = activate_ctrl_connection(State0),
- {noreply, State#state{caller = {setup_data_connection,
- {LSock, Caller}}}};
- {ok, {{_,_,_,_} = IP0, _}} ->
+ {ok, {_, Port}} = sockname({tcp,LSock}),
+ IpAddress = inet_parse:ntoa(IP),
+ Cmd = mk_cmd("EPRT |2|~s|~p|", [IpAddress, Port]),
+ _ = send_ctrl_message(State0, Cmd),
+ State = activate_ctrl_connection(State0),
+ {noreply, State#state{caller = {setup_data_connection,
+ {LSock, Caller}}}};
+ {ok, {{_,_,_,_} = IP0, _}} ->
IP = proplists:get_value(ip, SockOpts, IP0),
- {ok, LSock} = gen_tcp:listen(0, [{ip, IP}, {active, false},
- binary, {packet, 0} |
+ {ok, LSock} = gen_tcp:listen(0, [{ip, IP}, {active, false},
+ binary, {packet, 0} |
lists:keydelete(ip,1,SockOpts)]),
- {ok, Port} = inet:port(LSock),
- _ = case FtpExt of
+ {ok, Port} = inet:port(LSock),
+ _ = case FtpExt of
false ->
{IP1, IP2, IP3, IP4} = IP,
{Port1, Port2} = {Port div 256, Port rem 256},
@@ -2124,27 +2124,27 @@ setup_data_connection(#state{mode = active,
Cmd = mk_cmd("EPRT |1|~s|~p|", [IpAddress, Port]),
send_ctrl_message(State0, Cmd)
end,
- State = activate_ctrl_connection(State0),
- {noreply, State#state{caller = {setup_data_connection,
- {LSock, Caller}}}}
+ State = activate_ctrl_connection(State0),
+ {noreply, State#state{caller = {setup_data_connection,
+ {LSock, Caller}}}}
end;
setup_data_connection(#state{mode = passive, ipfamily = inet6,
- caller = Caller} = State0) ->
+ caller = Caller} = State0) ->
_ = send_ctrl_message(State0, mk_cmd("EPSV", [])),
State = activate_ctrl_connection(State0),
{noreply, State#state{caller = {setup_data_connection, Caller}}};
setup_data_connection(#state{mode = passive, ipfamily = inet,
- caller = Caller,
- ftp_extension = false} = State0) ->
+ caller = Caller,
+ ftp_extension = false} = State0) ->
_ = send_ctrl_message(State0, mk_cmd("PASV", [])),
State = activate_ctrl_connection(State0),
- {noreply, State#state{caller = {setup_data_connection, Caller}}};
+ {noreply, State#state{caller = {setup_data_connection, Caller}}};
setup_data_connection(#state{mode = passive, ipfamily = inet,
- caller = Caller,
- ftp_extension = true} = State0) ->
+ caller = Caller,
+ ftp_extension = true} = State0) ->
_ = send_ctrl_message(State0, mk_cmd("EPSV", [])),
State = activate_ctrl_connection(State0),
{noreply, State#state{caller = {setup_data_connection, Caller}}}.
@@ -2157,76 +2157,76 @@ connect(Host, Port, SockOpts, Timeout, #state{ipfamily = inet6 = IpFam}) ->
connect(Host, Port, SockOpts, Timeout, #state{ipfamily = inet6fb4}) ->
case inet:getaddr(Host, inet6) of
- {ok, {0, 0, 0, 0, 0, 16#ffff, _, _} = IPv6} ->
- case inet:getaddr(Host, inet) of
- {ok, IPv4} ->
- IpFam = inet,
- connect2(IPv4, Port, IpFam, SockOpts, Timeout);
-
- _ ->
- IpFam = inet6,
- connect2(IPv6, Port, IpFam, SockOpts, Timeout)
- end;
-
- {ok, IPv6} ->
- IpFam = inet6,
- connect2(IPv6, Port, IpFam, SockOpts, Timeout);
-
- _ ->
- case inet:getaddr(Host, inet) of
- {ok, IPv4} ->
- IpFam = inet,
- connect2(IPv4, Port, IpFam, SockOpts, Timeout);
- Error ->
- Error
- end
+ {ok, {0, 0, 0, 0, 0, 16#ffff, _, _} = IPv6} ->
+ case inet:getaddr(Host, inet) of
+ {ok, IPv4} ->
+ IpFam = inet,
+ connect2(IPv4, Port, IpFam, SockOpts, Timeout);
+
+ _ ->
+ IpFam = inet6,
+ connect2(IPv6, Port, IpFam, SockOpts, Timeout)
+ end;
+
+ {ok, IPv6} ->
+ IpFam = inet6,
+ connect2(IPv6, Port, IpFam, SockOpts, Timeout);
+
+ _ ->
+ case inet:getaddr(Host, inet) of
+ {ok, IPv4} ->
+ IpFam = inet,
+ connect2(IPv4, Port, IpFam, SockOpts, Timeout);
+ Error ->
+ Error
+ end
end.
connect2(Host, Port, IpFam, SockOpts, Timeout) ->
Opts = [IpFam, binary, {packet, 0}, {active, false} | SockOpts],
case gen_tcp:connect(Host, Port, Opts, Timeout) of
- {ok, Sock} ->
- {ok, IpFam, Sock};
- Error ->
- Error
+ {ok, Sock} ->
+ {ok, IpFam, Sock};
+ Error ->
+ Error
end.
-
+
accept_data_connection(#state{mode = active,
- dtimeout = DTimeout,
- tls_options = TLSOptions,
- dsock = {lsock, LSock}} = State0) ->
+ dtimeout = DTimeout,
+ tls_options = TLSOptions,
+ dsock = {lsock, LSock}} = State0) ->
case gen_tcp:accept(LSock, DTimeout) of
- {ok, Socket} when is_list(TLSOptions) ->
- gen_tcp:close(LSock),
- ?DBG('<--data ssl:connect(~p, ~p)~n~p~n',[Socket,TLSOptions,State0]),
- case ssl:connect(Socket, TLSOptions, DTimeout) of
- {ok, TLSSocket} ->
- {ok, State0#state{dsock={ssl,TLSSocket}}};
- {error, Reason} ->
- {error, {ssl_connect_failed, Reason}}
- end;
- {ok, Socket} ->
- gen_tcp:close(LSock),
- {ok, State0#state{dsock={tcp,Socket}}};
- {error, Reason} ->
- {error, {data_connect_failed, Reason}}
+ {ok, Socket} when is_list(TLSOptions) ->
+ gen_tcp:close(LSock),
+ ?DBG('<--data ssl:connect(~p, ~p)~n~p~n',[Socket,TLSOptions,State0]),
+ case ssl:connect(Socket, TLSOptions, DTimeout) of
+ {ok, TLSSocket} ->
+ {ok, State0#state{dsock={ssl,TLSSocket}}};
+ {error, Reason} ->
+ {error, {ssl_connect_failed, Reason}}
+ end;
+ {ok, Socket} ->
+ gen_tcp:close(LSock),
+ {ok, State0#state{dsock={tcp,Socket}}};
+ {error, Reason} ->
+ {error, {data_connect_failed, Reason}}
end;
accept_data_connection(#state{mode = passive,
- dtimeout = DTimeout,
- dsock = {tcp,Socket},
- tls_options = TLSOptions} = State) when is_list(TLSOptions) ->
+ dtimeout = DTimeout,
+ dsock = {tcp,Socket},
+ tls_options = TLSOptions} = State) when is_list(TLSOptions) ->
?DBG('<--data ssl:connect(~p, ~p)~n~p~n',[Socket,TLSOptions,State]),
case ssl:connect(Socket, TLSOptions, DTimeout) of
- {ok, TLSSocket} ->
- {ok, State#state{dsock={ssl,TLSSocket}}};
- {error, Reason} ->
- {error, {ssl_connect_failed, Reason}}
+ {ok, TLSSocket} ->
+ {ok, State#state{dsock={ssl,TLSSocket}}};
+ {error, Reason} ->
+ {error, {ssl_connect_failed, Reason}}
end;
accept_data_connection(#state{mode = passive} = State) ->
{ok,State}.
-
+
send_ctrl_message(_S=#state{csock = Socket, verbose = Verbose}, Message) ->
verbose(lists:flatten(Message),Verbose,send),
@@ -2236,15 +2236,15 @@ send_ctrl_message(_S=#state{csock = Socket, verbose = Verbose}, Message) ->
send_data_message(_S=#state{dsock = Socket}, Message) ->
?DBG('<==data ~p ==== ~s~n~p~n',[Socket,Message,_S]),
case send_message(Socket, Message) of
- ok ->
- ok;
- {error, Reason} ->
- Report = io_lib:format("send/2 for socket ~p failed with "
- "reason ~p~n", [Socket, Reason]),
- error_logger:error_report(Report),
- %% If tcp/ssl does not work the only option is to terminate,
- %% this is the expected behavior under these circumstances.
- exit(normal) %% User will get error message from terminate/2
+ ok ->
+ ok;
+ {error, Reason} ->
+ Report = io_lib:format("send/2 for socket ~p failed with "
+ "reason ~p~n", [Socket, Reason]),
+ error_logger:error_report(Report),
+ %% If tcp/ssl does not work the only option is to terminate,
+ %% this is the expected behavior under these circumstances.
+ exit(normal) %% User will get error message from terminate/2
end.
send_message({tcp, Socket}, Message) ->
@@ -2287,7 +2287,7 @@ ignore_return_value(_) -> ok.
unwrap_socket({tcp,Socket}) -> Socket;
unwrap_socket({ssl,Socket}) -> Socket.
-
+
socket_type({tcp,_Socket}) -> tcp;
socket_type({ssl,_Socket}) -> ssl.
@@ -2301,25 +2301,25 @@ close_connection({lsock,Socket}) -> ignore_return_value( gen_tcp:close(Socket) )
close_connection({tcp, Socket}) -> ignore_return_value( gen_tcp:close(Socket) );
close_connection({ssl, Socket}) -> ignore_return_value( ssl:close(Socket) ).
-%% ------------ FILE HANDLING ----------------------------------------
+%% ------------ FILE HANDLING ----------------------------------------
send_file(#state{tls_upgrading_data_connection = {true, CTRL, _}} = State, Fd) ->
{noreply, State#state{tls_upgrading_data_connection = {true, CTRL, ?MODULE, send_file, Fd}}};
send_file(State0, Fd) ->
case file_read(Fd) of
- {ok, N, Bin} when N > 0 ->
- send_data_message(State0, Bin),
- progress_report({binary, Bin}, State0),
- send_file(State0, Fd);
- {ok, _, _} ->
- file_close(Fd),
- close_data_connection(State0),
- progress_report({transfer_size, 0}, State0),
- State = activate_ctrl_connection(State0),
- {noreply, State#state{caller = transfer_file_second_phase,
- dsock = undefined}};
+ {ok, N, Bin} when N > 0 ->
+ send_data_message(State0, Bin),
+ progress_report({binary, Bin}, State0),
+ send_file(State0, Fd);
+ {ok, _, _} ->
+ file_close(Fd),
+ close_data_connection(State0),
+ progress_report({transfer_size, 0}, State0),
+ State = activate_ctrl_connection(State0),
+ {noreply, State#state{caller = transfer_file_second_phase,
+ dsock = undefined}};
{error, Reason} ->
- gen_server:reply(State0#state.client, {error, Reason}),
- {stop, normal, State0#state{client = undefined}}
+ gen_server:reply(State0#state.client, {error, Reason}),
+ {stop, normal, State0#state{client = undefined}}
end.
file_open(File, Option) ->
@@ -2328,32 +2328,32 @@ file_open(File, Option) ->
file_close(Fd) ->
ignore_return_value( file:close(Fd) ).
-file_read(Fd) ->
+file_read(Fd) ->
case file:read(Fd, ?FILE_BUFSIZE) of
- {ok, Bytes} ->
- {ok, size(Bytes), Bytes};
- eof ->
- {ok, 0, []};
- Other ->
- Other
+ {ok, Bytes} ->
+ {ok, size(Bytes), Bytes};
+ eof ->
+ {ok, 0, []};
+ Other ->
+ Other
end.
file_write(Bytes, Fd) ->
file:write(Fd, Bytes).
-%% -------------- MISC ----------------------------------------------
+%% -------------- MISC ----------------------------------------------
call(GenServer, Msg, Format) ->
call(GenServer, Msg, Format, infinity).
-call(GenServer, Msg, Format, Timeout) ->
- Req = {self(), Msg},
+call(GenServer, Msg, Format, Timeout) ->
+ Req = {self(), Msg},
case (catch gen_server:call(GenServer, Req, Timeout)) of
- {ok, Bin} when is_binary(Bin) andalso (Format =:= string) ->
- {ok, binary_to_list(Bin)};
- {'EXIT', _} ->
- {error, eclosed};
- Result ->
- Result
+ {ok, Bin} when is_binary(Bin) andalso (Format =:= string) ->
+ {ok, binary_to_list(Bin)};
+ {'EXIT', _} ->
+ {error, eclosed};
+ Result ->
+ Result
end.
cast(GenServer, Msg) ->
@@ -2366,10 +2366,10 @@ send_bin(State0, Bin) ->
close_data_connection(State0),
State = activate_ctrl_connection(State0),
{noreply, State#state{caller = transfer_data_second_phase,
- dsock = undefined}}.
+ dsock = undefined}}.
mk_cmd(Fmt, Args) ->
- [io_lib:format(Fmt, Args)| [?CR, ?LF]]. % Deep list ok.
+ [io_lib:format(Fmt, Args)| [?CR, ?LF]]. % Deep list ok.
is_name_sane([]) ->
true;
@@ -2381,29 +2381,29 @@ is_name_sane([_| Rest]) ->
is_name_sane(Rest).
pwd_result(Lines) ->
- {_, [?DOUBLE_QUOTE | Rest]} =
- lists:splitwith(fun(?DOUBLE_QUOTE) -> false; (_) -> true end, Lines),
+ {_, [?DOUBLE_QUOTE | Rest]} =
+ lists:splitwith(fun(?DOUBLE_QUOTE) -> false; (_) -> true end, Lines),
{Dir, _} =
- lists:splitwith(fun(?DOUBLE_QUOTE) -> false; (_) -> true end, Rest),
+ lists:splitwith(fun(?DOUBLE_QUOTE) -> false; (_) -> true end, Rest),
Dir.
-key_search(Key, List, Default) ->
+key_search(Key, List, Default) ->
case lists:keysearch(Key, 1, List) of
- {value, {_,Val}} ->
- Val;
- false ->
- Default
+ {value, {_,Val}} ->
+ Val;
+ false ->
+ Default
end.
verbose(Lines, true, Direction) ->
DirStr =
- case Direction of
- send ->
- "Sending: ";
- _ ->
- "Receiving: "
- end,
+ case Direction of
+ send ->
+ "Sending: ";
+ _ ->
+ "Receiving: "
+ end,
Str = string:strip(string:strip(Lines, right, ?LF), right, ?CR),
erlang:display(DirStr++Str);
verbose(_, false,_) ->
@@ -2438,129 +2438,129 @@ start_chunk(#state{tls_upgrading_data_connection = {true, CTRL, _}} = State) ->
State#state{tls_upgrading_data_connection = {true, CTRL, ?MODULE, start_chunk, undefined}};
start_chunk(#state{client = From} = State) ->
gen_server:reply(From, ok),
- State#state{chunk = true,
- client = undefined,
- caller = undefined}.
+ State#state{chunk = true,
+ client = undefined,
+ caller = undefined}.
-%% This function extracts the start options from the
-%% Valid options:
-%% debug,
-%% verbose
+%% This function extracts the start options from the
+%% Valid options:
+%% debug,
+%% verbose
%% ipfamily
%% priority
%% flags (for backward compatibillity)
start_options(Options) ->
case lists:keysearch(flags, 1, Options) of
- {value, {flags, Flags}} ->
- Verbose = lists:member(verbose, Flags),
- IsTrace = lists:member(trace, Flags),
- IsDebug = lists:member(debug, Flags),
- DebugLevel =
- if
- (IsTrace =:= true) ->
- trace;
- IsDebug =:= true ->
- debug;
- true ->
- disable
- end,
- {ok, [{verbose, Verbose},
- {debug, DebugLevel},
- {priority, low}]};
- false ->
- ValidateVerbose =
- fun(true) -> true;
- (false) -> true;
- (_) -> false
- end,
- ValidateDebug =
- fun(trace) -> true;
- (debug) -> true;
- (disable) -> true;
- (_) -> false
- end,
- ValidatePriority =
- fun(low) -> true;
- (normal) -> true;
- (high) -> true;
- (_) -> false
- end,
- ValidOptions =
- [{verbose, ValidateVerbose, false, false},
- {debug, ValidateDebug, false, disable},
- {priority, ValidatePriority, false, low}],
- validate_options(Options, ValidOptions, [])
+ {value, {flags, Flags}} ->
+ Verbose = lists:member(verbose, Flags),
+ IsTrace = lists:member(trace, Flags),
+ IsDebug = lists:member(debug, Flags),
+ DebugLevel =
+ if
+ (IsTrace =:= true) ->
+ trace;
+ IsDebug =:= true ->
+ debug;
+ true ->
+ disable
+ end,
+ {ok, [{verbose, Verbose},
+ {debug, DebugLevel},
+ {priority, low}]};
+ false ->
+ ValidateVerbose =
+ fun(true) -> true;
+ (false) -> true;
+ (_) -> false
+ end,
+ ValidateDebug =
+ fun(trace) -> true;
+ (debug) -> true;
+ (disable) -> true;
+ (_) -> false
+ end,
+ ValidatePriority =
+ fun(low) -> true;
+ (normal) -> true;
+ (high) -> true;
+ (_) -> false
+ end,
+ ValidOptions =
+ [{verbose, ValidateVerbose, false, false},
+ {debug, ValidateDebug, false, disable},
+ {priority, ValidatePriority, false, low}],
+ validate_options(Options, ValidOptions, [])
end.
-%% This function extracts and validates the open options from the
-%% Valid options:
+%% This function extracts and validates the open options from the
+%% Valid options:
%% mode
%% host
%% port
%% timeout
%% dtimeout
%% progress
-%% ftp_extension
+%% ftp_extension
open_options(Options) ->
- ValidateMode =
- fun(active) -> true;
- (passive) -> true;
- (_) -> false
- end,
- ValidateHost =
- fun(Host) when is_list(Host) ->
- true;
- (Host) when is_tuple(Host) andalso
- ((size(Host) =:= 4) orelse (size(Host) =:= 8)) ->
- true;
- (_) ->
- false
- end,
- ValidatePort =
- fun(Port) when is_integer(Port) andalso (Port > 0) -> true;
- (_) -> false
- end,
- ValidateIpFamily =
- fun(inet) -> true;
- (inet6) -> true;
- (inet6fb4) -> true;
- (_) -> false
- end,
- ValidateTimeout =
- fun(Timeout) when is_integer(Timeout) andalso (Timeout >= 0) -> true;
- (_) -> false
- end,
- ValidateDTimeout =
- fun(DTimeout) when is_integer(DTimeout) andalso (DTimeout >= 0) -> true;
- (infinity) -> true;
- (_) -> false
- end,
- ValidateProgress =
- fun(ignore) ->
- true;
- ({Mod, Func, _InitProgress}) when is_atom(Mod) andalso
- is_atom(Func) ->
- true;
- (_) ->
- false
- end,
- ValidateFtpExtension =
- fun(true) -> true;
- (false) -> true;
- (_) -> false
- end,
- ValidOptions =
- [{mode, ValidateMode, false, ?DEFAULT_MODE},
- {host, ValidateHost, true, ehost},
- {port, ValidatePort, false, ?FTP_PORT},
- {ipfamily, ValidateIpFamily, false, inet},
- {timeout, ValidateTimeout, false, ?CONNECTION_TIMEOUT},
- {dtimeout, ValidateDTimeout, false, ?DATA_ACCEPT_TIMEOUT},
- {progress, ValidateProgress, false, ?PROGRESS_DEFAULT},
- {ftp_extension, ValidateFtpExtension, false, ?FTP_EXT_DEFAULT}],
+ ValidateMode =
+ fun(active) -> true;
+ (passive) -> true;
+ (_) -> false
+ end,
+ ValidateHost =
+ fun(Host) when is_list(Host) ->
+ true;
+ (Host) when is_tuple(Host) andalso
+ ((size(Host) =:= 4) orelse (size(Host) =:= 8)) ->
+ true;
+ (_) ->
+ false
+ end,
+ ValidatePort =
+ fun(Port) when is_integer(Port) andalso (Port > 0) -> true;
+ (_) -> false
+ end,
+ ValidateIpFamily =
+ fun(inet) -> true;
+ (inet6) -> true;
+ (inet6fb4) -> true;
+ (_) -> false
+ end,
+ ValidateTimeout =
+ fun(Timeout) when is_integer(Timeout) andalso (Timeout >= 0) -> true;
+ (_) -> false
+ end,
+ ValidateDTimeout =
+ fun(DTimeout) when is_integer(DTimeout) andalso (DTimeout >= 0) -> true;
+ (infinity) -> true;
+ (_) -> false
+ end,
+ ValidateProgress =
+ fun(ignore) ->
+ true;
+ ({Mod, Func, _InitProgress}) when is_atom(Mod) andalso
+ is_atom(Func) ->
+ true;
+ (_) ->
+ false
+ end,
+ ValidateFtpExtension =
+ fun(true) -> true;
+ (false) -> true;
+ (_) -> false
+ end,
+ ValidOptions =
+ [{mode, ValidateMode, false, ?DEFAULT_MODE},
+ {host, ValidateHost, true, ehost},
+ {port, ValidatePort, false, ?FTP_PORT},
+ {ipfamily, ValidateIpFamily, false, inet},
+ {timeout, ValidateTimeout, false, ?CONNECTION_TIMEOUT},
+ {dtimeout, ValidateDTimeout, false, ?DATA_ACCEPT_TIMEOUT},
+ {progress, ValidateProgress, false, ?PROGRESS_DEFAULT},
+ {ftp_extension, ValidateFtpExtension, false, ?FTP_EXT_DEFAULT}],
validate_options(Options, ValidOptions, []).
socket_options(Options) ->
@@ -2598,28 +2598,28 @@ validate_options([], [], Acc) ->
validate_options([], ValidOptions, Acc) ->
%% Check if any mandatory options are missing!
case [{Key, Reason} || {Key, _, true, Reason} <- ValidOptions] of
- [] ->
- Defaults =
- [{Key, Default} || {Key, _, _, Default} <- ValidOptions],
- {ok, lists:reverse(Defaults ++ Acc)};
- [{_, Reason}|_Missing] ->
- throw({error, Reason})
+ [] ->
+ Defaults =
+ [{Key, Default} || {Key, _, _, Default} <- ValidOptions],
+ {ok, lists:reverse(Defaults ++ Acc)};
+ [{_, Reason}|_Missing] ->
+ throw({error, Reason})
end;
validate_options([{Key, Value}|Options], ValidOptions, Acc) ->
case lists:keysearch(Key, 1, ValidOptions) of
- {value, {Key, Validate, _, Default}} ->
- case (catch Validate(Value)) of
- true ->
- NewValidOptions = lists:keydelete(Key, 1, ValidOptions),
- validate_options(Options, NewValidOptions,
- [{Key, Value} | Acc]);
- _ ->
- NewValidOptions = lists:keydelete(Key, 1, ValidOptions),
- validate_options(Options, NewValidOptions,
- [{Key, Default} | Acc])
- end;
- false ->
- validate_options(Options, ValidOptions, Acc)
+ {value, {Key, Validate, _, Default}} ->
+ case (catch Validate(Value)) of
+ true ->
+ NewValidOptions = lists:keydelete(Key, 1, ValidOptions),
+ validate_options(Options, NewValidOptions,
+ [{Key, Value} | Acc]);
+ _ ->
+ NewValidOptions = lists:keydelete(Key, 1, ValidOptions),
+ validate_options(Options, NewValidOptions,
+ [{Key, Default} | Acc])
+ end;
+ false ->
+ validate_options(Options, ValidOptions, Acc)
end;
validate_options([_|Options], ValidOptions, Acc) ->
validate_options(Options, ValidOptions, Acc).
@@ -2628,5 +2628,5 @@ validate_options([_|Options], ValidOptions, Acc) ->
millisec_passed(T0) ->
%% OTP 18
erlang:convert_time_unit(erlang:monotonic_time() - T0,
- native,
- micro_seconds) div 1000.
+ native,
+ micro_seconds) div 1000.
diff --git a/lib/ftp/test/ftp_SUITE.erl b/lib/ftp/test/ftp_SUITE.erl
index 0b070ee8cb..dc0bb8ab26 100644
--- a/lib/ftp/test/ftp_SUITE.erl
+++ b/lib/ftp/test/ftp_SUITE.erl
@@ -1,8 +1,8 @@
%%
%% %CopyrightBegin%
-%%
+%%
%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
-%%
+%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
@@ -14,7 +14,7 @@
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
-%%
+%%
%% %CopyrightEnd%
%%
%%
@@ -28,8 +28,8 @@
-define(FTP_USER, "anonymous").
-define(FTP_PASS(Cmnt), (fun({ok,__H}) -> "ftp_SUITE_"++Cmnt++"@" ++ __H;
- (_) -> "ftp_SUITE_"++Cmnt++"@localhost"
- end)(inet:gethostname())
+ (_) -> "ftp_SUITE_"++Cmnt++"@localhost"
+ end)(inet:gethostname())
).
-define(BAD_HOST, "badhostname").
@@ -37,9 +37,9 @@
-define(BAD_DIR, "baddirectory").
-record(progress, {
- current = 0,
- total
- }).
+ current = 0,
+ total
+ }).
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
@@ -73,32 +73,32 @@ ftp_tests()->
[
user,
bad_user,
- pwd,
- cd,
+ pwd,
+ cd,
lcd,
- ls,
- nlist,
- rename,
- delete,
- mkdir,
+ ls,
+ nlist,
+ rename,
+ delete,
+ mkdir,
rmdir,
- send,
+ send,
send_3,
- send_bin,
- send_chunk,
- append,
+ send_bin,
+ send_chunk,
+ append,
append_bin,
- append_chunk,
- recv,
- recv_3,
+ append_chunk,
+ recv,
+ recv_3,
recv_bin,
recv_bin_twice,
- recv_chunk,
+ recv_chunk,
recv_chunk_twice,
recv_chunk_three_times,
recv_chunk_delay,
- type,
- quote,
+ type,
+ quote,
error_elogin,
progress_report_send,
progress_report_recv,
@@ -117,80 +117,80 @@ ftp_sup_tests() ->
%%--------------------------------------------------------------------
%%% Config
-%%% key meaning
+%%% key meaning
%%% ................................................................
-%%% ftpservers list of servers to check if they are available
-%%% The element is:
-%%% {Name, % string(). The os command name
-%%% Path, % string(). The os PATH syntax, e.g "/bin:/usr/bin"
-%%% StartCommand, % fun()->{ok,start_result()} | {error,string()}.
-%%% % The command to start the daemon with.
-%%% ChkUp, % fun(start_result()) -> string(). Os command to check
-%%% % if the server is running. [] if not running.
-%%% % The string in string() is suitable for logging.
-%%% StopCommand, % fun(start_result()) -> void(). The command to stop the daemon with.
-%%% AugmentFun, % fun(config()) -> config() Adds two funs for transforming names of files
-%%% % and directories to the form they are returned from this server
-%%% ServerHost, % string(). Mostly "localhost"
-%%% ServerPort % pos_integer()
-%%% }
-%%%
+%%% ftpservers list of servers to check if they are available
+%%% The element is:
+%%% {Name, % string(). The os command name
+%%% Path, % string(). The os PATH syntax, e.g "/bin:/usr/bin"
+%%% StartCommand, % fun()->{ok,start_result()} | {error,string()}.
+%%% % The command to start the daemon with.
+%%% ChkUp, % fun(start_result()) -> string(). Os command to check
+%%% % if the server is running. [] if not running.
+%%% % The string in string() is suitable for logging.
+%%% StopCommand, % fun(start_result()) -> void(). The command to stop the daemon with.
+%%% AugmentFun, % fun(config()) -> config() Adds two funs for transforming names of files
+%%% % and directories to the form they are returned from this server
+%%% ServerHost, % string(). Mostly "localhost"
+%%% ServerPort % pos_integer()
+%%% }
+%%%
-define(default_ftp_servers,
- [{"vsftpd",
- "/sbin:/usr/sbin:/usr/local/sbin",
- fun(__CONF__, AbsName) ->
- DataDir = proplists:get_value(data_dir,__CONF__),
- ConfFile = filename:join(DataDir, "vsftpd.conf"),
- PrivDir = proplists:get_value(priv_dir,__CONF__),
- AnonRoot = PrivDir,
- Cmd = [AbsName ++" "++filename:join(DataDir,"vsftpd.conf"),
- " -oftpd_banner=erlang_otp_testing",
- " -oanon_root=\"",AnonRoot,"\"",
- " -orsa_cert_file=\"",filename:join(DataDir,"server-cert.pem"),"\"",
- " -orsa_private_key_file=\"",filename:join(DataDir,"server-key.pem"),"\""
- ],
- Result = os:cmd(Cmd),
- ct:log("Config file:~n~s~n~nServer start command:~n ~s~nResult:~n ~p",
- [case file:read_file(ConfFile) of
- {ok,X} -> X;
- _ -> ""
- end,
- Cmd, Result
- ]),
- case Result of
- [] -> {ok,'dont care'};
- [Msg] -> {error,Msg}
- end
- end,
- fun(_StartResult) -> os:cmd("ps ax | grep erlang_otp_testing | grep -v grep")
- end,
- fun(_StartResult) -> os:cmd("kill `ps ax | grep erlang_otp_testing | awk '/vsftpd/{print $1}'`")
- end,
- fun(__CONF__) ->
- AnonRoot = proplists:get_value(priv_dir,__CONF__),
- [{id2ftp, fun(Id) -> filename:join(AnonRoot,Id) end},
- {id2ftp_result,fun(Id) -> filename:join(AnonRoot,Id) end} | __CONF__]
- end,
- "localhost",
- 9999
- }
- ]
+ [{"vsftpd",
+ "/sbin:/usr/sbin:/usr/local/sbin",
+ fun(__CONF__, AbsName) ->
+ DataDir = proplists:get_value(data_dir,__CONF__),
+ ConfFile = filename:join(DataDir, "vsftpd.conf"),
+ PrivDir = proplists:get_value(priv_dir,__CONF__),
+ AnonRoot = PrivDir,
+ Cmd = [AbsName ++" "++filename:join(DataDir,"vsftpd.conf"),
+ " -oftpd_banner=erlang_otp_testing",
+ " -oanon_root=\"",AnonRoot,"\"",
+ " -orsa_cert_file=\"",filename:join(DataDir,"server-cert.pem"),"\"",
+ " -orsa_private_key_file=\"",filename:join(DataDir,"server-key.pem"),"\""
+ ],
+ Result = os:cmd(Cmd),
+ ct:log("Config file:~n~s~n~nServer start command:~n ~s~nResult:~n ~p",
+ [case file:read_file(ConfFile) of
+ {ok,X} -> X;
+ _ -> ""
+ end,
+ Cmd, Result
+ ]),
+ case Result of
+ [] -> {ok,'dont care'};
+ [Msg] -> {error,Msg}
+ end
+ end,
+ fun(_StartResult) -> os:cmd("ps ax | grep erlang_otp_testing | grep -v grep")
+ end,
+ fun(_StartResult) -> os:cmd("kill `ps ax | grep erlang_otp_testing | awk '/vsftpd/{print $1}'`")
+ end,
+ fun(__CONF__) ->
+ AnonRoot = proplists:get_value(priv_dir,__CONF__),
+ [{id2ftp, fun(Id) -> filename:join(AnonRoot,Id) end},
+ {id2ftp_result,fun(Id) -> filename:join(AnonRoot,Id) end} | __CONF__]
+ end,
+ "localhost",
+ 9999
+ }
+ ]
).
init_per_suite(Config) ->
case find_executable(Config) of
- false ->
- {skip, "No ftp server found"};
- {ok,Data} ->
- TstDir = filename:join(proplists:get_value(priv_dir,Config), "test"),
- file:make_dir(TstDir),
- %% make_cert_files(dsa, rsa, "server-", proplists:get_value(data_dir,Config)),
+ false ->
+ {skip, "No ftp server found"};
+ {ok,Data} ->
+ TstDir = filename:join(proplists:get_value(priv_dir,Config), "test"),
+ file:make_dir(TstDir),
+ %% make_cert_files(dsa, rsa, "server-", proplists:get_value(data_dir,Config)),
ftp_test_lib:make_cert_files(proplists:get_value(data_dir,Config)),
- start_ftpd([{test_dir,TstDir},
- {ftpd_data,Data}
- | Config])
+ start_ftpd([{test_dir,TstDir},
+ {ftpd_data,Data}
+ | Config])
end.
end_per_suite(Config) ->
@@ -218,14 +218,14 @@ init_per_group(ftp_sup, Config) ->
_:_ ->
{skip, "Ftp did not start"}
end;
-init_per_group(_Group, Config) ->
+init_per_group(_Group, Config) ->
Config.
-end_per_group(ftp_sup, Config) ->
+end_per_group(ftp_sup, Config) ->
ftp:stop(),
Config;
-end_per_group(_Group, Config) ->
+end_per_group(_Group, Config) ->
Config.
%%--------------------------------------------------------------------
@@ -250,31 +250,31 @@ init_per_testcase(Case, Config0) ->
ACTIVE = [{mode,active}],
PASSIVE = [{mode,passive}],
CaseOpts = case Case of
- progress_report_send -> [{progress, {?MODULE,progress,#progress{}}}];
- progress_report_recv -> [{progress, {?MODULE,progress,#progress{}}}];
- _ -> []
- end,
+ progress_report_send -> [{progress, {?MODULE,progress,#progress{}}}];
+ progress_report_recv -> [{progress, {?MODULE,progress,#progress{}}}];
+ _ -> []
+ end,
ExtraOpts = [verbose | CaseOpts],
Config =
- case Group of
- ftp_active -> ftp__open(Config0, ACTIVE ++ ExtraOpts);
- ftps_active -> ftp__open(Config0, TLS++ ACTIVE ++ ExtraOpts);
- ftp_passive -> ftp__open(Config0, PASSIVE ++ ExtraOpts);
- ftps_passive -> ftp__open(Config0, TLS++PASSIVE ++ ExtraOpts);
+ case Group of
+ ftp_active -> ftp__open(Config0, ACTIVE ++ ExtraOpts);
+ ftps_active -> ftp__open(Config0, TLS++ ACTIVE ++ ExtraOpts);
+ ftp_passive -> ftp__open(Config0, PASSIVE ++ ExtraOpts);
+ ftps_passive -> ftp__open(Config0, TLS++PASSIVE ++ ExtraOpts);
ftp_sup -> ftp_start_service(Config0, ACTIVE ++ ExtraOpts);
- undefined -> Config0
- end,
+ undefined -> Config0
+ end,
case Case of
- user -> Config;
- bad_user -> Config;
- error_elogin -> Config;
- error_ehost -> Config;
- clean_shutdown -> Config;
- _ ->
- Pid = proplists:get_value(ftp,Config),
- ok = ftp:user(Pid, ?FTP_USER, ?FTP_PASS(atom_to_list(Group)++"-"++atom_to_list(Case)) ),
- ok = ftp:cd(Pid, proplists:get_value(priv_dir,Config)),
- Config
+ user -> Config;
+ bad_user -> Config;
+ error_elogin -> Config;
+ error_ehost -> Config;
+ clean_shutdown -> Config;
+ _ ->
+ Pid = proplists:get_value(ftp,Config),
+ ok = ftp:user(Pid, ?FTP_USER, ?FTP_PASS(atom_to_list(Group)++"-"++atom_to_list(Case)) ),
+ ok = ftp:cd(Pid, proplists:get_value(priv_dir,Config)),
+ Config
end.
end_per_testcase(T, _Config) when T =:= app; T =:= appup -> ok;
@@ -283,16 +283,16 @@ end_per_testcase(bad_user, _Config) -> ok;
end_per_testcase(error_elogin, _Config) -> ok;
end_per_testcase(error_ehost, _Config) -> ok;
end_per_testcase(clean_shutdown, _Config) -> ok;
-end_per_testcase(_Case, Config) ->
+end_per_testcase(_Case, Config) ->
case proplists:get_value(tc_status,Config) of
- ok -> ok;
- _ ->
- try ftp:latest_ctrl_response(proplists:get_value(ftp,Config))
- of
- {ok,S} -> ct:log("***~n*** Latest ctrl channel response:~n*** ~p~n***",[S])
- catch
- _:_ -> ok
- end
+ ok -> ok;
+ _ ->
+ try ftp:latest_ctrl_response(proplists:get_value(ftp,Config))
+ of
+ {ok,S} -> ct:log("***~n*** Latest ctrl channel response:~n*** ~p~n***",[S])
+ catch
+ _:_ -> ok
+ end
end,
Group = proplists:get_value(name, proplists:get_value(tc_group_properties,Config)),
case Group of
@@ -319,17 +319,17 @@ appup(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
user() -> [
- {doc, "Open an ftp connection to a host, and logon as anonymous ftp,"
- " then logoff"}].
+ {doc, "Open an ftp connection to a host, and logon as anonymous ftp,"
+ " then logoff"}].
user(Config) ->
Pid = proplists:get_value(ftp, Config),
ok = ftp:user(Pid, ?FTP_USER, ?FTP_PASS("")),% logon
- ok = ftp:close(Pid), % logoff
- {error,eclosed} = ftp:pwd(Pid), % check logoff result
+ ok = ftp:close(Pid), % logoff
+ {error,eclosed} = ftp:pwd(Pid), % check logoff result
ok.
%%-------------------------------------------------------------------------
-bad_user() ->
+bad_user() ->
[{doc, "Open an ftp connection to a host, and logon with bad user."}].
bad_user(Config) ->
Pid = proplists:get_value(ftp, Config),
@@ -337,7 +337,7 @@ bad_user(Config) ->
ok.
%%-------------------------------------------------------------------------
-pwd() ->
+pwd() ->
[{doc, "Test ftp:pwd/1 & ftp:lpwd/1"}].
pwd(Config0) ->
Config = set_state([reset], Config0),
@@ -348,7 +348,7 @@ pwd(Config0) ->
PathLpwd = id2ftp_result("", Config).
%%-------------------------------------------------------------------------
-cd() ->
+cd() ->
["Open an ftp connection, log on as anonymous ftp, and cd to a"
"directory and to a non-existent directory."].
cd(Config0) ->
@@ -376,7 +376,7 @@ lcd(Config0) ->
{error, epath} = ftp:lcd(Pid, ?BAD_DIR).
%%-------------------------------------------------------------------------
-ls() ->
+ls() ->
[{doc, "Open an ftp connection; ls the current directory, and the "
"\"test\" directory. We assume that ls never fails, since "
"it's output is meant to be read by humans. "}].
@@ -386,40 +386,40 @@ ls(Config0) ->
{ok, _R1} = ftp:ls(Pid),
{ok, _R2} = ftp:ls(Pid, id2ftp("test",Config)),
%% neither nlist nor ls operates on a directory
- %% they operate on a pathname, which *can* be a
- %% directory, but can also be a filename or a group
+ %% they operate on a pathname, which *can* be a
+ %% directory, but can also be a filename or a group
%% of files (including wildcards).
case proplists:get_value(wildcard_support, Config) of
- true ->
- {ok, _R3} = ftp:ls(Pid, id2ftp("te*",Config));
- _ ->
- ok
+ true ->
+ {ok, _R3} = ftp:ls(Pid, id2ftp("te*",Config));
+ _ ->
+ ok
end.
%%-------------------------------------------------------------------------
-nlist() ->
+nlist() ->
[{doc,"Open an ftp connection; nlist the current directory, and the "
- "\"test\" directory. Nlist does not behave consistenly over "
- "operating systems. On some it is an error to have an empty "
- "directory."}].
+ "\"test\" directory. Nlist does not behave consistenly over "
+ "operating systems. On some it is an error to have an empty "
+ "directory."}].
nlist(Config0) ->
Config = set_state([reset,{mkdir,"test"}], Config0),
Pid = proplists:get_value(ftp, Config),
{ok, _R1} = ftp:nlist(Pid),
{ok, _R2} = ftp:nlist(Pid, id2ftp("test",Config)),
%% neither nlist nor ls operates on a directory
- %% they operate on a pathname, which *can* be a
- %% directory, but can also be a filename or a group
+ %% they operate on a pathname, which *can* be a
+ %% directory, but can also be a filename or a group
%% of files (including wildcards).
case proplists:get_value(wildcard_support, Config) of
- true ->
- {ok, _R3} = ftp:nlist(Pid, id2ftp("te*",Config));
- _ ->
- ok
+ true ->
+ {ok, _R3} = ftp:nlist(Pid, id2ftp("te*",Config));
+ _ ->
+ ok
end.
%%-------------------------------------------------------------------------
-rename() ->
+rename() ->
[{doc, "Rename a file."}].
rename(Config0) ->
Contents = <<"ftp_SUITE test ...">>,
@@ -428,19 +428,19 @@ rename(Config0) ->
Config = set_state([reset,{mkfile,OldFile,Contents}], Config0),
Pid = proplists:get_value(ftp, Config),
- ok = ftp:rename(Pid,
- id2ftp(OldFile,Config),
- id2ftp(NewFile,Config)),
+ ok = ftp:rename(Pid,
+ id2ftp(OldFile,Config),
+ id2ftp(NewFile,Config)),
- true = (chk_file(NewFile,Contents,Config)
- and chk_no_file([OldFile],Config)),
+ true = (chk_file(NewFile,Contents,Config)
+ and chk_no_file([OldFile],Config)),
{error,epath} = ftp:rename(Pid,
- id2ftp("non_existing_file",Config),
- id2ftp(NewFile,Config)),
+ id2ftp("non_existing_file",Config),
+ id2ftp(NewFile,Config)),
ok.
%%-------------------------------------------------------------------------
-send() ->
+send() ->
[{doc, "Transfer a file with ftp using send/2."}].
send(Config0) ->
Contents = <<"ftp_SUITE test ...">>,
@@ -461,7 +461,7 @@ send(Config0) ->
ok.
%%-------------------------------------------------------------------------
-send_3() ->
+send_3() ->
[{doc, "Transfer a file with ftp using send/3."}].
send_3(Config0) ->
Contents = <<"ftp_SUITE test ...">>,
@@ -479,8 +479,8 @@ send_3(Config0) ->
{error,epath} = ftp:send(Pid, "non_existing_file", RemoteFile),
ok.
-%%-------------------------------------------------------------------------
-send_bin() ->
+%%-------------------------------------------------------------------------
+send_bin() ->
[{doc, "Send a binary."}].
send_bin(Config0) ->
BinContents = <<"ftp_SUITE test ...">>,
@@ -493,8 +493,8 @@ send_bin(Config0) ->
{error, efnamena} = ftp:send_bin(Pid, BinContents, "/nothere"),
ok.
-%%-------------------------------------------------------------------------
-send_chunk() ->
+%%-------------------------------------------------------------------------
+send_chunk() ->
[{doc, "Send a binary using chunks."}].
send_chunk(Config0) ->
Contents1 = <<"1: ftp_SUITE test ...">>,
@@ -518,7 +518,7 @@ send_chunk(Config0) ->
ok.
%%-------------------------------------------------------------------------
-delete() ->
+delete() ->
[{doc, "Delete a file."}].
delete(Config0) ->
Contents = <<"ftp_SUITE test ...">>,
@@ -543,7 +543,7 @@ mkdir(Config0) ->
ok.
%%-------------------------------------------------------------------------
-rmdir() ->
+rmdir() ->
[{doc, "Remove a directory."}].
rmdir(Config0) ->
Dir = "dir",
@@ -555,7 +555,7 @@ rmdir(Config0) ->
ok.
%%-------------------------------------------------------------------------
-append() ->
+append() ->
[{doc, "Append a local file twice to a remote file"}].
append(Config0) ->
SrcFile = "f_src.txt",
@@ -568,9 +568,9 @@ append(Config0) ->
chk_file(DstFile, <<Contents/binary,Contents/binary>>, Config),
{error,epath} = ftp:append(Pid, id2ftp("non_existing_file",Config), id2ftp(DstFile,Config)),
ok.
-
+
%%-------------------------------------------------------------------------
-append_bin() ->
+append_bin() ->
[{doc, "Append a local file twice to a remote file using append_bin"}].
append_bin(Config0) ->
DstFile = "f_dst.txt",
@@ -582,7 +582,7 @@ append_bin(Config0) ->
chk_file(DstFile, <<Contents/binary,Contents/binary>>, Config).
%%-------------------------------------------------------------------------
-append_chunk() ->
+append_chunk() ->
[{doc, "Append chunks."}].
append_chunk(Config0) ->
File = "f_dst.txt",
@@ -598,7 +598,7 @@ append_chunk(Config0) ->
chk_file(File, <<"ERLERL">>, Config).
%%-------------------------------------------------------------------------
-recv() ->
+recv() ->
[{doc, "Receive a file using recv/2"}].
recv(Config0) ->
File1 = "f_dst1.txt",
@@ -618,7 +618,7 @@ recv(Config0) ->
ok.
%%-------------------------------------------------------------------------
-recv_3() ->
+recv_3() ->
[{doc,"Receive a file using recv/3"}].
recv_3(Config0) ->
DstFile = "f_src.txt",
@@ -631,7 +631,7 @@ recv_3(Config0) ->
chk_file(DstFile, Contents, Config).
%%-------------------------------------------------------------------------
-recv_bin() ->
+recv_bin() ->
[{doc, "Receive a file as a binary."}].
recv_bin(Config0) ->
File = "f_dst.txt",
@@ -644,7 +644,7 @@ recv_bin(Config0) ->
ok.
%%-------------------------------------------------------------------------
-recv_bin_twice() ->
+recv_bin_twice() ->
[{doc, "Receive two files as a binaries."}].
recv_bin_twice(Config0) ->
File1 = "f_dst1.txt",
@@ -663,7 +663,7 @@ recv_bin_twice(Config0) ->
{error,epath} = ftp:recv_bin(Pid, id2ftp("non_existing_file",Config)),
ok.
%%-------------------------------------------------------------------------
-recv_chunk() ->
+recv_chunk() ->
[{doc, "Receive a file using chunk-wise."}].
recv_chunk(Config0) ->
File = "big_file.txt",
@@ -709,7 +709,7 @@ recv_chunk_three_times(Config0) ->
ok = ftp:recv_chunk_start(Pid, id2ftp(File3,Config)),
{ok, ReceivedContents3} = do_recv_chunk(Pid),
-
+
ok = ftp:recv_chunk_start(Pid, id2ftp(File1,Config)),
{ok, ReceivedContents1} = do_recv_chunk(Pid),
@@ -721,15 +721,15 @@ recv_chunk_three_times(Config0) ->
find_diff(ReceivedContents3, Contents3).
-do_recv_chunk(Pid) ->
+do_recv_chunk(Pid) ->
recv_chunk(Pid, <<>>).
-recv_chunk(Pid, Acc) ->
+recv_chunk(Pid, Acc) ->
case ftp:recv_chunk(Pid) of
- ok ->
+ ok ->
{ok, Acc};
- {ok, Bin} ->
+ {ok, Bin} ->
recv_chunk(Pid, <<Acc/binary, Bin/binary>>);
- Error ->
+ Error ->
Error
end.
@@ -742,22 +742,22 @@ recv_chunk_delay(Config0) when is_list(Config0) ->
{ok, ReceivedContents} = delay_recv_chunk(Pid),
find_diff(ReceivedContents, Contents).
-delay_recv_chunk(Pid) ->
+delay_recv_chunk(Pid) ->
delay_recv_chunk(Pid, <<>>).
-delay_recv_chunk(Pid, Acc) ->
+delay_recv_chunk(Pid, Acc) ->
ct:pal("Recived size ~p", [byte_size(Acc)]),
case ftp:recv_chunk(Pid) of
- ok ->
+ ok ->
{ok, Acc};
- {ok, Bin} ->
+ {ok, Bin} ->
ct:sleep(100),
delay_recv_chunk(Pid, <<Acc/binary, Bin/binary>>);
- Error ->
+ Error ->
Error
end.
%%-------------------------------------------------------------------------
-type() ->
+type() ->
[{doc,"Test that we can change btween ASCCI and binary transfer mode"}].
type(Config) ->
Pid = proplists:get_value(ftp, Config),
@@ -773,32 +773,32 @@ quote(Config) ->
[_| _] = ftp:quote(Pid, "help"),
%% This negativ test causes some ftp servers to hang. This test
%% is not important for the client, so we skip it for now.
- %%["425 Can't build data connection: Connection refused."]
- %% = ftp:quote(Pid, "list"),
+ %%["425 Can't build data connection: Connection refused."]
+ %% = ftp:quote(Pid, "list"),
ok.
%%-------------------------------------------------------------------------
progress_report_send() ->
[{doc, "Test the option progress for ftp:send/[2,3]"}].
progress_report_send(Config) when is_list(Config) ->
- ReportPid =
- spawn_link(?MODULE, progress_report_receiver_init, [self(), 1]),
+ ReportPid =
+ spawn_link(?MODULE, progress_report_receiver_init, [self(), 1]),
send(Config),
receive
- {ReportPid, ok} ->
- ok
+ {ReportPid, ok} ->
+ ok
end.
%%-------------------------------------------------------------------------
progress_report_recv() ->
[{doc, "Test the option progress for ftp:recv/[2,3]"}].
progress_report_recv(Config) when is_list(Config) ->
- ReportPid =
- spawn_link(?MODULE, progress_report_receiver_init, [self(), 3]),
+ ReportPid =
+ spawn_link(?MODULE, progress_report_receiver_init, [self(), 3]),
recv(Config),
receive
- {ReportPid, ok} ->
- ok
+ {ReportPid, ok} ->
+ ok
end.
%%-------------------------------------------------------------------------
@@ -811,14 +811,14 @@ not_owner(Config) when is_list(Config) ->
Parent = self(),
OtherPid = spawn_link(
- fun() ->
- {error, not_connection_owner} = ftp:pwd(Pid),
- ftp:close(Pid),
- Parent ! {self(), ok}
- end),
+ fun() ->
+ {error, not_connection_owner} = ftp:pwd(Pid),
+ ftp:close(Pid),
+ Parent ! {self(), ok}
+ end),
receive
- {OtherPid, ok} ->
- {ok, _} = ftp:pwd(Pid)
+ {OtherPid, ok} ->
+ {ok, _} = ftp:pwd(Pid)
end.
@@ -830,13 +830,13 @@ unexpected_call()->
unexpected_call(Config) when is_list(Config) ->
Flag = process_flag(trap_exit, true),
Pid = proplists:get_value(ftp, Config),
-
- %% Serious programming fault, connetion will be shut down
+
+ %% Serious programming fault, connetion will be shut down
case (catch gen_server:call(Pid, {self(), foobar, 10}, infinity)) of
- {error, {connection_terminated, 'API_violation'}} ->
- ok;
- Unexpected1 ->
- exit({unexpected_result, Unexpected1})
+ {error, {connection_terminated, 'API_violation'}} ->
+ ok;
+ Unexpected1 ->
+ exit({unexpected_result, Unexpected1})
end,
ct:sleep(500),
undefined = process_info(Pid, status),
@@ -848,52 +848,52 @@ unexpected_cast()->
unexpected_cast(Config) when is_list(Config) ->
Flag = process_flag(trap_exit, true),
Pid = proplists:get_value(ftp, Config),
- %% Serious programming fault, connetion will be shut down
+ %% Serious programming fault, connetion will be shut down
gen_server:cast(Pid, {self(), foobar, 10}),
ct:sleep(500),
undefined = process_info(Pid, status),
process_flag(trap_exit, Flag).
%%-------------------------------------------------------------------------
-
+
unexpected_bang()->
[{doc, "Test that connection ignores unexpected bang"}].
unexpected_bang(Config) when is_list(Config) ->
Flag = process_flag(trap_exit, true),
Pid = proplists:get_value(ftp, Config),
- %% Could be an innocent misstake the connection lives.
- Pid ! foobar,
+ %% Could be an innocent misstake the connection lives.
+ Pid ! foobar,
ct:sleep(500),
{status, _} = process_info(Pid, status),
process_flag(trap_exit, Flag).
-
+
%%-------------------------------------------------------------------------
-clean_shutdown() ->
+clean_shutdown() ->
[{doc, "Test that owning process that exits with reason "
"'shutdown' does not cause an error message. OTP 6035"}].
clean_shutdown(Config) ->
Parent = self(),
HelperPid = spawn(
- fun() ->
- ftp__open(Config, [verbose]),
- Parent ! ok,
- receive
- nothing -> ok
- end
- end),
+ fun() ->
+ ftp__open(Config, [verbose]),
+ Parent ! ok,
+ receive
+ nothing -> ok
+ end
+ end),
receive
- ok ->
- PrivDir = proplists:get_value(priv_dir, Config),
- LogFile = filename:join([PrivDir,"ticket_6035.log"]),
- error_logger:logfile({open, LogFile}),
- exit(HelperPid, shutdown),
- timer:sleep(2000),
- error_logger:logfile(close),
- case is_error_report_6035(LogFile) of
- true -> ok;
- false -> {fail, "Bad logfile"}
- end
+ ok ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ LogFile = filename:join([PrivDir,"ticket_6035.log"]),
+ error_logger:logfile({open, LogFile}),
+ exit(HelperPid, shutdown),
+ timer:sleep(2000),
+ error_logger:logfile(close),
+ case is_error_report_6035(LogFile) of
+ true -> ok;
+ false -> {fail, "Bad logfile"}
+ end
end.
%%-------------------------------------------------------------------------
@@ -906,7 +906,7 @@ start_ftp(Config) ->
{ok, [_|_]} = ftp:service_info(Pid0),
ftp:stop_service(Pid0),
ct:sleep(100),
- Pids1 = [ServicePid || {_, ServicePid} <- ftp:services()],
+ Pids1 = [ServicePid || {_, ServicePid} <- ftp:services()],
false = lists:member(Pid0, Pids1),
Host = proplists:get_value(ftpd_host,Config),
@@ -924,7 +924,7 @@ ftp_worker(Config) ->
Pid = proplists:get_value(ftp,Config),
case supervisor:which_children(ftp_sup) of
[{_,_, worker, [ftp]}] ->
- ftp:stop_service(Pid),
+ ftp:stop_service(Pid),
ct:sleep(5000),
[] = supervisor:which_children(ftp_sup),
ok;
@@ -943,9 +943,9 @@ error_elogin(Config0) ->
SrcDir = "data",
File = "file.txt",
Config = set_state([reset,
- {mkdir,Dir},
- {mkfile,OldFile,<<"Contents..">>},
- {mkfile,[SrcDir,File],<<"Contents..">>}], Config0),
+ {mkdir,Dir},
+ {mkfile,OldFile,<<"Contents..">>},
+ {mkfile,[SrcDir,File],<<"Contents..">>}], Config0),
Pid = proplists:get_value(ftp, Config),
ok = ftp:lcd(Pid, id2ftp(SrcDir,Config)),
@@ -953,15 +953,15 @@ error_elogin(Config0) ->
ok = ftp:lcd(Pid, id2ftp("",Config)),
{error,elogin} = ftp:pwd(Pid),
{error,elogin} = ftp:cd(Pid, id2ftp(Dir,Config)),
- {error,elogin} = ftp:rename(Pid,
- id2ftp(OldFile,Config),
- id2ftp(NewFile,Config)),
+ {error,elogin} = ftp:rename(Pid,
+ id2ftp(OldFile,Config),
+ id2ftp(NewFile,Config)),
ok.
error_ehost(_Config) ->
{error, ehost} = ftp:open("nohost.nodomain"),
ok.
-
+
%%--------------------------------------------------------------------
%% Internal functions -----------------------------------------------
%%--------------------------------------------------------------------
@@ -973,22 +973,22 @@ chk_file(PathList, ExpectedContents, Config) ->
Path = filename:join(PathList),
AbsPath = id2abs(Path,Config),
case file:read_file(AbsPath) of
- {ok,ExpectedContents} ->
- true;
- {ok,ReadContents} ->
- {error,{diff,Pos,RC,LC}} = find_diff(ReadContents, ExpectedContents, 1),
- ct:log("Bad contents of ~p.~nGot:~n~p~nExpected:~n~p~nDiff at pos ~p ~nRead: ~p~nExp : ~p",
- [AbsPath,ReadContents,ExpectedContents,Pos,RC,LC]),
- ct:fail("Bad contents of ~p", [Path]);
- {error,Error} ->
- try begin
- {ok,CWD} = file:get_cwd(),
- ct:log("file:get_cwd()=~p~nfiles:~n~p",[CWD,file:list_dir(CWD)])
- end
- of _ -> ok
- catch _:_ ->ok
- end,
- ct:fail("Error reading ~p: ~p",[Path,Error])
+ {ok,ExpectedContents} ->
+ true;
+ {ok,ReadContents} ->
+ {error,{diff,Pos,RC,LC}} = find_diff(ReadContents, ExpectedContents, 1),
+ ct:log("Bad contents of ~p.~nGot:~n~p~nExpected:~n~p~nDiff at pos ~p ~nRead: ~p~nExp : ~p",
+ [AbsPath,ReadContents,ExpectedContents,Pos,RC,LC]),
+ ct:fail("Bad contents of ~p", [Path]);
+ {error,Error} ->
+ try begin
+ {ok,CWD} = file:get_cwd(),
+ ct:log("file:get_cwd()=~p~nfiles:~n~p",[CWD,file:list_dir(CWD)])
+ end
+ of _ -> ok
+ catch _:_ ->ok
+ end,
+ ct:fail("Error reading ~p: ~p",[Path,Error])
end.
@@ -999,14 +999,14 @@ chk_no_file(PathList, Config) ->
Path = filename:join(PathList),
AbsPath = id2abs(Path,Config),
case file:read_file(AbsPath) of
- {error,enoent} ->
- true;
- {ok,Contents} ->
- ct:log("File ~p exists although it shouldn't. Contents:~n~p",
- [AbsPath,Contents]),
- ct:fail("File exists: ~p", [Path]);
- {error,Error} ->
- ct:fail("Unexpected error reading ~p: ~p",[Path,Error])
+ {error,enoent} ->
+ true;
+ {ok,Contents} ->
+ ct:log("File ~p exists although it shouldn't. Contents:~n~p",
+ [AbsPath,Contents]),
+ ct:fail("File exists: ~p", [Path]);
+ {error,Error} ->
+ ct:fail("Unexpected error reading ~p: ~p",[Path,Error])
end.
@@ -1017,26 +1017,26 @@ chk_dir(PathList, Config) ->
Path = filename:join(PathList),
AbsPath = id2abs(Path,Config),
case file:read_file_info(AbsPath) of
- {ok, #file_info{type=directory}} ->
- true;
- {ok, #file_info{type=Type}} ->
- ct:fail("Expected dir ~p is a ~p",[Path,Type]);
- {error,Error} ->
- ct:fail("Expected dir ~p: ~p",[Path,Error])
+ {ok, #file_info{type=directory}} ->
+ true;
+ {ok, #file_info{type=Type}} ->
+ ct:fail("Expected dir ~p is a ~p",[Path,Type]);
+ {error,Error} ->
+ ct:fail("Expected dir ~p: ~p",[Path,Error])
end.
chk_no_dir(PathList, Config) ->
Path = filename:join(PathList),
AbsPath = id2abs(Path,Config),
case file:read_file_info(AbsPath) of
- {error,enoent} ->
- true;
- {ok, #file_info{type=directory}} ->
- ct:fail("Dir ~p erroneously exists",[Path]);
- {ok, #file_info{type=Type}} ->
- ct:fail("~p ~p erroneously exists",[Type,Path]);
- {error,Error} ->
- ct:fail("Unexpected error for ~p: ~p",[Path,Error])
+ {error,enoent} ->
+ true;
+ {ok, #file_info{type=directory}} ->
+ ct:fail("Dir ~p erroneously exists",[Path]);
+ {ok, #file_info{type=Type}} ->
+ ct:fail("~p ~p erroneously exists",[Type,Path]);
+ {error,Error} ->
+ ct:fail("Unexpected error for ~p: ~p",[Path,Error])
end.
%%--------------------------------------------------------------------
@@ -1046,12 +1046,12 @@ find_executable(Config) ->
search_executable([{Name,Paths,_StartCmd,_ChkUp,_StopCommand,_ConfigUpd,_Host,_Port}|Srvrs]) ->
case os_find(Name,Paths) of
- false ->
- ct:log("~p not found",[Name]),
- search_executable(Srvrs);
- AbsName ->
- ct:comment("Found ~p",[AbsName]),
- {ok, {AbsName,_StartCmd,_ChkUp,_StopCommand,_ConfigUpd,_Host,_Port}}
+ false ->
+ ct:log("~p not found",[Name]),
+ search_executable(Srvrs);
+ AbsName ->
+ ct:comment("Found ~p",[AbsName]),
+ {ok, {AbsName,_StartCmd,_ChkUp,_StopCommand,_ConfigUpd,_Host,_Port}}
end;
search_executable([]) ->
false.
@@ -1059,33 +1059,33 @@ search_executable([]) ->
os_find(Name, Paths) ->
case os:find_executable(Name, Paths) of
- false -> os:find_executable(Name);
- AbsName -> AbsName
+ false -> os:find_executable(Name);
+ AbsName -> AbsName
end.
%%%----------------------------------------------------------------
start_ftpd(Config0) ->
{AbsName,StartCmd,_ChkUp,_StopCommand,ConfigRewrite,Host,Port} =
- proplists:get_value(ftpd_data, Config0),
+ proplists:get_value(ftpd_data, Config0),
case StartCmd(Config0, AbsName) of
- {ok,StartResult} ->
- Config = [{ftpd_host,Host},
- {ftpd_port,Port},
- {ftpd_start_result,StartResult} | ConfigRewrite(Config0)],
- try
- ftp__close(ftp__open(Config,[verbose]))
- of
- Config1 when is_list(Config1) ->
- ct:log("Usuable ftp server ~p started on ~p:~p",[AbsName,Host,Port]),
- Config
- catch
- Class:Exception ->
- ct:log("Ftp server ~p started on ~p:~p but is unusable:~n~p:~p",
- [AbsName,Host,Port,Class,Exception]),
- {skip, [AbsName," started but unusuable"]}
- end;
- {error,Msg} ->
- {skip, [AbsName," not started: ",Msg]}
+ {ok,StartResult} ->
+ Config = [{ftpd_host,Host},
+ {ftpd_port,Port},
+ {ftpd_start_result,StartResult} | ConfigRewrite(Config0)],
+ try
+ ftp__close(ftp__open(Config,[verbose]))
+ of
+ Config1 when is_list(Config1) ->
+ ct:log("Usuable ftp server ~p started on ~p:~p",[AbsName,Host,Port]),
+ Config
+ catch
+ Class:Exception ->
+ ct:log("Ftp server ~p started on ~p:~p but is unusable:~n~p:~p",
+ [AbsName,Host,Port,Class,Exception]),
+ {skip, [AbsName," started but unusuable"]}
+ end;
+ {error,Msg} ->
+ {skip, [AbsName," not started: ",Msg]}
end.
stop_ftpd(Config) ->
@@ -1125,13 +1125,13 @@ ftp_stop_service(Config) ->
split(Cs) -> string:tokens(Cs, "\r\n").
-find_diff(Bin1, Bin2) ->
+find_diff(Bin1, Bin2) ->
case find_diff(Bin1, Bin2, 1) of
- {error, {diff,Pos,RC,LC}} ->
- ct:log("Contents differ at position ~p.~nOp1: ~p~nOp2: ~p",[Pos,RC,LC]),
- ct:fail("Contents differ at pos ~p",[Pos]);
- Other ->
- Other
+ {error, {diff,Pos,RC,LC}} ->
+ ct:log("Contents differ at position ~p.~nOp1: ~p~nOp2: ~p",[Pos,RC,LC]),
+ ct:fail("Contents differ at pos ~p",[Pos]);
+ Other ->
+ Other
end.
find_diff(A, A, _) -> true;
@@ -1140,7 +1140,7 @@ find_diff(RC, LC, Pos) -> {error, {diff, Pos, RC, LC}}.
set_state(Ops, Config) when is_list(Ops) -> lists:foldl(fun set_state/2, Config, Ops);
-set_state(reset, Config) ->
+set_state(reset, Config) ->
rm('*', id2abs("",Config)),
PrivDir = proplists:get_value(priv_dir,Config),
file:set_cwd(PrivDir),
@@ -1161,30 +1161,30 @@ mk_path(Abs) -> lists:foldl(fun mk_path/2, [], filename:split(filename:dirname(A
mk_path(F, Pfx) ->
case file:read_file_info(AbsName=filename:join(Pfx,F)) of
- {ok,#file_info{type=directory}} ->
- AbsName;
- {error,eexist} ->
- AbsName;
- {error,enoent} ->
- ok = file:make_dir(AbsName),
- AbsName
+ {ok,#file_info{type=directory}} ->
+ AbsName;
+ {error,eexist} ->
+ AbsName;
+ {error,enoent} ->
+ ok = file:make_dir(AbsName),
+ AbsName
end.
-
+
rm('*', Pfx) ->
{ok,Fs} = file:list_dir(Pfx),
lists:foreach(fun(F) -> rm(F, Pfx) end, Fs);
-rm(F, Pfx) ->
+rm(F, Pfx) ->
case file:read_file_info(AbsName=filename:join(Pfx,F)) of
- {ok,#file_info{type=directory}} ->
- {ok,Fs} = file:list_dir(AbsName),
- lists:foreach(fun(F1) -> rm(F1,AbsName) end, Fs),
- ok = file:del_dir(AbsName);
+ {ok,#file_info{type=directory}} ->
+ {ok,Fs} = file:list_dir(AbsName),
+ lists:foreach(fun(F1) -> rm(F1,AbsName) end, Fs),
+ ok = file:del_dir(AbsName);
- {ok,#file_info{type=regular}} ->
- ok = file:delete(AbsName);
+ {ok,#file_info{type=regular}} ->
+ ok = file:delete(AbsName);
- {error,enoent} ->
- ok
+ {error,enoent} ->
+ ok
end.
id2abs(Id, Conf) -> filename:join(proplists:get_value(priv_dir,Conf),ids(Id)).
@@ -1216,10 +1216,10 @@ progress(#progress{current = Current} = P, _File, {transfer_size, 0} = M) ->
ct:pal("Progress: ~p",[M]),
progress_report_receiver ! finish,
case P#progress.total of
- unknown -> P;
- Current -> P;
- Total -> ct:fail({error, {progress, {total,Total}, {current,Current}}}),
- P
+ unknown -> P;
+ Current -> P;
+ Total -> ct:fail({error, {progress, {total,Total}, {current,Current}}}),
+ P
end;
progress(#progress{current = Current} = P, _File, {transfer_size, Size} = M) ->
@@ -1244,7 +1244,7 @@ progress_report_receiver_expect_N_files(_Parent, 0) ->
progress_report_receiver_expect_N_files(Parent, N) ->
ct:pal("progress_report expects ~p more files",[N]),
receive
- start -> ok
+ start -> ok
end,
progress_report_receiver_loop(Parent, N-1).
@@ -1252,13 +1252,13 @@ progress_report_receiver_expect_N_files(Parent, N) ->
progress_report_receiver_loop(Parent, N) ->
ct:pal("progress_report expect update | finish. N = ~p",[N]),
receive
- update ->
- ct:pal("progress_report got update",[]),
- progress_report_receiver_loop(Parent, N);
- finish ->
- ct:pal("progress_report got finish, send ~p to ~p",[{self(),ok}, Parent]),
- Parent ! {self(), ok},
- progress_report_receiver_expect_N_files(Parent, N)
+ update ->
+ ct:pal("progress_report got update",[]),
+ progress_report_receiver_loop(Parent, N);
+ finish ->
+ ct:pal("progress_report got finish, send ~p to ~p",[{self(),ok}, Parent]),
+ Parent ! {self(), ok},
+ progress_report_receiver_expect_N_files(Parent, N)
end.
%%%----------------------------------------------------------------
@@ -1266,9 +1266,9 @@ progress_report_receiver_loop(Parent, N) ->
is_error_report_6035(LogFile) ->
case file:read_file(LogFile) of
- {ok, Bin} ->
- nomatch =/= binary:match(Bin, <<"=ERROR REPORT====">>);
- _ ->
- false
+ {ok, Bin} ->
+ nomatch =/= binary:match(Bin, <<"=ERROR REPORT====">>);
+ _ ->
+ false
end.
--
2.26.2