2011-02-14 14 views
9

Bu, yinelemeli olarak dizinlere ve düzenli dosyalara gitmek ve çıktı almak için yazdığım bir C programıdır. Linux makinemi derler ve iyi çalışır. Ama Solaris üzerinde, dit->d_type == 8 denetimi ve diğer benzerleri çalışmaz, çünkü d_type alanı yok. Bu soruna okuduğum bir cevap, S_ISREG() ve S_ISDIR() makrolarını kullanmaktır, ancak şu anda kodumda oldukları gibi çalışmıyorlar. Linux makinemde çalışan hatlara yorum yaptım. Doğru S_ISREG() ve S_ISDIR() kullandığınızS_ISREG() ve S_ISDIR() POSIX Makrolar nasıl kullanılır?

#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

Sorunun artık anlamlı olmadığı için kodu orijinaline geri yükledim. Çalışma koduna katkıda bulunmanız harika, ama bu soruya değil, bir cevaba ait. Mu'nin çözümünü uygulayan eksiksiz bir kod yayınlamaya değer olduğunu düşünüyorsanız, lütfen yanıt olarak gönderin. – Gilles

+0

Bu bir yıldan fazla bir süredir böyle oturuyor ve iyi bir görüşe sahip. Doğru kodun kaldırılması için bir neden yoktur çünkü buralarda insanlar buraya ilgi duyacaklardır (ve sorunu çözdüler). Kırılan çözümün olması hiç kimseye yardım etmiyor. Bunu değiştirmek isterseniz, en azından çözümü önce yanıt olarak yapıştırın. – zalberico

+0

Bu, "ağaç" ile aynı mı? –

cevap

14

, sadece yanlış bir şey bunları kullanıyoruz. main içinde while((dit = readdir(dip)) != NULL) döngüde

, sen currentPath değiştirmeden tekrar tekrar currentPath üzerinde stat aradığınız:

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

Tam yolu almak için bir çizgi ve currentPath için dit->d_name ekleme olmamalı stat için istediğiniz dosyaya? Diğer stat çağrılarınızda da benzer değişikliklerin olduğunu düşünür.

+0

Teşekkürler, bu sorun gibi görünüyor. Her şeyi bozmadan değişimi nasıl yapacağınıza dair herhangi bir fikir var mı? Sadece/veya dit-> d_name eklemek için strcat kullanmanız her yinelemenin yolu yanlış oluşturmasına rağmen, kodun geri kalanını da karıştırır. – zalberico

+2

Aslında sadece düşündüm düşünüyorum, benzer bir durumda diğer insanlara yardımcı olmak için bir anda güncellenmiş kodu göndereceğiz. Teşekkür ederim. – zalberico

3

[Yayınlayan: Fossuser] "mu çok kısa" sayesinde hata düzeltmeyi başardım. İşte benim çalışma kodum güzel bir örnek arayanlar için düzenlenmiştir (çevrimiçi olarak başkalarını bulamadığım için).

#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); 
    } 
} 
+0

, bir kütüphane nesnesini dizin olarak açma girişiminde bulunur ve daha sonra segfaults: 'Hata: Dizin açılamadı ==>/SDL_shaders_gl.lo' ... ' Segmentasyon hatası (çekirdek dökümü) ' – carefulnow1