對某個目錄具有訪問權限的任一用戶都可讀該目錄,但是,為了防止文件系統產生混亂,只有內核才能寫目錄。一個目錄的寫權限位和執行權限位決定了在該目錄中能否創建新文件以及刪除文件,它們并不表示能否寫目錄本身。
#include <dirent.h>DIR *opendir( const char *pathname );返回值:若成功則返回指針,若出錯則返回NULLstruct dirent *readdir( DIR *dp );返回值:若成功則返回指針,若在目錄結尾或出錯則返回NULLvoid rewinddir( DIR *dp );int closedir( DIR *dp );返回值:若成功則返回0,若出錯則返回-1long telldir( DIR *dp );返回值:與dp關聯的目錄中的當前位置void seekdir( DIR *dp, long loc );
頭文件<dirent.h>中定義的dirent結構與實現有關。幾種典型的UNIX實現對此結構所作的定義至少包含下列兩個成員:
struct dirent { ino_t d_ino; /* i-node number */ char d_name[NAME_MAX + 1]; /*null-terminated filename */}
DIR結構是一個內部結構,上述6個函數用這個內部結構保存當前正被讀的目錄的有關信息。其作用類似與FILE結構。FILE結構由標準I/O庫維護。
由opendir返回的指向DIR結構的指針由另外5個函數使用。opendir執行初始化操作,使第一個readdir讀目錄中的第一個目錄項。目錄中各目錄項的順序與實現有關。它們通常并不按字母順序排序。
程序清單4-7 遞歸降序遍歷目錄層次結構,并按文件類型計數
[root@localhost apue]# cat -b PRog4-7.c 1 #include "apue.h" 2 #include <dirent.h> 3 #include <limits.h> 4 #include <errno.h> 5 #ifdef PATH_MAX 6 static int pathmax = PATH_MAX; 7 #else 8 static int pathmax = 0; 9 #endif 10 #define SUSV3 200112L 11 static long posix_version = 0; 12 /* If PATH_MAX is indeterminate, no guarantee this is adequate */ 13 #define PATH_MAX_GUESS 1024 14 char * 15 path_alloc(int *sizep) /* also return allocated size, if nonull */ 16 { 17 char *ptr; 18 int size; 19 if(posix_version == 0) 20 posix_version = sysconf(_SC_VERSION); 21 22 if(pathmax == 0) { /* first time trough */ 23 errno = 0; 24 if((pathmax = pathconf("/", _PC_PATH_MAX)) < 0) { 25 if(errno == 0) 26 pathmax = PATH_MAX_GUESS; /* it's indeterminate */ 27 else 28 err_sys("pathconf error for _PC_PATH_MAX"); 29 } else { 30 pathmax++; /* add one since it's relative to root */ 31 } 32 } 33 if(posix_version < SUSV3) 34 size = pathmax + 1; 35 else 36 size = pathmax; 37 38 if((ptr = malloc(size)) == NULL) 39 err_sys("malloc error for pathname"); 40 if(sizep != NULL) 41 *sizep = size; 42 return(ptr); 43 } 44 /* function type that is called for each filename */ 45 typedef int Myfunc( const char *, const struct stat *, int ); 46 static Myfunc myfunc; 47 static int myftw( char *, Myfunc * ); 48 static int dopath( Myfunc * ); 49 static long nreg, ndir, nblk, nchr, nfifo, nslink, nsock, ntot; 50 int 51 main( int argc, char *argv[] ) 52 { 53 int ret; 54 55 if( argc != 2 ) 56 err_quit( "usage: ftw <starting-pathname>" ); 57 58 ret = myftw( argv[1], myfunc ); /* does it all */ 59 ntot = nreg + ndir + nblk + nchr + nfifo + nslink + nsock; 60 if( ntot == 0 ) 61 ntot = 1; /* avoid divide by 0; print 0 for all counts */ 62 printf( "regular files = %7ld, %5.2f %%/n", nreg, nreg*100.0/ntot ); 63 printf( "directories = %7ld, %5.2f %%/n", ndir, ndir*100.0/ntot ); 64 printf( "block special = %7ld, %5.2f %%/n", nblk, nblk*100.0/ntot ); 65 printf( "char special = %7ld, %5.2f %%/n", nchr, nchr*100.0/ntot ); 66 printf( "FIFOs = %7ld, %5.2f %%/n", nfifo, nfifo*100.0/ntot ); 67 printf( "symbolic links = %7ld, %5.2f %%/n", nslink, nslink*100.0/ntot ); 68 printf( "sockets = %7ld, %5.2f %%/n", nsock, nsock*100.0/ntot ); 69 exit( ret ); 70 } 71 /* 72 * Descend throuth the hierarchy, starting at "pathname". 73 * The caller's func() is called for every file. 74 */ 75 #define FTW_F 1 /* file other than directory */ 76 #define FTW_D 2 /* directory */ 77 #define FTW_DNR 3 /* directory that can't be read */ 78 #define FTW_NS 4 /* file that we can't stat */ 79 static char * fullpath; /*contains full pathname for every file */ 80 static int 81 myftw( char *pathname, Myfunc *func ) 82 { 83 int len; 84 fullpath = path_alloc( &len ); /* malloc's for PATH_MAX + 1 bytes */ 85 /* program_list 2-3 */ 86 strncpy( fullpath, pathname, len ); /* protect against */ 87 fullpath[len - 1] = 0; 88 return(dopath(func)); 89 } 90 /* 91 * Descend through the hierarchy, starting at "fullpath". 92 * If "fullpath" is anything other than a directory, we lstat() it, 93 * call func(), and return. For a directory, we call ourself 94 * recursively for each name in the directory. 95 */ 96 static int 97 dopath( Myfunc *func ) 98 { 99 struct stat statbuf; 100 struct dirent *dirp; 101 DIR *dp; 102 int ret; 103 char *ptr; 104 if( lstat( fullpath, &statbuf ) < 0 ) /* stat error */ 105 return( func(fullpath, &statbuf, FTW_NS) ); 106 if( S_ISDIR(statbuf.st_mode) == 0) /* not a directory */ 107 return( func(fullpath, &statbuf, FTW_F) ); 108 /* 109 * It's a directory. First call func() for the directory, 110 * then process each filename in the directory. 111 */ 112 if((ret = func(fullpath, &statbuf, FTW_D)) != 0) 113 return(ret); 114 ptr = fullpath + strlen(fullpath); /* point to end of fullpath */ 115 *ptr++ = '/'; 116 *ptr = 0; 117 if((dp = opendir(fullpath)) == NULL) /* can't read directory */ 118 return(func(fullpath, &statbuf, FTW_DNR)); 119 while((dirp = readdir(dp)) != NULL) 120 { 121 if(strcmp(dirp->d_name, ".") == 0 || 122 strcmp(dirp->d_name, "..") == 0) 123 continue; /* ignore dot and dot-dot */ 124 125 strcpy(ptr, dirp->d_name); /*append name after slash */ 126 // if((ret = dopath(func)) != 0) /* recursive */ 127 // break; /* time to leave */ 128 dopath(func); 129 } 130 ptr[-1] = 0; /* erase everything from slash onwards */ 131 if(closedir(dp) < 0) 132 err_ret("can't close directory %s", fullpath); 133 return(ret); 134 } 135 static int 136 myfunc(const char *pathname, const struct stat *statptr, int type) 137 { 138 switch(type) 139 { 140 case FTW_F: 141 switch(statptr->st_mode & S_IFMT) 142 { 143 case S_IFREG: nreg++; break; 144 case S_IFBLK: nblk++; break; 145 case S_IFCHR: nchr++; break; 146 case S_IFIFO: nfifo++; break; 147 case S_IFLNK: nslink++; break; 148 case S_IfsoCK: nsock++; break; 149 case S_IFDIR: 150 err_dump("for S_IFDIR for %s", pathname); 151 /* directories should have type = FTW_D */ 152 } 153 break; 154 case FTW_D: 155 ndir++; 156 break; 157 case FTW_DNR: 158 err_ret("can't read directory %s", pathname); 159 break; 160 case FTW_NS: 161 err_ret("stat error for %s", pathname); 162 break; 163 default: 164 err_dump("unknown type %d for pathname %s", type, pathname); 165 } 166 return( 0 ); 167 }
程序運行結果:
[root@localhost apue]# ./prog4-7 /home/zhu/testregular files = 3, 60.00 %directories = 2, 40.00 %block special = 0, 0.00 %char special = 0, 0.00 %FIFOs = 0, 0.00 %symbolic links = 0, 0.00 %sockets = 0, 0.00 %
上面的源程序代碼中有一個不理解的地方,第126-127行(這是APUE書中原來的代碼)。希望路過的有緣人可以指點一二,小弟不勝感激。將這兩行替換為128行,這樣能夠理解,而且程序正確執行。
本篇博文內容摘自《UNIX環境高級編程》(第二版),僅作個人學習記錄所用。關于本書可參考:http://www.apuebook.com/。
新聞熱點
疑難解答