我正在编写一个程序来模仿find
一些行为,这些行为lstat
目录树,并对它在那里find的文件调用lstat
来确定它们的types。 真正的find
将忽略用户在该目录中没有R或X访问权限的文件。 我似乎无法复制这种行为; 我的代码将继续进行,并进行lstat
调用,并得到一个非法的查找错误(这就是我试图阻止),即使执行此代码是在一个检查access()
的块内。
我的第一个想法是,也许第二次access()
调用应该是在path上,而不是path/文件名,但似乎也没有工作(而且不是多余的呢?)
任何指导将不胜感激。
我的代码(为了简洁,我正在删除错误捕获和其他内容):
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; }
lstat()
不应该返回ESPIPE
(非法查找)。 你确定这是不是另一个系统调用返回,或者一个成功的lstat()
之后没有改变的errno
值? (换句话说,这个错误可能实际上在你的错误检查代码中,你已经被忽略了)。
也就是说,以这种方式使用access()
是没有意义的 – 它只是引入了竞争条件(因为文件权限可能会在access()
调用和opendir()
/ lstat()
调用之间改变)无所不能。 只需检查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; }
这通常是正确的模式 – 而不是检查操作是否可以工作,然后尝试操作,而是无条件地尝试操作,然后检查为什么失败。