Monday, August 25, 2014

Unix Prog: Files -- Directories(3)

Comprehensive Reading Directory Example:

fileio.c:
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<unistd.h>  
 #include<dirent.h>  
 #include<string.h>  
 #include<sys/stat.h>  
   
 typedef int MyFunc(const char*, const struct stat *, int);  
   
 static long nreg, ndir, nblk, nchr, nfifo, nslink, nsock, ntot;  
 static char* fullpath;  
   
 #define FTW_F 1  
 #define FTW_D 2  
 #define FTW_DNR 3  
 #define FTW_NS 4  
   
 static int myfunc(const char *pathname, const struct stat *statptr, int type)  
 {  
  switch(type) {  
  case FTW_F:  
   switch(statptr->st_mode & S_IFMT) {  
   case S_IFREG: nreg++; break;  
   case S_IFBLK: nblk++; break;  
   case S_IFCHR: nchr++; break;  
   case S_IFIFO: nfifo++; break;  
   case S_IFLNK: nslink++; break;  
   case S_IFSOCK: nsock++; break;  
   case S_IFDIR:  
    printf("for S_IFDIR for %s\n", pathname);  
    exit(2);  
   }  
   break;  
   
  case FTW_D:  
   ndir++;  
   break;  
   
  case FTW_DNR:  
   printf("can't read directory %s\n", pathname);  
   return(3);  
   break;  
   
  case FTW_NS:  
   printf("stat error for %s\n", pathname);  
   return(4);  
   break;  
   
  default:  
   printf("unknown type %d for pathname %s\n", type, pathname);  
   return(5);  
  }  
   
  return 0;  
 }  
   
 static int dopath(MyFunc* func)  
 {  
  struct stat statbuf;  
  struct dirent *dirp;  
  DIR *dp;  
  int ret;  
  char *ptr;  
   
  // Retrieve the file state information  
  if(lstat(fullpath, &statbuf) < 0) {  
   return(func(fullpath, &statbuf, FTW_NS));  
  }  
   
  // Test if it is one directory. If not, output info and return  
  if(S_ISDIR(statbuf.st_mode) == 0) {  
   return(func(fullpath, &statbuf, FTW_F));  
  }  
   
  // If it is directory, firstly output the basic info  
  if((ret = func(fullpath, &statbuf, FTW_D)) != 0) {  
   return(ret);  
  }  
   
  if((dp = opendir(fullpath)) == NULL)  
   return(func(fullpath, &statbuf, FTW_DNR));  
   
  ptr = fullpath + strlen(fullpath);  
  *ptr++ = '/'; //firstly add one slash, then increase ptr  
  *ptr = 0; // Make last character be 0  
   
  while((dirp = readdir(dp)) != NULL) {  
   // skip "." and ".."  
   if(strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0)  
    continue;  
   
   strcpy(ptr, dirp->d_name); // append the name after fullpath's slash  
   if((ret = dopath(func)) != 0)  
    break;  
  }  
   
  ptr[-1] = 0;  
  if(closedir(dp) < 0) {  
   printf("closedir error!\n");  
   exit(2);  
  }  
   
  return ret;  
 }  
   
 static int myftw(char *pathname, MyFunc *func)  
 {  
  int pathmax = 256;  
  fullpath = (char*)malloc(pathmax);  
   
  // Copy first 256 characters of pathname to fullpath  
  // If pathname is not as long as 256 characters, then for  
  // remaining positions, it will be filled up with /0  
  strncpy(fullpath, pathname, pathmax);  
  fullpath[pathmax-1] = 0;  
   
  return(dopath(func));  
 }  
   
 int main(int argc, char* argv[])  
 {  
  int ret;  
   
  if(argc != 2) {  
   printf("usage: ftw.out <starting-pathname>");  
   exit(1);  
  }  
   
  ret = myftw(argv[1], myfunc);  
  ntot = nreg + ndir + nblk + nchr + nfifo + nslink + nsock;  
  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("block special = %7ld, %5.2f %%\n", nblk, nblk*100.0/ntot);  
  printf("char special  = %7ld, %5.2f %%\n", nchr, nchr*100.0/ntot);  
  printf("FIFOs     = %7ld, %5.2f %%\n", nfifo, nfifo*100.0/ntot);  
  printf("symbolic links = %7ld, %5.2f %%\n", nslink, nslink*100.0/ntot);  
  printf("sockets    = %7ld, %5.2f %%\n", nsock, nsock*100.0/ntot);  
   
  exit(ret);  
 }  
   

shell:
1) List regular file fileio.c
2) List content of directory testdir
3) Run the program against fileio.c, only 1 regular file
4) Run the program against testdir, 2 regular files, 1 directory and 1 symbolic link.
 ubuntu@ip-172-31-23-227:~$ ls -lrt fileio.c  
 -rw-rw-r-- 1 ubuntu ubuntu 3409 Aug 26 00:57 fileio.c  
 ubuntu@ip-172-31-23-227:~$ ls -lrt testdir  
 total 0  
 -rw-rw-r-- 1 ubuntu ubuntu 0 Aug 26 00:57 t2  
 -rw-rw-r-- 1 ubuntu ubuntu 0 Aug 26 00:57 t1  
 lrwxrwxrwx 1 ubuntu ubuntu 10 Aug 26 00:58 slnk -> ../testdir  
 ubuntu@ip-172-31-23-227:~$ ./io.out fileio.c  
 regular files =    1, 100.00 %  
 directories  =    0, 0.00 %  
 block special =    0, 0.00 %  
 char special  =    0, 0.00 %  
 FIFOs     =    0, 0.00 %  
 symbolic links =    0, 0.00 %  
 sockets    =    0, 0.00 %  
 ubuntu@ip-172-31-23-227:~$ ./io.out testdir  
 regular files =    2, 50.00 %  
 directories  =    1, 25.00 %  
 block special =    0, 0.00 %  
 char special  =    0, 0.00 %  
 FIFOs     =    0, 0.00 %  
 symbolic links =    1, 25.00 %  
 sockets    =    0, 0.00 %  

No comments:

Post a Comment