From 21c426a133798e7e643678791a02f7bb6f7c1bb4 Mon Sep 17 00:00:00 2001 From: Mark Date: Wed, 15 Jan 2020 15:18:43 +0200 Subject: [PATCH] Add cp and more tests --- Makefile | 4 +- core/bin/ls.c | 1 - init.c | 240 ++++++++++++++++++++++++++++++++++---------------- 3 files changed, 164 insertions(+), 81 deletions(-) diff --git a/Makefile b/Makefile index e8b772f..8ed30cc 100644 --- a/Makefile +++ b/Makefile @@ -5,8 +5,6 @@ KERNEL_HDRS?=kernel-hdr CC=x86_64-elf-yggdrasil-gcc DIRS=$(O) \ - $(O)/libc \ - $(O)/lib \ $(STAGE) HDRS=$(shell find $(S) -type f -name "*.h") STAGE_BIN=$(STAGE)/init \ @@ -18,6 +16,8 @@ usr_CFLAGS=-msse \ -msse2 \ -ggdb \ -O0 \ + -Wall \ + -Werror \ -ffreestanding usr_LDFLAGS=-lgcc \ diff --git a/core/bin/ls.c b/core/bin/ls.c index 87175fb..f0989d4 100644 --- a/core/bin/ls.c +++ b/core/bin/ls.c @@ -15,7 +15,6 @@ #define COLOR_RESET "\033[0m" static int ls_dir(const char *path, int flags) { - int res; DIR *dir; struct dirent *ent; struct stat ent_stat; diff --git a/init.c b/init.c index 78168bb..0caf3ff 100644 --- a/init.c +++ b/init.c @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include #include @@ -28,8 +30,6 @@ // -extern __attribute__((noreturn)) void abort(void); - struct builtin { const char *name; const char *desc; @@ -102,7 +102,6 @@ static int readline(char *buf, size_t lim) { static int b_cd(const char *path); static int b_pwd(const char *_); static int b_cat(const char *path); -static int b_curs(const char *arg); static int b_sleep(const char *arg); static int b_help(const char *arg); static int b_clear(const char *arg); @@ -116,6 +115,8 @@ static int b_abort(const char *arg); static int b_stat(const char *arg); static int b_chmown(const char *arg); static int b_drop(const char *arg); +static int b_app(const char *arg); +static int b_cp(const char *arg); static struct builtin builtins[] = { { @@ -193,6 +194,16 @@ static struct builtin builtins[] = { "Become a peasant", b_drop, }, + { + "app", + "Append a file", + b_app, + }, + { + "cp", + "Copy a file", + b_cp, + }, { "help", "Please help me", @@ -314,7 +325,7 @@ static int b_chmown(const char *arg) { if ((res = readline(buf, sizeof(buf))) < 0) { return res; } - if ((res = from_oct(&accmode, buf)) != 0) { + if ((res = from_oct((int *) &accmode, buf)) != 0) { return res; } @@ -343,6 +354,146 @@ static int b_chmown(const char *arg) { return 0; } +static char *basename(char *path) { + char *p = strrchr(path, '/'); + if (!p) { + return path; + } else { + return p + 1; + } +} + +static int b_cp(const char *arg) { + char src_path[256]; + char dst_path[256]; + struct stat st; + int fd_src, fd_dst; + int res; + + const char *spc = strchr(arg, ' '); + if (!spc) { + printf("Usage: cp "); + return -1; + } + + strncpy(src_path, arg, spc - arg); + strcpy(dst_path, spc + 1); + + // Check that source is a file + if ((res = stat(src_path, &st)) != 0) { + perror(src_path); + return res; + } else if ((st.st_mode & S_IFMT) != S_IFREG) { + printf("Not a file: %s\n", src_path); + return -1; + } + + // Check if destination is a directory + if ((res = stat(dst_path, &st)) == 0) { + if ((st.st_mode & S_IFMT) == S_IFDIR) { + const char *name = basename(src_path); + size_t len = strlen(dst_path); + dst_path[len++] = '/'; + strcpy(&dst_path[len], name); + // TODO: check that this file is not some kind of a special device + } else if ((st.st_mode & S_IFMT) != S_IFREG) { + printf("Invalid destination: %s\n", dst_path); + return -1; + } + } + + if ((fd_src = open(src_path, O_RDONLY, 0)) < 0) { + perror(src_path); + return -1; + } + + // TODO: does cp copy file mode? + if ((fd_dst = open(dst_path, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) { + close(fd_src); + perror(dst_path); + return -1; + } + + char buf[512]; + ssize_t bread; + ssize_t bwrite; + + while ((bread = read(fd_src, buf, sizeof(buf))) > 0) { + if ((bwrite = write(fd_dst, buf, bread)) != bread) { + printf("Write failed\n"); + break; + } + } + + close(fd_dst); + close(fd_src); + + return 0; +} + +static int b_app(const char *arg) { + if (!arg) { + return -1; + } + + int opt = O_APPEND | O_WRONLY; + + while (1) { + while (isspace(*arg)) { + ++arg; + } + if (arg[0] == '-' && isalpha(arg[1])) { + // Some flag + switch (arg[1]) { + case 'c': + opt |= O_CREAT; + break; + case 't': + opt |= O_TRUNC; + break; + default: + printf("Unknown flag: -%c\n", arg[1]); + return -1; + } + arg += 2; + } else { + break; + } + } + + int fd = open(arg, opt, 0644); + if (fd < 0) { + perror(arg); + return fd; + } + + printf("Type \"EOF\" to stop writing\n"); + + char buf[512]; + int line_len; + + while (1) { + if ((line_len = readline(buf, sizeof(buf))) < 0) { + break; + } + + if (!strcmp(buf, "EOF")) { + break; + } + + if (write(fd, buf, line_len) < 0) { + printf("Write failed\n"); + break; + } + *(char *) &line_len = '\n'; + write(fd, &line_len, 1); + } + + close(fd); + + return 0; +} + static int b_rm(const char *arg) { int res; int is_r = 0; @@ -440,7 +591,6 @@ static int b_stat(const char *arg) { static int b_wr(const char *arg) { int fd; - ssize_t bwr; char buf[512]; int line_len; @@ -514,74 +664,6 @@ static int b_cat(const char *arg) { return 0; } -static int b_curs(const char *arg) { - char c; - - size_t w = 60; - size_t h = 20; - size_t off_y = (25 - h) / 2 + 1; - size_t off_x = (80 - w) / 2; - - const char *lines[18] = { - NULL, - "Demo something", - NULL, - "Slow as hell" - }; - - clear(); - - while (1) { - printf("\033[47;30m"); - - curs_set(off_y, off_x); - printf(BOX_ANGLE_UL); - for (size_t i = 0; i < w; ++i) { - printf(BOX_HOR); - } - printf(BOX_ANGLE_UR); - - for (size_t i = 0; i < h - 2; ++i) { - curs_set(off_y + 1 + i, off_x); - printf(BOX_VERT); - for (size_t j = 0; j < w; ++j) { - printf(" "); - } - if (lines[i]) { - curs_set(off_y + 1 + i, off_x + (w - strlen(lines[i])) / 2); - printf("%s", lines[i]); - } - curs_set(off_y + 1 + i, off_x + w + 1); - printf(BOX_VERT); - } - - curs_set(off_y + h - 3, off_x + (w - 8) / 2); - printf("\033[0m\033[7m[ OK ]\033[47;30m"); - curs_set(off_y + h - 1, off_x); - printf(BOX_ANGLE_LL); - for (size_t i = 0; i < w; ++i) { - printf(BOX_HOR); - } - printf(BOX_ANGLE_LR); - - printf("\033[0m"); - - curs_set(1, 1); - - if (read(STDIN_FILENO, &c, 1) < 0) { - break; - } - - if (c == 'q' || c == '\n') { - break; - } - } - - curs_set(1, 1); - - return 0; -} - static int b_sleep(const char *arg) { if (!arg) { return -1; @@ -683,7 +765,6 @@ static int cmd_subproc_exec(const char *abs_path, const char *cmd, const char *e argp[argc + 1] = NULL; int pid = fork(); - int res; int status; switch (pid) { @@ -738,10 +819,13 @@ static int cmd_exec(const char *line) { return cmd_subproc_exec(cmd, cmd, e); } // Try to execute binary from /bin - char path_buf[512]; - snprintf(path_buf, sizeof(path_buf), "/bin/%s", cmd); - if (access(path_buf, X_OK) == 0) { - return cmd_subproc_exec(path_buf, cmd, e); + // if name has no slashes + if (!strchr(cmd, '/')) { + char path_buf[512]; + snprintf(path_buf, sizeof(path_buf), "/bin/%s", cmd); + if (access(path_buf, X_OK) == 0) { + return cmd_subproc_exec(path_buf, cmd, e); + } } printf("%s: Unknown command\n", cmd);