我有一个列出目录中所有文件的程序。如果文件被断开链接,我想跳过该文件并继续扫描文件中的其他文件。如果有人能指出我错在哪里,我将非常感激。以下是我的代码的一部分
d = opendir(".");
while((dir = readdir(d)) != NULL) {
char buff[256];
int target = readlink (dir->d_name, buff, sizeof(buff));
if (target == -1)
{
printf("i found broken link so continuing to next file..\n");
continue;
}
}
我遇到的问题是,当我只有一个断开链接时打印以下
i found broken link so continuing to next file
i found broken link so continuing to next file
i found broken link so continuing to next file
继续直到最后一个文件。
答案 0 :(得分:5)
您的问题应该有一些MCVE。另见inode(7)& symlink(7)。阅读Advanced Linux Programming或更新的内容。
考虑使用nftw(3)或fts(3)(如果需要递归扫描子目录)或至少使用文件路径执行stat(2)(因为您正在扫描当前目录,不需要构建该文件路径)。请务必跳过.
和..
的条目;所以也许尝试
d = opendir(".");
while((dir = readdir(d)) != NULL) {
struct stat mystat;
if (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, "..")) continue;
memset (&mystat, 0, sizeof(mystat));
if (stat(dir->d_name, &mystat) || S_ISLNK(mystat.st_mode))
continue;
/// etc...
}
您可能希望处理许多情况。另见errno(3)。对自己的符号链接怎么样?怎么样unix(7)套接字? fifo(7) - S?权限?
(我们没有时间和空间来解释所有细节;你需要阅读很多)
答案 1 :(得分:2)
通常,如果你有
d = opendir(dirname);
while((dir = readdir(d)) != NULL) {
some_operation(dir->d_name);
}
some_operation
每个 d_name
都会失败,因为您应该传递给some_operation
的路径是${dirname}/${dir->d_name}
,而不仅仅是{{1} }}
但是,您的程序通过硬连线将特殊目录dir->d_name
传递给.
;当你这样做时, 可以安全地仅将opendir
传递给dir->d_name
,因为some_operation
始终是当前的工作目录。问题是.
在应用于损坏的符号链接时不会失败,但 在应用于不是符号链接的目录条目时失败
readlink
和dir->d_name
,就可以更轻松地解决这个问题,例如:
strerror(errno)
如果你这样做了,你就会得到这样的输出:
d = opendir(".");
while ((dir = readdir(d)) != 0) {
char buff[256];
if (readlink(dir->d_name, buff, sizeof buff) {
printf("%s: readlink failed: %s\n", dir->d_name, strerror(errno));
} else {
printf("%s -> %s\n", dir->d_name, buff);
}
}
然后您可能会想到查看.gnome2: readlink failed: Invalid argument
.python_history: readlink failed: Invalid argument
test.s: readlink failed: Invalid argument
bin -> .local/bin
[etc]
联机帮助页并发现它在应用于不是符号链接的内容时会返回readlink
。
检测损坏的符号链接的正确方法是观察EINVAL
成功但lstat
失败stat
:
ENOENT
如果您不需要struct stat lst, st;
if (lstat(dir->d_name, &lst)) {
/* some other kind of problem */
} else if (!S_ISLNK(lst.st_mode)) {
/* not a symlink at all */
} else if (stat(dir->d_name, &st)) {
if (errno == ENOENT) {
/* broken symlink */
} else {
/* some other kind of problem */
}
} else {
/* valid symlink, `lst` tells you about the link,
`st` tells you about what it points to */
}
中的任何其他信息,并且您的文件系统支持lst
,则可以跳过d_type
来电:
lstat
但是,在if (dir->d_type == DT_LNK) {
struct stat st;
if (stat(dir->d_name, &st)) {
if (errno == ENOENT) {
/* broken symlink */
}
}
}
案例中,不要忽视与lstat
和stat
完成整个舞蹈,否则当你试图跑步时,你会感到难过您的程序在没有报告d_type信息的文件系统上。