Added readdirents(2), which ls(1) now uses, and added dir devices.

The initfs and ramfs are now able to list their contents.
This commit is contained in:
Jonas 'Sortie' Termansen 2011-11-21 00:02:53 +01:00
parent e3bb0dfc9d
commit 23fde42249
13 changed files with 230 additions and 12 deletions

View File

@ -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 \

View File

@ -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;

View File

@ -26,6 +26,7 @@
#include "syscall.h"
#include "io.h"
#include "format.h"
#include <sys/readdirents.h>
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
}

View File

@ -72,6 +72,7 @@ thread.o \
io.o \
pipe.o \
filesystem.o \
directory.o \
mount.o \
fs/initfs.o \
fs/ramfs.o \

View File

@ -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();

View File

@ -27,6 +27,7 @@
#include <libmaxsi/string.h>
#include <libmaxsi/memory.h>
#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; }

View File

@ -27,6 +27,7 @@
#include <libmaxsi/string.h>
#include <libmaxsi/memory.h>
#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;
}
}

View File

@ -34,7 +34,7 @@ namespace Sortix
class DevRAMFS : public DevFileSystem
{
public:
public:
DevRAMFS();
virtual ~DevRAMFS();
@ -44,6 +44,10 @@ namespace Sortix
private:
Maxsi::SortedList<DevRAMFSFile*>* 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);

View File

@ -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;

View File

@ -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
}
}

View File

@ -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();

View File

@ -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

View File

@ -1,18 +1,44 @@
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <sys/readdirents.h>
#include <libmaxsi/platform.h>
#include <libmaxsi/process.h>
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);
}