【问题标题】:Cannot open directory a second time无法再次打开目录
【发布时间】:2017-05-31 09:02:32
【问题描述】:

我在第二次通话时打开同一目录时遇到问题。 例如我首先打开文件夹 1/文件夹 2;然后,如果我调用我在 folder1 上使用的函数,它说它无法打开它。我虽然会关闭路径中的所有目录并尝试这样做但没有结果。 这是我的代码

void scanDir(char *dir, int depth, char type, char *path, long gtsize, int attrib)
{
    DIR *dp;
    struct dirent *entry;
    struct stat statbuf;
    char newPath[strlen(path)+strlen(dir)];
    if((dp = opendir(dir)) == NULL) {
        fprintf(stderr,"Cannot open directory %s\n because of e", dir);
        exit(10);
        return;
    }
    strcpy(newPath, path);
    strcat(newPath, dir);
    if (type!='f' && testAttrib(attrib, dir))
        printf("%s\n", newPath); 
    strcat(newPath, "/");
    chdir(dir);
    while((entry = readdir(dp)) != NULL) {
        stat(entry->d_name,&statbuf);

        if(S_ISDIR(statbuf.st_mode) && testAttrib(attrib, entry->d_name)) {
            if(!strcmp(".",entry->d_name) || !strcmp("..",entry->d_name))
               continue; // ignore . and ..
            if (depth>1 || depth<=-1)
                scanDir(entry->d_name,depth-1,type,newPath,gtsize,attrib);
        }
        if(S_ISREG(statbuf.st_mode) && type!='d' && testAttrib(attrib, entry->d_name)) {
                off_t sizeF = statbuf.st_size;
                char filePath[100];
                strcpy(filePath, newPath);
                strcat(filePath, entry->d_name);
                if(sizeF>=gtsize)
                    printf("%s \n", filePath);
            }
    }
    chdir("..");
    closedir(dp);
}

【问题讨论】:

  • 好吧,看看错误?以perror() 为例。
  • 它加入第一个 if 并打印“无法打开目录”

标签: c directory


【解决方案1】:
char newPath[strlen(path)+strlen(dir)];  //WRONG!

肯定是错的。您需要为终止的 0 保留一个额外的字节,并且您正在添加一个/。所以应该是

char newPath[strlen(path)+strlen(dir)+2];

顺便说一句,考虑使用 snprintf(3)asprintf(3) 代替您的 strcat 调用。

我不确定致电chdir(2) 是否明智,您当然应该检查它是否顺利。见perror(3)errno(3)strerror(3)

同时查看nftw(3)

【讨论】:

  • 还是太短了,因为他还加了一个尾随/
  • 然后在您的程序上使用errno 并尝试strace(1)。不要忘记使用所有警告和调试信息 (gcc -Wall -Wextra -g) 进行编译并使用调试器 gdb
【解决方案2】:

在 struct dirent 中,成员 d_name 包含没有路径的名称。这意味着传递给函数 opendir() 的参数没有文件或目录的路径,因此会发生错误 ENOENT。

假设您有目录 /home/usr/folder1/folder2。你打电话给

scandir("/home/usr/folder1/", 2, type, ...) // I understood only first two parameters.

这个函数似乎可以工作,但是当函数递归调用自身来搜索 /home/usr/folder1/folder2 时

if (depth>1 || depth<=-1) scanDir(entry->d_name,depth-1,type,newPath,gtsize,attrib);

这次传递给scandir的第一个参数是“folder2”而不是“/home/usr/folder1/folder2”所以opendir(dir)给出了名为ENOENT的错误

您还应该注意的另一件事是 readdir() 函数不是可重入函数,因此调用 readdir() 函数可能会导致意外错误。在您的代码中,该函数看起来像您想要的那样给出结果。但是,我认为“它是如何工作的”可能与您的想法不同。如果代码变得复杂,我建议使用 readdir_r() 函数,它是 readdir 的可重入版本

根据 readdir 的手册页:

成功时,readdir() 返回一个指向不同结构的指针。 (这个 结构可以静态分配;不要试图释放(3)它。)

递归调用scandir()函数后,在每个函数栈中,由于结构是静态分配的,所以你的条目变成了NUll指针。

对你函数的另一个建议是使用 linux 提供的 nftw() 或 scandir() 函数。尤其是 nftw 真的很强大,可以满足大多数人的需求。

【讨论】:

    猜你喜欢
    • 2012-08-06
    • 2021-05-24
    • 1970-01-01
    • 2016-01-02
    • 1970-01-01
    • 1970-01-01
    • 2013-01-11
    • 2018-08-23
    • 1970-01-01
    相关资源
    最近更新 更多