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

📄 utils.c

📁 Wget很好的处理了http和ftp的下载,很值得学习的经典代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#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, bool 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, bool binary, char **opened_name){  /* unique file name, based on NAME */  char *uname = unique_name (name, false);  FILE *fp;  while ((fp = fopen_excl (uname, binary)) == NULL && errno == EEXIST)    {      xfree (uname);      uname = unique_name (name, false);    }  if (opened_name && fp != NULL)    {      if (fp)        *opened_name = uname;      else        {          *opened_name = NULL;          xfree (uname);        }    }  else    xfree (uname);  return fp;}/* Open the file for writing, with the addition that the file is   opened "exclusively".  This means that, if the file already exists,   this function will *fail* and errno will be set to EEXIST.  If   BINARY is set, the file will be opened in binary mode, equivalent   to fopen's "wb".   If opening the file fails for any reason, including the file having   previously existed, this function returns NULL and sets errno   appropriately.  */   FILE *fopen_excl (const char *fname, bool binary){  int fd;#ifdef O_EXCL  int flags = O_WRONLY | O_CREAT | O_EXCL;# ifdef O_BINARY  if (binary)    flags |= O_BINARY;# endif  fd = open (fname, flags, 0666);  if (fd < 0)    return NULL;  return fdopen (fd, binary ? "wb" : "w");#else  /* not O_EXCL */  /* Manually check whether the file exists.  This is prone to race     conditions, but systems without O_EXCL haven't deserved     better.  */  if (file_exists_p (fname))    {      errno = EEXIST;      return NULL;    }  return fopen (fname, binary ? "wb" : "w");#endif /* not O_EXCL */}/* Create DIRECTORY.  If some of the pathname components of DIRECTORY   are missing, create them first.  In case any mkdir() call fails,   return its error status.  Returns 0 on successful completion.   The behaviour of this function should be identical to the behaviour   of `mkdir -p' on systems where mkdir supports the `-p' option.  */intmake_directory (const char *directory){  int i, ret, quit = 0;  char *dir;  /* Make a copy of dir, to be able to write to it.  Otherwise, the     function is unsafe if called with a read-only char *argument.  */  STRDUP_ALLOCA (dir, directory);  /* If the first character of dir is '/', skip it (and thus enable     creation of absolute-pathname directories.  */  for (i = (*dir == '/'); 1; ++i)    {      for (; dir[i] && dir[i] != '/'; i++)        ;      if (!dir[i])        quit = 1;      dir[i] = '\0';      /* Check whether the directory already exists.  Allow creation of         of intermediate directories to fail, as the initial path components         are not necessarily directories!  */      if (!file_exists_p (dir))        ret = mkdir (dir, 0777);      else        ret = 0;      if (quit)        break;      else        dir[i] = '/';    }  return ret;}/* Merge BASE with FILE.  BASE can be a directory or a file name, FILE   should be a file name.   file_merge("/foo/bar", "baz")  => "/foo/baz"   file_merge("/foo/bar/", "baz") => "/foo/bar/baz"   file_merge("foo", "bar")       => "bar"   In other words, it's a simpler and gentler version of uri_merge.  */char *file_merge (const char *base, const char *file){  char *result;  const char *cut = (const char *)strrchr (base, '/');  if (!cut)    return xstrdup (file);  result = xmalloc (cut - base + 1 + strlen (file) + 1);  memcpy (result, base, cut - base);  result[cut - base] = '/';  strcpy (result + (cut - base) + 1, file);  return result;}/* Like fnmatch, but performs a case-insensitive match.  */intfnmatch_nocase (const char *pattern, const char *string, int flags){#ifdef FNM_CASEFOLD  /* The FNM_CASEFOLD flag started as a GNU extension, but it is now     also present on *BSD platforms, and possibly elsewhere.  */  return fnmatch (pattern, string, flags | FNM_CASEFOLD);#else  /* Turn PATTERN and STRING to lower case and call fnmatch on them. */  char *patcopy = (char *) alloca (strlen (pattern) + 1);  char *strcopy = (char *) alloca (strlen (string) + 1);  char *p;  for (p = patcopy; *pattern; pattern++, p++)    *p = TOLOWER (*pattern);  *p = '\0';  for (p = strcopy; *string; string++, p++)    *p = TOLOWER (*string);  *p = '\0';  return fnmatch (patcopy, strcopy, flags);#endif}static bool in_acclist (const char *const *, const char *, bool);/* Determine whether a file is acceptable to be followed, according to   lists of patterns to accept/reject.  */boolacceptable (const char *s){  int l = strlen (s);  while (l && s[l] != '/')    --l;  if (s[l] == '/')    s += (l + 1);  if (opt.accepts)    {      if (opt.rejects)        return (in_acclist ((const char *const *)opt.accepts, s, true)                && !in_acclist ((const char *const *)opt.rejects, s, true));      else        return in_acclist ((const char *const *)opt.accepts, s, true);    }  else if (opt.rejects)    return !in_acclist ((const char *const *)opt.rejects, s, true);  return true;}/* Check if D2 is a subdirectory of D1.  E.g. if D1 is `/something', subdir_p()   will return true if and only if D2 begins with `/something/' or is exactly    '/something'.  */boolsubdir_p (const char *d1, const char *d2){  if (*d1 == '\0')    return true;  if (!opt.ignore_case)    for (; *d1 && *d2 && (*d1 == *d2); ++d1, ++d2)      ;  else    for (; *d1 && *d2 && (TOLOWER (*d1) == TOLOWER (*d2)); ++d1, ++d2)      ;    return *d1 == '\0' && (*d2 == '\0' || *d2 == '/');}/* Iterate through DIRLIST (which must be NULL-terminated), and return the   first element that matches DIR, through wildcards or front comparison (as   appropriate).  */static booldir_matches_p (char **dirlist, const char *dir){  char **x;  int (*matcher) (const char *, const char *, int)    = opt.ignore_case ? fnmatch_nocase : fnmatch;  for (x = dirlist; *x; x++)    {      /* Remove leading '/' */      char *p = *x + (**x == '/');      if (has_wildcards_p (p))        {          if (matcher (p, dir, FNM_PATHNAME) == 0)            break;        }      else        {          if (subdir_p (p, dir))            break;        }    }        return *x ? true : false;}/* Returns whether DIRECTORY is acceptable for download, wrt the   include/exclude lists.   The leading `/' is ignored in paths; relative and absolute paths   may be freely intermixed.  */boolaccdir (const char *directory){  /* Remove starting '/'.  */  if (*directory == '/')    ++directory;  if (opt.includes)    {      if (!dir_matches_p (opt.includes, directory))        return false;    }  if (opt.excludes)    {      if (dir_matches_p (opt.excludes, directory))        return false;    }  return true;}/* Return true if STRING ends with TAIL.  For instance:   match_tail ("abc", "bc", false)  -> 1   match_tail ("abc", "ab", false)  -> 0   match_tail ("abc", "abc", false) -> 1   If FOLD_CASE is true, the comparison will be case-insensitive.  */boolmatch_tail (const char *string, const char *tail, bool fold_case){  int i, j;  /* We want this to be fast, so we code two loops, one with     case-folding, one without. */  if (!fold_case)    {      for (i = strlen (string), j = strlen (tail); i >= 0 && j >= 0; i--, j--)        if (string[i] != tail[j])          break;    }  else    {      for (i = strlen (string), j = strlen (tail); i >= 0 && j >= 0; i--, j--)        if (TOLOWER (string[i]) != TOLOWER (tail[j]))          break;    }  /* If the tail was exhausted, the match was succesful.  */  if (j == -1)    return true;  else    return false;}/* Checks whether string S matches each element of ACCEPTS.  A list   element are matched either with fnmatch() or match_tail(),   according to whether the element contains wildcards or not.   If the BACKWARD is false, don't do backward comparison -- just compare   them normally.  */static boolin_acclist (const char *const *accepts, const char *s, bool backward){  for (; *accepts; accepts++)    {      if (has_wildcards_p (*accepts))        {          int res = opt.ignore_case            ? fnmatch_nocase (*accepts, s, 0) : fnmatch (*accepts, s, 0);          /* fnmatch returns 0 if the pattern *does* match the string.  */          if (res == 0)            return true;        }      else        {          if (backward)            {              if (match_tail (s, *accepts, opt.ignore_case))                return true;            }          else            {              int cmp = opt.ignore_case                ? strcasecmp (s, *accepts) : strcmp (s, *accepts);              if (cmp == 0)                return true;            }        }    }  return false;}/* Return the location of STR's suffix (file extension).  Examples:   suffix ("foo.bar")       -> "bar"   suffix ("foo.bar.baz")   -> "baz"   suffix ("/foo/bar")      -> NULL   suffix ("/foo.bar/baz")  -> NULL  */char *suffix (const char *str){  int i;  for (i = strlen (str); i && str[i] != '/' && str[i] != '.'; i--)    ;  if (str[i++] == '.')    return (char *)str + i;  else    return NULL;}/* Return true if S contains globbing wildcards (`*', `?', `[' or   `]').  */boolhas_wildcards_p (const char *s){  for (; *s; s++)    if (*s == '*' || *s == '?' || *s == '[' || *s == ']')      return true;  return false;}/* Return true if FNAME ends with a typical HTML suffix.  The   following (case-insensitive) suffixes are presumed to be HTML   files:        html     htm     ?html (`?' matches one character)   #### CAVEAT.  This is not necessarily a good indication that FNAME   refers to a file that contains HTML!  */boolhas_html_suffix_p (const char *fname){  char *suf;  if ((suf = suffix (fname)) == NULL)    return false;  if (!strcasecmp (suf, "html"))    return true;  if (!strcasecmp (suf, "htm"))    return true;

⌨️ 快捷键说明

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