From 56cc5da9fb86ff4e610732b62934b131650f86a4 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Thu, 5 Dec 2024 08:14:45 +0200 Subject: [PATCH] userspace: Implement `ln` utility --- userspace/programs/CMakeLists.txt | 1 + userspace/programs/ln/CMakeLists.txt | 8 ++++ userspace/programs/ln/main.cpp | 65 ++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 userspace/programs/ln/CMakeLists.txt create mode 100644 userspace/programs/ln/main.cpp diff --git a/userspace/programs/CMakeLists.txt b/userspace/programs/CMakeLists.txt index 6e49c53f..dabff242 100644 --- a/userspace/programs/CMakeLists.txt +++ b/userspace/programs/CMakeLists.txt @@ -14,6 +14,7 @@ set(USERSPACE_PROGRAMS id image init + ln loadfont loadkeys ls diff --git a/userspace/programs/ln/CMakeLists.txt b/userspace/programs/ln/CMakeLists.txt new file mode 100644 index 00000000..496e74ef --- /dev/null +++ b/userspace/programs/ln/CMakeLists.txt @@ -0,0 +1,8 @@ +set(SOURCES + main.cpp +) + +add_executable(ln ${SOURCES}) +banan_link_library(ln libc) + +install(TARGETS ln OPTIONAL) diff --git a/userspace/programs/ln/main.cpp b/userspace/programs/ln/main.cpp new file mode 100644 index 00000000..11e7647f --- /dev/null +++ b/userspace/programs/ln/main.cpp @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include + +int usage(const char* argv0, int ret) +{ + FILE* fout = ret ? stderr : stdout; + fprintf(fout, "usage: %s [OPTION]... TARGET [LINK_NAME]\n", argv0); + fprintf(fout, " -s, --symbolic create symbolic link instead of hard link\n"); + fprintf(fout, " -h, --help show this message and exit\n"); + return ret; +} + +int main(int argc, const char* argv[]) +{ + bool do_symlink = false; + + int i = 1; + for (; i < argc; i++) + { + if (argv[i][0] != '-') + break; + + if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--symbolic") == 0) + do_symlink = true; + else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) + return usage(argv[0], 0); + else + { + fprintf(stderr, "unrecognized option '%s'\n", argv[i]); + return usage(argv[0], 1); + } + } + + if (i == argc) + { + fprintf(stderr, "missing target\n"); + return usage(argv[0], 1); + } + + const char* target = argv[i++]; + + struct stat st; + if (stat(target, &st) == -1) + { + perror("stat"); + return 1; + } + + const char* link_name = (i == argc) + ? basename(const_cast(target)) + : argv[i]; + + int (*link_func)(const char*, const char*) = do_symlink ? &symlink : &link; + + if (link_func(target, link_name) == -1) + { + perror(do_symlink ? "symlink" : "link"); + return 1; + } + + return 0; +}