1
1
/* File Transfer Protocol support.
2
2
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
3
2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
3
2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
5
5
This file is part of GNU Wget.
64
69
int cmd; /* command code */
65
70
int csock; /* control connection socket */
66
71
double dltime; /* time of the download in msecs */
67
enum stype rs; /* remote system reported by ftp server */
72
enum stype rs; /* remote system reported by ftp server */
68
73
char *id; /* initial directory */
69
74
char *target; /* target file name */
70
75
struct url *proxy; /* FTWK-style proxy */
74
80
/* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in
75
81
the string S, and return the number converted to wgint, if found, 0
119
125
if (!socket_ip_address (csock, addr, ENDPOINT_PEER))
122
/* If our control connection is over IPv6, then we first try EPSV and then
123
* LPSV if the former is not supported. If the control connection is over
128
/* If our control connection is over IPv6, then we first try EPSV and then
129
* LPSV if the former is not supported. If the control connection is over
124
130
* IPv4, we simply issue the good old PASV request. */
125
131
switch (addr->family)
162
168
if (!socket_ip_address (csock, &cip, ENDPOINT_PEER))
165
/* If our control connection is over IPv6, then we first try EPRT and then
166
* LPRT if the former is not supported. If the control connection is over
171
/* If our control connection is over IPv6, then we first try EPRT and then
172
* LPRT if the former is not supported. If the control connection is over
167
173
* IPv4, we simply issue the good old PORT request. */
168
174
switch (cip.family)
217
223
logprintf (LOG_VERBOSE, " (%s)", human_readable (size));
226
if (size - start >= 1024)
221
227
logprintf (LOG_VERBOSE, _(", %s (%s) remaining"),
222
228
number_to_static_string (size - start),
223
229
human_readable (size - start));
228
234
logputs (LOG_VERBOSE, !authoritative ? _(" (unauthoritative)\n") : "\n");
237
static uerr_t ftp_get_listing (struct url *, ccon *, struct fileinfo **);
231
239
/* Retrieves a file with denoted parameters through opening an FTP
232
240
connection to the server. It always closes the data connection,
233
241
and closes the control connection in case of error. */
235
getftp (struct url *u, wgint *len, wgint restval, ccon *con)
243
getftp (struct url *u, wgint passed_expected_bytes, wgint *qtyread,
244
wgint restval, ccon *con)
237
246
int csock, dtsock, local_sock, res;
238
247
uerr_t err = RETROK; /* appease the compiler */
303
314
/* Second: Login with proper USER/PASS sequence. */
304
logprintf (LOG_VERBOSE, _("Logging in as %s ... "), escnonprint (user));
315
logprintf (LOG_VERBOSE, _("Logging in as %s ... "),
316
quotearg_style (escape_quoting_style, user));
305
317
if (opt.server_response)
306
318
logputs (LOG_ALWAYS, "\n");
307
319
err = ftp_login (csock, logname, passwd);
423
Don't help me out. Please.
424
A reasonably recent VMS FTP server will cope just fine with
425
UNIX file specifications. This code just spoils things.
426
Discarding the device name, for example, is not a wise move.
427
This code was disabled but left in as an example of what not
408
431
/* VMS will report something like "PUB$DEVICE:[INITIAL.FOLDER]".
409
Convert it to "/INITIAL/FOLDER" */
432
Convert it to "/INITIAL/FOLDER" */
410
433
if (con->rs == ST_VMS)
412
435
char *path = strchr (con->id, '[');
495
525
in "bar", not in "foo/bar", as would be customary
529
Why is this wise even on UNIX? It certainly fouls VMS.
530
See below for a more reliable, more universal method.
534
I'm not crazy about it either. I'm informed it's useful
535
for misconfigured servers that have some dirs in the path
536
with +x but -r, but this method is not RFC-conformant. I
537
understand the need to deal with crappy server
538
configurations, but it's far better to use the canonical
539
method first, and fall back to kludges second.
498
542
if (target[0] != '/'
499
543
&& !(con->rs != ST_UNIX
500
&& ISALPHA (target[0])
544
&& c_isalpha (target[0])
501
545
&& target[1] == ':')
502
&& con->rs != ST_OS400)
546
&& (con->rs != ST_OS400)
547
&& (con->rs != ST_VMS))
504
549
int idlen = strlen (con->id);
505
550
char *ntarget, *p;
519
564
target = ntarget;
569
Don't help me out. Please.
570
A reasonably recent VMS FTP server will cope just fine with
571
UNIX file specifications. This code just spoils things.
572
Discarding the device name, for example, is not a wise
574
This code was disabled but left in as an example of what
522
578
/* If the FTP host runs VMS, we will have to convert the absolute
523
579
directory path in UNIX notation to absolute directory path in
524
580
VMS notation as VMS FTP servers do not like UNIX notation of
544
600
DEBUGP ((" Unix: '%s'\n VMS: '%s'\n", target, ntarget));
545
601
target = ntarget;
606
A relative directory is relative to the initial directory.
607
Thus, what _is_ useful on VMS (and probably elsewhere) is
608
to CWD to the initial directory (ideally, whatever the
609
server reports, _exactly_, NOT badly UNIX-ixed), and then
610
CWD to the (new) relative directory. This should probably
611
be restructured as a function, called once or twice, but
612
I'm lazy enough to take the badly indented loop short-cut
616
/* Decide on one pass (absolute) or two (relative).
617
The VMS restriction may be relaxed when the squirrely code
620
if ((con->rs == ST_VMS) && (target[0] != '/'))
623
DEBUGP (("Using two-step CWD for relative path.\n"));
627
/* Go straight to the target. */
631
/* At least one VMS FTP server (TCPware V5.6-2) can switch to
632
a UNIX emulation mode when given a UNIX-like directory
633
specification (like "a/b/c"). If allowed to continue this
634
way, LIST interpretation will be confused, because the
635
system type (SYST response) will not be re-checked, and
636
future UNIX-format directory listings (for multiple URLs or
637
"-r") will be horribly misinterpreted.
639
The cheap and nasty work-around is to do a "CWD []" after a
640
UNIX-like directory specification is used. (A single-level
641
directory is harmless.) This puts the TCPware server back
642
into VMS mode, and does no harm on other servers.
644
Unlike the rest of this block, this particular behavior
645
_is_ VMS-specific, so it gets its own VMS test.
647
if ((con->rs == ST_VMS) && (strchr( target, '/') != NULL))
650
DEBUGP (("Using extra \"CWD []\" step for VMS server.\n"));
657
/* 2004-09-20 SMS. */
658
/* Sorry about the deviant indenting. Laziness. */
660
for (cwd_count = cwd_start; cwd_count < cwd_end; cwd_count++)
665
/* Step one (optional): Go to the initial directory,
666
exactly as reported by the server.
672
/* Step two: Go to the target directory. (Absolute or
673
relative will work now.)
679
/* Step three (optional): "CWD []" to restore server
548
690
if (!opt.server_response)
549
logprintf (LOG_VERBOSE, "==> CWD %s ... ", escnonprint (target));
691
logprintf (LOG_VERBOSE, "==> CWD (%d) %s ... ", cwd_count,
692
quotearg_style (escape_quoting_style, target));
550
693
err = ftp_cwd (csock, target);
551
694
/* FTPRERR, WRITEFAILED, FTPNSFOD */
580
723
if (!opt.server_response)
581
724
logputs (LOG_VERBOSE, _("done.\n"));
728
/* 2004-09-20 SMS. */
729
/* End of deviant indenting. */
584
733
else /* do not CWD */
585
734
logputs (LOG_VERBOSE, _("==> CWD not required.\n"));
587
if ((cmd & DO_RETR) && *len == 0)
736
if ((cmd & DO_RETR) && passed_expected_bytes == 0)
591
740
if (!opt.server_response)
592
logprintf (LOG_VERBOSE, "==> SIZE %s ... ", escnonprint (u->file));
741
logprintf (LOG_VERBOSE, "==> SIZE %s ... ",
742
quotearg_style (escape_quoting_style, u->file));
595
err = ftp_size (csock, u->file, len);
745
err = ftp_size (csock, u->file, &expected_bytes);
613
763
if (!opt.server_response)
614
logprintf (LOG_VERBOSE, *len ? "%s\n" : _("done.\n"),
615
number_to_static_string (*len));
764
logprintf (LOG_VERBOSE, expected_bytes ? "%s\n" : _("done.\n"),
765
number_to_static_string (expected_bytes));
618
768
/* If anything is to be retrieved, PORT (or PASV) must be sent. */
778
928
if (cmd & DO_RETR)
780
/* If we're in spider mode, don't really retrieve anything. The
781
fact that we got to this point should be proof enough that
782
the file exists, vaguely akin to HTTP's concept of a "HEAD"
930
/* If we're in spider mode, don't really retrieve anything except
931
the directory listing and verify whether the given "file" exists. */
937
res = ftp_get_listing (u, con, &f);
938
/* Set the DO_RETR command flag again, because it gets unset when
939
calling ftp_get_listing() and would otherwise cause an assertion
940
failure earlier on when this function gets repeatedly called
941
(e.g., when recursing). */
947
if (!strcmp (f->name, u->file))
956
logputs (LOG_VERBOSE, "\n");
957
logprintf (LOG_NOTQUIET, _("File %s exists.\n"),
962
logputs (LOG_VERBOSE, "\n");
963
logprintf (LOG_NOTQUIET, _("No such file %s.\n"),
786
967
fd_close (csock);
788
969
fd_close (dtsock);
892
1074
/* Some FTP servers return the total length of file after REST
893
1075
command, others just return the remaining size. */
894
if (*len && restval && expected_bytes
895
&& (expected_bytes == *len - restval))
1076
if (passed_expected_bytes && restval && expected_bytes
1077
&& (expected_bytes == passed_expected_bytes - restval))
897
1079
DEBUGP (("Lying FTP server found, adjusting.\n"));
898
expected_bytes = *len;
1080
expected_bytes = passed_expected_bytes;
901
1083
/* If no transmission was required, then everything is OK. */
910
1092
logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));
915
1097
/* Open the file -- if output_stream is set, use it instead. */
1100
Note that having the output_stream ("-O") file opened in main()
1101
(main.c) rather limits the ability in VMS to open the file
1102
differently for ASCII versus binary FTP here. (Of course, doing it
1103
there allows a open failure to be detected immediately, without first
1104
connecting to the server.)
916
1106
if (!output_stream || con->cmd & DO_LIST)
1108
/* On VMS, alter the name as required. */
1112
targ = ods_conform (con->target);
1113
if (targ != con->target)
1115
xfree (con->target);
1118
#endif /* def __VMS */
918
1120
mkalldirs (con->target);
919
1121
if (opt.backups)
920
1122
rotate_backups (con->target);
1125
For VMS, define common fopen() optional arguments, and a handy macro
1126
for use as a variable "binary" flag.
1127
Elsewhere, define a constant "binary" flag.
1128
Isn't it nice to have distinct text and binary file types?
1130
# define BIN_TYPE_TRANSFER (type_char != 'A')
1132
# define FOPEN_OPT_ARGS "fop=sqo", "acc", acc_cb, &open_id
1133
# define FOPEN_OPT_ARGS_BIN "ctx=bin,stm", "rfm=fix", "mrs=512" FOPEN_OPT_ARGS
1134
# define BIN_TYPE_FILE (BIN_TYPE_TRANSFER && (opt.ftp_stmlf == 0))
1135
#else /* def __VMS */
1136
# define BIN_TYPE_FILE 1
1137
#endif /* def __VMS [else] */
922
1139
if (restval && !(con->cmd & DO_LIST))
923
fp = fopen (con->target, "ab");
1147
fp = fopen (con->target, "ab", FOPEN_OPT_ARGS_BIN);
1152
fp = fopen (con->target, "a", FOPEN_OPT_ARGS);
1154
#else /* def __VMS */
1155
fp = fopen (con->target, "ab");
1156
#endif /* def __VMS [else] */
924
1158
else if (opt.noclobber || opt.always_rest || opt.timestamping || opt.dirstruct
925
1159
|| opt.output_document)
926
fp = fopen (con->target, "wb");
1167
fp = fopen (con->target, "wb", FOPEN_OPT_ARGS_BIN);
1172
fp = fopen (con->target, "w", FOPEN_OPT_ARGS);
1174
#else /* def __VMS */
1175
fp = fopen (con->target, "wb");
1176
#endif /* def __VMS [else] */
929
1180
fp = fopen_excl (con->target, true);
956
1207
fp = output_stream;
1209
if (passed_expected_bytes)
960
print_length (*len, restval, true);
961
expected_bytes = *len; /* for fd_read_body's progress bar */
1211
print_length (passed_expected_bytes, restval, true);
1212
expected_bytes = passed_expected_bytes;
1213
/* for fd_read_body's progress bar */
963
1215
else if (expected_bytes)
964
1216
print_length (expected_bytes, restval, false);
968
1220
if (restval && rest_failed)
969
1221
flags |= rb_skip_startpos;
972
1223
res = fd_read_body (dtsock, fp,
973
1224
expected_bytes ? expected_bytes - restval : 0,
974
restval, &rd_size, len, &con->dltime, flags);
1225
restval, &rd_size, qtyread, &con->dltime, flags);
976
1227
tms = datetime_str (time (NULL));
977
1228
tmrate = retr_rate (rd_size, con->dltime);
1050
1301
print it out. */
1051
1302
if (opt.server_response && (con->cmd & DO_LIST))
1305
Much of this work may already have been done, but repeating it should
1306
do no damage beyond wasting time.
1308
/* On VMS, alter the name as required. */
1312
targ = ods_conform( con->target);
1313
if (targ != con->target)
1315
xfree( con->target);
1318
#endif /* def __VMS */
1053
1320
mkalldirs (con->target);
1054
1321
fp = fopen (con->target, "r");
1064
1331
char *p = strchr (line, '\0');
1065
1332
while (p > line && (p[-1] == '\n' || p[-1] == '\r'))
1067
logprintf (LOG_ALWAYS, "%s\n", escnonprint (line));
1334
logprintf (LOG_ALWAYS, "%s\n",
1335
quotearg_style (escape_quoting_style, line));
1083
1351
ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
1085
1353
int count, orig_lp;
1086
wgint restval, len = 0;
1354
wgint restval, len = 0, qtyread = 0;
1087
1355
char *tms, *locf;
1088
1356
const char *tmrate = NULL;
1090
1358
struct_stat st;
1093
con->target = url_file_name (u);
1360
/* Get the target, and set the name for the message accordingly. */
1361
if ((f == NULL) && (con->target))
1363
/* Explicit file (like ".listing"). */
1368
/* URL-derived file. Consider "-O file" name. */
1369
con->target = url_file_name (u);
1370
if (!opt.output_document)
1373
locf = opt.output_document;
1095
1376
/* If the output_document was given, then this check was already done and
1096
1377
the file didn't exist. Hence the !opt.output_document */
1097
1378
if (opt.noclobber && !opt.output_document && file_exists_p (con->target))
1099
1380
logprintf (LOG_VERBOSE,
1100
_("File `%s' already there; not retrieving.\n"), con->target);
1381
_("File %s already there; not retrieving.\n"), quote (con->target));
1101
1382
/* If the file is there, we suppose it's retrieved OK. */
1105
1386
/* Remove it if it's a link. */
1106
1387
remove_link (con->target);
1107
if (!opt.output_document)
1110
locf = opt.output_document;
1168
1445
strcpy (tmp, " ");
1170
1447
sprintf (tmp, _("(try:%2d)"), count);
1171
logprintf (LOG_VERBOSE, "--%s-- %s\n %s => `%s'\n",
1172
tms, hurl, tmp, locf);
1448
logprintf (LOG_VERBOSE, "--%s-- %s\n %s => %s\n",
1449
tms, hurl, tmp, quote (locf));
1174
1451
ws_changetitle (hurl);
1237
1514
con->csock = -1;
1239
1516
if (!opt.spider)
1240
logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%s]\n\n"),
1241
tms, tmrate, locf, number_to_static_string (len));
1518
bool write_to_stdout = (opt.output_document && HYPHENP (opt.output_document));
1520
logprintf (LOG_VERBOSE,
1522
? _("%s (%s) - written to stdout %s[%s]\n\n")
1523
: _("%s (%s) - %s saved [%s]\n\n"),
1525
write_to_stdout ? "" : quote (locf),
1526
number_to_static_string (qtyread));
1242
1528
if (!opt.verbose && !opt.quiet)
1244
1530
/* Need to hide the password from the URL. The `if' is here
1247
1533
char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
1248
1534
logprintf (LOG_NONVERBOSE, "%s URL: %s [%s] -> \"%s\" [%d]\n",
1249
tms, hurl, number_to_static_string (len), locf, count);
1535
tms, hurl, number_to_static_string (qtyread), locf, count);
1321
1607
uf = url_file_name (u);
1322
1608
lf = file_merge (uf, LIST_FILENAME);
1324
DEBUGP ((_("Using `%s' as listing tmp file.\n"), lf));
1610
DEBUGP ((_("Using %s as listing tmp file.\n"), quote (lf)));
1612
con->target = xstrdup (lf);
1327
1614
err = ftp_loop_internal (u, NULL, con);
1615
lf = xstrdup (con->target);
1616
xfree (con->target);
1328
1617
con->target = old_target;
1330
1619
if (err == RETROK)
1331
*f = ftp_parse_ls (lf, con->rs);
1621
*f = ftp_parse_ls (lf, con->rs);
1622
if (opt.remove_listing)
1625
logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1627
logprintf (LOG_VERBOSE, _("Removed %s.\n"), quote (lf));
1334
if (opt.remove_listing)
1337
logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1339
logprintf (LOG_VERBOSE, _("Removed `%s'.\n"), lf);
1342
1633
con->cmd &= ~DO_LIST;
1440
1732
/* Remote file is older, file sizes can be compared and
1441
1733
are both equal. */
1442
1734
logprintf (LOG_VERBOSE, _("\
1443
Remote file no newer than local file `%s' -- not retrieving.\n"), con->target);
1735
Remote file no newer than local file %s -- not retrieving.\n"), quote (con->target));
1444
1736
dlthis = false;
1446
1738
else if (eq_size)
1448
1740
/* Remote file is newer or sizes cannot be matched */
1449
1741
logprintf (LOG_VERBOSE, _("\
1450
Remote file is newer than local file `%s' -- retrieving.\n\n"),
1742
Remote file is newer than local file %s -- retrieving.\n\n"),
1743
quote (con->target));
1491
1783
logprintf (LOG_VERBOSE, _("\
1492
1784
Already have correct symlink %s -> %s\n\n"),
1493
con->target, escnonprint (f->linkto));
1785
quote (con->target),
1494
1787
dlthis = false;
1499
1792
logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1500
con->target, escnonprint (f->linkto));
1793
quote (con->target), quote (f->linkto));
1501
1794
/* Unlink before creating symlink! */
1502
1795
unlink (con->target);
1503
1796
if (symlink (f->linkto, con->target) == -1)
1529
1822
case FT_UNKNOWN:
1530
1823
logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1531
escnonprint (f->name));
1830
* Set permissions _before_ setting the times, as setting the
1831
* permissions changes the modified-time, at least on VMS.
1832
* Also, use the opt.output_document name here, too, as
1833
* appropriate. (Do the test once, and save the result.)
1836
set_local_file (&actual_target, con->target);
1838
/* If downloading a plain file, set valid (non-zero) permissions. */
1839
if (dlthis && (actual_target != NULL) && (f->type == FT_PLAINFILE))
1842
chmod (actual_target, f->perms);
1844
DEBUGP (("Unrecognized permissions for %s.\n", actual_target));
1535
1847
/* Set the time-stamp information to the local file. Symlinks
1536
1848
are not to be stamped because it sets the stamp on the
1537
1849
original. :( */
1538
if (!(f->type == FT_SYMLINK && !opt.retr_symlinks)
1541
&& file_exists_p (con->target))
1850
if (actual_target != NULL)
1543
/* #### This code repeats in http.c and ftp.c. Move it to a
1545
const char *fl = NULL;
1546
if (opt.output_document)
1852
if (!(f->type == FT_SYMLINK && !opt.retr_symlinks)
1855
&& file_exists_p (con->target))
1548
if (output_stream_regular)
1549
fl = opt.output_document;
1857
touch (actual_target, f->tstamp);
1554
touch (fl, f->tstamp);
1556
else if (f->tstamp == -1)
1557
logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"), con->target);
1559
if (f->perms && f->type == FT_PLAINFILE && dlthis)
1561
if (opt.preserve_perm)
1562
chmod (con->target, f->perms);
1565
DEBUGP (("Unrecognized permissions for %s.\n", con->target));
1859
else if (f->tstamp == -1)
1860
logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"),
1567
1864
xfree (con->target);
1568
1865
con->target = old_target;
1753
2051
else if (action == GLOB_GETONE)
2055
* Odd-ball compiler ("HP C V7.3-009 on OpenVMS Alpha V7.3-2")
2056
* bug causes spurious %CC-E-BADCONDIT complaint with this
2057
* "?:" statement. (Different linkage attributes for strcmp()
2058
* and strcasecmp().) Converting to "if" changes the
2059
* complaint to %CC-W-PTRMISMATCH on "cmp = strcmp;". Adding
2060
* the senseless type cast clears the complaint, and looks
2063
int (*cmp) (const char *, const char *)
2064
= opt.ignore_case ? strcasecmp : (int (*)())strcmp;
2065
#else /* def __VMS */
1755
2066
int (*cmp) (const char *, const char *)
1756
2067
= opt.ignore_case ? strcasecmp : strcmp;
2068
#endif /* def __VMS [else] */
1777
2089
/* #### This message SUCKS. We should see what was the
1778
2090
reason that nothing was retrieved. */
1779
logprintf (LOG_VERBOSE, _("No matches on pattern `%s'.\n"),
1780
escnonprint (u->file));
2091
logprintf (LOG_VERBOSE, _("No matches on pattern %s.\n"),
1782
else if (*u->file) /* GLOB_GETONE or GLOB_GETALL */
2094
else if (action == GLOB_GETONE) /* GLOB_GETONE or GLOB_GETALL */
1784
2096
/* Let's try retrieving it anyway. */
1785
2097
con->st |= ON_YOUR_OWN;
1786
2098
res = ftp_loop_internal (u, NULL, con);
2102
/* If action == GLOB_GETALL, and the file list is empty, there's
2103
no point in trying to download anything or in complaining about
2104
it. (An empty directory should not cause complaints.)
1790
2107
freefileinfo (start);
1791
2108
if (opt.quota && total_downloaded_bytes > opt.quota)
1844
2161
logprintf (LOG_NOTQUIET,
1845
_("Wrote HTML-ized index to `%s' [%s].\n"),
1846
filename, number_to_static_string (sz));
2162
_("Wrote HTML-ized index to %s [%s].\n"),
2163
quote (filename), number_to_static_string (sz));
1849
2166
logprintf (LOG_NOTQUIET,
1850
_("Wrote HTML-ized index to `%s'.\n"),
2167
_("Wrote HTML-ized index to %s.\n"),
1853
2170
xfree (filename);