ftpgetput: add comment about EPSV (extended PASV).
Fix bug where we were using lstat instead of stat. Added many TODOs.
This commit is contained in:
parent
b9ad75fa60
commit
6c615a6c07
@ -68,29 +68,6 @@ static int ftpcmd(const char *s1, const char *s2, FILE *stream, char *buf)
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int xconnect_ftpdata(ftp_host_info_t *server, char *buf)
|
|
||||||
{
|
|
||||||
char *buf_ptr;
|
|
||||||
unsigned port_num;
|
|
||||||
|
|
||||||
/* Response is "NNN garbageN1,N2,N3,N4,P1,P2[)garbage]
|
|
||||||
* Server's IP is N1.N2.N3.N4 (we ignore it)
|
|
||||||
* Server's port for data connection is P1*256+P2 */
|
|
||||||
buf_ptr = strrchr(buf, ')');
|
|
||||||
if (buf_ptr) *buf_ptr = '\0';
|
|
||||||
|
|
||||||
buf_ptr = strrchr(buf, ',');
|
|
||||||
*buf_ptr = '\0';
|
|
||||||
port_num = xatoul_range(buf_ptr + 1, 0, 255);
|
|
||||||
|
|
||||||
buf_ptr = strrchr(buf, ',');
|
|
||||||
*buf_ptr = '\0';
|
|
||||||
port_num += xatoul_range(buf_ptr + 1, 0, 255) * 256;
|
|
||||||
|
|
||||||
set_nport(server->lsa, htons(port_num));
|
|
||||||
return xconnect_stream(server->lsa);
|
|
||||||
}
|
|
||||||
|
|
||||||
static FILE *ftp_login(ftp_host_info_t *server)
|
static FILE *ftp_login(ftp_host_info_t *server)
|
||||||
{
|
{
|
||||||
FILE *control_stream;
|
FILE *control_stream;
|
||||||
@ -125,6 +102,29 @@ static FILE *ftp_login(ftp_host_info_t *server)
|
|||||||
return control_stream;
|
return control_stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int xconnect_ftpdata(ftp_host_info_t *server, char *buf)
|
||||||
|
{
|
||||||
|
char *buf_ptr;
|
||||||
|
unsigned port_num;
|
||||||
|
|
||||||
|
/* Response is "NNN garbageN1,N2,N3,N4,P1,P2[)garbage]
|
||||||
|
* Server's IP is N1.N2.N3.N4 (we ignore it)
|
||||||
|
* Server's port for data connection is P1*256+P2 */
|
||||||
|
buf_ptr = strrchr(buf, ')');
|
||||||
|
if (buf_ptr) *buf_ptr = '\0';
|
||||||
|
|
||||||
|
buf_ptr = strrchr(buf, ',');
|
||||||
|
*buf_ptr = '\0';
|
||||||
|
port_num = xatoul_range(buf_ptr + 1, 0, 255);
|
||||||
|
|
||||||
|
buf_ptr = strrchr(buf, ',');
|
||||||
|
*buf_ptr = '\0';
|
||||||
|
port_num += xatoul_range(buf_ptr + 1, 0, 255) * 256;
|
||||||
|
|
||||||
|
set_nport(server->lsa, htons(port_num));
|
||||||
|
return xconnect_stream(server->lsa);
|
||||||
|
}
|
||||||
|
|
||||||
#if !ENABLE_FTPGET
|
#if !ENABLE_FTPGET
|
||||||
int ftp_receive(ftp_host_info_t *server, FILE *control_stream,
|
int ftp_receive(ftp_host_info_t *server, FILE *control_stream,
|
||||||
const char *local_path, char *server_path);
|
const char *local_path, char *server_path);
|
||||||
@ -141,7 +141,25 @@ int ftp_receive(ftp_host_info_t *server, FILE *control_stream,
|
|||||||
int fd_local = -1;
|
int fd_local = -1;
|
||||||
off_t beg_range = 0;
|
off_t beg_range = 0;
|
||||||
|
|
||||||
/* Connect to the data socket */
|
/*
|
||||||
|
TODO: PASV command will not work for IPv6. RFC2428 describes
|
||||||
|
IPv6-capable "extended PASV" - EPSV.
|
||||||
|
|
||||||
|
"EPSV [protocol]" asks server to bind to and listen on a data port
|
||||||
|
in specified protocol. Protocol is 1 for IPv4, 2 for IPv6.
|
||||||
|
If not specified, defaults to "same as used for control connection".
|
||||||
|
If server understood you, it should answer "229 <some text>(|||port|)"
|
||||||
|
where "|" are literal pipe chars and "port" is ASCII decimal port#.
|
||||||
|
|
||||||
|
There is also an IPv6-capable replacement for PORT (EPRT),
|
||||||
|
but we don't need that.
|
||||||
|
|
||||||
|
TODO: fold in sending of PASV/EPSV and parsing of response into
|
||||||
|
xconnect_ftpdata(). (Also, need to stop ignoring IP address in PASV
|
||||||
|
response).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* connect to the data socket */
|
||||||
if (ftpcmd("PASV", NULL, control_stream, buf) != 227) {
|
if (ftpcmd("PASV", NULL, control_stream, buf) != 227) {
|
||||||
ftp_die("PASV", buf);
|
ftp_die("PASV", buf);
|
||||||
}
|
}
|
||||||
@ -162,8 +180,9 @@ int ftp_receive(ftp_host_info_t *server, FILE *control_stream,
|
|||||||
|
|
||||||
if (do_continue) {
|
if (do_continue) {
|
||||||
struct stat sbuf;
|
struct stat sbuf;
|
||||||
if (lstat(local_path, &sbuf) < 0) {
|
/* lstat would be wrong here! */
|
||||||
bb_perror_msg_and_die("lstat");
|
if (stat(local_path, &sbuf) < 0) {
|
||||||
|
bb_perror_msg_and_die("stat");
|
||||||
}
|
}
|
||||||
if (sbuf.st_size > 0) {
|
if (sbuf.st_size > 0) {
|
||||||
beg_range = sbuf.st_size;
|
beg_range = sbuf.st_size;
|
||||||
@ -186,23 +205,26 @@ int ftp_receive(ftp_host_info_t *server, FILE *control_stream,
|
|||||||
ftp_die("RETR", buf);
|
ftp_die("RETR", buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* only make a local file if we know that one exists on the remote server */
|
/* make local _after_ we know that remote file exists */
|
||||||
if (fd_local == -1) {
|
if (fd_local == -1) {
|
||||||
if (do_continue) {
|
fd_local = xopen(local_path,
|
||||||
fd_local = xopen(local_path, O_APPEND | O_WRONLY);
|
do_continue ? (O_APPEND | O_WRONLY)
|
||||||
} else {
|
: (O_CREAT | O_TRUNC | O_WRONLY)
|
||||||
fd_local = xopen(local_path, O_CREAT | O_TRUNC | O_WRONLY);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy the file */
|
// TODO: merge tail of ftp_receive and ftp_send starting from here
|
||||||
if (filesize != -1) {
|
|
||||||
|
/* copy the file */
|
||||||
|
if (filesize != -1) { // NEVER HAPPENS, filesize is always -1
|
||||||
if (bb_copyfd_size(fd_data, fd_local, filesize) == -1)
|
if (bb_copyfd_size(fd_data, fd_local, filesize) == -1)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
} else {
|
} else {
|
||||||
if (bb_copyfd_eof(fd_data, fd_local) == -1)
|
if (bb_copyfd_eof(fd_data, fd_local) == -1) {
|
||||||
|
/* error msg is already printed by bb_copyfd_eof */
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* close it all down */
|
/* close it all down */
|
||||||
close(fd_data);
|
close(fd_data);
|
||||||
@ -229,7 +251,7 @@ int ftp_send(ftp_host_info_t *server, FILE *control_stream,
|
|||||||
int fd_local;
|
int fd_local;
|
||||||
int response;
|
int response;
|
||||||
|
|
||||||
/* Connect to the data socket */
|
/* connect to the data socket */
|
||||||
if (ftpcmd("PASV", NULL, control_stream, buf) != 227) {
|
if (ftpcmd("PASV", NULL, control_stream, buf) != 227) {
|
||||||
ftp_die("PASV", buf);
|
ftp_die("PASV", buf);
|
||||||
}
|
}
|
||||||
@ -241,6 +263,9 @@ int ftp_send(ftp_host_info_t *server, FILE *control_stream,
|
|||||||
fd_local = xopen(local_path, O_RDONLY);
|
fd_local = xopen(local_path, O_RDONLY);
|
||||||
fstat(fd_local, &sbuf);
|
fstat(fd_local, &sbuf);
|
||||||
|
|
||||||
|
// TODO: do we really need to send ALLO? It's ancient...
|
||||||
|
// Doesn't it break "ftpput .. .. fifo" too?
|
||||||
|
|
||||||
sprintf(buf, "ALLO %"OFF_FMT"u", sbuf.st_size);
|
sprintf(buf, "ALLO %"OFF_FMT"u", sbuf.st_size);
|
||||||
response = ftpcmd(buf, NULL, control_stream, buf);
|
response = ftpcmd(buf, NULL, control_stream, buf);
|
||||||
switch (response) {
|
switch (response) {
|
||||||
@ -248,7 +273,7 @@ int ftp_send(ftp_host_info_t *server, FILE *control_stream,
|
|||||||
case 202:
|
case 202:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
close(fd_local);
|
close(fd_local); // TODO: why bother?
|
||||||
ftp_die("ALLO", buf);
|
ftp_die("ALLO", buf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -259,13 +284,14 @@ int ftp_send(ftp_host_info_t *server, FILE *control_stream,
|
|||||||
case 150:
|
case 150:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
close(fd_local);
|
close(fd_local); // TODO: why bother?
|
||||||
ftp_die("STOR", buf);
|
ftp_die("STOR", buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* transfer the file */
|
/* transfer the file */
|
||||||
if (bb_copyfd_eof(fd_local, fd_data) == -1) {
|
if (bb_copyfd_eof(fd_local, fd_data) == -1) {
|
||||||
exit(EXIT_FAILURE);
|
/* error msg is already printed by bb_copyfd_eof */
|
||||||
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* close it all down */
|
/* close it all down */
|
||||||
|
Loading…
Reference in New Issue
Block a user