我正在寻找C程序中符号链接中的循环:
$ ln -s self self
$ ln -s a b
$ ln -s b a
这是我到目前为止所得到的:
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
int
main(int argc, char *argv[])
{
struct stat buffer;
int status;
if (argc != 2) {
fprintf(stderr, "error: file name required\n");
return 0;
}
errno = 0;
status = lstat(argv[1], &buffer);
if (errno == ELOOP) {
fprintf(stderr, "loop found");
}
return 1;
}
我正在运行我的程序:
$ findloops self
$ findloops a
知道我做错了吗?
这是 NOT 作业。
This是我从中得到这个想法的地方。
答案 0 :(得分:1)
我会看一下buffer returned。根据lstat的文档,缓冲区包含两个相关的项目:
如果您创建一个列表,其中包含每个元素的这两个项目+链接所在的目录作为先前访问过的元素,您可以检测到循环。当你离开创建它们的目录时,也不要忘记将它们弹出。
我不相信ELOOP是你认为的价值。根据{{3}},它标识了类路径中容忍的最大链接,但它不会告诉您首先循环哪个链接。
页面上的文档声称:“ELOOP:在翻译路径名时遇到了太多的符号链接。”
答案 1 :(得分:1)
问题在于'lstat()
'查看符号链接及其属性,并且符号链接实际存在。
如果用“stat()
”替换呼叫,则会出现ELOOP错误。这会尝试在符号链接的远端获取信息,并且由于ELOOP条件而无法找到该信息。
在验证errno
表示失败后,您应该只测试status
。使用真正的系统调用,在调用成功时不太可能设置errno,但是使用库函数,即使调用成功,也可以找到errno。例如,对于某些标准I / O库实现,即使在成功调用函数之后,您也可以拥有errno == ENOTTY
;代码检查文件描述符是否代表终端,并且errno设置为表示它不是,但由于函数成功,检查errno
是不合法的。
答案 2 :(得分:0)
ELOOP并不一定意味着有一个循环。它也可能意味着从源到目标的符号链接太多,如
a - &gt; b - &gt; c - &gt; d - &gt; e ... - &gt; ž
这样做的时间足够多,操作系统内核(特别是Linux上的某些情况)会放弃尝试跟踪链接,即使它们都是有效且非循环的。
您可能也对man 2 readlink感兴趣。
答案 3 :(得分:0)
在玩了一些代码之后,看起来你已经找到了lstat(2)的功能或错误。根据lstat上的手册页,也就是stat和fstat,stat和lstat之间的区别是:
stat()stats指向的文件 路径和填充buf。
lstat()与stat()相同,除了 如果路径是符号链接,那么 链接本身是统计的,而不是 它引用的文件
我接受了你的节目并玩了一下。我使用lstat,stat和fopen来检查链接。代码如下。底线是stat和fopen都正确检测到链接,而lstat失败。我对此没有任何解释。
下面的程序在创建为'ln -s bar bar'的文件栏上执行,给出了以下输出:
./foo ./bar
Errno as returned from lstat = 0
Errno as returned from stat = 92
loop found
Errno as returned from fopen = 92
loop found
代码:
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
int
main(int argc, char *argv[])
{
struct stat buffer;
int status;
int savedErrno1;
int savedErrno2;
int savedErrno3;
FILE *theFile;
if (argc != 2) {
printf("error: file name required\n");
return 0;
}
errno = 0;
status = lstat(argv[1], &buffer);
savedErrno1 = errno;
printf("Errno as returned from lstat = %d\n", savedErrno1);
if (savedErrno1 == ELOOP) {
printf("loop found\n");
}
errno = 0;
status = stat(argv[1], &buffer);
savedErrno2 = errno;
printf("Errno as returned from stat = %d\n", savedErrno2);
if (savedErrno2 == ELOOP) {
printf("loop found\n");
}
errno = 0;
theFile = fopen(argv[1], "w");
savedErrno3 = errno;
printf("Errno as returned from fopen = %d\n", savedErrno3);
if (savedErrno3 == ELOOP) {
printf("loop found\n");
}
return 1;
}