2011-01-19 11 views
2

私はプログラムの一部がすべてのディレクトリ(特に/から始まっている)をリストしていますが、/ proc/selfは無限に再帰的です(proc /タスク/ 4300/fd/3/proc/self /タスク/ 4300/fd/3/proc/self/task/4300/fd/3/proc/...など)。それに対処する良い方法は何ですか?linuxにディレクトリを列挙しているときに無限再帰

EDIT:プログラムはC言語で書かれていると私は(opendir関数を使用)、readdir関数()

+0

あなたはすべてのディレクトリinodeを追跡し、横断ないと考えているようにそれを呼び出しますあなたがすでにそれを見たことがあれば? – Gabe

+0

はい、私は、より洗練された解決策があり、あまりにも多くのメモリを消費しないと考えていました。 – chris

+4

あなたが見たすべてのinodeを追跡する必要はなく、同じパスの以前の要素のiノード番号だけを追跡する必要はありません。 –

答えて

6

S_ISLNK macro to test the st_mode fieldは、lstatの呼び出しによって返されます。ファイルがシンボリックリンクの場合は、それに従わないでください。

[[email protected]:~]:./list | grep link 
/proc/mounts is a symbolic link 
/proc/self is a symbolic link 

例コード

#include <stdio.h>  // For perror 
#include <stdlib.h> 
#include <sys/types.h> // For stat, opendir, readdir 
#include <sys/stat.h> // For stat 
#include <unistd.h> // For stat 
#include <dirent.h> // For opendir, readdir 

const char *prefix = "/proc"; 

int main(void) 
{ 
    DIR *dir; 
    struct dirent *entry; 
    int result; 
    struct stat status; 
    char path[PATH_MAX]; 

    dir = opendir(prefix); 
    if (!dir) 
    { 
     perror("opendir"); 
     exit(1); 
    } 

    entry = readdir(dir); 
    while (entry) 
    { 
     result = snprintf(path, sizeof(path), "%s", prefix); 
     snprintf(&path[result], sizeof(path) - result, "/%s", entry->d_name); 
     printf("%s", path); 

     result = lstat(path, &status); 
     if (-1 == result) 
     { 
      printf("\n"); 
      perror("stat"); 
      exit(2); 
     } 

     if (S_ISLNK(status.st_mode)) 
     { 
      printf("%s", " is a symbolic link"); 
     } 

     printf("\n"); 

     entry = readdir(dir); 
    } 

    return(0); 
} 
+0

パス '/ proc/$ pid/task/$ pid'にはシンボリックリンクがない。 –

+1

ローカルシステムでは、/ proc/selfはシンボリックリンクです。これがOPの例です。 – David1235

+0

私はすでにS_ISLINKを試しましたが、うまくいきませんでした。/proc/selfはディレクトリです(S_ISDIR!= 0) – chris

1

path_resolution(7)から:

 
Length limit 
    There is a maximum length for pathnames. If the pathname (or some intermediate pathname obtained while resolving symbolic links) is too long, an ENAMETOOLONG error 
    is returned ("File name too long"). 

私はあなたが同様の行動を採用すべきだと思う:あまりにをチェック長いですパス名。

0

私は便利な* nix端末を持っていませんが、いつでもls.cのソースを見て、それがどのように完了したかを見てください。

gnuコアの一部としてのソースは、hereで見つけることができます。

私は数年前に学校でlsクローンを作成しました。私は、ulidtkoが言及したように、パス名のサイズを見て周りにいると思います。

1
#include <stdio.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <unistd.h> 
#include <dirent.h> 
#include <sys/param.h> 

/* Short & sweet recursive directory scan, finds regular files only. 
    Good starting point, should work on Linux OS. 
    Pass the root path, and returns number of dirs and number of files 
    found. 
*/ 
char *tree_scan(const char *path, int *ndirs, int *nfiles){ 

    DIR    *dir; 
    struct dirent *entry; 
    char   spath[MAXPATHLEN] = ""; 

    if(!(dir = opendir(path))){ perror("opendir"); exit(1);} 

    for(entry = readdir(dir); entry; entry = readdir(dir)){ 

     sprintf(spath, "%s/%s", path, entry->d_name); 
     if(entry->d_type == DT_REG){ (*nfiles)++; printf("%s\n", spath);} 
     if(entry->d_type == DT_DIR && 
      (strcmp(".", entry->d_name)) && 
      (strcmp("..", entry->d_name))){ 
      (*ndirs)++; tree_scan(spath, ndirs, nfiles); 
     } 
    } 

closedir(dir); 

return(0); 

}

/*そう*/

int i = 0, l = 0; 
tree_scan("/path", &i, &l); 
printf("Scanned %d directories, %d files.\n", i, l); 
関連する問題