0

を使用してローカルファイルシステムを再帰的に一覧表示しようとしていますdirent.h。シンボリックリンクをたどらないようにするために、私はsys/stat.hヘッダーを使用しています。以下に私のSSCCEプログラムを見つけることができます。

/**
 * coding: utf-8
 *
 * Copyright (C) 2013, Niklas Rosenstein
 *
 * listdir.c - List up directories and file-content recursively.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>

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約1秒後に。を押してプログラムを停止し^Cます。

ここに画像の説明を入力してください

4

1 に答える 1

1

lstat代わりに試してみてくださいstat: 後者は、シンボリック リンクで行われると、そのターゲット (シンボリック リンクではない最後のもの) に関する情報を返します。

S_IFDIRS_IFLNK排他的なビットフラグであるかのように使用することは想定されていません。ディレクトリの場合はS_ISDIR(mode)、;を使用します。シンボリックリンクの場合、テストは必要ありません。lstatシンボリックリンクをディレクトリとして報告しません。シンボリックリンクをスキップすることだけが必要な場合は、それで十分です。

于 2013-01-22T00:17:28.123 に答える