⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftp.c

📁 Wget很好的处理了http和ftp的下载,很值得学习的经典代码
💻 C
📖 第 1 页 / 共 5 页
字号:
        }      if (err != FTPRESTFAIL && !opt.server_response)        logputs (LOG_VERBOSE, _("done.    "));    } /* restval && cmd & DO_RETR */  if (cmd & DO_RETR)    {      /* If we're in spider mode, don't really retrieve anything.  The         fact that we got to this point should be proof enough that         the file exists, vaguely akin to HTTP's concept of a "HEAD"         request.  */      if (opt.spider)        {          fd_close (csock);          con->csock = -1;          fd_close (dtsock);          fd_close (local_sock);          return RETRFINISHED;        }      if (opt.verbose)        {          if (!opt.server_response)            {              if (restval)                logputs (LOG_VERBOSE, "\n");              logprintf (LOG_VERBOSE, "==> RETR %s ... ", escnonprint (u->file));            }        }      err = ftp_retr (csock, u->file);      /* FTPRERR, WRITEFAILED, FTPNSFOD */      switch (err)        {        case FTPRERR:          logputs (LOG_VERBOSE, "\n");          logputs (LOG_NOTQUIET, _("\Error in server response, closing control connection.\n"));          fd_close (csock);          con->csock = -1;          fd_close (dtsock);          fd_close (local_sock);          return err;        case WRITEFAILED:          logputs (LOG_VERBOSE, "\n");          logputs (LOG_NOTQUIET,                   _("Write failed, closing control connection.\n"));          fd_close (csock);          con->csock = -1;          fd_close (dtsock);          fd_close (local_sock);          return err;        case FTPNSFOD:          logputs (LOG_VERBOSE, "\n");          logprintf (LOG_NOTQUIET, _("No such file `%s'.\n\n"),                     escnonprint (u->file));          fd_close (dtsock);          fd_close (local_sock);          return err;        case FTPOK:          break;        default:          abort ();        }      if (!opt.server_response)        logputs (LOG_VERBOSE, _("done.\n"));      expected_bytes = ftp_expected_bytes (ftp_last_respline);    } /* do retrieve */  if (cmd & DO_LIST)    {      if (!opt.server_response)        logputs (LOG_VERBOSE, "==> LIST ... ");      /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'         without arguments is better than `LIST .'; confirmed by         RFC959.  */      err = ftp_list (csock, NULL);      /* FTPRERR, WRITEFAILED */      switch (err)        {        case FTPRERR:          logputs (LOG_VERBOSE, "\n");          logputs (LOG_NOTQUIET, _("\Error in server response, closing control connection.\n"));          fd_close (csock);          con->csock = -1;          fd_close (dtsock);          fd_close (local_sock);          return err;        case WRITEFAILED:          logputs (LOG_VERBOSE, "\n");          logputs (LOG_NOTQUIET,                   _("Write failed, closing control connection.\n"));          fd_close (csock);          con->csock = -1;          fd_close (dtsock);          fd_close (local_sock);          return err;        case FTPNSFOD:          logputs (LOG_VERBOSE, "\n");          logprintf (LOG_NOTQUIET, _("No such file or directory `%s'.\n\n"),                     ".");          fd_close (dtsock);          fd_close (local_sock);          return err;        case FTPOK:          break;        default:          abort ();        }      if (!opt.server_response)        logputs (LOG_VERBOSE, _("done.\n"));      expected_bytes = ftp_expected_bytes (ftp_last_respline);    } /* cmd & DO_LIST */  if (!(cmd & (DO_LIST | DO_RETR)) || (opt.spider && !(cmd & DO_LIST)))    return RETRFINISHED;  /* Some FTP servers return the total length of file after REST     command, others just return the remaining size. */  if (*len && restval && expected_bytes      && (expected_bytes == *len - restval))    {      DEBUGP (("Lying FTP server found, adjusting.\n"));      expected_bytes = *len;    }  /* If no transmission was required, then everything is OK.  */  if (!pasv_mode_open)  /* we are not using pasive mode so we need                              to accept */    {      /* Wait for the server to connect to the address we're waiting         at.  */      dtsock = accept_connection (local_sock);      if (dtsock < 0)        {          logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));          return err;        }    }  /* Open the file -- if output_stream is set, use it instead.  */  if (!output_stream || con->cmd & DO_LIST)    {      mkalldirs (con->target);      if (opt.backups)        rotate_backups (con->target);      if (restval)        fp = fopen (con->target, "ab");      else if (opt.noclobber || opt.always_rest || opt.timestamping || opt.dirstruct               || opt.output_document)        fp = fopen (con->target, "wb");      else        {          fp = fopen_excl (con->target, true);          if (!fp && errno == EEXIST)            {              /* We cannot just invent a new name and use it (which is                 what functions like unique_create typically do)                 because we told the user we'd use this name.                 Instead, return and retry the download.  */              logprintf (LOG_NOTQUIET, _("%s has sprung into existence.\n"),                         con->target);              fd_close (csock);              con->csock = -1;              fd_close (dtsock);              fd_close (local_sock);              return FOPEN_EXCL_ERR;            }        }      if (!fp)        {          logprintf (LOG_NOTQUIET, "%s: %s\n", con->target, strerror (errno));          fd_close (csock);          con->csock = -1;          fd_close (dtsock);          fd_close (local_sock);          return FOPENERR;        }    }  else    fp = output_stream;  if (*len)    {      print_length (*len, restval, true);      expected_bytes = *len;    /* for fd_read_body's progress bar */    }  else if (expected_bytes)    print_length (expected_bytes, restval, false);  /* Get the contents of the document.  */  flags = 0;  if (restval && rest_failed)    flags |= rb_skip_startpos;  *len = restval;  rd_size = 0;  res = fd_read_body (dtsock, fp,                      expected_bytes ? expected_bytes - restval : 0,                      restval, &rd_size, len, &con->dltime, flags);  tms = datetime_str (time (NULL));  tmrate = retr_rate (rd_size, con->dltime);  total_download_time += con->dltime;  fd_close (local_sock);  /* Close the local file.  */  if (!output_stream || con->cmd & DO_LIST)    fclose (fp);  /* If fd_read_body couldn't write to fp, bail out.  */  if (res == -2)    {      logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),                 con->target, strerror (errno));      fd_close (csock);      con->csock = -1;      fd_close (dtsock);      return FWRITEERR;    }  else if (res == -1)    {      logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),                 tms, tmrate, fd_errstr (dtsock));      if (opt.server_response)        logputs (LOG_ALWAYS, "\n");    }  fd_close (dtsock);  /* Get the server to tell us if everything is retrieved.  */  err = ftp_response (csock, &respline);  if (err != FTPOK)    {      /* The control connection is decidedly closed.  Print the time         only if it hasn't already been printed.  */      if (res != -1)        logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);      logputs (LOG_NOTQUIET, _("Control connection closed.\n"));      /* If there is an error on the control connection, close it, but         return FTPRETRINT, since there is a possibility that the         whole file was retrieved nevertheless (but that is for         ftp_loop_internal to decide).  */      fd_close (csock);      con->csock = -1;      return FTPRETRINT;    } /* err != FTPOK */  /* If retrieval failed for any reason, return FTPRETRINT, but do not     close socket, since the control connection is still alive.  If     there is something wrong with the control connection, it will     become apparent later.  */  if (*respline != '2')    {      xfree (respline);      if (res != -1)        logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);      logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));      return FTPRETRINT;    }  xfree (respline);  if (res == -1)    {      /* What now?  The data connection was erroneous, whereas the         response says everything is OK.  We shall play it safe.  */      return FTPRETRINT;    }  if (!(cmd & LEAVE_PENDING))    {      /* Closing the socket is faster than sending 'QUIT' and the         effect is the same.  */      fd_close (csock);      con->csock = -1;    }  /* If it was a listing, and opt.server_response is true,     print it out.  */  if (opt.server_response && (con->cmd & DO_LIST))    {      mkalldirs (con->target);      fp = fopen (con->target, "r");      if (!fp)        logprintf (LOG_ALWAYS, "%s: %s\n", con->target, strerror (errno));      else        {          char *line;          /* The lines are being read with read_whole_line because of             no-buffering on opt.lfile.  */          while ((line = read_whole_line (fp)) != NULL)            {              char *p = strchr (line, '\0');              while (p > line && (p[-1] == '\n' || p[-1] == '\r'))                *--p = '\0';              logprintf (LOG_ALWAYS, "%s\n", escnonprint (line));              xfree (line);            }          fclose (fp);        }    } /* con->cmd & DO_LIST && server_response */  return RETRFINISHED;}/* A one-file FTP loop.  This is the part where FTP retrieval is   retried, and retried, and retried, and...   This loop either gets commands from con, or (if ON_YOUR_OWN is   set), makes them up to retrieve the file given by the URL.  */static uerr_tftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con){  int count, orig_lp;  wgint restval, len = 0;  char *tms, *locf;  const char *tmrate = NULL;  uerr_t err;  struct_stat st;  if (!con->target)    con->target = url_file_name (u);  if (opt.noclobber && file_exists_p (con->target))    {      logprintf (LOG_VERBOSE,                 _("File `%s' already there; not retrieving.\n"), con->target);      /* If the file is there, we suppose it's retrieved OK.  */      return RETROK;    }  /* Remove it if it's a link.  */  remove_link (con->target);  if (!opt.output_document)    locf = con->target;  else    locf = opt.output_document;  count = 0;  if (con->st & ON_YOUR_OWN)    con->st = ON_YOUR_OWN;  orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;  /* THE loop.  */  do    {      /* Increment the pass counter.  */      ++count;      sleep_between_retrievals (count);      if (con->st & ON_YOUR_OWN)        {          con->cmd = 0;          con->cmd |= (DO_RETR | LEAVE_PENDING);          if (con->csock != -1)            con->cmd &= ~ (DO_LOGIN | DO_CWD);          else            con->cmd |= (DO_LOGIN | DO_CWD);        }      else /* not on your own */        {          if (con->csock != -1)            con->cmd &= ~DO_LOGIN;          else            con->cmd |= DO_LOGIN;          if (con->st & DONE_CWD)            con->cmd &= ~DO_CWD;          else            con->cmd |= DO_CWD;        }      /* Decide whether or not to restart.  */      if (opt.always_rest          && stat (locf, &st) == 0          && S_ISREG (st.st_mode))        /* When -c is used, continue from on-disk size.  (Can't use           hstat.len even if count>1 because we don't want a failed           first attempt to clobber existing data.)  */        restval = st.st_size;      else if (count > 1)        restval = len;          /* start where the previous run left off */      else        restval = 0;      /* Get the current time string.  */      tms = datetime_str (time (NULL));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -