Reputation: 41
I'm making a program for Linux in C that recieves a directory as an argument, then for each file in that directory and each of it's sub-directories, calls a program called monfile. Here's the code:
#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;
}
Now, the result of this was...a ton of exec error messages and then a bunch of fork error messages, even though I was just calling this for a directory with a file and a sub-directory. This brought me 2 questions: a) How was the cicle doing so many iterations? b) What was wrong with the exec, seeing how monfile is built and in the same folder as mondir?
So, I decided to figure out what directory the program was looking at by adding
printf("%s\n", dentry->d_name);
at the beggining of the cicle, and it was somehow scanning every directory, even though it was called like this: mondir Subfolder1 ...(other args), being Subfolder1 in the same directory as mondir. What am I doing wrong here, both with the directory problem and the exec problem?
Upvotes: 1
Views: 687
Reputation: 754890
Your code is not handling sub-directories very well. You stop processing the current directory (but leak a DIR pointer in the process since you do not do closedir()
on the old one before overwriting with the new one) and then chdir()
into the new directory.
You also don't avoid directory entries .
and ..
; you probably do not want to process them, but readdir()
will faithfully return them as the first two entries in each directory. This accounts for the flood of processes.
You should look up the POSIX function nftw()
and use that - or not try handling directories until after your code is working.
Upvotes: 1
Reputation: 53320
readdir will return "." and ".." so you code will walk up the directory tree, as well as repeating every directory forever - fork/exec bombing your machine.
Also, as mentioned, find -exec
would seem a reasonable alternative?
Upvotes: 1
Reputation: 61459
You're tripping over a very common mistake: the names returned by readdir()
don't have the source directory name prepended, so you have to put it there yourself.
Upvotes: 0