From ae423eaeefbc916b2457f5a35ab9717370609e73 Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Thu, 17 Nov 2011 23:31:41 +0100 Subject: [PATCH] Added open(2). Please note that mount points and file systems do not exist yet. --- libmaxsi/c/hsrc/fcntl.h | 4 +- libmaxsi/io.cpp | 6 + sortix/Makefile | 2 + sortix/filesystem.cpp | 60 +++++++++ sortix/filesystem.h | 74 ++++------- sortix/kernel.cpp | 8 ++ sortix/mount.cpp | 279 ++-------------------------------------- sortix/mount.h | 37 +----- sortix/syscallnum.h | 3 +- 9 files changed, 112 insertions(+), 361 deletions(-) create mode 100644 sortix/filesystem.cpp diff --git a/libmaxsi/c/hsrc/fcntl.h b/libmaxsi/c/hsrc/fcntl.h index ecb24876..04d032f4 100644 --- a/libmaxsi/c/hsrc/fcntl.h +++ b/libmaxsi/c/hsrc/fcntl.h @@ -46,7 +46,7 @@ __BEGIN_DECLS #define O_RDONLY 00 #define O_WRONLY 01 #define O_RDWR 02 -#define O_CREAT 0100 +#define O_CREAT (1<<5) #define O_EXCL 0200 #define O_NOCTTY 0400 #define O_TRUNC 01000 @@ -82,10 +82,10 @@ struct _flock typedef struct _flock flock; /* TODO: These are not implemented in libmaxsi/sortix yet. */ +int open(const char* path, int oflag, ...); #ifndef SORTIX_UNIMPLEMENTED int creat(const char* path, mode_t mode); int fcntl(int fd, int cmd, ...); -int open(const char* path, int oflag, ...); int openat(int fd, const char* path, int oflag, ...); #endif diff --git a/libmaxsi/io.cpp b/libmaxsi/io.cpp index be89feab..09aea619 100644 --- a/libmaxsi/io.cpp +++ b/libmaxsi/io.cpp @@ -35,6 +35,7 @@ namespace Maxsi DEFN_SYSCALL1(int, SysPipe, 20, int*); DEFN_SYSCALL1(int, SysClose, 21, int); DEFN_SYSCALL1(int, SysDup, 22, int); + DEFN_SYSCALL3(int, SysOpen, 23, const char*, int, mode_t); size_t Print(const char* Message) { @@ -89,6 +90,11 @@ namespace Maxsi { return SysDup(fd); } + + extern "C" int open(const char* path, int flags, mode_t mode) + { + return SysOpen(path, flags, mode); + } #endif } diff --git a/sortix/Makefile b/sortix/Makefile index 646ade9c..8d54c525 100644 --- a/sortix/Makefile +++ b/sortix/Makefile @@ -71,6 +71,8 @@ initrd.o \ thread.o \ io.o \ pipe.o \ +filesystem.o \ +mount.o \ ../libmaxsi/libmaxsi-sortix.a JSOBJS:=$(subst .o,-js.o,$(OBJS)) diff --git a/sortix/filesystem.cpp b/sortix/filesystem.cpp new file mode 100644 index 00000000..9079ae92 --- /dev/null +++ b/sortix/filesystem.cpp @@ -0,0 +1,60 @@ +/****************************************************************************** + + COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011. + + This file is part of Sortix. + + Sortix is free software: you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) any later + version. + + Sortix is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + details. + + You should have received a copy of the GNU General Public License along + with Sortix. If not, see . + + filesystem.cpp + Allows access to stored sequences of bytes in an orderly fashion. + +******************************************************************************/ + +#include "platform.h" +#include "syscall.h" +#include "process.h" +#include "filesystem.h" +#include "mount.h" + +namespace Sortix +{ + namespace FileSystem + { + Device* Open(const char* path, int flags, mode_t mode) + { + size_t pathoffset = 0; + DevFileSystem* fs = Mount::WhichFileSystem(path, &pathoffset); + if ( !fs ) { return NULL; } + return fs->Open(path + pathoffset, flags, mode); + } + + int SysOpen(const char* path, int flags, mode_t mode) + { + Process* process = CurrentProcess(); + Device* dev = Open(path, flags, mode); + if ( !dev ) { return -1; /* TODO: errno */ } + int fd = process->descriptors.Allocate(dev); + if ( fd < 0 ) { dev->Unref(); } + return fd; + } + + void Init() + { + Syscall::Register(SYSCALL_OPEN, (void*) SysOpen); + } + } +} + + diff --git a/sortix/filesystem.h b/sortix/filesystem.h index 592d394a..ad734967 100644 --- a/sortix/filesystem.h +++ b/sortix/filesystem.h @@ -18,7 +18,7 @@ with Sortix. If not, see . filesystem.h - Abstracts away a file system device. + Allows access to stored sequences of bytes in an orderly fashion. ******************************************************************************/ @@ -26,71 +26,41 @@ #define SORTIX_FILESYSTEM_H #include "device.h" -#include "mount.h" namespace Sortix { - class Thread; - - namespace FileSystem - { - struct SysCallback - { - Device* device; - union { int deviceError; nat deviceType; } - } - } - // TODO: These belong in libmaxsi! - - const nat O_RDONLY = 1; - const nat O_WRONLY = 2; - const nat O_RDWR = 3; - const nat O_EXEC = 4; - const nat O_SEARCH = 5; - const nat O_LOWERFLAGS = 0x7; - // TODO: Sortix might never support all of these flags if they are stupid. - const nat O_APPEND = (1<<3); - const nat O_CLOEXEC = (1<<4); - const nat O_CREAT = (1<<5); - const nat O_DIRECTORY = (1<<6); - const nat O_DSYNC = (1<<6); - const nat O_EXCL = (1<<7); - const nat O_NOCTTY = (1<<8); - const nat O_NOFOLLOW = (1<<9); - const nat O_RSYNC = (1<<11); - const nat O_SYNC = (1<<12); - const nat O_TRUNC = (1<<13); - const nat O_TTY_INIT = (1<<13); - - // If O_RDONLY, then no one is allowed to write to this, or if O_RDWD then - // no one else is allowed to use this besides me. - const nat O_EXCLUSIVELY = (1<<14); - const nat O_USERSPACEABLE = ((1<<15)-1); - - const nat O_MOUNT = (1<<31); + const int O_RDONLY = 1; + const int O_WRONLY = 2; + const int O_RDWR = 3; + const int O_EXEC = 4; + const int O_SEARCH = 5; + const int O_LOWERFLAGS = 0x7; + const int O_APPEND = (1<<3); + const int O_CLOEXEC = (1<<4); + const int O_CREAT = (1<<5); + const int O_DIRECTORY = (1<<6); + const int O_DSYNC = (1<<6); + const int O_EXCL = (1<<7); + const int O_NOCTTY = (1<<8); + const int O_NOFOLLOW = (1<<9); + const int O_RSYNC = (1<<11); + const int O_SYNC = (1<<12); + const int O_TRUNC = (1<<13); + const int O_TTY_INIT = (1<<13); class DevFileSystem : public Device { public: - DevFileSystem() { }; - virtual ~DevFileSystem() { } - - public: - bool LegalNodeName(const char* name); - - public: - virtual int Initialize(MountPoint* mountPoint, const char* commandLine) = 0; - - public: - virtual bool Open(const char* path, nat openFlags, nat mode, FileSystem::SysCallback* callbackInfo, Thread* thread); + virtual Device* Open(const char* path, int flags, mode_t mode) = 0; }; namespace FileSystem { - DevFileSystem* CreateDriver(const char* fsType); + void Init(); + Device* Open(const char* path, int flags, mode_t mode); } } diff --git a/sortix/kernel.cpp b/sortix/kernel.cpp index 785a7b99..093f8b58 100644 --- a/sortix/kernel.cpp +++ b/sortix/kernel.cpp @@ -47,6 +47,8 @@ #include "sound.h" #include "io.h" #include "pipe.h" +#include "filesystem.h" +#include "mount.h" using namespace Maxsi; @@ -244,6 +246,12 @@ namespace Sortix // Initialize the pipe system. Pipe::Init(); + // Initialize the filesystem system. + FileSystem::Init(); + + // Initialize the mount system. + Mount::Init(); + // Initialize the scheduler. Scheduler::Init(); diff --git a/sortix/mount.cpp b/sortix/mount.cpp index dddcda92..57127662 100644 --- a/sortix/mount.cpp +++ b/sortix/mount.cpp @@ -23,283 +23,22 @@ ******************************************************************************/ #include "platform.h" -#include -#include "device.h" -#include "filesystem.h" -#include "thread.h" -#include "process.h" -#include "memorymanagement.h" +#include "mount.h" namespace Sortix { - namespace Syscall - { - void SysOpen(Thread* thread) - { - struct Parameters - { - struct - { - const char* USER userPath SYSPARAM; - nat openFlags SYSPARAM; - nat mode SYSPARAM; - }; - struct - { - int handle; - bool pending; - FileSystem::SysCallback callbackInfo; - const char* safePath; - }; - }; - - // We store our parameters and data inside the thread object, and we - // are passed parameters in a special way, so make sure it works. - STATIC_ASSERT(0 * sizeof(size_t) == offsetof(Parameters, userPath)); - STATIC_ASSERT(1 * sizeof(size_t) == offsetof(Parameters, openflags)); - STATIC_ASSERT(2 * sizeof(size_t) == offsetof(Parameters, mode)); - STATIC_ASSERT(sizeof(Parameters) <= sizeof(thread->sysParams)); - Parameters* params = (Parameters*) thread->sysParams; - - int handle; - const char* path; - - // Initialize our variables and validate parameters. - if ( !thread->sysParamsInited ) - { - thread->sysParamsInited = true; - params->handle = handle = -1; - params->pending = false; - - // Make sure the path is a valid string in userspace. - params->safePath = path = ValidateUserString(params->userPath) - if ( path == NULL ) { thread->SysReturnError(-1); return; } - - params->openFlags &= O_USERSPACEABLE; - } - else - { - path = params->safePath; - handle = param->handle; - } - - // Get a descriptor for our device. - if ( handle == -1 ) - { - param->handle = handle = thread->GetProcess()->_descs.Reserve(); - if ( handle < 0 ) { thread->SysReturnError(handle); return; } - } - - // Attempt to open the path. If the operation is blocking, this - // function will re-called when it completes, successful or not. - if ( !params->pending ) - { - params->pending = true; - - MountPoint* mount = Mount::GetMountPoint(path); - if ( mount == NULL ) { Error::Set(Error::BADINPUT); thread->SysReturnError(-1); return; } - - if ( !mount->fs->Open(path, params->openFlags, params->mode, ¶ms->callbackInfo, thread) ) { return; } - } - - // Return an error if the open failed. - if ( unlikely(params->callbackInfo.device == NULL) ) - { - handle = thread->GetProcess()->_descs.Free(handle); - Error::Set(params->callbackInfo.deviceError); - thread->SysReturnError(-1); return; - } - - // Bind the device to the descriptor and return it. - handle = thread->GetProcess()->_descs.UseReservation(handle, params->callbackInfo.device); - thread->SysReturn(handle); return; - } - - void SysMount(Thread* thread) - { - struct Parameters - { - struct - { - const char* USER userDevicePath SYSPARAM; - const char* USER userTargetPath SYSPARAM; - const char* USER userDriverName SYSPARAM; - nat mode SYSPARAM; - }; - struct - { - int stage; - DevBuffer* storage; - DevFileSystem* fsDriver; - DevDirectory* directory; - FileSystem::SysCallback callbackInfo; - }; - }; - - // We store our parameters and data inside the thread object, and we - // are passed parameters in a special way, so make sure it works. - STATIC_ASSERT(0 * sizeof(size_t) == offsetof(Parameters, userDevicePath)); - STATIC_ASSERT(1 * sizeof(size_t) == offsetof(Parameters, userTargetPath)); - STATIC_ASSERT(2 * sizeof(size_t) == offsetof(Parameters, userDriverName)); - STATIC_ASSERT(3 * sizeof(size_t) == offsetof(Parameters, mode)); - STATIC_ASSERT(sizeof(Parameters) <= sizeof(thread->sysParams)); - Parameters* params = (Parameters*) thread->sysParams; - - // Initialize our variables and validate parameters. - if ( !thread->sysParamsInited ) - { - thread->sysParamsInited = true; - if ( ValidateUserString(params->userDevicePath) == NULL || - ValidateUserString(params->userTargetPath) == NULL || - ( params->userDriverName != NULL && - ValidateUserString(params->userDriverName) == NULL ) ) - { - thread->SysReturnError(-1); return; - } - - params->mode &= O_USERSPACEABLE; - nat baseMode = params->mode & O_LOWERFLAGS; - nat extMode = params->mode & (~O_LOWERFLAGS); - - // Deny unsupported open modes. - if ( (baseMode != O_RDWR && baseMode != O_RDONLY) || - (extMode != 0 && extMode != O_EXCLUSIVELY && extMode != O_SYNC) ) - { - Error::Set(Error::BADINPUT); - thread->SysReturnError(-1); return; - } - - params->stage = 0; - params->storage = NULL; - params->fsDriver = NULL; - params->directory = NULL; - } - - MountPoint* mount; - Device* device = NULL; - - switch ( params->stage ) - { - // Get a handle to the storage device. - case 0: params->stage++; - - mount = Mount::GetMountPoint(¶ms->userDevicePath); - if ( mount == NULL ) { Error::Set(Error::BADINPUT); break; } - - ASSERT(params->mode & O_USERSPACEABLE == 0); - if ( !mount->fs->Open(params->userDevicePath, params->mode | O_EXCLUSIVELY, 0, ¶ms->callbackInfo, thread) ) { return; } - - // Validate the properness of the storage device. - case 1: params->stage++; - device = params->callbackInfo.device; - - // Did it exist/could we open it/did we have permission? - if ( unlikely(device == NULL) ) { Error::Set(params->callbackInfo.deviceError); break; } - - // Is it a buffer? - if ( unlikely(!device->IsType(Device::BUFFER)) ) { Error::Set(Error::ENOTBLK); break; } - - params->storage = (DevBuffer*) device; device = NULL; - - // Get a handle to the destination directory. - case 2: params->stage++; - - mount = Mount::GetMountPoint(¶ms->userTargetPath); - if ( mount == NULL ) { Error::Set(Error::BADINPUT); break; } - - // TODO: Figure out some good mode flags here! - // TODO: Make sure the FS driver forces the dest dir to be empty! - if ( !mount->fs->Open(params->userTargetPath, O_RDWR | O_DIRECTORY | O_MOUNT, 0, ¶ms->callbackInfo, thread) ) { return; } - - // Validate the properness of the destination directory. - case 2: params->stage++; - device = params->callbackInfo.device; - - // Did it exist/could we open it? - if ( unlikely(device == NULL) ) { Error::Set(params->callbackInfo.deviceError); break; } - - // Is it a directory? - if ( unlikely(!device->IsType(Device::DIRECTORY)) ) { Error::Set(Error::ENOTDIR); break; } - - params->directory = (DevDirectory*) device; device = NULL; - - // Validate that the user owns the directory. - if ( !params->directory->IsOwner(thread->GetProcess()->GetUser()) ) { Error::Set(Error::EPERM); break; } - - // TODO: Add a run-time assertion that the dir is empty! - - // Load the proper driver for this file system type. - case 3: params->stage++; - - // TODO: Make an async interface that can scan a device! - params->fsDriver = FileSystem::CreateDriver(params->userDriverName); - if ( params->fsDriver == NULL ) { Error::Set(Error::ENODEV); break; } - - // Now bind the file system driver to the device and directory. - case 4: params->stage++; - MountPoint* newMount = new MountPoint(); - - newMount->device = params->storage; - newMount->fs = params->fsDriver; - - // TODO: Actually do the mounting! - - // Check if everything went well. - case 4: - // TODO: Check if everything went well! - thread->SysReturn(0); return; - } - - if ( device != NULL ) { device->close(); } - if ( params->storage != NULL ) { params->storage->close(); } - if ( params->directory != NULL ) { params->directory->close(); } - if ( params->fsDriver != NULL ) { params->fsDriver->close(); } - - thread->SysReturnError(-1); return; - } - } - namespace Mount { - MountPoint* GetMountPoint(const char** path, Thread* thread) + DevFileSystem* WhichFileSystem(const char* path, size_t* pathoffset) { - ASSERT(path != NULL); - ASSERT(*path != NULL); - ASSERT(thread != NULL); + // TODO: Support some file systems! + *pathoffset = 0; + return NULL; + } - if ( unlikely(**path != '/') ) { return NULL; } (*path)++; - MountPoint* currentFS = thread->GetProcess->GetRootFS(); - - ASSERT(currentFS != NULL); - - // Simply check if path belongs to a child mount point. - for ( MountPoint* considering = currentFS->child; considering != NULL; considering = considering->nextSibling ) - { - ASSERT(considering->IsSane()); - - size_t consideringPathLen = String::Length(considering->path); - if ( String::CompareN(*path, considering->path, consideringPathLen) == 0 ) - { - // Check if this is the right dir! - char lastChar = (*path)[consideringPathLen]; - - if ( lastChar == '/' ) { (*path) += consideringPathLen + 1; } - else if ( lastChar == '\0' ) { (*path) += consideringPathLen + 0; } - else { continue; } - - // Check if the mountpoint isn't ready. - if ( considering->waiting != NULL ) { Error::Set(Error::EBUSY); return NULL; } - - currentFS = considering; - considering = currentFS->child; - } - } - - ASSERT(currentFS->fs != NULL); - - return currentFS; + void Init() + { + } } } - - diff --git a/sortix/mount.h b/sortix/mount.h index a56781d8..b6e7a624 100644 --- a/sortix/mount.h +++ b/sortix/mount.h @@ -27,47 +27,12 @@ namespace Sortix { - class Device; class DevFileSystem; - class DevBuffer; - class Process; - - class MountPoint - { - public: - MountPoint(); - ~MountPoint(); - - public: - const char* path; - DevFileSystem* fs; - DevBuffer* device; - nat flags; - - public: - Thread* waiting; - int* waitingResult; - - public: - bool Mount(); - - public: - bool IsSane() { return path != NULL && fs != NULL && device != NULL; } - - }; namespace Mount { void Init(); - MountPoint* GetMountPoint(const char*& path, Thread* thread); - void OnMountFailure(MountPoint* mountPoint, int cause); - void OnMountSuccess(MountPoint* mountPoint); - } - - namespace Syscall - { - void SysOpen(Thread* thread); - void SysMount(Thread* thread); + DevFileSystem* WhichFileSystem(const char* path, size_t* pathoffset); } } diff --git a/sortix/syscallnum.h b/sortix/syscallnum.h index a9678856..03883372 100644 --- a/sortix/syscallnum.h +++ b/sortix/syscallnum.h @@ -48,7 +48,8 @@ #define SYSCALL_PIPE 20 #define SYSCALL_CLOSE 21 #define SYSCALL_DUP 22 -#define SYSCALL_MAX_NUM 23 /* index of highest constant + 1 */ +#define SYSCALL_OPEN 23 +#define SYSCALL_MAX_NUM 24 /* index of highest constant + 1 */ #endif