minix 3.1 中的搜索功能

Search function in minix 3.1

我一直在尝试在 minix 中实现一个搜索功能,该功能将在当前目录或子目录中查找文件并打印路径。到目前为止,我的代码编译没有失败,但它 returns 由于某种原因只有几个奇怪的 ascii 字符,知道我做错了什么吗?

#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

_PROTOTYPE(int main, (int argc, char **argv));
_PROTOTYPE(char *find_file, (char *name, char *directory));

int main(argc, argv)
int argc;
char **argv;
{
    char *path = find_file(argv[0], "./");
    if (strcmp(path, "") == 0) {
        printf("file could not be found.");
    } else {
        printf("File found in: %s\n", path);
    }
    return(0);
}

char *find_file(name, directory)
char *name;
char *directory;
{
    DIR *d;
    struct dirent *e;
    struct stat s;

    char *dr;
    char *res;
    char *result;

    d = opendir(directory);
    if (d != NULL) {
        while (e = readdir(d)) {
            if (e->d_name == name)
                return name;
        }
    }
    closedir(d);

    d = opendir(directory);
    if (d != NULL) {
        while (e = readdir(d)) {
            stat(e->d_name, &s);
            if (s.st_mode & S_IFDIR) {
                dr = malloc(strlen(directory) + strlen(e->d_name) + 2);
                strcpy(dr, directory);
                strcat(dr, e->d_name);
                strcat(dr, "/");
                res = find_file(name, dr));
                if (strcmp(res, "") != 0) {
                    strcpy(result, e->d_name);
                    strcat(result, "/");
                    strcat(result, res);
                    return result;
                }
            }
        }
    }
    closedir(d);
    return "";
}

因此,在进入子文件夹之前,我首先检查文件是否在当前目录中,这就是我打开和关闭目录两次的原因。我唯一怀疑可能是非正统的事情是直接使用 malloc 并声明一个固定的数量,这是不行的吗?感谢您的帮助 <3

编辑:所以我尝试使用 malloc 和字符串的大小而不是设置的数量但没有改变,这是一个截图:

EDIT2:由于建议更新了我的代码,仍然无法 100% 工作,因为它正在进入父文件夹或类似的奇怪的东西,如果我设法让它完美地工作,post 解决方案会吗 (y)

EDIT3:我已经设法让它工作(在某种程度上)它可以完美地工作但在某些情况下它找不到现有文件,不知道这是什么原因并且太累了无法确定为什么 ^_^ 这是供将来寻找类似解决方案的任何其他人使用的最终工作代码:

#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

_PROTOTYPE(int main, (int argc, char **argv));
_PROTOTYPE(char *find_file, (char *name, char *directory));

int main(argc, argv)
int argc;
char **argv;
{
    char *path = find_file(argv[1], "./");
    if (strcmp(path, "") == 0) {
        printf("file could not be found.\n");
    } else {
        printf("File found in: %s\n", path);
    }
    return(0);
}

char *find_file(name, directory)
char *name;
char *directory;
{
    DIR *d;
    struct dirent *e;
    struct stat s;

    char *dr;
    char *res;
    char *result;

    d = opendir(directory);
    if (d != NULL) {
        while (e = readdir(d)) {
            if (strcmp(e->d_name, name) == 0)
                return e->d_name;
        }
    }
    closedir(d);

    d = opendir(directory);
    if (d != NULL) {
        while (e = readdir(d)) {
            stat(e->d_name, &s);
            if (strcmp(e->d_name, ".") != 0 && strcmp(e->d_name, "..") != 0) {    
                if (s.st_mode & S_IFDIR) != 0) {
                    dr = malloc(strlen(directory) + strlen(e->d_name) + 2);
                    strcpy(dr, directory);
                    strcat(dr, e->d_name);
                    strcat(dr, "/");
                    res = find_file(name, dr));
                    if (strcmp(res, "") != 0) {
                        result = malloc(strlen(e->d_name) + strlen(res) + 2);
                        strcpy(result, e->d_name);
                        strcat(result, "/");
                        strcat(result, res);
                        return result;
                    }
                }
            }
        }
    }
    closedir(d);
    return "";
}

出于某种原因,文件名是在 argv1 中传递的,而不是 argv[0],这很奇怪,因为我已经实现了另一个通过 argv[0] 传递文件名的函数...Minix ¯ |(ツ)

你给出了一个指向 stat 的未初始化指针。

struct stat *s
....
stat(e->d_name, s);

你应该做的是:

struct stat s
....
stat(e->d_name, &s);

另一个问题(除其他外)是这部分:

strcpy(res, find_file(name, dr));
if (res != "") {

你不能在 C 中像这样比较字符串,你必须使用 strcmp(res, "") == 0,因为你在这里比较指针。它甚至可以在这种情况下工作(如果静态字符串被您的编译器重用),但在一般情况下它不会。

我不熟悉 Minix,但您可能希望排除“.”。和 '..' 目录,因为 Minix 也是一个类 UNIX 系统。

其次,您不必两次打开目录,因为 readdir() 将遍历目录下的所有项目,包括“.”。和'..',无论是目录还是文件。

第三,对于这个代码块:

d = opendir(directory);
if (d != NULL) {
    while (e = readdir(d)) {
        if (e->d_name == name)
            return name;
    }
}
closedir(d);

这里只return name不太好,因为它只是一个文件名,没有绝对路径信息。这也是您应该将此代码块合并到 find_file().

的第二部分的原因

另外,你不应该return这里的结果,因为很可能在另一个目录下有另一个与你正在搜索的名称相同的项目。更好的解决方案是只打印出名称(带有绝对路径信息)并继续该过程。或者简单地说,您不必将 find_file() 变成 return 。你只需要打印出你已经找到的名字即可。

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h> // added
#include <dirent.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>


char *find_file(char *name, char *directory); // corrected

int main(int argc, char * argv[]) // corrected
{
    // added to correct compiler warning about unused parameter 'argc'
    if( 2 != argc ) {perror( "wrong number of parameters "); exit( EXIT_FAILURE); }

    // corrected to use parameter rather than current executable name
    char *path = find_file(argv[1], "./");

    // corrected to make useful comparison
    if ( '[=10=]' == path[0] )
    {
        printf("file could not be found.");
    }

    else
    {
        printf("File found in: %s\n", path);
    }

    return(0);
} // end function: main

char *find_file(char *name, char *directory) // corrected
{
    DIR *d;
    struct dirent *e;
    struct stat s;

    char *dr;
    char *res;
    char *result = malloc( 1024 ); // corrected so 'result' pointer to allocated memory

    printf("initial DIR: %s\n", directory); // added for debug

    d = opendir(directory);
    if (d != NULL)
    {
        // corrected to fix compiler warning
        while ( NULL != (e = readdir(d)) )
        {
            if (e->d_name == name)
                return name;
        }
    }
    closedir(d);

    d = opendir(directory);
    if (d != NULL)
    {
        // corrected to fix compiler warning
        while ( NULL != (e = readdir(d)) )
        {
            stat(e->d_name, &s); // corrected
            // corrected so actually works
            if (S_ISDIR(s.st_mode) )
            {
                dr = malloc(strlen(directory) + strlen(e->d_name) + 2);
                strcpy(dr, directory);
                strcat(dr, e->d_name);
                strcat(dr, "/");

                // added for debug
                printf( "nested DIR: %s\n", dr);

                res = find_file(name, dr);

                // corrected to make useful comparison
                if ( '[=10=]' != res[0] )
                {
                    strcpy(result, e->d_name);
                    strcat(result, "/");
                    strcat(result, res);
                    return result;
                } // end if
            } // end of
        } // end while
    } // end if
    closedir(d);
    return "";
} // end function: find_file

(注意:这会在每次迭代时泄漏内存,因为 malloc 的内存没有传递给 free()

给出以下输出:

(注意:这是代码 运行 几秒钟后重复输出的一次重复的快照。)

(注意:helloworld 是一个可执行文件,在大约 70 个条目的目录中间(按字母顺序))

(注意:命令行是:./untitled untitled.c

初始目录:./helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../ helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../ helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../ helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../ helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../ helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../ helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../你好世界/../你好世界/.. /helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/.. /你好世界/../你好世界/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../ helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../ helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../ helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../ helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../ helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../ helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../你好世界/../你好世界/ ../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/ ../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/ ../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/ ../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/ ../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/ ../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/ ../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/../helloworld/ ../helloworld/../hel低世界/