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