如何使用S_ISREG()和S_ISDIR()POSIX宏? [英] How to use S_ISREG() and S_ISDIR() POSIX Macros?
问题描述
这是我写的递归导航和输出目录和普通文件的C程序。它编译和运行我的Linux机器上的罚款。但在Solaris中, dit-> d_type == 8
检查和其他类似的不工作,因为没有 d_type
字段。我读过这个问题的答案是使用 S_ISREG()
和 S_ISDIR()
宏,但他们在所有我有他们在我的code目前的方式不起作用。我评论,我的Linux机器上运行的线路。
的#include< SYS / types.h中>
#包括LT&; SYS / stat.h>
#包括LT&;&stdlib.h中GT;
#包括LT&;&dirent.h GT;
#包括LT&;&stdio.h中GT;
#包括LT&;&unistd.h中GT;
#包括LT&;&errno.h中GT;
#包括LT&;&string.h中GT;无效帮手(DIR *,结构的dirent *,结构统计,字符*,INT,CHAR **);
无效dircheck(DIR *,结构的dirent *,结构统计,字符*,INT,CHAR **);INT主(INT ARGC,CHAR *的argv []){ DIR *浸;
结构的dirent * DIT;
结构统计statbuf;
焦炭currentPath [FILENAME_MAX]
INT深度= 0; / *用于正确输出空间* / / *打开当前目录* /
如果((DIP =执行opendir(。))== NULL)
返回错误号; / *在currentPath商店当前工作目录* /
如果((GETCWD(currentPath,FILENAME_MAX))== NULL)
返回错误号; / *读取目录中的所有项目* /
而((DIT = READDIR(DIP))!= NULL){
/ *跳过。和.. * /
如果(STRCMP(dit->中d_name,)== 0 || STRCMP(dit-> d_name,..)== 0)
继续; 如果(STAT(currentPath,&安培; statbuf)== -1){
PERROR(STAT);
返回错误号;
} / *检查,如果目前的产品类型文件(8型),并没有命令行参数
如果(dit-> d_type == 8安培;&放大器;的argv [1] == NULL)* /
如果(S_ISREG(statbuf.st_mode)及和放大器;的argv [1] == NULL)
的printf(%S(%d字节)\\ n,dit-> d_name,(INT)statbuf.st_size); / *如果一个命令行参数,给出了文件名匹配检查
如果(dit-> d_type == 8和;&放大器;!的argv [1] = NULL)* /
如果(S_ISREG(statbuf.st_mode)及&放大器;!的argv [1] = NULL)
如果(STRCMP(dit-> d_name,ARGV [1])== 0)
的printf(%S(%d字节)\\ n,dit-> d_name,(INT)statbuf.st_size); / *检查,如果目前的产品类型目录(类型4)
如果(dit-> d_type == 4)* /
如果(S_ISDIR(statbuf.st_mode))
dircheck(DIP,DIT,statbuf,currentPath,深度的argv); }
closedir(DIP);
返回0;
}/ *递归调用辅助函数* /
无效帮手(DIR *浸,结构的dirent * DIT,结构统计statbuf,
焦炭currentPath [FILENAME_MAX],INT深度的char * ARGV []){
INT I = 0; 如果((DIP =执行opendir(currentPath))== NULL)
的printf(错误:无法打开目录==>%S \\ n,currentPath); 而((DIT = READDIR(DIP))!= NULL){ 如果(STRCMP(dit->中d_name,)== 0 || STRCMP(dit-> d_name,..)== 0)
继续; STAT(currentPath,&安培; statbuf); / *如果(dit-> d_type == 8安培;&放大器;的argv [1] == NULL){* /
如果(S_ISREG(statbuf.st_mode)及和放大器;的argv [1] == NULL){
对于(i = 0; I<深度;我++)
的printf();
的printf(%S(%d字节)\\ n,dit-> d_name,(INT)statbuf.st_size);
} / *如果(dit-> d_type == 8安培;&安培;!ARGV [1] = NULL){* /
如果(S_ISREG(statbuf.st_mode)及&放大器;!的argv [1] = NULL){
如果(STRCMP(dit-> d_name,ARGV [1])== 0){
对于(i = 0; I<深度;我++)
的printf();
的printf(%S(%d字节)\\ n,dit-> d_name,(INT)statbuf.st_size);
}
} / *如果(dit-> d_type == 4)* /
如果(S_ISDIR(statbuf.st_mode))
dircheck(DIP,DIT,statbuf,currentPath,深度的argv); }
}无效dircheck(DIR *浸,结构的dirent * DIT,结构统计statbuf,
焦炭currentPath [FILENAME_MAX],INT深度的char * ARGV []){
INT I = 0; 的strcat(currentPath,/);
strcat的(currentPath,dit-> d_name); / *如果在同一水平的路径有两个目录:
建错误的,需要被校正* /
如果((CHDIR(currentPath))== -1){
CHDIR();
GETCWD(currentPath,FILENAME_MAX);
的strcat(currentPath,/);
strcat的(currentPath,dit-> d_name); 对于(i = 0; I<深度;我++)
的printf();
的printf(%S(子目录)\\ n,dit-> d_name);
深入++;
助手(DIP,DIT,statbuf,currentPath,深度的argv);
} 其他{
对于(i = 0; I<深度;我++)
的printf();
的printf(%S(子目录)\\ n,dit-> d_name);
CHDIR(currentPath);
深入++;
助手(DIP,DIT,statbuf,currentPath,深度的argv);
}}
您正在使用 S_ISREG()
和 S_ISDIR()
正确,你只是用他们在错误的事情。
在你的,而((DIT = READDIR(DIP))!= NULL)的
,你再打电话
环主与stat
在 currentPath
一遍又一遍不改变 currentPath
:
如果(STAT(currentPath,&安培; statbuf)== -1){
PERROR(STAT);
返回错误号;
}
你不是应该附加一个斜线和 dit-> d_name
到 currentPath
来获得完整路径为要统计
的文件?依我看到其他统计
还需要调用。
This is a C program I wrote to recursively navigate and output directories and regular files. It compiles and runs fine on my Linux machine. But on Solaris, the dit->d_type == 8
check and the other similar ones don't work because there is no d_type
field. An answer I've read to this problem is to use the S_ISREG()
and S_ISDIR()
macros, but they don't work at all the way I have them in my code currently. I commented out the lines that work on my Linux machine.
#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);
}
}
You're using S_ISREG()
and S_ISDIR()
correctly, you're just using them on the wrong thing.
In your while((dit = readdir(dip)) != NULL)
loop in main
, you're calling stat
on currentPath
over and over again without changing currentPath
:
if(stat(currentPath, &statbuf) == -1) {
perror("stat");
return errno;
}
Shouldn't you be appending a slash and dit->d_name
to currentPath
to get the full path to the file that you want to stat
? Methinks that similar changes to your other stat
calls are also needed.
这篇关于如何使用S_ISREG()和S_ISDIR()POSIX宏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!