diff --git a/userspace/CMakeLists.txt b/userspace/CMakeLists.txt index a704ceb1..3b457739 100644 --- a/userspace/CMakeLists.txt +++ b/userspace/CMakeLists.txt @@ -4,6 +4,7 @@ project(userspace CXX) set(USERSPACE_PROJECTS cat + cat-mmap dd echo id diff --git a/userspace/cat-mmap/CMakeLists.txt b/userspace/cat-mmap/CMakeLists.txt new file mode 100644 index 00000000..54562be3 --- /dev/null +++ b/userspace/cat-mmap/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.26) + +project(cat-mmap CXX) + +set(SOURCES + main.cpp +) + +add_executable(cat-mmap ${SOURCES}) +target_compile_options(cat-mmap PUBLIC -O2 -g) +target_link_libraries(cat-mmap PUBLIC libc) + +add_custom_target(cat-mmap-install + COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/cat-mmap ${BANAN_BIN}/ + DEPENDS cat-mmap + USES_TERMINAL +) diff --git a/userspace/cat-mmap/main.cpp b/userspace/cat-mmap/main.cpp new file mode 100644 index 00000000..29f12dd7 --- /dev/null +++ b/userspace/cat-mmap/main.cpp @@ -0,0 +1,62 @@ +#include +#include +#include +#include + +bool cat_file(int fd) +{ + struct stat st; + if (fstat(fd, &st) == -1) + { + perror("stat"); + return false; + } + + void* addr = mmap(nullptr, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (addr == MAP_FAILED) + { + perror("mmap"); + return false; + } + + ssize_t nwrite = write(STDOUT_FILENO, addr, st.st_size); + if (nwrite == -1) + perror("write"); + + if (munmap(addr, st.st_size) == -1) + { + perror("munmap"); + return false; + } + + return true; +} + +int main(int argc, char** argv) +{ + int ret = 0; + + if (argc > 1) + { + for (int i = 1; i < argc; i++) + { + int fd = open(argv[i], O_RDONLY); + if (fd == -1) + { + perror(argv[i]); + ret = 1; + continue; + } + if (!cat_file(fd)) + ret = 1; + close(fd); + } + } + else + { + if (!cat_file(STDIN_FILENO)) + ret = 1; + } + + return ret; +}