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

📄 ftw.c

📁 Newlib 嵌入式 C库 标准实现代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* File tree walker functions.   Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc.   This file is part of the GNU C Library.   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.   The GNU C Library is free software; you can redistribute it and/or   modify it under the terms of the GNU Lesser General Public   License as published by the Free Software Foundation; either   version 2.1 of the License, or (at your option) any later version.   The GNU C Library is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   Lesser General Public License for more details.   You should have received a copy of the GNU Lesser General Public   License along with the GNU C Library; if not, write to the Free   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA   02111-1307 USA.  *//* Modified for newlib by Jeff Johnston, July 26, 2002 */#define _GNU_SOURCE 1#include <dirent.h>#include <errno.h>#include <ftw.h>#include <search.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/param.h>#include <sys/stat.h>extern struct dirent64 *__readdir64 (DIR *);/* #define NDEBUG 1 */#include <assert.h>/* Support for the LFS API version.  */#ifndef FTW_NAME# define FTW_NAME ftw# define NFTW_NAME nftw# define INO_T ino_t# define STAT stat# define LXSTAT lstat# define XSTAT stat# define FTW_FUNC_T __ftw_func_t# define NFTW_FUNC_T __nftw_func_t#endif#define dirfd(x) ((x)->dd_fd)struct dir_data{  DIR *stream;  char *content;};struct known_object{  dev_t dev;  INO_T ino;};struct ftw_data{  /* Array with pointers to open directory streams.  */  struct dir_data **dirstreams;  size_t actdir;  size_t maxdir;  /* Buffer containing name of currently processed object.  */  char *dirbuf;  size_t dirbufsize;  /* Passed as fourth argument to `nftw' callback.  The `base' member     tracks the content of the `dirbuf'.  */  struct FTW ftw;  /* Flags passed to `nftw' function.  0 for `ftw'.  */  int flags;  /* Conversion array for flag values.  It is the identity mapping for     `nftw' calls, otherwise it maps the values to those know by     `ftw'.  */  const int *cvt_arr;  /* Callback function.  We always use the `nftw' form.  */  NFTW_FUNC_T func;  /* Device of starting point.  Needed for FTW_MOUNT.  */  dev_t dev;  /* Data structure for keeping fingerprints of already processed     object.  This is needed when not using FTW_PHYS.  */  void *known_objects;};/* Internally we use the FTW_* constants used for `nftw'.  When the   process called `ftw' we must reduce the flag to the known flags   for `ftw'.  */static const int nftw_arr[] ={  FTW_F, FTW_D, FTW_DNR, FTW_NS, FTW_SL, FTW_DP, FTW_SLN};static const int ftw_arr[] ={  FTW_F, FTW_D, FTW_DNR, FTW_NS, FTW_F, FTW_D, FTW_NS};/* Forward declarations of local functions.  */static int ftw_dir (struct ftw_data *data, struct STAT *st);static intobject_compare (const void *p1, const void *p2){  /* We don't need a sophisticated and useful comparison.  We are only     interested in equality.  However, we must be careful not to     accidentally compare `holes' in the structure.  */  const struct known_object *kp1 = p1, *kp2 = p2;  int cmp1;  cmp1 = (kp1->dev > kp2->dev) - (kp1->dev < kp2->dev);  if (cmp1 != 0)    return cmp1;  return (kp1->ino > kp2->ino) - (kp1->ino < kp2->ino);}static inline intadd_object (struct ftw_data *data, struct STAT *st){  struct known_object *newp = malloc (sizeof (struct known_object));  if (newp == NULL)    return -1;  newp->dev = st->st_dev;  newp->ino = st->st_ino;  return tsearch (newp, &data->known_objects, object_compare) ? 0 : -1;}static inline intfind_object (struct ftw_data *data, struct STAT *st){  struct known_object obj = { dev: st->st_dev, ino: st->st_ino };  return tfind (&obj, &data->known_objects, object_compare) != NULL;}static inline intopen_dir_stream (struct ftw_data *data, struct dir_data *dirp){  int result = 0;  if (data->dirstreams[data->actdir] != NULL)    {      /* Oh, oh.  We must close this stream.  Get all remaining	 entries and store them as a list in the `content' member of	 the `struct dir_data' variable.  */      size_t bufsize = 1024;      char *buf = malloc (bufsize);      if (buf == NULL)	result = -1;      else	{	  DIR *st = data->dirstreams[data->actdir]->stream;	  struct dirent64 *d;	  size_t actsize = 0;	  while ((d = __readdir64 (st)) != NULL)	    {	      size_t this_len = strlen (d->d_name);	      if (actsize + this_len + 2 >= bufsize)		{		  char *newp;		  bufsize += MAX (1024, 2 * this_len);		  newp = realloc (buf, bufsize);		  if (newp == NULL)		    {		      /* No more memory.  */		      int save_err = errno;		      free (buf);		      __set_errno (save_err);		      result = -1;		      break;		    }		  buf = newp;		}	      *((char *) mempcpy (buf + actsize, d->d_name, this_len))		= '\0';	      actsize += this_len + 1;	    }	  /* Terminate the list with an additional NUL byte.  */	  buf[actsize++] = '\0';	  /* Shrink the buffer to what we actually need.  */	  data->dirstreams[data->actdir]->content = realloc (buf, actsize);	  if (data->dirstreams[data->actdir]->content == NULL)	    {	      int save_err = errno;	      free (buf);	      __set_errno (save_err);	      result = -1;	    }	  else	    {	      closedir (st);	      data->dirstreams[data->actdir]->stream = NULL;	      data->dirstreams[data->actdir] = NULL;	    }	}    }  /* Open the new stream.  */  if (result == 0)    {      assert (data->dirstreams[data->actdir] == NULL);      dirp->stream = opendir (data->dirbuf);      if (dirp->stream == NULL)	result = -1;      else	{	  dirp->content = NULL;	  data->dirstreams[data->actdir] = dirp;	  if (++data->actdir == data->maxdir)	    data->actdir = 0;	}    }  return result;}static inline intprocess_entry (struct ftw_data *data, struct dir_data *dir, const char *name,	       size_t namlen){  struct STAT st;  int result = 0;  int flag = 0;  if (name[0] == '.' && (name[1] == '\0'			 || (name[1] == '.' && name[2] == '\0')))    /* Don't process the "." and ".." entries.  */    return 0;  if (data->dirbufsize < data->ftw.base + namlen + 2)    {      /* Enlarge the buffer.  */      char *newp;      data->dirbufsize *= 2;      newp = realloc (data->dirbuf, data->dirbufsize);      if (newp == NULL)	return -1;      data->dirbuf = newp;    }  *((char *) mempcpy (data->dirbuf + data->ftw.base, name, namlen)) = '\0';  if (((data->flags & FTW_PHYS)       ? LXSTAT (data->dirbuf, &st)       : XSTAT (data->dirbuf, &st)) < 0)    {      if (errno != EACCES && errno != ENOENT)	result = -1;      else if (!(data->flags & FTW_PHYS)	       && LXSTAT (data->dirbuf, &st) == 0	       && S_ISLNK (st.st_mode))	flag = FTW_SLN;      else	flag = FTW_NS;    }  else    {      if (S_ISDIR (st.st_mode))	flag = FTW_D;      else if (S_ISLNK (st.st_mode))	flag = FTW_SL;      else	flag = FTW_F;    }  if (result == 0      && (flag == FTW_NS	  || !(data->flags & FTW_MOUNT) || st.st_dev == data->dev))    {      if (flag == FTW_D)	{	  if ((data->flags & FTW_PHYS)	      || (!find_object (data, &st)		  /* Remember the object.  */		  && (result = add_object (data, &st)) == 0))	    {	      result = ftw_dir (data, &st);	      if (result == 0 && (data->flags & FTW_CHDIR))		{		  /* Change back to current directory.  */		  int done = 0;		  if (dir->stream != NULL)		    if (fchdir (dirfd (dir->stream)) == 0)		      done = 1;		  if (!done)		    {		      if (data->ftw.base == 1)			{			  if (chdir ("/") < 0)			    result = -1;			}		      else

⌨️ 快捷键说明

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