我正在用C语言编写一个Linux程序,它接收一个目录作为参数,然后对于该目录中的每个文件及其每个子目录,调用一个名为monfile的程序。这是代码:
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <fcntl.h>
#define DIR_ARG 1
#define DUR_ARG 2
#define SEC_ARG 3
#define LOG_ARG 4
#define OP1_ARG 5
#define OP2_ARG 6
int main(int argc, char** argv)
{
// Teste aos argumentos
if (argc < 5) {
printf("Erro! Argumentos insuficientes!\n");
return -1;
}
// Declaração de variáveis
DIR *dir;
struct dirent *dentry;
struct stat stat_entry;
int fork_result;
// Testa se o directório passado como argumento é válido
if ((dir = opendir( argv[DIR_ARG])) == NULL)
{
perror(argv[DIR_ARG]);
exit(2);
}
chdir(argv[DIR_ARG]);
// Ciclo de propagação
while ((dentry = readdir(dir)) != NULL) {
stat(dentry->d_name, &stat_entry);
// Se for ficheiro regular
if (S_ISREG(stat_entry.st_mode)) {
fork_result = fork();
if (fork_result == -1) {
printf("file fork error!\n");
exit(1);
}
if (fork_result == 0) {
execlp("monfile", "monfile", argv[SEC_ARG], dentry->d_name, filedes, (char *)NULL);
printf("Erro no exec!\n");
exit(1);
}
}
// Se for directório vai criar um novo processo e passar dir para esse directório
if (S_ISDIR (stat_entry.st_mode)) {
fork_result = fork();
if (fork_result == -1) {
printf ("dir fork error!\n");
exit(1);
}
if (fork_result == 0) {
chdir(dentry->d_name);
dir = opendir (dentry->d_name);
}
}
}
return 0;
}
现在,结果是...大量的exec错误消息然后是一堆fork错误消息,即使我只是为具有文件和子目录的目录调用它。这给我带来了两个问题: a)cicle如何进行如此多的迭代? b)exec有什么问题,看看monfile是如何构建的,和mondir在同一个文件夹中?
所以,我决定通过添加
找出程序正在查看的目录printf("%s\n", dentry->d_name);
在cicle的开始,它以某种方式扫描每个目录,即使它被调用如下:mondir Subfolder1 ...(其他args),与mondir在同一目录中的Subfolder1。我在这里做错了什么,包括目录问题和exec问题?
答案 0 :(得分:1)
readdir将返回“。”和“..”所以你的代码将走向目录树,并永远重复每个目录 - fork / exec轰炸你的机器。
另外,如上所述,find -exec
似乎是一个合理的选择?
答案 1 :(得分:1)
您的代码不能很好地处理子目录。您停止处理当前目录(但是在进程中泄漏DIR指针,因为您在覆盖旧目录之前没有closedir()
,然后chdir()
进入新目录。
您也不会避免目录条目.
和..
;您可能不想处理它们,但readdir()
将忠实地将它们作为每个目录中的前两个条目返回。这说明了大量的流程。
你应该查看POSIX函数nftw()
并使用它 - 或者在代码运行之前不要尝试处理目录。
答案 2 :(得分:0)
你正在绊倒一个非常常见的错误:readdir()
返回的名字没有前面的源目录名,所以你必须自己把它放在那里。