myownftw.c(4.21)

//Having read code for a long time, finally i get it written down, and it doesn't seem that hard, you can do it!!
 
#include "apue.h"
#include <dirent.h>
#include <limits.h>
 
 
#ifdef        PATH_MAX
static int  pathmax = PATH_MAX;
#else
static int  pathmax = 0;
#endif
 
#define SUSV3 200112L
 
static long        posix_version = 0;
 
/* If PATH_MAX is indeterminate, no guarantee this is adequate */
#define     PATH_MAX_GUESS  1024
 
char *
path_alloc(int *sizep) /* also return allocated size, if nonnull */
{
  char      *ptr;
  int         size;
 
  if (posix_version == 0)
    posix_version = sysconf(_SC_VERSION);
 
  if (pathmax == 0) {                 /* first time through */
    errno = 0;
    if ((pathmax = pathconf("/", _PC_PATH_MAX)) < 0) {
      if (errno == 0)
         pathmax = PATH_MAX_GUESS;       /* it's indeterminate */
      else
         err_sys("pathconf error for _PC_PATH_MAX");
    } else {
      pathmax++;          /* add one since it's relative to root */
    }
  }
  if (posix_version < SUSV3)
    size = pathmax + 1;
  else
    size = pathmax;
 
  if ((ptr = malloc(size)) == NULL)
    err_sys("malloc error for pathname");
 
  if (sizep != NULL)
    *sizep = size;
  return(ptr);
}
 
 
typedef int Myfunc(const char *,const struct stat *, int);
 
static Myfunc myfunc;
static int dopath(Myfunc *);
static int myftw(const char *, Myfunc *);
 
static int nreg, ndir, nblk, nchr, nsock, nslink, nfifo, ntot;
 
int main(int argc, char *argv[]){
  int ret;
 
  if(argc != 2)
    err_quit("<usage> %s pathname", argv[0]);
 
  ret = myftw(argv[1], myfunc);
 
  ntot = nreg + nblk + nchr + ndir + nsock + nslink + nfifo;
  if(ntot == 0)
    ntot = 1;
 
  printf("regular files       = %7ld, %5.2f%%\n",  nreg, nreg*100.0/ntot);
  printf("directories         = %7ld, %5.2f%%\n",  ndir, ndir*100.0/ntot);
  printf("character special   = %7ld, %5.2f%%\n",  nchr, nchr*100.0/ntot);
  printf("block sepcial       = %7ld, %5.2f%%\n",  nblk, nblk*100.0/ntot);
  printf("sockets             = %7ld, %5.2f%%\n",  nsock, nsock*100.0/ntot);
  printf("symbolic link       = %7ld, %5.2f%%\n",  nslink, nslink*100.0/ntot);
  printf("FIFOs               = %7ld, %5.2f%%\n",  nfifo, nfifo*100.0/ntot);
 
  exit(ret);
}
 
static char *fullpath;
 
static int myftw(const char *pathname, Myfunc func){
  int len, ret;
  fullpath = path_alloc(&len);
 
  strncpy(fullpath, pathname, len);
  fullpath[len-1] = 0;
 
  return(dopath(func));
}
 
#define FTW_F 1
#define FTW_D 2
#define FTW_NS 3
#define FTW_DNR 4
 
static int dopath(Myfunc func){
  struct stat statbuf;
  DIR *dp;
  struct dirent *dirp;
  int ret;
  char *ptr;
 
 
  if(lstat(fullpath, &statbuf) < 0)
    return(func(fullpath, &statbuf, FTW_NS));
  if(S_ISDIR(statbuf.st_mode) == 0)
    return(func(fullpath, &statbuf, FTW_F));
 
  if((ret = func(fullpath, &statbuf, FTW_D)) < 0)
    return(ret);
 
  ptr = fullpath + strlen(fullpath);
  *ptr++ = '/';
  *ptr = 0;
 
  if((dp = opendir(fullpath)) == NULL)
    return(func(fullpath, &statbuf, FTW_DNR));
  while((dirp = readdir(dp)) != NULL){
    if(!strcmp(dirp->d_name, ".") ||
       !strcmp(dirp->d_name, ".."))
      continue;
    // not "strcat(fullpath, dirp->d_name)"
    strcpy(ptr, dirp->d_name);
    if((ret = dopath(func)) < 0)
      break;
  }
 
  ptr[-1] = 0;
  if(closedir(dp) < 0)
    err_ret("close dir %s error", fullpath);
 
  return ret;
}
 
 
static int
myfunc(const char *pathname, const struct stat *statbuf, int type){
  switch(type){
  case FTW_F:
    switch(statbuf->st_mode & S_IFMT){
    case S_IFREG: nreg++; break;
    case S_IFCHR: nchr++; break;
    case S_IFBLK: nblk++; break;
    case S_IFIFO: nfifo++; break;
    case S_IFSOCK: nsock++; break;
    case S_IFLNK: nslink++; break;
    case S_IFDIR:
      err_dump("for S_IFDIR for %s", pathname);
    }
    break;
 case FTW_D:
   ndir++;
   break;
 case FTW_NS:
   err_ret("stat error for %s", pathname);
   break;
 case FTW_DNR:
   err_ret("can't read directory %s", pathname);
   break;
 default:
   err_dump("unknown type %d for pathname %s", type, pathname);
 
   return(0);
  }
}
原文地址:https://www.cnblogs.com/beanmoon/p/2731690.html