diff --git a/libmaxsi/Makefile b/libmaxsi/Makefile index 61b4c160..6e2693fd 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/errno.h \ c/h/sys/readdirents.h \ c/h/sys/stat.h \ c/h/sys/types.h \ diff --git a/libmaxsi/c/hsrc/errno.h b/libmaxsi/c/hsrc/errno.h new file mode 100644 index 00000000..fa35f953 --- /dev/null +++ b/libmaxsi/c/hsrc/errno.h @@ -0,0 +1,37 @@ +/****************************************************************************** + + COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011. + + This file is part of LibMaxsi. + + LibMaxsi is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + LibMaxsi 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 Lesser General Public License for + more details. + + You should have received a copy of the GNU Lesser General Public License + along with LibMaxsi. If not, see . + + errno.h + System error numbers. + +******************************************************************************/ + +#ifndef _ERRNO_H +#define _ERRNO_H 1 + +#include + +__BEGIN_DECLS + +@include(errno_decl.h) +@include(errno_values.h) + +__END_DECLS + +#endif diff --git a/libmaxsi/c/hsrc/string.h b/libmaxsi/c/hsrc/string.h index fc0e2b56..6379e953 100644 --- a/libmaxsi/c/hsrc/string.h +++ b/libmaxsi/c/hsrc/string.h @@ -37,6 +37,7 @@ void* memcpy(void* restrict, const void* restrict, size_t); char* strcat(char* restrict, const char* restrict); int strcmp(const char*, const char*); char* strcpy(char* restrict, const char* restrict); +char* strerror(int); size_t strlen(const char*); int strncmp(const char*, const char*, size_t); @@ -54,7 +55,6 @@ int strcoll(const char*, const char*); int strcoll_l(const char*, const char*, locale_t); size_t strcspn(const char*, const char*); char* strdup(const char*); -char* strerror(int); char* strerror_l(int, locale_t); int strerror_r(int, char*, size_t); char* strncat(char* restrict, const char* restrict, size_t); diff --git a/libmaxsi/decl/errno_decl.h b/libmaxsi/decl/errno_decl.h new file mode 100644 index 00000000..5ff1b35a --- /dev/null +++ b/libmaxsi/decl/errno_decl.h @@ -0,0 +1,6 @@ +#ifndef _ERRNO_DECL +#define _ERRNO_DECL + +extern volatile int errno; + +#endif diff --git a/libmaxsi/decl/errno_values.h b/libmaxsi/decl/errno_values.h new file mode 100644 index 00000000..abe8b545 --- /dev/null +++ b/libmaxsi/decl/errno_values.h @@ -0,0 +1,21 @@ +#ifndef _ERRNO_VALUES_DECL +#define _ERRNO_VALUES_DECL + +#define ENOTBLK 12 +#define ENODEV 13 +#define EWOULDBLOCK 14 +#define EBADF 15 +#define EOVERFLOW 16 +#define ENOENT 17 +#define ENOSPC 18 +#define EEXIST 19 +#define EROFS 20 +#define EINVAL 21 +#define ENOTDIR 22 +#define ENOMEM 23 +#define ERANGE 24 +#define EISDIR 25 +#define EPERM 26 +#define EIO 27 + +#endif diff --git a/libmaxsi/error.cpp b/libmaxsi/error.cpp index a2bb1992..97f6364e 100644 --- a/libmaxsi/error.cpp +++ b/libmaxsi/error.cpp @@ -22,14 +22,47 @@ ******************************************************************************/ +#include "platform.h" #include "error.h" +#include "syscall.h" namespace Maxsi { namespace Error { - // TODO: merge with errno interface. - int _errornumber; + DEFN_SYSCALL1(int, SysRegisterErrno, 28, int*); + + extern "C" int errno = 0; + + extern "C" void init_error_functions() + { + errno = 0; + SysRegisterErrno(&errno); + } + + extern "C" char* strerror(int code) + { + switch ( code ) + { + case ENOTBLK: return (char*) "Block device required"; + case ENODEV: return (char*) "No such device"; + case EWOULDBLOCK: return (char*) "Operation would block"; + case EBADF: return (char*) "Bad file descriptor"; + case EOVERFLOW: return (char*) "Value too large to be stored in data type"; + case ENOENT: return (char*) "No such file or directory"; + case ENOSPC: return (char*) "No space left on device"; + case EEXIST: return (char*) "File exists"; + case EROFS: return (char*) "Read-only file system"; + case EINVAL: return (char*) "Invalid argument"; + case ENOTDIR: return (char*) "Not a directory"; + case ENOMEM: return (char*) "Not enough space"; + case ERANGE: return (char*) "Result too large"; + case EISDIR: return (char*) "Is a directory"; + case EPERM: return (char*) "Permission denied"; + case EIO: return (char*) "Input/output error"; + default: return (char*) "Unknown error condition"; + } + } } } diff --git a/libmaxsi/hsrc/error.h b/libmaxsi/hsrc/error.h index 369d500f..f2f9dbe8 100644 --- a/libmaxsi/hsrc/error.h +++ b/libmaxsi/hsrc/error.h @@ -25,46 +25,18 @@ #ifndef LIBMAXSI_ERROR_H #define LIBMAXSI_ERROR_H +extern "C" +{ +@include(errno_decl.h); +@include(errno_values.h) +} + namespace Maxsi { namespace Error { - // TODO: merge with errno interface. - - const int SUCCESS = 0; - const int NONE = 1; - const int DENIED = 2; - const int NOTFOUND = 3; - const int NOSUPPORT = 4; - const int NOTIMPLEMENTED = 5; - const int PENDING = 6; - const int BADINPUT = 7; - const int CORRUPT = 8; - const int NOMEM = 9; - const int NOTDIR = 10; - const int ISDIR = 11; - - const int ENOTBLK = 12; - const int ENODEV = 13; - const int EWOULDBLOCK = 14; - const int EBADF = 15; - const int EOVERFLOW = 16; - const int ENOENT = 17; - const int ENOSPC = 18; - const int EEXIST = 19; - const int EROFS = 20; - const int EINVAL = 21; - const int ENOTDIR = 22; - const int ENOMEM = 23; - const int ERANGE = 24; - const int EISDIR = 25; - const int EPERM = 26; - const int EIO = 27; - - extern int _errornumber; - - inline int Last() { return _errornumber; } - inline void Set(int error) { _errornumber = error; } + inline int Last() { return errno; } + inline void Set(int error) { errno = error; } } } diff --git a/libmaxsi/init.cpp b/libmaxsi/init.cpp index 9aa4e4e4..7a9c5eef 100644 --- a/libmaxsi/init.cpp +++ b/libmaxsi/init.cpp @@ -27,8 +27,10 @@ namespace Maxsi { + extern "C" void init_error_functions(); + extern "C" void initialize_standard_library() { - + init_error_functions(); } } diff --git a/libmaxsi/memory.cpp b/libmaxsi/memory.cpp index a2090879..6a98ba0b 100644 --- a/libmaxsi/memory.cpp +++ b/libmaxsi/memory.cpp @@ -379,7 +379,7 @@ namespace Maxsi else { // We have no free chunks that are big enough, let's expand our heap into the unknown, if possible. - if ( WildernessSize < Size && !ExpandWilderness(Size) ) { Error::Set(Error::NOMEM); return NULL; } + if ( WildernessSize < Size && !ExpandWilderness(Size) ) { Error::Set(ENOMEM); return NULL; } // Write some headers and footers around our newly allocated data. UsedChunkHeader* ResultHeader = (UsedChunkHeader*) (Wilderness + WildernessSize - Size); diff --git a/libmaxsi/x86/start.s b/libmaxsi/x86/start.s index bf396595..567757ab 100644 --- a/libmaxsi/x86/start.s +++ b/libmaxsi/x86/start.s @@ -30,11 +30,13 @@ .type _start, @function _start: + # Arguments for main + push %ebx # argv + push %eax # argc + call initialize_standard_library # Run main - push %ebx # argv - push %eax # argc call main # Terminate the process with main's exit code. diff --git a/sortix/directory.cpp b/sortix/directory.cpp index 3ce2f3cd..f2ab934d 100644 --- a/sortix/directory.cpp +++ b/sortix/directory.cpp @@ -43,8 +43,8 @@ namespace Sortix { Process* process = CurrentProcess(); Device* dev = process->descriptors.Get(fd); - if ( !dev ) { Error::Set(Error::EBADF); return -1; } - if ( !dev->IsType(Device::DIRECTORY) ) { Error::Set(Error::EBADF); return -1; } + if ( !dev ) { Error::Set(EBADF); return -1; } + if ( !dev->IsType(Device::DIRECTORY) ) { Error::Set(EBADF); return -1; } DevDirectory* dir = (DevDirectory*) dev; sortix_dirent* prev = NULL; @@ -56,7 +56,7 @@ namespace Sortix if ( size < sizeof(sortix_dirent) ) { if ( prev ) { return 0; } // We did some work. - Error::Set(Error::EINVAL); // Nope, userspace was cheap. + Error::Set(EINVAL); // Nope, userspace was cheap. return -1; } @@ -92,7 +92,7 @@ namespace Sortix Process* process = CurrentProcess(); const char* wd = process->workingdir; char* abs = MakeAbsolute(wd, path); - if ( !abs ) { Error::Set(Error::ENOMEM); return -1; } + if ( !abs ) { Error::Set(ENOMEM); return -1; } size_t abslen = String::Length(abs); if ( 1 < abslen && abs[abslen-1] == '/' ) { @@ -102,9 +102,9 @@ namespace Sortix // Lookup the path and see if it is a directory. size_t pathoffset = 0; DevFileSystem* fs = Mount::WhichFileSystem(abs, &pathoffset); - if ( !fs ) { delete[] abs; Error::Set(Error::EINVAL); return -1; } + if ( !fs ) { delete[] abs; Error::Set(EINVAL); return -1; } Device* dev = fs->Open(abs + pathoffset, O_SEARCH | O_DIRECTORY, 0); - if ( !dev ) { Error::Set(Error::ENOTDIR); return -1; } + if ( !dev ) { Error::Set(ENOTDIR); return -1; } dev->Unref(); // Alright, the path passed. @@ -121,7 +121,7 @@ namespace Sortix const char* wd = process->workingdir; if ( !wd ) { wd = "/"; } size_t wdsize = String::Length(wd) + 1; - if ( size < wdsize ) { Error::Set(Error::ERANGE); return NULL; } + if ( size < wdsize ) { Error::Set(ERANGE); return NULL; } String::Copy(buf, wd); return buf; } diff --git a/sortix/filesystem.cpp b/sortix/filesystem.cpp index 9df92937..2cd600f8 100644 --- a/sortix/filesystem.cpp +++ b/sortix/filesystem.cpp @@ -43,7 +43,7 @@ namespace Sortix Process* process = CurrentProcess(); const char* wd = process->workingdir; char* abs = Directory::MakeAbsolute(wd, path); - if ( !abs ) { Error::Set(Error::ENOMEM); return NULL; } + if ( !abs ) { Error::Set(ENOMEM); return NULL; } size_t pathoffset = 0; DevFileSystem* fs = Mount::WhichFileSystem(abs, &pathoffset); @@ -58,7 +58,7 @@ namespace Sortix Process* process = CurrentProcess(); const char* wd = process->workingdir; char* abs = Directory::MakeAbsolute(wd, path); - if ( !abs ) { Error::Set(Error::ENOMEM); return false; } + if ( !abs ) { Error::Set(ENOMEM); return false; } size_t pathoffset = 0; DevFileSystem* fs = Mount::WhichFileSystem(abs, &pathoffset); diff --git a/sortix/fs/devfs.cpp b/sortix/fs/devfs.cpp index b153827d..3419c524 100644 --- a/sortix/fs/devfs.cpp +++ b/sortix/fs/devfs.cpp @@ -188,7 +188,7 @@ namespace Sortix if ( available < needed ) { dirent->d_namelen = needed; - Error::Set(Error::EINVAL); + Error::Set(EINVAL); return 0; } @@ -211,14 +211,14 @@ namespace Sortix if ( (flags & O_LOWERFLAGS) == O_SEARCH ) { if ( path[0] == 0 || (path[0] == '/' && path[1] == 0) ) { return new DevDevFSDir(); } - Error::Set(Error::ENOTDIR); + Error::Set(ENOTDIR); return NULL; } if ( String::Compare(path, "/null") == 0 ) { return new DevNull; } if ( String::Compare(path, "/tty") == 0 ) { return new DevLogTTY; } - Error::Set(Error::ENOENT); + Error::Set(ENOENT); return NULL; } @@ -226,11 +226,11 @@ namespace Sortix { if ( *path == '\0' || ( *path++ == '/' && *path == '\0' ) ) { - Error::Set(Error::EISDIR); + Error::Set(EISDIR); return false; } - Error::Set(Error::EPERM); + Error::Set(EPERM); return true; } } diff --git a/sortix/fs/initfs.cpp b/sortix/fs/initfs.cpp index eeec274d..5578ac8b 100644 --- a/sortix/fs/initfs.cpp +++ b/sortix/fs/initfs.cpp @@ -97,14 +97,14 @@ namespace Sortix bool DevInitFSFile::Seek(uintmax_t position) { - if ( SIZE_MAX < position ) { Error::Set(Error::EOVERFLOW); return false; } + if ( SIZE_MAX < position ) { Error::Set(EOVERFLOW); return false; } offset = position; return true; } bool DevInitFSFile::Resize(uintmax_t /*size*/) { - Error::Set(Error::EBADF); + Error::Set(EBADF); return false; } @@ -121,7 +121,7 @@ namespace Sortix ssize_t DevInitFSFile::Write(const byte* /*src*/, size_t /*count*/) { - Error::Set(Error::EBADF); + Error::Set(EBADF); return false; } @@ -184,7 +184,7 @@ namespace Sortix if ( available < needed ) { dirent->d_namelen = needed; - Error::Set(Error::EINVAL); + Error::Set(EINVAL); return 0; } @@ -210,29 +210,29 @@ namespace Sortix { 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); + Error::Set(buffer ? ENOTDIR : ENOENT); return NULL; } if ( *path++ != '/' ) { return NULL; } - if ( (flags & O_LOWERFLAGS) != O_RDONLY ) { Error::Set(Error::EROFS); return NULL; } + if ( (flags & O_LOWERFLAGS) != O_RDONLY ) { Error::Set(EROFS); return NULL; } const byte* buffer = InitRD::Open(path, &buffersize); - if ( !buffer ) { Error::Set(Error::ENOENT); return NULL; } + if ( !buffer ) { Error::Set(ENOENT); return NULL; } char* newpath = String::Clone(path); - if ( !newpath ) { Error::Set(Error::ENOSPC); return NULL; } + if ( !newpath ) { Error::Set(ENOSPC); return NULL; } Device* result = new DevInitFSFile(newpath, buffer, buffersize); - if ( !result ) { delete[] newpath; Error::Set(Error::ENOSPC); return NULL; } + if ( !result ) { delete[] newpath; Error::Set(ENOSPC); return NULL; } return result; } bool DevInitFS::Unlink(const char* path) { - Error::Set(Error::EROFS); + Error::Set(EROFS); return false; } } diff --git a/sortix/fs/ramfs.cpp b/sortix/fs/ramfs.cpp index 4251d2c8..b3e36401 100644 --- a/sortix/fs/ramfs.cpp +++ b/sortix/fs/ramfs.cpp @@ -96,16 +96,16 @@ namespace Sortix bool DevRAMFSFile::Seek(uintmax_t position) { - if ( SIZE_MAX < position ) { Error::Set(Error::EOVERFLOW); return false; } + if ( SIZE_MAX < position ) { Error::Set(EOVERFLOW); return false; } offset = position; return true; } bool DevRAMFSFile::Resize(uintmax_t size) { - if ( SIZE_MAX < size ) { Error::Set(Error::EOVERFLOW); return false; } + if ( SIZE_MAX < size ) { Error::Set(EOVERFLOW); return false; } byte* newbuffer = new byte[size]; - if ( !newbuffer ) { Error::Set(Error::ENOSPC); return false; } + if ( !newbuffer ) { Error::Set(ENOSPC); return false; } size_t sharedmemsize = ( size < buffersize ) ? size : buffersize; Memory::Copy(newbuffer, buffer, sharedmemsize); delete[] buffer; @@ -217,7 +217,7 @@ namespace Sortix if ( available < needed ) { dirent->d_namelen = needed; - Error::Set(Error::EINVAL); + Error::Set(EINVAL); return 0; } @@ -246,23 +246,23 @@ namespace Sortix return new DevRAMFSDir(this); } - Error::Set(Error::EISDIR); + Error::Set(EISDIR); return NULL; } DevBuffer* file = OpenFile(path, flags, mode); if ( !file ) { return NULL; } Device* wrapper = new DevFileWrapper(file, flags); - if ( !wrapper ) { Error::Set(Error::ENOSPC); return NULL; } + if ( !wrapper ) { Error::Set(ENOSPC); return NULL; } return wrapper; } DevBuffer* DevRAMFS::OpenFile(const char* path, int flags, mode_t mode) { - if ( *path++ != '/' ) { Error::Set(Error::ENOENT); return NULL; } + if ( *path++ != '/' ) { Error::Set(ENOENT); return NULL; } // Hack to prevent / from being a filename. - if ( path == 0 ) { Error::Set(Error::ENOENT); return NULL; } + if ( path == 0 ) { Error::Set(ENOENT); return NULL; } if ( files ) { @@ -280,26 +280,26 @@ namespace Sortix DevBuffer* DevRAMFS::CreateFile(const char* path, int flags, mode_t mode) { - if ( !(flags & O_CREAT) ) { Error::Set(Error::ENOENT); return NULL; } + if ( !(flags & O_CREAT) ) { Error::Set(ENOENT); return NULL; } if ( !files ) { files = new SortedList(CompareFiles); - if ( !files) { Error::Set(Error::ENOSPC); return NULL; } + if ( !files) { Error::Set(ENOSPC); return NULL; } } if ( files->Search(LookupFile, path) != SIZE_MAX ) { - Error::Set(Error::EEXIST); + Error::Set(EEXIST); return NULL; } char* newpath = String::Clone(path); - if ( !newpath ) { Error::Set(Error::ENOSPC); return NULL; } + if ( !newpath ) { Error::Set(ENOSPC); return NULL; } DevRAMFSFile* file = new DevRAMFSFile(newpath); - if ( !file ) { delete[] newpath; Error::Set(Error::ENOSPC); return NULL; } - if ( !files->Add(file) ) { delete file; Error::Set(Error::ENOSPC); return NULL; } + if ( !file ) { delete[] newpath; Error::Set(ENOSPC); return NULL; } + if ( !files->Add(file) ) { delete file; Error::Set(ENOSPC); return NULL; } file->Refer(); @@ -310,12 +310,12 @@ namespace Sortix { if ( *path == '\0' || ( *path++ == '/' && *path == '\0' ) ) { - Error::Set(Error::EISDIR); + Error::Set(EISDIR); return false; } size_t index = files->Search(LookupFile, path); - if ( index == SIZE_MAX ) { Error::Set(Error::ENOENT); return false; } + if ( index == SIZE_MAX ) { Error::Set(ENOENT); return false; } Device* dev = files->Remove(index); ASSERT(dev); diff --git a/sortix/io.cpp b/sortix/io.cpp index e1c838c6..96ed233a 100644 --- a/sortix/io.cpp +++ b/sortix/io.cpp @@ -58,7 +58,7 @@ namespace Sortix if ( !stream->IsWritable() ) { return -1; /* TODO: EBADF */ } ssize_t written = stream->Write(buffer, count); if ( 0 <= written ) { return written; } - if ( Error::Last() != Error::EWOULDBLOCK ) { return -1; /* TODO: errno */ } + if ( Error::Last() != EWOULDBLOCK ) { return -1; /* TODO: errno */ } // The stream will resume our system call once progress has been // made. Our request is certainly not forgotten. @@ -98,7 +98,7 @@ namespace Sortix if ( !stream->IsReadable() ) { return -1; /* TODO: EBADF */ } ssize_t bytesread = stream->Read(buffer, count); if ( 0 <= bytesread ) { return bytesread; } - if ( Error::Last() != Error::EWOULDBLOCK ) { return -1; /* TODO: errno */ } + if ( Error::Last() != EWOULDBLOCK ) { return -1; /* TODO: errno */ } // The stream will resume our system call once progress has been // made. Our request is certainly not forgotten. diff --git a/sortix/pipe.cpp b/sortix/pipe.cpp index 4f05ed57..1b2996e5 100644 --- a/sortix/pipe.cpp +++ b/sortix/pipe.cpp @@ -100,7 +100,7 @@ namespace Sortix return amount + Read(dest + amount, count - amount); } - Error::Set(Error::EWOULDBLOCK); + Error::Set(EWOULDBLOCK); // TODO: Only one thread can wait on a pipe at the same time. ASSERT(readwaiting == NULL); @@ -129,7 +129,7 @@ namespace Sortix return amount + Write(src + amount, count - amount); } - Error::Set(Error::EWOULDBLOCK); + Error::Set(EWOULDBLOCK); // TODO: Only one thread can wait on a pipe at the same time. ASSERT(writewaiting == NULL); @@ -175,7 +175,7 @@ namespace Sortix ssize_t DevPipeReading::Write(const byte* /*src*/, size_t /*count*/) { - Error::Set(Error::EBADF); + Error::Set(EBADF); return -1; } @@ -222,7 +222,7 @@ namespace Sortix ssize_t DevPipeWriting::Read(byte* /*dest*/, size_t /*count*/) { - Error::Set(Error::EBADF); + Error::Set(EBADF); return -1; } diff --git a/sortix/process.cpp b/sortix/process.cpp index c3da6bfd..52c45caa 100644 --- a/sortix/process.cpp +++ b/sortix/process.cpp @@ -101,6 +101,7 @@ namespace Sortix zombiechild = NULL; firstthread = NULL; workingdir = NULL; + errno = NULL; mmapfrom = 0x80000000UL; exitstatus = -1; pid = AllocatePID(); @@ -133,6 +134,7 @@ namespace Sortix } segments = NULL; + errno = NULL; } Process* Process::Fork() @@ -200,6 +202,7 @@ namespace Sortix // Copy variables. clone->mmapfrom = mmapfrom; + clone->errno = errno; if ( workingdir ) { clone->workingdir = String::Clone(workingdir); } else { clone->workingdir = NULL; } @@ -337,7 +340,7 @@ namespace Sortix int SysExevVEStage2(SysExecVEState* state) { - if ( !state->dev->IsReadable() ) { Error::Set(Error::EBADF); delete state; return -1; } + if ( !state->dev->IsReadable() ) { Error::Set(EBADF); delete state; return -1; } byte* dest = state->buffer + state->sofar; size_t amount = state->count - state->sofar; @@ -346,7 +349,7 @@ namespace Sortix // Check for premature end-of-file. if ( bytesread == 0 && amount != 0 ) { - Error::Set(Error::EIO); delete state; return -1; + Error::Set(EIO); delete state; return -1; } // We actually managed to read some data. @@ -366,7 +369,7 @@ namespace Sortix return SysExevVEStage2(state); } - if ( Error::Last() != Error::EWOULDBLOCK ) { delete state; return -1; } + if ( Error::Last() != EWOULDBLOCK ) { delete state; return -1; } // The stream will resume our system call once progress has been // made. Our request is certainly not forgotten. @@ -387,7 +390,7 @@ namespace Sortix // TODO: Use the PATH enviromental variable. const char* base = ( *progname == '.' ) ? wd : path; char* abs = Directory::MakeAbsolute(base, progname); - if ( !abs ) { Error::Set(Error::ENOMEM); return NULL; } + if ( !abs ) { Error::Set(ENOMEM); return NULL; } // TODO: Use O_EXEC here! Device* dev = FileSystem::Open(abs, O_RDONLY, 0); @@ -428,7 +431,7 @@ namespace Sortix state->dev->Refer(); // TODO: Rules of GC may change soon. uintmax_t needed = state->dev->Size(); - if ( SIZE_MAX < needed ) { Error::Set(Error::ENOMEM); delete state; return -1; } + if ( SIZE_MAX < needed ) { Error::Set(ENOMEM); delete state; return -1; } state->count = needed; state->buffer = new byte[state->count]; @@ -689,6 +692,12 @@ namespace Sortix return 0; } + int SysRegisterErrno(int* errnop) + { + CurrentProcess()->errno = errnop; + return 0; + } + void Process::Init() { Syscall::Register(SYSCALL_EXEC, (void*) SysExecVE); @@ -697,6 +706,7 @@ namespace Sortix Syscall::Register(SYSCALL_GETPPID, (void*) SysGetParentPID); Syscall::Register(SYSCALL_EXIT, (void*) SysExit); Syscall::Register(SYSCALL_WAIT, (void*) SysWait); + Syscall::Register(SYSCALL_REGISTER_ERRNO, (void*) SysRegisterErrno); nextpidtoallocate = 0; diff --git a/sortix/process.h b/sortix/process.h index 514b1750..25cd3bc1 100644 --- a/sortix/process.h +++ b/sortix/process.h @@ -69,6 +69,7 @@ namespace Sortix int exitstatus; char* workingdir; pid_t pid; + int* errno; public: Process* parent; diff --git a/sortix/syscall.cpp b/sortix/syscall.cpp index d624114c..802953a2 100644 --- a/sortix/syscall.cpp +++ b/sortix/syscall.cpp @@ -23,13 +23,15 @@ ******************************************************************************/ #include "platform.h" +#include #include "syscall.h" #include "syscallnum.h" #include "panic.h" +#include "process.h" #include "thread.h" #include "scheduler.h" -#include "log.h" // DEBUG +using namespace Maxsi; namespace Sortix { @@ -90,6 +92,16 @@ namespace Sortix Scheduler::SetThreadState(thread, Thread::State::RUNNABLE); } + extern "C" void update_userspace_errno() + { + int error = Error::Last(); + if ( !error ) { return; } + Process* process = CurrentProcess(); + if ( !process->errno ) { return; } + // TODO: Validate that process->errno is in userspace memory! + *process->errno = error; + } + extern "C" size_t resume_syscall(void* scfunc, size_t scsize, size_t* scstate); void Resume(CPU::InterruptRegisters* regs) @@ -105,6 +117,7 @@ namespace Sortix void* scfunc = thread->scfunc; system_was_incomplete = 0; + Error::Set(0); size_t result = resume_syscall(scfunc, scsize, scstate); @@ -115,6 +128,7 @@ namespace Sortix if ( !incomplete ) { syscall_state_ptr->result = result; + update_userspace_errno(); return; } diff --git a/sortix/syscallnum.h b/sortix/syscallnum.h index bcd0504f..b07a59a2 100644 --- a/sortix/syscallnum.h +++ b/sortix/syscallnum.h @@ -53,7 +53,8 @@ #define SYSCALL_CHDIR 25 #define SYSCALL_GETCWD 26 #define SYSCALL_UNLINK 27 -#define SYSCALL_MAX_NUM 28 /* index of highest constant + 1 */ +#define SYSCALL_REGISTER_ERRNO 28 +#define SYSCALL_MAX_NUM 29 /* index of highest constant + 1 */ #endif diff --git a/sortix/x86/syscall.s b/sortix/x86/syscall.s index 11771ee4..47e75498 100644 --- a/sortix/x86/syscall.s +++ b/sortix/x86/syscall.s @@ -58,6 +58,9 @@ syscall_handler: # By default, assume the system call was complete. movl $0, system_was_incomplete + # Reset the kernel errno. + movl $0, errno + # Make sure the requested system call is valid. cmp SYSCALL_MAX, %eax jl valid_eax @@ -91,6 +94,9 @@ valid_eax: # The system call was completed, so store the return value. movl %eax, 36(%esp) + # Don't forget to update userspace's errno value. + call update_userspace_errno + return_to_userspace: # Compabillity with InterruptRegisters. addl $4, %esp diff --git a/utils/cat.cpp b/utils/cat.cpp index b055afc1..e941a274 100644 --- a/utils/cat.cpp +++ b/utils/cat.cpp @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include int cat(int argc, char* argv[]) @@ -10,7 +12,12 @@ int cat(int argc, char* argv[]) for ( int i = 1; i < argc; i++ ) { int fd = open(argv[i], O_RDONLY); - if ( fd < 0 ) { printf("%s: unable to open: %s\n", argv[0], argv[i]); result = 1; continue; } + if ( fd < 0 ) + { + printf("%s: %s: %s\n", argv[0], argv[i], strerror(errno)); + result = 1; + continue; + } do { @@ -18,7 +25,12 @@ int cat(int argc, char* argv[]) char buffer[BUFFER_SIZE+1]; ssize_t bytesread = read(fd, buffer, BUFFER_SIZE); if ( bytesread == 0 ) { break; } - if ( bytesread < 0 ) { printf("%s: read failed: %s\n", argv[0], argv[i]); result = 1; break; } + if ( bytesread < 0 ) + { + printf("%s: %s: %s\n", argv[0], argv[i], strerror(errno)); + result = 1; + break; + } buffer[bytesread] = 0; printf("%s", buffer); } while ( true ); diff --git a/utils/cp.cpp b/utils/cp.cpp index a43002ba..3a8db821 100644 --- a/utils/cp.cpp +++ b/utils/cp.cpp @@ -1,6 +1,8 @@ #include #include #include +#include +#include bool writeall(int fd, const void* buffer, size_t len) { @@ -21,18 +23,18 @@ int main(int argc, char* argv[]) if ( argc != 3 ) { printf("usage: %s \n", argv[0]); return 0; } int fromfd = open(argv[1], O_RDONLY); - if ( fromfd < 0 ) { printf("%s: cannot open for reading: %s\n", argv[0], argv[1]); return 1; } + if ( fromfd < 0 ) { printf("%s: %s: %s\n", argv[0], argv[1], strerror(errno)); return 1; } int tofd = open(argv[2], O_WRONLY | O_TRUNC | O_CREAT, 0777); - if ( tofd < 0 ) { printf("%s: cannot open for writing: %s\n", argv[0], argv[2]); return 1; } + if ( tofd < 0 ) { printf("%s: %s: %s\n", argv[0], argv[2], strerror(errno)); return 1; } while ( true ) { const size_t BUFFER_SIZE = 4096; char buffer[BUFFER_SIZE]; ssize_t bytesread = read(fromfd, buffer, BUFFER_SIZE); - if ( bytesread < 0 ) { printf("%s: read failed: %s\n", argv[0], argv[1]); return 1; } + if ( bytesread < 0 ) { printf("%s: %s: %s\n", argv[0], argv[1], strerror(errno)); return 1; } if ( bytesread == 0 ) { return 0; } - if ( !writeall(tofd, buffer, bytesread) ) { printf("%s: write failed: %s\n", argv[0], argv[2]); return 1; } + if ( !writeall(tofd, buffer, bytesread) ) { printf("%s: %s: %s\n", argv[0], argv[2], strerror(errno)); return 1; } } } diff --git a/utils/editor.cpp b/utils/editor.cpp index 4470ab0d..a242d906 100644 --- a/utils/editor.cpp +++ b/utils/editor.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -208,7 +209,7 @@ bool writeall(int fd, const void* buffer, size_t len) bool savetofile(const char* path) { int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0777); - if ( fd < 0 ) { printf("unable to open for writing: %s\n", path); return false; } + if ( fd < 0 ) { printf("%s: %s\n", path, strerror(errno)); return false; } for ( unsigned y = 0; y < numlines; y++ ) { @@ -216,10 +217,10 @@ bool savetofile(const char* path) buffers[y][len] = '\n'; bool result = writeall(fd, buffers[y], len+1); buffers[y][len] = 0; - if ( !result ) { printf("unable to write: %s\n", path); close(fd); return false; } + if ( !result ) { printf("%s: %s\n", path, strerror(errno)); close(fd); return false; } } - if ( close(fd) ) { printf("unable to write: %s\n", path); return false; } + if ( close(fd) ) { printf("%s: %s\n", path, strerror(errno)); return false; } return true; } @@ -283,7 +284,7 @@ retry: bool loadfromfile(const char* path) { int fd = open(path, O_RDONLY, 0777); - if ( fd < 0 ) { printf("unable to open for reading: %s\n", path); return false; } + if ( fd < 0 ) { printf("%s: %s\n", path, strerror(errno)); return false; } clearbuffers(); @@ -294,7 +295,7 @@ bool loadfromfile(const char* path) while ( !done ) { ssize_t bytesread = read(fd, buffer, BUFFER_SIZE); - if ( bytesread < 0 ) { close(fd); return false; } + if ( bytesread < 0 ) { printf("%s: %s\n", path, strerror(errno)); close(fd); return false; } if ( bytesread == 0 ) { break; } for ( ssize_t i = 0; i < bytesread; i++ ) { diff --git a/utils/init.cpp b/utils/init.cpp index 96c942e4..1c83839c 100644 --- a/utils/init.cpp +++ b/utils/init.cpp @@ -1,5 +1,7 @@ -#include #include +#include +#include +#include #include #include #include @@ -32,7 +34,7 @@ int main(int argc, char* argv[]) if ( childpid < 0 ) { - printf("init: unable to fork a child\n"); + printf("init: fork: %s\n", strerror(errno)); return 2; } diff --git a/utils/ls.cpp b/utils/ls.cpp index a6741129..c903359a 100644 --- a/utils/ls.cpp +++ b/utils/ls.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -11,7 +12,7 @@ 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; } + if ( fd < 0 ) { printf("ls: %s: %s\n", path, strerror(errno)); return 2; } const size_t BUFFER_SIZE = 512; char buffer[BUFFER_SIZE]; @@ -24,7 +25,7 @@ int ls(const char* path) { if ( readdirents(fd, dirent, BUFFER_SIZE) ) { - printf("readdirents() failed\n"); + printf("ls: %s: %s\n", path, strerror(errno)); return 1; } diff --git a/utils/mxsh.cpp b/utils/mxsh.cpp index f495a18d..ab369d1b 100644 --- a/utils/mxsh.cpp +++ b/utils/mxsh.cpp @@ -1,8 +1,9 @@ +#include #include #include #include #include -#include +#include #include #include #include @@ -93,14 +94,14 @@ void command() if ( 1 < argc ) { newdir = argv[1]; } if ( chdir(newdir) ) { - printf("cd: %s: cannot change directory\n", newdir); + printf("sh: cd: %s: %s\n", newdir, strerror(errno)); status = 1; } return; } pid_t child = fork(); - if ( child < 0 ) { printf("fork failed\n"); return; } + if ( child < 0 ) { printf("sh: fork failed: %s\n", strerror(errno)); return; } if ( child != 0 ) { pid_t childpid = wait(&status); @@ -111,7 +112,7 @@ void command() Process::Execute(argv[0], argc, argv); // This is clever. This only happens if the program didn't change. - printf("%s: command not found\n", argv[0]); + printf("%s: %s\n", argv[0], strerror(errno)); exit(127); } diff --git a/utils/rm.cpp b/utils/rm.cpp index 1203d0b7..29ff43dd 100644 --- a/utils/rm.cpp +++ b/utils/rm.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include int main(int argc, char* argv[]) { @@ -11,7 +13,7 @@ int main(int argc, char* argv[]) { if ( unlink(argv[i]) ) { - printf("%s: unable to unlink: %s\n", argv[0], argv[i]); + printf("%s: cannot remove %s: %s\n", argv[0], argv[i], strerror(errno)); result = 1; } }