aboutsummaryrefslogtreecommitdiff
path: root/networking/ftpgetput.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-03-28 22:11:49 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-03-28 22:11:49 +0000
commit6c615a6c0718667d64fa45bb3169ec7d8a1c0ad5 (patch)
treed7f3d2ad8722c78c18b012170f1ac35e63c4d368 /networking/ftpgetput.c
parentb9ad75fa602dd72b042b2ea08ce86da50746ab30 (diff)
downloadbusybox-w32-6c615a6c0718667d64fa45bb3169ec7d8a1c0ad5.tar.gz
busybox-w32-6c615a6c0718667d64fa45bb3169ec7d8a1c0ad5.tar.bz2
busybox-w32-6c615a6c0718667d64fa45bb3169ec7d8a1c0ad5.zip
ftpgetput: add comment about EPSV (extended PASV).
Fix bug where we were using lstat instead of stat. Added many TODOs.
Diffstat (limited to 'networking/ftpgetput.c')
-rw-r--r--networking/ftpgetput.c104
1 files changed, 65 insertions, 39 deletions
diff --git a/networking/ftpgetput.c b/networking/ftpgetput.c
index a1ee05426..3a9930cd7 100644
--- a/networking/ftpgetput.c
+++ b/networking/ftpgetput.c
@@ -68,29 +68,6 @@ static int ftpcmd(const char *s1, const char *s2, FILE *stream, char *buf)
68 return n; 68 return n;
69} 69}
70 70
71static int xconnect_ftpdata(ftp_host_info_t *server, char *buf)
72{
73 char *buf_ptr;
74 unsigned port_num;
75
76 /* Response is "NNN garbageN1,N2,N3,N4,P1,P2[)garbage]
77 * Server's IP is N1.N2.N3.N4 (we ignore it)
78 * Server's port for data connection is P1*256+P2 */
79 buf_ptr = strrchr(buf, ')');
80 if (buf_ptr) *buf_ptr = '\0';
81
82 buf_ptr = strrchr(buf, ',');
83 *buf_ptr = '\0';
84 port_num = xatoul_range(buf_ptr + 1, 0, 255);
85
86 buf_ptr = strrchr(buf, ',');
87 *buf_ptr = '\0';
88 port_num += xatoul_range(buf_ptr + 1, 0, 255) * 256;
89
90 set_nport(server->lsa, htons(port_num));
91 return xconnect_stream(server->lsa);
92}
93
94static FILE *ftp_login(ftp_host_info_t *server) 71static FILE *ftp_login(ftp_host_info_t *server)
95{ 72{
96 FILE *control_stream; 73 FILE *control_stream;
@@ -125,6 +102,29 @@ static FILE *ftp_login(ftp_host_info_t *server)
125 return control_stream; 102 return control_stream;
126} 103}
127 104
105static int xconnect_ftpdata(ftp_host_info_t *server, char *buf)
106{
107 char *buf_ptr;
108 unsigned port_num;
109
110 /* Response is "NNN garbageN1,N2,N3,N4,P1,P2[)garbage]
111 * Server's IP is N1.N2.N3.N4 (we ignore it)
112 * Server's port for data connection is P1*256+P2 */
113 buf_ptr = strrchr(buf, ')');
114 if (buf_ptr) *buf_ptr = '\0';
115
116 buf_ptr = strrchr(buf, ',');
117 *buf_ptr = '\0';
118 port_num = xatoul_range(buf_ptr + 1, 0, 255);
119
120 buf_ptr = strrchr(buf, ',');
121 *buf_ptr = '\0';
122 port_num += xatoul_range(buf_ptr + 1, 0, 255) * 256;
123
124 set_nport(server->lsa, htons(port_num));
125 return xconnect_stream(server->lsa);
126}
127
128#if !ENABLE_FTPGET 128#if !ENABLE_FTPGET
129int ftp_receive(ftp_host_info_t *server, FILE *control_stream, 129int ftp_receive(ftp_host_info_t *server, FILE *control_stream,
130 const char *local_path, char *server_path); 130 const char *local_path, char *server_path);
@@ -141,7 +141,25 @@ int ftp_receive(ftp_host_info_t *server, FILE *control_stream,
141 int fd_local = -1; 141 int fd_local = -1;
142 off_t beg_range = 0; 142 off_t beg_range = 0;
143 143
144 /* Connect to the data socket */ 144/*
145TODO: PASV command will not work for IPv6. RFC2428 describes
146IPv6-capable "extended PASV" - EPSV.
147
148"EPSV [protocol]" asks server to bind to and listen on a data port
149in specified protocol. Protocol is 1 for IPv4, 2 for IPv6.
150If not specified, defaults to "same as used for control connection".
151If server understood you, it should answer "229 <some text>(|||port|)"
152where "|" are literal pipe chars and "port" is ASCII decimal port#.
153
154There is also an IPv6-capable replacement for PORT (EPRT),
155but we don't need that.
156
157TODO: fold in sending of PASV/EPSV and parsing of response into
158xconnect_ftpdata(). (Also, need to stop ignoring IP address in PASV
159response).
160*/
161
162 /* connect to the data socket */
145 if (ftpcmd("PASV", NULL, control_stream, buf) != 227) { 163 if (ftpcmd("PASV", NULL, control_stream, buf) != 227) {
146 ftp_die("PASV", buf); 164 ftp_die("PASV", buf);
147 } 165 }
@@ -162,8 +180,9 @@ int ftp_receive(ftp_host_info_t *server, FILE *control_stream,
162 180
163 if (do_continue) { 181 if (do_continue) {
164 struct stat sbuf; 182 struct stat sbuf;
165 if (lstat(local_path, &sbuf) < 0) { 183 /* lstat would be wrong here! */
166 bb_perror_msg_and_die("lstat"); 184 if (stat(local_path, &sbuf) < 0) {
185 bb_perror_msg_and_die("stat");
167 } 186 }
168 if (sbuf.st_size > 0) { 187 if (sbuf.st_size > 0) {
169 beg_range = sbuf.st_size; 188 beg_range = sbuf.st_size;
@@ -186,22 +205,25 @@ int ftp_receive(ftp_host_info_t *server, FILE *control_stream,
186 ftp_die("RETR", buf); 205 ftp_die("RETR", buf);
187 } 206 }
188 207
189 /* only make a local file if we know that one exists on the remote server */ 208 /* make local _after_ we know that remote file exists */
190 if (fd_local == -1) { 209 if (fd_local == -1) {
191 if (do_continue) { 210 fd_local = xopen(local_path,
192 fd_local = xopen(local_path, O_APPEND | O_WRONLY); 211 do_continue ? (O_APPEND | O_WRONLY)
193 } else { 212 : (O_CREAT | O_TRUNC | O_WRONLY)
194 fd_local = xopen(local_path, O_CREAT | O_TRUNC | O_WRONLY); 213 );
195 }
196 } 214 }
197 215
198 /* Copy the file */ 216// TODO: merge tail of ftp_receive and ftp_send starting from here
199 if (filesize != -1) { 217
218 /* copy the file */
219 if (filesize != -1) { // NEVER HAPPENS, filesize is always -1
200 if (bb_copyfd_size(fd_data, fd_local, filesize) == -1) 220 if (bb_copyfd_size(fd_data, fd_local, filesize) == -1)
201 return EXIT_FAILURE; 221 return EXIT_FAILURE;
202 } else { 222 } else {
203 if (bb_copyfd_eof(fd_data, fd_local) == -1) 223 if (bb_copyfd_eof(fd_data, fd_local) == -1) {
224 /* error msg is already printed by bb_copyfd_eof */
204 return EXIT_FAILURE; 225 return EXIT_FAILURE;
226 }
205 } 227 }
206 228
207 /* close it all down */ 229 /* close it all down */
@@ -229,7 +251,7 @@ int ftp_send(ftp_host_info_t *server, FILE *control_stream,
229 int fd_local; 251 int fd_local;
230 int response; 252 int response;
231 253
232 /* Connect to the data socket */ 254 /* connect to the data socket */
233 if (ftpcmd("PASV", NULL, control_stream, buf) != 227) { 255 if (ftpcmd("PASV", NULL, control_stream, buf) != 227) {
234 ftp_die("PASV", buf); 256 ftp_die("PASV", buf);
235 } 257 }
@@ -241,6 +263,9 @@ int ftp_send(ftp_host_info_t *server, FILE *control_stream,
241 fd_local = xopen(local_path, O_RDONLY); 263 fd_local = xopen(local_path, O_RDONLY);
242 fstat(fd_local, &sbuf); 264 fstat(fd_local, &sbuf);
243 265
266// TODO: do we really need to send ALLO? It's ancient...
267// Doesn't it break "ftpput .. .. fifo" too?
268
244 sprintf(buf, "ALLO %"OFF_FMT"u", sbuf.st_size); 269 sprintf(buf, "ALLO %"OFF_FMT"u", sbuf.st_size);
245 response = ftpcmd(buf, NULL, control_stream, buf); 270 response = ftpcmd(buf, NULL, control_stream, buf);
246 switch (response) { 271 switch (response) {
@@ -248,7 +273,7 @@ int ftp_send(ftp_host_info_t *server, FILE *control_stream,
248 case 202: 273 case 202:
249 break; 274 break;
250 default: 275 default:
251 close(fd_local); 276 close(fd_local); // TODO: why bother?
252 ftp_die("ALLO", buf); 277 ftp_die("ALLO", buf);
253 break; 278 break;
254 } 279 }
@@ -259,13 +284,14 @@ int ftp_send(ftp_host_info_t *server, FILE *control_stream,
259 case 150: 284 case 150:
260 break; 285 break;
261 default: 286 default:
262 close(fd_local); 287 close(fd_local); // TODO: why bother?
263 ftp_die("STOR", buf); 288 ftp_die("STOR", buf);
264 } 289 }
265 290
266 /* transfer the file */ 291 /* transfer the file */
267 if (bb_copyfd_eof(fd_local, fd_data) == -1) { 292 if (bb_copyfd_eof(fd_local, fd_data) == -1) {
268 exit(EXIT_FAILURE); 293 /* error msg is already printed by bb_copyfd_eof */
294 return EXIT_FAILURE;
269 } 295 }
270 296
271 /* close it all down */ 297 /* close it all down */