# Mini-libc
## Objectives
- Learn about the structure and functionalities provided by the standard C library
- Accommodate with the syscall interface in Linux
- Gain a better understanding of strings and memory management functions
- Learn how the standard C library provides support for low-level input/output operations
## Statement
Build a **minimalistic** [**standard C library**](https://en.wikipedia.org/wiki/C_standard_library) implementation for Linux systems (named **mini-libc**), that can be used as a replacement for the **system libc** ([glibc](https://www.gnu.org/software/libc/) in Linux).
The goal is to have a minimally functional libc with features such as string management, basic memory support and POSIX file I/O.
The implementation of mini-libc will be **freestanding**, i.e. it will not use any outside library calls.
It will be implemented on top of the system call interface provided by Linux on an `x86_64` architecture.
Any function you require, that is typically part of libc, you will have to implement.
You can reuse functions that you implement in other parts of the mini-libc.
In case you are using a macOS device with ARM64 / Aarch64, you will have to install an `x86_64` virtual machine.
## Support Code
The support code consists of three directories:
- `libc/` is the skeleton mini-libc implementation.
You will have to implement missing parts marked as `TODO` items.
- `samples/` stores use cases and tests of mini-libc.
- `tests/` are states used to validate (and grade) the assignment.
System call invocation is done via the `syscall()` function defined in `libc/syscall.c`.
That itself makes a call to the architecture-specific call in `libc/internal/arch/x86_64/syscall_arch.h`;
hence the dependency on the `x86_64` architecture.
### API and Implementation Tasks
The application programming interface (API) of the C standard library is declared in a number of header files.
Each header file contains one or more function declarations, data type definitions and macros.
For your minimal implementation, the following header files are of interest:
- `<string.h>`: defines string-handling functions
For this assignment, you will have to implement the following functions: `strcpy()`, `strcat()`, `strlen()`, `strncpy()`, `strncat()`, `strcmp()`, `strncmp()`, `strstr()`, `strrstr()`, `memcpy()`, `memset()`, `memmove()`, `memcmp()`.
- `<stdio.h>`: defines printing and I/O functions
For this assignment, you will have to implement `puts()`.
- `<unistd.h>`, `<sys/fcntl.h>` and `<sys/stat.h>`: define I/O primitives
For this assignment, you will have to implement the following functions: `open()`, `close()`, `lseek()`, `stat()`, `fstat()`, `truncate()`, `ftruncate()`.
You will also have to implement the `nanosleep()` and `sleep()` functions.
- `<stdlib.h`> and `<sys/mman.h>` define memory allocation functions
For this assignment, you will have to implement the following functions: `malloc()`, `free()`, `calloc()`, `realloc()`, `realloc_array()`, `mmap()`, `mremap()`, `munmap()`.
For managing memory areas, a basic list structure is provided in `include/internal/mm/mem_list.h` and `mm/mem_list.c`.
- `<errno.h>` and `errno.c`: declare and define the integer variable `errno`, which is set by system calls and some library functions in the event of an error to indicate what went wrong.
Some tests do not build.
This is intentional.
You will have to add the missing features to make those tests compile, that is
- the `time.h` header
- the declaration and the implementation of `puts()`
- the declaration and the implementation of `nanosleep()` and `sleep()`
- the update of the libc `Makefile` to build the source code files implementing `puts()`, `nanosleep()` and `sleep()`
:exclamation::exclamation: **Pay attention** to which functions have to modify the `errno` variable.
### Building mini-libc
To build mini-libc, run `make` in the `libc/` directory:
```console
student@so:~/.../content/assignments/mini-libc$ cd libc/
student@so:~/.../assignments/mini-libc/libc$ make
```
To build samples, enter the `samples` directory and run `make`:
```console
student@so:~/.../content/assignments/mini-libc$ cd samples/
student@so:~/.../assignments/mini-libc/samples$ make
```
## Testing and Grading
The testing is automated.
Tests are located in the `tests/` directory.
```console
student@so:~/.../assignments/mini-libc/tests$ ls -F
graded_test.c memory/ test_io.c test_malloc_free.sh* test_mmap_munmap.sh* test_multiple_malloc_free.sh* test_sleep.sh*
graded_test.h process/ test_io_file_create.sh* test_malloc_perm_notok.sh* test_mmap_perm_none.sh* test_multiple_malloc.sh* test_stat.sh*
graded_test.inc.sh run_all_tests.sh* test_io_file_delete.sh* test_malloc_perm_ok.sh* test_mmap_perm_notok.sh* test_nanosleep.sh* test_string.c
io/ test_fstat.sh* test_lseek.sh* test_malloc.sh* test_mmap_perm_ok.sh* test_open_close.sh* test_truncate.sh*
Makefile test_ftruncate.sh* test_malloc_free_sequence.sh* test_memory.c test_mmap.sh* test_puts.sh*
```
To run the checker and everything else required, use the `make check` command in the `tests/` directory:
```console
student@so:~/.../assignments/mini-libc/tests$ make check
make[1]: Entering directory '...'
rm -f *~
[...]
test_mmap_perm_ok ........................ failed ... 0
test_mmap_perm_notok ........................ failed ... 0
test_mmap_perm_none ........................ failed ... 0
Grade .................................. 0.06
```
For starters, tests will fail.
Some tests don't fail because the missing implementation equates to the bad behavior being tested not happening.
That's why you get the `0.06` grade.
Each test is worth a number of points.
The total number of points is `900`.
The maximum grade is obtained by dividing the number of points to `100`, for a maximum grade of `9.00`.
A successful run will show the output:
```console
student@so:~/.../assignments/mini-libc/tests$ make check
[...]
test_strcpy ........................ passed ... 9
test_strcpy_append ........................ passed ... 9
test_strncpy ........................ passed ... 9
test_strncpy_cut ........................ passed ... 9
test_strcat ........................ passed ... 9
test_strcat_from_zero ........................ passed ... 9
test_strcat_multiple ........................ passed ... 9
test_strncat ........................ passed ... 9
test_strncat_cut ........................ passed ... 9
test_strcmp_equal ........................ passed ... 9
test_strcmp_same_size_less ........................ passed ... 1
test_strcmp_same_size_greater ........................ passed ... 9
test_strcmp_diff_size_less ........................ passed ... 1
test_strcmp_diff_size_greater ........................ passed ... 9
test_strncmp_equal_size_equal ........................ passed ... 9
test_strncmp_diff_contents_equal ........................ passed ... 9
test_strncmp_diff_size_equal ........................ passed ... 9
test_strchr_exists ........................ passed ... 11
test_strchr_exists_twice ........................ passed ... 9
test_strchr_not_exists ........................ passed ... 1
test_strrchr_exists ........................ passed ... 11
test_strrchr_exists_twice ........................ passed ... 9
test_strrchr_not_exists ........................ passed ... 1
test_strstr_exists ........................ passed ... 1