~ubuntu-branches/ubuntu/precise/wget/precise-proposed

« back to all changes in this revision

Viewing changes to src/ftp.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Langasek
  • Date: 2011-10-19 00:00:09 UTC
  • mfrom: (2.1.13 sid)
  • Revision ID: james.westby@ubuntu.com-20111019000009-8p33w3wz4b1rdri0
Tags: 1.13-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add wget-udeb to ship wget.gnu as alternative to busybox wget
    implementation.
  - Depend on libssl-dev 0.9.8k-7ubuntu4 (LP: #503339)
* Dropped changes, superseded in Debian:
  - Keep build dependencies in main:
    + debian/control: remove info2man build-dep
    + debian/patches/series: disable wget-infopod_generated_manpage
  - Mark wget Multi-Arch: foreign, so packages that aren't of the same arch
    can depend on it.
* Pass --with-ssl=openssl; we don't want to use gnutls, there's no udeb for
  it.
* Add a second build pass for the udeb, so we can build without libidn.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* File Transfer Protocol support.
2
 
   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
3
 
   2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 
2
   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 
3
   2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
 
4
   Inc.
4
5
 
5
6
This file is part of GNU Wget.
6
7
 
34
35
#include <stdlib.h>
35
36
#include <string.h>
36
37
#include <strings.h>
37
 
#ifdef HAVE_UNISTD_H
38
 
# include <unistd.h>
39
 
#endif
 
38
#include <unistd.h>
40
39
#include <assert.h>
41
40
#include <errno.h>
42
41
#include <time.h>
241
240
   and closes the control connection in case of error.  */
242
241
static uerr_t
243
242
getftp (struct url *u, wgint passed_expected_bytes, wgint *qtyread,
244
 
        wgint restval, ccon *con)
 
243
        wgint restval, ccon *con, int count)
245
244
{
246
245
  int csock, dtsock, local_sock, res;
247
246
  uerr_t err = RETROK;          /* appease the compiler */
252
251
  int cmd = con->cmd;
253
252
  bool pasv_mode_open = false;
254
253
  wgint expected_bytes = 0;
 
254
  bool got_expected_bytes = false;
255
255
  bool rest_failed = false;
256
256
  int flags;
257
257
  wgint rd_size;
301
301
 
302
302
      csock = connect_to_host (host, port);
303
303
      if (csock == E_HOST)
304
 
        return HOSTERR;
 
304
        {
 
305
          if (con->proxy)
 
306
            xfree (logname);
 
307
 
 
308
          return HOSTERR;
 
309
        }
305
310
      else if (csock < 0)
306
 
        return (retryable_socket_connect_error (errno)
307
 
                ? CONERROR : CONIMPOSSIBLE);
 
311
        {
 
312
          if (con->proxy)
 
313
            xfree (logname);
 
314
 
 
315
          return (retryable_socket_connect_error (errno)
 
316
                  ? CONERROR : CONIMPOSSIBLE);
 
317
        }
308
318
 
309
319
      if (cmd & LEAVE_PENDING)
310
320
        con->csock = csock;
502
512
        logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
503
513
      else
504
514
        {
505
 
          char *targ;
506
 
          int cwd_count;
507
 
          int cwd_end;
508
 
          int cwd_start;
 
515
          char *targ = NULL;
 
516
          int cwd_count;
 
517
          int cwd_end;
 
518
          int cwd_start;
509
519
 
510
520
          char *target = u->dir;
511
521
 
690
700
          if (!opt.server_response)
691
701
            logprintf (LOG_VERBOSE, "==> CWD (%d) %s ... ", cwd_count,
692
702
                       quotearg_style (escape_quoting_style, target));
693
 
          err = ftp_cwd (csock, target);
 
703
          err = ftp_cwd (csock, targ);
694
704
          /* FTPRERR, WRITEFAILED, FTPNSFOD */
695
705
          switch (err)
696
706
            {
755
765
          con->csock = -1;
756
766
          return err;
757
767
        case FTPOK:
 
768
          got_expected_bytes = true;
758
769
          /* Everything is OK.  */
759
770
          break;
760
771
        default:
765
776
                     number_to_static_string (expected_bytes));
766
777
    }
767
778
 
 
779
  if (cmd & DO_RETR && restval > 0 && restval == expected_bytes)
 
780
    {
 
781
      /* Server confirms that file has length restval. We should stop now.
 
782
         Some servers (f.e. NcFTPd) return error when receive REST 0 */
 
783
      logputs (LOG_VERBOSE, _("File has already been retrieved.\n"));
 
784
      fd_close (csock);
 
785
      con->csock = -1;
 
786
      return RETRFINISHED;
 
787
    }
 
788
 
768
789
  /* If anything is to be retrieved, PORT (or PASV) must be sent.  */
769
790
  if (cmd & (DO_LIST | DO_RETR))
770
791
    {
1019
1040
 
1020
1041
      if (!opt.server_response)
1021
1042
        logputs (LOG_VERBOSE, _("done.\n"));
1022
 
      expected_bytes = ftp_expected_bytes (ftp_last_respline);
 
1043
 
 
1044
      if (! got_expected_bytes)
 
1045
        expected_bytes = ftp_expected_bytes (ftp_last_respline);
1023
1046
    } /* do retrieve */
1024
1047
 
1025
1048
  if (cmd & DO_LIST)
1065
1088
        }
1066
1089
      if (!opt.server_response)
1067
1090
        logputs (LOG_VERBOSE, _("done.\n"));
1068
 
      expected_bytes = ftp_expected_bytes (ftp_last_respline);
 
1091
 
 
1092
      if (! got_expected_bytes)
 
1093
        expected_bytes = ftp_expected_bytes (ftp_last_respline);
1069
1094
    } /* cmd & DO_LIST */
1070
1095
 
1071
1096
  if (!(cmd & (DO_LIST | DO_RETR)) || (opt.spider && !(cmd & DO_LIST)))
1156
1181
#endif /* def __VMS [else] */
1157
1182
        }
1158
1183
      else if (opt.noclobber || opt.always_rest || opt.timestamping || opt.dirstruct
1159
 
               || opt.output_document)
1160
 
        {
 
1184
               || opt.output_document || count > 0)
 
1185
        {         
 
1186
          if (opt.unlink && file_exists_p (con->target))
 
1187
            {
 
1188
              int res = unlink (con->target);
 
1189
              if (res < 0)
 
1190
                {
 
1191
                  logprintf (LOG_NOTQUIET, "%s: %s\n", con->target,
 
1192
                             strerror (errno));
 
1193
                  fd_close (csock);
 
1194
                  con->csock = -1;
 
1195
                  fd_close (dtsock);
 
1196
                  fd_close (local_sock);
 
1197
                  return UNLINKERR;
 
1198
                }
 
1199
            }
 
1200
 
1161
1201
#ifdef __VMS
1162
1202
          int open_id;
1163
1203
 
1348
1388
   This loop either gets commands from con, or (if ON_YOUR_OWN is
1349
1389
   set), makes them up to retrieve the file given by the URL.  */
1350
1390
static uerr_t
1351
 
ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
 
1391
ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_file)
1352
1392
{
1353
1393
  int count, orig_lp;
1354
1394
  wgint restval, len = 0, qtyread = 0;
1366
1406
  else
1367
1407
    {
1368
1408
      /* URL-derived file.  Consider "-O file" name. */
1369
 
      con->target = url_file_name (u);
 
1409
      con->target = url_file_name (u, NULL);
1370
1410
      if (!opt.output_document)
1371
1411
        locf = con->target;
1372
1412
      else
1453
1493
          xfree (hurl);
1454
1494
        }
1455
1495
      /* Send getftp the proper length, if fileinfo was provided.  */
1456
 
      if (f)
 
1496
      if (f && f->type != FT_SYMLINK)
1457
1497
        len = f->size;
1458
1498
      else
1459
1499
        len = 0;
1460
 
      err = getftp (u, len, &qtyread, restval, con);
 
1500
      err = getftp (u, len, &qtyread, restval, con, count);
1461
1501
 
1462
1502
      if (con->csock == -1)
1463
1503
        con->st &= ~DONE_CWD;
1468
1508
        {
1469
1509
        case HOSTERR: case CONIMPOSSIBLE: case FWRITEERR: case FOPENERR:
1470
1510
        case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
 
1511
        case UNLINKERR:
1471
1512
          /* Fatal errors, give up.  */
1472
1513
          return err;
1473
1514
        case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
1480
1521
            {
1481
1522
              /* Re-determine the file name. */
1482
1523
              xfree_null (con->target);
1483
 
              con->target = url_file_name (u);
 
1524
              con->target = url_file_name (u, NULL);
1484
1525
              locf = con->target;
1485
1526
            }
1486
1527
          continue;
1561
1602
          total_downloaded_bytes += qtyread;
1562
1603
          numurls++;
1563
1604
 
1564
 
          if (opt.delete_after)
 
1605
          if (opt.delete_after && !input_file_url (opt.input_filename))
1565
1606
            {
1566
1607
              DEBUGP (("\
1567
1608
Removing file due to --delete-after in ftp_loop_internal():\n"));
1576
1617
        con->cmd |= LEAVE_PENDING;
1577
1618
      else
1578
1619
        con->cmd &= ~LEAVE_PENDING;
 
1620
 
 
1621
      if (local_file)
 
1622
        *local_file = xstrdup (locf);
 
1623
 
1579
1624
      return RETROK;
1580
1625
    } while (!opt.ntry || (count < opt.ntry));
1581
1626
 
1604
1649
  /* Find the listing file name.  We do it by taking the file name of
1605
1650
     the URL and replacing the last component with the listing file
1606
1651
     name.  */
1607
 
  uf = url_file_name (u);
 
1652
  uf = url_file_name (u, NULL);
1608
1653
  lf = file_merge (uf, LIST_FILENAME);
1609
1654
  xfree (uf);
1610
1655
  DEBUGP ((_("Using %s as listing tmp file.\n"), quote (lf)));
1611
1656
 
1612
1657
  con->target = xstrdup (lf);
1613
1658
  xfree (lf);
1614
 
  err = ftp_loop_internal (u, NULL, con);
 
1659
  err = ftp_loop_internal (u, NULL, con, NULL);
1615
1660
  lf = xstrdup (con->target);
1616
1661
  xfree (con->target);
1617
1662
  con->target = old_target;
1698
1743
      ofile = xstrdup (u->file);
1699
1744
      url_set_file (u, f->name);
1700
1745
 
1701
 
      con->target = url_file_name (u);
 
1746
      con->target = url_file_name (u, NULL);
1702
1747
      err = RETROK;
1703
1748
 
1704
1749
      dlthis = true;
1806
1851
          else                /* opt.retr_symlinks */
1807
1852
            {
1808
1853
              if (dlthis)
1809
 
                err = ftp_loop_internal (u, f, con);
 
1854
                err = ftp_loop_internal (u, f, con, NULL);
1810
1855
            } /* opt.retr_symlinks */
1811
1856
          break;
1812
1857
        case FT_DIRECTORY:
1817
1862
        case FT_PLAINFILE:
1818
1863
          /* Call the retrieve loop.  */
1819
1864
          if (dlthis)
1820
 
            err = ftp_loop_internal (u, f, con);
 
1865
            err = ftp_loop_internal (u, f, con, NULL);
1821
1866
          break;
1822
1867
        case FT_UNKNOWN:
1823
1868
          logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1849
1894
         original.  :( */
1850
1895
      if (actual_target != NULL)
1851
1896
        {
1852
 
          if (!(f->type == FT_SYMLINK && !opt.retr_symlinks)
 
1897
          if (opt.useservertimestamps
 
1898
              && !(f->type == FT_SYMLINK && !opt.retr_symlinks)
1853
1899
              && f->tstamp != -1
1854
1900
              && dlthis
1855
1901
              && file_exists_p (con->target))
2095
2141
        {
2096
2142
          /* Let's try retrieving it anyway.  */
2097
2143
          con->st |= ON_YOUR_OWN;
2098
 
          res = ftp_loop_internal (u, NULL, con);
 
2144
          res = ftp_loop_internal (u, NULL, con, NULL);
2099
2145
          return res;
2100
2146
        }
2101
2147
 
2116
2162
   of URL.  Inherently, its capabilities are limited on what can be
2117
2163
   encoded into a URL.  */
2118
2164
uerr_t
2119
 
ftp_loop (struct url *u, int *dt, struct url *proxy, bool recursive, bool glob)
 
2165
ftp_loop (struct url *u, char **local_file, int *dt, struct url *proxy,
 
2166
          bool recursive, bool glob)
2120
2167
{
2121
2168
  ccon con;                     /* FTP connection */
2122
2169
  uerr_t res;
2146
2193
              char *filename = (opt.output_document
2147
2194
                                ? xstrdup (opt.output_document)
2148
2195
                                : (con.target ? xstrdup (con.target)
2149
 
                                   : url_file_name (u)));
 
2196
                                   : url_file_name (u, NULL)));
2150
2197
              res = ftp_index (filename, u, f);
2151
2198
              if (res == FTPOK && opt.verbose)
2152
2199
                {
2195
2242
                                   ispattern ? GLOB_GLOBALL : GLOB_GETONE);
2196
2243
        }
2197
2244
      else
2198
 
        res = ftp_loop_internal (u, NULL, &con);
 
2245
        res = ftp_loop_internal (u, NULL, &con, local_file);
2199
2246
    }
2200
2247
  if (res == FTPOK)
2201
2248
    res = RETROK;