Implemented errno(3), added support in both kernel and utils.

This commit is contained in:
Jonas 'Sortie' Termansen 2011-11-22 17:26:47 +01:00
parent 8678ad6444
commit 9f35df813e
29 changed files with 243 additions and 116 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/errno.h \
c/h/sys/readdirents.h \
c/h/sys/stat.h \
c/h/sys/types.h \

37
libmaxsi/c/hsrc/errno.h Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
errno.h
System error numbers.
******************************************************************************/
#ifndef _ERRNO_H
#define _ERRNO_H 1
#include <features.h>
__BEGIN_DECLS
@include(errno_decl.h)
@include(errno_values.h)
__END_DECLS
#endif

View File

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

View File

@ -0,0 +1,6 @@
#ifndef _ERRNO_DECL
#define _ERRNO_DECL
extern volatile int errno;
#endif

View File

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

View File

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

View File

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

View File

@ -27,8 +27,10 @@
namespace Maxsi
{
extern "C" void init_error_functions();
extern "C" void initialize_standard_library()
{
init_error_functions();
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -69,6 +69,7 @@ namespace Sortix
int exitstatus;
char* workingdir;
pid_t pid;
int* errno;
public:
Process* parent;

View File

@ -23,13 +23,15 @@
******************************************************************************/
#include "platform.h"
#include <libmaxsi/error.h>
#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;
}

View File

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

View File

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

View File

@ -1,6 +1,8 @@
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <libmaxsi/sortix-keyboard.h>
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 );

View File

@ -1,6 +1,8 @@
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
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 <from> <to>\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; }
}
}

View File

@ -2,6 +2,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <libmaxsi/platform.h>
#include <libmaxsi/sortix-keyboard.h>
@ -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++ )
{

View File

@ -1,5 +1,7 @@
#include <stdio.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <libmaxsi/platform.h>
#include <libmaxsi/process.h>
#include <libmaxsi/thread.h>
@ -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;
}

View File

@ -2,6 +2,7 @@
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/readdirents.h>
#include <libmaxsi/platform.h>
#include <libmaxsi/process.h>
@ -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;
}

View File

@ -1,8 +1,9 @@
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <errno.h>
#include <libmaxsi/platform.h>
#include <libmaxsi/process.h>
#include <libmaxsi/sortix-keyboard.h>
@ -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);
}

View File

@ -1,5 +1,7 @@
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
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;
}
}