Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ mkfs/mkfs: mkfs/mkfs.c $K/fs.h $K/param.h
.PRECIOUS: %.o

UPROGS=\
$U/_find\
$U/_cat\
$U/_echo\
$U/_forktest\
Expand All @@ -133,8 +134,8 @@ UPROGS=\
$U/_wc\
$U/_zombie\

fs.img: mkfs/mkfs README.md $(UPROGS)
mkfs/mkfs fs.img README.md $(UPROGS)
fs.img: mkfs/mkfs README.md $(UPROGS) tester.txt
mkfs/mkfs fs.img README.md $(UPROGS) tester.txt

-include kernel/*.d user/*.d

Expand Down
17 changes: 17 additions & 0 deletions tester.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣤⡤⠤⠤⠤⣤⣄⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡤⠞⠋⠁⠀⠀⠀⠀⠀⠀⠀⠉⠛⢦⣤⠶⠦⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⢀⣴⠞⢋⡽⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠃⠀⠀⠙⢶⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⣰⠟⠁⠀⠘⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⡀⠀⠀⠉⠓⠦⣤⣤⣤⣤⣤⣤⣄⣀⠀⠀⠀
⠀⠀⠀⠀⣠⠞⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣷⡄⠀⠀⢻⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣆⠀
⠀⠀⣠⠞⠁⠀⠀⣀⣠⣏⡀⠀⢠⣶⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⠿⡃⠀⠀⠀⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⡆
⢀⡞⠁⠀⣠⠶⠛⠉⠉⠉⠙⢦⡸⣿⡿⠀⠀⠀⡄⢀⣀⣀⡶⠀⠀⠀⢀⡄⣀⠀⣢⠟⢦⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⠃
⡞⠀⠀⠸⠁⠀⠀⠀⠀⠀⠀⢳⢀⣠⠀⠀⠀⠉⠉⠀⠀⣀⠀⠀⠀⢀⣠⡴⠞⠁⠀⠀⠈⠓⠦⣄⣀⠀⠀⠀⠀⣀⣤⠞⠁⠀
⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⠀⠁⠀⢀⣀⣀⡴⠋⢻⡉⠙⠾⡟⢿⣅⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠙⠛⠉⠉⠀⠀⠀⠀
⠘⣦⡀⠀⠀⠀⠀⠀⠀⣀⣤⠞⢉⣹⣯⣍⣿⠉⠟⠀⠀⣸⠳⣄⡀⠀⠀⠙⢧⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠈⠙⠒⠒⠒⠒⠚⠋⠁⠀⡴⠋⢀⡀⢠⡇⠀⠀⠀⠀⠃⠀⠀⠀⠀⠀⢀⡾⠋⢻⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇⠀⢸⡀⠸⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠀⠀⢠⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣇⠀⠀⠉⠋⠻⣄⠀⠀⠀⠀⠀⣀⣠⣴⠞⠋⠳⠶⠞⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠳⠦⢤⠤⠶⠋⠙⠳⣆⣀⣈⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀

⠀Hi I'm testing the find command right now!
147 changes: 147 additions & 0 deletions user/find.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fcntl.h"
#include "stdbool.h"
#include "kernel/fs.h"

//goal: to recursively search thru directories to find a file
// cite/research: https://www.geeksforgeeks.org/find-command-in-linux-with-examples/

/**
* checks if pattern (file name or other symbols) matches target string
* patterns include: * or ?
*
* @param str file/directory name
* @param pattern target provided
* @return true if file/directory matches name or pattern
*/
bool matches(const char *str, const char *pattern) {
const char *tmp_pattern = pattern;
const char *tmp_str = str;
int star = -1;
int last_match = -1;

for (int i = 0; *tmp_str; i++) {
// move pattern pointer to next if a match or contains ? character
if (*tmp_pattern == *tmp_str || *tmp_pattern == '?') {
tmp_pattern++;
// save position of * when found and save index of last match if string contains * character
} else if (*tmp_pattern == '*') {
// star position
star = i;
tmp_pattern++;
last_match = i;
// check if theres a mismatch after * character and revisit to last matched char
} else if (star != -1) {
i = last_match;
tmp_pattern = pattern + (tmp_pattern - pattern);
// no match found
} else {
return false;
}
tmp_str++;
}

// condition added to skip other chars after * in the pattern
while (*tmp_pattern == '*') {
tmp_pattern++;
}

// return if pattern matches strings
return *tmp_pattern == '\0';
}

/**
* finds path towards specific files or directories (some restrictions include)
*
* @param path starting directory for search
* @param flag settings or conditions
* @param target pattern or file/directory name
*/
void find(const char *path, const char *flag, const char *target) {
int fd;
struct stat st;
struct dirent de;
char buf[512], *p;

if ((fd = open(path, O_RDONLY)) < 0) {
printf("find: cannot open %s\n", path);
return;
}

if (fstat(fd, &st) < 0) {
printf("find: cannot stat %s\n", path);
close(fd);
return;
}

// if it's a directory, traverse it
if (st.type == T_DIR) {
if (strlen(path) + 1 + DIRSIZ + 1 > sizeof(buf)) {
printf("find: path too long\n");
return;
}

strcpy(buf, path);
p = buf + strlen(buf);
*p++ = '/';

while (read(fd, &de, sizeof(de)) == sizeof(de)) {
if (de.inum == 0) // Skip invalid args
continue;

memmove(p, de.name, DIRSIZ);
p[DIRSIZ] = 0;

// skip "." and ".."
if (strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0)
continue;

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

// prints all directory if argument is like "find path -type d"
if ((strcmp(target, "d") == 0) && (strcmp(flag, "-type") == 0) && (st.type == T_DIR)) {
printf("%s\n", buf);
}

// prints all files if argument is like "find path -type f"
if ((strcmp(target, "f") == 0) && (strcmp(flag, "-type") == 0) && (st.type == T_FILE)) {
printf("%s\n", buf);
}

// if the file/directory name matches the target
// see if target includes any symbols like * or ?
if (strcmp(flag, "-name") == 0 && matches(de.name, target)) {
printf("%s\n", buf); // print if it matches
}

// recurse into it if it's a directory
if (st.type == T_DIR) {
find(buf, flag, target);
}
}
}

close(fd);
}

/**
* main method used for testing
*
* @param argc number of arguments
* @param argv array of arguments
* @return exit code
*/
int main(int argc, char *argv[]) {
if (argc < 3) {
printf("Usage: find <directory> <file_name>\n");
exit(1);
}

find(argv[1], argv[2], argv[3]);
exit(0);
}