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

📄 utils.c

📁 wget讓你可以在console介面下
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Various utility functions.   Copyright (C) 2005 Free Software Foundation, Inc.This file is part of GNU Wget.GNU Wget is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.GNU Wget is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with Wget; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.In addition, as a special exception, the Free Software Foundationgives permission to link the code of its release of Wget with theOpenSSL project's "OpenSSL" library (or with modified versions of itthat use the same license as the "OpenSSL" library), and distributethe linked executables.  You must obey the GNU General Public Licensein all respects for all of the code used other than "OpenSSL".  If youmodify this file, you may extend this exception to your version of thefile, but you are not obligated to do so.  If you do not wish to doso, delete this exception statement from your version.  */#include <config.h>#include <stdio.h>#include <stdlib.h>#ifdef HAVE_STRING_H# include <string.h>#else  /* not HAVE_STRING_H */# include <strings.h>#endif /* not HAVE_STRING_H */#include <sys/types.h>#ifdef HAVE_UNISTD_H# include <unistd.h>#endif#ifdef HAVE_MMAP# include <sys/mman.h>#endif#ifdef HAVE_PWD_H# include <pwd.h>#endif#ifdef HAVE_LIMITS_H# include <limits.h>#endif#ifdef HAVE_UTIME_H# include <utime.h>#endif#ifdef HAVE_SYS_UTIME_H# include <sys/utime.h>#endif#include <errno.h>#ifdef NeXT# include <libc.h>		/* for access() */#endif#include <fcntl.h>#include <assert.h>#ifdef WGET_USE_STDARG# include <stdarg.h>#else# include <varargs.h>#endif#ifdef HAVE_LOCALE_H# include <locale.h>#endif/* For TIOCGWINSZ and friends: */#ifdef HAVE_SYS_IOCTL_H# include <sys/ioctl.h>#endif#ifdef HAVE_TERMIOS_H# include <termios.h>#endif/* Needed for run_with_timeout. */#undef USE_SIGNAL_TIMEOUT#ifdef HAVE_SIGNAL_H# include <signal.h>#endif#ifdef HAVE_SETJMP_H# include <setjmp.h>#endif#ifndef HAVE_SIGSETJMP/* If sigsetjmp is a macro, configure won't pick it up. */# ifdef sigsetjmp#  define HAVE_SIGSETJMP# endif#endif#ifdef HAVE_SIGNAL# ifdef HAVE_SIGSETJMP#  define USE_SIGNAL_TIMEOUT# endif# ifdef HAVE_SIGBLOCK#  define USE_SIGNAL_TIMEOUT# endif#endif#include "wget.h"#include "utils.h"#include "hash.h"#ifndef errnoextern int errno;#endif/* Utility function: like xstrdup(), but also lowercases S.  */char *xstrdup_lower (const char *s){  char *copy = xstrdup (s);  char *p = copy;  for (; *p; p++)    *p = TOLOWER (*p);  return copy;}/* Copy the string formed by two pointers (one on the beginning, other   on the char after the last char) to a new, malloc-ed location.   0-terminate it.  */char *strdupdelim (const char *beg, const char *end){  char *res = (char *)xmalloc (end - beg + 1);  memcpy (res, beg, end - beg);  res[end - beg] = '\0';  return res;}/* Parse a string containing comma-separated elements, and return a   vector of char pointers with the elements.  Spaces following the   commas are ignored.  */char **sepstring (const char *s){  char **res;  const char *p;  int i = 0;  if (!s || !*s)    return NULL;  res = NULL;  p = s;  while (*s)    {      if (*s == ',')	{	  res = (char **)xrealloc (res, (i + 2) * sizeof (char *));	  res[i] = strdupdelim (p, s);	  res[++i] = NULL;	  ++s;	  /* Skip the blanks following the ','.  */	  while (ISSPACE (*s))	    ++s;	  p = s;	}      else	++s;    }  res = (char **)xrealloc (res, (i + 2) * sizeof (char *));  res[i] = strdupdelim (p, s);  res[i + 1] = NULL;  return res;}#ifdef WGET_USE_STDARG# define VA_START(args, arg1) va_start (args, arg1)#else# define VA_START(args, ignored) va_start (args)#endif/* Like sprintf, but allocates a string of sufficient size with malloc   and returns it.  GNU libc has a similar function named asprintf,   which requires the pointer to the string to be passed.  */char *aprintf (const char *fmt, ...){  /* This function is implemented using vsnprintf, which we provide     for the systems that don't have it.  Therefore, it should be 100%     portable.  */  int size = 32;  char *str = xmalloc (size);  while (1)    {      int n;      va_list args;      /* See log_vprintf_internal for explanation why it's OK to rely	 on the return value of vsnprintf.  */      VA_START (args, fmt);      n = vsnprintf (str, size, fmt, args);      va_end (args);      /* If the printing worked, return the string. */      if (n > -1 && n < size)	return str;      /* Else try again with a larger buffer. */      if (n > -1)		/* C99 */	size = n + 1;		/* precisely what is needed */      else	size <<= 1;		/* twice the old size */      str = xrealloc (str, size);    }}/* Concatenate the NULL-terminated list of string arguments into   freshly allocated space.  */char *concat_strings (const char *str0, ...){  va_list args;  int saved_lengths[5];		/* inspired by Apache's apr_pstrcat */  char *ret, *p;  const char *next_str;  int total_length = 0;  int argcount;  /* Calculate the length of and allocate the resulting string. */  argcount = 0;  VA_START (args, str0);  for (next_str = str0; next_str != NULL; next_str = va_arg (args, char *))    {      int len = strlen (next_str);      if (argcount < countof (saved_lengths))	saved_lengths[argcount++] = len;      total_length += len;    }  va_end (args);  p = ret = xmalloc (total_length + 1);  /* Copy the strings into the allocated space. */  argcount = 0;  VA_START (args, str0);  for (next_str = str0; next_str != NULL; next_str = va_arg (args, char *))    {      int len;      if (argcount < countof (saved_lengths))	len = saved_lengths[argcount++];      else	len = strlen (next_str);      memcpy (p, next_str, len);      p += len;    }  va_end (args);  *p = '\0';  return ret;}/* Return pointer to a static char[] buffer in which zero-terminated   string-representation of TM (in form hh:mm:ss) is printed.   If TM is NULL, the current time will be used.  */char *time_str (time_t *tm){  static char output[15];  struct tm *ptm;  time_t secs = tm ? *tm : time (NULL);  if (secs == -1)    {      /* In case of error, return the empty string.  Maybe we should	 just abort if this happens?  */      *output = '\0';      return output;    }  ptm = localtime (&secs);  sprintf (output, "%02d:%02d:%02d", ptm->tm_hour, ptm->tm_min, ptm->tm_sec);  return output;}/* Like the above, but include the date: YYYY-MM-DD hh:mm:ss.  */char *datetime_str (time_t *tm){  static char output[20];	/* "YYYY-MM-DD hh:mm:ss" + \0 */  struct tm *ptm;  time_t secs = tm ? *tm : time (NULL);  if (secs == -1)    {      /* In case of error, return the empty string.  Maybe we should	 just abort if this happens?  */      *output = '\0';      return output;    }  ptm = localtime (&secs);  sprintf (output, "%04d-%02d-%02d %02d:%02d:%02d",	   ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday,	   ptm->tm_hour, ptm->tm_min, ptm->tm_sec);  return output;}/* The Windows versions of the following two functions are defined in   mswindows.c.  */#ifndef WINDOWSvoidfork_to_background (void){  pid_t pid;  /* Whether we arrange our own version of opt.lfilename here.  */  int logfile_changed = 0;  if (!opt.lfilename)    {      /* We must create the file immediately to avoid either a race	 condition (which arises from using unique_name and failing to	 use fopen_excl) or lying to the user about the log file name	 (which arises from using unique_name, printing the name, and	 using fopen_excl later on.)  */      FILE *new_log_fp = unique_create (DEFAULT_LOGFILE, 0, &opt.lfilename);      if (new_log_fp)	{	  logfile_changed = 1;	  fclose (new_log_fp);	}    }  pid = fork ();  if (pid < 0)    {      /* parent, error */      perror ("fork");      exit (1);    }  else if (pid != 0)    {      /* parent, no error */      printf (_("Continuing in background, pid %d.\n"), (int)pid);      if (logfile_changed)	printf (_("Output will be written to `%s'.\n"), opt.lfilename);      exit (0);			/* #### should we use _exit()? */    }  /* child: give up the privileges and keep running. */  setsid ();  freopen ("/dev/null", "r", stdin);  freopen ("/dev/null", "w", stdout);  freopen ("/dev/null", "w", stderr);}#endif /* not WINDOWS *//* "Touch" FILE, i.e. make its mtime ("modified time") equal the time   specified with TM.  The atime ("access time") is set to the current   time.  */voidtouch (const char *file, time_t tm){#ifdef HAVE_STRUCT_UTIMBUF  struct utimbuf times;#else  struct {    time_t actime;    time_t modtime;  } times;#endif  times.modtime = tm;  times.actime = time (NULL);  if (utime (file, &times) == -1)    logprintf (LOG_NOTQUIET, "utime(%s): %s\n", file, strerror (errno));}/* Checks if FILE is a symbolic link, and removes it if it is.  Does   nothing under MS-Windows.  */intremove_link (const char *file){  int err = 0;  struct_stat st;  if (lstat (file, &st) == 0 && S_ISLNK (st.st_mode))    {      DEBUGP (("Unlinking %s (symlink).\n", file));      err = unlink (file);      if (err != 0)	logprintf (LOG_VERBOSE, _("Failed to unlink symlink `%s': %s\n"),		   file, strerror (errno));    }  return err;}/* Does FILENAME exist?  This is quite a lousy implementation, since   it supplies no error codes -- only a yes-or-no answer.  Thus it   will return that a file does not exist if, e.g., the directory is   unreadable.  I don't mind it too much currently, though.  The   proper way should, of course, be to have a third, error state,   other than true/false, but that would introduce uncalled-for   additional complexity to the callers.  */intfile_exists_p (const char *filename){#ifdef HAVE_ACCESS  return access (filename, F_OK) >= 0;#else  struct_stat buf;  return stat (filename, &buf) >= 0;#endif}/* Returns 0 if PATH is a directory, 1 otherwise (any kind of file).   Returns 0 on error.  */intfile_non_directory_p (const char *path){  struct_stat buf;  /* Use lstat() rather than stat() so that symbolic links pointing to     directories can be identified correctly.  */  if (lstat (path, &buf) != 0)    return 0;  return S_ISDIR (buf.st_mode) ? 0 : 1;}/* Return the size of file named by FILENAME, or -1 if it cannot be   opened or seeked into. */wgintfile_size (const char *filename){#if defined(HAVE_FSEEKO) && defined(HAVE_FTELLO)  wgint size;  /* We use fseek rather than stat to determine the file size because     that way we can also verify that the file is readable without     explicitly checking for permissions.  Inspired by the POST patch     by Arnaud Wylie.  */  FILE *fp = fopen (filename, "rb");  if (!fp)    return -1;  fseeko (fp, 0, SEEK_END);  size = ftello (fp);  fclose (fp);  return size;#else  struct_stat st;  if (stat (filename, &st) < 0)    return -1;  return st.st_size;#endif}/* stat file names named PREFIX.1, PREFIX.2, etc., until one that   doesn't exist is found.  Return a freshly allocated copy of the   unused file name.  */static char *unique_name_1 (const char *prefix){  int count = 1;  int plen = strlen (prefix);  char *template = (char *)alloca (plen + 1 + 24);  char *template_tail = template + plen;  memcpy (template, prefix, plen);  *template_tail++ = '.';  do    number_to_string (template_tail, count++);  while (file_exists_p (template));  return xstrdup (template);}/* Return a unique file name, based on FILE.   More precisely, if FILE doesn't exist, it is returned unmodified.   If not, FILE.1 is tried, then FILE.2, etc.  The first FILE.<number>   file name that doesn't exist is returned.   The resulting file is not created, only verified that it didn't   exist at the point in time when the function was called.   Therefore, where security matters, don't rely that the file created   by this function exists until you open it with O_EXCL or   equivalent.   If ALLOW_PASSTHROUGH is 0, it always returns a freshly allocated   string.  Otherwise, it may return FILE if the file doesn't exist   (and therefore doesn't need changing).  */char *unique_name (const char *file, int allow_passthrough){  /* If the FILE itself doesn't exist, return it without     modification. */  if (!file_exists_p (file))    return allow_passthrough ? (char *)file : xstrdup (file);  /* Otherwise, find a numeric suffix that results in unused file name     and return it.  */  return unique_name_1 (file);}/* Create a file based on NAME, except without overwriting an existing   file with that name.  Providing O_EXCL is correctly implemented,   this function does not have the race condition associated with   opening the file returned by unique_name.  */FILE *unique_create (const char *name, int binary, char **opened_name){  /* unique file name, based on NAME */  char *uname = unique_name (name, 0);  FILE *fp;  while ((fp = fopen_excl (uname, binary)) == NULL && errno == EEXIST)    {

⌨️ 快捷键说明

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