1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 02:47:35 +00:00

Implement errno in LibC.

This also meant I had to implement BSS (SHT_NOBITS) sections in ELFLoader.
I also added an strerror() so we can print out what the errors are.
This commit is contained in:
Andreas Kling 2018-10-25 12:06:00 +02:00
parent 434b6a8688
commit 260b14e505
14 changed files with 209 additions and 27 deletions

View file

@ -2,8 +2,12 @@
extern "C" int main(int, char**);
int errno;
extern "C" int _start()
{
errno = 0;
// FIXME: Pass appropriate argc/argv.
int status = main(0, nullptr);

57
LibC/errno.h Normal file
View file

@ -0,0 +1,57 @@
#pragma once
#define EPERM 1 // Operation not permitted
#define ENOENT 2 // No such file or directory
#define ESRCH 3 // No such process
#define EINTR 4 // Interrupted system call
#define EIO 5 // I/O error
#define ENXIO 6 // No such device or address
#define E2BIG 7 // Argument list too long
#define ENOEXEC 8 // Exec format error
#define EBADF 9 // Bad file number
#define ECHILD 10 // No child processes
#define EAGAIN 11 // Try again
#define ENOMEM 12 // Out of memory
#define EACCES 13 // Permission denied
#define EFAULT 14 // Bad address
#define ENOTBLK 15 // Block device required
#define EBUSY 16 // Device or resource busy
#define EEXIST 17 // File exists
#define EXDEV 18 // Cross-device link
#define ENODEV 19 // No such device
#define ENOTDIR 20 // Not a directory
#define EISDIR 21 // Is a directory
#define EINVAL 22 // Invalid argument
#define ENFILE 23 // File table overflow
#define EMFILE 24 // Too many open files
#define ENOTTY 25 // Not a typewriter
#define ETXTBSY 26 // Text file busy
#define EFBIG 27 // File too large
#define ENOSPC 28 // No space left on device
#define ESPIPE 29 // Illegal seek
#define EROFS 30 // Read-only file system
#define EMLINK 31 // Too many links
#define EPIPE 32 // Broken pipe
#define EDOM 33 // Math argument out of domain of func
#define ERANGE 34 // Math result not representable
#define EOVERFLOW 75 // Value too large for defined data type
#define __RETURN_WITH_ERRNO(rc, good_ret, bad_ret) \
do { \
if (rc < 0) { \
errno = -rc; \
return (bad_ret); \
} else { \
errno = 0; \
return (good_ret); \
} \
} while(0)
extern "C" {
extern int errno;
};

View file

@ -1,16 +1,19 @@
#include "mman.h"
#include "errno.h"
#include <Kernel/Syscall.h>
extern "C" {
void* mmap(void* addr, size_t size)
{
return (void*)Syscall::invoke(Syscall::PosixMmap, (dword)addr, (dword)size);
int rc = Syscall::invoke(Syscall::PosixMmap, (dword)addr, (dword)size);
__RETURN_WITH_ERRNO(rc, (void*)rc, (void*)-1);
}
int munmap(void* addr, size_t size)
{
return Syscall::invoke(Syscall::PosixMunmap, (dword)addr, (dword)size);
int rc = Syscall::invoke(Syscall::PosixMunmap, (dword)addr, (dword)size);
__RETURN_WITH_ERRNO(rc, rc, -1);
}
}

View file

@ -1,11 +1,13 @@
#include "process.h"
#include "errno.h"
#include <Kernel/Syscall.h>
extern "C" {
int spawn(const char* path)
{
return Syscall::invoke(Syscall::Spawn, (dword)path);
int rc = Syscall::invoke(Syscall::Spawn, (dword)path);
__RETURN_WITH_ERRNO(rc, rc, -1);
}
}

View file

@ -1,4 +1,6 @@
#include "string.h"
#include "errno.h"
#include "stdio.h"
extern "C" {
@ -10,5 +12,49 @@ size_t strlen(const char* str)
return len;
}
const char* strerror(int errnum)
{
switch (errnum) {
case 0: return "No error";
case EPERM: return "Operation not permitted";
case ENOENT: return "No such file or directory";
case ESRCH: return "No such process";
case EINTR: return "Interrupted syscall";
case EIO: return "I/O error";
case ENXIO: return "No such device/address";
case E2BIG: return "Argument list too long";
case ENOEXEC: return "Exec format error";
case EBADF: return "Bad fd number";
case ECHILD: return "No child processes";
case EAGAIN: return "Try again";
case ENOMEM: return "Out of memory";
case EACCES: return "Access denied";
case EFAULT: return "Bad address";
case ENOTBLK: return "Not a block device";
case EBUSY: return "Resource busy";
case EEXIST: return "File already exists";
case EXDEV: return "Cross-device link";
case ENODEV: return "No such device";
case ENOTDIR: return "Not a directory";
case EISDIR: return "Is a directory";
case EINVAL: return "Invalid argument";
case ENFILE: return "File table overflow";
case EMFILE: return "Too many open files";
case ENOTTY: return "Not a TTY";
case ETXTBSY: return "Text file busy";
case EFBIG: return "File too big";
case ENOSPC: return "No space left";
case ESPIPE: return "Illegal seek";
case EROFS: return "File system is read-only";
case EMLINK: return "Too many links";
case EPIPE: return "Broken pipe";
case EDOM: return "Math argument out of domain";
case ERANGE: return "Math result not representable";
case EOVERFLOW: return "Value too large for data type";
}
printf("strerror() missing string for errnum=%d\n", errnum);
return "Unknown error";
}
}

View file

@ -5,6 +5,7 @@
extern "C" {
size_t strlen(const char*);
const char* strerror(int errnum);
}

View file

@ -1,5 +1,6 @@
#include "unistd.h"
#include "string.h"
#include "errno.h"
#include <Kernel/Syscall.h>
extern "C" {
@ -22,35 +23,38 @@ pid_t getpid()
int open(const char* path)
{
size_t length = strlen(path);
return Syscall::invoke(Syscall::PosixOpen, (dword)path, (dword)length);
int rc = Syscall::invoke(Syscall::PosixOpen, (dword)path, (dword)length);
__RETURN_WITH_ERRNO(rc, rc, -1);
}
ssize_t read(int fd, void* buf, size_t count)
{
return Syscall::invoke(Syscall::PosixRead, (dword)fd, (dword)buf, (dword)count);
int rc = Syscall::invoke(Syscall::PosixRead, (dword)fd, (dword)buf, (dword)count);
__RETURN_WITH_ERRNO(rc, rc, -1);
}
int close(int fd)
{
return Syscall::invoke(Syscall::PosixClose, fd);
int rc = Syscall::invoke(Syscall::PosixClose, fd);
__RETURN_WITH_ERRNO(rc, rc, -1);
}
pid_t waitpid(pid_t waitee)
{
return Syscall::invoke(Syscall::PosixWaitpid, waitee);
int rc = Syscall::invoke(Syscall::PosixWaitpid, waitee);
__RETURN_WITH_ERRNO(rc, rc, -1);
}
int lstat(const char* path, stat* statbuf)
{
return Syscall::invoke(Syscall::PosixLstat, (dword)path, (dword)statbuf);
int rc = Syscall::invoke(Syscall::PosixLstat, (dword)path, (dword)statbuf);
__RETURN_WITH_ERRNO(rc, rc, -1);
}
char* getcwd(char* buffer, size_t size)
{
int rc = Syscall::invoke(Syscall::PosixGetcwd, (dword)buffer, (dword)size);
if (rc != 0)
return nullptr;
return buffer;
__RETURN_WITH_ERRNO(rc, buffer, nullptr);
}
}