在 Ubuntu(Linux)下,opendir() 对**符号链接(symbolic link)**的处理规则如下:
opendir() 的基本行为DIR *opendir(const char *name);
opendir() 会跟随符号链接name 是一个指向目录的符号链接,opendir() 会打开链接指向的真实目录name 是一个指向文件的符号链接,opendir() 会失败,返回 NULL,并设置 errno = ENOTDIRsymlink("/real/dir", "mylink");
DIR *d = opendir("mylink"); // 成功
/real/dirreaddir() 读到的是目标目录里的内容symlink("/etc/passwd", "filelink");
DIR *d = opendir("filelink"); // 失败
NULLerrno == ENOTDIRopendir() 不会把符号链接当成“目录对象”来打开
它只关心最终指向的是什么
readdir() 的关系readdir() 返回的结构体中:
struct dirent {
ino_t d_ino;
off_t d_off;
unsigned short d_rendtl;
unsigned char d_type;
char d_name[256];
};
d_type 可能是:
DT_LNK:符号链接本身DT_DIR:目录opendir() 该链接名 → 会跟随lstat()opendir() 没有不跟随符号链接的版本
替代方案:
open() + fdopendir() + O_NOFOLLOWint fd = open("mylink", O_RDONLY | O_NOFOLLOW | O_DIRECTORY);
if (fd == -1) {
// 如果是符号链接,open 会失败 (ELOOP)
}
DIR *d = fdopendir(fd);
Ubuntu 下
opendir()会跟随符号链接;指向目录则成功,指向文件则失败(ENOTDIR)。
如果你有具体代码场景(比如递归遍历目录、防止符号链接循环),我可以帮你写示例。