Created
November 15, 2010 20:43
-
-
Save xslogic/700908 to your computer and use it in GitHub Desktop.
FTP Patch for resuming FTP download..
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/lib/inets/src/ftp/ftp.erl b/lib/inets/src/ftp/ftp.erl | |
index 534fcae..1062c08 100644 | |
--- a/lib/inets/src/ftp/ftp.erl | |
+++ b/lib/inets/src/ftp/ftp.erl | |
@@ -31,11 +31,11 @@ | |
%% 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, | |
+ mkdir/2, nlist/1, nlist/2, sizeof/2, | |
open/1, open/2, open/3, force_active/1, | |
pwd/1, quote/2, | |
recv/2, recv/3, recv_bin/2, | |
- recv_chunk_start/2, recv_chunk/1, | |
+ recv_chunk_start/2, recv_chunk_start/3, 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, | |
@@ -250,12 +250,26 @@ cd(Pid, Dir) -> | |
lcd(Pid, Dir) -> | |
call(Pid, {lcd, Dir}, string). | |
+ | |
+%%-------------------------------------------------------------------------- | |
+%% sizeof(Pid, File) -> ok | {error, <something>} | |
+%% Pid = pid() | |
+%% Dir = string() | |
+%% | |
+%% Description: Return size of file. | |
+%%-------------------------------------------------------------------------- | |
+sizeof(Pid, File) -> | |
+ call(Pid, {sizeof, File}, string). | |
+ | |
+ | |
%%-------------------------------------------------------------------------- | |
%% ls(Pid) -> Result | |
%% ls(Pid, <Dir>) -> Result | |
+%% ls(Pid, <Dir>, RType) -> Result | |
%% | |
%% Pid = pid() | |
%% Dir = string() | |
+%% RType = string | binary | |
%% Result = {ok, Listing} | {error, Reason} | |
%% Listing = string() | |
%% Reason = epath | elogin | econn | |
@@ -263,9 +277,11 @@ lcd(Pid, Dir) -> | |
%% Description: Returns a list of files in long format. | |
%%-------------------------------------------------------------------------- | |
ls(Pid) -> | |
- ls(Pid, ""). | |
+ ls(Pid, "", string). | |
ls(Pid, Dir) -> | |
- call(Pid, {dir, long, Dir}, string). | |
+ ls(Pid, Dir, string). | |
+ls(Pid, Dir, RType) -> | |
+ call(Pid, {dir, long, Dir}, RType). | |
%%-------------------------------------------------------------------------- | |
%% nlist(Pid) -> Result | |
@@ -373,6 +389,9 @@ recv_bin(Pid, RemoteFile) -> | |
recv_chunk_start(Pid, RemoteFile) -> | |
call(Pid, {recv_chunk_start, RemoteFile}, atom). | |
+recv_chunk_start(Pid, RemoteFile, Pos) -> | |
+ call(Pid, {recv_chunk_start, RemoteFile, Pos}, atom). | |
+ | |
%%-------------------------------------------------------------------------- | |
%% recv_chunk(Pid, RemoteFile) -> ok | {ok, Bin} | {error, Reason} | |
%% Pid = pid() | |
@@ -938,6 +957,12 @@ handle_call({_, {delete, File}}, {_Pid, _} = From, | |
activate_ctrl_connection(State), | |
{noreply, State#state{client = From}}; | |
+handle_call({_, {sizeof, File}}, {_Pid, _} = From, | |
+ #state{chunk = false} = State) -> | |
+ send_ctrl_message(State, mk_cmd("SIZE ~s", [File])), | |
+ activate_ctrl_connection(State), | |
+ {noreply, State#state{client = From, caller = sizeof}}; | |
+ | |
handle_call({_, {mkdir, Dir}}, From, #state{chunk = false} = State) -> | |
send_ctrl_message(State, mk_cmd("MKD ~s", [Dir])), | |
activate_ctrl_connection(State), | |
@@ -985,6 +1010,12 @@ handle_call({_, {recv_bin, RemoteFile}}, From, #state{chunk = false} = | |
setup_data_connection(State#state{caller = {recv_bin, RemoteFile}, | |
client = From}); | |
+handle_call({_,{recv_chunk_start, RemoteFile, Pos}}, From, #state{chunk = false} | |
+ = State) -> | |
+ setup_data_connection(State#state{caller = {start_chunk_transfer, | |
+ "RETR", RemoteFile, Pos}, | |
+ client = From}); | |
+ | |
handle_call({_,{recv_chunk_start, RemoteFile}}, From, #state{chunk = false} | |
= State) -> | |
setup_data_connection(State#state{caller = {start_chunk_transfer, | |
@@ -992,6 +1023,10 @@ handle_call({_,{recv_chunk_start, RemoteFile}}, From, #state{chunk = false} | |
client = From}); | |
handle_call({_, recv_chunk}, _, #state{chunk = false} = State) -> | |
+ activate_ctrl_connection(State#state{chunk = flush_ctrl}), | |
+ {reply, ok, State#state{chunk = flush_ctrl}}; | |
+ | |
+handle_call({_, recv_chunk}, _, #state{chunk = flush_ctrl} = State) -> | |
{reply, {error, "ftp:recv_chunk_start/2 not called"}, State}; | |
handle_call({_, recv_chunk}, From, #state{chunk = true} = State) -> | |
@@ -1047,13 +1082,12 @@ handle_call({_, {quote, Cmd}}, From, #state{chunk = false} = State) -> | |
activate_ctrl_connection(State), | |
{noreply, State#state{client = From, caller = quote}}; | |
-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}; | |
+handle_call(_Request, _, #state{chunk = flush_ctrl} = State) -> | |
+ {reply, {wait, "Awaiting flush"}, State}; | |
+ | |
%% Catch all - This can only happen if the application programmer writes | |
%% really bad code that violates the API. | |
handle_call(Request, _Timeout, State) -> | |
@@ -1366,6 +1400,15 @@ handle_user_account(Acc, State) -> | |
%%-------------------------------------------------------------------------- | |
%%-------------------------------------------------------------------------- | |
%% Handling of control connection setup | |
+handle_ctrl_result({pos_size, Size}, State) -> | |
+ ctrl_result_response({pos_size, Size}, State, ok); | |
+ | |
+handle_ctrl_result({pos_complx, _}, State) -> | |
+ handle_caller(State); | |
+ | |
+handle_ctrl_result(_, #state{chunk = flush_ctrl} = State) -> | |
+ {noreply, State#state{chunk = false}}; | |
+ | |
handle_ctrl_result({pos_compl, _}, #state{caller = open, client = From} | |
= State) -> | |
gen_server:reply(From, {ok, self()}), | |
@@ -1631,6 +1674,10 @@ handle_ctrl_result({Status, Lines}, #state{client = From} = State) | |
%%-------------------------------------------------------------------------- | |
%% Help functions to handle_ctrl_result | |
%%-------------------------------------------------------------------------- | |
+ctrl_result_response({pos_size, Size}, #state{client = From} = State, _) -> | |
+ gen_server:reply(From, {ok, Size}), | |
+ {noreply, State#state{client = undefined, caller = undefined}}; | |
+ | |
ctrl_result_response(pos_compl, #state{client = From} = State, _) -> | |
gen_server:reply(From, ok), | |
{noreply, State#state{client = undefined, caller = undefined}}; | |
@@ -1669,6 +1716,13 @@ handle_caller(#state{caller = {recv_bin, RemoteFile}} = State) -> | |
activate_ctrl_connection(State), | |
{noreply, State#state{caller = recv_bin}}; | |
+ | |
+handle_caller(#state{caller = {start_chunk_transfer, Cmd, RemoteFile, Pos}} = | |
+ State) -> | |
+ send_ctrl_message(State, mk_cmd("~s ~p", ["REST", Pos])), | |
+ activate_ctrl_connection(State), | |
+ {noreply, State#state{caller = {start_chunk_transfer, Cmd, RemoteFile}}}; | |
+ | |
handle_caller(#state{caller = {start_chunk_transfer, Cmd, RemoteFile}} = | |
State) -> | |
send_ctrl_message(State, mk_cmd("~s ~s", [Cmd, RemoteFile])), | |
@@ -1924,9 +1978,16 @@ file_write(Bytes, Fd) -> | |
call(GenServer, Msg, Format) -> | |
call(GenServer, Msg, Format, infinity). | |
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) -> | |
+ | |
+ Result = (catch gen_server:call(GenServer, {self(), Msg}, Timeout)), | |
+ | |
+ case Result of | |
+ {wait, _} -> | |
+ receive | |
+ after 1500 -> | |
+ call(GenServer, Msg, Format, Timeout) | |
+ end; | |
+ {ok, Bin} when is_binary(Bin), Format == string -> | |
{ok, binary_to_list(Bin)}; | |
{'EXIT', _} -> | |
{error, eclosed}; | |
diff --git a/lib/inets/src/ftp/ftp_response.erl b/lib/inets/src/ftp/ftp_response.erl | |
index faeacb3..404e3ae 100644 | |
--- a/lib/inets/src/ftp/ftp_response.erl | |
+++ b/lib/inets/src/ftp/ftp_response.erl | |
@@ -175,9 +175,11 @@ error_string(Reason) -> | |
%% Positive Preleminary Reply | |
interpret_status(?POS_PREL,_,_) -> pos_prel; | |
%% Positive Completion Reply | |
+interpret_status(?POS_COMPL,?INFORMATION,3) -> pos_size; | |
interpret_status(?POS_COMPL,_,_) -> pos_compl; | |
%% Positive Intermediate Reply nedd account | |
interpret_status(?POS_INTERM,?AUTH_ACC,2) -> pos_interm_acct; | |
+interpret_status(?POS_INTERM,?FILE_SYSTEM,_) -> pos_complx; | |
%% Positive Intermediate Reply | |
interpret_status(?POS_INTERM,_,_) -> pos_interm; | |
%% No storage area no action taken |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment