Skip to content

find.c

#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fs.h"

TIP

find 函��在指定路径下递归地查找具有特定名���的文件

void find(char *path, const char *filename) {
    char path_buffer[512], *path_pointer;
    int file_descriptor;
    struct dirent directory_entry;
    struct stat status;

TIP

打开路径对应的文件或目录

    if ((file_descriptor = open(path, 0)) < 0) {
        fprintf(2, "find: cannot open %s\n", path);
        return;
    }

TIP

获��文件或目录的状态信息

    if (fstat(file_descriptor, &status) < 0) {
        fprintf(2, "find: cannot stat %s\n", path);
        close(file_descriptor);
        return;
    }

TIP

根据文件类型进行处理

    switch (status.type) {

TIP

如果是普通文件

        case T_FILE:

TIP

从路径中提取文件名

            for (path_pointer = path + strlen(path); path_pointer >= path && *path_pointer != '/'; path_pointer--);
            path_pointer++;

TIP

检查文件名是否与目标文件名匹配

            if (strcmp(path_pointer, filename) == 0) {
                printf("%s\n", path);
            }
            break;

TIP

如果是目录

        case T_DIR:

TIP

检查路径长度是否会��出缓冲区

            if (strlen(path) + 1 + DIRSIZ + 1 > sizeof path_buffer) {
                printf("find: path too long\n");
                break;
            }

TIP

构建访问的���径

            strcpy(path_buffer, path);
            path_pointer = path_buffer + strlen(path_buffer);
            *path_pointer++ = '/';

TIP

读取目录项

            while (read(file_descriptor, &directory_entry, sizeof(directory_entry)) == sizeof(directory_entry)) {

TIP

跳过无效的目录项

                if (directory_entry.inum == 0)
                    continue;

TIP

跳过 "." 和 ".." 目录

                if (strcmp(directory_entry.name, ".") == 0 || strcmp(directory_entry.name, "..") == 0)
                    continue;

TIP

构建子文件或子目录的完整路径

                memmove(path_pointer, directory_entry.name, DIRSIZ);
                path_pointer[DIRSIZ] = 0;

TIP

获取子文件或子目录的状态

                if (stat(path_buffer, &status) < 0) {
                    printf("find: cannot stat %s\n", path_buffer);
                    continue;
                }

TIP

根据子项的类型进行处理

                switch (status.type) {

TIP

如果是���件,则检查文件名是否匹配

                    case T_FILE:
                        if (strcmp(directory_entry.name, filename) == 0) {
                            printf("%s\n", path_buffer);
                        }
                        break;

TIP

如果是目录,则递归调用 find

                    case T_DIR:
                        find(path_buffer, filename);
                        break;
                }
            }
            break;
    }

TIP

关闭文件描述符

    close(file_descriptor);
}

TIP

主函数

int main(int argc, char *argv[]) {

TIP

检查命��行参数的数量

    if (argc != 3) {
        fprintf(2, "Usage: find <directory> <filename>\n");
        exit(1);
    }

TIP

调用 find 函数开始查找

    find(argv[1], argv[2]);

    exit(0);
}