Initial commit

This commit is contained in:
Mark
2020-07-16 22:49:00 +03:00
commit d63e3c4352
142 changed files with 2754 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
build
+72
View File
@@ -0,0 +1,72 @@
# Files
HEADERS=$(shell find include -type f -name "*.h")
INSTALL_HEADERS=$(filter-out include/_libc/%,$(HEADERS))
OBJ_CRT=$(O)/obj/crt0.o
SRC_LIBC=$(shell find src -type f -name "*.c")
OBJ_LIBC=$(SRC_LIBC:src/%.c=$(O)/libc/%.o)
SRC_DIR_LIBC=$(shell find src/* -type d)
DIR_LIBC=$(SRC_DIR_LIBC:src/%=$(O)/libc/%)
STATIC_LIBS=$(O)/lib/libc.a
SHARED_LIBS=
# Build
CFLAGS=-mno-sse \
-mno-sse2 \
-mno-mmx \
-I include \
-ffreestanding \
-Wall \
-Wextra \
-Werror \
-zmax-page-size=4096
LDFLAGS=-nostdlib
CC=$(CROSS_COMPILE)gcc
O=build
DESTDIR?=/usr/local
LIBS=$(STATIC_LIBS) $(SHARED_LIBS)
### General rules
all: mkdirs $(LIBS) $(OBJ_CRT)
mkdirs:
mkdir -p $(O)/obj $(O)/lib $(DIR_LIBC)
clean:
rm -rf $(O)
### Install rules
install-crt: mkdirs $(OBJ_CRT)
$(foreach obj,$(OBJ_CRT), \
install -Dm 0644 $(obj) $(obj:$(O)/obj/%.o=$(DESTDIR)/lib/%.o); \
)
install-static-libs: mkdirs $(STATIC_LIBS)
$(foreach lib,$(STATIC_LIBS), \
install -Dm 0644 $(lib) $(DESTDIR)/$(lib:$(O)/%=%); \
)
install-headers: mkdirs $(INSTALL_HEADERS)
$(foreach hdr,$(INSTALL_HEADERS), \
install -Dm 0644 $(hdr) $(DESTDIR)/$(hdr:$(O)/%=%); \
)
install: install-crt install-static-libs install-headers
### CRT objects
$(O)/obj/crt%.o: crt/crt%.c $(HEADERS)
$(CC) $(CFLAGS) -c -o $@ $<
### lib
$(O)/lib/libc.a: $(OBJ_LIBC)
$(CROSS_COMPILE)ar rcs $@
$(foreach obj,$(OBJ_LIBC), \
$(CROSS_COMPILE)ar rs $@ $(obj); \
)
$(O)/libc/%.o: src/%.c $(HEADERS)
$(CC) $(CFLAGS) -c -o $@ $<
+28
View File
@@ -0,0 +1,28 @@
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <_libc/stdio.h>
#include <_libc/signal.h>
// XXX: envp
extern int main(int argc, char **argv);
extern char **environ;
void _start(void *_arg) {
uintptr_t arg = (uintptr_t) _arg;
// arg: argp page number << 24 | 12 bit page count << 12 | 12 bit argc
char **argp = (char **) ((arg >> 12) & ~0xFFF);
int argc = arg & 0xFFF;
//__libc_vecp_pages = (arg >> 12) & 0xFFF;
// TODO: better handling for this
environ = &argp[argc + 1];
__libc_signal_init();
fwrite("Test\n", 1, 5, stdout);
exit(main(argc, argp));
}
+3
View File
@@ -0,0 +1,3 @@
#pragma once
_Noreturn void __libc_abort_init(const char *reason);
+72
View File
@@ -0,0 +1,72 @@
#pragma once
struct list_head {
struct list_head *prev, *next;
};
#define LIST_HEAD(name) \
struct list_head name = { &name, &name }
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
#define list_entry(link, type, member) ({ \
const typeof (((type *) 0)->member) *__memb = (link); \
(type *) ((char *) __memb - offsetof(type, member)); \
})
#define list_next_entry(pos, member) \
list_entry((pos)->member.next, typeof(*(pos)), member)
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
static inline void list_head_init(struct list_head *list) {
list->next = list;
list->prev = list;
}
static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next) {
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
static inline void list_add(struct list_head *new, struct list_head *head) {
__list_add(new, head, head->next);
}
static inline void list_add_tail(struct list_head *new, struct list_head *head) {
__list_add(new, head->prev, head);
}
static inline void __list_del(struct list_head *prev, struct list_head *next) {
next->prev = prev;
prev->next = next;
}
static inline void list_del(struct list_head *entry) {
__list_del(entry->prev, entry->next);
}
static inline int list_empty(const struct list_head *head) {
return head->next == head;
}
static inline void list_del_init(struct list_head *entry) {
__list_del(entry->prev, entry->next);
list_head_init(entry);
}
+35
View File
@@ -0,0 +1,35 @@
#pragma once
#include <_libc/list.h>
#include <stddef.h>
#include <stdint.h>
#define BLOCK_ALLOC 1
#define BLOCK_MMAP 2
#define BLOCK_MAGIC_MASK 0xFFFFFFC
#define BLOCK_MAGIC 0xBAD8EA0
// Fits ~56 blocks of 256
#define SMALL_ZONE_ELEM 256
#define SMALL_ZONE_SIZE (4 * 0x1000)
// Fits ~31 block of 2K
#define MID_ZONE_ELEM 2048
#define MID_ZONE_SIZE (16 * 0x1000)
// Fits ~15 blocks of 8K
#define LARGE_ZONE_ELEM 8192
#define LARGE_ZONE_SIZE (32 * 0x1000)
// Larger objects are allocated directly using mmap()
struct block {
struct block *prev, *next;
uint32_t flags, size;
};
struct zone {
size_t size;
struct list_head list;
};
extern struct list_head small_zone_list, mid_zone_list, large_zone_list;
struct zone *zone_create(size_t size);
void zone_destroy(struct zone *zone);
+4
View File
@@ -0,0 +1,4 @@
#pragma once
#define __LIBC_SIGNAL_STACK_SIZE 4096
void __libc_signal_init(void);
+33
View File
@@ -0,0 +1,33 @@
#pragma once
#include <sys/types.h>
#define FILE_MODE_READ (1 << 0)
#define FILE_MODE_WRITE (1 << 1)
#define FILE_MODE_APPEND (1 << 2)
#define FILE_MODE_TRUNC (1 << 3)
#define FILE_MODE_CREAT (1 << 4)
#define FILE_FLAG_ERROR (1 << 16)
#define FILE_FLAG_EOF (1 << 17)
struct __FILE {
void *ctx;
void *buf;
ssize_t (*write)(void *ctx, const void *data, size_t len);
ssize_t (*read) (void *ctx, void *data, size_t len);
off_t (*seek) (void *ctx, off_t offset, int whence);
int (*close)(void *ctx);
void (*free) (void *ctx, struct __FILE *fp);
int fd, flags, buf_mode;
size_t wrbuf, rdbuf, rdbufpos;
};
struct __FILE *__libc_file_create(void);
int __libc_file_open_path(struct __FILE *fp, const char *pathname, const char *mode);
int __libc_file_open_fd(struct __FILE *fp, int fd, int flags);
int __libc_file_mode(const char *mode);
int __libc_file_flush_read(struct __FILE *fp);
int __libc_file_flush_write(struct __FILE *fp);
+57
View File
@@ -0,0 +1,57 @@
#pragma once
static inline long __syscall0(long n) {
unsigned long ret;
asm volatile ("syscall"
:"=a"(ret)
:"a"(n)
:"rcx","r11","memory");
return ret;
}
static inline long __syscall1(long n, long a1) {
unsigned long ret;
asm volatile ("syscall"
:"=a"(ret)
:"a"(n),"D"(a1)
:"rcx","r11","memory");
return ret;
}
static inline long __syscall2(long n, long a1, long a2) {
unsigned long ret;
asm volatile ("syscall"
:"=a"(ret)
:"a"(n),"D"(a1),"S"(a2)
:"rcx","r11","memory");
return ret;
}
static inline long __syscall3(long n, long a1, long a2, long a3) {
unsigned long ret;
asm volatile ("syscall"
:"=a"(ret)
:"a"(n),"D"(a1),"S"(a2),"d"(a3)
:"rcx","r11","memory");
return ret;
}
static inline long __syscall6(long n, long a1, long a2, long a3, long a4, long a5, long a6) {
unsigned long ret;
register long r10 __asm__("r10") = a4;
register long r8 __asm__("r8") = a5;
register long r9 __asm__("r9") = a6;
asm volatile ("syscall"
:"=a"(ret)
:"a"(n),"D"(a1),"S"(a2),"d"(a3),"r"(r10),"r"(r8),"r"(r9)
:"rcx","r11","memory");
return ret;
}
#define SET_ERRNO(t, r) ({ \
t res = (t) r; \
if (res < 0) { \
errno = -res; \
} \
((int) res) < 0 ? (t) -1 : res; \
})
+12
View File
@@ -0,0 +1,12 @@
#pragma once
#define _assert_stringify_line(x) #x
#define _assert_line(x) _assert_stringify_line(x)
#if !defined(NDEBUG)
#define assert(c) \
if (!(c)) { _assert_fail(__func__, __FILE__ ":" _assert_line(__LINE__) ": Assertion `" #c "' failed." ); }
#else
#define assert(c)
#endif
_Noreturn void _assert_fail(const char *func, const char *msg);
+3
View File
@@ -0,0 +1,3 @@
#pragma once
#define __Malloc __attribute__((malloc))
+4
View File
@@ -0,0 +1,4 @@
#pragma once
#include <ygg/errno.h>
extern int errno;
+4
View File
@@ -0,0 +1,4 @@
#pragma once
#include <ygg/fcntl.h>
int open(const char *pathname, int flags, mode_t mode);
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#include <ygg/signum.h>
#define SIG_DFL _sig_dfl
#define SIG_ERR ((sighandler_t) -1)
#define SIG_HOLD _sig_hold
#define SIG_IGN _sig_ign
typedef void (*sighandler_t) (int);
extern void _sig_dfl(int signum);
extern void _sig_hold(int signum);
extern void _sig_ign(int signum);
sighandler_t signal(int signum, sighandler_t handler);
int sigaltstack(const stack_t *ss, stack_t *old_ss);
+22
View File
@@ -0,0 +1,22 @@
#pragma once
// Exact-width integer types
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef signed short int16_t;
typedef unsigned short uint16_t;
typedef signed int int32_t;
typedef unsigned int uint32_t;
typedef signed long int64_t;
typedef unsigned long uint64_t;
// Integer types capable of holding object pointers
typedef int64_t intptr_t;
typedef uint64_t uintptr_t;
// Greatest-width integer types
typedef int64_t intmax_t;
typedef uint64_t uintmax_t;
+32
View File
@@ -0,0 +1,32 @@
#pragma once
#include <stddef.h>
#define EOF -1
#define BUFSIZ 8192
#define _IOLBF 1
#define _IONBF 2
#define TMP_MAX 10000
#define FOPEN_MAX 8 // TODO
#define FILENAME_MAX 1024
typedef struct __FILE FILE;
extern FILE *const stdin;
extern FILE *const stdout;
extern FILE *const stderr;
FILE *fopen(const char *pathname, const char *mode);
int fclose(FILE *fp);
void flockfile(FILE *fp);
void funlockfile(FILE *fp);
//// _unlocked functions
size_t fwrite_unlocked(const void *data, size_t size, size_t nmemb, FILE *fp);
size_t fread_unlocked(void *data, size_t size, size_t nmemb, FILE *fp);
int fgetc_unlocked(FILE *fp);
int fputc_unlocked(int ch, FILE *fp);
//// Regular functions
size_t fwrite(const void *data, size_t size, size_t nmemb, FILE *fp);
size_t fread(void *data, size_t size, size_t nmemb, FILE *fp);
+10
View File
@@ -0,0 +1,10 @@
#pragma once
#include <bits/attr.h>
#include <stddef.h>
__Malloc void *malloc(size_t size);
void free(void *ptr);
// XXX: POSIX doesn't define _Noreturn attribute on those?
void _Exit(int status);
void exit(int status);
+36
View File
@@ -0,0 +1,36 @@
#pragma once
#include <stddef.h>
void *memccpy(void *restrict dst, const void *restrict src, int c, size_t len);
void *memchr(const void *ptr, int v, size_t len);
int memcmp(const void *p0, const void *p1, size_t len);
void *memcpy(void *dest, const void *src, size_t n);
void *memmove(void *dst, const void *src, size_t len);
void *memset(void *dest, int c, size_t n);
char *stpcpy(char *restrict dst, const char *restrict src);
char *stpncpy(char *restrict dst, const char *restrict src, size_t len);
char *strcat(char *dst, const char *src);
char *strchr(const char *str, int chr);
int strcmp(const char *a, const char *b);
int strcoll(const char *a, const char *b);
// TODO: strcoll_l
char *strcpy(char *restrict dst, const char *restrict src);
size_t strcspn(const char *a, const char *b);
char *strdup(const char *str);
char *strerror(int errnum);
// TODO: strerror_l
int strerror_r(int errnum, char *dst, size_t lim);
size_t strlen(const char *str);
char *strncat(char *restrict dst, const char *restrict src, size_t len);
int strncmp(const char *a, const char *b, size_t len);
char *strncpy(char *restrict dst, const char *restrict src, size_t len);
char *strndup(const char *str, size_t len);
size_t strnlen(const char *str, size_t len);
char *strpbrk(const char *str, const char *set);
char *strrchr(const char *str, int chr);
char *strsignal(int signum);
size_t strspn(const char *a, const char *b);
char *strstr(const char *a, const char *b);
char *strtok(char *restrict str, const char *restrict delim);
char *strtok_r(char *restrict str, const char *restrict delim, char **restrict saveptr);
+6
View File
@@ -0,0 +1,6 @@
#pragma once
#include <ygg/mman.h>
#include <sys/types.h>
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
int munmap(void *addr, size_t length);
+3
View File
@@ -0,0 +1,3 @@
#pragma once
#include <stddef.h> // size_t
#include <ygg/types.h>
+338
View File
@@ -0,0 +1,338 @@
#pragma once
#include <sys/types.h> // size_t, ssize_t
extern char **environ;
//// Defines
// POSIX conformance
#undef _POSIX_ADVISORY_INFO
#undef _POSIX_ASYNCHRONOUS_IO
#undef _POSIX_BARRIERS
#define _POSIX_CHOWN_RESTRICTED 200809L
#undef _POSIX_CLOCK_SELECTION
#undef _POSIX_CPU_TIME
#undef _POSIX_FSYNC // TODO: maybe I'll add this on a per-file basis
#undef _POSIX_IPV6 // I don't even support IPv4 yet lol
#define _POSIX_JOB_CONTROL 200809L
#undef _POSIX_MAPPED_FILES // TODO: I'll implement this eventually
#undef _POSIX_MEMLOCK
#undef _POSIX_MEMLOCK_RANGE
#undef _POSIX_MEMORY_PROTECTION
#undef _POSIX_MESSAGE_PASSING
#undef _POSIX_MONOTONIC_CLOCK // TODO
#define _POSIX_NO_TRUNC 200809L
#undef _POSIX_PRIORITIZED_IO
#undef _POSIX_PRIORITY_SCHEDULING // TODO: maybe just define that and ignore the priorities
#undef _POSIX_RAW_SOCKETS // TODO: the kernel kinda supports them, but pending rewrite
#undef _POSIX_READER_WRITER_LOCKS
#undef _POSIX_REALTIME_SIGNALS
#undef _POSIX_REGEXP // TODO
#undef _POSIX_SAVED_IDS // TODO?
#undef _POSIX_SEMAPHORES
#undef _POSIX_SHARED_MEMORY_OBJECTS // TODO
#define _POSIX_SHELL 200809L
#undef _POSIX_SPAWN // TODO?
#undef _POSIX_SPIN_LOCKS // TODO?
#undef _POSIX_SPORADIC_SERVER
#undef _POSIX_SYNCHRONIZED_IO
#undef _POSIX_THREAD_ATTR_STACKADDR
#undef _POSIX_THREAD_ATTR_STACKSIZE
#undef _POSIX_THREAD_CPUTIME
#undef _POSIX_THREAD_PRIO_INHERIT
#undef _POSIX_THREAD_PRIO_PROTECT
#undef _POSIX_THREAD_PRIORITY_SCHEDULING
#undef _POSIX_THREAD_PROCESS_SHARED
#undef _POSIX_THREAD_ROBUST_PRIO_INHERIT
#undef _POSIX_THREAD_ROBUST_PRIO_PROTECT
#define _POSIX_THREAD_SAFE_FUNCTIONS 200809L
#undef _POSIX_THREAD_SPORADIC_SERVER
#undef _POSIX_THREADS // TODO
#undef _POSIX_TIMEOUTS // TODO?
#undef _POSIX_TIMERS // TODO
#undef _POSIX_TRACE // TODO?
#undef _POSIX_TRACE_EVENT_FILTER
#undef _POSIX_TRACE_INHERIT
#undef _POSIX_TRACE_LOG
#undef _POSIX_TYPED_MEMORY_OBJECTS
#define _POSIX_V6_LP64_OFF64 200809L
#define _POSIX_V7_LP64_OFF64 200809L
#undef _POSIX2_C_BIND // Dunno what that is
#undef _POSIX2_C_DEV // Ditto
#undef _POSIX2_CHAR_TERM
#undef _POSIX2_FORT_DEV // Lel
#undef _POSIX2_FORT_RUN // Lmao
#undef _POSIX2_LOCALEDEV
#undef _POSIX2_PBS
#undef _POSIX2_PBS_ACCOUNTING
#undef _POSIX2_PBS_CHECKPOINT
#undef _POSIX2_PBS_LOCATE
#undef _POSIX2_PBS_MESSAGE
#undef _POSIX2_PBS_TRACK
#undef _POSIX2_SW_DEV
#undef _POSIX2_UPE
#undef _XOPEN_CRYPT
#undef _XOPEN_ENH_I18N
#undef _XOPEN_REALTIME
#undef _XOPEN_SHM
#undef _XOPEN_STREAMS
#undef _XOPEN_UUCP
// TODO: merge these with kernel's fcntl.h
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#define R_OK 4
#define W_OK 2
#define X_OK 1
#define F_OK 0
// No POSIX advisory locks
#define _PC_2_SYMLINKS 1
#define _PC_ALLOC_SIZE_MIN 2
#define _PC_ASYNC_IO 3
#define _PC_CHOWN_RESTRICTED 4
#define _PC_FILESIZEBITS 5
#define _PC_LINK_MAX 6
#define _PC_MAX_CANON 7
#define _PC_MAX_INPUT 8
#define _PC_NAME_MAX 9
#define _PC_NO_TRUNC 10
#define _PC_PATH_MAX 11
#define _PC_PIPE_BUF 12
#define _PC_PRIO_IO 13
#define _PC_REC_INCR_XFER_SIZE 14
#define _PC_REC_MAX_XFER_SIZE 15
#define _PC_REC_MIN_XFER_SIZE 16
#define _PC_REC_XFER_ALIGN 17
#define _PC_SYMLINK_MAX 18
#define _PC_SYNC_IO 19
#define _PC_TIMESTAMP_RESOLUTION 20
#define _PC_VDISABLE 21
#define _SC_2_C_BIND 1
#define _SC_2_C_DEV 2
#define _SC_2_CHAR_TERM 3
#define _SC_2_FORT_DEV 4
#define _SC_2_FORT_RUN 5
#define _SC_2_LOCALEDEF 6
#define _SC_2_PBS 7
#define _SC_2_PBS_ACCOUNTING 8
#define _SC_2_PBS_CHECKPOINT 9
#define _SC_2_PBS_LOCATE 10
#define _SC_2_PBS_MESSAGE 11
#define _SC_2_PBS_TRACK 12
#define _SC_2_SW_DEV 13
#define _SC_2_UPE 14
#define _SC_2_VERSION 15
#define _SC_ADVISORY_INFO 16
#define _SC_AIO_LISTIO_MAX 17
#define _SC_AIO_MAX 18
#define _SC_AIO_PRIO_DELTA_MAX 19
#define _SC_ARG_MAX 20
#define _SC_ASYNCHRONOUS_IO 21
#define _SC_ATEXIT_MAX 22
#define _SC_BARRIERS 23
#define _SC_BC_BASE_MAX 24
#define _SC_BC_DIM_MAX 25
#define _SC_BC_SCALE_MAX 26
#define _SC_BC_STRING_MAX 27
#define _SC_CHILD_MAX 28
#define _SC_CLK_TCK 29
#define _SC_CLOCK_SELECTION 30
#define _SC_COLL_WEIGHTS_MAX 31
#define _SC_CPUTIME 32
#define _SC_DELAYTIMER_MAX 33
#define _SC_EXPR_NEST_MAX 34
#define _SC_FSYNC 35
#define _SC_GETGR_R_SIZE_MAX 36
#define _SC_GETPW_R_SIZE_MAX 37
#define _SC_HOST_NAME_MAX 38
#define _SC_IOV_MAX 39
#define _SC_IPV6 40
#define _SC_JOB_CONTROL 41
#define _SC_LINE_MAX 42
#define _SC_LOGIN_NAME_MAX 43
#define _SC_MAPPED_FILES 44
#define _SC_MEMLOCK 45
#define _SC_MEMLOCK_RANGE 46
#define _SC_MEMORY_PROTECTION 47
#define _SC_MESSAGE_PASSING 48
#define _SC_MONOTONIC_CLOCK 49
#define _SC_MQ_OPEN_MAX 50
#define _SC_MQ_PRIO_MAX 51
#define _SC_NGROUPS_MAX 52
#define _SC_OPEN_MAX 53
#define _SC_PAGE_SIZE 54
#define _SC_PAGESIZE 55
#define _SC_PRIORITIZED_IO 56
#define _SC_PRIORITY_SCHEDULING 57
#define _SC_RAW_SOCKETS 58
#define _SC_RE_DUP_MAX 59
#define _SC_READER_WRITER_LOCKS 60
#define _SC_REALTIME_SIGNALS 61
#define _SC_REGEXP 62
#define _SC_RTSIG_MAX 63
#define _SC_SAVED_IDS 64
#define _SC_SEM_NSEMS_MAX 65
#define _SC_SEM_VALUE_MAX 66
#define _SC_SEMAPHORES 67
#define _SC_SHARED_MEMORY_OBJECTS 68
#define _SC_SHELL 69
#define _SC_SIGQUEUE_MAX 70
#define _SC_SPAWN 71
#define _SC_SPIN_LOCKS 72
#define _SC_SPORADIC_SERVER 73
#define _SC_SS_REPL_MAX 74
#define _SC_STREAM_MAX 75
#define _SC_SYMLOOP_MAX 76
#define _SC_SYNCHRONIZED_IO 77
#define _SC_THREAD_ATTR_STACKADDR 78
#define _SC_THREAD_ATTR_STACKSIZE 79
#define _SC_THREAD_CPUTIME 80
#define _SC_THREAD_DESTRUCTOR_ITERATIONS 81
#define _SC_THREAD_KEYS_MAX 82
#define _SC_THREAD_PRIO_INHERIT 83
#define _SC_THREAD_PRIO_PROTECT 84
#define _SC_THREAD_PRIORITY_SCHEDULING 85
#define _SC_THREAD_PROCESS_SHARED 86
#define _SC_THREAD_ROBUST_PRIO_INHERIT 87
#define _SC_THREAD_ROBUST_PRIO_PROTECT 88
#define _SC_THREAD_SAFE_FUNCTIONS 89
#define _SC_THREAD_SPORADIC_SERVER 90
#define _SC_THREAD_STACK_MIN 91
#define _SC_THREAD_THREADS_MAX 92
#define _SC_THREADS 93
#define _SC_TIMEOUTS 94
#define _SC_TIMER_MAX 95
#define _SC_TIMERS 96
#define _SC_TRACE 97
#define _SC_TRACE_EVENT_FILTER 98
#define _SC_TRACE_EVENT_NAME_MAX 99
#define _SC_TRACE_INHERIT 100
#define _SC_TRACE_LOG 101
#define _SC_TRACE_NAME_MAX 102
#define _SC_TRACE_SYS_MAX 103
#define _SC_TRACE_USER_EVENT_MAX 104
#define _SC_TTY_NAME_MAX 105
#define _SC_TYPED_MEMORY_OBJECTS 106
#define _SC_TZNAME_MAX 107
#define _SC_V7_ILP32_OFF32 108
#define _SC_V7_ILP32_OFFBIG 109
#define _SC_V7_LP64_OFF64 110
#define _SC_V7_LPBIG_OFFBIG 111
#define _SC_V6_ILP32_OFF32 112
#define _SC_V6_ILP32_OFFBIG 113
#define _SC_V6_LP64_OFF64 114
#define _SC_V6_LPBIG_OFFBIG 115
#define _SC_VERSION 116
#define _SC_XOPEN_CRYPT 117
#define _SC_XOPEN_ENH_I18N 118
#define _SC_XOPEN_REALTIME 119
#define _SC_XOPEN_REALTIME_THREADS 120
#define _SC_XOPEN_SHM 121
#define _SC_XOPEN_STREAMS 122
#define _SC_XOPEN_UNIX 123
#define _SC_XOPEN_UUCP 124
#define _SC_XOPEN_VERSION 125
#define _POSIX_VDISABLE 0
#define STDERR_FILENO 2
#define STDOUT_FILENO 1
#define STDIN_FILENO 0
// File control
int access(const char *pathname, int acc); //+
int chdir(const char *pathname); //+
int chown(const char *pathname, uid_t uid, gid_t gid); //+
int close(int fd); //+
int dup(int fd); //+
int dup2(int oldfd, int newfd); //+
int execl(const char *pathname, const char *arg, ...); //+
int execle(const char *pathname, const char *arg, ...); //+
int execlp(const char *file, const char *arg, ...); //-
int execv(const char *pathname, char *const argv[]); //+
int execve(const char *pathname, char *const argv[], char *const envp[]); //+
int execvp(const char *file, char *const argv[]); //-
int faccessat(int dfd, const char *pathname, int mode, int flags); //-
int fchdir(int dfd); //-
int fchown(int dfd, uid_t uid, gid_t gid); //-
int fchownat(int dfd, const char *pathname, uid_t uid, gid_t gid, int flags); //-
int fdatasync(int fd); //?
int fexecve(int fd, char *const argv[], char *const argp[]); //-
long fpathconf(int fd, int name); //-
int fsync(int fd); //?
int ftruncate(int fd, off_t size); //-
char *getcwd(char *buf, size_t lim); //+
int isatty(int fd); //+
int lchown(const char *pathname, uid_t uid, gid_t gid); //-
int link(const char *oldpath, const char *newpath); //-
int linkat(int old_dfd, const char *oldpath, int new_dfd, const char *newpath, int flags); //-
int lockf(int fd, int cmd, off_t len); //-
off_t lseek(int fd, off_t off, int whence); //+
long pathconf(const char *pathname, int name); //+
int pipe(int fds[2]); //+
ssize_t pread(int fd, void *buf, size_t count, off_t offset); //-
ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset); //-
ssize_t read(int fd, void *buf, size_t count); //+
ssize_t readlink(const char *restrict pathname, char *restrict buf, size_t lim); //-
ssize_t readlinkat(int dfd, const char *restrict pathname, char *restrict buf, size_t lim); //-
int rmdir(const char *dirname); //+
int symlink(const char *target, const char *linkpath); //-
int symlinkat(const char *target, int linkdfd, const char *linkpath); //-
void sync(void); //+
int truncate(const char *pathname, off_t size); //-
int unlink(const char *pathname); //+
int unlinkat(int dfd, const char *pathname, int flags); //-
ssize_t write(int fd, const void *buf, size_t count); //+
// Access control
gid_t getegid(void); //+
uid_t geteuid(void); //+
gid_t getgid(void); //+
int getgroups(int size, gid_t list[]); //?
uid_t getuid(void); //+
int setegid(gid_t egid); //-
int seteuid(uid_t euid); //-
int setgid(gid_t gid); //+
int setregid(gid_t rgid, gid_t egid); //-
int setreuid(uid_t ruid, uid_t euid); //-
int setuid(uid_t uid); //+
// System control
size_t confstr(int name, char *buf, size_t lim); //+
long gethostid(void); //+
int gethostname(char *buf, size_t lim); //+
char *getlogin(void); //W
int getlogin_r(char *buf, size_t lim); //-
long sysconf(int name); //-
// getopt
int getopt(int argc, char *const argv[], const char *optstr); //
// Process control
_Noreturn void _exit(int status); //+
pid_t fork(void); //+
pid_t getpgid(pid_t pid); //+
pid_t getpgrp(void); //+
pid_t getpid(void); //+
pid_t getppid(void); //-
pid_t getsid(void); //-
int nice(int inc); //+
int pause(void); //+
int setpgid(pid_t pid, pid_t pgid); //+
pid_t setpgrp(void); //+
pid_t setsid(void); //-
unsigned int sleep(unsigned int sec); //+
pid_t tcgetprgp(int fd); //+
int tcsetpgrp(int fd, pid_t pgrp); //+
char *ttyname(int fd); //W
int ttyname_r(int fd, char *buf, size_t size); //?
// Helpers and crypt
char *crypt(const char *key, const char *salt); //
void encrypt(char block[64], int edflag); //
void swab(const void *from, void *to, ssize_t n); //
+2
View File
@@ -0,0 +1,2 @@
static char *dummy[] = { (char *) 0 };
char **environ = (char **) &dummy;
+3
View File
@@ -0,0 +1,3 @@
#include <errno.h>
int errno = 0;
+12
View File
@@ -0,0 +1,12 @@
#include <unistd.h>
#include <string.h>
#include <_libc/abort.h>
_Noreturn void __libc_abort_init(const char *reason) {
static const char prefix[] = "libc abort: ";
char ln = '\n';
write(STDERR_FILENO, prefix, sizeof(prefix) - 1);
write(STDERR_FILENO, reason, strlen(reason));
write(STDERR_FILENO, &ln, 1);
_exit(-1);
}
+16
View File
@@ -0,0 +1,16 @@
// TODO: move to a proper place once I do abort()
#include <assert.h>
#include <string.h>
#include <unistd.h>
_Noreturn void _assert_fail(const char *func, const char *msg) {
static const char msg0[] = "In function `";
static const char msg1[] = "':\n";
write(STDERR_FILENO, msg0, sizeof(msg0) - 1);
write(STDERR_FILENO, func, strlen(func));
write(STDERR_FILENO, msg1, sizeof(msg1) - 1);
write(STDERR_FILENO, msg, strlen(msg));
write(STDERR_FILENO, msg1 + 2, 1);
_exit(-1);
}
+6
View File
@@ -0,0 +1,6 @@
#include <stdlib.h>
void exit(int status) {
// TODO: call atexit()s here
_Exit(status);
}
+58
View File
@@ -0,0 +1,58 @@
#include <_libc/malloc.h>
#include <sys/mman.h>
#include <assert.h>
void free(void *ptr) {
if (!ptr) {
return;
}
struct block *block = ptr - sizeof(struct block);
if ((block->flags & BLOCK_MAGIC_MASK) != BLOCK_MAGIC) {
while (1);
}
if (!(block->flags & BLOCK_ALLOC)) {
while (1);
}
if (block->flags & BLOCK_MMAP) {
void *base = (void *) ((uintptr_t) block & ~0xFFF);
size_t len = block->size + 0x1000;
munmap(base, len);
return;
}
block->flags &= ~BLOCK_ALLOC;
struct block *prev, *next;
prev = block->prev;
next = block->next;
if (prev && !(prev->flags & BLOCK_ALLOC)) {
block->flags = 0;
prev->next = next;
if (next) {
next->prev = prev;
}
prev->size += block->size + sizeof(struct block);
block = prev;
}
if (next && !(next->flags & BLOCK_ALLOC)) {
next->flags = 0;
if (next->next) {
next->next->prev = block;
}
block->next = next->next;
block->size += next->size + sizeof(struct block);
}
if (!block->prev && !block->next) {
struct zone *zone = (void *) block - sizeof(struct zone);
assert(!((uintptr_t) zone & 0xFFF));
list_del(&zone->list);
zone_destroy(zone);
}
}
+91
View File
@@ -0,0 +1,91 @@
#include <_libc/malloc.h>
#include <_libc/list.h>
#include <sys/mman.h>
#include <string.h>
#include <assert.h>
// Small zone allocation function
// XXX: This is absolute bullshit: meet my first fit allocator
static void *zone_alloc(struct zone *zone, size_t count) {
struct block *begin = (struct block *) &zone[1];
count = (count + 15) & ~15;
for (struct block *block = begin; block; block = block->next) {
if (block->flags & BLOCK_ALLOC) {
continue;
}
if (count == block->size) {
block->flags |= BLOCK_ALLOC;
void *ptr = &block[1];
memset(ptr, 0, count);
return ptr;
} else if (block->size >= count + sizeof(struct block)) {
// Insert new block after this one
struct block *cur_next = block->next;
struct block *new_block = (struct block *) (((uintptr_t) block) + sizeof(struct block) + count);
if (cur_next) {
cur_next->prev = new_block;
}
new_block->next = cur_next;
new_block->prev = block;
new_block->size = block->size - sizeof(struct block) - count;
new_block->flags = BLOCK_MAGIC;
block->next = new_block;
block->size = count;
block->flags |= 1;
void *ptr = &block[1];
memset(ptr, 0, count);
return ptr;
}
}
return NULL;
}
///
static void *alloc_from(struct list_head *head, size_t zone_size, size_t size) {
struct zone *zone;
void *ptr;
try_again:
list_for_each_entry(zone, head, list) {
if ((ptr = zone_alloc(zone, size))) {
return ptr;
}
}
zone = zone_create(zone_size);
if (!zone) {
return NULL;
}
list_add(&zone->list, head);
goto try_again;
}
void *malloc(size_t size) {
if (size <= SMALL_ZONE_ELEM) {
return alloc_from(&small_zone_list, SMALL_ZONE_SIZE, size);
} else if (size <= MID_ZONE_ELEM) {
return alloc_from(&mid_zone_list, MID_ZONE_SIZE, size);
} else if (size <= LARGE_ZONE_ELEM) {
return alloc_from(&large_zone_list, LARGE_ZONE_SIZE, size);
} else {
size_t pages_needed = (size + 0xFFF) & ~0xFFF;
void *pages = mmap(NULL, pages_needed + 0x1000, 0, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (pages == MAP_FAILED) {
return NULL;
}
struct block *block = pages + 0x1000 - sizeof(struct block);
block->flags = BLOCK_MAGIC | BLOCK_ALLOC | BLOCK_MMAP;
block->size = pages_needed;
return pages + 0x1000;
}
}
+26
View File
@@ -0,0 +1,26 @@
#include <_libc/malloc.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
void *realloc(void *old, size_t size) {
// TODO: maybe optimize this
void *ptr = malloc(size);
if (!ptr) {
return NULL;
}
if (old) {
struct block *old_block = old - sizeof(struct block);
size_t less_size = size;
if (less_size > old_block->size) {
less_size = old_block->size;
}
assert((old_block->flags & BLOCK_MAGIC_MASK) == BLOCK_MAGIC);
memcpy(ptr, old, less_size);
free(old);
}
return ptr;
}
+33
View File
@@ -0,0 +1,33 @@
#include <_libc/malloc.h>
#include <sys/mman.h>
#include <assert.h>
LIST_HEAD(small_zone_list);
LIST_HEAD(mid_zone_list);
LIST_HEAD(large_zone_list);
struct zone *zone_create(size_t size) {
void *pages = mmap(NULL, size, 0, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (pages == MAP_FAILED) {
return NULL;
}
struct zone *zone = pages;
struct block *head = pages + sizeof(struct zone);
zone->size = size - sizeof(struct zone);
list_head_init(&zone->list);
head->size = size - sizeof(struct zone) - sizeof(struct block);
head->flags = BLOCK_MAGIC;
head->prev = NULL;
head->next = NULL;
return zone;
}
void zone_destroy(struct zone *zone) {
assert(!((uintptr_t) zone & 0xFFF));
munmap(zone, zone->size + sizeof(struct zone));
}
+6
View File
@@ -0,0 +1,6 @@
#include <stdlib.h>
#include <_libc/signal.h>
void _sig_dfl(int signum) {
exit(signum << 8);
}
+50
View File
@@ -0,0 +1,50 @@
/*
* Yggdrasil's signal implementation details
*/
#include <signal.h>
#include <stdlib.h>
#include <ygg/syscall.h>
#include <_libc/abort.h>
#include <_libc/signal.h>
#include <_libc/syscalls.h>
static sighandler_t signal_handlers[NSIG];
// _Noreturn because this function *must* end up
// calling sigreturn syscall
static _Noreturn void __libc_signal_handle(int signum) {
if (signum <= 0 || signum >= NSIG) {
// TODO: abort()
exit(-1);
}
if (signal_handlers[signum]) {
signal_handlers[signum](signum);
} else {
_sig_dfl(signum);
}
__syscall0(SYSCALL_NR_SIGRETURN);
// To enforce _Noreturn
while (1);
}
void __libc_signal_init(void) {
stack_t ss;
void *sig_stack;
sig_stack = malloc(__LIBC_SIGNAL_STACK_SIZE);
if (sig_stack == NULL) {
__libc_abort_init("Failed to allocate signal stack");
}
// Tell kernel about signal stack
ss.ss_sp = sig_stack;
ss.ss_size = __LIBC_SIGNAL_STACK_SIZE;
if (sigaltstack(&ss, NULL) != 0) {
__libc_abort_init("Failed to set signal stack");
}
// Tell kernel about signal entry
__syscall1(SYSCALL_NRX_SIGENTRY, (long) __libc_signal_handle);
}
+8
View File
@@ -0,0 +1,8 @@
#include <errno.h>
#include <signal.h>
#include <ygg/syscall.h>
#include <_libc/syscalls.h>
int sigaltstack(const stack_t *ss, stack_t *old_ss) {
return SET_ERRNO(int, __syscall2(SYSCALL_NR_SIGALTSTACK, (long) ss, (long) old_ss));
}
View File
+44
View File
@@ -0,0 +1,44 @@
#include <_libc/stdio.h>
#include <errno.h>
#include <stdio.h>
int fgetc_unlocked(FILE *fp) {
if (fp->buf_mode == _IONBF) {
unsigned char c;
if (fread_unlocked(&c, sizeof(c), 1, fp) == 1) {
return c;
}
return EOF;
}
if (fp->flags & FILE_FLAG_EOF) {
return 0;
}
if (!(fp->flags & FILE_MODE_READ)) {
errno = EBADF;
fp->flags |= FILE_FLAG_ERROR;
return 0;
}
__libc_file_flush_write(fp);
if (fp->rdbufpos >= fp->rdbuf) {
// Reached end of readbuf
// TODO: arbitrary buffer size setting?
ssize_t bread = fp->read(fp->ctx, fp->buf, BUFSIZ);
if (bread < 0) {
fp->flags |= FILE_FLAG_ERROR;
return EOF;
}
if (bread == 0) {
fp->flags |= FILE_FLAG_EOF;
return EOF;
}
fp->rdbufpos = 0;
fp->rdbuf = bread;
}
return ((char *) fp->buf)[fp->rdbufpos++];
}
+89
View File
@@ -0,0 +1,89 @@
#include <_libc/stdio.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
static void file_default_free(void *ctx, FILE *fp) {
(void) ctx;
free(fp);
}
FILE *__libc_file_create(void) {
FILE *res = malloc(sizeof(FILE) + BUFSIZ);
if (!res) {
errno = ENOMEM;
return NULL;
}
memset(res, 0, sizeof(FILE));
res->free = file_default_free;
res->buf = ((void *) res) + sizeof(FILE);
return res;
}
int __libc_file_mode(const char *mode) {
int flags = 0;
switch (*mode++) {
case 'r':
flags |= FILE_MODE_READ;
break;
case 'w':
flags |= FILE_MODE_WRITE | FILE_MODE_CREAT | FILE_MODE_TRUNC;
break;
case 'a':
flags |= FILE_MODE_WRITE | FILE_MODE_CREAT | FILE_MODE_APPEND;
break;
default:
return -1;
}
return flags;
}
int __libc_file_flush_read(FILE *fp) {
if ((fp->flags & FILE_MODE_READ) && fp->seek) {
// TODO: off_t
long count = fp->rdbuf - fp->rdbufpos;
if (count < 0) {
count = fp->seek(fp->ctx, count, SEEK_CUR);
// Reset file read buffer
fp->rdbuf = 0;
fp->rdbufpos = 0;
if (count < 0) {
fp->flags |= FILE_FLAG_ERROR;
return -1;
}
}
}
return 0;
}
int __libc_file_flush_write(FILE *fp) {
if (fp->flags & FILE_MODE_WRITE) {
size_t rem = fp->wrbuf;
size_t off = 0;
fp->wrbuf = 0;
while (rem) {
ssize_t bwrite = fp->write(fp->ctx, fp->buf + off, rem);
if (bwrite < 0) {
fp->flags |= FILE_FLAG_ERROR;
return -1;
}
if (bwrite == 0) {
fp->flags |= FILE_FLAG_EOF;
return -1;
}
rem -= bwrite;
off += bwrite;
}
}
return 0;
}
+130
View File
@@ -0,0 +1,130 @@
#include <_libc/stdio.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
static ssize_t file_read(void *ctx, void *buf, size_t lim);
static ssize_t file_write(void *ctx, const void *buf, size_t lim);
static int file_close(void *ctx);
char _stdin_buf[BUFSIZ];
char _stdout_buf[BUFSIZ];
char _stderr_buf[BUFSIZ];
FILE _stdin = {
.buf = _stdin_buf,
.buf_mode = _IOLBF,
.ctx = &_stdin,
.fd = STDIN_FILENO,
.free = NULL,
.read = file_read,
.write = file_write,
.close = file_close,
.flags = FILE_MODE_READ
};
FILE _stdout = {
.buf = _stdout_buf,
.buf_mode = _IOLBF,
.ctx = &_stdout,
.fd = STDOUT_FILENO,
.free = NULL,
.read = file_read,
.write = file_write,
.close = file_close,
.flags = FILE_MODE_WRITE
};
FILE _stderr = {
.buf = _stderr_buf,
.buf_mode = _IONBF,
.ctx = &_stdout,
.fd = STDERR_FILENO,
.free = NULL,
.read = file_read,
.write = file_write,
.close = file_close,
.flags = FILE_MODE_WRITE
};
FILE *const stdin = &_stdin;
FILE *const stdout = &_stdout;
FILE *const stderr = &_stderr;
static ssize_t file_read(void *ctx, void *buf, size_t lim) {
return read(((FILE *) ctx)->fd, buf, lim);
}
static ssize_t file_write(void *ctx, const void *buf, size_t lim) {
return write(((FILE *) ctx)->fd, buf, lim);
}
static int file_close(void *ctx) {
return close(((FILE *) ctx)->fd);
}
static long file_seek(void *ctx, long off, int whence) {
return lseek(((FILE *) ctx)->fd, off, whence);
}
int __libc_file_open_fd(FILE *fp, int fd, int flags) {
// TODO: disallow certain combinations of params
if (flags & FILE_MODE_READ) {
fp->flags |= FILE_MODE_READ;
}
if (flags & FILE_MODE_WRITE) {
fp->flags |= FILE_MODE_WRITE;
}
fp->fd = fd;
fp->ctx = fp;
fp->read = file_read;
fp->write = file_write;
fp->close = file_close;
fp->seek = file_seek;
return 0;
}
int __libc_file_open_path(FILE *fp, const char *pathname, const char *mode) {
int flags, c_flags = 0;
if ((flags = __libc_file_mode(mode)) == -1) {
errno = EINVAL;
return -1;
}
if (!(flags & (FILE_MODE_WRITE | FILE_MODE_READ))) {
errno = EINVAL;
return -1;
}
if (flags & FILE_MODE_WRITE) {
if (flags & FILE_MODE_READ) {
c_flags |= O_RDWR;
} else {
c_flags |= O_WRONLY;
}
} else {
c_flags |= O_RDONLY;
}
if (flags & FILE_MODE_CREAT) {
c_flags |= O_CREAT;
}
if (flags & FILE_MODE_TRUNC) {
c_flags |= O_TRUNC;
}
int fd = open(pathname, c_flags, 0666);
if (fd < 0) {
return -1;
}
if (__libc_file_open_fd(fp, fd, flags) != 0) {
int e = errno;
close(fd);
errno = e;
return -1;
}
return 0;
}
+6
View File
@@ -0,0 +1,6 @@
#include <stdio.h>
void flockfile(FILE *fp) {
// TODO: pthread mutices
(void) fp;
}
+20
View File
@@ -0,0 +1,20 @@
#include <_libc/stdio.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
FILE *fopen(const char *pathname, const char *mode) {
FILE *fp = __libc_file_create();
if (!fp) {
return NULL;
}
if (__libc_file_open_path(fp, pathname, mode) != 0) {
int e = errno;
fclose(fp);
errno = e;
return NULL;
}
return fp;
}
+30
View File
@@ -0,0 +1,30 @@
#include <_libc/stdio.h>
#include <errno.h>
#include <stdio.h>
int fputc_unlocked(int ch, FILE *fp) {
if (fp->buf_mode == _IONBF) {
unsigned char c = ch;
if (fwrite_unlocked(&c, sizeof(c), 1, fp) == 1) {
return c;
}
return EOF;
}
if (!(fp->flags & FILE_MODE_WRITE)) {
errno = EBADF;
fp->flags |= FILE_FLAG_ERROR;
return 0;
}
__libc_file_flush_read(fp);
((char *) fp->buf)[fp->wrbuf++] = ch;
if ((fp->buf_mode == _IOLBF && ch == '\n') || fp->wrbuf >= BUFSIZ) {
if (__libc_file_flush_write(fp) != 0) {
return EOF;
}
}
return ch;
}
+8
View File
@@ -0,0 +1,8 @@
#include <stdio.h>
size_t fread(void *buf, size_t size, size_t nmemb, FILE *fp) {
flockfile(fp);
size_t r = fread_unlocked(buf, size, nmemb, fp);
funlockfile(fp);
return r;
}
+31
View File
@@ -0,0 +1,31 @@
#include <_libc/stdio.h>
#include <stdio.h>
#include <errno.h>
size_t fread_unlocked(void *buf, size_t size, size_t nmemb, FILE *fp) {
// TODO: buffering
if (!(fp->flags & FILE_MODE_READ)) {
errno = EBADF;
fp->flags |= FILE_FLAG_ERROR;
return 0;
}
size_t rem = size * nmemb;
size_t off = 0;
fp->flags &= ~FILE_FLAG_EOF;
while (rem) {
ssize_t bread = fp->read(fp->ctx, buf + off, rem);
if (bread < 0) {
fp->flags |= FILE_FLAG_ERROR;
return off / size;
}
if (bread == 0) {
fp->flags |= FILE_FLAG_EOF;
return off / size;
}
off += bread;
rem -= bread;
}
return off / size;
}
+6
View File
@@ -0,0 +1,6 @@
#include <stdio.h>
void funlockfile(FILE *fp) {
// TODO: pthread mutices
(void) fp;
}
+8
View File
@@ -0,0 +1,8 @@
#include <stdio.h>
size_t fwrite(const void *data, size_t size, size_t nmemb, FILE *fp) {
flockfile(fp);
size_t r = fwrite_unlocked(data, size, nmemb, fp);
funlockfile(fp);
return r;
}
+53
View File
@@ -0,0 +1,53 @@
#include <_libc/stdio.h>
#include <assert.h>
#include <errno.h>
#include <stdio.h>
size_t fwrite_unlocked(const void *ptr, size_t size, size_t nmemb, FILE *fp) {
assert(fp);
if (fp->flags & FILE_FLAG_EOF) {
return 0;
}
if (!(fp->flags & FILE_MODE_WRITE)) {
errno = EBADF;
fp->flags |= FILE_FLAG_ERROR;
return 0;
}
if (fp->buf_mode == _IONBF) {
size_t rem = size * nmemb;
size_t off = 0;
fp->flags &= ~FILE_FLAG_EOF;
while (rem) {
ssize_t res = fp->write(fp->ctx, ptr + off, rem);
if (res < 0) {
// Signalled error
fp->flags |= FILE_FLAG_ERROR;
return off / size;
}
if (res == 0) {
// Signalled EOF
fp->flags |= FILE_FLAG_EOF;
return off /size;
}
off += res;
rem -= res;
}
return off / size;
}
for (size_t i = 0; i < size * nmemb; i += size) {
for (size_t b = 0; b < size; ++b) {
int r = fputc_unlocked(((char *) ptr)[i + b], fp);
if (r < 0) {
return i / size;
}
}
}
return nmemb;
}
+11
View File
@@ -0,0 +1,11 @@
#include <string.h>
void *memccpy(void *dst, const void *src, int c, size_t len) {
for (size_t i = 0; i < len; ++i) {
((unsigned char *) dst)[i] = ((unsigned char *) src)[i];
if (((unsigned char *) dst)[i] == c) {
return dst + i;
}
}
return NULL;
}
+10
View File
@@ -0,0 +1,10 @@
#include <string.h>
void *memchr(const void *ptr, int v, size_t len) {
for (size_t i = 0; i < len; ++i) {
if (((unsigned char *) ptr)[i] == v) {
return (void *) ptr + i;
}
}
return NULL;
}
+12
View File
@@ -0,0 +1,12 @@
#include <string.h>
int memcmp(const void *p0, const void *p1, size_t n) {
int diff;
for (size_t i = 0; i < n; ++i) {
diff = ((unsigned char *) p0)[i] - ((unsigned char *) p1)[i];
if (diff) {
return diff;
}
}
return 0;
}
+8
View File
@@ -0,0 +1,8 @@
#include <string.h>
void *memcpy(void *dst, const void *src, size_t sz) {
for (size_t i = 0; i < sz; ++i) {
((unsigned char *) dst)[i] = ((unsigned char *) src)[i];
}
return dst;
}
+24
View File
@@ -0,0 +1,24 @@
#include <string.h>
void *memmove(void *dest, const void *src, size_t n) {
if (dest == src) {
return dest;
}
if ((src + n) <= dest || (dest + n) <= src) {
return memcpy(dest, src, n);
}
if (dest < src) {
ptrdiff_t a = src - dest;
memcpy( dest, src, a);
memcpy((void *) src, src + a, n - a);
} else {
ptrdiff_t a = dest - src;
memcpy( dest + a, dest, n - a);
memcpy( dest, src, a);
}
return dest;
}
+8
View File
@@ -0,0 +1,8 @@
#include <string.h>
void *memset(void *ptr, int v, size_t len) {
for (size_t i = 0; i < len; ++i) {
((unsigned char *) ptr)[i] = v;
}
return ptr;
}
+27
View File
@@ -0,0 +1,27 @@
#include <string.h>
char *stpcpy(char *dest, const char *src) {
do {
*dest = *src;
if (!*src++) {
return dest;
}
++dest;
} while (1);
}
char *stpncpy(char *dest, const char *src, size_t n) {
if (!n) {
return dest;
}
do {
*dest = *src;
if (!*src++) {
return dest;
}
++dest;
if (!--n) {
return dest;
}
} while (1);
}
+25
View File
@@ -0,0 +1,25 @@
#include <string.h>
char *strcat(char *dst, const char *src) {
size_t len = strlen(dst);
for (size_t i = 0;; ++i) {
dst[len + i] = src[i];
if (!src[i]) {
break;
}
}
return dst;
}
char *strncat(char *dst, const char *src, size_t n) {
size_t d = strlen(dst);
size_t i;
for (i = 0; i < n && src[i]; ++i) {
dst[d + i] = src[i];
}
dst[d + i] = 0;
return dst;
}
+23
View File
@@ -0,0 +1,23 @@
#include <string.h>
char *strchr(const char *str, int chr) {
for (; *str; ++str) {
if (*str == chr) {
return (char *) str;
}
}
return NULL;
}
char *strrchr(const char *str, int chr) {
size_t len = strlen(str);
if (!len) {
return NULL;
}
while (--len) {
if (str[len] == chr) {
return (char *) &str[len];
}
}
return NULL;
}
+27
View File
@@ -0,0 +1,27 @@
#include <string.h>
int strcmp(const char *a, const char *b) {
for (;; ++a, ++b) {
int delta = *a - *b;
if (delta) {
return delta;
}
if (!*a) { // Implies !*b
break;
}
}
return 0;
}
int strncmp(const char *a, const char *b, size_t lim) {
for (; lim; ++a, ++b, --lim) {
int delta = *a - *b;
if (delta) {
return delta;
}
if (!*a) { // Implies !*b
break;
}
}
return 0;
}
+6
View File
@@ -0,0 +1,6 @@
#include <string.h>
// XXX: Not actually implemented - current locale is C
int strcoll(const char *a, const char *b) {
return strcmp(a, b);
}
+23
View File
@@ -0,0 +1,23 @@
#include <string.h>
char *strcpy(char *dst, const char *src) {
size_t i;
for (i = 0;; ++i) {
dst[i] = src[i];
if (!src[i]) {
break;
}
}
return dst;
}
char *strncpy(char *dst, const char *src, size_t n) {
size_t i;
for (i = 0; i < n; ++i) {
dst[i] = src[i];
if (!src[i]) {
break;
}
}
return dst;
}
+21
View File
@@ -0,0 +1,21 @@
#include <stdlib.h>
#include <string.h>
char *strdup(const char *str) {
char *ptr = malloc(strlen(str) + 1);
if (ptr) {
strcpy(ptr, str);
}
return ptr;
}
char *strndup(const char *str, size_t len) {
char *ptr;
size_t l = strnlen(str, len);
ptr = malloc(l + 1);
if (ptr) {
strncpy(ptr, str, l);
ptr[l] = 0;
}
return ptr;
}
+24
View File
@@ -0,0 +1,24 @@
#include <string.h>
// "Lower" group of errors
static const char *error0[64] = {};
char *strerror(int errnum) {
if (!errnum) {
return "success";
}
if (errnum < 0 || errnum >= 64 || !error0[errnum]) {
return "unknown error";
}
return (char *) error0[errnum];
}
int strerror_r(int errnum, char *buf, size_t len) {
const char *err = strerror(errnum);
if (!len) {
return -1;
}
strncpy(buf, err, len - 1);
buf[len - 1] = 0;
return 0;
}
+13
View File
@@ -0,0 +1,13 @@
#include <string.h>
size_t strlen(const char *s) {
size_t r;
for (r = 0; s[r]; ++r);
return r;
}
size_t strnlen(const char *s, size_t len) {
size_t r;
for (r = 0; r < len && s[r]; ++r);
return r;
}
+10
View File
@@ -0,0 +1,10 @@
#include <string.h>
char *strpbrk(const char *str, const char *accept) {
for (; *str; ++str) {
if (strchr(accept, *str)) {
return (char *) str;
}
}
return NULL;
}
+12
View File
@@ -0,0 +1,12 @@
#include <ygg/signum.h>
#include <string.h>
static const char *signal0[NSIG] = {
};
char *strsignal(int signum) {
if (signum <= 0 || signum >= NSIG) {
return "unknown signal";
}
return (char *) signal0[signum];
}
+27
View File
@@ -0,0 +1,27 @@
#include <string.h>
size_t strspn(const char *s, const char *accept) {
size_t l = 0;
while (*s) {
if (!strchr(accept, *s)) {
return l;
}
++l;
++s;
}
return l;
}
size_t strcspn(const char *s, const char *reject) {
size_t l = 0;
while (*s) {
if (strchr(reject, *s)) {
return l;
}
++l;
++s;
}
return l;
}
+17
View File
@@ -0,0 +1,17 @@
#include <string.h>
char *_strstr(const char *haystack, const char *needle) {
// TODO: maybe use KMP algorithm for small needle sizes
size_t n = strlen(needle);
if (!*needle && !*haystack) {
return (char *) haystack;
}
for (size_t i = 0; haystack[i]; ++i) {
if (!strncmp(haystack + i, needle, n)) {
return (char *) haystack + i;
}
}
return NULL;
}
+38
View File
@@ -0,0 +1,38 @@
#include <string.h>
char *strtok_r(char *str, const char *delim, char **saveptr) {
char *token;
if (!str) {
str = *saveptr;
}
// Skip leading delimiter
str += strspn(str, delim);
if (!*str) {
*saveptr = str;
// No next token - NULL
return NULL;
}
token = str;
str = strpbrk(str, delim);
if (str) {
// Have a delimiter
*str = 0;
*saveptr = str + 1;
} else {
// Point to end
*saveptr = token + strlen(token);
}
return token;
}
// TODO: throw an error "programmer" for using this
char *strtok(char *str, const char *delim) {
static char *saveptr;
if (str) {
saveptr = NULL;
}
return strtok_r(str, delim, &saveptr);
}
+8
View File
@@ -0,0 +1,8 @@
#include <_libc/syscalls.h>
#include <ygg/syscall.h>
#include <unistd.h>
#include <errno.h>
int open(const char *pathname, int flags, mode_t mode) {
return SET_ERRNO(int, __syscall3(SYSCALL_NR_OPEN, (long) pathname, flags, mode));
}
+24
View File
@@ -0,0 +1,24 @@
#include <_libc/syscalls.h>
#include <ygg/syscall.h>
#include <sys/mman.h>
#include <errno.h>
void *mmap(void *hint, size_t length, int prot, int flags, int fd, off_t offset) {
intptr_t res = (intptr_t) __syscall6(SYSCALL_NR_MMAP,
(long) hint,
length,
(long) prot,
(long) flags,
(long) fd,
offset);
if (res < 0) {
errno = (int) -res;
return (void *) -1;
} else {
return (void *) res;
}
}
int munmap(void *ptr, size_t len) {
return SET_ERRNO(int, __syscall2(SYSCALL_NR_MUNMAP, (long) ptr, len));
}
+11
View File
@@ -0,0 +1,11 @@
#include <_libc/syscalls.h>
#include <ygg/syscall.h>
#include <unistd.h>
#include <errno.h>
_Noreturn void _exit(int status) {
__syscall1(SYSCALL_NR_EXIT, status);
while (1);
}
_Noreturn void _Exit(int status) __attribute__((alias("_exit")));
+8
View File
@@ -0,0 +1,8 @@
#include <unistd.h>
#include <_libc/syscalls.h>
#include <ygg/syscall.h>
#include <errno.h>
int access(const char *pathname, int mode) {
return SET_ERRNO(int, __syscall2(SYSCALL_NR_ACCESS, (long) pathname, mode));
}
+8
View File
@@ -0,0 +1,8 @@
#include <_libc/syscalls.h>
#include <ygg/syscall.h>
#include <unistd.h>
#include <errno.h>
int chdir(const char *pathname) {
return SET_ERRNO(int, __syscall1(SYSCALL_NR_CHDIR, (long) pathname));
}
+8
View File
@@ -0,0 +1,8 @@
#include <_libc/syscalls.h>
#include <ygg/syscall.h>
#include <unistd.h>
#include <errno.h>
int chown(const char *pathname, uid_t uid, gid_t gid) {
return SET_ERRNO(int, __syscall3(SYSCALL_NR_CHOWN, (long) pathname, uid, gid));
}
+10
View File
@@ -0,0 +1,10 @@
#include <_libc/syscalls.h>
#include <ygg/syscall.h>
#include <unistd.h>
#include <errno.h>
int close(int fd) {
__syscall1(SYSCALL_NR_CLOSE, fd);
errno = 0;
return 0;
}
+11
View File
@@ -0,0 +1,11 @@
#include <unistd.h>
#include <errno.h>
size_t confstr(int name, char *buf, size_t len) {
(void) name;
(void) buf;
(void) len;
// TODO: _CS_PATH
errno = EINVAL;
return 0;
}
+8
View File
@@ -0,0 +1,8 @@
#include <_libc/syscalls.h>
#include <ygg/syscall.h>
#include <unistd.h>
#include <errno.h>
int dup(int oldfd) {
return SET_ERRNO(int, __syscall1(SYSCALL_NR_DUP, oldfd));
}
+9
View File
@@ -0,0 +1,9 @@
#include <_libc/syscalls.h>
#include <ygg/syscall.h>
#include <unistd.h>
#include <errno.h>
int dup2(int oldfd, int newfd) {
return SET_ERRNO(int, __syscall2(SYSCALL_NR_DUP2, oldfd, newfd));
}
+44
View File
@@ -0,0 +1,44 @@
#include <unistd.h>
#include <stdarg.h>
#include <stdlib.h>
#include <errno.h>
int execl(const char *pathname, const char *arg, ...) {
va_list args;
size_t argc;
int res;
if (!arg) {
// execv pathname without arguments
return execv(pathname, (char *const *) &arg);
}
// 1. collect arg count
va_start(args, arg);
while (va_arg(args, const char *)) {
++argc;
}
va_end(args);
// 2. allocate space for args
char **argv = malloc(sizeof(char *) * (argc + 1));
if (!argv) {
errno = ENOMEM;
return -1;
}
// 3. copy args
va_start(args, arg);
for (size_t i = 0; i < argc; ++i) {
argv[i] = va_arg(args, char *);
}
va_end(args);
argv[argc] = NULL;
res = execv(pathname, argv);
// Won't return normally, so free()
free(argv);
return res;
}
+49
View File
@@ -0,0 +1,49 @@
#include <unistd.h>
#include <stdarg.h>
#include <stdlib.h>
#include <errno.h>
int execle(const char *pathname, const char *arg, ...) {
va_list args;
char *const *envp;
size_t argc;
int res;
if (!arg) {
va_start(args, arg);
char *const *envp = va_arg(args, char *const *);
va_end(args);
return execve(pathname, (char *const *) &arg, envp);
}
// 1. collect arg count
va_start(args, arg);
while (va_arg(args, const char *)) {
++argc;
}
va_end(args);
// 2. allocate space for args
char **argv = malloc(sizeof(char *) * (argc + 1));
if (!argv) {
errno = ENOMEM;
return -1;
}
// 3. copy args
va_start(args, arg);
for (size_t i = 0; i < argc; ++i) {
argv[i] = va_arg(args, char *);
}
envp = va_arg(args, char *const *);
va_end(args);
argv[argc] = NULL;
res = execve(pathname, argv, envp);
// Won't return normally, so free()
free(argv);
return res;
}
+10
View File
@@ -0,0 +1,10 @@
#include <assert.h>
#include <unistd.h>
int execlp(const char *file, const char *arg, ...) {
(void) file;
(void) arg;
// TODO: PATH search impl.
assert(0 && "function not implemented");
}
+5
View File
@@ -0,0 +1,5 @@
#include <unistd.h>
int execv(const char *pathname, char *const argv[]) {
return execve(pathname, argv, environ);
}
+8
View File
@@ -0,0 +1,8 @@
#include <_libc/syscalls.h>
#include <ygg/syscall.h>
#include <unistd.h>
#include <errno.h>
int execve(const char *pathname, char *const argv[], char *const envp[]) {
return SET_ERRNO(int, __syscall3(SYSCALL_NR_EXECVE, (long) pathname, (long) argv, (long) envp));
}
+10
View File
@@ -0,0 +1,10 @@
#include <assert.h>
#include <unistd.h>
int execvp(const char *file, char *const argv[]) {
(void) file;
(void) argv;
// TODO: PATH search impl.
assert(0 && "function not implemented");
}
+14
View File
@@ -0,0 +1,14 @@
#include <_libc/syscalls.h>
#include <ygg/syscall.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
int faccessat(int dfd, const char *pathname, int mode, int flags) {
(void) dfd;
(void) pathname;
(void) mode;
(void) flags;
assert(0 && "system call not yet implemented");
}
+11
View File
@@ -0,0 +1,11 @@
#include <_libc/syscalls.h>
#include <ygg/syscall.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
int fchdir(int dfd) {
(void) dfd;
assert(0 && "system call not yet implemented");
}
+12
View File
@@ -0,0 +1,12 @@
#include <_libc/syscalls.h>
#include <ygg/syscall.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
int fchown(int fd, uid_t uid, gid_t gid) {
(void) fd;
(void) uid;
(void) gid;
assert(0 && "system call not yet implemented");
}
+14
View File
@@ -0,0 +1,14 @@
#include <_libc/syscalls.h>
#include <ygg/syscall.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
int fchownat(int dfd, const char *pathname, uid_t uid, gid_t gid, int flags) {
(void) dfd;
(void) pathname;
(void) uid;
(void) gid;
(void) flags;
assert(0 && "system call not yet implemented");
}
+11
View File
@@ -0,0 +1,11 @@
#include <_libc/syscalls.h>
#include <ygg/syscall.h>
#include <unistd.h>
#include <errno.h>
int fdatasync(int fd) {
(void) fd;
// FS is synchronous lol
return 0;
}
+13
View File
@@ -0,0 +1,13 @@
#include <_libc/syscalls.h>
#include <ygg/syscall.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
int fexecve(int fd, char *const argv[], char *const envp[]) {
(void) fd;
(void) argv;
(void) envp;
assert(0 && "system call not yet implemented");
}
+9
View File
@@ -0,0 +1,9 @@
#include <_libc/syscalls.h>
#include <ygg/syscall.h>
#include <unistd.h>
#include <errno.h>
pid_t fork(void) {
return SET_ERRNO(pid_t, __syscall0(SYSCALL_NR_FORK));
}
+12
View File
@@ -0,0 +1,12 @@
#include <_libc/syscalls.h>
#include <ygg/syscall.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
long fpathconf(int fd, int name) {
(void) fd;
(void) name;
assert(0 && "system call not yet implemented");
}
+11
View File
@@ -0,0 +1,11 @@
#include <_libc/syscalls.h>
#include <ygg/syscall.h>
#include <unistd.h>
#include <errno.h>
int fsync(int fd) {
(void) fd;
// FS is synchronous lol
return 0;
}
+12
View File
@@ -0,0 +1,12 @@
#include <ygg/syscall.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
int ftruncate(int fd, off_t size) {
(void) fd;
(void) size;
assert(0 && "system call not yet implemented");
}
+13
View File
@@ -0,0 +1,13 @@
#include <_libc/syscalls.h>
#include <ygg/syscall.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
char *getcwd(char *buf, size_t size) {
if (SET_ERRNO(int, __syscall2(SYSCALL_NR_GETCWD, (long) buf, size)) == 0) {
return buf;
} else {
return NULL;
}
}
+6
View File
@@ -0,0 +1,6 @@
#include <unistd.h>
gid_t getegid(void) {
// TODO: differentiate between gid and egid
return getgid();
}
+6
View File
@@ -0,0 +1,6 @@
#include <unistd.h>
uid_t geteuid(void) {
// TODO: differentiate between uid and euid
return getuid();
}
+8
View File
@@ -0,0 +1,8 @@
#include <_libc/syscalls.h>
#include <ygg/syscall.h>
#include <unistd.h>
#include <errno.h>
gid_t getgid(void) {
return __syscall0(SYSCALL_NR_GETGID);
}
+8
View File
@@ -0,0 +1,8 @@
#include <unistd.h>
int getgroups(int size, gid_t list[]) {
(void) size;
(void) list;
// TODO: supplementary groups
return 0;
}
+5
View File
@@ -0,0 +1,5 @@
#include <unistd.h>
long gethostid(void) {
return 0;
}
+20
View File
@@ -0,0 +1,20 @@
#include <unistd.h>
#include <string.h>
#include <errno.h>
// TODO: sys/utsname.h
#include <ygg/utsname.h>
extern int uname(struct utsname *buf);
int gethostname(char *name, size_t len) {
// Use uname to retrieve hostname
struct utsname v;
if (!len || uname(&v) != 0) {
return -1;
}
strncpy(name, v.nodename, len - 1);
name[len] = 0;
return 0;
}
+10
View File
@@ -0,0 +1,10 @@
#include <unistd.h>
#include <errno.h>
int getlogin_r(char *buf, size_t bufsize) {
(void) buf;
(void) bufsize;
// TODO: read pwd for username
errno = ENOENT;
return -1;
}
+8
View File
@@ -0,0 +1,8 @@
#include <_libc/syscalls.h>
#include <ygg/syscall.h>
#include <unistd.h>
#include <errno.h>
pid_t getpgid(pid_t pid) {
return SET_ERRNO(pid_t, __syscall1(SYSCALL_NR_GETPGID, pid));
}

Some files were not shown because too many files have changed in this diff Show More