2012-02-27 20 views
3

findの動作を模倣するプログラムを作成しており、ディレクトリツリーを参照して見つかったファイルでlstatを呼び出してタイプを判別します。実際のfindは、そのディレクトリにRまたはXアクセス権がないファイルは無視します。私はこの振る舞いを再現することはできません。私のコードは先に進んで、lstatを呼び出し、これを実行するコードがブロックaccess()をチェックしているにもかかわらず、不正なシークエラー(これは私が避けようとしているものです)を取得します。アクセス許可()にアクセス許可の問題などがありません

私が最初に考えたのは、おそらく二access()呼び出しは、パスではなく、パス/ファイル名にする必要がありますということでしたが、それはどちらか動作していないようでした(と冗長それがとにかくないですか?)

どれ指導大いに感謝します。

私のコード(私は簡潔にするためキャッチエラーや他のものを切り出しています):

void open_dir(char *dir, char *pattern, char type) 
    { 
     DIR *d; 
     struct dirent *de; 

     if (access(dir, (R_OK | X_OK)) == 0) 
     { 
      d = opendir(dir); 

      while((de = readdir(d))) 
       examine_de(de, dir, pattern, type); 

      closedir(d); 
     } 
    } 

    void examine_de(struct dirent *de, char *dir, char *pattern, char type) 
    { 
     char fn[ _POSIX_PATH_MAX ]; 
     strcpy(fn, dir); 
     strcat(fn, "/"); 
     strcat(fn, de->d_name); 

     if (access(fn, (R_OK | X_OK)) == 0) 
     { 
      struct stat buf; 
      lstat(fn, &buf); 
      //check pattern matches, etc., printf fn if appropriate 
      if ((S_ISDIR(buf.st_mode)) && 
       (strcmp(de->d_name, ".") != 0) && 
       (strcmp(de->d_name, "..") != 0)) 
       open_dir(fn, pattern, type); 
     } 
     return; 
    } 

答えて

4

lstat()べき決してリターンESPIPE(不正を求めて)。あなたはそれが返されている別のシステムコールではないと確信していますか、またはlstat()の成功後に値が変更されていないerrnoの値ですか? (言い換えれば、バグは実際にあなたが省略したエラーチェックコードの中にあるかもしれません)。

とにかくこのようにaccess()を使用してもポイントがない、と述べた - それだけで(ファイルのパーミッションがaccess()コールとopendir()/lstat()呼び出しの間で変化する可能性があるため)競合状態を紹介し、何を得ていませんが。これは、一般的に右のパターンである

void open_dir(char *dir, char *pattern, char type) 
{ 
    DIR *d; 
    struct dirent *de; 

    if (d = opendir(dir)) 
    { 
     while((de = readdir(d))) 
      examine_de(de, dir, pattern, type); 

     closedir(d); 
    } 
} 

void examine_de(struct dirent *de, char *dir, char *pattern, char type) 
{ 
    char fn[ _POSIX_PATH_MAX ]; 
    struct stat buf; 

    strcpy(fn, dir); 
    strcat(fn, "/"); 
    strcat(fn, de->d_name); 

    if (lstat(fn, &buf) == 0) 
    { 
     //check pattern matches, etc., printf fn if appropriate 
     if ((S_ISDIR(buf.st_mode)) && 
      (strcmp(de->d_name, ".") != 0) && 
      (strcmp(de->d_name, "..") != 0)) 
      open_dir(fn, pattern, type); 
    } 
    return; 
} 

を - むしろ操作がうまくいくかもしれないかどうかをチェックして、操作をしようとするよりも、代わりに無条件に操作を試してみて、なぜチェック:単純に代わりopendir()lstat()の戻り値をチェックそれは失敗した。

+0

「アクセス」が役に立たないレースを指摘するため+1。 –

+0

あなたはおそらくそれはお手上げのコメントだと思ったかもしれませんが、 'perr'の後に' errno = 0'を設定すると、 'readdir'のエラーチェックの場合に特に違いがあることがわかりました。エラーが発生した場合はディレクトリ*と*の末尾に移動する前に、私のコードが 'errno == 0 'をチェックしていました。しかし、私は確かに 'アクセス'についてのあなたの警告を心に持っていくでしょう - ありがとう! –

+1

@SabrinaStar: 'readdir()'呼び出しの直前に 'errno = 0;'を設定する必要があります。ここで重要な点は 'errno'を設定した呼び出しが成功しないことです。 – caf

関連する問題