2
* lftp - file transfer program
4
* Copyright (c) 1999-2000 by Alexander V. Lukyanov (lav@yars.free.net)
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
/* $Id: FileCopy.cc,v 1.102 2004/03/19 14:20:55 lav Exp $ */
23
/* FileCopyPeer behaviour:
24
1) when suspended, does nothing
25
2) tries to read some data at seek_pos, sets pos to position of Get (get).
26
2.5) tries to position to seek_pos and gets ready to write (put).
27
3) if it cannot seek to seek_pos, changes pos to what it can seek.
28
4) if it knows that it cannot seek to pos>0, CanSeek()==false
29
5) if it knows that it cannot seek to pos==0, CanSeek0()==false
30
6) it tries to get date/size if told to. (get)
31
7) it sets date on the file if eof is reached and date is known (put).
32
8) if put needs size/date before it writes data, NeedSizeDateBeforehand()==true.
39
#include <sys/types.h>
49
#include "OutputJob.h"
51
#define skip_threshold 0x1000
52
#define debug(a) Log::global->Format a
54
ResDecl rate_period ("xfer:rate-period","15", ResMgr::UNumberValidate,ResMgr::NoClosure);
55
ResDecl eta_period ("xfer:eta-period", "120",ResMgr::UNumberValidate,ResMgr::NoClosure);
56
ResDecl max_redir ("xfer:max-redirections", "0",ResMgr::UNumberValidate,ResMgr::NoClosure);
76
if(remove_target_first && !put->FileRemoved())
78
remove_target_first=false;
79
if(put->NeedSizeDateBeforehand() || (cont && put->CanSeek()))
81
if(get->GetSize()==NO_SIZE_YET || get->GetDate()==NO_DATE_YET)
84
get->DontStartTransferYet();
89
goto pre_GET_INFO_WAIT;
92
if(get->GetSize()!=NO_SIZE && get->GetSize()!=NO_SIZE_YET)
93
put->SetEntitySize(get->GetSize());
94
else if(get->GetSize()==NO_SIZE_YET)
96
if(get->GetDate()!=NO_DATE && get->GetDate()!=NO_DATE_YET)
97
put->SetDate(get->GetDate());
98
else if(get->GetDate()==NO_DATE_YET)
104
if(cont && put->CanSeek())
108
if(put->range_start>0 && put->CanSeek())
109
put->Seek(put->range_start);
110
if(get->range_start>0 && get->CanSeek())
111
get->Seek(get->range_start);
123
if(put->GetSeekPos()!=FILE_END && get->GetSize()>=0
124
&& put->GetSeekPos()>=get->GetSize())
126
debug((9,_("copy: destination file is already complete\n")));
127
if(get->GetDate()!=NO_DATE)
128
goto pre_CONFIRM_WAIT; // have to set the date.
129
goto pre_GET_DONE_WAIT;
133
/* now we know if put's seek failed. Seek get accordingly. */
135
get->Seek(put->GetRealPos());
138
get->StartTransfer();
147
SetError(put->ErrorText());
153
SetError(get->ErrorText());
161
debug((9,_("copy: put is broken\n")));
164
SetError(strerror(EPIPE));
167
goto pre_GET_DONE_WAIT;
170
if(put->GetSeekPos()==FILE_END) // put position is not known yet.
176
if(fail_if_cannot_seek && (get->GetRealPos()<get->range_start
177
|| put->GetRealPos()<put->range_start
178
|| get->GetRealPos()!=put->GetRealPos()))
180
SetError(_("seek failed"));
183
if(get->GetSize()>0 && get->GetRealPos()>get->GetSize())
185
get->SetSize(NO_SIZE_YET);
186
get->SetDate(NO_DATE_YET);
190
lbsize=line_buffer->Size();
191
/* check if positions are correct */
192
off_t get_pos=get->GetRealPos()-get->range_start;
193
off_t put_pos=put->GetRealPos()-put->range_start;
194
if(get_pos-lbsize!=put_pos)
197
line_buffer->Empty();
204
if(!get->CanSeek(put->GetRealPos()))
206
// we lose... How about a large buffer?
207
SetError(_("cannot seek on data source"));
210
debug((9,_("copy: put rolled back to %lld, seeking get accordingly\n"),
211
(long long)put->GetRealPos()));
212
debug((10,"copy: get position was %lld\n",
213
(long long)get->GetRealPos()));
214
get->Seek(put->GetRealPos());
217
else // put_pos > get_pos
219
off_t size=get->GetSize();
220
if(size>=0 && put->GetRealPos()>=size)
222
// simulate eof, as we have already have the whole file.
223
debug((9,_("copy: all data received, but get rolled back\n")));
226
off_t skip=put->GetRealPos()-get->GetRealPos();
227
if(!put->CanSeek(get->GetRealPos()) || skip<skip_threshold)
229
// we have to skip some data
239
debug((9,_("copy: get rolled back to %lld, seeking put accordingly\n"),
240
(long long)get->GetRealPos()));
241
put->Seek(get->GetRealPos());
245
if(put->Size()>max_buf)
246
get->Suspend(); // stall the get.
250
debug((10,"copy: get hit eof\n"));
258
put_buf=put->Buffered();
268
if(get->range_limit!=FILE_END && get->range_limit<get->GetRealPos()+s)
269
s=get->range_limit-get->GetRealPos();
275
if(line_buffer->Size()>line_buffer_max)
277
line_buffer->Get(&lb,&ls);
279
line_buffer->Skip(ls);
281
line_buffer->Put(b,s);
285
// now find eol in line_buffer.
286
line_buffer->Get(&lb,&ls);
289
const char *eol=(const char *)memchr(lb,'\n',ls);
292
put->Put(lb,eol-lb+1);
293
line_buffer->Skip(eol-lb+1);
294
line_buffer->Get(&lb,&ls);
304
put_buf=put->Buffered();
308
if(get->range_limit!=FILE_END && get->range_limit<=get->GetRealPos())
310
debug((10,"copy: get reached range limit\n"));
319
line_buffer->Get(&b,&s);
321
line_buffer->Skip(s);
324
put->SetDate(get->GetDate());
325
if(get->GetSize()!=NO_SIZE && get->GetSize()!=NO_SIZE_YET)
326
put->SetEntitySize(get->GetSize());
330
put_eof_pos=put->GetRealPos();
331
debug((10,"copy: waiting for put confirmation\n"));
337
/* check if put position is correct */
338
if(put_eof_pos!=put->GetRealPos() || put->GetSeekPos()==FILE_END)
345
put_buf=put->Buffered();
351
debug((10,"copy: put confirmed store\n"));
365
if(remove_source_later)
368
remove_source_later=false;
372
debug((10,"copy: get is finished - all done\n"));
383
if(get->GetSize()==NO_SIZE_YET || get->GetDate()==NO_DATE_YET)
393
void FileCopy::Init()
401
rate =new Speedometer("xfer:rate-period");
402
rate_for_eta=new Speedometer("xfer:eta-period");
406
fail_if_cannot_seek=false;
408
remove_source_later=false;
409
remove_target_first=false;
414
FileCopy::FileCopy(FileCopyPeer *s,FileCopyPeer *d,bool c)
421
FileCopy::~FileCopy()
428
Delete(rate_for_eta);
430
FileCopy *FileCopy::New(FileCopyPeer *s,FileCopyPeer *d,bool c)
434
res=fxp_create(s,d,c);
437
return new FileCopy(s,d,c);
439
void FileCopy::Suspend()
441
if(get) get->Suspend();
442
if(put) put->Suspend();
445
void FileCopy::Resume()
450
if(get && !(put && put->Size()>=max_buf))
453
if(state!=GET_INFO_WAIT)
470
void FileCopy::Reconfig(const char *s)
474
void FileCopy::SetError(const char *str)
477
error_text=xstrdup(str);
482
void FileCopy::LineBuffered(int s)
485
line_buffer=new Buffer();
489
off_t FileCopy::GetPos()
492
return put->GetRealPos() - put->Buffered();
494
return get->GetRealPos();
498
off_t FileCopy::GetSize()
501
return get->GetSize();
505
int FileCopy::GetPercentDone()
509
off_t size=get->GetSize();
510
if(size==NO_SIZE || size==NO_SIZE_YET)
514
off_t ppos=put->GetRealPos() - put->Buffered() - put->range_start;
517
off_t psize=size-put->range_start;
518
if(put->range_limit!=FILE_END)
519
psize=put->range_limit-put->range_start;
524
return percent(ppos,psize);
526
const char *FileCopy::GetPercentDoneStr()
528
int pct=GetPercentDone();
532
sprintf(buf,"(%d%%) ",pct);
535
float FileCopy::GetRate()
537
if(!rate->Valid() || !put)
541
const char *FileCopy::GetRateStr()
543
if(!rate->Valid() || !put)
545
return rate->GetStrS();
547
off_t FileCopy::GetBytesRemaining()
551
if(get->range_limit==FILE_END)
553
off_t size=get->GetSize();
554
if(size<=0 || size<get->GetRealPos() || !rate_for_eta->Valid())
556
return(size-GetPos());
558
return get->range_limit-GetPos();
560
const char *FileCopy::GetETAStr()
562
off_t b=GetBytesRemaining();
565
return rate_for_eta->GetETAStrSFromSize(b);
567
long FileCopy::GetETA(off_t b)
569
if(b<0 || !rate_for_eta->Valid())
571
return (long)(double(b) / rate_for_eta->Get() + 0.5);
573
const char *FileCopy::GetStatus()
577
const char *get_st=0;
579
get_st=get->GetStatus();
580
const char *put_st=0;
582
put_st=put->GetStatus();
583
if(get_st && get_st[0] && put_st && put_st[0])
584
buf=xasprintf("[%s->%s]",get_st,put_st);
585
else if(get_st && get_st[0])
586
buf=xasprintf("[%s]",get_st);
587
else if(put_st && put_st[0])
588
buf=xasprintf("[%s]",put_st);
594
double FileCopy::GetTimeSpent()
596
if(end_time<start_time)
598
return TimeDiff(end_time,start_time);
601
FgData *FileCopy::GetFgData(bool fg)
603
// NOTE: only one of get/put can have FgData in this implementation.
605
if(get) f=get->GetFgData(fg);
607
if(put) f=put->GetFgData(fg);
611
pid_t FileCopy::GetProcGroup()
614
if(get) p=get->GetProcGroup();
616
if(put) p=put->GetProcGroup();
620
void FileCopy::Kill(int sig)
622
if(get) get->Kill(sig);
623
if(put) put->Kill(sig);
626
// FileCopyPeer implementation
629
void FileCopyPeer::SetSize(off_t s)
632
if(seek_pos==FILE_END)
634
if(size!=NO_SIZE && size!=NO_SIZE_YET)
640
void FileCopyPeer::SetDate(time_t d)
643
if(date==NO_DATE || date==NO_DATE_YET)
649
bool FileCopyPeer::Done()
653
if(eof && in_buffer==0)
666
FileCopyPeer::FileCopyPeer(dir_t m) : IOBuffer(m)
681
range_limit=FILE_END;
687
Suspend(); // don't do anything too early
689
FileCopyPeer::~FileCopyPeer()
693
// FileCopyPeerFA implementation
695
#define super FileCopyPeer
696
int FileCopyPeerFA::Do()
716
if(Done() || Error())
718
if(want_size && size==NO_SIZE_YET && (mode==PUT || !start_transfer))
720
if(session->IsClosed())
724
info.get_time=want_date;
725
session->GetInfoArray(&info,1);
729
if(res==FA::IN_PROGRESS)
751
res=Put_LL(buffer+buffer_ptr,in_buffer);
764
if(date!=NO_DATE && date!=NO_DATE_YET)
765
session->SetDate(date);
766
if(e_size!=NO_SIZE && e_size!=NO_SIZE_YET)
767
session->SetSize(e_size);
768
res=session->StoreStatus();
773
// FIXME: set date for real.
778
else if(res==FA::IN_PROGRESS)
782
if(res==FA::DO_AGAIN)
784
if(res==FA::STORE_FAILED)
786
try_time=session->GetTryTime();
787
retries=session->GetRetries();
788
Log::global->Format(10,"try_time=%ld, retries=%d\n",try_time,retries);
790
if(can_seek && seek_pos>0)
796
SetError(session->StrError(res));
809
res=Get_LL(GET_BUFSIZE);
828
bool FileCopyPeerFA::IOReady()
832
if(seek_pos==FILE_END && size==NO_SIZE_YET)
834
return session->IOReady();
837
void FileCopyPeerFA::Suspend()
844
void FileCopyPeerFA::Resume()
850
const char *FileCopyPeerFA::GetStatus()
852
if(!session->IsOpen())
854
return session->CurrentStatus();
857
void FileCopyPeerFA::Seek(off_t new_pos)
861
super::Seek(new_pos);
863
if(seek_pos==FILE_END)
869
void FileCopyPeerFA::OpenSession()
871
current->Timeout(0); // mark it MOVED.
874
if(size!=NO_SIZE && size!=NO_SIZE_YET && seek_pos>=size && !ascii)
877
debug((10,"copy src: seek past eof (seek_pos=%lld, size=%lld)\n",
878
(long long)seek_pos,(long long)size));
885
if(use_cache && LsCache::Find(session,file,FAmode,&b,&s))
894
memmove(buffer+buffer_ptr,b,s);
903
if(e_size>=0 && size>=0 && seek_pos>=e_size)
905
debug((10,"copy dst: seek past eof (seek_pos=%lld, size=%lld)\n",
906
(long long)seek_pos,(long long)e_size));
908
if(date==NO_DATE || date==NO_DATE_YET)
912
session->Open(file,FAmode,seek_pos);
913
session->SetFileURL(orig_url);
917
session->SetTryTime(try_time);
919
session->SetRetries(retries);
920
if(e_size!=NO_SIZE && e_size!=NO_SIZE_YET)
921
session->SetSize(e_size);
922
if(date!=NO_DATE && date!=NO_DATE_YET)
923
session->SetDate(date);
925
session->RereadManual();
927
session->AsciiTransfer();
928
if(want_size && size==NO_SIZE_YET)
929
session->WantSize(&size);
930
if(want_date && date==NO_DATE_YET)
931
session->WantDate(&date);
934
SaveRollback(seek_pos);
939
pos=seek_pos+in_buffer;
943
void FileCopyPeerFA::RemoveFile()
945
session->Open(file,FA::REMOVE);
949
int FileCopyPeerFA::Get_LL(int len)
953
if(session->IsClosed())
956
if(eof) // OpenSession can set eof=true.
960
if(GetRealPos()!=io_at) // GetRealPos can alter pos.
965
res=session->Read(buffer+buffer_ptr+in_buffer,len);
968
if(res==FA::DO_AGAIN)
970
if(res==FA::FILE_MOVED)
972
// handle redirection.
974
const char *loc_c=session->GetNewLocation();
975
int max_redirections=max_redir.Query(0);
976
if(loc_c && loc_c[0] && max_redirections>0)
978
Log::global->Format(3,_("copy: received redirection to `%s'\n"),loc_c);
979
if(++redirections>max_redirections)
981
SetError(_("Too many redirections"));
984
if(FAmode==FA::QUOTE_CMD)
987
char *loc=alloca_strdup(loc_c);
988
session->Close(); // loc_c is no longer valid.
990
ParsedURL u(loc,true);
995
SessionPool::Reuse(session);
997
session=FileAccess::New(&u);
1001
file=xstrdup(u.path?u.path:"");
1003
orig_url=xstrdup(loc);
1009
int p_ind=url::path_index(orig_url);
1010
char *s=strrchr(orig_url,'/');
1011
int s_ind=s?s-orig_url:-1;
1012
if(p_ind==-1 || s_ind==-1 || s_ind<p_ind)
1013
s_ind=p_ind=strlen(orig_url);
1016
orig_url=(char*)xrealloc(orig_url,p_ind+strlen(loc)+1);
1017
strcpy(orig_url+p_ind,loc);
1021
orig_url=(char*)xrealloc(orig_url,s_ind+1+strlen(loc)+1);
1022
strcpy(orig_url+s_ind,"/");
1023
strcpy(orig_url+s_ind+1,loc);
1027
url::decode_string(loc);
1028
char *slash=strrchr(file,'/');
1030
if(loc[0]!='/' && slash)
1033
new_file=xstrdup(dir_file(file,loc));
1037
new_file=xstrdup(loc);
1048
current->Timeout(0); // retry with new location.
1052
SetError(session->StrError(res));
1058
LsCache::Add(session,file,FAmode,this);
1063
int FileCopyPeerFA::Put_LL(const char *buf,int len)
1065
if(session->IsClosed())
1068
off_t io_at=pos; // GetRealPos can alter pos, save it.
1069
if(GetRealPos()!=io_at)
1075
int res=session->Write(buf,len);
1078
if(res==FA::DO_AGAIN)
1080
if(res==FA::STORE_FAILED)
1082
try_time=session->GetTryTime();
1083
retries=session->GetRetries();
1084
Log::global->Format(10,"try_time=%ld, retries=%d\n",try_time,retries);
1086
if(can_seek && seek_pos>0)
1092
SetError(session->StrError(res));
1095
seek_pos+=res; // mainly to indicate that there was some output.
1099
off_t FileCopyPeerFA::GetRealPos()
1101
if(session->OpenMode()!=FAmode || fxp)
1105
if(pos-in_buffer!=session->GetPos())
1109
pos=session->GetPos();
1116
if(session->GetRealPos()==0 && session->GetPos()>0)
1119
session->SeekReal();
1121
if(pos+in_buffer!=session->GetPos())
1123
SaveRollback(session->GetPos());
1124
pos=session->GetPos();
1130
void FileCopyPeerFA::Init()
1132
FAmode=FA::RETRIEVE;
1145
FileCopyPeerFA::FileCopyPeerFA(FileAccess *s,const char *f,int m)
1146
: FileCopyPeer(m==FA::STORE ? PUT : GET)
1153
if(FAmode==FA::LIST || FAmode==FA::LONG_LIST)
1154
Save(LsCache::SizeLimit());
1156
FileCopyPeerFA::~FileCopyPeerFA()
1162
SessionPool::Reuse(session);
1168
FileCopyPeerFA::FileCopyPeerFA(ParsedURL *u,int m)
1169
: FileCopyPeer(m==FA::STORE ? PUT : GET)
1173
file=xstrdup(u->path);
1174
session=FileAccess::New(u);
1176
orig_url=u->orig_url;
1180
SetError(_("file name missed in URL"));
1184
FileCopyPeerFA *FileCopyPeerFA::New(FileAccess *s,const char *url,int m,bool reuse)
1186
ParsedURL u(url,true);
1190
SessionPool::Reuse(s);
1191
return new FileCopyPeerFA(&u,m);
1193
FileCopyPeerFA *peer=new FileCopyPeerFA(s,url,m);
1195
peer->DontReuseSession();
1199
// FileCopyPeerFDStream
1201
#define super FileCopyPeer
1202
FileCopyPeerFDStream::FileCopyPeerFDStream(FDStream *o,dir_t m)
1206
o=new FDStream(1,"<stdout>");
1210
create_fg_data=true;
1212
can_seek = can_seek0 = stream->can_seek();
1213
if(can_seek && stream->fd!=-1)
1215
seek_base=lseek(stream->fd,0,SEEK_CUR);
1223
if(stream->usesfd(1))
1224
write_allowed=false;
1227
put_ll_timer=new Timer(TimeDiff(0,200));
1229
FileCopyPeerFDStream::~FileCopyPeerFDStream()
1233
delete put_ll_timer;
1236
void FileCopyPeerFDStream::Seek_LL()
1240
if(CanSeek(seek_pos))
1242
if(seek_pos==FILE_END)
1244
seek_pos=lseek(fd,0,SEEK_END);
1254
if(seek_pos>seek_base)
1255
seek_pos-=seek_base;
1263
if(lseek(fd,seek_pos+seek_base,SEEK_SET)==-1)
1280
int FileCopyPeerFDStream::getfd()
1284
int fd=stream->getfd();
1289
SetError(stream->error_text);
1290
current->Timeout(0);
1294
current->TimeoutS(1);
1298
stream->clear_status();
1305
int FileCopyPeerFDStream::Do()
1308
if(Done() || Error())
1317
if(!date_set && date!=NO_DATE && do_set_date)
1319
if(date==NO_DATE_YET)
1323
stream->setmtime(date);
1327
if(stream && delete_stream && !stream->Done())
1339
if(!eof && in_buffer<PUT_LL_MIN
1340
&& put_ll_timer && !put_ll_timer->Stopped())
1342
int res=Put_LL(buffer+buffer_ptr,in_buffer);
1359
while(in_buffer<GET_BUFSIZE)
1361
int res=Get_LL(GET_BUFSIZE);
1380
bool FileCopyPeerFDStream::IOReady()
1382
return seek_pos==pos || stream->fd!=-1;
1385
void FileCopyPeerFDStream::Seek(off_t new_pos)
1390
if(ascii && new_pos!=0)
1392
// it is possible to read file to determine right position,
1393
// but it is costly.
1395
// can_seek0 is still true.
1399
super::Seek(new_pos);
1403
if(seek_pos!=FILE_END)
1405
pos=seek_pos+(mode==PUT)*in_buffer;
1410
off_t s=stream->get_size();
1414
pos=seek_pos+(mode==PUT)*in_buffer;
1419
// ok, have to try getfd.
1429
int FileCopyPeerFDStream::Get_LL(int len)
1437
if((want_date && date==NO_DATE_YET)
1438
|| (want_size && size==NO_SIZE_YET))
1441
if(fstat(fd,&st)==-1)
1448
SetDate(st.st_mtime);
1449
SetSize(st.st_size);
1460
if(need_seek) // this does not combine with ascii.
1461
lseek(fd,seek_base+pos,SEEK_SET);
1463
res=read(fd,buffer+buffer_ptr+in_buffer,len);
1471
if(stream->NonFatalError(errno))
1473
stream->MakeErrorText();
1474
SetError(stream->error_text);
1477
stream->clear_status();
1482
char *p=buffer+buffer_ptr+in_buffer;
1483
for(int i=res; i>0; i--)
1501
int FileCopyPeerFDStream::Put_LL(const char *buf,int len)
1515
// find where line ends.
1519
cr=(const char *)memchr(cr,'\r',len-(cr-buf));
1522
if(cr-buf<len-1 && cr[1]=='\n')
1538
#endif // NATIVE_CRLF
1543
if(need_seek) // this does not combine with ascii.
1544
lseek(fd,seek_base+pos-in_buffer,SEEK_SET);
1546
int res=write(fd,buf,len);
1561
if(stream->NonFatalError(errno))
1563
// in case of full disk, check file correctness.
1564
if(errno==ENOSPC && can_seek)
1567
if(fstat(fd,&st)!=-1)
1569
if(st.st_size<seek_base+pos-in_buffer)
1571
// workaround solaris nfs bug. It can lose data if disk is full.
1572
if(buffer_ptr>=seek_base+pos-in_buffer-buffer_ptr-st.st_size)
1573
UnSkip(seek_base+pos-in_buffer-st.st_size);
1584
stream->MakeErrorText();
1585
SetError(stream->error_text);
1588
stream->clear_status();
1589
if(res==len && skip_cr)
1592
// performance gets worse because of writing a single char,
1593
// but leaving uncomplete line on screen allows mixing it with debug text.
1594
if(write(fd,"\n",1)==1)
1598
put_ll_timer->Reset();
1601
FgData *FileCopyPeerFDStream::GetFgData(bool fg)
1603
if(!delete_stream || !create_fg_data)
1604
return 0; // if we don't own the stream, don't create FgData.
1605
if(stream->GetProcGroup())
1606
return new FgData(stream->GetProcGroup(),fg);
1610
void FileCopyPeerFDStream::RemoveFile()
1613
removing=false; // it is instant.
1616
current->Timeout(0);
1619
const char *FileCopyPeerFDStream::GetStatus()
1621
return stream->status;
1623
void FileCopyPeerFDStream::Kill(int sig)
1629
FileCopyPeerFDStream *FileCopyPeerFDStream::NewPut(const char *file,bool cont)
1631
return new FileCopyPeerFDStream(new FileStream(file,O_WRONLY|O_CREAT
1632
|(cont?0:O_TRUNC)),FileCopyPeer::PUT);
1634
FileCopyPeerFDStream *FileCopyPeerFDStream::NewGet(const char *file)
1636
return new FileCopyPeerFDStream(new FileStream(file,O_RDONLY),
1641
// FileCopyPeerDirList
1642
FileCopyPeerDirList::FileCopyPeerDirList(FA *s,ArgV *v)
1646
dl=session->MakeDirList(v);
1653
FileCopyPeerDirList::~FileCopyPeerDirList()
1656
SessionPool::Reuse(session);
1659
int FileCopyPeerDirList::Do()
1665
SetError(dl->ErrorText());
1680
memmove(buffer+buffer_ptr+in_buffer,b,s);
1686
FileCopyPeerOutputJob::FileCopyPeerOutputJob(OutputJob *new_o)
1693
int FileCopyPeerOutputJob::Put_LL(const char *buf,int len)
1696
if(GetRealPos()!=io_at) // GetRealPos can alter pos.
1707
seek_pos+=len; // mainly to indicate that there was some output.
1711
int FileCopyPeerOutputJob::Do()
1719
if(eof && !in_buffer)
1732
int res=Put_LL(buffer+buffer_ptr,in_buffer);
1747
void FileCopyPeerOutputJob::Fg()
1752
void FileCopyPeerOutputJob::Bg()
1758
// special pointer to creator of ftp/ftp copier. It is init'ed in Ftp class.
1759
FileCopy *(*FileCopy::fxp_create)(FileCopyPeer *src,FileCopyPeer *dst,bool cont);