Cómo usar S_ISREG () y S_ISDIR () POSIX Macros?

Este es un progtwig de C que escribí para navegar recursivamente y publicar directorios y archivos regulares. Se comstack y funciona bien en mi máquina Linux. Pero en Solaris, la dit->d_type == 8 y las otras similares no funcionan porque no hay campo d_type . Una respuesta que leí a este problema es usar las S_ISREG() y S_ISDIR() , pero no funcionan en la forma en que las tengo actualmente en mi código. Comentaba las líneas que funcionan en mi máquina Linux.

 #include  #include  #include  #include  #include  #include  #include  #include  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 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 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 d_name); depth++; helper(dip, dit, statbuf, currentPath, depth, argv); } else{ for(i =0; i d_name); chdir(currentPath); depth++; helper(dip, dit, statbuf, currentPath, depth, argv); } } 

Está utilizando S_ISREG() y S_ISDIR() correctamente, solo los está usando incorrectamente.

En su while((dit = readdir(dip)) != NULL) loop en main , está llamando stat en currentPath una y otra vez sin cambiar currentPath :

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

¿No debería dit->d_name una barra diagonal y dit->d_name a currentPath para obtener la ruta completa al archivo que desea stat ? Me parece que también se necesitan cambios similares a sus otras llamadas de stat .

[Publicado en nombre de fossuser] Gracias a “mu es demasiado corto”, pude arreglar el error. Aquí está mi código de trabajo editado para aquellos que buscan un buen ejemplo (ya que no pude encontrar otros en línea).

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