newer patch to ftp.erl
Luke Gorrie
luke@REDACTED
Mon Jan 13 10:59:13 CET 2003
Here's an update of a previously posted patch to ftp.erl, against
inets 2.6.7. The patch is to add incremental (chunked) file
downloading. This newer patch fixes a bug in the old one (on
incremental download of a non-existent file), and changes an io:format
into an error_logger call.
Also at http://www.bluetail.com/~luke/misc/erlang/otp_ftp.patch
-Luke
-------------- next part --------------
--- ftp.erl 2003-01-07 08:15:46.000000000 +0100
+++ /home/luke/misc/ftp.erl 2003-01-13 10:35:01.000000000 +0100
@@ -13,7 +13,7 @@
%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
%% AB. All Rights Reserved.''
%%
-%% $Id: ftp.erl,v 1.1.1.3 2002/10/08 07:42:22 magnus Exp $
+%% $Id: ftp.erl,v 1.1.2.3 2002/12/05 13:49:15 klacke Exp $
%%
-module(ftp).
@@ -33,7 +33,7 @@
-export([cd/2, close/1, delete/2, formaterror/1, help/0,
lcd/2, lpwd/1, ls/1, ls/2, mkdir/2, nlist/1,
nlist/2, open/1, open/2, open/3, pwd/1, recv/2, recv/3,
- recv_bin/2, rename/3, rmdir/2, send/2, send/3,
+ recv_bin/2, recv_chunk/2, rename/3, rmdir/2, send/2, send/3,
send_bin/3, send_chunk/2, send_chunk_end/1,
send_chunk_start/2, type/2, user/3,user/4,account/2,
append/3,append/2,append_bin/3,
@@ -233,6 +233,11 @@
recv_bin(Pid, RFile) ->
gen_server:call(Pid, {recv_bin, RFile}, infinity).
+recv_chunk(Pid, RFile) ->
+ Ref = make_ref(),
+ gen_server:cast(Pid, {recv_chunk, self(), Ref, RFile}),
+ Ref.
+
%% send(Pid, LFile [, RFile])
%%
%% Purpose: Transfer file to remote server.
@@ -530,7 +535,7 @@
{error,enotconn}->
?STOP_RET(econn);
Error ->
- io:format("~p",[Error]),
+ error_logger:info_msg("~p",[Error]),
{reply, {error, eacct}, State}
end;
@@ -779,6 +784,22 @@
handle_call(_, _From, State) when State#state.chunk == true ->
{reply, {error, echunk}, State}.
+handle_cast({recv_chunk, From, Ref, RFile}, State) ->
+ #state{csock = CSock, ldir = LDir} = State,
+ LSock = listen_data(CSock, binary),
+ case ctrl_cmd(CSock, "RETR ~s", [RFile]) of
+ pos_prel ->
+ DSock = accept_data(LSock),
+ Reply = recv_chunk(DSock,CSock,From,Ref),
+ sock_close(DSock),
+ {noreply, State};
+ {error, enotconn} ->
+ ?STOP_RET(econn);
+ Err ->
+ From ! {ftp, Ref, {finished, {error, epath}}},
+ {noreply, State}
+ end;
+
handle_cast(Msg, State) ->
{noreply, State}.
@@ -944,6 +965,42 @@
%% --------------------------------------------------
+%% recv_chunk(DSock, CSock, From, Ref) -> ok
+%% Streams data from DSock to the From process with this protocol:
+%% From ! {ftp, Ref, {data, Pid, Bin}}
+%% From ? {ftp_ack, Ref}
+%% ...
+%% From ! {ftp, Ref, {finished, Result}}
+
+recv_chunk(DSock,CSock, From, Ref) ->
+ Result = recv_chunk1(recv_chunk2(DSock,From,Ref,0),CSock),
+ From ! {ftp, Ref, {finished, Result}}.
+
+recv_chunk1(Reply,Sock) ->
+ case result(Sock) of
+ pos_compl -> Reply;
+ _ -> {error, epath}
+ end.
+
+recv_chunk2(Sock, From, Ref, ?OPER_TIMEOUT) ->
+ sock_close(Sock),
+ {error,eclosed};
+recv_chunk2(Sock, From, Ref, Retry) ->
+ case sock_read(Sock) of
+ {ok, Bin} ->
+ From ! {ftp, Ref, {data, self(), Bin}},
+ receive
+ {ftp_ack, Ref} ->
+ recv_chunk2(Sock, From, Ref, 0)
+ end;
+ {error, timeout} ->
+ recv_chunk2(Sock, From, Ref, Retry+1);
+ {closed, _Why} ->
+ ok
+ end.
+
+%% --------------------------------------------------
+
%% recv_binary(Sock) = {ok, Bin}
%%
%recv_binary(Sock) ->
More information about the erlang-questions
mailing list