diff --git a/AK/printf.cpp b/AK/printf.cpp new file mode 100644 index 0000000000..5df39a8cfa --- /dev/null +++ b/AK/printf.cpp @@ -0,0 +1,181 @@ +typedef unsigned char byte; +typedef unsigned short word; +typedef unsigned int dword; + +inline size_t strlen(const char* str) +{ + size_t len = 0; + while (*(str++)) + ++len; + return len; +} + +static constexpr const char* h = "0123456789abcdef"; + +template +int printHex(PutChFunc putch, char*& bufptr, dword number, byte fields) +{ + int ret = 0; + byte shr_count = fields * 4; + while (shr_count) { + shr_count -= 4; + putch(bufptr, h[(number >> shr_count) & 0x0F]); + ++ret; + } + return ret; +} + +template +int printNumber(PutChFunc putch, char*& bufptr, dword number, bool leftPad, bool zeroPad, dword fieldWidth) +{ + dword divisor = 1000000000; + char ch; + char padding = 1; + char buf[16]; + char* p = buf; + + for (;;) { + ch = '0' + (number / divisor); + number %= divisor; + if (ch != '0') + padding = 0; + if (!padding || divisor == 1) + *(p++) = ch; + if (divisor == 1) + break; + divisor /= 10; + } + + size_t numlen = p - buf; + if (!fieldWidth) + fieldWidth = numlen; + if (!leftPad) { + for (unsigned i = 0; i < fieldWidth - numlen; ++i) { + putch(bufptr, zeroPad ? '0' : ' '); + } + } + for (unsigned i = 0; i < numlen; ++i) { + putch(bufptr, buf[i]); + } + if (leftPad) { + for (unsigned i = 0; i < fieldWidth - numlen; ++i) { + putch(bufptr, ' '); + } + } + + return fieldWidth; +} + +template +int printString(PutChFunc putch, char*& bufptr, const char* str, bool leftPad, dword fieldWidth) +{ + size_t len = strlen(str); + if (!fieldWidth) + fieldWidth = len; + if (!leftPad) { + for (unsigned i = 0; i < fieldWidth - len; ++i) + putch(bufptr, ' '); + } + for (unsigned i = 0; i < len; ++i) { + putch(bufptr, str[i]); + } + if (leftPad) { + for (unsigned i = 0; i < fieldWidth - len; ++i) + putch(bufptr, ' '); + } + return fieldWidth; +} + + +template +int printSignedNumber(PutChFunc putch, char*& bufptr, int number, bool leftPad, bool zeroPad, dword fieldWidth) +{ + if (number < 0) { + putch(bufptr, '-'); + return printNumber(putch, bufptr, 0 - number, leftPad, zeroPad, fieldWidth) + 1; + } + return printNumber(putch, bufptr, number, leftPad, zeroPad, fieldWidth); +} + +template +int printfInternal(PutChFunc putch, char* buffer, const char*& fmt, char*& ap) +{ + const char *p; + + int ret = 0; + char* bufptr = buffer; + + for (p = fmt; *p; ++p) { + bool leftPad = false; + bool zeroPad = false; + unsigned fieldWidth = 0; + if (*p == '%' && *(p + 1)) { +one_more: + ++p; + if (*p == ' ') { + leftPad = true; + if (*(p + 1)) + goto one_more; + } + if (!zeroPad && !fieldWidth && *p == '0') { + zeroPad = true; + if (*(p + 1)) + goto one_more; + } + if (*p >= '0' && *p <= '9') { + fieldWidth *= 10; + fieldWidth += *p - '0'; + if (*(p + 1)) + goto one_more; + } + switch( *p ) + { + case 's': + { + const char* sp = va_arg(ap, const char*); + ret += printString(putch, bufptr, sp ? sp : "(null)", leftPad, fieldWidth); + } + break; + + case 'd': + ret += printSignedNumber(putch, bufptr, va_arg(ap, int), leftPad, zeroPad, fieldWidth); + break; + + case 'u': + ret += printNumber(putch, bufptr, va_arg(ap, dword), leftPad, zeroPad, fieldWidth); + break; + + case 'x': + ret += printHex(putch, bufptr, va_arg(ap, dword), 8); + break; + + case 'w': + ret += printHex(putch, bufptr, va_arg(ap, int), 4); + break; + + case 'b': + ret += printHex(putch, bufptr, va_arg(ap, int), 2); + break; + + case 'c': + putch(bufptr, (char)va_arg(ap, int)); + ++ret; + break; + + case 'p': + putch(bufptr, '0'); + putch(bufptr, 'x'); + ret += 2; + ret += printHex(putch, bufptr, va_arg(ap, dword), 8); + break; + } + } + else { + putch(bufptr, *p); + ++ret; + } + } + return ret; +} + + diff --git a/Kernel/Task.cpp b/Kernel/Task.cpp index 72293365c1..10326fe03d 100644 --- a/Kernel/Task.cpp +++ b/Kernel/Task.cpp @@ -230,6 +230,11 @@ Task* Task::createUserTask(const String& path, uid_t uid, gid_t gid, pid_t paren return nullptr; } + if (!handle->metadata().mayExecute(uid, gid)) { + error = -EACCES; + return nullptr; + } + auto elfData = handle->readEntireFile(); if (!elfData) { error = -EIO; // FIXME: Get a more detailed error from VFS. diff --git a/Kernel/_fs_contents b/Kernel/_fs_contents index 1adddde26b..93f5d7a144 100644 Binary files a/Kernel/_fs_contents and b/Kernel/_fs_contents differ diff --git a/Kernel/kprintf.cpp b/Kernel/kprintf.cpp index b80fcc2e0b..463a3ce915 100644 --- a/Kernel/kprintf.cpp +++ b/Kernel/kprintf.cpp @@ -2,95 +2,18 @@ #include "Console.h" #include #include - -template static int printNumber(PutChFunc, char*&, dword); -template static int printHex(PutChFunc, char*&, dword, byte fields); -template static int printSignedNumber(PutChFunc, char*&, int); +#include static void console_putch(char*, char ch) { Console::the().write((byte*)&ch, 1); } -template -int kprintfInternal(PutChFunc putch, char* buffer, const char*& fmt, char*& ap) -{ - const char *p; - - int ret = 0; - char* bufptr = buffer; - - for (p = fmt; *p; ++p) { - if (*p == '%' && *(p + 1)) { - ++p; - switch( *p ) - { - case 's': - { - const char* sp = va_arg(ap, const char*); - //ASSERT(sp != nullptr); - if (!sp) { - putch(bufptr, '<'); - putch(bufptr, 'N'); - putch(bufptr, 'u'); - putch(bufptr, 'L'); - putch(bufptr, '>'); - ret += 5; - } else { - for (; *sp; ++sp) { - putch(bufptr, *sp); - ++ret; - } - } - } - break; - - case 'd': - ret += printSignedNumber(putch, bufptr, va_arg(ap, int)); - break; - - case 'u': - ret += printNumber(putch, bufptr, va_arg(ap, dword)); - break; - - case 'x': - ret += printHex(putch, bufptr, va_arg(ap, dword), 8); - break; - - case 'w': - ret += printHex(putch, bufptr, va_arg(ap, int), 4); - break; - - case 'b': - ret += printHex(putch, bufptr, va_arg(ap, int), 2); - break; - - case 'c': - putch(bufptr, (char)va_arg(ap, int)); - ++ret; - break; - - case 'p': - putch(bufptr, '0'); - putch(bufptr, 'x'); - ret += 2; - ret += printHex(putch, bufptr, va_arg(ap, dword), 8); - break; - } - } - else { - putch(bufptr, *p); - ++ret; - } - } - return ret; -} - int kprintf(const char* fmt, ...) { va_list ap; va_start(ap, fmt); - int ret = kprintfInternal(console_putch, nullptr, fmt, ap); + int ret = printfInternal(console_putch, nullptr, fmt, ap); va_end(ap); return ret; } @@ -104,64 +27,8 @@ int ksprintf(char* buffer, const char* fmt, ...) { va_list ap; va_start(ap, fmt); - int ret = kprintfInternal(buffer_putch, buffer, fmt, ap); + int ret = printfInternal(buffer_putch, buffer, fmt, ap); buffer[ret] = '\0'; va_end(ap); return ret; } - -template -int printHex(PutChFunc putch, char*& bufptr, dword number, byte fields) -{ - static const char h[] = { - '0','1','2','3','4','5','6','7', - '8','9','a','b','c','d','e','f' - }; - - int ret = 0; - byte shr_count = fields * 4; - while (shr_count) { - shr_count -= 4; - putch(bufptr, h[(number >> shr_count) & 0x0F]); - ++ret; - } - return ret; -} - -template -int printNumber(PutChFunc putch, char*& bufptr, dword number) -{ - dword divisor = 1000000000; - char ch; - char padding = 1; - int ret = 0; - - for (;;) { - ch = '0' + (number / divisor); - number %= divisor; - - if (ch != '0') - padding = 0; - - if (!padding || divisor == 1) { - putch(bufptr, ch); - ++ret; - } - - if (divisor == 1) - break; - divisor /= 10; - } - return ret; -} - -template -static int printSignedNumber(PutChFunc putch, char*& bufptr, int number) -{ - if (number < 0) { - putch(bufptr, '-'); - return printNumber(putch, bufptr, 0 - number) + 1; - } - return printNumber(putch, bufptr, number); -} - diff --git a/LibC/stdio.cpp b/LibC/stdio.cpp index 3448659fab..ed0a169ab8 100644 --- a/LibC/stdio.cpp +++ b/LibC/stdio.cpp @@ -4,140 +4,7 @@ #include "string.h" #include "errno.h" #include - -#define ALWAYS_INLINE __attribute__ ((always_inline)) - -static constexpr const char* h = "0123456789abcdef"; - -template -ALWAYS_INLINE int printHex(PutChFunc putch, char*& bufptr, dword number, byte fields) -{ - int ret = 0; - byte shr_count = fields * 4; - while (shr_count) { - shr_count -= 4; - putch(bufptr, h[(number >> shr_count) & 0x0F]); - ++ret; - } - return ret; -} - -template -ALWAYS_INLINE int printNumber(PutChFunc putch, char*& bufptr, dword number) -{ - dword divisor = 1000000000; - char ch; - char padding = 1; - int ret = 0; - - for (;;) { - ch = '0' + (number / divisor); - number %= divisor; - - if (ch != '0') - padding = 0; - - if (!padding || divisor == 1) { - putch(bufptr, ch); - ++ret; - } - - if (divisor == 1) - break; - divisor /= 10; - } - return ret; -} - -template -ALWAYS_INLINE int printSignedNumber(PutChFunc putch, char*& bufptr, int number) -{ - if (number < 0) { - putch(bufptr, '-'); - return printNumber(putch, bufptr, 0 - number) + 1; - } - return printNumber(putch, bufptr, number); -} - -static void sys_putch(char*, char ch) -{ - Syscall::invoke(Syscall::PutCharacter, ch); -} - -template -int printfInternal(PutChFunc putch, char* buffer, const char*& fmt, char*& ap) -{ - const char *p; - - int ret = 0; - char* bufptr = buffer; - - for (p = fmt; *p; ++p) { - if (*p == '%' && *(p + 1)) { - ++p; - switch( *p ) - { - case 's': - { - const char* sp = va_arg(ap, const char*); - //ASSERT(sp != nullptr); - if (!sp) { - putch(bufptr, '('); - putch(bufptr, 'n'); - putch(bufptr, 'u'); - putch(bufptr, 'l'); - putch(bufptr, 'l'); - putch(bufptr, ')'); - ret += 6; - } else { - for (; *sp; ++sp) { - putch(bufptr, *sp); - ++ret; - } - } - } - break; - - case 'd': - ret += printSignedNumber(putch, bufptr, va_arg(ap, int)); - break; - - case 'u': - ret += printNumber(putch, bufptr, va_arg(ap, dword)); - break; - - case 'x': - ret += printHex(putch, bufptr, va_arg(ap, dword), 8); - break; - - case 'w': - ret += printHex(putch, bufptr, va_arg(ap, int), 4); - break; - - case 'b': - ret += printHex(putch, bufptr, va_arg(ap, int), 2); - break; - - case 'c': - putch(bufptr, (char)va_arg(ap, int)); - ++ret; - break; - - case 'p': - putch(bufptr, '0'); - putch(bufptr, 'x'); - ret += 2; - ret += printHex(putch, bufptr, va_arg(ap, dword), 8); - break; - } - } - else { - putch(bufptr, *p); - ++ret; - } - } - return ret; -} +#include extern "C" { @@ -147,6 +14,11 @@ int putchar(int ch) return (byte)ch; } +static void sys_putch(char*, char ch) +{ + Syscall::invoke(Syscall::PutCharacter, ch); +} + int printf(const char* fmt, ...) { va_list ap; diff --git a/Userland/ls.cpp b/Userland/ls.cpp index b37b3f07d3..3af8252608 100644 --- a/Userland/ls.cpp +++ b/Userland/ls.cpp @@ -22,6 +22,8 @@ int main(int c, char** v) return 2; } + printf("%08u ", de->d_ino); + if (S_ISDIR(st.st_mode)) printf("d"); else if (S_ISLNK(st.st_mode)) @@ -53,8 +55,9 @@ int main(int c, char** v) else printf("%c", st.st_mode & S_IXOTH ? 'x' : '-'); - printf(" i:%x ", de->d_ino); - printf(" %x ", st.st_size); + printf(" %4u %4u", st.st_uid, st.st_gid); + + printf(" %10u ", st.st_size); printf("%s%c", de->d_name, S_ISDIR(st.st_mode) ? '/' : ' '); printf("\n"); } diff --git a/VirtualFileSystem/FileHandle.h b/VirtualFileSystem/FileHandle.h index cc3cc4ee0a..9e8407f002 100644 --- a/VirtualFileSystem/FileHandle.h +++ b/VirtualFileSystem/FileHandle.h @@ -1,6 +1,7 @@ #pragma once #include "VirtualFileSystem.h" +#include "InodeMetadata.h" #include class FileHandle { @@ -22,6 +23,8 @@ public: bool isDirectory() const; + InodeMetadata metadata() const { return m_vnode->metadata(); } + VirtualFileSystem::Node* vnode() { return m_vnode.ptr(); } #ifdef SERENITY diff --git a/VirtualFileSystem/InodeMetadata.h b/VirtualFileSystem/InodeMetadata.h index e5d35b6b93..9d31145b54 100644 --- a/VirtualFileSystem/InodeMetadata.h +++ b/VirtualFileSystem/InodeMetadata.h @@ -17,6 +17,15 @@ inline bool isSetGID(Unix::mode_t mode) { return mode & 02000; } struct InodeMetadata { bool isValid() const { return inode.isValid(); } + bool mayExecute(uid_t u, gid_t g) const + { + if (uid == u) + return mode & 0100; + if (gid == g) + return mode & 0010; + return mode & 0001; + } + bool isDirectory() const { return ::isDirectory(mode); } bool isCharacterDevice() const { return ::isCharacterDevice(mode); } bool isBlockDevice() const { return ::isBlockDevice(mode); }