From 0ca0e2a565657cd3e37315fe665b45b13daaebf4 Mon Sep 17 00:00:00 2001 From: Minep Date: Mon, 2 Jan 2023 16:47:37 +0000 Subject: [PATCH] feat: provide some libc routines only for testing feat: ls feat: readdir(3) for wrapping sys_readdir(2) chore: clean ups --- lunaix-os/libs/klibc/string/strlen.c | 3 +- lunaix-os/libs/ulibc/printf.c | 24 --- lunaix-os/uprog/init.c | 12 +- lunaix-os/uprog/ls.c | 30 +++ lunaix-os/usr/includes/dirent.h | 24 +++ lunaix-os/usr/includes/fcntl_defs.h | 10 + .../{includes/ulibc => usr/includes}/stdio.h | 3 + lunaix-os/usr/includes/stdlib.h | 7 + lunaix-os/usr/includes/string.h | 15 ++ .../usr/includes/sys/{dirent.h => lxdirent.h} | 4 +- lunaix-os/usr/includes/sys/types.h | 2 + lunaix-os/usr/libc/_mystdio.h | 10 + lunaix-os/usr/libc/_vprintf.c | 198 ++++++++++++++++++ lunaix-os/usr/libc/itoa.c | 46 ++++ lunaix-os/usr/libc/printf.c | 15 ++ lunaix-os/usr/libc/readdir.c | 41 ++++ lunaix-os/usr/libc/string.c | 44 ++++ lunaix-os/usr/uwrap.S | 1 - 18 files changed, 460 insertions(+), 29 deletions(-) delete mode 100644 lunaix-os/libs/ulibc/printf.c create mode 100644 lunaix-os/uprog/ls.c create mode 100644 lunaix-os/usr/includes/dirent.h rename lunaix-os/{includes/ulibc => usr/includes}/stdio.h (74%) create mode 100644 lunaix-os/usr/includes/stdlib.h create mode 100644 lunaix-os/usr/includes/string.h rename lunaix-os/usr/includes/sys/{dirent.h => lxdirent.h} (64%) create mode 100644 lunaix-os/usr/libc/_mystdio.h create mode 100644 lunaix-os/usr/libc/_vprintf.c create mode 100644 lunaix-os/usr/libc/itoa.c create mode 100644 lunaix-os/usr/libc/printf.c create mode 100644 lunaix-os/usr/libc/readdir.c create mode 100644 lunaix-os/usr/libc/string.c diff --git a/lunaix-os/libs/klibc/string/strlen.c b/lunaix-os/libs/klibc/string/strlen.c index 30ceb65..c982f7a 100644 --- a/lunaix-os/libs/klibc/string/strlen.c +++ b/lunaix-os/libs/klibc/string/strlen.c @@ -10,7 +10,8 @@ strlen(const char* str) } size_t -strnlen(const char* str, size_t max_len) { +strnlen(const char* str, size_t max_len) +{ size_t len = 0; while (str[len] && len <= max_len) len++; diff --git a/lunaix-os/libs/ulibc/printf.c b/lunaix-os/libs/ulibc/printf.c deleted file mode 100644 index 3d0b0f6..0000000 --- a/lunaix-os/libs/ulibc/printf.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include - -#include - -// This is VERY bad implementation as it mixes both kernel and user space -// code together. It is here however, just for the convenience of our testing -// program. -// FIXME Eliminate this when we're able to load program. - -void __USER__ -printf(const char* fmt, ...) -{ - const char buf[512]; - va_list args; - va_start(args, fmt); - - size_t sz = __ksprintf_internal(buf, fmt, 512, args); - - write(stdout, buf, sz); - - va_end(args); -} \ No newline at end of file diff --git a/lunaix-os/uprog/init.c b/lunaix-os/uprog/init.c index 0d1eebc..c0c3fdd 100644 --- a/lunaix-os/uprog/init.c +++ b/lunaix-os/uprog/init.c @@ -1,4 +1,5 @@ #include +#include #include #include @@ -17,7 +18,16 @@ main(int argc, const char** argv) return 0; } - syslog(0, "(%p) user space!\n", main); + printf("(%p) user space!\n", main); + + pid_t pid; + if (!(pid = fork())) { + int err = execve("/mnt/lunaix-os/usr/ls", NULL, NULL); + printf("fail to execute (%d)\n", err); + _exit(err); + } + + waitpid(pid, NULL, 0); return 0; } \ No newline at end of file diff --git a/lunaix-os/uprog/ls.c b/lunaix-os/uprog/ls.c new file mode 100644 index 0000000..605723c --- /dev/null +++ b/lunaix-os/uprog/ls.c @@ -0,0 +1,30 @@ +#include +#include +#include + +int +main(int argc, const char* argv[]) +{ + char* path = "."; + if (argc > 0) { + path = argv[0]; + } + + DIR* dir = opendir(path); + + if (!dir) { + return errno; + } + + struct dirent* dent; + + while ((dent = readdir(dir))) { + if (dent->d_type == DT_DIR) { + printf(" \033[3m%s\033[39;49m\n", dent->d_name); + } else { + printf(" %s\n", dent->d_name); + } + } + + return 0; +} \ No newline at end of file diff --git a/lunaix-os/usr/includes/dirent.h b/lunaix-os/usr/includes/dirent.h new file mode 100644 index 0000000..30ed892 --- /dev/null +++ b/lunaix-os/usr/includes/dirent.h @@ -0,0 +1,24 @@ +#ifndef __LUNAIX_SYS_DIRENT_H +#define __LUNAIX_SYS_DIRENT_H + +#include + +typedef struct +{ + int dirfd; + int prev_res; +} DIR; + +struct dirent +{ + unsigned char d_type; + char d_name[256]; +}; + +DIR* +opendir(const char* dir); + +struct dirent* +readdir(DIR* dir); + +#endif /* __LUNAIX_DIRENT_H */ diff --git a/lunaix-os/usr/includes/fcntl_defs.h b/lunaix-os/usr/includes/fcntl_defs.h index 01930cb..c6cbe4f 100644 --- a/lunaix-os/usr/includes/fcntl_defs.h +++ b/lunaix-os/usr/includes/fcntl_defs.h @@ -4,11 +4,21 @@ #define FO_CREATE 0x1 #define FO_APPEND 0x2 #define FO_DIRECT 0x4 +#define FO_WRONLY 0x8 +#define FO_RDONLY 0x10 +#define FO_RDWR 0x20 #define FSEEK_SET 0x1 #define FSEEK_CUR 0x2 #define FSEEK_END 0x3 +#define O_CREAT FO_CREATE +#define O_APPEND FO_APPEND +#define O_DIRECT FO_DIRECT +#define O_WRONLY FO_WRONLY +#define O_RDONLY FO_RDONLY +#define O_RDWR FO_RDWR + #define MNT_RO 0x1 #endif /* __LUNAIX_FNCTL_DEFS_H */ diff --git a/lunaix-os/includes/ulibc/stdio.h b/lunaix-os/usr/includes/stdio.h similarity index 74% rename from lunaix-os/includes/ulibc/stdio.h rename to lunaix-os/usr/includes/stdio.h index e9496a8..f898bed 100644 --- a/lunaix-os/includes/ulibc/stdio.h +++ b/lunaix-os/usr/includes/stdio.h @@ -7,4 +7,7 @@ void printf(const char* fmt, ...); +const char* +strchr(const char* str, int character); + #endif /* __LUNAIX_USTDIO_H */ diff --git a/lunaix-os/usr/includes/stdlib.h b/lunaix-os/usr/includes/stdlib.h new file mode 100644 index 0000000..0e38fb5 --- /dev/null +++ b/lunaix-os/usr/includes/stdlib.h @@ -0,0 +1,7 @@ +#ifndef __LUNAIX_STDLIB_H +#define __LUNAIX_STDLIB_H + +char* +itoa(int value, char* str, int base); + +#endif /* __LUNAIX_STDLIB_H */ diff --git a/lunaix-os/usr/includes/string.h b/lunaix-os/usr/includes/string.h new file mode 100644 index 0000000..a309924 --- /dev/null +++ b/lunaix-os/usr/includes/string.h @@ -0,0 +1,15 @@ +#ifndef __LUNAIX_STRING_H +#define __LUNAIX_STRING_H + +#include + +size_t +strlen(const char* str); + +size_t +strnlen(const char* str, size_t max_len); + +char* +strncpy(char* dest, const char* src, size_t n); + +#endif /* __LUNAIX_STRING_H */ diff --git a/lunaix-os/usr/includes/sys/dirent.h b/lunaix-os/usr/includes/sys/lxdirent.h similarity index 64% rename from lunaix-os/usr/includes/sys/dirent.h rename to lunaix-os/usr/includes/sys/lxdirent.h index 101f050..e616180 100644 --- a/lunaix-os/usr/includes/sys/dirent.h +++ b/lunaix-os/usr/includes/sys/lxdirent.h @@ -1,5 +1,5 @@ -#ifndef __LUNAIX_SYS_DIRENT_H -#define __LUNAIX_SYS_DIRENT_H +#ifndef __LUNAIX_SYS_LXDIRENT_H +#define __LUNAIX_SYS_LXDIRENT_H #include diff --git a/lunaix-os/usr/includes/sys/types.h b/lunaix-os/usr/includes/sys/types.h index a4b7f29..8b30318 100644 --- a/lunaix-os/usr/includes/sys/types.h +++ b/lunaix-os/usr/includes/sys/types.h @@ -1,6 +1,8 @@ #ifndef __LUNAIX_SYS_TYPES_H #define __LUNAIX_SYS_TYPES_H +#define NULL (void*)0 + #define PEXITTERM 0x100 #define PEXITSTOP 0x200 #define PEXITSIG 0x400 diff --git a/lunaix-os/usr/libc/_mystdio.h b/lunaix-os/usr/libc/_mystdio.h new file mode 100644 index 0000000..d60fed3 --- /dev/null +++ b/lunaix-os/usr/libc/_mystdio.h @@ -0,0 +1,10 @@ +#ifndef __LUNAIX__MYSTDIO_H +#define __LUNAIX__MYSTDIO_H + +#include +#include + +int +__vprintf_internal(char* buffer, char* fmt, size_t max_len, va_list vargs); + +#endif /* __LUNAIX__MYSTDIO_H */ diff --git a/lunaix-os/usr/libc/_vprintf.c b/lunaix-os/usr/libc/_vprintf.c new file mode 100644 index 0000000..1e56305 --- /dev/null +++ b/lunaix-os/usr/libc/_vprintf.c @@ -0,0 +1,198 @@ +#include "_mystdio.h" +#include +#include +#include + +#define NUMBUFSIZ 24 + +static const char flag_chars[] = "#0- +"; + +#define FLAG_ALT (1 << 0) +#define FLAG_ZERO (1 << 1) +#define FLAG_LEFTJUSTIFY (1 << 2) +#define FLAG_SPACEPOSITIVE (1 << 3) +#define FLAG_PLUSPOSITIVE (1 << 4) +#define FLAG_NUMERIC (1 << 5) +#define FLAG_SIGNED (1 << 6) +#define FLAG_NEGATIVE (1 << 7) +#define FLAG_ALT2 (1 << 8) +#define FLAG_CAPS (1 << 9) + +int +__vprintf_internal(char* buffer, char* fmt, size_t max_len, va_list vargs) +{ + // This sprintf just a random implementation I found it on Internet . lol. + // Of course, with some modifications for porting to LunaixOS :) + + char numbuf[NUMBUFSIZ]; + uintptr_t ptr = 0; + for (; *fmt; ++fmt) { + if (max_len && ptr >= max_len - 1) { + break; + } + + if (*fmt != '%') { + buffer[ptr++] = *fmt; + continue; + } + + // process flags + int flags = 0; + for (++fmt; *fmt; ++fmt) { + const char* flagc = strchr(flag_chars, *fmt); + if (flagc) { + flags |= 1 << (flagc - flag_chars); + } else { + break; + } + } + + // process width + int width = -1; + if (*fmt >= '1' && *fmt <= '9') { + for (width = 0; *fmt >= '0' && *fmt <= '9';) { + width = 10 * width + *fmt++ - '0'; + } + } else if (*fmt == '*') { + width = va_arg(vargs, int); + ++fmt; + } + + // process precision + int precision = -1; + if (*fmt == '.') { + ++fmt; + if (*fmt >= '0' && *fmt <= '9') { + for (precision = 0; *fmt >= '0' && *fmt <= '9';) { + precision = 10 * precision + *fmt++ - '0'; + } + } else if (*fmt == '*') { + precision = va_arg(vargs, int); + ++fmt; + } + if (precision < 0) { + precision = 0; + } + } + + // process main conversion character + int base = 10; + unsigned long num = 0; + int length = 0; + char* data = ""; + again: + switch (*fmt) { + case 'l': + case 'z': + length = 1; + ++fmt; + goto again; + case 'd': + case 'i': { + long x = length ? va_arg(vargs, long) : va_arg(vargs, int); + int negative = x < 0 ? FLAG_NEGATIVE : 0; + num = negative ? -x : x; + flags |= FLAG_NUMERIC | FLAG_SIGNED | negative; + break; + } + case 'u': + format_unsigned: + num = length ? va_arg(vargs, unsigned long) + : va_arg(vargs, unsigned); + flags |= FLAG_NUMERIC; + break; + case 'b': + base = 2; + goto format_unsigned; + case 'x': + base = 16; + goto format_unsigned; + case 'X': + flags = flags | FLAG_CAPS; + base = 16; + goto format_unsigned; + case 'p': + num = (uintptr_t)va_arg(vargs, void*); + base = 16; + flags |= FLAG_ALT | FLAG_ALT2 | FLAG_NUMERIC; + break; + case 's': + data = va_arg(vargs, char*); + break; + case 'c': + data = numbuf; + numbuf[0] = va_arg(vargs, int); + numbuf[1] = '\0'; + break; + default: + data = numbuf; + numbuf[0] = (*fmt ? *fmt : '%'); + numbuf[1] = '\0'; + if (!*fmt) { + fmt--; + } + break; + } + + if (flags & FLAG_NUMERIC) { + data = itoa(num, numbuf, base); + int i = 0; + char c; + while ((flags & FLAG_CAPS) && (c = data[i])) { + data[i] = c & ~((c & 0x40) >> 1); + i++; + } + } + + const char* prefix = ""; + if ((flags & FLAG_NUMERIC) && (flags & FLAG_SIGNED)) { + if (flags & FLAG_NEGATIVE) { + prefix = "-"; + } else if (flags & FLAG_PLUSPOSITIVE) { + prefix = "+"; + } else if (flags & FLAG_SPACEPOSITIVE) { + prefix = " "; + } + } else if ((flags & FLAG_NUMERIC) && (flags & FLAG_ALT) && + (base == 16 || base == -16) && + (num || (flags & FLAG_ALT2))) { + prefix = "0x"; + } + + int len; + if (precision >= 0 && !(flags & FLAG_NUMERIC)) { + len = strnlen(data, precision); + } else { + len = strlen(data); + } + int zeros; + if ((flags & FLAG_NUMERIC) && precision >= 0) { + zeros = precision > len ? precision - len : 0; + } else if ((flags & FLAG_NUMERIC) && (flags & FLAG_ZERO) && + !(flags & FLAG_LEFTJUSTIFY) && + len + (int)strlen(prefix) < width) { + zeros = width - len - strlen(prefix); + } else { + zeros = 0; + } + width -= len + zeros + strlen(prefix); + for (; !(flags & FLAG_LEFTJUSTIFY) && width > 0; --width) { + buffer[ptr++] = ' '; + } + for (; *prefix; ++prefix) { + buffer[ptr++] = *prefix; + } + for (; zeros > 0; --zeros) { + buffer[ptr++] = '0'; + } + for (; len > 0; ++data, --len) { + buffer[ptr++] = *data; + } + for (; width > 0; --width) { + buffer[ptr++] = ' '; + } + } + buffer[ptr++] = '\0'; + + return ptr; +} diff --git a/lunaix-os/usr/libc/itoa.c b/lunaix-os/usr/libc/itoa.c new file mode 100644 index 0000000..d60599f --- /dev/null +++ b/lunaix-os/usr/libc/itoa.c @@ -0,0 +1,46 @@ +#include +#include + +char base_char[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + +char* +__uitoa_internal(unsigned int value, char* str, int base, unsigned int* size) +{ + unsigned int ptr = 0; + do { + str[ptr] = base_char[value % base]; + value = value / base; + ptr++; + } while (value); + + for (unsigned int i = 0; i < (ptr >> 1); i++) { + char c = str[i]; + str[i] = str[ptr - i - 1]; + str[ptr - i - 1] = c; + } + str[ptr] = '\0'; + if (size) { + *size = ptr; + } + return str; +} + +char* +__itoa_internal(int value, char* str, int base, unsigned int* size) +{ + if (value < 0 && base == 10) { + str[0] = '-'; + unsigned int _v = (unsigned int)(-value); + __uitoa_internal(_v, str + 1, base, size); + } else { + __uitoa_internal(value, str, base, size); + } + + return str; +} + +char* +itoa(int value, char* str, int base) +{ + return __itoa_internal(value, str, base, NULL); +} \ No newline at end of file diff --git a/lunaix-os/usr/libc/printf.c b/lunaix-os/usr/libc/printf.c new file mode 100644 index 0000000..2557117 --- /dev/null +++ b/lunaix-os/usr/libc/printf.c @@ -0,0 +1,15 @@ +#include "_mystdio.h" +#include +#include + +void +printf(const char* fmt, ...) +{ + char buf[1024]; + va_list args; + va_start(args, fmt); + int n = __vprintf_internal(buf, fmt, 1024, args); + va_end(args); + + return write(stdout, buf, n); +} \ No newline at end of file diff --git a/lunaix-os/usr/libc/readdir.c b/lunaix-os/usr/libc/readdir.c new file mode 100644 index 0000000..9d2b23e --- /dev/null +++ b/lunaix-os/usr/libc/readdir.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include + +DIR* +opendir(const char* dir) +{ + static DIR _dir; + int fd = open(dir, O_RDONLY); + if (fd < 0) { + return NULL; + } + + _dir = (DIR){ .dirfd = fd, .prev_res = 0 }; + return &_dir; +} + +struct dirent* +readdir(DIR* dir) +{ + static struct dirent _dirent; + if (!dir) { + return NULL; + } + + struct lx_dirent _lxd; + int more = sys_readdir(dir->dirfd, &_lxd); + + _dirent.d_type = _lxd.d_type; + strncpy(_dirent.d_name, _lxd.d_name, 256); + + if (more || dir->prev_res) { + dir->prev_res = more; + return &_dirent; + } + + if (!dir->prev_res) { + return NULL; + } +} \ No newline at end of file diff --git a/lunaix-os/usr/libc/string.c b/lunaix-os/usr/libc/string.c new file mode 100644 index 0000000..2e34dc7 --- /dev/null +++ b/lunaix-os/usr/libc/string.c @@ -0,0 +1,44 @@ +#include + +size_t +strlen(const char* str) +{ + size_t len = 0; + while (str[len]) + len++; + return len; +} + +const char* +strchr(const char* str, int character) +{ + char c = (char)character; + while ((*str)) { + if (*str == c) { + return str; + } + str++; + } + return c == '\0' ? str : NULL; +} + +size_t +strnlen(const char* str, size_t max_len) +{ + size_t len = 0; + while (str[len] && len <= max_len) + len++; + return len; +} + +char* +strncpy(char* dest, const char* src, size_t n) +{ + char c; + unsigned int i = 0; + while ((c = src[i]) && i <= n) + dest[i++] = c; + while (i <= n) + dest[i++] = 0; + return dest; +} \ No newline at end of file diff --git a/lunaix-os/usr/uwrap.S b/lunaix-os/usr/uwrap.S index 1cd6515..1f07722 100644 --- a/lunaix-os/usr/uwrap.S +++ b/lunaix-os/usr/uwrap.S @@ -4,7 +4,6 @@ .section .text .global _u_start _u_start: - movl $2, %eax call usr_pre_init jnz 1f -- 2.27.0