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

📄 ftp.c

📁 wget (command line browser) source code
💻 C
📖 第 1 页 / 共 4 页
字号:
		{		  /* 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 = 0;		}	      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 %ld) -- retrieving.\n\n"), 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, f->linkto);                              dlthis = 0;			      break;			    }			}		    }		  logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),			     con->target, 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"),		       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"),		     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 (opt.od_known_regular)		fl = opt.output_document;	    }	  else	    fl = con->target;	  if (fl)	    touch (fl, f->tstamp);	}      else if (f->tstamp == -1)	logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"), con->target);      if (f->perms && f->type == FT_PLAINFILE && dlthis)	chmod (con->target, f->perms);      else	DEBUGP (("Unrecognized permissions for %s.\n", con->target));      xfree (con->target);      con->target = old_target;      url_set_file (u, ofile);      xfree (ofile);      /* Break on fatals.  */      if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR)	break;      con->cmd &= ~ (DO_CWD | DO_LOGIN);      f = f->next;    }  /* We do not want to call ftp_retrieve_dirs here */  if (opt.recursive &&      !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))    err = ftp_retrieve_dirs (u, orig, con);  else if (opt.recursive)    DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),	     depth, opt.reclevel));  --depth;  return err;}/* Retrieve the directories given in a file list.  This function works   by simply going through the linked list and calling   ftp_retrieve_glob on each directory entry.  The function knows   about excluded directories.  */static uerr_tftp_retrieve_dirs (struct url *u, struct fileinfo *f, ccon *con){  char *container = NULL;  int container_size = 0;  for (; f; f = f->next)    {      int size;      char *odir, *newdir;      if (opt.quota && total_downloaded_bytes > opt.quota)	break;      if (f->type != FT_DIRECTORY)	continue;      /* Allocate u->dir off stack, but reallocate only if a larger         string is needed.  It's a pity there's no "realloca" for an         item on the bottom of the stack.  */      size = strlen (u->dir) + 1 + strlen (f->name) + 1;      if (size > container_size)	container = (char *)alloca (size);      newdir = container;      odir = u->dir;      if (*odir == '\0'	  || (*odir == '/' && *(odir + 1) == '\0'))	/* If ODIR is empty or just "/", simply append f->name to	   ODIR.  (In the former case, to preserve u->dir being	   relative; in the latter case, to avoid double slash.)  */	sprintf (newdir, "%s%s", odir, f->name);      else	/* Else, use a separator. */	sprintf (newdir, "%s/%s", odir, f->name);      DEBUGP (("Composing new CWD relative to the initial directory.\n"));      DEBUGP (("  odir = '%s'\n  f->name = '%s'\n  newdir = '%s'\n\n",	       odir, f->name, newdir));      if (!accdir (newdir, ALLABS))	{	  logprintf (LOG_VERBOSE, _("\Not descending to `%s' as it is excluded/not-included.\n"), newdir);	  continue;	}      con->st &= ~DONE_CWD;      odir = xstrdup (u->dir);	/* because url_set_dir will free				   u->dir. */      url_set_dir (u, newdir);      ftp_retrieve_glob (u, con, GETALL);      url_set_dir (u, odir);      xfree (odir);      /* Set the time-stamp?  */    }  if (opt.quota && total_downloaded_bytes > opt.quota)    return QUOTEXC;  else    return RETROK;}/* Return non-zero if S has a leading '/'  or contains '../' */static inthas_insecure_name_p (const char *s){  if (*s == '/')    return 1;  if (strstr(s, "../") != 0)    return 1;  return 0;}/* A near-top-level function to retrieve the files in a directory.   The function calls ftp_get_listing, to get a linked list of files.   Then it weeds out the file names that do not match the pattern.   ftp_retrieve_list is called with this updated list as an argument.   If the argument ACTION is GETONE, just download the file (but first   get the listing, so that the time-stamp is heeded); if it's GLOBALL,   use globbing; if it's GETALL, download the whole directory.  */static uerr_tftp_retrieve_glob (struct url *u, ccon *con, int action){  struct fileinfo *f, *start;  uerr_t res;  con->cmd |= LEAVE_PENDING;  res = ftp_get_listing (u, con, &start);  if (res != RETROK)    return res;  /* First: weed out that do not conform the global rules given in     opt.accepts and opt.rejects.  */  if (opt.accepts || opt.rejects)    {      f = start;      while (f)	{	  if (f->type != FT_DIRECTORY && !acceptable (f->name))	    {	      logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"), f->name);	      f = delelement (f, &start);	    }	  else	    f = f->next;	}    }  /* Remove all files with possible harmful names */  f = start;  while (f)    {      if (has_insecure_name_p (f->name))	{	  logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"), f->name);	  f = delelement (f, &start);	}      else	f = f->next;    }  /* Now weed out the files that do not match our globbing pattern.     If we are dealing with a globbing pattern, that is.  */  if (*u->file && (action == GLOBALL || action == GETONE))    {      int matchres = 0;      f = start;      while (f)	{	  matchres = fnmatch (u->file, f->name, 0);	  if (matchres == -1)	    {	      logprintf (LOG_NOTQUIET, "%s: %s\n", con->target,			 strerror (errno));	      break;	    }	  if (matchres == FNM_NOMATCH)	    f = delelement (f, &start); /* delete the element from the list */	  else	    f = f->next;        /* leave the element in the list */	}      if (matchres == -1)	{	  freefileinfo (start);	  return RETRBADPATTERN;	}    }  res = RETROK;  if (start)    {      /* Just get everything.  */      ftp_retrieve_list (u, start, con);    }  else if (!start)    {      if (action == GLOBALL)	{	  /* No luck.  */	  /* #### This message SUCKS.  We should see what was the	     reason that nothing was retrieved.  */	  logprintf (LOG_VERBOSE, _("No matches on pattern `%s'.\n"), u->file);	}      else /* GETONE or GETALL */	{	  /* Let's try retrieving it anyway.  */	  con->st |= ON_YOUR_OWN;	  res = ftp_loop_internal (u, NULL, con);	  return res;	}    }  freefileinfo (start);  if (opt.quota && total_downloaded_bytes > opt.quota)    return QUOTEXC;  else    /* #### Should we return `res' here?  */    return RETROK;}/* The wrapper that calls an appropriate routine according to contents   of URL.  Inherently, its capabilities are limited on what can be   encoded into a URL.  */uerr_tftp_loop (struct url *u, int *dt, struct url *proxy){  ccon con;			/* FTP connection */  uerr_t res;  *dt = 0;  memset (&con, 0, sizeof (con));  rbuf_uninitialize (&con.rbuf);  con.st = ON_YOUR_OWN;  con.rs = ST_UNIX;  con.id = NULL;  con.proxy = proxy;  res = RETROK;			/* in case it's not used */  /* If the file name is empty, the user probably wants a directory     index.  We'll provide one, properly HTML-ized.  Unless     opt.htmlify is 0, of course.  :-) */  if (!*u->file && !opt.recursive)    {      struct fileinfo *f;      res = ftp_get_listing (u, &con, &f);      if (res == RETROK)	{	  if (opt.htmlify && !opt.spider)	    {	      char *filename = (opt.output_document				? xstrdup (opt.output_document)				: (con.target ? xstrdup (con.target)				   : url_file_name (u)));	      res = ftp_index (filename, u, f);	      if (res == FTPOK && opt.verbose)		{		  if (!opt.output_document)		    {		      struct stat st;		      long sz;		      if (stat (filename, &st) == 0)			sz = st.st_size;		      else			sz = -1;		      logprintf (LOG_NOTQUIET,				 _("Wrote HTML-ized index to `%s' [%ld].\n"),				 filename, sz);		    }		  else		    logprintf (LOG_NOTQUIET,			       _("Wrote HTML-ized index to `%s'.\n"),			       filename);		}	      xfree (filename);	    }	  freefileinfo (f);	}    }  else    {      int wild = has_wildcards_p (u->file);      if ((opt.ftp_glob && wild) || opt.recursive || opt.timestamping)	{	  /* ftp_retrieve_glob is a catch-all function that gets called	     if we need globbing, time-stamping or recursion.  Its	     third argument is just what we really need.  */	  res = ftp_retrieve_glob (u, &con,				   (opt.ftp_glob && wild) ? GLOBALL : GETONE);	}      else	res = ftp_loop_internal (u, NULL, &con);    }  if (res == FTPOK)    res = RETROK;  if (res == RETROK)    *dt |= RETROKF;  /* If a connection was left, quench it.  */  if (rbuf_initialized_p (&con.rbuf))    CLOSE (RBUF_FD (&con.rbuf));  FREE_MAYBE (con.id);  con.id = NULL;  FREE_MAYBE (con.target);  con.target = NULL;  return res;}/* Delete an element from the fileinfo linked list.  Returns the   address of the next element, or NULL if the list is exhausted.  It   can modify the start of the list.  */static struct fileinfo *delelement (struct fileinfo *f, struct fileinfo **start){  struct fileinfo *prev = f->prev;  struct fileinfo *next = f->next;  xfree (f->name);  FREE_MAYBE (f->linkto);  xfree (f);  if (next)    next->prev = prev;  if (prev)    prev->next = next;  else    *start = next;  return next;}/* Free the fileinfo linked list of files.  */static voidfreefileinfo (struct fileinfo *f){  while (f)    {      struct fileinfo *next = f->next;      xfree (f->name);      if (f->linkto)	xfree (f->linkto);      xfree (f);      f = next;    }}

⌨️ 快捷键说明

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