├── LICENSE ├── README.md └── src ├── Makefile ├── crt ├── __libc_start_main.c └── start.asm ├── errno.c ├── include ├── errno.h ├── fcntl.h ├── internal │ ├── arch │ │ └── x86_64 │ │ │ ├── syscall_arch.h │ │ │ └── syscall_list.h │ ├── essentials.h │ ├── io.h │ ├── mm │ │ └── mem_list.h │ ├── syscall.h │ └── types.h ├── stdarg.h ├── stddef.h ├── stdio.h ├── stdlib.h ├── string.h ├── sys │ ├── mman.h │ ├── stat.h │ └── types.h ├── time.h └── unistd.h ├── io ├── close.c ├── ftruncate.c ├── lseek.c ├── open.c ├── read_write.c └── truncate.c ├── mm ├── malloc.c ├── mem_list.c └── mmap.c ├── process ├── exit.c ├── nanosleep.c └── sleep.c ├── stat ├── fstat.c ├── fstatat.c └── stat.c ├── stdio └── puts.c ├── string └── string.c └── syscall.c /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Florian Ariașu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Mini-libc: A Minimalist Standard C Library Implementation 2 | 3 | ### Overview 4 | Welcome to **mini-libc**, a lightweight and freestanding implementation of the **standard C library** for Linux systems! This project is built from the ground up to replace the default system libc, relying solely on Linux system calls. By crafting a minimal yet functional libc, you'll dive deep into **string manipulation, memory management, and low-level file I/O** operations. 5 | 6 | ### Objectives 7 | - Understand the structure and purpose of the **C standard library** 8 | - Develop a **freestanding** implementation using only **syscalls** 9 | - Implement fundamental **string and memory functions** 10 | - Provide essential **file I/O and process utilities** 11 | - Gain insights into **Linux syscall interfaces** 12 | 13 | ### Core Features 14 | 15 | #### String Manipulation (``) 16 | Efficient string-handling functions: 17 | - `strcpy()` / `strncpy()` 18 | - `strcat()` / `strncat()` 19 | - `strlen()` 20 | - `strcmp()` / `strncmp()` 21 | - `strstr()` / `strrstr()` 22 | - `memcpy()` / `memmove()` 23 | - `memset()` / `memcmp()` 24 | 25 | #### Input/Output (``) 26 | - `puts()` – Simple **string printing** via `syscall(__NR_write)` 27 | 28 | #### File & Process Control (``, ``, ``) 29 | Essential **POSIX-compliant file operations**: 30 | - `open()` / `close()` 31 | - `lseek()` 32 | - `stat()` / `fstat()` 33 | - `truncate()` / `ftruncate()` 34 | 35 | #### Time Utilities (``) 36 | - `nanosleep()` / `sleep()` 37 | 38 | #### Memory Management (``, ``) 39 | Lightweight **dynamic memory allocation**: 40 | - `malloc()` / `free()` 41 | - `calloc()` 42 | - `realloc()` / `reallocarray()` 43 | - `mmap()` / `mremap()` / `munmap()` 44 | 45 | #### Error Handling (``) 46 | - `errno` variable management for **system call failures** 47 | 48 | ### Build & Installation 49 | #### Compiling mini-libc 50 | ```bash 51 | cd src/ 52 | make 53 | ``` 54 | 55 | ### Resources & References 56 | - [GNU libc manual](https://www.gnu.org/software/libc/manual/html_mono/libc.html) 57 | - [musl libc source](https://elixir.bootlin.com/musl/latest/source) 58 | - [Linux man pages](https://man7.org/linux/man-pages/index.html) 59 | 60 | ### Licence 61 | This project is licensed under the MIT Licence. See the [LICENCE](./LICENSE) file for further details. 62 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | NASM = nasm 2 | CPPFLAGS = -nostdinc -Iinclude 3 | CFLAGS = -Wall -Wextra -fno-PIC -fno-stack-protector -fno-builtin 4 | # Remove the line below to disable debugging support. 5 | CFLAGS += -g -O0 6 | 7 | .PHONY: all clean pack 8 | 9 | SRCS = syscall.c \ 10 | process/exit.c process/sleep.c process/nanosleep.c \ 11 | mm/malloc.c mm/mmap.c mm/mem_list.c \ 12 | string/string.c \ 13 | stat/fstat.c stat/stat.c \ 14 | io/open.c io/close.c io/read_write.c \ 15 | io/lseek.c io/truncate.c io/ftruncate.c \ 16 | errno.c \ 17 | crt/__libc_start_main.c \ 18 | io/puts.c 19 | 20 | # TODO: Add sleep.c and puts.c dependency. 21 | 22 | OBJS = $(patsubst %.c,%.o,$(SRCS)) 23 | 24 | all: libc.a 25 | 26 | libc.a: $(OBJS) crt/start.o 27 | $(AR) -rc $@ $^ 28 | 29 | $(OBJS): %.o:%.c 30 | 31 | crt/start.o: crt/start.asm 32 | $(NASM) -f elf64 -o $@ $< 33 | 34 | pack: clean 35 | zip -r ../src.zip * 36 | 37 | clean: 38 | -rm -f *~ 39 | -rm -f $(OBJS) crt/start.o 40 | -rm -f libc.a 41 | -------------------------------------------------------------------------------- /src/crt/__libc_start_main.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | 3 | #include 4 | #include 5 | 6 | static void init(void) 7 | { 8 | mem_list_init(); 9 | } 10 | 11 | static void cleanup(void) 12 | { 13 | mem_list_cleanup(); 14 | } 15 | 16 | int __libc_start_main(int (*main_fn)(void)) 17 | { 18 | int exit_code; 19 | 20 | init(); 21 | exit_code = main_fn(); 22 | cleanup(); 23 | 24 | return exit_code; 25 | } 26 | -------------------------------------------------------------------------------- /src/crt/start.asm: -------------------------------------------------------------------------------- 1 | extern main 2 | extern exit 3 | extern __libc_start_main 4 | 5 | section .text 6 | 7 | global _start 8 | 9 | _start: 10 | mov rdi, main 11 | call __libc_start_main 12 | 13 | mov rdi, rax 14 | call exit 15 | 16 | hlt 17 | -------------------------------------------------------------------------------- /src/errno.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | 3 | #include 4 | 5 | int errno; 6 | -------------------------------------------------------------------------------- /src/include/errno.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: BSD-3-Clause */ 2 | 3 | #ifndef __ERRNO_H__ 4 | #define __ERRNO_H__ 1 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | extern int errno; 11 | 12 | #define EPERM 1 /* Operation not permitted */ 13 | #define ENOENT 2 /* No such file or directory */ 14 | #define ESRCH 3 /* No such process */ 15 | #define EINTR 4 /* Interrupted system call */ 16 | #define EIO 5 /* I/O error */ 17 | #define ENXIO 6 /* No such device or address */ 18 | #define E2BIG 7 /* Arg list too long */ 19 | #define ENOEXEC 8 /* Exec format error */ 20 | #define EBADF 9 /* Bad file number */ 21 | #define ECHILD 10 /* No child processes */ 22 | #define EAGAIN 11 /* Try again */ 23 | #define ENOMEM 12 /* Out of memory */ 24 | #define EACCES 13 /* Permission denied */ 25 | #define EFAULT 14 /* Bad address */ 26 | #define ENOTBLK 15 /* Block device required */ 27 | #define EBUSY 16 /* Device or resource busy */ 28 | #define EEXIST 17 /* File exists */ 29 | #define EXDEV 18 /* Cross-device link */ 30 | #define ENODEV 19 /* No such device */ 31 | #define ENOTDIR 20 /* Not a directory */ 32 | #define EISDIR 21 /* Is a directory */ 33 | #define EINVAL 22 /* Invalid argument */ 34 | #define ENFILE 23 /* File table overflow */ 35 | #define EMFILE 24 /* Too many open files */ 36 | #define ENOTTY 25 /* Not a typewriter */ 37 | #define ETXTBSY 26 /* Text file busy */ 38 | #define EFBIG 27 /* File too large */ 39 | #define ENOSPC 28 /* No space left on device */ 40 | #define ESPIPE 29 /* Illegal seek */ 41 | #define EROFS 30 /* Read-only file system */ 42 | #define EMLINK 31 /* Too many links */ 43 | #define EPIPE 32 /* Broken pipe */ 44 | #define EDOM 33 /* Math argument out of domain of func */ 45 | #define ERANGE 34 /* Math result not representable */ 46 | #define EDEADLK 35 /* Resource deadlock would occur */ 47 | #define ENAMETOOLONG 36 /* File name too long */ 48 | #define ENOLCK 37 /* No record locks available */ 49 | #define ENOSYS 38 /* Function not implemented */ 50 | #define ENOTEMPTY 39 /* Directory not empty */ 51 | #define ELOOP 40 /* Too many symbolic links encountered */ 52 | #define EWOULDBLOCK 41 /* Operation would block */ 53 | #define ENOMSG 42 /* No message of desired type */ 54 | #define EIDRM 43 /* Identifier removed */ 55 | #define ECHRNG 44 /* Channel number out of range */ 56 | #define EL2NSYNC 45 /* Level 2 not synchronized */ 57 | #define EL3HLT 46 /* Level 3 halted */ 58 | #define EL3RST 47 /* Level 3 reset */ 59 | #define ELNRNG 48 /* Link number out of range */ 60 | #define EUNATCH 49 /* Protocol driver not attached */ 61 | #define ENOCSI 50 /* No CSI structure available */ 62 | #define EL2HLT 51 /* Level 2 halted */ 63 | #define EBADE 52 /* Invalid exchange */ 64 | #define EBADR 53 /* Invalid request descriptor */ 65 | #define EXFULL 54 /* Exchange full */ 66 | #define ENOANO 55 /* No anode */ 67 | #define EBADRQC 56 /* Invalid request code */ 68 | #define EBADSLT 57 /* Invalid slot */ 69 | #define EDEADLOCK 58 /* File locking deadlock error */ 70 | #define EBFONT 59 /* Bad font file format */ 71 | #define ENOSTR 60 /* Device not a stream */ 72 | #define ENODATA 61 /* No data available */ 73 | #define ETIME 62 /* Timer expired */ 74 | #define ENOSR 63 /* Out of streams resources */ 75 | #define ENONET 64 /* Machine is not on the network */ 76 | #define ENOPKG 65 /* Package not installed */ 77 | #define EREMOTE 66 /* Object is remote */ 78 | #define ENOLINK 67 /* Link has been severed */ 79 | #define EADV 68 /* Advertise error */ 80 | #define ESRMNT 69 /* Srmount error */ 81 | #define ECOMM 70 /* Communication error on send */ 82 | #define EPROTO 71 /* Protocol error */ 83 | #define EMULTIHOP 72 /* Multihop attempted */ 84 | #define EDOTDOT 73 /* RFS specific error */ 85 | #define EBADMSG 74 /* Not a data message */ 86 | #define EOVERFLOW 75 /* Value too large for defined data type */ 87 | #define ENOTUNIQ 76 /* Name not unique on network */ 88 | #define EBADFD 77 /* File descriptor in bad state */ 89 | #define EREMCHG 78 /* Remote address changed */ 90 | #define ELIBACC 79 /* Can not access a needed shared library */ 91 | #define ELIBBAD 80 /* Accessing a corrupted shared library */ 92 | #define ELIBSCN 81 /* .lib section in a.out corrupted */ 93 | #define ELIBMAX 82 /* Attempting to link in too many shared libraries */ 94 | #define ELIBEXEC 83 /* Cannot exec a shared library directly */ 95 | #define EILSEQ 84 /* Illegal byte sequence */ 96 | #define ERESTART 85 /* Interrupted system call should be restarted */ 97 | #define ESTRPIPE 86 /* Streams pipe error */ 98 | #define EUSERS 87 /* Too many users */ 99 | #define ENOTSOCK 88 /* Socket operation on non-socket */ 100 | #define EDESTADDRREQ 89 /* Destination address required */ 101 | #define EMSGSIZE 90 /* Message too long */ 102 | #define EPROTOTYPE 91 /* Protocol wrong type for socket */ 103 | #define ENOPROTOOPT 92 /* Protocol not available */ 104 | #define EPROTONOSUPPORT 93 /* Protocol not supported */ 105 | #define ESOCKTNOSUPPORT 94 /* Socket type not supported */ 106 | #define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ 107 | #define EPFNOSUPPORT 96 /* Protocol family not supported */ 108 | #define EAFNOSUPPORT 97 /* Address family not supported by protocol */ 109 | #define EADDRINUSE 98 /* Address already in use */ 110 | #define EADDRNOTAVAIL 99 /* Cannot assign requested address */ 111 | #define ENETDOWN 100 /* Network is down */ 112 | #define ENETUNREACH 101 /* Network is unreachable */ 113 | #define ENETRESET 102 /* Network dropped connection because of reset */ 114 | #define ECONNABORTED 103 /* Software caused connection abort */ 115 | #define ECONNRESET 104 /* Connection reset by peer */ 116 | #define ENOBUFS 105 /* No buffer space available */ 117 | #define EISCONN 106 /* Transport endpoint is already connected */ 118 | #define ENOTCONN 107 /* Transport endpoint is not connected */ 119 | #define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ 120 | #define ETOOMANYREFS 109 /* Too many references: cannot splice */ 121 | #define ETIMEDOUT 110 /* Connection timed out */ 122 | #define ECONNREFUSED 111 /* Connection refused */ 123 | #define EHOSTDOWN 112 /* Host is down */ 124 | #define EHOSTUNREACH 113 /* No route to host */ 125 | #define EALREADY 114 /* Operation already in progress */ 126 | #define EINPROGRESS 115 /* Operation now in progress */ 127 | #define ESTALE 116 /* Stale NFS file handle */ 128 | #define EUCLEAN 117 /* Structure needs cleaning */ 129 | #define ENOTNAM 118 /* Not a XENIX named type file */ 130 | #define ENAVAIL 119 /* No XENIX semaphores available */ 131 | #define EISNAM 120 /* Is a named type file */ 132 | #define EREMOTEIO 121 /* Remote I/O error */ 133 | 134 | #ifdef __cplusplus 135 | } 136 | #endif 137 | 138 | #endif 139 | -------------------------------------------------------------------------------- /src/include/fcntl.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: BSD-3-Clause */ 2 | 3 | #ifndef _FCNTL_H 4 | #define _FCNTL_H 1 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #include 11 | 12 | #define O_ACCMODE 0003 13 | #define O_RDONLY 00 14 | #define O_WRONLY 01 15 | #define O_RDWR 02 16 | #define FD_CLOEXEC 1 17 | 18 | #ifndef O_CREAT 19 | # define O_CREAT 0100 /* Not fcntl. */ 20 | #endif 21 | #ifndef O_EXCL 22 | # define O_EXCL 0200 /* Not fcntl. */ 23 | #endif 24 | #ifndef O_NOCTTY 25 | # define O_NOCTTY 0400 /* Not fcntl. */ 26 | #endif 27 | #ifndef O_TRUNC 28 | # define O_TRUNC 01000 /* Not fcntl. */ 29 | #endif 30 | #ifndef O_APPEND 31 | # define O_APPEND 02000 32 | #endif 33 | #ifndef O_DIRECTORY 34 | # define O_DIRECTORY 0200000 35 | #endif 36 | #ifndef O_TMPFILE 37 | # define O_TMPFILE (020000000 | O_DIRECTORY) 38 | #endif 39 | #ifndef O_CLOEXEC 40 | # define O_CLOEXEC 02000000 41 | #endif 42 | 43 | #ifndef S_IRUSR 44 | #define S_ISUID 04000 45 | #define S_ISGID 02000 46 | #define S_ISVTX 01000 47 | #define S_IRUSR 0400 48 | #define S_IWUSR 0200 49 | #define S_IXUSR 0100 50 | #define S_IRWXU 0700 51 | #define S_IRGRP 0040 52 | #define S_IWGRP 0020 53 | #define S_IXGRP 0010 54 | #define S_IRWXG 0070 55 | #define S_IROTH 0004 56 | #define S_IWOTH 0002 57 | #define S_IXOTH 0001 58 | #define S_IRWXO 0007 59 | #endif 60 | 61 | #define F_DUPFD 0 /* Duplicate file descriptor. */ 62 | #define F_GETFD 1 /* Get file descriptor flags. */ 63 | #define F_SETFD 2 /* Set file descriptor flags. */ 64 | #define F_GETFL 3 /* Get file status flags. */ 65 | #define F_SETFL 4 /* Set file status flags. */ 66 | 67 | #define AT_FDCWD -100 /* Special value used to indicate openat should use the current working directory. */ 68 | 69 | int open(const char *filename, int flags, ...); 70 | 71 | #ifdef __cplusplus 72 | } 73 | #endif 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /src/include/internal/arch/x86_64/syscall_arch.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: BSD-3-Clause */ 2 | 3 | /* 4 | * From Musl Libc: https://musl.libc.org/ 5 | * 6 | * https://git.musl-libc.org/cgit/musl/tree/arch/x86_64/syscall_arch.h 7 | */ 8 | 9 | #ifndef __SYSCALL_ARCH_X86_64__ 10 | #define __SYSCALL_ARCH_X86_64__ 1 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | static inline long __syscall(long n, long a1, long a2, long a3, long a4, long a5, long a6) 17 | { 18 | unsigned long ret; 19 | 20 | register long r10 __asm__("r10") = a4; 21 | register long r8 __asm__("r8") = a5; 22 | register long r9 __asm__("r9") = a6; 23 | 24 | __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), 25 | "d"(a3), "r"(r10), "r"(r8), "r"(r9) : "rcx", "r11", "memory"); 26 | 27 | return ret; 28 | } 29 | 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/include/internal/arch/x86_64/syscall_list.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: BSD-3-Clause */ 2 | 3 | #ifndef __SYSCALL_LIST_X86_64__ 4 | #define __SYSCALL_LIST_X86_64__ 1 5 | 6 | #define __NR_read 0 7 | #define __NR_write 1 8 | #define __NR_open 2 9 | #define __NR_close 3 10 | #define __NR_stat 4 11 | #define __NR_fstat 5 12 | #define __NR_lstat 6 13 | #define __NR_poll 7 14 | #define __NR_lseek 8 15 | #define __NR_mmap 9 16 | #define __NR_mprotect 10 17 | #define __NR_munmap 11 18 | #define __NR_brk 12 19 | #define __NR_rt_sigaction 13 20 | #define __NR_rt_sigprocmask 14 21 | #define __NR_rt_sigreturn 15 22 | #define __NR_ioctl 16 23 | #define __NR_pread64 17 24 | #define __NR_pwrite64 18 25 | #define __NR_readv 19 26 | #define __NR_writev 20 27 | #define __NR_access 21 28 | #define __NR_pipe 22 29 | #define __NR_select 23 30 | #define __NR_sched_yield 24 31 | #define __NR_mremap 25 32 | #define __NR_msync 26 33 | #define __NR_mincore 27 34 | #define __NR_madvise 28 35 | #define __NR_shmget 29 36 | #define __NR_shmat 30 37 | #define __NR_shmctl 31 38 | #define __NR_dup 32 39 | #define __NR_dup2 33 40 | #define __NR_pause 34 41 | #define __NR_nanosleep 35 42 | #define __NR_getitimer 36 43 | #define __NR_alarm 37 44 | #define __NR_setitimer 38 45 | #define __NR_getpid 39 46 | #define __NR_sendfile 40 47 | #define __NR_socket 41 48 | #define __NR_connect 42 49 | #define __NR_accept 43 50 | #define __NR_sendto 44 51 | #define __NR_recvfrom 45 52 | #define __NR_sendmsg 46 53 | #define __NR_recvmsg 47 54 | #define __NR_shutdown 48 55 | #define __NR_bind 49 56 | #define __NR_listen 50 57 | #define __NR_getsockname 51 58 | #define __NR_getpeername 52 59 | #define __NR_socketpair 53 60 | #define __NR_setsockopt 54 61 | #define __NR_getsockopt 55 62 | #define __NR_clone 56 63 | #define __NR_fork 57 64 | #define __NR_vfork 58 65 | #define __NR_execve 59 66 | #define __NR_exit 60 67 | #define __NR_wait4 61 68 | #define __NR_kill 62 69 | #define __NR_uname 63 70 | #define __NR_semget 64 71 | #define __NR_semop 65 72 | #define __NR_semctl 66 73 | #define __NR_shmdt 67 74 | #define __NR_msgget 68 75 | #define __NR_msgsnd 69 76 | #define __NR_msgrcv 70 77 | #define __NR_msgctl 71 78 | #define __NR_fcntl 72 79 | #define __NR_flock 73 80 | #define __NR_fsync 74 81 | #define __NR_fdatasync 75 82 | #define __NR_truncate 76 83 | #define __NR_ftruncate 77 84 | #define __NR_getdents 78 85 | #define __NR_getcwd 79 86 | #define __NR_chdir 80 87 | #define __NR_fchdir 81 88 | #define __NR_rename 82 89 | #define __NR_mkdir 83 90 | #define __NR_rmdir 84 91 | #define __NR_creat 85 92 | #define __NR_link 86 93 | #define __NR_unlink 87 94 | #define __NR_symlink 88 95 | #define __NR_readlink 89 96 | #define __NR_chmod 90 97 | #define __NR_fchmod 91 98 | #define __NR_chown 92 99 | #define __NR_fchown 93 100 | #define __NR_lchown 94 101 | #define __NR_umask 95 102 | #define __NR_gettimeofday 96 103 | #define __NR_getrlimit 97 104 | #define __NR_getrusage 98 105 | #define __NR_sysinfo 99 106 | #define __NR_times 100 107 | #define __NR_ptrace 101 108 | #define __NR_getuid 102 109 | #define __NR_syslog 103 110 | #define __NR_getgid 104 111 | #define __NR_setuid 105 112 | #define __NR_setgid 106 113 | #define __NR_geteuid 107 114 | #define __NR_getegid 108 115 | #define __NR_setpgid 109 116 | #define __NR_getppid 110 117 | #define __NR_getpgrp 111 118 | #define __NR_setsid 112 119 | #define __NR_setreuid 113 120 | #define __NR_setregid 114 121 | #define __NR_getgroups 115 122 | #define __NR_setgroups 116 123 | #define __NR_setresuid 117 124 | #define __NR_getresuid 118 125 | #define __NR_setresgid 119 126 | #define __NR_getresgid 120 127 | #define __NR_getpgid 121 128 | #define __NR_setfsuid 122 129 | #define __NR_setfsgid 123 130 | #define __NR_getsid 124 131 | #define __NR_capget 125 132 | #define __NR_capset 126 133 | #define __NR_rt_sigpending 127 134 | #define __NR_rt_sigtimedwait 128 135 | #define __NR_rt_sigqueueinfo 129 136 | #define __NR_rt_sigsuspend 130 137 | #define __NR_sigaltstack 131 138 | #define __NR_utime 132 139 | #define __NR_mknod 133 140 | #define __NR_uselib 134 141 | #define __NR_personality 135 142 | #define __NR_ustat 136 143 | #define __NR_statfs 137 144 | #define __NR_fstatfs 138 145 | #define __NR_sysfs 139 146 | #define __NR_getpriority 140 147 | #define __NR_setpriority 141 148 | #define __NR_sched_setparam 142 149 | #define __NR_sched_getparam 143 150 | #define __NR_sched_setscheduler 144 151 | #define __NR_sched_getscheduler 145 152 | #define __NR_sched_get_priority_max 146 153 | #define __NR_sched_get_priority_min 147 154 | #define __NR_sched_rr_get_interval 148 155 | #define __NR_mlock 149 156 | #define __NR_munlock 150 157 | #define __NR_mlockall 151 158 | #define __NR_munlockall 152 159 | #define __NR_vhangup 153 160 | #define __NR_modify_ldt 154 161 | #define __NR_pivot_root 155 162 | #define __NR__sysctl 156 163 | #define __NR_prctl 157 164 | #define __NR_arch_prctl 158 165 | #define __NR_adjtimex 159 166 | #define __NR_setrlimit 160 167 | #define __NR_chroot 161 168 | #define __NR_sync 162 169 | #define __NR_acct 163 170 | #define __NR_settimeofday 164 171 | #define __NR_mount 165 172 | #define __NR_umount2 166 173 | #define __NR_swapon 167 174 | #define __NR_swapoff 168 175 | #define __NR_reboot 169 176 | #define __NR_sethostname 170 177 | #define __NR_setdomainname 171 178 | #define __NR_iopl 172 179 | #define __NR_ioperm 173 180 | #define __NR_create_module 174 181 | #define __NR_init_module 175 182 | #define __NR_delete_module 176 183 | #define __NR_get_kernel_syms 177 184 | #define __NR_query_module 178 185 | #define __NR_quotactl 179 186 | #define __NR_nfsservctl 180 187 | #define __NR_getpmsg 181 188 | #define __NR_putpmsg 182 189 | #define __NR_afs_syscall 183 190 | #define __NR_tuxcall 184 191 | #define __NR_security 185 192 | #define __NR_gettid 186 193 | #define __NR_readahead 187 194 | #define __NR_setxattr 188 195 | #define __NR_lsetxattr 189 196 | #define __NR_fsetxattr 190 197 | #define __NR_getxattr 191 198 | #define __NR_lgetxattr 192 199 | #define __NR_fgetxattr 193 200 | #define __NR_listxattr 194 201 | #define __NR_llistxattr 195 202 | #define __NR_flistxattr 196 203 | #define __NR_removexattr 197 204 | #define __NR_lremovexattr 198 205 | #define __NR_fremovexattr 199 206 | #define __NR_tkill 200 207 | #define __NR_time 201 208 | #define __NR_futex 202 209 | #define __NR_sched_setaffinity 203 210 | #define __NR_sched_getaffinity 204 211 | #define __NR_set_thread_area 205 212 | #define __NR_io_setup 206 213 | #define __NR_io_destroy 207 214 | #define __NR_io_getevents 208 215 | #define __NR_io_submit 209 216 | #define __NR_io_cancel 210 217 | #define __NR_get_thread_area 211 218 | #define __NR_lookup_dcookie 212 219 | #define __NR_epoll_create 213 220 | #define __NR_epoll_ctl_old 214 221 | #define __NR_epoll_wait_old 215 222 | #define __NR_remap_file_pages 216 223 | #define __NR_getdents64 217 224 | #define __NR_set_tid_address 218 225 | #define __NR_restart_syscall 219 226 | #define __NR_semtimedop 220 227 | #define __NR_fadvise64 221 228 | #define __NR_timer_create 222 229 | #define __NR_timer_settime 223 230 | #define __NR_timer_gettime 224 231 | #define __NR_timer_getoverrun 225 232 | #define __NR_timer_delete 226 233 | #define __NR_clock_settime 227 234 | #define __NR_clock_gettime 228 235 | #define __NR_clock_getres 229 236 | #define __NR_clock_nanosleep 230 237 | #define __NR_exit_group 231 238 | #define __NR_epoll_wait 232 239 | #define __NR_epoll_ctl 233 240 | #define __NR_tgkill 234 241 | #define __NR_utimes 235 242 | #define __NR_vserver 236 243 | #define __NR_mbind 237 244 | #define __NR_set_mempolicy 238 245 | #define __NR_get_mempolicy 239 246 | #define __NR_mq_open 240 247 | #define __NR_mq_unlink 241 248 | #define __NR_mq_timedsend 242 249 | #define __NR_mq_timedreceive 243 250 | #define __NR_mq_notify 244 251 | #define __NR_mq_getsetattr 245 252 | #define __NR_kexec_load 246 253 | #define __NR_waitid 247 254 | #define __NR_add_key 248 255 | #define __NR_request_key 249 256 | #define __NR_keyctl 250 257 | #define __NR_ioprio_set 251 258 | #define __NR_ioprio_get 252 259 | #define __NR_inotify_init 253 260 | #define __NR_inotify_add_watch 254 261 | #define __NR_inotify_rm_watch 255 262 | #define __NR_migrate_pages 256 263 | #define __NR_openat 257 264 | #define __NR_mkdirat 258 265 | #define __NR_mknodat 259 266 | #define __NR_fchownat 260 267 | #define __NR_futimesat 261 268 | #define __NR_newfstatat 262 269 | #define __NR_unlinkat 263 270 | #define __NR_renameat 264 271 | #define __NR_linkat 265 272 | #define __NR_symlinkat 266 273 | #define __NR_readlinkat 267 274 | #define __NR_fchmodat 268 275 | #define __NR_faccessat 269 276 | #define __NR_pselect6 270 277 | #define __NR_ppoll 271 278 | #define __NR_unshare 272 279 | #define __NR_set_robust_list 273 280 | #define __NR_get_robust_list 274 281 | #define __NR_splice 275 282 | #define __NR_tee 276 283 | #define __NR_sync_file_range 277 284 | #define __NR_vmsplice 278 285 | #define __NR_move_pages 279 286 | #define __NR_utimensat 280 287 | #define __NR_epoll_pwait 281 288 | #define __NR_signalfd 282 289 | #define __NR_timerfd_create 283 290 | #define __NR_eventfd 284 291 | #define __NR_fallocate 285 292 | #define __NR_timerfd_settime 286 293 | #define __NR_timerfd_gettime 287 294 | #define __NR_accept4 288 295 | #define __NR_signalfd4 289 296 | #define __NR_eventfd2 290 297 | #define __NR_epoll_create1 291 298 | #define __NR_dup3 292 299 | #define __NR_pipe2 293 300 | #define __NR_inotify_init1 294 301 | #define __NR_preadv 295 302 | #define __NR_pwritev 296 303 | #define __NR_rt_tgsigqueueinfo 297 304 | #define __NR_perf_event_open 298 305 | #define __NR_recvmmsg 299 306 | #define __NR_fanotify_init 300 307 | #define __NR_fanotify_mark 301 308 | #define __NR_prlimit64 302 309 | #define __NR_name_to_handle_at 303 310 | #define __NR_open_by_handle_at 304 311 | #define __NR_clock_adjtime 305 312 | #define __NR_syncfs 306 313 | #define __NR_sendmmsg 307 314 | #define __NR_setns 308 315 | #define __NR_getcpu 309 316 | #define __NR_process_vm_readv 310 317 | #define __NR_process_vm_writev 311 318 | #define __NR_kcmp 312 319 | #define __NR_finit_module 313 320 | #define __NR_sched_setattr 314 321 | #define __NR_sched_getattr 315 322 | #define __NR_renameat2 316 323 | #define __NR_seccomp 317 324 | #define __NR_getrandom 318 325 | #define __NR_memfd_create 319 326 | #define __NR_kexec_file_load 320 327 | #define __NR_bpf 321 328 | #define __NR_execveat 322 329 | #define __NR_userfaultfd 323 330 | #define __NR_membarrier 324 331 | #define __NR_mlock2 325 332 | #define __NR_copy_file_range 326 333 | #define __NR_preadv2 327 334 | #define __NR_pwritev2 328 335 | #define __NR_pkey_mprotect 329 336 | #define __NR_pkey_alloc 330 337 | #define __NR_pkey_free 331 338 | #define __NR_statx 332 339 | 340 | #endif /* __SYSCALL_LIST_X86_64__ */ 341 | -------------------------------------------------------------------------------- /src/include/internal/essentials.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: BSD-3-Clause */ 2 | 3 | #ifndef __ESSENTIALS_H__ 4 | #define __ESSENTIALS_H__ 1 5 | 6 | #define MIN(a, b) ((a) > (b) ? (b) : (a)) 7 | #define MAX(a, b) ((a) > (b) ? (a) : (b)) 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /src/include/internal/io.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: BSD-3-Clause */ 2 | 3 | #ifndef __IO_H__ 4 | #define __IO_H__ 1 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #include 11 | 12 | ssize_t write(int fd, const void *buf, size_t len); 13 | ssize_t read(int fd, void *buf, size_t len); 14 | 15 | #ifdef __cplusplus 16 | } 17 | #endif 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/include/internal/mm/mem_list.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: BSD-3-Clause */ 2 | 3 | #ifndef __MEM_LIST_H__ 4 | #define __MEM_LIST_H__ 1 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #include 11 | 12 | struct mem_list { 13 | void *start; 14 | size_t len; 15 | struct mem_list *prev; 16 | struct mem_list *next; 17 | }; 18 | 19 | extern struct mem_list mem_list_head; 20 | 21 | void mem_list_init(void); 22 | int mem_list_add(void *start, size_t len); 23 | struct mem_list *mem_list_find(void *start); 24 | int mem_list_del(void *start); 25 | void mem_list_cleanup(void); 26 | size_t mem_list_num_items(void); 27 | 28 | #ifdef __cplusplus 29 | } 30 | #endif 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /src/include/internal/syscall.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: BSD-3-Clause */ 2 | 3 | #ifndef __SYSCALL_H__ 4 | #define __SYSCALL_H__ 1 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #include 11 | 12 | long syscall(long n, ...); 13 | 14 | #ifdef __cplusplus 15 | } 16 | #endif 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/include/internal/types.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: BSD-3-Clause */ 2 | 3 | #ifndef __TYPES_H__ 4 | #define __TYPES_H__ 1 5 | 6 | typedef unsigned long size_t; 7 | typedef long ssize_t; 8 | typedef long off_t; 9 | typedef long long quad_t; 10 | 11 | typedef unsigned int mode_t; /* Type of file attribute bitmasks. */ 12 | typedef unsigned int ino_t; /* Type of file serial numbers. */ 13 | typedef quad_t ino64_t; /* Type of file serial numbers (LFS). */ 14 | typedef int dev_t; /* Type of device numbers. */ 15 | typedef unsigned short int nlink_t; /* Type of file link counts. */ 16 | typedef unsigned int uid_t; /* Type of user identifications. */ 17 | typedef unsigned int gid_t; /* Type of group identifications. */ 18 | 19 | typedef unsigned char uint8_t; 20 | typedef unsigned short uint16_t; 21 | typedef unsigned int uint32_t; 22 | typedef unsigned long uint64_t; 23 | typedef int int32_t; 24 | typedef long int64_t; 25 | 26 | #define NULL ((void *) 0) 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/include/stdarg.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: BSD-3-Clause */ 2 | 3 | #ifndef __STDARG_H__ 4 | #define __STDARG_H__ 1 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #include 11 | 12 | #define va_start(v, l) __builtin_va_start(v, l) 13 | #define va_end(v) __builtin_va_end(v) 14 | #define va_arg(v, l) __builtin_va_arg(v, l) 15 | #define va_copy(d, s) __builtin_va_copy(d, s) 16 | 17 | typedef __builtin_va_list va_list; 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/include/stddef.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: BSD-3-Clause */ 2 | 3 | #ifndef __STDDEF_H__ 4 | #define __STDDEF_H__ 1 5 | 6 | #include 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /src/include/stdio.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: BSD-3-Clause */ 2 | 3 | #ifndef __STDIO_H__ 4 | #define __STDIO_H__ 1 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | /* TODO: Add puts() declaration. */ 11 | 12 | int puts(const char *str); 13 | 14 | #ifdef __cplusplus 15 | } 16 | #endif 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/include/stdlib.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: BSD-3-Clause */ 2 | 3 | #ifndef __STDLIB_H__ 4 | #define __STDLIB_H__ 1 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #include 11 | #include 12 | 13 | #define EXIT_SUCCESS 0 14 | #define EXIT_FAILURE 1 15 | 16 | void *malloc(size_t size); 17 | void free(void *ptr); 18 | void *calloc(size_t nmemb, size_t size); 19 | void *realloc(void *ptr, size_t size); 20 | void *reallocarray(void *ptr, size_t nmemb, size_t size); 21 | long exit(long exit_code); 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /src/include/string.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: BSD-3-Clause */ 2 | 3 | #ifndef __STRING_H__ 4 | #define __STRING_H__ 1 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #include 11 | 12 | char *strcpy(char *destination, const char *source); 13 | char *strncpy(char *destination, const char *source, size_t len); 14 | 15 | char *strcat(char *destination, const char *source); 16 | char *strncat(char *destination, const char *source, size_t len); 17 | 18 | size_t strlen(const char *str); 19 | 20 | int strcmp(const char *str1, const char *str2); 21 | int strncmp(const char *str1, const char *str2, size_t len); 22 | 23 | char *strchr(const char *str, int c); 24 | char *strrchr(const char *str, int c); 25 | 26 | char *strstr(const char *str1, const char *str2); 27 | char *strrstr(const char *str1, const char *str2); 28 | 29 | void *memcpy(void *destination, const void *source, size_t num); 30 | void *memset(void *source, int value, size_t num); 31 | void *memmove(void *destination, const void *source, size_t num); 32 | int memcmp(const void *ptr1, const void *ptr2, size_t num); 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /src/include/sys/mman.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: BSD-3-Clause */ 2 | 3 | #ifndef __SYS_MMAN_H__ 4 | #define __SYS_MMAN_H__ 1 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #include 11 | 12 | #define PROT_READ 0x1 /* Page can be read. */ 13 | #define PROT_WRITE 0x2 /* Page can be written. */ 14 | #define PROT_EXEC 0x4 /* Page can be executed. */ 15 | #define PROT_NONE 0x0 /* Page can not be accessed. */ 16 | 17 | /* Sharing types (must choose one and only one of these). */ 18 | #define MAP_SHARED 0x01 /* Share changes. */ 19 | #define MAP_PRIVATE 0x02 /* Changes are private. */ 20 | #define MAP_ANONYMOUS 0x20 /* Don't use a file. */ 21 | #define MAP_ANON MAP_ANONYMOUS 22 | 23 | #define MREMAP_MAYMOVE 1 24 | 25 | #define MAP_FAILED ((void *) -1) 26 | 27 | void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); 28 | void *mremap(void *old_address, size_t old_size, size_t new_size, int flags); 29 | int munmap(void *addr, size_t length); 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/include/sys/stat.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: BSD-3-Clause */ 2 | 3 | #ifndef __SYS_STAT_H__ 4 | #define __SYS_STAT_H__ 1 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #include 11 | 12 | /* 13 | * These bits should be set in the mask argument of statx() to request 14 | * particular items when calling statx(). 15 | */ 16 | #define STATX_TYPE 0x00000001U /* Want/got stx_mode & S_IFMT */ 17 | #define STATX_MODE 0x00000002U /* Want/got stx_mode & ~S_IFMT */ 18 | #define STATX_NLINK 0x00000004U /* Want/got stx_nlink */ 19 | #define STATX_UID 0x00000008U /* Want/got stx_uid */ 20 | #define STATX_GID 0x00000010U /* Want/got stx_gid */ 21 | #define STATX_ATIME 0x00000020U /* Want/got stx_atime */ 22 | #define STATX_MTIME 0x00000040U /* Want/got stx_mtime */ 23 | #define STATX_CTIME 0x00000080U /* Want/got stx_ctime */ 24 | #define STATX_INO 0x00000100U /* Want/got stx_ino */ 25 | #define STATX_SIZE 0x00000200U /* Want/got stx_size */ 26 | #define STATX_BLOCKS 0x00000400U /* Want/got stx_blocks */ 27 | #define STATX_BASIC_STATS 0x000007ffU /* The stuff in the normal stat struct */ 28 | #define STATX_BTIME 0x00000800U /* Want/got stx_btime */ 29 | #define STATX_MNT_ID 0x00001000U /* Got stx_mnt_id */ 30 | 31 | #define __S_IFMT 0170000 /* These bits determine file type. */ 32 | 33 | /* File types. */ 34 | #define __S_IFDIR 0040000 /* Directory. */ 35 | #define __S_IFCHR 0020000 /* Character device. */ 36 | #define __S_IFBLK 0060000 /* Block device. */ 37 | #define __S_IFREG 0100000 /* Regular file. */ 38 | #define __S_IFIFO 0010000 /* FIFO. */ 39 | #define __S_IFLNK 0120000 /* Symbolic link. */ 40 | #define __S_IFSOCK 0140000 /* Socket. */ 41 | 42 | #define AT_EMPTY_PATH 0x1000 43 | 44 | /* Structure describing file characteristics. */ 45 | struct stat { 46 | uint64_t st_dev; 47 | uint64_t st_ino; 48 | uint64_t st_nlink; 49 | 50 | unsigned int st_mode; 51 | unsigned int st_uid; 52 | unsigned int st_gid; 53 | unsigned int __pad0; 54 | uint64_t st_rdev; 55 | int64_t st_size; 56 | int64_t st_blksize; 57 | int64_t st_blocks; /* Number 512-byte blocks allocated. */ 58 | 59 | uint64_t st_atime; 60 | uint64_t st_atime_nsec; 61 | uint64_t st_mtime; 62 | uint64_t st_mtime_nsec; 63 | uint64_t st_ctime; 64 | uint64_t st_ctime_nsec; 65 | int64_t __unused[3]; 66 | }; 67 | 68 | int stat(const char *__restrict, struct stat *__restrict); 69 | int fstat(int fd, struct stat *st); 70 | int fstatat(int fd, const char *restrict path, struct stat *restrict st, int flag); 71 | 72 | #ifdef __cplusplus 73 | } 74 | #endif 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /src/include/sys/types.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: BSD-3-Clause */ 2 | 3 | #ifndef __TYPES_H__ 4 | #define __TYPES_H__ 1 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #include 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/include/time.h: -------------------------------------------------------------------------------- 1 | #ifndef _TIME_H 2 | #define _TIME_H 3 | 4 | typedef long time_t; 5 | 6 | struct timespec { 7 | time_t tv_sec; 8 | long tv_nsec; 9 | }; 10 | 11 | int nanosleep(const struct timespec *req, struct timespec *rem); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /src/include/unistd.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: BSD-3-Clause */ 2 | 3 | #ifndef __UNISTD_H__ 4 | #define __UNISTD_H__ 1 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #include 11 | #include 12 | 13 | #define SEEK_SET 0 14 | #define SEEK_CUR 1 15 | #define SEEK_END 2 16 | #define SEEK_DATA 3 17 | #define SEEK_HOLE 4 18 | 19 | int close(int fd); 20 | off_t lseek(int fd, off_t offset, int whence); 21 | int truncate(const char *path, off_t length); 22 | int ftruncate(int fd, off_t length); 23 | unsigned int sleep(unsigned int seconds); 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/io/close.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int close(int fd) { 9 | if (syscall(__NR_close, fd) == 0) { 10 | return 0; 11 | } 12 | 13 | errno = -syscall(__NR_close, fd); 14 | 15 | return -1; 16 | } 17 | -------------------------------------------------------------------------------- /src/io/ftruncate.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | int ftruncate(int fd, off_t length) { 8 | if (length < 0) { 9 | errno = EINVAL; 10 | return -1; 11 | } 12 | 13 | if (fd < 0) { 14 | errno = EBADF; 15 | return -1; 16 | } 17 | 18 | long ret = syscall(__NR_ftruncate, fd, length); 19 | 20 | if (ret < 0) { 21 | errno = -ret; 22 | return -1; 23 | } 24 | 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /src/io/lseek.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | off_t lseek(int fd, off_t offset, int whence) { 8 | if (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END) { 9 | errno = EINVAL; 10 | return -1; 11 | } 12 | 13 | if (fd < 0) { 14 | errno = EBADF; 15 | return -1; 16 | } 17 | 18 | long ret = syscall(__NR_lseek, fd, offset, whence); 19 | 20 | if (ret >= 0) { 21 | return ret; 22 | } 23 | 24 | errno = -ret; 25 | 26 | return -1; 27 | } 28 | -------------------------------------------------------------------------------- /src/io/open.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int open(const char *filename, int flags, ...) { 9 | int mode = 0; 10 | 11 | if (flags & O_CREAT) { 12 | va_list args; 13 | va_start(args, flags); 14 | mode = va_arg(args, int); 15 | va_end(args); 16 | } 17 | 18 | int ret = syscall(__NR_open, filename, flags, mode); 19 | 20 | if (ret < 0) { 21 | errno = -ret; 22 | return -1; 23 | } 24 | 25 | return ret; 26 | } 27 | -------------------------------------------------------------------------------- /src/io/read_write.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | ssize_t write(int fd, const void *buf, size_t len) { 9 | int ret = syscall(__NR_write, fd, buf, len); 10 | 11 | if (ret < 0) { 12 | errno = -ret; 13 | return -1; 14 | } 15 | 16 | return ret; 17 | } 18 | 19 | ssize_t read(int fd, void *buf, size_t len) { 20 | int ret = syscall(__NR_read, fd, buf, len); 21 | 22 | if (ret < 0) { 23 | errno = -ret; 24 | return -1; 25 | } 26 | 27 | return ret; 28 | } 29 | -------------------------------------------------------------------------------- /src/io/truncate.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | int truncate(const char *path, off_t length) { 8 | if (syscall(__NR_truncate, path, length) == 0) { 9 | return 0; 10 | } 11 | 12 | errno = -syscall(__NR_truncate, path, length); 13 | 14 | return -1; 15 | } 16 | -------------------------------------------------------------------------------- /src/mm/malloc.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | void *malloc(size_t size) { 11 | if (size == 0) { 12 | return NULL; 13 | } 14 | 15 | void *ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 16 | 17 | if (ptr == MAP_FAILED) { 18 | return NULL; 19 | } 20 | 21 | mem_list_add(ptr, size); 22 | 23 | return ptr; 24 | } 25 | 26 | void *calloc(size_t nmemb, size_t size) { 27 | void *ptr = malloc(nmemb * size); 28 | mem_list_add(ptr, nmemb * size); 29 | 30 | if (ptr == NULL) { 31 | return NULL; 32 | } 33 | 34 | memset(ptr, 0, nmemb * size); 35 | return ptr; 36 | } 37 | 38 | void free(void *ptr) { 39 | struct mem_list* item = mem_list_find(ptr); 40 | 41 | if (item == NULL) { 42 | return; 43 | } 44 | 45 | size_t length = item->len; 46 | 47 | mem_list_del(ptr); 48 | munmap(ptr, length); 49 | } 50 | 51 | void *realloc(void *ptr, size_t size) { 52 | mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 53 | mem_list_add(ptr, size); 54 | 55 | if (ptr == MAP_FAILED) { 56 | return NULL; 57 | } 58 | 59 | return ptr; 60 | } 61 | 62 | void *reallocarray(void *ptr, size_t nmemb, size_t size) { 63 | mmap(NULL, nmemb * size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 64 | mem_list_add(ptr, nmemb * size); 65 | 66 | if (ptr == MAP_FAILED) { 67 | return NULL; 68 | } 69 | 70 | return ptr; 71 | } 72 | -------------------------------------------------------------------------------- /src/mm/mem_list.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | struct mem_list mem_list_head; 8 | 9 | void mem_list_init(void) { 10 | mem_list_head.start = NULL; 11 | mem_list_head.len = 0; 12 | mem_list_head.prev = &mem_list_head; 13 | mem_list_head.next = &mem_list_head; 14 | } 15 | 16 | static struct mem_list *mem_list_alloc(void) { 17 | return mmap(NULL, sizeof(struct mem_list), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 18 | } 19 | 20 | static int mem_list_free(struct mem_list *item) { 21 | return munmap(item, sizeof(struct mem_list)); 22 | } 23 | 24 | int mem_list_add(void *start, size_t len) { 25 | struct mem_list *item; 26 | 27 | item = mem_list_alloc(); 28 | if (item == NULL) 29 | return -1; 30 | 31 | item->start = start; 32 | item->len = len; 33 | 34 | /* Add item in list. */ 35 | item->next = &mem_list_head; 36 | item->prev = mem_list_head.prev; 37 | mem_list_head.prev->next = item; 38 | mem_list_head.prev = item; 39 | 40 | return 0; 41 | } 42 | 43 | struct mem_list *mem_list_find(void *start) { 44 | struct mem_list *iter; 45 | 46 | for (iter = mem_list_head.next; iter != &mem_list_head; iter = iter->next) 47 | if (iter->start == start) 48 | return iter; 49 | 50 | return NULL; 51 | } 52 | 53 | static struct mem_list *mem_list_extract(void *start) { 54 | struct mem_list *item; 55 | 56 | item = mem_list_find(start); 57 | if (item == NULL) 58 | return NULL; 59 | 60 | /* Extract item from doubly-linked list. */ 61 | item->next->prev = item->prev; 62 | item->prev->next = item->next; 63 | item->next = item; 64 | item->prev = item; 65 | 66 | return item; 67 | } 68 | 69 | int mem_list_del(void *start) { 70 | struct mem_list *item; 71 | 72 | item = mem_list_extract(start); 73 | if (item == NULL) 74 | return -1; 75 | 76 | mem_list_free(item); 77 | 78 | return 0; 79 | } 80 | 81 | void mem_list_cleanup(void) { 82 | struct mem_list *iter, *tmp; 83 | 84 | for (iter = mem_list_head.next, tmp = iter->next; 85 | iter != &mem_list_head; 86 | iter = tmp, tmp = iter->next) { 87 | /* Extract item from doubly-linked list. */ 88 | iter->next->prev = iter->prev; 89 | iter->prev->next = iter->next; 90 | iter->next = iter; 91 | iter->prev = iter; 92 | 93 | /* Free item. */ 94 | mem_list_free(iter); 95 | } 96 | } 97 | 98 | size_t mem_list_num_items(void) { 99 | struct mem_list *iter; 100 | size_t count = 0; 101 | 102 | for (iter = mem_list_head.next; iter != &mem_list_head; iter = iter->next) 103 | count++; 104 | 105 | return count; 106 | } 107 | -------------------------------------------------------------------------------- /src/mm/mmap.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) { 8 | if (length == 0) { 9 | errno = EINVAL; 10 | return MAP_FAILED; 11 | } 12 | 13 | long ret = syscall(__NR_mmap, addr, length, prot, flags, fd, offset); 14 | 15 | if (ret < 0) { 16 | errno = -ret; 17 | return MAP_FAILED; 18 | } 19 | 20 | return (void *)ret; 21 | } 22 | 23 | void *mremap(void *old_address, size_t old_size, size_t new_size, int flags) { 24 | if (new_size == 0) { 25 | errno = EINVAL; 26 | return MAP_FAILED; 27 | } 28 | 29 | long ret = syscall(__NR_mremap, old_address, old_size, new_size, flags); 30 | 31 | if (ret < 0) { 32 | errno = -ret; 33 | return MAP_FAILED; 34 | } 35 | 36 | return (void *)ret; 37 | } 38 | 39 | int munmap(void *addr, size_t length) { 40 | long ret = syscall(__NR_munmap, addr, length); 41 | 42 | if (ret < 0) { 43 | errno = -ret; 44 | return -1; 45 | } 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /src/process/exit.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | 3 | #include 4 | #include 5 | 6 | long exit(long exit_code) { 7 | return syscall(__NR_exit, exit_code); 8 | } 9 | -------------------------------------------------------------------------------- /src/process/nanosleep.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "time.h" 5 | 6 | int nanosleep(const struct timespec *req, struct timespec *rem) { 7 | if (req == NULL) { 8 | errno = EFAULT; 9 | return -1; 10 | } 11 | 12 | if (req->tv_nsec < 0 || req->tv_nsec >= 1000000000) { 13 | errno = EINVAL; 14 | return -1; 15 | } 16 | 17 | if (rem != NULL) { 18 | rem->tv_sec = 0; 19 | rem->tv_nsec = 0; 20 | } 21 | 22 | long ret = syscall(__NR_nanosleep, req, rem); 23 | 24 | if (ret < 0) { 25 | errno = -ret; 26 | return -1; 27 | } 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /src/process/sleep.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "time.h" 5 | 6 | unsigned int sleep(unsigned int seconds) { 7 | struct timespec req = { 8 | .tv_sec = seconds, 9 | .tv_nsec = 0 10 | }; 11 | 12 | struct timespec rem = { 13 | .tv_sec = 0, 14 | .tv_nsec = 0 15 | }; 16 | 17 | int ret = nanosleep(&req, &rem); 18 | 19 | if (ret < 0) { 20 | errno = -ret; 21 | return seconds; 22 | } 23 | 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /src/stat/fstat.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | int fstat(int fd, struct stat *st) { 8 | if (st == NULL) { 9 | errno = EINVAL; 10 | return -1; 11 | } 12 | 13 | if (fd < 0) { 14 | errno = EBADF; 15 | return -1; 16 | } 17 | 18 | long ret = syscall(__NR_fstat, fd, st); 19 | 20 | if (ret < 0) { 21 | errno = -ret; 22 | return -1; 23 | } 24 | 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /src/stat/fstatat.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define makedev(x, y) ( \ 11 | (((x)&0xfffff000ULL) << 32) | \ 12 | (((x)&0x00000fffULL) << 8) | \ 13 | (((y)&0xffffff00ULL) << 12) | \ 14 | (((y)&0x000000ffULL)) \ 15 | ) 16 | 17 | /* Structure describing file characteristics as defined in linux/stat.h */ 18 | struct statx { 19 | uint32_t stx_mask; 20 | uint32_t stx_blksize; 21 | uint64_t stx_attributes; 22 | uint32_t stx_nlink; 23 | uint32_t stx_uid; 24 | uint32_t stx_gid; 25 | uint16_t stx_mode; 26 | uint16_t pad1; 27 | uint64_t stx_ino; 28 | uint64_t stx_size; 29 | uint64_t stx_blocks; 30 | uint64_t stx_attributes_mask; 31 | struct { 32 | int64_t tv_sec; 33 | uint32_t tv_nsec; 34 | int32_t pad; 35 | } stx_atime, stx_btime, stx_ctime, stx_mtime; 36 | uint32_t stx_rdev_major; 37 | uint32_t stx_rdev_minor; 38 | uint32_t stx_dev_major; 39 | uint32_t stx_dev_minor; 40 | uint64_t spare[14]; 41 | }; 42 | 43 | int fstatat_statx(int fd, const char *restrict path, struct stat *restrict st, int flag) { 44 | return -1; 45 | } 46 | 47 | int fstatat(int fd, const char *restrict path, struct stat *restrict st, int flag) { 48 | return -1; 49 | } 50 | -------------------------------------------------------------------------------- /src/stat/stat.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int stat(const char *restrict path, struct stat *restrict buf) { 9 | if (buf == NULL) { 10 | errno = EFAULT; 11 | return -1; 12 | } 13 | 14 | if (path == NULL) { 15 | errno = ENOENT; 16 | return -1; 17 | } 18 | 19 | long ret = syscall(__NR_stat, path, buf); 20 | 21 | if (ret < 0) { 22 | errno = -ret; 23 | return -1; 24 | } 25 | 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /src/stdio/puts.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int puts(const char *str) { 8 | if (str == NULL) { 9 | return -1; 10 | } 11 | 12 | long ret = syscall(__NR_write, 1, str, strlen(str)); 13 | if (ret < 0) { 14 | errno = -ret; 15 | return -1; 16 | } 17 | 18 | ret = syscall(__NR_write, 1, "\n", 1); 19 | if (ret < 0) { 20 | errno = -ret; 21 | return -1; 22 | } 23 | 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /src/string/string.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | 3 | #include 4 | 5 | char *strcpy(char *destination, const char *source) { 6 | char *start = destination; 7 | 8 | while (*source != '\0') { 9 | *destination = *source; 10 | destination++; 11 | source++; 12 | } 13 | 14 | *destination = '\0'; 15 | 16 | return start; 17 | } 18 | 19 | char *strncpy(char *destination, const char *source, size_t len) { 20 | char *start = destination; 21 | 22 | while (*source != '\0' && len > 0) { 23 | *destination = *source; 24 | destination++; 25 | source++; 26 | len--; 27 | } 28 | 29 | while (len > 0) { 30 | *destination = '\0'; 31 | destination++; 32 | len--; 33 | } 34 | 35 | return start; 36 | } 37 | 38 | char *strcat(char *destination, const char *source) { 39 | char *start = destination; 40 | 41 | while (*destination != '\0') { 42 | destination++; 43 | } 44 | 45 | while (*source != '\0') { 46 | *destination = *source; 47 | destination++; 48 | source++; 49 | } 50 | 51 | *destination = '\0'; 52 | 53 | return start; 54 | } 55 | 56 | char *strncat(char *destination, const char *source, size_t len) { 57 | char *start = destination; 58 | 59 | while (*destination != '\0') { 60 | destination++; 61 | } 62 | 63 | while (*source != '\0' && len > 0) { 64 | *destination = *source; 65 | destination++; 66 | source++; 67 | len--; 68 | } 69 | 70 | *destination = '\0'; 71 | 72 | return start; 73 | } 74 | 75 | int strcmp(const char *str1, const char *str2) { 76 | while (*str1 != '\0' && *str2 != '\0') { 77 | if (*str1 != *str2) { 78 | return *str1 - *str2; 79 | } 80 | str1++; 81 | str2++; 82 | } 83 | 84 | if (*str1 == '\0' && *str2 == '\0') { 85 | return 0; 86 | } else if (*str1 == '\0') { 87 | return -1; 88 | } else { 89 | return 1; 90 | } 91 | } 92 | 93 | int strncmp(const char *str1, const char *str2, size_t len) { 94 | while (*str1 != '\0' && *str2 != '\0' && len > 0) { 95 | if (*str1 != *str2) { 96 | return *str1 - *str2; 97 | } 98 | 99 | str1++; 100 | str2++; 101 | len--; 102 | } 103 | 104 | if (len == 0) { 105 | return 0; 106 | } else if (*str1 == '\0' && *str2 == '\0') { 107 | return 0; 108 | } else if (*str1 == '\0') { 109 | return -1; 110 | } else { 111 | return 1; 112 | } 113 | 114 | return -1; 115 | } 116 | 117 | size_t strlen(const char *str) { 118 | size_t i = 0; 119 | 120 | for (; *str != '\0'; str++, i++) 121 | ; 122 | 123 | return i; 124 | } 125 | 126 | char *strchr(const char *str, int c) { 127 | while (*str != '\0') { 128 | if (*str == c) { 129 | return (char *)str; 130 | } 131 | str++; 132 | } 133 | 134 | return NULL; 135 | } 136 | 137 | char *strrchr(const char *str, int c) { 138 | const char *start = str; 139 | 140 | while (*str != '\0') { 141 | str++; 142 | } 143 | 144 | while (str >= start) { 145 | if (*str == c) { 146 | return (char *)str; 147 | } 148 | str--; 149 | } 150 | 151 | return NULL; 152 | } 153 | 154 | char *strstr(const char *haystack, const char *needle) { 155 | while (*haystack != '\0') { 156 | const char *start = haystack; 157 | const char *sub = needle; 158 | 159 | while (*haystack != '\0' && *sub != '\0' && *haystack == *sub) { 160 | haystack++; 161 | sub++; 162 | } 163 | 164 | if (*sub == '\0') { 165 | return (char *)start; 166 | } 167 | 168 | haystack = start + 1; 169 | } 170 | 171 | return NULL; 172 | } 173 | 174 | char *strrstr(const char *haystack, const char *needle) { 175 | if (haystack == NULL || needle == NULL) { 176 | return NULL; 177 | } 178 | 179 | int len_haystack = strlen(haystack); 180 | int len_needle = strlen(needle); 181 | 182 | if (len_needle == 0) { 183 | return (char *)haystack + len_haystack; 184 | } 185 | 186 | for (int i = len_haystack - len_needle; i >= 0; i--) { 187 | if (strncmp(haystack + i, needle, len_needle) == 0) { 188 | return (char *)haystack + i; 189 | } 190 | } 191 | 192 | return NULL; 193 | } 194 | 195 | void *memcpy(void *destination, const void *source, size_t num) { 196 | char *dest = (char *)destination; 197 | const char *src = (const char *)source; 198 | char *start = dest; 199 | 200 | while (num > 0) { 201 | *dest = *src; 202 | dest++; 203 | src++; 204 | num--; 205 | } 206 | 207 | return start; 208 | } 209 | 210 | void *memmove(void *destination, const void *source, size_t num) { 211 | char *dest = (char *)destination; 212 | const char *src = (const char *)source; 213 | 214 | if (dest < src) { 215 | while (num > 0) { 216 | *dest = *src; 217 | dest++; 218 | src++; 219 | num--; 220 | } 221 | } else { 222 | dest += num; 223 | src += num; 224 | 225 | while (num > 0) { 226 | dest--; 227 | src--; 228 | *dest = *src; 229 | num--; 230 | } 231 | } 232 | 233 | return destination; 234 | } 235 | 236 | int memcmp(const void *ptr1, const void *ptr2, size_t num) { 237 | const unsigned char *p1 = (const unsigned char *)ptr1; 238 | const unsigned char *p2 = (const unsigned char *)ptr2; 239 | 240 | while (num > 0) { 241 | if (*p1 != *p2) { 242 | return *p1 - *p2; 243 | } 244 | 245 | p1++; 246 | p2++; 247 | num--; 248 | } 249 | 250 | return 0; 251 | } 252 | 253 | void *memset(void *source, int value, size_t num) { 254 | unsigned char *src = (unsigned char *)source; 255 | unsigned char val = (unsigned char)value; 256 | unsigned char *start = src; 257 | 258 | while (num > 0) { 259 | *src = val; 260 | src++; 261 | num--; 262 | } 263 | 264 | return start; 265 | } 266 | -------------------------------------------------------------------------------- /src/syscall.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | 3 | #include 4 | #include 5 | 6 | long syscall(long num, ...) 7 | { 8 | va_list valist; 9 | long a, b, c, d, e, f; 10 | 11 | va_start(valist, num); 12 | a = va_arg(valist, long); 13 | b = va_arg(valist, long); 14 | c = va_arg(valist, long); 15 | d = va_arg(valist, long); 16 | e = va_arg(valist, long); 17 | f = va_arg(valist, long); 18 | va_end(valist); 19 | 20 | return __syscall(num, a, b, c, d, e, f); 21 | } 22 | --------------------------------------------------------------------------------