Files
xv6-labs/user/find.c
2025-03-04 11:23:18 +08:00

99 lines
1.9 KiB
C

#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 <path> <pattern>\n");
exit(1);
}
find(argv[1], argv[2]);
exit(0);
}