diff --git a/find.c b/find.c new file mode 100644 index 00000000..de8b966e --- /dev/null +++ b/find.c @@ -0,0 +1,122 @@ +// Lab Xv6 and Unix utilities +// find.c + +#include "kernel/types.h" +#include "user/user.h" +#include "kernel/stat.h" +#include "kernel/fs.h" + +// find 函数 +void +find(char *dir, char *file) +{ + // 声明 文件名缓冲区 和 指针 + char buf[512], *p; + // 声明文件描述符 fd + int fd; + // 声明与文件相关的结构体 + struct dirent de; + struct stat st; + + // open() 函数打开路径,返回一个文件描述符,如果错误返回 -1 + if ((fd = open(dir, 0)) < 0) + { + // 报错,提示无法打开此路径 + fprintf(2, "find: cannot open %s\n", dir); + return; + } + + // int fstat(int fd, struct stat *); + // 系统调用 fstat 与 stat 类似,但它以文件描述符作为参数 + // int stat(char *, struct stat *); + // stat 系统调用,可以获得一个已存在文件的模式,并将此模式赋值给它的副本 + // stat 以文件名作为参数,返回文件的 i 结点中的所有信息 + // 如果出错,则返回 -1 + if (fstat(fd, &st) < 0) + { + // 出错则报错 + fprintf(2, "find: cannot stat %s\n", dir); + // 关闭文件描述符 fd + close(fd); + return; + } + + // 如果不是目录类型 + if (st.type != T_DIR) + { + // 报类型不是目录错误 + fprintf(2, "find: %s is not a directory\n", dir); + // 关闭文件描述符 fd + close(fd); + return; + } + + // 如果路径过长放不入缓冲区,则报错提示 + if(strlen(dir) + 1 + DIRSIZ + 1 > sizeof buf) + { + fprintf(2, "find: directory too long\n"); + // 关闭文件描述符 fd + close(fd); + return; + } + // 将 dir 指向的字符串即绝对路径复制到 buf + strcpy(buf, dir); + // buf 是一个绝对路径,p 是一个文件名,通过加 "/" 前缀拼接在 buf 的后面 + p = buf + strlen(buf); + *p++ = '/'; + // 读取 fd ,如果 read 返回字节数与 de 长度相等则循环 + while (read(fd, &de, sizeof(de)) == sizeof(de)) + { + if(de.inum == 0) + continue; + // strcmp(s, t); + // 根据 s 指向的字符串小于(st) t 指向的字符串的不同情况 + // 分别返回负整数、0或正整数 + // 不要递归 "." 和 "..." + if (!strcmp(de.name, ".") || !strcmp(de.name, "..")) + continue; + // memmove,把 de.name 信息复制 p,其中 de.name 代表文件名 + memmove(p, de.name, DIRSIZ); + // 设置文件名结束符 + p[DIRSIZ] = 0; + // int stat(char *, struct stat *); + // stat 系统调用,可以获得一个已存在文件的模式,并将此模式赋值给它的副本 + // stat 以文件名作为参数,返回文件的 i 结点中的所有信息 + // 如果出错,则返回 -1 + if(stat(buf, &st) < 0) + { + // 出错则报错 + fprintf(2, "find: cannot stat %s\n", buf); + continue; + } + // 如果是目录类型,递归查找 + if (st.type == T_DIR) + { + find(buf, file); + } + // 如果是文件类型 并且 名称与要查找的文件名相同 + else if (st.type == T_FILE && !strcmp(de.name, file)) + { + // 打印缓冲区存放的路径 + printf("%s\n", buf); + } + } +} + +int +main(int argc, char *argv[]) +{ + // 如果参数个数不为 3 则报错 + if (argc != 3) + { + // 输出提示 + fprintf(2, "usage: find dirName fileName\n"); + // 异常退出 + exit(1); + } + // 调用 find 函数查找指定目录下的文件 + find(argv[1], argv[2]); + // 正常退出 + exit(0); +} +