diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-03-28 22:11:49 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-03-28 22:11:49 +0000 |
commit | 6c615a6c0718667d64fa45bb3169ec7d8a1c0ad5 (patch) | |
tree | d7f3d2ad8722c78c18b012170f1ac35e63c4d368 /networking/ftpgetput.c | |
parent | b9ad75fa602dd72b042b2ea08ce86da50746ab30 (diff) | |
download | busybox-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.c | 104 |
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 | ||
71 | static 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 | |||
94 | static FILE *ftp_login(ftp_host_info_t *server) | 71 | static 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 | ||
105 | static 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 |
129 | int ftp_receive(ftp_host_info_t *server, FILE *control_stream, | 129 | int 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 | /* |
145 | TODO: PASV command will not work for IPv6. RFC2428 describes | ||
146 | IPv6-capable "extended PASV" - EPSV. | ||
147 | |||
148 | "EPSV [protocol]" asks server to bind to and listen on a data port | ||
149 | in specified protocol. Protocol is 1 for IPv4, 2 for IPv6. | ||
150 | If not specified, defaults to "same as used for control connection". | ||
151 | If server understood you, it should answer "229 <some text>(|||port|)" | ||
152 | where "|" are literal pipe chars and "port" is ASCII decimal port#. | ||
153 | |||
154 | There is also an IPv6-capable replacement for PORT (EPRT), | ||
155 | but we don't need that. | ||
156 | |||
157 | TODO: fold in sending of PASV/EPSV and parsing of response into | ||
158 | xconnect_ftpdata(). (Also, need to stop ignoring IP address in PASV | ||
159 | response). | ||
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 */ |