~ubuntu-branches/ubuntu/lucid/wget/lucid-security

« back to all changes in this revision

Viewing changes to src/ftp.c

  • Committer: Bazaar Package Importer
  • Author(s): Marc Deslauriers
  • Date: 2009-12-12 08:15:59 UTC
  • mfrom: (2.1.5 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091212081559-mvccl4kzdqb138y3
Tags: 1.12-1.1ubuntu1
* Merge from debian testing, remaining changes:
  - Add wget-udeb to ship wget.gnu as alternative to busybox wget
    implementation.
* Keep build dependencies in main:
  - debian/control: remove info2man build-dep
  - debian/patches/00list: disable wget-infopod_generated_manpage.dpatch

Show diffs side-by-side

added added

removed removed

Lines of Context:
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.
4
4
 
5
5
This file is part of GNU Wget.
6
6
 
28
28
shall include the source code for the parts of OpenSSL used as well
29
29
as that of the covered work.  */
30
30
 
31
 
#include <config.h>
 
31
#include "wget.h"
32
32
 
33
33
#include <stdio.h>
34
34
#include <stdlib.h>
35
35
#include <string.h>
 
36
#include <strings.h>
36
37
#ifdef HAVE_UNISTD_H
37
38
# include <unistd.h>
38
39
#endif
40
41
#include <errno.h>
41
42
#include <time.h>
42
43
 
43
 
#include "wget.h"
44
44
#include "utils.h"
45
45
#include "url.h"
46
46
#include "retr.h"
51
51
#include "convert.h"            /* for downloaded_file */
52
52
#include "recur.h"              /* for INFINITE_RECURSION */
53
53
 
 
54
#ifdef __VMS
 
55
# include "vms.h"
 
56
#endif /* def __VMS */
 
57
 
 
58
 
54
59
/* File where the "ls -al" listing will be saved.  */
55
60
#ifdef MSDOS
56
61
#define LIST_FILENAME "_listing"
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 */
71
76
} ccon;
72
77
 
 
78
extern int numurls;
73
79
 
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
89
95
      res = str_to_wgint (s, (char **) &s, 10);
90
96
      if (!*s)
91
97
        return 0;
92
 
      while (*s && ISSPACE (*s))
 
98
      while (*s && c_isspace (*s))
93
99
        ++s;
94
100
      if (!*s)
95
101
        return 0;
96
 
      if (TOLOWER (*s) != 'b')
 
102
      if (c_tolower (*s) != 'b')
97
103
        continue;
98
104
      if (strncasecmp (s, "byte", 4))
99
105
        continue;
104
110
}
105
111
 
106
112
#ifdef ENABLE_IPV6
107
 
/* 
 
113
/*
108
114
 * This function sets up a passive data connection with the FTP server.
109
115
 * It is merely a wrapper around ftp_epsv, ftp_lpsv and ftp_pasv.
110
116
 */
119
125
  if (!socket_ip_address (csock, addr, ENDPOINT_PEER))
120
126
    abort ();
121
127
 
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)
126
132
    {
149
155
  return err;
150
156
}
151
157
 
152
 
/* 
 
158
/*
153
159
 * This function sets up an active data connection with the FTP server.
154
160
 * It is merely a wrapper around ftp_eprt, ftp_lprt and ftp_port.
155
161
 */
162
168
  if (!socket_ip_address (csock, &cip, ENDPOINT_PEER))
163
169
    abort ();
164
170
 
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)
169
175
    {
217
223
    logprintf (LOG_VERBOSE, " (%s)", human_readable (size));
218
224
  if (start > 0)
219
225
    {
220
 
      if (start >= 1024)
 
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");
229
235
}
230
236
 
 
237
static uerr_t ftp_get_listing (struct url *, ccon *, struct fileinfo **);
 
238
 
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.  */
234
242
static uerr_t
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)
236
245
{
237
246
  int csock, dtsock, local_sock, res;
238
247
  uerr_t err = RETROK;          /* appease the compiler */
246
255
  bool rest_failed = false;
247
256
  int flags;
248
257
  wgint rd_size;
 
258
  char type_char;
249
259
 
250
260
  assert (con != NULL);
251
261
  assert (con->target != NULL);
257
267
  /* Make sure that at least *something* is requested.  */
258
268
  assert ((cmd & (DO_LIST | DO_CWD | DO_RETR | DO_LOGIN)) != 0);
259
269
 
 
270
  *qtyread = restval;
 
271
 
260
272
  user = u->user;
261
273
  passwd = u->passwd;
262
274
  search_netrc (u->host, (const char **)&user, (const char **)&passwd, 1);
273
285
    csock = con->csock;
274
286
  else                          /* cmd & DO_LOGIN */
275
287
    {
276
 
      char type_char;
277
288
      char    *host = con->proxy ? con->proxy->host : u->host;
278
289
      int      port = con->proxy ? con->proxy->port : u->port;
279
290
      char *logname = user;
301
312
        con->csock = -1;
302
313
 
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);
405
417
        default:
406
418
          abort ();
407
419
        }
 
420
 
 
421
#if 0
 
422
      /* 2004-09-17 SMS.
 
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
 
428
         to do.
 
429
      */
 
430
 
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)
411
434
        {
412
435
          char *path = strchr (con->id, '[');
428
451
              DEBUGP (("  new = '%s'\n\n", con->id));
429
452
            }
430
453
        }
 
454
#endif /* 0 */
 
455
 
431
456
      if (!opt.server_response)
432
457
        logputs (LOG_VERBOSE, _("done.\n"));
433
458
 
477
502
        logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
478
503
      else
479
504
        {
 
505
          char *targ;
 
506
          int cwd_count;
 
507
          int cwd_end;
 
508
          int cwd_start;
 
509
 
480
510
          char *target = u->dir;
481
511
 
482
512
          DEBUGP (("changing working directory\n"));
495
525
             in "bar", not in "foo/bar", as would be customary
496
526
             elsewhere.  */
497
527
 
 
528
            /* 2004-09-20 SMS.
 
529
               Why is this wise even on UNIX?  It certainly fouls VMS.
 
530
               See below for a more reliable, more universal method.
 
531
            */
 
532
 
 
533
            /* 2008-04-22 MJC.
 
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.
 
540
            */
 
541
 
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))
503
548
            {
504
549
              int idlen = strlen (con->id);
505
550
              char *ntarget, *p;
519
564
              target = ntarget;
520
565
            }
521
566
 
 
567
#if 0
 
568
          /* 2004-09-17 SMS.
 
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
 
573
             move.
 
574
             This code was disabled but left in as an example of what
 
575
             not to do.
 
576
          */
 
577
 
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;
546
602
            }
 
603
#endif /* 0 */
 
604
 
 
605
          /* 2004-09-20 SMS.
 
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
 
613
             for now.
 
614
          */
 
615
 
 
616
          /* Decide on one pass (absolute) or two (relative).
 
617
             The VMS restriction may be relaxed when the squirrely code
 
618
             above is reformed.
 
619
          */
 
620
          if ((con->rs == ST_VMS) && (target[0] != '/'))
 
621
            {
 
622
              cwd_start = 0;
 
623
              DEBUGP (("Using two-step CWD for relative path.\n"));
 
624
            }
 
625
          else
 
626
            {
 
627
              /* Go straight to the target. */
 
628
              cwd_start = 1;
 
629
            }
 
630
 
 
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.
 
638
 
 
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.
 
643
 
 
644
             Unlike the rest of this block, this particular behavior
 
645
             _is_ VMS-specific, so it gets its own VMS test.
 
646
          */
 
647
          if ((con->rs == ST_VMS) && (strchr( target, '/') != NULL))
 
648
            {
 
649
              cwd_end = 3;
 
650
              DEBUGP (("Using extra \"CWD []\" step for VMS server.\n"));
 
651
            }
 
652
          else
 
653
            {
 
654
              cwd_end = 2;
 
655
            }
 
656
 
 
657
          /* 2004-09-20 SMS. */
 
658
          /* Sorry about the deviant indenting.  Laziness. */
 
659
 
 
660
          for (cwd_count = cwd_start; cwd_count < cwd_end; cwd_count++)
 
661
        {
 
662
          switch (cwd_count)
 
663
            {
 
664
              case 0:
 
665
                /* Step one (optional): Go to the initial directory,
 
666
                   exactly as reported by the server.
 
667
                */
 
668
                targ = con->id;
 
669
                break;
 
670
 
 
671
              case 1:
 
672
                /* Step two: Go to the target directory.  (Absolute or
 
673
                   relative will work now.)
 
674
                */
 
675
                targ = target;
 
676
                break;
 
677
 
 
678
              case 2:
 
679
                /* Step three (optional): "CWD []" to restore server
 
680
                   VMS-ness.
 
681
                */
 
682
                targ = "[]";
 
683
                break;
 
684
 
 
685
              default:
 
686
                /* Can't happen. */
 
687
                assert (1);
 
688
            }
547
689
 
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 */
552
695
          switch (err)
567
710
              return err;
568
711
            case FTPNSFOD:
569
712
              logputs (LOG_VERBOSE, "\n");
570
 
              logprintf (LOG_NOTQUIET, _("No such directory `%s'.\n\n"),
571
 
                         escnonprint (u->dir));
 
713
              logprintf (LOG_NOTQUIET, _("No such directory %s.\n\n"),
 
714
                         quote (u->dir));
572
715
              fd_close (csock);
573
716
              con->csock = -1;
574
717
              return err;
579
722
            }
580
723
          if (!opt.server_response)
581
724
            logputs (LOG_VERBOSE, _("done.\n"));
582
 
        }
 
725
 
 
726
        } /* for */
 
727
 
 
728
          /* 2004-09-20 SMS. */
 
729
          /* End of deviant indenting. */
 
730
 
 
731
        } /* else */
583
732
    }
584
733
  else /* do not CWD */
585
734
    logputs (LOG_VERBOSE, _("==> CWD not required.\n"));
586
735
 
587
 
  if ((cmd & DO_RETR) && *len == 0)
 
736
  if ((cmd & DO_RETR) && passed_expected_bytes == 0)
588
737
    {
589
738
      if (opt.verbose)
590
739
        {
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));
593
743
        }
594
744
 
595
 
      err = ftp_size (csock, u->file, len);
 
745
      err = ftp_size (csock, u->file, &expected_bytes);
596
746
      /* FTPRERR */
597
747
      switch (err)
598
748
        {
611
761
          abort ();
612
762
        }
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));
616
766
    }
617
767
 
618
768
  /* If anything is to be retrieved, PORT (or PASV) must be sent.  */
655
805
            }   /* switch (err) */
656
806
          if (err==FTPOK)
657
807
            {
658
 
              DEBUGP (("trying to connect to %s port %d\n", 
 
808
              DEBUGP (("trying to connect to %s port %d\n",
659
809
                      print_address (&passive_addr), passive_port));
660
810
              dtsock = connect_to_ip (&passive_addr, passive_port, NULL);
661
811
              if (dtsock < 0)
777
927
 
778
928
  if (cmd & DO_RETR)
779
929
    {
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"
783
 
         request.  */
 
930
      /* If we're in spider mode, don't really retrieve anything except
 
931
         the directory listing and verify whether the given "file" exists.  */
784
932
      if (opt.spider)
785
933
        {
 
934
          bool exists = false;
 
935
          uerr_t res;
 
936
          struct fileinfo *f;
 
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).  */
 
942
          con->cmd |= DO_RETR;
 
943
          if (res == RETROK)
 
944
            {
 
945
              while (f)
 
946
                {
 
947
                  if (!strcmp (f->name, u->file))
 
948
                    {
 
949
                      exists = true;
 
950
                      break;
 
951
                    }
 
952
                  f = f->next;
 
953
                }
 
954
              if (exists)
 
955
                {
 
956
                  logputs (LOG_VERBOSE, "\n");
 
957
                  logprintf (LOG_NOTQUIET, _("File %s exists.\n"),
 
958
                             quote (u->file));
 
959
                }
 
960
              else
 
961
                {
 
962
                  logputs (LOG_VERBOSE, "\n");
 
963
                  logprintf (LOG_NOTQUIET, _("No such file %s.\n"),
 
964
                             quote (u->file));
 
965
                }
 
966
            }
786
967
          fd_close (csock);
787
968
          con->csock = -1;
788
969
          fd_close (dtsock);
796
977
            {
797
978
              if (restval)
798
979
                logputs (LOG_VERBOSE, "\n");
799
 
              logprintf (LOG_VERBOSE, "==> RETR %s ... ", escnonprint (u->file));
 
980
              logprintf (LOG_VERBOSE, "==> RETR %s ... ",
 
981
                         quotearg_style (escape_quoting_style, u->file));
800
982
            }
801
983
        }
802
984
 
824
1006
          return err;
825
1007
        case FTPNSFOD:
826
1008
          logputs (LOG_VERBOSE, "\n");
827
 
          logprintf (LOG_NOTQUIET, _("No such file `%s'.\n\n"),
828
 
                     escnonprint (u->file));
 
1009
          logprintf (LOG_NOTQUIET, _("No such file %s.\n\n"),
 
1010
                     quote (u->file));
829
1011
          fd_close (dtsock);
830
1012
          fd_close (local_sock);
831
1013
          return err;
847
1029
      /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'
848
1030
         without arguments is better than `LIST .'; confirmed by
849
1031
         RFC959.  */
850
 
      err = ftp_list (csock, NULL);
 
1032
      err = ftp_list (csock, NULL, con->rs);
851
1033
      /* FTPRERR, WRITEFAILED */
852
1034
      switch (err)
853
1035
        {
871
1053
          return err;
872
1054
        case FTPNSFOD:
873
1055
          logputs (LOG_VERBOSE, "\n");
874
 
          logprintf (LOG_NOTQUIET, _("No such file or directory `%s'.\n\n"),
875
 
                     ".");
 
1056
          logprintf (LOG_NOTQUIET, _("No such file or directory %s.\n\n"),
 
1057
                     quote ("."));
876
1058
          fd_close (dtsock);
877
1059
          fd_close (local_sock);
878
1060
          return err;
891
1073
 
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))
896
1078
    {
897
1079
      DEBUGP (("Lying FTP server found, adjusting.\n"));
898
 
      expected_bytes = *len;
 
1080
      expected_bytes = passed_expected_bytes;
899
1081
    }
900
1082
 
901
1083
  /* If no transmission was required, then everything is OK.  */
908
1090
      if (dtsock < 0)
909
1091
        {
910
1092
          logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));
911
 
          return err;
 
1093
          return CONERROR;
912
1094
        }
913
1095
    }
914
1096
 
915
1097
  /* Open the file -- if output_stream is set, use it instead.  */
 
1098
 
 
1099
  /* 2005-04-17 SMS.
 
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.)
 
1105
  */
916
1106
  if (!output_stream || con->cmd & DO_LIST)
917
1107
    {
 
1108
/* On VMS, alter the name as required. */
 
1109
#ifdef __VMS
 
1110
      char *targ;
 
1111
 
 
1112
      targ = ods_conform (con->target);
 
1113
      if (targ != con->target)
 
1114
        {
 
1115
          xfree (con->target);
 
1116
          con->target = targ;
 
1117
        }
 
1118
#endif /* def __VMS */
 
1119
 
918
1120
      mkalldirs (con->target);
919
1121
      if (opt.backups)
920
1122
        rotate_backups (con->target);
921
1123
 
 
1124
/* 2005-04-15 SMS.
 
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?
 
1129
*/
 
1130
# define BIN_TYPE_TRANSFER (type_char != 'A')
 
1131
#ifdef __VMS
 
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] */
 
1138
 
922
1139
      if (restval && !(con->cmd & DO_LIST))
923
 
        fp = fopen (con->target, "ab");
 
1140
        {
 
1141
#ifdef __VMS
 
1142
          int open_id;
 
1143
 
 
1144
          if (BIN_TYPE_FILE)
 
1145
            {
 
1146
              open_id = 3;
 
1147
              fp = fopen (con->target, "ab", FOPEN_OPT_ARGS_BIN);
 
1148
            }
 
1149
          else
 
1150
            {
 
1151
              open_id = 4;
 
1152
              fp = fopen (con->target, "a", FOPEN_OPT_ARGS);
 
1153
            }
 
1154
#else /* def __VMS */
 
1155
          fp = fopen (con->target, "ab");
 
1156
#endif /* def __VMS [else] */
 
1157
        }
924
1158
      else if (opt.noclobber || opt.always_rest || opt.timestamping || opt.dirstruct
925
1159
               || opt.output_document)
926
 
        fp = fopen (con->target, "wb");
 
1160
        {
 
1161
#ifdef __VMS
 
1162
          int open_id;
 
1163
 
 
1164
          if (BIN_TYPE_FILE)
 
1165
            {
 
1166
              open_id = 5;
 
1167
              fp = fopen (con->target, "wb", FOPEN_OPT_ARGS_BIN);
 
1168
            }
 
1169
          else
 
1170
            {
 
1171
              open_id = 6;
 
1172
              fp = fopen (con->target, "w", FOPEN_OPT_ARGS);
 
1173
            }
 
1174
#else /* def __VMS */
 
1175
          fp = fopen (con->target, "wb");
 
1176
#endif /* def __VMS [else] */
 
1177
        }
927
1178
      else
928
1179
        {
929
1180
          fp = fopen_excl (con->target, true);
955
1206
  else
956
1207
    fp = output_stream;
957
1208
 
958
 
  if (*len)
 
1209
  if (passed_expected_bytes)
959
1210
    {
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 */
962
1214
    }
963
1215
  else if (expected_bytes)
964
1216
    print_length (expected_bytes, restval, false);
967
1219
  flags = 0;
968
1220
  if (restval && rest_failed)
969
1221
    flags |= rb_skip_startpos;
970
 
  *len = restval;
971
1222
  rd_size = 0;
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);
975
1226
 
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))
1052
1303
    {
 
1304
/* 2005-02-25 SMS.
 
1305
   Much of this work may already have been done, but repeating it should
 
1306
   do no damage beyond wasting time.
 
1307
*/
 
1308
/* On VMS, alter the name as required. */
 
1309
#ifdef __VMS
 
1310
      char *targ;
 
1311
 
 
1312
      targ = ods_conform( con->target);
 
1313
      if (targ != con->target)
 
1314
        {
 
1315
          xfree( con->target);
 
1316
          con->target = targ;
 
1317
        }
 
1318
#endif /* def __VMS */
 
1319
 
1053
1320
      mkalldirs (con->target);
1054
1321
      fp = fopen (con->target, "r");
1055
1322
      if (!fp)
1064
1331
              char *p = strchr (line, '\0');
1065
1332
              while (p > line && (p[-1] == '\n' || p[-1] == '\r'))
1066
1333
                *--p = '\0';
1067
 
              logprintf (LOG_ALWAYS, "%s\n", escnonprint (line));
 
1334
              logprintf (LOG_ALWAYS, "%s\n",
 
1335
                         quotearg_style (escape_quoting_style, line));
1068
1336
              xfree (line);
1069
1337
            }
1070
1338
          fclose (fp);
1083
1351
ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
1084
1352
{
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;
1089
1357
  uerr_t err;
1090
1358
  struct_stat st;
1091
1359
 
1092
 
  if (!con->target)
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))
 
1362
    {
 
1363
      /* Explicit file (like ".listing"). */
 
1364
      locf = con->target;
 
1365
    }
 
1366
  else
 
1367
    {
 
1368
      /* URL-derived file.  Consider "-O file" name. */
 
1369
      con->target = url_file_name (u);
 
1370
      if (!opt.output_document)
 
1371
        locf = con->target;
 
1372
      else
 
1373
        locf = opt.output_document;
 
1374
    }
1094
1375
 
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))
1098
1379
    {
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.  */
1102
1383
      return RETROK;
1103
1384
    }
1104
1385
 
1105
1386
  /* Remove it if it's a link.  */
1106
1387
  remove_link (con->target);
1107
 
  if (!opt.output_document)
1108
 
    locf = con->target;
1109
 
  else
1110
 
    locf = opt.output_document;
1111
1388
 
1112
1389
  count = 0;
1113
1390
 
1154
1431
           first attempt to clobber existing data.)  */
1155
1432
        restval = st.st_size;
1156
1433
      else if (count > 1)
1157
 
        restval = len;          /* start where the previous run left off */
 
1434
        restval = qtyread;          /* start where the previous run left off */
1158
1435
      else
1159
1436
        restval = 0;
1160
1437
 
1168
1445
          strcpy (tmp, "        ");
1169
1446
          if (count > 1)
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));
1173
1450
#ifdef WINDOWS
1174
1451
          ws_changetitle (hurl);
1175
1452
#endif
1180
1457
        len = f->size;
1181
1458
      else
1182
1459
        len = 0;
1183
 
      err = getftp (u, &len, restval, con);
 
1460
      err = getftp (u, len, &qtyread, restval, con);
1184
1461
 
1185
1462
      if (con->csock == -1)
1186
1463
        con->st &= ~DONE_CWD;
1210
1487
        case FTPRETRINT:
1211
1488
          /* If the control connection was closed, the retrieval
1212
1489
             will be considered OK if f->size == len.  */
1213
 
          if (!f || len != f->size)
 
1490
          if (!f || qtyread != f->size)
1214
1491
            {
1215
1492
              printwhat (count, opt.ntry);
1216
1493
              continue;
1225
1502
        }
1226
1503
      tms = datetime_str (time (NULL));
1227
1504
      if (!opt.spider)
1228
 
        tmrate = retr_rate (len - restval, con->dltime);
 
1505
        tmrate = retr_rate (qtyread - restval, con->dltime);
1229
1506
 
1230
1507
      /* If we get out of the switch above without continue'ing, we've
1231
1508
         successfully downloaded a file.  Remember this fact. */
1237
1514
          con->csock = -1;
1238
1515
        }
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));
 
1517
        {
 
1518
          bool write_to_stdout = (opt.output_document && HYPHENP (opt.output_document));
 
1519
 
 
1520
          logprintf (LOG_VERBOSE,
 
1521
                     write_to_stdout
 
1522
                     ? _("%s (%s) - written to stdout %s[%s]\n\n")
 
1523
                     : _("%s (%s) - %s saved [%s]\n\n"),
 
1524
                     tms, tmrate,
 
1525
                     write_to_stdout ? "" : quote (locf),
 
1526
                     number_to_static_string (qtyread));
 
1527
        }
1242
1528
      if (!opt.verbose && !opt.quiet)
1243
1529
        {
1244
1530
          /* Need to hide the password from the URL.  The `if' is here
1246
1532
             time. */
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);
1250
1536
          xfree (hurl);
1251
1537
        }
1252
1538
 
1257
1543
            /* --dont-remove-listing was specified, so do count this towards the
1258
1544
               number of bytes and files downloaded. */
1259
1545
            {
1260
 
              total_downloaded_bytes += len;
1261
 
              opt.numurls++;
 
1546
              total_downloaded_bytes += qtyread;
 
1547
              numurls++;
1262
1548
            }
1263
1549
 
1264
1550
          /* Deletion of listing files is not controlled by --delete-after, but
1272
1558
             downloaded if they're going to be deleted.  People seeding proxies,
1273
1559
             for instance, may want to know how many bytes and files they've
1274
1560
             downloaded through it. */
1275
 
          total_downloaded_bytes += len;
1276
 
          opt.numurls++;
 
1561
          total_downloaded_bytes += qtyread;
 
1562
          numurls++;
1277
1563
 
1278
1564
          if (opt.delete_after)
1279
1565
            {
1321
1607
  uf = url_file_name (u);
1322
1608
  lf = file_merge (uf, LIST_FILENAME);
1323
1609
  xfree (uf);
1324
 
  DEBUGP ((_("Using `%s' as listing tmp file.\n"), lf));
 
1610
  DEBUGP ((_("Using %s as listing tmp file.\n"), quote (lf)));
1325
1611
 
1326
 
  con->target = lf;
 
1612
  con->target = xstrdup (lf);
 
1613
  xfree (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;
1329
1618
 
1330
1619
  if (err == RETROK)
1331
 
    *f = ftp_parse_ls (lf, con->rs);
 
1620
    {
 
1621
      *f = ftp_parse_ls (lf, con->rs);
 
1622
      if (opt.remove_listing)
 
1623
        {
 
1624
          if (unlink (lf))
 
1625
            logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
 
1626
          else
 
1627
            logprintf (LOG_VERBOSE, _("Removed %s.\n"), quote (lf));
 
1628
        }
 
1629
    }
1332
1630
  else
1333
1631
    *f = NULL;
1334
 
  if (opt.remove_listing)
1335
 
    {
1336
 
      if (unlink (lf))
1337
 
        logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1338
 
      else
1339
 
        logprintf (LOG_VERBOSE, _("Removed `%s'.\n"), lf);
1340
 
    }
1341
1632
  xfree (lf);
1342
1633
  con->cmd &= ~DO_LIST;
1343
1634
  return err;
1363
1654
  struct fileinfo *orig;
1364
1655
  wgint local_size;
1365
1656
  time_t tml;
1366
 
  bool dlthis;
 
1657
  bool dlthis; /* Download this (file). */
 
1658
  const char *actual_target = NULL;
1367
1659
 
1368
1660
  /* Increase the depth.  */
1369
1661
  ++depth;
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;
1445
1737
                }
1446
1738
              else if (eq_size)
1447
1739
                {
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"),
1451
 
                             con->target);
 
1742
Remote file is newer than local file %s -- retrieving.\n\n"),
 
1743
                             quote (con->target));
1452
1744
                }
1453
1745
              else
1454
1746
                {
1490
1782
                            {
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),
 
1786
                                         quote (f->linkto));
1494
1787
                              dlthis = false;
1495
1788
                              break;
1496
1789
                            }
1497
1790
                        }
1498
1791
                    }
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)
1506
1799
                } /* have f->linkto */
1507
1800
#else  /* not HAVE_SYMLINK */
1508
1801
              logprintf (LOG_NOTQUIET,
1509
 
                         _("Symlinks not supported, skipping symlink `%s'.\n"),
1510
 
                         con->target);
 
1802
                         _("Symlinks not supported, skipping symlink %s.\n"),
 
1803
                         quote (con->target));
1511
1804
#endif /* not HAVE_SYMLINK */
1512
1805
            }
1513
1806
          else                /* opt.retr_symlinks */
1518
1811
          break;
1519
1812
        case FT_DIRECTORY:
1520
1813
          if (!opt.recursive)
1521
 
            logprintf (LOG_NOTQUIET, _("Skipping directory `%s'.\n"),
1522
 
                       escnonprint (f->name));
 
1814
            logprintf (LOG_NOTQUIET, _("Skipping directory %s.\n"),
 
1815
                       quote (f->name));
1523
1816
          break;
1524
1817
        case FT_PLAINFILE:
1525
1818
          /* Call the retrieve loop.  */
1528
1821
          break;
1529
1822
        case FT_UNKNOWN:
1530
1823
          logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1531
 
                     escnonprint (f->name));
 
1824
                     quote (f->name));
1532
1825
          break;
1533
1826
        }       /* switch */
1534
1827
 
 
1828
 
 
1829
      /* 2004-12-15 SMS.
 
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.)
 
1834
       */
 
1835
 
 
1836
      set_local_file (&actual_target, con->target);
 
1837
 
 
1838
      /* If downloading a plain file, set valid (non-zero) permissions. */
 
1839
      if (dlthis && (actual_target != NULL) && (f->type == FT_PLAINFILE))
 
1840
        {
 
1841
          if (f->perms)
 
1842
            chmod (actual_target, f->perms);
 
1843
          else
 
1844
            DEBUGP (("Unrecognized permissions for %s.\n", actual_target));
 
1845
        }
 
1846
 
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)
1539
 
          && f->tstamp != -1
1540
 
          && dlthis
1541
 
          && file_exists_p (con->target))
 
1850
      if (actual_target != NULL)
1542
1851
        {
1543
 
          /* #### This code repeats in http.c and ftp.c.  Move it to a
1544
 
             function!  */
1545
 
          const char *fl = NULL;
1546
 
          if (opt.output_document)
 
1852
          if (!(f->type == FT_SYMLINK && !opt.retr_symlinks)
 
1853
              && f->tstamp != -1
 
1854
              && dlthis
 
1855
              && file_exists_p (con->target))
1547
1856
            {
1548
 
              if (output_stream_regular)
1549
 
                fl = opt.output_document;
 
1857
              touch (actual_target, f->tstamp);
1550
1858
            }
1551
 
          else
1552
 
            fl = con->target;
1553
 
          if (fl)
1554
 
            touch (fl, f->tstamp);
1555
 
        }
1556
 
      else if (f->tstamp == -1)
1557
 
        logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"), con->target);
1558
 
 
1559
 
      if (f->perms && f->type == FT_PLAINFILE && dlthis)
1560
 
        {
1561
 
          if (opt.preserve_perm)
1562
 
            chmod (con->target, f->perms);
1563
 
        }
1564
 
      else
1565
 
        DEBUGP (("Unrecognized permissions for %s.\n", con->target));
 
1859
          else if (f->tstamp == -1)
 
1860
            logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"),
 
1861
                       actual_target);
 
1862
        }
1566
1863
 
1567
1864
      xfree (con->target);
1568
1865
      con->target = old_target;
1633
1930
      if (!accdir (newdir))
1634
1931
        {
1635
1932
          logprintf (LOG_VERBOSE, _("\
1636
 
Not descending to `%s' as it is excluded/not-included.\n"),
1637
 
                     escnonprint (newdir));
 
1933
Not descending to %s as it is excluded/not-included.\n"),
 
1934
                     quote (newdir));
1638
1935
          continue;
1639
1936
        }
1640
1937
 
1698
1995
        {
1699
1996
          if (f->type != FT_DIRECTORY && !acceptable (f->name))
1700
1997
            {
1701
 
              logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"),
1702
 
                         escnonprint (f->name));
 
1998
              logprintf (LOG_VERBOSE, _("Rejecting %s.\n"),
 
1999
                         quote (f->name));
1703
2000
              f = delelement (f, &start);
1704
2001
            }
1705
2002
          else
1712
2009
    {
1713
2010
      if (has_insecure_name_p (f->name))
1714
2011
        {
1715
 
          logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"),
1716
 
                     escnonprint (f->name));
 
2012
          logprintf (LOG_VERBOSE, _("Rejecting %s.\n"),
 
2013
                     quote (f->name));
1717
2014
          f = delelement (f, &start);
1718
2015
        }
1719
2016
      else
1736
2033
              if (matchres == -1)
1737
2034
                {
1738
2035
                  logprintf (LOG_NOTQUIET, _("Error matching %s against %s: %s\n"),
1739
 
                             u->file, escnonprint (f->name), strerror (errno));
 
2036
                             u->file, quotearg_style (escape_quoting_style, f->name),
 
2037
                             strerror (errno));
1740
2038
                  break;
1741
2039
                }
1742
2040
              if (matchres == FNM_NOMATCH)
1752
2050
        }
1753
2051
      else if (action == GLOB_GETONE)
1754
2052
        {
 
2053
#ifdef __VMS
 
2054
          /* 2009-09-09 SMS.
 
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
 
2061
           * harmless.
 
2062
           */
 
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] */
1757
2069
          f = start;
1758
2070
          while (f)
1759
2071
            {
1776
2088
          /* No luck.  */
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"),
 
2092
                     quote (u->file));
1781
2093
        }
1782
 
      else if (*u->file) /* GLOB_GETONE or GLOB_GETALL */
 
2094
      else if (action == GLOB_GETONE) /* GLOB_GETONE or GLOB_GETALL */
1783
2095
        {
1784
2096
          /* Let's try retrieving it anyway.  */
1785
2097
          con->st |= ON_YOUR_OWN;
1786
2098
          res = ftp_loop_internal (u, NULL, con);
1787
2099
          return res;
1788
2100
        }
 
2101
 
 
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.)
 
2105
      */
1789
2106
    }
1790
2107
  freefileinfo (start);
1791
2108
  if (opt.quota && total_downloaded_bytes > opt.quota)
1842
2159
                      else
1843
2160
                        sz = -1;
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));
1847
2164
                    }
1848
2165
                  else
1849
2166
                    logprintf (LOG_NOTQUIET,
1850
 
                               _("Wrote HTML-ized index to `%s'.\n"),
1851
 
                               filename);
 
2167
                               _("Wrote HTML-ized index to %s.\n"),
 
2168
                               quote (filename));
1852
2169
                }
1853
2170
              xfree (filename);
1854
2171
            }