如何在C(macOS)中检查文件夹是否实际上是一个别名?

huangapple go评论68阅读模式
英文:

How to check if a folder is actually an alias in C (macOS)?

问题

我正在编写一个简单的递归程序,用于在 macOS 上的特定目录树中查找特定文件。问题是,如果它找到了一个指向位于当前目录上同一分支上的目录的别名,它就会开始无限循环,并在一段时间后崩溃,出现分段错误(似乎仅在递归约 252 层左右时出现,这对我来说似乎是一个很低的数字)。我尝试修改我的代码,不导航符号链接文件,但它仍然导航到这些别名。

这是一个示例目录结构(每行左边是某个文件夹的名称,右边是它的内容):

folder1: folder2

folder2: folder1(alias)

以下是我编写的一些代码片段,已更新为完整(没有释放和错误检查):

char *name = //目标文件名
int myfind(){
    DIR *curr_dir = opendir(".");
    struct dirent *next_entry;
    struct stat info;
    char *entry_name;
    char *path;
    while((next_entry = readdir(curr_dir)) != NULL){
        entry_name = next_entry->d_name;
        //忽略 . 和 ..
        if(strcmp(entry_name,".") == 0 || strcmp(entry_name,"..") == 0)
            continue;
        stat(entry_name, &info);
        if(strncmp(name, entry_name, 255) == 0){
            path = realpath(entry_name, NULL);
            //打印找到的文件信息
        }
        if(S_ISDIR(info.st_mode) && !S_ISLNK(info.st_mode)){ 
            char *prev_path = getwd(NULL);
            chdir(entry_name);
            myfind();
            chdir(prev_path);
        }
    }
}

请注意,这段代码是用 C 语言编写的,用于在给定目录中递归查找文件,并且存在问题可能导致无限循环。如果需要进一步的帮助或修复,请提供更多详细信息。

英文:

I'm writing a simple recursive program that looks for specific files in a certain directory tree on macOS.
Problem is, if it finds an alias to a folder that is above the current directory on the same branch of the tree it starts to loop infinitely and crashes after a while with segmentation fault (after only 252 levels or so of recursion it seems, which appears to be a low number to me by the way). I tried to modify my code not to navigate files which are symbolic links, but it still navigates those aliases.

Here's an example structure of directories(every line has at the left the name of some folder, at the right its contents):

folder1: folder2

folder2: folder1(alias)

These are some lines taken out from the code I wrote, updated to be complete(without frees and error checks):

char *name = //target file name
int myfind(){
	DIR *curr_dir = opendir(".");
	struct dirent *next_entry;
	struct stat info;
	char *entry_name;
	char *path;
	while((next_entry = readdir(curr_dir)) != NULL){
		entry_name = next_entry->d_name;
		//ignore . and ..
		if(strcmp(entry_name,".") == 0 || strcmp(entry_name,"..") == 0)
			continue;
		stat(entry_name, &info);
		if(strncmp(name, entry_name, 255) == 0){
			path = realpath(entry_name, NULL);
			//print info about file found
		}
		if(S_ISDIR(info.st_mode) && !S_ISLNK(info.st_mode)){ 
			char *prev_path = getwd(NULL);
			chdir(entry_name);
			myfind();
			chdir(prev_path);
		}
	}
}

答案1

得分: 4

I tried to modify my code not to navigate files which are symbolic links, but it still navigates those aliases

尝试修改我的代码以不导航符号链接文件,但仍然导航到这些别名。

stat() will never return data such that S_ISLNK(info.st_mode) is true (except see below). Per the POSIX stat() documentation:

stat() 永远不会返回数据,使得 S_ISLNK(info.st_mode) 为真(除非参见下文)。根据POSIX stat() 文档

If the named file is a symbolic link, the stat() function shall continue pathname resolution using the contents of the symbolic link, and shall return information pertaining to the resulting file if the file exists.

如果命名的文件是符号链接,则 stat() 函数将继续使用符号链接的内容进行路径名解析,并且如果文件存在,则将返回与结果文件相关的信息。

and

The lstat()function shall be equivalent to stat(), except when path refers to a symbolic link. In that caselstat()` shall return information about the link, while stat() shall return information about the file the link references.

lstat() 函数与 stat() 等效,除非路径引用符号链接。在这种情况下,lstat() 将返回关于链接的信息,而 stat() 将返回关于链接引用的文件的信息。

You need to replace

stat(entry_name, &info);
if(S_ISDIR(info.st_mode) && !S_ISLNK(info.st_mode)){ 
  //navigate to next_entry
}

with

int rc = lstat(entry_name, &info);
if((rc==0) && S_ISDIR(info.st_mode) && !S_ISLNK(info.st_mode)){ 
  //navigate to next_entry
}

Note also the return value from [l]stat() needs to be checked. The contents of the info struct will not mean anything if the [l]stat() call fails, so the checks using ISDIR() and ISLNK() could return any value.

还需要注意检查 [l]stat() 的返回值。如果 [l]stat() 调用失败,info 结构的内容将无意义,因此使用 ISDIR()ISLNK() 进行的检查可以返回任何值。

英文:

> I tried to modify my code not to navigate files which are symbolic links, but it still navigates those aliases

stat() will never return data such that S_ISLNK(info.st_mode) is true (except see below). Per the POSIX stat() documentation:

> If the named file is a symbolic link, the stat() function shall continue pathname resolution using the contents of the symbolic link, and shall return information pertaining to the resulting file if the file exists.

and

> The lstat() function shall be equivalent to stat(), except when path refers to a symbolic link. In that case lstat() shall return information about the link, while stat() shall return information about the file the link references.

You need to replace

stat(entry_name, &info);
if(S_ISDIR(info.st_mode) && !S_ISLNK(info.st_mode)){ 
  //navigate to next_entry
}

with

int rc = lstat(entry_name, &info);
if((rc==0) && S_ISDIR(info.st_mode) && !S_ISLNK(info.st_mode)){ 
  //navigate to next_entry
}

Note also the return value from [l]stat() needs to be checked. The contents of the info struct will not mean anything if the [l]stat() call fails, so the checks using ISDIR() and ISLNK() could return any value.

huangapple
  • 本文由 发表于 2023年5月25日 18:12:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/76331158.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定