Skip to content

Commit

Permalink
Directory listing in userspace
Browse files Browse the repository at this point in the history
  • Loading branch information
Twometer committed Feb 14, 2021
1 parent 481dfeb commit c9d04c2
Show file tree
Hide file tree
Showing 11 changed files with 146 additions and 30 deletions.
16 changes: 5 additions & 11 deletions kernel/fs/fat16.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,10 @@ namespace FS
} while ((cluster = NextCluster(cluster)) != FAT_END);
}

void Fat16::ListDirectory(const nk::String &path)
nk::Vector<DirEntry> Fat16::ListDirectory(const nk::String &path)
{
printf("List of %s:\n", path.CStr());

nk::Vector<DirEntry> result;
result.EnsureCapacity(16);
auto directory = LoadDirectory(path);

bool eof = false;
Expand All @@ -140,15 +140,9 @@ namespace FS
if (eof)
break;

if (entry.type == DirEntryType::File)
{
printf(" [f] %s\n", entry.name.CStr());
}
else if (entry.type == DirEntryType::Folder)
{
printf(" [d] %s\n", entry.name.CStr());
}
result.Add(entry);
}
return result;
}

uint8_t *Fat16::LoadDirectory(const nk::Path &path)
Expand Down
9 changes: 3 additions & 6 deletions kernel/fs/vfs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,18 +108,15 @@ namespace FS
}
}

void VirtualFileSystem::ListDirectory(const nk::String &path)
nk::Vector<DirEntry> VirtualFileSystem::ListDirectory(const nk::String &path)
{
auto mountPoint = FindMountPoint(path);
if (mountPoint == nullptr)
{
kdbg("vfs: Mount point not found for %s\n", path.CStr());
return;
return {};
}
#if VFS_DEBUG
kdbg("vfs: list_dir %s\n", mountPoint->path.CStr());
#endif
mountPoint->fs->ListDirectory(GetRelativePath(mountPoint, path));
return mountPoint->fs->ListDirectory(GetRelativePath(mountPoint, path));
}

nk::String VirtualFileSystem::GetRelativePath(MountPoint *mountPoint, const nk::String &absolutePath)
Expand Down
2 changes: 1 addition & 1 deletion kernel/include/kernel/fs/fat16.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ namespace FS

void Read(const DirEntry &entry, size_t offset, size_t size, uint8_t *dst) override;

void ListDirectory(const nk::String &path) override;
nk::Vector<DirEntry> ListDirectory(const nk::String &path) override;

private:
uint8_t *LoadDirectory(const nk::Path &path);
Expand Down
3 changes: 2 additions & 1 deletion kernel/include/kernel/fs/filesystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <kernel/fs/partition.h>
#include <kernel/fs/direntry.h>
#include <nk/string.h>
#include <nk/vector.h>

namespace FS
{
Expand All @@ -26,7 +27,7 @@ namespace FS

virtual void Read(const DirEntry &entry, size_t offset, size_t size, uint8_t *dst) = 0;

virtual void ListDirectory(const nk::String &path) = 0;
virtual nk::Vector<DirEntry> ListDirectory(const nk::String &path) = 0;
};

} // namespace FS
Expand Down
2 changes: 1 addition & 1 deletion kernel/include/kernel/fs/vfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ namespace FS

void Close(uint32_t fileHandle);

void ListDirectory(const nk::String &path);
nk::Vector<DirEntry> ListDirectory(const nk::String &path);

private:
nk::String GetRelativePath(MountPoint *mountPoint, const nk::String &absolutePath);
Expand Down
10 changes: 10 additions & 0 deletions kernel/include/kernel/syscalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <sys/types.h>
#include <stddef.h>
#include <stdint.h>
#include <dirent.h>

#define SYS_INVAL 0
#define SYS_TEXIT 1
Expand All @@ -25,6 +26,7 @@
#define SYS_CHDIR 17
#define SYS_GETCWD 18
#define SYS_GETENV 19
#define SYS_READDIR 20

#define PARAM_VALUE(param, type) (*(type *)(param))

Expand Down Expand Up @@ -94,6 +96,13 @@ extern "C"
char *val;
} sys$$getenv_param;

typedef struct
{
const char *dir;
dirent *dst;
size_t dstSize;
} sys$$readdir_param;

#ifdef __cplusplus
}
#endif
Expand All @@ -117,5 +126,6 @@ int sys$$fb_release(void *param);
int sys$$chdir(void *param);
int sys$$getcwd(void *param);
int sys$$getenv(void *param);
int sys$$readdir(void *param);

#endif
1 change: 1 addition & 0 deletions kernel/syscallhandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ namespace Kernel
AddSyscall(SYS_CHDIR, sys$$chdir);
AddSyscall(SYS_GETCWD, sys$$getcwd);
AddSyscall(SYS_GETENV, sys$$getenv);
AddSyscall(SYS_READDIR, sys$$readdir);
Interrupts::AddHandler(0x80, this);
}

Expand Down
22 changes: 22 additions & 0 deletions kernel/syscalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,4 +239,26 @@ int sys$$getenv(void *param)
return -EINVAL;
memcpy(params->val, val.CStr(), val.Length());
return 0;
}

int sys$$readdir(void *param)
{
sys$$readdir_param *params = (sys$$readdir_param *)param;
auto dirent = FS::VirtualFileSystem::GetInstance()->GetFileMeta(params->dir);
if (!dirent.IsValid())
return -ENOENT;
if (dirent.type != FS::DirEntryType::Folder)
return -ENOTDIR;

auto dir = FS::VirtualFileSystem::GetInstance()->ListDirectory(params->dir);
size_t maxSize = dir.Size() > params->dstSize ? params->dstSize : dir.Size();
for (size_t i = 0; i < maxSize; i++)
{
auto src = dir[i];
auto &dst = params->dst[i];
memcpy(dst.name, src.name.CStr(), src.name.Length() + 1);
dst.size = src.size;
dst.type = static_cast<unsigned>(src.type);
}
return maxSize;
}
35 changes: 35 additions & 0 deletions libc/dirent.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include <sys/syscall.h>
#include <dirent.h>

DIR *opendir(const char *name)
{
DIR *dir = malloc(sizeof(DIR));
dir->idx = 0;

sys$$readdir_param param;
param.dir = name;
param.dst = dir->data;
param.dstSize = 256;
int result = syscall(SYS_READDIR, &param);
if (result < 0)
{
free(dir);
return NULL;
}
dir->max = result;
return dir;
}

int closedir(DIR *dir)
{
free(dir);
}

dirent *readdir(DIR *dir)
{
if (dir->idx >= dir->max)
return NULL;
dirent *d = &dir->data[dir->idx];
dir->idx++;
return d;
}
36 changes: 36 additions & 0 deletions libc/include/dirent.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#ifndef _DIRENT_H
#define _DIRENT_H

#include <stddef.h>

#ifdef __cplusplus
extern "C"
{
#endif

#define TYPE_FILE 0
#define TYPE_DIR 1

typedef struct
{
char name[256];
size_t size;
unsigned type;
} dirent;

typedef struct
{
dirent data[256];
size_t idx;
size_t max;
} DIR;

DIR *opendir(const char *name);
int closedir(DIR *);
dirent *readdir(DIR *);

#ifdef __cplusplus
}
#endif

#endif
40 changes: 30 additions & 10 deletions userland/ls/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,38 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <dirent.h>

int main(int argc, char **argv)
void printdir(const char *path)
{
char *p = getenv("Path");
printf("path env: %s\n", p);
free(p);
DIR *dir = opendir(path);

dirent *ent;
while ((ent = readdir(dir)) != NULL)
{
if (ent->type == TYPE_DIR)
{
printf("[d] %s\n", ent->name);
}
else if (ent->type == TYPE_FILE)
{
printf("[f] [%d B] %s\n", ent->size, ent->name);
}
}

char cwd[PATH_MAX];
getcwd(cwd, PATH_MAX);
closedir(dir);
}

printf("Running ls with %d args\n", argc);
printf(" CWD: %s\n", cwd);
if (argc != 0)
printf("Args[0] %s\n", argv[0]);
int main(int argc, char **argv)
{
if (argc == 0)
{
char cwd[PATH_MAX];
getcwd(cwd, PATH_MAX);
printdir(cwd);
}
else
{
printdir(argv[0]);
}
}

0 comments on commit c9d04c2

Please sign in to comment.