Ubuntu рекурсивно перечисляет файлы, обнаруживая sym-ссылки

Я пытаюсь перечислить свою локальную файловую систему рекурсивно, используя dirent.h . Чтобы предотвратить sys/stat.h ссылками, я использую заголовок sys/stat.h Ниже вы можете найти мою программу SSCCE.

 /** * coding: utf-8 * * Copyright (C) 2013, Niklas Rosenstein * * listdir.c - List up directories and file-content recursively. */ #include  #include  #include  #include  #include  void list_dir(const char* directory_name) { DIR* directory_handle = opendir(directory_name); if (directory_handle == NULL) { fprintf(stderr, "Could not open directory %s.\n", directory_name); return; } char buffer[1024]; struct dirent* dentry; int directory_name_length = strlen(directory_name); memcpy(buffer, directory_name, directory_name_length); buffer[directory_name_length] = '/'; while ((dentry = readdir(directory_handle)) != NULL) { char* name = dentry->d_name; int length = strlen(name); // Skip the dotted elements. if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) continue; // Concatenate the directory name with the element name. memcpy(buffer + directory_name_length + 1, name, length); buffer[directory_name_length + 1 + length] = 0; printf("%s\n", buffer); // Proceed recursively if the element is a directory. struct stat s; if (stat(buffer, &s) != 0) { fprintf(stderr, "WARNING: stat() failed on %s\n", buffer); continue; } mode_t mode = s.st_mode; if (mode & S_IFDIR && !(mode & S_IFLNK)) { list_dir(buffer); } } closedir(directory_handle); } int main(int argc, char** argv) { if (argc != 2) { fprintf(stderr, "Expected exactly 2 arguments.\n"); return -1; } list_dir(argv[1]); return 0; } 

Я просто не могу заставить его работать, чтобы правильно распознавать символические ссылки. Когда это происходит через символическую ссылку, ссылаясь на ее родительский каталог, она продолжается и продолжается. Похоже, в моей системе есть несколько таких папок, например. /usr/bin/X11 :

 /usr/bin/X11/ X11/ -> . 

Эта строка не должна быть полностью правильной: if (mode & S_IFDIR && !(mode & S_IFLNK)) { . Является ли это проблемой для проблемы с функцией stat() или я пропущу что-то очевидное здесь?

Вот изображение моего терминала после вызова ./listdir /usr/bin/X11 , останавливая программу примерно через секунду, нажав ^C

введите описание изображения здесь

    Попробуйте lstat вместо stat : последний, когда делается по символической ссылке, возвращает информацию о своей цели (последняя, ​​которая не является символической ссылкой).

    S_IFDIR и S_IFLNK не должны использоваться так, как если бы они были эксклюзивными битовыми флагами. Для каталога используйте S_ISDIR(mode) ; для символической ссылки вам не понадобится тест: lstat не будет сообщать символическую ссылку как каталог, и этого достаточно, когда вы хотите только пропустить символические ссылки.