ftw.c

来自「一个C源代码分析器」· C语言 代码 · 共 217 行

C
217
字号
/* Copyright (C) 1992 Free Software Foundation, Inc.This file is part of the GNU C Library.Contributed by Ian Lance Taylor (ian@airs.com).The GNU C Library is free software; you can redistribute it and/ormodify it under the terms of the GNU Library General Public License aspublished by the Free Software Foundation; either version 2 of theLicense, 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNULibrary General Public License for more details.You should have received a copy of the GNU Library General PublicLicense along with the GNU C Library; see the file COPYING.LIB.  Ifnot, write to the Free Software Foundation, Inc., 675 Mass Ave,Cambridge, MA 02139, USA.  */#include <ansidecl.h>#include <errno.h>#include <limits.h>#include <stdlib.h>#include <string.h>#include <dirent.h>#include <sys/types.h>#include <sys/stat.h>#include <ftw.h>#ifndef PATH_MAX#define PATH_MAX 1024		/* XXX */#endif/* Traverse one level of a directory tree.  */static intDEFUN (ftw_dir, (dirs, level, descriptors, dir, len, func),       DIR **dirs AND int level AND int descriptors AND       char *dir AND size_t len AND       int EXFUN((*func), (CONST char *file, struct stat *status,			   int flag))){  int got;  struct dirent *entry;  got = 0;  errno = 0;  while ((entry = readdir (dirs[level])) != NULL)    {      struct stat s;      int flag, ret, newlev;      ++got;      if (entry->d_name[0] == '.'	  && (entry->d_namlen == 1 ||	      (entry->d_namlen == 2 && entry->d_name[1] == '.')))	{	  errno = 0;	  continue;	}      if (entry->d_namlen + len + 1 > PATH_MAX)	{#ifdef ENAMETOOLONG	  errno = ENAMETOOLONG;#else	  errno = ENOMEM;#endif	  return -1;	}      dir[len] = '/';      memcpy ((PTR) (dir + len + 1), (PTR) entry->d_name,	      entry->d_namlen + 1);      if (stat (dir, &s) < 0)	{	  if (errno != EACCES)	    return -1;	  flag = FTW_NS;	}      else if (S_ISDIR (s.st_mode))	{	  newlev = (level + 1) % descriptors;	  if (dirs[newlev] != NULL)	    closedir (dirs[newlev]);	  dirs[newlev] = opendir (dir);	  if (dirs[newlev] != NULL)	    flag = FTW_D;	  else	    {	      if (errno != EACCES)		return -1;	      flag = FTW_DNR;	    }	}      else	flag = FTW_F;      ret = (*func) (dir, &s, flag);      if (flag == FTW_D)	{	  if (ret == 0)	    ret = ftw_dir (dirs, newlev, descriptors, dir,			   entry->d_namlen + len + 1, func);	  if (dirs[newlev] != NULL)	    {	      int save;	      save = errno;	      closedir (dirs[newlev]);	      errno = save;	      dirs[newlev] = NULL;	    }	}      if (ret != 0)	return ret;      if (dirs[level] == NULL)	{	  int skip;	  dir[len] = '\0';	  dirs[level] = opendir (dir);	  if (dirs[level] == NULL)	    return -1;	  skip = got;	  while (skip-- != 0)	    {	      errno = 0;	      if (readdir (dirs[level]) == NULL)		return errno == 0 ? 0 : -1;	    }	}      errno = 0;    }  return errno == 0 ? 0 : -1;}/* Call a function on every element in a directory tree.  */intDEFUN(ftw, (dir, func, descriptors),      CONST char *dir AND      int EXFUN((*func), (CONST char *file, struct stat *status,			  int flag)) AND      int descriptors){  DIR **dirs;  size_t len;  char buf[PATH_MAX + 1];  struct stat s;  int flag, ret;  int i;  if (descriptors <= 0)    descriptors = 1;  dirs = (DIR **) __alloca (descriptors * sizeof (DIR *));  i = descriptors;  while (i-- > 0)    dirs[i] = NULL;  if (stat (dir, &s) < 0)    {      if (errno != EACCES)	return -1;      flag = FTW_NS;    }  else if (S_ISDIR (s.st_mode))    {      dirs[0] = opendir (dir);      if (dirs[0] != NULL)	flag = FTW_D;      else	{	  if (errno != EACCES)	    return -1;	  flag = FTW_DNR;	}    }  else    flag = FTW_F;  len = strlen (dir);  memcpy ((PTR) buf, (PTR) dir, len + 1);  ret = (*func) (buf, &s, flag);  if (flag == FTW_D)    {      if (ret == 0)	ret = ftw_dir (dirs, 0, descriptors, buf, len, func);      if (dirs[0] != NULL)	{	  int save;	  save = errno;	  closedir (dirs[0]);	  errno = save;	}    }  return ret;}

⌨️ 快捷键说明

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