diff --git a/libmaxsi/Makefile b/libmaxsi/Makefile index 1447ee30..61b4c160 100644 --- a/libmaxsi/Makefile +++ b/libmaxsi/Makefile @@ -39,6 +39,7 @@ c/h/stdarg.h \ c/h/wctype.h \ c/h/features.h \ c/h/string.h \ +c/h/sys/readdirents.h \ c/h/sys/stat.h \ c/h/sys/types.h \ c/h/sys/wait.h \ diff --git a/libmaxsi/hsrc/error.h b/libmaxsi/hsrc/error.h index 211c66b6..b006c314 100644 --- a/libmaxsi/hsrc/error.h +++ b/libmaxsi/hsrc/error.h @@ -53,6 +53,8 @@ namespace Maxsi const int ENOSPC = 18; const int EEXIST = 19; const int EROFS = 20; + const int EINVAL = 21; + const int ENOTDIR = 22; extern int _errornumber; diff --git a/libmaxsi/io.cpp b/libmaxsi/io.cpp index 09aea619..9c511841 100644 --- a/libmaxsi/io.cpp +++ b/libmaxsi/io.cpp @@ -26,6 +26,7 @@ #include "syscall.h" #include "io.h" #include "format.h" +#include namespace Maxsi { @@ -36,6 +37,7 @@ namespace Maxsi DEFN_SYSCALL1(int, SysClose, 21, int); DEFN_SYSCALL1(int, SysDup, 22, int); DEFN_SYSCALL3(int, SysOpen, 23, const char*, int, mode_t); + DEFN_SYSCALL3(int, SysReadDirEnts, 24, int, struct sortix_dirent*, size_t); size_t Print(const char* Message) { @@ -95,6 +97,11 @@ namespace Maxsi { return SysOpen(path, flags, mode); } + + extern "C" int readdirents(int fd, struct sortix_dirent* dirent, size_t size) + { + return SysReadDirEnts(fd, dirent, size); + } #endif } diff --git a/sortix/Makefile b/sortix/Makefile index b9a2547d..4e5e8b8b 100644 --- a/sortix/Makefile +++ b/sortix/Makefile @@ -72,6 +72,7 @@ thread.o \ io.o \ pipe.o \ filesystem.o \ +directory.o \ mount.o \ fs/initfs.o \ fs/ramfs.o \ diff --git a/sortix/device.h b/sortix/device.h index ec5d83c0..591f61f9 100644 --- a/sortix/device.h +++ b/sortix/device.h @@ -34,6 +34,7 @@ namespace Sortix static const unsigned BUFFER = 1; static const unsigned VGABUFFER = 2; static const unsigned FILESYSTEM = 3; + static const unsigned DIRECTORY = 4; public: Device(); diff --git a/sortix/fs/initfs.cpp b/sortix/fs/initfs.cpp index 4ae1b4df..0b919110 100644 --- a/sortix/fs/initfs.cpp +++ b/sortix/fs/initfs.cpp @@ -27,6 +27,7 @@ #include #include #include "../filesystem.h" +#include "../directory.h" #include "../stream.h" #include "initfs.h" #include "../initrd.h" @@ -133,6 +134,65 @@ namespace Sortix return false; } + class DevInitFSDir : public DevDirectory + { + public: + typedef Device DevDirectory; + + public: + DevInitFSDir(); + virtual ~DevInitFSDir(); + + private: + size_t position; + + public: + virtual void Rewind(); + virtual int Read(sortix_dirent* dirent, size_t available); + + }; + + DevInitFSDir::DevInitFSDir() + { + position = 0; + } + + DevInitFSDir::~DevInitFSDir() + { + } + + void DevInitFSDir::Rewind() + { + position = 0; + } + + int DevInitFSDir::Read(sortix_dirent* dirent, size_t available) + { + if ( available <= sizeof(sortix_dirent) ) { return -1; } + if ( InitRD::GetNumFiles() <= position ) + { + dirent->d_namelen = 0; + dirent->d_name[0] = 0; + return 0; + } + + const char* name = InitRD::GetFilename(position); + size_t namelen = String::Length(name); + size_t needed = sizeof(sortix_dirent) + namelen + 1; + + if ( available < needed ) + { + dirent->d_namelen = needed; + Error::Set(Error::EINVAL); + return 0; + } + + Memory::Copy(dirent->d_name, name, namelen + 1); + dirent->d_namelen = namelen; + position++; + return 0; + } + DevInitFS::DevInitFS() { } @@ -143,11 +203,20 @@ namespace Sortix Device* DevInitFS::Open(const char* path, int flags, mode_t mode) { + size_t buffersize; + + if ( (flags & O_LOWERFLAGS) == O_SEARCH ) + { + if ( path[0] == 0 || (path[0] == '/' && path[1] == 0) ) { return new DevInitFSDir; } + const byte* buffer = InitRD::Open(path, &buffersize); + Error::Set(buffer ? Error::ENOTDIR : Error::ENOENT); + return NULL; + } + if ( *path++ != '/' ) { return NULL; } if ( (flags & O_LOWERFLAGS) != O_RDONLY ) { Error::Set(Error::EROFS); return NULL; } - size_t buffersize; const byte* buffer = InitRD::Open(path, &buffersize); if ( !buffer ) { Error::Set(Error::ENOENT); return NULL; } diff --git a/sortix/fs/ramfs.cpp b/sortix/fs/ramfs.cpp index 45a9d4f2..8f841c25 100644 --- a/sortix/fs/ramfs.cpp +++ b/sortix/fs/ramfs.cpp @@ -27,6 +27,7 @@ #include #include #include "../filesystem.h" +#include "../directory.h" #include "../stream.h" #include "ramfs.h" @@ -162,6 +163,70 @@ namespace Sortix } } + class DevRAMFSDir : public DevDirectory + { + public: + typedef Device DevDirectory; + + public: + DevRAMFSDir(DevRAMFS* fs); + virtual ~DevRAMFSDir(); + + private: + DevRAMFS* fs; + size_t position; + + public: + virtual void Rewind(); + virtual int Read(sortix_dirent* dirent, size_t available); + + }; + + DevRAMFSDir::DevRAMFSDir(DevRAMFS* fs) + { + position = 0; + this->fs = fs; + fs->Refer(); + } + + DevRAMFSDir::~DevRAMFSDir() + { + fs->Unref(); + } + + void DevRAMFSDir::Rewind() + { + position = 0; + } + + int DevRAMFSDir::Read(sortix_dirent* dirent, size_t available) + { + if ( available <= sizeof(sortix_dirent) ) { return -1; } + if ( fs->GetNumFiles() <= position ) + { + dirent->d_namelen = 0; + dirent->d_name[0] = 0; + return 0; + } + + const char* name = fs->GetFilename(position); + if ( !name ) { return -1; } + size_t namelen = String::Length(name); + size_t needed = sizeof(sortix_dirent) + namelen + 1; + + if ( available < needed ) + { + dirent->d_namelen = needed; + Error::Set(Error::EINVAL); + return 0; + } + + Memory::Copy(dirent->d_name, name, namelen + 1); + dirent->d_namelen = namelen; + position++; + return 0; + } + int CompareFiles(DevRAMFSFile* file1, DevRAMFSFile* file2) { return String::Compare(file1->name, file2->name); @@ -174,6 +239,13 @@ namespace Sortix Device* DevRAMFS::Open(const char* path, int flags, mode_t mode) { + if ( (flags & O_LOWERFLAGS) == O_SEARCH ) + { + if ( path[0] == 0 || (path[0] == '/' && path[1] == 0) ) { return new DevRAMFSDir(this); } + Error::Set(Error::ENOTDIR); + return NULL; + } + DevBuffer* file = OpenFile(path, flags, mode); if ( !file ) { return NULL; } Device* wrapper = new DevFileWrapper(file, flags); @@ -224,5 +296,19 @@ namespace Sortix return file; } + + size_t DevRAMFS::GetNumFiles() + { + if ( !files ) { return 0; } + return files->Length(); + } + + const char* DevRAMFS::GetFilename(size_t index) + { + if ( !files ) { return NULL; } + if ( files->Length() <= index ) { return NULL; } + DevRAMFSFile* file = files->Get(index); + return file->name; + } } diff --git a/sortix/fs/ramfs.h b/sortix/fs/ramfs.h index 0c8e6277..8179ee24 100644 --- a/sortix/fs/ramfs.h +++ b/sortix/fs/ramfs.h @@ -34,7 +34,7 @@ namespace Sortix class DevRAMFS : public DevFileSystem { - public: + public: DevRAMFS(); virtual ~DevRAMFS(); @@ -44,6 +44,10 @@ namespace Sortix private: Maxsi::SortedList* files; + public: + size_t GetNumFiles(); + const char* GetFilename(size_t index); + private: virtual DevBuffer* OpenFile(const char* path, int flags, mode_t mode); virtual DevBuffer* CreateFile(const char* path, int flags, mode_t mode); diff --git a/sortix/initrd.cpp b/sortix/initrd.cpp index 041b44a3..1de84542 100644 --- a/sortix/initrd.cpp +++ b/sortix/initrd.cpp @@ -50,12 +50,26 @@ namespace Sortix } } - size_t SysGetNumFiles() + size_t GetNumFiles() { Header* header = (Header*) initrd; return header->numfiles; } + size_t SysGetNumFiles() + { + return GetNumFiles(); + } + + const char* GetFilename(size_t index) + { + Header* header = (Header*) initrd; + if ( index >= header->numfiles ) { return NULL; } + FileHeader* fhtbl = (FileHeader*) (initrd + sizeof(Header)); + FileHeader* fileheader = &(fhtbl[index]); + return fileheader->name; + } + struct FileInfo { mode_t permissions; diff --git a/sortix/initrd.h b/sortix/initrd.h index 5a826a9a..f2b5af81 100644 --- a/sortix/initrd.h +++ b/sortix/initrd.h @@ -52,6 +52,8 @@ namespace Sortix #ifdef SORTIX_KERNEL void Init(byte* initrd, size_t size); byte* Open(const char* filepath, size_t* size); + const char* GetFilename(size_t index); + size_t GetNumFiles(); #endif } } diff --git a/sortix/kernel.cpp b/sortix/kernel.cpp index 093f8b58..78961352 100644 --- a/sortix/kernel.cpp +++ b/sortix/kernel.cpp @@ -49,6 +49,7 @@ #include "pipe.h" #include "filesystem.h" #include "mount.h" +#include "directory.h" using namespace Maxsi; @@ -249,6 +250,9 @@ namespace Sortix // Initialize the filesystem system. FileSystem::Init(); + // Initialize the directory system. + Directory::Init(); + // Initialize the mount system. Mount::Init(); diff --git a/sortix/syscallnum.h b/sortix/syscallnum.h index 03883372..61f92f2f 100644 --- a/sortix/syscallnum.h +++ b/sortix/syscallnum.h @@ -49,7 +49,8 @@ #define SYSCALL_CLOSE 21 #define SYSCALL_DUP 22 #define SYSCALL_OPEN 23 -#define SYSCALL_MAX_NUM 24 /* index of highest constant + 1 */ +#define SYSCALL_READDIRENTS 24 +#define SYSCALL_MAX_NUM 25 /* index of highest constant + 1 */ #endif diff --git a/utils/ls.cpp b/utils/ls.cpp index 6ad0e954..2f3ac068 100644 --- a/utils/ls.cpp +++ b/utils/ls.cpp @@ -1,18 +1,44 @@ #include +#include +#include +#include #include #include using namespace Maxsi; +int ls(const char* path) +{ + int fd = open(path, O_SEARCH | O_DIRECTORY); + if ( fd < 0 ) { printf("ls: %s: open() failed\n", path); return 2; } + + const size_t BUFFER_SIZE = 512; + char buffer[BUFFER_SIZE]; + sortix_dirent* dirent = (sortix_dirent*) buffer; + + // TODO: Hack until mountpoints work correctly. + if ( strcmp(path, "/") == 0 ) { printf("bin\n"); } + + while ( true ) + { + if ( readdirents(fd, dirent, BUFFER_SIZE) ) + { + printf("readdirents() failed\n"); + return 1; + } + + for ( sortix_dirent* iter = dirent; iter; iter = iter->d_next ) + { + if ( iter->d_namelen == 0 ) { return 0; } + printf("%s\n", iter->d_name); + } + } +} + int main(int argc, char* argv[]) { - size_t numfiles = Process::GetNumFiles(); - for ( size_t i = 0; i < numfiles; i++ ) - { - FileInfo fileinfo; - Process::GetFileInfo(i, &fileinfo); - printf("%s\n", fileinfo.name); - } + const char* path = "/"; + if ( 1 < argc ) { path = argv[1]; } - return 0; + return ls(path); }