1 #include "apue.h"
2 #include <dirent.h>
3 #include <limits.h>
4 #include "fig2.16"
5
6 typedef int Myfunc(const char *, const struct stat *, int);
7
8 static Myfunc myfunc;
9 static int myftw(char *, Myfunc *);
10 static int dopath(Myfunc *);
11 static long nreg, ndir, nblk, nchr, nfifo, nslink, nsock, ntot;
12
13 int main(int argc, char *argv[])
14 {
15 int ret;
16 if( argc != 2)
17 err_quit("usage: ftw <starting-pathname>");
18
19 ret = myftw(argv[1],myfunc);
20 ntot = nreg + ndir + nblk + nchr + nfifo + nslink + nsock;
21 if( ntot == 0)
22 ntot = 1;
23 printf("regular files = %71d, %5.2f %%\n", nreg, nreg * 100 / ntot);
24 printf("directories = %71d, %5.2f %%\n", ndir, ndir * 100 / ntot);
25 printf("block special = %71d, %5.2f %%\n",nblk, nblk * 100 / ntot);
26 printf("char special = %71d, %5.2f %%\n", nchr, nchr * 100 / ntot);
27 printf("fifo special = %71d, %5.2f %%\n", nfifo, nfifo * 100 / ntot);
28 printf("symbolic links = %71d, %5.2f %%\n", nslink, nslink * 100 / ntot);
29 printf("sockets = %71d, %5.2f %%\n",nsock, nsock * 100 / ntot);
30
31 exit(ret);
32 }
33
34 #define FTW_F 1
35 #define FTW_D 2
36 #define FTW_DNR 3
37 #define FTW_NS 4
38
39 static char *fullpath;
40 static size_t pathlen;
41
42 static int myftw(char *pathname, Myfunc *func)
43 {
44 fullpath = path_alloc(&pathlen);
45 if( pathlen <= strlen(pathname) )
46 {
47 pathlen = strlen(pathname) * 2;
48 if( (fullpath = realloc(fullpath, pathlen) == NULL) )
49 err_sys("realloc failed");
50 }
51
52 strcpy(fullpath, pathname);
53 return(dopath(func));
54 }
55
56
57 static int dopath(Myfunc *func)
58 {
59 struct stat statbuf;
60 struct dirent *dirp;
61 DIR *dp;
62 int ret,n;
63 if( lstat(fullpath, &statbuf) < 0 )
64 return(func(fullpath,&statbuf,FTW_NS));
65 if (S_ISCHR(statbuf.st_mode) == 0)
66 return(func(fullpath,&statbuf,FTW_F));
67
68 if( (ret = func(fullpath, &statbuf, FTW_D)) != 0)
69 return(ret);
70 n = strlen(fullpath);
71 if( n + NAME_MAX +2 > pathlen)
72 {
73 pathlen *= 2;
74 if( (fullpath = realloc(fullpath,pathlen)) == NULL )
75 err_sys("realloc failed");
76 }
77 fullpath[n++] = '/';
78 fullpath[n] = 0;
79 if ( (dp = opendir(fullpath)) == NULL)
80 return (func(fullpath, &statbuf,FTW_DNR));
81 while ( dirp = readdir(dp) != NULL)
82 {
83 if ( strcmp(dirp->d_name,".") == 0 || strcmp(dirp->d_name, "..") == 0 )
84 continue;
85 strcpy(&fullpath[n],dirp->d_name);
86 if ( (ret = dopath(func)) != 0)
87 break;
88 }
89
90 fullpath[n-1] = 0;
91 if ( closedir(dp) < 0)
92 err_ret("can't close directory %s",fullpath);
93 return (ret);
94 }
95
96 static int myfunc (const char *pathname, const struct stat *statptr, int type)
97 {
98 switch( type ){
99 case FTW_F:
100 switch (statptr->st_mode & S_IFMT){
101 case S_IFREG: nreg++; break;
102 case S_IFBLK: nblk++; break;
103 case S_IFCHR: nchr++; break;
104 case S_IFIFO: nfifo++; break;
105 case S_IFLNK: nslink++; break;
106 case S_IFSOCK: nsock++; break;
107 case S_IFDIR:
108 err_dump("for S_IFDIR for %s",pathname);
109 }
110 break;
111 case FTW_D:
112 ndir++;
113 break;
114 case FTW_DNR:
115 err_ret("can't read directory %s",pathname);
116 break;
117 case FTW_NS:
118 err_ret("stat error for %s", pathname);
119 break;
120 default:
121 err_dump("unknow type %d for pathname %s", type, pathname);
122
123 }
124 return 0;
125
126 }
127
128
129
130
131
132
133
二、运行结果:
<usnavsvmh15:/home/tingbinz/apue.3e/SBSCODE/3>R*_*G:./statistic_file_type /home/tingbinz
for S_IFDIR for /home/tingbinz: Succes