#include "kernel/fs.h" #include "kernel/stat.h" #include "kernel/types.h" #include "user/user.h" int match_pattern(const char *name, const char *pattern) { const char *star = 0; const char *name_ptr = name; const char *pattern_ptr = pattern; while (1) { if (*pattern_ptr == '*') { star = pattern_ptr++; name_ptr = name; continue; } if (!*name) return (!*pattern_ptr || (star && !*++pattern_ptr)); if (*pattern_ptr == '?' || *pattern_ptr == *name) { pattern_ptr++; name++; continue; } if (star) { pattern_ptr = star + 1; name = ++name_ptr; continue; } return 0; } } void find(char *path, char *pattern) { char buf[512], *p; int fd; struct dirent de; struct stat st; if ((fd = open(path, 0)) < 0) { fprintf(2, "find: cannot open %s\n", path); return; } if (fstat(fd, &st) < 0) { fprintf(2, "find: cannot stat %s\n", path); close(fd); return; } if (st.type != T_DIR) { fprintf(2, "find: %s is not a directory\n", path); close(fd); return; } if (strlen(path) + 1 + DIRSIZ + 1 > sizeof buf) { fprintf(2, "find: path too long\n"); close(fd); return; } strcpy(buf, path); p = buf + strlen(buf); *p++ = '/'; while (read(fd, &de, sizeof(de)) == sizeof(de)) { if (de.inum == 0 || !strcmp(de.name, ".") || !strcmp(de.name, "..")) continue; memmove(p, de.name, DIRSIZ); p[DIRSIZ] = 0; if (stat(buf, &st) < 0) { fprintf(2, "find: cannot stat %s\n", buf); continue; } if (st.type == T_DIR) { find(buf, pattern); } else if (st.type == T_FILE) { if (match_pattern(de.name, pattern)) { fprintf(1, "%s\n", buf); } } } close(fd); } int main(int argc, char *argv[]) { if (argc != 3) { fprintf(2, "Usage: find \n"); exit(1); } find(argv[1], argv[2]); exit(0); }