Проблема с каталогами в C - PullRequest
1 голос
/ 03 апреля 2011

Я делаю программу для Linux на C, которая получает каталог в качестве аргумента, а затем для каждого файла в этом каталоге и каждого из его подкаталогов вызывает программу с именем 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, а затем куча сообщений об ошибках разветвления, хотя я просто вызывал это для каталога сфайл и подкаталог.Это принесло мне 2 вопроса: а) Как цикл делал так много итераций?б) Что не так с exec, увидев, как monfile собран и находится в той же папке, что и mondir?

Итак, я решил выяснить, на какой каталог смотрела программа, добавив

printf("%s\n", dentry->d_name);

в начале цикла, и он каким-то образом сканировал каждый каталог, хотя он назывался так: mondir Subfolder1 ... (другие аргументы), являющийся Subfolder1 в том же каталоге, что и mondir.Что я здесь делаю не так, как с проблемой каталога, так и с проблемой exec?

Ответы [ 3 ]

1 голос
/ 03 апреля 2011

readdir вернет "." и "..", поэтому ваш код будет проходить по дереву каталогов, а также повторять каждый каталог навсегда - fork / exec бомбардировав вашу машину.

Кроме того, как уже упоминалось, find -exec может показаться разумной альтернативой?

1 голос
/ 03 апреля 2011

Ваш код плохо обрабатывает подкаталоги. Вы прекращаете обработку текущего каталога (но теряете указатель DIR в процессе, поскольку вы не делаете closedir() для старого, прежде чем перезаписывать новым), а затем chdir() в новый каталог.

Вы также не избегаете записей каталога . и ..; вы, вероятно, не хотите обрабатывать их, но readdir() будет верно возвращать их в качестве первых двух записей в каждом каталоге. Это объясняет поток процессов.

Вы должны найти функцию POSIX nftw() и использовать ее - или не пытаться обрабатывать каталоги до тех пор, пока ваш код не заработает.

0 голосов
/ 03 апреля 2011

Вы ошибаетесь из-за очень распространенной ошибки: имена, возвращаемые readdir(), не содержат префикс имени исходного каталога, поэтому вы должны поместить его туда самостоятельно.

...