Skip to content

Commit

Permalink
Lab util: regexfind
Browse files Browse the repository at this point in the history
  • Loading branch information
foyoodo committed Mar 8, 2021
1 parent 0318941 commit 5638b40
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 0 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ UPROGS=\
$U/_mkdir\
$U/_pingpong\
$U/_primes\
$U/_regexfind\
$U/_rm\
$U/_sh\
$U/_sleep\
Expand Down
112 changes: 112 additions & 0 deletions user/regexfind.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#include "kernel/types.h"
#include "kernel/stat.h"
#include "kernel/fs.h"
#include "user/user.h"

int match(char*, char*);

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 find path %s\n", path);
exit(1);
}

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

if (st.type != T_DIR) {
fprintf(2, "find: %s is not a directory\n", path);
close(fd);
exit(1);
}

if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){
fprintf(2, "find: path too long\n");
close(fd);
exit(1);
}

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(1, "find: cannot stat %s\n", buf);
continue;
}
if (st.type == T_FILE && match(pattern, de.name)) {
fprintf(1, "%s\n", buf);
} else if (st.type == T_DIR) {
find(buf, pattern);
}
}
close(fd);
}

int
main(int argc, char *argv[])
{
if (argc < 2 || argc > 3) {
fprintf(2, "Usage: find (path) [file]\n");
exit(1);
} else if (argc < 3) {
find(".", argv[1]);
} else {
find(argv[1], argv[2]);
}

exit(0);
}

int matchhere(char*, char*);
int matchstar(int, char*, char*);

int
match(char *re, char *text)
{
if(re[0] == '^')
return matchhere(re+1, text);
do{ // must look at empty string
if(matchhere(re, text))
return 1;
}while(*text++ != '\0');
return 0;
}

// matchhere: search for re at beginning of text
int matchhere(char *re, char *text)
{
if(re[0] == '\0')
return 1;
if(re[1] == '*')
return matchstar(re[0], re+2, text);
if(re[0] == '$' && re[1] == '\0')
return *text == '\0';
if(*text!='\0' && (re[0]=='.' || re[0]==*text))
return matchhere(re+1, text+1);
return 0;
}

// matchstar: search for c*re at beginning of text
int matchstar(int c, char *re, char *text)
{
do{ // a * matches zero or more instances
if(matchhere(re, text))
return 1;
}while(*text!='\0' && (*text++==c || c=='.'));
return 0;
}

0 comments on commit 5638b40

Please sign in to comment.