Deleted Added
full compact
ftp.c (135546) ftp.c (148986)
1/*-
2 * Copyright (c) 1998-2004 Dag-Erling Co�dan Sm�rgrav
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 13 unchanged lines hidden (view full) ---

22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1998-2004 Dag-Erling Co�dan Sm�rgrav
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 13 unchanged lines hidden (view full) ---

22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD: head/lib/libfetch/ftp.c 135546 2004-09-21 18:35:21Z des $");
30__FBSDID("$FreeBSD: head/lib/libfetch/ftp.c 148986 2005-08-12 12:48:50Z des $");
31
32/*
33 * Portions of this code were taken from or based on ftpio.c:
34 *
35 * ----------------------------------------------------------------------------
36 * "THE BEER-WARE LICENSE" (Revision 42):
37 * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
38 * can do whatever you want with this stuff. If we meet some day, and you think

--- 46 unchanged lines hidden (view full) ---

85#define FTP_FILE_STATUS 213
86#define FTP_SERVICE_READY 220
87#define FTP_TRANSFER_COMPLETE 226
88#define FTP_PASSIVE_MODE 227
89#define FTP_LPASSIVE_MODE 228
90#define FTP_EPASSIVE_MODE 229
91#define FTP_LOGGED_IN 230
92#define FTP_FILE_ACTION_OK 250
31
32/*
33 * Portions of this code were taken from or based on ftpio.c:
34 *
35 * ----------------------------------------------------------------------------
36 * "THE BEER-WARE LICENSE" (Revision 42):
37 * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
38 * can do whatever you want with this stuff. If we meet some day, and you think

--- 46 unchanged lines hidden (view full) ---

85#define FTP_FILE_STATUS 213
86#define FTP_SERVICE_READY 220
87#define FTP_TRANSFER_COMPLETE 226
88#define FTP_PASSIVE_MODE 227
89#define FTP_LPASSIVE_MODE 228
90#define FTP_EPASSIVE_MODE 229
91#define FTP_LOGGED_IN 230
92#define FTP_FILE_ACTION_OK 250
93#define FTP_DIRECTORY_CREATED 257 /* multiple meanings */
94#define FTP_FILE_CREATED 257 /* multiple meanings */
95#define FTP_WORKING_DIRECTORY 257 /* multiple meanings */
93#define FTP_NEED_PASSWORD 331
94#define FTP_NEED_ACCOUNT 332
95#define FTP_FILE_OK 350
96#define FTP_SYNTAX_ERROR 500
97#define FTP_PROTOCOL_ERROR 999
98
99static struct url cached_host;
100static conn_t *cached_connection;

--- 93 unchanged lines hidden (view full) ---

194
195 return (_ftp_chkerr(conn));
196}
197
198/*
199 * Return a pointer to the filename part of a path
200 */
201static const char *
96#define FTP_NEED_PASSWORD 331
97#define FTP_NEED_ACCOUNT 332
98#define FTP_FILE_OK 350
99#define FTP_SYNTAX_ERROR 500
100#define FTP_PROTOCOL_ERROR 999
101
102static struct url cached_host;
103static conn_t *cached_connection;

--- 93 unchanged lines hidden (view full) ---

197
198 return (_ftp_chkerr(conn));
199}
200
201/*
202 * Return a pointer to the filename part of a path
203 */
204static const char *
202_ftp_filename(const char *file)
205_ftp_filename(const char *file, int *len, int *type)
203{
206{
204 char *s;
207 const char *s;
205
206 if ((s = strrchr(file, '/')) == NULL)
208
209 if ((s = strrchr(file, '/')) == NULL)
207 return (file);
210 s = file;
208 else
211 else
209 return (s + 1);
212 s = s + 1;
213 *len = strlen(s);
214 if (*len > 7 && strncmp(s + *len - 7, ";type=", 6) == 0) {
215 *type = s[*len - 1];
216 *len -= 7;
217 } else {
218 *type = '\0';
219 }
220 return (s);
210}
211
212/*
221}
222
223/*
224 * Get current working directory from the reply to a CWD, PWD or CDUP
225 * command.
226 */
227static int
228_ftp_pwd(conn_t *conn, char *pwd, size_t pwdlen)
229{
230 char *src, *dst, *end;
231 int q;
232
233 if (conn->err != FTP_WORKING_DIRECTORY &&
234 conn->err != FTP_FILE_ACTION_OK)
235 return (FTP_PROTOCOL_ERROR);
236 end = conn->buf + conn->buflen;
237 src = conn->buf + 4;
238 if (src >= end || *src++ != '"')
239 return (FTP_PROTOCOL_ERROR);
240 for (q = 0, dst = pwd; src < end && pwdlen--; ++src) {
241 if (!q && *src == '"')
242 q = 1;
243 else if (q && *src != '"')
244 break;
245 else if (q)
246 *dst++ = '"', q = 0;
247 else
248 *dst++ = *src;
249 }
250 if (!pwdlen)
251 return (FTP_PROTOCOL_ERROR);
252 *dst = '\0';
253#if 0
254 DEBUG(fprintf(stderr, "pwd: [%s]\n", pwd));
255#endif
256 return (FTP_OK);
257}
258
259/*
213 * Change working directory to the directory that contains the specified
214 * file.
215 */
216static int
217_ftp_cwd(conn_t *conn, const char *file)
218{
260 * Change working directory to the directory that contains the specified
261 * file.
262 */
263static int
264_ftp_cwd(conn_t *conn, const char *file)
265{
219 char *s;
220 int e;
266 const char *beg, *end;
267 char pwd[PATH_MAX];
268 int e, i, len;
221
269
222 if ((s = strrchr(file, '/')) == NULL || s == file) {
223 e = _ftp_cmd(conn, "CWD /");
224 } else {
225 e = _ftp_cmd(conn, "CWD %.*s", s - file, file);
226 }
227 if (e != FTP_FILE_ACTION_OK) {
270 if ((end = strrchr(file, '/')) == NULL)
271 return (0);
272 if ((e = _ftp_cmd(conn, "PWD")) != FTP_WORKING_DIRECTORY ||
273 (e = _ftp_pwd(conn, pwd, sizeof(pwd))) != FTP_OK) {
228 _ftp_seterr(e);
229 return (-1);
230 }
274 _ftp_seterr(e);
275 return (-1);
276 }
277 for (;;) {
278 len = strlen(pwd);
279 /* look for a common prefix */
280 for (i = 0; i <= len && i <= end - file; ++i)
281 if (pwd[i] != file[i])
282 break;
283#if 0
284 DEBUG(fprintf(stderr, "have: [%.*s|%s]\n", i, pwd, pwd + i));
285 DEBUG(fprintf(stderr, "want: [%.*s|%s]\n", i, file, file + i));
286#endif
287 if (pwd[i] == '\0' && (file[i - 1] == '/' || file[i] == '/'))
288 break;
289 if ((e = _ftp_cmd(conn, "CDUP")) != FTP_FILE_ACTION_OK ||
290 (e = _ftp_cmd(conn, "PWD")) != FTP_WORKING_DIRECTORY ||
291 (e = _ftp_pwd(conn, pwd, sizeof(pwd))) != FTP_OK) {
292 _ftp_seterr(e);
293 return (-1);
294 }
295 }
296 for (beg = file + i; beg < end; beg = file + i + 1) {
297 for (++i; file + i < end && file[i] != '/'; ++i)
298 /* nothing */ ;
299 e = _ftp_cmd(conn, "CWD %.*s", file + i - beg, beg);
300 if (e != FTP_FILE_ACTION_OK) {
301 _ftp_seterr(e);
302 return (-1);
303 }
304 }
231 return (0);
232}
233
234/*
305 return (0);
306}
307
308/*
309 * Set transfer mode and data type
310 */
311static int
312_ftp_mode_type(conn_t *conn, int mode, int type)
313{
314 int e;
315
316 switch (mode) {
317 case 0:
318 case 's':
319 mode = 'S';
320 case 'S':
321 break;
322 default:
323 return (FTP_PROTOCOL_ERROR);
324 }
325 if ((e = _ftp_cmd(conn, "MODE %c", mode)) != FTP_OK)
326 return (e);
327
328 switch (type) {
329 case 0:
330 case 'i':
331 type = 'I';
332 case 'I':
333 break;
334 case 'a':
335 type = 'A';
336 case 'A':
337 break;
338 case 'd':
339 type = 'D';
340 case 'D':
341 /* can't handle yet */
342 default:
343 return (FTP_PROTOCOL_ERROR);
344 }
345 if ((e = _ftp_cmd(conn, "TYPE %c", type)) != FTP_OK)
346 return (e);
347
348 return (FTP_OK);
349}
350
351/*
235 * Request and parse file stats
236 */
237static int
238_ftp_stat(conn_t *conn, const char *file, struct url_stat *us)
239{
240 char *ln;
352 * Request and parse file stats
353 */
354static int
355_ftp_stat(conn_t *conn, const char *file, struct url_stat *us)
356{
357 char *ln;
241 const char *s;
358 const char *filename;
359 int filenamelen, type;
242 struct tm tm;
243 time_t t;
244 int e;
245
246 us->size = -1;
247 us->atime = us->mtime = 0;
248
360 struct tm tm;
361 time_t t;
362 int e;
363
364 us->size = -1;
365 us->atime = us->mtime = 0;
366
249 if ((s = strrchr(file, '/')) == NULL)
250 s = file;
251 else
252 ++s;
367 filename = _ftp_filename(file, &filenamelen, &type);
253
368
254 if ((e = _ftp_cmd(conn, "SIZE %s", s)) != FTP_FILE_STATUS) {
369 if ((e = _ftp_mode_type(conn, 0, type)) != FTP_OK) {
255 _ftp_seterr(e);
256 return (-1);
257 }
370 _ftp_seterr(e);
371 return (-1);
372 }
373
374 e = _ftp_cmd(conn, "SIZE %.*s", filenamelen, filename);
375 if (e != FTP_FILE_STATUS) {
376 _ftp_seterr(e);
377 return (-1);
378 }
258 for (ln = conn->buf + 4; *ln && isspace(*ln); ln++)
259 /* nothing */ ;
260 for (us->size = 0; *ln && isdigit(*ln); ln++)
261 us->size = us->size * 10 + *ln - '0';
262 if (*ln && !isspace(*ln)) {
263 _ftp_seterr(FTP_PROTOCOL_ERROR);
264 us->size = -1;
265 return (-1);
266 }
267 if (us->size == 0)
268 us->size = -1;
269 DEBUG(fprintf(stderr, "size: [%lld]\n", (long long)us->size));
270
379 for (ln = conn->buf + 4; *ln && isspace(*ln); ln++)
380 /* nothing */ ;
381 for (us->size = 0; *ln && isdigit(*ln); ln++)
382 us->size = us->size * 10 + *ln - '0';
383 if (*ln && !isspace(*ln)) {
384 _ftp_seterr(FTP_PROTOCOL_ERROR);
385 us->size = -1;
386 return (-1);
387 }
388 if (us->size == 0)
389 us->size = -1;
390 DEBUG(fprintf(stderr, "size: [%lld]\n", (long long)us->size));
391
271 if ((e = _ftp_cmd(conn, "MDTM %s", s)) != FTP_FILE_STATUS) {
392 e = _ftp_cmd(conn, "MDTM %.*s", filenamelen, filename);
393 if (e != FTP_FILE_STATUS) {
272 _ftp_seterr(e);
273 return (-1);
274 }
275 for (ln = conn->buf + 4; *ln && isspace(*ln); ln++)
276 /* nothing */ ;
277 switch (strspn(ln, "0123456789")) {
278 case 14:
279 break;

--- 171 unchanged lines hidden (view full) ---

451 */
452static FILE *
453_ftp_transfer(conn_t *conn, const char *oper, const char *file,
454 int mode, off_t offset, const char *flags)
455{
456 struct sockaddr_storage sa;
457 struct sockaddr_in6 *sin6;
458 struct sockaddr_in *sin4;
394 _ftp_seterr(e);
395 return (-1);
396 }
397 for (ln = conn->buf + 4; *ln && isspace(*ln); ln++)
398 /* nothing */ ;
399 switch (strspn(ln, "0123456789")) {
400 case 14:
401 break;

--- 171 unchanged lines hidden (view full) ---

573 */
574static FILE *
575_ftp_transfer(conn_t *conn, const char *oper, const char *file,
576 int mode, off_t offset, const char *flags)
577{
578 struct sockaddr_storage sa;
579 struct sockaddr_in6 *sin6;
580 struct sockaddr_in *sin4;
581 const char *filename;
582 int filenamelen, type;
459 int low, pasv, verbose;
460 int e, sd = -1;
461 socklen_t l;
462 char *s;
463 FILE *df;
464
465 /* check flags */
466 low = CHECK_FLAG('l');
467 pasv = CHECK_FLAG('p');
468 verbose = CHECK_FLAG('v');
469
470 /* passive mode */
471 if (!pasv)
472 pasv = ((s = getenv("FTP_PASSIVE_MODE")) != NULL &&
473 strncasecmp(s, "no", 2) != 0);
474
583 int low, pasv, verbose;
584 int e, sd = -1;
585 socklen_t l;
586 char *s;
587 FILE *df;
588
589 /* check flags */
590 low = CHECK_FLAG('l');
591 pasv = CHECK_FLAG('p');
592 verbose = CHECK_FLAG('v');
593
594 /* passive mode */
595 if (!pasv)
596 pasv = ((s = getenv("FTP_PASSIVE_MODE")) != NULL &&
597 strncasecmp(s, "no", 2) != 0);
598
599 /* isolate filename */
600 filename = _ftp_filename(file, &filenamelen, &type);
601
602 /* set transfer mode and data type */
603 if ((e = _ftp_mode_type(conn, 0, type)) != FTP_OK)
604 goto ouch;
605
475 /* find our own address, bind, and listen */
476 l = sizeof(sa);
477 if (getsockname(conn->sd, (struct sockaddr *)&sa, &l) == -1)
478 goto sysouch;
479 if (sa.ss_family == AF_INET6)
480 unmappedaddr((struct sockaddr_in6 *)&sa);
481
482 /* open data socket */

--- 109 unchanged lines hidden (view full) ---

592 if (verbose)
593 _fetch_info("opening data connection");
594 if (connect(sd, (struct sockaddr *)&sa, sa.ss_len) == -1)
595 goto sysouch;
596
597 /* make the server initiate the transfer */
598 if (verbose)
599 _fetch_info("initiating transfer");
606 /* find our own address, bind, and listen */
607 l = sizeof(sa);
608 if (getsockname(conn->sd, (struct sockaddr *)&sa, &l) == -1)
609 goto sysouch;
610 if (sa.ss_family == AF_INET6)
611 unmappedaddr((struct sockaddr_in6 *)&sa);
612
613 /* open data socket */

--- 109 unchanged lines hidden (view full) ---

723 if (verbose)
724 _fetch_info("opening data connection");
725 if (connect(sd, (struct sockaddr *)&sa, sa.ss_len) == -1)
726 goto sysouch;
727
728 /* make the server initiate the transfer */
729 if (verbose)
730 _fetch_info("initiating transfer");
600 e = _ftp_cmd(conn, "%s %s", oper, _ftp_filename(file));
731 e = _ftp_cmd(conn, "%s %.*s", oper, filenamelen, filename);
601 if (e != FTP_CONNECTION_ALREADY_OPEN && e != FTP_OPEN_DATA_CONNECTION)
602 goto ouch;
603
604 } else {
605 u_int32_t a;
606 u_short p;
607 int arg, d;
608 char *ap;

--- 74 unchanged lines hidden (view full) ---

683 /* seek to required offset */
684 if (offset)
685 if (_ftp_cmd(conn, "REST %ju", (uintmax_t)offset) != FTP_FILE_OK)
686 goto sysouch;
687
688 /* make the server initiate the transfer */
689 if (verbose)
690 _fetch_info("initiating transfer");
732 if (e != FTP_CONNECTION_ALREADY_OPEN && e != FTP_OPEN_DATA_CONNECTION)
733 goto ouch;
734
735 } else {
736 u_int32_t a;
737 u_short p;
738 int arg, d;
739 char *ap;

--- 74 unchanged lines hidden (view full) ---

814 /* seek to required offset */
815 if (offset)
816 if (_ftp_cmd(conn, "REST %ju", (uintmax_t)offset) != FTP_FILE_OK)
817 goto sysouch;
818
819 /* make the server initiate the transfer */
820 if (verbose)
821 _fetch_info("initiating transfer");
691 e = _ftp_cmd(conn, "%s %s", oper, _ftp_filename(file));
822 e = _ftp_cmd(conn, "%s %.*s", oper, filenamelen, filename);
692 if (e != FTP_CONNECTION_ALREADY_OPEN && e != FTP_OPEN_DATA_CONNECTION)
693 goto ouch;
694
695 /* accept the incoming connection and go to town */
696 if ((d = accept(sd, NULL, NULL)) == -1)
697 goto sysouch;
698 close(sd);
699 sd = d;

--- 107 unchanged lines hidden (view full) ---

807 /* expect welcome message */
808 if ((e = _ftp_chkerr(conn)) != FTP_SERVICE_READY)
809 goto fouch;
810
811 /* authenticate */
812 if ((e = _ftp_authenticate(conn, url, purl)) != FTP_LOGGED_IN)
813 goto fouch;
814
823 if (e != FTP_CONNECTION_ALREADY_OPEN && e != FTP_OPEN_DATA_CONNECTION)
824 goto ouch;
825
826 /* accept the incoming connection and go to town */
827 if ((d = accept(sd, NULL, NULL)) == -1)
828 goto sysouch;
829 close(sd);
830 sd = d;

--- 107 unchanged lines hidden (view full) ---

938 /* expect welcome message */
939 if ((e = _ftp_chkerr(conn)) != FTP_SERVICE_READY)
940 goto fouch;
941
942 /* authenticate */
943 if ((e = _ftp_authenticate(conn, url, purl)) != FTP_LOGGED_IN)
944 goto fouch;
945
815 /* might as well select mode and type at once */
816#ifdef FTP_FORCE_STREAM_MODE
817 if ((e = _ftp_cmd(conn, "MODE S")) != FTP_OK) /* default is S */
818 goto fouch;
819#endif
820 if ((e = _ftp_cmd(conn, "TYPE I")) != FTP_OK) /* default is A */
821 goto fouch;
822
823 /* done */
824 return (conn);
825
826fouch:
827 if (e != -1)
828 _ftp_seterr(e);
829 _fetch_close(conn);
830 return (NULL);

--- 190 unchanged lines hidden ---
946 /* done */
947 return (conn);
948
949fouch:
950 if (e != -1)
951 _ftp_seterr(e);
952 _fetch_close(conn);
953 return (NULL);

--- 190 unchanged lines hidden ---