2011-02-14 130 views
9

這是我寫的遞歸導航和輸出目錄和常規文件的C程序。它在我的Linux機器上編譯並運行良好。但在Solaris上,dit->d_type == 8檢查和其他類似檢查不起作用,因爲沒有d_type字段。我讀過這個問題的一個答案是使用S_ISREG()S_ISDIR()宏,但它們目前在我的代碼中並沒有像我的代碼那樣工作。我評論了在我的Linux機器上工作的線路。如何使用S_ISREG()和S_ISDIR()POSIX宏?

#include <sys/types.h> 
#include <sys/stat.h> 
#include <stdlib.h> 
#include <dirent.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <errno.h> 
#include <string.h> 

void helper(DIR *, struct dirent *, struct stat, char *, int, char **); 
void dircheck(DIR *, struct dirent *, struct stat, char *, int, char **); 

int main(int argc, char *argv[]){ 

    DIR *dip; 
    struct dirent *dit; 
    struct stat statbuf; 
    char currentPath[FILENAME_MAX]; 
    int depth = 0; /*Used to correctly space output*/ 

    /*Open Current Directory*/ 
    if((dip = opendir(".")) == NULL) 
    return errno; 

    /*Store Current Working Directory in currentPath*/ 
    if((getcwd(currentPath, FILENAME_MAX)) == NULL) 
    return errno; 

    /*Read all items in directory*/ 
    while((dit = readdir(dip)) != NULL){ 
    /*Skips . and ..*/ 
    if(strcmp(dit->d_name, ".") == 0 || strcmp(dit->d_name, "..") == 0) 
     continue; 

    if(stat(currentPath, &statbuf) == -1){ 
     perror("stat"); 
     return errno; 
    } 

    /*Checks if current item is of the type file (type 8) and no command line arguments 
     if(dit->d_type == 8 && argv[1] == NULL)*/ 
    if(S_ISREG(statbuf.st_mode) && argv[1] == NULL) 
     printf("%s (%d bytes)\n", dit->d_name, (int)statbuf.st_size); 

     /*If a command line argument is given, checks for filename match 
    if(dit->d_type == 8 && argv[1] != NULL)*/ 
    if(S_ISREG(statbuf.st_mode) && argv[1] != NULL) 
     if(strcmp(dit->d_name, argv[1]) == 0) 
     printf("%s (%d bytes)\n", dit->d_name, (int)statbuf.st_size); 

     /*Checks if current item is of the type directory (type 4) 
     if(dit->d_type == 4)*/ 
    if(S_ISDIR(statbuf.st_mode)) 
     dircheck(dip, dit, statbuf, currentPath, depth, argv); 

    } 
    closedir(dip); 
    return 0; 
} 

/*Recursively called helper function*/ 
void helper(DIR *dip, struct dirent *dit, struct stat statbuf, 
    char currentPath[FILENAME_MAX], int depth, char *argv[]){ 
    int i = 0; 

    if((dip = opendir(currentPath)) == NULL) 
    printf("Error: Failed to open Directory ==> %s\n", currentPath); 

    while((dit = readdir(dip)) != NULL){ 

    if(strcmp(dit->d_name, ".") == 0 || strcmp(dit->d_name, "..") == 0) 
     continue; 

    stat(currentPath, &statbuf); 

    /*if(dit->d_type == 8 && argv[1] == NULL){*/ 
    if(S_ISREG(statbuf.st_mode) && argv[1] == NULL){ 
     for(i = 0; i < depth; i++) 
     printf(" "); 
     printf("%s (%d bytes)\n", dit->d_name, (int)statbuf.st_size); 
    } 

    /*if(dit->d_type == 8 && argv[1] != NULL){*/ 
    if(S_ISREG(statbuf.st_mode) && argv[1] != NULL){ 
     if(strcmp(dit->d_name, argv[1]) == 0){ 
    for(i = 0; i < depth; i++) 
     printf(" "); 
    printf("%s (%d bytes)\n", dit->d_name, (int)statbuf.st_size); 
     } 
    } 

    /*if(dit->d_type == 4)*/ 
    if(S_ISDIR(statbuf.st_mode)) 
     dircheck(dip, dit, statbuf, currentPath, depth, argv); 

    } 
} 

void dircheck(DIR *dip, struct dirent *dit, struct stat statbuf, 
     char currentPath[FILENAME_MAX], int depth, char *argv[]){ 
    int i = 0; 

    strcat(currentPath, "/"); 
    strcat(currentPath, dit->d_name); 

    /*If two directories exist at the same level the path 
    is built wrong and needs to be corrected*/ 
    if((chdir(currentPath)) == -1){ 
    chdir(".."); 
    getcwd(currentPath, FILENAME_MAX); 
    strcat(currentPath, "/"); 
    strcat(currentPath, dit->d_name); 

    for(i = 0; i < depth; i++) 
     printf (" "); 
    printf("%s (subdirectory)\n", dit->d_name); 
    depth++; 
    helper(dip, dit, statbuf, currentPath, depth, argv); 
    } 

    else{ 
    for(i =0; i < depth; i++) 
     printf(" "); 
    printf("%s (subdirectory)\n", dit->d_name); 
    chdir(currentPath); 
    depth++; 
    helper(dip, dit, statbuf, currentPath, depth, argv); 
    } 

} 
+2

我已將代碼恢復到原始狀態,因爲問題沒有任何意義。你提供工作代碼是很好的,但這屬於答案,而不是問題。如果您認爲需要發佈實現mu解決方案的完整代碼,請將其作爲答案發布。 – Gilles 2012-02-28 17:58:53

+0

這已經坐了一年多了,並且有相當數量的意見。沒有理由刪除正確的代碼,因爲來到這裏的人可能會對它感興趣(並解決了問題)。有破解的解決方案不會幫助任何人。如果您想將其更改回來,那麼至少應先將解決方案粘貼爲答案。 – zalberico 2012-03-27 23:41:22

+0

這與「樹」相同嗎? – 2015-01-17 11:39:57

回答

14

您使用S_ISREG()S_ISDIR()正確的,你只是用他們在錯誤的事情。

mainwhile((dit = readdir(dip)) != NULL)循環,你呼籲currentPathstat一遍又一遍,而不改變currentPath

if(stat(currentPath, &statbuf) == -1) { 
    perror("stat"); 
    return errno; 
} 

你不是應該附加一個斜線和dit->d_namecurrentPath得到充分的路徑到你想要的文件stat?好像也需要對其他stat調用進行類似的更改。

3

[發表於fossuser]感謝「mu太短」我能修復這個bug。這裏是我的工作代碼已被編輯爲那些尋找一個很好的例子(因爲我無法在網上找到任何其他人)。

#include <sys/types.h> 
#include <sys/stat.h> 
#include <stdlib.h> 
#include <dirent.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <errno.h> 
#include <string.h> 

void helper(DIR *, struct dirent *, struct stat, char *, int, char **); 
void dircheck(DIR *, struct dirent *, struct stat, char *, int, char **); 

int main(int argc, char *argv[]){ 

    DIR *dip; 
    struct dirent *dit; 
    struct stat statbuf; 
    char currentPath[FILENAME_MAX]; 
    int depth = 0; /*Used to correctly space output*/ 

    /*Open Current Directory*/ 
    if((dip = opendir(".")) == NULL) 
    return errno; 

    /*Store Current Working Directory in currentPath*/ 
    if((getcwd(currentPath, FILENAME_MAX)) == NULL) 
    return errno; 

    /*Read all items in directory*/ 
    while((dit = readdir(dip)) != NULL){ 

    /*Skips . and ..*/ 
    if(strcmp(dit->d_name, ".") == 0 || strcmp(dit->d_name, "..") == 0) 
     continue; 

    /*Correctly forms the path for stat and then resets it for rest of algorithm*/ 
    getcwd(currentPath, FILENAME_MAX); 
    strcat(currentPath, "/"); 
    strcat(currentPath, dit->d_name); 
    if(stat(currentPath, &statbuf) == -1){ 
     perror("stat"); 
     return errno; 
    } 
    getcwd(currentPath, FILENAME_MAX); 


    /*Checks if current item is of the type file (type 8) and no command line arguments*/ 
    if(S_ISREG(statbuf.st_mode) && argv[1] == NULL) 
     printf("%s (%d bytes)\n", dit->d_name, (int)statbuf.st_size); 

    /*If a command line argument is given, checks for filename match*/ 
    if(S_ISREG(statbuf.st_mode) && argv[1] != NULL) 
     if(strcmp(dit->d_name, argv[1]) == 0) 
     printf("%s (%d bytes)\n", dit->d_name, (int)statbuf.st_size); 

    /*Checks if current item is of the type directory (type 4)*/ 
    if(S_ISDIR(statbuf.st_mode)) 
     dircheck(dip, dit, statbuf, currentPath, depth, argv); 

    } 
    closedir(dip); 
    return 0; 
} 

/*Recursively called helper function*/ 
void helper(DIR *dip, struct dirent *dit, struct stat statbuf, 
     char currentPath[FILENAME_MAX], int depth, char *argv[]){ 
    int i = 0; 

    if((dip = opendir(currentPath)) == NULL) 
    printf("Error: Failed to open Directory ==> %s\n", currentPath); 

    while((dit = readdir(dip)) != NULL){ 

    if(strcmp(dit->d_name, ".") == 0 || strcmp(dit->d_name, "..") == 0) 
     continue; 

    strcat(currentPath, "/"); 
    strcat(currentPath, dit->d_name); 
    stat(currentPath, &statbuf); 
    getcwd(currentPath, FILENAME_MAX); 

    if(S_ISREG(statbuf.st_mode) && argv[1] == NULL){ 
     for(i = 0; i < depth; i++) 
    printf(" "); 
     printf("%s (%d bytes)\n", dit->d_name, (int)statbuf.st_size); 
    } 

    if(S_ISREG(statbuf.st_mode) && argv[1] != NULL){ 
     if(strcmp(dit->d_name, argv[1]) == 0){ 
    for(i = 0; i < depth; i++) 
     printf(" "); 
    printf("%s (%d bytes)\n", dit->d_name, (int)statbuf.st_size); 
     } 
    } 

    if(S_ISDIR(statbuf.st_mode)) 
     dircheck(dip, dit, statbuf, currentPath, depth, argv); 
    } 
    /*Changing back here is necessary because of how stat is done*/ 
    chdir(".."); 
    closedir(dip); 
} 

void dircheck(DIR *dip, struct dirent *dit, struct stat statbuf, 
      char currentPath[FILENAME_MAX], int depth, char *argv[]){ 
    int i = 0; 

    strcat(currentPath, "/"); 
    strcat(currentPath, dit->d_name); 

    /*If two directories exist at the same level the path 
    is built wrong and needs to be corrected*/ 
    if((chdir(currentPath)) == -1){ 
    chdir(".."); 
    getcwd(currentPath, FILENAME_MAX); 
    strcat(currentPath, "/"); 
    strcat(currentPath, dit->d_name); 

    for(i = 0; i < depth; i++) 
     printf (" "); 
    printf("%s (subdirectory)\n", dit->d_name); 
    depth++; 
    helper(dip, dit, statbuf, currentPath, depth, argv); 
    } 

    else{ 
    for(i =0; i < depth; i++) 
     printf(" "); 
    printf("%s (subdirectory)\n", dit->d_name); 
    chdir(currentPath); 
    depth++; 
    helper(dip, dit, statbuf, currentPath, depth, argv); 
    } 
}