Как правильно использовать функцию stat() для проверки, является ли DIRENT каталогом или файлом?

У меня возникли проблемы со строкой 'if(S_IFDIR(stbuf.st_mode))'. Это правильный способ проверить каталог для рекурсии? Функция на данный момент, кажется, делает это правильно для 1 или 2 циклов, а затем терпит неудачу и ошибки сегментации.

Я пробовал следующее и, возможно, больше в качестве условия.

S_ISDIR(st_mode)
((st_mode & ST_IFMT) == S_IFDIR)
S_IFDIR(stbuf.st_mode)

Я включил всю функцию, потому что я обеспокоен тем, что проблема может быть в другом месте.

void getFolderContents(char *source, int temp){
    struct stat stbuf;
    int isDir;
    dirPnt = opendir(source);
    if(dirPnt != NULL){
        while(entry = readdir(dirPnt)){
            char *c = entry->d_name;
            if(strcmp(entry->d_name, cwd) == 0 || strcmp(entry->d_name, parent) == 0){
            }
            else{
                stat(entry->d_name, &stbuf);
                printf("%i %i ", S_IFMT, stbuf.st_mode);
                if(S_IFDIR(stbuf.st_mode)){            //Test DIR or file
                printf("DIR: %s\n", entry->d_name);
                getFolderContents(entry->d_name, 0);
            }
            printf("FILE: %s\n", entry->d_name);
        }
    }
    closedir(dirPnt);
}

person cheesysam    schedule 09.10.2009    source источник
comment
Для правильного ответа посмотрите здесь.   -  person te7    schedule 26.07.2016


Ответы (2)


Да, это правильно. Но так как вы никогда не переходите в каталог, вы его не найдете.

Рассмотрим следующую иерархию каталогов:

 a
 |
 +- b
 |  |
 |  +- c
 ...

Ваш код просканирует свой текущий каталог и найдет «a». Он определит, что это каталог, рекурсивно вызовет сам себя и откроет "a" для чтения. Это работает. Это сканирование найдет каталог с именем «b», но попытка открыть его, используя только имя записи, потерпит неудачу, поскольку путь теперь «a/b».

Я рекомендую перейти в каталог (с chdir()) перед его открытием. Это означает, что вы можете просто opendir("."). Сохраните старый путь и снова chdir(), когда рекурсия этого уровня будет выполнена (не раньше, чем сделать рекурсивный вызов, чтобы углубиться).

person unwind    schedule 09.10.2009
comment
хм, это не объясняет SEGFAULT? - person Bahbar; 09.10.2009
comment
Когда структура записи проверяется и обнаруживается, что это каталог, я снова рекурсивно вызываю функцию, которая затем открывает этот путь к каталогу. - person cheesysam; 09.10.2009
comment
Вы имеете в виду, что мне нужно указать полный относительный путь к каталогу, с которого я начал? - person cheesysam; 09.10.2009
comment
Ваш процесс имеет ровно один текущий каталог. Все неабсолютные файловые операции выполняются с использованием этого в качестве базы. Если вы делаете opendir() для a, а затем opendir для b, ничто не делает это означающим a/b. Вам нужно вызвать chdir(), чтобы сделать отсканированный каталог текущим, затем opendir(.) и recurse. - person unwind; 09.10.2009

Где определяется вход? это локальная переменная? Я не понимаю, почему это будет segfault, но, возможно, вам следует сделать его локальной переменной. Один из примеров, где он вас укусит, здесь:

                    if(S_IFDIR(stbuf.st_mode)){            //Test DIR or file
                            printf("DIR: %s\n", entry->d_name);
                            getFolderContents(entry->d_name, 0);
                    }
                    printf("FILE: %s\n", entry->d_name);

printf напечатает неправильное имя, поэтому вам, вероятно, следует добавить здесь else.

То же самое и с dirpnt. Когда вы выходите из getFolderContents внутри цикла while, вы в конечном итоге вызываете readdir для закрытой точки каталога, что должно вывести вас из цикла.

Но, как заявил Бахбар: вы не можете рекурсивно хранить временную переменную в глобальной переменной

person shodanex    schedule 09.10.2009
comment
struct dirent *entry; Это определено непосредственно перед main() - person cheesysam; 09.10.2009
comment
вы не можете рекурсивно хранить временные значения в глобальном массиве. Поместите как entry, так и dirPnt в локальные переменные. - person Bahbar; 09.10.2009
comment
Спасибо, Бахбар, я думаю, что это меня сильно сдерживало. Теперь он работает намного лучше, но рекурсивно рекурсирует только на одну папку. - person cheesysam; 09.10.2009