Myownftw. C (4.21)
Last Update:2018-12-05
Source: Internet
Author: User
// 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_maxStatic int pathmax = path_max;# ElseStatic int pathmax = 0;# Endif # Define susv3 20010000l 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 */ElseErr_sys ("pathconf error for _ pc_path_max ");} Else {Pathmax ++;/* Add one since it's relative to root */}}If (posix_version <susv3)Size = pathmax + 1;ElseSize = 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;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 ("operating OS = % 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 intMyfunc (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 );}}