2012-02-27 7 views
3

의 동작을 모방 한 프로그램을 작성하여 디렉토리 트리를 탐색하고 발견 한 파일에 lstat을 호출하여 유형을 판별합니다. 실제 find은 사용자가 해당 디렉토리에서 R 또는 X 액세스 권한이없는 파일은 무시합니다. 이 동작을 복제 할 수 없습니다. 내 코드는 계속 진행하고 lstat 호출을 수행하고이를 수행하는 코드가 access()을 검사하는 블록 안에있는 경우에도 내가 막으려 고하는 잘못된 탐색 오류가 발생합니다.리눅스에서 C : 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

당신은 아마도 오프 헌트 코멘트라고 생각했을 것입니다 만, 각'perror '이후에'errno = 0'을 설정하면, 특히'readdir'에 대한 에러 체크의 경우에 약간의 차이가 있음을 발견했습니다. 왜냐하면'readdir'는'NULL'을 리턴하기 때문에 디렉토리 *와 *의 끝에 오류가 생겼다. 그래서 내 코드는 계속 진행하기 전에'errno == 0' 여부를 확인하고 있었다. 그러나 나는 또한'접근'에 대한 당신의 경고를 가슴에 품을 것입니다 - 고마워요! –

+1

@SabrinaStar :'readdir()'호출 전에 즉시'errno = 0;'을 설정해야합니다. 여기서 중요한 점은 실패한 호출은'errno'를 설정하지만 성공한 호출은'errno'를 변경하지 않는 것입니다. – caf