chdir과 stat간의 미묘한 문제점에 대해서

익명 사용자의 이미지

예전에 linux.co.kr에 올렸다가 답글이 안올라와서 이곳에
다시 올립니다.

이것이 진짜로 호환의 문제인지 저의 무지에서 오는 잘못된 인식인지 명확하지 않지만 몇자 적어보겠습니다. 간단히 다음과 같은 코드를 작성했습니다.

 struct stat s_Stat; 

 chdir("/usr/home/users/guest"); 

 if(stat(".bashrc", &s_Stat) == 0)fprintf(stdout, "OK\n"); 
 else perror("Directory test: "); 

근데 다음의 코드는 진짜로 문제가 없어보입니다.
근데 희한하게도 root계정으로 실행을 하였음에도 불구하고
간혹 이것은 Error를 나타냅니다.
즉, chdir은 되었음에도 불구하고
그곳에 있는 .bashrc라는 파일의 상태를 얻는것에 실패를 합니다.
항상 실패하는 것도 아니며 간혹 그런다는것도 희한합니다.
당연히 이 프로그램은 /usr/home/users/guest 에서 실행한것은 아니고 /root 에서 실행한 것입니다.

그래서 저는 다음과 같이 작성해봤습니다.

 struct stat s_Stat; 
 char *s_CurrentPath; 
 char s_TempPath[256]; 

 chdir("/usr/home/users/guest"); 

 s_CurruntPath = getcwd(NULL, 0); 

 sprintf(s_TempPath, "%s/%s", s_CurrentPath, ".bashrc"); 
 if(stat(&s_TempPath[0], &s_Stat) == 0)fprintf(stdout, "OK\n"); 
 else perror("Directory test: "); 

 free(s_CurrentPath); 

참 희한하죠? 이렇게 하면 100% 됩니다.
저는 이게 Linux syscall의 bug이거나 Cache의 버그라고 생각의 방향을
결정중인데 어떤지 모르겠군요.
어찌되었건 stat 함수에 절대경로를 취하면 잘 되지만 chdir로 디렉토리를 설정하고
하게 되면 stat에는 상대경로가 적용되지 않는다고 봐야 겠지요...
혹시 이 문제의 원인을 아신다면 리플 달아주세요.

참고로 커널은 2.4.18 정식(패치되지 않은) 커널입니다.

hunkim의 이미지

>간혹 이것은 Error를 나타냅니다.
다음중 어떤 에러가 발생하는지요?

 
       EBADF  filedes is bad.
       ENOENT A  component  of the path file_name does not exist,
              or the path is an empty string.

       ENOTDIR
              A component of the path is not a directory.

       ELOOP  Too many symbolic links encountered while  travers?
              ing the path.

       EFAULT Bad address.

       EACCES Permission denied.

       ENOMEM Out of memory (i.e. kernel memory).

       ENAMETOOLONG
              File name too long.
Necromancer의 이미지

 struct stat s_Stat; 

 chdir("/usr/home/users/guest"); 

 if(stat(".bashrc", &s_Stat) == 0)fprintf(stdout, "OK\n"); 
 else perror("Directory test: "); 

이거는 경로지정없이 .bashrc 파일에 대고 stat()하는거고요.
이것은 상대경로이기 때문에 문제의 소지가 좀 있고요.
(chdir()이 fail한다면.... 다 fail나지요)

 struct stat s_Stat; 
 char *s_CurrentPath; 
 char s_TempPath[256]; 

 chdir("/usr/home/users/guest"); 

 s_CurruntPath = getcwd(NULL, 0); 

 sprintf(s_TempPath, "%s/%s", s_CurrentPath, ".bashrc"); 
 if(stat(&s_TempPath[0], &s_Stat) == 0)fprintf(stdout, "OK\n"); 
 else perror("Directory test: "); 

 free(s_CurrentPath); 

이거는 /usr/home/users/guest/.bashrc 파일에다 하고요.(절대경로)

첫번째것이 안된다고 하는걸로 봐서는 상대경로 지정상의 문제일듯
싶네요. 첫번째것의 경우 chdir()이 왜 fail하는지 검사해보시는게 좋을 듯 합니다. 보니까 chdir()검사루틴이 안보이네요.

아니면 커널 버그일 수도 있고요...

Written By the Black Knight of Destruction

xfmulder의 이미지

errno 를 적어 주세요 쫌.

chdir() 실패 하는 이유는 아마도 퍼미션문제가 아닐런지...

또 stat(".bashrc" ) 말고 stat("./.bashrc") 로도 해보시고...

내 자식들도 나처럼 !!

익명 사용자의 이미지

음... 역시 chdir 쪽에서 에러를 리턴한 경우겠지요?

근데 이 코드를 호출하는 함수이전에 이미

그 경로가 디렉토리가 있는지 검사했었거든요.

그래서 chdir에 대한 에러검사를 누락시킨건데

거기서 오류가 있나봅니다.

chdir의 man page를 찾아보니 파일시스템에 따라서 다른 에러도 더 있을수

있다고 하는군요.......

답변 감사합니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.