diff --git a/userspace/CMakeLists.txt b/userspace/CMakeLists.txt index 28f7f5740b..cb9bf28c8a 100644 --- a/userspace/CMakeLists.txt +++ b/userspace/CMakeLists.txt @@ -5,6 +5,7 @@ project(userspace CXX) set(USERSPACE_PROJECTS cat cat-mmap + chmod cp dd echo diff --git a/userspace/chmod/CMakeLists.txt b/userspace/chmod/CMakeLists.txt new file mode 100644 index 0000000000..29b3c28dd2 --- /dev/null +++ b/userspace/chmod/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.26) + +project(chmod CXX) + +set(SOURCES + main.cpp +) + +add_executable(chmod ${SOURCES}) +target_compile_options(chmod PUBLIC -O2 -g) +target_link_libraries(chmod PUBLIC libc) + +add_custom_target(chmod-install + COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/chmod ${BANAN_BIN}/ + DEPENDS chmod + USES_TERMINAL +) diff --git a/userspace/chmod/main.cpp b/userspace/chmod/main.cpp new file mode 100644 index 0000000000..522a674e7a --- /dev/null +++ b/userspace/chmod/main.cpp @@ -0,0 +1,43 @@ +#include +#include +#include +#include + +void usage(const char* argv0, int ret) +{ + FILE* out = (ret == 0) ? stdout : stderr; + fprintf(out, "usage: %s MODE FILE...\n", argv0); + fprintf(out, " Change the mode of each FILE to MODE.\n"); + exit(ret); +} + +int main(int argc, char** argv) +{ + if (argc <= 2) + usage(argv[0], 1); + + int base = (argv[1][0] == '0') ? 8 : 10; + + mode_t mode = 0; + for (const char* ptr = argv[1]; *ptr; ptr++) + { + if (!isdigit(*ptr)) + { + fprintf(stderr, "Invalid MODE %s\n", argv[1]); + usage(argv[0], 1); + } + mode = (mode * base) + (*ptr - '0'); + } + + int ret = 0; + for (int i = 2; i < argc; i++) + { + if (chmod(argv[i], mode) == -1) + { + perror("chmod"); + ret = 1; + } + } + + return ret; +}