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 @@ -142,9 +142,10 @@ UPROGS=\
$U/_logstress\
$U/_forphan\
$U/_dorphan\
$U/_find\

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

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

Expand Down
23 changes: 23 additions & 0 deletions docs/find.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
FogOS - Find Implementation

Build
- Build the OS as usual (make qemu)

Run
- In the command line type: find <path> <expression>
- If "." is given as path, then it will look through current directory
- If 0 args are given it will return an error statement
- If expression/file does not exist in path, then it will return an error statement
- The output will be printed in the following format if successful
- Path: /tests/itests test1.txt

Test
- Created local testing directory (tests) containing two text files and another directory (itests) with a text file

Test Input 1: find . test1.txt
Test Output 1: Path: /tests/itest/test1.txt test1.txt /tests/test1.txt test1.txt

Test Input 2: find /tests test2.txt
Test Output 2: Path: /tests/test2.txt test2.txt


2 changes: 2 additions & 0 deletions kernel/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ extern uint64 sys_unlink(void);
extern uint64 sys_link(void);
extern uint64 sys_mkdir(void);
extern uint64 sys_close(void);
extern uint64 sys_find(void);

// An array mapping syscall numbers from syscall.h
// to the function that handles the system call.
Expand All @@ -126,6 +127,7 @@ static uint64 (*syscalls[])(void) = {
[SYS_link] sys_link,
[SYS_mkdir] sys_mkdir,
[SYS_close] sys_close,
[SYS_find] sys_find,
};

void
Expand Down
1 change: 1 addition & 0 deletions kernel/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@
#define SYS_link 19
#define SYS_mkdir 20
#define SYS_close 21
#define SYS_find 22
8 changes: 8 additions & 0 deletions kernel/sysproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,11 @@ sys_uptime(void)
release(&tickslock);
return xticks;
}


uint64
sys_find(void)
{
return 0;
}

103 changes: 95 additions & 8 deletions mkfs/mkfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@
#include <string.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>

#define dirent xv6_dirent
#define stat xv6_stat // avoid clash with host struct stat
#include "kernel/types.h"
#include "kernel/fs.h"
#include "kernel/stat.h"
#include "kernel/param.h"
#undef dirent
#undef stat

#ifndef static_assert
#define static_assert(a, b) do { switch (0) case 0: case (a): ; } while (0)
Expand All @@ -20,9 +26,9 @@
// Disk layout:
// [ boot block | sb block | log | inode blocks | free bit map | data blocks ]

int nbitmap = FSSIZE/BPB + 1;
int nbitmap = FSSIZE/(BSIZE*8) + 1;
int ninodeblocks = NINODES / IPB + 1;
int nlog = LOGBLOCKS+1; // Header followed by LOGBLOCKS data blocks.
int nlog = LOGBLOCKS;
int nmeta; // Number of meta blocks (boot, sb, nlog, inode, bitmap)
int nblocks; // Number of data blocks

Expand Down Expand Up @@ -65,12 +71,88 @@ xint(uint x)
return y;
}

void
add_file(int parent_fd, uint parentino, char *filename)
{
uint inum;
int fd;
char buf[BSIZE];
struct xv6_dirent de;

if((fd = openat(parent_fd, filename, 0)) < 0)
die(filename);

inum = ialloc(T_FILE);

bzero(&de, sizeof(de));
de.inum = xshort(inum);
strncpy(de.name, filename, DIRSIZ);
iappend(parentino, &de, sizeof(de));

ssize_t cc;
while((cc = read(fd, buf, sizeof(buf))) > 0)
iappend(inum, buf, cc);

close(fd);
}

uint
add_dir(int level, int parent_fd, uint parentino, char *dirname)
{
struct xv6_dirent de;
uint dino = ialloc(T_DIR);
bzero(&de, sizeof(de));
de.inum = xshort(dino);
strcpy(de.name, dirname);
iappend(parentino, &de, sizeof(de));

bzero(&de, sizeof(de));
de.inum = xshort(dino);
strcpy(de.name, ".");
iappend(dino, &de, sizeof(de));

bzero(&de, sizeof(de));
de.inum = xshort(parentino);
strcpy(de.name, "..");
iappend(dino, &de, sizeof(de));

int dir_fd = -1;
if ((dir_fd = openat(parent_fd, dirname, O_RDONLY)) == -1) {
perror("open");
return dino;
}

DIR *d = fdopendir(dir_fd);
if (d == NULL) {
perror("fdopendir");
return dino;
}

struct dirent *e;
while ((e = readdir(d)) != NULL) {
if (e->d_name[0] == '.') {
continue;
}

if (e->d_type == DT_REG) {
printf("%*s+ %s\n", level * 2, "", e->d_name);
add_file(dir_fd, dino, e->d_name);
} else if (e->d_type == DT_DIR) {
printf("%*s+ /%s\n", level * 2, "", e->d_name);
add_dir(level + 1, dir_fd, dino, e->d_name);
}
}
close(dir_fd);

return dino;
}

int
main(int argc, char *argv[])
{
int i, cc, fd;
uint rootino, inum, off;
struct dirent de;
struct xv6_dirent de;
char buf[BSIZE];
struct dinode din;

Expand All @@ -83,7 +165,7 @@ main(int argc, char *argv[])
}

assert((BSIZE % sizeof(struct dinode)) == 0);
assert((BSIZE % sizeof(struct dirent)) == 0);
assert((BSIZE % sizeof(struct xv6_dirent)) == 0);

fsfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666);
if(fsfd < 0)
Expand All @@ -102,7 +184,7 @@ main(int argc, char *argv[])
sb.inodestart = xint(2+nlog);
sb.bmapstart = xint(2+nlog+ninodeblocks);

printf("nmeta %d (boot, super, log blocks %u, inode blocks %u, bitmap blocks %u) blocks %d total %d\n",
printf("nmeta %d (boot, super, log blocks %u inode blocks %u, bitmap blocks %u) blocks %d total %d\n",
nmeta, nlog, ninodeblocks, nbitmap, nblocks, FSSIZE);

freeblock = nmeta; // the first free block that we can allocate
Expand All @@ -128,6 +210,13 @@ main(int argc, char *argv[])
iappend(rootino, &de, sizeof(de));

for(i = 2; i < argc; i++){
struct stat sb;
stat(argv[i], &sb);
if (S_ISDIR(sb.st_mode)) {
add_dir(0, AT_FDCWD, rootino, argv[i]);
continue;
}

// get rid of "user/"
char *shortname;
if(strncmp(argv[i], "user/", 5) == 0)
Expand All @@ -147,8 +236,6 @@ main(int argc, char *argv[])
if(shortname[0] == '_')
shortname += 1;

assert(strlen(shortname) <= DIRSIZ);

inum = ialloc(T_FILE);

bzero(&de, sizeof(de));
Expand Down Expand Up @@ -240,7 +327,7 @@ balloc(int used)
int i;

printf("balloc: first %d blocks have been allocated\n", used);
assert(used < BPB);
assert(used < BSIZE*8);
bzero(buf, BSIZE);
for(i = 0; i < used; i++){
buf[i/8] = buf[i/8] | (0x1 << (i%8));
Expand Down
Empty file added tests/itestdir/itest1.txt
Empty file.
Empty file added tests/itestdir/itest2.txt
Empty file.
Empty file added tests/test1.txt
Empty file.
Empty file added tests/test2.txt
Empty file.
137 changes: 137 additions & 0 deletions user/find.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
#include "kernel/types.h"
#include "kernel/stat.h"
#include "kernel/fcntl.h"
#include "user/user.h"
#include "kernel/fs.h"

char buf[1024];
int match(char*, char*);

char*
fmtname(char *path)
{
static char buf[DIRSIZ+1];
char *p;

// Find first character after last slash.
for(p=path+strlen(path); p >= path && *p != '/'; p--)
;
p++;

// Return blank-padded name.
if(strlen(p) >= DIRSIZ)
return p;
memmove(buf, p, strlen(p));
memset(buf+strlen(p), ' ', DIRSIZ-strlen(p));
return buf;
}
// ls implementation code
void
findit(char *path, char *expr)
{
char buf[512], *p;
int fd;
struct dirent de;
struct stat st;
if((fd = open(path, O_RDONLY)) < 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_FILE) {
if (match(expr, fmtname(path))) {
printf("Path: %s\n", path);
}
} else if (T_DIR) {
if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){
printf("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){
continue;
}
if (strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0) {
continue;
}

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

if(stat(buf, &st) < 0){
printf("find: cannot stat %s\n", buf);
continue;
}
if(st.type == T_DIR){
findit(buf, expr);
} else if (match(expr,de.name)) {
printf("Path: %s \nFound!\n", buf);
}
}
close(fd);
}
}

int
main(int argc, char *argv[])
{
if(argc < 3){
fprintf(2, "usage: find path expression\n");
exit(1);
}
findit(argv[1], argv[2]);
exit(0);
}
// Regexp matcher from Kernighan & Pike,
// The Practice of Programming, Chapter 9, or
// https://www.cs.princeton.edu/courses/archive/spr09/cos333/beautiful.html

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;
}
1 change: 1 addition & 0 deletions user/user.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ int getpid(void);
char* sys_sbrk(int,int);
int pause(int);
int uptime(void);
void find(char* /*str*/ path, char* /*str*/ expression);

// ulib.c
int stat(const char*, struct stat*);
Expand Down
1 change: 1 addition & 0 deletions user/usys.pl
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,4 @@ sub entry {
entry("sbrk");
entry("pause");
entry("uptime");
entry("find");