2017-05-31 98 views
0

我在第二次調用時打開同一目錄時出現問題。 例如,我先打開folder1/folder2;那麼如果我調用我在folder1上使用的函數,它說它無法打開它。我雖然我會關閉一個路徑中的所有目錄,並試圖做到這一點,但沒有結果。 這是我的代碼第二次無法打開目錄

void scanDir(char *dir, int depth, char type, char *path, long gtsize, int attrib) 
{ 
    DIR *dp; 
    struct dirent *entry; 
    struct stat statbuf; 
    char newPath[strlen(path)+strlen(dir)]; 
    if((dp = opendir(dir)) == NULL) { 
     fprintf(stderr,"Cannot open directory %s\n because of e", dir); 
     exit(10); 
     return; 
    } 
    strcpy(newPath, path); 
    strcat(newPath, dir); 
    if (type!='f' && testAttrib(attrib, dir)) 
     printf("%s\n", newPath); 
    strcat(newPath, "/"); 
    chdir(dir); 
    while((entry = readdir(dp)) != NULL) { 
     stat(entry->d_name,&statbuf); 

     if(S_ISDIR(statbuf.st_mode) && testAttrib(attrib, entry->d_name)) { 
      if(!strcmp(".",entry->d_name) || !strcmp("..",entry->d_name)) 
       continue; // ignore . and .. 
      if (depth>1 || depth<=-1) 
       scanDir(entry->d_name,depth-1,type,newPath,gtsize,attrib); 
     } 
     if(S_ISREG(statbuf.st_mode) && type!='d' && testAttrib(attrib, entry->d_name)) { 
       off_t sizeF = statbuf.st_size; 
       char filePath[100]; 
       strcpy(filePath, newPath); 
       strcat(filePath, entry->d_name); 
       if(sizeF>=gtsize) 
        printf("%s \n", filePath); 
      } 
    } 
    chdir(".."); 
    closedir(dp); 
} 
+1

那麼,看看錯誤?例如'perror()'。 – Stargateur

+0

它加入第一個if並打印「無法打開目錄」 –

回答

2
char newPath[strlen(path)+strlen(dir)]; //WRONG! 

肯定是錯誤的。您需要爲終止0保留一個額外的字節,並且您要添加/。所以它應該是

char newPath[strlen(path)+strlen(dir)+2]; 

順便說一句,可以考慮使用snprintf(3)asprintf(3),而不是你strcat電話。

我不確定調用chdir(2)是一個明智的想法,你當然應該檢查它是否順利。見perror(3),errno(3),strerror(3)

另請參閱nftw(3)

+1

它仍然太短,因爲他還添加了一個尾隨的'/'。 – JeremyP

+0

你對,但這不是問題 –

+0

然後在你的程序中使用'errno'並嘗試[strace(1)](http://man7.org/linux/man-pages/man1/strace.1.html) 。不要忘記編譯所有警告和調試信息('gcc -Wall -Wextra -g')和**使用調試器'gdb' ** –

1

在struct dirent中,成員d_name包含沒有路徑的名稱。這意味着傳遞給函數opendir()的參數沒有指向文件或目錄的路徑,所以發生錯誤ENOENT。

可以說你有目錄/ home/usr/folder1/folder2。你叫

scandir("/home/usr/folder1/", 2, type, ...) // I understood only first two parameters.

這個功能似乎起作用,但是當函數調用自身遞歸搜索/家庭的/ usr /資料夾/文件夾2

if (depth>1 || depth<=-1) scanDir(entry->d_name,depth-1,type,newPath,gtsize,attrib);

第一傳遞給SCANDIR參數這個時間是「folder2」而不是「/ home/usr/folder1/folder2」所以opendir(dir)給出的錯誤命名爲ENOENT

還有一點你應該小心的是readdir不是可重入函數,因此調用readdir()函數可能會導致不期望的錯誤。在你的代碼中,它看起來像函數給出了你想要的結果。但是,我認爲「它的工作原理」可能與您的想法有所不同。如果代碼變得複雜,我建議根據READDIR的手冊頁使用readdir_r()函數,這是重入READDIR

的版本:

成功時,READDIR()返回一個指針一個直接的結構。 (這 結構可以靜態分配的;不要試圖釋放(3))之後遞歸調用SCANDIR()函數,在函數中的每個堆棧

,您的條目變成空指針,因爲結構是靜態分配。

對你的另一個建議是使用linux提供的nftw()或scandir()函數。尤其是nftw真的很強大,並且你們大部分都想要。