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

📄 ftp.c

📁 Wget很好的处理了http和ftp的下载,很值得学习的经典代码
💻 C
📖 第 1 页 / 共 5 页
字号:
      /* Print fetch message, if opt.verbose.  */      if (opt.verbose)        {          char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);          char tmp[256];          strcpy (tmp, "        ");          if (count > 1)            sprintf (tmp, _("(try:%2d)"), count);          logprintf (LOG_VERBOSE, "--%s--  %s\n  %s => `%s'\n",                     tms, hurl, tmp, locf);#ifdef WINDOWS          ws_changetitle (hurl);#endif          xfree (hurl);        }      /* Send getftp the proper length, if fileinfo was provided.  */      if (f)        len = f->size;      else        len = 0;      err = getftp (u, &len, restval, con);      if (con->csock == -1)        con->st &= ~DONE_CWD;      else        con->st |= DONE_CWD;      switch (err)        {        case HOSTERR: case CONIMPOSSIBLE: case FWRITEERR: case FOPENERR:        case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:          /* Fatal errors, give up.  */          return err;        case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:        case WRITEFAILED: case FTPUNKNOWNTYPE: case FTPSYSERR:        case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:        case FOPEN_EXCL_ERR:          printwhat (count, opt.ntry);          /* non-fatal errors */          if (err == FOPEN_EXCL_ERR)            {              /* Re-determine the file name. */              xfree_null (con->target);              con->target = url_file_name (u);              locf = con->target;            }          continue;        case FTPRETRINT:          /* If the control connection was closed, the retrieval             will be considered OK if f->size == len.  */          if (!f || len != f->size)            {              printwhat (count, opt.ntry);              continue;            }          break;        case RETRFINISHED:          /* Great!  */          break;        default:          /* Not as great.  */          abort ();        }      tms = datetime_str (time (NULL));      if (!opt.spider)        tmrate = retr_rate (len - restval, con->dltime);      /* If we get out of the switch above without continue'ing, we've         successfully downloaded a file.  Remember this fact. */      downloaded_file (FILE_DOWNLOADED_NORMALLY, locf);      if (con->st & ON_YOUR_OWN)        {          fd_close (con->csock);          con->csock = -1;        }      if (!opt.spider)        logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%s]\n\n"),                   tms, tmrate, locf, number_to_static_string (len));      if (!opt.verbose && !opt.quiet)        {          /* Need to hide the password from the URL.  The `if' is here             so that we don't do the needless allocation every             time. */          char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);          logprintf (LOG_NONVERBOSE, "%s URL: %s [%s] -> \"%s\" [%d]\n",                     tms, hurl, number_to_static_string (len), locf, count);          xfree (hurl);        }      if ((con->cmd & DO_LIST))        /* This is a directory listing file. */        {          if (!opt.remove_listing)            /* --dont-remove-listing was specified, so do count this towards the               number of bytes and files downloaded. */            {              total_downloaded_bytes += len;              opt.numurls++;            }          /* Deletion of listing files is not controlled by --delete-after, but             by the more specific option --dont-remove-listing, and the code             to do this deletion is in another function. */        }      else if (!opt.spider)        /* This is not a directory listing file. */        {          /* Unlike directory listing files, don't pretend normal files weren't             downloaded if they're going to be deleted.  People seeding proxies,             for instance, may want to know how many bytes and files they've             downloaded through it. */          total_downloaded_bytes += len;          opt.numurls++;          if (opt.delete_after)            {              DEBUGP (("\Removing file due to --delete-after in ftp_loop_internal():\n"));              logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);              if (unlink (locf))                logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));            }        }      /* Restore the original leave-pendingness.  */      if (orig_lp)        con->cmd |= LEAVE_PENDING;      else        con->cmd &= ~LEAVE_PENDING;      return RETROK;    } while (!opt.ntry || (count < opt.ntry));  if (con->csock != -1 && (con->st & ON_YOUR_OWN))    {      fd_close (con->csock);      con->csock = -1;    }  return TRYLIMEXC;}/* Return the directory listing in a reusable format.  The directory   is specifed in u->dir.  */static uerr_tftp_get_listing (struct url *u, ccon *con, struct fileinfo **f){  uerr_t err;  char *uf;                     /* url file name */  char *lf;                     /* list file name */  char *old_target = con->target;  con->st &= ~ON_YOUR_OWN;  con->cmd |= (DO_LIST | LEAVE_PENDING);  con->cmd &= ~DO_RETR;  /* Find the listing file name.  We do it by taking the file name of     the URL and replacing the last component with the listing file     name.  */  uf = url_file_name (u);  lf = file_merge (uf, LIST_FILENAME);  xfree (uf);  DEBUGP ((_("Using `%s' as listing tmp file.\n"), lf));  con->target = lf;  err = ftp_loop_internal (u, NULL, con);  con->target = old_target;  if (err == RETROK)    *f = ftp_parse_ls (lf, con->rs);  else    *f = NULL;  if (opt.remove_listing)    {      if (unlink (lf))        logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));      else        logprintf (LOG_VERBOSE, _("Removed `%s'.\n"), lf);    }  xfree (lf);  con->cmd &= ~DO_LIST;  return err;}static uerr_t ftp_retrieve_dirs (struct url *, struct fileinfo *, ccon *);static uerr_t ftp_retrieve_glob (struct url *, ccon *, int);static struct fileinfo *delelement (struct fileinfo *, struct fileinfo **);static void freefileinfo (struct fileinfo *f);/* Retrieve a list of files given in struct fileinfo linked list.  If   a file is a symbolic link, do not retrieve it, but rather try to   set up a similar link on the local disk, if the symlinks are   supported.   If opt.recursive is set, after all files have been retrieved,   ftp_retrieve_dirs will be called to retrieve the directories.  */static uerr_tftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con){  static int depth = 0;  uerr_t err;  struct fileinfo *orig;  wgint local_size;  time_t tml;  bool dlthis;  /* Increase the depth.  */  ++depth;  if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)    {      DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),               depth, opt.reclevel));      --depth;      return RECLEVELEXC;    }  assert (f != NULL);  orig = f;  con->st &= ~ON_YOUR_OWN;  if (!(con->st & DONE_CWD))    con->cmd |= DO_CWD;  else    con->cmd &= ~DO_CWD;  con->cmd |= (DO_RETR | LEAVE_PENDING);  if (con->csock < 0)    con->cmd |= DO_LOGIN;  else    con->cmd &= ~DO_LOGIN;  err = RETROK;                 /* in case it's not used */  while (f)    {      char *old_target, *ofile;      if (opt.quota && total_downloaded_bytes > opt.quota)        {          --depth;          return QUOTEXC;        }      old_target = con->target;      ofile = xstrdup (u->file);      url_set_file (u, f->name);      con->target = url_file_name (u);      err = RETROK;      dlthis = true;      if (opt.timestamping && f->type == FT_PLAINFILE)        {          struct_stat st;          /* If conversion of HTML files retrieved via FTP is ever implemented,             we'll need to stat() <file>.orig here when -K has been specified.             I'm not implementing it now since files on an FTP server are much             more likely than files on an HTTP server to legitimately have a             .orig suffix. */          if (!stat (con->target, &st))            {              bool eq_size;              bool cor_val;              /* Else, get it from the file.  */              local_size = st.st_size;              tml = st.st_mtime;#ifdef WINDOWS              /* Modification time granularity is 2 seconds for Windows, so                 increase local time by 1 second for later comparison. */              tml++;#endif              /* Compare file sizes only for servers that tell us correct                 values. Assume sizes being equal for servers that lie                 about file size.  */              cor_val = (con->rs == ST_UNIX || con->rs == ST_WINNT);              eq_size = cor_val ? (local_size == f->size) : true;              if (f->tstamp <= tml && eq_size)                {                  /* Remote file is older, file sizes can be compared and                     are both equal. */                  logprintf (LOG_VERBOSE, _("\Remote file no newer than local file `%s' -- not retrieving.\n"), con->target);                  dlthis = false;                }              else if (eq_size)                {                  /* Remote file is newer or sizes cannot be matched */                  logprintf (LOG_VERBOSE, _("\Remote file is newer than local file `%s' -- retrieving.\n\n"),                             con->target);                }              else                {                  /* Sizes do not match */                  logprintf (LOG_VERBOSE, _("\The sizes do not match (local %s) -- retrieving.\n\n"),                             number_to_static_string (local_size));                }            }        }       /* opt.timestamping && f->type == FT_PLAINFILE */      switch (f->type)        {        case FT_SYMLINK:          /* If opt.retr_symlinks is defined, we treat symlinks as             if they were normal files.  There is currently no way             to distinguish whether they might be directories, and             follow them.  */          if (!opt.retr_symlinks)            {#ifdef HAVE_SYMLINK              if (!f->linkto)                logputs (LOG_NOTQUIET,                         _("Invalid name of the symlink, skipping.\n"));              else                {                  struct_stat st;                  /* Check whether we already have the correct                     symbolic link.  */                  int rc = lstat (con->target, &st);                  if (rc == 0)                    {                      size_t len = strlen (f->linkto) + 1;                      if (S_ISLNK (st.st_mode))                        {                          char *link_target = (char *)alloca (len);                          size_t n = readlink (con->target, link_target, len);                          if ((n == len - 1)                              && (memcmp (link_target, f->linkto, n) == 0))                            {                              logprintf (LOG_VERBOSE, _("\Already have correct symlink %s -> %s\n\n"),                                         con->target, escnonprint (f->linkto));                              dlthis = false;                              break;                            }                        }                    }                  logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),                             con->target, escnonprint (f->linkto));                  /* Unlink before creating symlink!  */                  unlink (con->target);                  if (symlink (f->linkto, con->target) == -1)                    logprintf (LOG_NOTQUIET, "symlink: %s\n", strerror (errno));                  logputs (LOG_VERBOSE, "\n");                } /* have f->linkto */#else  /* not HAVE_SYMLINK */              logprintf (LOG_NOTQUIET,                         _("Symlinks not supported, skipping symlink `%s'.\n"),                         con->target);#endif /* not HAVE_SYMLINK */            }          else                /* opt.retr_symlinks */            {              if (dlthis)                err = ftp_loop_internal (u, f, con);            } /* opt.retr_symlinks */          break;        case FT_DIRECTORY:          if (!opt.recursive)            logprintf (LOG_NOTQUIET, _("Skipping directory `%s'.\n"),                       escnonprint (f->name));          break;        case FT_PLAINFILE:          /* Call the retrieve loop.  */          if (dlthis)            err = ftp_loop_internal (u, f, con);          break;        case FT_UNKNOWN:          logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),                     escnonprint (f->name));          break;        }       /* switch */      /* Set the time-stamp information to the local file.  Symlinks         are not to be stamped because it sets the stamp on the         original.  :( */      if (!(f->type == FT_SYMLINK && !opt.retr_symlinks)          && f->tstamp != -1          && dlthis          && file_exists_p (con->target))        {          /* #### This code repeats in http.c and ftp.c.  Move it to a             function!  */          const char *fl = NULL;          if (opt.output_document)            {              if (output_stream_regular)

⌨️ 快捷键说明

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