Implemented errno(3), added support in both kernel and utils.
This commit is contained in:
parent
8678ad6444
commit
9f35df813e
|
@ -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 \
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef _ERRNO_DECL
|
||||
#define _ERRNO_DECL
|
||||
|
||||
extern volatile int errno;
|
||||
|
||||
#endif
|
|
@ -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
|
|
@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,8 +27,10 @@
|
|||
|
||||
namespace Maxsi
|
||||
{
|
||||
extern "C" void init_error_functions();
|
||||
|
||||
extern "C" void initialize_standard_library()
|
||||
{
|
||||
|
||||
init_error_functions();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -69,6 +69,7 @@ namespace Sortix
|
|||
int exitstatus;
|
||||
char* workingdir;
|
||||
pid_t pid;
|
||||
int* errno;
|
||||
|
||||
public:
|
||||
Process* parent;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
|
|
10
utils/cp.cpp
10
utils/cp.cpp
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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++ )
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue