diff --git a/.clang-format b/.clang-format index d2314f72ac..8a109530e5 100644 --- a/.clang-format +++ b/.clang-format @@ -10,4 +10,3 @@ IndentPPDirectives: AfterHash BreakBeforeBraces: Custom BraceWrapping: AfterFunction: true - AfterEnum: true diff --git a/.gitignore b/.gitignore index 02d28254fc..c821301076 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ Toolchain/Tarballs Toolchain/Build Toolchain/Local .vscode +compile_commands.json +.clang_complete diff --git a/.travis.yml b/.travis.yml index d24bc2296e..f8e8d67449 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ notifications: before_install: - sudo apt-get update - sudo apt-get install -y libmpfr-dev libmpc-dev libgmp-dev -- sudo apt-get install -y e2fsprogs qemu-system-i386 +- sudo apt-get install -y e2fsprogs qemu-system-i386 qemu-utils script: - cd Toolchain diff --git a/AK/AKString.h b/AK/AKString.h index b93843b719..7784c9252f 100644 --- a/AK/AKString.h +++ b/AK/AKString.h @@ -10,15 +10,38 @@ namespace AK { +// String is a convenience wrapper around StringImpl, suitable for passing +// around as a value type. It's basically the same as passing around a +// RetainPtr, with a bit of syntactic sugar. +// +// Note that StringImpl is an immutable object that cannot shrink or grow. +// Its allocation size is snugly tailored to the specific string it contains. +// Copying a String is very efficient, since the internal StringImpl is +// retainable and so copying only requires modifying the retain count. +// +// There are three main ways to construct a new String: +// +// s = String("some literal"); +// +// s = String::format("%d little piggies", m_piggies); +// +// StringBuilder builder; +// builder.append("abc"); +// builder.append("123"); +// s = builder.to_string(); + class String { public: ~String() {} String() {} - String(StringView view) - : m_impl(StringImpl::create(view.characters(), view.length())) + String(const StringView& view) { + if (view.m_impl) + m_impl = *view.m_impl; + else + m_impl = StringImpl::create(view.characters(), view.length()); } String(const String& other) @@ -36,7 +59,7 @@ public: { } - String(const char* cstring, ssize_t length, ShouldChomp shouldChomp = NoChomp) + String(const char* cstring, int length, ShouldChomp shouldChomp = NoChomp) : m_impl(StringImpl::create(cstring, length, shouldChomp)) { } @@ -67,7 +90,7 @@ public: }; static String repeated(char, int count); - bool matches(const String& pattern, CaseSensitivity = CaseSensitivity::CaseInsensitive) const; + bool matches(const StringView& pattern, CaseSensitivity = CaseSensitivity::CaseInsensitive) const; int to_int(bool& ok) const; unsigned to_uint(bool& ok) const; @@ -86,6 +109,7 @@ public: return m_impl->to_uppercase(); } + Vector split_limit(char separator, int limit) const; Vector split(char separator) const; String substring(int start, int length) const; @@ -94,20 +118,35 @@ public: bool is_null() const { return !m_impl; } bool is_empty() const { return length() == 0; } - ssize_t length() const { return m_impl ? m_impl->length() : 0; } + int length() const { return m_impl ? m_impl->length() : 0; } const char* characters() const { return m_impl ? m_impl->characters() : nullptr; } - char operator[](ssize_t i) const + char operator[](int i) const { ASSERT(m_impl); return (*m_impl)[i]; } - bool ends_with(const String&) const; + bool starts_with(const StringView&) const; + bool ends_with(const StringView&) const; bool operator==(const String&) const; bool operator!=(const String& other) const { return !(*this == other); } bool operator<(const String&) const; + bool operator==(const char* cstring) const + { + if (is_null()) + return !cstring; + if (!cstring) + return false; + return !strcmp(characters(), cstring); + } + + bool operator!=(const char* cstring) const + { + return !(*this == cstring); + } + String isolated_copy() const; static String empty(); @@ -146,7 +185,7 @@ public: StringView view() const { return { characters(), length() }; } private: - bool match_helper(const String& mask) const; + bool match_helper(const StringView& mask) const; RetainPtr m_impl; }; diff --git a/AK/Badge.h b/AK/Badge.h index 0bcb62de4c..bab524cc7c 100644 --- a/AK/Badge.h +++ b/AK/Badge.h @@ -1,7 +1,20 @@ #pragma once +namespace AK { + template class Badge { friend T; Badge() {} + + Badge(const Badge&) = delete; + Badge& operator=(const Badge&) = delete; + + Badge(Badge&&) = delete; + Badge& operator=(Badge&&) = delete; }; + +} + +using AK::Badge; + diff --git a/AK/Bitmap.h b/AK/Bitmap.h index 1c013cc3c0..50021cde93 100644 --- a/AK/Bitmap.h +++ b/AK/Bitmap.h @@ -20,6 +20,11 @@ public: return Bitmap(size, default_value); } + static Bitmap create() + { + return Bitmap(); + } + ~Bitmap() { if (m_owned) @@ -45,12 +50,74 @@ public: byte* data() { return m_data; } const byte* data() const { return m_data; } + void grow(int size, bool default_value) + { + ASSERT(size > m_size); + + auto previous_size_bytes = size_in_bytes(); + auto previous_size = m_size; + auto previous_data = m_data; + + m_size = size; + m_data = reinterpret_cast(kmalloc(size_in_bytes())); + + fill(default_value); + + if (previous_data != nullptr) { + memcpy(m_data, previous_data, previous_size_bytes); + + if ((previous_size % 8) != 0) { + if (default_value) + m_data[previous_size_bytes - 1] |= (0xff >> (previous_size % 8)); + else + m_data[previous_size_bytes - 1] &= ~(0xff >> (previous_size % 8)); + } + + kfree(previous_data); + } + } + void fill(bool value) { memset(m_data, value ? 0xff : 0x00, size_in_bytes()); } + int find_first_set() const + { + int i = 0; + while (i < m_size / 8 && m_data[i] == 0x00) + i++; + + int j = 0; + for (j = i * 8; j < m_size; j++) + if (get(j)) + return j; + + return -1; + } + + int find_first_unset() const + { + int i = 0; + while (i < m_size / 8 && m_data[i] == 0xff) + i++; + + int j = 0; + for (j = i * 8; j < m_size; j++) + if (!get(j)) + return j; + + return -1; + } + private: + explicit Bitmap() + : m_size(0) + , m_owned(true) + { + m_data = nullptr; + } + explicit Bitmap(int size, bool default_value) : m_size(size) , m_owned(true) diff --git a/AK/BufferStream.h b/AK/BufferStream.h index db2907963f..7edc9f6e65 100644 --- a/AK/BufferStream.h +++ b/AK/BufferStream.h @@ -36,15 +36,7 @@ public: m_buffer[m_offset++] = (byte)(value >> 24) & 0xffu; } - void operator<<(const char* str) - { - ssize_t len = strlen(str); - ASSERT(len >= 0); - for (ssize_t i = 0; i < len; ++i) - m_buffer[m_offset++] = str[i]; - } - - void operator<<(const String& value) + void operator<<(const StringView& value) { for (ssize_t i = 0; i < value.length(); ++i) m_buffer[m_offset++] = value[i]; diff --git a/AK/ByteBuffer.h b/AK/ByteBuffer.h index c472e94022..1f866ed5e5 100644 --- a/AK/ByteBuffer.h +++ b/AK/ByteBuffer.h @@ -100,12 +100,12 @@ public: return *this; } - static ByteBuffer create_uninitialized(ssize_t size) { return ByteBuffer(ByteBufferImpl::create_uninitialized(size)); } - static ByteBuffer create_zeroed(ssize_t size) { return ByteBuffer(ByteBufferImpl::create_zeroed(size)); } - static ByteBuffer copy(const void* data, ssize_t size) { return ByteBuffer(ByteBufferImpl::copy(data, size)); } - static ByteBuffer wrap(const void* data, ssize_t size) { return ByteBuffer(ByteBufferImpl::wrap(data, size)); } - static ByteBuffer wrap(void* data, ssize_t size) { return ByteBuffer(ByteBufferImpl::wrap(data, size)); } - static ByteBuffer adopt(void* data, ssize_t size) { return ByteBuffer(ByteBufferImpl::adopt(data, size)); } + static ByteBuffer create_uninitialized(int size) { return ByteBuffer(ByteBufferImpl::create_uninitialized(size)); } + static ByteBuffer create_zeroed(int size) { return ByteBuffer(ByteBufferImpl::create_zeroed(size)); } + static ByteBuffer copy(const void* data, int size) { return ByteBuffer(ByteBufferImpl::copy(data, size)); } + static ByteBuffer wrap(const void* data, int size) { return ByteBuffer(ByteBufferImpl::wrap(data, size)); } + static ByteBuffer wrap(void* data, int size) { return ByteBuffer(ByteBufferImpl::wrap(data, size)); } + static ByteBuffer adopt(void* data, int size) { return ByteBuffer(ByteBufferImpl::adopt(data, size)); } ~ByteBuffer() { clear(); } void clear() { m_impl = nullptr; } @@ -114,18 +114,18 @@ public: bool operator!() const { return is_null(); } bool is_null() const { return m_impl == nullptr; } - byte& operator[](ssize_t i) + byte& operator[](int i) { ASSERT(m_impl); return (*m_impl)[i]; } - byte operator[](ssize_t i) const + byte operator[](int i) const { ASSERT(m_impl); return (*m_impl)[i]; } bool is_empty() const { return !m_impl || m_impl->is_empty(); } - ssize_t size() const { return m_impl ? m_impl->size() : 0; } + int size() const { return m_impl ? m_impl->size() : 0; } byte* data() { return pointer(); } const byte* data() const { return pointer(); } @@ -133,8 +133,8 @@ public: byte* pointer() { return m_impl ? m_impl->pointer() : nullptr; } const byte* pointer() const { return m_impl ? m_impl->pointer() : nullptr; } - byte* offset_pointer(ssize_t offset) { return m_impl ? m_impl->offset_pointer(offset) : nullptr; } - const byte* offset_pointer(ssize_t offset) const { return m_impl ? m_impl->offset_pointer(offset) : nullptr; } + byte* offset_pointer(int offset) { return m_impl ? m_impl->offset_pointer(offset) : nullptr; } + const byte* offset_pointer(int offset) const { return m_impl ? m_impl->offset_pointer(offset) : nullptr; } void* end_pointer() { return m_impl ? m_impl->end_pointer() : nullptr; } const void* end_pointer() const { return m_impl ? m_impl->end_pointer() : nullptr; } @@ -147,13 +147,13 @@ public: } // NOTE: trim() does not reallocate. - void trim(ssize_t size) + void trim(int size) { if (m_impl) m_impl->trim(size); } - ByteBuffer slice(ssize_t offset, ssize_t size) const + ByteBuffer slice(int offset, int size) const { if (is_null()) return {}; @@ -164,7 +164,7 @@ public: return copy(offset_pointer(offset), size); } - void grow(ssize_t size) + void grow(int size) { if (!m_impl) m_impl = ByteBufferImpl::create_uninitialized(size); @@ -204,7 +204,7 @@ inline ByteBufferImpl::ByteBufferImpl(const void* data, int size, ConstructionMo m_owned = true; } -inline ByteBufferImpl::ByteBufferImpl(void* data, ssize_t size, ConstructionMode mode) +inline ByteBufferImpl::ByteBufferImpl(void* data, int size, ConstructionMode mode) : m_data(static_cast(data)) , m_size(size) { @@ -215,7 +215,7 @@ inline ByteBufferImpl::ByteBufferImpl(void* data, ssize_t size, ConstructionMode } } -inline void ByteBufferImpl::grow(ssize_t size) +inline void ByteBufferImpl::grow(int size) { ASSERT(size > m_size); ASSERT(m_owned); diff --git a/AK/ELF/ELFImage.cpp b/AK/ELF/ELFImage.cpp index c39c59bc2e..02a1dba42c 100644 --- a/AK/ELF/ELFImage.cpp +++ b/AK/ELF/ELFImage.cpp @@ -14,12 +14,18 @@ ELFImage::~ELFImage() static const char* object_file_type_to_string(Elf32_Half type) { switch (type) { - case ET_NONE: return "None"; - case ET_REL: return "Relocatable"; - case ET_EXEC: return "Executable"; - case ET_DYN: return "Shared object"; - case ET_CORE: return "Core"; - default: return "(?)"; + case ET_NONE: + return "None"; + case ET_REL: + return "Relocatable"; + case ET_EXEC: + return "Executable"; + case ET_DYN: + return "Shared object"; + case ET_CORE: + return "Core"; + default: + return "(?)"; } } diff --git a/AK/ELF/ELFImage.h b/AK/ELF/ELFImage.h index c3e6e779ee..6f0eee52ec 100644 --- a/AK/ELF/ELFImage.h +++ b/AK/ELF/ELFImage.h @@ -1,9 +1,9 @@ #pragma once -#include -#include #include #include +#include +#include class ELFImage { public: @@ -27,7 +27,7 @@ public: { } - ~Symbol() { } + ~Symbol() {} const char* name() const { return m_image.table_string(m_sym.st_name); } unsigned section_index() const { return m_sym.st_shndx; } @@ -51,13 +51,13 @@ public: , m_program_header_index(program_header_index) { } - ~ProgramHeader() { } + ~ProgramHeader() {} unsigned index() const { return m_program_header_index; } dword type() const { return m_program_header.p_type; } dword flags() const { return m_program_header.p_flags; } dword offset() const { return m_program_header.p_offset; } - LinearAddress laddr() const { return LinearAddress(m_program_header.p_vaddr); } + VirtualAddress vaddr() const { return VirtualAddress(m_program_header.p_vaddr); } dword size_in_memory() const { return m_program_header.p_memsz; } dword size_in_image() const { return m_program_header.p_filesz; } dword alignment() const { return m_program_header.p_align; } @@ -65,6 +65,7 @@ public: bool is_writable() const { return flags() & PF_W; } bool is_executable() const { return flags() & PF_X; } const char* raw_data() const { return m_image.raw_data(m_program_header.p_offset); } + private: const ELFImage& m_image; const Elf32_Phdr& m_program_header; @@ -79,7 +80,7 @@ public: , m_section_index(sectionIndex) { } - ~Section() { } + ~Section() {} const char* name() const { return m_image.section_header_table_string(m_section_header.sh_name); } unsigned type() const { return m_section_header.sh_type; } @@ -109,15 +110,19 @@ public: const Section section(unsigned) const; const ProgramHeader program_header(unsigned const) const; - template void for_each_section(F) const; - template void for_each_section_of_type(unsigned, F) const; - template void for_each_symbol(F) const; - template void for_each_program_header(F) const; + template + void for_each_section(F) const; + template + void for_each_section_of_type(unsigned, F) const; + template + void for_each_symbol(F) const; + template + void for_each_program_header(F) const; bool is_executable() const { return header().e_type == ET_EXEC; } bool is_relocatable() const { return header().e_type == ET_REL; } - LinearAddress entry() const { return LinearAddress(header().e_entry); } + VirtualAddress entry() const { return VirtualAddress(header().e_entry); } private: bool parse_header(); @@ -158,7 +163,7 @@ template inline void ELFImage::for_each_symbol(F func) const { for (unsigned i = 0; i < symbol_count(); ++i) { - if (func(symbol(i)) == IterationDecision::Abort) + if (func(symbol(i)) == IterationDecision::Break) break; } } diff --git a/AK/ELF/ELFLoader.cpp b/AK/ELF/ELFLoader.cpp index cd65954272..895108b90c 100644 --- a/AK/ELF/ELFLoader.cpp +++ b/AK/ELF/ELFLoader.cpp @@ -1,6 +1,6 @@ #include "ELFLoader.h" -#include #include +#include //#define ELFLOADER_DEBUG @@ -30,33 +30,31 @@ bool ELFLoader::load() bool ELFLoader::layout() { bool failed = false; - m_image.for_each_program_header([&] (const ELFImage::ProgramHeader& program_header) { + m_image.for_each_program_header([&](const ELFImage::ProgramHeader& program_header) { if (program_header.type() != PT_LOAD) return; #ifdef ELFLOADER_DEBUG - kprintf("PH: L%x %u r:%u w:%u\n", program_header.laddr().get(), program_header.size_in_memory(), program_header.is_readable(), program_header.is_writable()); + kprintf("PH: L%x %u r:%u w:%u\n", program_header.vaddr().get(), program_header.size_in_memory(), program_header.is_readable(), program_header.is_writable()); #endif if (program_header.is_writable()) { alloc_section_hook( - program_header.laddr(), + program_header.vaddr(), program_header.size_in_memory(), program_header.alignment(), program_header.is_readable(), program_header.is_writable(), - String::format("elf-alloc-%s%s", program_header.is_readable() ? "r" : "", program_header.is_writable() ? "w" : "") - ); - memcpy(program_header.laddr().as_ptr(), program_header.raw_data(), program_header.size_in_image()); + String::format("elf-alloc-%s%s", program_header.is_readable() ? "r" : "", program_header.is_writable() ? "w" : "")); + memcpy(program_header.vaddr().as_ptr(), program_header.raw_data(), program_header.size_in_image()); } else { map_section_hook( - program_header.laddr(), + program_header.vaddr(), program_header.size_in_memory(), program_header.alignment(), program_header.offset(), program_header.is_readable(), program_header.is_writable(), program_header.is_executable(), - String::format("elf-map-%s%s%s", program_header.is_readable() ? "r" : "", program_header.is_writable() ? "w" : "", program_header.is_executable() ? "x" : "") - ); + String::format("elf-map-%s%s%s", program_header.is_readable() ? "r" : "", program_header.is_writable() ? "w" : "", program_header.is_executable() ? "x" : "")); } }); return !failed; @@ -65,7 +63,7 @@ bool ELFLoader::layout() char* ELFLoader::symbol_ptr(const char* name) { char* found_ptr = nullptr; - m_image.for_each_symbol([&] (const ELFImage::Symbol symbol) { + m_image.for_each_symbol([&](const ELFImage::Symbol symbol) { if (symbol.type() != STT_FUNC) return IterationDecision::Continue; if (strcmp(symbol.name(), name)) @@ -74,7 +72,7 @@ char* ELFLoader::symbol_ptr(const char* name) found_ptr = (char*)symbol.value(); else ASSERT_NOT_REACHED(); - return IterationDecision::Abort; + return IterationDecision::Break; }); return found_ptr; } @@ -83,11 +81,11 @@ String ELFLoader::symbolicate(dword address) const { if (m_sorted_symbols.is_empty()) { m_sorted_symbols.ensure_capacity(m_image.symbol_count()); - m_image.for_each_symbol([this] (auto& symbol) { + m_image.for_each_symbol([this](auto& symbol) { m_sorted_symbols.append({ symbol.value(), symbol.name() }); return IterationDecision::Continue; }); - quick_sort(m_sorted_symbols.begin(), m_sorted_symbols.end(), [] (auto& a, auto& b) { + quick_sort(m_sorted_symbols.begin(), m_sorted_symbols.end(), [](auto& a, auto& b) { return a.address < b.address; }); } diff --git a/AK/ELF/ELFLoader.h b/AK/ELF/ELFLoader.h index be319425de..e3c3ab4098 100644 --- a/AK/ELF/ELFLoader.h +++ b/AK/ELF/ELFLoader.h @@ -5,7 +5,7 @@ #include #include #if defined(KERNEL) -#include +# include #endif #include @@ -16,9 +16,9 @@ public: bool load(); #if defined(KERNEL) - Function alloc_section_hook; - Function map_section_hook; - LinearAddress entry() const { return m_image.entry(); } + Function alloc_section_hook; + Function map_section_hook; + VirtualAddress entry() const { return m_image.entry(); } #endif char* symbol_ptr(const char* name); @@ -34,7 +34,7 @@ private: char* area_for_section_name(const char*); struct PtrAndSize { - PtrAndSize() { } + PtrAndSize() {} PtrAndSize(char* p, unsigned s) : ptr(p) , size(s) @@ -52,4 +52,3 @@ private: }; mutable Vector m_sorted_symbols; }; - diff --git a/AK/ELF/exec_elf.h b/AK/ELF/exec_elf.h index d7f8c59168..90dca3a6e3 100644 --- a/AK/ELF/exec_elf.h +++ b/AK/ELF/exec_elf.h @@ -35,390 +35,386 @@ #include -typedef uint8_t Elf_Byte; +typedef uint8_t Elf_Byte; -typedef uint32_t Elf32_Addr; /* Unsigned program address */ -typedef uint32_t Elf32_Off; /* Unsigned file offset */ -typedef int32_t Elf32_Sword; /* Signed large integer */ -typedef uint32_t Elf32_Word; /* Unsigned large integer */ -typedef uint16_t Elf32_Half; /* Unsigned medium integer */ -typedef uint64_t Elf32_Lword; +typedef uint32_t Elf32_Addr; /* Unsigned program address */ +typedef uint32_t Elf32_Off; /* Unsigned file offset */ +typedef int32_t Elf32_Sword; /* Signed large integer */ +typedef uint32_t Elf32_Word; /* Unsigned large integer */ +typedef uint16_t Elf32_Half; /* Unsigned medium integer */ +typedef uint64_t Elf32_Lword; -typedef uint64_t Elf64_Addr; -typedef uint64_t Elf64_Off; -typedef int32_t Elf64_Shalf; +typedef uint64_t Elf64_Addr; +typedef uint64_t Elf64_Off; +typedef int32_t Elf64_Shalf; #ifdef __alpha__ -typedef int64_t Elf64_Sword; -typedef uint64_t Elf64_Word; +typedef int64_t Elf64_Sword; +typedef uint64_t Elf64_Word; #else -typedef int32_t Elf64_Sword; -typedef uint32_t Elf64_Word; +typedef int32_t Elf64_Sword; +typedef uint32_t Elf64_Word; #endif -typedef int64_t Elf64_Sxword; -typedef uint64_t Elf64_Xword; -typedef uint64_t Elf64_Lword; +typedef int64_t Elf64_Sxword; +typedef uint64_t Elf64_Xword; +typedef uint64_t Elf64_Lword; -typedef uint32_t Elf64_Half; -typedef uint16_t Elf64_Quarter; +typedef uint32_t Elf64_Half; +typedef uint16_t Elf64_Quarter; /* * e_ident[] identification indexes * See http://www.sco.com/developers/gabi/latest/ch4.eheader.html */ -#define EI_MAG0 0 /* file ID */ -#define EI_MAG1 1 /* file ID */ -#define EI_MAG2 2 /* file ID */ -#define EI_MAG3 3 /* file ID */ -#define EI_CLASS 4 /* file class */ -#define EI_DATA 5 /* data encoding */ -#define EI_VERSION 6 /* ELF header version */ -#define EI_OSABI 7 /* OS/ABI ID */ -#define EI_ABIVERSION 8 /* ABI version */ -#define EI_PAD 9 /* start of pad bytes */ -#define EI_NIDENT 16 /* Size of e_ident[] */ +#define EI_MAG0 0 /* file ID */ +#define EI_MAG1 1 /* file ID */ +#define EI_MAG2 2 /* file ID */ +#define EI_MAG3 3 /* file ID */ +#define EI_CLASS 4 /* file class */ +#define EI_DATA 5 /* data encoding */ +#define EI_VERSION 6 /* ELF header version */ +#define EI_OSABI 7 /* OS/ABI ID */ +#define EI_ABIVERSION 8 /* ABI version */ +#define EI_PAD 9 /* start of pad bytes */ +#define EI_NIDENT 16 /* Size of e_ident[] */ /* e_ident[] magic number */ -#define ELFMAG0 0x7f /* e_ident[EI_MAG0] */ -#define ELFMAG1 'E' /* e_ident[EI_MAG1] */ -#define ELFMAG2 'L' /* e_ident[EI_MAG2] */ -#define ELFMAG3 'F' /* e_ident[EI_MAG3] */ -#define ELFMAG "\177ELF" /* magic */ -#define SELFMAG 4 /* size of magic */ +#define ELFMAG0 0x7f /* e_ident[EI_MAG0] */ +#define ELFMAG1 'E' /* e_ident[EI_MAG1] */ +#define ELFMAG2 'L' /* e_ident[EI_MAG2] */ +#define ELFMAG3 'F' /* e_ident[EI_MAG3] */ +#define ELFMAG "\177ELF" /* magic */ +#define SELFMAG 4 /* size of magic */ /* e_ident[] file class */ -#define ELFCLASSNONE 0 /* invalid */ -#define ELFCLASS32 1 /* 32-bit objs */ -#define ELFCLASS64 2 /* 64-bit objs */ -#define ELFCLASSNUM 3 /* number of classes */ +#define ELFCLASSNONE 0 /* invalid */ +#define ELFCLASS32 1 /* 32-bit objs */ +#define ELFCLASS64 2 /* 64-bit objs */ +#define ELFCLASSNUM 3 /* number of classes */ /* e_ident[] data encoding */ -#define ELFDATANONE 0 /* invalid */ -#define ELFDATA2LSB 1 /* Little-Endian */ -#define ELFDATA2MSB 2 /* Big-Endian */ -#define ELFDATANUM 3 /* number of data encode defines */ +#define ELFDATANONE 0 /* invalid */ +#define ELFDATA2LSB 1 /* Little-Endian */ +#define ELFDATA2MSB 2 /* Big-Endian */ +#define ELFDATANUM 3 /* number of data encode defines */ /* e_ident[] Operating System/ABI */ -#define ELFOSABI_SYSV 0 /* UNIX System V ABI */ -#define ELFOSABI_HPUX 1 /* HP-UX operating system */ -#define ELFOSABI_NETBSD 2 /* NetBSD */ -#define ELFOSABI_LINUX 3 /* GNU/Linux */ -#define ELFOSABI_HURD 4 /* GNU/Hurd */ -#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */ -#define ELFOSABI_SOLARIS 6 /* Solaris */ -#define ELFOSABI_MONTEREY 7 /* Monterey */ -#define ELFOSABI_IRIX 8 /* IRIX */ -#define ELFOSABI_FREEBSD 9 /* FreeBSD */ -#define ELFOSABI_TRU64 10 /* TRU64 UNIX */ -#define ELFOSABI_MODESTO 11 /* Novell Modesto */ -#define ELFOSABI_OPENBSD 12 /* OpenBSD */ -#define ELFOSABI_ARM 97 /* ARM */ -#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ +#define ELFOSABI_SYSV 0 /* UNIX System V ABI */ +#define ELFOSABI_HPUX 1 /* HP-UX operating system */ +#define ELFOSABI_NETBSD 2 /* NetBSD */ +#define ELFOSABI_LINUX 3 /* GNU/Linux */ +#define ELFOSABI_HURD 4 /* GNU/Hurd */ +#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */ +#define ELFOSABI_SOLARIS 6 /* Solaris */ +#define ELFOSABI_MONTEREY 7 /* Monterey */ +#define ELFOSABI_IRIX 8 /* IRIX */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD */ +#define ELFOSABI_TRU64 10 /* TRU64 UNIX */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ /* e_ident */ -#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ - (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ - (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \ - (ehdr).e_ident[EI_MAG3] == ELFMAG3) +#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && (ehdr).e_ident[EI_MAG1] == ELFMAG1 && (ehdr).e_ident[EI_MAG2] == ELFMAG2 && (ehdr).e_ident[EI_MAG3] == ELFMAG3) /* ELF Header */ typedef struct elfhdr { - unsigned char e_ident[EI_NIDENT]; /* ELF Identification */ - Elf32_Half e_type; /* object file type */ - Elf32_Half e_machine; /* machine */ - Elf32_Word e_version; /* object file version */ - Elf32_Addr e_entry; /* virtual entry point */ - Elf32_Off e_phoff; /* program header table offset */ - Elf32_Off e_shoff; /* section header table offset */ - Elf32_Word e_flags; /* processor-specific flags */ - Elf32_Half e_ehsize; /* ELF header size */ - Elf32_Half e_phentsize; /* program header entry size */ - Elf32_Half e_phnum; /* number of program header entries */ - Elf32_Half e_shentsize; /* section header entry size */ - Elf32_Half e_shnum; /* number of section header entries */ - Elf32_Half e_shstrndx; /* section header table's "section + unsigned char e_ident[EI_NIDENT]; /* ELF Identification */ + Elf32_Half e_type; /* object file type */ + Elf32_Half e_machine; /* machine */ + Elf32_Word e_version; /* object file version */ + Elf32_Addr e_entry; /* virtual entry point */ + Elf32_Off e_phoff; /* program header table offset */ + Elf32_Off e_shoff; /* section header table offset */ + Elf32_Word e_flags; /* processor-specific flags */ + Elf32_Half e_ehsize; /* ELF header size */ + Elf32_Half e_phentsize; /* program header entry size */ + Elf32_Half e_phnum; /* number of program header entries */ + Elf32_Half e_shentsize; /* section header entry size */ + Elf32_Half e_shnum; /* number of section header entries */ + Elf32_Half e_shstrndx; /* section header table's "section header string table" entry offset */ } Elf32_Ehdr; typedef struct { - unsigned char e_ident[EI_NIDENT]; /* Id bytes */ - Elf64_Quarter e_type; /* file type */ - Elf64_Quarter e_machine; /* machine type */ - Elf64_Half e_version; /* version number */ - Elf64_Addr e_entry; /* entry point */ - Elf64_Off e_phoff; /* Program hdr offset */ - Elf64_Off e_shoff; /* Section hdr offset */ - Elf64_Half e_flags; /* Processor flags */ - Elf64_Quarter e_ehsize; /* sizeof ehdr */ - Elf64_Quarter e_phentsize; /* Program header entry size */ - Elf64_Quarter e_phnum; /* Number of program headers */ - Elf64_Quarter e_shentsize; /* Section header entry size */ - Elf64_Quarter e_shnum; /* Number of section headers */ - Elf64_Quarter e_shstrndx; /* String table index */ + unsigned char e_ident[EI_NIDENT]; /* Id bytes */ + Elf64_Quarter e_type; /* file type */ + Elf64_Quarter e_machine; /* machine type */ + Elf64_Half e_version; /* version number */ + Elf64_Addr e_entry; /* entry point */ + Elf64_Off e_phoff; /* Program hdr offset */ + Elf64_Off e_shoff; /* Section hdr offset */ + Elf64_Half e_flags; /* Processor flags */ + Elf64_Quarter e_ehsize; /* sizeof ehdr */ + Elf64_Quarter e_phentsize; /* Program header entry size */ + Elf64_Quarter e_phnum; /* Number of program headers */ + Elf64_Quarter e_shentsize; /* Section header entry size */ + Elf64_Quarter e_shnum; /* Number of section headers */ + Elf64_Quarter e_shstrndx; /* String table index */ } Elf64_Ehdr; /* e_type */ -#define ET_NONE 0 /* No file type */ -#define ET_REL 1 /* relocatable file */ -#define ET_EXEC 2 /* executable file */ -#define ET_DYN 3 /* shared object file */ -#define ET_CORE 4 /* core file */ -#define ET_NUM 5 /* number of types */ -#define ET_LOPROC 0xff00 /* reserved range for processor */ -#define ET_HIPROC 0xffff /* specific e_type */ +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* relocatable file */ +#define ET_EXEC 2 /* executable file */ +#define ET_DYN 3 /* shared object file */ +#define ET_CORE 4 /* core file */ +#define ET_NUM 5 /* number of types */ +#define ET_LOPROC 0xff00 /* reserved range for processor */ +#define ET_HIPROC 0xffff /* specific e_type */ /* e_machine */ -#define EM_NONE 0 /* No Machine */ -#define EM_M32 1 /* AT&T WE 32100 */ -#define EM_SPARC 2 /* SPARC */ -#define EM_386 3 /* Intel 80386 */ -#define EM_68K 4 /* Motorola 68000 */ -#define EM_88K 5 /* Motorola 88000 */ -#define EM_486 6 /* Intel 80486 - unused? */ -#define EM_860 7 /* Intel 80860 */ -#define EM_MIPS 8 /* MIPS R3000 Big-Endian only */ +#define EM_NONE 0 /* No Machine */ +#define EM_M32 1 /* AT&T WE 32100 */ +#define EM_SPARC 2 /* SPARC */ +#define EM_386 3 /* Intel 80386 */ +#define EM_68K 4 /* Motorola 68000 */ +#define EM_88K 5 /* Motorola 88000 */ +#define EM_486 6 /* Intel 80486 - unused? */ +#define EM_860 7 /* Intel 80860 */ +#define EM_MIPS 8 /* MIPS R3000 Big-Endian only */ /* * Don't know if EM_MIPS_RS4_BE, * EM_SPARC64, EM_PARISC, * or EM_PPC are ABI compliant */ -#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ -#define EM_SPARC64 11 /* SPARC v9 64-bit unofficial */ -#define EM_PARISC 15 /* HPPA */ -#define EM_SPARC32PLUS 18 /* Enhanced instruction set SPARC */ -#define EM_PPC 20 /* PowerPC */ -#define EM_PPC64 21 /* PowerPC 64 */ -#define EM_ARM 40 /* Advanced RISC Machines ARM */ -#define EM_ALPHA 41 /* DEC ALPHA */ -#define EM_SH 42 /* Hitachi/Renesas Super-H */ -#define EM_SPARCV9 43 /* SPARC version 9 */ -#define EM_IA_64 50 /* Intel IA-64 Processor */ -#define EM_AMD64 62 /* AMD64 architecture */ -#define EM_X86_64 EM_AMD64 -#define EM_VAX 75 /* DEC VAX */ -#define EM_AARCH64 183 /* ARM 64-bit architecture (AArch64) */ +#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ +#define EM_SPARC64 11 /* SPARC v9 64-bit unofficial */ +#define EM_PARISC 15 /* HPPA */ +#define EM_SPARC32PLUS 18 /* Enhanced instruction set SPARC */ +#define EM_PPC 20 /* PowerPC */ +#define EM_PPC64 21 /* PowerPC 64 */ +#define EM_ARM 40 /* Advanced RISC Machines ARM */ +#define EM_ALPHA 41 /* DEC ALPHA */ +#define EM_SH 42 /* Hitachi/Renesas Super-H */ +#define EM_SPARCV9 43 /* SPARC version 9 */ +#define EM_IA_64 50 /* Intel IA-64 Processor */ +#define EM_AMD64 62 /* AMD64 architecture */ +#define EM_X86_64 EM_AMD64 +#define EM_VAX 75 /* DEC VAX */ +#define EM_AARCH64 183 /* ARM 64-bit architecture (AArch64) */ /* Non-standard */ -#define EM_ALPHA_EXP 0x9026 /* DEC ALPHA */ -#define EM__LAST__ (EM_ALPHA_EXP + 1) +#define EM_ALPHA_EXP 0x9026 /* DEC ALPHA */ +#define EM__LAST__ (EM_ALPHA_EXP + 1) -#define EM_NUM 22 /* number of machine types */ +#define EM_NUM 22 /* number of machine types */ /* Version */ -#define EV_NONE 0 /* Invalid */ -#define EV_CURRENT 1 /* Current */ -#define EV_NUM 2 /* number of versions */ +#define EV_NONE 0 /* Invalid */ +#define EV_CURRENT 1 /* Current */ +#define EV_NUM 2 /* number of versions */ /* Magic for e_phnum: get real value from sh_info of first section header */ -#define PN_XNUM 0xffff +#define PN_XNUM 0xffff /* Section Header */ typedef struct { - Elf32_Word sh_name; /* name - index into section header + Elf32_Word sh_name; /* name - index into section header string table section */ - Elf32_Word sh_type; /* type */ - Elf32_Word sh_flags; /* flags */ - Elf32_Addr sh_addr; /* address */ - Elf32_Off sh_offset; /* file offset */ - Elf32_Word sh_size; /* section size */ - Elf32_Word sh_link; /* section header table index link */ - Elf32_Word sh_info; /* extra information */ - Elf32_Word sh_addralign; /* address alignment */ - Elf32_Word sh_entsize; /* section entry size */ + Elf32_Word sh_type; /* type */ + Elf32_Word sh_flags; /* flags */ + Elf32_Addr sh_addr; /* address */ + Elf32_Off sh_offset; /* file offset */ + Elf32_Word sh_size; /* section size */ + Elf32_Word sh_link; /* section header table index link */ + Elf32_Word sh_info; /* extra information */ + Elf32_Word sh_addralign; /* address alignment */ + Elf32_Word sh_entsize; /* section entry size */ } Elf32_Shdr; typedef struct { - Elf64_Half sh_name; /* section name */ - Elf64_Half sh_type; /* section type */ - Elf64_Xword sh_flags; /* section flags */ - Elf64_Addr sh_addr; /* virtual address */ - Elf64_Off sh_offset; /* file offset */ - Elf64_Xword sh_size; /* section size */ - Elf64_Half sh_link; /* link to another */ - Elf64_Half sh_info; /* misc info */ - Elf64_Xword sh_addralign; /* memory alignment */ - Elf64_Xword sh_entsize; /* table entry size */ + Elf64_Half sh_name; /* section name */ + Elf64_Half sh_type; /* section type */ + Elf64_Xword sh_flags; /* section flags */ + Elf64_Addr sh_addr; /* virtual address */ + Elf64_Off sh_offset; /* file offset */ + Elf64_Xword sh_size; /* section size */ + Elf64_Half sh_link; /* link to another */ + Elf64_Half sh_info; /* misc info */ + Elf64_Xword sh_addralign; /* memory alignment */ + Elf64_Xword sh_entsize; /* table entry size */ } Elf64_Shdr; /* Special Section Indexes */ -#define SHN_UNDEF 0 /* undefined */ -#define SHN_LORESERVE 0xff00 /* lower bounds of reserved indexes */ -#define SHN_LOPROC 0xff00 /* reserved range for processor */ -#define SHN_HIPROC 0xff1f /* specific section indexes */ -#define SHN_ABS 0xfff1 /* absolute value */ -#define SHN_COMMON 0xfff2 /* common symbol */ -#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */ -#define SHN_HIRESERVE 0xffff /* upper bounds of reserved indexes */ +#define SHN_UNDEF 0 /* undefined */ +#define SHN_LORESERVE 0xff00 /* lower bounds of reserved indexes */ +#define SHN_LOPROC 0xff00 /* reserved range for processor */ +#define SHN_HIPROC 0xff1f /* specific section indexes */ +#define SHN_ABS 0xfff1 /* absolute value */ +#define SHN_COMMON 0xfff2 /* common symbol */ +#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */ +#define SHN_HIRESERVE 0xffff /* upper bounds of reserved indexes */ /* sh_type */ -#define SHT_NULL 0 /* inactive */ -#define SHT_PROGBITS 1 /* program defined information */ -#define SHT_SYMTAB 2 /* symbol table section */ -#define SHT_STRTAB 3 /* string table section */ -#define SHT_RELA 4 /* relocation section with addends*/ -#define SHT_HASH 5 /* symbol hash table section */ -#define SHT_DYNAMIC 6 /* dynamic section */ -#define SHT_NOTE 7 /* note section */ -#define SHT_NOBITS 8 /* no space section */ -#define SHT_REL 9 /* relation section without addends */ -#define SHT_SHLIB 10 /* reserved - purpose unknown */ -#define SHT_DYNSYM 11 /* dynamic symbol table section */ -#define SHT_NUM 12 /* number of section types */ -#define SHT_INIT_ARRAY 14 /* pointers to init functions */ -#define SHT_FINI_ARRAY 15 /* pointers to termination functions */ -#define SHT_PREINIT_ARRAY 16 /* ptrs to funcs called before init */ -#define SHT_GROUP 17 /* defines a section group */ -#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */ -#define SHT_LOOS 0x60000000 /* reserved range for OS specific */ -#define SHT_SUNW_dof 0x6ffffff4 /* used by dtrace */ -#define SHT_GNU_LIBLIST 0x6ffffff7 /* libraries to be prelinked */ -#define SHT_SUNW_move 0x6ffffffa /* inf for partially init'ed symbols */ -#define SHT_SUNW_syminfo 0x6ffffffc /* ad symbol information */ -#define SHT_SUNW_verdef 0x6ffffffd /* symbol versioning inf */ -#define SHT_SUNW_verneed 0x6ffffffe /* symbol versioning req */ -#define SHT_SUNW_versym 0x6fffffff /* symbol versioning table */ -#define SHT_HIOS 0x6fffffff /* section header types */ -#define SHT_LOPROC 0x70000000 /* reserved range for processor */ -#define SHT_HIPROC 0x7fffffff /* specific section header types */ -#define SHT_LOUSER 0x80000000 /* reserved range for application */ -#define SHT_HIUSER 0xffffffff /* specific indexes */ +#define SHT_NULL 0 /* inactive */ +#define SHT_PROGBITS 1 /* program defined information */ +#define SHT_SYMTAB 2 /* symbol table section */ +#define SHT_STRTAB 3 /* string table section */ +#define SHT_RELA 4 /* relocation section with addends*/ +#define SHT_HASH 5 /* symbol hash table section */ +#define SHT_DYNAMIC 6 /* dynamic section */ +#define SHT_NOTE 7 /* note section */ +#define SHT_NOBITS 8 /* no space section */ +#define SHT_REL 9 /* relation section without addends */ +#define SHT_SHLIB 10 /* reserved - purpose unknown */ +#define SHT_DYNSYM 11 /* dynamic symbol table section */ +#define SHT_NUM 12 /* number of section types */ +#define SHT_INIT_ARRAY 14 /* pointers to init functions */ +#define SHT_FINI_ARRAY 15 /* pointers to termination functions */ +#define SHT_PREINIT_ARRAY 16 /* ptrs to funcs called before init */ +#define SHT_GROUP 17 /* defines a section group */ +#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */ +#define SHT_LOOS 0x60000000 /* reserved range for OS specific */ +#define SHT_SUNW_dof 0x6ffffff4 /* used by dtrace */ +#define SHT_GNU_LIBLIST 0x6ffffff7 /* libraries to be prelinked */ +#define SHT_SUNW_move 0x6ffffffa /* inf for partially init'ed symbols */ +#define SHT_SUNW_syminfo 0x6ffffffc /* ad symbol information */ +#define SHT_SUNW_verdef 0x6ffffffd /* symbol versioning inf */ +#define SHT_SUNW_verneed 0x6ffffffe /* symbol versioning req */ +#define SHT_SUNW_versym 0x6fffffff /* symbol versioning table */ +#define SHT_HIOS 0x6fffffff /* section header types */ +#define SHT_LOPROC 0x70000000 /* reserved range for processor */ +#define SHT_HIPROC 0x7fffffff /* specific section header types */ +#define SHT_LOUSER 0x80000000 /* reserved range for application */ +#define SHT_HIUSER 0xffffffff /* specific indexes */ -#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table section */ +#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table section */ /* Section names */ -#define ELF_BSS ".bss" /* uninitialized data */ -#define ELF_DATA ".data" /* initialized data */ -#define ELF_CTF ".SUNW_ctf" /* CTF data */ -#define ELF_DEBUG ".debug" /* debug */ -#define ELF_DYNAMIC ".dynamic" /* dynamic linking information */ -#define ELF_DYNSTR ".dynstr" /* dynamic string table */ -#define ELF_DYNSYM ".dynsym" /* dynamic symbol table */ -#define ELF_FINI ".fini" /* termination code */ -#define ELF_GOT ".got" /* global offset table */ -#define ELF_HASH ".hash" /* symbol hash table */ -#define ELF_INIT ".init" /* initialization code */ -#define ELF_REL_DATA ".rel.data" /* relocation data */ -#define ELF_REL_FINI ".rel.fini" /* relocation termination code */ -#define ELF_REL_INIT ".rel.init" /* relocation initialization code */ -#define ELF_REL_DYN ".rel.dyn" /* relocation dynamic link info */ -#define ELF_REL_RODATA ".rel.rodata" /* relocation read-only data */ -#define ELF_REL_TEXT ".rel.text" /* relocation code */ -#define ELF_RODATA ".rodata" /* read-only data */ -#define ELF_SHSTRTAB ".shstrtab" /* section header string table */ -#define ELF_STRTAB ".strtab" /* string table */ -#define ELF_SYMTAB ".symtab" /* symbol table */ -#define ELF_TEXT ".text" /* code */ +#define ELF_BSS ".bss" /* uninitialized data */ +#define ELF_DATA ".data" /* initialized data */ +#define ELF_CTF ".SUNW_ctf" /* CTF data */ +#define ELF_DEBUG ".debug" /* debug */ +#define ELF_DYNAMIC ".dynamic" /* dynamic linking information */ +#define ELF_DYNSTR ".dynstr" /* dynamic string table */ +#define ELF_DYNSYM ".dynsym" /* dynamic symbol table */ +#define ELF_FINI ".fini" /* termination code */ +#define ELF_GOT ".got" /* global offset table */ +#define ELF_HASH ".hash" /* symbol hash table */ +#define ELF_INIT ".init" /* initialization code */ +#define ELF_REL_DATA ".rel.data" /* relocation data */ +#define ELF_REL_FINI ".rel.fini" /* relocation termination code */ +#define ELF_REL_INIT ".rel.init" /* relocation initialization code */ +#define ELF_REL_DYN ".rel.dyn" /* relocation dynamic link info */ +#define ELF_REL_RODATA ".rel.rodata" /* relocation read-only data */ +#define ELF_REL_TEXT ".rel.text" /* relocation code */ +#define ELF_RODATA ".rodata" /* read-only data */ +#define ELF_SHSTRTAB ".shstrtab" /* section header string table */ +#define ELF_STRTAB ".strtab" /* string table */ +#define ELF_SYMTAB ".symtab" /* symbol table */ +#define ELF_TEXT ".text" /* code */ #define ELF_OPENBSDRANDOMDATA ".openbsd.randomdata" /* constant randomdata */ - /* Section Attribute Flags - sh_flags */ -#define SHF_WRITE 0x1 /* Writable */ -#define SHF_ALLOC 0x2 /* occupies memory */ -#define SHF_EXECINSTR 0x4 /* executable */ -#define SHF_MERGE 0x10 /* may be merged */ -#define SHF_STRINGS 0x20 /* contains strings */ -#define SHF_INFO_LINK 0x40 /* sh_info holds section index */ -#define SHF_LINK_ORDER 0x80 /* ordering requirements */ -#define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required */ -#define SHF_GROUP 0x200 /* member of section group */ -#define SHF_TLS 0x400 /* thread local storage */ -#define SHF_COMPRESSED 0x800 /* contains compressed data */ -#define SHF_MASKOS 0x0ff00000 /* OS-specific semantics */ -#define SHF_MASKPROC 0xf0000000 /* reserved bits for processor */ - /* specific section attributes */ +#define SHF_WRITE 0x1 /* Writable */ +#define SHF_ALLOC 0x2 /* occupies memory */ +#define SHF_EXECINSTR 0x4 /* executable */ +#define SHF_MERGE 0x10 /* may be merged */ +#define SHF_STRINGS 0x20 /* contains strings */ +#define SHF_INFO_LINK 0x40 /* sh_info holds section index */ +#define SHF_LINK_ORDER 0x80 /* ordering requirements */ +#define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required */ +#define SHF_GROUP 0x200 /* member of section group */ +#define SHF_TLS 0x400 /* thread local storage */ +#define SHF_COMPRESSED 0x800 /* contains compressed data */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific semantics */ +#define SHF_MASKPROC 0xf0000000 /* reserved bits for processor */ + /* specific section attributes */ /* Symbol Table Entry */ typedef struct elf32_sym { - Elf32_Word st_name; /* name - index into string table */ - Elf32_Addr st_value; /* symbol value */ - Elf32_Word st_size; /* symbol size */ - unsigned char st_info; /* type and binding */ - unsigned char st_other; /* 0 - no defined meaning */ - Elf32_Half st_shndx; /* section header index */ + Elf32_Word st_name; /* name - index into string table */ + Elf32_Addr st_value; /* symbol value */ + Elf32_Word st_size; /* symbol size */ + unsigned char st_info; /* type and binding */ + unsigned char st_other; /* 0 - no defined meaning */ + Elf32_Half st_shndx; /* section header index */ } Elf32_Sym; typedef struct { - Elf64_Half st_name; /* Symbol name index in str table */ - Elf_Byte st_info; /* type / binding attrs */ - Elf_Byte st_other; /* unused */ - Elf64_Quarter st_shndx; /* section index of symbol */ - Elf64_Xword st_value; /* value of symbol */ - Elf64_Xword st_size; /* size of symbol */ + Elf64_Half st_name; /* Symbol name index in str table */ + Elf_Byte st_info; /* type / binding attrs */ + Elf_Byte st_other; /* unused */ + Elf64_Quarter st_shndx; /* section index of symbol */ + Elf64_Xword st_value; /* value of symbol */ + Elf64_Xword st_size; /* size of symbol */ } Elf64_Sym; /* Symbol table index */ -#define STN_UNDEF 0 /* undefined */ +#define STN_UNDEF 0 /* undefined */ /* Extract symbol info - st_info */ -#define ELF32_ST_BIND(x) ((x) >> 4) -#define ELF32_ST_TYPE(x) (((unsigned int) x) & 0xf) -#define ELF32_ST_INFO(b,t) (((b) << 4) + ((t) & 0xf)) +#define ELF32_ST_BIND(x) ((x) >> 4) +#define ELF32_ST_TYPE(x) (((unsigned int)x) & 0xf) +#define ELF32_ST_INFO(b, t) (((b) << 4) + ((t)&0xf)) -#define ELF64_ST_BIND(x) ((x) >> 4) -#define ELF64_ST_TYPE(x) (((unsigned int) x) & 0xf) -#define ELF64_ST_INFO(b,t) (((b) << 4) + ((t) & 0xf)) +#define ELF64_ST_BIND(x) ((x) >> 4) +#define ELF64_ST_TYPE(x) (((unsigned int)x) & 0xf) +#define ELF64_ST_INFO(b, t) (((b) << 4) + ((t)&0xf)) /* Symbol Binding - ELF32_ST_BIND - st_info */ -#define STB_LOCAL 0 /* Local symbol */ -#define STB_GLOBAL 1 /* Global symbol */ -#define STB_WEAK 2 /* like global - lower precedence */ -#define STB_NUM 3 /* number of symbol bindings */ -#define STB_LOPROC 13 /* reserved range for processor */ -#define STB_HIPROC 15 /* specific symbol bindings */ +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* like global - lower precedence */ +#define STB_NUM 3 /* number of symbol bindings */ +#define STB_LOPROC 13 /* reserved range for processor */ +#define STB_HIPROC 15 /* specific symbol bindings */ /* Symbol type - ELF32_ST_TYPE - st_info */ -#define STT_NOTYPE 0 /* not specified */ -#define STT_OBJECT 1 /* data object */ -#define STT_FUNC 2 /* function */ -#define STT_SECTION 3 /* section */ -#define STT_FILE 4 /* file */ -#define STT_TLS 6 /* thread local storage */ -#define STT_LOPROC 13 /* reserved range for processor */ -#define STT_HIPROC 15 /* specific symbol types */ +#define STT_NOTYPE 0 /* not specified */ +#define STT_OBJECT 1 /* data object */ +#define STT_FUNC 2 /* function */ +#define STT_SECTION 3 /* section */ +#define STT_FILE 4 /* file */ +#define STT_TLS 6 /* thread local storage */ +#define STT_LOPROC 13 /* reserved range for processor */ +#define STT_HIPROC 15 /* specific symbol types */ /* Extract symbol visibility - st_other */ -#define ELF_ST_VISIBILITY(v) ((v) & 0x3) -#define ELF32_ST_VISIBILITY ELF_ST_VISIBILITY -#define ELF64_ST_VISIBILITY ELF_ST_VISIBILITY +#define ELF_ST_VISIBILITY(v) ((v)&0x3) +#define ELF32_ST_VISIBILITY ELF_ST_VISIBILITY +#define ELF64_ST_VISIBILITY ELF_ST_VISIBILITY -#define STV_DEFAULT 0 /* Visibility set by binding type */ -#define STV_INTERNAL 1 /* OS specific version of STV_HIDDEN */ -#define STV_HIDDEN 2 /* can only be seen inside own .so */ -#define STV_PROTECTED 3 /* HIDDEN inside, DEFAULT outside */ +#define STV_DEFAULT 0 /* Visibility set by binding type */ +#define STV_INTERNAL 1 /* OS specific version of STV_HIDDEN */ +#define STV_HIDDEN 2 /* can only be seen inside own .so */ +#define STV_PROTECTED 3 /* HIDDEN inside, DEFAULT outside */ /* Relocation entry with implicit addend */ typedef struct { - Elf32_Addr r_offset; /* offset of relocation */ - Elf32_Word r_info; /* symbol table index and type */ + Elf32_Addr r_offset; /* offset of relocation */ + Elf32_Word r_info; /* symbol table index and type */ } Elf32_Rel; /* Relocation entry with explicit addend */ typedef struct { - Elf32_Addr r_offset; /* offset of relocation */ - Elf32_Word r_info; /* symbol table index and type */ - Elf32_Sword r_addend; + Elf32_Addr r_offset; /* offset of relocation */ + Elf32_Word r_info; /* symbol table index and type */ + Elf32_Sword r_addend; } Elf32_Rela; /* Extract relocation info - r_info */ -#define ELF32_R_SYM(i) ((i) >> 8) -#define ELF32_R_TYPE(i) ((unsigned char) (i)) -#define ELF32_R_INFO(s,t) (((s) << 8) + (unsigned char)(t)) +#define ELF32_R_SYM(i) ((i) >> 8) +#define ELF32_R_TYPE(i) ((unsigned char)(i)) +#define ELF32_R_INFO(s, t) (((s) << 8) + (unsigned char)(t)) typedef struct { - Elf64_Xword r_offset; /* where to do it */ - Elf64_Xword r_info; /* index & type of relocation */ + Elf64_Xword r_offset; /* where to do it */ + Elf64_Xword r_info; /* index & type of relocation */ } Elf64_Rel; typedef struct { - Elf64_Xword r_offset; /* where to do it */ - Elf64_Xword r_info; /* index & type of relocation */ - Elf64_Sxword r_addend; /* adjustment value */ + Elf64_Xword r_offset; /* where to do it */ + Elf64_Xword r_info; /* index & type of relocation */ + Elf64_Sxword r_addend; /* adjustment value */ } Elf64_Rela; -#define ELF64_R_SYM(info) ((info) >> 32) -#define ELF64_R_TYPE(info) ((info) & 0xFFFFFFFF) -#define ELF64_R_INFO(s,t) (((s) << 32) + (uint32_t)(t)) +#define ELF64_R_SYM(info) ((info) >> 32) +#define ELF64_R_TYPE(info) ((info)&0xFFFFFFFF) +#define ELF64_R_INFO(s, t) (((s) << 32) + (uint32_t)(t)) #if defined(__mips64__) && defined(__MIPSEL__) /* @@ -426,186 +422,186 @@ typedef struct { * than the regular ELF ABI: the r_info field is split into several * pieces (see gnu/usr.bin/binutils-2.17/include/elf/mips.h for details). */ -#undef ELF64_R_SYM -#undef ELF64_R_TYPE -#undef ELF64_R_INFO -#define ELF64_R_TYPE(info) ((uint64_t)swap32((info) >> 32)) -#define ELF64_R_SYM(info) ((info) & 0xFFFFFFFF) -#define ELF64_R_INFO(s,t) (((uint64_t)swap32(t) << 32) + (uint32_t)(s)) -#endif /* __mips64__ && __MIPSEL__ */ +# undef ELF64_R_SYM +# undef ELF64_R_TYPE +# undef ELF64_R_INFO +# define ELF64_R_TYPE(info) ((uint64_t)swap32((info) >> 32)) +# define ELF64_R_SYM(info) ((info)&0xFFFFFFFF) +# define ELF64_R_INFO(s, t) (((uint64_t)swap32(t) << 32) + (uint32_t)(s)) +#endif /* __mips64__ && __MIPSEL__ */ /* Program Header */ typedef struct { - Elf32_Word p_type; /* segment type */ - Elf32_Off p_offset; /* segment offset */ - Elf32_Addr p_vaddr; /* virtual address of segment */ - Elf32_Addr p_paddr; /* physical address - ignored? */ - Elf32_Word p_filesz; /* number of bytes in file for seg. */ - Elf32_Word p_memsz; /* number of bytes in mem. for seg. */ - Elf32_Word p_flags; /* flags */ - Elf32_Word p_align; /* memory alignment */ + Elf32_Word p_type; /* segment type */ + Elf32_Off p_offset; /* segment offset */ + Elf32_Addr p_vaddr; /* virtual address of segment */ + Elf32_Addr p_paddr; /* physical address - ignored? */ + Elf32_Word p_filesz; /* number of bytes in file for seg. */ + Elf32_Word p_memsz; /* number of bytes in mem. for seg. */ + Elf32_Word p_flags; /* flags */ + Elf32_Word p_align; /* memory alignment */ } Elf32_Phdr; typedef struct { - Elf64_Half p_type; /* entry type */ - Elf64_Half p_flags; /* flags */ - Elf64_Off p_offset; /* offset */ - Elf64_Addr p_vaddr; /* virtual address */ - Elf64_Addr p_paddr; /* physical address */ - Elf64_Xword p_filesz; /* file size */ - Elf64_Xword p_memsz; /* memory size */ - Elf64_Xword p_align; /* memory & file alignment */ + Elf64_Half p_type; /* entry type */ + Elf64_Half p_flags; /* flags */ + Elf64_Off p_offset; /* offset */ + Elf64_Addr p_vaddr; /* virtual address */ + Elf64_Addr p_paddr; /* physical address */ + Elf64_Xword p_filesz; /* file size */ + Elf64_Xword p_memsz; /* memory size */ + Elf64_Xword p_align; /* memory & file alignment */ } Elf64_Phdr; /* Segment types - p_type */ -#define PT_NULL 0 /* unused */ -#define PT_LOAD 1 /* loadable segment */ -#define PT_DYNAMIC 2 /* dynamic linking section */ -#define PT_INTERP 3 /* the RTLD */ -#define PT_NOTE 4 /* auxiliary information */ -#define PT_SHLIB 5 /* reserved - purpose undefined */ -#define PT_PHDR 6 /* program header */ -#define PT_TLS 7 /* thread local storage */ -#define PT_LOOS 0x60000000 /* reserved range for OS */ -#define PT_HIOS 0x6fffffff /* specific segment types */ -#define PT_LOPROC 0x70000000 /* reserved range for processor */ -#define PT_HIPROC 0x7fffffff /* specific segment types */ +#define PT_NULL 0 /* unused */ +#define PT_LOAD 1 /* loadable segment */ +#define PT_DYNAMIC 2 /* dynamic linking section */ +#define PT_INTERP 3 /* the RTLD */ +#define PT_NOTE 4 /* auxiliary information */ +#define PT_SHLIB 5 /* reserved - purpose undefined */ +#define PT_PHDR 6 /* program header */ +#define PT_TLS 7 /* thread local storage */ +#define PT_LOOS 0x60000000 /* reserved range for OS */ +#define PT_HIOS 0x6fffffff /* specific segment types */ +#define PT_LOPROC 0x70000000 /* reserved range for processor */ +#define PT_HIPROC 0x7fffffff /* specific segment types */ -#define PT_GNU_EH_FRAME 0x6474e550 /* Exception handling info */ -#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ +#define PT_GNU_EH_FRAME 0x6474e550 /* Exception handling info */ +#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ -#define PT_OPENBSD_RANDOMIZE 0x65a3dbe6 /* fill with random data */ -#define PT_OPENBSD_WXNEEDED 0x65a3dbe7 /* program performs W^X violations */ -#define PT_OPENBSD_BOOTDATA 0x65a41be6 /* section for boot arguments */ +#define PT_OPENBSD_RANDOMIZE 0x65a3dbe6 /* fill with random data */ +#define PT_OPENBSD_WXNEEDED 0x65a3dbe7 /* program performs W^X violations */ +#define PT_OPENBSD_BOOTDATA 0x65a41be6 /* section for boot arguments */ /* Segment flags - p_flags */ -#define PF_X 0x1 /* Executable */ -#define PF_W 0x2 /* Writable */ -#define PF_R 0x4 /* Readable */ -#define PF_MASKPROC 0xf0000000 /* reserved bits for processor */ - /* specific segment flags */ +#define PF_X 0x1 /* Executable */ +#define PF_W 0x2 /* Writable */ +#define PF_R 0x4 /* Readable */ +#define PF_MASKPROC 0xf0000000 /* reserved bits for processor */ + /* specific segment flags */ /* Dynamic structure */ typedef struct { - Elf32_Sword d_tag; /* controls meaning of d_val */ - union { - Elf32_Word d_val; /* Multiple meanings - see d_tag */ - Elf32_Addr d_ptr; /* program virtual address */ - } d_un; + Elf32_Sword d_tag; /* controls meaning of d_val */ + union { + Elf32_Word d_val; /* Multiple meanings - see d_tag */ + Elf32_Addr d_ptr; /* program virtual address */ + } d_un; } Elf32_Dyn; typedef struct { - Elf64_Xword d_tag; /* controls meaning of d_val */ - union { - Elf64_Addr d_ptr; - Elf64_Xword d_val; - } d_un; + Elf64_Xword d_tag; /* controls meaning of d_val */ + union { + Elf64_Addr d_ptr; + Elf64_Xword d_val; + } d_un; } Elf64_Dyn; /* Dynamic Array Tags - d_tag */ -#define DT_NULL 0 /* marks end of _DYNAMIC array */ -#define DT_NEEDED 1 /* string table offset of needed lib */ -#define DT_PLTRELSZ 2 /* size of relocation entries in PLT */ -#define DT_PLTGOT 3 /* address PLT/GOT */ -#define DT_HASH 4 /* address of symbol hash table */ -#define DT_STRTAB 5 /* address of string table */ -#define DT_SYMTAB 6 /* address of symbol table */ -#define DT_RELA 7 /* address of relocation table */ -#define DT_RELASZ 8 /* size of relocation table */ -#define DT_RELAENT 9 /* size of relocation entry */ -#define DT_STRSZ 10 /* size of string table */ -#define DT_SYMENT 11 /* size of symbol table entry */ -#define DT_INIT 12 /* address of initialization func. */ -#define DT_FINI 13 /* address of termination function */ -#define DT_SONAME 14 /* string table offset of shared obj */ -#define DT_RPATH 15 /* string table offset of library - search path */ -#define DT_SYMBOLIC 16 /* start sym search in shared obj. */ -#define DT_REL 17 /* address of rel. tbl. w addends */ -#define DT_RELSZ 18 /* size of DT_REL relocation table */ -#define DT_RELENT 19 /* size of DT_REL relocation entry */ -#define DT_PLTREL 20 /* PLT referenced relocation entry */ -#define DT_DEBUG 21 /* bugger */ -#define DT_TEXTREL 22 /* Allow rel. mod. to unwritable seg */ -#define DT_JMPREL 23 /* add. of PLT's relocation entries */ -#define DT_BIND_NOW 24 /* Bind now regardless of env setting */ -#define DT_INIT_ARRAY 25 /* address of array of init func */ -#define DT_FINI_ARRAY 26 /* address of array of term func */ -#define DT_INIT_ARRAYSZ 27 /* size of array of init func */ -#define DT_FINI_ARRAYSZ 28 /* size of array of term func */ -#define DT_RUNPATH 29 /* strtab offset of lib search path */ -#define DT_FLAGS 30 /* Set of DF_* flags */ -#define DT_ENCODING 31 /* further DT_* follow encoding rules */ -#define DT_PREINIT_ARRAY 32 /* address of array of preinit func */ -#define DT_PREINIT_ARRAYSZ 33 /* size of array of preinit func */ -#define DT_LOOS 0x6000000d /* reserved range for OS */ -#define DT_HIOS 0x6ffff000 /* specific dynamic array tags */ -#define DT_LOPROC 0x70000000 /* reserved range for processor */ -#define DT_HIPROC 0x7fffffff /* specific dynamic array tags */ +#define DT_NULL 0 /* marks end of _DYNAMIC array */ +#define DT_NEEDED 1 /* string table offset of needed lib */ +#define DT_PLTRELSZ 2 /* size of relocation entries in PLT */ +#define DT_PLTGOT 3 /* address PLT/GOT */ +#define DT_HASH 4 /* address of symbol hash table */ +#define DT_STRTAB 5 /* address of string table */ +#define DT_SYMTAB 6 /* address of symbol table */ +#define DT_RELA 7 /* address of relocation table */ +#define DT_RELASZ 8 /* size of relocation table */ +#define DT_RELAENT 9 /* size of relocation entry */ +#define DT_STRSZ 10 /* size of string table */ +#define DT_SYMENT 11 /* size of symbol table entry */ +#define DT_INIT 12 /* address of initialization func. */ +#define DT_FINI 13 /* address of termination function */ +#define DT_SONAME 14 /* string table offset of shared obj */ +#define DT_RPATH 15 /* string table offset of library \ + search path */ +#define DT_SYMBOLIC 16 /* start sym search in shared obj. */ +#define DT_REL 17 /* address of rel. tbl. w addends */ +#define DT_RELSZ 18 /* size of DT_REL relocation table */ +#define DT_RELENT 19 /* size of DT_REL relocation entry */ +#define DT_PLTREL 20 /* PLT referenced relocation entry */ +#define DT_DEBUG 21 /* bugger */ +#define DT_TEXTREL 22 /* Allow rel. mod. to unwritable seg */ +#define DT_JMPREL 23 /* add. of PLT's relocation entries */ +#define DT_BIND_NOW 24 /* Bind now regardless of env setting */ +#define DT_INIT_ARRAY 25 /* address of array of init func */ +#define DT_FINI_ARRAY 26 /* address of array of term func */ +#define DT_INIT_ARRAYSZ 27 /* size of array of init func */ +#define DT_FINI_ARRAYSZ 28 /* size of array of term func */ +#define DT_RUNPATH 29 /* strtab offset of lib search path */ +#define DT_FLAGS 30 /* Set of DF_* flags */ +#define DT_ENCODING 31 /* further DT_* follow encoding rules */ +#define DT_PREINIT_ARRAY 32 /* address of array of preinit func */ +#define DT_PREINIT_ARRAYSZ 33 /* size of array of preinit func */ +#define DT_LOOS 0x6000000d /* reserved range for OS */ +#define DT_HIOS 0x6ffff000 /* specific dynamic array tags */ +#define DT_LOPROC 0x70000000 /* reserved range for processor */ +#define DT_HIPROC 0x7fffffff /* specific dynamic array tags */ /* some other useful tags */ -#define DT_GNU_HASH 0x6ffffef5 /* address of GNU hash table */ -#define DT_RELACOUNT 0x6ffffff9 /* if present, number of RELATIVE */ -#define DT_RELCOUNT 0x6ffffffa /* relocs, which must come first */ -#define DT_FLAGS_1 0x6ffffffb +#define DT_GNU_HASH 0x6ffffef5 /* address of GNU hash table */ +#define DT_RELACOUNT 0x6ffffff9 /* if present, number of RELATIVE */ +#define DT_RELCOUNT 0x6ffffffa /* relocs, which must come first */ +#define DT_FLAGS_1 0x6ffffffb /* Dynamic Flags - DT_FLAGS .dynamic entry */ -#define DF_ORIGIN 0x00000001 -#define DF_SYMBOLIC 0x00000002 -#define DF_TEXTREL 0x00000004 -#define DF_BIND_NOW 0x00000008 -#define DF_STATIC_TLS 0x00000010 +#define DF_ORIGIN 0x00000001 +#define DF_SYMBOLIC 0x00000002 +#define DF_TEXTREL 0x00000004 +#define DF_BIND_NOW 0x00000008 +#define DF_STATIC_TLS 0x00000010 /* Dynamic Flags - DT_FLAGS_1 .dynamic entry */ -#define DF_1_NOW 0x00000001 -#define DF_1_GLOBAL 0x00000002 -#define DF_1_GROUP 0x00000004 -#define DF_1_NODELETE 0x00000008 -#define DF_1_LOADFLTR 0x00000010 -#define DF_1_INITFIRST 0x00000020 -#define DF_1_NOOPEN 0x00000040 -#define DF_1_ORIGIN 0x00000080 -#define DF_1_DIRECT 0x00000100 -#define DF_1_TRANS 0x00000200 -#define DF_1_INTERPOSE 0x00000400 -#define DF_1_NODEFLIB 0x00000800 -#define DF_1_NODUMP 0x00001000 -#define DF_1_CONLFAT 0x00002000 +#define DF_1_NOW 0x00000001 +#define DF_1_GLOBAL 0x00000002 +#define DF_1_GROUP 0x00000004 +#define DF_1_NODELETE 0x00000008 +#define DF_1_LOADFLTR 0x00000010 +#define DF_1_INITFIRST 0x00000020 +#define DF_1_NOOPEN 0x00000040 +#define DF_1_ORIGIN 0x00000080 +#define DF_1_DIRECT 0x00000100 +#define DF_1_TRANS 0x00000200 +#define DF_1_INTERPOSE 0x00000400 +#define DF_1_NODEFLIB 0x00000800 +#define DF_1_NODUMP 0x00001000 +#define DF_1_CONLFAT 0x00002000 /* * Note header */ typedef struct { - Elf32_Word n_namesz; - Elf32_Word n_descsz; - Elf32_Word n_type; + Elf32_Word n_namesz; + Elf32_Word n_descsz; + Elf32_Word n_type; } Elf32_Nhdr; typedef struct { - Elf64_Half n_namesz; - Elf64_Half n_descsz; - Elf64_Half n_type; + Elf64_Half n_namesz; + Elf64_Half n_descsz; + Elf64_Half n_type; } Elf64_Nhdr; /* * Note Definitions */ typedef struct { - Elf32_Word namesz; - Elf32_Word descsz; - Elf32_Word type; + Elf32_Word namesz; + Elf32_Word descsz; + Elf32_Word type; } Elf32_Note; typedef struct { - Elf64_Half namesz; - Elf64_Half descsz; - Elf64_Half type; + Elf64_Half namesz; + Elf64_Half descsz; + Elf64_Half type; } Elf64_Note; /* Values for n_type. */ -#define NT_PRSTATUS 1 /* Process status. */ -#define NT_FPREGSET 2 /* Floating point registers. */ -#define NT_PRPSINFO 3 /* Process state info. */ +#define NT_PRSTATUS 1 /* Process status. */ +#define NT_FPREGSET 2 /* Floating point registers. */ +#define NT_PRPSINFO 3 /* Process state info. */ /* * OpenBSD-specific core file information. @@ -633,36 +629,36 @@ typedef struct { * bump the version. */ -#define NT_OPENBSD_PROCINFO 10 -#define NT_OPENBSD_AUXV 11 +#define NT_OPENBSD_PROCINFO 10 +#define NT_OPENBSD_AUXV 11 -#define NT_OPENBSD_REGS 20 -#define NT_OPENBSD_FPREGS 21 -#define NT_OPENBSD_XFPREGS 22 -#define NT_OPENBSD_WCOOKIE 23 +#define NT_OPENBSD_REGS 20 +#define NT_OPENBSD_FPREGS 21 +#define NT_OPENBSD_XFPREGS 22 +#define NT_OPENBSD_WCOOKIE 23 struct elfcore_procinfo { - /* Version 1 fields start here. */ - uint32_t cpi_version; /* netbsd_elfcore_procinfo version */ -#define ELFCORE_PROCINFO_VERSION 1 - uint32_t cpi_cpisize; /* sizeof(netbsd_elfcore_procinfo) */ - uint32_t cpi_signo; /* killing signal */ - uint32_t cpi_sigcode; /* signal code */ - uint32_t cpi_sigpend; /* pending signals */ - uint32_t cpi_sigmask; /* blocked signals */ - uint32_t cpi_sigignore; /* ignored signals */ - uint32_t cpi_sigcatch; /* signals being caught by user */ - int32_t cpi_pid; /* process ID */ - int32_t cpi_ppid; /* parent process ID */ - int32_t cpi_pgrp; /* process group ID */ - int32_t cpi_sid; /* session ID */ - uint32_t cpi_ruid; /* real user ID */ - uint32_t cpi_euid; /* effective user ID */ - uint32_t cpi_svuid; /* saved user ID */ - uint32_t cpi_rgid; /* real group ID */ - uint32_t cpi_egid; /* effective group ID */ - uint32_t cpi_svgid; /* saved group ID */ - int8_t cpi_name[32]; /* copy of pr->ps_comm */ + /* Version 1 fields start here. */ + uint32_t cpi_version; /* netbsd_elfcore_procinfo version */ +#define ELFCORE_PROCINFO_VERSION 1 + uint32_t cpi_cpisize; /* sizeof(netbsd_elfcore_procinfo) */ + uint32_t cpi_signo; /* killing signal */ + uint32_t cpi_sigcode; /* signal code */ + uint32_t cpi_sigpend; /* pending signals */ + uint32_t cpi_sigmask; /* blocked signals */ + uint32_t cpi_sigignore; /* ignored signals */ + uint32_t cpi_sigcatch; /* signals being caught by user */ + int32_t cpi_pid; /* process ID */ + int32_t cpi_ppid; /* parent process ID */ + int32_t cpi_pgrp; /* process group ID */ + int32_t cpi_sid; /* session ID */ + uint32_t cpi_ruid; /* real user ID */ + uint32_t cpi_euid; /* effective user ID */ + uint32_t cpi_svuid; /* saved user ID */ + uint32_t cpi_rgid; /* real group ID */ + uint32_t cpi_egid; /* effective group ID */ + uint32_t cpi_svgid; /* saved group ID */ + int8_t cpi_name[32]; /* copy of pr->ps_comm */ }; /* @@ -670,113 +666,113 @@ struct elfcore_procinfo { */ #if defined(_KERNEL) || defined(_DYN_LOADER) -#define ELF32_NO_ADDR ((uint32_t) ~0) /* Indicates addr. not yet filled in */ +# define ELF32_NO_ADDR ((uint32_t)~0) /* Indicates addr. not yet filled in */ typedef struct { - Elf32_Sword au_id; /* 32-bit id */ - Elf32_Word au_v; /* 32-bit value */ + Elf32_Sword au_id; /* 32-bit id */ + Elf32_Word au_v; /* 32-bit value */ } Aux32Info; -#define ELF64_NO_ADDR ((uint64_t) ~0)/* Indicates addr. not yet filled in */ +# define ELF64_NO_ADDR ((uint64_t)~0) /* Indicates addr. not yet filled in */ typedef struct { - Elf64_Shalf au_id; /* 32-bit id */ - Elf64_Xword au_v; /* 64-bit value */ + Elf64_Shalf au_id; /* 32-bit id */ + Elf64_Xword au_v; /* 64-bit value */ } Aux64Info; enum AuxID { - AUX_null = 0, - AUX_ignore = 1, - AUX_execfd = 2, - AUX_phdr = 3, /* &phdr[0] */ - AUX_phent = 4, /* sizeof(phdr[0]) */ - AUX_phnum = 5, /* # phdr entries */ - AUX_pagesz = 6, /* PAGESIZE */ - AUX_base = 7, /* ld.so base addr */ - AUX_flags = 8, /* processor flags */ - AUX_entry = 9, /* a.out entry */ - AUX_sun_uid = 2000, /* euid */ - AUX_sun_ruid = 2001, /* ruid */ - AUX_sun_gid = 2002, /* egid */ - AUX_sun_rgid = 2003 /* rgid */ + AUX_null = 0, + AUX_ignore = 1, + AUX_execfd = 2, + AUX_phdr = 3, /* &phdr[0] */ + AUX_phent = 4, /* sizeof(phdr[0]) */ + AUX_phnum = 5, /* # phdr entries */ + AUX_pagesz = 6, /* PAGESIZE */ + AUX_base = 7, /* ld.so base addr */ + AUX_flags = 8, /* processor flags */ + AUX_entry = 9, /* a.out entry */ + AUX_sun_uid = 2000, /* euid */ + AUX_sun_ruid = 2001, /* ruid */ + AUX_sun_gid = 2002, /* egid */ + AUX_sun_rgid = 2003 /* rgid */ }; struct elf_args { - u_long arg_entry; /* program entry point */ - u_long arg_interp; /* Interpreter load address */ - u_long arg_phaddr; /* program header address */ - u_long arg_phentsize; /* Size of program header */ - u_long arg_phnum; /* Number of program headers */ + u_long arg_entry; /* program entry point */ + u_long arg_interp; /* Interpreter load address */ + u_long arg_phaddr; /* program header address */ + u_long arg_phentsize; /* Size of program header */ + u_long arg_phnum; /* Number of program headers */ }; #endif #if !defined(ELFSIZE) && defined(ARCH_ELFSIZE) -#define ELFSIZE ARCH_ELFSIZE +# define ELFSIZE ARCH_ELFSIZE #endif #if defined(ELFSIZE) -#define CONCAT(x,y) __CONCAT(x,y) -#define ELFNAME(x) CONCAT(elf,CONCAT(ELFSIZE,CONCAT(_,x))) -#define ELFDEFNNAME(x) CONCAT(ELF,CONCAT(ELFSIZE,CONCAT(_,x))) +# define CONCAT(x, y) __CONCAT(x, y) +# define ELFNAME(x) CONCAT(elf, CONCAT(ELFSIZE, CONCAT(_, x))) +# define ELFDEFNNAME(x) CONCAT(ELF, CONCAT(ELFSIZE, CONCAT(_, x))) #endif #if defined(ELFSIZE) && (ELFSIZE == 32) -#define Elf_Ehdr Elf32_Ehdr -#define Elf_Phdr Elf32_Phdr -#define Elf_Shdr Elf32_Shdr -#define Elf_Sym Elf32_Sym -#define Elf_Rel Elf32_Rel -#define Elf_RelA Elf32_Rela -#define Elf_Dyn Elf32_Dyn -#define Elf_Half Elf32_Half -#define Elf_Word Elf32_Word -#define Elf_Sword Elf32_Sword -#define Elf_Addr Elf32_Addr -#define Elf_Off Elf32_Off -#define Elf_Nhdr Elf32_Nhdr -#define Elf_Note Elf32_Note +# define Elf_Ehdr Elf32_Ehdr +# define Elf_Phdr Elf32_Phdr +# define Elf_Shdr Elf32_Shdr +# define Elf_Sym Elf32_Sym +# define Elf_Rel Elf32_Rel +# define Elf_RelA Elf32_Rela +# define Elf_Dyn Elf32_Dyn +# define Elf_Half Elf32_Half +# define Elf_Word Elf32_Word +# define Elf_Sword Elf32_Sword +# define Elf_Addr Elf32_Addr +# define Elf_Off Elf32_Off +# define Elf_Nhdr Elf32_Nhdr +# define Elf_Note Elf32_Note -#define ELF_R_SYM ELF32_R_SYM -#define ELF_R_TYPE ELF32_R_TYPE -#define ELF_R_INFO ELF32_R_INFO -#define ELFCLASS ELFCLASS32 +# define ELF_R_SYM ELF32_R_SYM +# define ELF_R_TYPE ELF32_R_TYPE +# define ELF_R_INFO ELF32_R_INFO +# define ELFCLASS ELFCLASS32 -#define ELF_ST_BIND ELF32_ST_BIND -#define ELF_ST_TYPE ELF32_ST_TYPE -#define ELF_ST_INFO ELF32_ST_INFO +# define ELF_ST_BIND ELF32_ST_BIND +# define ELF_ST_TYPE ELF32_ST_TYPE +# define ELF_ST_INFO ELF32_ST_INFO -#define ELF_NO_ADDR ELF32_NO_ADDR -#define AuxInfo Aux32Info +# define ELF_NO_ADDR ELF32_NO_ADDR +# define AuxInfo Aux32Info #elif defined(ELFSIZE) && (ELFSIZE == 64) -#define Elf_Ehdr Elf64_Ehdr -#define Elf_Phdr Elf64_Phdr -#define Elf_Shdr Elf64_Shdr -#define Elf_Sym Elf64_Sym -#define Elf_Rel Elf64_Rel -#define Elf_RelA Elf64_Rela -#define Elf_Dyn Elf64_Dyn -#define Elf_Half Elf64_Half -#define Elf_Word Elf64_Word -#define Elf_Sword Elf64_Sword -#define Elf_Addr Elf64_Addr -#define Elf_Off Elf64_Off -#define Elf_Nhdr Elf64_Nhdr -#define Elf_Note Elf64_Note +# define Elf_Ehdr Elf64_Ehdr +# define Elf_Phdr Elf64_Phdr +# define Elf_Shdr Elf64_Shdr +# define Elf_Sym Elf64_Sym +# define Elf_Rel Elf64_Rel +# define Elf_RelA Elf64_Rela +# define Elf_Dyn Elf64_Dyn +# define Elf_Half Elf64_Half +# define Elf_Word Elf64_Word +# define Elf_Sword Elf64_Sword +# define Elf_Addr Elf64_Addr +# define Elf_Off Elf64_Off +# define Elf_Nhdr Elf64_Nhdr +# define Elf_Note Elf64_Note -#define ELF_R_SYM ELF64_R_SYM -#define ELF_R_TYPE ELF64_R_TYPE -#define ELF_R_INFO ELF64_R_INFO -#define ELFCLASS ELFCLASS64 +# define ELF_R_SYM ELF64_R_SYM +# define ELF_R_TYPE ELF64_R_TYPE +# define ELF_R_INFO ELF64_R_INFO +# define ELFCLASS ELFCLASS64 -#define ELF_ST_BIND ELF64_ST_BIND -#define ELF_ST_TYPE ELF64_ST_TYPE -#define ELF_ST_INFO ELF64_ST_INFO +# define ELF_ST_BIND ELF64_ST_BIND +# define ELF_ST_TYPE ELF64_ST_TYPE +# define ELF_ST_INFO ELF64_ST_INFO -#define ELF_NO_ADDR ELF64_NO_ADDR -#define AuxInfo Aux64Info +# define ELF_NO_ADDR ELF64_NO_ADDR +# define AuxInfo Aux64Info #endif -#define ELF_TARG_VER 1 /* The ver for which this code is intended */ +#define ELF_TARG_VER 1 /* The ver for which this code is intended */ #endif /* _SYS_EXEC_ELF_H_ */ diff --git a/AK/FileSystemPath.cpp b/AK/FileSystemPath.cpp index 07d8d5ea82..fbef784160 100644 --- a/AK/FileSystemPath.cpp +++ b/AK/FileSystemPath.cpp @@ -5,7 +5,7 @@ namespace AK { -FileSystemPath::FileSystemPath(const String& s) +FileSystemPath::FileSystemPath(const StringView& s) : m_string(s) { m_is_valid = canonicalize(); diff --git a/AK/FileSystemPath.h b/AK/FileSystemPath.h index b62160a526..4e09386ed7 100644 --- a/AK/FileSystemPath.h +++ b/AK/FileSystemPath.h @@ -7,12 +7,12 @@ namespace AK { class FileSystemPath { public: FileSystemPath() {} - explicit FileSystemPath(const String&); + explicit FileSystemPath(const StringView&); bool is_valid() const { return m_is_valid; } - String string() const { return m_string; } + const String& string() const { return m_string; } - String basename() const { return m_basename; } + const String& basename() const { return m_basename; } const Vector& parts() const { return m_parts; } diff --git a/AK/IterationDecision.h b/AK/IterationDecision.h new file mode 100644 index 0000000000..26620ee438 --- /dev/null +++ b/AK/IterationDecision.h @@ -0,0 +1,12 @@ +#pragma once + +namespace AK { + +enum class IterationDecision { + Continue, + Break, +}; + +} + +using AK::IterationDecision; diff --git a/AK/MappedFile.cpp b/AK/MappedFile.cpp index b234fa19c6..87af44be9c 100644 --- a/AK/MappedFile.cpp +++ b/AK/MappedFile.cpp @@ -9,11 +9,10 @@ namespace AK { -MappedFile::MappedFile(const String& file_name) - : m_file_name(file_name) +MappedFile::MappedFile(const StringView& file_name) { m_size = PAGE_SIZE; - m_fd = open(m_file_name.characters(), O_RDONLY | O_CLOEXEC); + m_fd = open(file_name.characters(), O_RDONLY | O_CLOEXEC); if (m_fd != -1) { struct stat st; @@ -26,7 +25,7 @@ MappedFile::MappedFile(const String& file_name) } #ifdef DEBUG_MAPPED_FILE - dbgprintf("MappedFile{%s} := { m_fd=%d, m_size=%u, m_map=%p }\n", m_file_name.characters(), m_fd, m_size, m_map); + dbgprintf("MappedFile{%s} := { m_fd=%d, m_size=%u, m_map=%p }\n", file_name.characters(), m_fd, m_size, m_map); #endif } @@ -44,15 +43,13 @@ void MappedFile::unmap() ASSERT(rc == 0); rc = close(m_fd); ASSERT(rc == 0); - m_file_name = {}; m_size = 0; m_fd = -1; m_map = (void*)-1; } MappedFile::MappedFile(MappedFile&& other) - : m_file_name(move(other.m_file_name)) - , m_size(other.m_size) + : m_size(other.m_size) , m_fd(other.m_fd) , m_map(other.m_map) { @@ -66,7 +63,6 @@ MappedFile& MappedFile::operator=(MappedFile&& other) if (this == &other) return *this; unmap(); - swap(m_file_name, other.m_file_name); swap(m_size, other.m_size); swap(m_fd, other.m_fd); swap(m_map, other.m_map); diff --git a/AK/MappedFile.h b/AK/MappedFile.h index 513fd28e5e..82421e6e3d 100644 --- a/AK/MappedFile.h +++ b/AK/MappedFile.h @@ -1,13 +1,13 @@ #pragma once -#include "AKString.h" +#include "StringView.h" namespace AK { class MappedFile { public: MappedFile() {} - explicit MappedFile(const String& file_name); + explicit MappedFile(const StringView& file_name); MappedFile(MappedFile&&); ~MappedFile(); @@ -21,7 +21,6 @@ public: size_t size() const { return m_size; } private: - String m_file_name; size_t m_size { 0 }; int m_fd { -1 }; void* m_map { (void*)-1 }; diff --git a/AK/printf.cpp b/AK/PrintfImplementation.h similarity index 95% rename from AK/printf.cpp rename to AK/PrintfImplementation.h index 0b5ee149ad..087eb34d43 100644 --- a/AK/printf.cpp +++ b/AK/PrintfImplementation.h @@ -1,17 +1,15 @@ -typedef unsigned char byte; -typedef unsigned short word; -typedef unsigned int dword; -typedef long long unsigned int qword; +#pragma once -[[gnu::always_inline]] inline size_t strlen(const char* str) -{ - size_t len = 0; - while (*(str++)) - ++len; - return len; -} +#include +#include -static constexpr const char* h = "0123456789abcdef"; +static constexpr const char* printf_hex_digits = "0123456789abcdef"; + +#ifdef __serenity__ +extern "C" size_t strlen(const char*); +#else +#include +#endif template [[gnu::always_inline]] inline int print_hex(PutChFunc putch, char*& bufptr, T number, byte fields) @@ -20,7 +18,7 @@ template byte shr_count = fields * 4; while (shr_count) { shr_count -= 4; - putch(bufptr, h[(number >> shr_count) & 0x0F]); + putch(bufptr, printf_hex_digits[(number >> shr_count) & 0x0F]); ++ret; } return ret; @@ -180,7 +178,7 @@ template } template -[[gnu::always_inline]] inline int printf_internal(PutChFunc putch, char* buffer, const char*& fmt, char*& ap) +[[gnu::always_inline]] inline int printf_internal(PutChFunc putch, char* buffer, const char*& fmt, va_list ap) { const char* p; diff --git a/AK/Queue.h b/AK/Queue.h new file mode 100644 index 0000000000..b3ae8f024a --- /dev/null +++ b/AK/Queue.h @@ -0,0 +1,49 @@ +#pragma once + +#include +#include +#include + +namespace AK { + +template +class Queue { +public: + Queue() { } + ~Queue() { } + + int size() const { return m_size; } + bool is_empty() const { return m_size == 0; } + + void enqueue(T&& value) + { + if (m_segments.is_empty() || m_segments.last()->size() >= segment_size) + m_segments.append(make>()); + m_segments.last()->append(move(value)); + ++m_size; + } + + T dequeue() + { + ASSERT(!is_empty()); + auto value = move((*m_segments.first())[m_index_into_first++]); + if (m_index_into_first == segment_size) { + m_segments.take_first(); + m_index_into_first = 0; + } + --m_size; + return value; + } + +private: + static const int segment_size = 1000; + + SinglyLinkedList>> m_segments; + int m_index_into_first { 0 }; + int m_size { 0 }; +}; + +} + +using AK::Queue; + diff --git a/AK/QuickSort.h b/AK/QuickSort.h index 2d196d2977..71611ad7e3 100644 --- a/AK/QuickSort.h +++ b/AK/QuickSort.h @@ -1,5 +1,7 @@ #pragma once +#include + namespace AK { template diff --git a/AK/RetainPtr.h b/AK/RetainPtr.h index 0044202dee..f22b0d0f73 100644 --- a/AK/RetainPtr.h +++ b/AK/RetainPtr.h @@ -103,20 +103,41 @@ public: return *this; } - RetainPtr& operator=(T* ptr) + template + RetainPtr& operator=(const Retained& other) { - if (m_ptr != ptr) + if (m_ptr != other.ptr()) release_if_not_null(m_ptr); - m_ptr = ptr; + m_ptr = const_cast(other.ptr()); + ASSERT(m_ptr); retain_if_not_null(m_ptr); return *this; } - RetainPtr& operator=(T& object) + template + RetainPtr& operator=(const RetainPtr& other) + { + if (m_ptr != other.ptr()) + release_if_not_null(m_ptr); + m_ptr = const_cast(other.ptr()); + retain_if_not_null(m_ptr); + return *this; + } + + RetainPtr& operator=(const T* ptr) + { + if (m_ptr != ptr) + release_if_not_null(m_ptr); + m_ptr = const_cast(ptr); + retain_if_not_null(m_ptr); + return *this; + } + + RetainPtr& operator=(const T& object) { if (m_ptr != &object) release_if_not_null(m_ptr); - m_ptr = &object; + m_ptr = const_cast(&object); retain_if_not_null(m_ptr); return *this; } diff --git a/AK/Retained.h b/AK/Retained.h index e1aa22f8ec..a7938e0174 100644 --- a/AK/Retained.h +++ b/AK/Retained.h @@ -44,16 +44,10 @@ public: { m_ptr->retain(); } - RETURN_TYPESTATE(unconsumed) - Retained(T& object) - : m_ptr(&object) - { - m_ptr->retain(); - } template RETURN_TYPESTATE(unconsumed) - Retained(U& object) - : m_ptr(&static_cast(object)) + Retained(const U& object) + : m_ptr(&const_cast(static_cast(object))) { m_ptr->retain(); } @@ -200,6 +194,19 @@ public: return m_ptr; } + CALLABLE_WHEN(unconsumed) + operator T&() + { + ASSERT(m_ptr); + return *m_ptr; + } + CALLABLE_WHEN(unconsumed) + operator const T&() const + { + ASSERT(m_ptr); + return *m_ptr; + } + private: Retained() {} diff --git a/AK/ScopeGuard.h b/AK/ScopeGuard.h new file mode 100644 index 0000000000..44556e0ee6 --- /dev/null +++ b/AK/ScopeGuard.h @@ -0,0 +1,24 @@ +#pragma once + +namespace AK { + +template +class ScopeGuard { +public: + ScopeGuard(Callback callback) + : m_callback(move(callback)) + { + } + + ~ScopeGuard() + { + m_callback(); + } + +private: + Callback m_callback; +}; + +} + +using AK::ScopeGuard; diff --git a/AK/SinglyLinkedList.h b/AK/SinglyLinkedList.h index c14fe97b45..34e837c465 100644 --- a/AK/SinglyLinkedList.h +++ b/AK/SinglyLinkedList.h @@ -9,7 +9,7 @@ class SinglyLinkedList { private: struct Node { explicit Node(T&& v) - : value(v) + : value(move(v)) { } T value; @@ -66,7 +66,7 @@ public: { ASSERT(m_head); auto* prev_head = m_head; - T value = first(); + T value = move(first()); if (m_tail == m_head) m_tail = nullptr; m_head = m_head->next; diff --git a/AK/StdLibExtras.h b/AK/StdLibExtras.h index f233ab4219..2e132a5a1e 100644 --- a/AK/StdLibExtras.h +++ b/AK/StdLibExtras.h @@ -292,4 +292,5 @@ using AK::IsSame; using AK::max; using AK::min; using AK::move; +using AK::RemoveConst; using AK::swap; diff --git a/AK/String.cpp b/AK/String.cpp index 5ec6f355ee..fce8006e4d 100644 --- a/AK/String.cpp +++ b/AK/String.cpp @@ -1,7 +1,7 @@ #include "AKString.h" #include "StdLibExtras.h" #include "StringBuilder.h" -#include +#include namespace AK { @@ -68,22 +68,27 @@ StringView String::substring_view(int start, int length) const } Vector String::split(const char separator) const +{ + return split_limit(separator, 0); +} + +Vector String::split_limit(const char separator, int limit) const { if (is_empty()) return {}; Vector v; - ssize_t substart = 0; - for (ssize_t i = 0; i < length(); ++i) { + int substart = 0; + for (int i = 0; i < length() && (v.size() + 1) != limit; ++i) { char ch = characters()[i]; if (ch == separator) { - ssize_t sublen = i - substart; + int sublen = i - substart; if (sublen != 0) v.append(substring(substart, sublen)); substart = i + 1; } } - ssize_t taillen = length() - substart; + int taillen = length() - substart; if (taillen != 0) v.append(substring(substart, taillen)); if (characters()[length() - 1] == separator) @@ -97,21 +102,21 @@ Vector String::split_view(const char separator) const return {}; Vector v; - ssize_t substart = 0; - for (ssize_t i = 0; i < length(); ++i) { + int substart = 0; + for (int i = 0; i < length(); ++i) { char ch = characters()[i]; if (ch == separator) { - ssize_t sublen = i - substart; + int sublen = i - substart; if (sublen != 0) v.append(substring_view(substart, sublen)); substart = i + 1; } } - ssize_t taillen = length() - substart; + int taillen = length() - substart; if (taillen != 0) v.append(substring_view(substart, taillen)); if (characters()[length() - 1] == separator) - v.append(empty().view()); + v.append(empty()); return v; } @@ -126,7 +131,7 @@ int String::to_int(bool& ok) const { bool negative = false; int value = 0; - ssize_t i = 0; + int i = 0; if (is_null()) { ok = false; @@ -153,7 +158,7 @@ int String::to_int(bool& ok) const unsigned String::to_uint(bool& ok) const { unsigned value = 0; - for (ssize_t i = 0; i < length(); ++i) { + for (int i = 0; i < length(); ++i) { if (characters()[i] < '0' || characters()[i] > '9') { ok = false; return 0; @@ -175,7 +180,18 @@ String String::format(const char* fmt, ...) return builder.to_string(); } -bool String::ends_with(const String& str) const +bool String::starts_with(const StringView& str) const +{ + if (str.is_empty()) + return true; + if (is_empty()) + return false; + if (str.length() > length()) + return false; + return !memcmp(characters(), str.characters(), str.length()); +} + +bool String::ends_with(const StringView& str) const { if (str.is_empty()) return true; @@ -196,27 +212,28 @@ String String::repeated(char ch, int count) return *impl; } -bool String::matches(const String& mask, CaseSensitivity case_sensitivity) const +bool String::matches(const StringView& mask, CaseSensitivity case_sensitivity) const { if (case_sensitivity == CaseSensitivity::CaseInsensitive) { String this_lower = this->to_lowercase(); - String mask_lower = mask.to_lowercase(); + String mask_lower = String(mask).to_lowercase(); return this_lower.match_helper(mask_lower); } return match_helper(mask); } -bool String::match_helper(const String& mask) const +bool String::match_helper(const StringView& mask) const { - if (is_null() || mask.is_null()) + if (is_null()) return false; const char* string_ptr = characters(); const char* mask_ptr = mask.characters(); + const char* mask_end = mask_ptr + mask.length(); // Match string against mask directly unless we hit a * - while ((*string_ptr) && (*mask_ptr != '*')) { + while ((*string_ptr) && (mask_ptr < mask_end) && (*mask_ptr != '*')) { if ((*mask_ptr != *string_ptr) && (*mask_ptr != '?')) return false; mask_ptr++; @@ -227,27 +244,29 @@ bool String::match_helper(const String& mask) const const char* mp = nullptr; while (*string_ptr) { - if (*mask_ptr == '*') { + if ((mask_ptr < mask_end) && (*mask_ptr == '*')) { // If we have only a * left, there is no way to not match. - if (!*++mask_ptr) + if (++mask_ptr == mask_end) return true; mp = mask_ptr; cp = string_ptr + 1; - } else if ((*mask_ptr == *string_ptr) || (*mask_ptr == '?')) { + } else if ((mask_ptr < mask_end) && ((*mask_ptr == *string_ptr) || (*mask_ptr == '?'))) { mask_ptr++; string_ptr++; - } else { + } else if ((cp != nullptr) && (mp != nullptr)) { mask_ptr = mp; string_ptr = cp++; + } else { + break; } } // Handle any trailing mask - while (*mask_ptr == '*') + while ((mask_ptr < mask_end) && (*mask_ptr == '*')) mask_ptr++; - // If we 'ate' all of the mask then we match. - return !*mask_ptr; + // If we 'ate' all of the mask and the string then we match. + return (mask_ptr == mask_end) && !*string_ptr; } } diff --git a/AK/StringBuilder.cpp b/AK/StringBuilder.cpp index 0fe550242e..429bb5771b 100644 --- a/AK/StringBuilder.cpp +++ b/AK/StringBuilder.cpp @@ -1,22 +1,22 @@ -#include "StringBuilder.h" -#include "printf.cpp" +#include #include -#include +#include +#include namespace AK { -inline void StringBuilder::will_append(ssize_t size) +inline void StringBuilder::will_append(int size) { if ((m_length + size) > m_buffer.size()) - m_buffer.grow(max((ssize_t)16, m_buffer.size() * 2 + size)); + m_buffer.grow(max((int)16, m_buffer.size() * 2 + size)); } -StringBuilder::StringBuilder(ssize_t initial_capacity) +StringBuilder::StringBuilder(int initial_capacity) { m_buffer.grow(initial_capacity); } -void StringBuilder::append(const String& str) +void StringBuilder::append(const StringView& str) { if (str.is_empty()) return; @@ -25,7 +25,7 @@ void StringBuilder::append(const String& str) m_length += str.length(); } -void StringBuilder::append(const char* characters, ssize_t length) +void StringBuilder::append(const char* characters, int length) { if (!length) return; diff --git a/AK/StringBuilder.h b/AK/StringBuilder.h index 700540942a..744c71ef4b 100644 --- a/AK/StringBuilder.h +++ b/AK/StringBuilder.h @@ -2,18 +2,18 @@ #include "AKString.h" #include "Vector.h" -#include +#include namespace AK { class StringBuilder { public: - explicit StringBuilder(ssize_t initial_capacity = 16); + explicit StringBuilder(int initial_capacity = 16); ~StringBuilder() {} - void append(const String&); + void append(const StringView&); void append(char); - void append(const char*, ssize_t); + void append(const char*, int); void appendf(const char*, ...); void appendvf(const char*, va_list); @@ -21,10 +21,10 @@ public: ByteBuffer to_byte_buffer(); private: - void will_append(ssize_t); + void will_append(int); ByteBuffer m_buffer; - ssize_t m_length { 0 }; + int m_length { 0 }; }; } diff --git a/AK/StringImpl.cpp b/AK/StringImpl.cpp index 2799e237d6..0130cb90ba 100644 --- a/AK/StringImpl.cpp +++ b/AK/StringImpl.cpp @@ -3,6 +3,10 @@ #include "StdLibExtras.h" #include "kmalloc.h" +#ifndef __serenity__ +#include +#endif + //#define DEBUG_STRINGIMPL #ifdef DEBUG_STRINGIMPL diff --git a/AK/StringView.cpp b/AK/StringView.cpp index 77fc057c39..94cbf9d356 100644 --- a/AK/StringView.cpp +++ b/AK/StringView.cpp @@ -3,6 +3,13 @@ namespace AK { +StringView::StringView(const String& string) + : m_impl(string.impl()) + , m_characters(string.characters()) + , m_length(string.length()) +{ +} + Vector StringView::split_view(const char separator) const { if (is_empty()) @@ -23,7 +30,7 @@ Vector StringView::split_view(const char separator) const if (taillen != 0) v.append(substring_view(substart, taillen)); if (characters()[length() - 1] == separator) - v.append(String::empty().view()); + v.append(String::empty()); return v; } @@ -35,6 +42,24 @@ StringView StringView::substring_view(int start, int length) const return { m_characters + start, length }; } +StringView StringView::substring_view_starting_from_substring(const StringView& substring) const +{ + const char* remaining_characters = substring.characters(); + ASSERT(remaining_characters >= m_characters); + ASSERT(remaining_characters <= m_characters + m_length); + int remaining_length = m_length - (remaining_characters - m_characters); + return { remaining_characters, remaining_length }; +} + +StringView StringView::substring_view_starting_after_substring(const StringView& substring) const +{ + const char* remaining_characters = substring.characters() + substring.length(); + ASSERT(remaining_characters >= m_characters); + ASSERT(remaining_characters <= m_characters + m_length); + int remaining_length = m_length - (remaining_characters - m_characters); + return { remaining_characters, remaining_length }; +} + unsigned StringView::to_uint(bool& ok) const { unsigned value = 0; diff --git a/AK/StringView.h b/AK/StringView.h index ced68488a0..76335eeb04 100644 --- a/AK/StringView.h +++ b/AK/StringView.h @@ -5,6 +5,7 @@ namespace AK { class String; +class StringImpl; class StringView { public: @@ -27,7 +28,9 @@ public: ++m_length; } } + StringView(const String& string); + bool is_null() const { return !m_characters; } bool is_empty() const { return m_length == 0; } const char* characters() const { return m_characters; } int length() const { return m_length; } @@ -37,12 +40,46 @@ public: Vector split_view(char) const; unsigned to_uint(bool& ok) const; - bool operator==(const char* cstring) const { return !strcmp(m_characters, cstring); } - bool operator!=(const char* cstring) const { return strcmp(m_characters, cstring); } + // Create a new substring view of this string view, starting either at the beginning of + // the given substring view, or after its end, and continuing until the end of this string + // view (that is, for the remaining part of its length). For example, + // + // StringView str { "foobar" }; + // StringView substr = str.substring_view(1, 2); // "oo" + // StringView substr_from = str.substring_view_starting_from_substring(subst); // "oobar" + // StringView substr_after = str.substring_view_starting_after_substring(subst); // "bar" + // + // Note that this only works if the string view passed as an argument is indeed a substring + // view of this string view, such as one created by substring_view() and split_view(). It + // does not work for arbitrary strings; for example declaring substr in the example above as + // + // StringView substr { "oo" }; + // + // would not work. + StringView substring_view_starting_from_substring(const StringView& substring) const; + StringView substring_view_starting_after_substring(const StringView& substring) const; + + bool operator==(const char* cstring) const + { + if (is_null()) + return !cstring; + if (!cstring) + return false; + int other_length = strlen(cstring); + if (m_length != other_length) + return false; + return !memcmp(m_characters, cstring, m_length); + } + bool operator!=(const char* cstring) const + { + return !(*this == cstring); + } bool operator==(const String&) const; private: + friend class String; + const StringImpl* m_impl { nullptr }; const char* m_characters { nullptr }; int m_length { 0 }; }; diff --git a/AK/Tests/.gitignore b/AK/Tests/.gitignore new file mode 100644 index 0000000000..2e42a5a41c --- /dev/null +++ b/AK/Tests/.gitignore @@ -0,0 +1,2 @@ +TestString +TestQueue diff --git a/AK/Tests/Makefile b/AK/Tests/Makefile new file mode 100644 index 0000000000..dd7fc4a8e8 --- /dev/null +++ b/AK/Tests/Makefile @@ -0,0 +1,12 @@ +all: TestString TestQueue + +CXXFLAGS = -std=c++17 -Wall -Wextra + +TestString: TestString.cpp ../String.cpp ../StringImpl.cpp ../StringBuilder.cpp ../StringView.cpp TestHelpers.h + $(CXX) $(CXXFLAGS) -I../ -I../../ -o $@ TestString.cpp ../String.cpp ../StringImpl.cpp ../StringBuilder.cpp ../StringView.cpp + +TestQueue: TestQueue.cpp ../String.cpp ../StringImpl.cpp ../StringBuilder.cpp ../StringView.cpp TestHelpers.h + $(CXX) $(CXXFLAGS) -I../ -I../../ -o $@ TestQueue.cpp ../String.cpp ../StringImpl.cpp ../StringBuilder.cpp ../StringView.cpp + +clean: + rm -f TestString TestQueue diff --git a/AK/Tests/TestHelpers.h b/AK/Tests/TestHelpers.h new file mode 100644 index 0000000000..311eb6ad1f --- /dev/null +++ b/AK/Tests/TestHelpers.h @@ -0,0 +1,68 @@ +#pragma once + +#include +#include + +#define LOG_FAIL(cond) \ + fprintf(stderr, "\033[31;1mFAIL\033[0m: " #cond "\n") + +#define LOG_PASS(cond) \ + fprintf(stderr, "\033[32;1mPASS\033[0m: " #cond "\n") + +#define LOG_FAIL_EQ(cond, expected_value, actual_value) \ + fprintf(stderr, "\033[31;1mFAIL\033[0m: " #cond " should be " #expected_value ", got "); \ + stringify_for_test(actual_value); \ + fprintf(stderr, "\n") + +#define LOG_PASS_EQ(cond, expected_value) \ + fprintf(stderr, "\033[32;1mPASS\033[0m: " #cond " should be " #expected_value " and it is\n") + +#define EXPECT_EQ(expr, expected_value) \ + do { \ + auto result = (expr); \ + if (!(result == expected_value)) { \ + LOG_FAIL_EQ(expr, expected_value, result); \ + } else { \ + LOG_PASS_EQ(expr, expected_value); \ + } \ + } while(0) + +#define EXPECT(cond) \ + do { \ + if (!(cond)) { \ + LOG_FAIL(cond); \ + } else { \ + LOG_PASS(cond); \ + } \ + } while(0) + +inline void stringify_for_test(int value) +{ + fprintf(stderr, "%d", value); +} + +inline void stringify_for_test(unsigned value) +{ + fprintf(stderr, "%u", value); +} + +inline void stringify_for_test(const char* value) +{ + fprintf(stderr, "%s", value); +} + +inline void stringify_for_test(char value) +{ + fprintf(stderr, "%c", value); +} + +inline void stringify_for_test(const AK::String& string) +{ + stringify_for_test(string.characters()); +} + +inline void stringify_for_test(const AK::StringImpl& string) +{ + stringify_for_test(string.characters()); +} + diff --git a/AK/Tests/TestQueue.cpp b/AK/Tests/TestQueue.cpp new file mode 100644 index 0000000000..708835f154 --- /dev/null +++ b/AK/Tests/TestQueue.cpp @@ -0,0 +1,43 @@ +#include "TestHelpers.h" +#include +#include + +int main() +{ + EXPECT(Queue().is_empty()); + EXPECT(Queue().size() == 0); + + Queue ints; + ints.enqueue(1); + ints.enqueue(2); + ints.enqueue(3); + EXPECT_EQ(ints.size(), 3); + EXPECT_EQ(ints.dequeue(), 1); + EXPECT_EQ(ints.size(), 2); + EXPECT_EQ(ints.dequeue(), 2); + EXPECT_EQ(ints.size(), 1); + EXPECT_EQ(ints.dequeue(), 3); + EXPECT_EQ(ints.size(), 0); + + Queue strings; + strings.enqueue("ABC"); + strings.enqueue("DEF"); + EXPECT_EQ(strings.size(), 2); + EXPECT_EQ(strings.dequeue(), "ABC"); + EXPECT_EQ(strings.dequeue(), "DEF"); + EXPECT(strings.is_empty()); + + for (int i = 0; i < 10000; ++i) { + strings.enqueue(String::format("%d", i)); + EXPECT_EQ(strings.size(), i + 1); + } + + for (int i = 0; i < 10000; ++i) { + bool ok; + EXPECT_EQ(strings.dequeue().to_int(ok), i); + } + + EXPECT(strings.is_empty()); + + return 0; +} diff --git a/AK/Tests/TestString.cpp b/AK/Tests/TestString.cpp new file mode 100644 index 0000000000..851971a77e --- /dev/null +++ b/AK/Tests/TestString.cpp @@ -0,0 +1,59 @@ +#include "TestHelpers.h" +#include + +int main() +{ + EXPECT(String().is_null()); + EXPECT(String().is_empty()); + EXPECT(!String().characters()); + + EXPECT(!String("").is_null()); + EXPECT(String("").is_empty()); + EXPECT(String("").characters()); + + EXPECT(String("").impl() == String::empty().impl()); + + String test_string = "ABCDEF"; + EXPECT(!test_string.is_empty()); + EXPECT(!test_string.is_null()); + EXPECT_EQ(test_string.length(), 6); + EXPECT_EQ(test_string.length(), (int)strlen(test_string.characters())); + EXPECT(test_string.characters()); + EXPECT(!strcmp(test_string.characters(), "ABCDEF")); + + EXPECT(test_string == "ABCDEF"); + EXPECT(test_string != "ABCDE"); + EXPECT(test_string != "ABCDEFG"); + + EXPECT_EQ(test_string[0], 'A'); + EXPECT_EQ(test_string[1], 'B'); + + EXPECT(test_string.starts_with("AB")); + EXPECT(test_string.starts_with("ABCDEF")); + EXPECT(!test_string.starts_with("DEF")); + + EXPECT(test_string.ends_with("EF")); + EXPECT(test_string.ends_with("ABCDEF")); + EXPECT(!test_string.ends_with("ABC")); + + auto test_string_copy = test_string; + EXPECT_EQ(test_string, test_string_copy); + EXPECT_EQ(test_string.characters(), test_string_copy.characters()); + + auto test_string_move = move(test_string_copy); + EXPECT_EQ(test_string, test_string_move); + EXPECT(test_string_copy.is_null()); + + EXPECT_EQ(String::repeated('x', 0), ""); + EXPECT_EQ(String::repeated('x', 1), "x"); + EXPECT_EQ(String::repeated('x', 2), "xx"); + + bool ok; + EXPECT(String("123").to_int(ok) == 123 && ok); + EXPECT(String("-123").to_int(ok) == -123 && ok); + + EXPECT(String("ABC").to_lowercase() == "abc"); + EXPECT(String("AbC").to_uppercase() == "ABC"); + + return 0; +} diff --git a/AK/Time.h b/AK/Time.h index cab8ec54ba..da06a34e6e 100644 --- a/AK/Time.h +++ b/AK/Time.h @@ -3,25 +3,28 @@ namespace AK { template -inline void timeval_sub(const TimevalType* a, const TimevalType* b, TimevalType* result) +inline void timeval_sub(const TimevalType& a, const TimevalType& b, TimevalType& result) { - result->tv_sec = a->tv_sec - b->tv_sec; - result->tv_usec = a->tv_usec - b->tv_usec; - if (result->tv_usec < 0) { - --result->tv_sec; - result->tv_usec += 1000000; + result.tv_sec = a.tv_sec - b.tv_sec; + result.tv_usec = a.tv_usec - b.tv_usec; + if (result.tv_usec < 0) { + --result.tv_sec; + result.tv_usec += 1000000; } } template -inline void timeval_add(const TimevalType* a, const TimevalType* b, TimevalType* result) +inline void timeval_add(const TimevalType& a, const TimevalType& b, TimevalType& result) { - result->tv_sec = a->tv_sec + b->tv_sec; - result->tv_usec = a->tv_usec + b->tv_usec; - if (result->tv_usec > 1000000) { - ++result->tv_sec; - result->tv_usec -= 1000000; + result.tv_sec = a.tv_sec + b.tv_sec; + result.tv_usec = a.tv_usec + b.tv_usec; + if (result.tv_usec > 1000000) { + ++result.tv_sec; + result.tv_usec -= 1000000; } } } + +using AK::timeval_add; +using AK::timeval_sub; diff --git a/AK/Types.h b/AK/Types.h index 6764995430..12f65115e3 100644 --- a/AK/Types.h +++ b/AK/Types.h @@ -1,5 +1,7 @@ #pragma once +#include + #ifdef __serenity__ typedef unsigned char byte; typedef unsigned short word; @@ -48,11 +50,6 @@ constexpr unsigned KB = 1024; constexpr unsigned MB = KB * KB; constexpr unsigned GB = KB * KB * KB; -enum class IterationDecision { - Continue, - Abort -}; - namespace std { typedef decltype(nullptr) nullptr_t; } diff --git a/AK/ValueRestorer.h b/AK/ValueRestorer.h new file mode 100644 index 0000000000..99fa43e187 --- /dev/null +++ b/AK/ValueRestorer.h @@ -0,0 +1,26 @@ +#pragma once + +namespace AK { + +template +class ValueRestorer { +public: + ValueRestorer(T& variable) + : m_variable(variable) + , m_saved_value(variable) + { + } + + ~ValueRestorer() + { + m_variable = m_saved_value; + } + +private: + T& m_variable; + T m_saved_value; +}; + +} + +using AK::ValueRestorer; diff --git a/AK/Vector.h b/AK/Vector.h index c1b9c5622f..adc0e76823 100644 --- a/AK/Vector.h +++ b/AK/Vector.h @@ -4,6 +4,10 @@ #include #include +#ifndef __serenity__ +#include +#endif + namespace AK { template @@ -294,6 +298,19 @@ public: m_capacity = new_capacity; } + void shift_left(int count) + { + ASSERT(count <= m_size); + if (count == m_size) { + clear(); + return; + } + for (int i = 0; i < m_size - count; ++i) { + at(i) = move(at(i + count)); + } + m_size -= count; + } + void resize(int new_size) { if (new_size == size()) diff --git a/Applications/About/main.cpp b/Applications/About/main.cpp index e6c22966cb..e89a903c14 100644 --- a/Applications/About/main.cpp +++ b/Applications/About/main.cpp @@ -1,10 +1,9 @@ #include -#include -#include -#include #include +#include #include -#include +#include +#include #include int main(int argc, char** argv) @@ -50,7 +49,7 @@ int main(int argc, char** argv) quit_button->set_text("Okay"); quit_button->set_size_policy(SizePolicy::Fixed, SizePolicy::Fixed); quit_button->set_preferred_size({ 100, 20 }); - quit_button->on_click = [] (GButton&) { + quit_button->on_click = [](GButton&) { GApplication::the().quit(0); }; diff --git a/Applications/Downloader/main.cpp b/Applications/Downloader/main.cpp index 99b536b461..7bb069363c 100644 --- a/Applications/Downloader/main.cpp +++ b/Applications/Downloader/main.cpp @@ -1,7 +1,7 @@ -#include #include #include #include +#include #include int main(int argc, char** argv) @@ -13,7 +13,7 @@ int main(int argc, char** argv) request.set_path("/"); auto job = request.schedule(); - job->on_finish = [&job] (bool success) { + job->on_finish = [&job](bool success) { if (!success) { dbgprintf("on_finish: request failed :(\n"); return; diff --git a/Applications/FileManager/DirectoryView.cpp b/Applications/FileManager/DirectoryView.cpp index cf8187ecd4..cf7326ea1e 100644 --- a/Applications/FileManager/DirectoryView.cpp +++ b/Applications/FileManager/DirectoryView.cpp @@ -1,8 +1,8 @@ #include "DirectoryView.h" -#include #include -#include +#include #include +#include void DirectoryView::handle_activation(const GModelIndex& index) { @@ -58,28 +58,28 @@ DirectoryView::DirectoryView(GWidget* parent) m_item_view->set_model_column(GDirectoryModel::Column::Name); - m_item_view->on_model_notification = [this] (const GModelNotification& notification) { + m_item_view->on_model_notification = [this](const GModelNotification& notification) { if (notification.type() == GModelNotification::Type::ModelUpdated) { set_status_message(String::format("%d item%s (%u byte%s)", - model().row_count(), - model().row_count() != 1 ? "s" : "", - model().bytes_in_files(), - model().bytes_in_files() != 1 ? "s" : "")); + model().row_count(), + model().row_count() != 1 ? "s" : "", + model().bytes_in_files(), + model().bytes_in_files() != 1 ? "s" : "")); if (on_path_change) on_path_change(model().path()); } }; - m_model->on_thumbnail_progress = [this] (int done, int total) { + m_model->on_thumbnail_progress = [this](int done, int total) { if (on_thumbnail_progress) on_thumbnail_progress(done, total); }; - m_item_view->on_activation = [&] (const GModelIndex& index) { + m_item_view->on_activation = [&](const GModelIndex& index) { handle_activation(index); }; - m_table_view->on_activation = [&] (auto& index) { + m_table_view->on_activation = [&](auto& index) { auto& filter_model = (GSortingProxyModel&)*m_table_view->model(); handle_activation(filter_model.map_to_target(index)); }; @@ -108,7 +108,7 @@ void DirectoryView::set_view_mode(ViewMode mode) ASSERT_NOT_REACHED(); } -void DirectoryView::add_path_to_history(const String& path) +void DirectoryView::add_path_to_history(const StringView& path) { if (m_path_history_position < m_path_history.size()) m_path_history.resize(m_path_history_position + 1); @@ -117,13 +117,13 @@ void DirectoryView::add_path_to_history(const String& path) m_path_history_position = m_path_history.size() - 1; } -void DirectoryView::open(const String& path) +void DirectoryView::open(const StringView& path) { add_path_to_history(path); model().open(path); } -void DirectoryView::set_status_message(const String& message) +void DirectoryView::set_status_message(const StringView& message) { if (on_status_message) on_status_message(message); diff --git a/Applications/FileManager/DirectoryView.h b/Applications/FileManager/DirectoryView.h index c494419e5d..c7e2f08bc5 100644 --- a/Applications/FileManager/DirectoryView.h +++ b/Applications/FileManager/DirectoryView.h @@ -12,7 +12,7 @@ public: explicit DirectoryView(GWidget* parent); virtual ~DirectoryView() override; - void open(const String& path); + void open(const StringView& path); String path() const { return model().path(); } void open_parent_directory(); void open_previous_directory(); @@ -22,12 +22,11 @@ public: void refresh(); - Function on_path_change; - Function on_status_message; + Function on_path_change; + Function on_status_message; Function on_thumbnail_progress; - enum ViewMode - { + enum ViewMode { Invalid, List, Icon @@ -41,14 +40,14 @@ private: void handle_activation(const GModelIndex&); - void set_status_message(const String&); + void set_status_message(const StringView&); ViewMode m_view_mode { Invalid }; Retained m_model; int m_path_history_position { 0 }; Vector m_path_history; - void add_path_to_history(const String& path); + void add_path_to_history(const StringView& path); GTableView* m_table_view { nullptr }; GItemView* m_item_view { nullptr }; diff --git a/Applications/FileManager/main.cpp b/Applications/FileManager/main.cpp index 7c6fe3bc73..4f8f1cbc01 100644 --- a/Applications/FileManager/main.cpp +++ b/Applications/FileManager/main.cpp @@ -1,25 +1,25 @@ -#include -#include -#include +#include "DirectoryView.h" +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include +#include +#include #include #include -#include "DirectoryView.h" +#include int main(int argc, char** argv) { @@ -76,24 +76,24 @@ int main(int argc, char** argv) directory_view->open(location_textbox->text()); }; - file_system_model->on_selection_changed = [&] (auto& index) { + file_system_model->on_selection_changed = [&](auto& index) { auto path = file_system_model->path(index); if (directory_view->path() == path) return; directory_view->open(path); }; - auto open_parent_directory_action = GAction::create("Open parent directory", { Mod_Alt, Key_Up }, GraphicsBitmap::load_from_file("/res/icons/16x16/open-parent-directory.png"), [directory_view] (const GAction&) { + auto open_parent_directory_action = GAction::create("Open parent directory", { Mod_Alt, Key_Up }, GraphicsBitmap::load_from_file("/res/icons/16x16/open-parent-directory.png"), [directory_view](const GAction&) { directory_view->open_parent_directory(); }); - auto mkdir_action = GAction::create("New directory...", GraphicsBitmap::load_from_file("/res/icons/16x16/mkdir.png"), [&] (const GAction&) { + auto mkdir_action = GAction::create("New directory...", GraphicsBitmap::load_from_file("/res/icons/16x16/mkdir.png"), [&](const GAction&) { GInputBox input_box("Enter name:", "New directory", window); if (input_box.exec() == GInputBox::ExecOK && !input_box.text_value().is_empty()) { auto new_dir_path = FileSystemPath(String::format("%s/%s", - directory_view->path().characters(), - input_box.text_value().characters() - )).string(); + directory_view->path().characters(), + input_box.text_value().characters())) + .string(); int rc = mkdir(new_dir_path.characters(), 0777); if (rc < 0) { GMessageBox::show(String::format("mkdir(\"%s\") failed: %s", new_dir_path.characters(), strerror(errno)), "Error", GMessageBox::Type::Error, window); @@ -106,7 +106,7 @@ int main(int argc, char** argv) RetainPtr view_as_table_action; RetainPtr view_as_icons_action; - view_as_table_action = GAction::create("Table view", { Mod_Ctrl, KeyCode::Key_L }, GraphicsBitmap::load_from_file("/res/icons/16x16/table-view.png"), [&] (const GAction&) { + view_as_table_action = GAction::create("Table view", { Mod_Ctrl, KeyCode::Key_L }, GraphicsBitmap::load_from_file("/res/icons/16x16/table-view.png"), [&](const GAction&) { directory_view->set_view_mode(DirectoryView::ViewMode::List); view_as_icons_action->set_checked(false); view_as_table_action->set_checked(true); @@ -114,7 +114,7 @@ int main(int argc, char** argv) view_as_table_action->set_checkable(true); view_as_table_action->set_checked(false); - view_as_icons_action = GAction::create("Icon view", { Mod_Ctrl, KeyCode::Key_I }, GraphicsBitmap::load_from_file("/res/icons/16x16/icon-view.png"), [&] (const GAction&) { + view_as_icons_action = GAction::create("Icon view", { Mod_Ctrl, KeyCode::Key_I }, GraphicsBitmap::load_from_file("/res/icons/16x16/icon-view.png"), [&](const GAction&) { directory_view->set_view_mode(DirectoryView::ViewMode::Icon); view_as_table_action->set_checked(false); view_as_icons_action->set_checked(true); @@ -122,20 +122,20 @@ int main(int argc, char** argv) view_as_icons_action->set_checkable(true); view_as_icons_action->set_checked(true); - auto copy_action = GAction::create("Copy", GraphicsBitmap::load_from_file("/res/icons/16x16/edit-copy.png"), [] (const GAction&) { + auto copy_action = GAction::create("Copy", GraphicsBitmap::load_from_file("/res/icons/16x16/edit-copy.png"), [](const GAction&) { dbgprintf("'Copy' action activated!\n"); }); - auto delete_action = GAction::create("Delete", GraphicsBitmap::load_from_file("/res/icons/16x16/delete.png"), [] (const GAction&) { + auto delete_action = GAction::create("Delete", GraphicsBitmap::load_from_file("/res/icons/16x16/delete.png"), [](const GAction&) { dbgprintf("'Delete' action activated!\n"); }); - auto go_back_action = GAction::create("Go Back", GraphicsBitmap::load_from_file("/res/icons/16x16/go-back.png"), [directory_view] (const GAction&) { + auto go_back_action = GAction::create("Go Back", GraphicsBitmap::load_from_file("/res/icons/16x16/go-back.png"), [directory_view](const GAction&) { dbgprintf("'Go Back' action activated!\n"); directory_view->open_previous_directory(); }); - auto go_forward_action = GAction::create("Go Forward", GraphicsBitmap::load_from_file("/res/icons/16x16/go-forward.png"), [directory_view] (const GAction&) { + auto go_forward_action = GAction::create("Go Forward", GraphicsBitmap::load_from_file("/res/icons/16x16/go-forward.png"), [directory_view](const GAction&) { dbgprintf("'Go Forward' action activated!\n"); directory_view->open_next_directory(); }); @@ -143,7 +143,7 @@ int main(int argc, char** argv) auto menubar = make(); auto app_menu = make("File Manager"); - app_menu->add_action(GAction::create("Quit", { Mod_Alt, Key_F4 }, [] (const GAction&) { + app_menu->add_action(GAction::create("Quit", { Mod_Alt, Key_F4 }, [](const GAction&) { GApplication::the().quit(0); return; })); @@ -167,7 +167,7 @@ int main(int argc, char** argv) menubar->add_menu(move(go_menu)); auto help_menu = make("Help"); - help_menu->add_action(GAction::create("About", [] (const GAction&) { + help_menu->add_action(GAction::create("About", [](const GAction&) { dbgprintf("FIXME: Implement Help/About\n"); })); menubar->add_menu(move(help_menu)); @@ -187,7 +187,7 @@ int main(int argc, char** argv) main_toolbar->add_action(*view_as_icons_action); main_toolbar->add_action(*view_as_table_action); - directory_view->on_path_change = [window, location_textbox, &file_system_model, tree_view, &go_forward_action, &go_back_action, directory_view] (const String& new_path) { + directory_view->on_path_change = [window, location_textbox, &file_system_model, tree_view, &go_forward_action, &go_back_action, directory_view](const String& new_path) { window->set_title(String::format("File Manager: %s", new_path.characters())); location_textbox->set_text(new_path); file_system_model->set_selected_index(file_system_model->index(new_path)); @@ -195,15 +195,15 @@ int main(int argc, char** argv) tree_view->update(); go_forward_action->set_enabled(directory_view->path_history_position() - < directory_view->path_history_size() - 1); + < directory_view->path_history_size() - 1); go_back_action->set_enabled(directory_view->path_history_position() > 0); }; - directory_view->on_status_message = [statusbar] (String message) { - statusbar->set_text(move(message)); + directory_view->on_status_message = [statusbar](const StringView& message) { + statusbar->set_text(message); }; - directory_view->on_thumbnail_progress = [&] (int done, int total) { + directory_view->on_thumbnail_progress = [&](int done, int total) { if (done == total) { progressbar->set_visible(false); return; diff --git a/Applications/FontEditor/FontEditor.cpp b/Applications/FontEditor/FontEditor.cpp index 1ef0b49639..247e17d276 100644 --- a/Applications/FontEditor/FontEditor.cpp +++ b/Applications/FontEditor/FontEditor.cpp @@ -1,13 +1,13 @@ #include "FontEditor.h" -#include "GlyphMapWidget.h" #include "GlyphEditorWidget.h" -#include +#include "GlyphMapWidget.h" #include -#include -#include #include -#include #include +#include +#include +#include +#include #include FontEditorWidget::FontEditorWidget(const String& path, RetainPtr&& edited_font, GWidget* parent) @@ -52,7 +52,7 @@ FontEditorWidget::FontEditorWidget(const String& path, RetainPtr&& edited_ auto* save_button = new GButton(this); save_button->set_text("Save"); save_button->set_relative_rect({ 5, 300, 105, 20 }); - save_button->on_click = [this] (GButton&) { + save_button->on_click = [this](GButton&) { dbgprintf("write to file: '%s'\n", m_path.characters()); m_edited_font->write_to_file(m_path); }; @@ -60,7 +60,7 @@ FontEditorWidget::FontEditorWidget(const String& path, RetainPtr&& edited_ auto* quit_button = new GButton(this); quit_button->set_text("Quit"); quit_button->set_relative_rect({ 110, 300, 105, 20 }); - quit_button->on_click = [] (GButton&) { + quit_button->on_click = [](GButton&) { exit(0); }; @@ -91,25 +91,25 @@ FontEditorWidget::FontEditorWidget(const String& path, RetainPtr&& edited_ demo_label_2->update(); }; - m_glyph_editor_widget->on_glyph_altered = [this, update_demo] (byte glyph) { + m_glyph_editor_widget->on_glyph_altered = [this, update_demo](byte glyph) { m_glyph_map_widget->update_glyph(glyph); update_demo(); }; - m_glyph_map_widget->on_glyph_selected = [this, info_label, width_spinbox] (byte glyph) { + m_glyph_map_widget->on_glyph_selected = [this, info_label, width_spinbox](byte glyph) { m_glyph_editor_widget->set_glyph(glyph); width_spinbox->set_value(m_edited_font->glyph_width(m_glyph_map_widget->selected_glyph())); info_label->set_text(String::format("0x%b (%c)", glyph, glyph)); }; - fixed_width_checkbox->on_checked = [this, width_spinbox, update_demo] (bool checked) { + fixed_width_checkbox->on_checked = [this, width_spinbox, update_demo](bool checked) { m_edited_font->set_fixed_width(checked); width_spinbox->set_value(m_edited_font->glyph_width(m_glyph_map_widget->selected_glyph())); m_glyph_editor_widget->update(); update_demo(); }; - width_spinbox->on_change = [this, update_demo] (int value) { + width_spinbox->on_change = [this, update_demo](int value) { m_edited_font->set_glyph_width(m_glyph_map_widget->selected_glyph(), value); m_glyph_editor_widget->update(); m_glyph_map_widget->update_glyph(m_glyph_map_widget->selected_glyph()); diff --git a/Applications/FontEditor/GlyphMapWidget.cpp b/Applications/FontEditor/GlyphMapWidget.cpp index de45591036..4d94b2eeaf 100644 --- a/Applications/FontEditor/GlyphMapWidget.cpp +++ b/Applications/FontEditor/GlyphMapWidget.cpp @@ -44,7 +44,8 @@ Rect GlyphMapWidget::get_outer_rect(byte glyph) const row * (font().glyph_height() + m_vertical_spacing) + 1, font().max_glyph_width() + m_horizontal_spacing, font().glyph_height() + m_horizontal_spacing - }.translated(frame_thickness(), frame_thickness()); + } + .translated(frame_thickness(), frame_thickness()); } void GlyphMapWidget::update_glyph(byte glyph) @@ -71,8 +72,7 @@ void GlyphMapWidget::paint_event(GPaintEvent& event) outer_rect.x() + m_horizontal_spacing / 2, outer_rect.y() + m_vertical_spacing / 2, font().max_glyph_width(), - font().glyph_height() - ); + font().glyph_height()); if (glyph == m_selected_glyph) { painter.fill_rect(outer_rect, Color::from_rgb(0x84351a)); painter.draw_glyph(inner_rect.location(), glyph, Color::White); diff --git a/Applications/IRCClient/IRCAppWindow.cpp b/Applications/IRCClient/IRCAppWindow.cpp index ca19133cdd..6d42984f01 100644 --- a/Applications/IRCClient/IRCAppWindow.cpp +++ b/Applications/IRCClient/IRCAppWindow.cpp @@ -1,16 +1,16 @@ #include "IRCAppWindow.h" #include "IRCWindow.h" #include "IRCWindowListModel.h" -#include -#include -#include -#include -#include #include +#include +#include +#include #include #include -#include #include +#include +#include +#include #include #include @@ -36,7 +36,7 @@ void IRCAppWindow::update_title() void IRCAppWindow::setup_client() { - m_client.aid_create_window = [this] (void* owner, IRCWindow::Type type, const String& name) { + m_client.aid_create_window = [this](void* owner, IRCWindow::Type type, const String& name) { return &create_window(owner, type, name); }; m_client.aid_get_active_window = [this] { @@ -45,7 +45,7 @@ void IRCAppWindow::setup_client() m_client.aid_update_window_list = [this] { m_window_list->model()->update(); }; - m_client.on_nickname_changed = [this] (const String&) { + m_client.on_nickname_changed = [this](const String&) { update_title(); }; @@ -64,33 +64,33 @@ void IRCAppWindow::setup_client() void IRCAppWindow::setup_actions() { - m_join_action = GAction::create("Join channel", GraphicsBitmap::load_from_file("/res/icons/16x16/irc-join.png"), [&] (auto&) { + m_join_action = GAction::create("Join channel", GraphicsBitmap::load_from_file("/res/icons/16x16/irc-join.png"), [&](auto&) { GInputBox input_box("Enter channel name:", "Join channel", this); if (input_box.exec() == GInputBox::ExecOK && !input_box.text_value().is_empty()) m_client.handle_join_action(input_box.text_value()); }); - m_part_action = GAction::create("Part from channel", GraphicsBitmap::load_from_file("/res/icons/16x16/irc-part.png"), [] (auto&) { + m_part_action = GAction::create("Part from channel", GraphicsBitmap::load_from_file("/res/icons/16x16/irc-part.png"), [](auto&) { printf("FIXME: Implement part action\n"); }); - m_whois_action = GAction::create("Whois user", GraphicsBitmap::load_from_file("/res/icons/16x16/irc-whois.png"), [&] (auto&) { + m_whois_action = GAction::create("Whois user", GraphicsBitmap::load_from_file("/res/icons/16x16/irc-whois.png"), [&](auto&) { GInputBox input_box("Enter nickname:", "IRC WHOIS lookup", this); if (input_box.exec() == GInputBox::ExecOK && !input_box.text_value().is_empty()) m_client.handle_whois_action(input_box.text_value()); }); - m_open_query_action = GAction::create("Open query", GraphicsBitmap::load_from_file("/res/icons/16x16/irc-open-query.png"), [&] (auto&) { + m_open_query_action = GAction::create("Open query", GraphicsBitmap::load_from_file("/res/icons/16x16/irc-open-query.png"), [&](auto&) { GInputBox input_box("Enter nickname:", "Open IRC query with...", this); if (input_box.exec() == GInputBox::ExecOK && !input_box.text_value().is_empty()) m_client.handle_open_query_action(input_box.text_value()); }); - m_close_query_action = GAction::create("Close query", GraphicsBitmap::load_from_file("/res/icons/16x16/irc-close-query.png"), [] (auto&) { + m_close_query_action = GAction::create("Close query", GraphicsBitmap::load_from_file("/res/icons/16x16/irc-close-query.png"), [](auto&) { printf("FIXME: Implement close-query action\n"); }); - m_change_nick_action = GAction::create("Change nickname", GraphicsBitmap::load_from_file("/res/icons/16x16/irc-nick.png"), [this] (auto&) { + m_change_nick_action = GAction::create("Change nickname", GraphicsBitmap::load_from_file("/res/icons/16x16/irc-nick.png"), [this](auto&) { GInputBox input_box("Enter nickname:", "Change nickname", this); if (input_box.exec() == GInputBox::ExecOK && !input_box.text_value().is_empty()) m_client.handle_change_nick_action(input_box.text_value()); @@ -101,7 +101,7 @@ void IRCAppWindow::setup_menus() { auto menubar = make(); auto app_menu = make("IRC Client"); - app_menu->add_action(GAction::create("Quit", { Mod_Alt, Key_F4 }, [] (const GAction&) { + app_menu->add_action(GAction::create("Quit", { Mod_Alt, Key_F4 }, [](const GAction&) { dbgprintf("Terminal: Quit menu activated!\n"); GApplication::the().quit(0); return; @@ -120,7 +120,7 @@ void IRCAppWindow::setup_menus() menubar->add_menu(move(server_menu)); auto help_menu = make("Help"); - help_menu->add_action(GAction::create("About", [] (const GAction&) { + help_menu->add_action(GAction::create("About", [](const GAction&) { dbgprintf("FIXME: Implement Help/About\n"); })); menubar->add_menu(move(help_menu)); @@ -156,7 +156,7 @@ void IRCAppWindow::setup_widgets() m_window_list->set_activates_on_selection(true); m_window_list->set_size_policy(SizePolicy::Fixed, SizePolicy::Fill); m_window_list->set_preferred_size({ 100, 0 }); - m_window_list->on_activation = [this] (auto& index) { + m_window_list->on_activation = [this](auto& index) { auto& window = m_client.window_at(index.row()); m_container->set_active_widget(&window); window.clear_unread_count(); diff --git a/Applications/IRCClient/IRCChannel.cpp b/Applications/IRCClient/IRCChannel.cpp index 57e645bdd9..8e18b558b3 100644 --- a/Applications/IRCClient/IRCChannel.cpp +++ b/Applications/IRCClient/IRCChannel.cpp @@ -1,6 +1,6 @@ #include "IRCChannel.h" -#include "IRCClient.h" #include "IRCChannelMemberListModel.h" +#include "IRCClient.h" #include #include @@ -37,7 +37,7 @@ void IRCChannel::add_member(const String& name, char prefix) void IRCChannel::remove_member(const String& name) { - m_members.remove_first_matching([&] (auto& member) { return name == member.name; }); + m_members.remove_first_matching([&](auto& member) { return name == member.name; }); } void IRCChannel::add_message(char prefix, const String& name, const String& text, Color color) diff --git a/Applications/IRCClient/IRCChannelMemberListModel.cpp b/Applications/IRCClient/IRCChannelMemberListModel.cpp index 25fed4cbf3..6c84e9783c 100644 --- a/Applications/IRCClient/IRCChannelMemberListModel.cpp +++ b/Applications/IRCClient/IRCChannelMemberListModel.cpp @@ -25,7 +25,8 @@ int IRCChannelMemberListModel::column_count(const GModelIndex&) const String IRCChannelMemberListModel::column_name(int column) const { switch (column) { - case Column::Name: return "Name"; + case Column::Name: + return "Name"; } ASSERT_NOT_REACHED(); } @@ -33,7 +34,8 @@ String IRCChannelMemberListModel::column_name(int column) const GModel::ColumnMetadata IRCChannelMemberListModel::column_metadata(int column) const { switch (column) { - case Column::Name: return { 70, TextAlignment::CenterLeft }; + case Column::Name: + return { 70, TextAlignment::CenterLeft }; } ASSERT_NOT_REACHED(); } @@ -42,10 +44,11 @@ GVariant IRCChannelMemberListModel::data(const GModelIndex& index, Role role) co { if (role == Role::Display) { switch (index.column()) { - case Column::Name: return m_channel.member_at(index.row()); + case Column::Name: + return m_channel.member_at(index.row()); } } - return { }; + return {}; } void IRCChannelMemberListModel::update() diff --git a/Applications/IRCClient/IRCChannelMemberListModel.h b/Applications/IRCClient/IRCChannelMemberListModel.h index ac380ec62d..df0e762264 100644 --- a/Applications/IRCClient/IRCChannelMemberListModel.h +++ b/Applications/IRCClient/IRCChannelMemberListModel.h @@ -7,8 +7,7 @@ class IRCChannel; class IRCChannelMemberListModel final : public GModel { public: - enum Column - { + enum Column { Name }; static Retained create(IRCChannel& channel) { return adopt(*new IRCChannelMemberListModel(channel)); } diff --git a/Applications/IRCClient/IRCClient.cpp b/Applications/IRCClient/IRCClient.cpp index a4e2cdb165..9a89780622 100644 --- a/Applications/IRCClient/IRCClient.cpp +++ b/Applications/IRCClient/IRCClient.cpp @@ -1,16 +1,16 @@ #include "IRCClient.h" #include "IRCChannel.h" -#include "IRCQuery.h" #include "IRCLogBuffer.h" +#include "IRCQuery.h" #include "IRCWindow.h" #include "IRCWindowListModel.h" #include -#include -#include #include -#include +#include #include +#include #include +#include #define IRC_DEBUG @@ -43,7 +43,7 @@ IRCClient::~IRCClient() { } -void IRCClient::set_server(const String &hostname, int port) +void IRCClient::set_server(const String& hostname, int port) { m_hostname = hostname; m_port = port; @@ -112,7 +112,8 @@ void IRCClient::process_line(ByteBuffer&& line) InStartOfParameter, InParameter, InTrailingParameter, - } state = Start; + } state + = Start; for (int i = 0; i < line.size(); ++i) { char ch = line[i]; @@ -216,8 +217,7 @@ void IRCClient::handle(const Message& msg) printf("IRCClient::execute: prefix='%s', command='%s', arguments=%d\n", msg.prefix.characters(), msg.command.characters(), - msg.arguments.size() - ); + msg.arguments.size()); int i = 0; for (auto& arg : msg.arguments) { @@ -231,16 +231,26 @@ void IRCClient::handle(const Message& msg) if (is_numeric) { switch (numeric) { - case RPL_WHOISCHANNELS: return handle_rpl_whoischannels(msg); - case RPL_ENDOFWHOIS: return handle_rpl_endofwhois(msg); - case RPL_WHOISOPERATOR: return handle_rpl_whoisoperator(msg); - case RPL_WHOISSERVER: return handle_rpl_whoisserver(msg); - case RPL_WHOISUSER: return handle_rpl_whoisuser(msg); - case RPL_WHOISIDLE: return handle_rpl_whoisidle(msg); - case RPL_TOPICWHOTIME: return handle_rpl_topicwhotime(msg); - case RPL_TOPIC: return handle_rpl_topic(msg); - case RPL_NAMREPLY: return handle_rpl_namreply(msg); - case RPL_ENDOFNAMES: return handle_rpl_endofnames(msg); + case RPL_WHOISCHANNELS: + return handle_rpl_whoischannels(msg); + case RPL_ENDOFWHOIS: + return handle_rpl_endofwhois(msg); + case RPL_WHOISOPERATOR: + return handle_rpl_whoisoperator(msg); + case RPL_WHOISSERVER: + return handle_rpl_whoisserver(msg); + case RPL_WHOISUSER: + return handle_rpl_whoisuser(msg); + case RPL_WHOISIDLE: + return handle_rpl_whoisidle(msg); + case RPL_TOPICWHOTIME: + return handle_rpl_topicwhotime(msg); + case RPL_TOPIC: + return handle_rpl_topic(msg); + case RPL_NAMREPLY: + return handle_rpl_namreply(msg); + case RPL_ENDOFNAMES: + return handle_rpl_endofnames(msg); } } @@ -441,7 +451,7 @@ void IRCClient::handle_rpl_topic(const Message& msg) return; auto& channel_name = msg.arguments[1]; auto& topic = msg.arguments[2]; - ensure_channel(channel_name).handle_topic({ }, topic); + ensure_channel(channel_name).handle_topic({}, topic); // FIXME: Handle RPL_TOPICWHOTIME so we can know who set it and when. } @@ -502,8 +512,7 @@ void IRCClient::handle_rpl_whoisuser(const Message& msg) nick.characters(), username.characters(), host.characters(), - realname.characters() - )); + realname.characters())); } void IRCClient::handle_rpl_whoisidle(const Message& msg) @@ -541,8 +550,7 @@ void IRCClient::handle_rpl_topicwhotime(const Message& msg) tm->tm_mday, tm->tm_hour, tm->tm_min, - tm->tm_sec - ); + tm->tm_sec); } ensure_channel(channel_name).add_message(String::format("*** (set by %s at %s)", nick.characters(), setat.characters()), Color::Blue); } diff --git a/Applications/IRCClient/IRCLogBufferModel.cpp b/Applications/IRCClient/IRCLogBufferModel.cpp index 518ad63f3c..6c3874b476 100644 --- a/Applications/IRCClient/IRCLogBufferModel.cpp +++ b/Applications/IRCClient/IRCLogBufferModel.cpp @@ -1,8 +1,8 @@ #include "IRCLogBufferModel.h" #include "IRCLogBuffer.h" +#include #include #include -#include IRCLogBufferModel::IRCLogBufferModel(Retained&& log_buffer) : m_log_buffer(move(log_buffer)) @@ -26,9 +26,12 @@ int IRCLogBufferModel::column_count(const GModelIndex&) const String IRCLogBufferModel::column_name(int column) const { switch (column) { - case Column::Timestamp: return "Time"; - case Column::Name: return "Name"; - case Column::Text: return "Text"; + case Column::Timestamp: + return "Time"; + case Column::Name: + return "Name"; + case Column::Text: + return "Text"; } ASSERT_NOT_REACHED(); } @@ -36,9 +39,12 @@ String IRCLogBufferModel::column_name(int column) const GModel::ColumnMetadata IRCLogBufferModel::column_metadata(int column) const { switch (column) { - case Column::Timestamp: return { 60, TextAlignment::CenterLeft }; - case Column::Name: return { 70, TextAlignment::CenterRight, &Font::default_bold_font() }; - case Column::Text: return { 800, TextAlignment::CenterLeft }; + case Column::Timestamp: + return { 60, TextAlignment::CenterLeft }; + case Column::Name: + return { 70, TextAlignment::CenterRight, &Font::default_bold_font() }; + case Column::Text: + return { 800, TextAlignment::CenterLeft }; } ASSERT_NOT_REACHED(); } @@ -56,7 +62,8 @@ GVariant IRCLogBufferModel::data(const GModelIndex& index, Role role) const if (entry.sender.is_empty()) return String::empty(); return String::format("<%c%s>", entry.prefix ? entry.prefix : ' ', entry.sender.characters()); - case Column::Text: return entry.text; + case Column::Text: + return entry.text; } } if (role == Role::ForegroundColor) { @@ -65,7 +72,7 @@ GVariant IRCLogBufferModel::data(const GModelIndex& index, Role role) const if (index.column() == Column::Text) return m_log_buffer->at(index.row()).color; } - return { }; + return {}; } void IRCLogBufferModel::update() diff --git a/Applications/IRCClient/IRCLogBufferModel.h b/Applications/IRCClient/IRCLogBufferModel.h index d5479da887..5be8237d07 100644 --- a/Applications/IRCClient/IRCLogBufferModel.h +++ b/Applications/IRCClient/IRCLogBufferModel.h @@ -6,8 +6,7 @@ class IRCLogBuffer; class IRCLogBufferModel final : public GModel { public: - enum Column - { + enum Column { Timestamp = 0, Name, Text, diff --git a/Applications/IRCClient/IRCWindow.cpp b/Applications/IRCClient/IRCWindow.cpp index 7364707e82..ba3bfbea47 100644 --- a/Applications/IRCClient/IRCWindow.cpp +++ b/Applications/IRCClient/IRCWindow.cpp @@ -1,13 +1,13 @@ #include "IRCWindow.h" -#include "IRCClient.h" #include "IRCChannel.h" #include "IRCChannelMemberListModel.h" +#include "IRCClient.h" #include "IRCLogBufferModel.h" #include -#include -#include -#include #include +#include +#include +#include IRCWindow::IRCWindow(IRCClient& client, void* owner, Type type, const String& name, GWidget* parent) : GWidget(parent) diff --git a/Applications/IRCClient/IRCWindow.h b/Applications/IRCClient/IRCWindow.h index f8fe692542..2fce542fe5 100644 --- a/Applications/IRCClient/IRCWindow.h +++ b/Applications/IRCClient/IRCWindow.h @@ -11,8 +11,7 @@ class GTextEditor; class IRCWindow : public GWidget { public: - enum Type - { + enum Type { Server, Channel, Query, diff --git a/Applications/IRCClient/IRCWindowListModel.cpp b/Applications/IRCClient/IRCWindowListModel.cpp index bc089c2e0c..e68a3a5d93 100644 --- a/Applications/IRCClient/IRCWindowListModel.cpp +++ b/Applications/IRCClient/IRCWindowListModel.cpp @@ -1,7 +1,7 @@ #include "IRCWindowListModel.h" -#include "IRCWindow.h" -#include "IRCClient.h" #include "IRCChannel.h" +#include "IRCClient.h" +#include "IRCWindow.h" #include #include @@ -27,7 +27,8 @@ int IRCWindowListModel::column_count(const GModelIndex&) const String IRCWindowListModel::column_name(int column) const { switch (column) { - case Column::Name: return "Name"; + case Column::Name: + return "Name"; } ASSERT_NOT_REACHED(); } @@ -35,7 +36,8 @@ String IRCWindowListModel::column_name(int column) const GModel::ColumnMetadata IRCWindowListModel::column_metadata(int column) const { switch (column) { - case Column::Name: return { 70, TextAlignment::CenterLeft }; + case Column::Name: + return { 70, TextAlignment::CenterLeft }; } ASSERT_NOT_REACHED(); } @@ -64,7 +66,7 @@ GVariant IRCWindowListModel::data(const GModelIndex& index, Role role) const } } } - return { }; + return {}; } void IRCWindowListModel::update() diff --git a/Applications/IRCClient/IRCWindowListModel.h b/Applications/IRCClient/IRCWindowListModel.h index 93fa6b6abd..47e4621c96 100644 --- a/Applications/IRCClient/IRCWindowListModel.h +++ b/Applications/IRCClient/IRCWindowListModel.h @@ -8,8 +8,7 @@ class IRCWindow; class IRCWindowListModel final : public GModel { public: - enum Column - { + enum Column { Name, }; diff --git a/Applications/IRCClient/main.cpp b/Applications/IRCClient/main.cpp index a69fbec802..a3a670ad5a 100644 --- a/Applications/IRCClient/main.cpp +++ b/Applications/IRCClient/main.cpp @@ -1,6 +1,6 @@ +#include "IRCAppWindow.h" #include "IRCClient.h" #include -#include "IRCAppWindow.h" #include int main(int argc, char** argv) diff --git a/Applications/Launcher/main.cpp b/Applications/Launcher/main.cpp index 9f4db8cbdd..2e56508ada 100644 --- a/Applications/Launcher/main.cpp +++ b/Applications/Launcher/main.cpp @@ -1,16 +1,16 @@ -#include -#include -#include -#include +#include +#include #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include #include -#include +#include +#include +#include +#include static GWindow* make_launcher_window(); @@ -47,7 +47,7 @@ public: set_icon(GraphicsBitmap::load_from_file(icon_path)); set_preferred_size({ 50, 50 }); set_size_policy(SizePolicy::Fixed, SizePolicy::Fixed); - on_click = [this] (GButton&) { + on_click = [this](GButton&) { pid_t child_pid = fork(); if (!child_pid) { int rc = execl(m_executable_path.characters(), m_executable_path.characters(), nullptr); @@ -55,7 +55,8 @@ public: perror("execl"); } }; - } virtual ~LauncherButton() { } + } + virtual ~LauncherButton() {} private: String m_executable_path; @@ -78,9 +79,9 @@ GWindow* make_launcher_window() for (auto& group : config->groups()) { new LauncherButton(config->read_entry(group, "Name", group), - config->read_entry(group, "Icon", ""), - config->read_entry(group, "Path", ""), - widget); + config->read_entry(group, "Icon", ""), + config->read_entry(group, "Path", ""), + widget); } return window; diff --git a/Applications/PaintBrush/.gitignore b/Applications/PaintBrush/.gitignore new file mode 100644 index 0000000000..30424a7dff --- /dev/null +++ b/Applications/PaintBrush/.gitignore @@ -0,0 +1,3 @@ +*.o +*.d +PaintBrush diff --git a/Applications/PaintBrush/BucketTool.cpp b/Applications/PaintBrush/BucketTool.cpp new file mode 100644 index 0000000000..c2b6353418 --- /dev/null +++ b/Applications/PaintBrush/BucketTool.cpp @@ -0,0 +1,55 @@ +#include "BucketTool.h" +#include "PaintableWidget.h" +#include +#include +#include +#include +#include + +BucketTool::BucketTool() +{ +} + +BucketTool::~BucketTool() +{ +} + +static void flood_fill(GraphicsBitmap& bitmap, const Point& start_position, Color target_color, Color fill_color) +{ + ASSERT(bitmap.format() == GraphicsBitmap::Format::RGB32); + + Queue queue; + queue.enqueue(Point(start_position)); + while (!queue.is_empty()) { + auto position = queue.dequeue(); + + if (bitmap.get_pixel(position.x(), position.y()) != target_color) + continue; + bitmap.set_pixel(position.x(), position.y(), fill_color); + + if (position.x() != 0) + queue.enqueue(position.translated(-1, 0)); + + if (position.x() != bitmap.width() - 1) + queue.enqueue(position.translated(1, 0)); + + if (position.y() != 0) + queue.enqueue(position.translated(0, -1)); + + if (position.y() != bitmap.height() - 1) + queue.enqueue(position.translated(0, 1)); + } +} + +void BucketTool::on_mousedown(PaintableWidget& paintable_widget, GMouseEvent& event) +{ + if (!paintable_widget.rect().contains(event.position())) + return; + + GPainter painter(paintable_widget.bitmap()); + auto target_color = paintable_widget.bitmap().get_pixel(event.x(), event.y()); + + flood_fill(paintable_widget.bitmap(), event.position(), target_color, paintable_widget.color_for(event)); + + paintable_widget.update(); +} diff --git a/Applications/PaintBrush/BucketTool.h b/Applications/PaintBrush/BucketTool.h new file mode 100644 index 0000000000..0c72c9e7f1 --- /dev/null +++ b/Applications/PaintBrush/BucketTool.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Tool.h" + +class BucketTool final : public Tool { +public: + BucketTool(); + virtual ~BucketTool() override; + + virtual void on_mousedown(PaintableWidget&, GMouseEvent&) override; + +private: + virtual const char* class_name() const override { return "BucketTool"; } +}; diff --git a/Applications/PaintBrush/Makefile b/Applications/PaintBrush/Makefile new file mode 100644 index 0000000000..2146f55ab7 --- /dev/null +++ b/Applications/PaintBrush/Makefile @@ -0,0 +1,28 @@ +include ../../Makefile.common + +OBJS = \ + PaintableWidget.o \ + PaletteWidget.o \ + ToolboxWidget.o \ + Tool.o \ + PenTool.o \ + BucketTool.o \ + main.o + +APP = PaintBrush + +DEFINES += -DUSERLAND + +all: $(APP) + +$(APP): $(OBJS) + $(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lgui -lcore -lc + +.cpp.o: + @echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $< + +-include $(OBJS:%.o=%.d) + +clean: + @echo "CLEAN"; rm -f $(APP) $(OBJS) *.d + diff --git a/Applications/PaintBrush/PaintableWidget.cpp b/Applications/PaintBrush/PaintableWidget.cpp new file mode 100644 index 0000000000..02ddc2da01 --- /dev/null +++ b/Applications/PaintBrush/PaintableWidget.cpp @@ -0,0 +1,60 @@ +#include "PaintableWidget.h" +#include "Tool.h" +#include +#include + +static PaintableWidget* s_the; + +PaintableWidget& PaintableWidget::the() +{ + return *s_the; +} + +PaintableWidget::PaintableWidget(GWidget* parent) + : GWidget(parent) +{ + ASSERT(!s_the); + s_the = this; + set_fill_with_background_color(true); + set_background_color(Color::MidGray); + m_bitmap = GraphicsBitmap::create(GraphicsBitmap::Format::RGB32, { 600, 400 }); + m_bitmap->fill(Color::White); +} + +PaintableWidget::~PaintableWidget() +{ +} + +void PaintableWidget::paint_event(GPaintEvent& event) +{ + GPainter painter(*this); + painter.add_clip_rect(event.rect()); + painter.blit({ 0, 0 }, *m_bitmap, m_bitmap->rect()); +} + +Color PaintableWidget::color_for(const GMouseEvent& event) +{ + if (event.buttons() & GMouseButton::Left) + return m_primary_color; + if (event.buttons() & GMouseButton::Right) + return m_secondary_color; + ASSERT_NOT_REACHED(); +} + +void PaintableWidget::mousedown_event(GMouseEvent& event) +{ + if (m_tool) + m_tool->on_mousedown(*this, event); +} + +void PaintableWidget::mouseup_event(GMouseEvent& event) +{ + if (m_tool) + m_tool->on_mouseup(*this, event); +} + +void PaintableWidget::mousemove_event(GMouseEvent& event) +{ + if (m_tool) + m_tool->on_mousemove(*this, event); +} diff --git a/Applications/PaintBrush/PaintableWidget.h b/Applications/PaintBrush/PaintableWidget.h new file mode 100644 index 0000000000..7734b60c24 --- /dev/null +++ b/Applications/PaintBrush/PaintableWidget.h @@ -0,0 +1,42 @@ +#pragma once + +#include + +class Tool; + +class PaintableWidget final : public GWidget { +public: + static PaintableWidget& the(); + + explicit PaintableWidget(GWidget* parent); + virtual ~PaintableWidget() override; + + virtual const char* class_name() const override { return "PaintableWidget"; } + + Color primary_color() const { return m_primary_color; } + Color secondary_color() const { return m_secondary_color; } + + void set_primary_color(Color color) { m_primary_color = color; } + void set_secondary_color(Color color) { m_secondary_color = color; } + + void set_tool(Tool* tool) { m_tool = tool; } + Tool* tool() { return m_tool; } + + Color color_for(const GMouseEvent&); + + GraphicsBitmap& bitmap() { return *m_bitmap; } + const GraphicsBitmap& bitmap() const { return *m_bitmap; } + +private: + virtual void paint_event(GPaintEvent&) override; + virtual void mousedown_event(GMouseEvent&) override; + virtual void mouseup_event(GMouseEvent&) override; + virtual void mousemove_event(GMouseEvent&) override; + + RetainPtr m_bitmap; + + Color m_primary_color { Color::Black }; + Color m_secondary_color { Color::White }; + + Tool* m_tool { nullptr }; +}; diff --git a/Applications/PaintBrush/PaletteWidget.cpp b/Applications/PaintBrush/PaletteWidget.cpp new file mode 100644 index 0000000000..ec3ff48e05 --- /dev/null +++ b/Applications/PaintBrush/PaletteWidget.cpp @@ -0,0 +1,131 @@ +#include "PaletteWidget.h" +#include "PaintableWidget.h" +#include + +class ColorWidget : public GFrame { +public: + explicit ColorWidget(Color color, PaletteWidget& palette_widget, GWidget* parent) + : GFrame(parent) + , m_palette_widget(palette_widget) + , m_color(color) + { + set_frame_thickness(2); + set_frame_shadow(FrameShadow::Sunken); + set_frame_shape(FrameShape::Container); + } + + virtual ~ColorWidget() override + { + } + + virtual void mousedown_event(GMouseEvent& event) override + { + if (event.button() == GMouseButton::Left) + m_palette_widget.set_primary_color(m_color); + else if (event.button() == GMouseButton::Right) + m_palette_widget.set_secondary_color(m_color); + } + +private: + PaletteWidget& m_palette_widget; + Color m_color; +}; + +PaletteWidget::PaletteWidget(PaintableWidget& paintable_widget, GWidget* parent) + : GFrame(parent) + , m_paintable_widget(paintable_widget) +{ + set_frame_shape(FrameShape::Panel); + set_frame_shadow(FrameShadow::Raised); + set_frame_thickness(0); + set_fill_with_background_color(true); + set_background_color(Color::LightGray); + + set_size_policy(SizePolicy::Fill, SizePolicy::Fixed); + set_preferred_size({ 0, 34 }); + + m_secondary_color_widget = new GFrame(this); + m_secondary_color_widget->set_frame_thickness(2); + m_secondary_color_widget->set_frame_shape(FrameShape::Container); + m_secondary_color_widget->set_frame_shadow(FrameShadow::Sunken); + m_secondary_color_widget->set_relative_rect({ 2, 2, 60, 31 }); + m_secondary_color_widget->set_fill_with_background_color(true); + set_secondary_color(paintable_widget.secondary_color()); + + m_primary_color_widget = new GFrame(this); + m_primary_color_widget->set_frame_thickness(2); + m_primary_color_widget->set_frame_shape(FrameShape::Container); + m_primary_color_widget->set_frame_shadow(FrameShadow::Sunken); + Rect rect { 0, 0, 38, 15 }; + rect.center_within(m_secondary_color_widget->relative_rect()); + m_primary_color_widget->set_relative_rect(rect); + m_primary_color_widget->set_fill_with_background_color(true); + set_primary_color(paintable_widget.primary_color()); + + auto* color_container = new GWidget(this); + color_container->set_relative_rect(m_secondary_color_widget->relative_rect().right() + 2, 2, 500, 32); + color_container->set_layout(make(Orientation::Vertical)); + color_container->layout()->set_spacing(1); + + auto* top_color_container = new GWidget(color_container); + top_color_container->set_layout(make(Orientation::Horizontal)); + top_color_container->layout()->set_spacing(1); + + auto* bottom_color_container = new GWidget(color_container); + bottom_color_container->set_layout(make(Orientation::Horizontal)); + bottom_color_container->layout()->set_spacing(1); + + auto add_color_widget = [&] (GWidget* container, Color color) { + auto* color_widget = new ColorWidget(color, *this, container); + color_widget->set_fill_with_background_color(true); + color_widget->set_background_color(color); + }; + + add_color_widget(top_color_container, Color::from_rgb(0x000000)); + add_color_widget(top_color_container, Color::from_rgb(0x808080)); + add_color_widget(top_color_container, Color::from_rgb(0x800000)); + add_color_widget(top_color_container, Color::from_rgb(0x808000)); + add_color_widget(top_color_container, Color::from_rgb(0x008000)); + add_color_widget(top_color_container, Color::from_rgb(0x008080)); + add_color_widget(top_color_container, Color::from_rgb(0x000080)); + add_color_widget(top_color_container, Color::from_rgb(0x800080)); + add_color_widget(top_color_container, Color::from_rgb(0x808040)); + add_color_widget(top_color_container, Color::from_rgb(0x004040)); + add_color_widget(top_color_container, Color::from_rgb(0x0080ff)); + add_color_widget(top_color_container, Color::from_rgb(0x004080)); + add_color_widget(top_color_container, Color::from_rgb(0x8000ff)); + add_color_widget(top_color_container, Color::from_rgb(0x804000)); + + add_color_widget(bottom_color_container, Color::from_rgb(0xffffff)); + add_color_widget(bottom_color_container, Color::from_rgb(0xc0c0c0)); + add_color_widget(bottom_color_container, Color::from_rgb(0xff0000)); + add_color_widget(bottom_color_container, Color::from_rgb(0xffff00)); + add_color_widget(bottom_color_container, Color::from_rgb(0x00ff00)); + add_color_widget(bottom_color_container, Color::from_rgb(0x00ffff)); + add_color_widget(bottom_color_container, Color::from_rgb(0x0000ff)); + add_color_widget(bottom_color_container, Color::from_rgb(0xff00ff)); + add_color_widget(bottom_color_container, Color::from_rgb(0xffff80)); + add_color_widget(bottom_color_container, Color::from_rgb(0x00ff80)); + add_color_widget(bottom_color_container, Color::from_rgb(0x80ffff)); + add_color_widget(bottom_color_container, Color::from_rgb(0x8080ff)); + add_color_widget(bottom_color_container, Color::from_rgb(0xff0080)); + add_color_widget(bottom_color_container, Color::from_rgb(0xff8040)); +} + +PaletteWidget::~PaletteWidget() +{ +} + +void PaletteWidget::set_primary_color(Color color) +{ + m_paintable_widget.set_primary_color(color); + m_primary_color_widget->set_background_color(color); + m_primary_color_widget->update(); +} + +void PaletteWidget::set_secondary_color(Color color) +{ + m_paintable_widget.set_secondary_color(color); + m_secondary_color_widget->set_background_color(color); + m_secondary_color_widget->update(); +} diff --git a/Applications/PaintBrush/PaletteWidget.h b/Applications/PaintBrush/PaletteWidget.h new file mode 100644 index 0000000000..dd7ce6d378 --- /dev/null +++ b/Applications/PaintBrush/PaletteWidget.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +class PaintableWidget; + +class PaletteWidget final : public GFrame { +public: + explicit PaletteWidget(PaintableWidget&, GWidget* parent); + virtual ~PaletteWidget() override; + + virtual const char* class_name() const override { return "PaletteWidget"; } + + void set_primary_color(Color); + void set_secondary_color(Color); + +private: + PaintableWidget& m_paintable_widget; + GFrame* m_primary_color_widget { nullptr }; + GFrame* m_secondary_color_widget { nullptr }; +}; diff --git a/Applications/PaintBrush/PenTool.cpp b/Applications/PaintBrush/PenTool.cpp new file mode 100644 index 0000000000..185ef430b5 --- /dev/null +++ b/Applications/PaintBrush/PenTool.cpp @@ -0,0 +1,48 @@ +#include "PenTool.h" +#include "PaintableWidget.h" +#include + +PenTool::PenTool() +{ +} + +PenTool::~PenTool() +{ +} + +void PenTool::on_mousedown(PaintableWidget& paintable_widget, GMouseEvent& event) +{ + if (event.button() != GMouseButton::Left && event.button() != GMouseButton::Right) + return; + + GPainter painter(paintable_widget.bitmap()); + painter.set_pixel(event.position(), paintable_widget.color_for(event)); + paintable_widget.update({ event.position(), { 1, 1 } }); + m_last_drawing_event_position = event.position(); +} + +void PenTool::on_mouseup(PaintableWidget&, GMouseEvent& event) +{ + if (event.button() == GMouseButton::Left || event.button() == GMouseButton::Right) + m_last_drawing_event_position = { -1, -1 }; +} + +void PenTool::on_mousemove(PaintableWidget& paintable_widget, GMouseEvent& event) +{ + if (!paintable_widget.rect().contains(event.position())) + return; + + if (event.buttons() & GMouseButton::Left || event.buttons() & GMouseButton::Right) { + GPainter painter(paintable_widget.bitmap()); + + if (m_last_drawing_event_position != Point(-1, -1)) { + painter.draw_line(m_last_drawing_event_position, event.position(), paintable_widget.color_for(event)); + paintable_widget.update(); + } else { + painter.set_pixel(event.position(), paintable_widget.color_for(event)); + paintable_widget.update({ event.position(), { 1, 1 } }); + } + + m_last_drawing_event_position = event.position(); + } +} diff --git a/Applications/PaintBrush/PenTool.h b/Applications/PaintBrush/PenTool.h new file mode 100644 index 0000000000..82c1ff2c07 --- /dev/null +++ b/Applications/PaintBrush/PenTool.h @@ -0,0 +1,19 @@ +#pragma once + +#include "Tool.h" +#include + +class PenTool final : public Tool { +public: + PenTool(); + virtual ~PenTool() override; + + virtual void on_mousedown(PaintableWidget&, GMouseEvent&) override; + virtual void on_mousemove(PaintableWidget&, GMouseEvent&) override; + virtual void on_mouseup(PaintableWidget&, GMouseEvent&) override; + +private: + virtual const char* class_name() const override { return "PenTool"; } + + Point m_last_drawing_event_position { -1, -1 }; +}; diff --git a/Applications/PaintBrush/Tool.cpp b/Applications/PaintBrush/Tool.cpp new file mode 100644 index 0000000000..52e711c48a --- /dev/null +++ b/Applications/PaintBrush/Tool.cpp @@ -0,0 +1,9 @@ +#include "Tool.h" + +Tool::Tool() +{ +} + +Tool::~Tool() +{ +} diff --git a/Applications/PaintBrush/Tool.h b/Applications/PaintBrush/Tool.h new file mode 100644 index 0000000000..c564cfb6a2 --- /dev/null +++ b/Applications/PaintBrush/Tool.h @@ -0,0 +1,18 @@ +#pragma once + +class GMouseEvent; +class PaintableWidget; + +class Tool { +public: + virtual ~Tool(); + + virtual const char* class_name() const = 0; + + virtual void on_mousedown(PaintableWidget&, GMouseEvent&) { } + virtual void on_mousemove(PaintableWidget&, GMouseEvent&) { } + virtual void on_mouseup(PaintableWidget&, GMouseEvent&) { } + +protected: + Tool(); +}; diff --git a/Applications/PaintBrush/ToolboxWidget.cpp b/Applications/PaintBrush/ToolboxWidget.cpp new file mode 100644 index 0000000000..1d13b51e9a --- /dev/null +++ b/Applications/PaintBrush/ToolboxWidget.cpp @@ -0,0 +1,64 @@ +#include "ToolboxWidget.h" +#include "BucketTool.h" +#include "PaintableWidget.h" +#include "PenTool.h" +#include +#include +#include + +class ToolButton final : public GButton { +public: + ToolButton(const String& name, GWidget* parent, OwnPtr&& tool) + : GButton(parent) + , m_tool(move(tool)) + { + set_tooltip(name); + } + + const Tool& tool() const { return *m_tool; } + Tool& tool() { return *m_tool; } + +private: + OwnPtr m_tool; +}; + +ToolboxWidget::ToolboxWidget(GWidget* parent) + : GFrame(parent) +{ + set_background_color(Color::LightGray); + set_fill_with_background_color(true); + + set_frame_thickness(1); + set_frame_shape(FrameShape::Panel); + set_frame_shadow(FrameShadow::Raised); + + set_size_policy(SizePolicy::Fixed, SizePolicy::Fill); + set_preferred_size({ 48, 0 }); + + set_layout(make(Orientation::Vertical)); + layout()->set_margins({ 4, 4, 4, 4 }); + + auto add_tool = [&](const StringView& name, const StringView& icon_name, OwnPtr&& tool) { + auto* button = new ToolButton(name, this, move(tool)); + button->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed); + button->set_preferred_size({ 0, 32 }); + button->set_checkable(true); + button->set_exclusive(true); + + button->set_icon(load_png(String::format("/res/icons/paintbrush/%s.png", icon_name.characters()))); + + button->on_checked = [button](auto checked) { + if (checked) + PaintableWidget::the().set_tool(&button->tool()); + else + PaintableWidget::the().set_tool(nullptr); + }; + }; + + add_tool("Pen", "pen", make()); + add_tool("Bucket Fill", "bucket", make()); +} + +ToolboxWidget::~ToolboxWidget() +{ +} diff --git a/Applications/PaintBrush/ToolboxWidget.h b/Applications/PaintBrush/ToolboxWidget.h new file mode 100644 index 0000000000..514803439e --- /dev/null +++ b/Applications/PaintBrush/ToolboxWidget.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +class ToolboxWidget final : public GFrame { +public: + explicit ToolboxWidget(GWidget* parent); + virtual ~ToolboxWidget() override; + + virtual const char* class_name() const override { return "ToolboxWidget"; } + +private: +}; diff --git a/Applications/PaintBrush/main.cpp b/Applications/PaintBrush/main.cpp new file mode 100644 index 0000000000..9e61c02ffa --- /dev/null +++ b/Applications/PaintBrush/main.cpp @@ -0,0 +1,58 @@ +#include "PaintableWidget.h" +#include "PaletteWidget.h" +#include "ToolboxWidget.h" +#include +#include +#include +#include +#include +#include + +int main(int argc, char** argv) +{ + GApplication app(argc, argv); + + auto* window = new GWindow; + window->set_title("PaintBrush"); + window->set_rect(100, 100, 640, 480); + + auto* horizontal_container = new GWidget(nullptr); + window->set_main_widget(horizontal_container); + horizontal_container->set_layout(make(Orientation::Horizontal)); + horizontal_container->layout()->set_spacing(0); + + auto* toolbox_widget = new ToolboxWidget(horizontal_container); + + auto* vertical_container = new GWidget(horizontal_container); + vertical_container->set_layout(make(Orientation::Vertical)); + vertical_container->layout()->set_spacing(0); + + auto* paintable_widget = new PaintableWidget(vertical_container); + auto* palette_widget = new PaletteWidget(*paintable_widget, vertical_container); + + window->show(); + + auto menubar = make(); + auto app_menu = make("PaintBrush"); + app_menu->add_action(GAction::create("Quit", { Mod_Alt, Key_F4 }, [](const GAction&) { + GApplication::the().quit(0); + return; + })); + menubar->add_menu(move(app_menu)); + + auto file_menu = make("File"); + menubar->add_menu(move(file_menu)); + + auto edit_menu = make("Edit"); + menubar->add_menu(move(edit_menu)); + + auto help_menu = make("Help"); + help_menu->add_action(GAction::create("About", [](const GAction&) { + dbgprintf("FIXME: Implement Help/About\n"); + })); + menubar->add_menu(move(help_menu)); + + app.set_menubar(move(menubar)); + + return app.exec(); +} diff --git a/Applications/ProcessManager/MemoryStatsWidget.cpp b/Applications/ProcessManager/MemoryStatsWidget.cpp index 0893b3483e..124636e795 100644 --- a/Applications/ProcessManager/MemoryStatsWidget.cpp +++ b/Applications/ProcessManager/MemoryStatsWidget.cpp @@ -1,8 +1,8 @@ #include "MemoryStatsWidget.h" #include "GraphWidget.h" -#include #include #include +#include #include #include #include @@ -21,7 +21,7 @@ MemoryStatsWidget::MemoryStatsWidget(GraphWidget& graph, GWidget* parent) layout()->set_margins({ 0, 8, 0, 0 }); layout()->set_spacing(3); - auto build_widgets_for_label = [this] (const String& description) -> GLabel* { + auto build_widgets_for_label = [this](const String& description) -> GLabel* { auto* container = new GWidget(this); container->set_layout(make(Orientation::Horizontal)); container->set_size_policy(SizePolicy::Fixed, SizePolicy::Fixed); diff --git a/Applications/ProcessManager/ProcessModel.cpp b/Applications/ProcessManager/ProcessModel.cpp index e9eae323dc..f7f7c86fed 100644 --- a/Applications/ProcessManager/ProcessModel.cpp +++ b/Applications/ProcessManager/ProcessModel.cpp @@ -2,8 +2,8 @@ #include "GraphWidget.h" #include #include -#include #include +#include ProcessModel::ProcessModel(GraphWidget& graph) : m_graph(graph) @@ -42,34 +42,56 @@ int ProcessModel::column_count(const GModelIndex&) const String ProcessModel::column_name(int column) const { switch (column) { - case Column::Icon: return ""; - case Column::PID: return "PID"; - case Column::State: return "State"; - case Column::User: return "User"; - case Column::Priority: return "Pr"; - case Column::Linear: return "Linear"; - case Column::Physical: return "Physical"; - case Column::CPU: return "CPU"; - case Column::Name: return "Name"; - case Column::Syscalls: return "Syscalls"; - default: ASSERT_NOT_REACHED(); + case Column::Icon: + return ""; + case Column::PID: + return "PID"; + case Column::State: + return "State"; + case Column::User: + return "User"; + case Column::Priority: + return "Pr"; + case Column::Virtual: + return "Virtual"; + case Column::Physical: + return "Physical"; + case Column::CPU: + return "CPU"; + case Column::Name: + return "Name"; + case Column::Syscalls: + return "Syscalls"; + default: + ASSERT_NOT_REACHED(); } } GModel::ColumnMetadata ProcessModel::column_metadata(int column) const { switch (column) { - case Column::Icon: return { 16, TextAlignment::CenterLeft }; - case Column::PID: return { 32, TextAlignment::CenterRight }; - case Column::State: return { 75, TextAlignment::CenterLeft }; - case Column::Priority: return { 16, TextAlignment::CenterLeft }; - case Column::User: return { 50, TextAlignment::CenterLeft }; - case Column::Linear: return { 65, TextAlignment::CenterRight }; - case Column::Physical: return { 65, TextAlignment::CenterRight }; - case Column::CPU: return { 32, TextAlignment::CenterRight }; - case Column::Name: return { 140, TextAlignment::CenterLeft }; - case Column::Syscalls: return { 60, TextAlignment::CenterRight }; - default: ASSERT_NOT_REACHED(); + case Column::Icon: + return { 16, TextAlignment::CenterLeft }; + case Column::PID: + return { 32, TextAlignment::CenterRight }; + case Column::State: + return { 75, TextAlignment::CenterLeft }; + case Column::Priority: + return { 16, TextAlignment::CenterLeft }; + case Column::User: + return { 50, TextAlignment::CenterLeft }; + case Column::Virtual: + return { 65, TextAlignment::CenterRight }; + case Column::Physical: + return { 65, TextAlignment::CenterRight }; + case Column::CPU: + return { 32, TextAlignment::CenterRight }; + case Column::Name: + return { 140, TextAlignment::CenterLeft }; + case Column::Syscalls: + return { 60, TextAlignment::CenterRight }; + default: + ASSERT_NOT_REACHED(); } } @@ -87,10 +109,14 @@ GVariant ProcessModel::data(const GModelIndex& index, Role role) const if (role == Role::Sort) { switch (index.column()) { - case Column::Icon: return 0; - case Column::PID: return process.current_state.pid; - case Column::State: return process.current_state.state; - case Column::User: return process.current_state.user; + case Column::Icon: + return 0; + case Column::PID: + return process.current_state.pid; + case Column::State: + return process.current_state.state; + case Column::User: + return process.current_state.user; case Column::Priority: if (process.current_state.priority == "Idle") return 0; @@ -102,23 +128,32 @@ GVariant ProcessModel::data(const GModelIndex& index, Role role) const return 3; ASSERT_NOT_REACHED(); return 3; - case Column::Linear: return (int)process.current_state.linear; - case Column::Physical: return (int)process.current_state.physical; - case Column::CPU: return process.current_state.cpu_percent; - case Column::Name: return process.current_state.name; + case Column::Virtual: + return (int)process.current_state.virtual_size; + case Column::Physical: + return (int)process.current_state.physical_size; + case Column::CPU: + return process.current_state.cpu_percent; + case Column::Name: + return process.current_state.name; // FIXME: GVariant with unsigned? - case Column::Syscalls: return (int)process.current_state.syscalls; + case Column::Syscalls: + return (int)process.current_state.syscalls; } ASSERT_NOT_REACHED(); - return { }; + return {}; } if (role == Role::Display) { switch (index.column()) { - case Column::Icon: return *m_generic_process_icon; - case Column::PID: return process.current_state.pid; - case Column::State: return process.current_state.state; - case Column::User: return process.current_state.user; + case Column::Icon: + return *m_generic_process_icon; + case Column::PID: + return process.current_state.pid; + case Column::State: + return process.current_state.state; + case Column::User: + return process.current_state.user; case Column::Priority: if (process.current_state.priority == "Idle") return String::empty(); @@ -129,16 +164,21 @@ GVariant ProcessModel::data(const GModelIndex& index, Role role) const if (process.current_state.priority == "Normal") return *m_normal_priority_icon; return process.current_state.priority; - case Column::Linear: return pretty_byte_size(process.current_state.linear); - case Column::Physical: return pretty_byte_size(process.current_state.physical); - case Column::CPU: return process.current_state.cpu_percent; - case Column::Name: return process.current_state.name; + case Column::Virtual: + return pretty_byte_size(process.current_state.virtual_size); + case Column::Physical: + return pretty_byte_size(process.current_state.physical_size); + case Column::CPU: + return process.current_state.cpu_percent; + case Column::Name: + return process.current_state.name; // FIXME: It's weird that GVariant doesn't support unsigned ints. Should it? - case Column::Syscalls: return (int)process.current_state.syscalls; + case Column::Syscalls: + return (int)process.current_state.syscalls; } } - return { }; + return {}; } void ProcessModel::update() @@ -181,9 +221,9 @@ void ProcessModel::update() ASSERT(ok); state.state = parts[7]; state.name = parts[11]; - state.linear = parts[12].to_uint(ok); + state.virtual_size = parts[12].to_uint(ok); ASSERT(ok); - state.physical = parts[13].to_uint(ok); + state.physical_size = parts[13].to_uint(ok); ASSERT(ok); sum_nsched += nsched; { diff --git a/Applications/ProcessManager/ProcessModel.h b/Applications/ProcessManager/ProcessModel.h index 3f6b18b111..cebe524d26 100644 --- a/Applications/ProcessManager/ProcessModel.h +++ b/Applications/ProcessManager/ProcessModel.h @@ -11,8 +11,7 @@ class GraphWidget; class ProcessModel final : public GModel { public: - enum Column - { + enum Column { Icon = 0, Name, CPU, @@ -20,7 +19,7 @@ public: Priority, User, PID, - Linear, + Virtual, Physical, Syscalls, __Count @@ -48,8 +47,8 @@ private: String state; String user; String priority; - size_t linear; - size_t physical; + size_t virtual_size; + size_t physical_size; unsigned syscalls; float cpu_percent; }; diff --git a/Applications/ProcessManager/main.cpp b/Applications/ProcessManager/main.cpp index 68bd660ac9..d39ad0e934 100644 --- a/Applications/ProcessManager/main.cpp +++ b/Applications/ProcessManager/main.cpp @@ -1,20 +1,20 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ProcessTableView.h" -#include "MemoryStatsWidget.h" #include "GraphWidget.h" +#include "MemoryStatsWidget.h" +#include "ProcessTableView.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include int main(int argc, char** argv) { @@ -46,7 +46,7 @@ int main(int argc, char** argv) cpu_graph->set_max(100); cpu_graph->set_text_color(Color::Green); cpu_graph->set_graph_color(Color::from_rgb(0x00bb00)); - cpu_graph->text_formatter = [] (int value, int) { + cpu_graph->text_formatter = [](int value, int) { return String::format("%d%%", value); }; @@ -58,7 +58,7 @@ int main(int argc, char** argv) auto* memory_graph = new GraphWidget(memory_graph_group_box); memory_graph->set_text_color(Color::Cyan); memory_graph->set_graph_color(Color::from_rgb(0x00bbbb)); - memory_graph->text_formatter = [] (int value, int max) { + memory_graph->text_formatter = [](int value, int max) { return String::format("%d / %d KB", value, max); }; @@ -78,19 +78,19 @@ int main(int argc, char** argv) memory_stats_widget->refresh(); }); - auto kill_action = GAction::create("Kill process", GraphicsBitmap::load_from_file("/res/icons/kill16.png"), [process_table_view] (const GAction&) { + auto kill_action = GAction::create("Kill process", GraphicsBitmap::load_from_file("/res/icons/kill16.png"), [process_table_view](const GAction&) { pid_t pid = process_table_view->selected_pid(); if (pid != -1) kill(pid, SIGKILL); }); - auto stop_action = GAction::create("Stop process", GraphicsBitmap::load_from_file("/res/icons/stop16.png"), [process_table_view] (const GAction&) { + auto stop_action = GAction::create("Stop process", GraphicsBitmap::load_from_file("/res/icons/stop16.png"), [process_table_view](const GAction&) { pid_t pid = process_table_view->selected_pid(); if (pid != -1) kill(pid, SIGSTOP); }); - auto continue_action = GAction::create("Continue process", GraphicsBitmap::load_from_file("/res/icons/continue16.png"), [process_table_view] (const GAction&) { + auto continue_action = GAction::create("Continue process", GraphicsBitmap::load_from_file("/res/icons/continue16.png"), [process_table_view](const GAction&) { pid_t pid = process_table_view->selected_pid(); if (pid != -1) kill(pid, SIGCONT); @@ -102,7 +102,7 @@ int main(int argc, char** argv) auto menubar = make(); auto app_menu = make("Process Manager"); - app_menu->add_action(GAction::create("Quit", { Mod_Alt, Key_F4 }, [] (const GAction&) { + app_menu->add_action(GAction::create("Quit", { Mod_Alt, Key_F4 }, [](const GAction&) { GApplication::the().quit(0); return; })); @@ -115,25 +115,25 @@ int main(int argc, char** argv) menubar->add_menu(move(process_menu)); auto frequency_menu = make("Frequency"); - frequency_menu->add_action(GAction::create("0.25 sec", [refresh_timer] (auto&) { + frequency_menu->add_action(GAction::create("0.25 sec", [refresh_timer](auto&) { refresh_timer->restart(250); })); - frequency_menu->add_action(GAction::create("0.5 sec", [refresh_timer] (auto&) { + frequency_menu->add_action(GAction::create("0.5 sec", [refresh_timer](auto&) { refresh_timer->restart(500); })); - frequency_menu->add_action(GAction::create("1 sec", [refresh_timer] (auto&) { + frequency_menu->add_action(GAction::create("1 sec", [refresh_timer](auto&) { refresh_timer->restart(1000); })); - frequency_menu->add_action(GAction::create("3 sec", [refresh_timer] (auto&) { + frequency_menu->add_action(GAction::create("3 sec", [refresh_timer](auto&) { refresh_timer->restart(3000); })); - frequency_menu->add_action(GAction::create("5 sec", [refresh_timer] (auto&) { + frequency_menu->add_action(GAction::create("5 sec", [refresh_timer](auto&) { refresh_timer->restart(5000); })); menubar->add_menu(move(frequency_menu)); auto help_menu = make("Help"); - help_menu->add_action(GAction::create("About", [] (const GAction&) { + help_menu->add_action(GAction::create("About", [](const GAction&) { dbgprintf("FIXME: Implement Help/About\n"); })); menubar->add_menu(move(help_menu)); diff --git a/Applications/Taskbar/TaskbarButton.cpp b/Applications/Taskbar/TaskbarButton.cpp index c7e2f60fdc..18c7c57749 100644 --- a/Applications/Taskbar/TaskbarButton.cpp +++ b/Applications/Taskbar/TaskbarButton.cpp @@ -1,8 +1,8 @@ #include "TaskbarButton.h" -#include #include -#include #include +#include +#include static void set_window_minimized_state(const WindowIdentifier& identifier, bool minimized) { @@ -34,13 +34,13 @@ GMenu& TaskbarButton::ensure_menu() { if (!m_menu) { m_menu = make(""); - m_menu->add_action(GAction::create("Minimize", [this] (auto&) { + m_menu->add_action(GAction::create("Minimize", [this](auto&) { set_window_minimized_state(m_identifier, true); })); - m_menu->add_action(GAction::create("Unminimize", [this] (auto&) { + m_menu->add_action(GAction::create("Unminimize", [this](auto&) { set_window_minimized_state(m_identifier, false); })); - m_menu->add_action(GAction::create("Close", [this] (auto&) { + m_menu->add_action(GAction::create("Close", [this](auto&) { dbgprintf("FIXME: Close!\n"); })); } diff --git a/Applications/Taskbar/TaskbarWindow.cpp b/Applications/Taskbar/TaskbarWindow.cpp index c8189c1940..25207e4883 100644 --- a/Applications/Taskbar/TaskbarWindow.cpp +++ b/Applications/Taskbar/TaskbarWindow.cpp @@ -1,11 +1,11 @@ #include "TaskbarWindow.h" #include "TaskbarButton.h" -#include -#include -#include #include #include +#include +#include #include +#include #include #include @@ -19,7 +19,7 @@ TaskbarWindow::TaskbarWindow() on_screen_rect_change(GDesktop::the().rect()); - GDesktop::the().on_rect_change = [this] (const Rect& rect) { on_screen_rect_change(rect); }; + GDesktop::the().on_rect_change = [this](const Rect& rect) { on_screen_rect_change(rect); }; auto* widget = new GFrame; widget->set_fill_with_background_color(true); @@ -31,7 +31,7 @@ TaskbarWindow::TaskbarWindow() widget->set_frame_shadow(FrameShadow::Raised); set_main_widget(widget); - WindowList::the().aid_create_button = [this] (auto& identifier) { + WindowList::the().aid_create_button = [this](auto& identifier) { return create_button(identifier); }; } @@ -70,8 +70,7 @@ void TaskbarWindow::wm_event(GWMEvent& event) auto& removed_event = static_cast(event); dbgprintf("WM_WindowRemoved: client_id=%d, window_id=%d\n", removed_event.client_id(), - removed_event.window_id() - ); + removed_event.window_id()); #endif WindowList::the().remove_window(identifier); update(); @@ -83,8 +82,7 @@ void TaskbarWindow::wm_event(GWMEvent& event) dbgprintf("WM_WindowRectChanged: client_id=%d, window_id=%d, rect=%s\n", changed_event.client_id(), changed_event.window_id(), - changed_event.rect().to_string().characters() - ); + changed_event.rect().to_string().characters()); #endif break; } @@ -94,8 +92,7 @@ void TaskbarWindow::wm_event(GWMEvent& event) dbgprintf("WM_WindowIconChanged: client_id=%d, window_id=%d, icon_path=%s\n", changed_event.client_id(), changed_event.window_id(), - changed_event.icon_path().characters() - ); + changed_event.icon_path().characters()); #endif if (auto* window = WindowList::the().window(identifier)) { window->set_icon_path(changed_event.icon_path()); @@ -113,8 +110,7 @@ void TaskbarWindow::wm_event(GWMEvent& event) changed_event.title().characters(), changed_event.rect().to_string().characters(), changed_event.is_active(), - changed_event.is_minimized() - ); + changed_event.is_minimized()); #endif if (!should_include_window(changed_event.window_type())) break; diff --git a/Applications/Taskbar/WindowList.cpp b/Applications/Taskbar/WindowList.cpp index dc1b8da90a..6147ed1e92 100644 --- a/Applications/Taskbar/WindowList.cpp +++ b/Applications/Taskbar/WindowList.cpp @@ -1,6 +1,6 @@ #include "WindowList.h" -#include #include +#include WindowList& WindowList::the() { @@ -25,7 +25,7 @@ Window& WindowList::ensure_window(const WindowIdentifier& identifier) return *it->value; auto window = make(identifier); window->set_button(aid_create_button(identifier)); - window->button()->on_click = [window = window.ptr(), identifier] (GButton&) { + window->button()->on_click = [window = window.ptr(), identifier](GButton&) { WSAPI_ClientMessage message; if (window->is_minimized() || !window->is_active()) { message.type = WSAPI_ClientMessage::Type::WM_SetActiveWindow; diff --git a/Applications/Taskbar/main.cpp b/Applications/Taskbar/main.cpp index d30f756f17..73356d2588 100644 --- a/Applications/Taskbar/main.cpp +++ b/Applications/Taskbar/main.cpp @@ -1,5 +1,5 @@ -#include #include "TaskbarWindow.h" +#include int main(int argc, char** argv) { diff --git a/Applications/Terminal/.gitignore b/Applications/Terminal/.gitignore index 1029333f8d..e804885307 100644 --- a/Applications/Terminal/.gitignore +++ b/Applications/Terminal/.gitignore @@ -1,3 +1,4 @@ *.o *.d Terminal +compile_commands.json diff --git a/Applications/Terminal/Terminal.cpp b/Applications/Terminal/Terminal.cpp index 4e568dab07..94720d8f62 100644 --- a/Applications/Terminal/Terminal.cpp +++ b/Applications/Terminal/Terminal.cpp @@ -1,19 +1,19 @@ #include "Terminal.h" #include "XtermColors.h" -#include -#include -#include -#include -#include #include -#include -#include -#include #include -#include -#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include //#define TERMINAL_DEBUG byte Terminal::Attribute::default_foreground_color = 7; @@ -30,8 +30,8 @@ Terminal::Terminal(int ptm_fd, RetainPtr config) dbgprintf("Terminal: Load config file from %s\n", m_config->file_name().characters()); m_cursor_blink_timer.set_interval(m_config->read_num_entry("Text", - "CursorBlinkInterval", - 500)); + "CursorBlinkInterval", + 500)); m_cursor_blink_timer.on_timeout = [this] { m_cursor_blink_state = !m_cursor_blink_state; update_cursor(); @@ -43,7 +43,7 @@ Terminal::Terminal(int ptm_fd, RetainPtr config) else set_font(Font::load_from_file(font_entry)); - m_notifier.on_ready_to_read = [this]{ + m_notifier.on_ready_to_read = [this] { byte buffer[BUFSIZ]; ssize_t nread = read(m_ptm_fd, buffer, sizeof(buffer)); if (nread < 0) { @@ -65,37 +65,48 @@ Terminal::Terminal(int ptm_fd, RetainPtr config) m_line_height = font().glyph_height() + m_line_spacing; set_size(m_config->read_num_entry("Window", "Width", 80), - m_config->read_num_entry("Window", "Height", 25)); + m_config->read_num_entry("Window", "Height", 25)); } -Terminal::Line::Line(word columns) - : length(columns) +Terminal::Line::Line(word length) { - characters = new byte[length]; - attributes = new Attribute[length]; - memset(characters, ' ', length); + set_length(length); } Terminal::Line::~Line() { - delete [] characters; - delete [] attributes; + delete[] characters; + delete[] attributes; +} + +void Terminal::Line::set_length(word new_length) +{ + if (m_length == new_length) + return; + auto* new_characters = new byte[new_length]; + auto* new_attributes = new Attribute[new_length]; + memset(new_characters, ' ', new_length); + delete[] characters; + delete[] attributes; + characters = new_characters; + attributes = new_attributes; + m_length = new_length; } void Terminal::Line::clear(Attribute attribute) { if (dirty) { - memset(characters, ' ', length); - for (word i = 0 ; i < length; ++i) + memset(characters, ' ', m_length); + for (word i = 0; i < m_length; ++i) attributes[i] = attribute; return; } - for (unsigned i = 0 ; i < length; ++i) { + for (unsigned i = 0; i < m_length; ++i) { if (characters[i] != ' ') dirty = true; characters[i] = ' '; } - for (unsigned i = 0 ; i < length; ++i) { + for (unsigned i = 0; i < m_length; ++i) { if (attributes[i] != attribute) dirty = true; attributes[i] = attribute; @@ -104,10 +115,6 @@ void Terminal::Line::clear(Attribute attribute) Terminal::~Terminal() { - for (int i = 0; i < m_rows; ++i) - delete m_lines[i]; - delete [] m_lines; - free(m_horizontal_tabs); } void Terminal::clear() @@ -137,6 +144,35 @@ static inline Color lookup_color(unsigned color) return Color::from_rgb(xterm_colors[color]); } +void Terminal::escape$h_l(bool should_set, bool question_param, const ParamVector& params) +{ + int mode = 2; + if (params.size() > 0) { + mode = params[0]; + } + if (!question_param) { + switch (mode) { + // FIXME: implement *something* for this + default: + unimplemented_escape(); + break; + } + } else { + switch (mode) { + case 25: + // Hide cursor command, but doesn't need to be run (for now, because + // we don't do inverse control codes anyways) + if (should_set) + dbgprintf("Terminal: Hide Cursor escapecode recieved. Not needed: ignored.\n"); + else + dbgprintf("Terminal: Show Cursor escapecode recieved. Not needed: ignored.\n"); + break; + default: + break; + } + } +} + void Terminal::escape$m(const ParamVector& params) { if (params.is_empty()) { @@ -243,7 +279,7 @@ void Terminal::escape$t(const ParamVector& params) { if (params.size() < 1) return; - dbgprintf("FIXME: escape$t: Ps: %u\n", params[0]); + dbgprintf("FIXME: escape$t: Ps: %u (param count: %d)\n", params[0], params.size()); } void Terminal::escape$r(const ParamVector& params) @@ -254,7 +290,13 @@ void Terminal::escape$r(const ParamVector& params) top = params[0]; if (params.size() >= 2) bottom = params[1]; - dbgprintf("FIXME: escape$r: Set scrolling region: %u-%u\n", top, bottom); + if ((bottom - top) < 2 || bottom > m_rows || top < 0) { + dbgprintf("Error: escape$r: scrolling region invalid: %u-%u\n", top, bottom); + return; + } + m_scroll_region_top = top - 1; + m_scroll_region_bottom = bottom - 1; + set_cursor(0, 0); } void Terminal::escape$H(const ParamVector& params) @@ -330,6 +372,15 @@ void Terminal::escape$G(const ParamVector& params) set_cursor(m_cursor_row, new_column); } +void Terminal::escape$b(const ParamVector& params) +{ + if (params.size() < 1) + return; + + for (unsigned i = 0; i < params[0]; ++i) + put_character_at(m_cursor_row, m_cursor_column++, m_last_char); +} + void Terminal::escape$d(const ParamVector& params) { int new_row = 1; @@ -373,7 +424,10 @@ void Terminal::escape$K(const ParamVector& params) } break; case 2: - unimplemented_escape(); + // Clear the complete line + for (int i = 0; i < m_columns; ++i) { + put_character_at(m_cursor_row, i, ' '); + } break; default: unimplemented_escape(); @@ -389,9 +443,8 @@ void Terminal::escape$J(const ParamVector& params) switch (mode) { case 0: // Clear from cursor to end of screen. - for (int i = m_cursor_column; i < m_columns; ++i) { + for (int i = m_cursor_column; i < m_columns; ++i) put_character_at(m_cursor_row, i, ' '); - } for (int row = m_cursor_row + 1; row < m_rows; ++row) { for (int column = 0; column < m_columns; ++column) { put_character_at(row, column, ' '); @@ -399,8 +452,14 @@ void Terminal::escape$J(const ParamVector& params) } break; case 1: - // FIXME: Clear from cursor to beginning of screen. - unimplemented_escape(); + /// Clear from cursor to beginning of screen + for (int i = m_cursor_column - 1; i >= 0; --i) + put_character_at(m_cursor_row, i, ' '); + for (int row = m_cursor_row - 1; row >= 0; --row) { + for (int column = 0; column < m_columns; ++column) { + put_character_at(row, column, ' '); + } + } break; case 2: clear(); @@ -415,6 +474,42 @@ void Terminal::escape$J(const ParamVector& params) } } +void Terminal::escape$S(const ParamVector& params) +{ + int count = 1; + if (params.size() >= 1) + count = params[0]; + + for (word i = 0; i < count; i++) + scroll_up(); +} + +void Terminal::escape$T(const ParamVector& params) +{ + int count = 1; + if (params.size() >= 1) + count = params[0]; + + for (word i = 0; i < count; i++) + scroll_down(); +} + +void Terminal::escape$L(const ParamVector& params) +{ + int count = 1; + if (params.size() >= 1) + count = params[0]; + invalidate_cursor(); + for (; count > 0; --count) { + m_lines.insert(m_cursor_row + m_scroll_region_top, make(m_columns)); + if (m_scroll_region_bottom + 1 < m_lines.size()) + m_lines.remove(m_scroll_region_bottom + 1); + else + m_lines.remove(m_lines.size() - 1); + } + m_need_full_flush = true; +} + void Terminal::escape$M(const ParamVector& params) { int count = 1; @@ -426,12 +521,38 @@ void Terminal::escape$M(const ParamVector& params) return; } - int max_count = m_rows - m_cursor_row; + int max_count = m_rows - (m_scroll_region_top + m_cursor_row); count = min(count, max_count); - dbgprintf("Delete %d line(s) starting from %d\n", count, m_cursor_row); - // FIXME: Implement. - ASSERT_NOT_REACHED(); + for (int c = count; c > 0; --c) { + m_lines.remove(m_cursor_row + m_scroll_region_top); + if (m_scroll_region_bottom < m_lines.size()) + m_lines.insert(m_scroll_region_bottom, make(m_columns)); + else + m_lines.append(make(m_columns)); + } +} + +void Terminal::escape$P(const ParamVector& params) +{ + int num = 1; + if (params.size() >= 1) + num = params[0]; + + if (num == 0) + num = 1; + + auto& line = this->line(m_cursor_row); + + // Move n characters of line to the left + for (int i = m_cursor_column; i < line.m_length - num; i++) + line.characters[i] = line.characters[i + num]; + + // Fill remainder of line with blanks + for (int i = line.m_length - num; i < line.m_length; i++) + line.characters[i] = ' '; + + line.dirty = true; } void Terminal::execute_xterm_command() @@ -457,42 +578,122 @@ void Terminal::execute_xterm_command() void Terminal::execute_escape_sequence(byte final) { + bool question_param = false; m_final = final; - auto paramparts = String::copy(m_parameters).split(';'); ParamVector params; + + if (m_parameters.size() > 0 && m_parameters[0] == '?') { + question_param = true; + m_parameters.remove(0); + } + auto paramparts = String::copy(m_parameters).split(';'); for (auto& parampart : paramparts) { bool ok; unsigned value = parampart.to_uint(ok); if (!ok) { + // FIXME: Should we do something else? m_parameters.clear_with_capacity(); m_intermediates.clear_with_capacity(); - // FIXME: Should we do something else? return; } params.append(value); } + +#if defined(TERMINAL_DEBUG) + dbgprintf("Terminal::execute_escape_sequence: Handled final '%c'\n", final); + dbgprintf("Params: "); + for (auto& p : params) { + dbgprintf("%d ", p); + } + dbgprintf("\b\n"); +#endif + switch (final) { - case 'A': escape$A(params); break; - case 'B': escape$B(params); break; - case 'C': escape$C(params); break; - case 'D': escape$D(params); break; - case 'H': escape$H(params); break; - case 'J': escape$J(params); break; - case 'K': escape$K(params); break; - case 'M': escape$M(params); break; - case 'G': escape$G(params); break; - case 'X': escape$X(params); break; - case 'd': escape$d(params); break; - case 'm': escape$m(params); break; - case 's': escape$s(params); break; - case 'u': escape$u(params); break; - case 't': escape$t(params); break; - case 'r': escape$r(params); break; + case 'A': + escape$A(params); + break; + case 'B': + escape$B(params); + break; + case 'C': + escape$C(params); + break; + case 'D': + escape$D(params); + break; + case 'H': + escape$H(params); + break; + case 'J': + escape$J(params); + break; + case 'K': + escape$K(params); + break; + case 'M': + escape$M(params); + break; + case 'P': + escape$P(params); + break; + case 'S': + escape$S(params); + break; + case 'T': + escape$T(params); + break; + case 'L': + escape$L(params); + break; + case 'G': + escape$G(params); + break; + case 'X': + escape$X(params); + break; + case 'b': + escape$b(params); + break; + case 'd': + escape$d(params); + break; + case 'm': + escape$m(params); + break; + case 's': + escape$s(params); + break; + case 'u': + escape$u(params); + break; + case 't': + escape$t(params); + break; + case 'r': + escape$r(params); + break; + case 'l': + escape$h_l(true, question_param, params); + break; + case 'h': + escape$h_l(false, question_param, params); + break; default: dbgprintf("Terminal::execute_escape_sequence: Unhandled final '%c'\n", final); break; } +#if defined(TERMINAL_DEBUG) + dbgprintf("\n"); + for (auto& line : m_lines) { + dbgprintf("Terminal: Line: "); + for (int i = 0; i < line->length; i++) { + dbgprintf("%c", line->characters[i]); + } + dbgprintf("\n"); + } +#endif + m_parameters.clear_with_capacity(); m_intermediates.clear_with_capacity(); } @@ -500,7 +701,7 @@ void Terminal::execute_escape_sequence(byte final) void Terminal::newline() { word new_row = m_cursor_row; - if (m_cursor_row == (rows() - 1)) { + if (m_cursor_row == m_scroll_region_bottom) { scroll_up(); } else { ++new_row; @@ -512,11 +713,17 @@ void Terminal::scroll_up() { // NOTE: We have to invalidate the cursor first. invalidate_cursor(); - delete m_lines[0]; - for (word row = 1; row < rows(); ++row) - m_lines[row - 1] = m_lines[row]; - m_lines[m_rows - 1] = new Line(m_columns); - ++m_rows_to_scroll_backing_store; + m_lines.remove(m_scroll_region_top); + m_lines.insert(m_scroll_region_bottom, make(m_columns)); + m_need_full_flush = true; +} + +void Terminal::scroll_down() +{ + // NOTE: We have to invalidate the cursor first. + invalidate_cursor(); + m_lines.remove(m_scroll_region_bottom); + m_lines.insert(m_scroll_region_top, make(m_columns)); m_need_full_flush = true; } @@ -531,7 +738,7 @@ void Terminal::set_cursor(unsigned a_row, unsigned a_column) invalidate_cursor(); m_cursor_row = row; m_cursor_column = column; - if (column != columns() - 1) + if (column != columns() - 1u) m_stomp = false; invalidate_cursor(); } @@ -541,11 +748,11 @@ void Terminal::put_character_at(unsigned row, unsigned column, byte ch) ASSERT(row < rows()); ASSERT(column < columns()); auto& line = this->line(row); - if ((line.characters[column] == ch) && (line.attributes[column] == m_current_attribute)) - return; line.characters[column] = ch; line.attributes[column] = m_current_attribute; line.dirty = true; + + m_last_char = ch; } void Terminal::on_char(byte ch) @@ -628,7 +835,16 @@ void Terminal::on_char(byte ch) } return; case '\a': - sysbeep(); + if (m_should_beep) + sysbeep(); + else { + m_visual_beep_timer.restart(200); + m_visual_beep_timer.set_single_shot(true); + m_visual_beep_timer.on_timeout = [this] { + force_repaint(); + }; + force_repaint(); + } return; case '\t': { for (unsigned i = m_cursor_column; i < columns(); ++i) { @@ -700,39 +916,43 @@ void Terminal::set_size(word columns, word rows) if (columns == m_columns && rows == m_rows) return; - if (m_lines) { - for (size_t i = 0; i < m_rows; ++i) - delete m_lines[i]; - delete m_lines; +#if defined(TERMINAL_DEBUG) + dbgprintf("Terminal: RESIZE to: %d rows\n", rows); +#endif + + if (rows > m_rows) { + while (m_lines.size() < rows) + m_lines.append(make(columns)); + } else { + m_lines.resize(rows); } + for (int i = 0; i < rows; ++i) + m_lines[i]->set_length(columns); + m_columns = columns; m_rows = rows; + m_scroll_region_top = 0; + m_scroll_region_bottom = rows - 1; + m_cursor_row = 0; m_cursor_column = 0; m_saved_cursor_row = 0; m_saved_cursor_column = 0; - if (m_horizontal_tabs) - free(m_horizontal_tabs); - m_horizontal_tabs = static_cast(malloc(columns)); + m_horizontal_tabs.resize(columns); for (unsigned i = 0; i < columns; ++i) m_horizontal_tabs[i] = (i % 8) == 0; // Rightmost column is always last tab on line. m_horizontal_tabs[columns - 1] = 1; - m_lines = new Line*[rows]; - for (size_t i = 0; i < rows; ++i) - m_lines[i] = new Line(columns); - m_pixel_width = (frame_thickness() * 2) + (m_inset * 2) + (m_columns * font().glyph_width('x')); m_pixel_height = (frame_thickness() * 2) + (m_inset * 2) + (m_rows * (font().glyph_height() + m_line_spacing)) - m_line_spacing; set_size_policy(SizePolicy::Fixed, SizePolicy::Fixed); set_preferred_size({ m_pixel_width, m_pixel_height }); - m_rows_to_scroll_backing_store = 0; m_needs_background_fill = true; force_repaint(); @@ -760,11 +980,11 @@ Rect Terminal::row_rect(word row) bool Terminal::Line::has_only_one_background_color() const { - if (!length) + if (!m_length) return true; // FIXME: Cache this result? auto color = attributes[0].background_color; - for (size_t i = 1; i < length; ++i) { + for (size_t i = 1; i < m_length; ++i) { if (attributes[i].background_color != color) return false; } @@ -816,6 +1036,11 @@ void Terminal::keydown_event(GKeyEvent& event) case KeyCode::Key_End: write(m_ptm_fd, "\033[F", 3); break; + case KeyCode::Key_RightShift: + // Prevent RightShift from being sent to whatever's running in the + // terminal. Prevents `~@` (null) character from being sent after every + // character entered with right shift. + break; default: write(m_ptm_fd, &ch, 1); break; @@ -823,45 +1048,28 @@ void Terminal::keydown_event(GKeyEvent& event) } void Terminal::paint_event(GPaintEvent& event) -{ +{ GFrame::paint_event(event); GPainter painter(*this); - if (m_needs_background_fill) { - m_needs_background_fill = false; + if (m_visual_beep_timer.is_active()) + painter.fill_rect(frame_inner_rect(), Color::Red); + else painter.fill_rect(frame_inner_rect(), Color(Color::Black).with_alpha(255 * m_opacity)); - } - - if (m_rows_to_scroll_backing_store && m_rows_to_scroll_backing_store < m_rows) { - int first_scanline = m_inset; - int second_scanline = m_inset + (m_rows_to_scroll_backing_store * m_line_height); - int num_rows_to_memcpy = m_rows - m_rows_to_scroll_backing_store; - int scanlines_to_copy = (num_rows_to_memcpy * m_line_height) - m_line_spacing; - memcpy( - painter.target()->scanline(first_scanline), - painter.target()->scanline(second_scanline), - scanlines_to_copy * painter.target()->pitch() - ); - line(max(0, m_cursor_row - m_rows_to_scroll_backing_store)).dirty = true; - } - m_rows_to_scroll_backing_store = 0; - invalidate_cursor(); for (word row = 0; row < m_rows; ++row) { auto& line = this->line(row); - if (!line.dirty) - continue; - line.dirty = false; bool has_only_one_background_color = line.has_only_one_background_color(); - if (has_only_one_background_color) { + if (m_visual_beep_timer.is_active()) + painter.fill_rect(row_rect(row), Color::Red); + else if (has_only_one_background_color) painter.fill_rect(row_rect(row), lookup_color(line.attributes[0].background_color).with_alpha(255 * m_opacity)); - } for (word column = 0; column < m_columns; ++column) { + char ch = line.characters[column]; bool should_reverse_fill_for_cursor = m_cursor_blink_state && m_in_active_window && row == m_cursor_row && column == m_cursor_column; auto& attribute = line.attributes[column]; - char ch = line.characters[column]; auto character_rect = glyph_rect(row, column); if (!has_only_one_background_color || should_reverse_fill_for_cursor) { auto cell_rect = character_rect.inflated(0, m_line_spacing); @@ -877,9 +1085,6 @@ void Terminal::paint_event(GPaintEvent& event) auto cell_rect = glyph_rect(m_cursor_row, m_cursor_column).inflated(0, m_line_spacing); painter.draw_rect(cell_rect, lookup_color(line(m_cursor_row).attributes[m_cursor_column].foreground_color)); } - - if (m_belling) - painter.draw_rect(frame_inner_rect(), Color::Red); } void Terminal::set_window_title(const String& title) diff --git a/Applications/Terminal/Terminal.h b/Applications/Terminal/Terminal.h index 13b3440cfd..d631416bf6 100644 --- a/Applications/Terminal/Terminal.h +++ b/Applications/Terminal/Terminal.h @@ -26,6 +26,9 @@ public: void apply_size_increments_to_window(GWindow&); void set_opacity(float); + float opacity() { return m_opacity; }; + bool should_beep() { return m_should_beep; } + void set_should_beep(bool sb) { m_should_beep = sb; }; RetainPtr config() const { return m_config; } @@ -39,6 +42,7 @@ private: virtual const char* class_name() const override { return "Terminal"; } void scroll_up(); + void scroll_down(); void newline(); void set_cursor(unsigned row, unsigned column); void put_character_at(unsigned row, unsigned column, byte ch); @@ -57,14 +61,20 @@ private: void escape$J(const ParamVector&); void escape$K(const ParamVector&); void escape$M(const ParamVector&); + void escape$P(const ParamVector&); void escape$G(const ParamVector&); void escape$X(const ParamVector&); + void escape$b(const ParamVector&); void escape$d(const ParamVector&); void escape$m(const ParamVector&); void escape$s(const ParamVector&); void escape$u(const ParamVector&); void escape$t(const ParamVector&); void escape$r(const ParamVector&); + void escape$S(const ParamVector&); + void escape$T(const ParamVector&); + void escape$L(const ParamVector&); + void escape$h_l(bool, bool, const ParamVector&); void clear(); @@ -118,10 +128,11 @@ private: ~Line(); void clear(Attribute); bool has_only_one_background_color() const; + void set_length(word); byte* characters { nullptr }; Attribute* attributes { nullptr }; bool dirty { false }; - word length { 0 }; + word m_length { 0 }; }; Line& line(size_t index) { @@ -129,7 +140,10 @@ private: return *m_lines[index]; } - Line** m_lines { nullptr }; + Vector> m_lines; + + int m_scroll_region_top { 0 }; + int m_scroll_region_bottom { 0 }; word m_columns { 0 }; word m_rows { 0 }; @@ -140,13 +154,14 @@ private: byte m_saved_cursor_column { 0 }; bool m_stomp { false }; + bool m_should_beep { false }; + Attribute m_current_attribute; void execute_escape_sequence(byte final); void execute_xterm_command(); - enum EscapeState - { + enum EscapeState { Normal, ExpectBracket, ExpectParameter, @@ -162,13 +177,12 @@ private: Vector m_intermediates; Vector m_xterm_param1; Vector m_xterm_param2; + Vector m_horizontal_tabs; byte m_final { 0 }; - byte* m_horizontal_tabs { nullptr }; bool m_belling { false }; int m_pixel_width { 0 }; int m_pixel_height { 0 }; - int m_rows_to_scroll_backing_store { 0 }; int m_inset { 2 }; int m_line_spacing { 4 }; @@ -190,5 +204,8 @@ private: int m_glyph_width { 0 }; CTimer m_cursor_blink_timer; + CTimer m_visual_beep_timer; RetainPtr m_config; + + byte m_last_char { 0 }; }; diff --git a/Applications/Terminal/main.cpp b/Applications/Terminal/main.cpp index 2cf5f5dbf1..e78eb11332 100644 --- a/Applications/Terminal/main.cpp +++ b/Applications/Terminal/main.cpp @@ -1,23 +1,26 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include "Terminal.h" #include +#include +#include #include +#include +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include static void make_shell(int ptm_fd) { @@ -36,7 +39,7 @@ static void make_shell(int ptm_fd) } // NOTE: It's okay if this fails. - (void) ioctl(0, TIOCNOTTY); + (void)ioctl(0, TIOCNOTTY); close(0); close(1); @@ -78,6 +81,54 @@ static void make_shell(int ptm_fd) } } +GWindow* create_settings_window(Terminal& terminal, RetainPtr config) +{ + auto* window = new GWindow; + window->set_title("Terminal Settings"); + window->set_rect(50, 50, 200, 140); + + auto* settings = new GWidget; + window->set_main_widget(settings); + settings->set_fill_with_background_color(true); + settings->set_layout(make(Orientation::Vertical)); + settings->layout()->set_margins({ 4, 4, 4, 4 }); + + auto* radio_container = new GGroupBox("Bell Mode", settings); + radio_container->set_layout(make(Orientation::Vertical)); + radio_container->layout()->set_margins({ 6, 16, 6, 6 }); + radio_container->set_fill_with_background_color(true); + radio_container->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed); + radio_container->set_preferred_size({ 100, 70 }); + + auto* sysbell_radio = new GRadioButton("Use (Audible) System Bell", radio_container); + auto* visbell_radio = new GRadioButton("Use (Visual) Terminal Bell", radio_container); + sysbell_radio->set_checked(terminal.should_beep()); + visbell_radio->set_checked(!terminal.should_beep()); + sysbell_radio->on_checked = [&terminal](const bool checked) { + terminal.set_should_beep(checked); + }; + + auto* slider_container = new GGroupBox("Background Opacity", settings); + slider_container->set_layout(make(Orientation::Vertical)); + slider_container->layout()->set_margins({ 6, 16, 6, 6 }); + slider_container->set_fill_with_background_color(true); + slider_container->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed); + slider_container->set_preferred_size({ 100, 50 }); + auto* slider = new GSlider(slider_container); + slider->set_fill_with_background_color(true); + slider->set_background_color(Color::LightGray); + + slider->on_value_changed = [&terminal, &config](int value) { + float opacity = value / 100.0; + terminal.set_opacity(opacity); + }; + + slider->set_range(0, 100); + slider->set_value(terminal.opacity() * 100.0); + + return window; +} + int main(int argc, char** argv) { GApplication app(argc, argv); @@ -106,23 +157,9 @@ int main(int argc, char** argv) terminal.apply_size_increments_to_window(*window); window->show(); window->set_icon_path("/res/icons/16x16/app-terminal.png"); + terminal.set_should_beep(config->read_bool_entry("Window", "AudibleBeep", false)); - auto* opacity_adjustment_window = new GWindow; - opacity_adjustment_window->set_title("Adjust opacity"); - opacity_adjustment_window->set_rect(50, 50, 200, 100); - - auto* slider = new GSlider(nullptr); - opacity_adjustment_window->set_main_widget(slider); - slider->set_fill_with_background_color(true); - slider->set_background_color(Color::LightGray); - - slider->on_value_changed = [&terminal, &config] (int value) { - float opacity = value / 100.0; - terminal.set_opacity(opacity); - }; - - slider->set_range(0, 100); - slider->set_value(100); + WeakPtr settings_window; auto new_opacity = config->read_num_entry("Window", "Opacity", 255); terminal.set_opacity((float)new_opacity / 255.0); @@ -130,10 +167,14 @@ int main(int argc, char** argv) auto menubar = make(); auto app_menu = make("Terminal"); - app_menu->add_action(GAction::create("Adjust opacity...", [opacity_adjustment_window] (const GAction&) { - opacity_adjustment_window->show(); - })); - app_menu->add_action(GAction::create("Quit", { Mod_Alt, Key_F4 }, [] (const GAction&) { + app_menu->add_action(GAction::create("Settings...", + [&settings_window, &terminal, &config](const GAction&) { + if (!settings_window) + settings_window = create_settings_window(terminal, config)->make_weak_ptr(); + settings_window->show(); + settings_window->move_to_front(); + })); + app_menu->add_action(GAction::create("Quit", { Mod_Alt, Key_F4 }, [](const GAction&) { dbgprintf("Terminal: Quit menu activated!\n"); GApplication::the().quit(0); return; @@ -141,8 +182,8 @@ int main(int argc, char** argv) menubar->add_menu(move(app_menu)); auto font_menu = make("Font"); - GFontDatabase::the().for_each_fixed_width_font([&] (const String& font_name) { - font_menu->add_action(GAction::create(font_name, [&terminal, &config] (const GAction& action) { + GFontDatabase::the().for_each_fixed_width_font([&](const StringView& font_name) { + font_menu->add_action(GAction::create(font_name, [&terminal, &config](const GAction& action) { terminal.set_font(GFontDatabase::the().get_by_name(action.text())); auto metadata = GFontDatabase::the().get_metadata_by_name(action.text()); config->write_entry("Text", "Font", metadata.path); @@ -153,7 +194,7 @@ int main(int argc, char** argv) menubar->add_menu(move(font_menu)); auto help_menu = make("Help"); - help_menu->add_action(GAction::create("About", [] (const GAction&) { + help_menu->add_action(GAction::create("About", [](const GAction&) { dbgprintf("FIXME: Implement Help/About\n"); })); menubar->add_menu(move(help_menu)); diff --git a/Applications/TextEditor/main.cpp b/Applications/TextEditor/main.cpp index 4b868a6a51..04bc938636 100644 --- a/Applications/TextEditor/main.cpp +++ b/Applications/TextEditor/main.cpp @@ -1,21 +1,21 @@ -#include -#include -#include +#include +#include +#include #include +#include #include +#include +#include #include #include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include #include +#include +#include +#include void open_sesame(GWindow& window, GTextEditor& editor, const String& path) { @@ -57,7 +57,7 @@ int main(int argc, char** argv) open_sesame(*window, *text_editor, path); } - auto new_action = GAction::create("New document", { Mod_Ctrl, Key_N }, GraphicsBitmap::load_from_file("/res/icons/16x16/new.png"), [] (const GAction&) { + auto new_action = GAction::create("New document", { Mod_Ctrl, Key_N }, GraphicsBitmap::load_from_file("/res/icons/16x16/new.png"), [](const GAction&) { dbgprintf("FIXME: Implement File/New\n"); }); @@ -69,14 +69,14 @@ int main(int argc, char** argv) } }); - auto save_action = GAction::create("Save document", { Mod_Ctrl, Key_S }, GraphicsBitmap::load_from_file("/res/icons/16x16/save.png"), [&] (const GAction&) { + auto save_action = GAction::create("Save document", { Mod_Ctrl, Key_S }, GraphicsBitmap::load_from_file("/res/icons/16x16/save.png"), [&](const GAction&) { dbgprintf("Writing document to '%s'\n", path.characters()); text_editor->write_to_file(path); }); auto menubar = make(); auto app_menu = make("Text Editor"); - app_menu->add_action(GAction::create("Quit", { Mod_Alt, Key_F4 }, [] (const GAction&) { + app_menu->add_action(GAction::create("Quit", { Mod_Alt, Key_F4 }, [](const GAction&) { GApplication::the().quit(0); return; })); @@ -99,8 +99,8 @@ int main(int argc, char** argv) menubar->add_menu(move(edit_menu)); auto font_menu = make("Font"); - GFontDatabase::the().for_each_fixed_width_font([&] (const String& font_name) { - font_menu->add_action(GAction::create(font_name, [text_editor] (const GAction& action) { + GFontDatabase::the().for_each_fixed_width_font([&](const StringView& font_name) { + font_menu->add_action(GAction::create(font_name, [text_editor](const GAction& action) { text_editor->set_font(GFontDatabase::the().get_by_name(action.text())); text_editor->update(); })); @@ -108,7 +108,7 @@ int main(int argc, char** argv) menubar->add_menu(move(font_menu)); auto help_menu = make("Help"); - help_menu->add_action(GAction::create("About", [] (const GAction&) { + help_menu->add_action(GAction::create("About", [](const GAction&) { dbgprintf("FIXME: Implement Help/About\n"); })); menubar->add_menu(move(help_menu)); diff --git a/Base/etc/LookupServer.ini b/Base/etc/LookupServer.ini index b0504773c4..8ee1c6619e 100644 --- a/Base/etc/LookupServer.ini +++ b/Base/etc/LookupServer.ini @@ -1,3 +1,2 @@ [DNS] IPAddress=8.8.8.8 - diff --git a/Base/etc/hosts b/Base/etc/hosts new file mode 100644 index 0000000000..ba712fe033 --- /dev/null +++ b/Base/etc/hosts @@ -0,0 +1 @@ +127.0.0.1 localhost diff --git a/Base/home/anon/Terminal.ini b/Base/home/anon/Terminal.ini index 824c296d39..2ccb03acf0 100644 --- a/Base/home/anon/Terminal.ini +++ b/Base/home/anon/Terminal.ini @@ -1,2 +1,3 @@ [Window] Opacity=255 +AudibleBeep=0 diff --git a/Base/home/anon/WindowManager.ini b/Base/home/anon/WindowManager.ini index ed3b007148..e4b29dab4a 100644 --- a/Base/home/anon/WindowManager.ini +++ b/Base/home/anon/WindowManager.ini @@ -1,5 +1,5 @@ [Screen] -Width=1080 +Width=1024 Height=768 [Cursor] @@ -36,4 +36,4 @@ MenuSelectionColor=132,53,26 DoubleClickSpeed=250 [Background] -Mode=center +Mode=scaled diff --git a/Base/res/icons/16x16/app-demo.png b/Base/res/icons/16x16/app-demo.png new file mode 100644 index 0000000000..b0e2faffe2 Binary files /dev/null and b/Base/res/icons/16x16/app-demo.png differ diff --git a/Base/res/icons/paintbrush/bucket.png b/Base/res/icons/paintbrush/bucket.png new file mode 100644 index 0000000000..7c4082e2ac Binary files /dev/null and b/Base/res/icons/paintbrush/bucket.png differ diff --git a/Base/res/icons/paintbrush/pen.png b/Base/res/icons/paintbrush/pen.png new file mode 100644 index 0000000000..5bfbd1a715 Binary files /dev/null and b/Base/res/icons/paintbrush/pen.png differ diff --git a/Demos/Fire/.gitignore b/Demos/Fire/.gitignore new file mode 100644 index 0000000000..7a47f816fa --- /dev/null +++ b/Demos/Fire/.gitignore @@ -0,0 +1,3 @@ +Fire +*.o +*.d diff --git a/Demos/Fire/Fire.cpp b/Demos/Fire/Fire.cpp new file mode 100644 index 0000000000..0407b9ffc3 --- /dev/null +++ b/Demos/Fire/Fire.cpp @@ -0,0 +1,236 @@ +/* Fire.cpp - a (classic) graphics demo for Serenity, by pd. + * heavily based on the Fabien Sanglard's article: + * http://fabiensanglard.net/doom_fire_psx/index.html + * + * Future directions: + * [X] This does suggest the need for a palletized graphics surface. Thanks kling! + * [X] alternate column updates, or vertical interlacing. this would certainly alter + * the effect, but the update load would be halved. + * [/] scaled blit + * [ ] dithering? + * [X] inlining rand() + * [/] precalculating and recycling random data + * [ ] rework/expand palette + * [ ] switch to use tsc values for perf check + * [ ] handle mouse events differently for smoother painting (queue) + * [ ] handle fire bitmap edges better +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FIRE_WIDTH 320 +#define FIRE_HEIGHT 168 +#define FIRE_MAX 29 + +const Color palette[] = { + Color(0x07, 0x07, 0x07), Color(0x1F, 0x07, 0x07), Color(0x2F, 0x0F, 0x07), + Color(0x47, 0x0F, 0x07), Color(0x57, 0x17, 0x07), Color(0x67, 0x1F, 0x07), + Color(0x77, 0x1F, 0x07), Color(0x9F, 0x2F, 0x07), Color(0xAF, 0x3F, 0x07), + Color(0xBF, 0x47, 0x07), Color(0xC7, 0x47, 0x07), Color(0xDF, 0x4F, 0x07), + Color(0xDF, 0x57, 0x07), Color(0xD7, 0x5F, 0x07), Color(0xD7, 0x5F, 0x07), + Color(0xD7, 0x67, 0x0F), Color(0xCF, 0x6F, 0x0F), Color(0xCF, 0x7F, 0x0F), + Color(0xCF, 0x87, 0x17), Color(0xC7, 0x87, 0x17), Color(0xC7, 0x8F, 0x17), + Color(0xC7, 0x97, 0x1F), Color(0xBF, 0x9F, 0x1F), Color(0xBF, 0xA7, 0x27), + Color(0xBF, 0xAF, 0x2F), Color(0xB7, 0xAF, 0x2F), Color(0xB7, 0xB7, 0x37), + Color(0xCF, 0xCF, 0x6F), Color(0xEF, 0xEF, 0xC7), Color(0xFF, 0xFF, 0xFF) +}; + +/* Random functions... + * These are from musl libc's prng/rand.c +*/ +static uint64_t seed; + +void my_srand(unsigned s) +{ + seed = s - 1; +} + +static int my_rand(void) +{ + seed = 6364136223846793005ULL * seed + 1; + return seed >> 33; +} + +/* + * Fire Widget +*/ +class Fire : public GWidget { +public: + explicit Fire(GWidget* parent = nullptr); + virtual ~Fire() override; + void set_stat_label(GLabel* l) { stats = l; }; + +private: + RetainPtr bitmap; + GLabel* stats; + + virtual void paint_event(GPaintEvent&) override; + virtual void timer_event(CTimerEvent&) override; + virtual void mousedown_event(GMouseEvent& event) override; + virtual void mousemove_event(GMouseEvent& event) override; + virtual void mouseup_event(GMouseEvent& event) override; + + bool dragging; + int timeAvg; + int cycles; + int phase; +}; + +Fire::Fire(GWidget* parent) + : GWidget(parent) +{ + bitmap = GraphicsBitmap::create(GraphicsBitmap::Format::Indexed8, { 320, 200 }); + + /* Initialize fire palette */ + for (int i = 0; i < 30; i++) + bitmap->set_palette_color(i, palette[i]); + + /* Set remaining entries to white */ + for (int i = 30; i < 256; i++) + bitmap->set_palette_color(i, Color::White); + + dragging = false; + timeAvg = 0; + cycles = 0; + phase = 0; + + my_srand(time(nullptr)); + stop_timer(); + start_timer(20); + + /* Draw fire "source" on bottom row of pixels */ + for (int i = 0; i < FIRE_WIDTH; i++) + bitmap->bits(bitmap->height() - 1)[i] = FIRE_MAX; + + /* Set off initital paint event */ + //update(); +} + +Fire::~Fire() +{ +} + +void Fire::paint_event(GPaintEvent& event) +{ + CElapsedTimer timer; + timer.start(); + + GPainter painter(*this); + painter.add_clip_rect(event.rect()); + + /* Blit it! */ + painter.draw_scaled_bitmap(event.rect(), *bitmap, bitmap->rect()); + + timeAvg += timer.elapsed(); + cycles++; +} + +void Fire::timer_event(CTimerEvent&) +{ + /* Update only even or odd columns per frame... */ + phase++; + if (phase > 1) + phase = 0; + + /* Paint our palettized buffer to screen */ + for (int px = 0 + phase; px < FIRE_WIDTH; px += 2) { + for (int py = 1; py < 200; py++) { + int rnd = my_rand() % 3; + + /* Calculate new pixel value, don't go below 0 */ + byte nv = bitmap->bits(py)[px]; + if (nv > 0) + nv -= (rnd & 1); + + /* ...sigh... */ + int epx = px + (1 - rnd); + if (epx < 0) + epx = 0; + else if (epx > FIRE_WIDTH) + epx = FIRE_WIDTH; + + bitmap->bits(py - 1)[epx] = nv; + } + } + + if ((cycles % 50) == 0) { + dbgprintf("%d total cycles. finished 50 in %d ms, avg %d ms\n", cycles, timeAvg, timeAvg / 50); + stats->set_text(String::format("%d ms", timeAvg / 50)); + timeAvg = 0; + } + + update(); +} + +/* + * Mouse handling events +*/ +void Fire::mousedown_event(GMouseEvent& event) +{ + if (event.button() == GMouseButton::Left) + dragging = true; + + return GWidget::mousedown_event(event); +} + +/* FIXME: needs to account for the size of the window rect */ +void Fire::mousemove_event(GMouseEvent& event) +{ + if (dragging) { + if (event.y() >= 2 && event.y() < 398 && event.x() <= 638) { + int ypos = event.y() / 2; + int xpos = event.x() / 2; + bitmap->bits(ypos - 1)[xpos] = FIRE_MAX + 5; + bitmap->bits(ypos - 1)[xpos + 1] = FIRE_MAX + 5; + bitmap->bits(ypos)[xpos] = FIRE_MAX + 5; + bitmap->bits(ypos)[xpos + 1] = FIRE_MAX + 5; + } + } + + return GWidget::mousemove_event(event); +} + +void Fire::mouseup_event(GMouseEvent& event) +{ + if (event.button() == GMouseButton::Left) + dragging = false; + + return GWidget::mouseup_event(event); +} + +/* + * Main +*/ +int main(int argc, char** argv) +{ + GApplication app(argc, argv); + + auto* window = new GWindow; + window->set_should_exit_event_loop_on_close(true); + window->set_double_buffering_enabled(false); + window->set_title("Fire"); + window->set_resizable(false); + window->set_rect(100, 100, 640, 400); + + auto* fire = new Fire; + window->set_main_widget(fire); + + auto* time = new GLabel(fire); + time->set_relative_rect({ 0, 4, 40, 10 }); + time->move_by({ window->width() - time->width(), 0 }); + time->set_foreground_color(Color::from_rgb(0x444444)); + fire->set_stat_label(time); + + window->show(); + window->set_icon_path("/res/icons/16x16/app-demo.png"); + + return app.exec(); +} diff --git a/Demos/Fire/Makefile b/Demos/Fire/Makefile new file mode 100644 index 0000000000..2bfd381499 --- /dev/null +++ b/Demos/Fire/Makefile @@ -0,0 +1,22 @@ +include ../../Makefile.common + +OBJS = \ + Fire.o + +APP = Fire + +DEFINES += -DUSERLAND + +all: $(APP) + +$(APP): $(OBJS) + $(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lgui -lcore -lc + +.cpp.o: + @echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $< + +-include $(OBJS:%.o=%.d) + +clean: + @echo "CLEAN"; rm -f $(APP) $(OBJS) *.d + diff --git a/Demos/HelloWorld/main.cpp b/Demos/HelloWorld/main.cpp index a66b3490e5..3598868b8f 100644 --- a/Demos/HelloWorld/main.cpp +++ b/Demos/HelloWorld/main.cpp @@ -1,9 +1,9 @@ #include -#include -#include -#include -#include #include +#include +#include +#include +#include int main(int argc, char** argv) { @@ -27,7 +27,7 @@ int main(int argc, char** argv) button->set_text("Good-bye"); button->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed); button->set_preferred_size({ 0, 20 }); - button->on_click = [&] (GButton&) { + button->on_click = [&](GButton&) { app.quit(); }; diff --git a/Demos/PaintTest/main.cpp b/Demos/PaintTest/main.cpp index 2174afe9c4..4a2f9fd860 100644 --- a/Demos/PaintTest/main.cpp +++ b/Demos/PaintTest/main.cpp @@ -1,13 +1,16 @@ #include -#include -#include #include +#include +#include #include class TestWidget final : public GWidget { public: - TestWidget(GWidget* parent) : GWidget(parent) { } - virtual ~TestWidget() override { } + TestWidget(GWidget* parent) + : GWidget(parent) + { + } + virtual ~TestWidget() override {} void set_bitmap(RetainPtr&& bitmap) { diff --git a/Demos/RetroFetch/main.cpp b/Demos/RetroFetch/main.cpp index 1b0abfdf08..4e465d67b5 100644 --- a/Demos/RetroFetch/main.cpp +++ b/Demos/RetroFetch/main.cpp @@ -1,8 +1,8 @@ +#include +#include #include #include #include -#include -#include static void moveto(int row, int column) { @@ -68,4 +68,3 @@ int main() printf("\033[u\n"); return 0; } - diff --git a/Demos/WidgetGallery/main.cpp b/Demos/WidgetGallery/main.cpp index 81f219b51e..a97d08899f 100644 --- a/Demos/WidgetGallery/main.cpp +++ b/Demos/WidgetGallery/main.cpp @@ -1,18 +1,18 @@ +#include #include -#include -#include -#include -#include #include +#include #include -#include -#include +#include +#include #include +#include #include #include #include -#include -#include +#include +#include +#include int main(int argc, char** argv) { diff --git a/DevTools/VisualBuilder/VBForm.cpp b/DevTools/VisualBuilder/VBForm.cpp index aac6e8f122..9472b1b631 100644 --- a/DevTools/VisualBuilder/VBForm.cpp +++ b/DevTools/VisualBuilder/VBForm.cpp @@ -1,11 +1,11 @@ #include "VBForm.h" -#include "VBWidget.h" #include "VBProperty.h" -#include -#include -#include -#include +#include "VBWidget.h" #include +#include +#include +#include +#include static VBForm* s_current; VBForm* VBForm::current() @@ -39,15 +39,15 @@ VBForm::VBForm(const String& name, GWidget* parent) m_widgets.append(move(groupbox1)); m_context_menu = make("Context menu"); - m_context_menu->add_action(GAction::create("Move to front", [this] (auto&) { + m_context_menu->add_action(GAction::create("Move to front", [this](auto&) { if (auto* widget = single_selected_widget()) widget->gwidget()->move_to_front(); })); - m_context_menu->add_action(GAction::create("Move to back", [this] (auto&) { + m_context_menu->add_action(GAction::create("Move to back", [this](auto&) { if (auto* widget = single_selected_widget()) widget->gwidget()->move_to_back(); })); - m_context_menu->add_action(GAction::create("Delete", [this] (auto&) { + m_context_menu->add_action(GAction::create("Delete", [this](auto&) { delete_selected_widgets(); })); } @@ -88,7 +88,7 @@ void VBForm::second_paint_event(GPaintEvent& event) for (auto& widget : m_widgets) { if (widget->is_selected()) { - for_each_direction([&] (Direction direction) { + for_each_direction([&](Direction direction) { painter.fill_rect(widget->grabber_rect(direction), Color::Black); }); } @@ -112,7 +112,7 @@ VBWidget* VBForm::widget_at(const Point& position) void VBForm::grabber_mousedown_event(GMouseEvent& event, Direction grabber) { m_transform_event_origin = event.position(); - for_each_selected_widget([] (auto& widget) { widget.capture_transform_origin_rect(); }); + for_each_selected_widget([](auto& widget) { widget.capture_transform_origin_rect(); }); m_resize_direction = grabber; } @@ -146,19 +146,19 @@ void VBForm::keydown_event(GKeyEvent& event) switch (event.key()) { case KeyCode::Key_Up: update(); - for_each_selected_widget([this] (auto& widget) { widget.gwidget()->move_by(0, -m_grid_size); }); + for_each_selected_widget([this](auto& widget) { widget.gwidget()->move_by(0, -m_grid_size); }); break; case KeyCode::Key_Down: update(); - for_each_selected_widget([this] (auto& widget) { widget.gwidget()->move_by(0, m_grid_size); }); + for_each_selected_widget([this](auto& widget) { widget.gwidget()->move_by(0, m_grid_size); }); break; case KeyCode::Key_Left: update(); - for_each_selected_widget([this] (auto& widget) { widget.gwidget()->move_by(-m_grid_size, 0); }); + for_each_selected_widget([this](auto& widget) { widget.gwidget()->move_by(-m_grid_size, 0); }); break; case KeyCode::Key_Right: update(); - for_each_selected_widget([this] (auto& widget) { widget.gwidget()->move_by(m_grid_size, 0); }); + for_each_selected_widget([this](auto& widget) { widget.gwidget()->move_by(m_grid_size, 0); }); break; } return; @@ -197,7 +197,7 @@ void VBForm::mousedown_event(GMouseEvent& event) { if (m_resize_direction == Direction::None) { bool hit_grabber = false; - for_each_selected_widget([&] (auto& widget) { + for_each_selected_widget([&](auto& widget) { auto grabber = widget.grabber_at(event.position()); if (grabber != Direction::None) { hit_grabber = true; @@ -220,7 +220,7 @@ void VBForm::mousedown_event(GMouseEvent& event) add_to_selection(*widget); else if (!m_selected_widgets.contains(widget)) set_single_selected_widget(widget); - for_each_selected_widget([] (auto& widget) { widget.capture_transform_origin_rect(); }); + for_each_selected_widget([](auto& widget) { widget.capture_transform_origin_rect(); }); on_widget_selected(single_selected_widget()); } } @@ -231,7 +231,7 @@ void VBForm::mousemove_event(GMouseEvent& event) if (m_resize_direction == Direction::None) { update(); auto delta = event.position() - m_transform_event_origin; - for_each_selected_widget([&] (auto& widget) { + for_each_selected_widget([&](auto& widget) { auto new_rect = widget.transform_origin_rect().translated(delta); new_rect.set_x(new_rect.x() - (new_rect.x() % m_grid_size)); new_rect.set_y(new_rect.y() - (new_rect.y() % m_grid_size)); @@ -287,7 +287,7 @@ void VBForm::mousemove_event(GMouseEvent& event) } update(); - for_each_selected_widget([&] (auto& widget) { + for_each_selected_widget([&](auto& widget) { auto new_rect = widget.transform_origin_rect(); Size minimum_size { 5, 5 }; new_rect.set_x(new_rect.x() + change_x); @@ -316,7 +316,7 @@ void VBForm::write_to_file(const String& path) int i = 0; for (auto& widget : m_widgets) { file.printf("[Widget %d]\n", i++); - widget->for_each_property([&] (auto& property) { + widget->for_each_property([&](auto& property) { file.printf("%s=%s\n", property.name().characters(), property.value().to_string().characters()); }); file.printf("\n"); @@ -331,7 +331,7 @@ void VBForm::dump() int i = 0; for (auto& widget : m_widgets) { dbgprintf("[Widget %d]\n", i++); - widget->for_each_property([] (auto& property) { + widget->for_each_property([](auto& property) { dbgprintf("%s=%s\n", property.name().characters(), property.value().to_string().characters()); }); dbgprintf("\n"); @@ -341,7 +341,7 @@ void VBForm::dump() void VBForm::mouseup_event(GMouseEvent& event) { if (event.button() == GMouseButton::Left) { - m_transform_event_origin = { }; + m_transform_event_origin = {}; m_resize_direction = Direction::None; } } @@ -349,11 +349,11 @@ void VBForm::mouseup_event(GMouseEvent& event) void VBForm::delete_selected_widgets() { Vector to_delete; - for_each_selected_widget([&] (auto& widget) { + for_each_selected_widget([&](auto& widget) { to_delete.append(&widget); }); for (auto& widget : to_delete) - m_widgets.remove_first_matching([&widget] (auto& entry) { return entry == widget; } ); + m_widgets.remove_first_matching([&widget](auto& entry) { return entry == widget; }); on_widget_selected(single_selected_widget()); } diff --git a/DevTools/VisualBuilder/VBPropertiesWindow.cpp b/DevTools/VisualBuilder/VBPropertiesWindow.cpp index 29733fb3a9..146389a19e 100644 --- a/DevTools/VisualBuilder/VBPropertiesWindow.cpp +++ b/DevTools/VisualBuilder/VBPropertiesWindow.cpp @@ -1,8 +1,8 @@ #include "VBPropertiesWindow.h" -#include #include #include #include +#include VBPropertiesWindow::VBPropertiesWindow() { diff --git a/DevTools/VisualBuilder/VBWidget.cpp b/DevTools/VisualBuilder/VBWidget.cpp index 084cddbaf4..886b05fbd1 100644 --- a/DevTools/VisualBuilder/VBWidget.cpp +++ b/DevTools/VisualBuilder/VBWidget.cpp @@ -1,18 +1,19 @@ #include "VBWidget.h" #include "VBForm.h" #include "VBProperty.h" -#include "VBWidgetRegistry.h" #include "VBWidgetPropertyModel.h" -#include -#include +#include "VBWidgetRegistry.h" #include +#include +#include +#include +#include +#include +#include #include +#include #include #include -#include -#include -#include -#include VBWidget::VBWidget(VBWidgetType type, VBForm& form) : m_type(type) @@ -78,7 +79,7 @@ Rect VBWidget::grabber_rect(Direction direction) const Direction VBWidget::grabber_at(const Point& position) const { Direction found_grabber = Direction::None; - for_each_direction([&] (Direction direction) { + for_each_direction([&](Direction direction) { if (grabber_rect(direction).contains(position)) found_grabber = direction; }); @@ -99,11 +100,10 @@ void VBWidget::add_property(const String& name, Function GVariant { return ((const gclass&)widget).getter(); }, \ - [] (auto& widget, auto& value) { ((gclass&)widget).setter(value.to_ ## variant_type()); } \ - ) +#define VB_ADD_PROPERTY(gclass, name, getter, setter, variant_type) \ + add_property(name, \ + [](auto& widget) -> GVariant { return ((const gclass&)widget).getter(); }, \ + [](auto& widget, auto& value) { ((gclass&)widget).setter(value.to_##variant_type()); }) void VBWidget::setup_properties() { @@ -161,9 +161,14 @@ void VBWidget::setup_properties() } if (m_type == VBWidgetType::GCheckBox) { - VB_ADD_PROPERTY(GCheckBox, "caption", text, set_text, string); + VB_ADD_PROPERTY(GCheckBox, "text", text, set_text, string); VB_ADD_PROPERTY(GCheckBox, "checked", is_checked, set_checked, bool); } + + if (m_type == VBWidgetType::GRadioButton) { + VB_ADD_PROPERTY(GRadioButton, "text", text, set_text, string); + VB_ADD_PROPERTY(GRadioButton, "checked", is_checked, set_checked, bool); + } } void VBWidget::synchronize_properties() diff --git a/DevTools/VisualBuilder/VBWidget.h b/DevTools/VisualBuilder/VBWidget.h index 7395157098..8717e519d3 100644 --- a/DevTools/VisualBuilder/VBWidget.h +++ b/DevTools/VisualBuilder/VBWidget.h @@ -15,8 +15,7 @@ class VBForm; class VBProperty; class VBWidgetPropertyModel; -enum class Direction -{ +enum class Direction { None, Left, UpLeft, diff --git a/DevTools/VisualBuilder/VBWidgetPropertyModel.cpp b/DevTools/VisualBuilder/VBWidgetPropertyModel.cpp index 0a4935c660..5bee6870cb 100644 --- a/DevTools/VisualBuilder/VBWidgetPropertyModel.cpp +++ b/DevTools/VisualBuilder/VBWidgetPropertyModel.cpp @@ -1,6 +1,6 @@ #include "VBWidgetPropertyModel.h" -#include "VBWidget.h" #include "VBProperty.h" +#include "VBWidget.h" #include VBWidgetPropertyModel::VBWidgetPropertyModel(VBWidget& widget) @@ -20,9 +20,12 @@ int VBWidgetPropertyModel::row_count(const GModelIndex&) const String VBWidgetPropertyModel::column_name(int column) const { switch (column) { - case Column::Name: return "Name"; - case Column::Value: return "Value"; - default: ASSERT_NOT_REACHED(); + case Column::Name: + return "Name"; + case Column::Value: + return "Value"; + default: + ASSERT_NOT_REACHED(); } } @@ -39,20 +42,24 @@ GVariant VBWidgetPropertyModel::data(const GModelIndex& index, Role role) const if (role == Role::Display) { auto& property = *m_widget.m_properties[index.row()]; switch (index.column()) { - case Column::Name: return property.name(); - case Column::Value: return property.value(); + case Column::Name: + return property.name(); + case Column::Value: + return property.value(); } ASSERT_NOT_REACHED(); } if (role == Role::ForegroundColor) { auto& property = *m_widget.m_properties[index.row()]; switch (index.column()) { - case Column::Name: return Color::Black; - case Column::Value: return property.is_readonly() ? Color(Color::MidGray) : Color(Color::Black); + case Column::Name: + return Color::Black; + case Column::Value: + return property.is_readonly() ? Color(Color::MidGray) : Color(Color::Black); } ASSERT_NOT_REACHED(); } - return { }; + return {}; } void VBWidgetPropertyModel::set_data(const GModelIndex& index, const GVariant& value) diff --git a/DevTools/VisualBuilder/VBWidgetPropertyModel.h b/DevTools/VisualBuilder/VBWidgetPropertyModel.h index 2aa4542424..b84bffc697 100644 --- a/DevTools/VisualBuilder/VBWidgetPropertyModel.h +++ b/DevTools/VisualBuilder/VBWidgetPropertyModel.h @@ -7,8 +7,7 @@ class VBProperty; class VBWidgetPropertyModel : public GModel { public: - enum Column - { + enum Column { Name = 0, Value, __Count diff --git a/DevTools/VisualBuilder/VBWidgetRegistry.cpp b/DevTools/VisualBuilder/VBWidgetRegistry.cpp index 1f38e5de7c..6303974854 100644 --- a/DevTools/VisualBuilder/VBWidgetRegistry.cpp +++ b/DevTools/VisualBuilder/VBWidgetRegistry.cpp @@ -1,29 +1,43 @@ #include "VBWidgetRegistry.h" #include "VBProperty.h" -#include #include +#include +#include +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include -#include static String to_class_name(VBWidgetType type) { switch (type) { - case VBWidgetType::GWidget: return "GWidget"; - case VBWidgetType::GButton: return "GButton"; - case VBWidgetType::GLabel: return "GLabel"; - case VBWidgetType::GSpinBox: return "GSpinBox"; - case VBWidgetType::GTextEditor: return "GTextEditor"; - case VBWidgetType::GProgressBar: return "GProgressBar"; - case VBWidgetType::GCheckBox: return "GCheckBox"; - case VBWidgetType::GScrollBar: return "GScrollBar"; - case VBWidgetType::GGroupBox: return "GGroupBox"; - case VBWidgetType::GSlider: return "GSlider"; - default: ASSERT_NOT_REACHED(); + case VBWidgetType::GWidget: + return "GWidget"; + case VBWidgetType::GButton: + return "GButton"; + case VBWidgetType::GLabel: + return "GLabel"; + case VBWidgetType::GSpinBox: + return "GSpinBox"; + case VBWidgetType::GTextEditor: + return "GTextEditor"; + case VBWidgetType::GProgressBar: + return "GProgressBar"; + case VBWidgetType::GCheckBox: + return "GCheckBox"; + case VBWidgetType::GRadioButton: + return "GRadioButton"; + case VBWidgetType::GScrollBar: + return "GScrollBar"; + case VBWidgetType::GGroupBox: + return "GGroupBox"; + case VBWidgetType::GSlider: + return "GSlider"; + default: + ASSERT_NOT_REACHED(); } } @@ -76,6 +90,8 @@ static GWidget* build_gwidget(VBWidgetType type, GWidget* parent) box->set_text("checkbox_1"); return box; } + case VBWidgetType::GRadioButton: + return new GRadioButton("radio_1", parent); default: ASSERT_NOT_REACHED(); return nullptr; @@ -85,12 +101,12 @@ static GWidget* build_gwidget(VBWidgetType type, GWidget* parent) GWidget* VBWidgetRegistry::build_gwidget(VBWidget& widget, VBWidgetType type, GWidget* parent, Vector>& properties) { auto* gwidget = ::build_gwidget(type, parent); - auto add_readonly_property = [&] (const String& name, const GVariant& value) { + auto add_readonly_property = [&](const String& name, const GVariant& value) { auto property = make(widget, name, value); property->set_readonly(true); properties.append(move(property)); }; - auto add_property = [&] (const String& name, Function&& getter, Function&& setter) { + auto add_property = [&](const String& name, Function&& getter, Function&& setter) { auto property = make(widget, name, move(getter), move(setter)); properties.append(move(property)); }; diff --git a/DevTools/VisualBuilder/VBWidgetType.h b/DevTools/VisualBuilder/VBWidgetType.h index a816a7cf52..3c441051fb 100644 --- a/DevTools/VisualBuilder/VBWidgetType.h +++ b/DevTools/VisualBuilder/VBWidgetType.h @@ -1,7 +1,6 @@ #pragma once -enum class VBWidgetType -{ +enum class VBWidgetType { None = 0, GWidget, GButton, @@ -10,6 +9,7 @@ enum class VBWidgetType GTextEditor, GProgressBar, GCheckBox, + GRadioButton, GScrollBar, GGroupBox, GSlider, diff --git a/DevTools/VisualBuilder/main.cpp b/DevTools/VisualBuilder/main.cpp index 03b32576c3..9401ba3413 100644 --- a/DevTools/VisualBuilder/main.cpp +++ b/DevTools/VisualBuilder/main.cpp @@ -1,19 +1,19 @@ -#include -#include -#include -#include -#include -#include -#include -#include #include "VBForm.h" +#include "VBPropertiesWindow.h" #include "VBWidget.h" #include "VBWidgetPropertyModel.h" -#include "VBPropertiesWindow.h" -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include static GWindow* make_toolbox_window(); @@ -24,23 +24,23 @@ int main(int argc, char** argv) auto* propbox = new VBPropertiesWindow; auto* form1 = new VBForm("Form1"); - form1->on_widget_selected = [propbox] (VBWidget* widget) { + form1->on_widget_selected = [propbox](VBWidget* widget) { propbox->table_view().set_model(widget ? &widget->property_model() : nullptr); }; auto menubar = make(); auto app_menu = make("Visual Builder"); - app_menu->add_action(GAction::create("Quit", { Mod_Alt, Key_F4 }, [] (const GAction&) { + app_menu->add_action(GAction::create("Quit", { Mod_Alt, Key_F4 }, [](const GAction&) { GApplication::the().quit(0); return; })); menubar->add_menu(move(app_menu)); auto file_menu = make("File"); - file_menu->add_action(GAction::create("Dump Form", [&] (auto&) { + file_menu->add_action(GAction::create("Dump Form", [&](auto&) { form1->dump(); })); - file_menu->add_action(GAction::create("Save Form...", { Mod_Ctrl, Key_S }, [form1] (auto&) { + file_menu->add_action(GAction::create("Save Form...", { Mod_Ctrl, Key_S }, [form1](auto&) { form1->write_to_file("/tmp/form.frm"); })); menubar->add_menu(move(file_menu)); @@ -49,7 +49,7 @@ int main(int argc, char** argv) menubar->add_menu(move(edit_menu)); auto help_menu = make("Help"); - help_menu->add_action(GAction::create("About", [] (const GAction&) { + help_menu->add_action(GAction::create("About", [](const GAction&) { dbgprintf("FIXME: Implement Help/About\n"); })); menubar->add_menu(move(help_menu)); @@ -80,69 +80,87 @@ GWindow* make_toolbox_window() auto* widget = new GWidget; widget->set_fill_with_background_color(true); widget->set_layout(make(Orientation::Vertical)); + widget->layout()->set_spacing(0); window->set_main_widget(widget); auto* label_button = new GButton(widget); + label_button->set_button_style(ButtonStyle::CoolBar); label_button->set_tooltip("GLabel"); label_button->set_icon(GraphicsBitmap::load_from_file("/res/icons/vbwidgets/label.png")); - label_button->on_click = [] (GButton&) { + label_button->on_click = [](GButton&) { if (auto* form = VBForm::current()) form->insert_widget(VBWidgetType::GLabel); }; auto* button_button = new GButton(widget); + button_button->set_button_style(ButtonStyle::CoolBar); button_button->set_tooltip("GButton"); button_button->set_icon(GraphicsBitmap::load_from_file("/res/icons/vbwidgets/button.png")); - button_button->on_click = [] (GButton&) { + button_button->on_click = [](GButton&) { if (auto* form = VBForm::current()) form->insert_widget(VBWidgetType::GButton); }; auto* spinbox_button = new GButton(widget); + spinbox_button->set_button_style(ButtonStyle::CoolBar); spinbox_button->set_tooltip("GSpinBox"); spinbox_button->set_icon(GraphicsBitmap::load_from_file("/res/icons/vbwidgets/spinbox.png")); - spinbox_button->on_click = [] (GButton&) { + spinbox_button->on_click = [](GButton&) { if (auto* form = VBForm::current()) form->insert_widget(VBWidgetType::GSpinBox); }; auto* editor_button = new GButton(widget); + editor_button->set_button_style(ButtonStyle::CoolBar); editor_button->set_tooltip("GTextEditor"); editor_button->set_icon(GraphicsBitmap::load_from_file("/res/icons/vbwidgets/textbox.png")); - editor_button->on_click = [] (GButton&) { + editor_button->on_click = [](GButton&) { if (auto* form = VBForm::current()) form->insert_widget(VBWidgetType::GTextEditor); }; auto* progress_bar_button = new GButton(widget); + progress_bar_button->set_button_style(ButtonStyle::CoolBar); progress_bar_button->set_tooltip("GProgressBar"); progress_bar_button->set_icon(GraphicsBitmap::load_from_file("/res/icons/vbwidgets/progressbar.png")); - progress_bar_button->on_click = [] (GButton&) { + progress_bar_button->on_click = [](GButton&) { if (auto* form = VBForm::current()) form->insert_widget(VBWidgetType::GProgressBar); }; auto* slider_button = new GButton(widget); + slider_button->set_button_style(ButtonStyle::CoolBar); slider_button->set_tooltip("GSlider"); slider_button->set_icon(GraphicsBitmap::load_from_file("/res/icons/vbwidgets/slider.png")); - slider_button->on_click = [] (GButton&) { + slider_button->on_click = [](GButton&) { if (auto* form = VBForm::current()) form->insert_widget(VBWidgetType::GSlider); }; auto* checkbox_button = new GButton(widget); + checkbox_button->set_button_style(ButtonStyle::CoolBar); checkbox_button->set_tooltip("GCheckBox"); checkbox_button->set_icon(GraphicsBitmap::load_from_file("/res/icons/vbwidgets/checkbox.png")); - checkbox_button->on_click = [] (GButton&) { + checkbox_button->on_click = [](GButton&) { if (auto* form = VBForm::current()) form->insert_widget(VBWidgetType::GCheckBox); }; + auto* radiobutton_button = new GButton(widget); + radiobutton_button->set_button_style(ButtonStyle::CoolBar); + radiobutton_button->set_tooltip("GRadioButton"); + radiobutton_button->set_icon(GraphicsBitmap::load_from_file("/res/icons/filled-radio-circle.png")); + radiobutton_button->on_click = [](GButton&) { + if (auto* form = VBForm::current()) + form->insert_widget(VBWidgetType::GRadioButton); + }; auto* scrollbar_button = new GButton(widget); + scrollbar_button->set_button_style(ButtonStyle::CoolBar); scrollbar_button->set_tooltip("GScrollBar"); scrollbar_button->set_icon(GraphicsBitmap::load_from_file("/res/icons/vbwidgets/scrollbar.png")); - scrollbar_button->on_click = [] (GButton&) { + scrollbar_button->on_click = [](GButton&) { if (auto* form = VBForm::current()) form->insert_widget(VBWidgetType::GScrollBar); }; auto* groupbox_button = new GButton(widget); + groupbox_button->set_button_style(ButtonStyle::CoolBar); groupbox_button->set_tooltip("GGroupBox"); groupbox_button->set_icon(GraphicsBitmap::load_from_file("/res/icons/vbwidgets/groupbox.png")); - groupbox_button->on_click = [] (GButton&) { + groupbox_button->on_click = [](GButton&) { if (auto* form = VBForm::current()) form->insert_widget(VBWidgetType::GGroupBox); }; diff --git a/Games/Minesweeper/Field.cpp b/Games/Minesweeper/Field.cpp index 9b1176cd97..184d650587 100644 --- a/Games/Minesweeper/Field.cpp +++ b/Games/Minesweeper/Field.cpp @@ -1,11 +1,11 @@ #include "Field.h" +#include +#include #include #include #include -#include -#include -#include #include +#include class SquareButton final : public GButton { public: @@ -50,7 +50,7 @@ public: } } if (event.button() == GMouseButton::Middle) { - m_square.field->for_each_square([] (auto& square) { + m_square.field->for_each_square([](auto& square) { if (square.is_considering) { square.is_considering = false; square.button->set_icon(nullptr); @@ -120,7 +120,7 @@ Field::Field(GLabel& flag_label, GLabel& time_label, GButton& face_button, GWidg set_background_color(Color::LightGray); reset(); - m_face_button.on_click = [this] (auto&) { reset(); }; + m_face_button.on_click = [this](auto&) { reset(); }; set_face(Face::Default); } @@ -218,7 +218,7 @@ void Field::reset() if (!square.button) { square.button = new SquareButton(this); square.button->set_checkable(true); - square.button->on_click = [this, &square] (GButton&) { + square.button->on_click = [this, &square](GButton&) { on_square_clicked(square); }; square.button->on_right_click = [this, &square] { @@ -244,7 +244,7 @@ void Field::reset() for (int c = 0; c < columns(); ++c) { auto& square = this->square(r, c); int number = 0; - square.for_each_neighbor([&number] (auto& neighbor) { + square.for_each_neighbor([&number](auto& neighbor) { number += neighbor.has_mine; }); square.number = number; @@ -262,7 +262,7 @@ void Field::reset() void Field::flood_fill(Square& square) { on_square_clicked(square); - square.for_each_neighbor([this] (auto& neighbor) { + square.for_each_neighbor([this](auto& neighbor) { if (!neighbor.is_swept && !neighbor.has_mine && neighbor.number == 0) flood_fill(neighbor); if (!neighbor.has_mine && neighbor.number) @@ -333,13 +333,13 @@ void Field::on_square_chorded(Square& square) if (!square.number) return; int adjacent_flags = 0; - square.for_each_neighbor([&] (auto& neighbor) { + square.for_each_neighbor([&](auto& neighbor) { if (neighbor.has_flag) ++adjacent_flags; }); if (square.number != adjacent_flags) return; - square.for_each_neighbor([&] (auto& neighbor) { + square.for_each_neighbor([&](auto& neighbor) { if (neighbor.has_flag) return; on_square_clicked(neighbor); @@ -396,7 +396,7 @@ void Field::win() m_timer.stop(); set_greedy_for_hits(true); set_face(Face::Good); - for_each_square([&] (auto& square) { + for_each_square([&](auto& square) { if (!square.has_flag && square.has_mine) set_flag(square, true); }); @@ -435,7 +435,7 @@ void Field::set_chord_preview(Square& square, bool chord_preview) if (m_chord_preview == chord_preview) return; m_chord_preview = chord_preview; - square.for_each_neighbor([&] (auto& neighbor) { + square.for_each_neighbor([&](auto& neighbor) { neighbor.button->set_checked(false); if (!neighbor.has_flag && !neighbor.is_considering) neighbor.button->set_checked(chord_preview); diff --git a/Games/Minesweeper/Field.h b/Games/Minesweeper/Field.h index 5af284a466..1725ceefda 100644 --- a/Games/Minesweeper/Field.h +++ b/Games/Minesweeper/Field.h @@ -71,8 +71,7 @@ private: template void for_each_square(Callback); - enum class Face - { + enum class Face { Default, Good, Bad diff --git a/Games/Minesweeper/main.cpp b/Games/Minesweeper/main.cpp index d0ff7a97a0..113117399c 100644 --- a/Games/Minesweeper/main.cpp +++ b/Games/Minesweeper/main.cpp @@ -1,13 +1,13 @@ #include "Field.h" +#include +#include #include -#include #include #include +#include #include #include -#include -#include -#include +#include int main(int argc, char** argv) { @@ -58,33 +58,33 @@ int main(int argc, char** argv) auto menubar = make(); auto app_menu = make("Minesweeper"); - app_menu->add_action(GAction::create("Quit", { Mod_Alt, Key_F4 }, [] (const GAction&) { + app_menu->add_action(GAction::create("Quit", { Mod_Alt, Key_F4 }, [](const GAction&) { GApplication::the().quit(0); return; })); menubar->add_menu(move(app_menu)); auto game_menu = make("Game"); - game_menu->add_action(GAction::create("New game", { Mod_None, Key_F2 }, [field] (const GAction&) { + game_menu->add_action(GAction::create("New game", { Mod_None, Key_F2 }, [field](const GAction&) { field->reset(); })); game_menu->add_separator(); - game_menu->add_action(GAction::create("Beginner", { Mod_Ctrl, Key_B }, [field] (const GAction&) { + game_menu->add_action(GAction::create("Beginner", { Mod_Ctrl, Key_B }, [field](const GAction&) { field->set_field_size(9, 9, 10); })); - game_menu->add_action(GAction::create("Intermediate", { Mod_Ctrl, Key_I }, [field] (const GAction&) { + game_menu->add_action(GAction::create("Intermediate", { Mod_Ctrl, Key_I }, [field](const GAction&) { field->set_field_size(16, 16, 40); })); - game_menu->add_action(GAction::create("Expert", { Mod_Ctrl, Key_E }, [field] (const GAction&) { + game_menu->add_action(GAction::create("Expert", { Mod_Ctrl, Key_E }, [field](const GAction&) { field->set_field_size(16, 30, 99); })); - game_menu->add_action(GAction::create("Madwoman", { Mod_Ctrl, Key_M }, [field] (const GAction&) { + game_menu->add_action(GAction::create("Madwoman", { Mod_Ctrl, Key_M }, [field](const GAction&) { field->set_field_size(32, 60, 350); })); menubar->add_menu(move(game_menu)); auto help_menu = make("Help"); - help_menu->add_action(GAction::create("About", [] (const GAction&) { + help_menu->add_action(GAction::create("About", [](const GAction&) { dbgprintf("FIXME: Implement Help/About\n"); })); menubar->add_menu(move(help_menu)); diff --git a/Games/Snake/SnakeGame.cpp b/Games/Snake/SnakeGame.cpp index 9c8439c423..251367dace 100644 --- a/Games/Snake/SnakeGame.cpp +++ b/Games/Snake/SnakeGame.cpp @@ -1,6 +1,6 @@ #include "SnakeGame.h" -#include #include +#include #include #include #include @@ -198,7 +198,6 @@ void SnakeGame::paint_event(GPaintEvent& event) painter.fill_rect(right_side, Color::from_rgb(0x888800)); painter.fill_rect(top_side, Color::from_rgb(0xcccc00)); painter.fill_rect(bottom_side, Color::from_rgb(0x888800)); - } painter.draw_scaled_bitmap(cell_rect(m_fruit), *m_fruit_bitmaps[m_fruit_type], m_fruit_bitmaps[m_fruit_type]->rect()); diff --git a/Games/Snake/main.cpp b/Games/Snake/main.cpp index 34dee293b7..36f923437a 100644 --- a/Games/Snake/main.cpp +++ b/Games/Snake/main.cpp @@ -1,11 +1,11 @@ #include "SnakeGame.h" +#include #include -#include #include #include #include #include -#include +#include int main(int argc, char** argv) { @@ -23,20 +23,20 @@ int main(int argc, char** argv) auto menubar = make(); auto app_menu = make("Snake"); - app_menu->add_action(GAction::create("Quit", { Mod_Alt, Key_F4 }, [] (const GAction&) { + app_menu->add_action(GAction::create("Quit", { Mod_Alt, Key_F4 }, [](const GAction&) { GApplication::the().quit(0); return; })); menubar->add_menu(move(app_menu)); auto game_menu = make("Game"); - game_menu->add_action(GAction::create("New game", { Mod_None, Key_F2 }, [&] (const GAction&) { + game_menu->add_action(GAction::create("New game", { Mod_None, Key_F2 }, [&](const GAction&) { game->reset(); })); menubar->add_menu(move(game_menu)); auto help_menu = make("Help"); - help_menu->add_action(GAction::create("About", [] (const GAction&) { + help_menu->add_action(GAction::create("About", [](const GAction&) { dbgprintf("FIXME: Implement Help/About\n"); })); menubar->add_menu(move(help_menu)); diff --git a/Kernel/.gitignore b/Kernel/.gitignore index 95057be2ee..984793fa3d 100644 --- a/Kernel/.gitignore +++ b/Kernel/.gitignore @@ -7,3 +7,5 @@ _fs_contents sync-local.sh *.pcap eth_null* +_disk_image +compile_commmands.json diff --git a/Kernel/i386.cpp b/Kernel/Arch/i386/CPU.cpp similarity index 63% rename from Kernel/i386.cpp rename to Kernel/Arch/i386/CPU.cpp index 2a660cf55a..a1a7ec5177 100644 --- a/Kernel/i386.cpp +++ b/Kernel/Arch/i386/CPU.cpp @@ -1,16 +1,17 @@ -#include -#include "i386.h" #include "Assertions.h" -#include "Process.h" -#include #include "IRQHandler.h" #include "PIC.h" +#include "Process.h" #include "Scheduler.h" +#include +#include #include +#include //#define PAGE_FAULT_DEBUG -struct [[gnu::packed]] DescriptorTablePointer { +struct [[gnu::packed]] DescriptorTablePointer +{ word limit; void* address; }; @@ -55,71 +56,68 @@ asm( " popw %es\n" " popw %ds\n" " popa\n" - " iret\n" -); + " iret\n"); -#define EH_ENTRY(ec) \ -extern "C" void exception_ ## ec ## _handler(RegisterDumpWithExceptionCode&); \ -extern "C" void exception_ ## ec ## _entry(); \ -asm( \ - ".globl exception_" # ec "_entry\n" \ - "exception_" # ec "_entry: \n" \ - " pusha\n" \ - " pushw %ds\n" \ - " pushw %es\n" \ - " pushw %fs\n" \ - " pushw %gs\n" \ - " pushw %ss\n" \ - " pushw %ss\n" \ - " pushw %ss\n" \ - " pushw %ss\n" \ - " pushw %ss\n" \ - " popw %ds\n" \ - " popw %es\n" \ - " popw %fs\n" \ - " popw %gs\n" \ - " mov %esp, %eax\n" \ - " call exception_" # ec "_handler\n" \ - " popw %gs\n" \ - " popw %gs\n" \ - " popw %fs\n" \ - " popw %es\n" \ - " popw %ds\n" \ - " popa\n" \ - " add $0x4, %esp\n" \ - " iret\n" \ -); +#define EH_ENTRY(ec) \ + extern "C" void exception_##ec##_handler(RegisterDumpWithExceptionCode&); \ + extern "C" void exception_##ec##_entry(); \ + asm( \ + ".globl exception_" #ec "_entry\n" \ + "exception_" #ec "_entry: \n" \ + " pusha\n" \ + " pushw %ds\n" \ + " pushw %es\n" \ + " pushw %fs\n" \ + " pushw %gs\n" \ + " pushw %ss\n" \ + " pushw %ss\n" \ + " pushw %ss\n" \ + " pushw %ss\n" \ + " pushw %ss\n" \ + " popw %ds\n" \ + " popw %es\n" \ + " popw %fs\n" \ + " popw %gs\n" \ + " mov %esp, %eax\n" \ + " call exception_" #ec "_handler\n" \ + " popw %gs\n" \ + " popw %gs\n" \ + " popw %fs\n" \ + " popw %es\n" \ + " popw %ds\n" \ + " popa\n" \ + " add $0x4, %esp\n" \ + " iret\n"); -#define EH_ENTRY_NO_CODE(ec) \ -extern "C" void exception_ ## ec ## _handler(RegisterDump&); \ -extern "C" void exception_ ## ec ## _entry(); \ -asm( \ - ".globl exception_" # ec "_entry\n" \ - "exception_" # ec "_entry: \n" \ - " pusha\n" \ - " pushw %ds\n" \ - " pushw %es\n" \ - " pushw %fs\n" \ - " pushw %gs\n" \ - " pushw %ss\n" \ - " pushw %ss\n" \ - " pushw %ss\n" \ - " pushw %ss\n" \ - " pushw %ss\n" \ - " popw %ds\n" \ - " popw %es\n" \ - " popw %fs\n" \ - " popw %gs\n" \ - " mov %esp, %eax\n" \ - " call exception_" # ec "_handler\n" \ - " popw %gs\n" \ - " popw %gs\n" \ - " popw %fs\n" \ - " popw %es\n" \ - " popw %ds\n" \ - " popa\n" \ - " iret\n" \ -); +#define EH_ENTRY_NO_CODE(ec) \ + extern "C" void exception_##ec##_handler(RegisterDump&); \ + extern "C" void exception_##ec##_entry(); \ + asm( \ + ".globl exception_" #ec "_entry\n" \ + "exception_" #ec "_entry: \n" \ + " pusha\n" \ + " pushw %ds\n" \ + " pushw %es\n" \ + " pushw %fs\n" \ + " pushw %gs\n" \ + " pushw %ss\n" \ + " pushw %ss\n" \ + " pushw %ss\n" \ + " pushw %ss\n" \ + " pushw %ss\n" \ + " popw %ds\n" \ + " popw %es\n" \ + " popw %fs\n" \ + " popw %gs\n" \ + " mov %esp, %eax\n" \ + " call exception_" #ec "_handler\n" \ + " popw %gs\n" \ + " popw %gs\n" \ + " popw %fs\n" \ + " popw %es\n" \ + " popw %ds\n" \ + " popa\n" \ + " iret\n"); template static void dump(const DumpType& regs) @@ -158,7 +156,6 @@ static void dump(const DumpType& regs) } } - // 6: Invalid Opcode EH_ENTRY_NO_CODE(6); void exception_6_handler(RegisterDump& regs) @@ -171,8 +168,7 @@ void exception_6_handler(RegisterDump& regs) kprintf("%s Illegal instruction: %s(%u)\n", current->process().is_ring0() ? "Kernel" : "Process", current->process().name().characters(), - current->pid() - ); + current->pid()); dump(regs); dump_backtrace(); @@ -195,14 +191,15 @@ void exception_7_handler(RegisterDump& regs) if (g_last_fpu_thread == current) return; if (g_last_fpu_thread) { - asm volatile("fxsave %0":"=m"(g_last_fpu_thread->fpu_state())); + asm volatile("fxsave %0" + : "=m"(g_last_fpu_thread->fpu_state())); } else { asm volatile("fnclex"); } g_last_fpu_thread = current; if (current->has_used_fpu()) { - asm volatile("fxrstor %0"::"m"(current->fpu_state())); + asm volatile("fxrstor %0" ::"m"(current->fpu_state())); } else { asm volatile("fninit"); current->set_has_used_fpu(true); @@ -214,7 +211,6 @@ void exception_7_handler(RegisterDump& regs) #endif } - // 0: Divide error EH_ENTRY_NO_CODE(0); void exception_0_handler(RegisterDump& regs) @@ -222,8 +218,7 @@ void exception_0_handler(RegisterDump& regs) kprintf("%s Division by zero: %s(%u)\n", current->process().is_ring0() ? "Kernel" : "User", current->process().name().characters(), - current->pid() - ); + current->pid()); dump(regs); @@ -235,7 +230,6 @@ void exception_0_handler(RegisterDump& regs) current->process().crash(SIGFPE); } - // 13: General Protection Fault EH_ENTRY(13); void exception_13_handler(RegisterDumpWithExceptionCode& regs) @@ -259,10 +253,12 @@ void exception_14_handler(RegisterDumpWithExceptionCode& regs) ASSERT(current); dword faultAddress; - asm ("movl %%cr2, %%eax":"=a"(faultAddress)); + asm("movl %%cr2, %%eax" + : "=a"(faultAddress)); dword fault_page_directory; - asm ("movl %%cr3, %%eax":"=a"(fault_page_directory)); + asm("movl %%cr3, %%eax" + : "=a"(fault_page_directory)); #ifdef PAGE_FAULT_DEBUG dbgprintf("%s(%u): ring%u %s page fault in PD=%x, %s L%x\n", @@ -279,10 +275,10 @@ void exception_14_handler(RegisterDumpWithExceptionCode& regs) dump(regs); #endif - auto response = MM.handle_page_fault(PageFault(regs.exception_code, LinearAddress(faultAddress))); + auto response = MM.handle_page_fault(PageFault(regs.exception_code, VirtualAddress(faultAddress))); if (response == PageFaultResponse::ShouldCrash) { - kprintf("%s(%u:%u) unrecoverable page fault, %s laddr=%p\n", + kprintf("%s(%u:%u) unrecoverable page fault, %s vaddr=%p\n", current->process().name().characters(), current->pid(), current->tid(), @@ -299,17 +295,21 @@ void exception_14_handler(RegisterDumpWithExceptionCode& regs) } } -#define EH(i, msg) \ - static void _exception ## i () \ - { \ - kprintf(msg"\n"); \ - dword cr0, cr2, cr3, cr4; \ - asm ("movl %%cr0, %%eax":"=a"(cr0)); \ - asm ("movl %%cr2, %%eax":"=a"(cr2)); \ - asm ("movl %%cr3, %%eax":"=a"(cr3)); \ - asm ("movl %%cr4, %%eax":"=a"(cr4)); \ +#define EH(i, msg) \ + static void _exception##i() \ + { \ + kprintf(msg "\n"); \ + dword cr0, cr2, cr3, cr4; \ + asm("movl %%cr0, %%eax" \ + : "=a"(cr0)); \ + asm("movl %%cr2, %%eax" \ + : "=a"(cr2)); \ + asm("movl %%cr3, %%eax" \ + : "=a"(cr3)); \ + asm("movl %%cr4, %%eax" \ + : "=a"(cr4)); \ kprintf("CR0=%x CR2=%x CR3=%x CR4=%x\n", cr0, cr2, cr3, cr4); \ - hang(); \ + hang(); \ } EH(1, "Debug exception") @@ -350,7 +350,8 @@ void flush_gdt() { s_gdtr.address = s_gdt; s_gdtr.limit = (s_gdt_length * 8) - 1; - asm("lgdt %0"::"m"(s_gdtr):"memory"); + asm("lgdt %0" ::"m"(s_gdtr) + : "memory"); } void gdt_init() @@ -379,16 +380,13 @@ void gdt_init() "mov %%ax, %%es\n" "mov %%ax, %%fs\n" "mov %%ax, %%gs\n" - "mov %%ax, %%ss\n" - :: "a"(0x10) - : "memory" - ); + "mov %%ax, %%ss\n" ::"a"(0x10) + : "memory"); // Make sure CS points to the kernel code descriptor. asm volatile( "ljmpl $0x8, $sanity\n" - "sanity:\n" - ); + "sanity:\n"); } static void unimp_trap() @@ -413,20 +411,20 @@ void unregister_irq_handler(byte irq, IRQHandler& handler) void register_interrupt_handler(byte index, void (*f)()) { s_idt[index].low = 0x00080000 | LSW((f)); - s_idt[index].high = ((dword)(f) & 0xffff0000) | 0x8e00; + s_idt[index].high = ((dword)(f)&0xffff0000) | 0x8e00; flush_idt(); } void register_user_callable_interrupt_handler(byte index, void (*f)()) { s_idt[index].low = 0x00080000 | LSW((f)); - s_idt[index].high = ((dword)(f) & 0xffff0000) | 0xef00; + s_idt[index].high = ((dword)(f)&0xffff0000) | 0xef00; flush_idt(); } void flush_idt() { - asm("lidt %0"::"m"(s_idtr)); + asm("lidt %0" ::"m"(s_idtr)); } /* If an 8259 gets cranky, it'll generate a spurious IRQ7. @@ -438,8 +436,7 @@ extern "C" void irq7_handler(); asm( ".globl irq7_handler \n" "irq7_handler: \n" - " iret\n" -); + " iret\n"); void idt_init() { @@ -478,7 +475,7 @@ void idt_init() void load_task_register(word selector) { - asm("ltr %0"::"r"(selector)); + asm("ltr %0" ::"r"(selector)); } void handle_irq() @@ -511,7 +508,8 @@ void __assertion_failed(const char* msg, const char* file, unsigned line, const kprintf("ASSERTION FAILED: %s\n%s:%u in %s\n", msg, file, line, func); dump_backtrace(); asm volatile("hlt"); - for (;;); + for (;;) + ; } #endif @@ -524,6 +522,5 @@ void sse_init() "mov %eax, %cr0\n" "mov %cr4, %eax\n" "orl $0x600, %eax\n" - "mov %eax, %cr4\n" - ); + "mov %eax, %cr4\n"); } diff --git a/Kernel/i386.h b/Kernel/Arch/i386/CPU.h similarity index 96% rename from Kernel/i386.h rename to Kernel/Arch/i386/CPU.h index a323947d03..bb0f7a037b 100644 --- a/Kernel/i386.h +++ b/Kernel/Arch/i386/CPU.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #define PAGE_SIZE 4096 @@ -49,8 +49,7 @@ union [[gnu::packed]] Descriptor dword high; }; - enum Type - { + enum Type { Invalid = 0, AvailableTSS_16bit = 0x1, LDT = 0x2, @@ -180,8 +179,7 @@ private: #define IRQ_VECTOR_BASE 0x50 struct PageFaultFlags { - enum Flags - { + enum Flags { NotPresent = 0x00, ProtectionViolation = 0x01, Read = 0x00, @@ -194,13 +192,13 @@ struct PageFaultFlags { class PageFault { public: - PageFault(word code, LinearAddress laddr) + PageFault(word code, VirtualAddress vaddr) : m_code(code) - , m_laddr(laddr) + , m_vaddr(vaddr) { } - LinearAddress laddr() const { return m_laddr; } + VirtualAddress vaddr() const { return m_vaddr; } word code() const { return m_code; } bool is_not_present() const { return (m_code & 1) == PageFaultFlags::NotPresent; } @@ -213,7 +211,7 @@ public: private: word m_code; - LinearAddress m_laddr; + VirtualAddress m_vaddr; }; struct [[gnu::packed]] RegisterDump diff --git a/Kernel/Assertions.h b/Kernel/Assertions.h index de744bf11f..419e5bd7cd 100644 --- a/Kernel/Assertions.h +++ b/Kernel/Assertions.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #ifdef DEBUG diff --git a/Kernel/Boot/boot.S b/Kernel/Boot/boot.S index ff0c5665d3..d37bfe964b 100644 --- a/Kernel/Boot/boot.S +++ b/Kernel/Boot/boot.S @@ -39,8 +39,8 @@ stack_top: .extern init .type init, @function -.extern multiboot_ptr -.type multiboot_ptr, @object +.extern multiboot_info_ptr +.type multiboot_info_ptr, @object start: cli @@ -54,7 +54,7 @@ start: pushl %eax /* Multiboot header magic */ pushl %ebx /* Multiboot header pointer */ - mov %ebx, multiboot_ptr + mov %ebx, multiboot_info_ptr call init diff --git a/Kernel/CMOS.cpp b/Kernel/CMOS.cpp index a88b3744e5..93b261898f 100644 --- a/Kernel/CMOS.cpp +++ b/Kernel/CMOS.cpp @@ -1,5 +1,5 @@ -#include "CMOS.h" -#include "IO.h" +#include +#include namespace CMOS { diff --git a/Kernel/Console.cpp b/Kernel/Console.cpp index 394270a785..5ee1048557 100644 --- a/Kernel/Console.cpp +++ b/Kernel/Console.cpp @@ -23,19 +23,19 @@ Console::~Console() { } -bool Console::can_read(FileDescriptor&) const +bool Console::can_read(FileDescription&) const { return false; } -ssize_t Console::read(FileDescriptor&, byte*, ssize_t) +ssize_t Console::read(FileDescription&, byte*, ssize_t) { // FIXME: Implement reading from the console. // Maybe we could use a ring buffer for this device? return 0; } -ssize_t Console::write(FileDescriptor&, const byte* data, ssize_t size) +ssize_t Console::write(FileDescription&, const byte* data, ssize_t size) { if (!size) return 0; diff --git a/Kernel/Console.h b/Kernel/Console.h index 59fe006c4e..e1f4e2d2a3 100644 --- a/Kernel/Console.h +++ b/Kernel/Console.h @@ -19,10 +19,10 @@ public: virtual ~Console() override; // ^CharacterDevice - virtual bool can_read(FileDescriptor&) const override; - virtual bool can_write(FileDescriptor&) const override { return true; } - virtual ssize_t read(FileDescriptor&, byte*, ssize_t) override; - virtual ssize_t write(FileDescriptor&, const byte*, ssize_t) override; + virtual bool can_read(FileDescription&) const override; + virtual bool can_write(FileDescription&) const override { return true; } + virtual ssize_t read(FileDescription&, byte*, ssize_t) override; + virtual ssize_t write(FileDescription&, const byte*, ssize_t) override; virtual const char* class_name() const override { return "Console"; } void set_implementation(ConsoleImplementation* implementation) { m_implementation = implementation; } diff --git a/Kernel/Devices/BXVGADevice.cpp b/Kernel/Devices/BXVGADevice.cpp index 673f1b4c00..a59587181d 100644 --- a/Kernel/Devices/BXVGADevice.cpp +++ b/Kernel/Devices/BXVGADevice.cpp @@ -1,29 +1,29 @@ #include #include #include -#include #include +#include #include -#define VBE_DISPI_IOPORT_INDEX 0x01CE -#define VBE_DISPI_IOPORT_DATA 0x01CF +#define VBE_DISPI_IOPORT_INDEX 0x01CE +#define VBE_DISPI_IOPORT_DATA 0x01CF -#define VBE_DISPI_INDEX_ID 0x0 -#define VBE_DISPI_INDEX_XRES 0x1 -#define VBE_DISPI_INDEX_YRES 0x2 -#define VBE_DISPI_INDEX_BPP 0x3 -#define VBE_DISPI_INDEX_ENABLE 0x4 -#define VBE_DISPI_INDEX_BANK 0x5 -#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 -#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 -#define VBE_DISPI_INDEX_X_OFFSET 0x8 -#define VBE_DISPI_INDEX_Y_OFFSET 0x9 -#define VBE_DISPI_DISABLED 0x00 -#define VBE_DISPI_ENABLED 0x01 -#define VBE_DISPI_LFB_ENABLED 0x40 +#define VBE_DISPI_INDEX_ID 0x0 +#define VBE_DISPI_INDEX_XRES 0x1 +#define VBE_DISPI_INDEX_YRES 0x2 +#define VBE_DISPI_INDEX_BPP 0x3 +#define VBE_DISPI_INDEX_ENABLE 0x4 +#define VBE_DISPI_INDEX_BANK 0x5 +#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 +#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 +#define VBE_DISPI_INDEX_X_OFFSET 0x8 +#define VBE_DISPI_INDEX_Y_OFFSET 0x9 +#define VBE_DISPI_DISABLED 0x00 +#define VBE_DISPI_ENABLED 0x01 +#define VBE_DISPI_LFB_ENABLED 0x40 -#define BXVGA_DEV_IOCTL_SET_Y_OFFSET 1982 -#define BXVGA_DEV_IOCTL_SET_RESOLUTION 1985 +#define BXVGA_DEV_IOCTL_SET_Y_OFFSET 1982 +#define BXVGA_DEV_IOCTL_SET_RESOLUTION 1985 struct BXVGAResolution { int width; int height; @@ -75,7 +75,7 @@ dword BXVGADevice::find_framebuffer_address() static const PCI::ID bochs_vga_id = { 0x1234, 0x1111 }; static const PCI::ID virtualbox_vga_id = { 0x80ee, 0xbeef }; dword framebuffer_address = 0; - PCI::enumerate_all([&framebuffer_address] (const PCI::Address& address, PCI::ID id) { + PCI::enumerate_all([&framebuffer_address](const PCI::Address& address, PCI::ID id) { if (id == bochs_vga_id || id == virtualbox_vga_id) { framebuffer_address = PCI::get_BAR0(address) & 0xfffffff0; kprintf("BXVGA: framebuffer @ P%x\n", framebuffer_address); @@ -84,27 +84,26 @@ dword BXVGADevice::find_framebuffer_address() return framebuffer_address; } -KResultOr BXVGADevice::mmap(Process& process, LinearAddress preferred_laddr, size_t offset, size_t size, int prot) +KResultOr BXVGADevice::mmap(Process& process, FileDescription&, VirtualAddress preferred_vaddr, size_t offset, size_t size, int prot) { ASSERT(offset == 0); ASSERT(size == framebuffer_size_in_bytes()); auto vmo = VMObject::create_for_physical_range(framebuffer_address(), framebuffer_size_in_bytes()); auto* region = process.allocate_region_with_vmo( - preferred_laddr, + preferred_vaddr, framebuffer_size_in_bytes(), move(vmo), 0, "BXVGA Framebuffer", - prot - ); - kprintf("BXVGA: %s(%u) created Region{%p} with size %u for framebuffer P%x with laddr L%x\n", - process.name().characters(), process.pid(), - region, region->size(), framebuffer_address().as_ptr(), region->laddr().get()); + prot); + kprintf("BXVGA: %s(%u) created Region{%p} with size %u for framebuffer P%x with vaddr L%x\n", + process.name().characters(), process.pid(), + region, region->size(), framebuffer_address().as_ptr(), region->vaddr().get()); ASSERT(region); return region; } -int BXVGADevice::ioctl(FileDescriptor&, unsigned request, unsigned arg) +int BXVGADevice::ioctl(FileDescription&, unsigned request, unsigned arg) { switch (request) { case BXVGA_DEV_IOCTL_SET_Y_OFFSET: @@ -124,22 +123,22 @@ int BXVGADevice::ioctl(FileDescriptor&, unsigned request, unsigned arg) }; } -bool BXVGADevice::can_read(FileDescriptor&) const +bool BXVGADevice::can_read(FileDescription&) const { ASSERT_NOT_REACHED(); } -bool BXVGADevice::can_write(FileDescriptor&) const +bool BXVGADevice::can_write(FileDescription&) const { ASSERT_NOT_REACHED(); } -ssize_t BXVGADevice::read(FileDescriptor&, byte*, ssize_t) +ssize_t BXVGADevice::read(FileDescription&, byte*, ssize_t) { ASSERT_NOT_REACHED(); } -ssize_t BXVGADevice::write(FileDescriptor&, const byte*, ssize_t) +ssize_t BXVGADevice::write(FileDescription&, const byte*, ssize_t) { ASSERT_NOT_REACHED(); } diff --git a/Kernel/Devices/BXVGADevice.h b/Kernel/Devices/BXVGADevice.h index 517d13d4f6..807113cd85 100644 --- a/Kernel/Devices/BXVGADevice.h +++ b/Kernel/Devices/BXVGADevice.h @@ -17,18 +17,18 @@ public: void set_resolution(int width, int height); void set_y_offset(int); - virtual int ioctl(FileDescriptor&, unsigned request, unsigned arg) override; - virtual KResultOr mmap(Process&, LinearAddress preferred_laddr, size_t offset, size_t, int prot) override; + virtual int ioctl(FileDescription&, unsigned request, unsigned arg) override; + virtual KResultOr mmap(Process&, FileDescription&, VirtualAddress preferred_vaddr, size_t offset, size_t, int prot) override; size_t framebuffer_size_in_bytes() const { return m_framebuffer_size.area() * sizeof(dword) * 2; } Size framebuffer_size() const { return m_framebuffer_size; } private: virtual const char* class_name() const override { return "BXVGA"; } - virtual bool can_read(FileDescriptor&) const override; - virtual bool can_write(FileDescriptor&) const override; - virtual ssize_t read(FileDescriptor&, byte*, ssize_t) override; - virtual ssize_t write(FileDescriptor&, const byte*, ssize_t) override; + virtual bool can_read(FileDescription&) const override; + virtual bool can_write(FileDescription&) const override; + virtual ssize_t read(FileDescription&, byte*, ssize_t) override; + virtual ssize_t write(FileDescription&, const byte*, ssize_t) override; void set_register(word index, word value); dword find_framebuffer_address(); diff --git a/Kernel/Devices/BlockDevice.h b/Kernel/Devices/BlockDevice.h index d76d90614d..9c0229e71e 100644 --- a/Kernel/Devices/BlockDevice.h +++ b/Kernel/Devices/BlockDevice.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include class BlockDevice : public Device { public: diff --git a/Kernel/Devices/DebugLogDevice.cpp b/Kernel/Devices/DebugLogDevice.cpp index daa879ffb1..da6720f139 100644 --- a/Kernel/Devices/DebugLogDevice.cpp +++ b/Kernel/Devices/DebugLogDevice.cpp @@ -19,10 +19,9 @@ DebugLogDevice::~DebugLogDevice() { } -ssize_t DebugLogDevice::write(FileDescriptor&, const byte* data, ssize_t data_size) +ssize_t DebugLogDevice::write(FileDescription&, const byte* data, ssize_t data_size) { for (int i = 0; i < data_size; ++i) IO::out8(0xe9, data[i]); return data_size; } - diff --git a/Kernel/Devices/DebugLogDevice.h b/Kernel/Devices/DebugLogDevice.h index 9b09205074..2ef4ade046 100644 --- a/Kernel/Devices/DebugLogDevice.h +++ b/Kernel/Devices/DebugLogDevice.h @@ -9,9 +9,9 @@ public: private: // ^CharacterDevice - virtual ssize_t read(FileDescriptor&, byte*, ssize_t) override { return 0; } - virtual ssize_t write(FileDescriptor&, const byte*, ssize_t) override; - virtual bool can_write(FileDescriptor&) const override { return true; } - virtual bool can_read(FileDescriptor&) const override { return true; } + virtual ssize_t read(FileDescription&, byte*, ssize_t) override { return 0; } + virtual ssize_t write(FileDescription&, const byte*, ssize_t) override; + virtual bool can_write(FileDescription&) const override { return true; } + virtual bool can_read(FileDescription&) const override { return true; } virtual const char* class_name() const override { return "DebugLogDevice"; } }; diff --git a/Kernel/Devices/Device.cpp b/Kernel/Devices/Device.cpp index fb636d376f..601ff9fa71 100644 --- a/Kernel/Devices/Device.cpp +++ b/Kernel/Devices/Device.cpp @@ -3,8 +3,8 @@ #include Device::Device(unsigned major, unsigned minor) - : m_major(major) - , m_minor(minor) + : m_major(major) + , m_minor(minor) { VFS::the().register_device({}, *this); } @@ -14,7 +14,7 @@ Device::~Device() VFS::the().unregister_device({}, *this); } -String Device::absolute_path(FileDescriptor&) const +String Device::absolute_path(const FileDescription&) const { return String::format("device:%u,%u (%s)", m_major, m_minor, class_name()); } diff --git a/Kernel/Devices/Device.h b/Kernel/Devices/Device.h index ce0b407aa7..3b2256cf64 100644 --- a/Kernel/Devices/Device.h +++ b/Kernel/Devices/Device.h @@ -9,30 +9,6 @@ // There are two main subclasses: // - BlockDevice (random access) // - CharacterDevice (sequential) -// -// The most important functions in Device are: -// -// class_name() -// - Used in the /proc filesystem to identify the type of Device. -// -// read() and write() -// - Implement reading and writing. -// - Return the number of bytes read/written, OR a negative error code. -// -// can_read() and can_write() -// -// - Used to implement blocking I/O, and the select() and poll() syscalls. -// - Return true if read() or write() would succeed, respectively. -// - Note that can_read() should return true in EOF conditions, -// and a subsequent call to read() should return 0. -// -// ioctl() -// -// - Optional. If unimplemented, ioctl() on the device will fail with -ENOTTY. -// - Can be overridden in subclasses to implement arbitrary functionality. -// - Subclasses should take care to validate incoming addresses before dereferencing. -// - #include #include @@ -43,7 +19,7 @@ public: unsigned major() const { return m_major; } unsigned minor() const { return m_minor; } - virtual String absolute_path(FileDescriptor&) const override; + virtual String absolute_path(const FileDescription&) const override; uid_t uid() const { return m_uid; } uid_t gid() const { return m_gid; } diff --git a/Kernel/Devices/DiskDevice.cpp b/Kernel/Devices/DiskDevice.cpp index b3a63b2a56..ce131307ca 100644 --- a/Kernel/Devices/DiskDevice.cpp +++ b/Kernel/Devices/DiskDevice.cpp @@ -27,4 +27,3 @@ bool DiskDevice::write(DiskOffset offset, unsigned length, const byte* in) ASSERT(end_block <= 0xffffffff); return write_blocks(first_block, end_block - first_block, in); } - diff --git a/Kernel/Devices/DiskPartition.cpp b/Kernel/Devices/DiskPartition.cpp new file mode 100644 index 0000000000..34ebf00ea5 --- /dev/null +++ b/Kernel/Devices/DiskPartition.cpp @@ -0,0 +1,64 @@ +#include + +// #define OFFD_DEBUG + +Retained DiskPartition::create(Retained&& device, unsigned block_offset) +{ + return adopt(*new DiskPartition(move(device), block_offset)); +} + +DiskPartition::DiskPartition(Retained&& device, unsigned block_offset) + : m_device(move(device)) + , m_block_offset(block_offset) +{ +} + +DiskPartition::~DiskPartition() +{ +} + +unsigned DiskPartition::block_size() const +{ + return m_device->block_size(); +} + +bool DiskPartition::read_block(unsigned index, byte* out) const +{ +#ifdef OFFD_DEBUG + kprintf("DiskPartition::read_block %u (really: %u)\n", index, m_block_offset + index); +#endif + + return m_device->read_block(m_block_offset + index, out); +} + +bool DiskPartition::write_block(unsigned index, const byte* data) +{ +#ifdef OFFD_DEBUG + kprintf("DiskPartition::write_block %u (really: %u)\n", index, m_block_offset + index); +#endif + + return m_device->write_block(m_block_offset + index, data); +} + +bool DiskPartition::read_blocks(unsigned index, word count, byte* out) +{ +#ifdef OFFD_DEBUG + kprintf("DiskPartition::read_blocks %u (really: %u) count=%u\n", index, m_block_offset + index, count); +#endif + + return m_device->read_blocks(m_block_offset + index, count, out); +} + +bool DiskPartition::write_blocks(unsigned index, word count, const byte* data) +{ +#ifdef OFFD_DEBUG + kprintf("DiskPartition::write_blocks %u (really: %u) count=%u\n", index, m_block_offset + index, count); +#endif + + return m_device->write_blocks(m_block_offset + index, count, data); +} + +const char* DiskPartition::class_name() const +{ + return "DiskPartition"; +} diff --git a/Kernel/Devices/DiskPartition.h b/Kernel/Devices/DiskPartition.h new file mode 100644 index 0000000000..c4e1b39ee9 --- /dev/null +++ b/Kernel/Devices/DiskPartition.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include + +class DiskPartition final : public DiskDevice { +public: + static Retained create(Retained&& device, unsigned block_offset); + virtual ~DiskPartition(); + + virtual unsigned block_size() const override; + virtual bool read_block(unsigned index, byte* out) const override; + virtual bool write_block(unsigned index, const byte*) override; + virtual bool read_blocks(unsigned index, word count, byte*) override; + virtual bool write_blocks(unsigned index, word count, const byte*) override; + +private: + virtual const char* class_name() const override; + + DiskPartition(Retained&&, unsigned); + + Retained m_device; + unsigned m_block_offset; +}; diff --git a/Kernel/Devices/FileBackedDiskDevice.cpp b/Kernel/Devices/FileBackedDiskDevice.cpp index 6e936fb778..b56aaff6d6 100644 --- a/Kernel/Devices/FileBackedDiskDevice.cpp +++ b/Kernel/Devices/FileBackedDiskDevice.cpp @@ -79,4 +79,3 @@ const char* FileBackedDiskDevice::class_name() const { return "FileBackedDiskDevice"; } - diff --git a/Kernel/Devices/FullDevice.cpp b/Kernel/Devices/FullDevice.cpp index 024cd699e2..6198c174a6 100644 --- a/Kernel/Devices/FullDevice.cpp +++ b/Kernel/Devices/FullDevice.cpp @@ -1,7 +1,7 @@ #include "FullDevice.h" -#include #include #include +#include FullDevice::FullDevice() : CharacterDevice(1, 7) @@ -12,22 +12,21 @@ FullDevice::~FullDevice() { } -bool FullDevice::can_read(FileDescriptor&) const +bool FullDevice::can_read(FileDescription&) const { return true; } -ssize_t FullDevice::read(FileDescriptor&, byte* buffer, ssize_t size) +ssize_t FullDevice::read(FileDescription&, byte* buffer, ssize_t size) { ssize_t count = min(PAGE_SIZE, size); memset(buffer, 0, (size_t)count); return count; } -ssize_t FullDevice::write(FileDescriptor&, const byte*, ssize_t size) +ssize_t FullDevice::write(FileDescription&, const byte*, ssize_t size) { if (size == 0) return 0; return -ENOSPC; } - diff --git a/Kernel/Devices/FullDevice.h b/Kernel/Devices/FullDevice.h index 9974e47c4d..fa4ffcb8bc 100644 --- a/Kernel/Devices/FullDevice.h +++ b/Kernel/Devices/FullDevice.h @@ -10,9 +10,9 @@ public: private: // ^CharacterDevice - virtual ssize_t read(FileDescriptor&, byte*, ssize_t) override; - virtual ssize_t write(FileDescriptor&, const byte*, ssize_t) override; - virtual bool can_read(FileDescriptor&) const override; - virtual bool can_write(FileDescriptor&) const override { return true; } + virtual ssize_t read(FileDescription&, byte*, ssize_t) override; + virtual ssize_t write(FileDescription&, const byte*, ssize_t) override; + virtual bool can_read(FileDescription&) const override; + virtual bool can_write(FileDescription&) const override { return true; } virtual const char* class_name() const override { return "FullDevice"; } }; diff --git a/Kernel/Devices/IDEDiskDevice.cpp b/Kernel/Devices/IDEDiskDevice.cpp index 436891da61..4c50915e61 100644 --- a/Kernel/Devices/IDEDiskDevice.cpp +++ b/Kernel/Devices/IDEDiskDevice.cpp @@ -1,81 +1,81 @@ #include #include -#include -#include -#include #include #include +#include +#include +#include //#define DISK_DEBUG #define IRQ_FIXED_DISK 14 -#define ATA_SR_BSY 0x80 -#define ATA_SR_DRDY 0x40 -#define ATA_SR_DF 0x20 -#define ATA_SR_DSC 0x10 -#define ATA_SR_DRQ 0x08 -#define ATA_SR_CORR 0x04 -#define ATA_SR_IDX 0x02 -#define ATA_SR_ERR 0x01 +#define ATA_SR_BSY 0x80 +#define ATA_SR_DRDY 0x40 +#define ATA_SR_DF 0x20 +#define ATA_SR_DSC 0x10 +#define ATA_SR_DRQ 0x08 +#define ATA_SR_CORR 0x04 +#define ATA_SR_IDX 0x02 +#define ATA_SR_ERR 0x01 -#define ATA_ER_BBK 0x80 -#define ATA_ER_UNC 0x40 -#define ATA_ER_MC 0x20 -#define ATA_ER_IDNF 0x10 -#define ATA_ER_MCR 0x08 -#define ATA_ER_ABRT 0x04 -#define ATA_ER_TK0NF 0x02 -#define ATA_ER_AMNF 0x01 +#define ATA_ER_BBK 0x80 +#define ATA_ER_UNC 0x40 +#define ATA_ER_MC 0x20 +#define ATA_ER_IDNF 0x10 +#define ATA_ER_MCR 0x08 +#define ATA_ER_ABRT 0x04 +#define ATA_ER_TK0NF 0x02 +#define ATA_ER_AMNF 0x01 -#define ATA_CMD_READ_PIO 0x20 -#define ATA_CMD_READ_PIO_EXT 0x24 -#define ATA_CMD_READ_DMA 0xC8 -#define ATA_CMD_READ_DMA_EXT 0x25 -#define ATA_CMD_WRITE_PIO 0x30 -#define ATA_CMD_WRITE_PIO_EXT 0x34 -#define ATA_CMD_WRITE_DMA 0xCA -#define ATA_CMD_WRITE_DMA_EXT 0x35 -#define ATA_CMD_CACHE_FLUSH 0xE7 -#define ATA_CMD_CACHE_FLUSH_EXT 0xEA -#define ATA_CMD_PACKET 0xA0 -#define ATA_CMD_IDENTIFY_PACKET 0xA1 -#define ATA_CMD_IDENTIFY 0xEC +#define ATA_CMD_READ_PIO 0x20 +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_READ_DMA 0xC8 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_WRITE_DMA 0xCA +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_CACHE_FLUSH 0xE7 +#define ATA_CMD_CACHE_FLUSH_EXT 0xEA +#define ATA_CMD_PACKET 0xA0 +#define ATA_CMD_IDENTIFY_PACKET 0xA1 +#define ATA_CMD_IDENTIFY 0xEC -#define ATAPI_CMD_READ 0xA8 -#define ATAPI_CMD_EJECT 0x1B +#define ATAPI_CMD_READ 0xA8 +#define ATAPI_CMD_EJECT 0x1B -#define ATA_IDENT_DEVICETYPE 0 -#define ATA_IDENT_CYLINDERS 2 -#define ATA_IDENT_HEADS 6 -#define ATA_IDENT_SECTORS 12 -#define ATA_IDENT_SERIAL 20 -#define ATA_IDENT_MODEL 54 +#define ATA_IDENT_DEVICETYPE 0 +#define ATA_IDENT_CYLINDERS 2 +#define ATA_IDENT_HEADS 6 +#define ATA_IDENT_SECTORS 12 +#define ATA_IDENT_SERIAL 20 +#define ATA_IDENT_MODEL 54 #define ATA_IDENT_CAPABILITIES 98 -#define ATA_IDENT_FIELDVALID 106 -#define ATA_IDENT_MAX_LBA 120 -#define ATA_IDENT_COMMANDSETS 164 -#define ATA_IDENT_MAX_LBA_EXT 200 +#define ATA_IDENT_FIELDVALID 106 +#define ATA_IDENT_MAX_LBA 120 +#define ATA_IDENT_COMMANDSETS 164 +#define ATA_IDENT_MAX_LBA_EXT 200 -#define IDE_ATA 0x00 -#define IDE_ATAPI 0x01 +#define IDE_ATA 0x00 +#define IDE_ATAPI 0x01 -#define ATA_REG_DATA 0x00 -#define ATA_REG_ERROR 0x01 -#define ATA_REG_FEATURES 0x01 -#define ATA_REG_SECCOUNT0 0x02 -#define ATA_REG_LBA0 0x03 -#define ATA_REG_LBA1 0x04 -#define ATA_REG_LBA2 0x05 -#define ATA_REG_HDDEVSEL 0x06 -#define ATA_REG_COMMAND 0x07 -#define ATA_REG_STATUS 0x07 -#define ATA_REG_SECCOUNT1 0x08 -#define ATA_REG_LBA3 0x09 -#define ATA_REG_LBA4 0x0A -#define ATA_REG_LBA5 0x0B -#define ATA_REG_CONTROL 0x0C -#define ATA_REG_ALTSTATUS 0x0C +#define ATA_REG_DATA 0x00 +#define ATA_REG_ERROR 0x01 +#define ATA_REG_FEATURES 0x01 +#define ATA_REG_SECCOUNT0 0x02 +#define ATA_REG_LBA0 0x03 +#define ATA_REG_LBA1 0x04 +#define ATA_REG_LBA2 0x05 +#define ATA_REG_HDDEVSEL 0x06 +#define ATA_REG_COMMAND 0x07 +#define ATA_REG_STATUS 0x07 +#define ATA_REG_SECCOUNT1 0x08 +#define ATA_REG_LBA3 0x09 +#define ATA_REG_LBA4 0x0A +#define ATA_REG_LBA5 0x0B +#define ATA_REG_CONTROL 0x0C +#define ATA_REG_ALTSTATUS 0x0C #define ATA_REG_DEVADDRESS 0x0D Retained IDEDiskDevice::create() @@ -137,14 +137,14 @@ bool IDEDiskDevice::write_block(unsigned index, const byte* data) static void print_ide_status(byte status) { kprintf("DRQ=%u BSY=%u DRDY=%u DSC=%u DF=%u CORR=%u IDX=%u ERR=%u\n", - (status & ATA_SR_DRQ) != 0, - (status & ATA_SR_BSY) != 0, - (status & ATA_SR_DRDY) != 0, - (status & ATA_SR_DSC) != 0, - (status & ATA_SR_DF) != 0, - (status & ATA_SR_CORR) != 0, - (status & ATA_SR_IDX) != 0, - (status & ATA_SR_ERR) != 0); + (status & ATA_SR_DRQ) != 0, + (status & ATA_SR_BSY) != 0, + (status & ATA_SR_DRDY) != 0, + (status & ATA_SR_DSC) != 0, + (status & ATA_SR_DF) != 0, + (status & ATA_SR_CORR) != 0, + (status & ATA_SR_IDX) != 0, + (status & ATA_SR_ERR) != 0); } bool IDEDiskDevice::wait_for_irq() @@ -184,7 +184,7 @@ void IDEDiskDevice::initialize() { static const PCI::ID piix3_ide_id = { 0x8086, 0x7010 }; static const PCI::ID piix4_ide_id = { 0x8086, 0x7111 }; - PCI::enumerate_all([this] (const PCI::Address& address, PCI::ID id) { + PCI::enumerate_all([this](const PCI::Address& address, PCI::ID id) { if (id == piix3_ide_id || id == piix4_ide_id) { m_pci_address = address; kprintf("PIIX%u IDE device found!\n", id == piix3_ide_id ? 3 : 4); @@ -199,7 +199,8 @@ void IDEDiskDevice::initialize() m_interrupted = false; - while (IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_BSY); + while (IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_BSY) + ; enable_irq(); @@ -236,8 +237,7 @@ void IDEDiskDevice::initialize() bbuf.pointer() + 54, m_cylinders, m_heads, - m_sectors_per_track - ); + m_sectors_per_track); // Let's try to set up DMA transfers. if (!m_pci_address.is_null()) { @@ -260,8 +260,8 @@ bool IDEDiskDevice::read_sectors_with_dma(dword lba, word count, byte* outbuf) LOCKER(m_lock); #ifdef DISK_DEBUG dbgprintf("%s(%u): IDEDiskDevice::read_sectors_with_dma (%u x%u) -> %p\n", - current->process().name().characters(), - current->pid(), lba, count, outbuf); + current->process().name().characters(), + current->pid(), lba, count, outbuf); #endif disable_irq(); @@ -286,7 +286,8 @@ bool IDEDiskDevice::read_sectors_with_dma(dword lba, word count, byte* outbuf) m_interrupted = false; enable_irq(); - while (IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_BSY); + while (IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_BSY) + ; bool is_slave = false; @@ -337,13 +338,14 @@ bool IDEDiskDevice::read_sectors(dword start_sector, word count, byte* outbuf) LOCKER(m_lock); #ifdef DISK_DEBUG dbgprintf("%s: Disk::read_sectors request (%u sector(s) @ %u)\n", - current->process().name().characters(), - count, - start_sector); + current->process().name().characters(), + count, + start_sector); #endif disable_irq(); - while (IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_BSY); + while (IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_BSY) + ; #ifdef DISK_DEBUG kprintf("IDEDiskDevice: Reading %u sector(s) @ LBA %u\n", count, start_sector); @@ -356,7 +358,8 @@ bool IDEDiskDevice::read_sectors(dword start_sector, word count, byte* outbuf) IO::out8(m_io_base + ATA_REG_HDDEVSEL, 0xe0 | ((start_sector >> 24) & 0xf)); // 0xf0 for 2nd device IO::out8(0x3F6, 0x08); - while (!(IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_DRDY)); + while (!(IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_DRDY)) + ; IO::out8(m_io_base + ATA_REG_COMMAND, ATA_CMD_READ_PIO); m_interrupted = false; @@ -381,8 +384,8 @@ bool IDEDiskDevice::write_sectors_with_dma(dword lba, word count, const byte* in LOCKER(m_lock); #ifdef DISK_DEBUG dbgprintf("%s(%u): IDEDiskDevice::write_sectors_with_dma (%u x%u) <- %p\n", - current->process().name().characters(), - current->pid(), lba, count, inbuf); + current->process().name().characters(), + current->pid(), lba, count, inbuf); #endif disable_irq(); @@ -406,7 +409,8 @@ bool IDEDiskDevice::write_sectors_with_dma(dword lba, word count, const byte* in m_interrupted = false; enable_irq(); - while (IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_BSY); + while (IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_BSY) + ; bool is_slave = false; @@ -455,14 +459,15 @@ bool IDEDiskDevice::write_sectors(dword start_sector, word count, const byte* da LOCKER(m_lock); #ifdef DISK_DEBUG dbgprintf("%s(%u): IDEDiskDevice::write_sectors request (%u sector(s) @ %u)\n", - current->process().name().characters(), - current->pid(), - count, - start_sector); + current->process().name().characters(), + current->pid(), + count, + start_sector); #endif disable_irq(); - while (IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_BSY); + while (IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_BSY) + ; //dbgprintf("IDEDiskDevice: Writing %u sector(s) @ LBA %u\n", count, start_sector); @@ -476,7 +481,8 @@ bool IDEDiskDevice::write_sectors(dword start_sector, word count, const byte* da IO::out8(m_io_base + ATA_REG_COMMAND, ATA_CMD_WRITE_PIO); - while (!(IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_DRQ)); + while (!(IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_DRQ)) + ; byte status = IO::in8(m_io_base + ATA_REG_STATUS); ASSERT(status & ATA_SR_DRQ); @@ -488,7 +494,8 @@ bool IDEDiskDevice::write_sectors(dword start_sector, word count, const byte* da disable_irq(); IO::out8(m_io_base + ATA_REG_COMMAND, ATA_CMD_CACHE_FLUSH); - while (IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_BSY); + while (IO::in8(m_io_base + ATA_REG_STATUS) & ATA_SR_BSY) + ; m_interrupted = false; enable_irq(); wait_for_irq(); diff --git a/Kernel/Devices/KeyboardDevice.cpp b/Kernel/Devices/KeyboardDevice.cpp index 856fcc2fb8..d939691a92 100644 --- a/Kernel/Devices/KeyboardDevice.cpp +++ b/Kernel/Devices/KeyboardDevice.cpp @@ -1,24 +1,23 @@ -#include -#include "i386.h" #include "IO.h" #include "PIC.h" +#include +#include +#include #include #include -#include //#define KEYBOARD_DEBUG -#define IRQ_KEYBOARD 1 -#define I8042_BUFFER 0x60 -#define I8042_STATUS 0x64 -#define I8042_ACK 0xFA -#define I8042_BUFFER_FULL 0x01 -#define I8042_WHICH_BUFFER 0x20 -#define I8042_MOUSE_BUFFER 0x20 -#define I8042_KEYBOARD_BUFFER 0x00 +#define IRQ_KEYBOARD 1 +#define I8042_BUFFER 0x60 +#define I8042_STATUS 0x64 +#define I8042_ACK 0xFA +#define I8042_BUFFER_FULL 0x01 +#define I8042_WHICH_BUFFER 0x20 +#define I8042_MOUSE_BUFFER 0x20 +#define I8042_KEYBOARD_BUFFER 0x00 -static char map[0x80] = -{ +static char map[0x80] = { 0, '\033', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 0x08, '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0, '\\', @@ -26,8 +25,7 @@ static char map[0x80] = 0, 0, 0, ' ' }; -static char shift_map[0x80] = -{ +static char shift_map[0x80] = { 0, '\033', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', 0x08, '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', 0, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', 0, '|', @@ -35,24 +33,76 @@ static char shift_map[0x80] = 0, 0, 0, ' ' }; -static KeyCode unshifted_key_map[0x80] = -{ - Key_Invalid, Key_Escape, - Key_1, Key_2, Key_3, Key_4, Key_5, Key_6, Key_7, Key_8, Key_9, Key_0, Key_Minus, Key_Equal, Key_Backspace, +static KeyCode unshifted_key_map[0x80] = { + Key_Invalid, + Key_Escape, + Key_1, + Key_2, + Key_3, + Key_4, + Key_5, + Key_6, + Key_7, + Key_8, + Key_9, + Key_0, + Key_Minus, + Key_Equal, + Key_Backspace, Key_Tab, //15 - Key_Q, Key_W, Key_E, Key_R, Key_T, Key_Y, Key_U, Key_I, Key_O, Key_P, Key_LeftBracket, Key_RightBracket, - Key_Return, // 28 + Key_Q, + Key_W, + Key_E, + Key_R, + Key_T, + Key_Y, + Key_U, + Key_I, + Key_O, + Key_P, + Key_LeftBracket, + Key_RightBracket, + Key_Return, // 28 Key_Control, // 29 - Key_A, Key_S, Key_D, Key_F, Key_G, Key_H, Key_J, Key_K, Key_L, Key_Semicolon, Key_Apostrophe, Key_Backtick, + Key_A, + Key_S, + Key_D, + Key_F, + Key_G, + Key_H, + Key_J, + Key_K, + Key_L, + Key_Semicolon, + Key_Apostrophe, + Key_Backtick, Key_LeftShift, // 42 Key_Backslash, - Key_Z, Key_X, Key_C, Key_V, Key_B, Key_N, Key_M, Key_Comma, Key_Period, Key_Slash, + Key_Z, + Key_X, + Key_C, + Key_V, + Key_B, + Key_N, + Key_M, + Key_Comma, + Key_Period, + Key_Slash, Key_RightShift, // 54 Key_Invalid, - Key_Alt, // 56 - Key_Space, // 57 + Key_Alt, // 56 + Key_Space, // 57 Key_Invalid, // 58 - Key_F1, Key_F2, Key_F3, Key_F4, Key_F5, Key_F6, Key_F7, Key_F8, Key_F9, Key_F10, + Key_F1, + Key_F2, + Key_F3, + Key_F4, + Key_F5, + Key_F6, + Key_F7, + Key_F8, + Key_F9, + Key_F10, Key_Invalid, Key_Invalid, // 70 Key_Home, @@ -78,24 +128,76 @@ static KeyCode unshifted_key_map[0x80] = Key_Logo, }; -static KeyCode shifted_key_map[0x100] = -{ - Key_Invalid, Key_Escape, - Key_ExclamationPoint, Key_AtSign, Key_Hashtag, Key_Dollar, Key_Percent, Key_Circumflex, Key_Ampersand, Key_Asterisk, Key_LeftParen, Key_RightParen, Key_Underscore, Key_Plus, Key_Backspace, +static KeyCode shifted_key_map[0x100] = { + Key_Invalid, + Key_Escape, + Key_ExclamationPoint, + Key_AtSign, + Key_Hashtag, + Key_Dollar, + Key_Percent, + Key_Circumflex, + Key_Ampersand, + Key_Asterisk, + Key_LeftParen, + Key_RightParen, + Key_Underscore, + Key_Plus, + Key_Backspace, Key_Tab, - Key_Q, Key_W, Key_E, Key_R, Key_T, Key_Y, Key_U, Key_I, Key_O, Key_P, Key_LeftBrace, Key_RightBrace, + Key_Q, + Key_W, + Key_E, + Key_R, + Key_T, + Key_Y, + Key_U, + Key_I, + Key_O, + Key_P, + Key_LeftBrace, + Key_RightBrace, Key_Return, Key_Control, - Key_A, Key_S, Key_D, Key_F, Key_G, Key_H, Key_J, Key_K, Key_L, Key_Colon, Key_DoubleQuote, Key_Tilde, + Key_A, + Key_S, + Key_D, + Key_F, + Key_G, + Key_H, + Key_J, + Key_K, + Key_L, + Key_Colon, + Key_DoubleQuote, + Key_Tilde, Key_LeftShift, // 42 Key_Pipe, - Key_Z, Key_X, Key_C, Key_V, Key_B, Key_N, Key_M, Key_LessThan, Key_GreaterThan, Key_QuestionMark, + Key_Z, + Key_X, + Key_C, + Key_V, + Key_B, + Key_N, + Key_M, + Key_LessThan, + Key_GreaterThan, + Key_QuestionMark, Key_RightShift, // 54 Key_Invalid, Key_Alt, - Key_Space, // 57 + Key_Space, // 57 Key_Invalid, // 58 - Key_F1, Key_F2, Key_F3, Key_F4, Key_F5, Key_F6, Key_F7, Key_F8, Key_F9, Key_F10, + Key_F1, + Key_F2, + Key_F3, + Key_F4, + Key_F5, + Key_F6, + Key_F7, + Key_F8, + Key_F9, + Key_F10, Key_Invalid, Key_Invalid, // 70 Key_Home, @@ -163,7 +265,8 @@ void KeyboardDevice::handle_irq() break; } switch (ch) { - case I8042_ACK: break; + case I8042_ACK: + break; default: if (m_modifiers & Mod_Alt) { switch (map[ch]) { @@ -208,12 +311,12 @@ KeyboardDevice::~KeyboardDevice() { } -bool KeyboardDevice::can_read(FileDescriptor&) const +bool KeyboardDevice::can_read(FileDescription&) const { return !m_queue.is_empty(); } -ssize_t KeyboardDevice::read(FileDescriptor&, byte* buffer, ssize_t size) +ssize_t KeyboardDevice::read(FileDescription&, byte* buffer, ssize_t size) { ssize_t nread = 0; while (nread < size) { @@ -229,7 +332,7 @@ ssize_t KeyboardDevice::read(FileDescriptor&, byte* buffer, ssize_t size) return nread; } -ssize_t KeyboardDevice::write(FileDescriptor&, const byte*, ssize_t) +ssize_t KeyboardDevice::write(FileDescription&, const byte*, ssize_t) { return 0; } diff --git a/Kernel/Devices/KeyboardDevice.h b/Kernel/Devices/KeyboardDevice.h index 16f134b2a7..1edffe3869 100644 --- a/Kernel/Devices/KeyboardDevice.h +++ b/Kernel/Devices/KeyboardDevice.h @@ -23,10 +23,10 @@ public: void set_client(KeyboardClient* client) { m_client = client; } // ^CharacterDevice - virtual ssize_t read(FileDescriptor&, byte* buffer, ssize_t) override; - virtual bool can_read(FileDescriptor&) const override; - virtual ssize_t write(FileDescriptor&, const byte* buffer, ssize_t) override; - virtual bool can_write(FileDescriptor&) const override { return true; } + virtual ssize_t read(FileDescription&, byte* buffer, ssize_t) override; + virtual bool can_read(FileDescription&) const override; + virtual ssize_t write(FileDescription&, const byte* buffer, ssize_t) override; + virtual bool can_write(FileDescription&) const override { return true; } private: // ^IRQHandler diff --git a/Kernel/Devices/MBRPartitionTable.cpp b/Kernel/Devices/MBRPartitionTable.cpp new file mode 100644 index 0000000000..b194855b3e --- /dev/null +++ b/Kernel/Devices/MBRPartitionTable.cpp @@ -0,0 +1,69 @@ +#include +#include + +#define MBR_DEBUG + +MBRPartitionTable::MBRPartitionTable(Retained&& device) + : m_device(move(device)) +{ +} + +MBRPartitionTable::~MBRPartitionTable() +{ +} + +const MBRPartitionHeader& MBRPartitionTable::header() const +{ + return *reinterpret_cast(m_cached_header); +} + +bool MBRPartitionTable::initialize() +{ + if (!m_device->read_block(0, m_cached_header)) { + return false; + } + + auto& header = this->header(); + +#ifdef MBR_DEBUG + kprintf("MBRPartitionTable::initialize: mbr_signature=%#x\n", header.mbr_signature); +#endif + + if (header.mbr_signature != MBR_SIGNATURE) { + kprintf("MBRPartitionTable::initialize: bad mbr signature %#x\n", header.mbr_signature); + return false; + } + + return true; +} + +RetainPtr MBRPartitionTable::partition(unsigned index) +{ + ASSERT(index >= 1 && index <= 4); + + auto& header = this->header(); + auto& entry = header.entry[index - 1]; + + if (header.mbr_signature != MBR_SIGNATURE) { + kprintf("MBRPartitionTable::initialize: bad mbr signature - not initalized? %#x\n", header.mbr_signature); + return nullptr; + } + +#ifdef MBR_DEBUG + kprintf("MBRPartitionTable::partition: status=%#x offset=%#x\n", entry.status, entry.offset); +#endif + + if (entry.offset == 0x00) { +#ifdef MBR_DEBUG + kprintf("MBRPartitionTable::partition: missing partition requested index=%d\n", index); +#endif + + return nullptr; + } + +#ifdef MBR_DEBUG + kprintf("MBRPartitionTable::partition: found partition index=%d type=%x\n", index, entry.type); +#endif + + return DiskPartition::create(m_device.copy_ref(), entry.offset); +} diff --git a/Kernel/Devices/MBRPartitionTable.h b/Kernel/Devices/MBRPartitionTable.h new file mode 100644 index 0000000000..a3ad937b2c --- /dev/null +++ b/Kernel/Devices/MBRPartitionTable.h @@ -0,0 +1,47 @@ +#pragma once + +#include +#include +#include +#include + +#define MBR_SIGNATURE 0xaa55 + +struct MBRPartitionEntry { + byte status; + byte chs1[3]; + byte type; + byte chs2[3]; + dword offset; + dword length; +} __attribute__((packed)); + +struct MBRPartitionHeader { + byte code1[218]; + word ts_zero; + byte ts_drive, ts_seconds, ts_minutes, ts_hours; + byte code2[216]; + dword disk_signature; + word disk_signature_zero; + MBRPartitionEntry entry[4]; + word mbr_signature; +} __attribute__((packed)); + +class MBRPartitionTable { + AK_MAKE_ETERNAL + +public: + MBRPartitionTable(Retained&& device); + ~MBRPartitionTable(); + + bool initialize(); + RetainPtr partition(unsigned index); + +private: + Retained m_device; + + ByteBuffer read_header() const; + const MBRPartitionHeader& header() const; + + byte m_cached_header[512]; +}; diff --git a/Kernel/Devices/NullDevice.cpp b/Kernel/Devices/NullDevice.cpp index e93bd55891..1d4cfcdaf6 100644 --- a/Kernel/Devices/NullDevice.cpp +++ b/Kernel/Devices/NullDevice.cpp @@ -20,18 +20,17 @@ NullDevice::~NullDevice() { } -bool NullDevice::can_read(FileDescriptor&) const +bool NullDevice::can_read(FileDescription&) const { return true; } -ssize_t NullDevice::read(FileDescriptor&, byte*, ssize_t) +ssize_t NullDevice::read(FileDescription&, byte*, ssize_t) { return 0; } -ssize_t NullDevice::write(FileDescriptor&, const byte*, ssize_t buffer_size) +ssize_t NullDevice::write(FileDescription&, const byte*, ssize_t buffer_size) { return min(PAGE_SIZE, buffer_size); } - diff --git a/Kernel/Devices/NullDevice.h b/Kernel/Devices/NullDevice.h index 47ba7baf5a..964565c690 100644 --- a/Kernel/Devices/NullDevice.h +++ b/Kernel/Devices/NullDevice.h @@ -12,9 +12,9 @@ public: private: // ^CharacterDevice - virtual ssize_t read(FileDescriptor&, byte*, ssize_t) override; - virtual ssize_t write(FileDescriptor&, const byte*, ssize_t) override; - virtual bool can_write(FileDescriptor&) const override { return true; } - virtual bool can_read(FileDescriptor&) const override; + virtual ssize_t read(FileDescription&, byte*, ssize_t) override; + virtual ssize_t write(FileDescription&, const byte*, ssize_t) override; + virtual bool can_write(FileDescription&) const override { return true; } + virtual bool can_read(FileDescription&) const override; virtual const char* class_name() const override { return "NullDevice"; } }; diff --git a/Kernel/Devices/PCSpeaker.cpp b/Kernel/Devices/PCSpeaker.cpp index 347dd33b62..5fa9bd83e1 100644 --- a/Kernel/Devices/PCSpeaker.cpp +++ b/Kernel/Devices/PCSpeaker.cpp @@ -1,7 +1,7 @@ +#include #include -#include #include -#include +#include void PCSpeaker::tone_on(int frequency) { diff --git a/Kernel/Devices/PS2MouseDevice.cpp b/Kernel/Devices/PS2MouseDevice.cpp index c7d8ff54f5..b48b537e8b 100644 --- a/Kernel/Devices/PS2MouseDevice.cpp +++ b/Kernel/Devices/PS2MouseDevice.cpp @@ -1,16 +1,16 @@ #include "PS2MouseDevice.h" #include "IO.h" -#define IRQ_MOUSE 1 -#define I8042_BUFFER 0x60 -#define I8042_STATUS 0x64 -#define I8042_ACK 0xFA -#define I8042_BUFFER_FULL 0x01 -#define I8042_WHICH_BUFFER 0x20 -#define I8042_MOUSE_BUFFER 0x20 -#define I8042_KEYBOARD_BUFFER 0x00 +#define IRQ_MOUSE 1 +#define I8042_BUFFER 0x60 +#define I8042_STATUS 0x64 +#define I8042_ACK 0xFA +#define I8042_BUFFER_FULL 0x01 +#define I8042_WHICH_BUFFER 0x20 +#define I8042_MOUSE_BUFFER 0x20 +#define I8042_KEYBOARD_BUFFER 0x00 -#define PS2MOUSE_GET_DEVICE_ID 0xF2 +#define PS2MOUSE_GET_DEVICE_ID 0xF2 #define PS2MOUSE_SET_SAMPLE_RATE 0xF3 #define PS2MOUSE_INTELLIMOUSE_ID 0x03 @@ -54,8 +54,7 @@ void PS2MouseDevice::handle_irq() m_data[2], (m_data[0] & 1) ? "Left" : "", (m_data[0] & 2) ? "Right" : "", - m_queue.size() - ); + m_queue.size()); #endif parse_data_packet(); }; @@ -218,12 +217,12 @@ byte PS2MouseDevice::mouse_read() return IO::in8(0x60); } -bool PS2MouseDevice::can_read(FileDescriptor&) const +bool PS2MouseDevice::can_read(FileDescription&) const { return !m_queue.is_empty(); } -ssize_t PS2MouseDevice::read(FileDescriptor&, byte* buffer, ssize_t size) +ssize_t PS2MouseDevice::read(FileDescription&, byte* buffer, ssize_t size) { ssize_t nread = 0; while (nread < size) { @@ -239,7 +238,7 @@ ssize_t PS2MouseDevice::read(FileDescriptor&, byte* buffer, ssize_t size) return nread; } -ssize_t PS2MouseDevice::write(FileDescriptor&, const byte*, ssize_t) +ssize_t PS2MouseDevice::write(FileDescription&, const byte*, ssize_t) { return 0; } diff --git a/Kernel/Devices/PS2MouseDevice.h b/Kernel/Devices/PS2MouseDevice.h index de97cfe4e1..e63db8a998 100644 --- a/Kernel/Devices/PS2MouseDevice.h +++ b/Kernel/Devices/PS2MouseDevice.h @@ -14,10 +14,10 @@ public: static PS2MouseDevice& the(); // ^CharacterDevice - virtual bool can_read(FileDescriptor&) const override; - virtual ssize_t read(FileDescriptor&, byte*, ssize_t) override; - virtual ssize_t write(FileDescriptor&, const byte*, ssize_t) override; - virtual bool can_write(FileDescriptor&) const override { return true; } + virtual bool can_read(FileDescription&) const override; + virtual ssize_t read(FileDescription&, byte*, ssize_t) override; + virtual ssize_t write(FileDescription&, const byte*, ssize_t) override; + virtual bool can_write(FileDescription&) const override { return true; } private: // ^IRQHandler diff --git a/Kernel/Devices/RandomDevice.cpp b/Kernel/Devices/RandomDevice.cpp index 354212fbcd..c5ff3f2562 100644 --- a/Kernel/Devices/RandomDevice.cpp +++ b/Kernel/Devices/RandomDevice.cpp @@ -26,12 +26,12 @@ static void mysrand(unsigned seed) } #endif -bool RandomDevice::can_read(FileDescriptor&) const +bool RandomDevice::can_read(FileDescription&) const { return true; } -ssize_t RandomDevice::read(FileDescriptor&, byte* buffer, ssize_t size) +ssize_t RandomDevice::read(FileDescription&, byte* buffer, ssize_t size) { const int range = 'z' - 'a'; ssize_t nread = min(size, PAGE_SIZE); @@ -42,9 +42,8 @@ ssize_t RandomDevice::read(FileDescriptor&, byte* buffer, ssize_t size) return nread; } -ssize_t RandomDevice::write(FileDescriptor&, const byte*, ssize_t size) +ssize_t RandomDevice::write(FileDescription&, const byte*, ssize_t size) { // FIXME: Use input for entropy? I guess that could be a neat feature? return min(PAGE_SIZE, size); } - diff --git a/Kernel/Devices/RandomDevice.h b/Kernel/Devices/RandomDevice.h index ecce3c6bfb..4d6dce159e 100644 --- a/Kernel/Devices/RandomDevice.h +++ b/Kernel/Devices/RandomDevice.h @@ -12,9 +12,9 @@ public: private: // ^CharacterDevice - virtual ssize_t read(FileDescriptor&, byte*, ssize_t) override; - virtual ssize_t write(FileDescriptor&, const byte*, ssize_t) override; - virtual bool can_read(FileDescriptor&) const override; - virtual bool can_write(FileDescriptor&) const override { return true; } + virtual ssize_t read(FileDescription&, byte*, ssize_t) override; + virtual ssize_t write(FileDescription&, const byte*, ssize_t) override; + virtual bool can_read(FileDescription&) const override; + virtual bool can_write(FileDescription&) const override { return true; } virtual const char* class_name() const override { return "RandomDevice"; } }; diff --git a/Kernel/Devices/SerialDevice.cpp b/Kernel/Devices/SerialDevice.cpp new file mode 100644 index 0000000000..d945e4c1d4 --- /dev/null +++ b/Kernel/Devices/SerialDevice.cpp @@ -0,0 +1,110 @@ +#include +#include + +SerialDevice::SerialDevice(int base_addr, unsigned minor) + : CharacterDevice(4, minor) + , m_base_addr(base_addr) +{ + initialize(); +} + +SerialDevice::~SerialDevice() +{ +} + +bool SerialDevice::can_read(FileDescription&) const +{ + return (get_line_status() & DataReady) != 0; +} + +ssize_t SerialDevice::read(FileDescription&, byte* buffer, ssize_t size) +{ + if (!size) + return 0; + + if (!(get_line_status() & DataReady)) + return 0; + + buffer[0] = IO::in8(m_base_addr); + + return 1; +} + +bool SerialDevice::can_write(FileDescription&) const +{ + return (get_line_status() & EmptyTransmitterHoldingRegister) != 0; +} + +ssize_t SerialDevice::write(FileDescription&, const byte* buffer, ssize_t size) +{ + if (!size) + return 0; + + if (!(get_line_status() & EmptyTransmitterHoldingRegister)) + return 0; + + IO::out8(m_base_addr, buffer[0]); + + return 1; +} + +void SerialDevice::initialize() +{ + set_interrupts(0); + set_baud(Baud38400); + set_line_control(None, One, EightBits); + set_fifo_control(EnableFIFO | ClearReceiveFIFO | ClearTransmitFIFO | TriggerLevel4); + set_modem_control(RequestToSend | DataTerminalReady); +} + +void SerialDevice::set_interrupts(char interrupt_enable) +{ + m_interrupt_enable = interrupt_enable; + + IO::out8(m_base_addr + 1, interrupt_enable); +} + +void SerialDevice::set_baud(Baud baud) +{ + m_baud = baud; + + IO::out8(m_base_addr + 3, IO::in8(m_base_addr + 3) | 0x80); // turn on DLAB + IO::out8(m_base_addr + 0, ((char)(baud)) >> 2); // lower half of divisor + IO::out8(m_base_addr + 1, ((char)(baud)) & 0xff); // upper half of divisor + IO::out8(m_base_addr + 3, IO::in8(m_base_addr + 3) & 0x7f); // turn off DLAB +} + +void SerialDevice::set_fifo_control(char fifo_control) +{ + m_fifo_control = fifo_control; + + IO::out8(m_base_addr + 2, fifo_control); +} + +void SerialDevice::set_line_control(ParitySelect parity_select, StopBits stop_bits, WordLength word_length) +{ + m_parity_select = parity_select; + m_stop_bits = stop_bits; + m_word_length = word_length; + + IO::out8(m_base_addr + 3, IO::in8(m_base_addr + 3) & (0xc0 | parity_select | stop_bits | word_length)); +} + +void SerialDevice::set_break_enable(bool break_enable) +{ + m_break_enable = break_enable; + + IO::out8(m_base_addr + 3, IO::in8(m_base_addr + 3) & (break_enable ? 0xff : 0xbf)); +} + +void SerialDevice::set_modem_control(char modem_control) +{ + m_modem_control = modem_control; + + IO::out8(m_base_addr + 4, modem_control); +} + +char SerialDevice::get_line_status() const +{ + return IO::in8(m_base_addr + 5); +} diff --git a/Kernel/Devices/SerialDevice.h b/Kernel/Devices/SerialDevice.h new file mode 100644 index 0000000000..3cccf0c91a --- /dev/null +++ b/Kernel/Devices/SerialDevice.h @@ -0,0 +1,120 @@ +#include + +#define SERIAL_COM1_ADDR 0x3F8 +#define SERIAL_COM2_ADDR 0x2F8 +#define SERIAL_COM3_ADDR 0x3E8 +#define SERIAL_COM4_ADDR 0x2E8 + +class SerialDevice final : public CharacterDevice { + AK_MAKE_ETERNAL +public: + SerialDevice(int base_addr, unsigned minor); + virtual ~SerialDevice() override; + + // ^CharacterDevice + virtual bool can_read(FileDescription&) const override; + virtual ssize_t read(FileDescription&, byte*, ssize_t) override; + virtual bool can_write(FileDescription&) const override; + virtual ssize_t write(FileDescription&, const byte*, ssize_t) override; + + enum InterruptEnable { + LowPowerMode = 0x01 << 5, + SleepMode = 0x01 << 4, + ModemStatusInterrupt = 0x01 << 3, + ReceiverLineStatusInterrupt = 0x01 << 2, + TransmitterHoldingRegisterEmptyInterrupt = 0x01 << 1, + ReceivedDataAvailableInterrupt = 0x01 << 0 + }; + + enum Baud { + Baud50 = 2304, + Baud110 = 1047, + Baud220 = 524, + Baud300 = 384, + Baud600 = 192, + Baud1200 = 96, + Baud2400 = 48, + Baud4800 = 24, + Baud9600 = 12, + Baud19200 = 6, + Baud38400 = 3, + Baud57600 = 2, + Baud115200 = 1 + }; + + enum ParitySelect { + None = 0x00 << 3, + Odd = 0x01 << 3, + Even = 0x03 << 3, + Mark = 0x05 << 3, + Space = 0x07 << 3 + }; + + enum StopBits { + One = 0x00 << 2, + Two = 0x01 << 2 + }; + + enum WordLength { + FiveBits = 0x00, + SixBits = 0x01, + SevenBits = 0x02, + EightBits = 0x03 + }; + + enum FIFOControl { + EnableFIFO = 0x01 << 0, + ClearReceiveFIFO = 0x01 << 1, + ClearTransmitFIFO = 0x01 << 2, + Enable64ByteFIFO = 0x01 << 5, + TriggerLevel1 = 0x00 << 6, + TriggerLevel2 = 0x01 << 6, + TriggerLevel3 = 0x02 << 6, + TriggerLevel4 = 0x03 << 6 + }; + + enum ModemControl { + AutoflowControlEnabled = 0x01 << 5, + LoopbackMode = 0x01 << 4, + AuxiliaryOutput2 = 0x01 << 3, + AuxiliaryOutput1 = 0x01 << 2, + RequestToSend = 0x01 << 1, + DataTerminalReady = 0x01 << 0 + }; + + enum LineStatus { + ErrorInReceivedFIFO = 0x01 << 7, + EmptyDataHoldingRegisters = 0x01 << 6, + EmptyTransmitterHoldingRegister = 0x01 << 5, + BreakInterrupt = 0x01 << 4, + FramingError = 0x01 << 3, + ParityError = 0x01 << 2, + OverrunError = 0x01 << 1, + DataReady = 0x01 << 0 + }; + +private: + // ^CharacterDevice + virtual const char* class_name() const override { return "SerialDevice"; } + + void initialize(); + void set_interrupts(char interrupt_enable); + void set_baud(Baud); + void set_fifo_control(char fifo_control); + void set_line_control(ParitySelect, StopBits, WordLength); + void set_break_enable(bool break_enable); + void set_modem_control(char modem_control); + char get_line_status() const; + bool rx_ready(); + bool tx_ready(); + + int m_base_addr; + char m_interrupt_enable; + char m_fifo_control; + Baud m_baud; + ParitySelect m_parity_select; + StopBits m_stop_bits; + WordLength m_word_length; + bool m_break_enable; + char m_modem_control; +}; diff --git a/Kernel/Devices/ZeroDevice.cpp b/Kernel/Devices/ZeroDevice.cpp index ee809045bc..e9eed27af0 100644 --- a/Kernel/Devices/ZeroDevice.cpp +++ b/Kernel/Devices/ZeroDevice.cpp @@ -11,20 +11,19 @@ ZeroDevice::~ZeroDevice() { } -bool ZeroDevice::can_read(FileDescriptor&) const +bool ZeroDevice::can_read(FileDescription&) const { return true; } -ssize_t ZeroDevice::read(FileDescriptor&, byte* buffer, ssize_t size) +ssize_t ZeroDevice::read(FileDescription&, byte* buffer, ssize_t size) { ssize_t count = min(PAGE_SIZE, size); memset(buffer, 0, (size_t)count); return count; } -ssize_t ZeroDevice::write(FileDescriptor&, const byte*, ssize_t size) +ssize_t ZeroDevice::write(FileDescription&, const byte*, ssize_t size) { return min(PAGE_SIZE, size); } - diff --git a/Kernel/Devices/ZeroDevice.h b/Kernel/Devices/ZeroDevice.h index 930f3adec2..631fdd8965 100644 --- a/Kernel/Devices/ZeroDevice.h +++ b/Kernel/Devices/ZeroDevice.h @@ -10,9 +10,9 @@ public: private: // ^CharacterDevice - virtual ssize_t read(FileDescriptor&, byte*, ssize_t) override; - virtual ssize_t write(FileDescriptor&, const byte*, ssize_t) override; - virtual bool can_read(FileDescriptor&) const override; - virtual bool can_write(FileDescriptor&) const override { return true; } + virtual ssize_t read(FileDescription&, byte*, ssize_t) override; + virtual ssize_t write(FileDescription&, const byte*, ssize_t) override; + virtual bool can_read(FileDescription&) const override; + virtual bool can_write(FileDescription&) const override { return true; } virtual const char* class_name() const override { return "ZeroDevice"; } }; diff --git a/Kernel/File.cpp b/Kernel/File.cpp index 7de0f240f8..b366c523b1 100644 --- a/Kernel/File.cpp +++ b/Kernel/File.cpp @@ -1,5 +1,5 @@ #include -#include +#include File::File() { @@ -9,23 +9,22 @@ File::~File() { } -KResultOr> File::open(int options) +KResultOr> File::open(int options) { UNUSED_PARAM(options); - return FileDescriptor::create(this); + return FileDescription::create(this); } void File::close() { } -int File::ioctl(FileDescriptor&, unsigned, unsigned) +int File::ioctl(FileDescription&, unsigned, unsigned) { return -ENOTTY; } -KResultOr File::mmap(Process&, LinearAddress, size_t, size_t, int) +KResultOr File::mmap(Process&, FileDescription&, VirtualAddress, size_t, size_t, int) { return KResult(-ENODEV); } - diff --git a/Kernel/File.h b/Kernel/File.h index 9daa97ca79..03fb9d4aef 100644 --- a/Kernel/File.h +++ b/Kernel/File.h @@ -5,29 +5,56 @@ #include #include #include -#include #include +#include -class FileDescriptor; +class FileDescription; class Process; class Region; +// File is the base class for anything that can be referenced by a FileDescription. +// +// The most important functions in File are: +// +// read() and write() +// - Implement reading and writing. +// - Return the number of bytes read/written, OR a negative error code. +// +// can_read() and can_write() +// +// - Used to implement blocking I/O, and the select() and poll() syscalls. +// - Return true if read() or write() would succeed, respectively. +// - Note that can_read() should return true in EOF conditions, +// and a subsequent call to read() should return 0. +// +// ioctl() +// +// - Optional. If unimplemented, ioctl() on this File will fail with -ENOTTY. +// - Can be overridden in subclasses to implement arbitrary functionality. +// - Subclasses should take care to validate incoming addresses before dereferencing. +// +// mmap() +// +// - Optional. If unimplemented, mmap() on this File will fail with -ENODEV. +// - Called by mmap() when userspace wants to memory-map this File somewhere. +// - Should create a Region in the Process and return it if successful. + class File : public Retainable { public: virtual ~File(); - virtual KResultOr> open(int options); + virtual KResultOr> open(int options); virtual void close(); - virtual bool can_read(FileDescriptor&) const = 0; - virtual bool can_write(FileDescriptor&) const = 0; + virtual bool can_read(FileDescription&) const = 0; + virtual bool can_write(FileDescription&) const = 0; - virtual ssize_t read(FileDescriptor&, byte*, ssize_t) = 0; - virtual ssize_t write(FileDescriptor&, const byte*, ssize_t) = 0; - virtual int ioctl(FileDescriptor&, unsigned request, unsigned arg); - virtual KResultOr mmap(Process&, LinearAddress preferred_laddr, size_t offset, size_t size, int prot); + virtual ssize_t read(FileDescription&, byte*, ssize_t) = 0; + virtual ssize_t write(FileDescription&, const byte*, ssize_t) = 0; + virtual int ioctl(FileDescription&, unsigned request, unsigned arg); + virtual KResultOr mmap(Process&, FileDescription&, VirtualAddress preferred_vaddr, size_t offset, size_t size, int prot); - virtual String absolute_path(FileDescriptor&) const = 0; + virtual String absolute_path(const FileDescription&) const = 0; virtual KResult truncate(off_t) { return KResult(-EINVAL); } diff --git a/Kernel/FileSystem/Custody.cpp b/Kernel/FileSystem/Custody.cpp index f70d1a2719..769d4c0de8 100644 --- a/Kernel/FileSystem/Custody.cpp +++ b/Kernel/FileSystem/Custody.cpp @@ -31,9 +31,9 @@ Retained Custody::get_or_create(Custody* parent, const String& name, In if (RetainPtr cached_custody = get_if_cached(parent, name)) { if (&cached_custody->inode() != &inode) { dbgprintf("WTF! cached custody for name '%s' has inode=%s, new inode=%s\n", - name.characters(), - cached_custody->inode().identifier().to_string().characters(), - inode.identifier().to_string().characters()); + name.characters(), + cached_custody->inode().identifier().to_string().characters(), + inode.identifier().to_string().characters()); } ASSERT(&cached_custody->inode() == &inode); return *cached_custody; @@ -83,4 +83,3 @@ void Custody::did_rename(Badge, const String& name) { m_name = name; } - diff --git a/Kernel/FileSystem/DevPtsFS.cpp b/Kernel/FileSystem/DevPtsFS.cpp index 8e8fd94637..be3a0d6968 100644 --- a/Kernel/FileSystem/DevPtsFS.cpp +++ b/Kernel/FileSystem/DevPtsFS.cpp @@ -1,7 +1,7 @@ -#include -#include -#include #include +#include +#include +#include static DevPtsFS* s_the; diff --git a/Kernel/FileSystem/DiskBackedFileSystem.cpp b/Kernel/FileSystem/DiskBackedFileSystem.cpp index fe241e99d3..413e4931ed 100644 --- a/Kernel/FileSystem/DiskBackedFileSystem.cpp +++ b/Kernel/FileSystem/DiskBackedFileSystem.cpp @@ -1,6 +1,6 @@ #include "DiskBackedFileSystem.h" -#include "i386.h" #include +#include #include //#define DBFS_DEBUG diff --git a/Kernel/FileSystem/Ext2FileSystem.cpp b/Kernel/FileSystem/Ext2FileSystem.cpp index b0e8925dde..3ad2c9b306 100644 --- a/Kernel/FileSystem/Ext2FileSystem.cpp +++ b/Kernel/FileSystem/Ext2FileSystem.cpp @@ -1,12 +1,12 @@ -#include "Ext2FileSystem.h" -#include "ext2_fs.h" -#include "UnixTypes.h" -#include "RTC.h" #include -#include #include -#include +#include +#include +#include #include +#include +#include +#include //#define EXT2_DEBUG @@ -162,10 +162,10 @@ ByteBuffer Ext2FS::read_block_containing_inode(unsigned inode, unsigned& block_i auto& super_block = this->super_block(); if (inode != EXT2_ROOT_INO && inode < EXT2_FIRST_INO(&super_block)) - return { }; + return {}; if (inode > super_block.s_inodes_count) - return { }; + return {}; auto& bgd = group_descriptor(group_index_from_inode(inode)); @@ -314,7 +314,7 @@ Vector Ext2FS::block_list_for_inode(const ext2_inode& e2inod if (!blocks_remaining) return list; - auto process_block_array = [&] (unsigned array_block_index, auto&& callback) { + auto process_block_array = [&](unsigned array_block_index, auto&& callback) { if (include_block_list_blocks) callback(array_block_index); auto array_block = read_block(array_block_index); @@ -331,15 +331,15 @@ Vector Ext2FS::block_list_for_inode(const ext2_inode& e2inod } }; - process_block_array(e2inode.i_block[EXT2_IND_BLOCK], [&] (unsigned entry) { + process_block_array(e2inode.i_block[EXT2_IND_BLOCK], [&](unsigned entry) { list.unchecked_append(entry); }); if (!blocks_remaining) return list; - process_block_array(e2inode.i_block[EXT2_DIND_BLOCK], [&] (unsigned entry) { - process_block_array(entry, [&] (unsigned entry) { + process_block_array(e2inode.i_block[EXT2_DIND_BLOCK], [&](unsigned entry) { + process_block_array(entry, [&](unsigned entry) { list.unchecked_append(entry); }); }); @@ -347,9 +347,9 @@ Vector Ext2FS::block_list_for_inode(const ext2_inode& e2inod if (!blocks_remaining) return list; - process_block_array(e2inode.i_block[EXT2_TIND_BLOCK], [&] (unsigned entry) { - process_block_array(entry, [&] (unsigned entry) { - process_block_array(entry, [&] (unsigned entry) { + process_block_array(e2inode.i_block[EXT2_TIND_BLOCK], [&](unsigned entry) { + process_block_array(entry, [&](unsigned entry) { + process_block_array(entry, [&](unsigned entry) { list.unchecked_append(entry); }); }); @@ -468,7 +468,7 @@ RetainPtr Ext2FS::get_inode(InodeIdentifier inode) const unsigned offset; auto block = read_block_containing_inode(inode.index(), block_index, offset); if (!block) - return { }; + return {}; auto it = m_inode_cache.find(inode.index()); if (it != m_inode_cache.end()) @@ -479,7 +479,7 @@ RetainPtr Ext2FS::get_inode(InodeIdentifier inode) const return new_inode; } -ssize_t Ext2FSInode::read_bytes(off_t offset, ssize_t count, byte* buffer, FileDescriptor*) const +ssize_t Ext2FSInode::read_bytes(off_t offset, ssize_t count, byte* buffer, FileDescription*) const { Locker inode_locker(m_lock); ASSERT(offset >= 0); @@ -585,7 +585,7 @@ bool Ext2FSInode::resize(qword new_size) return true; } -ssize_t Ext2FSInode::write_bytes(off_t offset, ssize_t count, const byte* data, FileDescriptor*) +ssize_t Ext2FSInode::write_bytes(off_t offset, ssize_t count, const byte* data, FileDescription*) { ASSERT(offset >= 0); ASSERT(count >= 0); @@ -704,85 +704,10 @@ bool Ext2FSInode::traverse_as_directory(Function& entries) { LOCKER(m_lock); - ASSERT(is_directory()); - -//#ifdef EXT2_DEBUG - dbgprintf("Ext2FS: Adding inode %u with name '%s' to directory %u\n", child_id.index(), name.characters(), index()); -//#endif - - Vector entries; - bool name_already_exists = false; - traverse_as_directory([&] (auto& entry) { - if (!strcmp(entry.name, name.characters())) { - name_already_exists = true; - return false; - } - entries.append(entry); - return true; - }); - if (name_already_exists) { - kprintf("Ext2FS: Name '%s' already exists in directory inode %u\n", name.characters(), index()); - return KResult(-EEXIST); - } - - auto child_inode = fs().get_inode(child_id); - if (child_inode) - child_inode->increment_link_count(); - - entries.append({ name.characters(), name.length(), child_id, to_ext2_file_type(mode) }); - bool success = fs().write_directory_inode(index(), move(entries)); - if (success) - m_lookup_cache.set(name, child_id.index()); - return KSuccess; -} - -KResult Ext2FSInode::remove_child(const String& name) -{ - LOCKER(m_lock); -#ifdef EXT2_DEBUG - dbgprintf("Ext2FSInode::remove_child(%s) in inode %u\n", name.characters(), index()); -#endif - ASSERT(is_directory()); - - unsigned child_inode_index; - auto it = m_lookup_cache.find(name); - if (it == m_lookup_cache.end()) - return KResult(-ENOENT); - child_inode_index = (*it).value; - - InodeIdentifier child_id { fsid(), child_inode_index }; - -//#ifdef EXT2_DEBUG - dbgprintf("Ext2FS: Removing '%s' in directory %u\n", name.characters(), index()); -//#endif - - Vector entries; - traverse_as_directory([&] (auto& entry) { - if (strcmp(entry.name, name.characters()) != 0) - entries.append(entry); - return true; - }); - - bool success = fs().write_directory_inode(index(), move(entries)); - if (!success) { - // FIXME: Plumb error from write_directory_inode(). - return KResult(-EIO); - } - - m_lookup_cache.remove(name); - - auto child_inode = fs().get_inode(child_id); - child_inode->decrement_link_count(); - return KSuccess; -} - -bool Ext2FS::write_directory_inode(InodeIndex directory_inode_index, Vector&& entries) -{ - LOCKER(m_lock); - dbgprintf("Ext2FS: New directory inode %u contents to write:\n", directory_inode_index); + dbgprintf("Ext2FS: New directory inode %u contents to write:\n", index()); int directory_size = 0; for (auto& entry : entries) { @@ -790,8 +715,10 @@ bool Ext2FS::write_directory_inode(InodeIndex directory_inode_index, Vectorwrite_bytes(0, directory_data.size(), directory_data.pointer(), nullptr); + ssize_t nwritten = write_bytes(0, directory_data.size(), directory_data.pointer(), nullptr); return nwritten == directory_data.size(); } +KResult Ext2FSInode::add_child(InodeIdentifier child_id, const StringView& name, mode_t mode) +{ + LOCKER(m_lock); + ASSERT(is_directory()); + + //#ifdef EXT2_DEBUG + dbgprintf("Ext2FS: Adding inode %u with name '%s' and mode %o to directory %u\n", child_id.index(), name.characters(), mode, index()); + //#endif + + Vector entries; + bool name_already_exists = false; + traverse_as_directory([&](auto& entry) { + if (name == entry.name) { + name_already_exists = true; + return false; + } + entries.append(entry); + return true; + }); + if (name_already_exists) { + kprintf("Ext2FS: Name '%s' already exists in directory inode %u\n", name.characters(), index()); + return KResult(-EEXIST); + } + + auto child_inode = fs().get_inode(child_id); + if (child_inode) + child_inode->increment_link_count(); + + entries.append({ name.characters(), name.length(), child_id, to_ext2_file_type(mode) }); + bool success = write_directory(entries); + if (success) + m_lookup_cache.set(name, child_id.index()); + return KSuccess; +} + +KResult Ext2FSInode::remove_child(const StringView& name) +{ + LOCKER(m_lock); +#ifdef EXT2_DEBUG + dbgprintf("Ext2FSInode::remove_child(%s) in inode %u\n", name.characters(), index()); +#endif + ASSERT(is_directory()); + + unsigned child_inode_index; + auto it = m_lookup_cache.find(name); + if (it == m_lookup_cache.end()) + return KResult(-ENOENT); + child_inode_index = (*it).value; + + InodeIdentifier child_id { fsid(), child_inode_index }; + + //#ifdef EXT2_DEBUG + dbgprintf("Ext2FS: Removing '%s' in directory %u\n", name.characters(), index()); + //#endif + + Vector entries; + traverse_as_directory([&](auto& entry) { + if (name != entry.name) + entries.append(entry); + return true; + }); + + bool success = write_directory(entries); + if (!success) { + // FIXME: Plumb error from write_directory(). + return KResult(-EIO); + } + + m_lookup_cache.remove(name); + + auto child_inode = fs().get_inode(child_id); + child_inode->decrement_link_count(); + return KSuccess; +} + unsigned Ext2FS::inodes_per_block() const { return EXT2_INODES_PER_BLOCK(&super_block()); @@ -842,7 +843,6 @@ unsigned Ext2FS::inodes_per_group() const unsigned Ext2FS::inode_size() const { return EXT2_INODE_SIZE(&super_block()); - } unsigned Ext2FS::blocks_per_group() const { @@ -868,12 +868,12 @@ Vector Ext2FS::allocate_blocks(GroupIndex group_index, int c LOCKER(m_lock); dbgprintf("Ext2FS: allocate_blocks(group: %u, count: %u)\n", group_index, count); if (count == 0) - return { }; + return {}; auto& bgd = group_descriptor(group_index); if (bgd.bg_free_blocks_count < count) { kprintf("Ext2FS: allocate_blocks can't allocate out of group %u, wanted %u but only %u available\n", group_index, count, bgd.bg_free_blocks_count); - return { }; + return {}; } // FIXME: Implement a scan that finds consecutive blocks if possible. @@ -881,7 +881,7 @@ Vector Ext2FS::allocate_blocks(GroupIndex group_index, int c auto bitmap_block = read_block(bgd.bg_block_bitmap); int blocks_in_group = min(blocks_per_group(), super_block().s_blocks_count); auto block_bitmap = Bitmap::wrap(bitmap_block.pointer(), blocks_in_group); - BlockIndex first_block_in_group = (group_index - 1) * blocks_per_group(); + BlockIndex first_block_in_group = (group_index - 1) * blocks_per_group() + 1; for (int i = 0; i < block_bitmap.size(); ++i) { if (!block_bitmap.get(i)) { blocks.append(first_block_in_group + i); @@ -910,7 +910,7 @@ unsigned Ext2FS::allocate_inode(GroupIndex preferred_group, off_t expected_size) unsigned group_index = 0; - auto is_suitable_group = [this, needed_blocks] (GroupIndex group_index) { + auto is_suitable_group = [this, needed_blocks](GroupIndex group_index) { auto& bgd = group_descriptor(group_index); return bgd.bg_free_inodes_count && bgd.bg_free_blocks_count >= needed_blocks; }; @@ -1041,7 +1041,7 @@ bool Ext2FS::set_block_allocation_state(BlockIndex block_index, bool new_state) #endif unsigned group_index = group_index_from_block_index(block_index); auto& bgd = group_descriptor(group_index); - BlockIndex index_in_group = block_index - ((group_index - 1) * blocks_per_group()); + BlockIndex index_in_group = (block_index - 1) - ((group_index - 1) * blocks_per_group()); unsigned bit_index = index_in_group % blocks_per_group(); #ifdef EXT2_DEBUG dbgprintf(" index_in_group: %u\n", index_in_group); @@ -1107,7 +1107,7 @@ RetainPtr Ext2FS::create_directory(InodeIdentifier parent_id, const Strin entries.append({ ".", inode->identifier(), EXT2_FT_DIR }); entries.append({ "..", parent_id, EXT2_FT_DIR }); - bool success = write_directory_inode(inode->identifier().index(), move(entries)); + bool success = static_cast(*inode).write_directory(entries); ASSERT(success); auto parent_inode = get_inode(parent_id); @@ -1138,7 +1138,7 @@ RetainPtr Ext2FS::create_inode(InodeIdentifier parent_id, const String& n if (!inode_id) { kprintf("Ext2FS: create_inode: allocate_inode failed\n"); error = -ENOSPC; - return { }; + return {}; } auto needed_blocks = ceil_div(size, block_size()); @@ -1146,14 +1146,14 @@ RetainPtr Ext2FS::create_inode(InodeIdentifier parent_id, const String& n if (blocks.size() != needed_blocks) { kprintf("Ext2FS: create_inode: allocate_blocks failed\n"); error = -ENOSPC; - return { }; + return {}; } // Try adding it to the directory first, in case the name is already in use. - auto result = parent_inode->add_child({ fsid(), inode_id }, name, to_ext2_file_type(mode)); + auto result = parent_inode->add_child({ fsid(), inode_id }, name, mode); if (result.is_error()) { error = result; - return { }; + return {}; } // Looks like we're good, time to update the inode bitmap and group+global inode counters. @@ -1204,36 +1204,6 @@ RetainPtr Ext2FS::create_inode(InodeIdentifier parent_id, const String& n return get_inode({ fsid(), inode_id }); } -RetainPtr Ext2FSInode::parent() const -{ - LOCKER(m_lock); - if (m_parent_id.is_valid()) - return fs().get_inode(m_parent_id); - - unsigned group_index = fs().group_index_from_inode(index()); - unsigned first_inode_in_group = fs().inodes_per_group() * (group_index - 1); - - Vector> directories_in_group; - - for (unsigned i = 0; i < fs().inodes_per_group(); ++i) { - auto group_member = fs().get_inode({ fsid(), first_inode_in_group + i }); - if (!group_member) - continue; - if (group_member->is_directory()) - directories_in_group.append(*group_member); - } - - for (auto& directory : directories_in_group) { - if (!directory->reverse_lookup(identifier()).is_null()) { - m_parent_id = directory->identifier(); - break; - } - } - - ASSERT(m_parent_id.is_valid()); - return fs().get_inode(m_parent_id); -} - void Ext2FSInode::populate_lookup_cache() const { LOCKER(m_lock); @@ -1241,7 +1211,7 @@ void Ext2FSInode::populate_lookup_cache() const return; HashMap children; - traverse_as_directory([&children] (auto& entry) { + traverse_as_directory([&children](auto& entry) { children.set(String(entry.name, entry.name_length), entry.inode.index()); return true; }); @@ -1251,7 +1221,7 @@ void Ext2FSInode::populate_lookup_cache() const m_lookup_cache = move(children); } -InodeIdentifier Ext2FSInode::lookup(const String& name) +InodeIdentifier Ext2FSInode::lookup(StringView name) { ASSERT(is_directory()); populate_lookup_cache(); @@ -1259,20 +1229,7 @@ InodeIdentifier Ext2FSInode::lookup(const String& name) auto it = m_lookup_cache.find(name); if (it != m_lookup_cache.end()) return { fsid(), (*it).value }; - return { }; -} - -String Ext2FSInode::reverse_lookup(InodeIdentifier child_id) -{ - ASSERT(is_directory()); - ASSERT(child_id.fsid() == fsid()); - populate_lookup_cache(); - LOCKER(m_lock); - for (auto it : m_lookup_cache) { - if (it.value == child_id.index()) - return it.key; - } - return { }; + return {}; } void Ext2FSInode::one_retain_left() diff --git a/Kernel/FileSystem/Ext2FileSystem.h b/Kernel/FileSystem/Ext2FileSystem.h index e53d6b2724..ead3e9ec62 100644 --- a/Kernel/FileSystem/Ext2FileSystem.h +++ b/Kernel/FileSystem/Ext2FileSystem.h @@ -25,16 +25,14 @@ public: private: // ^Inode - virtual ssize_t read_bytes(off_t, ssize_t, byte* buffer, FileDescriptor*) const override; + virtual ssize_t read_bytes(off_t, ssize_t, byte* buffer, FileDescription*) const override; virtual InodeMetadata metadata() const override; virtual bool traverse_as_directory(Function) const override; - virtual InodeIdentifier lookup(const String& name) override; - virtual String reverse_lookup(InodeIdentifier) override; + virtual InodeIdentifier lookup(StringView name) override; virtual void flush_metadata() override; - virtual ssize_t write_bytes(off_t, ssize_t, const byte* data, FileDescriptor*) override; - virtual KResult add_child(InodeIdentifier child_id, const String& name, mode_t) override; - virtual KResult remove_child(const String& name) override; - virtual RetainPtr parent() const override; + virtual ssize_t write_bytes(off_t, ssize_t, const byte* data, FileDescription*) override; + virtual KResult add_child(InodeIdentifier child_id, const StringView& name, mode_t) override; + virtual KResult remove_child(const StringView& name) override; virtual int set_atime(time_t) override; virtual int set_ctime(time_t) override; virtual int set_mtime(time_t) override; @@ -45,6 +43,7 @@ private: virtual KResult chown(uid_t, gid_t) override; virtual KResult truncate(off_t) override; + bool write_directory(const Vector&); void populate_lookup_cache() const; bool resize(qword); @@ -55,7 +54,6 @@ private: mutable Vector m_block_list; mutable HashMap m_lookup_cache; ext2_inode m_raw_inode; - mutable InodeIdentifier m_parent_id; }; class Ext2FS final : public DiskBackedFS { @@ -106,8 +104,6 @@ private: Vector block_list_for_inode(const ext2_inode&, bool include_block_list_blocks = false) const; bool write_block_list_for_inode(InodeIndex, ext2_inode&, const Vector&); - bool add_inode_to_directory(InodeIndex parent, InodeIndex child, const String& name, byte file_type, int& error); - bool write_directory_inode(InodeIndex, Vector&&); bool get_inode_allocation_state(InodeIndex) const; bool set_inode_allocation_state(InodeIndex, bool); bool set_block_allocation_state(BlockIndex, bool); diff --git a/Kernel/FileSystem/FIFO.cpp b/Kernel/FileSystem/FIFO.cpp index e20c022dbd..6e1f081848 100644 --- a/Kernel/FileSystem/FIFO.cpp +++ b/Kernel/FileSystem/FIFO.cpp @@ -1,8 +1,10 @@ -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include //#define FIFO_DEBUG @@ -28,12 +30,12 @@ Retained FIFO::create(uid_t uid) return adopt(*new FIFO(uid)); } -Retained FIFO::open_direction(FIFO::Direction direction) +Retained FIFO::open_direction(FIFO::Direction direction) { - auto descriptor = FileDescriptor::create(this); + auto description = FileDescription::create(this); attach(direction); - descriptor->set_fifo_direction({ }, direction); - return descriptor; + description->set_fifo_direction({}, direction); + return description; } FIFO::FIFO(uid_t uid) @@ -81,22 +83,22 @@ void FIFO::detach(Direction direction) } } -bool FIFO::can_read(FileDescriptor&) const +bool FIFO::can_read(FileDescription&) const { return !m_buffer.is_empty() || !m_writers; } -bool FIFO::can_write(FileDescriptor&) const +bool FIFO::can_write(FileDescription&) const { - return m_buffer.bytes_in_write_buffer() < 4096; + return m_buffer.bytes_in_write_buffer() < 4096 || !m_readers; } -ssize_t FIFO::read(FileDescriptor&, byte* buffer, ssize_t size) +ssize_t FIFO::read(FileDescription&, byte* buffer, ssize_t size) { if (!m_writers && m_buffer.is_empty()) return 0; #ifdef FIFO_DEBUG - dbgprintf("fifo: read(%u)\n",size); + dbgprintf("fifo: read(%u)\n", size); #endif ssize_t nread = m_buffer.read(buffer, size); #ifdef FIFO_DEBUG @@ -105,17 +107,19 @@ ssize_t FIFO::read(FileDescriptor&, byte* buffer, ssize_t size) return nread; } -ssize_t FIFO::write(FileDescriptor&, const byte* buffer, ssize_t size) +ssize_t FIFO::write(FileDescription&, const byte* buffer, ssize_t size) { - if (!m_readers) - return 0; + if (!m_readers) { + current->process().send_signal(SIGPIPE, ¤t->process()); + return -EPIPE; + } #ifdef FIFO_DEBUG dbgprintf("fifo: write(%p, %u)\n", buffer, size); #endif return m_buffer.write(buffer, size); } -String FIFO::absolute_path(FileDescriptor&) const +String FIFO::absolute_path(const FileDescription&) const { return String::format("fifo:%u", this); } diff --git a/Kernel/FileSystem/FIFO.h b/Kernel/FileSystem/FIFO.h index 72faae428d..baad9bd8a1 100644 --- a/Kernel/FileSystem/FIFO.h +++ b/Kernel/FileSystem/FIFO.h @@ -4,12 +4,11 @@ #include #include -class FileDescriptor; +class FileDescription; class FIFO final : public File { public: - enum class Direction : byte - { + enum class Direction : byte { Neither, Reader, Writer @@ -22,18 +21,18 @@ public: uid_t uid() const { return m_uid; } - Retained open_direction(Direction); + Retained open_direction(Direction); void attach(Direction); void detach(Direction); private: // ^File - virtual ssize_t write(FileDescriptor&, const byte*, ssize_t) override; - virtual ssize_t read(FileDescriptor&, byte*, ssize_t) override; - virtual bool can_read(FileDescriptor&) const override; - virtual bool can_write(FileDescriptor&) const override; - virtual String absolute_path(FileDescriptor&) const override; + virtual ssize_t write(FileDescription&, const byte*, ssize_t) override; + virtual ssize_t read(FileDescription&, byte*, ssize_t) override; + virtual bool can_read(FileDescription&) const override; + virtual bool can_write(FileDescription&) const override; + virtual String absolute_path(const FileDescription&) const override; virtual const char* class_name() const override { return "FIFO"; } virtual bool is_fifo() const override { return true; } diff --git a/Kernel/FileSystem/FileDescriptor.cpp b/Kernel/FileSystem/FileDescription.cpp similarity index 57% rename from Kernel/FileSystem/FileDescriptor.cpp rename to Kernel/FileSystem/FileDescription.cpp index 49862fee25..a75ec14259 100644 --- a/Kernel/FileSystem/FileDescriptor.cpp +++ b/Kernel/FileSystem/FileDescription.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include #include @@ -15,19 +15,19 @@ #include #include -Retained FileDescriptor::create(RetainPtr&& custody) +Retained FileDescription::create(RetainPtr&& custody) { - auto descriptor = adopt(*new FileDescriptor(InodeFile::create(custody->inode()))); - descriptor->m_custody = move(custody); - return descriptor; + auto description = adopt(*new FileDescription(InodeFile::create(custody->inode()))); + description->m_custody = move(custody); + return description; } -Retained FileDescriptor::create(RetainPtr&& file, SocketRole role) +Retained FileDescription::create(RetainPtr&& file, SocketRole role) { - return adopt(*new FileDescriptor(move(file), role)); + return adopt(*new FileDescription(move(file), role)); } -FileDescriptor::FileDescriptor(RetainPtr&& file, SocketRole role) +FileDescription::FileDescription(RetainPtr&& file, SocketRole role) : m_file(move(file)) { if (m_file->is_inode()) @@ -35,7 +35,7 @@ FileDescriptor::FileDescriptor(RetainPtr&& file, SocketRole role) set_socket_role(role); } -FileDescriptor::~FileDescriptor() +FileDescription::~FileDescription() { if (is_socket()) socket()->detach(*this); @@ -46,7 +46,7 @@ FileDescriptor::~FileDescriptor() m_inode = nullptr; } -void FileDescriptor::set_socket_role(SocketRole role) +void FileDescription::set_socket_role(SocketRole role) { if (role == m_socket_role) return; @@ -58,58 +58,40 @@ void FileDescriptor::set_socket_role(SocketRole role) socket()->attach(*this); } -Retained FileDescriptor::clone() +Retained FileDescription::clone() { - RetainPtr descriptor; + RetainPtr description; if (is_fifo()) { - descriptor = fifo()->open_direction(m_fifo_direction); + description = fifo()->open_direction(m_fifo_direction); } else { - descriptor = FileDescriptor::create(m_file.copy_ref(), m_socket_role); - descriptor->m_custody = m_custody.copy_ref(); - descriptor->m_inode = m_inode.copy_ref(); + description = FileDescription::create(m_file.copy_ref(), m_socket_role); + description->m_custody = m_custody.copy_ref(); + description->m_inode = m_inode.copy_ref(); } - ASSERT(descriptor); - descriptor->m_current_offset = m_current_offset; - descriptor->m_is_blocking = m_is_blocking; - descriptor->m_should_append = m_should_append; - descriptor->m_file_flags = m_file_flags; - return *descriptor; + ASSERT(description); + description->m_current_offset = m_current_offset; + description->m_is_blocking = m_is_blocking; + description->m_should_append = m_should_append; + description->m_file_flags = m_file_flags; + return *description; } -KResult FileDescriptor::fstat(stat& buffer) +KResult FileDescription::fstat(stat& buffer) { ASSERT(!is_fifo()); if (!m_inode) return KResult(-EBADF); - - auto metadata = this->metadata(); - if (!metadata.is_valid()) - return KResult(-EIO); - - buffer.st_rdev = encoded_device(metadata.major_device, metadata.minor_device); - buffer.st_ino = metadata.inode.index(); - buffer.st_mode = metadata.mode; - buffer.st_nlink = metadata.link_count; - buffer.st_uid = metadata.uid; - buffer.st_gid = metadata.gid; - buffer.st_dev = 0; // FIXME - buffer.st_size = metadata.size; - buffer.st_blksize = metadata.block_size; - buffer.st_blocks = metadata.block_count; - buffer.st_atime = metadata.atime; - buffer.st_mtime = metadata.mtime; - buffer.st_ctime = metadata.ctime; - return KSuccess; + return metadata().stat(buffer); } -KResult FileDescriptor::fchmod(mode_t mode) +KResult FileDescription::fchmod(mode_t mode) { if (!m_inode) return KResult(-EBADF); - return VFS::the().fchmod(*m_inode, mode); + return VFS::the().chmod(*m_inode, mode); } -off_t FileDescriptor::seek(off_t offset, int whence) +off_t FileDescription::seek(off_t offset, int whence) { if (!m_file->is_seekable()) return -EINVAL; @@ -145,7 +127,7 @@ off_t FileDescriptor::seek(off_t offset, int whence) return m_current_offset; } -ssize_t FileDescriptor::read(byte* buffer, ssize_t count) +ssize_t FileDescription::read(byte* buffer, ssize_t count) { int nread = m_file->read(*this, buffer, count); if (m_file->is_seekable()) @@ -153,7 +135,7 @@ ssize_t FileDescriptor::read(byte* buffer, ssize_t count) return nread; } -ssize_t FileDescriptor::write(const byte* data, ssize_t size) +ssize_t FileDescription::write(const byte* data, ssize_t size) { int nwritten = m_file->write(*this, data, size); if (m_file->is_seekable()) @@ -161,17 +143,17 @@ ssize_t FileDescriptor::write(const byte* data, ssize_t size) return nwritten; } -bool FileDescriptor::can_write() +bool FileDescription::can_write() { return m_file->can_write(*this); } -bool FileDescriptor::can_read() +bool FileDescription::can_read() { return m_file->can_read(*this); } -ByteBuffer FileDescriptor::read_entire_file() +ByteBuffer FileDescription::read_entire_file() { // HACK ALERT: (This entire function) ASSERT(m_file->is_inode()); @@ -179,13 +161,13 @@ ByteBuffer FileDescriptor::read_entire_file() return m_inode->read_entire(this); } -bool FileDescriptor::is_directory() const +bool FileDescription::is_directory() const { ASSERT(!is_fifo()); return metadata().is_directory(); } -ssize_t FileDescriptor::get_dir_entries(byte* buffer, ssize_t size) +ssize_t FileDescription::get_dir_entries(byte* buffer, ssize_t size) { auto metadata = this->metadata(); if (!metadata.is_valid()) @@ -197,7 +179,7 @@ ssize_t FileDescriptor::get_dir_entries(byte* buffer, ssize_t size) auto temp_buffer = ByteBuffer::create_uninitialized(size_to_allocate); BufferStream stream(temp_buffer); - VFS::the().traverse_directory_inode(*m_inode, [&stream] (auto& entry) { + VFS::the().traverse_directory_inode(*m_inode, [&stream](auto& entry) { stream << (dword)entry.inode.index(); stream << (byte)entry.file_type; stream << (dword)entry.name_length; @@ -213,132 +195,139 @@ ssize_t FileDescriptor::get_dir_entries(byte* buffer, ssize_t size) return stream.offset(); } -bool FileDescriptor::is_device() const +bool FileDescription::is_device() const { return m_file->is_device(); } -bool FileDescriptor::is_tty() const +bool FileDescription::is_tty() const { return m_file->is_tty(); } -const TTY* FileDescriptor::tty() const +const TTY* FileDescription::tty() const { if (!is_tty()) return nullptr; return static_cast(m_file.ptr()); } -TTY* FileDescriptor::tty() +TTY* FileDescription::tty() { if (!is_tty()) return nullptr; return static_cast(m_file.ptr()); } -bool FileDescriptor::is_master_pty() const +bool FileDescription::is_master_pty() const { return m_file->is_master_pty(); } -const MasterPTY* FileDescriptor::master_pty() const +const MasterPTY* FileDescription::master_pty() const { if (!is_master_pty()) return nullptr; return static_cast(m_file.ptr()); } -MasterPTY* FileDescriptor::master_pty() +MasterPTY* FileDescription::master_pty() { if (!is_master_pty()) return nullptr; return static_cast(m_file.ptr()); } -int FileDescriptor::close() +int FileDescription::close() { return 0; } -String FileDescriptor::absolute_path() +String FileDescription::absolute_path() const { if (m_custody) return m_custody->absolute_path(); - dbgprintf("FileDescriptor::absolute_path() for FD without custody, File type: %s\n", m_file->class_name()); + dbgprintf("FileDescription::absolute_path() for FD without custody, File type: %s\n", m_file->class_name()); return m_file->absolute_path(*this); } -InodeMetadata FileDescriptor::metadata() const +InodeMetadata FileDescription::metadata() const { if (m_inode) return m_inode->metadata(); - return { }; + return {}; } -KResultOr FileDescriptor::mmap(Process& process, LinearAddress laddr, size_t offset, size_t size, int prot) +KResultOr FileDescription::mmap(Process& process, VirtualAddress vaddr, size_t offset, size_t size, int prot) { - return m_file->mmap(process, laddr, offset, size, prot); + return m_file->mmap(process, *this, vaddr, offset, size, prot); } -KResult FileDescriptor::truncate(off_t length) +KResult FileDescription::truncate(off_t length) { return m_file->truncate(length); } -bool FileDescriptor::is_shared_memory() const +bool FileDescription::is_shared_memory() const { return m_file->is_shared_memory(); } -SharedMemory* FileDescriptor::shared_memory() +SharedMemory* FileDescription::shared_memory() { if (!is_shared_memory()) return nullptr; return static_cast(m_file.ptr()); } -const SharedMemory* FileDescriptor::shared_memory() const +const SharedMemory* FileDescription::shared_memory() const { if (!is_shared_memory()) return nullptr; return static_cast(m_file.ptr()); } -bool FileDescriptor::is_fifo() const +bool FileDescription::is_fifo() const { return m_file->is_fifo(); } -FIFO* FileDescriptor::fifo() +FIFO* FileDescription::fifo() { if (!is_fifo()) return nullptr; return static_cast(m_file.ptr()); } -bool FileDescriptor::is_socket() const +bool FileDescription::is_socket() const { return m_file->is_socket(); } -Socket* FileDescriptor::socket() +Socket* FileDescription::socket() { if (!is_socket()) return nullptr; return static_cast(m_file.ptr()); } -const Socket* FileDescriptor::socket() const +const Socket* FileDescription::socket() const { if (!is_socket()) return nullptr; return static_cast(m_file.ptr()); } -void FileDescriptor::set_file_flags(dword flags) +void FileDescription::set_file_flags(dword flags) { m_is_blocking = !(flags & O_NONBLOCK); m_should_append = flags & O_APPEND; m_file_flags = flags; } + +KResult FileDescription::chown(uid_t uid, gid_t gid) +{ + if (!m_inode) + return KResult(-EINVAL); + return VFS::the().chown(*m_inode, uid, gid); +} diff --git a/Kernel/FileSystem/FileDescriptor.h b/Kernel/FileSystem/FileDescription.h similarity index 82% rename from Kernel/FileSystem/FileDescriptor.h rename to Kernel/FileSystem/FileDescription.h index cf5f9891ee..4c8e0175e7 100644 --- a/Kernel/FileSystem/FileDescriptor.h +++ b/Kernel/FileSystem/FileDescription.h @@ -8,8 +8,8 @@ #include #include #include -#include #include +#include class File; class TTY; @@ -19,13 +19,13 @@ class Region; class CharacterDevice; class SharedMemory; -class FileDescriptor : public Retainable { +class FileDescription : public Retainable { public: - static Retained create(RetainPtr&&); - static Retained create(RetainPtr&&, SocketRole = SocketRole::None); - ~FileDescriptor(); + static Retained create(RetainPtr&&); + static Retained create(RetainPtr&&, SocketRole = SocketRole::None); + ~FileDescription(); - Retained clone(); + Retained clone(); int close(); @@ -43,7 +43,7 @@ public: ByteBuffer read_entire_file(); - String absolute_path(); + String absolute_path() const; bool is_directory() const; @@ -67,7 +67,7 @@ public: Custody* custody() { return m_custody.ptr(); } const Custody* custody() const { return m_custody.ptr(); } - KResultOr mmap(Process&, LinearAddress, size_t offset, size_t, int prot); + KResultOr mmap(Process&, VirtualAddress, size_t offset, size_t, int prot); bool is_blocking() const { return m_is_blocking; } void set_blocking(bool b) { m_is_blocking = b; } @@ -101,10 +101,12 @@ public: off_t offset() const { return m_current_offset; } + KResult chown(uid_t, gid_t); + private: friend class VFS; - FileDescriptor(RetainPtr&&, SocketRole = SocketRole::None); - FileDescriptor(FIFO&, FIFO::Direction); + FileDescription(RetainPtr&&, SocketRole = SocketRole::None); + FileDescription(FIFO&, FIFO::Direction); RetainPtr m_custody; RetainPtr m_inode; diff --git a/Kernel/FileSystem/FileSystem.cpp b/Kernel/FileSystem/FileSystem.cpp index a8619bd806..96728554bc 100644 --- a/Kernel/FileSystem/FileSystem.cpp +++ b/Kernel/FileSystem/FileSystem.cpp @@ -1,11 +1,11 @@ #include #include #include -#include #include #include -#include #include +#include +#include static dword s_lastFileSystemID; static HashMap* s_fs_map; @@ -17,7 +17,6 @@ static HashMap& all_fses() return *s_fs_map; } - FS::FS() : m_fsid(++s_lastFileSystemID) { diff --git a/Kernel/FileSystem/FileSystem.h b/Kernel/FileSystem/FileSystem.h index 097d479b00..81d953c832 100644 --- a/Kernel/FileSystem/FileSystem.h +++ b/Kernel/FileSystem/FileSystem.h @@ -19,7 +19,7 @@ static const dword mepoch = 476763780; class Inode; -class FileDescriptor; +class FileDescription; class LocalSocket; class VMObject; diff --git a/Kernel/FileSystem/Inode.cpp b/Kernel/FileSystem/Inode.cpp index 38eb0395d1..ef4fbe8207 100644 --- a/Kernel/FileSystem/Inode.cpp +++ b/Kernel/FileSystem/Inode.cpp @@ -1,7 +1,7 @@ -#include #include -#include +#include #include +#include HashTable& all_inodes() { @@ -28,7 +28,7 @@ void Inode::sync() } } -ByteBuffer Inode::read_entire(FileDescriptor* descriptor) const +ByteBuffer Inode::read_entire(FileDescription* descriptor) const { size_t initial_size = metadata().size ? metadata().size : 4096; StringBuilder builder(initial_size); diff --git a/Kernel/FileSystem/Inode.h b/Kernel/FileSystem/Inode.h index 6aa6d5a5eb..b2c56a5a20 100644 --- a/Kernel/FileSystem/Inode.h +++ b/Kernel/FileSystem/Inode.h @@ -10,7 +10,7 @@ #include #include -class FileDescriptor; +class FileDescription; class LocalSocket; class VMObject; @@ -37,16 +37,14 @@ public: InodeIdentifier identifier() const { return { fsid(), index() }; } virtual InodeMetadata metadata() const = 0; - ByteBuffer read_entire(FileDescriptor* = nullptr) const; + ByteBuffer read_entire(FileDescription* = nullptr) const; - virtual ssize_t read_bytes(off_t, ssize_t, byte* buffer, FileDescriptor*) const = 0; + virtual ssize_t read_bytes(off_t, ssize_t, byte* buffer, FileDescription*) const = 0; virtual bool traverse_as_directory(Function) const = 0; - virtual InodeIdentifier lookup(const String& name) = 0; - virtual String reverse_lookup(InodeIdentifier) = 0; - virtual ssize_t write_bytes(off_t, ssize_t, const byte* data, FileDescriptor*) = 0; - virtual KResult add_child(InodeIdentifier child_id, const String& name, mode_t) = 0; - virtual KResult remove_child(const String& name) = 0; - virtual RetainPtr parent() const = 0; + virtual InodeIdentifier lookup(StringView name) = 0; + virtual ssize_t write_bytes(off_t, ssize_t, const byte* data, FileDescription*) = 0; + virtual KResult add_child(InodeIdentifier child_id, const StringView& name, mode_t) = 0; + virtual KResult remove_child(const StringView& name) = 0; virtual size_t directory_entry_count() const = 0; virtual KResult chmod(mode_t) = 0; virtual KResult chown(uid_t, gid_t) = 0; diff --git a/Kernel/FileSystem/InodeFile.cpp b/Kernel/FileSystem/InodeFile.cpp index 80a25e5301..5dee202e68 100644 --- a/Kernel/FileSystem/InodeFile.cpp +++ b/Kernel/FileSystem/InodeFile.cpp @@ -1,6 +1,6 @@ -#include +#include #include -#include +#include #include #include @@ -13,39 +13,32 @@ InodeFile::~InodeFile() { } -ssize_t InodeFile::read(FileDescriptor& descriptor, byte* buffer, ssize_t count) +ssize_t InodeFile::read(FileDescription& description, byte* buffer, ssize_t count) { - return m_inode->read_bytes(descriptor.offset(), count, buffer, &descriptor); + return m_inode->read_bytes(description.offset(), count, buffer, &description); } -ssize_t InodeFile::write(FileDescriptor& descriptor, const byte* data, ssize_t count) +ssize_t InodeFile::write(FileDescription& description, const byte* data, ssize_t count) { - return m_inode->write_bytes(descriptor.offset(), count, data, &descriptor); + return m_inode->write_bytes(description.offset(), count, data, &description); } -KResultOr InodeFile::mmap(Process& process, LinearAddress preferred_laddr, size_t offset, size_t size, int prot) +KResultOr InodeFile::mmap(Process& process, FileDescription& description, VirtualAddress preferred_vaddr, size_t offset, size_t size, int prot) { ASSERT(offset == 0); // FIXME: If PROT_EXEC, check that the underlying file system isn't mounted noexec. - String region_name; -#if 0 - // FIXME: I would like to do this, but it would instantiate all the damn inodes. - region_name = absolute_path(); -#else - region_name = "Memory-mapped file"; -#endif InterruptDisabler disabler; - auto* region = process.allocate_file_backed_region(preferred_laddr, size, inode(), move(region_name), prot); + auto* region = process.allocate_file_backed_region(preferred_vaddr, size, inode(), description.absolute_path(), prot); if (!region) return KResult(-ENOMEM); return region; } -String InodeFile::absolute_path(FileDescriptor& descriptor) const +String InodeFile::absolute_path(const FileDescription& description) const { ASSERT_NOT_REACHED(); - ASSERT(descriptor.custody()); - return descriptor.absolute_path(); + ASSERT(description.custody()); + return description.absolute_path(); } KResult InodeFile::truncate(off_t size) diff --git a/Kernel/FileSystem/InodeFile.h b/Kernel/FileSystem/InodeFile.h index 5c86386005..73f1f2444f 100644 --- a/Kernel/FileSystem/InodeFile.h +++ b/Kernel/FileSystem/InodeFile.h @@ -16,14 +16,14 @@ public: const Inode& inode() const { return *m_inode; } Inode& inode() { return *m_inode; } - virtual bool can_read(FileDescriptor&) const override { return true; } - virtual bool can_write(FileDescriptor&) const override { return true; } + virtual bool can_read(FileDescription&) const override { return true; } + virtual bool can_write(FileDescription&) const override { return true; } - virtual ssize_t read(FileDescriptor&, byte*, ssize_t) override; - virtual ssize_t write(FileDescriptor&, const byte*, ssize_t) override; - virtual KResultOr mmap(Process&, LinearAddress preferred_laddr, size_t offset, size_t size, int prot) override; + virtual ssize_t read(FileDescription&, byte*, ssize_t) override; + virtual ssize_t write(FileDescription&, const byte*, ssize_t) override; + virtual KResultOr mmap(Process&, FileDescription&, VirtualAddress preferred_vaddr, size_t offset, size_t size, int prot) override; - virtual String absolute_path(FileDescriptor&) const override; + virtual String absolute_path(const FileDescription&) const override; virtual KResult truncate(off_t) override; diff --git a/Kernel/FileSystem/InodeMetadata.h b/Kernel/FileSystem/InodeMetadata.h index f151fbe048..97794e5470 100644 --- a/Kernel/FileSystem/InodeMetadata.h +++ b/Kernel/FileSystem/InodeMetadata.h @@ -1,11 +1,17 @@ #pragma once -#include "InodeIdentifier.h" -#include "UnixTypes.h" #include +#include +#include +#include class Process; +inline constexpr dword encoded_device(unsigned major, unsigned minor) +{ + return (minor & 0xff) | (major << 8) | ((minor & ~0xff) << 12); +} + inline bool is_directory(mode_t mode) { return (mode & 0170000) == 0040000; } inline bool is_character_device(mode_t mode) { return (mode & 0170000) == 0020000; } inline bool is_block_device(mode_t mode) { return (mode & 0170000) == 0060000; } @@ -69,6 +75,26 @@ struct InodeMetadata { bool is_setuid() const { return ::is_setuid(mode); } bool is_setgid() const { return ::is_setgid(mode); } + KResult stat(stat& buffer) const + { + if (!is_valid()) + return KResult(-EIO); + buffer.st_rdev = encoded_device(major_device, minor_device); + buffer.st_ino = inode.index(); + buffer.st_mode = mode; + buffer.st_nlink = link_count; + buffer.st_uid = uid; + buffer.st_gid = gid; + buffer.st_dev = 0; // FIXME + buffer.st_size = size; + buffer.st_blksize = block_size; + buffer.st_blocks = block_count; + buffer.st_atime = atime; + buffer.st_mtime = mtime; + buffer.st_ctime = ctime; + return KSuccess; + } + InodeIdentifier inode; off_t size { 0 }; mode_t mode { 0 }; diff --git a/Kernel/FileSystem/ProcFS.cpp b/Kernel/FileSystem/ProcFS.cpp index 517b96d689..f1cc2c74aa 100644 --- a/Kernel/FileSystem/ProcFS.cpp +++ b/Kernel/FileSystem/ProcFS.cpp @@ -1,17 +1,17 @@ #include "ProcFS.h" -#include "Process.h" -#include -#include -#include -#include -#include "StdLib.h" -#include "i386.h" -#include "KSyms.h" #include "Console.h" +#include "KSyms.h" +#include "Process.h" #include "Scheduler.h" -#include -#include +#include "StdLib.h" #include +#include +#include +#include +#include +#include +#include +#include #include enum ProcParentDirectory { @@ -41,7 +41,7 @@ enum ProcFileType { FI_Root_pci, FI_Root_uptime, FI_Root_self, // symlink - FI_Root_sys, // directory + FI_Root_sys, // directory __FI_Root_End, FI_PID, @@ -54,7 +54,7 @@ enum ProcFileType { FI_PID_fds, FI_PID_exe, // symlink FI_PID_cwd, // symlink - FI_PID_fd, // directory + FI_PID_fd, // directory __FI_PID_End, FI_MaxStaticFileIndex, @@ -183,16 +183,16 @@ ByteBuffer procfs$pid_fds(InodeIdentifier identifier) { auto handle = ProcessInspectionHandle::from_pid(to_pid(identifier)); if (!handle) - return { }; + return {}; auto& process = handle->process(); if (process.number_of_open_file_descriptors() == 0) - return { }; + return {}; StringBuilder builder; for (int i = 0; i < process.max_open_file_descriptors(); ++i) { - auto* descriptor = process.file_descriptor(i); - if (!descriptor) + auto* description = process.file_description(i); + if (!description) continue; - builder.appendf("% 3u %s\n", i, descriptor->absolute_path().characters()); + builder.appendf("% 3u %s\n", i, description->absolute_path().characters()); } return builder.to_byte_buffer(); } @@ -201,20 +201,20 @@ ByteBuffer procfs$pid_fd_entry(InodeIdentifier identifier) { auto handle = ProcessInspectionHandle::from_pid(to_pid(identifier)); if (!handle) - return { }; + return {}; auto& process = handle->process(); int fd = to_fd(identifier); - auto* descriptor = process.file_descriptor(fd); - if (!descriptor) - return { }; - return descriptor->absolute_path().to_byte_buffer(); + auto* description = process.file_description(fd); + if (!description) + return {}; + return description->absolute_path().to_byte_buffer(); } ByteBuffer procfs$pid_vm(InodeIdentifier identifier) { auto handle = ProcessInspectionHandle::from_pid(to_pid(identifier)); if (!handle) - return { }; + return {}; auto& process = handle->process(); StringBuilder builder; builder.appendf("BEGIN END SIZE COMMIT FLAGS NAME\n"); @@ -225,8 +225,8 @@ ByteBuffer procfs$pid_vm(InodeIdentifier identifier) if (region->is_writable()) flags_builder.append('W'); builder.appendf("%x -- %x %x %x % 4s %s\n", - region->laddr().get(), - region->laddr().offset(region->size() - 1).get(), + region->vaddr().get(), + region->vaddr().offset(region->size() - 1).get(), region->size(), region->amount_resident(), flags_builder.to_string().characters(), @@ -238,7 +238,7 @@ ByteBuffer procfs$pid_vm(InodeIdentifier identifier) ByteBuffer procfs$pci(InodeIdentifier) { StringBuilder builder; - PCI::enumerate_all([&builder] (PCI::Address address, PCI::ID id) { + PCI::enumerate_all([&builder](PCI::Address address, PCI::ID id) { builder.appendf("%b:%b.%b %w:%w\n", address.bus(), address.slot(), address.function(), id.vendor_id, id.device_id); }); return builder.to_byte_buffer(); @@ -255,14 +255,14 @@ ByteBuffer procfs$pid_vmo(InodeIdentifier identifier) { auto handle = ProcessInspectionHandle::from_pid(to_pid(identifier)); if (!handle) - return { }; + return {}; auto& process = handle->process(); StringBuilder builder; builder.appendf("BEGIN END SIZE NAME\n"); for (auto& region : process.regions()) { builder.appendf("%x -- %x %x %s\n", - region->laddr().get(), - region->laddr().offset(region->size() - 1).get(), + region->vaddr().get(), + region->vaddr().offset(region->size() - 1).get(), region->size(), region->name().characters()); builder.appendf("VMO: %s \"%s\" @ %x(%u)\n", @@ -275,8 +275,7 @@ ByteBuffer procfs$pid_vmo(InodeIdentifier identifier) builder.appendf("P%x%s(%u) ", physical_page ? physical_page->paddr().get() : 0, region->should_cow(i) ? "!" : "", - physical_page ? physical_page->retain_count() : 0 - ); + physical_page ? physical_page->retain_count() : 0); } builder.appendf("\n"); } @@ -287,7 +286,7 @@ ByteBuffer procfs$pid_stack(InodeIdentifier identifier) { auto handle = ProcessInspectionHandle::from_pid(to_pid(identifier)); if (!handle) - return { }; + return {}; auto& process = handle->process(); ProcessPagingScope paging_scope(process); struct RecognizedSymbol { @@ -295,11 +294,11 @@ ByteBuffer procfs$pid_stack(InodeIdentifier identifier) const KSym* ksym; }; StringBuilder builder; - process.for_each_thread([&] (Thread& thread) { + process.for_each_thread([&](Thread& thread) { builder.appendf("Thread %d:\n", thread.tid()); Vector recognized_symbols; recognized_symbols.append({ thread.tss().eip, ksymbolicate(thread.tss().eip) }); - for (dword* stack_ptr = (dword*)thread.frame_ptr(); process.validate_read_from_kernel(LinearAddress((dword)stack_ptr)); stack_ptr = (dword*)*stack_ptr) { + for (dword* stack_ptr = (dword*)thread.frame_ptr(); process.validate_read_from_kernel(VirtualAddress((dword)stack_ptr)); stack_ptr = (dword*)*stack_ptr) { dword retaddr = stack_ptr[1]; recognized_symbols.append({ retaddr, ksymbolicate(retaddr) }); } @@ -326,10 +325,10 @@ ByteBuffer procfs$pid_regs(InodeIdentifier identifier) { auto handle = ProcessInspectionHandle::from_pid(to_pid(identifier)); if (!handle) - return { }; + return {}; auto& process = handle->process(); StringBuilder builder; - process.for_each_thread([&] (Thread& thread) { + process.for_each_thread([&](Thread& thread) { builder.appendf("Thread %d:\n", thread.tid()); auto& tss = thread.tss(); builder.appendf("eax: %x\n", tss.eax); @@ -352,7 +351,7 @@ ByteBuffer procfs$pid_exe(InodeIdentifier identifier) { auto handle = ProcessInspectionHandle::from_pid(to_pid(identifier)); if (!handle) - return { }; + return {}; auto& process = handle->process(); auto* custody = process.executable(); ASSERT(custody); @@ -363,7 +362,7 @@ ByteBuffer procfs$pid_cwd(InodeIdentifier identifier) { auto handle = ProcessInspectionHandle::from_pid(to_pid(identifier)); if (!handle) - return { }; + return {}; return handle->process().current_directory().absolute_path().to_byte_buffer(); } @@ -388,8 +387,8 @@ ByteBuffer procfs$mm(InodeIdentifier) vmo->name().characters()); } builder.appendf("VMO count: %u\n", MM.m_vmos.size()); - builder.appendf("Free physical pages: %u\n", MM.m_free_physical_pages.size()); - builder.appendf("Free supervisor physical pages: %u\n", MM.m_free_supervisor_physical_pages.size()); + builder.appendf("Free physical pages: %u\n", MM.user_physical_pages() - MM.user_physical_pages_used()); + builder.appendf("Free supervisor physical pages: %u\n", MM.super_physical_pages() - MM.super_physical_pages_used()); return builder.to_byte_buffer(); } @@ -406,7 +405,7 @@ ByteBuffer procfs$mounts(InodeIdentifier) { // FIXME: This is obviously racy against the VFS mounts changing. StringBuilder builder; - VFS::the().for_each_mount([&builder] (auto& mount) { + VFS::the().for_each_mount([&builder](auto& mount) { auto& fs = mount.guest_fs(); builder.appendf("%s @ ", fs.class_name()); if (!mount.host().is_valid()) @@ -425,7 +424,7 @@ ByteBuffer procfs$df(InodeIdentifier) { // FIXME: This is obviously racy against the VFS mounts changing. StringBuilder builder; - VFS::the().for_each_mount([&builder] (auto& mount) { + VFS::the().for_each_mount([&builder](auto& mount) { auto& fs = mount.guest_fs(); builder.appendf("%s,", fs.class_name()); builder.appendf("%u,", fs.total_block_count()); @@ -444,7 +443,7 @@ ByteBuffer procfs$cpuinfo(InodeIdentifier) { CPUID cpuid(0); builder.appendf("cpuid: "); - auto emit_dword = [&] (dword value) { + auto emit_dword = [&](dword value) { builder.appendf("%c%c%c%c", value & 0xff, (value >> 8) & 0xff, @@ -486,7 +485,7 @@ ByteBuffer procfs$cpuinfo(InodeIdentifier) // and verifying that the returned eax>=0x80000004. char buffer[48]; dword* bufptr = reinterpret_cast(buffer); - auto copy_brand_string_part_to_buffer = [&] (dword i) { + auto copy_brand_string_part_to_buffer = [&](dword i) { CPUID cpuid(0x80000002 + i); *bufptr++ = cpuid.eax(); *bufptr++ = cpuid.ebx(); @@ -510,8 +509,7 @@ ByteBuffer procfs$kmalloc(InodeIdentifier) "free: %u\n", kmalloc_sum_eternal, sum_alloc, - sum_free - ); + sum_free); return builder.to_byte_buffer(); } @@ -546,13 +544,12 @@ ByteBuffer procfs$memstat(InodeIdentifier) kmalloc_sum_eternal, sum_alloc, sum_free, - MM.user_physical_pages_in_existence() - MM.m_free_physical_pages.size(), - MM.m_free_physical_pages.size(), - MM.super_physical_pages_in_existence() - MM.m_free_supervisor_physical_pages.size(), - MM.m_free_supervisor_physical_pages.size(), + MM.user_physical_pages_used(), + MM.user_physical_pages() - MM.user_physical_pages_used(), + MM.super_physical_pages_used(), + MM.super_physical_pages() - MM.super_physical_pages_used(), g_kmalloc_call_count, - g_kfree_call_count - ); + g_kfree_call_count); return builder.to_byte_buffer(); } @@ -561,7 +558,7 @@ ByteBuffer procfs$all(InodeIdentifier) InterruptDisabler disabler; auto processes = Process::all_processes(); StringBuilder builder(processes.size() * 80); - auto build_process_line = [&builder] (Process* process) { + auto build_process_line = [&builder](Process* process) { builder.appendf("%u,%u,%u,%u,%u,%u,%u,%s,%u,%u,%s,%s,%u,%u,%u,%u,%s,%u\n", process->pid(), process->main_thread().times_scheduled(), // FIXME(Thread): Bill all scheds to the process @@ -580,8 +577,7 @@ ByteBuffer procfs$all(InodeIdentifier) process->amount_shared(), process->main_thread().ticks(), // FIXME(Thread): Bill all ticks to the process to_string(process->priority()), - process->syscall_count() - ); + process->syscall_count()); }; build_process_line(Scheduler::colonel()); for (auto* process : processes) @@ -601,7 +597,7 @@ ByteBuffer procfs$inodes(InodeIdentifier) } struct SysVariableData final : public ProcFSInodeCustomData { - virtual ~SysVariableData() override { } + virtual ~SysVariableData() override {} enum Type { Invalid, @@ -617,7 +613,7 @@ static ByteBuffer read_sys_bool(InodeIdentifier inode_id) { auto inode_ptr = ProcFS::the().get_inode(inode_id); if (!inode_ptr) - return { }; + return {}; auto& inode = static_cast(*inode_ptr); ASSERT(inode.custom_data()); auto buffer = ByteBuffer::create_uninitialized(2); @@ -637,7 +633,7 @@ static ssize_t write_sys_bool(InodeIdentifier inode_id, const ByteBuffer& data) { auto inode_ptr = ProcFS::the().get_inode(inode_id); if (!inode_ptr) - return { }; + return {}; auto& inode = static_cast(*inode_ptr); ASSERT(inode.custom_data()); if (data.is_empty() || !(data[0] == '0' || data[0] == '1')) @@ -658,7 +654,7 @@ static ByteBuffer read_sys_string(InodeIdentifier inode_id) { auto inode_ptr = ProcFS::the().get_inode(inode_id); if (!inode_ptr) - return { }; + return {}; auto& inode = static_cast(*inode_ptr); ASSERT(inode.custom_data()); auto buffer = ByteBuffer::create_uninitialized(2); @@ -674,7 +670,7 @@ static ssize_t write_sys_string(InodeIdentifier inode_id, const ByteBuffer& data { auto inode_ptr = ProcFS::the().get_inode(inode_id); if (!inode_ptr) - return { }; + return {}; auto& inode = static_cast(*inode_ptr); ASSERT(inode.custom_data()); auto& custom_data = *static_cast(inode.custom_data()); @@ -730,7 +726,7 @@ const char* ProcFS::class_name() const RetainPtr ProcFS::create_inode(InodeIdentifier, const String&, mode_t, off_t, dev_t, int&) { kprintf("FIXME: Implement ProcFS::create_inode()?\n"); - return { }; + return {}; } RetainPtr ProcFS::create_directory(InodeIdentifier, const String&, mode_t, int& error) @@ -739,11 +735,6 @@ RetainPtr ProcFS::create_directory(InodeIdentifier, const String&, mode_t return nullptr; } -RetainPtr ProcFSInode::parent() const -{ - return fs().get_inode(to_parent_id(identifier())); -} - InodeIdentifier ProcFS::root_inode() const { return { fsid(), FI_Root }; @@ -840,7 +831,7 @@ InodeMetadata ProcFSInode::metadata() const return metadata; } -ssize_t ProcFSInode::read_bytes(off_t offset, ssize_t count, byte* buffer, FileDescriptor* descriptor) const +ssize_t ProcFSInode::read_bytes(off_t offset, ssize_t count, byte* buffer, FileDescription* description) const { #ifdef PROCFS_DEBUG dbgprintf("ProcFS: read_bytes %u\n", index()); @@ -864,19 +855,19 @@ ssize_t ProcFSInode::read_bytes(off_t offset, ssize_t count, byte* buffer, FileD ASSERT(read_callback); ByteBuffer generated_data; - if (!descriptor) { + if (!description) { generated_data = (*read_callback)(identifier()); } else { - if (!descriptor->generator_cache()) - descriptor->generator_cache() = (*read_callback)(identifier()); - generated_data = descriptor->generator_cache(); + if (!description->generator_cache()) + description->generator_cache() = (*read_callback)(identifier()); + generated_data = description->generator_cache(); } auto& data = generated_data; ssize_t nread = min(static_cast(data.size() - offset), static_cast(count)); memcpy(buffer, data.pointer() + offset, nread); - if (nread == 0 && descriptor && descriptor->generator_cache()) - descriptor->generator_cache().clear(); + if (nread == 0 && description && description->generator_cache()) + description->generator_cache().clear(); return nread; } @@ -937,8 +928,7 @@ bool ProcFSInode::traverse_as_directory(Functionprocess(); for (int i = 0; i < process.max_open_file_descriptors(); ++i) { - auto* descriptor = process.file_descriptor(i); - if (!descriptor) + auto* description = process.file_description(i); + if (!description) continue; char name[16]; int name_length = ksprintf(name, "%u", i); callback({ name, name_length, to_identifier_with_fd(fsid(), pid, i), 0 }); } - } - break; + } break; default: return true; } @@ -962,7 +951,7 @@ bool ProcFSInode::traverse_as_directory(Function __FI_Root_Start && entry.proc_file_type < __FI_Root_End) { - if (!strcmp(entry.name, name.characters())) { + if (name == entry.name) { return to_identifier(fsid(), PDI_Root, 0, (ProcFileType)entry.proc_file_type); } } @@ -993,22 +982,22 @@ InodeIdentifier ProcFSInode::lookup(const String& name) if (process_exists) return to_identifier(fsid(), PDI_Root, name_as_number, FI_PID); } - return { }; + return {}; } if (proc_file_type == FI_Root_sys) { for (int i = 0; i < fs().m_sys_entries.size(); ++i) { auto& entry = fs().m_sys_entries[i]; - if (!strcmp(entry.name, name.characters())) + if (name == entry.name) return sys_var_to_identifier(fsid(), i); } - return { }; + return {}; } if (proc_file_type == FI_PID) { auto handle = ProcessInspectionHandle::from_pid(to_pid(identifier())); if (!handle) - return { }; + return {}; auto& process = handle->process(); for (auto& entry : fs().m_entries) { if (entry.proc_file_type > __FI_PID_Start && entry.proc_file_type < __FI_PID_End) { @@ -1016,12 +1005,12 @@ InodeIdentifier ProcFSInode::lookup(const String& name) continue; if (entry.name == nullptr) continue; - if (!strcmp(entry.name, name.characters())) { + if (name == entry.name) { return to_identifier(fsid(), PDI_PID, to_pid(identifier()), (ProcFileType)entry.proc_file_type); } } } - return { }; + return {}; } if (proc_file_type == FI_PID_fd) { @@ -1032,41 +1021,20 @@ InodeIdentifier ProcFSInode::lookup(const String& name) { InterruptDisabler disabler; if (auto* process = Process::from_pid(to_pid(identifier()))) - fd_exists = process->file_descriptor(name_as_number); - + fd_exists = process->file_description(name_as_number); } if (fd_exists) return to_identifier_with_fd(fsid(), to_pid(identifier()), name_as_number); } } - return { }; -} - -String ProcFSInode::reverse_lookup(InodeIdentifier child_id) -{ - ASSERT(is_directory()); - auto proc_file_type = to_proc_file_type(identifier()); - if (proc_file_type == FI_Root) { - for (auto& entry : fs().m_entries) { - if (child_id == to_identifier(fsid(), PDI_Root, 0, (ProcFileType)entry.proc_file_type)) { - return entry.name; - } - } - auto child_proc_file_type = to_proc_file_type(child_id); - if (child_proc_file_type == FI_PID) - return String::format("%u", to_pid(child_id)); - return { }; - } - // FIXME: Implement - ASSERT_NOT_REACHED(); - return { }; + return {}; } void ProcFSInode::flush_metadata() { } -ssize_t ProcFSInode::write_bytes(off_t offset, ssize_t size, const byte* buffer, FileDescriptor*) +ssize_t ProcFSInode::write_bytes(off_t offset, ssize_t size, const byte* buffer, FileDescription*) { auto* directory_entry = fs().get_directory_entry(identifier()); if (!directory_entry || !directory_entry->write_callback) @@ -1079,14 +1047,14 @@ ssize_t ProcFSInode::write_bytes(off_t offset, ssize_t size, const byte* buffer, return 0; } -KResult ProcFSInode::add_child(InodeIdentifier child_id, const String& name, mode_t) +KResult ProcFSInode::add_child(InodeIdentifier child_id, const StringView& name, mode_t) { (void)child_id; (void)name; return KResult(-EPERM); } -KResult ProcFSInode::remove_child(const String& name) +KResult ProcFSInode::remove_child(const StringView& name) { (void)name; return KResult(-EPERM); @@ -1100,7 +1068,7 @@ size_t ProcFSInode::directory_entry_count() const { ASSERT(is_directory()); size_t count = 0; - traverse_as_directory([&count] (const FS::DirectoryEntry&) { + traverse_as_directory([&count](const FS::DirectoryEntry&) { ++count; return true; }); @@ -1124,7 +1092,7 @@ ProcFS::ProcFS() m_entries[FI_Root_all] = { "all", FI_Root_all, procfs$all }; m_entries[FI_Root_memstat] = { "memstat", FI_Root_memstat, procfs$memstat }; m_entries[FI_Root_summary] = { "summary", FI_Root_summary, procfs$summary }; - m_entries[FI_Root_cpuinfo] = { "cpuinfo", FI_Root_cpuinfo, procfs$cpuinfo}; + m_entries[FI_Root_cpuinfo] = { "cpuinfo", FI_Root_cpuinfo, procfs$cpuinfo }; m_entries[FI_Root_inodes] = { "inodes", FI_Root_inodes, procfs$inodes }; m_entries[FI_Root_dmesg] = { "dmesg", FI_Root_dmesg, procfs$dmesg }; m_entries[FI_Root_self] = { "self", FI_Root_self, procfs$self }; diff --git a/Kernel/FileSystem/ProcFS.h b/Kernel/FileSystem/ProcFS.h index eff50cd225..5b3e82969c 100644 --- a/Kernel/FileSystem/ProcFS.h +++ b/Kernel/FileSystem/ProcFS.h @@ -80,16 +80,14 @@ public: private: // ^Inode - virtual ssize_t read_bytes(off_t, ssize_t, byte* buffer, FileDescriptor*) const override; + virtual ssize_t read_bytes(off_t, ssize_t, byte* buffer, FileDescription*) const override; virtual InodeMetadata metadata() const override; virtual bool traverse_as_directory(Function) const override; - virtual InodeIdentifier lookup(const String& name) override; - virtual String reverse_lookup(InodeIdentifier) override; + virtual InodeIdentifier lookup(StringView name) override; virtual void flush_metadata() override; - virtual ssize_t write_bytes(off_t, ssize_t, const byte* buffer, FileDescriptor*) override; - virtual KResult add_child(InodeIdentifier child_id, const String& name, mode_t) override; - virtual KResult remove_child(const String& name) override; - virtual RetainPtr parent() const override; + virtual ssize_t write_bytes(off_t, ssize_t, const byte* buffer, FileDescription*) override; + virtual KResult add_child(InodeIdentifier child_id, const StringView& name, mode_t) override; + virtual KResult remove_child(const StringView& name) override; virtual size_t directory_entry_count() const override; virtual KResult chmod(mode_t) override; virtual KResult chown(uid_t, gid_t) override; diff --git a/Kernel/FileSystem/SyntheticFileSystem.cpp b/Kernel/FileSystem/SyntheticFileSystem.cpp index 79ec6c9968..62ea9c55fd 100644 --- a/Kernel/FileSystem/SyntheticFileSystem.cpp +++ b/Kernel/FileSystem/SyntheticFileSystem.cpp @@ -1,7 +1,7 @@ -#include -#include -#include #include +#include +#include +#include //#define SYNTHFS_DEBUG @@ -140,13 +140,13 @@ InodeIdentifier SynthFS::root_inode() const RetainPtr SynthFS::create_inode(InodeIdentifier parentInode, const String& name, mode_t mode, off_t size, dev_t, int& error) { - (void) parentInode; - (void) name; - (void) mode; - (void) size; - (void) error; + (void)parentInode; + (void)name; + (void)mode; + (void)size; + (void)error; kprintf("FIXME: Implement SyntheticFileSystem::create_inode().\n"); - return { }; + return {}; } RetainPtr SynthFS::create_directory(InodeIdentifier, const String&, mode_t, int& error) @@ -161,18 +161,12 @@ auto SynthFS::generate_inode_index() -> InodeIndex return m_next_inode_index++; } -RetainPtr SynthFSInode::parent() const -{ - LOCKER(m_lock); - return fs().get_inode(m_parent); -} - RetainPtr SynthFS::get_inode(InodeIdentifier inode) const { LOCKER(m_lock); auto it = m_inodes.find(inode.index()); if (it == m_inodes.end()) - return { }; + return {}; return (*it).value; } @@ -191,7 +185,7 @@ InodeMetadata SynthFSInode::metadata() const return m_metadata; } -ssize_t SynthFSInode::read_bytes(off_t offset, ssize_t count, byte* buffer, FileDescriptor* descriptor) const +ssize_t SynthFSInode::read_bytes(off_t offset, ssize_t count, byte* buffer, FileDescription* description) const { LOCKER(m_lock); #ifdef SYNTHFS_DEBUG @@ -202,20 +196,20 @@ ssize_t SynthFSInode::read_bytes(off_t offset, ssize_t count, byte* buffer, File ByteBuffer generated_data; if (m_generator) { - if (!descriptor) { + if (!description) { generated_data = m_generator(const_cast(*this)); } else { - if (!descriptor->generator_cache()) - descriptor->generator_cache() = m_generator(const_cast(*this)); - generated_data = descriptor->generator_cache(); + if (!description->generator_cache()) + description->generator_cache() = m_generator(const_cast(*this)); + generated_data = description->generator_cache(); } } auto* data = generated_data ? &generated_data : &m_data; ssize_t nread = min(static_cast(data->size() - offset), static_cast(count)); memcpy(buffer, data->pointer() + offset, nread); - if (nread == 0 && descriptor && descriptor->generator_cache()) - descriptor->generator_cache().clear(); + if (nread == 0 && description && description->generator_cache()) + description->generator_cache().clear(); return nread; } @@ -237,7 +231,7 @@ bool SynthFSInode::traverse_as_directory(Functionm_name == name) return child->identifier(); } - return { }; -} - -String SynthFSInode::reverse_lookup(InodeIdentifier child_id) -{ - LOCKER(m_lock); - ASSERT(is_directory()); - for (auto& child : m_children) { - if (child->identifier() == child_id) - return child->m_name; - } - return { }; + return {}; } void SynthFSInode::flush_metadata() { } -ssize_t SynthFSInode::write_bytes(off_t offset, ssize_t size, const byte* buffer, FileDescriptor*) +ssize_t SynthFSInode::write_bytes(off_t offset, ssize_t size, const byte* buffer, FileDescription*) { LOCKER(m_lock); if (!m_write_callback) @@ -279,14 +262,14 @@ ssize_t SynthFSInode::write_bytes(off_t offset, ssize_t size, const byte* buffer return 0; } -KResult SynthFSInode::add_child(InodeIdentifier child_id, const String& name, mode_t) +KResult SynthFSInode::add_child(InodeIdentifier child_id, const StringView& name, mode_t) { (void)child_id; (void)name; ASSERT_NOT_REACHED(); } -KResult SynthFSInode::remove_child(const String& name) +KResult SynthFSInode::remove_child(const StringView& name) { (void)name; ASSERT_NOT_REACHED(); diff --git a/Kernel/FileSystem/SyntheticFileSystem.h b/Kernel/FileSystem/SyntheticFileSystem.h index 825844732f..5a46f85a87 100644 --- a/Kernel/FileSystem/SyntheticFileSystem.h +++ b/Kernel/FileSystem/SyntheticFileSystem.h @@ -57,16 +57,14 @@ public: private: // ^Inode - virtual ssize_t read_bytes(off_t, ssize_t, byte* buffer, FileDescriptor*) const override; + virtual ssize_t read_bytes(off_t, ssize_t, byte* buffer, FileDescription*) const override; virtual InodeMetadata metadata() const override; virtual bool traverse_as_directory(Function) const override; - virtual InodeIdentifier lookup(const String& name) override; - virtual String reverse_lookup(InodeIdentifier) override; + virtual InodeIdentifier lookup(StringView name) override; virtual void flush_metadata() override; - virtual ssize_t write_bytes(off_t, ssize_t, const byte* buffer, FileDescriptor*) override; - virtual KResult add_child(InodeIdentifier child_id, const String& name, mode_t) override; - virtual KResult remove_child(const String& name) override; - virtual RetainPtr parent() const override; + virtual ssize_t write_bytes(off_t, ssize_t, const byte* buffer, FileDescription*) override; + virtual KResult add_child(InodeIdentifier child_id, const StringView& name, mode_t) override; + virtual KResult remove_child(const StringView& name) override; virtual size_t directory_entry_count() const override; virtual KResult chmod(mode_t) override; virtual KResult chown(uid_t, gid_t) override; diff --git a/Kernel/FileSystem/VirtualFileSystem.cpp b/Kernel/FileSystem/VirtualFileSystem.cpp index d03af1d6ac..296821094e 100644 --- a/Kernel/FileSystem/VirtualFileSystem.cpp +++ b/Kernel/FileSystem/VirtualFileSystem.cpp @@ -1,12 +1,12 @@ -#include "VirtualFileSystem.h" -#include -#include "FileSystem.h" #include #include #include -#include -#include #include +#include +#include +#include +#include +#include //#define VFS_DEBUG @@ -104,7 +104,7 @@ bool VFS::is_vfs_root(InodeIdentifier inode) const void VFS::traverse_directory_inode(Inode& dir_inode, Function callback) { - dir_inode.traverse_as_directory([&] (const FS::DirectoryEntry& entry) { + dir_inode.traverse_as_directory([&](const FS::DirectoryEntry& entry) { InodeIdentifier resolved_inode; if (auto mount = find_mount_for_host(entry.inode)) resolved_inode = mount->guest(); @@ -146,15 +146,21 @@ KResult VFS::stat(StringView path, int options, Custody& base, struct stat& stat auto custody_or_error = resolve_path(path, base, nullptr, options); if (custody_or_error.is_error()) return custody_or_error.error(); - return FileDescriptor::create(custody_or_error.value().ptr())->fstat(statbuf); + return custody_or_error.value()->inode().metadata().stat(statbuf); } -KResultOr> VFS::open(StringView path, int options, mode_t mode, Custody& base) +KResultOr> VFS::open(StringView path, int options, mode_t mode, Custody& base) { - auto custody_or_error = resolve_path(path, base, nullptr, options); + RetainPtr parent_custody; + auto custody_or_error = resolve_path(path, base, &parent_custody, options); if (options & O_CREAT) { - if (custody_or_error.is_error()) - return create(path, options, mode, base); + if (!parent_custody) + return KResult(-ENOENT); + if (custody_or_error.is_error()) { + if (custody_or_error.error() != -ENOENT) + return custody_or_error.error(); + return create(path, options, mode, *parent_custody); + } if (options & O_EXCL) return KResult(-EEXIST); } @@ -194,7 +200,7 @@ KResultOr> VFS::open(StringView path, int options, mode } if (should_truncate_file) inode.truncate(0); - return FileDescriptor::create(custody); + return FileDescription::create(custody); } KResult VFS::mknod(StringView path, mode_t mode, dev_t dev, Custody& base) @@ -224,7 +230,7 @@ KResult VFS::mknod(StringView path, mode_t mode, dev_t dev, Custody& base) return KSuccess; } -KResultOr> VFS::create(StringView path, int options, mode_t mode, Custody& base) +KResultOr> VFS::create(StringView path, int options, mode_t mode, Custody& parent_custody) { (void)options; @@ -233,18 +239,9 @@ KResultOr> VFS::create(StringView path, int options, mo mode |= 0100000; } - RetainPtr parent_custody; - auto existing_custody_or_error = resolve_path(path, base, &parent_custody); - if (!existing_custody_or_error.is_error()) - return KResult(-EEXIST); - if (!parent_custody) - return KResult(-ENOENT); - auto& parent_inode = parent_custody->inode(); - if (existing_custody_or_error.error() != -ENOENT) - return existing_custody_or_error.error(); + auto& parent_inode = parent_custody.inode(); if (!parent_inode.metadata().may_write(current->process())) return KResult(-EACCES); - FileSystemPath p(path); dbgprintf("VFS::create_file: '%s' in %u:%u\n", p.basename().characters(), parent_inode.fsid(), parent_inode.index()); int error; @@ -252,8 +249,8 @@ KResultOr> VFS::create(StringView path, int options, mo if (!new_file) return KResult(error); - auto new_custody = Custody::create(parent_custody, p.basename(), *new_file); - return FileDescriptor::create(*new_custody); + auto new_custody = Custody::create(&parent_custody, p.basename(), *new_file); + return FileDescription::create(*new_custody); } KResult VFS::mkdir(StringView path, mode_t mode, Custody& base) @@ -317,7 +314,7 @@ KResultOr> VFS::open_directory(StringView path, Custody& base) return custody; } -KResult VFS::fchmod(Inode& inode, mode_t mode) +KResult VFS::chmod(Inode& inode, mode_t mode) { if (inode.fs().is_readonly()) return KResult(-EROFS); @@ -337,7 +334,7 @@ KResult VFS::chmod(StringView path, mode_t mode, Custody& base) return custody_or_error.error(); auto& custody = *custody_or_error.value(); auto& inode = custody.inode(); - return fchmod(inode, mode); + return chmod(inode, mode); } KResult VFS::rename(StringView old_path, StringView new_path, Custody& base) @@ -402,22 +399,18 @@ KResult VFS::rename(StringView old_path, StringView new_path, Custody& base) return KSuccess; } -KResult VFS::chown(StringView path, uid_t a_uid, gid_t a_gid, Custody& base) +KResult VFS::chown(Inode& inode, uid_t a_uid, gid_t a_gid) { - auto custody_or_error = resolve_path(path, base); - if (custody_or_error.is_error()) - return custody_or_error.error(); - auto& custody = *custody_or_error.value(); - auto& inode = custody.inode(); - if (inode.fs().is_readonly()) return KResult(-EROFS); - if (current->process().euid() != inode.metadata().uid && !current->process().is_superuser()) + auto metadata = inode.metadata(); + + if (current->process().euid() != metadata.uid && !current->process().is_superuser()) return KResult(-EPERM); - uid_t new_uid = inode.metadata().uid; - gid_t new_gid = inode.metadata().gid; + uid_t new_uid = metadata.uid; + gid_t new_gid = metadata.gid; if (a_uid != (uid_t)-1) { if (current->process().euid() != a_uid && !current->process().is_superuser()) @@ -434,6 +427,16 @@ KResult VFS::chown(StringView path, uid_t a_uid, gid_t a_gid, Custody& base) return inode.chown(new_uid, new_gid); } +KResult VFS::chown(StringView path, uid_t a_uid, gid_t a_gid, Custody& base) +{ + auto custody_or_error = resolve_path(path, base); + if (custody_or_error.is_error()) + return custody_or_error.error(); + auto& custody = *custody_or_error.value(); + auto& inode = custody.inode(); + return chown(inode, a_uid, a_gid); +} + KResult VFS::link(StringView old_path, StringView new_path, Custody& base) { auto old_custody_or_error = resolve_path(old_path, base); @@ -580,7 +583,7 @@ String VFS::Mount::absolute_path() const InodeIdentifier VFS::Mount::host() const { if (!m_host_custody) - return { }; + return {}; return m_host_custody->inode().identifier(); } @@ -647,9 +650,6 @@ KResultOr> VFS::resolve_path(StringView path, Custody& base, R for (int i = 0; i < parts.size(); ++i) { bool inode_was_root_at_head_of_loop = crumb_id.is_root_inode(); - auto& part = parts[i]; - if (part.is_empty()) - break; auto crumb_inode = get_inode(crumb_id); if (!crumb_inode) return KResult(-EIO); @@ -658,6 +658,11 @@ KResultOr> VFS::resolve_path(StringView path, Custody& base, R return KResult(-ENOTDIR); if (!metadata.may_execute(current->process())) return KResult(-EACCES); + + auto& part = parts[i]; + if (part.is_empty()) + break; + auto current_parent = custody_chain.last(); crumb_id = crumb_inode->lookup(part); if (!crumb_id.is_valid()) @@ -694,13 +699,25 @@ KResultOr> VFS::resolve_path(StringView path, Custody& base, R return KResult(-ENOENT); // FIXME: We should limit the recursion here and return -ELOOP if it goes to deep. - return resolve_path( + auto symlink_target = resolve_path( StringView(symlink_contents.pointer(), - symlink_contents.size()), + symlink_contents.size()), *current_parent, parent_custody, - options - ); + options); + + if (symlink_target.is_error()) + return symlink_target; + + bool have_more_parts = i + 1 < parts.size(); + if (i + 1 == parts.size() - 1 && parts[i + 1].is_empty()) + have_more_parts = false; + + if (!have_more_parts) + return symlink_target; + + StringView remaining_path = path.substring_view_starting_from_substring(parts[i + 1]); + return resolve_path(remaining_path, *symlink_target.value(), parent_custody, options); } } return custody_chain.last(); diff --git a/Kernel/FileSystem/VirtualFileSystem.h b/Kernel/FileSystem/VirtualFileSystem.h index 0027cb408f..c1f2e20860 100644 --- a/Kernel/FileSystem/VirtualFileSystem.h +++ b/Kernel/FileSystem/VirtualFileSystem.h @@ -28,14 +28,7 @@ class Custody; class Device; -class FileDescriptor; - -inline constexpr dword encoded_device(unsigned major, unsigned minor) -{ - return (minor & 0xff) | (major << 8) | ((minor & ~0xff) << 12); -} - -class VFS; +class FileDescription; class VFS { AK_MAKE_ETERNAL @@ -66,17 +59,18 @@ public: bool mount_root(Retained&&); bool mount(Retained&&, StringView path); - KResultOr> open(RetainPtr&&, int options); - KResultOr> open(StringView path, int options, mode_t mode, Custody& base); - KResultOr> create(StringView path, int options, mode_t mode, Custody& base); + KResultOr> open(RetainPtr&&, int options); + KResultOr> open(StringView path, int options, mode_t mode, Custody& base); + KResultOr> create(StringView path, int options, mode_t mode, Custody& parent_custody); KResult mkdir(StringView path, mode_t mode, Custody& base); KResult link(StringView old_path, StringView new_path, Custody& base); KResult unlink(StringView path, Custody& base); KResult symlink(StringView target, StringView linkpath, Custody& base); KResult rmdir(StringView path, Custody& base); KResult chmod(StringView path, mode_t, Custody& base); - KResult fchmod(Inode&, mode_t); + KResult chmod(Inode&, mode_t); KResult chown(StringView path, uid_t, gid_t, Custody& base); + KResult chown(Inode&, uid_t, gid_t); KResult access(StringView path, int mode, Custody& base); KResult stat(StringView path, int options, Custody& base, struct stat&); KResult utime(StringView path, Custody& base, time_t atime, time_t mtime); @@ -100,7 +94,7 @@ public: KResultOr> resolve_path(StringView path, Custody& base, RetainPtr* parent = nullptr, int options = 0); private: - friend class FileDescriptor; + friend class FileDescription; RetainPtr get_inode(InodeIdentifier); diff --git a/Kernel/IRQHandler.cpp b/Kernel/IRQHandler.cpp index fb852a4ae5..400944289c 100644 --- a/Kernel/IRQHandler.cpp +++ b/Kernel/IRQHandler.cpp @@ -1,6 +1,6 @@ #include "IRQHandler.h" -#include "i386.h" #include "PIC.h" +#include IRQHandler::IRQHandler(byte irq) : m_irq_number(irq) @@ -22,4 +22,3 @@ void IRQHandler::disable_irq() { PIC::disable(m_irq_number); } - diff --git a/Kernel/KParams.cpp b/Kernel/KParams.cpp new file mode 100644 index 0000000000..26f4df771a --- /dev/null +++ b/Kernel/KParams.cpp @@ -0,0 +1,38 @@ +#include + +static KParams* s_the; + +KParams& KParams::the() +{ + return *s_the; +} + +KParams::KParams(const String& cmdline) + : m_cmdline(cmdline) +{ + s_the = this; + + for (auto str : m_cmdline.split(' ')) { + if (str == "") { + continue; + } + + auto pair = str.split_limit('=', 2); + + if (pair.size() == 1) { + m_params.set(pair[0], ""); + } else { + m_params.set(pair[0], pair[1]); + } + } +} + +String KParams::get(const String& key) const +{ + return m_params.get(key); +} + +bool KParams::has(const String& key) const +{ + return m_params.contains(key); +} diff --git a/Kernel/KParams.h b/Kernel/KParams.h new file mode 100644 index 0000000000..603aedb5d6 --- /dev/null +++ b/Kernel/KParams.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + +class KParams { + AK_MAKE_ETERNAL +public: + static KParams& the(); + + KParams(const String& cmdline); + + const String& cmdline() const { return m_cmdline; } + String get(const String& key) const; + bool has(const String& key) const; + +private: + String m_cmdline; + HashMap m_params; +}; diff --git a/Kernel/KResult.h b/Kernel/KResult.h index 291e9ea2ea..b0c7a67f37 100644 --- a/Kernel/KResult.h +++ b/Kernel/KResult.h @@ -3,8 +3,7 @@ #include #include -enum KSuccessTag -{ +enum KSuccessTag { KSuccess }; @@ -54,7 +53,11 @@ public: KResultOr(KResultOr&& other) { - new (&m_storage) T(move(other.value())); + m_is_error = other.m_is_error; + if (m_is_error) + m_error = other.m_error; + else + new (&m_storage) T(move(other.value())); other.m_is_error = true; other.m_error = KSuccess; } diff --git a/Kernel/KSyms.cpp b/Kernel/KSyms.cpp index 6ee0a3ac23..9e0eddc458 100644 --- a/Kernel/KSyms.cpp +++ b/Kernel/KSyms.cpp @@ -1,9 +1,9 @@ #include "KSyms.h" #include "Process.h" #include "Scheduler.h" -#include #include #include +#include static KSym* s_ksyms; dword ksym_lowest_address; @@ -94,12 +94,12 @@ static void load_ksyms_from_data(const ByteBuffer& buffer) RecognizedSymbol recognized_symbols[max_recognized_symbol_count]; int recognized_symbol_count = 0; if (use_ksyms) { - for (dword* stack_ptr = (dword*)ebp; current->process().validate_read_from_kernel(LinearAddress((dword)stack_ptr)); stack_ptr = (dword*)*stack_ptr) { + for (dword* stack_ptr = (dword*)ebp; current->process().validate_read_from_kernel(VirtualAddress((dword)stack_ptr)); stack_ptr = (dword*)*stack_ptr) { dword retaddr = stack_ptr[1]; recognized_symbols[recognized_symbol_count++] = { retaddr, ksymbolicate(retaddr) }; } } else { - for (dword* stack_ptr = (dword*)ebp; current->process().validate_read_from_kernel(LinearAddress((dword)stack_ptr)); stack_ptr = (dword*)*stack_ptr) { + for (dword* stack_ptr = (dword*)ebp; current->process().validate_read_from_kernel(VirtualAddress((dword)stack_ptr)); stack_ptr = (dword*)*stack_ptr) { dword retaddr = stack_ptr[1]; dbgprintf("%x (next: %x)\n", retaddr, stack_ptr ? (dword*)*stack_ptr : 0); } @@ -140,7 +140,8 @@ void dump_backtrace() } TemporaryChange change(in_dump_backtrace, true); dword ebp; - asm volatile("movl %%ebp, %%eax":"=a"(ebp)); + asm volatile("movl %%ebp, %%eax" + : "=a"(ebp)); dump_backtrace_impl(ebp, ksyms_ready); } @@ -156,8 +157,8 @@ void load_ksyms() { auto result = VFS::the().open("/kernel.map", 0, 0, VFS::the().root_custody()); ASSERT(!result.is_error()); - auto descriptor = result.value(); - auto buffer = descriptor->read_entire_file(); + auto description = result.value(); + auto buffer = description->read_entire_file(); ASSERT(buffer); load_ksyms_from_data(buffer); } diff --git a/Kernel/KeyCode.h b/Kernel/KeyCode.h index 67c065625f..310c950ca9 100644 --- a/Kernel/KeyCode.h +++ b/Kernel/KeyCode.h @@ -2,8 +2,7 @@ #include -enum KeyCode : byte -{ +enum KeyCode : byte { Key_Invalid = 0, Key_Escape, Key_Tab, @@ -114,8 +113,7 @@ enum KeyCode : byte Key_Shift = Key_LeftShift, }; -enum KeyModifier -{ +enum KeyModifier { Mod_None = 0x00, Mod_Alt = 0x01, Mod_Ctrl = 0x02, diff --git a/Kernel/LinearAddress.h b/Kernel/LinearAddress.h deleted file mode 100644 index 3b0eecea02..0000000000 --- a/Kernel/LinearAddress.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include - -class LinearAddress { -public: - LinearAddress() {} - explicit LinearAddress(dword address) - : m_address(address) - { - } - - bool is_null() const { return m_address == 0; } - - LinearAddress offset(dword o) const { return LinearAddress(m_address + o); } - dword get() const { return m_address; } - void set(dword address) { m_address = address; } - void mask(dword m) { m_address &= m; } - - bool operator<=(const LinearAddress& other) const { return m_address <= other.m_address; } - bool operator>=(const LinearAddress& other) const { return m_address >= other.m_address; } - bool operator>(const LinearAddress& other) const { return m_address > other.m_address; } - bool operator<(const LinearAddress& other) const { return m_address < other.m_address; } - bool operator==(const LinearAddress& other) const { return m_address == other.m_address; } - bool operator!=(const LinearAddress& other) const { return m_address != other.m_address; } - - byte* as_ptr() { return reinterpret_cast(m_address); } - const byte* as_ptr() const { return reinterpret_cast(m_address); } - - dword page_base() const { return m_address & 0xfffff000; } - -private: - dword m_address { 0 }; -}; - -inline LinearAddress operator-(const LinearAddress& a, const LinearAddress& b) -{ - return LinearAddress(a.get() - b.get()); -} diff --git a/Kernel/Lock.h b/Kernel/Lock.h index fcd9a69a94..875dc84ae4 100644 --- a/Kernel/Lock.h +++ b/Kernel/Lock.h @@ -2,9 +2,9 @@ #include #include +#include #include #include -#include class Thread; extern Thread* current; diff --git a/Kernel/Makefile b/Kernel/Makefile index 1593bfc41c..8579d3bf38 100644 --- a/Kernel/Makefile +++ b/Kernel/Makefile @@ -4,7 +4,7 @@ KERNEL_OBJS = \ init.o \ kmalloc.o \ StdLib.o \ - i386.o \ + Arch/i386/CPU.o \ Process.o \ Thread.o \ i8253.o \ @@ -18,6 +18,7 @@ KERNEL_OBJS = \ VM/VMObject.o \ VM/PageDirectory.o \ VM/PhysicalPage.o \ + VM/PhysicalRegion.o \ VM/RangeAllocator.o \ Console.o \ IRQHandler.o \ @@ -32,11 +33,13 @@ KERNEL_OBJS = \ Scheduler.o \ DoubleBuffer.o \ KSyms.o \ + KParams.o \ SharedMemory.o \ FileSystem/DevPtsFS.o \ Devices/BXVGADevice.o \ PCI.o \ Devices/PS2MouseDevice.o \ + Devices/SerialDevice.o \ Net/Socket.o \ Net/LocalSocket.o \ Net/IPv4Socket.o \ @@ -65,11 +68,13 @@ VFS_OBJS = \ Devices/ZeroDevice.o \ Devices/RandomDevice.o \ Devices/DebugLogDevice.o \ + Devices/DiskPartition.o \ + Devices/MBRPartitionTable.o \ FileSystem/FileSystem.o \ FileSystem/DiskBackedFileSystem.o \ FileSystem/Ext2FileSystem.o \ FileSystem/VirtualFileSystem.o \ - FileSystem/FileDescriptor.o \ + FileSystem/FileDescription.o \ FileSystem/SyntheticFileSystem.o AK_OBJS = \ diff --git a/Kernel/Multiboot.h b/Kernel/Multiboot.h new file mode 100644 index 0000000000..a74c4feb34 --- /dev/null +++ b/Kernel/Multiboot.h @@ -0,0 +1,111 @@ +#pragma once + +#include + +struct multiboot_aout_symbol_table { + dword tabsize; + dword strsize; + dword addr; + dword reserved; +}; +typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t; + +struct multiboot_elf_section_header_table { + dword num; + dword size; + dword addr; + dword shndx; +}; +typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t; + +#define MULTIBOOT_MEMORY_AVAILABLE 1 +#define MULTIBOOT_MEMORY_RESERVED 2 +#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3 +#define MULTIBOOT_MEMORY_NVS 4 +#define MULTIBOOT_MEMORY_BADRAM 5 + +struct multiboot_mmap_entry { + dword size; + qword addr; + qword len; + dword type; +} __attribute__((packed)); +typedef struct multiboot_mmap_entry multiboot_memory_map_t; + +struct multiboot_info { + // Multiboot info version number. + dword flags; + + // Available memory from BIOS. + dword mem_lower; + dword mem_upper; + + // "root" partition. + dword boot_device; + + // Kernel command line. + dword cmdline; + + // Boot-Module list. + dword mods_count; + dword mods_addr; + + union { + multiboot_aout_symbol_table_t aout_sym; + multiboot_elf_section_header_table_t elf_sec; + } u; + + // Memory Mapping buffer. + dword mmap_length; + dword mmap_addr; + + // Drive Info buffer. + dword drives_length; + dword drives_addr; + + // ROM configuration table. + dword config_table; + + // Boot Loader Name. + dword boot_loader_name; + + // APM table. + dword apm_table; + + // Video. + dword vbe_control_info; + dword vbe_mode_info; + word vbe_mode; + word vbe_interface_seg; + word vbe_interface_off; + word vbe_interface_len; + + qword framebuffer_addr; + dword framebuffer_pitch; + dword framebuffer_width; + dword framebuffer_height; + byte framebuffer_bpp; +#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0 +#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1 +#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2 + byte framebuffer_type; + union { + struct + { + dword framebuffer_palette_addr; + word framebuffer_palette_num_colors; + }; + struct + { + byte framebuffer_red_field_position; + byte framebuffer_red_mask_size; + byte framebuffer_green_field_position; + byte framebuffer_green_mask_size; + byte framebuffer_blue_field_position; + byte framebuffer_blue_mask_size; + }; + }; +}; +typedef struct multiboot_info multiboot_info_t; + +extern "C" multiboot_info_t* multiboot_info_ptr; diff --git a/Kernel/Net/ARP.h b/Kernel/Net/ARP.h index 2fecc2b0a0..6f3a3cb0ab 100644 --- a/Kernel/Net/ARP.h +++ b/Kernel/Net/ARP.h @@ -1,20 +1,19 @@ #pragma once +#include #include #include #include struct ARPOperation { - enum : word - { + enum : word { Request = 1, Response = 2, }; }; struct ARPHardwareType { - enum : word - { + enum : word { Ethernet = 1, }; }; @@ -22,11 +21,11 @@ struct ARPHardwareType { class [[gnu::packed]] ARPPacket { public: - word hardware_type() const { return ntohs(m_hardware_type); } - void set_hardware_type(word w) { m_hardware_type = htons(w); } + word hardware_type() const { return m_hardware_type; } + void set_hardware_type(word w) { m_hardware_type = w; } - word protocol_type() const { return ntohs(m_protocol_type); } - void set_protocol_type(word w) { m_protocol_type = htons(w); } + word protocol_type() const { return m_protocol_type; } + void set_protocol_type(word w) { m_protocol_type = w; } byte hardware_address_length() const { return m_hardware_address_length; } void set_hardware_address_length(byte b) { m_hardware_address_length = b; } @@ -34,8 +33,8 @@ public: byte protocol_address_length() const { return m_protocol_address_length; } void set_protocol_address_length(byte b) { m_protocol_address_length = b; } - word operation() const { return ntohs(m_operation); } - void set_operation(word w) { m_operation = htons(w); } + word operation() const { return m_operation; } + void set_operation(word w) { m_operation = w; } const MACAddress& sender_hardware_address() const { return m_sender_hardware_address; } void set_sender_hardware_address(const MACAddress& address) { m_sender_hardware_address = address; } @@ -50,11 +49,11 @@ public: void set_target_protocol_address(const IPv4Address& address) { m_target_protocol_address = address; } private: - word m_hardware_type { 0x0100 }; - word m_protocol_type { 0x0008 }; + NetworkOrdered m_hardware_type { ARPHardwareType::Ethernet }; + NetworkOrdered m_protocol_type { EtherType::IPv4 }; byte m_hardware_address_length { sizeof(MACAddress) }; byte m_protocol_address_length { sizeof(IPv4Address) }; - word m_operation { 0 }; + NetworkOrdered m_operation; MACAddress m_sender_hardware_address; IPv4Address m_sender_protocol_address; MACAddress m_target_hardware_address; diff --git a/Kernel/Net/E1000NetworkAdapter.cpp b/Kernel/Net/E1000NetworkAdapter.cpp index b73ddc70e2..fcfaa48e6b 100644 --- a/Kernel/Net/E1000NetworkAdapter.cpp +++ b/Kernel/Net/E1000NetworkAdapter.cpp @@ -1,90 +1,90 @@ +#include #include #include -#include -#define REG_CTRL 0x0000 -#define REG_STATUS 0x0008 -#define REG_EEPROM 0x0014 -#define REG_CTRL_EXT 0x0018 -#define REG_IMASK 0x00D0 -#define REG_RCTRL 0x0100 -#define REG_RXDESCLO 0x2800 -#define REG_RXDESCHI 0x2804 -#define REG_RXDESCLEN 0x2808 -#define REG_RXDESCHEAD 0x2810 -#define REG_RXDESCTAIL 0x2818 -#define REG_TCTRL 0x0400 -#define REG_TXDESCLO 0x3800 -#define REG_TXDESCHI 0x3804 -#define REG_TXDESCLEN 0x3808 -#define REG_TXDESCHEAD 0x3810 -#define REG_TXDESCTAIL 0x3818 -#define REG_RDTR 0x2820 // RX Delay Timer Register -#define REG_RXDCTL 0x3828 // RX Descriptor Control -#define REG_RADV 0x282C // RX Int. Absolute Delay Timer -#define REG_RSRPD 0x2C00 // RX Small Packet Detect Interrupt -#define REG_TIPG 0x0410 // Transmit Inter Packet Gap -#define ECTRL_SLU 0x40 //set link up -#define RCTL_EN (1 << 1) // Receiver Enable -#define RCTL_SBP (1 << 2) // Store Bad Packets -#define RCTL_UPE (1 << 3) // Unicast Promiscuous Enabled -#define RCTL_MPE (1 << 4) // Multicast Promiscuous Enabled -#define RCTL_LPE (1 << 5) // Long Packet Reception Enable -#define RCTL_LBM_NONE (0 << 6) // No Loopback -#define RCTL_LBM_PHY (3 << 6) // PHY or external SerDesc loopback -#define RTCL_RDMTS_HALF (0 << 8) // Free Buffer Threshold is 1/2 of RDLEN -#define RTCL_RDMTS_QUARTER (1 << 8) // Free Buffer Threshold is 1/4 of RDLEN -#define RTCL_RDMTS_EIGHTH (2 << 8) // Free Buffer Threshold is 1/8 of RDLEN -#define RCTL_MO_36 (0 << 12) // Multicast Offset - bits 47:36 -#define RCTL_MO_35 (1 << 12) // Multicast Offset - bits 46:35 -#define RCTL_MO_34 (2 << 12) // Multicast Offset - bits 45:34 -#define RCTL_MO_32 (3 << 12) // Multicast Offset - bits 43:32 -#define RCTL_BAM (1 << 15) // Broadcast Accept Mode -#define RCTL_VFE (1 << 18) // VLAN Filter Enable -#define RCTL_CFIEN (1 << 19) // Canonical Form Indicator Enable -#define RCTL_CFI (1 << 20) // Canonical Form Indicator Bit Value -#define RCTL_DPF (1 << 22) // Discard Pause Frames -#define RCTL_PMCF (1 << 23) // Pass MAC Control Frames -#define RCTL_SECRC (1 << 26) // Strip Ethernet CRC +#define REG_CTRL 0x0000 +#define REG_STATUS 0x0008 +#define REG_EEPROM 0x0014 +#define REG_CTRL_EXT 0x0018 +#define REG_IMASK 0x00D0 +#define REG_RCTRL 0x0100 +#define REG_RXDESCLO 0x2800 +#define REG_RXDESCHI 0x2804 +#define REG_RXDESCLEN 0x2808 +#define REG_RXDESCHEAD 0x2810 +#define REG_RXDESCTAIL 0x2818 +#define REG_TCTRL 0x0400 +#define REG_TXDESCLO 0x3800 +#define REG_TXDESCHI 0x3804 +#define REG_TXDESCLEN 0x3808 +#define REG_TXDESCHEAD 0x3810 +#define REG_TXDESCTAIL 0x3818 +#define REG_RDTR 0x2820 // RX Delay Timer Register +#define REG_RXDCTL 0x3828 // RX Descriptor Control +#define REG_RADV 0x282C // RX Int. Absolute Delay Timer +#define REG_RSRPD 0x2C00 // RX Small Packet Detect Interrupt +#define REG_TIPG 0x0410 // Transmit Inter Packet Gap +#define ECTRL_SLU 0x40 //set link up +#define RCTL_EN (1 << 1) // Receiver Enable +#define RCTL_SBP (1 << 2) // Store Bad Packets +#define RCTL_UPE (1 << 3) // Unicast Promiscuous Enabled +#define RCTL_MPE (1 << 4) // Multicast Promiscuous Enabled +#define RCTL_LPE (1 << 5) // Long Packet Reception Enable +#define RCTL_LBM_NONE (0 << 6) // No Loopback +#define RCTL_LBM_PHY (3 << 6) // PHY or external SerDesc loopback +#define RTCL_RDMTS_HALF (0 << 8) // Free Buffer Threshold is 1/2 of RDLEN +#define RTCL_RDMTS_QUARTER (1 << 8) // Free Buffer Threshold is 1/4 of RDLEN +#define RTCL_RDMTS_EIGHTH (2 << 8) // Free Buffer Threshold is 1/8 of RDLEN +#define RCTL_MO_36 (0 << 12) // Multicast Offset - bits 47:36 +#define RCTL_MO_35 (1 << 12) // Multicast Offset - bits 46:35 +#define RCTL_MO_34 (2 << 12) // Multicast Offset - bits 45:34 +#define RCTL_MO_32 (3 << 12) // Multicast Offset - bits 43:32 +#define RCTL_BAM (1 << 15) // Broadcast Accept Mode +#define RCTL_VFE (1 << 18) // VLAN Filter Enable +#define RCTL_CFIEN (1 << 19) // Canonical Form Indicator Enable +#define RCTL_CFI (1 << 20) // Canonical Form Indicator Bit Value +#define RCTL_DPF (1 << 22) // Discard Pause Frames +#define RCTL_PMCF (1 << 23) // Pass MAC Control Frames +#define RCTL_SECRC (1 << 26) // Strip Ethernet CRC // Buffer Sizes -#define RCTL_BSIZE_256 (3 << 16) -#define RCTL_BSIZE_512 (2 << 16) -#define RCTL_BSIZE_1024 (1 << 16) -#define RCTL_BSIZE_2048 (0 << 16) -#define RCTL_BSIZE_4096 ((3 << 16) | (1 << 25)) -#define RCTL_BSIZE_8192 ((2 << 16) | (1 << 25)) -#define RCTL_BSIZE_16384 ((1 << 16) | (1 << 25)) +#define RCTL_BSIZE_256 (3 << 16) +#define RCTL_BSIZE_512 (2 << 16) +#define RCTL_BSIZE_1024 (1 << 16) +#define RCTL_BSIZE_2048 (0 << 16) +#define RCTL_BSIZE_4096 ((3 << 16) | (1 << 25)) +#define RCTL_BSIZE_8192 ((2 << 16) | (1 << 25)) +#define RCTL_BSIZE_16384 ((1 << 16) | (1 << 25)) // Transmit Command -#define CMD_EOP (1 << 0) // End of Packet -#define CMD_IFCS (1 << 1) // Insert FCS -#define CMD_IC (1 << 2) // Insert Checksum -#define CMD_RS (1 << 3) // Report Status -#define CMD_RPS (1 << 4) // Report Packet Sent -#define CMD_VLE (1 << 6) // VLAN Packet Enable -#define CMD_IDE (1 << 7) // Interrupt Delay Enable +#define CMD_EOP (1 << 0) // End of Packet +#define CMD_IFCS (1 << 1) // Insert FCS +#define CMD_IC (1 << 2) // Insert Checksum +#define CMD_RS (1 << 3) // Report Status +#define CMD_RPS (1 << 4) // Report Packet Sent +#define CMD_VLE (1 << 6) // VLAN Packet Enable +#define CMD_IDE (1 << 7) // Interrupt Delay Enable // TCTL Register -#define TCTL_EN (1 << 1) // Transmit Enable -#define TCTL_PSP (1 << 3) // Pad Short Packets -#define TCTL_CT_SHIFT 4 // Collision Threshold -#define TCTL_COLD_SHIFT 12 // Collision Distance -#define TCTL_SWXOFF (1 << 22) // Software XOFF Transmission -#define TCTL_RTLC (1 << 24) // Re-transmit on Late Collision +#define TCTL_EN (1 << 1) // Transmit Enable +#define TCTL_PSP (1 << 3) // Pad Short Packets +#define TCTL_CT_SHIFT 4 // Collision Threshold +#define TCTL_COLD_SHIFT 12 // Collision Distance +#define TCTL_SWXOFF (1 << 22) // Software XOFF Transmission +#define TCTL_RTLC (1 << 24) // Re-transmit on Late Collision -#define TSTA_DD (1 << 0) // Descriptor Done -#define TSTA_EC (1 << 1) // Excess Collisions -#define TSTA_LC (1 << 2) // Late Collision -#define LSTA_TU (1 << 3) // Transmit Underrun +#define TSTA_DD (1 << 0) // Descriptor Done +#define TSTA_EC (1 << 1) // Excess Collisions +#define TSTA_LC (1 << 2) // Late Collision +#define LSTA_TU (1 << 3) // Transmit Underrun OwnPtr E1000NetworkAdapter::autodetect() { static const PCI::ID qemu_bochs_vbox_id = { 0x8086, 0x100e }; PCI::Address found_address; - PCI::enumerate_all([&] (const PCI::Address& address, PCI::ID id) { + PCI::enumerate_all([&](const PCI::Address& address, PCI::ID id) { if (id == qemu_bochs_vbox_id) { found_address = address; return; @@ -112,11 +112,11 @@ E1000NetworkAdapter::E1000NetworkAdapter(PCI::Address pci_address, byte irq) enable_bus_mastering(m_pci_address); m_mmio_base = PhysicalAddress(PCI::get_BAR0(m_pci_address)); - MM.map_for_kernel(LinearAddress(m_mmio_base.get()), m_mmio_base); - MM.map_for_kernel(LinearAddress(m_mmio_base.offset(4096).get()), m_mmio_base.offset(4096)); - MM.map_for_kernel(LinearAddress(m_mmio_base.offset(8192).get()), m_mmio_base.offset(8192)); - MM.map_for_kernel(LinearAddress(m_mmio_base.offset(12288).get()), m_mmio_base.offset(12288)); - MM.map_for_kernel(LinearAddress(m_mmio_base.offset(16384).get()), m_mmio_base.offset(16384)); + MM.map_for_kernel(VirtualAddress(m_mmio_base.get()), m_mmio_base); + MM.map_for_kernel(VirtualAddress(m_mmio_base.offset(4096).get()), m_mmio_base.offset(4096)); + MM.map_for_kernel(VirtualAddress(m_mmio_base.offset(8192).get()), m_mmio_base.offset(8192)); + MM.map_for_kernel(VirtualAddress(m_mmio_base.offset(12288).get()), m_mmio_base.offset(12288)); + MM.map_for_kernel(VirtualAddress(m_mmio_base.offset(16384).get()), m_mmio_base.offset(16384)); m_use_mmio = true; m_io_base = PCI::get_BAR1(m_pci_address) & ~1; m_interrupt_line = PCI::get_interrupt_line(m_pci_address); @@ -231,7 +231,7 @@ void E1000NetworkAdapter::initialize_rx_descriptors() out32(REG_RXDESCHEAD, 0); out32(REG_RXDESCTAIL, number_of_rx_descriptors - 1); - out32(REG_RCTRL, RCTL_EN| RCTL_SBP| RCTL_UPE | RCTL_MPE | RCTL_LBM_NONE | RTCL_RDMTS_HALF | RCTL_BAM | RCTL_SECRC | RCTL_BSIZE_8192); + out32(REG_RCTRL, RCTL_EN | RCTL_SBP | RCTL_UPE | RCTL_MPE | RCTL_LBM_NONE | RTCL_RDMTS_HALF | RCTL_BAM | RCTL_SECRC | RCTL_BSIZE_8192); } void E1000NetworkAdapter::initialize_tx_descriptors() diff --git a/Kernel/Net/EtherType.h b/Kernel/Net/EtherType.h index 42edc16427..ae845d5bf5 100644 --- a/Kernel/Net/EtherType.h +++ b/Kernel/Net/EtherType.h @@ -3,8 +3,7 @@ #include struct EtherType { - enum : word - { + enum : word { ARP = 0x0806, IPv4 = 0x0800, }; diff --git a/Kernel/Net/ICMP.h b/Kernel/Net/ICMP.h index 2433626a64..40bb691181 100644 --- a/Kernel/Net/ICMP.h +++ b/Kernel/Net/ICMP.h @@ -4,8 +4,7 @@ #include struct ICMPType { - enum - { + enum { EchoReply = 0, EchoRequest = 8, }; diff --git a/Kernel/Net/IPv4.h b/Kernel/Net/IPv4.h index 0c858d94d0..3463bf3cee 100644 --- a/Kernel/Net/IPv4.h +++ b/Kernel/Net/IPv4.h @@ -5,8 +5,7 @@ #include #include -enum class IPv4Protocol : word -{ +enum class IPv4Protocol : word { ICMP = 1, TCP = 6, UDP = 17, diff --git a/Kernel/Net/IPv4Socket.cpp b/Kernel/Net/IPv4Socket.cpp index 681674ba61..0b205b191a 100644 --- a/Kernel/Net/IPv4Socket.cpp +++ b/Kernel/Net/IPv4Socket.cpp @@ -1,17 +1,17 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include #include -#include #define IPV4_SOCKET_DEBUG @@ -89,7 +89,7 @@ KResult IPv4Socket::bind(const sockaddr* address, socklen_t address_size) return protocol_bind(); } -KResult IPv4Socket::connect(FileDescriptor& descriptor, const sockaddr* address, socklen_t address_size, ShouldBlock should_block) +KResult IPv4Socket::connect(FileDescription& description, const sockaddr* address, socklen_t address_size, ShouldBlock should_block) { ASSERT(!m_bound); if (address_size != sizeof(sockaddr_in)) @@ -101,39 +101,39 @@ KResult IPv4Socket::connect(FileDescriptor& descriptor, const sockaddr* address, m_peer_address = IPv4Address((const byte*)&ia.sin_addr.s_addr); m_peer_port = ntohs(ia.sin_port); - return protocol_connect(descriptor, should_block); + return protocol_connect(description, should_block); } -void IPv4Socket::attach(FileDescriptor&) +void IPv4Socket::attach(FileDescription&) { ++m_attached_fds; } -void IPv4Socket::detach(FileDescriptor&) +void IPv4Socket::detach(FileDescription&) { --m_attached_fds; } -bool IPv4Socket::can_read(FileDescriptor& descriptor) const +bool IPv4Socket::can_read(FileDescription& description) const { - if (descriptor.socket_role() == SocketRole::Listener) + if (description.socket_role() == SocketRole::Listener) return can_accept(); if (protocol_is_disconnected()) return true; return m_can_read; } -ssize_t IPv4Socket::read(FileDescriptor& descriptor, byte* buffer, ssize_t size) +ssize_t IPv4Socket::read(FileDescription& description, byte* buffer, ssize_t size) { - return recvfrom(descriptor, buffer, size, 0, nullptr, 0); + return recvfrom(description, buffer, size, 0, nullptr, 0); } -ssize_t IPv4Socket::write(FileDescriptor& descriptor, const byte* data, ssize_t size) +ssize_t IPv4Socket::write(FileDescription& description, const byte* data, ssize_t size) { - return sendto(descriptor, data, size, 0, nullptr, 0); + return sendto(description, data, size, 0, nullptr, 0); } -bool IPv4Socket::can_write(FileDescriptor&) const +bool IPv4Socket::can_write(FileDescription&) const { return is_connected(); } @@ -149,7 +149,7 @@ int IPv4Socket::allocate_local_port_if_needed() return port; } -ssize_t IPv4Socket::sendto(FileDescriptor&, const void* data, size_t data_length, int flags, const sockaddr* addr, socklen_t addr_length) +ssize_t IPv4Socket::sendto(FileDescription&, const void* data, size_t data_length, int flags, const sockaddr* addr, socklen_t addr_length) { (void)flags; if (addr && addr_length != sizeof(sockaddr_in)) @@ -184,7 +184,7 @@ ssize_t IPv4Socket::sendto(FileDescriptor&, const void* data, size_t data_length return protocol_send(data, data_length); } -ssize_t IPv4Socket::recvfrom(FileDescriptor& descriptor, void* buffer, size_t buffer_length, int flags, sockaddr* addr, socklen_t* addr_length) +ssize_t IPv4Socket::recvfrom(FileDescription& description, void* buffer, size_t buffer_length, int flags, sockaddr* addr, socklen_t* addr_length) { (void)flags; if (addr_length && *addr_length < sizeof(sockaddr_in)) @@ -212,7 +212,7 @@ ssize_t IPv4Socket::recvfrom(FileDescriptor& descriptor, void* buffer, size_t bu } load_receive_deadline(); - current->block(Thread::BlockedReceive, descriptor); + current->block(Thread::BlockedReceive, description); LOCKER(lock()); if (!m_can_read) { diff --git a/Kernel/Net/IPv4Socket.h b/Kernel/Net/IPv4Socket.h index 4f18d63113..dea6b5c171 100644 --- a/Kernel/Net/IPv4Socket.h +++ b/Kernel/Net/IPv4Socket.h @@ -21,17 +21,17 @@ public: static Lockable>& all_sockets(); virtual KResult bind(const sockaddr*, socklen_t) override; - virtual KResult connect(FileDescriptor&, const sockaddr*, socklen_t, ShouldBlock = ShouldBlock::Yes) override; + virtual KResult connect(FileDescription&, const sockaddr*, socklen_t, ShouldBlock = ShouldBlock::Yes) override; virtual bool get_local_address(sockaddr*, socklen_t*) override; virtual bool get_peer_address(sockaddr*, socklen_t*) override; - virtual void attach(FileDescriptor&) override; - virtual void detach(FileDescriptor&) override; - virtual bool can_read(FileDescriptor&) const override; - virtual ssize_t read(FileDescriptor&, byte*, ssize_t) override; - virtual ssize_t write(FileDescriptor&, const byte*, ssize_t) override; - virtual bool can_write(FileDescriptor&) const override; - virtual ssize_t sendto(FileDescriptor&, const void*, size_t, int, const sockaddr*, socklen_t) override; - virtual ssize_t recvfrom(FileDescriptor&, void*, size_t, int flags, sockaddr*, socklen_t*) override; + virtual void attach(FileDescription&) override; + virtual void detach(FileDescription&) override; + virtual bool can_read(FileDescription&) const override; + virtual ssize_t read(FileDescription&, byte*, ssize_t) override; + virtual ssize_t write(FileDescription&, const byte*, ssize_t) override; + virtual bool can_write(FileDescription&) const override; + virtual ssize_t sendto(FileDescription&, const void*, size_t, int, const sockaddr*, socklen_t) override; + virtual ssize_t recvfrom(FileDescription&, void*, size_t, int flags, sockaddr*, socklen_t*) override; void did_receive(const IPv4Address& peer_address, word peer_port, ByteBuffer&&); @@ -52,7 +52,7 @@ protected: virtual KResult protocol_bind() { return KSuccess; } virtual int protocol_receive(const ByteBuffer&, void*, size_t, int, sockaddr*, socklen_t*) { return -ENOTIMPL; } virtual int protocol_send(const void*, int) { return -ENOTIMPL; } - virtual KResult protocol_connect(FileDescriptor&, ShouldBlock) { return KSuccess; } + virtual KResult protocol_connect(FileDescription&, ShouldBlock) { return KSuccess; } virtual int protocol_allocate_local_port() { return 0; } virtual bool protocol_is_disconnected() const { return false; } diff --git a/Kernel/Net/LocalSocket.cpp b/Kernel/Net/LocalSocket.cpp index 99457e2cc4..95fcc6b940 100644 --- a/Kernel/Net/LocalSocket.cpp +++ b/Kernel/Net/LocalSocket.cpp @@ -1,8 +1,8 @@ -#include -#include -#include -#include +#include #include +#include +#include +#include #include //#define DEBUG_LOCAL_SOCKET @@ -71,7 +71,7 @@ KResult LocalSocket::bind(const sockaddr* address, socklen_t address_size) return KSuccess; } -KResult LocalSocket::connect(FileDescriptor& descriptor, const sockaddr* address, socklen_t address_size, ShouldBlock) +KResult LocalSocket::connect(FileDescription& description, const sockaddr* address, socklen_t address_size, ShouldBlock) { ASSERT(!m_bound); if (address_size != sizeof(sockaddr_un)) @@ -87,10 +87,10 @@ KResult LocalSocket::connect(FileDescriptor& descriptor, const sockaddr* address kprintf("%s(%u) LocalSocket{%p} connect(%s)\n", current->process().name().characters(), current->pid(), this, safe_address); #endif - auto descriptor_or_error = VFS::the().open(safe_address, 0, 0, current->process().current_directory()); - if (descriptor_or_error.is_error()) + auto description_or_error = VFS::the().open(safe_address, 0, 0, current->process().current_directory()); + if (description_or_error.is_error()) return KResult(-ECONNREFUSED); - m_file = move(descriptor_or_error.value()); + m_file = move(description_or_error.value()); ASSERT(m_file->inode()); if (!m_file->inode()->socket()) @@ -103,12 +103,12 @@ KResult LocalSocket::connect(FileDescriptor& descriptor, const sockaddr* address if (result.is_error()) return result; - return current->wait_for_connect(descriptor); + return current->wait_for_connect(description); } -void LocalSocket::attach(FileDescriptor& descriptor) +void LocalSocket::attach(FileDescription& description) { - switch (descriptor.socket_role()) { + switch (description.socket_role()) { case SocketRole::Accepted: ++m_accepted_fds_open; break; @@ -123,9 +123,9 @@ void LocalSocket::attach(FileDescriptor& descriptor) } } -void LocalSocket::detach(FileDescriptor& descriptor) +void LocalSocket::detach(FileDescription& description) { - switch (descriptor.socket_role()) { + switch (description.socket_role()) { case SocketRole::Accepted: ASSERT(m_accepted_fds_open); --m_accepted_fds_open; @@ -143,30 +143,30 @@ void LocalSocket::detach(FileDescriptor& descriptor) } } -bool LocalSocket::can_read(FileDescriptor& descriptor) const +bool LocalSocket::can_read(FileDescription& description) const { - auto role = descriptor.socket_role(); + auto role = description.socket_role(); if (role == SocketRole::Listener) return can_accept(); if (role == SocketRole::Accepted) - return !has_attached_peer(descriptor) || !m_for_server.is_empty(); + return !has_attached_peer(description) || !m_for_server.is_empty(); if (role == SocketRole::Connected) - return !has_attached_peer(descriptor) || !m_for_client.is_empty(); + return !has_attached_peer(description) || !m_for_client.is_empty(); ASSERT_NOT_REACHED(); } -ssize_t LocalSocket::read(FileDescriptor& descriptor, byte* buffer, ssize_t size) +ssize_t LocalSocket::read(FileDescription& description, byte* buffer, ssize_t size) { - auto role = descriptor.socket_role(); + auto role = description.socket_role(); if (role == SocketRole::Accepted) { - if (!descriptor.is_blocking()) { + if (!description.is_blocking()) { if (m_for_server.is_empty()) return -EAGAIN; } return m_for_server.read(buffer, size); } if (role == SocketRole::Connected) { - if (!descriptor.is_blocking()) { + if (!description.is_blocking()) { if (m_for_client.is_empty()) return -EAGAIN; } @@ -175,41 +175,41 @@ ssize_t LocalSocket::read(FileDescriptor& descriptor, byte* buffer, ssize_t size ASSERT_NOT_REACHED(); } -bool LocalSocket::has_attached_peer(const FileDescriptor& descriptor) const +bool LocalSocket::has_attached_peer(const FileDescription& description) const { - if (descriptor.socket_role() == SocketRole::Accepted) + if (description.socket_role() == SocketRole::Accepted) return m_connected_fds_open || m_connecting_fds_open; - if (descriptor.socket_role() == SocketRole::Connected) + if (description.socket_role() == SocketRole::Connected) return m_accepted_fds_open; ASSERT_NOT_REACHED(); } -ssize_t LocalSocket::write(FileDescriptor& descriptor, const byte* data, ssize_t size) +ssize_t LocalSocket::write(FileDescription& description, const byte* data, ssize_t size) { - if (!has_attached_peer(descriptor)) + if (!has_attached_peer(description)) return -EPIPE; - if (descriptor.socket_role() == SocketRole::Accepted) + if (description.socket_role() == SocketRole::Accepted) return m_for_client.write(data, size); - if (descriptor.socket_role() == SocketRole::Connected) + if (description.socket_role() == SocketRole::Connected) return m_for_server.write(data, size); ASSERT_NOT_REACHED(); } -bool LocalSocket::can_write(FileDescriptor& descriptor) const +bool LocalSocket::can_write(FileDescription& description) const { - if (descriptor.socket_role() == SocketRole::Accepted) - return !has_attached_peer(descriptor) || m_for_client.bytes_in_write_buffer() < 16384; - if (descriptor.socket_role() == SocketRole::Connected) - return !has_attached_peer(descriptor) || m_for_server.bytes_in_write_buffer() < 16384; + if (description.socket_role() == SocketRole::Accepted) + return !has_attached_peer(description) || m_for_client.bytes_in_write_buffer() < 16384; + if (description.socket_role() == SocketRole::Connected) + return !has_attached_peer(description) || m_for_server.bytes_in_write_buffer() < 16384; ASSERT_NOT_REACHED(); } -ssize_t LocalSocket::sendto(FileDescriptor& descriptor, const void* data, size_t data_size, int, const sockaddr*, socklen_t) +ssize_t LocalSocket::sendto(FileDescription& description, const void* data, size_t data_size, int, const sockaddr*, socklen_t) { - return write(descriptor, (const byte*)data, data_size); + return write(description, (const byte*)data, data_size); } -ssize_t LocalSocket::recvfrom(FileDescriptor& descriptor, void* buffer, size_t buffer_size, int, sockaddr*, socklen_t*) +ssize_t LocalSocket::recvfrom(FileDescription& description, void* buffer, size_t buffer_size, int, sockaddr*, socklen_t*) { - return read(descriptor, (byte*)buffer, buffer_size); + return read(description, (byte*)buffer, buffer_size); } diff --git a/Kernel/Net/LocalSocket.h b/Kernel/Net/LocalSocket.h index 3328fd4eba..f1ac23719b 100644 --- a/Kernel/Net/LocalSocket.h +++ b/Kernel/Net/LocalSocket.h @@ -3,7 +3,7 @@ #include #include -class FileDescriptor; +class FileDescription; class LocalSocket final : public Socket { public: @@ -11,24 +11,24 @@ public: virtual ~LocalSocket() override; virtual KResult bind(const sockaddr*, socklen_t) override; - virtual KResult connect(FileDescriptor&, const sockaddr*, socklen_t, ShouldBlock = ShouldBlock::Yes) override; + virtual KResult connect(FileDescription&, const sockaddr*, socklen_t, ShouldBlock = ShouldBlock::Yes) override; virtual bool get_local_address(sockaddr*, socklen_t*) override; virtual bool get_peer_address(sockaddr*, socklen_t*) override; - virtual void attach(FileDescriptor&) override; - virtual void detach(FileDescriptor&) override; - virtual bool can_read(FileDescriptor&) const override; - virtual ssize_t read(FileDescriptor&, byte*, ssize_t) override; - virtual ssize_t write(FileDescriptor&, const byte*, ssize_t) override; - virtual bool can_write(FileDescriptor&) const override; - virtual ssize_t sendto(FileDescriptor&, const void*, size_t, int, const sockaddr*, socklen_t) override; - virtual ssize_t recvfrom(FileDescriptor&, void*, size_t, int flags, sockaddr*, socklen_t*) override; + virtual void attach(FileDescription&) override; + virtual void detach(FileDescription&) override; + virtual bool can_read(FileDescription&) const override; + virtual ssize_t read(FileDescription&, byte*, ssize_t) override; + virtual ssize_t write(FileDescription&, const byte*, ssize_t) override; + virtual bool can_write(FileDescription&) const override; + virtual ssize_t sendto(FileDescription&, const void*, size_t, int, const sockaddr*, socklen_t) override; + virtual ssize_t recvfrom(FileDescription&, void*, size_t, int flags, sockaddr*, socklen_t*) override; private: explicit LocalSocket(int type); virtual bool is_local() const override { return true; } - bool has_attached_peer(const FileDescriptor&) const; + bool has_attached_peer(const FileDescription&) const; - RetainPtr m_file; + RetainPtr m_file; bool m_bound { false }; int m_accepted_fds_open { 0 }; diff --git a/Kernel/Net/NetworkAdapter.cpp b/Kernel/Net/NetworkAdapter.cpp index a1e5e31c9d..139c5d0ba8 100644 --- a/Kernel/Net/NetworkAdapter.cpp +++ b/Kernel/Net/NetworkAdapter.cpp @@ -1,10 +1,10 @@ -#include -#include -#include -#include -#include #include #include +#include +#include +#include +#include +#include static Lockable>& all_adapters() { @@ -81,7 +81,7 @@ ByteBuffer NetworkAdapter::dequeue_packet() { InterruptDisabler disabler; if (m_packet_queue.is_empty()) - return { }; + return {}; return m_packet_queue.take_first(); } diff --git a/Kernel/Net/NetworkTask.cpp b/Kernel/Net/NetworkTask.cpp index 55e1357e55..6113d241dd 100644 --- a/Kernel/Net/NetworkTask.cpp +++ b/Kernel/Net/NetworkTask.cpp @@ -1,18 +1,17 @@ -#include -#include +#include #include +#include +#include +#include #include -#include -#include #include #include -#include -#include #include +#include +#include +#include +#include #include -#include -#include - //#define ETHERNET_DEBUG #define IPV4_DEBUG @@ -36,7 +35,7 @@ Lockable>& arp_table() class CombinedPacketQueueAlarm : public Alarm { public: - CombinedPacketQueueAlarm() { } + CombinedPacketQueueAlarm() {} virtual bool is_ringing() const override { @@ -61,7 +60,7 @@ void NetworkTask_main() if (adapter) adapter->set_ipv4_address(IPv4Address(192, 168, 5, 2)); - auto dequeue_packet = [&] () -> ByteBuffer { + auto dequeue_packet = [&]() -> ByteBuffer { auto packet = LoopbackAdapter::the().dequeue_packet(); if (!packet.is_null()) { dbgprintf("Receive loopback packet (%d bytes)\n", packet.size()); @@ -69,7 +68,7 @@ void NetworkTask_main() } if (adapter && adapter->has_queued_packets()) return adapter->dequeue_packet(); - return { }; + return {}; }; CombinedPacketQueueAlarm queue_alarm; @@ -91,8 +90,7 @@ void NetworkTask_main() eth.source().to_string().characters(), eth.destination().to_string().characters(), eth.ether_type(), - packet.size() - ); + packet.size()); #endif switch (eth.ether_type()) { @@ -117,15 +115,13 @@ void handle_arp(const EthernetFrameHeader& eth, int frame_size) if (packet.hardware_type() != 1 || packet.hardware_address_length() != sizeof(MACAddress)) { kprintf("handle_arp: Hardware type not ethernet (%w, len=%u)\n", packet.hardware_type(), - packet.hardware_address_length() - ); + packet.hardware_address_length()); return; } if (packet.protocol_type() != EtherType::IPv4 || packet.protocol_address_length() != sizeof(IPv4Address)) { kprintf("handle_arp: Protocol type not IPv4 (%w, len=%u)\n", packet.hardware_type(), - packet.protocol_address_length() - ); + packet.protocol_address_length()); return; } @@ -135,8 +131,7 @@ void handle_arp(const EthernetFrameHeader& eth, int frame_size) packet.sender_hardware_address().to_string().characters(), packet.sender_protocol_address().to_string().characters(), packet.target_hardware_address().to_string().characters(), - packet.target_protocol_address().to_string().characters() - ); + packet.target_protocol_address().to_string().characters()); #endif if (packet.operation() == ARPOperation::Request) { @@ -144,7 +139,7 @@ void handle_arp(const EthernetFrameHeader& eth, int frame_size) if (auto* adapter = NetworkAdapter::from_ipv4_address(packet.target_protocol_address())) { // We do! kprintf("handle_arp: Responding to ARP request for my IPv4 address (%s)\n", - adapter->ipv4_address().to_string().characters()); + adapter->ipv4_address().to_string().characters()); ARPPacket response; response.set_operation(ARPOperation::Response); response.set_target_hardware_address(packet.sender_hardware_address()); @@ -183,8 +178,7 @@ void handle_ipv4(const EthernetFrameHeader& eth, int frame_size) #ifdef IPV4_DEBUG kprintf("handle_ipv4: source=%s, target=%s\n", packet.source().to_string().characters(), - packet.destination().to_string().characters() - ); + packet.destination().to_string().characters()); #endif switch ((IPv4Protocol)packet.protocol()) { @@ -210,8 +204,7 @@ void handle_icmp(const EthernetFrameHeader& eth, int frame_size) ipv4_packet.source().to_string().characters(), ipv4_packet.destination().to_string().characters(), icmp_header.type(), - icmp_header.code() - ); + icmp_header.code()); #endif { @@ -231,10 +224,9 @@ void handle_icmp(const EthernetFrameHeader& eth, int frame_size) if (icmp_header.type() == ICMPType::EchoRequest) { auto& request = reinterpret_cast(icmp_header); kprintf("handle_icmp: EchoRequest from %s: id=%u, seq=%u\n", - ipv4_packet.source().to_string().characters(), - (word)request.identifier, - (word)request.sequence_number - ); + ipv4_packet.source().to_string().characters(), + (word)request.identifier, + (word)request.sequence_number); size_t icmp_packet_size = ipv4_packet.payload_size(); auto buffer = ByteBuffer::create_zeroed(icmp_packet_size); auto& response = *(ICMPEchoPacket*)buffer.pointer(); @@ -267,8 +259,7 @@ void handle_udp(const EthernetFrameHeader& eth, int frame_size) udp_packet.source_port(), ipv4_packet.destination().to_string().characters(), udp_packet.destination_port(), - udp_packet.length() - ); + udp_packet.length()); #endif auto socket = UDPSocket::from_port(udp_packet.destination_port()); @@ -308,8 +299,7 @@ void handle_tcp(const EthernetFrameHeader& eth, int frame_size) tcp_packet.has_syn() ? "SYN" : "", tcp_packet.has_ack() ? "ACK" : "", tcp_packet.window_size(), - payload_size - ); + payload_size); #endif auto socket = TCPSocket::from_port(tcp_packet.destination_port()); @@ -350,12 +340,11 @@ void handle_tcp(const EthernetFrameHeader& eth, int frame_size) socket->set_ack_number(tcp_packet.sequence_number() + payload_size); kprintf("Got packet with ack_no=%u, seq_no=%u, payload_size=%u, acking it with new ack_no=%u, seq_no=%u\n", - tcp_packet.ack_number(), - tcp_packet.sequence_number(), - payload_size, - socket->ack_number(), - socket->sequence_number() - ); + tcp_packet.ack_number(), + tcp_packet.sequence_number(), + payload_size, + socket->ack_number(), + socket->sequence_number()); socket->send_tcp_packet(TCPFlags::ACK); if (payload_size != 0) diff --git a/Kernel/Net/Routing.cpp b/Kernel/Net/Routing.cpp index 9561fd9249..b2c3d8a782 100644 --- a/Kernel/Net/Routing.cpp +++ b/Kernel/Net/Routing.cpp @@ -1,5 +1,5 @@ -#include #include +#include NetworkAdapter* adapter_for_route_to(const IPv4Address& ipv4_address) { diff --git a/Kernel/Net/Socket.cpp b/Kernel/Net/Socket.cpp index f7892ce759..6164cbe783 100644 --- a/Kernel/Net/Socket.cpp +++ b/Kernel/Net/Socket.cpp @@ -1,9 +1,9 @@ -#include -#include -#include +#include #include -#include +#include +#include #include +#include #include KResultOr> Socket::create(int domain, int type, int protocol) @@ -142,7 +142,7 @@ static const char* to_string(SocketRole role) } } -String Socket::absolute_path(FileDescriptor& descriptor) const +String Socket::absolute_path(const FileDescription& description) const { - return String::format("socket:%x (role: %s)", this, to_string(descriptor.socket_role())); + return String::format("socket:%x (role: %s)", this, to_string(description.socket_role())); } diff --git a/Kernel/Net/Socket.h b/Kernel/Net/Socket.h index 45693a2ffc..ff129f8e54 100644 --- a/Kernel/Net/Socket.h +++ b/Kernel/Net/Socket.h @@ -9,21 +9,19 @@ #include #include -enum class SocketRole : byte -{ +enum class SocketRole : byte { None, Listener, Accepted, Connected, Connecting }; -enum class ShouldBlock -{ +enum class ShouldBlock { No = 0, Yes = 1 }; -class FileDescriptor; +class FileDescription; class Socket : public File { public: @@ -40,15 +38,15 @@ public: KResult listen(int backlog); virtual KResult bind(const sockaddr*, socklen_t) = 0; - virtual KResult connect(FileDescriptor&, const sockaddr*, socklen_t, ShouldBlock) = 0; + virtual KResult connect(FileDescription&, const sockaddr*, socklen_t, ShouldBlock) = 0; virtual bool get_local_address(sockaddr*, socklen_t*) = 0; virtual bool get_peer_address(sockaddr*, socklen_t*) = 0; virtual bool is_local() const { return false; } virtual bool is_ipv4() const { return false; } - virtual void attach(FileDescriptor&) = 0; - virtual void detach(FileDescriptor&) = 0; - virtual ssize_t sendto(FileDescriptor&, const void*, size_t, int flags, const sockaddr*, socklen_t) = 0; - virtual ssize_t recvfrom(FileDescriptor&, void*, size_t, int flags, sockaddr*, socklen_t*) = 0; + virtual void attach(FileDescription&) = 0; + virtual void detach(FileDescription&) = 0; + virtual ssize_t sendto(FileDescription&, const void*, size_t, int flags, const sockaddr*, socklen_t) = 0; + virtual ssize_t recvfrom(FileDescription&, void*, size_t, int flags, sockaddr*, socklen_t*) = 0; KResult setsockopt(int level, int option, const void*, socklen_t); KResult getsockopt(int level, int option, void*, socklen_t*); @@ -62,7 +60,7 @@ public: Lock& lock() { return m_lock; } - virtual String absolute_path(FileDescriptor&) const override; + virtual String absolute_path(const FileDescription&) const override; protected: Socket(int domain, int type, int protocol); diff --git a/Kernel/Net/TCP.h b/Kernel/Net/TCP.h index 8138ed3d52..611c451105 100644 --- a/Kernel/Net/TCP.h +++ b/Kernel/Net/TCP.h @@ -3,8 +3,7 @@ #include struct TCPFlags { - enum : word - { + enum : word { FIN = 0x01, SYN = 0x02, RST = 0x04, diff --git a/Kernel/Net/TCPSocket.cpp b/Kernel/Net/TCPSocket.cpp index acb3c47569..c38f3c3cd6 100644 --- a/Kernel/Net/TCPSocket.cpp +++ b/Kernel/Net/TCPSocket.cpp @@ -1,9 +1,9 @@ -#include -#include +#include #include #include +#include +#include #include -#include Lockable>& TCPSocket::sockets_by_port() { @@ -20,14 +20,13 @@ TCPSocketHandle TCPSocket::from_port(word port) LOCKER(sockets_by_port().lock()); auto it = sockets_by_port().resource().find(port); if (it == sockets_by_port().resource().end()) - return { }; + return {}; socket = (*it).value; ASSERT(socket); } return { move(socket) }; } - TCPSocket::TCPSocket(int protocol) : IPv4Socket(SOCK_STREAM, protocol) { @@ -102,14 +101,14 @@ void TCPSocket::send_tcp_packet(word flags, const void* payload, int payload_siz tcp_packet.has_syn() ? "SYN" : "", tcp_packet.has_ack() ? "ACK" : "", tcp_packet.sequence_number(), - tcp_packet.ack_number() - ); + tcp_packet.ack_number()); adapter->send_ipv4(MACAddress(), peer_address(), IPv4Protocol::TCP, move(buffer)); } NetworkOrdered TCPSocket::compute_tcp_checksum(const IPv4Address& source, const IPv4Address& destination, const TCPPacket& packet, word payload_size) { - struct [[gnu::packed]] PseudoHeader { + struct [[gnu::packed]] PseudoHeader + { IPv4Address source; IPv4Address destination; byte zero; @@ -148,7 +147,7 @@ NetworkOrdered TCPSocket::compute_tcp_checksum(const IPv4Address& source, return ~(checksum & 0xffff); } -KResult TCPSocket::protocol_connect(FileDescriptor& descriptor, ShouldBlock should_block) +KResult TCPSocket::protocol_connect(FileDescription& description, ShouldBlock should_block) { auto* adapter = adapter_for_route_to(peer_address()); if (!adapter) @@ -163,7 +162,7 @@ KResult TCPSocket::protocol_connect(FileDescriptor& descriptor, ShouldBlock shou m_state = State::Connecting; if (should_block == ShouldBlock::Yes) { - current->block(Thread::BlockedConnect, descriptor); + current->block(Thread::BlockedConnect, description); ASSERT(is_connected()); return KSuccess; } diff --git a/Kernel/Net/TCPSocket.h b/Kernel/Net/TCPSocket.h index 35856d7ae8..a54d04417d 100644 --- a/Kernel/Net/TCPSocket.h +++ b/Kernel/Net/TCPSocket.h @@ -7,8 +7,7 @@ public: static Retained create(int protocol); virtual ~TCPSocket() override; - enum class State - { + enum class State { Disconnected, Connecting, Connected, @@ -36,7 +35,7 @@ private: virtual int protocol_receive(const ByteBuffer&, void* buffer, size_t buffer_size, int flags, sockaddr* addr, socklen_t* addr_length) override; virtual int protocol_send(const void*, int) override; - virtual KResult protocol_connect(FileDescriptor&, ShouldBlock) override; + virtual KResult protocol_connect(FileDescription&, ShouldBlock) override; virtual int protocol_allocate_local_port() override; virtual bool protocol_is_disconnected() const override; virtual KResult protocol_bind() override; diff --git a/Kernel/Net/UDPSocket.cpp b/Kernel/Net/UDPSocket.cpp index ee3597e386..6ae66cfb09 100644 --- a/Kernel/Net/UDPSocket.cpp +++ b/Kernel/Net/UDPSocket.cpp @@ -1,9 +1,9 @@ -#include -#include -#include -#include #include +#include #include +#include +#include +#include Lockable>& UDPSocket::sockets_by_port() { @@ -20,14 +20,13 @@ UDPSocketHandle UDPSocket::from_port(word port) LOCKER(sockets_by_port().lock()); auto it = sockets_by_port().resource().find(port); if (it == sockets_by_port().resource().end()) - return { }; + return {}; socket = (*it).value; ASSERT(socket); } return { move(socket) }; } - UDPSocket::UDPSocket(int protocol) : IPv4Socket(SOCK_DGRAM, protocol) { diff --git a/Kernel/Net/UDPSocket.h b/Kernel/Net/UDPSocket.h index a76eaa7fe7..80ef09b7bf 100644 --- a/Kernel/Net/UDPSocket.h +++ b/Kernel/Net/UDPSocket.h @@ -18,7 +18,7 @@ private: virtual int protocol_receive(const ByteBuffer&, void* buffer, size_t buffer_size, int flags, sockaddr* addr, socklen_t* addr_length) override; virtual int protocol_send(const void*, int) override; - virtual KResult protocol_connect(FileDescriptor&, ShouldBlock) override { return KSuccess; } + virtual KResult protocol_connect(FileDescription&, ShouldBlock) override { return KSuccess; } virtual int protocol_allocate_local_port() override; virtual KResult protocol_bind() override; }; diff --git a/Kernel/PCI.cpp b/Kernel/PCI.cpp index 2b22cf75c6..2b7e66aab7 100644 --- a/Kernel/PCI.cpp +++ b/Kernel/PCI.cpp @@ -1,32 +1,32 @@ -#include #include +#include -#define PCI_VENDOR_ID 0x00 // word -#define PCI_DEVICE_ID 0x02 // word -#define PCI_COMMAND 0x04 // word -#define PCI_STATUS 0x06 // word -#define PCI_REVISION_ID 0x08 // byte -#define PCI_PROG_IF 0x09 // byte -#define PCI_SUBCLASS 0x0a // byte -#define PCI_CLASS 0x0b // byte -#define PCI_CACHE_LINE_SIZE 0x0c // byte -#define PCI_LATENCY_TIMER 0x0d // byte -#define PCI_HEADER_TYPE 0x0e // byte -#define PCI_BIST 0x0f // byte -#define PCI_BAR0 0x10 // dword -#define PCI_BAR1 0x14 // dword -#define PCI_BAR2 0x18 // dword -#define PCI_BAR3 0x1C // dword -#define PCI_BAR4 0x20 // dword -#define PCI_BAR5 0x24 // dword -#define PCI_INTERRUPT_LINE 0x3C // byte -#define PCI_SECONDARY_BUS 0x19 // byte -#define PCI_HEADER_TYPE_DEVICE 0 -#define PCI_HEADER_TYPE_BRIDGE 1 -#define PCI_TYPE_BRIDGE 0x0604 -#define PCI_ADDRESS_PORT 0xCF8 -#define PCI_VALUE_PORT 0xCFC -#define PCI_NONE 0xFFFF +#define PCI_VENDOR_ID 0x00 // word +#define PCI_DEVICE_ID 0x02 // word +#define PCI_COMMAND 0x04 // word +#define PCI_STATUS 0x06 // word +#define PCI_REVISION_ID 0x08 // byte +#define PCI_PROG_IF 0x09 // byte +#define PCI_SUBCLASS 0x0a // byte +#define PCI_CLASS 0x0b // byte +#define PCI_CACHE_LINE_SIZE 0x0c // byte +#define PCI_LATENCY_TIMER 0x0d // byte +#define PCI_HEADER_TYPE 0x0e // byte +#define PCI_BIST 0x0f // byte +#define PCI_BAR0 0x10 // dword +#define PCI_BAR1 0x14 // dword +#define PCI_BAR2 0x18 // dword +#define PCI_BAR3 0x1C // dword +#define PCI_BAR4 0x20 // dword +#define PCI_BAR5 0x24 // dword +#define PCI_INTERRUPT_LINE 0x3C // byte +#define PCI_SECONDARY_BUS 0x19 // byte +#define PCI_HEADER_TYPE_DEVICE 0 +#define PCI_HEADER_TYPE_BRIDGE 1 +#define PCI_TYPE_BRIDGE 0x0604 +#define PCI_ADDRESS_PORT 0xCF8 +#define PCI_VALUE_PORT 0xCFC +#define PCI_NONE 0xFFFF namespace PCI { diff --git a/Kernel/PIC.cpp b/Kernel/PIC.cpp index 31094849c7..3ce2a0bfe5 100644 --- a/Kernel/PIC.cpp +++ b/Kernel/PIC.cpp @@ -1,17 +1,17 @@ -#include -#include "i386.h" -#include "IO.h" #include "PIC.h" #include "Assertions.h" +#include "IO.h" +#include +#include // The slave 8259 is connected to the master's IRQ2 line. // This is really only to enhance clarity. -#define SLAVE_INDEX 2 +#define SLAVE_INDEX 2 -#define PIC0_CTL 0x20 -#define PIC0_CMD 0x21 -#define PIC1_CTL 0xA0 -#define PIC1_CMD 0xA1 +#define PIC0_CTL 0x20 +#define PIC0_CMD 0x21 +#define PIC1_CTL 0xA0 +#define PIC1_CMD 0xA1 #ifdef DEBUG_PIC static bool initialized; @@ -74,7 +74,7 @@ void initialize() /* ICW4 (set x86 mode) */ IO::out8(PIC0_CMD, 0x01); - IO::out8(PIC1_CMD, 0x01 ); + IO::out8(PIC1_CMD, 0x01); // Mask -- start out with all IRQs disabled. IO::out8(PIC0_CMD, 0xff); diff --git a/Kernel/PhysicalAddress.h b/Kernel/PhysicalAddress.h index 6fd869dca6..8457006aba 100644 --- a/Kernel/PhysicalAddress.h +++ b/Kernel/PhysicalAddress.h @@ -21,6 +21,11 @@ public: dword page_base() const { return m_address & 0xfffff000; } bool operator==(const PhysicalAddress& other) const { return m_address == other.m_address; } + bool operator!=(const PhysicalAddress& other) const { return m_address != other.m_address; } + bool operator>(const PhysicalAddress& other) const { return m_address > other.m_address; } + bool operator>=(const PhysicalAddress& other) const { return m_address >= other.m_address; } + bool operator<(const PhysicalAddress& other) const { return m_address < other.m_address; } + bool operator<=(const PhysicalAddress& other) const { return m_address <= other.m_address; } private: dword m_address { 0 }; diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 4a03e5e674..f388e42251 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -1,30 +1,31 @@ -#include -#include "Process.h" -#include "kmalloc.h" -#include "StdLib.h" -#include "i386.h" -#include -#include -#include -#include -#include "i8253.h" -#include "RTC.h" -#include -#include -#include -#include "Syscall.h" -#include "Scheduler.h" -#include -#include "KSyms.h" -#include -#include -#include #include +#include +#include #include #include -#include -#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include //#define DEBUG_POLL_SELECT //#define DEBUG_IO @@ -71,13 +72,13 @@ bool Process::in_group(gid_t gid) const return m_gids.contains(gid); } -Range Process::allocate_range(LinearAddress laddr, size_t size) +Range Process::allocate_range(VirtualAddress vaddr, size_t size) { - laddr.mask(PAGE_MASK); + vaddr.mask(PAGE_MASK); size = PAGE_ROUND_UP(size); - if (laddr.is_null()) + if (vaddr.is_null()) return page_directory().range_allocator().allocate_anywhere(size); - return page_directory().range_allocator().allocate_specific(laddr, size); + return page_directory().range_allocator().allocate_specific(vaddr, size); } static unsigned prot_to_region_access_flags(int prot) @@ -92,9 +93,9 @@ static unsigned prot_to_region_access_flags(int prot) return access; } -Region* Process::allocate_region(LinearAddress laddr, size_t size, String&& name, int prot, bool commit) +Region* Process::allocate_region(VirtualAddress vaddr, size_t size, const String& name, int prot, bool commit) { - auto range = allocate_range(laddr, size); + auto range = allocate_range(vaddr, size); if (!range.is_valid()) return nullptr; m_regions.append(adopt(*new Region(range, move(name), prot_to_region_access_flags(prot)))); @@ -104,23 +105,23 @@ Region* Process::allocate_region(LinearAddress laddr, size_t size, String&& name return m_regions.last().ptr(); } -Region* Process::allocate_file_backed_region(LinearAddress laddr, size_t size, RetainPtr&& inode, String&& name, int prot) +Region* Process::allocate_file_backed_region(VirtualAddress vaddr, size_t size, RetainPtr&& inode, const String& name, int prot) { - auto range = allocate_range(laddr, size); + auto range = allocate_range(vaddr, size); if (!range.is_valid()) return nullptr; - m_regions.append(adopt(*new Region(range, move(inode), move(name), prot_to_region_access_flags(prot)))); + m_regions.append(adopt(*new Region(range, move(inode), name, prot_to_region_access_flags(prot)))); MM.map_region(*this, *m_regions.last()); return m_regions.last().ptr(); } -Region* Process::allocate_region_with_vmo(LinearAddress laddr, size_t size, Retained&& vmo, size_t offset_in_vmo, String&& name, int prot) +Region* Process::allocate_region_with_vmo(VirtualAddress vaddr, size_t size, Retained&& vmo, size_t offset_in_vmo, const String& name, int prot) { - auto range = allocate_range(laddr, size); + auto range = allocate_range(vaddr, size); if (!range.is_valid()) return nullptr; offset_in_vmo &= PAGE_MASK; - m_regions.append(adopt(*new Region(range, move(vmo), offset_in_vmo, move(name), prot_to_region_access_flags(prot)))); + m_regions.append(adopt(*new Region(range, move(vmo), offset_in_vmo, name, prot_to_region_access_flags(prot)))); MM.map_region(*this, *m_regions.last()); return m_regions.last().ptr(); } @@ -130,7 +131,7 @@ bool Process::deallocate_region(Region& region) InterruptDisabler disabler; for (int i = 0; i < m_regions.size(); ++i) { if (m_regions[i] == ®ion) { - page_directory().range_allocator().deallocate({ region.laddr(), region.size() }); + page_directory().range_allocator().deallocate({ region.vaddr(), region.size() }); MM.unmap_region(region); m_regions.remove(i); return true; @@ -139,11 +140,11 @@ bool Process::deallocate_region(Region& region) return false; } -Region* Process::region_from_range(LinearAddress laddr, size_t size) +Region* Process::region_from_range(VirtualAddress vaddr, size_t size) { size = PAGE_ROUND_UP(size); for (auto& region : m_regions) { - if (region->laddr() == laddr && region->size() == size) + if (region->vaddr() == vaddr && region->size() == size) return region.ptr(); } return nullptr; @@ -153,7 +154,7 @@ int Process::sys$set_mmap_name(void* addr, size_t size, const char* name) { if (!validate_read_str(name)) return -EFAULT; - auto* region = region_from_range(LinearAddress((dword)addr), size); + auto* region = region_from_range(VirtualAddress((dword)addr), size); if (!region) return -EINVAL; region->set_name(String(name)); @@ -178,21 +179,21 @@ void* Process::sys$mmap(const Syscall::SC_mmap_params* params) if ((dword)addr & ~PAGE_MASK) return (void*)-EINVAL; if (flags & MAP_ANONYMOUS) { - auto* region = allocate_region(LinearAddress((dword)addr), size, "mmap", prot, false); + auto* region = allocate_region(VirtualAddress((dword)addr), size, "mmap", prot, false); if (!region) return (void*)-ENOMEM; if (flags & MAP_SHARED) region->set_shared(true); if (name) region->set_name(name); - return region->laddr().as_ptr(); + return region->vaddr().as_ptr(); } if (offset & ~PAGE_MASK) return (void*)-EINVAL; - auto* descriptor = file_descriptor(fd); - if (!descriptor) + auto* description = file_description(fd); + if (!description) return (void*)-EBADF; - auto region_or_error = descriptor->mmap(*this, LinearAddress((dword)addr), offset, size, prot); + auto region_or_error = description->mmap(*this, VirtualAddress((dword)addr), offset, size, prot); if (region_or_error.is_error()) return (void*)(int)region_or_error.error(); auto region = region_or_error.value(); @@ -200,12 +201,12 @@ void* Process::sys$mmap(const Syscall::SC_mmap_params* params) region->set_shared(true); if (name) region->set_name(name); - return region->laddr().as_ptr(); + return region->vaddr().as_ptr(); } int Process::sys$munmap(void* addr, size_t size) { - auto* region = region_from_range(LinearAddress((dword)addr), size); + auto* region = region_from_range(VirtualAddress((dword)addr), size); if (!region) return -EINVAL; if (!deallocate_region(*region)) @@ -238,7 +239,7 @@ Process* Process::fork(RegisterDump& regs) for (auto& region : m_regions) { #ifdef FORK_DEBUG - dbgprintf("fork: cloning Region{%p} \"%s\" L%x\n", region.ptr(), region->name().characters(), region->laddr().get()); + dbgprintf("fork: cloning Region{%p} \"%s\" L%x\n", region.ptr(), region->name().characters(), region->vaddr().get()); #endif auto cloned_region = region->clone(); child->m_regions.append(move(cloned_region)); @@ -298,7 +299,7 @@ int Process::do_exec(String path, Vector arguments, Vector envir // FIXME(Thread): Kill any threads the moment we commit to the exec(). if (thread_count() != 1) { dbgprintf("Gonna die because I have many threads! These are the threads:\n"); - for_each_thread([] (Thread& thread) { + for_each_thread([](Thread& thread) { dbgprintf("Thread{%p}: TID=%d, PID=%d\n", &thread, thread.tid(), thread.pid()); return IterationDecision::Continue; }); @@ -306,16 +307,15 @@ int Process::do_exec(String path, Vector arguments, Vector envir ASSERT_NOT_REACHED(); } - auto parts = path.split('/'); if (parts.is_empty()) return -ENOENT; - auto result = VFS::the().open(path.view(), 0, 0, current_directory()); + auto result = VFS::the().open(path, 0, 0, current_directory()); if (result.is_error()) return result.error(); - auto descriptor = result.value(); - auto metadata = descriptor->metadata(); + auto description = result.value(); + auto metadata = description->metadata(); if (!metadata.may_execute(m_euid, m_gids)) return -EACCES; @@ -332,14 +332,9 @@ int Process::do_exec(String path, Vector arguments, Vector envir #endif ProcessPagingScope paging_scope(*this); - auto vmo = VMObject::create_file_backed(descriptor->inode()); -#if 0 - // FIXME: I would like to do this, but it would instantiate all the damn inodes. - vmo->set_name(descriptor->absolute_path()); -#else - vmo->set_name("ELF image"); -#endif - RetainPtr region = allocate_region_with_vmo(LinearAddress(), metadata.size, vmo.copy_ref(), 0, "executable", PROT_READ); + auto vmo = VMObject::create_file_backed(description->inode()); + vmo->set_name(description->absolute_path()); + RetainPtr region = allocate_region_with_vmo(VirtualAddress(), metadata.size, vmo.copy_ref(), 0, vmo->name(), PROT_READ); ASSERT(region); if (this != ¤t->process()) { @@ -352,8 +347,8 @@ int Process::do_exec(String path, Vector arguments, Vector envir // Okay, here comes the sleight of hand, pay close attention.. auto old_regions = move(m_regions); m_regions.append(*region); - loader = make(region->laddr().as_ptr()); - loader->map_section_hook = [&] (LinearAddress laddr, size_t size, size_t alignment, size_t offset_in_image, bool is_readable, bool is_writable, bool is_executable, const String& name) { + loader = make(region->vaddr().as_ptr()); + loader->map_section_hook = [&](VirtualAddress vaddr, size_t size, size_t alignment, size_t offset_in_image, bool is_readable, bool is_writable, bool is_executable, const String& name) { ASSERT(size); ASSERT(alignment == PAGE_SIZE); int prot = 0; @@ -363,10 +358,10 @@ int Process::do_exec(String path, Vector arguments, Vector envir prot |= PROT_WRITE; if (is_executable) prot |= PROT_EXEC; - (void) allocate_region_with_vmo(laddr, size, vmo.copy_ref(), offset_in_image, String(name), prot); - return laddr.as_ptr(); + (void)allocate_region_with_vmo(vaddr, size, vmo.copy_ref(), offset_in_image, String(name), prot); + return vaddr.as_ptr(); }; - loader->alloc_section_hook = [&] (LinearAddress laddr, size_t size, size_t alignment, bool is_readable, bool is_writable, const String& name) { + loader->alloc_section_hook = [&](VirtualAddress vaddr, size_t size, size_t alignment, bool is_readable, bool is_writable, const String& name) { ASSERT(size); ASSERT(alignment == PAGE_SIZE); int prot = 0; @@ -374,8 +369,8 @@ int Process::do_exec(String path, Vector arguments, Vector envir prot |= PROT_READ; if (is_writable) prot |= PROT_WRITE; - (void) allocate_region(laddr, size, String(name), prot); - return laddr.as_ptr(); + (void)allocate_region(vaddr, size, String(name), prot); + return vaddr.as_ptr(); }; bool success = loader->load(); if (!success || !loader->entry().get()) { @@ -393,7 +388,7 @@ int Process::do_exec(String path, Vector arguments, Vector envir } m_elf_loader = move(loader); - m_executable = descriptor->custody(); + m_executable = description->custody(); if (metadata.is_setuid()) m_euid = metadata.uid; @@ -408,9 +403,9 @@ int Process::do_exec(String path, Vector arguments, Vector envir for (int i = 0; i < m_fds.size(); ++i) { auto& daf = m_fds[i]; - if (daf.descriptor && daf.flags & FD_CLOEXEC) { - daf.descriptor->close(); - daf = { }; + if (daf.description && daf.flags & FD_CLOEXEC) { + daf.description->close(); + daf = {}; } } @@ -610,12 +605,12 @@ Process::Process(String&& name, uid_t uid, gid_t gid, pid_t ppid, RingLevel ring if (fork_parent) { m_fds.resize(fork_parent->m_fds.size()); for (int i = 0; i < fork_parent->m_fds.size(); ++i) { - if (!fork_parent->m_fds[i].descriptor) + if (!fork_parent->m_fds[i].description) continue; #ifdef FORK_DEBUG - dbgprintf("fork: cloning fd %u... (%p) istty? %u\n", i, fork_parent->m_fds[i].descriptor.ptr(), fork_parent->m_fds[i].descriptor->is_tty()); + dbgprintf("fork: cloning fd %u... (%p) istty? %u\n", i, fork_parent->m_fds[i].description.ptr(), fork_parent->m_fds[i].description->is_tty()); #endif - m_fds[i].descriptor = fork_parent->m_fds[i].descriptor->clone(); + m_fds[i].description = fork_parent->m_fds[i].description->clone(); m_fds[i].flags = fork_parent->m_fds[i].flags; } } else { @@ -640,7 +635,7 @@ Process::~Process() m_main_thread = nullptr; Vector my_threads; - for_each_thread([&my_threads] (auto& thread) { + for_each_thread([&my_threads](auto& thread) { my_threads.append(&thread); return IterationDecision::Continue; }); @@ -654,8 +649,8 @@ void Process::dump_regions() kprintf("BEGIN END SIZE NAME\n"); for (auto& region : m_regions) { kprintf("%x -- %x %x %s\n", - region->laddr().get(), - region->laddr().offset(region->size() - 1).get(), + region->vaddr().get(), + region->vaddr().offset(region->size() - 1).get(), region->size(), region->name().characters()); } @@ -682,8 +677,8 @@ void Process::create_signal_trampolines_if_needed() return; // FIXME: This should be a global trampoline shared by all processes, not one created per process! // FIXME: Remap as read-only after setup. - auto* region = allocate_region(LinearAddress(), PAGE_SIZE, "Signal trampolines", PROT_READ | PROT_WRITE | PROT_EXEC); - m_return_to_ring3_from_signal_trampoline = region->laddr(); + auto* region = allocate_region(VirtualAddress(), PAGE_SIZE, "Signal trampolines", PROT_READ | PROT_WRITE | PROT_EXEC); + m_return_to_ring3_from_signal_trampoline = region->vaddr(); byte* code_ptr = m_return_to_ring3_from_signal_trampoline.as_ptr(); *code_ptr++ = 0x58; // pop eax (Argument to signal handler (ignored here)) *code_ptr++ = 0x5a; // pop edx (Original signal mask to restore) @@ -703,7 +698,7 @@ void Process::create_signal_trampolines_if_needed() *code_ptr++ = 0x0f; // ud2 *code_ptr++ = 0x0b; - m_return_to_ring0_from_signal_trampoline = LinearAddress((dword)code_ptr); + m_return_to_ring0_from_signal_trampoline = VirtualAddress((dword)code_ptr); *code_ptr++ = 0x58; // pop eax (Argument to signal handler (ignored here)) *code_ptr++ = 0x5a; // pop edx (Original signal mask to restore) *code_ptr++ = 0xb8; // mov eax, @@ -769,21 +764,21 @@ Process* Process::from_pid(pid_t pid) return nullptr; } -FileDescriptor* Process::file_descriptor(int fd) +FileDescription* Process::file_description(int fd) { if (fd < 0) return nullptr; if (fd < m_fds.size()) - return m_fds[fd].descriptor.ptr(); + return m_fds[fd].description.ptr(); return nullptr; } -const FileDescriptor* Process::file_descriptor(int fd) const +const FileDescription* Process::file_description(int fd) const { if (fd < 0) return nullptr; if (fd < m_fds.size()) - return m_fds[fd].descriptor.ptr(); + return m_fds[fd].description.ptr(); return nullptr; } @@ -793,18 +788,18 @@ ssize_t Process::sys$get_dir_entries(int fd, void* buffer, ssize_t size) return -EINVAL; if (!validate_write(buffer, size)) return -EFAULT; - auto* descriptor = file_descriptor(fd); - if (!descriptor) + auto* description = file_description(fd); + if (!description) return -EBADF; - return descriptor->get_dir_entries((byte*)buffer, size); + return description->get_dir_entries((byte*)buffer, size); } int Process::sys$lseek(int fd, off_t offset, int whence) { - auto* descriptor = file_descriptor(fd); - if (!descriptor) + auto* description = file_description(fd); + if (!description) return -EBADF; - return descriptor->seek(offset, whence); + return description->seek(offset, whence); } int Process::sys$ttyname_r(int fd, char* buffer, ssize_t size) @@ -813,12 +808,12 @@ int Process::sys$ttyname_r(int fd, char* buffer, ssize_t size) return -EINVAL; if (!validate_write(buffer, size)) return -EFAULT; - auto* descriptor = file_descriptor(fd); - if (!descriptor) + auto* description = file_description(fd); + if (!description) return -EBADF; - if (!descriptor->is_tty()) + if (!description->is_tty()) return -ENOTTY; - auto tty_name = descriptor->tty()->tty_name(); + auto tty_name = description->tty()->tty_name(); if (size < tty_name.length() + 1) return -ERANGE; strcpy(buffer, tty_name.characters()); @@ -831,10 +826,10 @@ int Process::sys$ptsname_r(int fd, char* buffer, ssize_t size) return -EINVAL; if (!validate_write(buffer, size)) return -EFAULT; - auto* descriptor = file_descriptor(fd); - if (!descriptor) + auto* description = file_description(fd); + if (!description) return -EBADF; - auto* master_pty = descriptor->master_pty(); + auto* master_pty = description->master_pty(); if (!master_pty) return -ENOTTY; auto pts_name = master_pty->pts_name(); @@ -854,13 +849,13 @@ ssize_t Process::sys$writev(int fd, const struct iovec* iov, int iov_count) // FIXME: Return EINVAL if sum of iovecs is greater than INT_MAX - auto* descriptor = file_descriptor(fd); - if (!descriptor) + auto* description = file_description(fd); + if (!description) return -EBADF; int nwritten = 0; for (int i = 0; i < iov_count; ++i) { - int rc = do_write(*descriptor, (const byte*)iov[i].iov_base, iov[i].iov_len); + int rc = do_write(*description, (const byte*)iov[i].iov_base, iov[i].iov_len); if (rc < 0) { if (nwritten == 0) return rc; @@ -878,32 +873,32 @@ ssize_t Process::sys$writev(int fd, const struct iovec* iov, int iov_count) return nwritten; } -ssize_t Process::do_write(FileDescriptor& descriptor, const byte* data, int data_size) +ssize_t Process::do_write(FileDescription& description, const byte* data, int data_size) { ssize_t nwritten = 0; - if (!descriptor.is_blocking()) { - if (!descriptor.can_write()) + if (!description.is_blocking()) { + if (!description.can_write()) return -EAGAIN; } - if (descriptor.should_append()) { + if (description.should_append()) { #ifdef IO_DEBUG dbgprintf("seeking to end (O_APPEND)\n"); #endif - descriptor.seek(0, SEEK_END); + description.seek(0, SEEK_END); } while (nwritten < data_size) { #ifdef IO_DEBUG dbgprintf("while %u < %u\n", nwritten, size); #endif - if (!descriptor.can_write()) { + if (!description.can_write()) { #ifdef IO_DEBUG dbgprintf("block write on %d\n", fd); #endif - current->block(Thread::State::BlockedWrite, descriptor); + current->block(Thread::State::BlockedWrite, description); } - ssize_t rc = descriptor.write(data + nwritten, data_size - nwritten); + ssize_t rc = description.write(data + nwritten, data_size - nwritten); #ifdef IO_DEBUG dbgprintf(" -> write returned %d\n", rc); #endif @@ -935,10 +930,10 @@ ssize_t Process::sys$write(int fd, const byte* data, ssize_t size) #ifdef DEBUG_IO dbgprintf("%s(%u): sys$write(%d, %p, %u)\n", name().characters(), pid(), fd, data, size); #endif - auto* descriptor = file_descriptor(fd); - if (!descriptor) + auto* description = file_description(fd); + if (!description) return -EBADF; - auto nwritten = do_write(*descriptor, data, size); + auto nwritten = do_write(*description, data, size); if (current->has_unmasked_pending_signals()) { current->block(Thread::State::BlockedSignal); if (nwritten == 0) @@ -958,26 +953,26 @@ ssize_t Process::sys$read(int fd, byte* buffer, ssize_t size) #ifdef DEBUG_IO dbgprintf("%s(%u) sys$read(%d, %p, %u)\n", name().characters(), pid(), fd, buffer, size); #endif - auto* descriptor = file_descriptor(fd); - if (!descriptor) + auto* description = file_description(fd); + if (!description) return -EBADF; - if (descriptor->is_blocking()) { - if (!descriptor->can_read()) { - current->block(Thread::State::BlockedRead, *descriptor); + if (description->is_blocking()) { + if (!description->can_read()) { + current->block(Thread::State::BlockedRead, *description); if (current->m_was_interrupted_while_blocked) return -EINTR; } } - return descriptor->read(buffer, size); + return description->read(buffer, size); } int Process::sys$close(int fd) { - auto* descriptor = file_descriptor(fd); - if (!descriptor) + auto* description = file_description(fd); + if (!description) return -EBADF; - int rc = descriptor->close(); - m_fds[fd] = { }; + int rc = description->close(); + m_fds[fd] = {}; return rc; } @@ -1010,13 +1005,13 @@ int Process::sys$access(const char* pathname, int mode) int Process::sys$fcntl(int fd, int cmd, dword arg) { - (void) cmd; - (void) arg; + (void)cmd; + (void)arg; dbgprintf("sys$fcntl: fd=%d, cmd=%d, arg=%u\n", fd, cmd, arg); - auto* descriptor = file_descriptor(fd); - if (!descriptor) + auto* description = file_description(fd); + if (!description) return -EBADF; - // NOTE: The FD flags are not shared between FileDescriptor objects. + // NOTE: The FD flags are not shared between FileDescription objects. // This means that dup() doesn't copy the FD_CLOEXEC flag! switch (cmd) { case F_DUPFD: { @@ -1026,7 +1021,7 @@ int Process::sys$fcntl(int fd, int cmd, dword arg) int new_fd = alloc_fd(arg_fd); if (new_fd < 0) return new_fd; - m_fds[new_fd].set(*descriptor); + m_fds[new_fd].set(*description); break; } case F_GETFD: @@ -1035,9 +1030,9 @@ int Process::sys$fcntl(int fd, int cmd, dword arg) m_fds[fd].flags = arg; break; case F_GETFL: - return descriptor->file_flags(); + return description->file_flags(); case F_SETFL: - descriptor->set_file_flags(arg); + description->set_file_flags(arg); break; default: ASSERT_NOT_REACHED(); @@ -1049,10 +1044,10 @@ int Process::sys$fstat(int fd, stat* statbuf) { if (!validate_write_typed(statbuf)) return -EFAULT; - auto* descriptor = file_descriptor(fd); - if (!descriptor) + auto* description = file_description(fd); + if (!description) return -EBADF; - return descriptor->fstat(*statbuf); + return description->fstat(*statbuf); } int Process::sys$lstat(const char* path, stat* statbuf) @@ -1081,12 +1076,12 @@ int Process::sys$readlink(const char* path, char* buffer, ssize_t size) auto result = VFS::the().open(path, O_RDONLY | O_NOFOLLOW_NOERROR, 0, current_directory()); if (result.is_error()) return result.error(); - auto descriptor = result.value(); + auto description = result.value(); - if (!descriptor->metadata().is_symlink()) + if (!description->metadata().is_symlink()) return -EINVAL; - auto contents = descriptor->read_entire_file(); + auto contents = description->read_entire_file(); if (!contents) return -EIO; // FIXME: Get a more detailed error from VFS. @@ -1123,8 +1118,8 @@ int Process::sys$getcwd(char* buffer, ssize_t size) int Process::number_of_open_file_descriptors() const { int count = 0; - for (auto& descriptor : m_fds) { - if (descriptor) + for (auto& description : m_fds) { + if (description) ++count; } return count; @@ -1143,12 +1138,12 @@ int Process::sys$open(const char* path, int options, mode_t mode) auto result = VFS::the().open(path, options, mode & ~umask(), current_directory()); if (result.is_error()) return result.error(); - auto descriptor = result.value(); - if (options & O_DIRECTORY && !descriptor->is_directory()) + auto description = result.value(); + if (options & O_DIRECTORY && !description->is_directory()) return -ENOTDIR; // FIXME: This should be handled by VFS::open. - descriptor->set_file_flags(options); + description->set_file_flags(options); dword fd_flags = (options & O_CLOEXEC) ? FD_CLOEXEC : 0; - m_fds[fd].set(move(descriptor), fd_flags); + m_fds[fd].set(move(description), fd_flags); return fd; } @@ -1187,7 +1182,7 @@ int Process::sys$killpg(int pgrp, int signum) { if (signum < 1 || signum >= 32) return -EINVAL; - (void) pgrp; + (void)pgrp; ASSERT_NOT_REACHED(); } @@ -1211,8 +1206,16 @@ int Process::sys$setgid(gid_t gid) unsigned Process::sys$alarm(unsigned seconds) { - (void) seconds; - ASSERT_NOT_REACHED(); + unsigned previous_alarm_remaining = 0; + if (m_alarm_deadline && m_alarm_deadline > g_uptime) { + previous_alarm_remaining = (m_alarm_deadline - g_uptime) / TICKS_PER_SECOND; + } + if (!seconds) { + m_alarm_deadline = 0; + return previous_alarm_remaining; + } + m_alarm_deadline = g_uptime + seconds * TICKS_PER_SECOND; + return previous_alarm_remaining; } int Process::sys$uname(utsname* buf) @@ -1230,10 +1233,10 @@ int Process::sys$uname(utsname* buf) int Process::sys$isatty(int fd) { - auto* descriptor = file_descriptor(fd); - if (!descriptor) + auto* description = file_description(fd); + if (!description) return -EBADF; - if (!descriptor->is_tty()) + if (!description->is_tty()) return -ENOTTY; return 1; } @@ -1298,10 +1301,17 @@ int Process::sys$sleep(unsigned seconds) return 0; } -void kgettimeofday(timeval& tv) +timeval kgettimeofday() { + timeval tv; tv.tv_sec = RTC::boot_time() + PIT::seconds_since_boot(); tv.tv_usec = PIT::ticks_this_second() * 1000; + return tv; +} + +void kgettimeofday(timeval& tv) +{ + tv = kgettimeofday(); } int Process::sys$gettimeofday(timeval* tv) @@ -1376,7 +1386,7 @@ pid_t Process::sys$waitpid(pid_t waitee, int* wstatus, int options) { dbgprintf("sys$waitpid(%d, %p, %d)\n", waitee, wstatus, options); // FIXME: Respect options - (void) options; + (void)options; if (wstatus) if (!validate_write_typed(wstatus)) return -EFAULT; @@ -1394,7 +1404,7 @@ pid_t Process::sys$waitpid(pid_t waitee, int* wstatus, int options) if (waitee == -1) { pid_t reaped_pid = 0; InterruptDisabler disabler; - for_each_child([&reaped_pid, &exit_status] (Process& process) { + for_each_child([&reaped_pid, &exit_status](Process& process) { if (process.is_dead()) { reaped_pid = process.pid(); exit_status = reap(process); @@ -1431,44 +1441,22 @@ pid_t Process::sys$waitpid(pid_t waitee, int* wstatus, int options) return current->m_waitee_pid; } - enum class KernelMemoryCheckResult { NotInsideKernelMemory, AccessGranted, AccessDenied }; -// FIXME: Nothing about this is really super... -// This structure is only present at offset 28 in the main multiboot info struct -// if bit 5 of offset 0 (flags) is set. We're just assuming that the flag is set. -// -// Also, there's almost certainly a better way to get that information here than -// a global set by boot.S -// -// Also I'm not 100% sure any of this is correct... - -struct mb_elf { - uint32_t num; - uint32_t size; - uint32_t addr; - uint32_t shndx; -}; - -extern "C" { -void* multiboot_ptr; -} - -static KernelMemoryCheckResult check_kernel_memory_access(LinearAddress laddr, bool is_write) +static KernelMemoryCheckResult check_kernel_memory_access(VirtualAddress vaddr, bool is_write) { - // FIXME: It would be better to have a proper structure for this... - auto* sections = (const mb_elf*)((const byte*)multiboot_ptr + 28); + auto& sections = multiboot_info_ptr->u.elf_sec; - auto* kernel_program_headers = (Elf32_Phdr*)(sections->addr); - for (unsigned i = 0; i < sections->num; ++i) { + auto* kernel_program_headers = (Elf32_Phdr*)(sections.addr); + for (unsigned i = 0; i < sections.num; ++i) { auto& segment = kernel_program_headers[i]; if (segment.p_type != PT_LOAD || !segment.p_vaddr || !segment.p_memsz) continue; - if (laddr.get() < segment.p_vaddr || laddr.get() > (segment.p_vaddr + segment.p_memsz)) + if (vaddr.get() < segment.p_vaddr || vaddr.get() > (segment.p_vaddr + segment.p_memsz)) continue; if (is_write && !(kernel_program_headers[i].p_flags & PF_W)) return KernelMemoryCheckResult::AccessDenied; @@ -1479,20 +1467,20 @@ static KernelMemoryCheckResult check_kernel_memory_access(LinearAddress laddr, b return KernelMemoryCheckResult::NotInsideKernelMemory; } -bool Process::validate_read_from_kernel(LinearAddress laddr) const +bool Process::validate_read_from_kernel(VirtualAddress vaddr) const { - if (laddr.is_null()) + if (vaddr.is_null()) return false; // We check extra carefully here since the first 4MB of the address space is identity-mapped. // This code allows access outside of the known used address ranges to get caught. - auto kmc_result = check_kernel_memory_access(laddr, false); + auto kmc_result = check_kernel_memory_access(vaddr, false); if (kmc_result == KernelMemoryCheckResult::AccessGranted) return true; if (kmc_result == KernelMemoryCheckResult::AccessDenied) return false; - if (is_kmalloc_address(laddr.as_ptr())) + if (is_kmalloc_address(vaddr.as_ptr())) return true; - return validate_read(laddr.as_ptr(), 1); + return validate_read(vaddr.as_ptr(), 1); } bool Process::validate_read_str(const char* str) @@ -1505,8 +1493,8 @@ bool Process::validate_read_str(const char* str) bool Process::validate_read(const void* address, ssize_t size) const { ASSERT(size >= 0); - LinearAddress first_address((dword)address); - LinearAddress last_address = first_address.offset(size - 1); + VirtualAddress first_address((dword)address); + VirtualAddress last_address = first_address.offset(size - 1); if (is_ring0()) { auto kmc_result = check_kernel_memory_access(first_address, false); if (kmc_result == KernelMemoryCheckResult::AccessGranted) @@ -1529,8 +1517,8 @@ bool Process::validate_read(const void* address, ssize_t size) const bool Process::validate_write(void* address, ssize_t size) const { ASSERT(size >= 0); - LinearAddress first_address((dword)address); - LinearAddress last_address = first_address.offset(size - 1); + VirtualAddress first_address((dword)address); + VirtualAddress last_address = first_address.offset(size - 1); if (is_ring0()) { if (is_kmalloc_address(address)) return true; @@ -1566,7 +1554,7 @@ pid_t Process::sys$setsid() { InterruptDisabler disabler; bool found_process_with_same_pgid_as_my_pid = false; - Process::for_each_in_pgrp(pid(), [&] (auto&) { + Process::for_each_in_pgrp(pid(), [&](auto&) { found_process_with_same_pgid_as_my_pid = true; return false; }); @@ -1625,10 +1613,10 @@ int Process::sys$setpgid(pid_t specified_pid, pid_t specified_pgid) int Process::sys$ioctl(int fd, unsigned request, unsigned arg) { - auto* descriptor = file_descriptor(fd); - if (!descriptor) + auto* description = file_description(fd); + if (!description) return -EBADF; - return descriptor->file().ioctl(*descriptor, request, arg); + return description->file().ioctl(*description, request, arg); } int Process::sys$getdtablesize() @@ -1638,24 +1626,24 @@ int Process::sys$getdtablesize() int Process::sys$dup(int old_fd) { - auto* descriptor = file_descriptor(old_fd); - if (!descriptor) + auto* description = file_description(old_fd); + if (!description) return -EBADF; int new_fd = alloc_fd(0); if (new_fd < 0) return new_fd; - m_fds[new_fd].set(*descriptor); + m_fds[new_fd].set(*description); return new_fd; } int Process::sys$dup2(int old_fd, int new_fd) { - auto* descriptor = file_descriptor(old_fd); - if (!descriptor) + auto* description = file_description(old_fd); + if (!description) return -EBADF; if (new_fd < 0 || new_fd >= m_max_open_file_descriptors) return -EINVAL; - m_fds[new_fd].set(*descriptor); + m_fds[new_fd].set(*description); return new_fd; } @@ -1709,7 +1697,7 @@ int Process::sys$sigaction(int signum, const sigaction* act, sigaction* old_act) old_act->sa_sigaction = (decltype(old_act->sa_sigaction))action.handler_or_sigaction.get(); } action.flags = act->sa_flags; - action.handler_or_sigaction = LinearAddress((dword)act->sa_sigaction); + action.handler_or_sigaction = VirtualAddress((dword)act->sa_sigaction); return 0; } @@ -1769,106 +1757,71 @@ clock_t Process::sys$times(tms* times) int Process::sys$select(const Syscall::SC_select_params* params) { + // FIXME: Return -EINTR if a signal is caught. + // FIXME: Return -EINVAL if timeout is invalid. if (!validate_read_typed(params)) return -EFAULT; - if (params->writefds && !validate_read_typed(params->writefds)) + if (params->writefds && !validate_write_typed(params->writefds)) return -EFAULT; - if (params->readfds && !validate_read_typed(params->readfds)) + if (params->readfds && !validate_write_typed(params->readfds)) return -EFAULT; - if (params->exceptfds && !validate_read_typed(params->exceptfds)) + if (params->exceptfds && !validate_write_typed(params->exceptfds)) return -EFAULT; if (params->timeout && !validate_read_typed(params->timeout)) return -EFAULT; - int nfds = params->nfds; - fd_set* writefds = params->writefds; - fd_set* readfds = params->readfds; - fd_set* exceptfds = params->exceptfds; - auto* timeout = params->timeout; + if (params->nfds < 0) + return -EINVAL; - // FIXME: Implement exceptfds support. - (void)exceptfds; - - if (timeout && (timeout->tv_sec || timeout->tv_usec)) { - struct timeval now; - kgettimeofday(now); - AK::timeval_add(&now, timeout, ¤t->m_select_timeout); + if (params->timeout && (params->timeout->tv_sec || params->timeout->tv_usec)) { + timeval_add(kgettimeofday(), *params->timeout, current->m_select_timeout); current->m_select_has_timeout = true; } else { current->m_select_has_timeout = false; } - if (nfds < 0) - return -EINVAL; - - // FIXME: Return -EINTR if a signal is caught. - // FIXME: Return -EINVAL if timeout is invalid. - - auto transfer_fds = [this, nfds] (fd_set* set, auto& vector) -> int { + auto transfer_fds = [&](auto* fds, auto& vector) -> int { vector.clear_with_capacity(); - if (!set) + if (!fds) return 0; - auto bitmap = Bitmap::wrap((byte*)set, FD_SETSIZE); - for (int i = 0; i < nfds; ++i) { - if (bitmap.get(i)) { - if (!file_descriptor(i)) + for (int fd = 0; fd < params->nfds; ++fd) { + if (FD_ISSET(fd, fds)) { + if (!file_description(fd)) return -EBADF; - vector.append(i); + vector.append(fd); } } return 0; }; - - int error = 0; - error = transfer_fds(writefds, current->m_select_write_fds); - if (error) + if (int error = transfer_fds(params->writefds, current->m_select_write_fds)) return error; - error = transfer_fds(readfds, current->m_select_read_fds); - if (error) + if (int error = transfer_fds(params->readfds, current->m_select_read_fds)) return error; - error = transfer_fds(exceptfds, current->m_select_exceptional_fds); - if (error) + if (int error = transfer_fds(params->exceptfds, current->m_select_exceptional_fds)) return error; #if defined(DEBUG_IO) || defined(DEBUG_POLL_SELECT) - dbgprintf("%s<%u> selecting on (read:%u, write:%u), timeout=%p\n", name().characters(), pid(), current->m_select_read_fds.size(), current->m_select_write_fds.size(), timeout); + dbgprintf("%s<%u> selecting on (read:%u, write:%u), timeout=%p\n", name().characters(), pid(), current->m_select_read_fds.size(), current->m_select_write_fds.size(), params->timeout); #endif - if (!timeout || current->m_select_has_timeout) + if (!params->timeout || current->m_select_has_timeout) current->block(Thread::State::BlockedSelect); - int markedfds = 0; - - if (readfds) { - memset(readfds, 0, sizeof(fd_set)); - auto bitmap = Bitmap::wrap((byte*)readfds, FD_SETSIZE); - for (int fd : current->m_select_read_fds) { - auto* descriptor = file_descriptor(fd); - if (!descriptor) - continue; - if (descriptor->can_read()) { - bitmap.set(fd, true); - ++markedfds; + int marked_fd_count = 0; + auto mark_fds = [&](auto* fds, auto& vector, auto should_mark) { + if (!fds) + return; + FD_ZERO(fds); + for (int fd : vector) { + if (auto* description = file_description(fd); description && should_mark(*description)) { + FD_SET(fd, fds); + ++marked_fd_count; } } - } - - if (writefds) { - memset(writefds, 0, sizeof(fd_set)); - auto bitmap = Bitmap::wrap((byte*)writefds, FD_SETSIZE); - for (int fd : current->m_select_write_fds) { - auto* descriptor = file_descriptor(fd); - if (!descriptor) - continue; - if (descriptor->can_write()) { - bitmap.set(fd, true); - ++markedfds; - } - } - } - - // FIXME: Check for exceptional conditions. - - return markedfds; + }; + mark_fds(params->readfds, current->m_select_read_fds, [](auto& description) { return description.can_read(); }); + mark_fds(params->writefds, current->m_select_write_fds, [](auto& description) { return description.can_write(); }); + // FIXME: We should also mark params->exceptfds as appropriate. + return marked_fd_count; } int Process::sys$poll(pollfd* fds, int nfds, int timeout) @@ -1894,10 +1847,7 @@ int Process::sys$poll(pollfd* fds, int nfds, int timeout) timeout -= 1000; } tvtimeout.tv_usec = timeout * 1000; - - struct timeval now; - kgettimeofday(now); - AK::timeval_add(&now, &tvtimeout, ¤t->m_select_timeout); + timeval_add(kgettimeofday(), tvtimeout, current->m_select_timeout); current->m_select_has_timeout = true; } else { current->m_select_has_timeout = false; @@ -1914,15 +1864,15 @@ int Process::sys$poll(pollfd* fds, int nfds, int timeout) int fds_with_revents = 0; for (int i = 0; i < nfds; ++i) { - auto* descriptor = file_descriptor(fds[i].fd); - if (!descriptor) { + auto* description = file_description(fds[i].fd); + if (!description) { fds[i].revents = POLLNVAL; continue; } fds[i].revents = 0; - if (fds[i].events & POLLIN && descriptor->can_read()) + if (fds[i].events & POLLIN && description->can_read()) fds[i].revents |= POLLIN; - if (fds[i].events & POLLOUT && descriptor->can_write()) + if (fds[i].events & POLLOUT && description->can_write()) fds[i].revents |= POLLOUT; if (fds[i].revents) @@ -1990,10 +1940,18 @@ int Process::sys$chmod(const char* pathname, mode_t mode) int Process::sys$fchmod(int fd, mode_t mode) { - auto* descriptor = file_descriptor(fd); - if (!descriptor) + auto* description = file_description(fd); + if (!description) return -EBADF; - return descriptor->fchmod(mode); + return description->fchmod(mode); +} + +int Process::sys$fchown(int fd, uid_t uid, gid_t gid) +{ + auto* description = file_description(fd); + if (!description) + return -EBADF; + return description->chown(uid, gid); } int Process::sys$chown(const char* pathname, uid_t uid, gid_t gid) @@ -2038,7 +1996,7 @@ void Process::die() { InterruptDisabler disabler; - for_each_thread([] (Thread& thread) { + for_each_thread([](Thread& thread) { if (thread.state() != Thread::State::Dead) thread.set_state(Thread::State::Dying); return IterationDecision::Continue; @@ -2089,13 +2047,13 @@ int Process::sys$socket(int domain, int type, int protocol) auto result = Socket::create(domain, type, protocol); if (result.is_error()) return result.error(); - auto descriptor = FileDescriptor::create(*result.value()); + auto description = FileDescription::create(*result.value()); unsigned flags = 0; if (type & SOCK_CLOEXEC) flags |= FD_CLOEXEC; if (type & SOCK_NONBLOCK) - descriptor->set_blocking(false); - m_fds[fd].set(move(descriptor), flags); + description->set_blocking(false); + m_fds[fd].set(move(description), flags); return fd; } @@ -2103,27 +2061,27 @@ int Process::sys$bind(int sockfd, const sockaddr* address, socklen_t address_len { if (!validate_read(address, address_length)) return -EFAULT; - auto* descriptor = file_descriptor(sockfd); - if (!descriptor) + auto* description = file_description(sockfd); + if (!description) return -EBADF; - if (!descriptor->is_socket()) + if (!description->is_socket()) return -ENOTSOCK; - auto& socket = *descriptor->socket(); + auto& socket = *description->socket(); return socket.bind(address, address_length); } int Process::sys$listen(int sockfd, int backlog) { - auto* descriptor = file_descriptor(sockfd); - if (!descriptor) + auto* description = file_description(sockfd); + if (!description) return -EBADF; - if (!descriptor->is_socket()) + if (!description->is_socket()) return -ENOTSOCK; - auto& socket = *descriptor->socket(); + auto& socket = *description->socket(); auto result = socket.listen(backlog); if (result.is_error()) return result; - descriptor->set_socket_role(SocketRole::Listener); + description->set_socket_role(SocketRole::Listener); return 0; } @@ -2136,25 +2094,25 @@ int Process::sys$accept(int accepting_socket_fd, sockaddr* address, socklen_t* a int accepted_socket_fd = alloc_fd(); if (accepted_socket_fd < 0) return accepted_socket_fd; - auto* accepting_socket_descriptor = file_descriptor(accepting_socket_fd); - if (!accepting_socket_descriptor) + auto* accepting_socket_description = file_description(accepting_socket_fd); + if (!accepting_socket_description) return -EBADF; - if (!accepting_socket_descriptor->is_socket()) + if (!accepting_socket_description->is_socket()) return -ENOTSOCK; - auto& socket = *accepting_socket_descriptor->socket(); + auto& socket = *accepting_socket_description->socket(); if (!socket.can_accept()) { - ASSERT(!accepting_socket_descriptor->is_blocking()); + ASSERT(!accepting_socket_description->is_blocking()); return -EAGAIN; } auto accepted_socket = socket.accept(); ASSERT(accepted_socket); bool success = accepted_socket->get_local_address(address, address_size); ASSERT(success); - auto accepted_socket_descriptor = FileDescriptor::create(move(accepted_socket), SocketRole::Accepted); + auto accepted_socket_description = FileDescription::create(move(accepted_socket), SocketRole::Accepted); // NOTE: The accepted socket inherits fd flags from the accepting socket. // I'm not sure if this matches other systems but it makes sense to me. - accepted_socket_descriptor->set_blocking(accepting_socket_descriptor->is_blocking()); - m_fds[accepted_socket_fd].set(move(accepted_socket_descriptor), m_fds[accepting_socket_fd].flags); + accepted_socket_description->set_blocking(accepting_socket_description->is_blocking()); + m_fds[accepted_socket_fd].set(move(accepted_socket_description), m_fds[accepting_socket_fd].flags); return accepted_socket_fd; } @@ -2165,21 +2123,21 @@ int Process::sys$connect(int sockfd, const sockaddr* address, socklen_t address_ int fd = alloc_fd(); if (fd < 0) return fd; - auto* descriptor = file_descriptor(sockfd); - if (!descriptor) + auto* description = file_description(sockfd); + if (!description) return -EBADF; - if (!descriptor->is_socket()) + if (!description->is_socket()) return -ENOTSOCK; - if (descriptor->socket_role() == SocketRole::Connected) + if (description->socket_role() == SocketRole::Connected) return -EISCONN; - auto& socket = *descriptor->socket(); - descriptor->set_socket_role(SocketRole::Connecting); - auto result = socket.connect(*descriptor, address, address_size, descriptor->is_blocking() ? ShouldBlock::Yes : ShouldBlock::No); + auto& socket = *description->socket(); + description->set_socket_role(SocketRole::Connecting); + auto result = socket.connect(*description, address, address_size, description->is_blocking() ? ShouldBlock::Yes : ShouldBlock::No); if (result.is_error()) { - descriptor->set_socket_role(SocketRole::None); + description->set_socket_role(SocketRole::None); return result; } - descriptor->set_socket_role(SocketRole::Connected); + description->set_socket_role(SocketRole::Connected); return 0; } @@ -2199,14 +2157,14 @@ ssize_t Process::sys$sendto(const Syscall::SC_sendto_params* params) return -EFAULT; if (addr && !validate_read(addr, addr_length)) return -EFAULT; - auto* descriptor = file_descriptor(sockfd); - if (!descriptor) + auto* description = file_description(sockfd); + if (!description) return -EBADF; - if (!descriptor->is_socket()) + if (!description->is_socket()) return -ENOTSOCK; - auto& socket = *descriptor->socket(); + auto& socket = *description->socket(); kprintf("sendto %p (%u), flags=%u, addr: %p (%u)\n", data, data_length, flags, addr, addr_length); - return socket.sendto(*descriptor, data, data_length, flags, addr, addr_length); + return socket.sendto(*description, data, data_length, flags, addr, addr_length); } ssize_t Process::sys$recvfrom(const Syscall::SC_recvfrom_params* params) @@ -2229,22 +2187,22 @@ ssize_t Process::sys$recvfrom(const Syscall::SC_recvfrom_params* params) if (!validate_write(addr, *addr_length)) return -EFAULT; } else if (addr) { - return -EINVAL; + return -EINVAL; } - auto* descriptor = file_descriptor(sockfd); - if (!descriptor) + auto* description = file_description(sockfd); + if (!description) return -EBADF; - if (!descriptor->is_socket()) + if (!description->is_socket()) return -ENOTSOCK; - auto& socket = *descriptor->socket(); + auto& socket = *description->socket(); - bool original_blocking = descriptor->is_blocking(); + bool original_blocking = description->is_blocking(); if (flags & MSG_DONTWAIT) - descriptor->set_blocking(false); + description->set_blocking(false); - auto nrecv = socket.recvfrom(*descriptor, buffer, buffer_length, flags, addr, addr_length); + auto nrecv = socket.recvfrom(*description, buffer, buffer_length, flags, addr, addr_length); if (flags & MSG_DONTWAIT) - descriptor->set_blocking(original_blocking); + description->set_blocking(original_blocking); return nrecv; } @@ -2260,14 +2218,14 @@ int Process::sys$getsockname(int sockfd, sockaddr* addr, socklen_t* addrlen) if (!validate_write(addr, *addrlen)) return -EFAULT; - auto* descriptor = file_descriptor(sockfd); - if (!descriptor) + auto* description = file_description(sockfd); + if (!description) return -EBADF; - if (!descriptor->is_socket()) + if (!description->is_socket()) return -ENOTSOCK; - auto& socket = *descriptor->socket(); + auto& socket = *description->socket(); if (!socket.get_local_address(addr, addrlen)) return -EINVAL; // FIXME: Should this be another error? I'm not sure. @@ -2285,14 +2243,14 @@ int Process::sys$getpeername(int sockfd, sockaddr* addr, socklen_t* addrlen) if (!validate_write(addr, *addrlen)) return -EFAULT; - auto* descriptor = file_descriptor(sockfd); - if (!descriptor) + auto* description = file_description(sockfd); + if (!description) return -EBADF; - if (!descriptor->is_socket()) + if (!description->is_socket()) return -ENOTSOCK; - auto& socket = *descriptor->socket(); + auto& socket = *description->socket(); if (!socket.is_connected()) return -ENOTCONN; @@ -2360,12 +2318,12 @@ int Process::sys$getsockopt(const Syscall::SC_getsockopt_params* params) return -EFAULT; if (!validate_write(value, *value_size)) return -EFAULT; - auto* descriptor = file_descriptor(sockfd); - if (!descriptor) + auto* description = file_description(sockfd); + if (!description) return -EBADF; - if (!descriptor->is_socket()) + if (!description->is_socket()) return -ENOTSOCK; - auto& socket = *descriptor->socket(); + auto& socket = *description->socket(); return socket.getsockopt(level, option, value, value_size); } @@ -2381,12 +2339,12 @@ int Process::sys$setsockopt(const Syscall::SC_setsockopt_params* params) if (!validate_read(value, value_size)) return -EFAULT; - auto* descriptor = file_descriptor(sockfd); - if (!descriptor) + auto* description = file_description(sockfd); + if (!description) return -EBADF; - if (!descriptor->is_socket()) + if (!description->is_socket()) return -ENOTSOCK; - auto& socket = *descriptor->socket(); + auto& socket = *description->socket(); return socket.setsockopt(level, option, value, value_size); } @@ -2404,17 +2362,17 @@ struct SharedBuffer { if (m_pid1 == process.pid()) { ++m_pid1_retain_count; if (!m_pid1_region) { - m_pid1_region = process.allocate_region_with_vmo(LinearAddress(), size(), m_vmo.copy_ref(), 0, "SharedBuffer", PROT_READ | (m_pid1_writable ? PROT_WRITE : 0)); + m_pid1_region = process.allocate_region_with_vmo(VirtualAddress(), size(), m_vmo.copy_ref(), 0, "SharedBuffer", PROT_READ | (m_pid1_writable ? PROT_WRITE : 0)); m_pid1_region->set_shared(true); } - return m_pid1_region->laddr().as_ptr(); + return m_pid1_region->vaddr().as_ptr(); } else if (m_pid2 == process.pid()) { ++m_pid2_retain_count; if (!m_pid2_region) { - m_pid2_region = process.allocate_region_with_vmo(LinearAddress(), size(), m_vmo.copy_ref(), 0, "SharedBuffer", PROT_READ | (m_pid2_writable ? PROT_WRITE : 0)); + m_pid2_region = process.allocate_region_with_vmo(VirtualAddress(), size(), m_vmo.copy_ref(), 0, "SharedBuffer", PROT_READ | (m_pid2_writable ? PROT_WRITE : 0)); m_pid2_region->set_shared(true); } - return m_pid2_region->laddr().as_ptr(); + return m_pid2_region->vaddr().as_ptr(); } return nullptr; } @@ -2540,11 +2498,11 @@ int Process::sys$create_shared_buffer(pid_t peer_pid, int size, void** buffer) auto shared_buffer = make(m_pid, peer_pid, size); shared_buffer->m_shared_buffer_id = shared_buffer_id; ASSERT(shared_buffer->size() >= size); - shared_buffer->m_pid1_region = allocate_region_with_vmo(LinearAddress(), shared_buffer->size(), shared_buffer->m_vmo.copy_ref(), 0, "SharedBuffer", PROT_READ | PROT_WRITE); + shared_buffer->m_pid1_region = allocate_region_with_vmo(VirtualAddress(), shared_buffer->size(), shared_buffer->m_vmo.copy_ref(), 0, "SharedBuffer", PROT_READ | PROT_WRITE); shared_buffer->m_pid1_region->set_shared(true); - *buffer = shared_buffer->m_pid1_region->laddr().as_ptr(); + *buffer = shared_buffer->m_pid1_region->vaddr().as_ptr(); #ifdef SHARED_BUFFER_DEBUG - kprintf("%s(%u): Created shared buffer %d (%u bytes, vmo is %u) for sharing with %d\n", name().characters(), pid(),shared_buffer_id, size, shared_buffer->size(), peer_pid); + kprintf("%s(%u): Created shared buffer %d (%u bytes, vmo is %u) for sharing with %d\n", name().characters(), pid(), shared_buffer_id, size, shared_buffer->size(), peer_pid); #endif shared_buffers().resource().set(shared_buffer_id, move(shared_buffer)); return shared_buffer_id; @@ -2613,10 +2571,14 @@ int Process::sys$get_shared_buffer_size(int shared_buffer_id) const char* to_string(Process::Priority priority) { switch (priority) { - case Process::IdlePriority: return "Idle"; - case Process::LowPriority: return "Low"; - case Process::NormalPriority: return "Normal"; - case Process::HighPriority: return "High"; + case Process::IdlePriority: + return "Idle"; + case Process::LowPriority: + return "Low"; + case Process::NormalPriority: + return "Normal"; + case Process::HighPriority: + return "High"; } kprintf("to_string(Process::Priority): Invalid priority: %u\n", priority); ASSERT_NOT_REACHED(); @@ -2642,14 +2604,14 @@ void Process::send_signal(byte signal, Process* sender) int Process::thread_count() const { int count = 0; - for_each_thread([&count] (auto&) { + for_each_thread([&count](auto&) { ++count; return IterationDecision::Continue; }); return count; } -int Process::sys$create_thread(int(*entry)(void*), void* argument) +int Process::sys$create_thread(int (*entry)(void*), void* argument) { if (!validate_read((const void*)entry, sizeof(void*))) return -EFAULT; @@ -2688,10 +2650,10 @@ int Process::sys$donate(int tid) return -EINVAL; InterruptDisabler disabler; Thread* beneficiary = nullptr; - for_each_thread([&] (Thread& thread) { + for_each_thread([&](Thread& thread) { if (thread.tid() == tid) { beneficiary = &thread; - return IterationDecision::Abort; + return IterationDecision::Break; } return IterationDecision::Continue; }); @@ -2720,8 +2682,8 @@ int Process::sys$shm_open(const char* name, int flags, mode_t mode) auto shm_or_error = SharedMemory::open(String(name), flags, mode); if (shm_or_error.is_error()) return shm_or_error.error(); - auto descriptor = FileDescriptor::create(shm_or_error.value().ptr()); - m_fds[fd].set(move(descriptor), FD_CLOEXEC); + auto description = FileDescription::create(shm_or_error.value().ptr()); + m_fds[fd].set(move(description), FD_CLOEXEC); return fd; } @@ -2734,11 +2696,11 @@ int Process::sys$shm_unlink(const char* name) int Process::sys$ftruncate(int fd, off_t length) { - auto* descriptor = file_descriptor(fd); - if (!descriptor) + auto* description = file_description(fd); + if (!description) return -EBADF; // FIXME: Check that fd is writable, otherwise EINVAL. - return descriptor->truncate(length); + return description->truncate(length); } int Process::sys$systrace(pid_t pid) @@ -2752,8 +2714,8 @@ int Process::sys$systrace(pid_t pid) int fd = alloc_fd(); if (fd < 0) return fd; - auto descriptor = FileDescriptor::create(peer->ensure_tracer()); - m_fds[fd].set(move(descriptor), 0); + auto description = FileDescription::create(peer->ensure_tracer()); + m_fds[fd].set(move(description), 0); return fd; } @@ -2764,15 +2726,15 @@ ProcessTracer& Process::ensure_tracer() return *m_tracer; } -void Process::FileDescriptorAndFlags::clear() +void Process::FileDescriptionAndFlags::clear() { - descriptor = nullptr; + description = nullptr; flags = 0; } -void Process::FileDescriptorAndFlags::set(Retained&& d, dword f) +void Process::FileDescriptionAndFlags::set(Retained&& d, dword f) { - descriptor = move(d); + description = move(d); flags = f; } diff --git a/Kernel/Process.h b/Kernel/Process.h index 6e1c30e723..90b685d582 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -16,12 +16,13 @@ #include class ELFLoader; -class FileDescriptor; +class FileDescription; class PageDirectory; class Region; class VMObject; class ProcessTracer; +timeval kgettimeofday(); void kgettimeofday(timeval&); class Process : public InlineLinkedListNode @@ -37,8 +38,7 @@ public: static Vector all_pids(); static Vector all_processes(); - enum Priority - { + enum Priority { IdlePriority, FirstPriority = IdlePriority, LowPriority, @@ -47,8 +47,7 @@ public: LastPriority = HighPriority, }; - enum RingLevel - { + enum RingLevel { Ring0 = 0, Ring3 = 3, }; @@ -86,8 +85,8 @@ public: bool in_group(gid_t) const; - FileDescriptor* file_descriptor(int fd); - const FileDescriptor* file_descriptor(int fd) const; + FileDescription* file_description(int fd); + const FileDescription* file_description(int fd) const; template static void for_each(Callback); @@ -177,6 +176,7 @@ public: int sys$chmod(const char* pathname, mode_t); int sys$fchmod(int fd, mode_t); int sys$chown(const char* pathname, uid_t, gid_t); + int sys$fchown(int fd, uid_t, gid_t); int sys$socket(int domain, int type, int protocol); int sys$bind(int sockfd, const sockaddr* addr, socklen_t); int sys$listen(int sockfd, int backlog); @@ -223,7 +223,7 @@ public: dword m_ticks_in_user_for_dead_children { 0 }; dword m_ticks_in_kernel_for_dead_children { 0 }; - bool validate_read_from_kernel(LinearAddress) const; + bool validate_read_from_kernel(VirtualAddress) const; bool validate_read(const void*, ssize_t) const; bool validate_write(void*, ssize_t) const; @@ -248,9 +248,9 @@ public: bool is_superuser() const { return m_euid == 0; } - Region* allocate_region_with_vmo(LinearAddress, size_t, Retained&&, size_t offset_in_vmo, String&& name, int prot); - Region* allocate_file_backed_region(LinearAddress, size_t, RetainPtr&&, String&& name, int prot); - Region* allocate_region(LinearAddress, size_t, String&& name, int prot = PROT_READ | PROT_WRITE, bool commit = true); + Region* allocate_region_with_vmo(VirtualAddress, size_t, Retained&&, size_t offset_in_vmo, const String& name, int prot); + Region* allocate_file_backed_region(VirtualAddress, size_t, RetainPtr&&, const String& name, int prot); + Region* allocate_region(VirtualAddress, size_t, const String& name, int prot = PROT_READ | PROT_WRITE, bool commit = true); bool deallocate_region(Region& region); void set_being_inspected(bool b) { m_being_inspected = b; } @@ -275,10 +275,10 @@ private: Process(String&& name, uid_t, gid_t, pid_t ppid, RingLevel, RetainPtr&& cwd = nullptr, RetainPtr&& executable = nullptr, TTY* = nullptr, Process* fork_parent = nullptr); - Range allocate_range(LinearAddress, size_t); + Range allocate_range(VirtualAddress, size_t); int do_exec(String path, Vector arguments, Vector environment); - ssize_t do_write(FileDescriptor&, const byte*, int data_size); + ssize_t do_write(FileDescription&, const byte*, int data_size); int alloc_fd(int first_candidate_fd = 0); void disown_all_shared_buffers(); @@ -304,17 +304,17 @@ private: Priority m_priority { NormalPriority }; - struct FileDescriptorAndFlags { - operator bool() const { return !!descriptor; } + struct FileDescriptionAndFlags { + operator bool() const { return !!description; } void clear(); - void set(Retained&& d, dword f = 0); - RetainPtr descriptor; + void set(Retained&& d, dword f = 0); + RetainPtr description; dword flags { 0 }; }; - Vector m_fds; + Vector m_fds; RingLevel m_ring { Ring0 }; - int m_max_open_file_descriptors { 128 }; + static const int m_max_open_file_descriptors { FD_SETSIZE }; byte m_termination_status { 0 }; byte m_termination_signal { 0 }; @@ -324,12 +324,12 @@ private: TTY* m_tty { nullptr }; - Region* region_from_range(LinearAddress, size_t); + Region* region_from_range(VirtualAddress, size_t); Vector> m_regions; - LinearAddress m_return_to_ring3_from_signal_trampoline; - LinearAddress m_return_to_ring0_from_signal_trampoline; + VirtualAddress m_return_to_ring3_from_signal_trampoline; + VirtualAddress m_return_to_ring0_from_signal_trampoline; pid_t m_ppid { 0 }; mode_t m_umask { 022 }; @@ -349,6 +349,8 @@ private: OwnPtr m_elf_loader; Lock m_big_lock { "Process" }; + + qword m_alarm_deadline { 0 }; }; class ProcessInspectionHandle { @@ -394,7 +396,7 @@ inline void Process::for_each(Callback callback) ASSERT_INTERRUPTS_DISABLED(); for (auto* process = g_processes->head(); process;) { auto* next_process = process->next(); - if (!callback(*process)) + if (callback(*process) == IterationDecision::Break) break; process = next_process; } @@ -423,7 +425,7 @@ inline void Process::for_each_thread(Callback callback) const for (auto* thread = g_runnable_threads->head(); thread;) { auto* next_thread = thread->next(); if (thread->pid() == my_pid) { - if (callback(*thread) == IterationDecision::Abort) + if (callback(*thread) == IterationDecision::Break) break; } thread = next_thread; @@ -431,7 +433,7 @@ inline void Process::for_each_thread(Callback callback) const for (auto* thread = g_nonrunnable_threads->head(); thread;) { auto* next_thread = thread->next(); if (thread->pid() == my_pid) { - if (callback(*thread) == IterationDecision::Abort) + if (callback(*thread) == IterationDecision::Break) break; } thread = next_thread; diff --git a/Kernel/ProcessTracer.cpp b/Kernel/ProcessTracer.cpp index 18493f54be..33cbf79966 100644 --- a/Kernel/ProcessTracer.cpp +++ b/Kernel/ProcessTracer.cpp @@ -1,15 +1,13 @@ -#include #include +#include ProcessTracer::ProcessTracer(pid_t pid) : m_pid(pid) { - } ProcessTracer::~ProcessTracer() { - } void ProcessTracer::did_syscall(dword function, dword arg1, dword arg2, dword arg3, dword result) @@ -18,7 +16,7 @@ void ProcessTracer::did_syscall(dword function, dword arg1, dword arg2, dword ar m_calls.enqueue(data); } -int ProcessTracer::read(FileDescriptor&, byte* buffer, int buffer_size) +int ProcessTracer::read(FileDescription&, byte* buffer, int buffer_size) { if (m_calls.is_empty()) return 0; @@ -29,7 +27,7 @@ int ProcessTracer::read(FileDescriptor&, byte* buffer, int buffer_size) return sizeof(data); } -String ProcessTracer::absolute_path(FileDescriptor&) const +String ProcessTracer::absolute_path(const FileDescription&) const { return String::format("tracer:%d", m_pid); } diff --git a/Kernel/ProcessTracer.h b/Kernel/ProcessTracer.h index b0b0321b67..0b71b0ba0a 100644 --- a/Kernel/ProcessTracer.h +++ b/Kernel/ProcessTracer.h @@ -12,13 +12,13 @@ public: bool is_dead() const { return m_dead; } void set_dead() { m_dead = true; } - virtual bool can_read(FileDescriptor&) const override { return !m_calls.is_empty() || m_dead; } - virtual int read(FileDescriptor&, byte*, int) override; + virtual bool can_read(FileDescription&) const override { return !m_calls.is_empty() || m_dead; } + virtual int read(FileDescription&, byte*, int) override; - virtual bool can_write(FileDescriptor&) const override { return true; } - virtual int write(FileDescriptor&, const byte*, int) override { return -EIO; } + virtual bool can_write(FileDescription&) const override { return true; } + virtual int write(FileDescription&, const byte*, int) override { return -EIO; } - virtual String absolute_path(FileDescriptor&) const override; + virtual String absolute_path(const FileDescription&) const override; void did_syscall(dword function, dword arg1, dword arg2, dword arg3, dword result); pid_t pid() const { return m_pid; } diff --git a/Kernel/RTC.cpp b/Kernel/RTC.cpp index 3c9f38b967..ac5ba4acd5 100644 --- a/Kernel/RTC.cpp +++ b/Kernel/RTC.cpp @@ -1,13 +1,13 @@ -#include "RTC.h" -#include "CMOS.h" #include +#include +#include namespace RTC { static time_t s_boot_time; void initialize() -{ +{ byte cmos_mode = CMOS::read(0x0b); cmos_mode |= 2; // 24 hour mode cmos_mode |= 4; // No BCD mode @@ -116,12 +116,11 @@ time_t now() ASSERT(year >= 2018); return days_in_years_since_epoch(year - 1) * 86400 - + days_in_months_since_start_of_year(month - 1, year) * 86400 - + (day - 1) * 86400 - + hour * 3600 - + minute * 60 - + second; + + days_in_months_since_start_of_year(month - 1, year) * 86400 + + (day - 1) * 86400 + + hour * 3600 + + minute * 60 + + second; } } - diff --git a/Kernel/Scheduler.cpp b/Kernel/Scheduler.cpp index 98c357e6b1..5ddae383a5 100644 --- a/Kernel/Scheduler.cpp +++ b/Kernel/Scheduler.cpp @@ -1,11 +1,11 @@ -#include "Scheduler.h" -#include "Process.h" -#include "RTC.h" -#include "i8253.h" #include #include -#include #include +#include +#include +#include +#include +#include //#define LOG_EVERY_CONTEXT_SWITCH //#define SCHEDULER_DEBUG @@ -72,7 +72,7 @@ bool Scheduler::pick_next() auto now_usec = now.tv_usec; // Check and unblock threads whose wait conditions have been met. - Thread::for_each_nonrunnable([&] (Thread& thread) { + Thread::for_each_nonrunnable([&](Thread& thread) { auto& process = thread.process(); if (thread.state() == Thread::BlockedSleep) { @@ -82,7 +82,7 @@ bool Scheduler::pick_next() } if (thread.state() == Thread::BlockedWait) { - process.for_each_child([&] (Process& child) { + process.for_each_child([&](Process& child) { if (!child.is_dead()) return true; if (thread.waitee_pid() == -1 || thread.waitee_pid() == child.pid()) { @@ -96,34 +96,34 @@ bool Scheduler::pick_next() } if (thread.state() == Thread::BlockedRead) { - ASSERT(thread.m_blocked_descriptor); + ASSERT(thread.m_blocked_description); // FIXME: Block until the amount of data wanted is available. - if (thread.m_blocked_descriptor->can_read()) + if (thread.m_blocked_description->can_read()) thread.unblock(); return IterationDecision::Continue; } if (thread.state() == Thread::BlockedWrite) { - ASSERT(thread.m_blocked_descriptor != -1); - if (thread.m_blocked_descriptor->can_write()) + ASSERT(thread.m_blocked_description != -1); + if (thread.m_blocked_description->can_write()) thread.unblock(); return IterationDecision::Continue; } if (thread.state() == Thread::BlockedConnect) { - auto& descriptor = *thread.m_blocked_descriptor; - auto& socket = *descriptor.socket(); + auto& description = *thread.m_blocked_description; + auto& socket = *description.socket(); if (socket.is_connected()) thread.unblock(); return IterationDecision::Continue; } if (thread.state() == Thread::BlockedReceive) { - auto& descriptor = *thread.m_blocked_descriptor; - auto& socket = *descriptor.socket(); + auto& description = *thread.m_blocked_description; + auto& socket = *description.socket(); // FIXME: Block until the amount of data wanted is available. bool timed_out = now_sec > socket.receive_deadline().tv_sec || (now_sec == socket.receive_deadline().tv_sec && now_usec >= socket.receive_deadline().tv_usec); - if (timed_out || descriptor.can_read()) { + if (timed_out || description.can_read()) { thread.unblock(); return IterationDecision::Continue; } @@ -138,13 +138,13 @@ bool Scheduler::pick_next() } } for (int fd : thread.m_select_read_fds) { - if (process.m_fds[fd].descriptor->can_read()) { + if (process.m_fds[fd].description->can_read()) { thread.unblock(); return IterationDecision::Continue; } } for (int fd : thread.m_select_write_fds) { - if (process.m_fds[fd].descriptor->can_write()) { + if (process.m_fds[fd].description->can_write()) { thread.unblock(); return IterationDecision::Continue; } @@ -180,7 +180,7 @@ bool Scheduler::pick_next() return IterationDecision::Continue; }); - Process::for_each([&] (Process& process) { + Process::for_each([&](Process& process) { if (process.is_dead()) { if (current != &process.main_thread() && (!process.ppid() || !Process::from_pid(process.ppid()))) { auto name = process.name(); @@ -188,13 +188,18 @@ bool Scheduler::pick_next() auto exit_status = Process::reap(process); dbgprintf("reaped unparented process %s(%u), exit status: %u\n", name.characters(), pid, exit_status); } + return IterationDecision::Continue; } - return true; + if (process.m_alarm_deadline && g_uptime > process.m_alarm_deadline) { + process.m_alarm_deadline = 0; + process.send_signal(SIGALRM, nullptr); + } + return IterationDecision::Continue; }); // Dispatch any pending signals. // FIXME: Do we really need this to be a separate pass over the process list? - Thread::for_each_living([] (Thread& thread) { + Thread::for_each_living([](Thread& thread) { if (!thread.has_unmasked_pending_signals()) return true; // FIXME: It would be nice if the Scheduler didn't have to worry about who is "current" @@ -284,12 +289,12 @@ bool Scheduler::yield() { InterruptDisabler disabler; ASSERT(current); -// dbgprintf("%s(%u:%u) yield()\n", current->process().name().characters(), current->pid(), current->tid()); + // dbgprintf("%s(%u:%u) yield()\n", current->process().name().characters(), current->pid(), current->tid()); if (!pick_next()) return false; -// dbgprintf("yield() jumping to new process: sel=%x, %s(%u:%u)\n", current->far_ptr().selector, current->process().name().characters(), current->pid(), current->tid()); + // dbgprintf("yield() jumping to new process: sel=%x, %s(%u:%u)\n", current->far_ptr().selector, current->process().name().characters(), current->pid(), current->tid()); switch_now(); return true; } @@ -307,9 +312,7 @@ void Scheduler::switch_now() descriptor.type = 9; flush_gdt(); asm("sti\n" - "ljmp *(%%eax)\n" - ::"a"(¤t->far_ptr()) - ); + "ljmp *(%%eax)\n" ::"a"(¤t->far_ptr())); } bool Scheduler::context_switch(Thread& thread) @@ -328,9 +331,9 @@ bool Scheduler::context_switch(Thread& thread) #ifdef LOG_EVERY_CONTEXT_SWITCH dbgprintf("Scheduler: %s(%u:%u) -> %s(%u:%u) %w:%x\n", - current->process().name().characters(), current->process().pid(), current->tid(), - thread.process().name().characters(), thread.process().pid(), thread.tid(), - thread.tss().cs, thread.tss().eip); + current->process().name().characters(), current->process().pid(), current->tid(), + thread.process().name().characters(), thread.process().pid(), thread.tid(), + thread.tss().cs, thread.tss().eip); #endif } @@ -451,6 +454,5 @@ void Scheduler::timer_tick(RegisterDump& regs) asm( "pushf\n" "orl $0x00004000, (%esp)\n" - "popf\n" - ); + "popf\n"); } diff --git a/Kernel/SharedMemory.cpp b/Kernel/SharedMemory.cpp index 8cf1603867..6100aee70c 100644 --- a/Kernel/SharedMemory.cpp +++ b/Kernel/SharedMemory.cpp @@ -1,8 +1,8 @@ -#include -#include +#include #include #include -#include +#include +#include Lockable>>& shared_memories() { @@ -68,12 +68,12 @@ KResult SharedMemory::truncate(int length) return KResult(-ENOTIMPL); } -String SharedMemory::absolute_path(FileDescriptor&) const +String SharedMemory::absolute_path(const FileDescription&) const { return String::format("shm:%u", this); } -int SharedMemory::read(FileDescriptor&, byte* buffer, int buffer_size) +int SharedMemory::read(FileDescription&, byte* buffer, int buffer_size) { UNUSED_PARAM(buffer); UNUSED_PARAM(buffer_size); @@ -81,7 +81,7 @@ int SharedMemory::read(FileDescriptor&, byte* buffer, int buffer_size) ASSERT_NOT_REACHED(); } -int SharedMemory::write(FileDescriptor&, const byte* data, int data_size) +int SharedMemory::write(FileDescription&, const byte* data, int data_size) { UNUSED_PARAM(data); UNUSED_PARAM(data_size); @@ -89,9 +89,9 @@ int SharedMemory::write(FileDescriptor&, const byte* data, int data_size) ASSERT_NOT_REACHED(); } -KResultOr SharedMemory::mmap(Process& process, LinearAddress laddr, size_t offset, size_t size, int prot) +KResultOr SharedMemory::mmap(Process& process, FileDescription&, VirtualAddress vaddr, size_t offset, size_t size, int prot) { if (!vmo()) return KResult(-ENODEV); - return process.allocate_region_with_vmo(laddr, size, *vmo(), offset, name(), prot); + return process.allocate_region_with_vmo(vaddr, size, *vmo(), offset, name(), prot); } diff --git a/Kernel/SharedMemory.h b/Kernel/SharedMemory.h index 2bdd13c59e..f7ec96f495 100644 --- a/Kernel/SharedMemory.h +++ b/Kernel/SharedMemory.h @@ -15,7 +15,7 @@ public: static KResult unlink(const String& name); virtual ~SharedMemory() override; - String name() const { return m_name; } + const String& name() const { return m_name; } virtual KResult truncate(off_t) override; VMObject* vmo() { return m_vmo.ptr(); } const VMObject* vmo() const { return m_vmo.ptr(); } @@ -24,14 +24,14 @@ public: private: // ^File - virtual bool can_read(FileDescriptor&) const override { return true; } - virtual bool can_write(FileDescriptor&) const override { return true; } - virtual int read(FileDescriptor&, byte*, int) override; - virtual int write(FileDescriptor&, const byte*, int) override; - virtual String absolute_path(FileDescriptor&) const override; + virtual bool can_read(FileDescription&) const override { return true; } + virtual bool can_write(FileDescription&) const override { return true; } + virtual int read(FileDescription&, byte*, int) override; + virtual int write(FileDescription&, const byte*, int) override; + virtual String absolute_path(const FileDescription&) const override; virtual const char* class_name() const override { return "SharedMemory"; } virtual bool is_shared_memory() const override { return true; } - virtual KResultOr mmap(Process&, LinearAddress, size_t offset, size_t size, int prot) override; + virtual KResultOr mmap(Process&, FileDescription&, VirtualAddress, size_t offset, size_t size, int prot) override; SharedMemory(const String& name, uid_t, gid_t, mode_t); diff --git a/Kernel/StdLib.cpp b/Kernel/StdLib.cpp index af9eacaab7..e146d643ee 100644 --- a/Kernel/StdLib.cpp +++ b/Kernel/StdLib.cpp @@ -1,18 +1,11 @@ +#include #include -#include "Assertions.h" -#include "kmalloc.h" -#include -#include +#include extern "C" { void* memcpy(void* dest_ptr, const void* src_ptr, size_t n) { -#ifndef KERNEL - if (n >= 1024) - return mmx_memcpy(dest_ptr, src_ptr, n); -#endif - size_t dest = (size_t)dest_ptr; size_t src = (size_t)src_ptr; // FIXME: Support starting at an unaligned address. @@ -22,17 +15,14 @@ void* memcpy(void* dest_ptr, const void* src_ptr, size_t n) "rep movsl\n" : "=S"(src), "=D"(dest) : "S"(src), "D"(dest), "c"(size_ts) - : "memory" - ); + : "memory"); n -= size_ts * sizeof(size_t); if (n == 0) return dest_ptr; } asm volatile( - "rep movsb\n" - :: "S"(src), "D"(dest), "c"(n) - : "memory" - ); + "rep movsb\n" ::"S"(src), "D"(dest), "c"(n) + : "memory"); return dest_ptr; } @@ -41,18 +31,19 @@ void* memmove(void* dest, const void* src, size_t n) if (dest < src) return memcpy(dest, src, n); - byte *pd = (byte*)dest; - const byte *ps = (const byte*)src; + byte* pd = (byte*)dest; + const byte* ps = (const byte*)src; for (pd += n, ps += n; n--;) *--pd = *--ps; return dest; } -char* strcpy(char* dest, const char *src) +char* strcpy(char* dest, const char* src) { auto* dest_ptr = dest; auto* src_ptr = src; - while ((*dest_ptr++ = *src_ptr++) != '\0'); + while ((*dest_ptr++ = *src_ptr++) != '\0') + ; return dest; } @@ -61,7 +52,7 @@ char* strncpy(char* dest, const char* src, size_t n) size_t i; for (i = 0; i < n && src[i] != '\0'; ++i) dest[i] = src[i]; - for ( ; i < n; ++i) + for (; i < n; ++i) dest[i] = '\0'; return dest; } @@ -79,24 +70,22 @@ void* memset(void* dest_ptr, int c, size_t n) "rep stosl\n" : "=D"(dest) : "D"(dest), "c"(size_ts), "a"(expanded_c) - : "memory" - ); + : "memory"); n -= size_ts * sizeof(size_t); if (n == 0) return dest_ptr; } asm volatile( "rep stosb\n" - : "=D" (dest), "=c" (n) - : "0" (dest), "1" (n), "a" (c) - : "memory" - ); + : "=D"(dest), "=c"(n) + : "0"(dest), "1"(n), "a"(c) + : "memory"); return dest_ptr; } char* strrchr(const char* str, int ch) { - char *last = nullptr; + char* last = nullptr; char c; for (; (c = *str); ++str) { if (c == ch) @@ -113,7 +102,7 @@ size_t strlen(const char* str) return len; } -int strcmp(const char *s1, const char *s2) +int strcmp(const char* s1, const char* s2) { for (; *s1 == *s2; ++s1, ++s2) { if (*s1 == 0) @@ -122,7 +111,7 @@ int strcmp(const char *s1, const char *s2) return *(const byte*)s1 < *(const byte*)s2 ? -1 : 1; } -char* strdup(const char *str) +char* strdup(const char* str) { size_t len = strlen(str); char* new_str = (char*)kmalloc(len + 1); @@ -145,5 +134,4 @@ int memcmp(const void* v1, const void* v2, size_t n) { ASSERT_NOT_REACHED(); } - } diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index 49ade71a3c..95d14e44d7 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -1,9 +1,9 @@ -#include "i386.h" -#include "Process.h" -#include "Syscall.h" -#include "Console.h" -#include "Scheduler.h" +#include +#include +#include #include +#include +#include extern "C" void syscall_trap_entry(RegisterDump&); extern "C" void syscall_trap_handler(); @@ -34,8 +34,7 @@ asm( " popw %es\n" " popw %ds\n" " popa\n" - " iret\n" -); + " iret\n"); namespace Syscall { @@ -242,6 +241,8 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2, return current->process().sys$release_shared_buffer((int)arg1); case Syscall::SC_chown: return current->process().sys$chown((const char*)arg1, (uid_t)arg2, (gid_t)arg3); + case Syscall::SC_fchown: + return current->process().sys$fchown((int)arg1, (uid_t)arg2, (gid_t)arg3); case Syscall::SC_restore_signal_mask: return current->process().sys$restore_signal_mask((dword)arg1); case Syscall::SC_seal_shared_buffer: @@ -257,7 +258,7 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2, case Syscall::SC_setsockopt: return current->process().sys$setsockopt((const SC_setsockopt_params*)arg1); case Syscall::SC_create_thread: - return current->process().sys$create_thread((int(*)(void*))arg1, (void*)arg2); + return current->process().sys$create_thread((int (*)(void*))arg1, (void*)arg2); case Syscall::SC_rename: return current->process().sys$rename((const char*)arg1, (const char*)arg2); case Syscall::SC_shm_open: @@ -301,4 +302,3 @@ void syscall_trap_entry(RegisterDump& regs) tracer->did_syscall(function, arg1, arg2, arg3, regs.eax); current->process().big_lock().unlock(); } - diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index 2428a74cec..fd2f7fceef 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -3,6 +3,10 @@ #include #include +extern "C" { +struct timeval; +} + #define ENUMERATE_SYSCALLS \ __ENUMERATE_SYSCALL(sleep) \ __ENUMERATE_SYSCALL(yield) \ @@ -106,13 +110,13 @@ __ENUMERATE_SYSCALL(beep) \ __ENUMERATE_SYSCALL(getsockname) \ __ENUMERATE_SYSCALL(getpeername) \ - __ENUMERATE_SYSCALL(sched_setparam) \ - __ENUMERATE_SYSCALL(sched_getparam) + __ENUMERATE_SYSCALL(sched_setparam) \ + __ENUMERATE_SYSCALL(sched_getparam) \ + __ENUMERATE_SYSCALL(fchown) namespace Syscall { -enum Function -{ +enum Function { #undef __ENUMERATE_SYSCALL #define __ENUMERATE_SYSCALL(x) SC_##x, ENUMERATE_SYSCALLS diff --git a/Kernel/TTY/MasterPTY.cpp b/Kernel/TTY/MasterPTY.cpp index 22e87495b0..b3e64ceda1 100644 --- a/Kernel/TTY/MasterPTY.cpp +++ b/Kernel/TTY/MasterPTY.cpp @@ -1,6 +1,6 @@ #include "MasterPTY.h" -#include "SlavePTY.h" #include "PTYMultiplexer.h" +#include "SlavePTY.h" #include #include #include @@ -31,14 +31,14 @@ String MasterPTY::pts_name() const return m_pts_name; } -ssize_t MasterPTY::read(FileDescriptor&, byte* buffer, ssize_t size) +ssize_t MasterPTY::read(FileDescription&, byte* buffer, ssize_t size) { if (!m_slave && m_buffer.is_empty()) return 0; return m_buffer.read(buffer, size); } -ssize_t MasterPTY::write(FileDescriptor&, const byte* buffer, ssize_t size) +ssize_t MasterPTY::write(FileDescription&, const byte* buffer, ssize_t size) { if (!m_slave) return -EIO; @@ -46,14 +46,14 @@ ssize_t MasterPTY::write(FileDescriptor&, const byte* buffer, ssize_t size) return size; } -bool MasterPTY::can_read(FileDescriptor&) const +bool MasterPTY::can_read(FileDescription&) const { if (!m_slave) return true; return !m_buffer.is_empty(); } -bool MasterPTY::can_write(FileDescriptor&) const +bool MasterPTY::can_write(FileDescription&) const { return true; } @@ -64,7 +64,7 @@ void MasterPTY::notify_slave_closed(Badge) dbgprintf("MasterPTY(%u): slave closed, my retains: %u, slave retains: %u\n", m_index, retain_count(), m_slave->retain_count()); #endif // +1 retain for my MasterPTY::m_slave - // +1 retain for FileDescriptor::m_device + // +1 retain for FileDescription::m_device if (m_slave->retain_count() == 2) m_slave = nullptr; } @@ -88,7 +88,7 @@ void MasterPTY::close() { if (retain_count() == 2) { InterruptDisabler disabler; - // After the closing FileDescriptor dies, slave is the only thing keeping me alive. + // After the closing FileDescription dies, slave is the only thing keeping me alive. // From this point, let's consider ourselves closed. m_closed = true; @@ -96,9 +96,9 @@ void MasterPTY::close() } } -int MasterPTY::ioctl(FileDescriptor& descriptor, unsigned request, unsigned arg) +int MasterPTY::ioctl(FileDescription& description, unsigned request, unsigned arg) { if (request == TIOCSWINSZ) - return m_slave->ioctl(descriptor, request, arg); + return m_slave->ioctl(description, request, arg); return -EINVAL; } diff --git a/Kernel/TTY/MasterPTY.h b/Kernel/TTY/MasterPTY.h index 22fd3db48e..accb6902bc 100644 --- a/Kernel/TTY/MasterPTY.h +++ b/Kernel/TTY/MasterPTY.h @@ -20,13 +20,13 @@ public: private: // ^CharacterDevice - virtual ssize_t read(FileDescriptor&, byte*, ssize_t) override; - virtual ssize_t write(FileDescriptor&, const byte*, ssize_t) override; - virtual bool can_read(FileDescriptor&) const override; - virtual bool can_write(FileDescriptor&) const override; + virtual ssize_t read(FileDescription&, byte*, ssize_t) override; + virtual ssize_t write(FileDescription&, const byte*, ssize_t) override; + virtual bool can_read(FileDescription&) const override; + virtual bool can_write(FileDescription&) const override; virtual void close() override; virtual bool is_master_pty() const override { return true; } - virtual int ioctl(FileDescriptor&, unsigned request, unsigned arg) override; + virtual int ioctl(FileDescription&, unsigned request, unsigned arg) override; virtual const char* class_name() const override { return "MasterPTY"; } RetainPtr m_slave; diff --git a/Kernel/TTY/PTYMultiplexer.cpp b/Kernel/TTY/PTYMultiplexer.cpp index 1620f8f952..3b8b596502 100644 --- a/Kernel/TTY/PTYMultiplexer.cpp +++ b/Kernel/TTY/PTYMultiplexer.cpp @@ -1,6 +1,6 @@ #include "PTYMultiplexer.h" #include "MasterPTY.h" -#include +#include #include #include @@ -28,7 +28,7 @@ PTYMultiplexer::~PTYMultiplexer() { } -KResultOr> PTYMultiplexer::open(int options) +KResultOr> PTYMultiplexer::open(int options) { UNUSED_PARAM(options); LOCKER(m_lock); @@ -39,7 +39,7 @@ KResultOr> PTYMultiplexer::open(int options) #ifdef PTMX_DEBUG dbgprintf("PTYMultiplexer::open: Vending master %u\n", master->index()); #endif - return FileDescriptor::create(master.ptr()); + return FileDescription::create(master.ptr()); } void PTYMultiplexer::notify_master_destroyed(Badge, unsigned index) diff --git a/Kernel/TTY/PTYMultiplexer.h b/Kernel/TTY/PTYMultiplexer.h index 1d06d6f4d8..b25a5674fc 100644 --- a/Kernel/TTY/PTYMultiplexer.h +++ b/Kernel/TTY/PTYMultiplexer.h @@ -15,11 +15,11 @@ public: static PTYMultiplexer& the(); // ^CharacterDevice - virtual KResultOr> open(int options) override; - virtual ssize_t read(FileDescriptor&, byte*, ssize_t) override { return 0; } - virtual ssize_t write(FileDescriptor&, const byte*, ssize_t) override { return 0; } - virtual bool can_read(FileDescriptor&) const override { return true; } - virtual bool can_write(FileDescriptor&) const override { return true; } + virtual KResultOr> open(int options) override; + virtual ssize_t read(FileDescription&, byte*, ssize_t) override { return 0; } + virtual ssize_t write(FileDescription&, const byte*, ssize_t) override { return 0; } + virtual bool can_read(FileDescription&) const override { return true; } + virtual bool can_write(FileDescription&) const override { return true; } void notify_master_destroyed(Badge, unsigned index); diff --git a/Kernel/TTY/SlavePTY.cpp b/Kernel/TTY/SlavePTY.cpp index f40392037c..2773db17a8 100644 --- a/Kernel/TTY/SlavePTY.cpp +++ b/Kernel/TTY/SlavePTY.cpp @@ -41,23 +41,23 @@ ssize_t SlavePTY::on_tty_write(const byte* data, ssize_t size) return m_master->on_slave_write(data, size); } -bool SlavePTY::can_write(FileDescriptor&) const +bool SlavePTY::can_write(FileDescription&) const { return m_master->can_write_from_slave(); } -bool SlavePTY::can_read(FileDescriptor& descriptor) const +bool SlavePTY::can_read(FileDescription& description) const { if (m_master->is_closed()) return true; - return TTY::can_read(descriptor); + return TTY::can_read(description); } -ssize_t SlavePTY::read(FileDescriptor& descriptor, byte* buffer, ssize_t size) +ssize_t SlavePTY::read(FileDescription& description, byte* buffer, ssize_t size) { if (m_master->is_closed()) return 0; - return TTY::read(descriptor, buffer, size); + return TTY::read(description, buffer, size); } void SlavePTY::close() diff --git a/Kernel/TTY/SlavePTY.h b/Kernel/TTY/SlavePTY.h index ffe7ebd8b1..83387d8731 100644 --- a/Kernel/TTY/SlavePTY.h +++ b/Kernel/TTY/SlavePTY.h @@ -21,9 +21,9 @@ private: virtual ssize_t on_tty_write(const byte*, ssize_t) override; // ^CharacterDevice - virtual bool can_read(FileDescriptor&) const override; - virtual ssize_t read(FileDescriptor&, byte*, ssize_t) override; - virtual bool can_write(FileDescriptor&) const override; + virtual bool can_read(FileDescription&) const override; + virtual ssize_t read(FileDescription&, byte*, ssize_t) override; + virtual bool can_write(FileDescription&) const override; virtual const char* class_name() const override { return "SlavePTY"; } virtual void close() override; diff --git a/Kernel/TTY/TTY.cpp b/Kernel/TTY/TTY.cpp index 5c02f4c5a9..7f5b892d7f 100644 --- a/Kernel/TTY/TTY.cpp +++ b/Kernel/TTY/TTY.cpp @@ -1,5 +1,5 @@ -#include #include "Process.h" +#include #include #include #include @@ -24,12 +24,12 @@ void TTY::set_default_termios() memcpy(m_termios.c_cc, default_cc, sizeof(default_cc)); } -ssize_t TTY::read(FileDescriptor&, byte* buffer, ssize_t size) +ssize_t TTY::read(FileDescription&, byte* buffer, ssize_t size) { return m_buffer.read(buffer, size); } -ssize_t TTY::write(FileDescriptor&, const byte* buffer, ssize_t size) +ssize_t TTY::write(FileDescription&, const byte* buffer, ssize_t size) { #ifdef TTY_DEBUG dbgprintf("TTY::write {%u} ", size); @@ -42,12 +42,12 @@ ssize_t TTY::write(FileDescriptor&, const byte* buffer, ssize_t size) return size; } -bool TTY::can_read(FileDescriptor&) const +bool TTY::can_read(FileDescription&) const { return !m_buffer.is_empty(); } -bool TTY::can_write(FileDescriptor&) const +bool TTY::can_write(FileDescription&) const { return true; } @@ -65,6 +65,11 @@ void TTY::emit(byte ch) generate_signal(SIGQUIT); return; } + if (ch == m_termios.c_cc[VSUSP]) { + dbgprintf("%s: VSUSP pressed!\n", tty_name().characters()); + generate_signal(SIGTSTP); + return; + } } m_buffer.write(&ch, 1); } @@ -75,7 +80,7 @@ void TTY::generate_signal(int signal) return; dbgprintf("%s: Send signal %d to everyone in pgrp %d\n", tty_name().characters(), signal, pgid()); InterruptDisabler disabler; // FIXME: Iterate over a set of process handles instead? - Process::for_each_in_pgrp(pgid(), [&] (auto& process) { + Process::for_each_in_pgrp(pgid(), [&](auto& process) { dbgprintf("%s: Send signal %d to %d\n", tty_name().characters(), signal, process.pid()); process.send_signal(signal, nullptr); return true; @@ -89,24 +94,21 @@ void TTY::set_termios(const termios& t) tty_name().characters(), should_echo_input(), should_generate_signals(), - in_canonical_mode() - ); + in_canonical_mode()); dbgprintf("%s set_termios: ECHOE=%u, ECHOK=%u, ECHONL=%u\n", - tty_name().characters(), - (m_termios.c_lflag & ECHOE) != 0, - (m_termios.c_lflag & ECHOK) != 0, - (m_termios.c_lflag & ECHONL) != 0 - ); + tty_name().characters(), + (m_termios.c_lflag & ECHOE) != 0, + (m_termios.c_lflag & ECHOK) != 0, + (m_termios.c_lflag & ECHONL) != 0); dbgprintf("%s set_termios: ISTRIP=%u, ICRNL=%u, INLCR=%u, IGNCR=%u\n", - tty_name().characters(), - (m_termios.c_iflag & ISTRIP) != 0, - (m_termios.c_iflag & ICRNL) != 0, - (m_termios.c_iflag & INLCR) != 0, - (m_termios.c_iflag & IGNCR) != 0 - ); + tty_name().characters(), + (m_termios.c_iflag & ISTRIP) != 0, + (m_termios.c_iflag & ICRNL) != 0, + (m_termios.c_iflag & INLCR) != 0, + (m_termios.c_iflag & IGNCR) != 0); } -int TTY::ioctl(FileDescriptor&, unsigned request, unsigned arg) +int TTY::ioctl(FileDescription&, unsigned request, unsigned arg) { auto& process = current->process(); pid_t pgid; diff --git a/Kernel/TTY/TTY.h b/Kernel/TTY/TTY.h index e6d489579c..78c7762829 100644 --- a/Kernel/TTY/TTY.h +++ b/Kernel/TTY/TTY.h @@ -10,12 +10,12 @@ class TTY : public CharacterDevice { public: virtual ~TTY() override; - virtual ssize_t read(FileDescriptor&, byte*, ssize_t) override; - virtual ssize_t write(FileDescriptor&, const byte*, ssize_t) override; - virtual bool can_read(FileDescriptor&) const override; - virtual bool can_write(FileDescriptor&) const override; - virtual int ioctl(FileDescriptor&, unsigned request, unsigned arg) override final; - virtual String absolute_path(FileDescriptor&) const override { return tty_name(); } + virtual ssize_t read(FileDescription&, byte*, ssize_t) override; + virtual ssize_t write(FileDescription&, const byte*, ssize_t) override; + virtual bool can_read(FileDescription&) const override; + virtual bool can_write(FileDescription&) const override; + virtual int ioctl(FileDescription&, unsigned request, unsigned arg) override final; + virtual String absolute_path(const FileDescription&) const override { return tty_name(); } virtual String tty_name() const = 0; diff --git a/Kernel/TTY/VirtualConsole.cpp b/Kernel/TTY/VirtualConsole.cpp index c4e3f9eb1a..84ee4c58bf 100644 --- a/Kernel/TTY/VirtualConsole.cpp +++ b/Kernel/TTY/VirtualConsole.cpp @@ -1,9 +1,9 @@ #include "VirtualConsole.h" -#include "kmalloc.h" -#include "i386.h" #include "IO.h" #include "StdLib.h" +#include "kmalloc.h" #include +#include static byte* s_vga_buffer; static VirtualConsole* s_consoles[6]; @@ -169,22 +169,38 @@ enum class ANSIColor : byte { static inline VGAColor ansi_color_to_vga(ANSIColor color) { switch (color) { - case ANSIColor::Black: return VGAColor::Black; - case ANSIColor::Red: return VGAColor::Red; - case ANSIColor::Brown: return VGAColor::Brown; - case ANSIColor::Blue: return VGAColor::Blue; - case ANSIColor::Magenta: return VGAColor::Magenta; - case ANSIColor::Green: return VGAColor::Green; - case ANSIColor::Cyan: return VGAColor::Cyan; - case ANSIColor::LightGray: return VGAColor::LightGray; - case ANSIColor::DarkGray: return VGAColor::DarkGray; - case ANSIColor::BrightRed: return VGAColor::BrightRed; - case ANSIColor::BrightGreen: return VGAColor::BrightGreen; - case ANSIColor::Yellow: return VGAColor::Yellow; - case ANSIColor::BrightBlue: return VGAColor::BrightBlue; - case ANSIColor::BrightMagenta: return VGAColor::BrightMagenta; - case ANSIColor::BrightCyan: return VGAColor::BrightCyan; - case ANSIColor::White: return VGAColor::White; + case ANSIColor::Black: + return VGAColor::Black; + case ANSIColor::Red: + return VGAColor::Red; + case ANSIColor::Brown: + return VGAColor::Brown; + case ANSIColor::Blue: + return VGAColor::Blue; + case ANSIColor::Magenta: + return VGAColor::Magenta; + case ANSIColor::Green: + return VGAColor::Green; + case ANSIColor::Cyan: + return VGAColor::Cyan; + case ANSIColor::LightGray: + return VGAColor::LightGray; + case ANSIColor::DarkGray: + return VGAColor::DarkGray; + case ANSIColor::BrightRed: + return VGAColor::BrightRed; + case ANSIColor::BrightGreen: + return VGAColor::BrightGreen; + case ANSIColor::Yellow: + return VGAColor::Yellow; + case ANSIColor::BrightBlue: + return VGAColor::BrightBlue; + case ANSIColor::BrightMagenta: + return VGAColor::BrightMagenta; + case ANSIColor::BrightCyan: + return VGAColor::BrightCyan; + case ANSIColor::White: + return VGAColor::White; } ASSERT_NOT_REACHED(); return VGAColor::LightGray; @@ -317,14 +333,29 @@ void VirtualConsole::execute_escape_sequence(byte final) params.append(value); } switch (final) { - case 'A': escape$A(params); break; - case 'D': escape$D(params); break; - case 'H': escape$H(params); break; - case 'J': escape$J(params); break; - case 'm': escape$m(params); break; - case 's': escape$s(params); break; - case 'u': escape$u(params); break; - default: break; + case 'A': + escape$A(params); + break; + case 'D': + escape$D(params); + break; + case 'H': + escape$H(params); + break; + case 'J': + escape$J(params); + break; + case 'm': + escape$m(params); + break; + case 's': + escape$s(params); + break; + case 'u': + escape$u(params); + break; + default: + break; } m_parameters.clear(); diff --git a/Kernel/TTY/VirtualConsole.h b/Kernel/TTY/VirtualConsole.h index 8e89fac853..7d9bb850da 100644 --- a/Kernel/TTY/VirtualConsole.h +++ b/Kernel/TTY/VirtualConsole.h @@ -9,8 +9,7 @@ class VirtualConsole final : public TTY , public ConsoleImplementation { AK_MAKE_ETERNAL public: - enum InitialContents - { + enum InitialContents { Cleared, AdoptCurrentVGABuffer }; @@ -73,8 +72,7 @@ private: void execute_escape_sequence(byte final); - enum EscapeState - { + enum EscapeState { Normal, ExpectBracket, ExpectParameter, diff --git a/Kernel/Thread.cpp b/Kernel/Thread.cpp index 62caa2ce23..7142a07a42 100644 --- a/Kernel/Thread.cpp +++ b/Kernel/Thread.cpp @@ -1,7 +1,7 @@ -#include -#include +#include #include -#include +#include +#include #include #include @@ -63,9 +63,9 @@ Thread::Thread(Process& process) } else { // Ring3 processes need a separate stack for Ring0. m_kernel_stack_region = MM.allocate_kernel_region(default_kernel_stack_size, String::format("Kernel Stack (Thread %d)", m_tid)); - m_kernel_stack_base = m_kernel_stack_region->laddr().get(); + m_kernel_stack_base = m_kernel_stack_region->vaddr().get(); m_tss.ss0 = 0x10; - m_tss.esp0 = m_kernel_stack_region->laddr().offset(default_kernel_stack_size).get() & 0xfffffff8u; + m_tss.esp0 = m_kernel_stack_region->vaddr().offset(default_kernel_stack_size).get() & 0xfffffff8u; } // HACK: Ring2 SS in the TSS is the current PID. @@ -99,7 +99,7 @@ Thread::~Thread() void Thread::unblock() { - m_blocked_descriptor = nullptr; + m_blocked_description = nullptr; if (current == this) { set_state(Thread::Running); return; @@ -129,9 +129,9 @@ void Thread::block(Thread::State new_state) process().big_lock().lock(); } -void Thread::block(Thread::State new_state, FileDescriptor& descriptor) +void Thread::block(Thread::State new_state, FileDescription& description) { - m_blocked_descriptor = &descriptor; + m_blocked_description = &description; block(new_state); } @@ -145,24 +145,42 @@ void Thread::sleep(dword ticks) const char* to_string(Thread::State state) { switch (state) { - case Thread::Invalid: return "Invalid"; - case Thread::Runnable: return "Runnable"; - case Thread::Running: return "Running"; - case Thread::Dying: return "Dying"; - case Thread::Dead: return "Dead"; - case Thread::Stopped: return "Stopped"; - case Thread::Skip1SchedulerPass: return "Skip1"; - case Thread::Skip0SchedulerPasses: return "Skip0"; - case Thread::BlockedSleep: return "Sleep"; - case Thread::BlockedWait: return "Wait"; - case Thread::BlockedRead: return "Read"; - case Thread::BlockedWrite: return "Write"; - case Thread::BlockedSignal: return "Signal"; - case Thread::BlockedSelect: return "Select"; - case Thread::BlockedLurking: return "Lurking"; - case Thread::BlockedConnect: return "Connect"; - case Thread::BlockedReceive: return "Receive"; - case Thread::BlockedSnoozing: return "Snoozing"; + case Thread::Invalid: + return "Invalid"; + case Thread::Runnable: + return "Runnable"; + case Thread::Running: + return "Running"; + case Thread::Dying: + return "Dying"; + case Thread::Dead: + return "Dead"; + case Thread::Stopped: + return "Stopped"; + case Thread::Skip1SchedulerPass: + return "Skip1"; + case Thread::Skip0SchedulerPasses: + return "Skip0"; + case Thread::BlockedSleep: + return "Sleep"; + case Thread::BlockedWait: + return "Wait"; + case Thread::BlockedRead: + return "Read"; + case Thread::BlockedWrite: + return "Write"; + case Thread::BlockedSignal: + return "Signal"; + case Thread::BlockedSelect: + return "Select"; + case Thread::BlockedLurking: + return "Lurking"; + case Thread::BlockedConnect: + return "Connect"; + case Thread::BlockedReceive: + return "Receive"; + case Thread::BlockedSnoozing: + return "Snoozing"; } kprintf("to_string(Thread::State): Invalid state: %u\n", state); ASSERT_NOT_REACHED(); @@ -174,7 +192,7 @@ void Thread::finalize() dbgprintf("Finalizing Thread %u in %s(%u)\n", tid(), m_process.name().characters(), pid()); set_state(Thread::State::Dead); - m_blocked_descriptor = nullptr; + m_blocked_description = nullptr; if (this == &m_process.main_thread()) m_process.finalize(); @@ -185,7 +203,7 @@ void Thread::finalize_dying_threads() Vector dying_threads; { InterruptDisabler disabler; - for_each_in_state(Thread::State::Dying, [&] (Thread& thread) { + for_each_in_state(Thread::State::Dying, [&](Thread& thread) { dying_threads.append(&thread); }); } @@ -313,8 +331,8 @@ ShouldUnblockThread Thread::dispatch_signal(byte signal) if (signal == SIGCONT && state() == Stopped) set_state(Runnable); - auto handler_laddr = action.handler_or_sigaction; - if (handler_laddr.is_null()) { + auto handler_vaddr = action.handler_or_sigaction; + if (handler_vaddr.is_null()) { switch (default_signal_action(signal)) { case DefaultSignalAction::Stop: set_state(Stopped); @@ -333,7 +351,7 @@ ShouldUnblockThread Thread::dispatch_signal(byte signal) ASSERT_NOT_REACHED(); } - if (handler_laddr.as_ptr() == SIG_IGN) { + if (handler_vaddr.as_ptr() == SIG_IGN) { #ifdef SIGNAL_DEBUG kprintf("%s(%u) ignored signal %u\n", process().name().characters(), pid(), signal); #endif @@ -370,15 +388,15 @@ ShouldUnblockThread Thread::dispatch_signal(byte signal) #endif if (!m_signal_stack_user_region) { - m_signal_stack_user_region = m_process.allocate_region(LinearAddress(), default_userspace_stack_size, String::format("User Signal Stack (Thread %d)", m_tid)); + m_signal_stack_user_region = m_process.allocate_region(VirtualAddress(), default_userspace_stack_size, String::format("User Signal Stack (Thread %d)", m_tid)); ASSERT(m_signal_stack_user_region); } if (!m_kernel_stack_for_signal_handler_region) m_kernel_stack_for_signal_handler_region = MM.allocate_kernel_region(default_kernel_stack_size, String::format("Kernel Signal Stack (Thread %d)", m_tid)); m_tss.ss = 0x23; - m_tss.esp = m_signal_stack_user_region->laddr().offset(default_userspace_stack_size).get(); + m_tss.esp = m_signal_stack_user_region->vaddr().offset(default_userspace_stack_size).get(); m_tss.ss0 = 0x10; - m_tss.esp0 = m_kernel_stack_for_signal_handler_region->laddr().offset(default_kernel_stack_size).get(); + m_tss.esp0 = m_kernel_stack_for_signal_handler_region->vaddr().offset(default_kernel_stack_size).get(); push_value_on_stack(0); } else { @@ -408,7 +426,7 @@ ShouldUnblockThread Thread::dispatch_signal(byte signal) m_tss.es = 0x23; m_tss.fs = 0x23; m_tss.gs = 0x23; - m_tss.eip = handler_laddr.get(); + m_tss.eip = handler_vaddr.get(); // FIXME: Should we worry about the stack being 16 byte aligned when entering a signal handler? push_value_on_stack(signal); @@ -433,8 +451,8 @@ void Thread::set_default_signal_dispositions() { // FIXME: Set up all the right default actions. See signal(7). memset(&m_signal_action_data, 0, sizeof(m_signal_action_data)); - m_signal_action_data[SIGCHLD].handler_or_sigaction = LinearAddress((dword)SIG_IGN); - m_signal_action_data[SIGWINCH].handler_or_sigaction = LinearAddress((dword)SIG_IGN); + m_signal_action_data[SIGCHLD].handler_or_sigaction = VirtualAddress((dword)SIG_IGN); + m_signal_action_data[SIGWINCH].handler_or_sigaction = VirtualAddress((dword)SIG_IGN); } void Thread::push_value_on_stack(dword value) @@ -446,11 +464,11 @@ void Thread::push_value_on_stack(dword value) void Thread::make_userspace_stack_for_main_thread(Vector arguments, Vector environment) { - auto* region = m_process.allocate_region(LinearAddress(), default_userspace_stack_size, "Stack (Main thread)"); + auto* region = m_process.allocate_region(VirtualAddress(), default_userspace_stack_size, "Stack (Main thread)"); ASSERT(region); - m_tss.esp = region->laddr().offset(default_userspace_stack_size).get(); + m_tss.esp = region->vaddr().offset(default_userspace_stack_size).get(); - char* stack_base = (char*)region->laddr().get(); + char* stack_base = (char*)region->vaddr().get(); int argc = arguments.size(); char** argv = (char**)stack_base; char** env = argv + arguments.size() + 1; @@ -490,11 +508,11 @@ void Thread::make_userspace_stack_for_main_thread(Vector arguments, Vect push_value_on_stack(0); } -void Thread::make_userspace_stack_for_secondary_thread(void *argument) +void Thread::make_userspace_stack_for_secondary_thread(void* argument) { - auto* region = m_process.allocate_region(LinearAddress(), default_userspace_stack_size, String::format("Stack (Thread %d)", tid())); + auto* region = m_process.allocate_region(VirtualAddress(), default_userspace_stack_size, String::format("Stack (Thread %d)", tid())); ASSERT(region); - m_tss.esp = region->laddr().offset(default_userspace_stack_size).get(); + m_tss.esp = region->vaddr().offset(default_userspace_stack_size).get(); // NOTE: The stack needs to be 16-byte aligned. push_value_on_stack((dword)argument); @@ -512,13 +530,13 @@ Thread* Thread::clone(Process& process) return clone; } -KResult Thread::wait_for_connect(FileDescriptor& descriptor) +KResult Thread::wait_for_connect(FileDescription& description) { - ASSERT(descriptor.is_socket()); - auto& socket = *descriptor.socket(); + ASSERT(description.is_socket()); + auto& socket = *description.socket(); if (socket.is_connected()) return KSuccess; - block(Thread::State::BlockedConnect, descriptor); + block(Thread::State::BlockedConnect, description); Scheduler::yield(); if (!socket.is_connected()) return KResult(-ECONNREFUSED); diff --git a/Kernel/Thread.h b/Kernel/Thread.h index 40f7abba11..91cd852e5e 100644 --- a/Kernel/Thread.h +++ b/Kernel/Thread.h @@ -5,26 +5,25 @@ #include #include #include +#include #include -#include #include #include -#include +#include class Alarm; -class FileDescriptor; +class FileDescription; class Process; class Region; class Thread; -enum class ShouldUnblockThread -{ +enum class ShouldUnblockThread { No = 0, Yes }; struct SignalActionData { - LinearAddress handler_or_sigaction; + VirtualAddress handler_or_sigaction; dword mask { 0 }; int flags { 0 }; }; @@ -54,8 +53,7 @@ public: void finalize(); - enum State : byte - { + enum State : byte { Invalid = 0, Runnable, Running, @@ -97,13 +95,13 @@ public: void sleep(dword ticks); void block(Thread::State); - void block(Thread::State, FileDescriptor&); + void block(Thread::State, FileDescription&); void unblock(); void set_wakeup_time(qword t) { m_wakeup_time = t; } qword wakeup_time() const { return m_wakeup_time; } void snooze_until(Alarm&); - KResult wait_for_connect(FileDescriptor&); + KResult wait_for_connect(FileDescription&); const FarPtr& far_ptr() const { return m_far_ptr; } @@ -112,7 +110,7 @@ public: dword ticks_left() const { return m_ticks_left; } dword kernel_stack_base() const { return m_kernel_stack_base; } - dword kernel_stack_for_signal_handler_base() const { return m_kernel_stack_for_signal_handler_region ? m_kernel_stack_for_signal_handler_region->laddr().get() : 0; } + dword kernel_stack_for_signal_handler_base() const { return m_kernel_stack_for_signal_handler_region ? m_kernel_stack_for_signal_handler_region->vaddr().get() : 0; } void set_selector(word s) { m_far_ptr.selector = s; } void set_state(State); @@ -181,7 +179,7 @@ private: RetainPtr m_kernel_stack_region; RetainPtr m_kernel_stack_for_signal_handler_region; pid_t m_waitee_pid { -1 }; - RetainPtr m_blocked_descriptor; + RetainPtr m_blocked_description; timeval m_select_timeout; SignalActionData m_signal_action_data[32]; Region* m_signal_stack_user_region { nullptr }; @@ -245,7 +243,7 @@ inline void Thread::for_each_runnable(Callback callback) ASSERT_INTERRUPTS_DISABLED(); for (auto* thread = g_runnable_threads->head(); thread;) { auto* next_thread = thread->next(); - if (callback(*thread) == IterationDecision::Abort) + if (callback(*thread) == IterationDecision::Break) return; thread = next_thread; } @@ -257,7 +255,7 @@ inline void Thread::for_each_nonrunnable(Callback callback) ASSERT_INTERRUPTS_DISABLED(); for (auto* thread = g_nonrunnable_threads->head(); thread;) { auto* next_thread = thread->next(); - if (callback(*thread) == IterationDecision::Abort) + if (callback(*thread) == IterationDecision::Break) return; thread = next_thread; } diff --git a/Kernel/VM/MemoryManager.cpp b/Kernel/VM/MemoryManager.cpp index 06e66f670b..d45fcda41f 100644 --- a/Kernel/VM/MemoryManager.cpp +++ b/Kernel/VM/MemoryManager.cpp @@ -1,18 +1,17 @@ -#include -#include +#include "CMOS.h" +#include "Process.h" +#include "StdLib.h" #include #include -#include "i386.h" -#include "StdLib.h" -#include "Process.h" -#include "CMOS.h" +#include +#include +#include +#include //#define MM_DEBUG //#define PAGE_FAULT_DEBUG static MemoryManager* s_the; -unsigned MemoryManager::s_user_physical_pages_in_existence; -unsigned MemoryManager::s_super_physical_pages_in_existence; MemoryManager& MM { @@ -21,18 +20,9 @@ MemoryManager& MM MemoryManager::MemoryManager() { - // FIXME: This is not the best way to do memory map detection. - // Rewrite to use BIOS int 15,e820 once we have VM86 support. - word base_memory = (CMOS::read(0x16) << 8) | CMOS::read(0x15); - word ext_memory = (CMOS::read(0x18) << 8) | CMOS::read(0x17); - - kprintf("%u kB base memory\n", base_memory); - kprintf("%u kB extended memory\n", ext_memory); - - m_ram_size = ext_memory * 1024; - m_kernel_page_directory = PageDirectory::create_at_fixed_address(PhysicalAddress(0x4000)); m_page_table_zero = (dword*)0x6000; + m_page_table_one = (dword*)0x7000; initialize_paging(); @@ -47,6 +37,7 @@ void MemoryManager::populate_page_directory(PageDirectory& page_directory) { page_directory.m_directory_page = allocate_supervisor_physical_page(); page_directory.entries()[0] = kernel_page_directory().entries()[0]; + page_directory.entries()[1] = kernel_page_directory().entries()[1]; // Defer to the kernel page tables for 0xC0000000-0xFFFFFFFF for (int i = 768; i < 1024; ++i) page_directory.entries()[i] = kernel_page_directory().entries()[i]; @@ -57,6 +48,7 @@ void MemoryManager::initialize_paging() static_assert(sizeof(MemoryManager::PageDirectoryEntry) == 4); static_assert(sizeof(MemoryManager::PageTableEntry) == 4); memset(m_page_table_zero, 0, PAGE_SIZE); + memset(m_page_table_one, 0, PAGE_SIZE); #ifdef MM_DEBUG dbgprintf("MM: Kernel page directory @ %p\n", kernel_page_directory().cr3()); @@ -66,42 +58,93 @@ void MemoryManager::initialize_paging() dbgprintf("MM: Protect against null dereferences\n"); #endif // Make null dereferences crash. - map_protected(LinearAddress(0), PAGE_SIZE); + map_protected(VirtualAddress(0), PAGE_SIZE); #ifdef MM_DEBUG - dbgprintf("MM: Identity map bottom 4MB\n"); + dbgprintf("MM: Identity map bottom 5MB\n"); #endif - // The bottom 4 MB (except for the null page) are identity mapped & supervisor only. + // The bottom 5 MB (except for the null page) are identity mapped & supervisor only. // Every process shares these mappings. - create_identity_mapping(kernel_page_directory(), LinearAddress(PAGE_SIZE), (4 * MB) - PAGE_SIZE); + create_identity_mapping(kernel_page_directory(), VirtualAddress(PAGE_SIZE), (5 * MB) - PAGE_SIZE); // Basic memory map: // 0 -> 512 kB Kernel code. Root page directory & PDE 0. // (last page before 1MB) Used by quickmap_page(). - // 1 MB -> 2 MB kmalloc_eternal() space. - // 2 MB -> 3 MB kmalloc() space. - // 3 MB -> 4 MB Supervisor physical pages (available for allocation!) - // 4 MB -> 0xc0000000 Userspace physical pages (available for allocation!) - // 0xc0000000-0xffffffff Kernel-only linear address space + // 1 MB -> 3 MB kmalloc_eternal() space. + // 3 MB -> 4 MB kmalloc() space. + // 4 MB -> 5 MB Supervisor physical pages (available for allocation!) + // 5 MB -> 0xc0000000 Userspace physical pages (available for allocation!) + // 0xc0000000-0xffffffff Kernel-only virtual address space + +#ifdef MM_DEBUG + dbgprintf("MM: Quickmap will use %p\n", m_quickmap_addr.get()); +#endif + m_quickmap_addr = VirtualAddress((1 * MB) - PAGE_SIZE); + + RetainPtr region = nullptr; + bool region_is_super = false; + + for (auto* mmap = (multiboot_memory_map_t*)multiboot_info_ptr->mmap_addr; (unsigned long)mmap < multiboot_info_ptr->mmap_addr + multiboot_info_ptr->mmap_length; mmap = (multiboot_memory_map_t*)((unsigned long)mmap + mmap->size + sizeof(mmap->size))) { + kprintf("MM: Multiboot mmap: base_addr = 0x%x%08x, length = 0x%x%08x, type = 0x%x\n", + (dword)(mmap->addr >> 32), + (dword)(mmap->addr & 0xffffffff), + (dword)(mmap->len >> 32), + (dword)(mmap->len & 0xffffffff), + (dword)mmap->type); + + if (mmap->type != MULTIBOOT_MEMORY_AVAILABLE) + continue; + + // FIXME: Maybe make use of stuff below the 1MB mark? + if (mmap->addr < (1 * MB)) + continue; + +#ifdef MM_DEBUG + kprintf("MM: considering memory at %p - %p\n", + (dword)mmap->addr, (dword)(mmap->addr + mmap->len)); +#endif + + for (size_t page_base = mmap->addr; page_base < (mmap->addr + mmap->len); page_base += PAGE_SIZE) { + auto addr = PhysicalAddress(page_base); + + if (page_base < 4 * MB) { + // nothing + } else if (page_base >= 4 * MB && page_base < 5 * MB) { + if (region.is_null() || !region_is_super || region->upper().offset(PAGE_SIZE) != addr) { + m_super_physical_regions.append(PhysicalRegion::create(addr, addr)); + region = m_super_physical_regions.last(); + region_is_super = true; + } else { + region->expand(region->lower(), addr); + } + } else { + if (region.is_null() || region_is_super || region->upper().offset(PAGE_SIZE) != addr) { + m_user_physical_regions.append(PhysicalRegion::create(addr, addr)); + region = m_user_physical_regions.last(); + region_is_super = false; + } else { + region->expand(region->lower(), addr); + } + } + } + } + + for (auto& region : m_super_physical_regions) + m_super_physical_pages += region->finalize_capacity(); + + for (auto& region : m_user_physical_regions) + m_user_physical_pages += region->finalize_capacity(); - for (size_t i = (2 * MB); i < (4 * MB); i += PAGE_SIZE) - m_free_supervisor_physical_pages.append(PhysicalPage::create_eternal(PhysicalAddress(i), true)); - - dbgprintf("MM: 4MB-%uMB available for allocation\n", m_ram_size / 1048576); - for (size_t i = (4 * MB); i < m_ram_size; i += PAGE_SIZE) - m_free_physical_pages.append(PhysicalPage::create_eternal(PhysicalAddress(i), false)); - m_quickmap_addr = LinearAddress((1 * MB) - PAGE_SIZE); #ifdef MM_DEBUG - dbgprintf("MM: Quickmap will use P%x\n", m_quickmap_addr.get()); dbgprintf("MM: Installing page directory\n"); #endif - asm volatile("movl %%eax, %%cr3"::"a"(kernel_page_directory().cr3())); + asm volatile("movl %%eax, %%cr3" ::"a"(kernel_page_directory().cr3())); asm volatile( "movl %%cr0, %%eax\n" "orl $0x80000001, %%eax\n" - "movl %%eax, %%cr0\n" - :::"%eax", "memory"); + "movl %%eax, %%cr0\n" :: + : "%eax", "memory"); #ifdef MM_DEBUG dbgprintf("MM: Paging initialized.\n"); @@ -118,12 +161,12 @@ RetainPtr MemoryManager::allocate_page_table(PageDirectory& page_d return physical_page; } -void MemoryManager::remove_identity_mapping(PageDirectory& page_directory, LinearAddress laddr, size_t size) +void MemoryManager::remove_identity_mapping(PageDirectory& page_directory, VirtualAddress vaddr, size_t size) { InterruptDisabler disabler; - // FIXME: ASSERT(laddr is 4KB aligned); + // FIXME: ASSERT(vaddr is 4KB aligned); for (dword offset = 0; offset < size; offset += PAGE_SIZE) { - auto pte_address = laddr.offset(offset); + auto pte_address = vaddr.offset(offset); auto pte = ensure_pte(page_directory, pte_address); pte.set_physical_page_base(0); pte.set_user_allowed(false); @@ -133,16 +176,16 @@ void MemoryManager::remove_identity_mapping(PageDirectory& page_directory, Linea } } -auto MemoryManager::ensure_pte(PageDirectory& page_directory, LinearAddress laddr) -> PageTableEntry +auto MemoryManager::ensure_pte(PageDirectory& page_directory, VirtualAddress vaddr) -> PageTableEntry { ASSERT_INTERRUPTS_DISABLED(); - dword page_directory_index = (laddr.get() >> 22) & 0x3ff; - dword page_table_index = (laddr.get() >> 12) & 0x3ff; + dword page_directory_index = (vaddr.get() >> 22) & 0x3ff; + dword page_table_index = (vaddr.get() >> 12) & 0x3ff; PageDirectoryEntry pde = PageDirectoryEntry(&page_directory.entries()[page_directory_index]); if (!pde.is_present()) { #ifdef MM_DEBUG - dbgprintf("MM: PDE %u not present (requested for L%x), allocating\n", page_directory_index, laddr.get()); + dbgprintf("MM: PDE %u not present (requested for L%x), allocating\n", page_directory_index, vaddr.get()); #endif if (page_directory_index == 0) { ASSERT(&page_directory == m_kernel_page_directory); @@ -150,6 +193,12 @@ auto MemoryManager::ensure_pte(PageDirectory& page_directory, LinearAddress ladd pde.set_user_allowed(false); pde.set_present(true); pde.set_writable(true); + } else if (page_directory_index == 1) { + ASSERT(&page_directory == m_kernel_page_directory); + pde.set_page_table_base((dword)m_page_table_one); + pde.set_user_allowed(false); + pde.set_present(true); + pde.set_writable(true); } else { //ASSERT(&page_directory != m_kernel_page_directory.ptr()); auto page_table = allocate_page_table(page_directory, page_directory_index); @@ -159,7 +208,7 @@ auto MemoryManager::ensure_pte(PageDirectory& page_directory, LinearAddress ladd &page_directory == m_kernel_page_directory ? "Kernel" : "User", page_directory.cr3(), page_directory_index, - laddr.get(), + vaddr.get(), page_table->paddr().get()); #endif @@ -173,12 +222,12 @@ auto MemoryManager::ensure_pte(PageDirectory& page_directory, LinearAddress ladd return PageTableEntry(&pde.page_table_base()[page_table_index]); } -void MemoryManager::map_protected(LinearAddress laddr, size_t length) +void MemoryManager::map_protected(VirtualAddress vaddr, size_t length) { InterruptDisabler disabler; - // FIXME: ASSERT(linearAddress is 4KB aligned); + ASSERT(vaddr.is_page_aligned()); for (dword offset = 0; offset < length; offset += PAGE_SIZE) { - auto pte_address = laddr.offset(offset); + auto pte_address = vaddr.offset(offset); auto pte = ensure_pte(kernel_page_directory(), pte_address); pte.set_physical_page_base(pte_address.get()); pte.set_user_allowed(false); @@ -188,12 +237,12 @@ void MemoryManager::map_protected(LinearAddress laddr, size_t length) } } -void MemoryManager::create_identity_mapping(PageDirectory& page_directory, LinearAddress laddr, size_t size) +void MemoryManager::create_identity_mapping(PageDirectory& page_directory, VirtualAddress vaddr, size_t size) { InterruptDisabler disabler; - ASSERT((laddr.get() & ~PAGE_MASK) == 0); + ASSERT((vaddr.get() & ~PAGE_MASK) == 0); for (dword offset = 0; offset < size; offset += PAGE_SIZE) { - auto pte_address = laddr.offset(offset); + auto pte_address = vaddr.offset(offset); auto pte = ensure_pte(page_directory, pte_address); pte.set_physical_page_base(pte_address.get()); pte.set_user_allowed(false); @@ -208,41 +257,41 @@ void MemoryManager::initialize() s_the = new MemoryManager; } -Region* MemoryManager::region_from_laddr(Process& process, LinearAddress laddr) +Region* MemoryManager::region_from_vaddr(Process& process, VirtualAddress vaddr) { ASSERT_INTERRUPTS_DISABLED(); - if (laddr.get() >= 0xc0000000) { + if (vaddr.get() >= 0xc0000000) { for (auto& region : MM.m_kernel_regions) { - if (region->contains(laddr)) + if (region->contains(vaddr)) return region; } } // FIXME: Use a binary search tree (maybe red/black?) or some other more appropriate data structure! for (auto& region : process.m_regions) { - if (region->contains(laddr)) + if (region->contains(vaddr)) return region.ptr(); } - dbgprintf("%s(%u) Couldn't find region for L%x (CR3=%x)\n", process.name().characters(), process.pid(), laddr.get(), process.page_directory().cr3()); + dbgprintf("%s(%u) Couldn't find region for L%x (CR3=%x)\n", process.name().characters(), process.pid(), vaddr.get(), process.page_directory().cr3()); return nullptr; } -const Region* MemoryManager::region_from_laddr(const Process& process, LinearAddress laddr) +const Region* MemoryManager::region_from_vaddr(const Process& process, VirtualAddress vaddr) { - if (laddr.get() >= 0xc0000000) { + if (vaddr.get() >= 0xc0000000) { for (auto& region : MM.m_kernel_regions) { - if (region->contains(laddr)) + if (region->contains(vaddr)) return region; } } // FIXME: Use a binary search tree (maybe red/black?) or some other more appropriate data structure! for (auto& region : process.m_regions) { - if (region->contains(laddr)) + if (region->contains(vaddr)) return region.ptr(); } - dbgprintf("%s(%u) Couldn't find region for L%x (CR3=%x)\n", process.name().characters(), process.pid(), laddr.get(), process.page_directory().cr3()); + dbgprintf("%s(%u) Couldn't find region for L%x (CR3=%x)\n", process.name().characters(), process.pid(), vaddr.get(), process.page_directory().cr3()); return nullptr; } @@ -261,7 +310,7 @@ bool MemoryManager::zero_page(Region& region, unsigned page_index_in_region) remap_region_page(region, page_index_in_region, true); return true; } - auto physical_page = allocate_physical_page(ShouldZeroFill::Yes); + auto physical_page = allocate_user_physical_page(ShouldZeroFill::Yes); #ifdef PAGE_FAULT_DEBUG dbgprintf(" >> ZERO P%x\n", physical_page->paddr().get()); #endif @@ -288,9 +337,9 @@ bool MemoryManager::copy_on_write(Region& region, unsigned page_index_in_region) dbgprintf(" >> It's a COW page and it's time to COW!\n"); #endif auto physical_page_to_copy = move(vmo.physical_pages()[page_index_in_region]); - auto physical_page = allocate_physical_page(ShouldZeroFill::No); + auto physical_page = allocate_user_physical_page(ShouldZeroFill::No); byte* dest_ptr = quickmap_page(*physical_page); - const byte* src_ptr = region.laddr().offset(page_index_in_region * PAGE_SIZE).as_ptr(); + const byte* src_ptr = region.vaddr().offset(page_index_in_region * PAGE_SIZE).as_ptr(); #ifdef PAGE_FAULT_DEBUG dbgprintf(" >> COW P%x <- P%x\n", physical_page->paddr().get(), physical_page_to_copy->paddr().get()); #endif @@ -302,7 +351,6 @@ bool MemoryManager::copy_on_write(Region& region, unsigned page_index_in_region) return true; } - bool MemoryManager::page_in_from_inode(Region& region, unsigned page_index_in_region) { ASSERT(region.page_directory()); @@ -340,13 +388,13 @@ bool MemoryManager::page_in_from_inode(Region& region, unsigned page_index_in_re memset(page_buffer + nread, 0, PAGE_SIZE - nread); } cli(); - vmo_page = allocate_physical_page(ShouldZeroFill::No); + vmo_page = allocate_user_physical_page(ShouldZeroFill::No); if (vmo_page.is_null()) { kprintf("MM: page_in_from_inode was unable to allocate a physical page\n"); return false; } remap_region_page(region, page_index_in_region, true); - byte* dest_ptr = region.laddr().offset(page_index_in_region * PAGE_SIZE).as_ptr(); + byte* dest_ptr = region.vaddr().offset(page_index_in_region * PAGE_SIZE).as_ptr(); memcpy(dest_ptr, page_buffer, PAGE_SIZE); return true; } @@ -356,15 +404,15 @@ PageFaultResponse MemoryManager::handle_page_fault(const PageFault& fault) ASSERT_INTERRUPTS_DISABLED(); ASSERT(current); #ifdef PAGE_FAULT_DEBUG - dbgprintf("MM: handle_page_fault(%w) at L%x\n", fault.code(), fault.laddr().get()); + dbgprintf("MM: handle_page_fault(%w) at L%x\n", fault.code(), fault.vaddr().get()); #endif - ASSERT(fault.laddr() != m_quickmap_addr); - auto* region = region_from_laddr(current->process(), fault.laddr()); + ASSERT(fault.vaddr() != m_quickmap_addr); + auto* region = region_from_vaddr(current->process(), fault.vaddr()); if (!region) { - kprintf("NP(error) fault at invalid address L%x\n", fault.laddr().get()); + kprintf("NP(error) fault at invalid address L%x\n", fault.vaddr().get()); return PageFaultResponse::ShouldCrash; } - auto page_index_in_region = region->page_index_from_address(fault.laddr()); + auto page_index_in_region = region->page_index_from_address(fault.vaddr()); if (fault.is_not_present()) { if (region->vmo().inode()) { #ifdef PAGE_FAULT_DEBUG @@ -388,7 +436,7 @@ PageFaultResponse MemoryManager::handle_page_fault(const PageFault& fault) ASSERT(success); return PageFaultResponse::Continue; } - kprintf("PV(error) fault in Region{%p}[%u] at L%x\n", region, page_index_in_region, fault.laddr().get()); + kprintf("PV(error) fault in Region{%p}[%u] at L%x\n", region, page_index_in_region, fault.vaddr().get()); } else { ASSERT_NOT_REACHED(); } @@ -410,40 +458,114 @@ RetainPtr MemoryManager::allocate_kernel_region(size_t size, String&& na return region; } -RetainPtr MemoryManager::allocate_physical_page(ShouldZeroFill should_zero_fill) +void MemoryManager::deallocate_user_physical_page(PhysicalPage&& page) +{ + for (auto& region : m_user_physical_regions) { + if (!region->contains(page)) { + kprintf( + "MM: deallocate_user_physical_page: %p not in %p -> %p\n", + page.paddr(), region->lower().get(), region->upper().get()); + continue; + } + + region->return_page(move(page)); + m_user_physical_pages_used--; + + return; + } + + kprintf("MM: deallocate_user_physical_page couldn't figure out region for user page @ %p\n", page.paddr()); + ASSERT_NOT_REACHED(); +} + +RetainPtr MemoryManager::allocate_user_physical_page(ShouldZeroFill should_zero_fill) { InterruptDisabler disabler; - if (1 > m_free_physical_pages.size()) { - kprintf("FUCK! No physical pages available.\n"); - ASSERT_NOT_REACHED(); - return { }; + + RetainPtr page = nullptr; + + for (auto& region : m_user_physical_regions) { + page = region->take_free_page(false); + if (page.is_null()) + continue; } + + if (!page) { + if (m_user_physical_regions.is_empty()) { + kprintf("MM: no user physical regions available (?)\n"); + } + + kprintf("MM: no user physical pages available\n"); + ASSERT_NOT_REACHED(); + return {}; + } + #ifdef MM_DEBUG - dbgprintf("MM: allocate_physical_page vending P%x (%u remaining)\n", m_free_physical_pages.last()->paddr().get(), m_free_physical_pages.size()); + dbgprintf("MM: allocate_user_physical_page vending P%p\n", page->paddr().get()); #endif - auto physical_page = m_free_physical_pages.take_last(); + if (should_zero_fill == ShouldZeroFill::Yes) { - auto* ptr = (dword*)quickmap_page(*physical_page); + auto* ptr = (dword*)quickmap_page(*page); fast_dword_fill(ptr, 0, PAGE_SIZE / sizeof(dword)); unquickmap_page(); } - return physical_page; + + m_user_physical_pages_used++; + + return page; +} + +void MemoryManager::deallocate_supervisor_physical_page(PhysicalPage&& page) +{ + for (auto& region : m_super_physical_regions) { + if (!region->contains(page)) { + kprintf( + "MM: deallocate_supervisor_physical_page: %p not in %p -> %p\n", + page.paddr(), region->lower().get(), region->upper().get()); + continue; + } + + region->return_page(move(page)); + m_super_physical_pages_used--; + + return; + } + + kprintf("MM: deallocate_supervisor_physical_page couldn't figure out region for super page @ %p\n", page.paddr()); + ASSERT_NOT_REACHED(); } RetainPtr MemoryManager::allocate_supervisor_physical_page() { InterruptDisabler disabler; - if (1 > m_free_supervisor_physical_pages.size()) { - kprintf("FUCK! No physical pages available.\n"); - ASSERT_NOT_REACHED(); - return { }; + + RetainPtr page = nullptr; + + for (auto& region : m_super_physical_regions) { + page = region->take_free_page(true); + if (page.is_null()) + continue; } + + if (!page) { + if (m_super_physical_regions.is_empty()) { + kprintf("MM: no super physical regions available (?)\n"); + } + + kprintf("MM: no super physical pages available\n"); + ASSERT_NOT_REACHED(); + return {}; + } + #ifdef MM_DEBUG - dbgprintf("MM: allocate_supervisor_physical_page vending P%x (%u remaining)\n", m_free_supervisor_physical_pages.last()->paddr().get(), m_free_supervisor_physical_pages.size()); + dbgprintf("MM: allocate_supervisor_physical_page vending P%p\n", page->paddr().get()); #endif - auto physical_page = m_free_supervisor_physical_pages.take_last(); - fast_dword_fill((dword*)physical_page->paddr().as_ptr(), 0, PAGE_SIZE / sizeof(dword)); - return physical_page; + + fast_dword_fill((dword*)page->paddr().as_ptr(), 0, PAGE_SIZE / sizeof(dword)); + + m_super_physical_pages_used++; + + return page; } void MemoryManager::enter_process_paging_scope(Process& process) @@ -451,37 +573,34 @@ void MemoryManager::enter_process_paging_scope(Process& process) ASSERT(current); InterruptDisabler disabler; current->tss().cr3 = process.page_directory().cr3(); - asm volatile("movl %%eax, %%cr3"::"a"(process.page_directory().cr3()):"memory"); -} - -void MemoryManager::enter_kernel_paging_scope() -{ - InterruptDisabler disabler; - asm volatile("movl %%eax, %%cr3"::"a"(kernel_page_directory().cr3()):"memory"); + asm volatile("movl %%eax, %%cr3" ::"a"(process.page_directory().cr3()) + : "memory"); } void MemoryManager::flush_entire_tlb() { asm volatile( "mov %%cr3, %%eax\n" - "mov %%eax, %%cr3\n" - ::: "%eax", "memory" - ); + "mov %%eax, %%cr3\n" :: + : "%eax", "memory"); } -void MemoryManager::flush_tlb(LinearAddress laddr) +void MemoryManager::flush_tlb(VirtualAddress vaddr) { - asm volatile("invlpg %0": :"m" (*(char*)laddr.get()) : "memory"); + asm volatile("invlpg %0" + : + : "m"(*(char*)vaddr.get()) + : "memory"); } -void MemoryManager::map_for_kernel(LinearAddress laddr, PhysicalAddress paddr) +void MemoryManager::map_for_kernel(VirtualAddress vaddr, PhysicalAddress paddr) { - auto pte = ensure_pte(kernel_page_directory(), laddr); + auto pte = ensure_pte(kernel_page_directory(), vaddr); pte.set_physical_page_base(paddr.get()); pte.set_present(true); pte.set_writable(true); pte.set_user_allowed(false); - flush_tlb(laddr); + flush_tlb(vaddr); } byte* MemoryManager::quickmap_page(PhysicalPage& physical_page) @@ -489,35 +608,35 @@ byte* MemoryManager::quickmap_page(PhysicalPage& physical_page) ASSERT_INTERRUPTS_DISABLED(); ASSERT(!m_quickmap_in_use); m_quickmap_in_use = true; - auto page_laddr = m_quickmap_addr; - auto pte = ensure_pte(kernel_page_directory(), page_laddr); + auto page_vaddr = m_quickmap_addr; + auto pte = ensure_pte(kernel_page_directory(), page_vaddr); pte.set_physical_page_base(physical_page.paddr().get()); pte.set_present(true); pte.set_writable(true); pte.set_user_allowed(false); - flush_tlb(page_laddr); + flush_tlb(page_vaddr); ASSERT((dword)pte.physical_page_base() == physical_page.paddr().get()); #ifdef MM_DEBUG - dbgprintf("MM: >> quickmap_page L%x => P%x @ PTE=%p\n", page_laddr, physical_page.paddr().get(), pte.ptr()); + dbgprintf("MM: >> quickmap_page L%x => P%x @ PTE=%p\n", page_vaddr, physical_page.paddr().get(), pte.ptr()); #endif - return page_laddr.as_ptr(); + return page_vaddr.as_ptr(); } void MemoryManager::unquickmap_page() { ASSERT_INTERRUPTS_DISABLED(); ASSERT(m_quickmap_in_use); - auto page_laddr = m_quickmap_addr; - auto pte = ensure_pte(kernel_page_directory(), page_laddr); + auto page_vaddr = m_quickmap_addr; + auto pte = ensure_pte(kernel_page_directory(), page_vaddr); #ifdef MM_DEBUG auto old_physical_address = pte.physical_page_base(); #endif pte.set_physical_page_base(0); pte.set_present(false); pte.set_writable(false); - flush_tlb(page_laddr); + flush_tlb(page_vaddr); #ifdef MM_DEBUG - dbgprintf("MM: >> unquickmap_page L%x =/> P%x\n", page_laddr, old_physical_address); + dbgprintf("MM: >> unquickmap_page L%x =/> P%x\n", page_vaddr, old_physical_address); #endif m_quickmap_in_use = false; } @@ -526,8 +645,8 @@ void MemoryManager::remap_region_page(Region& region, unsigned page_index_in_reg { ASSERT(region.page_directory()); InterruptDisabler disabler; - auto page_laddr = region.laddr().offset(page_index_in_region * PAGE_SIZE); - auto pte = ensure_pte(*region.page_directory(), page_laddr); + auto page_vaddr = region.vaddr().offset(page_index_in_region * PAGE_SIZE); + auto pte = ensure_pte(*region.page_directory(), page_vaddr); auto& physical_page = region.vmo().physical_pages()[page_index_in_region]; ASSERT(physical_page); pte.set_physical_page_base(physical_page->paddr().get()); @@ -539,9 +658,9 @@ void MemoryManager::remap_region_page(Region& region, unsigned page_index_in_reg pte.set_cache_disabled(!region.vmo().m_allow_cpu_caching); pte.set_write_through(!region.vmo().m_allow_cpu_caching); pte.set_user_allowed(user_allowed); - region.page_directory()->flush(page_laddr); + region.page_directory()->flush(page_vaddr); #ifdef MM_DEBUG - dbgprintf("MM: >> remap_region_page (PD=%x, PTE=P%x) '%s' L%x => P%x (@%p)\n", region.page_directory()->cr3(), pte.ptr(), region.name().characters(), page_laddr.get(), physical_page->paddr().get(), physical_page.ptr()); + dbgprintf("MM: >> remap_region_page (PD=%x, PTE=P%x) '%s' L%x => P%x (@%p)\n", region.page_directory()->cr3(), pte.ptr(), region.name().characters(), page_vaddr.get(), physical_page->paddr().get(), physical_page.ptr()); #endif } @@ -549,10 +668,10 @@ void MemoryManager::remap_region(PageDirectory& page_directory, Region& region) { InterruptDisabler disabler; ASSERT(region.page_directory() == &page_directory); - map_region_at_address(page_directory, region, region.laddr(), true); + map_region_at_address(page_directory, region, region.vaddr(), true); } -void MemoryManager::map_region_at_address(PageDirectory& page_directory, Region& region, LinearAddress laddr, bool user_allowed) +void MemoryManager::map_region_at_address(PageDirectory& page_directory, Region& region, VirtualAddress vaddr, bool user_allowed) { InterruptDisabler disabler; region.set_page_directory(page_directory); @@ -561,8 +680,8 @@ void MemoryManager::map_region_at_address(PageDirectory& page_directory, Region& dbgprintf("MM: map_region_at_address will map VMO pages %u - %u (VMO page count: %u)\n", region.first_page_index(), region.last_page_index(), vmo.page_count()); #endif for (size_t i = 0; i < region.page_count(); ++i) { - auto page_laddr = laddr.offset(i * PAGE_SIZE); - auto pte = ensure_pte(page_directory, page_laddr); + auto page_vaddr = vaddr.offset(i * PAGE_SIZE); + auto pte = ensure_pte(page_directory, page_vaddr); auto& physical_page = vmo.physical_pages()[region.first_page_index() + i]; if (physical_page) { pte.set_physical_page_base(physical_page->paddr().get()); @@ -580,9 +699,9 @@ void MemoryManager::map_region_at_address(PageDirectory& page_directory, Region& pte.set_writable(region.is_writable()); } pte.set_user_allowed(user_allowed); - page_directory.flush(page_laddr); + page_directory.flush(page_vaddr); #ifdef MM_DEBUG - dbgprintf("MM: >> map_region_at_address (PD=%x) '%s' L%x => P%x (@%p)\n", &page_directory, region.name().characters(), page_laddr, physical_page ? physical_page->paddr().get() : 0, physical_page.ptr()); + dbgprintf("MM: >> map_region_at_address (PD=%x) '%s' L%x => P%x (@%p)\n", &page_directory, region.name().characters(), page_vaddr, physical_page ? physical_page->paddr().get() : 0, physical_page.ptr()); #endif } } @@ -592,16 +711,16 @@ bool MemoryManager::unmap_region(Region& region) ASSERT(region.page_directory()); InterruptDisabler disabler; for (size_t i = 0; i < region.page_count(); ++i) { - auto laddr = region.laddr().offset(i * PAGE_SIZE); - auto pte = ensure_pte(*region.page_directory(), laddr); + auto vaddr = region.vaddr().offset(i * PAGE_SIZE); + auto pte = ensure_pte(*region.page_directory(), vaddr); pte.set_physical_page_base(0); pte.set_present(false); pte.set_writable(false); pte.set_user_allowed(false); - region.page_directory()->flush(laddr); + region.page_directory()->flush(vaddr); #ifdef MM_DEBUG auto& physical_page = region.vmo().physical_pages()[region.first_page_index() + i]; - dbgprintf("MM: >> Unmapped L%x => P%x <<\n", laddr, physical_page ? physical_page->paddr().get() : 0); + dbgprintf("MM: >> Unmapped L%x => P%x <<\n", vaddr, physical_page ? physical_page->paddr().get() : 0); #endif } region.release_page_directory(); @@ -610,19 +729,19 @@ bool MemoryManager::unmap_region(Region& region) bool MemoryManager::map_region(Process& process, Region& region) { - map_region_at_address(process.page_directory(), region, region.laddr(), true); + map_region_at_address(process.page_directory(), region, region.vaddr(), true); return true; } -bool MemoryManager::validate_user_read(const Process& process, LinearAddress laddr) const +bool MemoryManager::validate_user_read(const Process& process, VirtualAddress vaddr) const { - auto* region = region_from_laddr(process, laddr); + auto* region = region_from_vaddr(process, vaddr); return region && region->is_readable(); } -bool MemoryManager::validate_user_write(const Process& process, LinearAddress laddr) const +bool MemoryManager::validate_user_write(const Process& process, VirtualAddress vaddr) const { - auto* region = region_from_laddr(process, laddr); + auto* region = region_from_vaddr(process, vaddr); return region && region->is_writable(); } @@ -641,7 +760,7 @@ void MemoryManager::unregister_vmo(VMObject& vmo) void MemoryManager::register_region(Region& region) { InterruptDisabler disabler; - if (region.laddr().get() >= 0xc0000000) + if (region.vaddr().get() >= 0xc0000000) m_kernel_regions.set(®ion); else m_user_regions.set(®ion); @@ -650,7 +769,7 @@ void MemoryManager::register_region(Region& region) void MemoryManager::unregister_region(Region& region) { InterruptDisabler disabler; - if (region.laddr().get() >= 0xc0000000) + if (region.vaddr().get() >= 0xc0000000) m_kernel_regions.remove(®ion); else m_user_regions.remove(®ion); @@ -666,14 +785,3 @@ ProcessPagingScope::~ProcessPagingScope() { MM.enter_process_paging_scope(current->process()); } - -KernelPagingScope::KernelPagingScope() -{ - ASSERT(current); - MM.enter_kernel_paging_scope(); -} - -KernelPagingScope::~KernelPagingScope() -{ - MM.enter_process_paging_scope(current->process()); -} diff --git a/Kernel/VM/MemoryManager.h b/Kernel/VM/MemoryManager.h index b45cfcbf00..efa291e41c 100644 --- a/Kernel/VM/MemoryManager.h +++ b/Kernel/VM/MemoryManager.h @@ -1,6 +1,5 @@ #pragma once -#include "i386.h" #include #include #include @@ -11,18 +10,19 @@ #include #include #include +#include #include -#include #include +#include #include #include +#include #define PAGE_ROUND_UP(x) ((((dword)(x)) + PAGE_SIZE - 1) & (~(PAGE_SIZE - 1))) class SynthFSInode; -enum class PageFaultResponse -{ +enum class PageFaultResponse { ShouldCrash, Continue, }; @@ -33,6 +33,7 @@ class MemoryManager { AK_MAKE_ETERNAL friend class PageDirectory; friend class PhysicalPage; + friend class PhysicalRegion; friend class Region; friend class VMObject; friend ByteBuffer procfs$mm(InodeIdentifier); @@ -51,31 +52,31 @@ public: void populate_page_directory(PageDirectory&); void enter_process_paging_scope(Process&); - void enter_kernel_paging_scope(); - bool validate_user_read(const Process&, LinearAddress) const; - bool validate_user_write(const Process&, LinearAddress) const; + bool validate_user_read(const Process&, VirtualAddress) const; + bool validate_user_write(const Process&, VirtualAddress) const; - enum class ShouldZeroFill - { + enum class ShouldZeroFill { No, Yes }; - RetainPtr allocate_physical_page(ShouldZeroFill); + RetainPtr allocate_user_physical_page(ShouldZeroFill); RetainPtr allocate_supervisor_physical_page(); + void deallocate_user_physical_page(PhysicalPage&&); + void deallocate_supervisor_physical_page(PhysicalPage&&); void remap_region(PageDirectory&, Region&); - size_t ram_size() const { return m_ram_size; } - - int user_physical_pages_in_existence() const { return s_user_physical_pages_in_existence; } - int super_physical_pages_in_existence() const { return s_super_physical_pages_in_existence; } - - void map_for_kernel(LinearAddress, PhysicalAddress); + void map_for_kernel(VirtualAddress, PhysicalAddress); RetainPtr allocate_kernel_region(size_t, String&& name); - void map_region_at_address(PageDirectory&, Region&, LinearAddress, bool user_accessible); + void map_region_at_address(PageDirectory&, Region&, VirtualAddress, bool user_accessible); + + unsigned user_physical_pages() const { return m_user_physical_pages; } + unsigned user_physical_pages_used() const { return m_user_physical_pages_used; } + unsigned super_physical_pages() const { return m_super_physical_pages; } + unsigned super_physical_pages_used() const { return m_super_physical_pages_used; } private: MemoryManager(); @@ -90,17 +91,17 @@ private: void initialize_paging(); void flush_entire_tlb(); - void flush_tlb(LinearAddress); + void flush_tlb(VirtualAddress); RetainPtr allocate_page_table(PageDirectory&, unsigned index); - void map_protected(LinearAddress, size_t length); + void map_protected(VirtualAddress, size_t length); - void create_identity_mapping(PageDirectory&, LinearAddress, size_t length); - void remove_identity_mapping(PageDirectory&, LinearAddress, size_t); + void create_identity_mapping(PageDirectory&, VirtualAddress, size_t length); + void remove_identity_mapping(PageDirectory&, VirtualAddress, size_t); - static Region* region_from_laddr(Process&, LinearAddress); - static const Region* region_from_laddr(const Process&, LinearAddress); + static Region* region_from_vaddr(Process&, VirtualAddress); + static const Region* region_from_vaddr(const Process&, VirtualAddress); bool copy_on_write(Region&, unsigned page_index_in_region); bool page_in_from_inode(Region&, unsigned page_index_in_region); @@ -127,8 +128,7 @@ private: dword raw() const { return *m_pde; } dword* ptr() { return m_pde; } - enum Flags - { + enum Flags { Present = 1 << 0, ReadWrite = 1 << 1, UserSupervisor = 1 << 2, @@ -178,8 +178,7 @@ private: dword raw() const { return *m_pte; } dword* ptr() { return m_pte; } - enum Flags - { + enum Flags { Present = 1 << 0, ReadWrite = 1 << 1, UserSupervisor = 1 << 2, @@ -213,24 +212,26 @@ private: dword* m_pte; }; - static unsigned s_user_physical_pages_in_existence; - static unsigned s_super_physical_pages_in_existence; - - PageTableEntry ensure_pte(PageDirectory&, LinearAddress); + PageTableEntry ensure_pte(PageDirectory&, VirtualAddress); RetainPtr m_kernel_page_directory; - dword* m_page_table_zero; + dword* m_page_table_zero { nullptr }; + dword* m_page_table_one { nullptr }; - LinearAddress m_quickmap_addr; + VirtualAddress m_quickmap_addr; - Vector> m_free_physical_pages; - Vector> m_free_supervisor_physical_pages; + unsigned m_user_physical_pages { 0 }; + unsigned m_user_physical_pages_used { 0 }; + unsigned m_super_physical_pages { 0 }; + unsigned m_super_physical_pages_used { 0 }; + + Vector> m_user_physical_regions {}; + Vector> m_super_physical_regions {}; HashTable m_vmos; HashTable m_user_regions; HashTable m_kernel_regions; - size_t m_ram_size { 0 }; bool m_quickmap_in_use { false }; }; @@ -238,8 +239,3 @@ struct ProcessPagingScope { ProcessPagingScope(Process&); ~ProcessPagingScope(); }; - -struct KernelPagingScope { - KernelPagingScope(); - ~KernelPagingScope(); -}; diff --git a/Kernel/VM/PageDirectory.cpp b/Kernel/VM/PageDirectory.cpp index befd020ce4..7bc5ff3932 100644 --- a/Kernel/VM/PageDirectory.cpp +++ b/Kernel/VM/PageDirectory.cpp @@ -1,19 +1,19 @@ -#include -#include #include #include +#include +#include static const dword userspace_range_base = 0x01000000; static const dword kernelspace_range_base = 0xc0000000; PageDirectory::PageDirectory(PhysicalAddress paddr) - : m_range_allocator(LinearAddress(0xc0000000), 0x3f000000) + : m_range_allocator(VirtualAddress(0xc0000000), 0x3f000000) { - m_directory_page = PhysicalPage::create_eternal(paddr, true); + m_directory_page = PhysicalPage::create(paddr, true, false); } PageDirectory::PageDirectory(const RangeAllocator* parent_range_allocator) - : m_range_allocator(parent_range_allocator ? RangeAllocator(*parent_range_allocator) : RangeAllocator(LinearAddress(userspace_range_base), kernelspace_range_base - userspace_range_base)) + : m_range_allocator(parent_range_allocator ? RangeAllocator(*parent_range_allocator) : RangeAllocator(VirtualAddress(userspace_range_base), kernelspace_range_base - userspace_range_base)) { MM.populate_page_directory(*this); } @@ -25,13 +25,13 @@ PageDirectory::~PageDirectory() #endif } -void PageDirectory::flush(LinearAddress laddr) +void PageDirectory::flush(VirtualAddress vaddr) { #ifdef MM_DEBUG - dbgprintf("MM: Flush page L%x\n", laddr.get()); + dbgprintf("MM: Flush page L%x\n", vaddr.get()); #endif if (!current) return; - if (¤t->process().page_directory() == this) - MM.flush_tlb(laddr); + if (this == &MM.kernel_page_directory() || ¤t->process().page_directory() == this) + MM.flush_tlb(vaddr); } diff --git a/Kernel/VM/PageDirectory.h b/Kernel/VM/PageDirectory.h index 8207389ab7..b4f7ee876e 100644 --- a/Kernel/VM/PageDirectory.h +++ b/Kernel/VM/PageDirectory.h @@ -17,7 +17,7 @@ public: dword cr3() const { return m_directory_page->paddr().get(); } dword* entries() { return reinterpret_cast(cr3()); } - void flush(LinearAddress); + void flush(VirtualAddress); RangeAllocator& range_allocator() { return m_range_allocator; } diff --git a/Kernel/VM/PhysicalPage.cpp b/Kernel/VM/PhysicalPage.cpp index 459fde5c60..adc64e870b 100644 --- a/Kernel/VM/PhysicalPage.cpp +++ b/Kernel/VM/PhysicalPage.cpp @@ -1,18 +1,11 @@ -#include #include +#include #include -Retained PhysicalPage::create_eternal(PhysicalAddress paddr, bool supervisor) -{ - void* slot = kmalloc_eternal(sizeof(PhysicalPage)); - new (slot) PhysicalPage(paddr, supervisor); - return adopt(*(PhysicalPage*)slot); -} - -Retained PhysicalPage::create(PhysicalAddress paddr, bool supervisor) +Retained PhysicalPage::create(PhysicalAddress paddr, bool supervisor, bool may_return_to_freelist) { void* slot = kmalloc(sizeof(PhysicalPage)); - new (slot) PhysicalPage(paddr, supervisor, false); + new (slot) PhysicalPage(paddr, supervisor, may_return_to_freelist); return adopt(*(PhysicalPage*)slot); } @@ -21,21 +14,21 @@ PhysicalPage::PhysicalPage(PhysicalAddress paddr, bool supervisor, bool may_retu , m_supervisor(supervisor) , m_paddr(paddr) { - if (supervisor) - ++MemoryManager::s_super_physical_pages_in_existence; - else - ++MemoryManager::s_user_physical_pages_in_existence; } -void PhysicalPage::return_to_freelist() +void PhysicalPage::return_to_freelist() && { ASSERT((paddr().get() & ~PAGE_MASK) == 0); + InterruptDisabler disabler; + m_retain_count = 1; + if (m_supervisor) - MM.m_free_supervisor_physical_pages.append(adopt(*this)); + MM.deallocate_supervisor_physical_page(move(*this)); else - MM.m_free_physical_pages.append(adopt(*this)); + MM.deallocate_user_physical_page(move(*this)); + #ifdef MM_DEBUG dbgprintf("MM: P%x released to freelist\n", m_paddr.get()); #endif diff --git a/Kernel/VM/PhysicalPage.h b/Kernel/VM/PhysicalPage.h index bf2726bcef..7d5c8c9426 100644 --- a/Kernel/VM/PhysicalPage.h +++ b/Kernel/VM/PhysicalPage.h @@ -23,14 +23,12 @@ public: ASSERT(m_retain_count); if (!--m_retain_count) { if (m_may_return_to_freelist) - return_to_freelist(); - else - delete this; + move(*this).return_to_freelist(); + delete this; } } - static Retained create_eternal(PhysicalAddress, bool supervisor); - static Retained create(PhysicalAddress, bool supervisor); + static Retained create(PhysicalAddress, bool supervisor, bool may_return_to_freelist = true); word retain_count() const { return m_retain_count; } @@ -38,7 +36,7 @@ private: PhysicalPage(PhysicalAddress paddr, bool supervisor, bool may_return_to_freelist = true); ~PhysicalPage() {} - void return_to_freelist(); + void return_to_freelist() &&; word m_retain_count { 1 }; bool m_may_return_to_freelist { true }; diff --git a/Kernel/VM/PhysicalRegion.cpp b/Kernel/VM/PhysicalRegion.cpp new file mode 100644 index 0000000000..fd7021d977 --- /dev/null +++ b/Kernel/VM/PhysicalRegion.cpp @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include +#include +#include + +Retained PhysicalRegion::create(PhysicalAddress lower, PhysicalAddress upper) +{ + return adopt(*new PhysicalRegion(lower, upper)); +} + +PhysicalRegion::PhysicalRegion(PhysicalAddress lower, PhysicalAddress upper) + : m_lower(lower) + , m_upper(upper) + , m_bitmap(Bitmap::create()) +{ +} + +void PhysicalRegion::expand(PhysicalAddress lower, PhysicalAddress upper) +{ + ASSERT(!m_pages); + + m_lower = lower; + m_upper = upper; +} + +unsigned PhysicalRegion::finalize_capacity() +{ + ASSERT(!m_pages); + + m_pages = (m_upper.get() - m_lower.get()) / PAGE_SIZE; + m_bitmap.grow(m_pages, false); + + return size(); +} + +RetainPtr PhysicalRegion::take_free_page(bool supervisor) +{ + ASSERT(m_pages); + + if (m_used == m_pages) + return nullptr; + + // search from the last page we allocated + for (unsigned page = m_last; page < m_pages; page++) { + if (!m_bitmap.get(page)) { + m_bitmap.set(page, true); + m_used++; + m_last = page + 1; + return PhysicalPage::create(m_lower.offset(page * PAGE_SIZE), supervisor); + } + } + + // wrap back around to the start in case we missed something + for (unsigned page = 0; page < m_last; page++) { + if (!m_bitmap.get(page)) { + m_bitmap.set(page, true); + m_used++; + m_last = page + 1; + return PhysicalPage::create(m_lower.offset(page * PAGE_SIZE), supervisor); + } + } + + ASSERT_NOT_REACHED(); + + return nullptr; +} + +void PhysicalRegion::return_page_at(PhysicalAddress addr) +{ + ASSERT(m_pages); + + if (m_used == 0) { + ASSERT_NOT_REACHED(); + } + + int local_offset = addr.get() - m_lower.get(); + ASSERT(local_offset >= 0); + ASSERT(local_offset < m_pages * PAGE_SIZE); + + auto page = local_offset / PAGE_SIZE; + if (page < m_last) m_last = page; + + m_bitmap.set(page, false); + m_used--; +} diff --git a/Kernel/VM/PhysicalRegion.h b/Kernel/VM/PhysicalRegion.h new file mode 100644 index 0000000000..b14b6daf1a --- /dev/null +++ b/Kernel/VM/PhysicalRegion.h @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +#include +#include +#include + +class PhysicalRegion : public Retainable { + AK_MAKE_ETERNAL + +public: + static Retained create(PhysicalAddress lower, PhysicalAddress upper); + ~PhysicalRegion() {} + + void expand(PhysicalAddress lower, PhysicalAddress upper); + unsigned finalize_capacity(); + + PhysicalAddress lower() const { return m_lower; } + PhysicalAddress upper() const { return m_upper; } + unsigned size() const { return m_pages; } + unsigned used() const { return m_used; } + unsigned free() const { return m_pages - m_used; } + bool contains(PhysicalPage& page) const { return page.paddr() >= m_lower && page.paddr() <= m_upper; } + + RetainPtr take_free_page(bool supervisor); + void return_page_at(PhysicalAddress addr); + void return_page(PhysicalPage&& page) { return_page_at(page.paddr()); } + +private: + PhysicalRegion(PhysicalAddress lower, PhysicalAddress upper); + + PhysicalAddress m_lower; + PhysicalAddress m_upper; + unsigned m_pages { 0 }; + unsigned m_used { 0 }; + unsigned m_last { 0 }; + Bitmap m_bitmap; +}; diff --git a/Kernel/VM/RangeAllocator.cpp b/Kernel/VM/RangeAllocator.cpp index f077ff7383..f4fb7ab3c1 100644 --- a/Kernel/VM/RangeAllocator.cpp +++ b/Kernel/VM/RangeAllocator.cpp @@ -1,10 +1,10 @@ +#include #include #include -#include //#define VRA_DEBUG -RangeAllocator::RangeAllocator(LinearAddress base, size_t size) +RangeAllocator::RangeAllocator(VirtualAddress base, size_t size) { m_available_ranges.append({ base, size }); #ifdef VRA_DEBUG @@ -33,7 +33,7 @@ Vector Range::carve(const Range& taken) { Vector parts; if (taken == *this) - return { }; + return {}; if (taken.base() > base()) parts.append({ base(), taken.base().get() - base().get() }); if (taken.end() < end()) @@ -79,10 +79,10 @@ Range RangeAllocator::allocate_anywhere(size_t size) return allocated_range; } kprintf("VRA: Failed to allocate anywhere: %u\n", size); - return { }; + return {}; } -Range RangeAllocator::allocate_specific(LinearAddress base, size_t size) +Range RangeAllocator::allocate_specific(VirtualAddress base, size_t size) { Range allocated_range(base, size); for (int i = 0; i < m_available_ranges.size(); ++i) { @@ -101,7 +101,7 @@ Range RangeAllocator::allocate_specific(LinearAddress base, size_t size) return allocated_range; } kprintf("VRA: Failed to allocate specific range: %x(%u)\n", base.get(), size); - return { }; + return {}; } void RangeAllocator::deallocate(Range range) @@ -121,7 +121,7 @@ void RangeAllocator::deallocate(Range range) sort_and_merge: // FIXME: We don't have to sort if we insert at the right position immediately. - quick_sort(m_available_ranges.begin(), m_available_ranges.end(), [] (auto& a, auto& b) { + quick_sort(m_available_ranges.begin(), m_available_ranges.end(), [](auto& a, auto& b) { return a.base() < b.base(); }); diff --git a/Kernel/VM/RangeAllocator.h b/Kernel/VM/RangeAllocator.h index 7381aa5db7..1921d91b44 100644 --- a/Kernel/VM/RangeAllocator.h +++ b/Kernel/VM/RangeAllocator.h @@ -1,33 +1,33 @@ #pragma once #include -#include +#include class Range { friend class RangeAllocator; public: Range() {} - Range(LinearAddress base, size_t size) + Range(VirtualAddress base, size_t size) : m_base(base) , m_size(size) { } - LinearAddress base() const { return m_base; } + VirtualAddress base() const { return m_base; } size_t size() const { return m_size; } bool is_valid() const { return !m_base.is_null(); } - bool contains(LinearAddress laddr) const { return laddr >= base() && laddr < end(); } + bool contains(VirtualAddress vaddr) const { return vaddr >= base() && vaddr < end(); } - LinearAddress end() const { return m_base.offset(m_size); } + VirtualAddress end() const { return m_base.offset(m_size); } bool operator==(const Range& other) const { return m_base == other.m_base && m_size == other.m_size; } - bool contains(LinearAddress base, size_t size) const + bool contains(VirtualAddress base, size_t size) const { return base >= m_base && base.offset(size) <= end(); } @@ -40,18 +40,18 @@ public: Vector carve(const Range&); private: - LinearAddress m_base; + VirtualAddress m_base; size_t m_size { 0 }; }; class RangeAllocator { public: - RangeAllocator(LinearAddress, size_t); + RangeAllocator(VirtualAddress, size_t); RangeAllocator(const RangeAllocator&); ~RangeAllocator(); Range allocate_anywhere(size_t); - Range allocate_specific(LinearAddress, size_t); + Range allocate_specific(VirtualAddress, size_t); void deallocate(Range); void dump() const; diff --git a/Kernel/VM/Region.cpp b/Kernel/VM/Region.cpp index 3c93cfff7c..d3cfd0c655 100644 --- a/Kernel/VM/Region.cpp +++ b/Kernel/VM/Region.cpp @@ -1,13 +1,13 @@ -#include -#include -#include #include #include +#include +#include +#include -Region::Region(const Range& range, String&& n, byte access, bool cow) +Region::Region(const Range& range, const String& name, byte access, bool cow) : m_range(range) , m_vmo(VMObject::create_anonymous(size())) - , m_name(move(n)) + , m_name(name) , m_access(access) , m_cow_map(Bitmap::create(m_vmo->page_count(), cow)) { @@ -15,21 +15,21 @@ Region::Region(const Range& range, String&& n, byte access, bool cow) MM.register_region(*this); } -Region::Region(const Range& range, RetainPtr&& inode, String&& n, byte access) +Region::Region(const Range& range, RetainPtr&& inode, const String& name, byte access) : m_range(range) , m_vmo(VMObject::create_file_backed(move(inode))) - , m_name(move(n)) + , m_name(name) , m_access(access) , m_cow_map(Bitmap::create(m_vmo->page_count())) { MM.register_region(*this); } -Region::Region(const Range& range, Retained&& vmo, size_t offset_in_vmo, String&& n, byte access, bool cow) +Region::Region(const Range& range, Retained&& vmo, size_t offset_in_vmo, const String& name, byte access, bool cow) : m_range(range) , m_offset_in_vmo(offset_in_vmo) , m_vmo(move(vmo)) - , m_name(move(n)) + , m_name(name) , m_access(access) , m_cow_map(Bitmap::create(m_vmo->page_count(), cow)) { @@ -59,6 +59,7 @@ bool Region::page_in() bool success = MM.page_in_from_inode(*this, i); if (!success) return false; + continue; } MM.remap_region_page(*this, i, true); } @@ -71,10 +72,10 @@ Retained Region::clone() if (m_shared || (is_readable() && !is_writable())) { #ifdef MM_DEBUG dbgprintf("%s<%u> Region::clone(): sharing %s (L%x)\n", - current->process().name().characters(), - current->pid(), - m_name.characters(), - laddr().get()); + current->process().name().characters(), + current->pid(), + m_name.characters(), + vaddr().get()); #endif // Create a new region backed by the same VMObject. return adopt(*new Region(m_range, m_vmo.copy_ref(), m_offset_in_vmo, String(m_name), m_access)); @@ -82,10 +83,10 @@ Retained Region::clone() #ifdef MM_DEBUG dbgprintf("%s<%u> Region::clone(): cowing %s (L%x)\n", - current->process().name().characters(), - current->pid(), - m_name.characters(), - laddr().get()); + current->process().name().characters(), + current->pid(), + m_name.characters(), + vaddr().get()); #endif // Set up a COW region. The parent (this) region becomes COW as well! m_cow_map.fill(true); @@ -97,12 +98,12 @@ int Region::commit() { InterruptDisabler disabler; #ifdef MM_DEBUG - dbgprintf("MM: commit %u pages in Region %p (VMO=%p) at L%x\n", vmo().page_count(), this, &vmo(), laddr().get()); + dbgprintf("MM: commit %u pages in Region %p (VMO=%p) at L%x\n", vmo().page_count(), this, &vmo(), vaddr().get()); #endif for (size_t i = first_page_index(); i <= last_page_index(); ++i) { if (!vmo().physical_pages()[i].is_null()) continue; - auto physical_page = MM.allocate_physical_page(MemoryManager::ShouldZeroFill::Yes); + auto physical_page = MM.allocate_user_physical_page(MemoryManager::ShouldZeroFill::Yes); if (!physical_page) { kprintf("MM: commit was unable to allocate a physical page\n"); return -ENOMEM; diff --git a/Kernel/VM/Region.h b/Kernel/VM/Region.h index 76c6645f3e..ef094bc0b6 100644 --- a/Kernel/VM/Region.h +++ b/Kernel/VM/Region.h @@ -10,27 +10,27 @@ class VMObject; class Region : public Retainable { friend class MemoryManager; + public: - enum Access - { + enum Access { Read = 1, Write = 2, Execute = 4, }; - Region(const Range&, String&&, byte access, bool cow = false); - Region(const Range&, Retained&&, size_t offset_in_vmo, String&&, byte access, bool cow = false); - Region(const Range&, RetainPtr&&, String&&, byte access); + Region(const Range&, const String&, byte access, bool cow = false); + Region(const Range&, Retained&&, size_t offset_in_vmo, const String&, byte access, bool cow = false); + Region(const Range&, RetainPtr&&, const String&, byte access); ~Region(); - LinearAddress laddr() const { return m_range.base(); } + VirtualAddress vaddr() const { return m_range.base(); } size_t size() const { return m_range.size(); } bool is_readable() const { return m_access & Access::Read; } bool is_writable() const { return m_access & Access::Write; } bool is_executable() const { return m_access & Access::Execute; } - String name() const { return m_name; } + const String& name() const { return m_name; } - void set_name(String&& name) { m_name = move(name); } + void set_name(const String& name) { m_name = name; } const VMObject& vmo() const { return *m_vmo; } VMObject& vmo() { return *m_vmo; } @@ -40,14 +40,14 @@ public: Retained clone(); - bool contains(LinearAddress laddr) const + bool contains(VirtualAddress vaddr) const { - return m_range.contains(laddr); + return m_range.contains(vaddr); } - unsigned page_index_from_address(LinearAddress laddr) const + unsigned page_index_from_address(VirtualAddress vaddr) const { - return (laddr - m_range.base()).get() / PAGE_SIZE; + return (vaddr - m_range.base()).get() / PAGE_SIZE; } size_t first_page_index() const diff --git a/Kernel/VM/VMObject.cpp b/Kernel/VM/VMObject.cpp index 45cce32da0..34a8a2cf55 100644 --- a/Kernel/VM/VMObject.cpp +++ b/Kernel/VM/VMObject.cpp @@ -1,7 +1,7 @@ -#include -#include #include #include +#include +#include Retained VMObject::create_file_backed(RetainPtr&& inode) { @@ -54,12 +54,11 @@ VMObject::VMObject(PhysicalAddress paddr, size_t size) { MM.register_vmo(*this); for (size_t i = 0; i < size; i += PAGE_SIZE) { - m_physical_pages.append(PhysicalPage::create(paddr.offset(i), false)); + m_physical_pages.append(PhysicalPage::create(paddr.offset(i), false, false)); } ASSERT(m_physical_pages.size() == page_count()); } - VMObject::VMObject(RetainPtr&& inode) : m_inode(move(inode)) { @@ -113,7 +112,7 @@ void VMObject::inode_size_changed(Badge, size_t old_size, size_t new_size } // FIXME: Consolidate with inode_contents_changed() so we only do a single walk. - for_each_region([] (Region& region) { + for_each_region([](Region& region) { ASSERT(region.page_directory()); MM.remap_region(*region.page_directory(), region); }); @@ -165,7 +164,7 @@ void VMObject::inode_contents_changed(Badge, off_t offset, ssize_t size, #endif // FIXME: Consolidate with inode_size_changed() so we only do a single walk. - for_each_region([] (Region& region) { + for_each_region([](Region& region) { ASSERT(region.page_directory()); MM.remap_region(*region.page_directory(), region); }); diff --git a/Kernel/VM/VMObject.h b/Kernel/VM/VMObject.h index 0f7b9c4fea..6d69ac06ec 100644 --- a/Kernel/VM/VMObject.h +++ b/Kernel/VM/VMObject.h @@ -30,7 +30,7 @@ public: const Inode* inode() const { return m_inode.ptr(); } size_t inode_offset() const { return m_inode_offset; } - String name() const { return m_name; } + const String& name() const { return m_name; } void set_name(const String& name) { m_name = name; } size_t page_count() const { return m_size / PAGE_SIZE; } diff --git a/Kernel/VirtualAddress.h b/Kernel/VirtualAddress.h new file mode 100644 index 0000000000..5f9e7d546b --- /dev/null +++ b/Kernel/VirtualAddress.h @@ -0,0 +1,40 @@ +#pragma once + +#include + +class VirtualAddress { +public: + VirtualAddress() {} + explicit VirtualAddress(dword address) + : m_address(address) + { + } + + bool is_null() const { return m_address == 0; } + bool is_page_aligned() const { return (m_address & 0xfff) == 0; } + + VirtualAddress offset(dword o) const { return VirtualAddress(m_address + o); } + dword get() const { return m_address; } + void set(dword address) { m_address = address; } + void mask(dword m) { m_address &= m; } + + bool operator<=(const VirtualAddress& other) const { return m_address <= other.m_address; } + bool operator>=(const VirtualAddress& other) const { return m_address >= other.m_address; } + bool operator>(const VirtualAddress& other) const { return m_address > other.m_address; } + bool operator<(const VirtualAddress& other) const { return m_address < other.m_address; } + bool operator==(const VirtualAddress& other) const { return m_address == other.m_address; } + bool operator!=(const VirtualAddress& other) const { return m_address != other.m_address; } + + byte* as_ptr() { return reinterpret_cast(m_address); } + const byte* as_ptr() const { return reinterpret_cast(m_address); } + + dword page_base() const { return m_address & 0xfffff000; } + +private: + dword m_address { 0 }; +}; + +inline VirtualAddress operator-(const VirtualAddress& a, const VirtualAddress& b) +{ + return VirtualAddress(a.get() - b.get()); +} diff --git a/Kernel/build-image-grub.sh b/Kernel/build-image-grub.sh new file mode 100755 index 0000000000..dc4ca60966 --- /dev/null +++ b/Kernel/build-image-grub.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +set -e + +die() { + echo "die: $@" + exit 1 +} + +if [ $(id -u) != 0 ]; then + die "this script needs to run as root" +fi + +grub=$(which grub-install 2>/dev/null) || true +if [[ -z "$grub" ]]; then + grub=$(which grub2-install 2>/dev/null) || true +fi +if [ -z "$grub" ]; then + echo "can't find a grub-install or grub2-install binary, oh no" + exit 1 +fi +echo "using grub-install at ${grub}" + +echo "setting up disk image..." +dd if=/dev/zero of=_disk_image bs=1M count=${DISK_SIZE:-500} status=none || die "couldn't create disk image" +chown 1000:1000 _disk_image || die "couldn't adjust permissions on disk image" +echo "done" + +echo -n "creating loopback device... " +dev=$(losetup --find --partscan --show _disk_image) +if [ -z $dev ]; then + die "couldn't mount loopback device" +fi +echo "loopback device is at ${dev}" + +cleanup() { + if [ -d mnt ]; then + echo -n "unmounting filesystem... " + umount mnt || ( sleep 1 && sync && umount mnt ) + rm -rf mnt + echo "done" + fi + + if [ -e ${dev} ]; then + echo -n "cleaning up loopback device... " + losetup -d ${dev} + echo "done" + fi +} +trap cleanup EXIT + +echo -n "creating partition table... " +parted -s ${dev} mklabel msdos mkpart primary ext2 32k 100% -a minimal set 1 boot on || die "couldn't partition disk" +echo "done" + +echo -n "destroying old filesystem... " +dd if=/dev/zero of=${dev}p1 bs=1M count=1 status=none || die "couldn't destroy old filesystem" +echo "done" + +echo -n "creating new filesystem... " +mke2fs -q -I 128 ${dev}p1 || die "couldn't create filesystem" +echo "done" + +echo -n "mounting filesystem... " +mkdir -p mnt +mount ${dev}p1 mnt/ || die "couldn't mount filesystem" +echo "done" + +./build-root-filesystem.sh + +echo -n "creating /boot... " +mkdir -p mnt/boot +echo "done" + +echo "installing grub using $grub..." +$grub --boot-directory=mnt/boot --target=i386-pc --modules="ext2 part_msdos" ${dev} + +if [ -d mnt/boot/grub2 ]; then + cp grub.cfg mnt/boot/grub2/grub.cfg +else + cp grub.cfg mnt/boot/grub/grub.cfg +fi +echo "done" + +echo -n "installing kernel in /boot... " +cp kernel mnt/boot +echo "done" diff --git a/Kernel/build-image-qemu.sh b/Kernel/build-image-qemu.sh new file mode 100755 index 0000000000..229663868e --- /dev/null +++ b/Kernel/build-image-qemu.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +set -e + +die() { + echo "die: $@" + exit 1 +} + +if [ $(id -u) != 0 ]; then + die "this script needs to run as root" +fi + +echo "setting up disk image..." +qemu-img create _disk_image ${DISK_SIZE:-500}m || die "couldn't create disk image" +chown 1000:1000 _disk_image || die "couldn't adjust permissions on disk image" +echo "done" + +echo -n "creating new filesystem... " +mke2fs -q -I 128 _disk_image || die "couldn't create filesystem" +echo "done" + +echo -n "mounting filesystem... " +mkdir -p mnt +mount _disk_image mnt/ || die "couldn't mount filesystem" +echo "done" + +cleanup() { + if [ -d mnt ]; then + echo -n "unmounting filesystem... " + umount mnt || ( sleep 1 && sync && umount mnt ) + rm -rf mnt + echo "done" + fi +} +trap cleanup EXIT + +./build-root-filesystem.sh diff --git a/Kernel/build-root-filesystem.sh b/Kernel/build-root-filesystem.sh new file mode 100755 index 0000000000..8ffa9fe642 --- /dev/null +++ b/Kernel/build-root-filesystem.sh @@ -0,0 +1,106 @@ +#!/bin/bash + +set -e + +die() { + echo "die: $@" + exit 1 +} + +if [ $(id -u) != 0 ]; then + die "this script needs to run as root" +fi + +echo -n "creating initial filesystem structure... " +mkdir -p mnt/{bin,etc,proc,tmp} +chmod 1777 mnt/tmp +echo "done" + +echo -n "setting up device nodes... " +mkdir -p mnt/dev +mkdir -p mnt/dev/pts +mknod -m 666 mnt/dev/bxvga b 82 413 +mknod mnt/dev/tty0 c 4 0 +mknod mnt/dev/tty1 c 4 1 +mknod mnt/dev/tty2 c 4 2 +mknod mnt/dev/tty3 c 4 3 +mknod mnt/dev/ttyS0 c 4 64 +mknod mnt/dev/ttyS1 c 4 65 +mknod mnt/dev/ttyS2 c 4 66 +mknod mnt/dev/ttyS3 c 4 67 +mknod -m 666 mnt/dev/random c 1 8 +mknod -m 666 mnt/dev/null c 1 3 +mknod -m 666 mnt/dev/zero c 1 5 +mknod -m 666 mnt/dev/full c 1 7 +mknod -m 666 mnt/dev/debuglog c 1 18 +mknod mnt/dev/keyboard c 85 1 +mknod mnt/dev/psaux c 10 1 +mknod -m 666 mnt/dev/ptmx c 5 2 +ln -s /proc/self/fd/0 mnt/dev/stdin +ln -s /proc/self/fd/1 mnt/dev/stdout +ln -s /proc/self/fd/2 mnt/dev/stderr +echo "done" + +echo -n "installing base system... " +cp -R ../Base/* mnt/ +cp -R ../Root/* mnt/ +cp kernel.map mnt/ +echo "done" + +echo -n "installing users... " +mkdir -p mnt/home/anon +mkdir -p mnt/home/nona +cp ../ReadMe.md mnt/home/anon/ +chown -R 100:100 mnt/home/anon +chown -R 200:200 mnt/home/nona +echo "done" + +echo -n "installing userland... " +find ../Userland/ -type f -executable -exec cp {} mnt/bin/ \; +chmod 4755 mnt/bin/su +echo "done" + +echo -n "installing applications... " +cp ../Applications/About/About mnt/bin/About +cp ../Applications/Downloader/Downloader mnt/bin/Downloader +cp ../Applications/FileManager/FileManager mnt/bin/FileManager +cp ../Applications/FontEditor/FontEditor mnt/bin/FontEditor +cp ../Applications/IRCClient/IRCClient mnt/bin/IRCClient +cp ../Applications/Launcher/Launcher mnt/bin/Launcher +cp ../Applications/ProcessManager/ProcessManager mnt/bin/ProcessManager +cp ../Applications/Taskbar/Taskbar mnt/bin/Taskbar +cp ../Applications/Terminal/Terminal mnt/bin/Terminal +cp ../Applications/TextEditor/TextEditor mnt/bin/TextEditor +cp ../Applications/PaintBrush/PaintBrush mnt/bin/PaintBrush +cp ../Demos/HelloWorld/HelloWorld mnt/bin/HelloWorld +cp ../Demos/RetroFetch/RetroFetch mnt/bin/RetroFetch +cp ../Demos/WidgetGallery/WidgetGallery mnt/bin/WidgetGallery +cp ../Demos/Fire/Fire mnt/bin/Fire +cp ../DevTools/VisualBuilder/VisualBuilder mnt/bin/VisualBuilder +cp ../Games/Minesweeper/Minesweeper mnt/bin/Minesweeper +cp ../Games/Snake/Snake mnt/bin/Snake +cp ../Servers/LookupServer/LookupServer mnt/bin/LookupServer +cp ../Servers/SystemServer/SystemServer mnt/bin/SystemServer +cp ../Servers/WindowServer/WindowServer mnt/bin/WindowServer +cp ../Shell/Shell mnt/bin/Shell +echo "done" + +echo -n "installing shortcuts... " +ln -s Downloader mnt/bin/dl +ln -s FileManager mnt/bin/fm +ln -s HelloWorld mnt/bin/hw +ln -s IRCClient mnt/bin/irc +ln -s Minesweeper mnt/bin/ms +ln -s Shell mnt/bin/sh +ln -s Snake mnt/bin/sn +ln -s Taskbar mnt/bin/tb +ln -s VisualBuilder mnt/bin/vb +ln -s WidgetGallery mnt/bin/wg +ln -s TextEditor mnt/bin/te +ln -s PaintBrush mnt/bin/pb +echo "done" + +# Run local sync script, if it exists +if [ -f sync-local.sh ]; then + sh sync-local.sh +fi diff --git a/Kernel/grub.cfg b/Kernel/grub.cfg new file mode 100644 index 0000000000..9348f629c9 --- /dev/null +++ b/Kernel/grub.cfg @@ -0,0 +1,6 @@ +timeout=0 + +menuentry 'Serenity' { + root=hd0,1 + multiboot /boot/kernel root=/dev/hda1 +} diff --git a/Kernel/i8253.cpp b/Kernel/i8253.cpp index 8a8171e125..49818a3063 100644 --- a/Kernel/i8253.cpp +++ b/Kernel/i8253.cpp @@ -1,8 +1,8 @@ #include "i8253.h" -#include "i386.h" #include "IO.h" #include "PIC.h" #include "Scheduler.h" +#include #define IRQ_TIMER 0 @@ -34,8 +34,7 @@ asm( " popw %es\n" " popw %ds\n" " popa\n" - " iret\n" -); + " iret\n"); static dword s_ticks_this_second; static dword s_seconds_since_boot; diff --git a/Kernel/init.cpp b/Kernel/init.cpp index 32f7a2c00a..cde76f94e2 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -1,30 +1,35 @@ -#include -#include "kmalloc.h" -#include "i386.h" -#include "i8253.h" -#include -#include "Process.h" -#include "PIC.h" -#include #include "KSyms.h" -#include -#include -#include -#include -#include -#include -#include -#include +#include "PIC.h" +#include "Process.h" #include "RTC.h" -#include #include "Scheduler.h" -#include -#include -#include +#include "i8253.h" +#include "kmalloc.h" +#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include -#include +#include +#include +#include //#define STRESS_TEST_SPAWNING @@ -36,6 +41,10 @@ KeyboardDevice* keyboard; PS2MouseDevice* ps2mouse; DebugLogDevice* dev_debuglog; NullDevice* dev_null; +SerialDevice* ttyS0; +SerialDevice* ttyS1; +SerialDevice* ttyS2; +SerialDevice* ttyS3; VFS* vfs; #ifdef STRESS_TEST_SPAWNING @@ -45,7 +54,7 @@ VFS* vfs; for (unsigned i = 0; i < 10000; ++i) { int error; - Process::create_user_process("/bin/true", (uid_t)100, (gid_t)100, (pid_t)0, error, { }, { }, tty0); + Process::create_user_process("/bin/true", (uid_t)100, (gid_t)100, (pid_t)0, error, {}, {}, tty0); dbgprintf("malloc stats: alloc:%u free:%u eternal:%u !delta:%u\n", sum_alloc, sum_free, kmalloc_sum_eternal, sum_alloc - last_sum_alloc); last_sum_alloc = sum_alloc; sleep(60); @@ -64,9 +73,57 @@ VFS* vfs; auto dev_full = make(); auto dev_random = make(); auto dev_ptmx = make(); + + auto root = KParams::the().get("root"); + if (root.is_empty()) { + root = "/dev/hda"; + } + + if (!root.starts_with("/dev/hda")) { + kprintf("init_stage2: root filesystem must be on the first IDE hard drive (/dev/hda)\n"); + hang(); + } + auto dev_hd0 = IDEDiskDevice::create(); - auto e2fs = Ext2FS::create(dev_hd0.copy_ref()); - e2fs->initialize(); + + Retained root_dev = dev_hd0.copy_ref(); + + root = root.substring(strlen("/dev/hda"), root.length() - strlen("/dev/hda")); + + if (root.length()) { + bool ok; + unsigned partition_number = root.to_uint(ok); + + if (!ok) { + kprintf("init_stage2: couldn't parse partition number from root kernel parameter\n"); + hang(); + } + + if (partition_number < 1 || partition_number > 4) { + kprintf("init_stage2: invalid partition number %d; expected 1 to 4\n", partition_number); + hang(); + } + + MBRPartitionTable mbr(root_dev.copy_ref()); + if (!mbr.initialize()) { + kprintf("init_stage2: couldn't read MBR from disk\n"); + hang(); + } + + auto partition = mbr.partition(partition_number); + if (!partition) { + kprintf("init_stage2: couldn't get partition %d\n", partition_number); + hang(); + } + + root_dev = *partition; + } + + auto e2fs = Ext2FS::create(root_dev.copy_ref()); + if (!e2fs->initialize()) { + kprintf("init_stage2: couldn't open root filesystem\n"); + hang(); + } vfs->mount_root(e2fs.copy_ref()); @@ -79,9 +136,9 @@ VFS* vfs; int error; - auto* system_server_process = Process::create_user_process("/bin/SystemServer", (uid_t)100, (gid_t)100, (pid_t)0, error, { }, { }, tty0); + auto* system_server_process = Process::create_user_process("/bin/SystemServer", (uid_t)100, (gid_t)100, (pid_t)0, error, {}, {}, tty0); if (error != 0) { - dbgprintf("error spawning SystemServer: %d\n", error); + dbgprintf("init_stage2: error spawning SystemServer: %d\n", error); hang(); } system_server_process->set_priority(Process::HighPriority); @@ -94,15 +151,20 @@ VFS* vfs; ASSERT_NOT_REACHED(); } +extern "C" { +multiboot_info_t* multiboot_info_ptr; +} + extern "C" [[noreturn]] void init() { - cli(); - sse_init(); kmalloc_init(); init_ksyms(); + // must come after kmalloc_init because we use AK_MAKE_ETERNAL in KParams + new KParams(String(reinterpret_cast(multiboot_info_ptr->cmdline))); + vfs = new VFS; dev_debuglog = new DebugLogDevice; @@ -116,6 +178,10 @@ extern "C" [[noreturn]] void init() keyboard = new KeyboardDevice; ps2mouse = new PS2MouseDevice; dev_null = new NullDevice; + ttyS0 = new SerialDevice(SERIAL_COM1_ADDR, 64); + ttyS1 = new SerialDevice(SERIAL_COM2_ADDR, 65); + ttyS2 = new SerialDevice(SERIAL_COM3_ADDR, 66); + ttyS3 = new SerialDevice(SERIAL_COM4_ADDR, 67); VirtualConsole::initialize(); tty0 = new VirtualConsole(0, VirtualConsole::AdoptCurrentVGABuffer); diff --git a/Kernel/kmalloc.cpp b/Kernel/kmalloc.cpp index c00e9c139c..48d18cb98b 100644 --- a/Kernel/kmalloc.cpp +++ b/Kernel/kmalloc.cpp @@ -3,18 +3,19 @@ * just to get going. Don't ever let anyone see this shit. :^) */ +#include #include -#include -#include -#include +#include +#include #include #include -#include -#include +#include +#include #define SANITIZE_KMALLOC -struct [[gnu::packed]] allocation_t { +struct [[gnu::packed]] allocation_t +{ size_t start; size_t nchunk; }; @@ -22,11 +23,11 @@ struct [[gnu::packed]] allocation_t { #define CHUNK_SIZE 32 #define POOL_SIZE (1024 * 1024) -#define ETERNAL_BASE_PHYSICAL 0x100000 -#define ETERNAL_RANGE_SIZE 0x100000 +#define ETERNAL_BASE_PHYSICAL (1 * MB) +#define ETERNAL_RANGE_SIZE (2 * MB) -#define BASE_PHYSICAL 0x200000 -#define RANGE_SIZE 0x100000 +#define BASE_PHYSICAL (3 * MB) +#define RANGE_SIZE (1 * MB) static byte alloc_map[POOL_SIZE / CHUNK_SIZE / 8]; @@ -51,7 +52,7 @@ bool is_kmalloc_address(const void* ptr) void kmalloc_init() { memset(&alloc_map, 0, sizeof(alloc_map)); - memset((void *)BASE_PHYSICAL, 0, POOL_SIZE); + memset((void*)BASE_PHYSICAL, 0, POOL_SIZE); kmalloc_sum_eternal = 0; sum_alloc = 0; @@ -126,7 +127,7 @@ void* kmalloc_impl(size_t size) } // FIXME: This scan can be optimized further with LZCNT. for (size_t j = 0; j < 8; ++j) { - if (!(alloc_map[i] & (1<nchunk = chunks_needed; a->start = first_chunk; @@ -164,7 +165,7 @@ void* kmalloc_impl(size_t size) hang(); } -void kfree(void *ptr) +void kfree(void* ptr) { if (!ptr) return; diff --git a/Kernel/kprintf.cpp b/Kernel/kprintf.cpp index 884dfa9f39..9605d2cfec 100644 --- a/Kernel/kprintf.cpp +++ b/Kernel/kprintf.cpp @@ -1,10 +1,10 @@ -#include +#include +#include #include #include -#include #include -#include -#include +#include +#include static void console_putch(char*&, char ch) { diff --git a/Kernel/makeall.sh b/Kernel/makeall.sh index f782a1aa03..9b04f3339f 100755 --- a/Kernel/makeall.sh +++ b/Kernel/makeall.sh @@ -28,6 +28,7 @@ build_targets="$build_targets ../Applications/About" build_targets="$build_targets ../Applications/IRCClient" build_targets="$build_targets ../Applications/Taskbar" build_targets="$build_targets ../Applications/Downloader" +build_targets="$build_targets ../Applications/PaintBrush" build_targets="$build_targets ../DevTools/VisualBuilder" build_targets="$build_targets ../Games/Minesweeper" build_targets="$build_targets ../Games/Snake" @@ -35,6 +36,7 @@ build_targets="$build_targets ../Shell" build_targets="$build_targets ../Demos/HelloWorld" build_targets="$build_targets ../Demos/RetroFetch" build_targets="$build_targets ../Demos/WidgetGallery" +build_targets="$build_targets ../Demos/Fire" build_targets="$build_targets ." # the kernel for targ in $build_targets; do diff --git a/Kernel/run b/Kernel/run index 199b818919..db3414fa45 100755 --- a/Kernel/run +++ b/Kernel/run @@ -2,26 +2,27 @@ [ -z "$SERENITY_QEMU_BIN" ] && SERENITY_QEMU_BIN="qemu-system-i386" +SERENITY_KERNEL_CMDLINE="hello" + export SDL_VIDEO_X11_DGAMOUSE=0 -ram_size=128 if [ "$1" = "b" ]; then # ./run b: bochs bochs -q -f .bochsrc elif [ "$1" = "qn" ]; then # ./run qn: qemu without network - $SERENITY_QEMU_BIN -s -m $ram_size \ + $SERENITY_QEMU_BIN -s -m ${SERENITY_RAM_SIZE:-128} \ $SERENITY_EXTRA_QEMU_ARGS \ -d cpu_reset,guest_errors \ -device VGA,vgamem_mb=64 \ -debugcon stdio \ -device e1000 \ -kernel kernel \ - -hda _fs_contents \ + -hda _disk_image \ -soundhw pcspk elif [ "$1" = "qtap" ]; then # ./run qtap: qemu with tap - sudo $SERENITY_QEMU_BIN -s -m $ram_size \ + sudo $SERENITY_QEMU_BIN -s -m ${SERENITY_RAM_SIZE:-128} \ $SERENITY_EXTRA_QEMU_ARGS \ -d cpu_reset,guest_errors \ -device VGA,vgamem_mb=64 \ @@ -30,11 +31,23 @@ elif [ "$1" = "qtap" ]; then -netdev tap,ifname=tap0,id=br0 \ -device e1000,netdev=br0 \ -kernel kernel \ - -hda _fs_contents \ + -hda _disk_image \ + -soundhw pcspk +elif [ "$1" = "qgrub" ]; then + # ./run qgrub: qemu with grub + $SERENITY_QEMU_BIN -s -m ${SERENITY_RAM_SIZE:-128} \ + $SERENITY_EXTRA_QEMU_ARGS \ + -d cpu_reset,guest_errors \ + -device VGA,vgamem_mb=64 \ + -debugcon stdio \ + -object filter-dump,id=hue,netdev=breh,file=e1000.pcap \ + -netdev user,id=breh,hostfwd=tcp:127.0.0.1:8888-192.168.5.2:8888 \ + -device e1000,netdev=breh \ + -hda _disk_image \ -soundhw pcspk else # ./run: qemu with user networking - $SERENITY_QEMU_BIN -s -m $ram_size \ + $SERENITY_QEMU_BIN -s -m ${SERENITY_RAM_SIZE:-128} \ $SERENITY_EXTRA_QEMU_ARGS \ -d cpu_reset,guest_errors \ -device VGA,vgamem_mb=64 \ @@ -43,7 +56,7 @@ else -netdev user,id=breh,hostfwd=tcp:127.0.0.1:8888-192.168.5.2:8888 \ -device e1000,netdev=breh \ -kernel kernel \ - -hda _fs_contents \ + -hda _disk_image \ -soundhw pcspk fi diff --git a/Kernel/sync.sh b/Kernel/sync.sh index 92c15bff4d..e6114e7bd1 100755 --- a/Kernel/sync.sh +++ b/Kernel/sync.sh @@ -1,93 +1,3 @@ #!/bin/bash -if [ "$1" = "-f" ]; then - rm -vf _fs_contents -fi - -if [ $(id -u) != 0 ]; then - echo "This needs to be run as root" - exit 1 -fi - -rm -vf _fs_contents.lock - -# If target filesystem image doesn't exist, create it. -if [ ! -f _fs_contents ]; then - dd if=/dev/zero of=_fs_contents bs=1M count=512 -fi - -mke2fs -F -I 128 _fs_contents - -chown 1000:1000 _fs_contents -mkdir -vp mnt -mount -o loop _fs_contents mnt/ -mkdir -vp mnt/bin -mkdir -vp mnt/etc -mkdir -vp mnt/proc -mkdir -vp mnt/tmp -chmod 1777 mnt/tmp -mkdir -vp mnt/dev -mkdir -vp mnt/dev/pts -mknod -m 666 mnt/dev/bxvga b 82 413 -mknod mnt/dev/tty0 c 4 0 -mknod mnt/dev/tty1 c 4 1 -mknod mnt/dev/tty2 c 4 2 -mknod mnt/dev/tty3 c 4 3 -mknod mnt/dev/random c 1 8 -mknod mnt/dev/null c 1 3 -mknod mnt/dev/zero c 1 5 -mknod mnt/dev/full c 1 7 -mknod -m 666 mnt/dev/debuglog c 1 18 -mknod mnt/dev/keyboard c 85 1 -mknod mnt/dev/psaux c 10 1 -mknod -m 666 mnt/dev/ptmx c 5 2 -ln -s /proc/self/fd/0 mnt/dev/stdin -ln -s /proc/self/fd/1 mnt/dev/stdout -ln -s /proc/self/fd/2 mnt/dev/stderr -cp -vR ../Base/* mnt/ -cp -vR ../Root/* mnt/ -mkdir -vp mnt/home/anon -mkdir -vp mnt/home/nona -cp ../ReadMe.md mnt/home/anon/ -chown -vR 100:100 mnt/home/anon -chown -vR 200:200 mnt/home/nona -find ../Userland/ -type f -executable -exec cp -v {} mnt/bin/ \; -chmod 4755 mnt/bin/su -cp -v ../Applications/Terminal/Terminal mnt/bin/Terminal -cp -v ../Applications/FontEditor/FontEditor mnt/bin/FontEditor -cp -v ../Applications/Launcher/Launcher mnt/bin/Launcher -cp -v ../Applications/FileManager/FileManager mnt/bin/FileManager -cp -v ../Applications/ProcessManager/ProcessManager mnt/bin/ProcessManager -cp -v ../Applications/About/About mnt/bin/About -cp -v ../Applications/TextEditor/TextEditor mnt/bin/TextEditor -cp -v ../Applications/IRCClient/IRCClient mnt/bin/IRCClient -ln -s IRCClient mnt/bin/irc -ln -s FileManager mnt/bin/fm -cp -v ../Servers/SystemServer/SystemServer mnt/bin/SystemServer -cp -v ../Servers/LookupServer/LookupServer mnt/bin/LookupServer -cp -v ../Servers/WindowServer/WindowServer mnt/bin/WindowServer -cp -v ../Applications/Taskbar/Taskbar mnt/bin/Taskbar -ln -s Taskbar mnt/bin/tb -cp -v ../Applications/Downloader/Downloader mnt/bin/Downloader -ln -s Downloader mnt/bin/dl -cp -v ../DevTools/VisualBuilder/VisualBuilder mnt/bin/VisualBuilder -ln -s VisualBuilder mnt/bin/vb -cp -v ../Games/Minesweeper/Minesweeper mnt/bin/Minesweeper -ln -s Minesweeper mnt/bin/ms -cp -v ../Games/Snake/Snake mnt/bin/Snake -ln -s Snake mnt/bin/sn -cp -v ../Shell/Shell mnt/bin/Shell -ln -s Shell mnt/bin/sh -cp -v kernel.map mnt/ -cp -v ../Demos/HelloWorld/HelloWorld mnt/bin/HelloWorld -ln -s HelloWorld mnt/bin/hw -cp -v ../Demos/RetroFetch/RetroFetch mnt/bin/RetroFetch -cp -v ../Demos/WidgetGallery/WidgetGallery mnt/bin/WidgetGallery -ln -s WidgetGallery mnt/bin/wg - -# Run local sync script, if it exists -if [ -f sync-local.sh ]; then - sh sync-local.sh -fi - -umount mnt || ( sleep 0.5 && sync && umount mnt ) +./build-image-qemu.sh diff --git a/LibC/SharedBuffer.cpp b/LibC/SharedBuffer.cpp index ef8c262075..58537a0094 100644 --- a/LibC/SharedBuffer.cpp +++ b/LibC/SharedBuffer.cpp @@ -1,7 +1,7 @@ -#include -#include -#include #include +#include +#include +#include RetainPtr SharedBuffer::create(pid_t peer, int size) { diff --git a/LibC/arpa/inet.cpp b/LibC/arpa/inet.cpp index 790b9eb715..4156a0a740 100644 --- a/LibC/arpa/inet.cpp +++ b/LibC/arpa/inet.cpp @@ -1,7 +1,7 @@ #include +#include #include #include -#include extern "C" { @@ -29,7 +29,7 @@ int inet_pton(int af, const char* src, void* dst) int count = sscanf(src, "%u.%u.%u.%u", &a, &b, &c, &d); if (count != 4) { errno = EINVAL; - return -1; + return 0; } union { struct { @@ -45,7 +45,7 @@ int inet_pton(int af, const char* src, void* dst) u.c = c; u.d = d; *(uint32_t*)dst = u.l; - return 0; + return 1; } in_addr_t inet_addr(const char* str) @@ -56,6 +56,4 @@ in_addr_t inet_addr(const char* str) return INADDR_NONE; return tmp; } - } - diff --git a/LibC/assert.cpp b/LibC/assert.cpp index bf13d8e1e9..6bc306c2ad 100644 --- a/LibC/assert.cpp +++ b/LibC/assert.cpp @@ -1,6 +1,6 @@ #include -#include #include +#include #include extern "C" { @@ -11,8 +11,8 @@ void __assertion_failed(const char* msg, const char* file, unsigned line, const dbgprintf("USERSPACE(%d) ASSERTION FAILED: %s\n%s:%u in %s\n", getpid(), msg, file, line, func); fprintf(stderr, "ASSERTION FAILED: %s\n%s:%u in %s\n", msg, file, line, func); abort(); - for (;;); + for (;;) + ; } #endif - } diff --git a/LibC/crt0.cpp b/LibC/crt0.cpp index ee307daa81..82005fc9a2 100644 --- a/LibC/crt0.cpp +++ b/LibC/crt0.cpp @@ -51,5 +51,4 @@ int _start(int argc, char** argv, char** env) void __cxa_atexit() { } - } diff --git a/LibC/ctype.cpp b/LibC/ctype.cpp index 9d4c426ba7..beb0008e8d 100644 --- a/LibC/ctype.cpp +++ b/LibC/ctype.cpp @@ -5,18 +5,18 @@ extern "C" { const char _ctype_[256] = { _C, _C, _C, _C, _C, _C, _C, _C, - _C, _C|_S, _C|_S, _C|_S, _C|_S, _C|_S, _C, _C, + _C, _C | _S, _C | _S, _C | _S, _C | _S, _C | _S, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, - (char)(_S|_B), _P, _P, _P, _P, _P, _P, _P, + (char)(_S | _B), _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _N, _N, _N, _N, _N, _N, _N, _N, _N, _N, _P, _P, _P, _P, _P, _P, - _P, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U, + _P, _U | _X, _U | _X, _U | _X, _U | _X, _U | _X, _U | _X, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _P, _P, _P, _P, _P, - _P, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L, + _P, _L | _X, _L | _X, _L | _X, _L | _X, _L | _X, _L | _X, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _P, _P, _P, _P, _C @@ -35,5 +35,4 @@ int toupper(int c) return c & ~0x20; return c; } - } diff --git a/LibC/dirent.cpp b/LibC/dirent.cpp index f9c8d33db1..07a9ef22ff 100644 --- a/LibC/dirent.cpp +++ b/LibC/dirent.cpp @@ -1,14 +1,14 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include extern "C" { @@ -38,7 +38,8 @@ int closedir(DIR* dirp) return rc; } -struct [[gnu::packed]] sys_dirent { +struct [[gnu::packed]] sys_dirent +{ ino_t ino; byte file_type; size_t namelen; @@ -85,5 +86,9 @@ dirent* readdir(DIR* dirp) return &dirp->cur_ent; } +int dirfd(DIR* dirp) +{ + ASSERT(dirp); + return dirp->fd; +} } - diff --git a/LibC/dirent.h b/LibC/dirent.h index 27164519bf..b127489a92 100644 --- a/LibC/dirent.h +++ b/LibC/dirent.h @@ -25,5 +25,6 @@ typedef struct __DIR DIR; DIR* opendir(const char* name); int closedir(DIR*); struct dirent* readdir(DIR*); +int dirfd(DIR*); __END_DECLS diff --git a/LibC/dlfcn.cpp b/LibC/dlfcn.cpp index 08c5e12490..f4437b0272 100644 --- a/LibC/dlfcn.cpp +++ b/LibC/dlfcn.cpp @@ -8,19 +8,18 @@ int dlclose(void*) ASSERT_NOT_REACHED(); } -char *dlerror() +char* dlerror() { ASSERT_NOT_REACHED(); } -void *dlopen(const char*, int) +void* dlopen(const char*, int) { ASSERT_NOT_REACHED(); } -void *dlsym(void*, const char*) +void* dlsym(void*, const char*) { ASSERT_NOT_REACHED(); } - } diff --git a/LibC/fcntl.cpp b/LibC/fcntl.cpp index dd28a65cb6..ba4e425e1c 100644 --- a/LibC/fcntl.cpp +++ b/LibC/fcntl.cpp @@ -1,8 +1,8 @@ +#include #include #include #include #include -#include extern "C" { @@ -14,5 +14,4 @@ int fcntl(int fd, int cmd, ...) int rc = syscall(SC_fcntl, fd, cmd, extra_arg); __RETURN_WITH_ERRNO(rc, rc, -1); } - } diff --git a/LibC/getopt.cpp b/LibC/getopt.cpp index c7c6afa637..6798b65cbe 100644 --- a/LibC/getopt.cpp +++ b/LibC/getopt.cpp @@ -40,20 +40,20 @@ #include #include -int opterr = 1; /* if error message should be printed */ +int opterr = 1; /* if error message should be printed */ int optind = 1; /* index into parent argv vector */ int optopt; /* character checked for validity */ int optreset; /* reset getopt */ -char *optarg; /* argument associated with option */ +char* optarg; /* argument associated with option */ -#define BADCH (int)'?' -#define BADARG (int)':' -#define EMSG "" +#define BADCH (int)'?' +#define BADARG (int)':' +#define EMSG "" int getopt(int nargc, char* const nargv[], const char* ostr) { static const char* place = EMSG; /* option letter processing */ - char *oli; /* option letter list index */ + char* oli; /* option letter list index */ ASSERT(nargv != NULL); ASSERT(ostr != NULL); @@ -70,7 +70,7 @@ int getopt(int nargc, char* const nargv[], const char* ostr) place = EMSG; return -1; } - } /* option letter okay? */ + } /* option letter okay? */ if ((optopt = (int)*place++) == (int)':' || !(oli = strchr(ostr, optopt))) { /* * if the user didn't specify '-' as an option, @@ -88,8 +88,7 @@ int getopt(int nargc, char* const nargv[], const char* ostr) optarg = NULL; if (!*place) ++optind; - } - else { /* need an argument */ + } else { /* need an argument */ if (*place) /* no white space */ optarg = const_cast(place); else if (nargc <= ++optind) { /* no arg */ @@ -99,8 +98,7 @@ int getopt(int nargc, char* const nargv[], const char* ostr) if (opterr) fprintf(stderr, "option requires an argument -- %c\n", optopt); return BADCH; - } - else /* white space */ + } else /* white space */ optarg = nargv[optind]; place = EMSG; ++optind; diff --git a/LibC/grp.cpp b/LibC/grp.cpp index 744189bb80..2379d98e35 100644 --- a/LibC/grp.cpp +++ b/LibC/grp.cpp @@ -1,9 +1,9 @@ +#include #include #include #include -#include #include -#include +#include extern "C" { @@ -138,5 +138,4 @@ int initgroups(const char* user, gid_t extra_gid) gids[count++] = extra_gid; return setgroups(count, gids); } - } diff --git a/LibC/ioctl.cpp b/LibC/ioctl.cpp index 354d49e7b7..c2ac90524a 100644 --- a/LibC/ioctl.cpp +++ b/LibC/ioctl.cpp @@ -1,8 +1,8 @@ +#include #include #include #include #include -#include extern "C" { @@ -14,6 +14,4 @@ int ioctl(int fd, unsigned request, ...) int rc = syscall(SC_ioctl, fd, request, arg); __RETURN_WITH_ERRNO(rc, rc, -1); } - } - diff --git a/LibC/locale.cpp b/LibC/locale.cpp index 62bd414b7c..a85af30784 100644 --- a/LibC/locale.cpp +++ b/LibC/locale.cpp @@ -1,5 +1,5 @@ -#include #include +#include #include extern "C" { @@ -20,5 +20,4 @@ struct lconv* localeconv() { return &default_locale; } - } diff --git a/LibC/locale.h b/LibC/locale.h index 0f5c52e668..26b5367434 100644 --- a/LibC/locale.h +++ b/LibC/locale.h @@ -4,8 +4,7 @@ __BEGIN_DECLS -enum -{ +enum { LC_ALL, LC_NUMERIC, LC_CTYPE, diff --git a/LibC/malloc.cpp b/LibC/malloc.cpp index 21021ba03d..2225ba9caa 100644 --- a/LibC/malloc.cpp +++ b/LibC/malloc.cpp @@ -1,11 +1,11 @@ #include #include #include -#include -#include #include -#include #include +#include +#include +#include // FIXME: Thread safety. @@ -16,7 +16,7 @@ #define FREE_SCRUB_BYTE 0x82 #define MAGIC_PAGE_HEADER 0x42657274 #define MAGIC_BIGALLOC_HEADER 0x42697267 -#define PAGE_ROUND_UP(x) ((((size_t)(x)) + PAGE_SIZE-1) & (~(PAGE_SIZE-1))) +#define PAGE_ROUND_UP(x) ((((size_t)(x)) + PAGE_SIZE - 1) & (~(PAGE_SIZE - 1))) static const size_t number_of_chunked_blocks_to_keep_around_per_size_class = 32; static const size_t number_of_big_blocks_to_keep_around_per_size_class = 8; @@ -45,7 +45,8 @@ struct FreelistEntry { FreelistEntry* next; }; -struct ChunkedBlock : public CommonHeader, public InlineLinkedListNode { +struct ChunkedBlock : public CommonHeader + , public InlineLinkedListNode { ChunkedBlock(size_t bytes_per_chunk) { m_magic = MAGIC_PAGE_HEADER; @@ -59,7 +60,6 @@ struct ChunkedBlock : public CommonHeader, public InlineLinkedListNodenext = nullptr; } - } ChunkedBlock* m_prev { nullptr }; @@ -309,6 +309,4 @@ void __malloc_init() if (getenv("LIBC_LOG_MALLOC")) s_log_malloc = true; } - } - diff --git a/LibC/mman.cpp b/LibC/mman.cpp index bd87e5989c..0e89a4ead0 100644 --- a/LibC/mman.cpp +++ b/LibC/mman.cpp @@ -1,7 +1,7 @@ -#include -#include -#include #include +#include +#include +#include extern "C" { @@ -50,5 +50,4 @@ int shm_unlink(const char* name) int rc = syscall(SC_unlink, name); __RETURN_WITH_ERRNO(rc, rc, -1); } - } diff --git a/LibC/mntent.cpp b/LibC/mntent.cpp index 08116ec02b..3cc16cc8bf 100644 --- a/LibC/mntent.cpp +++ b/LibC/mntent.cpp @@ -1,5 +1,5 @@ -#include #include +#include extern "C" { @@ -8,6 +8,4 @@ struct mntent* getmntent(FILE*) ASSERT_NOT_REACHED(); return nullptr; } - } - diff --git a/LibC/netdb.cpp b/LibC/netdb.cpp index 5cc9742576..3376269223 100644 --- a/LibC/netdb.cpp +++ b/LibC/netdb.cpp @@ -1,12 +1,13 @@ +#include +#include +#include +#include +#include #include +#include #include #include -#include -#include #include -#include -#include -#include extern "C" { @@ -15,6 +16,39 @@ static char __gethostbyname_name_buffer[512]; static in_addr_t __gethostbyname_address; static in_addr_t* __gethostbyname_address_list_buffer[2]; +static hostent __gethostbyaddr_buffer; +static char __gethostbyaddr_name_buffer[512]; +static in_addr_t* __gethostbyaddr_address_list_buffer[2]; + +static int connect_to_lookup_server() +{ + int fd = socket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0); + if (fd < 0) { + perror("socket"); + return -1; + } + + sockaddr_un address; + address.sun_family = AF_LOCAL; + strcpy(address.sun_path, "/tmp/.LookupServer-socket"); + + int retries = 3; + int rc = 0; + while (retries) { + rc = connect(fd, (const sockaddr*)&address, sizeof(address)); + if (rc == 0) + break; + --retries; + sleep(1); + } + + if (rc < 0) { + close(fd); + return -1; + } + return fd; +} + hostent* gethostbyname(const char* name) { unsigned a; @@ -36,36 +70,19 @@ hostent* gethostbyname(const char* name) return &__gethostbyname_buffer; } - int fd = socket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0); - if (fd < 0) { - perror("socket"); + int fd = connect_to_lookup_server(); + if (fd < 0) return nullptr; - } - sockaddr_un address; - address.sun_family = AF_LOCAL; - strcpy(address.sun_path, "/tmp/.LookupServer-socket"); - - int retries = 3; - int rc = 0; - while (retries) { - rc = connect(fd, (const sockaddr*)&address, sizeof(address)); - if (rc == 0) - break; - --retries; - sleep(1); - } - - if (rc < 0) { + auto close_fd_on_exit = ScopeGuard([fd] { + dbgprintf("closing fd\n"); close(fd); - return nullptr; - } + }); - auto line = String::format("%s\n", name); + auto line = String::format("L%s\n", name); int nsent = write(fd, line.characters(), line.length()); if (nsent < 0) { - perror("send"); - close(fd); + perror("write"); return nullptr; } @@ -75,17 +92,15 @@ hostent* gethostbyname(const char* name) int nrecv = read(fd, buffer, sizeof(buffer) - 1); if (nrecv < 0) { perror("recv"); - close(fd); return nullptr; } buffer[nrecv] = '\0'; - close(fd); if (!memcmp(buffer, "Not found.", sizeof("Not found.") - 1)) return nullptr; - rc = inet_pton(AF_INET, buffer, &__gethostbyname_address); - if (rc < 0) + int rc = inet_pton(AF_INET, buffer, &__gethostbyname_address); + if (rc <= 0) return nullptr; strncpy(__gethostbyname_name_buffer, name, strlen(name)); @@ -101,4 +116,66 @@ hostent* gethostbyname(const char* name) return &__gethostbyname_buffer; } +hostent* gethostbyaddr(const void* addr, socklen_t addr_size, int type) +{ + if (type != AF_INET) { + errno = EAFNOSUPPORT; + return nullptr; + } + + if (addr_size < sizeof(in_addr)) { + errno = EINVAL; + return nullptr; + } + + int fd = connect_to_lookup_server(); + if (fd < 0) + return nullptr; + + auto close_fd_on_exit = ScopeGuard([fd] { + close(fd); + }); + + IPv4Address ipv4_address((const byte*)&((const in_addr*)addr)->s_addr); + + auto line = String::format("R%d.%d.%d.%d.in-addr.arpa\n", + ipv4_address[3], + ipv4_address[2], + ipv4_address[1], + ipv4_address[0]); + int nsent = write(fd, line.characters(), line.length()); + if (nsent < 0) { + perror("write"); + return nullptr; + } + + ASSERT(nsent == line.length()); + + char buffer[1024]; + int nrecv = read(fd, buffer, sizeof(buffer) - 1); + if (nrecv < 0) { + perror("recv"); + return nullptr; + } + if (nrecv > 1) { + // Strip newline. + buffer[nrecv - 1] = '\0'; + } + buffer[nrecv] = '\0'; + + if (!memcmp(buffer, "Not found.", sizeof("Not found.") - 1)) + return nullptr; + + strncpy(__gethostbyaddr_name_buffer, buffer, max(sizeof(__gethostbyaddr_name_buffer), (size_t)nrecv)); + + __gethostbyaddr_buffer.h_name = __gethostbyaddr_name_buffer; + __gethostbyaddr_buffer.h_aliases = nullptr; + __gethostbyaddr_buffer.h_addrtype = AF_INET; + // FIXME: Should we populate the hostent's address list here with a sockaddr_in for the provided host? + __gethostbyaddr_address_list_buffer[0] = nullptr; + __gethostbyaddr_buffer.h_addr_list = (char**)__gethostbyaddr_address_list_buffer; + __gethostbyaddr_buffer.h_length = 4; + + return &__gethostbyaddr_buffer; +} } diff --git a/LibC/netdb.h b/LibC/netdb.h index ed75e48240..6f7faffa85 100644 --- a/LibC/netdb.h +++ b/LibC/netdb.h @@ -15,6 +15,7 @@ struct hostent { }; struct hostent* gethostbyname(const char*); +struct hostent* gethostbyaddr(const void* addr, socklen_t len, int type); struct servent { char* s_name; diff --git a/LibC/poll.cpp b/LibC/poll.cpp index 2e3f939a80..9394048801 100644 --- a/LibC/poll.cpp +++ b/LibC/poll.cpp @@ -1,6 +1,6 @@ -#include #include #include +#include extern "C" { @@ -9,6 +9,4 @@ int poll(struct pollfd* fds, int nfds, int timeout) int rc = syscall(SC_poll, fds, nfds, timeout); __RETURN_WITH_ERRNO(rc, rc, -1); } - } - diff --git a/LibC/pwd.cpp b/LibC/pwd.cpp index 9bed1d1bd0..3303cf3d91 100644 --- a/LibC/pwd.cpp +++ b/LibC/pwd.cpp @@ -1,9 +1,9 @@ +#include #include #include #include -#include #include -#include +#include extern "C" { @@ -125,5 +125,4 @@ next_entry: strncpy(__pwdb_entry->shell_buffer, e_shell.characters(), PWDB_STR_MAX_LEN); return __pwdb_entry; } - } diff --git a/LibC/qsort.cpp b/LibC/qsort.cpp index 3bf55bc639..8946da07c2 100644 --- a/LibC/qsort.cpp +++ b/LibC/qsort.cpp @@ -35,16 +35,16 @@ static char sccsid[] = "@(#)qsort.c 5.9 (Berkeley) 2/23/91"; #endif /* LIBC_SCCS and not lint */ -#include #include +#include static void insertion_sort(void* bot, size_t nmemb, size_t size, int (*compar)(const void*, const void*)); static void insertion_sort_r(void* bot, size_t nmemb, size_t size, int (*compar)(const void*, const void*, void*), void* arg); -void qsort(void* bot, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) +void qsort(void* bot, size_t nmemb, size_t size, int (*compar)(const void*, const void*)) { - if (nmemb <= 1) - return; + if (nmemb <= 1) + return; insertion_sort(bot, nmemb, size, compar); } @@ -64,27 +64,29 @@ void insertion_sort(void* bot, size_t nmemb, size_t size, int (*compar)(const vo char *s1, *s2, *t1, *t2, *top; top = (char*)bot + nmemb * size; for (t1 = (char*)bot + size; t1 < top;) { - for (t2 = t1; (t2 -= size) >= bot && compar(t1, t2) < 0;); - if (t1 != (t2 += size)) { - for (cnt = size; cnt--; ++t1) { - ch = *t1; - for (s1 = s2 = t1; (s2 -= size) >= t2; s1 = s2) - *s1 = *s2; - *s1 = ch; - } - } else - t1 += size; - } -} - -void insertion_sort_r(void* bot, size_t nmemb, size_t size, int (*compar)(const void*, const void*, void*), void* arg) -{ - int cnt; - unsigned char ch; - char *s1, *s2, *t1, *t2, *top; - top = (char*)bot + nmemb * size; - for (t1 = (char*)bot + size; t1 < top;) { - for (t2 = t1; (t2 -= size) >= bot && compar(t1, t2, arg) < 0;); + for (t2 = t1; (t2 -= size) >= bot && compar(t1, t2) < 0;) + ; + if (t1 != (t2 += size)) { + for (cnt = size; cnt--; ++t1) { + ch = *t1; + for (s1 = s2 = t1; (s2 -= size) >= t2; s1 = s2) + *s1 = *s2; + *s1 = ch; + } + } else + t1 += size; + } +} + +void insertion_sort_r(void* bot, size_t nmemb, size_t size, int (*compar)(const void*, const void*, void*), void* arg) +{ + int cnt; + unsigned char ch; + char *s1, *s2, *t1, *t2, *top; + top = (char*)bot + nmemb * size; + for (t1 = (char*)bot + size; t1 < top;) { + for (t2 = t1; (t2 -= size) >= bot && compar(t1, t2, arg) < 0;) + ; if (t1 != (t2 += size)) { for (cnt = size; cnt--; ++t1) { ch = *t1; diff --git a/LibC/scanf.cpp b/LibC/scanf.cpp index 4aaa818177..bbf86cd1b5 100644 --- a/LibC/scanf.cpp +++ b/LibC/scanf.cpp @@ -28,10 +28,10 @@ * SUCH DAMAGE. * */ -#include -#include -#include #include +#include +#include +#include static const char* determine_base(const char* p, int& base) { @@ -119,31 +119,32 @@ int atob(unsigned int* vp, const char* p, int base) #define ISSPACE " \t\n\r\f\v" -int vsscanf(const char *buf, const char *s, va_list ap) +int vsscanf(const char* buf, const char* s, va_list ap) { int base = 10; - char *t; + char* t; char tmp[BUFSIZ]; bool noassign = false; int count = 0; int width = 0; while (*s && *buf) { - while (isspace (*s)) + while (isspace(*s)) s++; if (*s == '%') { s++; for (; *s; s++) { - if (strchr ("dibouxcsefg%", *s)) + if (strchr("dibouxcsefg%", *s)) break; if (*s == '*') noassign = true; else if (*s >= '1' && *s <= '9') { const char* tc; - for (tc = s; isdigit(*s); s++); - strncpy (tmp, tc, s - tc); + for (tc = s; isdigit(*s); s++) + ; + strncpy(tmp, tc, s - tc); tmp[s - tc] = '\0'; - atob ((uint32_t*)&width, tmp, 10); + atob((uint32_t*)&width, tmp, 10); s--; } } @@ -180,7 +181,7 @@ int vsscanf(const char *buf, const char *s, va_list ap) if (isspace(*(s + 1)) || *(s + 1) == 0) { width = strcspn(buf, ISSPACE); } else { - auto* p = strchr(buf, *(s+1)); + auto* p = strchr(buf, *(s + 1)); if (p) width = p - buf; else { @@ -204,7 +205,7 @@ int vsscanf(const char *buf, const char *s, va_list ap) ++s; } else { while (isspace(*buf)) - buf++; + buf++; if (*s != *buf) break; else { diff --git a/LibC/sched.cpp b/LibC/sched.cpp index b083595cc9..7c88f7c5d0 100644 --- a/LibC/sched.cpp +++ b/LibC/sched.cpp @@ -1,6 +1,6 @@ -#include -#include #include +#include +#include extern "C" { @@ -22,17 +22,15 @@ int sched_get_priority_max(int policy) return 3; // High } -int sched_setparam(pid_t pid, const struct sched_param *param) +int sched_setparam(pid_t pid, const struct sched_param* param) { int rc = syscall(SC_sched_setparam, pid, param); __RETURN_WITH_ERRNO(rc, rc, -1); } -int sched_getparam(pid_t pid, struct sched_param *param) +int sched_getparam(pid_t pid, struct sched_param* param) { int rc = syscall(SC_sched_getparam, pid, param); __RETURN_WITH_ERRNO(rc, rc, -1); } - } - diff --git a/LibC/sched.h b/LibC/sched.h index d1be1fdda0..080bfc070a 100644 --- a/LibC/sched.h +++ b/LibC/sched.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include __BEGIN_DECLS @@ -18,7 +18,7 @@ struct sched_param { int sched_get_priority_min(int policy); int sched_get_priority_max(int policy); -int sched_setparam(pid_t pid, const struct sched_param *param); -int sched_getparam(pid_t pid, struct sched_param *param); +int sched_setparam(pid_t pid, const struct sched_param* param); +int sched_getparam(pid_t pid, struct sched_param* param); __END_DECLS diff --git a/LibC/signal.cpp b/LibC/signal.cpp index 79f1bd5eb6..59ad5fa1f6 100644 --- a/LibC/signal.cpp +++ b/LibC/signal.cpp @@ -1,10 +1,10 @@ -#include +#include +#include #include +#include #include #include -#include -#include -#include +#include extern "C" { @@ -160,5 +160,4 @@ int sigsuspend(const sigset_t*) dbgprintf("FIXME: Implement sigsuspend()\n"); ASSERT_NOT_REACHED(); } - } diff --git a/LibC/stat.cpp b/LibC/stat.cpp index 8c1f84458f..e74ef33a3f 100644 --- a/LibC/stat.cpp +++ b/LibC/stat.cpp @@ -1,8 +1,8 @@ -#include -#include -#include -#include #include +#include +#include +#include +#include extern "C" { @@ -28,6 +28,4 @@ int fchmod(int fd, mode_t mode) int rc = syscall(SC_fchmod, fd, mode); __RETURN_WITH_ERRNO(rc, rc, -1); } - } - diff --git a/LibC/stdio.cpp b/LibC/stdio.cpp index e94ac7322a..7394819c94 100644 --- a/LibC/stdio.cpp +++ b/LibC/stdio.cpp @@ -1,16 +1,16 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include extern "C" { @@ -458,14 +458,70 @@ char* tmpnam(char*) FILE* popen(const char* command, const char* type) { - (void)command; - (void)type; - ASSERT_NOT_REACHED(); + if (!type || (*type != 'r' && *type != 'w')) { + errno = EINVAL; + return nullptr; + } + + int pipe_fds[2]; + + int rc = pipe(pipe_fds); + if (rc < 0) { + ValueRestorer restorer(errno); + perror("pipe"); + return nullptr; + } + + pid_t child_pid = fork(); + if (!child_pid) { + if (*type == 'r') { + int rc = dup2(pipe_fds[1], STDOUT_FILENO); + if (rc < 0) { + perror("dup2"); + exit(1); + } + close(pipe_fds[0]); + close(pipe_fds[1]); + } else if (*type == 'w') { + int rc = dup2(pipe_fds[0], STDIN_FILENO); + if (rc < 0) { + perror("dup2"); + exit(1); + } + close(pipe_fds[0]); + close(pipe_fds[1]); + } + + int rc = execl("/bin/sh", "sh", "-c", command, nullptr); + if (rc < 0) + perror("execl"); + exit(1); + } + + FILE* fp = nullptr; + if (*type == 'r') { + fp = make_FILE(pipe_fds[0]); + close(pipe_fds[1]); + } else if (*type == 'w') { + fp = make_FILE(pipe_fds[1]); + close(pipe_fds[0]); + } + + fp->popen_child = child_pid; + return fp; } -int pclose(FILE*) +int pclose(FILE* fp) { - ASSERT_NOT_REACHED(); + ASSERT(fp); + ASSERT(fp->popen_child != 0); + + int wstatus = 0; + int rc = waitpid(fp->popen_child, &wstatus, 0); + if (rc < 0) + return rc; + + return wstatus; } int remove(const char* pathname) @@ -516,6 +572,4 @@ FILE* tmpfile() dbgprintf("FIXME: Implement tmpfile()\n"); ASSERT_NOT_REACHED(); } - } - diff --git a/LibC/stdio.h b/LibC/stdio.h index 8da83d9cfb..a8d4c7269f 100644 --- a/LibC/stdio.h +++ b/LibC/stdio.h @@ -29,6 +29,7 @@ struct __STDIO_FILE { int eof; int error; int mode; + pid_t popen_child; char* buffer; size_t buffer_size; size_t buffer_index; diff --git a/LibC/stdlib.cpp b/LibC/stdlib.cpp index 3f4b64329c..d9a6c70fc3 100644 --- a/LibC/stdlib.cpp +++ b/LibC/stdlib.cpp @@ -18,7 +18,7 @@ extern "C" { -typedef void(*__atexit_handler)(); +typedef void (*__atexit_handler)(); static int __atexit_handler_count = 0; static __atexit_handler __atexit_handlers[32]; @@ -41,7 +41,6 @@ int atexit(void (*handler)()) return 0; } - void abort() { raise(SIGABRT); @@ -98,8 +97,8 @@ int unsetenv(const char* name) return 0; // not found: no failure. // Shuffle the existing array down by one. - memmove(&environ[skip], &environ[skip+1], ((environ_size-1)-skip) * sizeof(environ[0])); - environ[environ_size-1] = nullptr; + memmove(&environ[skip], &environ[skip + 1], ((environ_size - 1) - skip) * sizeof(environ[0])); + environ[environ_size - 1] = nullptr; free_environment_variable_if_needed(name); return 0; @@ -143,7 +142,7 @@ int putenv(char* new_var) // At this point, we need to append the new var. // 2 here: one for the new var, one for the sentinel value. - char **new_environ = (char**)malloc((environ_size + 2) * sizeof(char*)); + char** new_environ = (char**)malloc((environ_size + 2) * sizeof(char*)); if (new_environ == nullptr) { errno = ENOMEM; return -1; @@ -237,7 +236,7 @@ static unsigned long s_next_rand = 1; int rand() { s_next_rand = s_next_rand * 1103515245 + 12345; - return((unsigned)(s_next_rand/((RAND_MAX + 1) * 2)) % (RAND_MAX + 1)); + return ((unsigned)(s_next_rand / ((RAND_MAX + 1) * 2)) % (RAND_MAX + 1)); } void srand(unsigned seed) @@ -302,7 +301,7 @@ char* mktemp(char* pattern) return pattern; } -void* bsearch(const void* key, const void* base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) +void* bsearch(const void* key, const void* base, size_t nmemb, size_t size, int (*compar)(const void*, const void*)) { dbgprintf("FIXME(LibC): bsearch(%p, %p, %u, %u, %p)\n", key, base, nmemb, size, compar); ASSERT_NOT_REACHED(); @@ -347,8 +346,7 @@ long strtol(const char* str, char** endptr, int base) c = *s++; } else if (c == '+') c = *s++; - if ((base == 0 || base == 16) && - c == '0' && (*s == 'x' || *s == 'X')) { + if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) { c = s[1]; s += 2; base = 16; @@ -392,5 +390,4 @@ unsigned long strtoul(const char* str, char** endptr, int base) ASSERT(value >= 0); return value; } - } diff --git a/LibC/string.cpp b/LibC/string.cpp index 1f36864a77..dcd795fd30 100644 --- a/LibC/string.cpp +++ b/LibC/string.cpp @@ -1,12 +1,12 @@ -#include -#include -#include -#include -#include -#include -#include -#include #include "ctype.h" +#include +#include +#include +#include +#include +#include +#include +#include extern "C" { @@ -42,7 +42,7 @@ size_t strcspn(const char* s, const char* reject) do { if ((rc = *rp++) == c) return p - 1 - s; - } while(rc); + } while (rc); } } @@ -146,17 +146,14 @@ void* memcpy(void* dest_ptr, const void* src_ptr, size_t n) "rep movsl\n" : "=S"(src), "=D"(dest) : "S"(src), "D"(dest), "c"(dwords) - : "memory" - ); + : "memory"); n -= dwords * sizeof(dword); if (n == 0) return dest_ptr; } asm volatile( - "rep movsb\n" - :: "S"(src), "D"(dest), "c"(n) - : "memory" - ); + "rep movsb\n" ::"S"(src), "D"(dest), "c"(n) + : "memory"); return dest_ptr; } @@ -173,38 +170,36 @@ void* memset(void* dest_ptr, int c, size_t n) "rep stosl\n" : "=D"(dest) : "D"(dest), "c"(dwords), "a"(expanded_c) - : "memory" - ); + : "memory"); n -= dwords * sizeof(dword); if (n == 0) return dest_ptr; } asm volatile( "rep stosb\n" - : "=D" (dest), "=c" (n) - : "0" (dest), "1" (n), "a" (c) - : "memory" - ); + : "=D"(dest), "=c"(n) + : "0"(dest), "1"(n), "a"(c) + : "memory"); return dest_ptr; } - void* memmove(void* dest, const void* src, size_t n) { if (dest < src) return memcpy(dest, src, n); - byte *pd = (byte*)dest; - const byte *ps = (const byte*)src; + byte* pd = (byte*)dest; + const byte* ps = (const byte*)src; for (pd += n, ps += n; n--;) *--pd = *--ps; return dest; } -char* strcpy(char* dest, const char *src) +char* strcpy(char* dest, const char* src) { char* originalDest = dest; - while ((*dest++ = *src++) != '\0'); + while ((*dest++ = *src++) != '\0') + ; return originalDest; } @@ -213,7 +208,7 @@ char* strncpy(char* dest, const char* src, size_t n) size_t i; for (i = 0; i < n && src[i] != '\0'; ++i) dest[i] = src[i]; - for ( ; i < n; ++i) + for (; i < n; ++i) dest[i] = '\0'; return dest; } @@ -242,7 +237,7 @@ void* memchr(const void* ptr, int c, size_t size) char* strrchr(const char* str, int ch) { - char *last = nullptr; + char* last = nullptr; char c; for (; (c = *str); ++str) { if (c == ch) @@ -251,21 +246,21 @@ char* strrchr(const char* str, int ch) return last; } -char* strcat(char *dest, const char *src) +char* strcat(char* dest, const char* src) { size_t dest_length = strlen(dest); size_t i; - for (i = 0 ; src[i] != '\0' ; i++) + for (i = 0; src[i] != '\0'; i++) dest[dest_length + i] = src[i]; dest[dest_length + i] = '\0'; return dest; } -char* strncat(char *dest, const char *src, size_t n) +char* strncat(char* dest, const char* src, size_t n) { size_t dest_length = strlen(dest); size_t i; - for (i = 0 ; i < n && src[i] != '\0' ; i++) + for (i = 0; i < n && src[i] != '\0'; i++) dest[dest_length + i] = src[i]; dest[dest_length + i] = '\0'; return dest; @@ -387,12 +382,12 @@ char* strstr(const char* haystack, const char* needle) char* strpbrk(const char* s, const char* accept) { while (*s) - if(strchr(accept, *s++)) + if (strchr(accept, *s++)) return const_cast(--s); return nullptr; } -char *strtok(char* str, const char* delim) +char* strtok(char* str, const char* delim) { (void)str; (void)delim; @@ -409,10 +404,8 @@ size_t strxfrm(char* dest, const char* src, size_t n) size_t i; for (i = 0; i < n && src[i] != '\0'; ++i) dest[i] = src[i]; - for ( ; i < n; ++i) + for (; i < n; ++i) dest[i] = '\0'; return i; } - } - diff --git a/LibC/strings.cpp b/LibC/strings.cpp index abbfeca214..8f248e1438 100644 --- a/LibC/strings.cpp +++ b/LibC/strings.cpp @@ -1,6 +1,6 @@ -#include #include #include +#include extern "C" { @@ -32,5 +32,4 @@ int strncasecmp(const char* s1, const char* s2, size_t n) } while (--n); return 0; } - } diff --git a/LibC/sys/cdefs.h b/LibC/sys/cdefs.h index 1b6b52cca2..f83fbad3c2 100644 --- a/LibC/sys/cdefs.h +++ b/LibC/sys/cdefs.h @@ -3,7 +3,7 @@ #define _POSIX_VERSION 200809L #ifndef ALWAYS_INLINE -#define ALWAYS_INLINE inline __attribute__((always_inline)) +# define ALWAYS_INLINE inline __attribute__((always_inline)) #endif #ifdef __cplusplus diff --git a/LibC/sys/ioctl_numbers.h b/LibC/sys/ioctl_numbers.h index f8ac61aeda..dd6711c43c 100644 --- a/LibC/sys/ioctl_numbers.h +++ b/LibC/sys/ioctl_numbers.h @@ -1,7 +1,6 @@ #pragma once -enum IOCtlNumber -{ +enum IOCtlNumber { TIOCGPGRP, TIOCSPGRP, TCGETS, diff --git a/LibC/sys/select.cpp b/LibC/sys/select.cpp index 70a46e7850..60d54a20c8 100644 --- a/LibC/sys/select.cpp +++ b/LibC/sys/select.cpp @@ -1,7 +1,7 @@ -#include #include #include #include +#include extern "C" { @@ -11,5 +11,4 @@ int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struc int rc = syscall(SC_select, ¶ms); __RETURN_WITH_ERRNO(rc, rc, -1); } - } diff --git a/LibC/sys/socket.cpp b/LibC/sys/socket.cpp index 3206832a96..85f2b09ab9 100644 --- a/LibC/sys/socket.cpp +++ b/LibC/sys/socket.cpp @@ -1,8 +1,8 @@ -#include -#include -#include #include +#include +#include #include +#include extern "C" { @@ -85,5 +85,4 @@ int getpeername(int sockfd, struct sockaddr* addr, socklen_t* addrlen) int rc = syscall(SC_getpeername, sockfd, addr, addrlen); __RETURN_WITH_ERRNO(rc, rc, -1); } - } diff --git a/LibC/sys/uio.cpp b/LibC/sys/uio.cpp index efa4a1b5eb..f57f29bb7a 100644 --- a/LibC/sys/uio.cpp +++ b/LibC/sys/uio.cpp @@ -1,6 +1,6 @@ -#include -#include #include +#include +#include extern "C" { @@ -9,5 +9,4 @@ ssize_t writev(int fd, const struct iovec* iov, int iov_count) int rc = syscall(SC_writev, fd, iov, iov_count); __RETURN_WITH_ERRNO(rc, rc, -1); } - } diff --git a/LibC/sys/wait.cpp b/LibC/sys/wait.cpp index d010b39cba..9b0762653c 100644 --- a/LibC/sys/wait.cpp +++ b/LibC/sys/wait.cpp @@ -1,6 +1,6 @@ +#include #include #include -#include extern "C" { @@ -8,5 +8,4 @@ pid_t wait(int* wstatus) { return waitpid(-1, wstatus, 0); } - } diff --git a/LibC/termcap.cpp b/LibC/termcap.cpp index 9d34bc18f1..98b55a2e54 100644 --- a/LibC/termcap.cpp +++ b/LibC/termcap.cpp @@ -1,9 +1,9 @@ -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include //#define TERMCAP_DEBUG @@ -126,6 +126,4 @@ int tputs(const char* str, int affcnt, int (*putc)(int)) putc(str[i]); return 0; } - } - diff --git a/LibC/termios.cpp b/LibC/termios.cpp index 0e44aad819..be70fc6685 100644 --- a/LibC/termios.cpp +++ b/LibC/termios.cpp @@ -1,8 +1,8 @@ +#include #include #include -#include #include -#include +#include extern "C" { @@ -27,8 +27,8 @@ int tcsetattr(int fd, int optional_actions, const struct termios* t) int tcflow(int fd, int action) { - (void) fd; - (void) action; + (void)fd; + (void)action; ASSERT_NOT_REACHED(); } @@ -48,6 +48,4 @@ speed_t cfgetospeed(const struct termios* tp) { return tp->c_ospeed; } - } - diff --git a/LibC/time.cpp b/LibC/time.cpp index 30b6b296e6..6024664fed 100644 --- a/LibC/time.cpp +++ b/LibC/time.cpp @@ -1,9 +1,9 @@ -#include +#include +#include +#include #include #include -#include -#include -#include +#include extern "C" { @@ -91,7 +91,7 @@ struct tm* gmtime(const time_t* t) return localtime(t); } -char *asctime(const struct tm*) +char* asctime(const struct tm*) { ASSERT_NOT_REACHED(); } @@ -117,5 +117,4 @@ clock_t clock() times(&tms); return tms.tms_utime + tms.tms_stime; } - } diff --git a/LibC/times.cpp b/LibC/times.cpp index 7411af706d..76301ec0e0 100644 --- a/LibC/times.cpp +++ b/LibC/times.cpp @@ -1,6 +1,6 @@ -#include -#include #include +#include +#include clock_t times(struct tms* buf) { diff --git a/LibC/ulimit.cpp b/LibC/ulimit.cpp index c16a06fe1a..14e7cb8c34 100644 --- a/LibC/ulimit.cpp +++ b/LibC/ulimit.cpp @@ -1,13 +1,12 @@ -#include #include +#include extern "C" { long ulimit(int cmd, long newlimit) { - (void) cmd; - (void) newlimit; + (void)cmd; + (void)newlimit; ASSERT_NOT_REACHED(); } - } diff --git a/LibC/unistd.cpp b/LibC/unistd.cpp index 22a4204b8f..473c2b605d 100644 --- a/LibC/unistd.cpp +++ b/LibC/unistd.cpp @@ -1,18 +1,18 @@ -#include -#include -#include -#include +#include +#include +#include #include +#include +#include #include #include +#include #include #include +#include #include #include -#include -#include -#include -#include +#include extern "C" { @@ -28,6 +28,12 @@ int chown(const char* pathname, uid_t uid, gid_t gid) __RETURN_WITH_ERRNO(rc, rc, -1); } +int fchown(int fd, uid_t uid, gid_t gid) +{ + int rc = syscall(SC_fchown, fd, uid, gid); + __RETURN_WITH_ERRNO(rc, rc, -1); +} + pid_t fork() { int rc = syscall(SC_fork); @@ -219,7 +225,7 @@ int stat(const char* path, struct stat* statbuf) __RETURN_WITH_ERRNO(rc, rc, -1); } -int fstat(int fd, struct stat *statbuf) +int fstat(int fd, struct stat* statbuf) { int rc = syscall(SC_fstat, fd, statbuf); __RETURN_WITH_ERRNO(rc, rc, -1); @@ -372,15 +378,15 @@ int mknod(const char* pathname, mode_t mode, dev_t dev) long fpathconf(int fd, int name) { - (void) fd; - (void) name; + (void)fd; + (void)name; ASSERT_NOT_REACHED(); } long pathconf(const char* path, int name) { - (void) path; - (void) name; + (void)path; + (void)name; ASSERT_NOT_REACHED(); } @@ -445,7 +451,7 @@ char* getlogin() return nullptr; } -int create_thread(int(*entry)(void*), void* argument) +int create_thread(int (*entry)(void*), void* argument) { int rc = syscall(SC_create_thread, entry, argument); __RETURN_WITH_ERRNO(rc, rc, -1); @@ -486,5 +492,4 @@ int fsync(int fd) dbgprintf("FIXME: Implement fsync()\n"); return 0; } - } diff --git a/LibC/unistd.h b/LibC/unistd.h index a935330a6d..cfe5c26b26 100644 --- a/LibC/unistd.h +++ b/LibC/unistd.h @@ -88,10 +88,10 @@ long fpathconf(int fd, int name); long pathconf(const char* path, int name); char* getlogin(); int chown(const char* pathname, uid_t, gid_t); +int fchown(int fd, uid_t, gid_t); int ftruncate(int fd, off_t length); -enum -{ +enum { _PC_NAME_MAX, }; diff --git a/LibC/utime.cpp b/LibC/utime.cpp index 737d958e49..e8517ab4df 100644 --- a/LibC/utime.cpp +++ b/LibC/utime.cpp @@ -1,6 +1,6 @@ -#include -#include #include +#include +#include extern "C" { @@ -9,6 +9,4 @@ int utime(const char* pathname, const struct utimbuf* buf) int rc = syscall(SC_utime, (dword)pathname, (dword)buf); __RETURN_WITH_ERRNO(rc, rc, -1); } - } - diff --git a/LibC/utsname.cpp b/LibC/utsname.cpp index bc8d5f02a6..7b03cc1ae7 100644 --- a/LibC/utsname.cpp +++ b/LibC/utsname.cpp @@ -1,6 +1,6 @@ -#include -#include #include +#include +#include extern "C" { @@ -9,6 +9,4 @@ int uname(struct utsname* buf) int rc = syscall(SC_uname, buf); __RETURN_WITH_ERRNO(rc, rc, -1); } - } - diff --git a/LibCore/CDirIterator.cpp b/LibCore/CDirIterator.cpp index aa64ea8b71..d76d52970d 100644 --- a/LibCore/CDirIterator.cpp +++ b/LibCore/CDirIterator.cpp @@ -1,7 +1,7 @@ #include "CDirIterator.h" #include -CDirIterator::CDirIterator(const String& path, Flags flags) +CDirIterator::CDirIterator(const StringView& path, Flags flags) : m_flags(flags) { m_dir = opendir(path.characters()); diff --git a/LibCore/CDirIterator.h b/LibCore/CDirIterator.h index 72920c2c1f..08c9040b48 100644 --- a/LibCore/CDirIterator.h +++ b/LibCore/CDirIterator.h @@ -5,13 +5,12 @@ class CDirIterator { public: - enum Flags - { + enum Flags { NoFlags = 0x0, SkipDots = 0x1, }; - CDirIterator(const String& path, Flags = Flags::NoFlags); + CDirIterator(const StringView& path, Flags = Flags::NoFlags); ~CDirIterator(); bool has_error() const { return m_error != 0; } diff --git a/LibCore/CElapsedTimer.cpp b/LibCore/CElapsedTimer.cpp index e783f59b0d..4e8902d348 100644 --- a/LibCore/CElapsedTimer.cpp +++ b/LibCore/CElapsedTimer.cpp @@ -15,6 +15,6 @@ int CElapsedTimer::elapsed() const struct timeval now; gettimeofday(&now, nullptr); struct timeval diff; - AK::timeval_sub(&now, &m_start_time, &diff); + timeval_sub(now, m_start_time, diff); return diff.tv_sec * 1000 + diff.tv_usec / 1000; } diff --git a/LibCore/CEvent.h b/LibCore/CEvent.h index 1920df2688..9d262c4a76 100644 --- a/LibCore/CEvent.h +++ b/LibCore/CEvent.h @@ -9,8 +9,7 @@ class CObject; class CEvent { public: - enum Type - { + enum Type { Invalid = 0, Quit, Timer, diff --git a/LibCore/CEventLoop.cpp b/LibCore/CEventLoop.cpp index d84a45fe16..3bfe98893f 100644 --- a/LibCore/CEventLoop.cpp +++ b/LibCore/CEventLoop.cpp @@ -191,7 +191,7 @@ void CEventLoop::wait_for_event(WaitMode mode) if (!s_timers->is_empty() && queued_events_is_empty) { gettimeofday(&now, nullptr); get_next_timer_expiration(timeout); - AK::timeval_sub(&timeout, &now, &timeout); + timeval_sub(timeout, now, timeout); } else { should_wait_forever = true; } @@ -199,8 +199,8 @@ void CEventLoop::wait_for_event(WaitMode mode) should_wait_forever = false; } - int rc = select(max_fd + 1, &rfds, &wfds, nullptr, should_wait_forever ? nullptr : &timeout); - if (rc < 0) { + int marked_fd_count = select(max_fd + 1, &rfds, &wfds, nullptr, should_wait_forever ? nullptr : &timeout); + if (marked_fd_count < 0) { ASSERT_NOT_REACHED(); } @@ -224,6 +224,9 @@ void CEventLoop::wait_for_event(WaitMode mode) } } + if (!marked_fd_count) + return; + for (auto& notifier : *s_notifiers) { if (FD_ISSET(notifier->fd(), &rfds)) { if (notifier->on_ready_to_read) diff --git a/LibCore/CEventLoop.h b/LibCore/CEventLoop.h index dbcc67ddb7..8cab0bbe99 100644 --- a/LibCore/CEventLoop.h +++ b/LibCore/CEventLoop.h @@ -21,8 +21,7 @@ public: int exec(); - enum class WaitMode - { + enum class WaitMode { WaitForEvents, PollForEvents, }; diff --git a/LibCore/CFile.cpp b/LibCore/CFile.cpp index 44813e1c97..335f54009a 100644 --- a/LibCore/CFile.cpp +++ b/LibCore/CFile.cpp @@ -3,18 +3,18 @@ #include #include -CFile::CFile(const String& filename) +CFile::CFile(const StringView& filename) : m_filename(filename) { } CFile::~CFile() { - if (m_should_close_file_descriptor == ShouldCloseFileDescriptor::Yes && mode() != NotOpen) + if (m_should_close_file_descriptor == ShouldCloseFileDescription::Yes && mode() != NotOpen) close(); } -bool CFile::open(int fd, CIODevice::OpenMode mode, ShouldCloseFileDescriptor should_close) +bool CFile::open(int fd, CIODevice::OpenMode mode, ShouldCloseFileDescription should_close) { set_fd(fd); set_mode(mode); diff --git a/LibCore/CFile.h b/LibCore/CFile.h index fab396ac55..976d5718d9 100644 --- a/LibCore/CFile.h +++ b/LibCore/CFile.h @@ -6,24 +6,23 @@ class CFile final : public CIODevice { public: CFile() {} - explicit CFile(const String&); + explicit CFile(const StringView&); virtual ~CFile() override; String filename() const { return m_filename; } - void set_filename(const String& filename) { m_filename = filename; } + void set_filename(const StringView& filename) { m_filename = filename; } virtual bool open(CIODevice::OpenMode) override; - enum class ShouldCloseFileDescriptor - { + enum class ShouldCloseFileDescription { No = 0, Yes }; - bool open(int fd, CIODevice::OpenMode, ShouldCloseFileDescriptor); + bool open(int fd, CIODevice::OpenMode, ShouldCloseFileDescription); virtual const char* class_name() const override { return "CFile"; } private: String m_filename; - ShouldCloseFileDescriptor m_should_close_file_descriptor { ShouldCloseFileDescriptor::Yes }; + ShouldCloseFileDescription m_should_close_file_descriptor { ShouldCloseFileDescription::Yes }; }; diff --git a/LibCore/CHttpJob.h b/LibCore/CHttpJob.h index c8d2c8c361..5b714a7f77 100644 --- a/LibCore/CHttpJob.h +++ b/LibCore/CHttpJob.h @@ -18,8 +18,7 @@ public: private: void on_socket_connected(); - enum class State - { + enum class State { InStatus, InHeaders, InBody, diff --git a/LibCore/CHttpRequest.h b/LibCore/CHttpRequest.h index 8ab6fef413..c5a39c9ffd 100644 --- a/LibCore/CHttpRequest.h +++ b/LibCore/CHttpRequest.h @@ -6,8 +6,7 @@ class CNetworkJob; class CHttpRequest { public: - enum Method - { + enum Method { Invalid, HEAD, GET, diff --git a/LibCore/CIODevice.cpp b/LibCore/CIODevice.cpp index bf1fdb68b2..ff46374d2d 100644 --- a/LibCore/CIODevice.cpp +++ b/LibCore/CIODevice.cpp @@ -1,9 +1,9 @@ +#include #include #include #include #include #include -#include CIODevice::CIODevice(CObject* parent) : CObject(parent) @@ -22,9 +22,9 @@ const char* CIODevice::error_string() const ByteBuffer CIODevice::read(int max_size) { if (m_fd < 0) - return { }; + return {}; if (!max_size) - return { }; + return {}; auto buffer = ByteBuffer::create_uninitialized(max_size); auto* buffer_ptr = (char*)buffer.pointer(); int remaining_buffer_space = buffer.size(); @@ -42,11 +42,11 @@ ByteBuffer CIODevice::read(int max_size) int nread = ::read(m_fd, buffer_ptr, remaining_buffer_space); if (nread < 0) { set_error(errno); - return { }; + return {}; } if (nread == 0) { set_eof(true); - return { }; + return {}; } buffer.trim(nread); return buffer; @@ -58,7 +58,9 @@ bool CIODevice::can_read_from_fd() const fd_set rfds; FD_ZERO(&rfds); FD_SET(m_fd, &rfds); - struct timeval timeout { 0, 0 }; + struct timeval timeout { + 0, 0 + }; int rc = select(m_fd + 1, &rfds, nullptr, nullptr, &timeout); if (rc < 0) { // NOTE: We don't set m_error here. @@ -112,15 +114,15 @@ ByteBuffer CIODevice::read_all() ByteBuffer CIODevice::read_line(int max_size) { if (m_fd < 0) - return { }; + return {}; if (!max_size) - return { }; + return {}; if (!can_read_line()) - return { }; + return {}; if (m_eof) { if (m_buffered_data.size() > max_size) { dbgprintf("CIODevice::read_line: At EOF but there's more than max_size(%d) buffered\n", max_size); - return { }; + return {}; } auto buffer = ByteBuffer::copy(m_buffered_data.data(), m_buffered_data.size()); m_buffered_data.clear(); @@ -140,7 +142,7 @@ ByteBuffer CIODevice::read_line(int max_size) return line; } } - return { }; + return {}; } bool CIODevice::populate_read_buffer() @@ -175,7 +177,7 @@ bool CIODevice::close() return true; } -bool CIODevice::seek(signed_qword offset, SeekMode mode, off_t *pos) +bool CIODevice::seek(signed_qword offset, SeekMode mode, off_t* pos) { int m = SEEK_SET; switch (mode) { @@ -208,6 +210,7 @@ bool CIODevice::write(const byte* data, int size) int rc = ::write(m_fd, data, size); if (rc < 0) { perror("CIODevice::write: write"); + set_error(errno); return false; } return rc == size; @@ -218,11 +221,12 @@ int CIODevice::printf(const char* format, ...) va_list ap; va_start(ap, format); // FIXME: We're not propagating write() failures to client here! - int ret = printf_internal([this] (char*&, char ch) { + int ret = printf_internal([this](char*&, char ch) { int rc = write((const byte*)&ch, 1); if (rc < 0) dbgprintf("CIODevice::printf: write: %s\n", strerror(errno)); - }, nullptr, format, ap); + }, + nullptr, format, ap); va_end(ap); return ret; } diff --git a/LibCore/CIODevice.h b/LibCore/CIODevice.h index 4977c3f33b..36cbd0e0fd 100644 --- a/LibCore/CIODevice.h +++ b/LibCore/CIODevice.h @@ -1,12 +1,12 @@ #pragma once #include +#include #include class CIODevice : public CObject { public: - enum OpenMode - { + enum OpenMode { NotOpen = 0, ReadOnly = 1, WriteOnly = 2, @@ -32,14 +32,14 @@ public: ByteBuffer read_all(); bool write(const byte*, int size); + bool write(const AK::StringView& v) { return write((const byte*)v.characters(), v.length()); } // FIXME: I would like this to be const but currently it needs to call populate_read_buffer(). bool can_read_line(); bool can_read() const; - enum class SeekMode - { + enum class SeekMode { SetPosition, FromCurrentPosition, FromEndPosition, diff --git a/LibCore/CNetworkJob.h b/LibCore/CNetworkJob.h index 3d8117c754..eaae27c464 100644 --- a/LibCore/CNetworkJob.h +++ b/LibCore/CNetworkJob.h @@ -7,8 +7,7 @@ class CNetworkResponse; class CNetworkJob : public CObject { public: - enum class Error - { + enum class Error { None, ConnectionFailed, TransmissionFailed, diff --git a/LibCore/CNotifier.h b/LibCore/CNotifier.h index 736d78e04b..196cad8388 100644 --- a/LibCore/CNotifier.h +++ b/LibCore/CNotifier.h @@ -4,8 +4,7 @@ class CNotifier { public: - enum Event - { + enum Event { None = 0, Read = 1, Write = 2, diff --git a/LibCore/CObject.h b/LibCore/CObject.h index fda00cd976..392a94e189 100644 --- a/LibCore/CObject.h +++ b/LibCore/CObject.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -24,7 +25,7 @@ public: void for_each_child(Callback callback) { for (auto* child : m_children) { - if (callback(*child) == IterationDecision::Abort) + if (callback(*child) == IterationDecision::Break) return; } } @@ -63,19 +64,22 @@ private: }; template -inline bool is(const CObject&) { return true; } +inline bool is(const CObject&) { return false; } + +template<> +inline bool is(const CObject&) { return true; } template inline T& to(CObject& object) { - ASSERT(is(object)); + ASSERT(is::Type>(object)); return static_cast(object); } template inline const T& to(const CObject& object) { - ASSERT(is(object)); + ASSERT(is::Type>(object)); return static_cast(object); } diff --git a/LibCore/CProcessStatisticsReader.cpp b/LibCore/CProcessStatisticsReader.cpp index 439ec36e13..33977f1540 100644 --- a/LibCore/CProcessStatisticsReader.cpp +++ b/LibCore/CProcessStatisticsReader.cpp @@ -74,13 +74,13 @@ void CProcessStatisticsReader::update_map(HashMap& ma process.state = parts[7]; process.name = parts[11]; - process.linear = parts[12].to_uint(ok); + process.virtual_size = parts[12].to_uint(ok); if (!ok) { - fprintf(stderr, "CProcessHelper : couldn't convert %s to a valid amount of linear address space used\n", parts[12].characters()); + fprintf(stderr, "CProcessHelper : couldn't convert %s to a valid amount of virtual address space used\n", parts[12].characters()); return; } - process.physical = parts[13].to_uint(ok); + process.physical_size = parts[13].to_uint(ok); if (!ok) { fprintf(stderr, "CProcessHelper : couldn't convert %s to a valid amount of physical address space used\n", parts[13].characters()); return; diff --git a/LibCore/CProcessStatisticsReader.h b/LibCore/CProcessStatisticsReader.h index df9b788ea2..adb96f39ad 100644 --- a/LibCore/CProcessStatisticsReader.h +++ b/LibCore/CProcessStatisticsReader.h @@ -11,8 +11,8 @@ struct CProcessStatistics { String username; uid_t uid; String priority; - size_t linear; - size_t physical; + size_t virtual_size; + size_t physical_size; unsigned syscalls; }; diff --git a/LibCore/CSocket.h b/LibCore/CSocket.h index 0de7872fb2..587f80f290 100644 --- a/LibCore/CSocket.h +++ b/LibCore/CSocket.h @@ -7,8 +7,7 @@ class CNotifier; class CSocket : public CIODevice { public: - enum class Type - { + enum class Type { Invalid, TCP, UDP diff --git a/LibCore/CSocketAddress.h b/LibCore/CSocketAddress.h index efa545f24c..33ad5c0253 100644 --- a/LibCore/CSocketAddress.h +++ b/LibCore/CSocketAddress.h @@ -4,8 +4,7 @@ class CSocketAddress { public: - enum class Type - { + enum class Type { Invalid, IPv4, Local diff --git a/LibGUI/GAbstractButton.cpp b/LibGUI/GAbstractButton.cpp index 03f95e0e1d..27b0fefb32 100644 --- a/LibGUI/GAbstractButton.cpp +++ b/LibGUI/GAbstractButton.cpp @@ -6,7 +6,7 @@ GAbstractButton::GAbstractButton(GWidget* parent) { } -GAbstractButton::GAbstractButton(const String& text, GWidget* parent) +GAbstractButton::GAbstractButton(const StringView& text, GWidget* parent) : GWidget(parent) , m_text(text) { @@ -16,7 +16,7 @@ GAbstractButton::~GAbstractButton() { } -void GAbstractButton::set_text(const String& text) +void GAbstractButton::set_text(const StringView& text) { if (m_text == text) return; @@ -29,6 +29,20 @@ void GAbstractButton::set_checked(bool checked) if (m_checked == checked) return; m_checked = checked; + + if (is_exclusive() && checked) { + parent_widget()->for_each_child_of_type([&] (auto& sibling) { + if (!sibling.is_exclusive() || !sibling.is_checkable() || !sibling.is_checked()) + return IterationDecision::Continue; + sibling.m_checked = false; + sibling.update(); + if (sibling.on_checked) + sibling.on_checked(false); + return IterationDecision::Continue; + }); + m_checked = true; + } + update(); if (on_checked) on_checked(checked); diff --git a/LibGUI/GAbstractButton.h b/LibGUI/GAbstractButton.h index 40f9869f28..340b0ee880 100644 --- a/LibGUI/GAbstractButton.h +++ b/LibGUI/GAbstractButton.h @@ -11,9 +11,12 @@ public: Function on_checked; - void set_text(const String&); + void set_text(const StringView&); const String& text() const { return m_text; } + bool is_exclusive() const { return m_exclusive; } + void set_exclusive(bool b) { m_exclusive = b; } + bool is_checked() const { return m_checked; } void set_checked(bool); @@ -30,7 +33,7 @@ public: protected: explicit GAbstractButton(GWidget* parent); - GAbstractButton(const String&, GWidget* parent); + GAbstractButton(const StringView&, GWidget* parent); virtual void mousedown_event(GMouseEvent&) override; virtual void mousemove_event(GMouseEvent&) override; @@ -43,9 +46,20 @@ protected: void paint_text(GPainter&, const Rect&, const Font&, TextAlignment); private: + virtual bool is_abstract_button() const final { return true; } + String m_text; bool m_checked { false }; bool m_checkable { false }; bool m_hovered { false }; bool m_being_pressed { false }; + bool m_exclusive { false }; }; + +template<> +inline bool is(const CObject& object) +{ + if (!is(object)) + return false; + return to(object).is_abstract_button(); +} diff --git a/LibGUI/GAbstractView.cpp b/LibGUI/GAbstractView.cpp index 654566f244..36b10818ad 100644 --- a/LibGUI/GAbstractView.cpp +++ b/LibGUI/GAbstractView.cpp @@ -1,9 +1,9 @@ +#include #include #include -#include #include +#include #include -#include GAbstractView::GAbstractView(GWidget* parent) : GScrollableWidget(parent) @@ -84,7 +84,7 @@ void GAbstractView::begin_editing(const GModelIndex& index) void GAbstractView::stop_editing() { - m_edit_index = { }; + m_edit_index = {}; delete m_edit_widget; m_edit_widget = nullptr; } diff --git a/LibGUI/GAction.cpp b/LibGUI/GAction.cpp index a2718690d0..3e701d485a 100644 --- a/LibGUI/GAction.cpp +++ b/LibGUI/GAction.cpp @@ -3,7 +3,7 @@ #include #include -GAction::GAction(const String& text, const String& custom_data, Function on_activation_callback, GWidget* widget) +GAction::GAction(const StringView& text, const StringView& custom_data, Function on_activation_callback, GWidget* widget) : on_activation(move(on_activation_callback)) , m_text(text) , m_custom_data(custom_data) @@ -11,12 +11,12 @@ GAction::GAction(const String& text, const String& custom_data, Function on_activation_callback, GWidget* widget) +GAction::GAction(const StringView& text, Function on_activation_callback, GWidget* widget) : GAction(text, String(), move(on_activation_callback), widget) { } -GAction::GAction(const String& text, RetainPtr&& icon, Function on_activation_callback, GWidget* widget) +GAction::GAction(const StringView& text, RetainPtr&& icon, Function on_activation_callback, GWidget* widget) : on_activation(move(on_activation_callback)) , m_text(text) , m_icon(move(icon)) @@ -24,13 +24,12 @@ GAction::GAction(const String& text, RetainPtr&& icon, Function< { } -GAction::GAction(const String& text, const GShortcut& shortcut, Function on_activation_callback, GWidget* widget) +GAction::GAction(const StringView& text, const GShortcut& shortcut, Function on_activation_callback, GWidget* widget) : GAction(text, shortcut, nullptr, move(on_activation_callback), widget) { } - -GAction::GAction(const String& text, const GShortcut& shortcut, RetainPtr&& icon, Function on_activation_callback, GWidget* widget) +GAction::GAction(const StringView& text, const GShortcut& shortcut, RetainPtr&& icon, Function on_activation_callback, GWidget* widget) : on_activation(move(on_activation_callback)) , m_text(text) , m_icon(move(icon)) @@ -99,10 +98,10 @@ void GAction::set_enabled(bool enabled) if (m_enabled == enabled) return; m_enabled = enabled; - for_each_toolbar_button([enabled] (GButton& button) { + for_each_toolbar_button([enabled](GButton& button) { button.set_enabled(enabled); }); - for_each_menu_item([enabled] (GMenuItem& item) { + for_each_menu_item([enabled](GMenuItem& item) { item.set_enabled(enabled); }); } @@ -112,10 +111,10 @@ void GAction::set_checked(bool checked) if (m_checked == checked) return; m_checked = checked; - for_each_toolbar_button([checked] (GButton& button) { + for_each_toolbar_button([checked](GButton& button) { button.set_checked(checked); }); - for_each_menu_item([checked] (GMenuItem& item) { + for_each_menu_item([checked](GMenuItem& item) { item.set_checked(checked); }); } diff --git a/LibGUI/GAction.h b/LibGUI/GAction.h index 5770693a8c..02bca55e9a 100644 --- a/LibGUI/GAction.h +++ b/LibGUI/GAction.h @@ -18,29 +18,28 @@ class GWidget; class GAction : public Retainable , public Weakable { public: - enum class ShortcutScope - { + enum class ShortcutScope { None, ApplicationGlobal, WidgetLocal, }; - static Retained create(const String& text, Function callback, GWidget* widget = nullptr) + static Retained create(const StringView& text, Function callback, GWidget* widget = nullptr) { return adopt(*new GAction(text, move(callback), widget)); } - static Retained create(const String& text, const String& custom_data, Function callback, GWidget* widget = nullptr) + static Retained create(const StringView& text, const StringView& custom_data, Function callback, GWidget* widget = nullptr) { return adopt(*new GAction(text, custom_data, move(callback), widget)); } - static Retained create(const String& text, RetainPtr&& icon, Function callback, GWidget* widget = nullptr) + static Retained create(const StringView& text, RetainPtr&& icon, Function callback, GWidget* widget = nullptr) { return adopt(*new GAction(text, move(icon), move(callback), widget)); } - static Retained create(const String& text, const GShortcut& shortcut, Function callback, GWidget* widget = nullptr) + static Retained create(const StringView& text, const GShortcut& shortcut, Function callback, GWidget* widget = nullptr) { return adopt(*new GAction(text, shortcut, move(callback), widget)); } - static Retained create(const String& text, const GShortcut& shortcut, RetainPtr&& icon, Function callback, GWidget* widget = nullptr) + static Retained create(const StringView& text, const GShortcut& shortcut, RetainPtr&& icon, Function callback, GWidget* widget = nullptr) { return adopt(*new GAction(text, shortcut, move(icon), move(callback), widget)); } @@ -77,11 +76,11 @@ public: void unregister_menu_item(Badge, GMenuItem&); private: - GAction(const String& text, Function = nullptr, GWidget* = nullptr); - GAction(const String& text, const GShortcut&, Function = nullptr, GWidget* = nullptr); - GAction(const String& text, const GShortcut&, RetainPtr&& icon, Function = nullptr, GWidget* = nullptr); - GAction(const String& text, RetainPtr&& icon, Function = nullptr, GWidget* = nullptr); - GAction(const String& text, const String& custom_data = String(), Function = nullptr, GWidget* = nullptr); + GAction(const StringView& text, Function = nullptr, GWidget* = nullptr); + GAction(const StringView& text, const GShortcut&, Function = nullptr, GWidget* = nullptr); + GAction(const StringView& text, const GShortcut&, RetainPtr&& icon, Function = nullptr, GWidget* = nullptr); + GAction(const StringView& text, RetainPtr&& icon, Function = nullptr, GWidget* = nullptr); + GAction(const StringView& text, const StringView& custom_data = StringView(), Function = nullptr, GWidget* = nullptr); template void for_each_toolbar_button(Callback); diff --git a/LibGUI/GApplication.cpp b/LibGUI/GApplication.cpp index 8f16b07791..072021eb4a 100644 --- a/LibGUI/GApplication.cpp +++ b/LibGUI/GApplication.cpp @@ -1,10 +1,10 @@ +#include #include #include -#include -#include -#include #include +#include #include +#include #include static GApplication* s_the; @@ -84,7 +84,7 @@ public: set_main_widget(m_label); } - void set_tooltip(const String& tooltip) + void set_tooltip(const StringView& tooltip) { // FIXME: Add some kind of GLabel auto-sizing feature. int text_width = m_label->font().width(tooltip); @@ -95,7 +95,7 @@ public: GLabel* m_label { nullptr }; }; -void GApplication::show_tooltip(const String& tooltip, const Point& screen_location) +void GApplication::show_tooltip(const StringView& tooltip, const Point& screen_location) { if (!m_tooltip_window) { m_tooltip_window = new TooltipWindow; diff --git a/LibGUI/GApplication.h b/LibGUI/GApplication.h index 14b9d65f59..e68ad1f690 100644 --- a/LibGUI/GApplication.h +++ b/LibGUI/GApplication.h @@ -26,7 +26,7 @@ public: void register_global_shortcut_action(Badge, GAction&); void unregister_global_shortcut_action(Badge, GAction&); - void show_tooltip(const String&, const Point& screen_location); + void show_tooltip(const StringView&, const Point& screen_location); void hide_tooltip(); private: diff --git a/LibGUI/GButton.cpp b/LibGUI/GButton.cpp index 46f49a61ab..ea84af5976 100644 --- a/LibGUI/GButton.cpp +++ b/LibGUI/GButton.cpp @@ -1,16 +1,16 @@ #include "GButton.h" +#include +#include +#include #include #include -#include -#include -#include GButton::GButton(GWidget* parent) : GAbstractButton(parent) { } -GButton::GButton(const String& text, GWidget* parent) +GButton::GButton(const StringView& text, GWidget* parent) : GAbstractButton(text, parent) { } @@ -18,7 +18,7 @@ GButton::GButton(const String& text, GWidget* parent) GButton::~GButton() { if (m_action) - m_action->unregister_button({ }, *this); + m_action->unregister_button({}, *this); } void GButton::paint_event(GPaintEvent& event) @@ -60,6 +60,8 @@ void GButton::click() { if (!is_enabled()) return; + if (is_checkable()) + set_checked(!is_checked()); if (on_click) on_click(*this); } @@ -71,7 +73,7 @@ bool GButton::accepts_keyboard_select() const { void GButton::set_action(GAction& action) { m_action = action.make_weak_ptr(); - action.register_button({ }, *this); + action.register_button({}, *this); set_enabled(action.is_enabled()); set_checkable(action.is_checkable()); if (action.is_checkable()) diff --git a/LibGUI/GButton.h b/LibGUI/GButton.h index ae37ccf355..11eb68f9f8 100644 --- a/LibGUI/GButton.h +++ b/LibGUI/GButton.h @@ -11,7 +11,7 @@ class GAction; class GButton : public GAbstractButton { public: - GButton(const String& text, GWidget* parent); + GButton(const StringView& text, GWidget* parent); explicit GButton(GWidget* parent); virtual ~GButton() override; diff --git a/LibGUI/GCheckBox.cpp b/LibGUI/GCheckBox.cpp index b40c22624e..2bd5067bc9 100644 --- a/LibGUI/GCheckBox.cpp +++ b/LibGUI/GCheckBox.cpp @@ -1,8 +1,8 @@ +#include #include #include #include #include -#include static const char* s_checked_bitmap_data = { " " @@ -27,7 +27,7 @@ GCheckBox::GCheckBox(GWidget* parent) { } -GCheckBox::GCheckBox(const String& text, GWidget* parent) +GCheckBox::GCheckBox(const StringView& text, GWidget* parent) : GAbstractButton(text, parent) { } diff --git a/LibGUI/GCheckBox.h b/LibGUI/GCheckBox.h index 26116817e5..8235b577ba 100644 --- a/LibGUI/GCheckBox.h +++ b/LibGUI/GCheckBox.h @@ -6,7 +6,7 @@ class GCheckBox : public GAbstractButton { public: - GCheckBox(const String&, GWidget* parent); + GCheckBox(const StringView&, GWidget* parent); explicit GCheckBox(GWidget* parent); virtual ~GCheckBox() override; diff --git a/LibGUI/GClipboard.cpp b/LibGUI/GClipboard.cpp index 9a349a157d..fc02b3b623 100644 --- a/LibGUI/GClipboard.cpp +++ b/LibGUI/GClipboard.cpp @@ -1,7 +1,7 @@ +#include #include #include #include -#include GClipboard& GClipboard::the() { @@ -21,20 +21,20 @@ String GClipboard::data() const request.type = WSAPI_ClientMessage::Type::GetClipboardContents; auto response = GEventLoop::current().sync_request(request, WSAPI_ServerMessage::Type::DidGetClipboardContents); if (response.clipboard.shared_buffer_id < 0) - return { }; + return {}; auto shared_buffer = SharedBuffer::create_from_shared_buffer_id(response.clipboard.shared_buffer_id); if (!shared_buffer) { dbgprintf("GClipboard::data() failed to attach to the shared buffer\n"); - return { }; + return {}; } if (response.clipboard.contents_size > shared_buffer->size()) { dbgprintf("GClipboard::data() clipping contents size is greater than shared buffer size\n"); - return { }; + return {}; } return String((const char*)shared_buffer->data(), response.clipboard.contents_size); } -void GClipboard::set_data(const String& data) +void GClipboard::set_data(const StringView& data) { WSAPI_ClientMessage request; request.type = WSAPI_ClientMessage::Type::SetClipboardContents; diff --git a/LibGUI/GClipboard.h b/LibGUI/GClipboard.h index fc8cb5c95f..5e18c4fea7 100644 --- a/LibGUI/GClipboard.h +++ b/LibGUI/GClipboard.h @@ -7,7 +7,7 @@ public: static GClipboard& the(); String data() const; - void set_data(const String&); + void set_data(const StringView&); private: GClipboard(); diff --git a/LibGUI/GDesktop.cpp b/LibGUI/GDesktop.cpp index 234db21a84..809fdc80f0 100644 --- a/LibGUI/GDesktop.cpp +++ b/LibGUI/GDesktop.cpp @@ -24,7 +24,7 @@ void GDesktop::did_receive_screen_rect(Badge, const Rect& rect) on_rect_change(rect); } -bool GDesktop::set_wallpaper(const String& path) +bool GDesktop::set_wallpaper(const StringView& path) { WSAPI_ClientMessage message; message.type = WSAPI_ClientMessage::Type::SetWallpaper; diff --git a/LibGUI/GDesktop.h b/LibGUI/GDesktop.h index ca90ace83c..250e7138ce 100644 --- a/LibGUI/GDesktop.h +++ b/LibGUI/GDesktop.h @@ -13,7 +13,7 @@ public: GDesktop(); String wallpaper() const; - bool set_wallpaper(const String& path); + bool set_wallpaper(const StringView& path); Rect rect() const { return m_rect; } void did_receive_screen_rect(Badge, const Rect&); diff --git a/LibGUI/GDialog.cpp b/LibGUI/GDialog.cpp index d72b73c198..4de55f8c95 100644 --- a/LibGUI/GDialog.cpp +++ b/LibGUI/GDialog.cpp @@ -1,6 +1,6 @@ +#include #include #include -#include GDialog::GDialog(CObject* parent) : GWindow(parent) diff --git a/LibGUI/GDialog.h b/LibGUI/GDialog.h index 7244db5aa0..7e57ef8fbd 100644 --- a/LibGUI/GDialog.h +++ b/LibGUI/GDialog.h @@ -5,8 +5,7 @@ class GDialog : public GWindow { public: - enum ExecResult - { + enum ExecResult { ExecOK = 0, ExecCancel = 1, ExecAborted = 2 diff --git a/LibGUI/GDirectoryModel.cpp b/LibGUI/GDirectoryModel.cpp index f1d33f87cc..ee5ddcd39b 100644 --- a/LibGUI/GDirectoryModel.cpp +++ b/LibGUI/GDirectoryModel.cpp @@ -1,15 +1,15 @@ #include "GDirectoryModel.h" -#include -#include -#include -#include -#include #include #include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include static CLockable>>& thumbnail_cache() { @@ -94,13 +94,20 @@ int GDirectoryModel::column_count(const GModelIndex&) const String GDirectoryModel::column_name(int column) const { switch (column) { - case Column::Icon: return ""; - case Column::Name: return "Name"; - case Column::Size: return "Size"; - case Column::Owner: return "Owner"; - case Column::Group: return "Group"; - case Column::Permissions: return "Mode"; - case Column::Inode: return "Inode"; + case Column::Icon: + return ""; + case Column::Name: + return "Name"; + case Column::Size: + return "Size"; + case Column::Owner: + return "Owner"; + case Column::Group: + return "Group"; + case Column::Permissions: + return "Mode"; + case Column::Inode: + return "Inode"; } ASSERT_NOT_REACHED(); } @@ -108,13 +115,20 @@ String GDirectoryModel::column_name(int column) const GModel::ColumnMetadata GDirectoryModel::column_metadata(int column) const { switch (column) { - case Column::Icon: return { 16, TextAlignment::Center }; - case Column::Name: return { 120, TextAlignment::CenterLeft }; - case Column::Size: return { 80, TextAlignment::CenterRight }; - case Column::Owner: return { 50, TextAlignment::CenterLeft }; - case Column::Group: return { 50, TextAlignment::CenterLeft }; - case Column::Permissions: return { 80, TextAlignment::CenterLeft }; - case Column::Inode: return { 80, TextAlignment::CenterRight }; + case Column::Icon: + return { 16, TextAlignment::Center }; + case Column::Name: + return { 120, TextAlignment::CenterLeft }; + case Column::Size: + return { 80, TextAlignment::CenterRight }; + case Column::Owner: + return { 50, TextAlignment::CenterLeft }; + case Column::Group: + return { 50, TextAlignment::CenterLeft }; + case Column::Permissions: + return { 80, TextAlignment::CenterLeft }; + case Column::Inode: + return { 80, TextAlignment::CenterRight }; } ASSERT_NOT_REACHED(); } @@ -175,8 +189,7 @@ static String permission_string(mode_t mode) mode & S_IWGRP ? 'w' : '-', mode & S_ISGID ? 's' : (mode & S_IXGRP ? 'x' : '-'), mode & S_IROTH ? 'r' : '-', - mode & S_IWOTH ? 'w' : '-' - ); + mode & S_IWOTH ? 'w' : '-'); if (mode & S_ISVTX) builder.append("t"); @@ -207,31 +220,45 @@ GVariant GDirectoryModel::data(const GModelIndex& index, Role role) const auto& entry = this->entry(index.row()); if (role == Role::Sort) { switch (index.column()) { - case Column::Icon: return entry.is_directory() ? 0 : 1; - case Column::Name: return entry.name; - case Column::Size: return (int)entry.size; - case Column::Owner: return name_for_uid(entry.uid); - case Column::Group: return name_for_gid(entry.gid); - case Column::Permissions: return permission_string(entry.mode); - case Column::Inode: return (int)entry.inode; + case Column::Icon: + return entry.is_directory() ? 0 : 1; + case Column::Name: + return entry.name; + case Column::Size: + return (int)entry.size; + case Column::Owner: + return name_for_uid(entry.uid); + case Column::Group: + return name_for_gid(entry.gid); + case Column::Permissions: + return permission_string(entry.mode); + case Column::Inode: + return (int)entry.inode; } ASSERT_NOT_REACHED(); } if (role == Role::Display) { switch (index.column()) { - case Column::Icon: return icon_for(entry); - case Column::Name: return entry.name; - case Column::Size: return (int)entry.size; - case Column::Owner: return name_for_uid(entry.uid); - case Column::Group: return name_for_gid(entry.gid); - case Column::Permissions: return permission_string(entry.mode); - case Column::Inode: return (int)entry.inode; + case Column::Icon: + return icon_for(entry); + case Column::Name: + return entry.name; + case Column::Size: + return (int)entry.size; + case Column::Owner: + return name_for_uid(entry.uid); + case Column::Group: + return name_for_gid(entry.gid); + case Column::Permissions: + return permission_string(entry.mode); + case Column::Inode: + return (int)entry.inode; } } if (role == Role::Icon) { return icon_for(entry); } - return { }; + return {}; } void GDirectoryModel::update() @@ -272,7 +299,7 @@ void GDirectoryModel::update() did_update(); } -void GDirectoryModel::open(const String& a_path) +void GDirectoryModel::open(const StringView& a_path) { FileSystemPath canonical_path(a_path); auto path = canonical_path.string(); diff --git a/LibGUI/GDirectoryModel.h b/LibGUI/GDirectoryModel.h index d4f0e31073..41ad4c4a18 100644 --- a/LibGUI/GDirectoryModel.h +++ b/LibGUI/GDirectoryModel.h @@ -11,8 +11,7 @@ public: static Retained create() { return adopt(*new GDirectoryModel); } virtual ~GDirectoryModel() override; - enum Column - { + enum Column { Icon = 0, Name, Size, @@ -31,7 +30,7 @@ public: virtual void update() override; String path() const { return m_path; } - void open(const String& path); + void open(const StringView& path); size_t bytes_in_files() const { return m_bytes_in_files; } Function on_thumbnail_progress; diff --git a/LibGUI/GEvent.h b/LibGUI/GEvent.h index 54e111dfe3..f55f68b5a6 100644 --- a/LibGUI/GEvent.h +++ b/LibGUI/GEvent.h @@ -10,8 +10,7 @@ class CObject; class GEvent : public CEvent { public: - enum Type - { + enum Type { Show = 1000, Hide, Paint, @@ -82,7 +81,7 @@ public: class GWMWindowStateChangedEvent : public GWMEvent { public: - GWMWindowStateChangedEvent(int client_id, int window_id, const String& title, const Rect& rect, bool is_active, GWindowType window_type, bool is_minimized) + GWMWindowStateChangedEvent(int client_id, int window_id, const StringView& title, const Rect& rect, bool is_active, GWindowType window_type, bool is_minimized) : GWMEvent(GEvent::Type::WM_WindowStateChanged, client_id, window_id) , m_title(title) , m_rect(rect) @@ -122,7 +121,7 @@ private: class GWMWindowIconChangedEvent : public GWMEvent { public: - GWMWindowIconChangedEvent(int client_id, int window_id, const String& icon_path) + GWMWindowIconChangedEvent(int client_id, int window_id, const StringView& icon_path) : GWMEvent(GEvent::Type::WM_WindowIconChanged, client_id, window_id) , m_icon_path(icon_path) { @@ -218,8 +217,7 @@ public: } }; -enum GMouseButton : byte -{ +enum GMouseButton : byte { None = 0, Left = 1, Right = 2, diff --git a/LibGUI/GEventLoop.cpp b/LibGUI/GEventLoop.cpp index 127adbfead..ffa5b02c3b 100644 --- a/LibGUI/GEventLoop.cpp +++ b/LibGUI/GEventLoop.cpp @@ -1,24 +1,23 @@ -#include #include "GEventLoop.h" #include "GEvent.h" #include "GWindow.h" -#include -#include -#include -#include -#include -#include -#include -#include +#include #include +#include +#include #include -#include #include #include #include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include //#define GEVENTLOOP_DEBUG @@ -156,20 +155,42 @@ void GEventLoop::handle_mouse_event(const WSAPI_ServerMessage& event, GWindow& w #endif GMouseEvent::Type type; switch (event.type) { - case WSAPI_ServerMessage::Type::MouseMove: type = GEvent::MouseMove; break; - case WSAPI_ServerMessage::Type::MouseUp: type = GEvent::MouseUp; break; - case WSAPI_ServerMessage::Type::MouseDown: type = GEvent::MouseDown; break; - case WSAPI_ServerMessage::Type::MouseDoubleClick: type = GEvent::MouseDoubleClick; break; - case WSAPI_ServerMessage::Type::MouseWheel: type = GEvent::MouseWheel; break; - default: ASSERT_NOT_REACHED(); break; + case WSAPI_ServerMessage::Type::MouseMove: + type = GEvent::MouseMove; + break; + case WSAPI_ServerMessage::Type::MouseUp: + type = GEvent::MouseUp; + break; + case WSAPI_ServerMessage::Type::MouseDown: + type = GEvent::MouseDown; + break; + case WSAPI_ServerMessage::Type::MouseDoubleClick: + type = GEvent::MouseDoubleClick; + break; + case WSAPI_ServerMessage::Type::MouseWheel: + type = GEvent::MouseWheel; + break; + default: + ASSERT_NOT_REACHED(); + break; } GMouseButton button { GMouseButton::None }; switch (event.mouse.button) { - case WSAPI_MouseButton::NoButton: button = GMouseButton::None; break; - case WSAPI_MouseButton::Left: button = GMouseButton::Left; break; - case WSAPI_MouseButton::Right: button = GMouseButton::Right; break; - case WSAPI_MouseButton::Middle: button = GMouseButton::Middle; break; - default: ASSERT_NOT_REACHED(); break; + case WSAPI_MouseButton::NoButton: + button = GMouseButton::None; + break; + case WSAPI_MouseButton::Left: + button = GMouseButton::Left; + break; + case WSAPI_MouseButton::Right: + button = GMouseButton::Right; + break; + case WSAPI_MouseButton::Middle: + button = GMouseButton::Middle; + break; + default: + ASSERT_NOT_REACHED(); + break; } post_event(window, make(type, event.mouse.position, event.mouse.buttons, button, event.mouse.modifiers, event.mouse.wheel_delta)); } diff --git a/LibGUI/GFilePicker.cpp b/LibGUI/GFilePicker.cpp index ecf8b963ba..a6382cd695 100644 --- a/LibGUI/GFilePicker.cpp +++ b/LibGUI/GFilePicker.cpp @@ -12,7 +12,7 @@ #include #include -GFilePicker::GFilePicker(const String& path, CObject* parent) +GFilePicker::GFilePicker(const StringView& path, CObject* parent) : GDialog(parent) , m_model(GDirectoryModel::create()) { @@ -57,19 +57,19 @@ GFilePicker::GFilePicker(const String& path, CObject* parent) clear_preview(); }; - auto open_parent_directory_action = GAction::create("Open parent directory", { Mod_Alt, Key_Up }, GraphicsBitmap::load_from_file("/res/icons/16x16/open-parent-directory.png"), [this] (const GAction&) { + auto open_parent_directory_action = GAction::create("Open parent directory", { Mod_Alt, Key_Up }, GraphicsBitmap::load_from_file("/res/icons/16x16/open-parent-directory.png"), [this](const GAction&) { m_model->open(String::format("%s/..", m_model->path().characters())); clear_preview(); }); toolbar->add_action(*open_parent_directory_action); - auto mkdir_action = GAction::create("New directory...", GraphicsBitmap::load_from_file("/res/icons/16x16/mkdir.png"), [this] (const GAction&) { + auto mkdir_action = GAction::create("New directory...", GraphicsBitmap::load_from_file("/res/icons/16x16/mkdir.png"), [this](const GAction&) { GInputBox input_box("Enter name:", "New directory", this); if (input_box.exec() == GInputBox::ExecOK && !input_box.text_value().is_empty()) { auto new_dir_path = FileSystemPath(String::format("%s/%s", - m_model->path().characters(), - input_box.text_value().characters() - )).string(); + m_model->path().characters(), + input_box.text_value().characters())) + .string(); int rc = mkdir(new_dir_path.characters(), 0777); if (rc < 0) { GMessageBox::show(String::format("mkdir(\"%s\") failed: %s", new_dir_path.characters(), strerror(errno)), "Error", GMessageBox::Type::Error, this); @@ -96,7 +96,7 @@ GFilePicker::GFilePicker(const String& path, CObject* parent) filename_label->set_preferred_size({ 60, 0 }); auto* filename_textbox = new GTextBox(filename_container); - m_view->on_activation = [this, filename_textbox] (auto& index) { + m_view->on_activation = [this, filename_textbox](auto& index) { auto& filter_model = (GSortingProxyModel&)*m_view->model(); auto local_index = filter_model.map_to_target(index); const GDirectoryModel::Entry& entry = m_model->entry(local_index.row()); @@ -125,7 +125,7 @@ GFilePicker::GFilePicker(const String& path, CObject* parent) cancel_button->set_size_policy(SizePolicy::Fixed, SizePolicy::Fill); cancel_button->set_preferred_size({ 80, 0 }); cancel_button->set_text("Cancel"); - cancel_button->on_click = [this] (auto&) { + cancel_button->on_click = [this](auto&) { done(ExecCancel); }; @@ -133,7 +133,7 @@ GFilePicker::GFilePicker(const String& path, CObject* parent) ok_button->set_size_policy(SizePolicy::Fixed, SizePolicy::Fill); ok_button->set_preferred_size({ 80, 0 }); ok_button->set_text("OK"); - ok_button->on_click = [this, filename_textbox] (auto&) { + ok_button->on_click = [this, filename_textbox](auto&) { FileSystemPath path(String::format("%s/%s", m_model->path().characters(), filename_textbox->text().characters())); m_selected_file = path; done(ExecOK); diff --git a/LibGUI/GFilePicker.h b/LibGUI/GFilePicker.h index 4ec7c22859..12af7e3941 100644 --- a/LibGUI/GFilePicker.h +++ b/LibGUI/GFilePicker.h @@ -7,7 +7,7 @@ class GLabel; class GFilePicker final : public GDialog { public: - GFilePicker(const String& path = "/", CObject* parent = nullptr); + GFilePicker(const StringView& path = "/", CObject* parent = nullptr); virtual ~GFilePicker() override; FileSystemPath selected_file() const { return m_selected_file; } diff --git a/LibGUI/GFileSystemModel.cpp b/LibGUI/GFileSystemModel.cpp index 406af3f20b..3f06e00b95 100644 --- a/LibGUI/GFileSystemModel.cpp +++ b/LibGUI/GFileSystemModel.cpp @@ -1,17 +1,21 @@ -#include -#include #include #include -#include +#include +#include #include -#include #include +#include +#include struct GFileSystemModel::Node { String name; Node* parent { nullptr }; Vector children; - enum Type { Unknown, Directory, File }; + enum Type { + Unknown, + Directory, + File + }; Type type { Unknown }; bool has_traversed { false }; @@ -92,7 +96,7 @@ struct GFileSystemModel::Node { } }; -GModelIndex GFileSystemModel::index(const String& path) const +GModelIndex GFileSystemModel::index(const StringView& path) const { FileSystemPath canonical_path(path); const Node* node = m_root; @@ -111,21 +115,21 @@ GModelIndex GFileSystemModel::index(const String& path) const } } if (!found) - return { }; + return {}; } - return { }; + return {}; } String GFileSystemModel::path(const GModelIndex& index) const { if (!index.is_valid()) - return { }; + return {}; auto& node = *(Node*)index.internal_data(); node.reify_if_needed(*this); return node.full_path(*this); } -GFileSystemModel::GFileSystemModel(const String& root_path, Mode mode) +GFileSystemModel::GFileSystemModel(const StringView& root_path, Mode mode) : m_root_path(FileSystemPath(root_path).string()) , m_mode(mode) { @@ -172,11 +176,11 @@ GModelIndex GFileSystemModel::index(int row, int column, const GModelIndex& pare GModelIndex GFileSystemModel::parent_index(const GModelIndex& index) const { if (!index.is_valid()) - return { }; + return {}; auto& node = *(const Node*)index.internal_data(); if (!node.parent) { ASSERT(&node == m_root); - return { }; + return {}; } return node.parent->index(*this); } @@ -184,7 +188,7 @@ GModelIndex GFileSystemModel::parent_index(const GModelIndex& index) const GVariant GFileSystemModel::data(const GModelIndex& index, Role role) const { if (!index.is_valid()) - return { }; + return {}; auto& node = *(const Node*)index.internal_data(); if (role == GModel::Role::Display) return node.name; @@ -196,7 +200,7 @@ GVariant GFileSystemModel::data(const GModelIndex& index, Role role) const } return m_file_icon; } - return { }; + return {}; } int GFileSystemModel::column_count(const GModelIndex&) const diff --git a/LibGUI/GFileSystemModel.h b/LibGUI/GFileSystemModel.h index 7f21ca7794..5e7c7545e7 100644 --- a/LibGUI/GFileSystemModel.h +++ b/LibGUI/GFileSystemModel.h @@ -6,14 +6,13 @@ class GFileSystemModel : public GModel { friend class Node; public: - enum Mode - { + enum Mode { Invalid, DirectoriesOnly, FilesAndDirectories }; - static Retained create(const String& root_path = "/", Mode mode = Mode::FilesAndDirectories) + static Retained create(const StringView& root_path = "/", Mode mode = Mode::FilesAndDirectories) { return adopt(*new GFileSystemModel(root_path, mode)); } @@ -21,7 +20,7 @@ public: String root_path() const { return m_root_path; } String path(const GModelIndex&) const; - GModelIndex index(const String& path) const; + GModelIndex index(const StringView& path) const; virtual int row_count(const GModelIndex& = GModelIndex()) const override; virtual int column_count(const GModelIndex& = GModelIndex()) const override; @@ -31,7 +30,7 @@ public: virtual GModelIndex index(int row, int column = 0, const GModelIndex& parent = GModelIndex()) const override; private: - GFileSystemModel(const String& root_path, Mode); + GFileSystemModel(const StringView& root_path, Mode); String m_root_path; Mode m_mode { Invalid }; diff --git a/LibGUI/GFontDatabase.cpp b/LibGUI/GFontDatabase.cpp index b9218f36a8..b676c71016 100644 --- a/LibGUI/GFontDatabase.cpp +++ b/LibGUI/GFontDatabase.cpp @@ -1,5 +1,5 @@ -#include #include +#include #include #include #include @@ -38,14 +38,14 @@ GFontDatabase::~GFontDatabase() { } -void GFontDatabase::for_each_font(Function callback) +void GFontDatabase::for_each_font(Function callback) { for (auto& it : m_name_to_metadata) { callback(it.key); } } -void GFontDatabase::for_each_fixed_width_font(Function callback) +void GFontDatabase::for_each_fixed_width_font(Function callback) { for (auto& it : m_name_to_metadata) { if (it.value.is_fixed_width) @@ -53,7 +53,7 @@ void GFontDatabase::for_each_fixed_width_font(Function call } } -RetainPtr GFontDatabase::get_by_name(const String& name) +RetainPtr GFontDatabase::get_by_name(const StringView& name) { auto it = m_name_to_metadata.find(name); if (it == m_name_to_metadata.end()) diff --git a/LibGUI/GFontDatabase.h b/LibGUI/GFontDatabase.h index af49e68875..7b22bc4d10 100644 --- a/LibGUI/GFontDatabase.h +++ b/LibGUI/GFontDatabase.h @@ -16,11 +16,11 @@ class GFontDatabase { public: static GFontDatabase& the(); - RetainPtr get_by_name(const String&); - void for_each_font(Function); - void for_each_fixed_width_font(Function); + RetainPtr get_by_name(const StringView&); + void for_each_font(Function); + void for_each_fixed_width_font(Function); - Metadata get_metadata_by_name(const String& name) const + Metadata get_metadata_by_name(const StringView& name) const { return m_name_to_metadata.get(name); }; diff --git a/LibGUI/GFrame.cpp b/LibGUI/GFrame.cpp index 8048ce7791..418fe40492 100644 --- a/LibGUI/GFrame.cpp +++ b/LibGUI/GFrame.cpp @@ -1,6 +1,6 @@ #include -#include #include +#include GFrame::GFrame(GWidget* parent) : GWidget(parent) diff --git a/LibGUI/GGroupBox.cpp b/LibGUI/GGroupBox.cpp index 915b66e0dc..8633f25fe4 100644 --- a/LibGUI/GGroupBox.cpp +++ b/LibGUI/GGroupBox.cpp @@ -2,7 +2,7 @@ #include #include -GGroupBox::GGroupBox(const String& title, GWidget* parent) +GGroupBox::GGroupBox(const StringView& title, GWidget* parent) : GWidget(parent) , m_title(title) { @@ -30,7 +30,7 @@ void GGroupBox::paint_event(GPaintEvent& event) painter.draw_text(text_rect, m_title, TextAlignment::Center, foreground_color()); } -void GGroupBox::set_title(const String& title) +void GGroupBox::set_title(const StringView& title) { if (m_title == title) return; diff --git a/LibGUI/GGroupBox.h b/LibGUI/GGroupBox.h index 4b630ea365..513d52b57b 100644 --- a/LibGUI/GGroupBox.h +++ b/LibGUI/GGroupBox.h @@ -4,11 +4,11 @@ class GGroupBox : public GWidget { public: - GGroupBox(const String& title, GWidget* parent); + GGroupBox(const StringView& title, GWidget* parent); virtual ~GGroupBox() override; String title() const { return m_title; } - void set_title(const String&); + void set_title(const StringView&); virtual const char* class_name() const override { return "GGroupBox"; } diff --git a/LibGUI/GIcon.cpp b/LibGUI/GIcon.cpp index 0a2955ee7f..17c34e8356 100644 --- a/LibGUI/GIcon.cpp +++ b/LibGUI/GIcon.cpp @@ -62,7 +62,7 @@ void GIconImpl::set_bitmap_for_size(int size, RetainPtr&& bitmap m_bitmaps.set(size, move(bitmap)); } -GIcon GIcon::default_icon(const String& name) +GIcon GIcon::default_icon(const StringView& name) { auto bitmap16 = GraphicsBitmap::load_from_file(String::format("/res/icons/16x16/%s.png", name.characters())); auto bitmap32 = GraphicsBitmap::load_from_file(String::format("/res/icons/32x32/%s.png", name.characters())); diff --git a/LibGUI/GIcon.h b/LibGUI/GIcon.h index 61d928127f..47c09071d9 100644 --- a/LibGUI/GIcon.h +++ b/LibGUI/GIcon.h @@ -25,7 +25,7 @@ public: GIcon(const GIcon&); ~GIcon() {} - static GIcon default_icon(const String&); + static GIcon default_icon(const StringView&); GIcon& operator=(const GIcon& other) { diff --git a/LibGUI/GInputBox.cpp b/LibGUI/GInputBox.cpp index 884adeabbe..089003dbb9 100644 --- a/LibGUI/GInputBox.cpp +++ b/LibGUI/GInputBox.cpp @@ -1,11 +1,11 @@ -#include #include -#include #include +#include +#include #include #include -GInputBox::GInputBox(const String& prompt, const String& title, CObject* parent) +GInputBox::GInputBox(const StringView& prompt, const StringView& title, CObject* parent) : GDialog(parent) , m_prompt(prompt) { @@ -55,7 +55,7 @@ void GInputBox::build() m_cancel_button->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed); m_cancel_button->set_preferred_size({ 0, 20 }); m_cancel_button->set_text("Cancel"); - m_cancel_button->on_click = [this] (auto&) { + m_cancel_button->on_click = [this](auto&) { dbgprintf("GInputBox: Cancel button clicked\n"); done(ExecCancel); }; @@ -64,7 +64,7 @@ void GInputBox::build() m_ok_button->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed); m_ok_button->set_preferred_size({ 0, 20 }); m_ok_button->set_text("OK"); - m_ok_button->on_click = [this] (auto&) { + m_ok_button->on_click = [this](auto&) { dbgprintf("GInputBox: OK button clicked\n"); m_text_value = m_text_editor->text(); done(ExecOK); diff --git a/LibGUI/GInputBox.h b/LibGUI/GInputBox.h index 94de894040..76672b9a80 100644 --- a/LibGUI/GInputBox.h +++ b/LibGUI/GInputBox.h @@ -7,7 +7,7 @@ class GTextEditor; class GInputBox : public GDialog { public: - explicit GInputBox(const String& prompt, const String& title, CObject* parent = nullptr); + explicit GInputBox(const StringView& prompt, const StringView& title, CObject* parent = nullptr); virtual ~GInputBox() override; String text_value() const { return m_text_value; } diff --git a/LibGUI/GItemView.cpp b/LibGUI/GItemView.cpp index 71b0791f91..d5d9af0a6c 100644 --- a/LibGUI/GItemView.cpp +++ b/LibGUI/GItemView.cpp @@ -1,8 +1,8 @@ +#include #include #include -#include #include -#include +#include GItemView::GItemView(GWidget* parent) : GAbstractView(parent) @@ -38,7 +38,7 @@ void GItemView::did_update_model() void GItemView::update_content_size() { if (!model()) - return set_content_size({ }); + return set_content_size({}); m_visual_column_count = available_size().width() / effective_item_size().width(); if (m_visual_column_count) @@ -55,7 +55,7 @@ void GItemView::update_content_size() Rect GItemView::item_rect(int item_index) const { if (!m_visual_row_count || !m_visual_column_count) - return { }; + return {}; int visual_row_index = item_index / m_visual_column_count; int visual_column_index = item_index % m_visual_column_count; return { @@ -79,7 +79,7 @@ void GItemView::mousedown_event(GMouseEvent& event) return; } } - model()->set_selected_index({ }); + model()->set_selected_index({}); update(); } } @@ -100,7 +100,7 @@ void GItemView::paint_event(GPaintEvent& event) GPainter painter(*this); painter.add_clip_rect(widget_inner_rect()); - painter.add_clip_rect(event.rect()); + painter.add_clip_rect(event.rect()); painter.fill_rect(event.rect(), Color::White); painter.translate(-horizontal_scrollbar().value(), -vertical_scrollbar().value()); diff --git a/LibGUI/GLabel.cpp b/LibGUI/GLabel.cpp index 003a4d2132..abab0ac09a 100644 --- a/LibGUI/GLabel.cpp +++ b/LibGUI/GLabel.cpp @@ -7,7 +7,7 @@ GLabel::GLabel(GWidget* parent) { } -GLabel::GLabel(const String& text, GWidget* parent) +GLabel::GLabel(const StringView& text, GWidget* parent) : GFrame(parent) , m_text(text) { @@ -22,7 +22,7 @@ void GLabel::set_icon(RetainPtr&& icon) m_icon = move(icon); } -void GLabel::set_text(const String& text) +void GLabel::set_text(const StringView& text) { if (text == m_text) return; diff --git a/LibGUI/GLabel.h b/LibGUI/GLabel.h index a67b50b90c..406595756b 100644 --- a/LibGUI/GLabel.h +++ b/LibGUI/GLabel.h @@ -8,11 +8,11 @@ class GraphicsBitmap; class GLabel : public GFrame { public: explicit GLabel(GWidget* parent = nullptr); - GLabel(const String& text, GWidget* parent = nullptr); + GLabel(const StringView& text, GWidget* parent = nullptr); virtual ~GLabel() override; String text() const { return m_text; } - void set_text(const String&); + void set_text(const StringView&); void set_icon(RetainPtr&&); const GraphicsBitmap* icon() const { return m_icon.ptr(); } diff --git a/LibGUI/GLayout.cpp b/LibGUI/GLayout.cpp index 1aaa660ecc..13a547e4c0 100644 --- a/LibGUI/GLayout.cpp +++ b/LibGUI/GLayout.cpp @@ -54,7 +54,7 @@ void GLayout::add_widget(GWidget& widget) void GLayout::remove_widget(GWidget& widget) { - m_entries.remove_first_matching([&] (auto& entry) { + m_entries.remove_first_matching([&](auto& entry) { return entry.widget == &widget; }); if (m_owner) diff --git a/LibGUI/GLayout.h b/LibGUI/GLayout.h index 498f0efc6a..39418a712f 100644 --- a/LibGUI/GLayout.h +++ b/LibGUI/GLayout.h @@ -32,8 +32,7 @@ public: protected: struct Entry { - enum class Type - { + enum class Type { Invalid = 0, Widget, Layout, diff --git a/LibGUI/GListView.cpp b/LibGUI/GListView.cpp index b3b28a1ce7..bcf33a8fb4 100644 --- a/LibGUI/GListView.cpp +++ b/LibGUI/GListView.cpp @@ -1,7 +1,7 @@ -#include -#include -#include #include +#include +#include +#include GListView::GListView(GWidget* parent) : GAbstractView(parent) @@ -18,7 +18,7 @@ GListView::~GListView() void GListView::update_content_size() { if (!model()) - return set_content_size({ }); + return set_content_size({}); int content_width = 0; for (int row = 0, row_count = model()->row_count(); row < row_count; ++row) { @@ -76,7 +76,7 @@ void GListView::mousedown_event(GMouseEvent& event) update(); return; } - model()->set_selected_index({ }); + model()->set_selected_index({}); update(); } diff --git a/LibGUI/GMenu.cpp b/LibGUI/GMenu.cpp index dad8cc6f5a..cb5902adba 100644 --- a/LibGUI/GMenu.cpp +++ b/LibGUI/GMenu.cpp @@ -1,7 +1,7 @@ -#include -#include -#include #include +#include +#include +#include //#define GMENU_DEBUG @@ -21,7 +21,7 @@ GMenu* GMenu::from_menu_id(int menu_id) return (*it).value; } -GMenu::GMenu(const String& name) +GMenu::GMenu(const StringView& name) : m_name(name) { } @@ -81,8 +81,8 @@ int GMenu::realize_menu() ASSERT(m_menu_id > 0); for (int i = 0; i < m_items.size(); ++i) { auto& item = *m_items[i]; - item.set_menu_id({ }, m_menu_id); - item.set_identifier({ }, i); + item.set_menu_id({}, m_menu_id); + item.set_identifier({}, i); if (item.type() == GMenuItem::Separator) { WSAPI_ClientMessage request; request.type = WSAPI_ClientMessage::Type::AddMenuSeparator; diff --git a/LibGUI/GMenu.h b/LibGUI/GMenu.h index 97a8ed51c9..61b11c0692 100644 --- a/LibGUI/GMenu.h +++ b/LibGUI/GMenu.h @@ -11,7 +11,7 @@ class Point; class GMenu { public: - explicit GMenu(const String& name); + explicit GMenu(const StringView& name); ~GMenu(); static GMenu* from_menu_id(int); diff --git a/LibGUI/GMenuBar.cpp b/LibGUI/GMenuBar.cpp index 1622d09fa0..19c736d8bc 100644 --- a/LibGUI/GMenuBar.cpp +++ b/LibGUI/GMenuBar.cpp @@ -1,5 +1,5 @@ -#include #include +#include GMenuBar::GMenuBar() { diff --git a/LibGUI/GMenuItem.cpp b/LibGUI/GMenuItem.cpp index e721d051a5..cfd38e778d 100644 --- a/LibGUI/GMenuItem.cpp +++ b/LibGUI/GMenuItem.cpp @@ -1,6 +1,6 @@ -#include #include #include +#include #include GMenuItem::GMenuItem(unsigned menu_id, Type type) @@ -14,7 +14,7 @@ GMenuItem::GMenuItem(unsigned menu_id, Retained&& action) , m_menu_id(menu_id) , m_action(move(action)) { - m_action->register_menu_item({ }, *this); + m_action->register_menu_item({}, *this); m_enabled = m_action->is_enabled(); m_checkable = m_action->is_checkable(); if (m_checkable) @@ -24,7 +24,7 @@ GMenuItem::GMenuItem(unsigned menu_id, Retained&& action) GMenuItem::~GMenuItem() { if (m_action) - m_action->unregister_menu_item({ }, *this); + m_action->unregister_menu_item({}, *this); } void GMenuItem::set_enabled(bool enabled) diff --git a/LibGUI/GMenuItem.h b/LibGUI/GMenuItem.h index 6cb1df8e53..61ec355179 100644 --- a/LibGUI/GMenuItem.h +++ b/LibGUI/GMenuItem.h @@ -8,8 +8,7 @@ class GMenu; class GMenuItem { public: - enum Type - { + enum Type { Invalid, Action, Separator diff --git a/LibGUI/GMessageBox.cpp b/LibGUI/GMessageBox.cpp index 71fe04f043..c628997069 100644 --- a/LibGUI/GMessageBox.cpp +++ b/LibGUI/GMessageBox.cpp @@ -1,16 +1,16 @@ -#include #include -#include #include +#include +#include #include -void GMessageBox::show(const String& text, const String& title, Type type, CObject* parent) +void GMessageBox::show(const StringView& text, const StringView& title, Type type, CObject* parent) { GMessageBox box(text, title, type, parent); box.exec(); } -GMessageBox::GMessageBox(const String& text, const String& title, Type type, CObject* parent) +GMessageBox::GMessageBox(const StringView& text, const StringView& title, Type type, CObject* parent) : GDialog(parent) , m_text(text) , m_type(type) @@ -73,7 +73,7 @@ void GMessageBox::build() button->set_size_policy(SizePolicy::Fixed, SizePolicy::Fixed); button->set_preferred_size({ 100, 20 }); button->set_text("OK"); - button->on_click = [this] (auto&) { + button->on_click = [this](auto&) { dbgprintf("GMessageBox: OK button clicked\n"); done(0); }; diff --git a/LibGUI/GMessageBox.h b/LibGUI/GMessageBox.h index 31f4983ae3..e05e0d2e06 100644 --- a/LibGUI/GMessageBox.h +++ b/LibGUI/GMessageBox.h @@ -4,18 +4,17 @@ class GMessageBox : public GDialog { public: - enum class Type - { + enum class Type { None, Information, Warning, Error, }; - explicit GMessageBox(const String& text, const String& title, Type type = Type::None, CObject* parent = nullptr); + explicit GMessageBox(const StringView& text, const StringView& title, Type type = Type::None, CObject* parent = nullptr); virtual ~GMessageBox() override; - static void show(const String& text, const String& title, Type type = Type::None, CObject* parent = nullptr); + static void show(const StringView& text, const StringView& title, Type type = Type::None, CObject* parent = nullptr); virtual const char* class_name() const override { return "GMessageBox"; } diff --git a/LibGUI/GModel.cpp b/LibGUI/GModel.cpp index 454d9996d5..46e1037c29 100644 --- a/LibGUI/GModel.cpp +++ b/LibGUI/GModel.cpp @@ -1,5 +1,5 @@ -#include #include +#include GModel::GModel() { @@ -29,7 +29,7 @@ void GModel::did_update() { if (on_model_update) on_model_update(*this); - for_each_view([] (auto& view) { + for_each_view([](auto& view) { view.did_update_model(); }); } @@ -41,7 +41,7 @@ void GModel::set_selected_index(const GModelIndex& index) m_selected_index = index; if (on_selection_changed) on_selection_changed(index); - for_each_view([] (auto& view) { + for_each_view([](auto& view) { view.did_update_selection(); }); } @@ -54,9 +54,9 @@ GModelIndex GModel::create_index(int row, int column, void* data) const GModelIndex GModel::sibling(int row, int column, const GModelIndex& parent) const { if (!parent.is_valid()) - return { }; + return {}; int row_count = this->row_count(parent); if (row < 0 || row > row_count) - return { }; + return {}; return index(row, column, parent); } diff --git a/LibGUI/GModel.h b/LibGUI/GModel.h index 0aba8900cd..7efa61375e 100644 --- a/LibGUI/GModel.h +++ b/LibGUI/GModel.h @@ -12,8 +12,7 @@ class Font; class GAbstractView; -enum class GSortOrder -{ +enum class GSortOrder { None, Ascending, Descending @@ -21,8 +20,7 @@ enum class GSortOrder class GModelNotification { public: - enum Type - { + enum Type { Invalid = 0, ModelUpdated, }; @@ -49,8 +47,7 @@ public: const Font* font { nullptr }; }; - enum class Role - { + enum class Role { Display, Sort, Custom, diff --git a/LibGUI/GProgressBar.cpp b/LibGUI/GProgressBar.cpp index 1c60904cba..72c778242a 100644 --- a/LibGUI/GProgressBar.cpp +++ b/LibGUI/GProgressBar.cpp @@ -1,6 +1,6 @@ -#include -#include #include +#include +#include GProgressBar::GProgressBar(GWidget* parent) : GFrame(parent) diff --git a/LibGUI/GProgressBar.h b/LibGUI/GProgressBar.h index 42e3843403..0db9e5f529 100644 --- a/LibGUI/GProgressBar.h +++ b/LibGUI/GProgressBar.h @@ -17,10 +17,9 @@ public: int max() const { return m_max; } String caption() const { return m_caption; } - void set_caption(const String& caption) { m_caption = caption; } + void set_caption(const StringView& caption) { m_caption = caption; } - enum Format - { + enum Format { NoText, Percentage, ValueSlashMax diff --git a/LibGUI/GRadioButton.cpp b/LibGUI/GRadioButton.cpp index afcb2d9c32..59cab6d904 100644 --- a/LibGUI/GRadioButton.cpp +++ b/LibGUI/GRadioButton.cpp @@ -1,5 +1,5 @@ -#include #include +#include #include static RetainPtr s_unfilled_circle_bitmap; @@ -7,7 +7,7 @@ static RetainPtr s_filled_circle_bitmap; static RetainPtr s_changing_filled_circle_bitmap; static RetainPtr s_changing_unfilled_circle_bitmap; -GRadioButton::GRadioButton(const String& text, GWidget* parent) +GRadioButton::GRadioButton(const StringView& text, GWidget* parent) : GAbstractButton(text, parent) { if (!s_unfilled_circle_bitmap) { @@ -55,7 +55,7 @@ void GRadioButton::for_each_in_group(Callback callback) { if (!parent()) return; - parent()->for_each_child_of_type([&] (auto& child) { + parent()->for_each_child_of_type([&](auto& child) { return callback(static_cast(child)); }); } @@ -64,7 +64,7 @@ void GRadioButton::click() { if (!is_enabled()) return; - for_each_in_group([this] (auto& button) { + for_each_in_group([this](auto& button) { if (&button != this) button.set_checked(false); return IterationDecision::Continue; diff --git a/LibGUI/GRadioButton.h b/LibGUI/GRadioButton.h index 410f0e4556..44c0cfe97b 100644 --- a/LibGUI/GRadioButton.h +++ b/LibGUI/GRadioButton.h @@ -4,7 +4,7 @@ class GRadioButton : public GAbstractButton { public: - GRadioButton(const String& text, GWidget* parent); + GRadioButton(const StringView& text, GWidget* parent); virtual ~GRadioButton() override; virtual const char* class_name() const override { return "GRadioButton"; } diff --git a/LibGUI/GResizeCorner.cpp b/LibGUI/GResizeCorner.cpp index 91407a509f..1dfba8b786 100644 --- a/LibGUI/GResizeCorner.cpp +++ b/LibGUI/GResizeCorner.cpp @@ -1,5 +1,5 @@ -#include #include +#include #include #include #include diff --git a/LibGUI/GScrollBar.cpp b/LibGUI/GScrollBar.cpp index bc932dd242..dabd4649e9 100644 --- a/LibGUI/GScrollBar.cpp +++ b/LibGUI/GScrollBar.cpp @@ -1,10 +1,8 @@ +#include #include -#include #include #include -#include - -//#define GUTTER_DOES_PAGEUP_PAGEDOWN +#include static const char* s_up_arrow_bitmap_data = { " " @@ -30,7 +28,6 @@ static const char* s_down_arrow_bitmap_data = { " " }; - static const char* s_left_arrow_bitmap_data = { " " " # " @@ -78,6 +75,11 @@ GScrollBar::GScrollBar(Orientation orientation, GWidget* parent) } else { set_preferred_size({ 0, 15 }); } + + m_automatic_scrolling_timer.set_interval(100); + m_automatic_scrolling_timer.on_timeout = [this] { + on_automatic_scrolling_timer_fired(); + }; } GScrollBar::~GScrollBar() @@ -118,12 +120,12 @@ void GScrollBar::set_value(int value) update(); } -Rect GScrollBar::up_button_rect() const +Rect GScrollBar::decrement_button_rect() const { return { 0, 0, button_width(), button_height() }; } -Rect GScrollBar::down_button_rect() const +Rect GScrollBar::increment_button_rect() const { if (orientation() == Orientation::Vertical) return { 0, height() - button_height(), button_width(), button_height() }; @@ -131,7 +133,7 @@ Rect GScrollBar::down_button_rect() const return { width() - button_width(), 0, button_width(), button_height() }; } -Rect GScrollBar::upper_gutter_rect() const +Rect GScrollBar::decrement_gutter_rect() const { if (orientation() == Orientation::Vertical) return { 0, button_height(), button_width(), scrubber_rect().top() - button_height() }; @@ -139,11 +141,11 @@ Rect GScrollBar::upper_gutter_rect() const return { button_width(), 0, scrubber_rect().x() - button_width(), button_height() }; } -Rect GScrollBar::lower_gutter_rect() const +Rect GScrollBar::increment_gutter_rect() const { auto scrubber_rect = this->scrubber_rect(); if (orientation() == Orientation::Vertical) - return { 0, scrubber_rect.bottom() + 1, button_width(), height() - button_height() - scrubber_rect.bottom() - 1}; + return { 0, scrubber_rect.bottom() + 1, button_width(), height() - button_height() - scrubber_rect.bottom() - 1 }; else return { scrubber_rect.right() + 1, 0, width() - button_width() - scrubber_rect.right() - 1, button_width() }; } @@ -171,7 +173,7 @@ int GScrollBar::scrubber_size() const Rect GScrollBar::scrubber_rect() const { if (!has_scrubber()) - return { }; + return {}; float x_or_y; if (m_value == m_min) x_or_y = button_size(); @@ -197,38 +199,42 @@ void GScrollBar::paint_event(GPaintEvent& event) painter.fill_rect(rect(), Color::from_rgb(0xd6d2ce)); - StylePainter::paint_button(painter, up_button_rect(), ButtonStyle::Normal, false, m_hovered_component == Component::DecrementButton); - painter.draw_bitmap(up_button_rect().location().translated(3, 3), orientation() == Orientation::Vertical ? *s_up_arrow_bitmap : *s_left_arrow_bitmap, has_scrubber() ? Color::Black : Color::MidGray); + StylePainter::paint_button(painter, decrement_button_rect(), ButtonStyle::Normal, false, m_hovered_component == Component::DecrementButton); + painter.draw_bitmap(decrement_button_rect().location().translated(3, 3), orientation() == Orientation::Vertical ? *s_up_arrow_bitmap : *s_left_arrow_bitmap, has_scrubber() ? Color::Black : Color::MidGray); - StylePainter::paint_button(painter, down_button_rect(), ButtonStyle::Normal, false, m_hovered_component == Component::IncrementButton); - painter.draw_bitmap(down_button_rect().location().translated(3, 3), orientation() == Orientation::Vertical ? *s_down_arrow_bitmap : *s_right_arrow_bitmap, has_scrubber() ? Color::Black : Color::MidGray); + StylePainter::paint_button(painter, increment_button_rect(), ButtonStyle::Normal, false, m_hovered_component == Component::IncrementButton); + painter.draw_bitmap(increment_button_rect().location().translated(3, 3), orientation() == Orientation::Vertical ? *s_down_arrow_bitmap : *s_right_arrow_bitmap, has_scrubber() ? Color::Black : Color::MidGray); if (has_scrubber()) StylePainter::paint_button(painter, scrubber_rect(), ButtonStyle::Normal, false, m_hovered_component == Component::Scrubber); } +void GScrollBar::on_automatic_scrolling_timer_fired() +{ + if (m_automatic_scrolling_direction == AutomaticScrollingDirection::Decrement) { + set_value(value() - m_step); + return; + } + if (m_automatic_scrolling_direction == AutomaticScrollingDirection::Increment) { + set_value(value() + m_step); + return; + } +} + void GScrollBar::mousedown_event(GMouseEvent& event) { if (event.button() != GMouseButton::Left) return; - if (up_button_rect().contains(event.position())) { - set_value(value() - m_step); + if (decrement_button_rect().contains(event.position())) { + m_automatic_scrolling_direction = AutomaticScrollingDirection::Decrement; + set_automatic_scrolling_active(true); return; } - if (down_button_rect().contains(event.position())) { - set_value(value() + m_step); + if (increment_button_rect().contains(event.position())) { + m_automatic_scrolling_direction = AutomaticScrollingDirection::Increment; + set_automatic_scrolling_active(true); return; } -#ifdef GUTTER_DOES_PAGEUP_PAGEDOWN - if (has_scrubber() && upper_gutter_rect().contains(event.position())) { - set_value(value() - m_big_step); - return; - } - if (has_scrubber() && lower_gutter_rect().contains(event.position())) { - set_value(value() + m_big_step); - return; - } -#endif if (has_scrubber() && scrubber_rect().contains(event.position())) { m_scrubbing = true; m_scrub_start_value = value(); @@ -236,7 +242,7 @@ void GScrollBar::mousedown_event(GMouseEvent& event) update(); return; } -#ifndef GUTTER_DOES_PAGEUP_PAGEDOWN + if (has_scrubber()) { float range_size = m_max - m_min; float available = scrubbable_range_in_pixels(); @@ -256,34 +262,51 @@ void GScrollBar::mousedown_event(GMouseEvent& event) m_scrub_start_value = value(); m_scrub_origin = event.position(); } -#endif } void GScrollBar::mouseup_event(GMouseEvent& event) { if (event.button() != GMouseButton::Left) return; + m_automatic_scrolling_direction = AutomaticScrollingDirection::None; + set_automatic_scrolling_active(false); if (!m_scrubbing) return; m_scrubbing = false; update(); } +void GScrollBar::set_automatic_scrolling_active(bool active) +{ + if (active) { + on_automatic_scrolling_timer_fired(); + m_automatic_scrolling_timer.start(); + } else { + m_automatic_scrolling_timer.stop(); + } +} + void GScrollBar::mousemove_event(GMouseEvent& event) { auto old_hovered_component = m_hovered_component; if (scrubber_rect().contains(event.position())) m_hovered_component = Component::Scrubber; - else if (up_button_rect().contains(event.position())) + else if (decrement_button_rect().contains(event.position())) m_hovered_component = Component::DecrementButton; - else if (down_button_rect().contains(event.position())) + else if (increment_button_rect().contains(event.position())) m_hovered_component = Component::IncrementButton; else if (rect().contains(event.position())) m_hovered_component = Component::Gutter; else m_hovered_component = Component::Invalid; - if (old_hovered_component != m_hovered_component) + if (old_hovered_component != m_hovered_component) { update(); + + if (m_automatic_scrolling_direction == AutomaticScrollingDirection::Decrement) + set_automatic_scrolling_active(m_hovered_component == Component::DecrementButton); + else if (m_automatic_scrolling_direction == AutomaticScrollingDirection::Increment) + set_automatic_scrolling_active(m_hovered_component == Component::IncrementButton); + } if (!m_scrubbing) return; float delta = orientation() == Orientation::Vertical ? (event.y() - m_scrub_origin.y()) : (event.x() - m_scrub_origin.x()); diff --git a/LibGUI/GScrollBar.h b/LibGUI/GScrollBar.h index 7878a9b627..938328ae70 100644 --- a/LibGUI/GScrollBar.h +++ b/LibGUI/GScrollBar.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include class GScrollBar final : public GWidget { @@ -28,8 +29,7 @@ public: virtual const char* class_name() const override { return "GScrollBar"; } - enum Component - { + enum Component { Invalid, DecrementButton, IncrementButton, @@ -48,13 +48,15 @@ private: int button_size() const { return 16; } int button_width() const { return orientation() == Orientation::Vertical ? width() : button_size(); } int button_height() const { return orientation() == Orientation::Horizontal ? height() : button_size(); } - Rect up_button_rect() const; - Rect down_button_rect() const; - Rect upper_gutter_rect() const; - Rect lower_gutter_rect() const; + Rect decrement_button_rect() const; + Rect increment_button_rect() const; + Rect decrement_gutter_rect() const; + Rect increment_gutter_rect() const; Rect scrubber_rect() const; int scrubber_size() const; int scrubbable_range_in_pixels() const; + void on_automatic_scrolling_timer_fired(); + void set_automatic_scrolling_active(bool); int m_min { 0 }; int m_max { 0 }; @@ -68,4 +70,13 @@ private: Orientation m_orientation { Orientation::Vertical }; Component m_hovered_component { Component::Invalid }; + + enum class AutomaticScrollingDirection { + None = 0, + Decrement, + Increment, + }; + + AutomaticScrollingDirection m_automatic_scrolling_direction { AutomaticScrollingDirection::None }; + CTimer m_automatic_scrolling_timer; }; diff --git a/LibGUI/GScrollableWidget.cpp b/LibGUI/GScrollableWidget.cpp index 9ae217e792..906572f26e 100644 --- a/LibGUI/GScrollableWidget.cpp +++ b/LibGUI/GScrollableWidget.cpp @@ -1,12 +1,12 @@ -#include #include +#include GScrollableWidget::GScrollableWidget(GWidget* parent) : GFrame(parent) { m_vertical_scrollbar = new GScrollBar(Orientation::Vertical, this); m_vertical_scrollbar->set_step(4); - m_vertical_scrollbar->on_change = [this] (int) { + m_vertical_scrollbar->on_change = [this](int) { did_scroll(); update(); }; @@ -14,7 +14,7 @@ GScrollableWidget::GScrollableWidget(GWidget* parent) m_horizontal_scrollbar = new GScrollBar(Orientation::Horizontal, this); m_horizontal_scrollbar->set_step(4); m_horizontal_scrollbar->set_big_step(30); - m_horizontal_scrollbar->on_change = [this] (int) { + m_horizontal_scrollbar->on_change = [this](int) { did_scroll(); update(); }; diff --git a/LibGUI/GShortcut.cpp b/LibGUI/GShortcut.cpp index 871bf1c99c..07bf1f7524 100644 --- a/LibGUI/GShortcut.cpp +++ b/LibGUI/GShortcut.cpp @@ -1,114 +1,218 @@ -#include #include +#include static String to_string(KeyCode key) { switch (key) { - case Key_Escape: return "Escape"; - case Key_Tab: return "Tab"; - case Key_Backspace: return "Backspace"; - case Key_Return: return "Return"; - case Key_Insert: return "Insert"; - case Key_Delete: return "Delete"; - case Key_PrintScreen: return "PrintScreen"; - case Key_SysRq: return "SysRq"; - case Key_Home: return "Home"; - case Key_End: return "End"; - case Key_Left: return "Left"; - case Key_Up: return "Up"; - case Key_Right: return "Right"; - case Key_Down: return "Down"; - case Key_PageUp: return "PageUp"; - case Key_PageDown: return "PageDown"; - case Key_Shift: return "Shift"; - case Key_Control: return "Control"; - case Key_Alt: return "Alt"; - case Key_CapsLock: return "CapsLock"; - case Key_NumLock: return "NumLock"; - case Key_ScrollLock: return "ScrollLock"; - case Key_F1: return "F1"; - case Key_F2: return "F2"; - case Key_F3: return "F3"; - case Key_F4: return "F4"; - case Key_F5: return "F5"; - case Key_F6: return "F6"; - case Key_F7: return "F7"; - case Key_F8: return "F8"; - case Key_F9: return "F9"; - case Key_F10: return "F10"; - case Key_F11: return "F11"; - case Key_F12: return "F12"; - case Key_Space: return "Space"; - case Key_ExclamationPoint: return "!"; - case Key_DoubleQuote: return "\""; - case Key_Hashtag: return "#"; - case Key_Dollar: return "$"; - case Key_Percent: return "%"; - case Key_Ampersand: return "&"; - case Key_Apostrophe: return "'"; - case Key_LeftParen: return "("; - case Key_RightParen: return ")"; - case Key_Asterisk: return "*"; - case Key_Plus: return "+"; - case Key_Comma: return ","; - case Key_Minus: return "-"; - case Key_Period: return ","; - case Key_Slash: return "/"; - case Key_0: return "0"; - case Key_1: return "1"; - case Key_2: return "2"; - case Key_3: return "3"; - case Key_4: return "4"; - case Key_5: return "5"; - case Key_6: return "6"; - case Key_7: return "7"; - case Key_8: return "8"; - case Key_9: return "9"; - case Key_Colon: return ":"; - case Key_Semicolon: return ";"; - case Key_LessThan: return "<"; - case Key_Equal: return "="; - case Key_GreaterThan: return ">"; - case Key_QuestionMark: return "?"; - case Key_AtSign: return "@"; - case Key_A: return "A"; - case Key_B: return "B"; - case Key_C: return "C"; - case Key_D: return "D"; - case Key_E: return "E"; - case Key_F: return "F"; - case Key_G: return "G"; - case Key_H: return "H"; - case Key_I: return "I"; - case Key_J: return "J"; - case Key_K: return "K"; - case Key_L: return "L"; - case Key_M: return "M"; - case Key_N: return "N"; - case Key_O: return "O"; - case Key_P: return "P"; - case Key_Q: return "Q"; - case Key_R: return "R"; - case Key_S: return "S"; - case Key_T: return "T"; - case Key_U: return "U"; - case Key_V: return "V"; - case Key_W: return "W"; - case Key_X: return "X"; - case Key_Y: return "Y"; - case Key_Z: return "Z"; - case Key_LeftBracket: return "["; - case Key_RightBracket: return "]"; - case Key_Backslash: return "\\"; - case Key_Circumflex: return "^"; - case Key_Underscore: return "_"; - case Key_LeftBrace: return "{"; - case Key_RightBrace: return "}"; - case Key_Pipe: return "|"; - case Key_Tilde: return "~"; - case Key_Backtick: return "`"; + case Key_Escape: + return "Escape"; + case Key_Tab: + return "Tab"; + case Key_Backspace: + return "Backspace"; + case Key_Return: + return "Return"; + case Key_Insert: + return "Insert"; + case Key_Delete: + return "Delete"; + case Key_PrintScreen: + return "PrintScreen"; + case Key_SysRq: + return "SysRq"; + case Key_Home: + return "Home"; + case Key_End: + return "End"; + case Key_Left: + return "Left"; + case Key_Up: + return "Up"; + case Key_Right: + return "Right"; + case Key_Down: + return "Down"; + case Key_PageUp: + return "PageUp"; + case Key_PageDown: + return "PageDown"; + case Key_Shift: + return "Shift"; + case Key_Control: + return "Control"; + case Key_Alt: + return "Alt"; + case Key_CapsLock: + return "CapsLock"; + case Key_NumLock: + return "NumLock"; + case Key_ScrollLock: + return "ScrollLock"; + case Key_F1: + return "F1"; + case Key_F2: + return "F2"; + case Key_F3: + return "F3"; + case Key_F4: + return "F4"; + case Key_F5: + return "F5"; + case Key_F6: + return "F6"; + case Key_F7: + return "F7"; + case Key_F8: + return "F8"; + case Key_F9: + return "F9"; + case Key_F10: + return "F10"; + case Key_F11: + return "F11"; + case Key_F12: + return "F12"; + case Key_Space: + return "Space"; + case Key_ExclamationPoint: + return "!"; + case Key_DoubleQuote: + return "\""; + case Key_Hashtag: + return "#"; + case Key_Dollar: + return "$"; + case Key_Percent: + return "%"; + case Key_Ampersand: + return "&"; + case Key_Apostrophe: + return "'"; + case Key_LeftParen: + return "("; + case Key_RightParen: + return ")"; + case Key_Asterisk: + return "*"; + case Key_Plus: + return "+"; + case Key_Comma: + return ","; + case Key_Minus: + return "-"; + case Key_Period: + return ","; + case Key_Slash: + return "/"; + case Key_0: + return "0"; + case Key_1: + return "1"; + case Key_2: + return "2"; + case Key_3: + return "3"; + case Key_4: + return "4"; + case Key_5: + return "5"; + case Key_6: + return "6"; + case Key_7: + return "7"; + case Key_8: + return "8"; + case Key_9: + return "9"; + case Key_Colon: + return ":"; + case Key_Semicolon: + return ";"; + case Key_LessThan: + return "<"; + case Key_Equal: + return "="; + case Key_GreaterThan: + return ">"; + case Key_QuestionMark: + return "?"; + case Key_AtSign: + return "@"; + case Key_A: + return "A"; + case Key_B: + return "B"; + case Key_C: + return "C"; + case Key_D: + return "D"; + case Key_E: + return "E"; + case Key_F: + return "F"; + case Key_G: + return "G"; + case Key_H: + return "H"; + case Key_I: + return "I"; + case Key_J: + return "J"; + case Key_K: + return "K"; + case Key_L: + return "L"; + case Key_M: + return "M"; + case Key_N: + return "N"; + case Key_O: + return "O"; + case Key_P: + return "P"; + case Key_Q: + return "Q"; + case Key_R: + return "R"; + case Key_S: + return "S"; + case Key_T: + return "T"; + case Key_U: + return "U"; + case Key_V: + return "V"; + case Key_W: + return "W"; + case Key_X: + return "X"; + case Key_Y: + return "Y"; + case Key_Z: + return "Z"; + case Key_LeftBracket: + return "["; + case Key_RightBracket: + return "]"; + case Key_Backslash: + return "\\"; + case Key_Circumflex: + return "^"; + case Key_Underscore: + return "_"; + case Key_LeftBrace: + return "{"; + case Key_RightBrace: + return "}"; + case Key_Pipe: + return "|"; + case Key_Tilde: + return "~"; + case Key_Backtick: + return "`"; - case Key_Invalid: return "Invalid"; + case Key_Invalid: + return "Invalid"; default: ASSERT_NOT_REACHED(); } diff --git a/LibGUI/GSlider.cpp b/LibGUI/GSlider.cpp index 97546c8f82..66adb04cf1 100644 --- a/LibGUI/GSlider.cpp +++ b/LibGUI/GSlider.cpp @@ -1,5 +1,5 @@ -#include #include +#include #include GSlider::GSlider(GWidget* parent) diff --git a/LibGUI/GSortingProxyModel.cpp b/LibGUI/GSortingProxyModel.cpp index 0661fd3e9d..7897503ffd 100644 --- a/LibGUI/GSortingProxyModel.cpp +++ b/LibGUI/GSortingProxyModel.cpp @@ -1,13 +1,13 @@ -#include #include -#include +#include #include +#include GSortingProxyModel::GSortingProxyModel(Retained&& target) : m_target(move(target)) , m_key_column(-1) { - m_target->on_model_update = [this] (GModel&) { + m_target->on_model_update = [this](GModel&) { resort(); }; } @@ -29,9 +29,9 @@ int GSortingProxyModel::column_count(const GModelIndex& index) const GModelIndex GSortingProxyModel::map_to_target(const GModelIndex& index) const { if (!index.is_valid()) - return { }; + return {}; if (index.row() >= m_row_mappings.size() || index.column() >= column_count()) - return { }; + return {}; return target().index(m_row_mappings[index.row()], index.column()); } @@ -82,7 +82,7 @@ void GSortingProxyModel::resort() did_update(); return; } - quick_sort(m_row_mappings.begin(), m_row_mappings.end(), [&] (auto row1, auto row2) -> bool { + quick_sort(m_row_mappings.begin(), m_row_mappings.end(), [&](auto row1, auto row2) -> bool { auto data1 = target().data(target().index(row1, m_key_column), GModel::Role::Sort); auto data2 = target().data(target().index(row2, m_key_column), GModel::Role::Sort); if (data1 == data2) diff --git a/LibGUI/GSpinBox.cpp b/LibGUI/GSpinBox.cpp index 891d98a218..f7a6d4b38d 100644 --- a/LibGUI/GSpinBox.cpp +++ b/LibGUI/GSpinBox.cpp @@ -1,5 +1,5 @@ -#include #include +#include #include GSpinBox::GSpinBox(GWidget* parent) @@ -16,10 +16,10 @@ GSpinBox::GSpinBox(GWidget* parent) }; m_increment_button = new GButton(this); m_increment_button->set_text("\xf6"); - m_increment_button->on_click = [this] (GButton&) { set_value(m_value + 1); }; + m_increment_button->on_click = [this](GButton&) { set_value(m_value + 1); }; m_decrement_button = new GButton(this); m_decrement_button->set_text("\xf7"); - m_decrement_button->on_click = [this] (GButton&) { set_value(m_value - 1); }; + m_decrement_button->on_click = [this](GButton&) { set_value(m_value - 1); }; } GSpinBox::~GSpinBox() diff --git a/LibGUI/GSplitter.cpp b/LibGUI/GSplitter.cpp index 567dfb4693..2544541aef 100644 --- a/LibGUI/GSplitter.cpp +++ b/LibGUI/GSplitter.cpp @@ -1,5 +1,5 @@ -#include #include +#include #include GSplitter::GSplitter(Orientation orientation, GWidget* parent) @@ -40,7 +40,7 @@ void GSplitter::mousedown_event(GMouseEvent& event) GWidget* first_resizee { nullptr }; GWidget* second_resizee { nullptr }; int fudge = layout()->spacing(); - for_each_child_widget([&] (auto& child) { + for_each_child_widget([&](auto& child) { int child_start = m_orientation == Orientation::Horizontal ? child.relative_rect().left() : child.relative_rect().top(); int child_end = m_orientation == Orientation::Horizontal ? child.relative_rect().right() : child.relative_rect().bottom(); if (x_or_y > child_end && (x_or_y - fudge) <= child_end) @@ -65,7 +65,8 @@ void GSplitter::mousemove_event(GMouseEvent& event) if (!m_first_resizee || !m_second_resizee) { // One or both of the resizees were deleted during an ongoing resize, screw this. m_resizing = false; - return;; + return; + ; } int minimum_size = 0; auto new_first_resizee_size = m_first_resizee_start_size; @@ -112,5 +113,4 @@ void GSplitter::mouseup_event(GMouseEvent& event) m_resizing = false; if (!rect().contains(event.position())) window()->set_override_cursor(GStandardCursor::None); - } diff --git a/LibGUI/GStackWidget.cpp b/LibGUI/GStackWidget.cpp index 312938d66d..010cfc6855 100644 --- a/LibGUI/GStackWidget.cpp +++ b/LibGUI/GStackWidget.cpp @@ -1,5 +1,5 @@ -#include #include +#include GStackWidget::GStackWidget(GWidget* parent) : GWidget(parent) @@ -28,7 +28,7 @@ void GStackWidget::resize_event(GResizeEvent& event) { if (!m_active_widget) return; - m_active_widget->set_relative_rect({ { }, event.size() }); + m_active_widget->set_relative_rect({ {}, event.size() }); } void GStackWidget::child_event(CChildEvent& event) @@ -44,9 +44,9 @@ void GStackWidget::child_event(CChildEvent& event) } else if (event.type() == GEvent::ChildRemoved) { if (m_active_widget == &child) { GWidget* new_active_widget = nullptr; - for_each_child_widget([&] (auto& new_child) { + for_each_child_widget([&](auto& new_child) { new_active_widget = &new_child; - return IterationDecision::Abort; + return IterationDecision::Break; }); set_active_widget(new_active_widget); } diff --git a/LibGUI/GStatusBar.cpp b/LibGUI/GStatusBar.cpp index 210622bab9..e219035e32 100644 --- a/LibGUI/GStatusBar.cpp +++ b/LibGUI/GStatusBar.cpp @@ -1,9 +1,9 @@ -#include -#include #include -#include +#include #include #include +#include +#include GStatusBar::GStatusBar(GWidget* parent) : GWidget(parent) @@ -26,7 +26,7 @@ GStatusBar::~GStatusBar() { } -void GStatusBar::set_text(const String& text) +void GStatusBar::set_text(const StringView& text) { m_label->set_text(text); } diff --git a/LibGUI/GStatusBar.h b/LibGUI/GStatusBar.h index 1ba0888179..ad1deebb61 100644 --- a/LibGUI/GStatusBar.h +++ b/LibGUI/GStatusBar.h @@ -11,7 +11,7 @@ public: virtual ~GStatusBar() override; String text() const; - void set_text(const String&); + void set_text(const StringView&); virtual const char* class_name() const override { return "GStatusBar"; } diff --git a/LibGUI/GTabWidget.cpp b/LibGUI/GTabWidget.cpp index 4aa94e4a6e..991a060350 100644 --- a/LibGUI/GTabWidget.cpp +++ b/LibGUI/GTabWidget.cpp @@ -1,6 +1,6 @@ -#include #include #include +#include #include GTabWidget::GTabWidget(GWidget* parent) @@ -14,7 +14,7 @@ GTabWidget::~GTabWidget() { } -void GTabWidget::add_widget(const String& title, GWidget* widget) +void GTabWidget::add_widget(const StringView& title, GWidget* widget) { m_tabs.append({ title, widget }); add_child(*widget); @@ -61,9 +61,9 @@ void GTabWidget::child_event(CChildEvent& event) } else if (event.type() == GEvent::ChildRemoved) { if (m_active_widget == &child) { GWidget* new_active_widget = nullptr; - for_each_child_widget([&] (auto& new_child) { + for_each_child_widget([&](auto& new_child) { new_active_widget = &new_child; - return IterationDecision::Abort; + return IterationDecision::Break; }); set_active_widget(new_active_widget); } diff --git a/LibGUI/GTabWidget.h b/LibGUI/GTabWidget.h index 7452c81da8..0b2e41ad58 100644 --- a/LibGUI/GTabWidget.h +++ b/LibGUI/GTabWidget.h @@ -13,7 +13,7 @@ public: int bar_height() const { return 21; } int container_padding() const { return 2; } - void add_widget(const String&, GWidget*); + void add_widget(const StringView&, GWidget*); virtual const char* class_name() const override { return "GTabWidget"; } diff --git a/LibGUI/GTableView.cpp b/LibGUI/GTableView.cpp index e4b49af9e5..8e096f3b43 100644 --- a/LibGUI/GTableView.cpp +++ b/LibGUI/GTableView.cpp @@ -1,13 +1,13 @@ -#include +#include +#include +#include +#include #include -#include #include +#include +#include #include #include -#include -#include -#include -#include GTableView::GTableView(GWidget* parent) : GAbstractView(parent) @@ -24,7 +24,7 @@ GTableView::~GTableView() void GTableView::update_content_size() { if (!model()) - return set_content_size({ }); + return set_content_size({}); int content_width = 0; int column_count = model()->column_count(); @@ -80,9 +80,9 @@ int GTableView::column_width(int column_index) const Rect GTableView::header_rect(int column_index) const { if (!model()) - return { }; + return {}; if (is_column_hidden(column_index)) - return { }; + return {}; int x_offset = 0; for (int i = 0; i < column_index; ++i) { if (is_column_hidden(i)) @@ -100,7 +100,7 @@ Point GTableView::adjusted_position(const Point& position) Rect GTableView::column_resize_grabbable_rect(int column) const { if (!model()) - return { }; + return {}; auto header_rect = this->header_rect(column); return { header_rect.right() - 1, header_rect.top(), 4, header_rect.height() }; } @@ -148,7 +148,7 @@ void GTableView::mousedown_event(GMouseEvent& event) return; } } - model()->set_selected_index({ }); + model()->set_selected_index({}); update(); } @@ -427,7 +427,7 @@ GMenu& GTableView::ensure_header_context_menu() for (int column = 0; column < model()->column_count(); ++column) { auto& column_data = this->column_data(column); auto name = model()->column_name(column); - column_data.visibility_action = GAction::create(name, [this, column] (GAction& action) { + column_data.visibility_action = GAction::create(name, [this, column](GAction& action) { action.set_checked(!action.is_checked()); set_column_hidden(column, !action.is_checked()); }); diff --git a/LibGUI/GTextEditor.cpp b/LibGUI/GTextEditor.cpp index 4c85f13ae0..a21159c36a 100644 --- a/LibGUI/GTextEditor.cpp +++ b/LibGUI/GTextEditor.cpp @@ -1,17 +1,17 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include -#include +#include GTextEditor::GTextEditor(Type type, GWidget* parent) : GScrollableWidget(parent) @@ -22,6 +22,8 @@ GTextEditor::GTextEditor(Type type, GWidget* parent) set_frame_thickness(2); set_scrollbars_enabled(is_multi_line()); set_font(GFontDatabase::the().get_by_name("Csilla Thin")); + // FIXME: Recompute vertical scrollbar step size on font change. + vertical_scrollbar().set_step(line_height()); m_lines.append(make()); m_cursor = { 0, 0 }; create_actions(); @@ -33,32 +35,38 @@ GTextEditor::~GTextEditor() void GTextEditor::create_actions() { - m_undo_action = GAction::create("Undo", { Mod_Ctrl, Key_Z }, GraphicsBitmap::load_from_file("/res/icons/16x16/undo.png"), [&] (const GAction&) { + m_undo_action = GAction::create("Undo", { Mod_Ctrl, Key_Z }, GraphicsBitmap::load_from_file("/res/icons/16x16/undo.png"), [&](const GAction&) { // FIXME: Undo - }, this); + }, + this); - m_redo_action = GAction::create("Redo", { Mod_Ctrl, Key_Y }, GraphicsBitmap::load_from_file("/res/icons/16x16/redo.png"), [&] (const GAction&) { + m_redo_action = GAction::create("Redo", { Mod_Ctrl, Key_Y }, GraphicsBitmap::load_from_file("/res/icons/16x16/redo.png"), [&](const GAction&) { // FIXME: Redo - }, this); + }, + this); - m_cut_action = GAction::create("Cut", { Mod_Ctrl, Key_X }, GraphicsBitmap::load_from_file("/res/icons/cut16.png"), [&] (const GAction&) { + m_cut_action = GAction::create("Cut", { Mod_Ctrl, Key_X }, GraphicsBitmap::load_from_file("/res/icons/cut16.png"), [&](const GAction&) { cut(); - }, this); + }, + this); - m_copy_action = GAction::create("Copy", { Mod_Ctrl, Key_C }, GraphicsBitmap::load_from_file("/res/icons/16x16/edit-copy.png"), [&] (const GAction&) { + m_copy_action = GAction::create("Copy", { Mod_Ctrl, Key_C }, GraphicsBitmap::load_from_file("/res/icons/16x16/edit-copy.png"), [&](const GAction&) { copy(); - }, this); + }, + this); - m_paste_action = GAction::create("Paste", { Mod_Ctrl, Key_V }, GraphicsBitmap::load_from_file("/res/icons/paste16.png"), [&] (const GAction&) { + m_paste_action = GAction::create("Paste", { Mod_Ctrl, Key_V }, GraphicsBitmap::load_from_file("/res/icons/paste16.png"), [&](const GAction&) { paste(); - }, this); + }, + this); - m_delete_action = GAction::create("Delete", { 0, Key_Delete }, GraphicsBitmap::load_from_file("/res/icons/16x16/delete.png"), [&] (const GAction&) { + m_delete_action = GAction::create("Delete", { 0, Key_Delete }, GraphicsBitmap::load_from_file("/res/icons/16x16/delete.png"), [&](const GAction&) { do_delete(); - }, this); + }, + this); } -void GTextEditor::set_text(const String& text) +void GTextEditor::set_text(const StringView& text) { if (is_single_line() && text.length() == m_lines[0]->length() && !memcmp(text.characters(), m_lines[0]->characters(), text.length())) return; @@ -67,11 +75,11 @@ void GTextEditor::set_text(const String& text) m_lines.clear(); int start_of_current_line = 0; - auto add_line = [&] (int current_position) { + auto add_line = [&](int current_position) { int line_length = current_position - start_of_current_line; auto line = make(); if (line_length) - line->set_text(text.substring(start_of_current_line, current_position - start_of_current_line)); + line->set_text(text.substring_view(start_of_current_line, current_position - start_of_current_line)); m_lines.append(move(line)); start_of_current_line = current_position + 1; }; @@ -187,7 +195,7 @@ void GTextEditor::mousedown_event(GMouseEvent& event) if (event.modifiers() & Mod_Shift) { if (!has_selection()) - m_selection.set(m_cursor, { }); + m_selection.set(m_cursor, {}); } else { m_selection.clear(); } @@ -198,7 +206,7 @@ void GTextEditor::mousedown_event(GMouseEvent& event) if (!(event.modifiers() & Mod_Shift)) { if (!has_selection()) - m_selection.set(m_cursor, { }); + m_selection.set(m_cursor, {}); } if (m_selection.start().is_valid() && m_selection.start() != m_cursor) @@ -241,7 +249,7 @@ int GTextEditor::ruler_width() const Rect GTextEditor::ruler_content_rect(int line_index) const { if (!m_ruler_visible) - return { }; + return {}; return { 0 - ruler_width() + horizontal_scrollbar().value(), line_index * line_height(), @@ -261,7 +269,7 @@ void GTextEditor::paint_event(GPaintEvent& event) painter.translate(frame_thickness(), frame_thickness()); - Rect ruler_rect { 0, 0, ruler_width(), height() - height_occupied_by_horizontal_scrollbar()}; + Rect ruler_rect { 0, 0, ruler_width(), height() - height_occupied_by_horizontal_scrollbar() }; if (m_ruler_visible) { painter.fill_rect(ruler_rect, Color::LightGray); @@ -287,8 +295,7 @@ void GTextEditor::paint_event(GPaintEvent& event) String::format("%u", i), is_current_line ? Font::default_bold_font() : font(), TextAlignment::CenterRight, - is_current_line ? Color::DarkGray : Color::MidGray - ); + is_current_line ? Color::DarkGray : Color::MidGray); } } @@ -301,18 +308,19 @@ void GTextEditor::paint_event(GPaintEvent& event) //line_rect.set_width(exposed_width); if (is_multi_line() && i == m_cursor.line()) painter.fill_rect(line_rect, Color(230, 230, 230)); - painter.draw_text(line_rect, line.characters(), line.length(), m_text_alignment, Color::Black); + painter.draw_text(line_rect, StringView(line.characters(), line.length()), m_text_alignment, Color::Black); bool line_has_selection = has_selection && i >= selection.start().line() && i <= selection.end().line(); if (line_has_selection) { int selection_start_column_on_line = selection.start().line() == i ? selection.start().column() : 0; int selection_end_column_on_line = selection.end().line() == i ? selection.end().column() : line.length(); int selection_left = content_x_for_position({ i, selection_start_column_on_line }); - int selection_right = content_x_for_position({ i, selection_end_column_on_line });; + int selection_right = content_x_for_position({ i, selection_end_column_on_line }); + ; Rect selection_rect { selection_left, line_rect.y(), selection_right - selection_left, line_rect.height() }; painter.fill_rect(selection_rect, Color::from_rgb(0x955233)); - painter.draw_text(selection_rect, line.characters() + selection_start_column_on_line, line.length() - selection_start_column_on_line - (line.length() - selection_end_column_on_line), TextAlignment::CenterLeft, Color::White); + painter.draw_text(selection_rect, StringView(line.characters() + selection_start_column_on_line, line.length() - selection_start_column_on_line - (line.length() - selection_end_column_on_line)), TextAlignment::CenterLeft, Color::White); } } @@ -323,7 +331,7 @@ void GTextEditor::paint_event(GPaintEvent& event) void GTextEditor::toggle_selection_if_needed_for_event(const GKeyEvent& event) { if (event.shift() && !m_selection.is_valid()) { - m_selection.set(m_cursor, { }); + m_selection.set(m_cursor, {}); did_update_selection(); update(); return; @@ -574,7 +582,7 @@ void GTextEditor::do_delete() } } -void GTextEditor::insert_at_cursor(const String& text) +void GTextEditor::insert_at_cursor(const StringView& text) { // FIXME: This should obviously not be implemented this way. for (int i = 0; i < text.length(); ++i) { @@ -652,7 +660,7 @@ int GTextEditor::content_x_for_position(const GTextPosition& position) const Rect GTextEditor::cursor_content_rect() const { if (!m_cursor.is_valid()) - return { }; + return {}; ASSERT(!m_lines.is_empty()); ASSERT(m_cursor.column() <= (current_line().length() + 1)); @@ -660,7 +668,7 @@ Rect GTextEditor::cursor_content_rect() const if (is_single_line()) { Rect cursor_rect { cursor_x, 0, 1, font().glyph_height() + 2 }; - cursor_rect.center_vertically_within({ { }, frame_inner_rect().size() }); + cursor_rect.center_vertically_within({ {}, frame_inner_rect().size() }); return cursor_rect; } return { cursor_x, m_cursor.line() * line_height(), 1, line_height() }; @@ -692,7 +700,7 @@ Rect GTextEditor::line_content_rect(int line_index) const auto& line = *m_lines[line_index]; if (is_single_line()) { Rect line_rect = { content_x_for_position({ line_index, 0 }), 0, line.length() * glyph_width(), font().glyph_height() + 2 }; - line_rect.center_vertically_within({ { }, frame_inner_rect().size() }); + line_rect.center_vertically_within({ {}, frame_inner_rect().size() }); return line_rect; } return { @@ -756,7 +764,7 @@ GTextEditor::Line::Line() clear(); } -GTextEditor::Line::Line(const String& text) +GTextEditor::Line::Line(const StringView& text) { set_text(text); } @@ -767,7 +775,7 @@ void GTextEditor::Line::clear() m_text.append(0); } -void GTextEditor::Line::set_text(const String& text) +void GTextEditor::Line::set_text(const StringView& text) { if (text.length() == length() && !memcmp(text.characters(), characters(), length())) return; @@ -828,7 +836,7 @@ void GTextEditor::Line::truncate(int length) m_text.last() = 0; } -bool GTextEditor::write_to_file(const String& path) +bool GTextEditor::write_to_file(const StringView& path) { int fd = open(path.characters(), O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) { @@ -885,7 +893,7 @@ void GTextEditor::clear() String GTextEditor::selected_text() const { if (!has_selection()) - return { }; + return {}; auto selection = normalized_selection(); StringBuilder builder; @@ -952,7 +960,7 @@ void GTextEditor::delete_selection() update(); } -void GTextEditor::insert_at_cursor_or_replace_selection(const String& text) +void GTextEditor::insert_at_cursor_or_replace_selection(const StringView& text) { ASSERT(!is_readonly()); if (has_selection()) @@ -1003,7 +1011,7 @@ void GTextEditor::did_change() update_content_size(); if (!m_have_pending_change_notification) { m_have_pending_change_notification = true; - deferred_invoke([this] (auto&) { + deferred_invoke([this](auto&) { if (on_change) on_change(); m_have_pending_change_notification = false; diff --git a/LibGUI/GTextEditor.h b/LibGUI/GTextEditor.h index 648bf9d80d..124f82b8ca 100644 --- a/LibGUI/GTextEditor.h +++ b/LibGUI/GTextEditor.h @@ -78,8 +78,7 @@ private: class GTextEditor : public GScrollableWidget { public: - enum Type - { + enum Type { MultiLine, SingleLine }; @@ -105,7 +104,7 @@ public: Function on_cursor_change; Function on_selection_change; - void set_text(const String&); + void set_text(const StringView&); void scroll_cursor_into_view(); int line_count() const { return m_lines.size(); } int line_spacing() const { return m_line_spacing; } @@ -115,7 +114,7 @@ public: // FIXME: This should take glyph spacing into account, no? int glyph_width() const { return font().glyph_width('x'); } - bool write_to_file(const String& path); + bool write_to_file(const StringView& path); bool has_selection() const { return m_selection.is_valid(); } String selected_text() const; @@ -168,12 +167,12 @@ private: public: Line(); - explicit Line(const String&); + explicit Line(const StringView&); const char* characters() const { return m_text.data(); } int length() const { return m_text.size() - 1; } int width(const Font&) const; - void set_text(const String&); + void set_text(const StringView&); void append(char); void prepend(char); void insert(int index, char); @@ -197,11 +196,11 @@ private: const Line& current_line() const { return *m_lines[m_cursor.line()]; } GTextPosition text_position_at(const Point&) const; void insert_at_cursor(char); - void insert_at_cursor(const String&); + void insert_at_cursor(const StringView&); int ruler_width() const; Rect ruler_content_rect(int line) const; void toggle_selection_if_needed_for_event(const GKeyEvent&); - void insert_at_cursor_or_replace_selection(const String&); + void insert_at_cursor_or_replace_selection(const StringView&); void delete_selection(); void did_update_selection(); int content_x_for_position(const GTextPosition&) const; diff --git a/LibGUI/GToolBar.cpp b/LibGUI/GToolBar.cpp index 8b0fa64aaa..5aa6f469c2 100644 --- a/LibGUI/GToolBar.cpp +++ b/LibGUI/GToolBar.cpp @@ -1,8 +1,8 @@ -#include +#include #include #include -#include #include +#include GToolBar::GToolBar(GWidget* parent) : GWidget(parent) @@ -32,7 +32,7 @@ void GToolBar::add_action(Retained&& action) button->set_icon(item->action->icon()); else button->set_text(item->action->text()); - button->on_click = [raw_action_ptr] (const GButton&) { + button->on_click = [raw_action_ptr](const GButton&) { raw_action_ptr->activate(); }; @@ -54,7 +54,7 @@ public: set_background_color(Color::White); set_preferred_size({ 8, 22 }); } - virtual ~SeparatorWidget() override { } + virtual ~SeparatorWidget() override {} virtual void paint_event(GPaintEvent& event) override { diff --git a/LibGUI/GToolBar.h b/LibGUI/GToolBar.h index 5dac448e74..ec0c654bb0 100644 --- a/LibGUI/GToolBar.h +++ b/LibGUI/GToolBar.h @@ -21,8 +21,7 @@ private: virtual void paint_event(GPaintEvent&) override; struct Item { - enum Type - { + enum Type { Invalid, Separator, Action diff --git a/LibGUI/GTreeView.cpp b/LibGUI/GTreeView.cpp index 0b7203deb5..f58b4a2758 100644 --- a/LibGUI/GTreeView.cpp +++ b/LibGUI/GTreeView.cpp @@ -1,6 +1,6 @@ -#include #include #include +#include //#define DEBUG_ITEM_RECTS @@ -39,17 +39,17 @@ GModelIndex GTreeView::index_at_content_position(const Point& position, bool& is { is_toggle = false; if (!model()) - return { }; + return {}; GModelIndex result; - traverse_in_paint_order([&] (const GModelIndex& index, const Rect& rect, const Rect& toggle_rect, int) { + traverse_in_paint_order([&](const GModelIndex& index, const Rect& rect, const Rect& toggle_rect, int) { if (rect.contains(position)) { result = index; - return IterationDecision::Abort; + return IterationDecision::Break; } if (toggle_rect.contains(position)) { result = index; is_toggle = true; - return IterationDecision::Abort; + return IterationDecision::Break; } return IterationDecision::Continue; }); @@ -88,7 +88,7 @@ void GTreeView::traverse_in_paint_order(Callback callback) const int indent_level = 0; int y_offset = 0; - Function traverse_index = [&] (const GModelIndex& index) { + Function traverse_index = [&](const GModelIndex& index) { int row_count_at_index = model.row_count(index); if (index.is_valid()) { auto& metadata = ensure_metadata_for_index(index); @@ -104,8 +104,8 @@ void GTreeView::traverse_in_paint_order(Callback callback) const toggle_rect = { toggle_x, rect.y(), toggle_size(), toggle_size() }; toggle_rect.center_vertically_within(rect); } - if (callback(index, rect, toggle_rect, indent_level) == IterationDecision::Abort) - return IterationDecision::Abort; + if (callback(index, rect, toggle_rect, indent_level) == IterationDecision::Break) + return IterationDecision::Break; y_offset += item_height(); // NOTE: Skip traversing children if this index is closed! if (!metadata.open) @@ -115,8 +115,8 @@ void GTreeView::traverse_in_paint_order(Callback callback) const ++indent_level; int row_count = model.row_count(index); for (int i = 0; i < row_count; ++i) { - if (traverse_index(model.index(i, 0, index)) == IterationDecision::Abort) - return IterationDecision::Abort; + if (traverse_index(model.index(i, 0, index)) == IterationDecision::Break) + return IterationDecision::Break; } --indent_level; return IterationDecision::Continue; @@ -139,7 +139,7 @@ void GTreeView::paint_event(GPaintEvent& event) auto& model = *this->model(); auto visible_content_rect = this->visible_content_rect(); - traverse_in_paint_order([&] (const GModelIndex& index, const Rect& rect, const Rect& toggle_rect, int indent_level) { + traverse_in_paint_order([&](const GModelIndex& index, const Rect& rect, const Rect& toggle_rect, int indent_level) { if (!rect.intersects(visible_content_rect)) return IterationDecision::Continue; #ifdef DEBUG_ITEM_RECTS @@ -202,10 +202,10 @@ void GTreeView::scroll_into_view(const GModelIndex& a_index, Orientation orienta if (!a_index.is_valid()) return; Rect found_rect; - traverse_in_paint_order([&] (const GModelIndex& index, const Rect& rect, const Rect&, int) { + traverse_in_paint_order([&](const GModelIndex& index, const Rect& rect, const Rect&, int) { if (index == a_index) { found_rect = rect; - return IterationDecision::Abort; + return IterationDecision::Break; } return IterationDecision::Continue; }); @@ -251,7 +251,7 @@ void GTreeView::update_content_size() { int height = 0; int width = 0; - traverse_in_paint_order([&] (const GModelIndex&, const Rect& rect, const Rect&, int) { + traverse_in_paint_order([&](const GModelIndex&, const Rect& rect, const Rect&, int) { width = max(width, rect.right()); height += rect.height(); return IterationDecision::Continue; @@ -267,10 +267,10 @@ void GTreeView::keydown_event(GKeyEvent& event) if (event.key() == KeyCode::Key_Up) { GModelIndex previous_index; GModelIndex found_index; - traverse_in_paint_order([&] (const GModelIndex& index, const Rect&, const Rect&, int) { + traverse_in_paint_order([&](const GModelIndex& index, const Rect&, const Rect&, int) { if (index == cursor_index) { found_index = previous_index; - return IterationDecision::Abort; + return IterationDecision::Break; } previous_index = index; return IterationDecision::Continue; @@ -284,10 +284,10 @@ void GTreeView::keydown_event(GKeyEvent& event) if (event.key() == KeyCode::Key_Down) { GModelIndex previous_index; GModelIndex found_index; - traverse_in_paint_order([&] (const GModelIndex& index, const Rect&, const Rect&, int) { + traverse_in_paint_order([&](const GModelIndex& index, const Rect&, const Rect&, int) { if (previous_index == cursor_index) { found_index = index; - return IterationDecision::Abort; + return IterationDecision::Break; } previous_index = index; return IterationDecision::Continue; diff --git a/LibGUI/GVariant.cpp b/LibGUI/GVariant.cpp index e8c07e98e9..bad6f9d3b6 100644 --- a/LibGUI/GVariant.cpp +++ b/LibGUI/GVariant.cpp @@ -252,4 +252,3 @@ String GVariant::to_string() const } ASSERT_NOT_REACHED(); } - diff --git a/LibGUI/GVariant.h b/LibGUI/GVariant.h index 83193e82ad..38cdfd713b 100644 --- a/LibGUI/GVariant.h +++ b/LibGUI/GVariant.h @@ -27,8 +27,7 @@ public: void clear(); ~GVariant(); - enum class Type - { + enum class Type { Invalid, Bool, Int, diff --git a/LibGUI/GWidget.cpp b/LibGUI/GWidget.cpp index 30f4284a46..d0ac2161b0 100644 --- a/LibGUI/GWidget.cpp +++ b/LibGUI/GWidget.cpp @@ -2,13 +2,13 @@ #include "GEvent.h" #include "GEventLoop.h" #include "GWindow.h" -#include #include -#include #include -#include #include +#include #include +#include +#include #include GWidget::GWidget(GWidget* parent) @@ -116,7 +116,7 @@ void GWidget::handle_paint_event(GPaintEvent& event) #endif } paint_event(event); - for_each_child_widget([&] (auto& child) { + for_each_child_widget([&](auto& child) { if (!child.is_visible()) return IterationDecision::Continue; if (child.relative_rect().intersects(event.rect())) { @@ -418,7 +418,7 @@ void GWidget::invalidate_layout() if (m_layout_dirty) return; m_layout_dirty = true; - deferred_invoke([this] (auto&) { + deferred_invoke([this](auto&) { m_layout_dirty = false; auto* w = window(); if (!w) @@ -472,7 +472,7 @@ void GWidget::move_to_front() return; if (parent->children().size() == 1) return; - parent->children().remove_first_matching([this] (auto& entry) { + parent->children().remove_first_matching([this](auto& entry) { return entry == this; }); parent->children().append(this); @@ -486,7 +486,7 @@ void GWidget::move_to_back() return; if (parent->children().size() == 1) return; - parent->children().remove_first_matching([this] (auto& entry) { + parent->children().remove_first_matching([this](auto& entry) { return entry == this; }); parent->children().prepend(this); diff --git a/LibGUI/GWidget.h b/LibGUI/GWidget.h index 11524fb005..c978f913c9 100644 --- a/LibGUI/GWidget.h +++ b/LibGUI/GWidget.h @@ -17,23 +17,19 @@ class GLayout; class GMenu; class GWindow; -enum class SizePolicy -{ +enum class SizePolicy { Fixed, Fill }; -enum class Orientation -{ +enum class Orientation { Horizontal, Vertical }; -enum class HorizontalDirection -{ +enum class HorizontalDirection { Left, Right }; -enum class VerticalDirection -{ +enum class VerticalDirection { Up, Down }; @@ -56,7 +52,7 @@ public: bool has_tooltip() const { return !m_tooltip.is_empty(); } String tooltip() const { return m_tooltip; } - void set_tooltip(const String& tooltip) { m_tooltip = tooltip; } + void set_tooltip(const StringView& tooltip) { m_tooltip = tooltip; } bool is_enabled() const { return m_enabled; } void set_enabled(bool); @@ -203,6 +199,7 @@ public: } virtual bool is_radio_button() const { return false; } + virtual bool is_abstract_button() const { return false; } private: virtual bool is_widget() const final { return true; } diff --git a/LibGUI/GWindow.cpp b/LibGUI/GWindow.cpp index a84d55a0ed..9ef6ce4c90 100644 --- a/LibGUI/GWindow.cpp +++ b/LibGUI/GWindow.cpp @@ -2,12 +2,12 @@ #include "GEvent.h" #include "GEventLoop.h" #include "GWidget.h" -#include -#include +#include #include #include #include -#include +#include +#include //#define UPDATE_COALESCING_DEBUG @@ -49,6 +49,17 @@ void GWindow::close() delete_later(); } +void GWindow::move_to_front() +{ + if (!m_window_id) + return; + + WSAPI_ClientMessage request; + request.type = WSAPI_ClientMessage::Type::MoveWindowToFront; + request.window_id = m_window_id; + GEventLoop::post_message_to_server(request); +} + void GWindow::show() { if (m_window_id) @@ -93,7 +104,7 @@ void GWindow::hide() m_front_bitmap = nullptr; } -void GWindow::set_title(const String& title) +void GWindow::set_title(const StringView& title) { m_title_when_windowless = title; if (!m_window_id) @@ -224,7 +235,7 @@ void GWindow::event(CEvent& event) auto rect = rects.first(); if (rect.is_empty() || created_new_backing_store) { rects.clear(); - rects.append({ { }, paint_event.window_size() }); + rects.append({ {}, paint_event.window_size() }); } for (auto& rect : rects) @@ -325,10 +336,10 @@ void GWindow::event(CEvent& event) m_back_bitmap = nullptr; if (!m_pending_paint_event_rects.is_empty()) { m_pending_paint_event_rects.clear_with_capacity(); - m_pending_paint_event_rects.append({ { }, new_size }); + m_pending_paint_event_rects.append({ {}, new_size }); } - m_rect_when_windowless = { { }, new_size }; - m_main_widget->set_relative_rect({ { }, new_size }); + m_rect_when_windowless = { {}, new_size }; + m_main_widget->set_relative_rect({ {}, new_size }); return; } @@ -421,7 +432,7 @@ void GWindow::update(const Rect& a_rect) } if (m_pending_paint_event_rects.is_empty()) { - deferred_invoke([this] (auto&) { + deferred_invoke([this](auto&) { auto rects = move(m_pending_paint_event_rects); if (rects.is_empty()) return; @@ -452,7 +463,7 @@ void GWindow::set_main_widget(GWidget* widget) if (m_main_widget->vertical_size_policy() == SizePolicy::Fixed) new_window_rect.set_height(m_main_widget->preferred_size().height()); set_rect(new_window_rect); - m_main_widget->set_relative_rect({ { }, new_window_rect.size() }); + m_main_widget->set_relative_rect({ {}, new_window_rect.size() }); m_main_widget->set_window(this); if (m_main_widget->accepts_focus()) m_main_widget->set_focus(true); @@ -597,7 +608,7 @@ void GWindow::wm_event(GWMEvent&) { } -void GWindow::set_icon_path(const String& path) +void GWindow::set_icon_path(const StringView& path) { if (m_icon_path == path) return; @@ -625,14 +636,14 @@ void GWindow::start_wm_resize() Vector GWindow::focusable_widgets() const { if (!m_main_widget) - return { }; + return {}; Vector collected_widgets; - Function collect_focusable_widgets = [&] (GWidget& widget) { + Function collect_focusable_widgets = [&](GWidget& widget) { if (widget.accepts_focus()) collected_widgets.append(&widget); - widget.for_each_child_widget([&] (auto& child) { + widget.for_each_child_widget([&](auto& child) { if (!child.is_visible()) return IterationDecision::Continue; if (!child.is_enabled()) diff --git a/LibGUI/GWindow.h b/LibGUI/GWindow.h index 5ced9f7572..957a50ed93 100644 --- a/LibGUI/GWindow.h +++ b/LibGUI/GWindow.h @@ -13,8 +13,7 @@ class GPainter; class GWidget; class GWMEvent; -enum class GStandardCursor -{ +enum class GStandardCursor { None = 0, Arrow, IBeam, @@ -48,7 +47,7 @@ public: int window_id() const { return m_window_id; } String title() const; - void set_title(const String&); + void set_title(const StringView&); bool show_titlebar() const { return m_show_titlebar; }; void set_show_titlebar(bool show) { m_show_titlebar = show; }; @@ -82,6 +81,7 @@ public: void show(); void hide(); void close(); + void move_to_front(); void start_wm_resize(); @@ -121,7 +121,7 @@ public: void set_override_cursor(GStandardCursor); String icon_path() const { return m_icon_path; } - void set_icon_path(const String&); + void set_icon_path(const StringView&); Vector focusable_widgets() const; diff --git a/LibGUI/GWindowType.h b/LibGUI/GWindowType.h index a399dec4a3..d620889249 100644 --- a/LibGUI/GWindowType.h +++ b/LibGUI/GWindowType.h @@ -1,7 +1,6 @@ #pragma once -enum class GWindowType -{ +enum class GWindowType { Invalid = 0, Normal, Menu, diff --git a/LibM/math.cpp b/LibM/math.cpp index 5cb3f6fe2a..dcc642396e 100644 --- a/LibM/math.cpp +++ b/LibM/math.cpp @@ -95,30 +95,33 @@ double fabs(double value) { return value < 0 ? -value : value; } -double log2(double ) +double log2(double) { ASSERT_NOT_REACHED(); } -float log2f(float ){ - ASSERT_NOT_REACHED(); - -} - -long double log2l(long double ){ +float log2f(float) +{ ASSERT_NOT_REACHED(); } -double frexp(double , int *){ +long double log2l(long double) +{ ASSERT_NOT_REACHED(); } -float frexpf(float , int *){ +double frexp(double, int*) +{ ASSERT_NOT_REACHED(); } -long double frexpl(long double , int *){ +float frexpf(float, int*) +{ ASSERT_NOT_REACHED(); +} +long double frexpl(long double, int*) +{ + ASSERT_NOT_REACHED(); } } diff --git a/LibM/math.h b/LibM/math.h index adb282fa73..ccbce35d54 100644 --- a/LibM/math.h +++ b/LibM/math.h @@ -55,10 +55,9 @@ double pow(double x, double y); double log2(double); float log2f(float); -long double log2l(long double); -double frexp(double, int *); -float frexpf(float, int *); -long double frexpl(long double, int *); - +long double log2l(long double); +double frexp(double, int*); +float frexpf(float, int*); +long double frexpl(long double, int*); __END_DECLS diff --git a/Meta/BuildInstructions.md b/Meta/BuildInstructions.md index 8ee623a3d3..b24d3cc33d 100644 --- a/Meta/BuildInstructions.md +++ b/Meta/BuildInstructions.md @@ -16,6 +16,8 @@ For Serenity, we will need e2fsprogs and QEMU: sudo apt install e2fsprogs qemu-system-i386 +Note: there is a problem with the PS/2 keyboard/mouse emulation in QEMU 2.11.1 as packaged in Ubuntu's LTS releases. If you have any strange behaviour with missing keyboard inputs or jittery mouse movement, try building QEMU from source. 2.12.1, 3.0.1, 3.1.0, and 4.0.0 are all confirmed as working when built from source. + ## Binutils: Download GNU binutils-2.32 and apply the patch serenity/Meta/binutils-2.32-serenity.patch diff --git a/Meta/screenshot-191112e.png b/Meta/screenshot-191112e.png new file mode 100644 index 0000000000..391c92be04 Binary files /dev/null and b/Meta/screenshot-191112e.png differ diff --git a/Ports/.port_include.sh b/Ports/.port_include.sh index 06bc87fb28..075e8d70eb 100755 --- a/Ports/.port_include.sh +++ b/Ports/.port_include.sh @@ -19,19 +19,19 @@ if [ -z "$PORT_DIR" ]; then exit 1 fi -function run_command() { +run_command() { echo "+ $@" (cd "$PORT_DIR" && "$@") echo "+ FINISHED: $@" } -function run_command_nocd() { +run_command_nocd() { echo "+ $@ (nocd)" ("$@") echo "+ FINISHED (nocd): $@" } -function run_fetch_git() { +run_fetch_git() { if [ -d "$PORT_DIR/.git" ]; then run_command git fetch run_command git reset --hard FETCH_HEAD @@ -41,7 +41,7 @@ function run_fetch_git() { fi } -function run_fetch_web() { +run_fetch_web() { if [ -d "$PORT_DIR" ]; then run_command_nocd rm -rf "$PORT_DIR" fi @@ -54,36 +54,36 @@ function run_fetch_web() { run_command_nocd tar xavf "$file" -C "$PORT_DIR" --strip-components=1 } -function run_export_env() { +run_export_env() { export $1="$2" } -function run_replace_in_file() { +run_replace_in_file() { run_command perl -p -i -e "$1" $2 } -function run_patch() { +run_patch() { echo "+ Applying patch $1" run_command patch "$2" < "$1" } -function run_configure_cmake() { +run_configure_cmake() { run_command cmake -DCMAKE_TOOLCHAIN_FILE="$SERENITY_ROOT/Toolchain/CMakeToolchain.txt" . } -function run_configure_autotools() { +run_configure_autotools() { run_command ./configure --host=i686-pc-serenity "$@" } -function run_make() { +run_make() { run_command make $MAKEOPTS "$@" } -function run_make_install() { +run_make_install() { run_command make $INSTALLOPTS install "$@" } -function run_send_to_file() { +run_send_to_file() { echo "+ rewrite '$1'" (cd "$PORT_DIR" && echo "$2" > "$1") echo "+ FINISHED" @@ -101,16 +101,16 @@ if [ -z "$1" ]; then exit 0 fi -if [ "$1" == "fetch" ]; then +if [ "$1" = "fetch" ]; then echo "+ Fetching..." fetch -elif [ "$1" == "configure" ]; then +elif [ "$1" = "configure" ]; then echo "+ Configuring..." configure -elif [ "$1" == "build" ]; then +elif [ "$1" = "build" ]; then echo "+ Building..." build -elif [ "$1" == "install" ]; then +elif [ "$1" = "install" ]; then echo "+ Installing..." install else diff --git a/Ports/SDL2/SDL2.sh b/Ports/SDL2/SDL2.sh index 239e44d58b..4226b13811 100755 --- a/Ports/SDL2/SDL2.sh +++ b/Ports/SDL2/SDL2.sh @@ -1,15 +1,15 @@ #!/bin/sh PORT_DIR=SDL -function fetch() { +fetch() { run_fetch_git "https://github.com/SerenityOS/SDL" } -function configure() { +configure() { run_configure_cmake } -function build() { +build() { run_make } -function install() { +install() { run_make_install } -source ../.port_include.sh +. ../.port_include.sh diff --git a/Ports/bash/bash.sh b/Ports/bash/bash.sh index 61bc2ad269..fa701caa68 100755 --- a/Ports/bash/bash.sh +++ b/Ports/bash/bash.sh @@ -1,6 +1,6 @@ #!/bin/sh PORT_DIR=bash -function fetch() { +fetch() { run_fetch_git "https://git.savannah.gnu.org/git/bash.git" # Add serenity as a system for configure @@ -13,16 +13,16 @@ function fetch() { # Locale calls crash right now. LibC bug, probably. run_patch disable-locale.patch -p1 } -function configure() { +configure() { run_configure_autotools --disable-nls --without-bash-malloc } -function build() { +build() { # Avoid some broken cross compile tests... run_replace_in_file "s/define GETCWD_BROKEN 1/undef GETCWD_BROKEN/" config.h run_replace_in_file "s/define CAN_REDEFINE_GETENV 1/undef CAN_REDEFINE_GETENV/" config.h run_make } -function install() { +install() { run_make_install DESTDIR="$SERENITY_ROOT"/Root } -source ../.port_include.sh +. ../.port_include.sh diff --git a/Ports/binutils/binutils.sh b/Ports/binutils/binutils.sh index 36c6432ca6..b01e4816f7 100755 --- a/Ports/binutils/binutils.sh +++ b/Ports/binutils/binutils.sh @@ -1,12 +1,12 @@ -#!/bin/bash +#!/bin/sh PORT_DIR=binutils -function fetch() { +fetch() { run_fetch_web "https://ftp.gnu.org/gnu/binutils/binutils-2.32.tar.xz" # Add the big binutils patch (same one used by toolchain.) run_patch $SERENITY_ROOT/Toolchain/Patches/binutils.patch -p1 } -function configure() { +configure() { run_configure_autotools \ --target=i686-pc-serenity \ --with-sysroot=/ \ @@ -15,10 +15,10 @@ function configure() { --disable-gdb \ --disable-nls } -function build() { +build() { run_make } -function install() { +install() { run_make_install DESTDIR="$SERENITY_ROOT"/Root } -source ../.port_include.sh +. ../.port_include.sh diff --git a/Ports/figlet/figlet-no-toilet-fonts.patch b/Ports/figlet/figlet-no-toilet-fonts.patch new file mode 100644 index 0000000000..44cad8fc8e --- /dev/null +++ b/Ports/figlet/figlet-no-toilet-fonts.patch @@ -0,0 +1,11 @@ +--- figlet-2.2.5/Makefile 2012-06-01 14:51:09.000000000 +0200 ++++ figlet-2.2.5-patched/Makefile 2019-06-09 12:15:01.817177188 +0200 +@@ -26,7 +26,7 @@ + + # Feature flags: + # define TLF_FONTS to use TOIlet TLF fonts +-XCFLAGS = -DTLF_FONTS ++#XCFLAGS = -DTLF_FONTS + + # Where to install files + prefix = /usr/local diff --git a/Ports/figlet/figlet.sh b/Ports/figlet/figlet.sh new file mode 100755 index 0000000000..f38af411ed --- /dev/null +++ b/Ports/figlet/figlet.sh @@ -0,0 +1,23 @@ +#!/bin/sh +PORT_DIR=figlet +INSTALLOPTS="DESTDIR=$SERENITY_ROOT/Root/" + +fetch() { + run_fetch_web "http://ftp.figlet.org/pub/figlet/program/unix/figlet-2.2.5.tar.gz" + + run_patch figlet-no-toilet-fonts.patch -p1 +} + +configure() { + echo "No configure script" +} + +build() { + run_make CC=i686-pc-serenity-gcc LD=i686-pc-serenity-gcc +} + +install() { + run_make_install +} + +. ../.port_include.sh diff --git a/Ports/gcc/gcc.sh b/Ports/gcc/gcc.sh index 9b1cbbdfa8..88ce8aab39 100755 --- a/Ports/gcc/gcc.sh +++ b/Ports/gcc/gcc.sh @@ -1,6 +1,6 @@ -#!/bin/bash +#!/bin/sh PORT_DIR=gcc -function fetch() { +fetch() { run_fetch_web "https://ftp.gnu.org/gnu/gcc/gcc-8.3.0/gcc-8.3.0.tar.xz" # Add the big GCC patch (same one used by toolchain.) @@ -12,7 +12,7 @@ function fetch() { # Patch mpfr, mpc and isl to teach them about "serenity" targets. run_patch dependencies-config.patch -p1 } -function configure() { +configure() { run_configure_autotools \ --target=i686-pc-serenity \ --with-sysroot=/ \ @@ -22,12 +22,12 @@ function configure() { --disable-lto \ --disable-nls } -function build() { +build() { MAKEOPTS="" run_make all-gcc all-target-libgcc all-target-libstdc++-v3 run_command find ./host-i686-pc-serenity/gcc/ -maxdepth 1 -type f -executable -exec strip --strip-debug {} \; || echo } -function install() { +install() { run_make $INSTALLOPTS DESTDIR="$SERENITY_ROOT"/Root install-gcc install-target-libgcc install-target-libstdc++-v3 } -source ../.port_include.sh +. ../.port_include.sh diff --git a/Ports/less/less.sh b/Ports/less/less.sh index 808d08405d..9be9766b29 100755 --- a/Ports/less/less.sh +++ b/Ports/less/less.sh @@ -2,16 +2,16 @@ PORT_DIR=less INSTALLOPTS="DESTDIR=$SERENITY_ROOT/Root/" -function fetch() { +fetch() { run_fetch_web "http://ftp.gnu.org/gnu/less/less-530.tar.gz" } -function configure() { +configure() { run_configure_autotools } -function build() { +build() { run_make } -function install() { +install() { run_make_install } -source ../.port_include.sh +. ../.port_include.sh diff --git a/Ports/links/links.sh b/Ports/links/links.sh index 29a74aac6f..a3674d3b45 100755 --- a/Ports/links/links.sh +++ b/Ports/links/links.sh @@ -1,16 +1,16 @@ #!/bin/sh PORT_DIR=links -function fetch() { +fetch() { run_fetch_web "http://links.twibright.com/download/links-2.19.tar.bz2" } -function configure() { +configure() { run_export_env CC i686-pc-serenity-gcc run_configure_autotools } -function build() { +build() { run_make } -function install() { +install() { run_make_install DESTDIR="$SERENITY_ROOT"/Root } -source ../.port_include.sh +. ../.port_include.sh diff --git a/Ports/lua/lua.sh b/Ports/lua/lua.sh index 0656fa6534..924ca408ac 100755 --- a/Ports/lua/lua.sh +++ b/Ports/lua/lua.sh @@ -4,21 +4,21 @@ MAKEOPTS='generic' INSTALLOPTS="INSTALL_TOP=$SERENITY_ROOT/Root/" -function fetch() { +fetch() { run_fetch_web "http://www.lua.org/ftp/lua-5.3.5.tar.gz" run_patch lua.patch -p1 } -function configure() { +configure() { run_export_env CC i686-pc-serenity-gcc } -function run_make() { +run_make() { run_command make $MAKEOPTS "$@" } -function build() { +build() { run_make } -function install() { +install() { run_make_install DESTDIR="$SERENITY_ROOT"/Root } -source ../.port_include.sh +. ../.port_include.sh diff --git a/Ports/ncurses/ncurses.sh b/Ports/ncurses/ncurses.sh index 4d8ef0afb6..5d2bc20684 100755 --- a/Ports/ncurses/ncurses.sh +++ b/Ports/ncurses/ncurses.sh @@ -2,17 +2,17 @@ PORT_DIR=ncurses INSTALLOPTS="DESTDIR=$SERENITY_ROOT/Root/" -function fetch() { +fetch() { run_fetch_git "https://github.com/mirror/ncurses.git" run_patch allow-serenity-os-ncurses.patch -p1 } -function configure() { +configure() { run_configure_autotools } -function build() { +build() { run_make } -function install() { +install() { run_make_install } -source ../.port_include.sh +. ../.port_include.sh diff --git a/Ports/vim/vim.sh b/Ports/vim/vim.sh index cf4407190d..98a7567a10 100755 --- a/Ports/vim/vim.sh +++ b/Ports/vim/vim.sh @@ -2,11 +2,11 @@ PORT_DIR=vim INSTALLOPTS="DESTDIR=$SERENITY_ROOT/Root/" -function fetch() { +fetch() { run_fetch_git "https://github.com/vim/vim.git" } -function configure() { +configure() { run_send_to_file src/auto/config.cache " vim_cv_getcwd_broken=no vim_cv_memmove_handles_overlap=yes @@ -19,12 +19,12 @@ function configure() { run_configure_autotools --with-tlib=ncurses --with-features=small } -function build() { +build() { run_make } -function install() { +install() { run_make_install } -source ../.port_include.sh +. ../.port_include.sh diff --git a/ReadMe.md b/ReadMe.md index 5215961976..388d657b12 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -14,13 +14,15 @@ Roughly speaking, the goal is a marriage between the aesthetic of late-1990s pro If you like some of the same things, you are welcome to join the project. It would be great to one day change the above to say "this is a system by us, for us, based on the things we like." :^) -I regularly post raw hacking sessions and demos on [my YouTube channel](https://www.youtube.com/channel/UC3ts8coMP645hZw9JSD3pqQ). +I regularly post raw hacking sessions and demos on [my YouTube channel](https://www.youtube.com/c/AndreasKling/). + +Sometimes I write about about the system on [my github.io blog](https://awesomekling.github.io/). There's also a [Patreon](https://www.patreon.com/serenityos) if you would like to show some support that way. ## Screenshot -![Screenshot as of d727005](https://raw.githubusercontent.com/awesomekling/serenity/master/Meta/screenshot-d727005.png) +![Screenshot as of 191112e](https://raw.githubusercontent.com/SerenityOS/serenity/master/Meta/screenshot-191112e.png) ## Current features @@ -30,6 +32,7 @@ There's also a [Patreon](https://www.patreon.com/serenityos) if you would like t * IPv4 networking with ARP, TCP, UDP and ICMP * ext2 filesystem * Unix-like libc and userland +* POSIX signals * Shell with pipes and I/O redirection * mmap() * /proc filesystem @@ -43,17 +46,22 @@ There's also a [Patreon](https://www.patreon.com/serenityos) if you would like t * IRC client * DNS lookup * Desktop games: Minesweeper and Snake +* Ports system (needs more packages!) * Other stuff I can't think of right now... ## How do I build and run this? -Go into the Toolchain/ directory and run the **BuildIt.sh** script. Then source the **UseIt.sh** script to put the i686-pc-serenity toolchain in your $PATH. +Make sure you have all the dependencies installed: + +``` +sudo apt install libmpfr-dev libmpc-dev libgmp-dev e2fsprogs qemu-system-i386 qemu-utils +``` + +Go into the Toolchain/ directory and run the **BuildIt.sh** script. Then ***source*** the **UseIt.sh** script to put the i686-pc-serenity toolchain in your $PATH. Once you've done both of those, go into the Kernel directory, then run -**makeall.sh**, and if nothing breaks too much, take it for a spin by using -**run**. - -Otherwise, see the older [step-by-step guide to building Serenity](https://github.com/awesomekling/serenity/blob/master/Meta/BuildInstructions.md) +**./makeall.sh**, and if nothing breaks too much, take it for a spin by using +**./run**. ## IRC @@ -61,9 +69,14 @@ Come chat in `#serenityos` on the Freenode IRC network. ## Author -* **Andreas Kling** - [awesomekling](https://github.com/awesomekling) +* **Andreas Kling** - [awesomekling](https://twitter.com/awesomekling) + +## Contributors + * **Robin Burchell** - [rburchell](https://github.com/rburchell) +Feel free to append yourself here if you've made some sweet contributions. :) + ## License Serenity is licensed under a 2-clause BSD license. diff --git a/Servers/LookupServer/main.cpp b/Servers/LookupServer/main.cpp index 11e2ab49d0..3281ff7c57 100644 --- a/Servers/LookupServer/main.cpp +++ b/Servers/LookupServer/main.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -15,19 +16,19 @@ #include #include -#define T_A 1 -#define T_NS 2 +#define T_A 1 +#define T_NS 2 #define T_CNAME 5 -#define T_SOA 6 -#define T_PTR 12 -#define T_MX 15 +#define T_SOA 6 +#define T_PTR 12 +#define T_MX 15 -#define C_IN 1 +#define C_IN 1 -static Vector lookup(const String& hostname, bool& did_timeout, const String& DNS_IP); +static Vector lookup(const String& hostname, bool& did_timeout, const String& DNS_IP, unsigned short record_type); static String parse_dns_name(const byte*, int& offset, int max_offset); -int main(int argc, char**argv) +int main(int argc, char** argv) { (void)argc; (void)argv; @@ -36,10 +37,42 @@ int main(int argc, char**argv) auto config = CConfigFile::get_for_system("LookupServer"); dbgprintf("LookupServer: Using network config file at %s.\n", - config->file_name().characters()); + config->file_name().characters()); auto DNS_IP = config->read_entry("DNS", "IPAddress", "127.0.0.53"); - HashMap dns_cache; + dbgprintf("LookupServer: Loading hosts from /etc/hosts:\n"); + HashMap dns_custom_hostnames; + auto* file = fopen("/etc/hosts", "r"); + auto linebuf = ByteBuffer::create_uninitialized(256); + while (fgets((char*)linebuf.pointer(), linebuf.size(), file)) { + auto str_line = String::copy(linebuf); + auto fields = str_line.split('\t'); + + auto sections = fields[0].split('.'); + IPv4Address addr { + (byte)atoi(sections[0].characters()), + (byte)atoi(sections[1].characters()), + (byte)atoi(sections[2].characters()), + (byte)atoi(sections[3].characters()), + }; + int len = 0; + while ((fields[1][len++]) != -123) + ; + auto name = fields[1].substring(0, len - 3); + + dns_custom_hostnames.set(name, addr.to_string()); + + IPv4Address addr2 { + (byte)atoi(sections[3].characters()), + (byte)atoi(sections[2].characters()), + (byte)atoi(sections[1].characters()), + (byte)atoi(sections[0].characters()), + }; + auto sb = StringBuilder(); + sb.append(addr2.to_string()); + sb.append(".in-addr.arpa"); + dns_custom_hostnames.set(sb.to_string(), name); + } int server_fd = socket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0); if (server_fd < 0) { @@ -98,19 +131,34 @@ int main(int argc, char**argv) client_buffer[nrecv] = '\0'; - auto hostname = String(client_buffer, nrecv, Chomp); + char lookup_type = client_buffer[0]; + if (lookup_type != 'L' && lookup_type != 'R') { + dbgprintf("LookupServer: Invalid lookup_type '%c'\n", lookup_type); + close(client_fd); + continue; + } + auto hostname = String(client_buffer + 1, nrecv - 1, Chomp); dbgprintf("LookupServer: Got request for '%s' (using IP %s)\n", - hostname.characters(), - DNS_IP.view().characters()); + hostname.characters(), + DNS_IP.characters()); - Vector addresses; + Vector responses; - if (!hostname.is_empty()) { + for (auto& key : dns_custom_hostnames.keys()) { + dbgprintf("Known Hostname: %s\n", key.characters()); + } + if (dns_custom_hostnames.contains(hostname)) { + responses.append(dns_custom_hostnames.get(hostname)); + dbgprintf("LookupServer: Found preconfigured host (from /etc/hosts): %s\n", responses[0].characters()); + } else if (!hostname.is_empty()) { bool did_timeout; int retries = 3; do { did_timeout = false; - addresses = lookup(hostname, did_timeout, DNS_IP); + if (lookup_type == 'L') + responses = lookup(hostname, did_timeout, DNS_IP, T_A); + else if (lookup_type == 'R') + responses = lookup(hostname, did_timeout, DNS_IP, T_PTR); if (!did_timeout) break; } while (--retries); @@ -121,15 +169,15 @@ int main(int argc, char**argv) } } - if (addresses.is_empty()) { + if (responses.is_empty()) { int nsent = write(client_fd, "Not found.\n", sizeof("Not found.\n")); if (nsent < 0) perror("write"); close(client_fd); continue; } - for (auto& address : addresses) { - auto line = String::format("%s\n", address.to_string().characters()); + for (auto& response : responses) { + auto line = String::format("%s\n", response.characters()); int nsent = write(client_fd, line.characters(), line.length()); if (nsent < 0) { perror("write"); @@ -147,10 +195,8 @@ static word get_next_id() return ++s_next_id; } -Vector lookup(const String& hostname, bool& did_timeout, const String& DNS_IP) +Vector lookup(const String& hostname, bool& did_timeout, const String& DNS_IP, unsigned short record_type) { - // FIXME: First check if it's an IP address in a string! - DNSPacket request_header; request_header.set_id(get_next_id()); request_header.set_is_query(); @@ -170,7 +216,7 @@ Vector lookup(const String& hostname, bool& did_timeout, const Stri stream << part; } stream << '\0'; - stream << htons(T_A); + stream << htons(record_type); stream << htons(C_IN); stream.snip(); } @@ -178,15 +224,17 @@ Vector lookup(const String& hostname, bool& did_timeout, const Stri int fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { perror("socket"); - return { }; + return {}; } - struct timeval timeout { 1, 0 }; + struct timeval timeout { + 1, 0 + }; int rc = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); if (rc < 0) { perror("setsockopt"); close(fd); - return { }; + return {}; } struct sockaddr_in dst_addr; @@ -194,12 +242,12 @@ Vector lookup(const String& hostname, bool& did_timeout, const Stri dst_addr.sin_family = AF_INET; dst_addr.sin_port = htons(53); - rc = inet_pton(AF_INET, DNS_IP.view().characters(), &dst_addr.sin_addr); + rc = inet_pton(AF_INET, DNS_IP.characters(), &dst_addr.sin_addr); - int nsent = sendto(fd, buffer.pointer(), buffer.size(), 0,(const struct sockaddr *)&dst_addr, sizeof(dst_addr)); + int nsent = sendto(fd, buffer.pointer(), buffer.size(), 0, (const struct sockaddr*)&dst_addr, sizeof(dst_addr)); if (nsent < 0) { perror("sendto"); - return { }; + return {}; } ASSERT(nsent == buffer.size()); @@ -214,7 +262,7 @@ Vector lookup(const String& hostname, bool& did_timeout, const Stri perror("recvfrom"); } close(fd); - return { }; + return {}; } close(fd); @@ -222,7 +270,7 @@ Vector lookup(const String& hostname, bool& did_timeout, const Stri if (nrecv < (int)sizeof(DNSPacket)) { dbgprintf("LookupServer: Response not big enough (%d) to be a DNS packet :(\n", nrecv); - return { }; + return {}; } auto& response_header = *(DNSPacket*)(response_buffer); @@ -234,37 +282,46 @@ Vector lookup(const String& hostname, bool& did_timeout, const Stri if (response_header.id() != request_header.id()) { dbgprintf("LookupServer: ID mismatch (%u vs %u) :(\n", response_header.id(), request_header.id()); - return { }; + return {}; } if (response_header.question_count() != 1) { dbgprintf("LookupServer: Question count (%u vs %u) :(\n", response_header.question_count(), request_header.question_count()); - return { }; + return {}; } if (response_header.answer_count() < 1) { dbgprintf("LookupServer: Not enough answers (%u) :(\n", response_header.answer_count()); - return { }; + return {}; } int offset = 0; auto question = parse_dns_name((const byte*)response_header.payload(), offset, nrecv); offset += 4; - Vector addresses; + Vector addresses; for (word i = 0; i < response_header.answer_count(); ++i) { auto& record = *(const DNSRecord*)(&((const byte*)response_header.payload())[offset]); - auto ipv4_address = IPv4Address((const byte*)record.data()); - dbgprintf("LookupServer: Answer #%u: (question: %s), type=%u, ttl=%u, length=%u, data=%s\n", + dbgprintf("LookupServer: Answer #%u: (question: %s), type=%u, ttl=%u, length=%u, data=", i, question.characters(), record.type(), record.ttl(), - record.data_length(), - ipv4_address.to_string().characters()); + record.data_length()); offset += sizeof(DNSRecord) + record.data_length(); - if (record.type() == T_A) - addresses.append(ipv4_address); + if (record.type() == T_PTR) { + int dummy = 0; + auto name = parse_dns_name((const byte*)record.data(), dummy, record.data_length()); + dbgprintf("%s\n", name.characters()); + addresses.append(name); + } else if (record.type() == T_A) { + auto ipv4_address = IPv4Address((const byte*)record.data()); + dbgprintf("%s\n", ipv4_address.to_string().characters()); + addresses.append(ipv4_address.to_string()); + } else { + dbgprintf("(unimplemented)\n"); + dbgprintf("LookupServer: FIXME: Handle record type %u\n", record.type()); + } // FIXME: Parse some other record types perhaps? } diff --git a/Servers/SystemServer/.gitignore b/Servers/SystemServer/.gitignore new file mode 100644 index 0000000000..94be980e2b --- /dev/null +++ b/Servers/SystemServer/.gitignore @@ -0,0 +1,3 @@ +SystemServer +main.d +main.o diff --git a/Servers/SystemServer/main.cpp b/Servers/SystemServer/main.cpp index 06e9d70d8b..c908f665e9 100644 --- a/Servers/SystemServer/main.cpp +++ b/Servers/SystemServer/main.cpp @@ -1,12 +1,12 @@ +#include +#include +#include #include +#include #include #include -#include -#include -#include -#include -void start_process(const char *prog, int prio) +void start_process(const char* prog, int prio) { pid_t pid = 0; @@ -47,14 +47,14 @@ void start_process(const char *prog, int prio) } } -int main(int, char **) +int main(int, char**) { int lowest_prio = sched_get_priority_min(SCHED_OTHER); int highest_prio = sched_get_priority_max(SCHED_OTHER); start_process("/bin/LookupServer", lowest_prio); start_process("/bin/WindowServer", highest_prio); start_process("/bin/Taskbar", highest_prio); - start_process("/bin/Terminal", highest_prio-1); + start_process("/bin/Terminal", highest_prio - 1); start_process("/bin/Launcher", highest_prio); while (1) { diff --git a/Servers/WindowServer/WSAPITypes.h b/Servers/WindowServer/WSAPITypes.h index fe3a194cd5..0a1a6ea9a6 100644 --- a/Servers/WindowServer/WSAPITypes.h +++ b/Servers/WindowServer/WSAPITypes.h @@ -20,8 +20,7 @@ struct WSAPI_Rect { WSAPI_Size size; }; -enum WSAPI_WindowType -{ +enum WSAPI_WindowType { Invalid = 0, Normal, Menu, @@ -37,8 +36,7 @@ struct WSAPI_WindowBackingStoreInfo { RGBA32* pixels; }; -enum class WSAPI_MouseButton : unsigned char -{ +enum class WSAPI_MouseButton : unsigned char { NoButton = 0, Left = 1, Right = 2, @@ -46,16 +44,14 @@ enum class WSAPI_MouseButton : unsigned char }; struct WSAPI_KeyModifiers { - enum - { + enum { Shift = 1 << 0, Alt = 1 << 1, Ctrl = 1 << 2, }; }; -enum class WSAPI_StandardCursor : unsigned char -{ +enum class WSAPI_StandardCursor : unsigned char { None = 0, Arrow, IBeam, @@ -65,8 +61,7 @@ enum class WSAPI_StandardCursor : unsigned char ResizeDiagonalBLTR, }; -enum WSAPI_WMEventMask : unsigned -{ +enum WSAPI_WMEventMask : unsigned { WindowRectChanges = 1 << 0, WindowStateChanges = 1 << 1, WindowIconChanges = 1 << 2, @@ -74,8 +69,7 @@ enum WSAPI_WMEventMask : unsigned }; struct WSAPI_ServerMessage { - enum Type : unsigned - { + enum Type : unsigned { Invalid, Error, Paint, @@ -195,8 +189,7 @@ struct WSAPI_ServerMessage { }; struct WSAPI_ClientMessage { - enum Type : unsigned - { + enum Type : unsigned { Invalid, CreateMenubar, DestroyMenubar, @@ -232,6 +225,7 @@ struct WSAPI_ClientMessage { DismissMenu, SetWindowIcon, SetWindowHasAlphaChannel, + MoveWindowToFront, }; Type type { Invalid }; int window_id { -1 }; diff --git a/Servers/WindowServer/WSButton.cpp b/Servers/WindowServer/WSButton.cpp index bf26ffb552..f4dfb9f5da 100644 --- a/Servers/WindowServer/WSButton.cpp +++ b/Servers/WindowServer/WSButton.cpp @@ -1,9 +1,9 @@ +#include +#include +#include #include #include #include -#include -#include -#include WSButton::WSButton(WSWindowFrame& frame, Retained&& bitmap, Function&& on_click_handler) : on_click(move(on_click_handler)) diff --git a/Servers/WindowServer/WSCPUMonitor.cpp b/Servers/WindowServer/WSCPUMonitor.cpp index 1ba726c72d..71a3e6a234 100644 --- a/Servers/WindowServer/WSCPUMonitor.cpp +++ b/Servers/WindowServer/WSCPUMonitor.cpp @@ -1,8 +1,8 @@ #include #include #include -#include #include +#include WSCPUMonitor::WSCPUMonitor() : m_proc_all("/proc/all") @@ -10,7 +10,7 @@ WSCPUMonitor::WSCPUMonitor() if (!m_proc_all.open(CIODevice::OpenMode::ReadOnly)) ASSERT_NOT_REACHED(); - create_thread([] (void* context) -> int { + create_thread([](void* context) -> int { auto& monitor = *(WSCPUMonitor*)context; for (;;) { static unsigned last_busy; @@ -27,7 +27,8 @@ WSCPUMonitor::WSCPUMonitor() monitor.m_dirty = true; sleep(1); } - }, this); + }, + this); } void WSCPUMonitor::get_cpu_usage(unsigned& busy, unsigned& idle) @@ -65,8 +66,7 @@ void WSCPUMonitor::paint(Painter& painter, const Rect& rect) painter.draw_line( { rect.x() + i, rect.bottom() }, { rect.x() + i, (int)(rect.y() + (rect.height() - (cpu_usage * (float)rect.height()))) }, - Color::from_rgb(0xaa6d4b) - ); + Color::from_rgb(0xaa6d4b)); ++i; } } diff --git a/Servers/WindowServer/WSClientConnection.cpp b/Servers/WindowServer/WSClientConnection.cpp index c913cba1cd..830514e142 100644 --- a/Servers/WindowServer/WSClientConnection.cpp +++ b/Servers/WindowServer/WSClientConnection.cpp @@ -329,6 +329,18 @@ void WSClientConnection::handle_request(const WSAPIAddMenuSeparatorRequest& requ post_message(response); } +void WSClientConnection::handle_request(const WSAPIMoveWindowToFrontRequest& request) +{ + int window_id = request.window_id(); + auto it = m_windows.find(window_id); + if (it == m_windows.end()) { + post_error("WSAPIMoveWindowToFrontRequest: Bad window ID"); + return; + } + auto& window = *(*it).value; + WSWindowManager::the().move_to_front_and_make_active(window); +} + void WSClientConnection::handle_request(const WSAPISetWindowOpacityRequest& request) { int window_id = request.window_id(); @@ -343,7 +355,7 @@ void WSClientConnection::handle_request(const WSAPISetWindowOpacityRequest& requ void WSClientConnection::handle_request(const WSAPISetWallpaperRequest& request) { - WSCompositor::the().set_wallpaper(request.wallpaper(), [&] (bool success) { + WSCompositor::the().set_wallpaper(request.wallpaper(), [&](bool success) { WSAPI_ServerMessage response; response.type = WSAPI_ServerMessage::Type::DidSetWallpaper; response.value = success; @@ -552,7 +564,7 @@ void WSClientConnection::handle_request(const WSAPIInvalidateRectRequest& reques } auto& window = *(*it).value; for (int i = 0; i < request.rects().size(); ++i) - window.request_update(request.rects()[i].intersected({ { }, window.size() })); + window.request_update(request.rects()[i].intersected({ {}, window.size() })); } void WSClientConnection::handle_request(const WSAPIDidFinishPaintingNotification& request) @@ -786,6 +798,8 @@ void WSClientConnection::on_request(const WSAPIClientRequest& request) return handle_request(static_cast(request)); case WSEvent::APISetWindowHasAlphaChannelRequest: return handle_request(static_cast(request)); + case WSEvent::APIMoveWindowToFrontRequest: + return handle_request(static_cast(request)); default: break; } diff --git a/Servers/WindowServer/WSClientConnection.h b/Servers/WindowServer/WSClientConnection.h index e2d1025e8c..9f128f2586 100644 --- a/Servers/WindowServer/WSClientConnection.h +++ b/Servers/WindowServer/WSClientConnection.h @@ -80,6 +80,7 @@ private: void handle_request(const WSAPIPopupMenuRequest&); void handle_request(const WSAPIDismissMenuRequest&); void handle_request(const WSAPISetWindowHasAlphaChannelRequest&); + void handle_request(const WSAPIMoveWindowToFrontRequest&); void post_error(const String&); @@ -104,7 +105,7 @@ void WSClientConnection::for_each_window_matching(Matching matching, Callback ca { for (auto& it : m_windows) { if (matching(*it.value)) { - if (callback(*it.value) == IterationDecision::Abort) + if (callback(*it.value) == IterationDecision::Break) return; } } @@ -114,7 +115,7 @@ template void WSClientConnection::for_each_window(Callback callback) { for (auto& it : m_windows) { - if (callback(*it.value) == IterationDecision::Abort) + if (callback(*it.value) == IterationDecision::Break) return; } } diff --git a/Servers/WindowServer/WSCompositor.cpp b/Servers/WindowServer/WSCompositor.cpp index 32f8754d9f..1fc1e4c4f0 100644 --- a/Servers/WindowServer/WSCompositor.cpp +++ b/Servers/WindowServer/WSCompositor.cpp @@ -26,6 +26,7 @@ WallpaperMode mode_to_enum(const String& name) return WallpaperMode::Center; if (name == "scaled") return WallpaperMode::Scaled; + return WallpaperMode::Simple; } WSCompositor::WSCompositor() @@ -79,7 +80,7 @@ void WSCompositor::compose() dbgprintf("[WM] compose #%u (%u rects)\n", ++m_compose_count, dirty_rects.rects().size()); #endif - auto any_dirty_rect_intersects_window = [&dirty_rects] (const WSWindow& window) { + auto any_dirty_rect_intersects_window = [&dirty_rects](const WSWindow& window) { auto window_frame_rect = window.frame().rect(); for (auto& dirty_rect : dirty_rects.rects()) { if (dirty_rect.intersects(window_frame_rect)) @@ -96,22 +97,22 @@ void WSCompositor::compose() if (m_wallpaper_mode == WallpaperMode::Simple) { m_back_painter->blit(dirty_rect.location(), *m_wallpaper, dirty_rect); } else if (m_wallpaper_mode == WallpaperMode::Center) { - Point offset{ ws.size().width() / 2 - m_wallpaper->size().width() / 2, - ws.size().height() / 2 - m_wallpaper->size().height() / 2 }; + Point offset { ws.size().width() / 2 - m_wallpaper->size().width() / 2, + ws.size().height() / 2 - m_wallpaper->size().height() / 2 }; m_back_painter->blit_offset(dirty_rect.location(), *m_wallpaper, - dirty_rect, offset); + dirty_rect, offset); } else if (m_wallpaper_mode == WallpaperMode::Tile) { m_back_painter->blit_tiled(dirty_rect.location(), *m_wallpaper, dirty_rect); } else { - // FIXME: Does not work: offset rect creates trails. - m_back_painter->draw_scaled_bitmap(dirty_rect, *m_wallpaper, - { dirty_rect.location(), - m_wallpaper->size() }); + float hscale = (float)m_wallpaper->size().width() / (float)ws.size().width(); + float vscale = (float)m_wallpaper->size().height() / (float)ws.size().height(); + + m_back_painter->blit_scaled(dirty_rect, *m_wallpaper, dirty_rect, hscale, vscale); } } } - auto compose_window = [&] (WSWindow& window) -> IterationDecision { + auto compose_window = [&](WSWindow& window) -> IterationDecision { if (!any_dirty_rect_intersects_window(window)) return IterationDecision::Continue; PainterStateSaver saver(*m_back_painter); @@ -153,7 +154,7 @@ void WSCompositor::compose() if (auto* fullscreen_window = wm.active_fullscreen_window()) { compose_window(*fullscreen_window); } else { - wm.for_each_visible_window_from_back_to_front([&] (WSWindow& window) { + wm.for_each_visible_window_from_back_to_front([&](WSWindow& window) { return compose_window(window); }); @@ -233,7 +234,7 @@ bool WSCompositor::set_wallpaper(const String& path, Function&& call context->path = path; context->callback = move(callback); - int rc = create_thread([] (void* ctx) -> int { + int rc = create_thread([](void* ctx) -> int { OwnPtr context((Context*)ctx); context->bitmap = load_png(context->path); if (!context->bitmap) { @@ -241,13 +242,14 @@ bool WSCompositor::set_wallpaper(const String& path, Function&& call exit_thread(0); return 0; } - the().deferred_invoke([context = move(context)] (auto&) { + the().deferred_invoke([context = move(context)](auto&) { the().finish_setting_wallpaper(context->path, *context->bitmap); context->callback(true); }); exit_thread(0); return 0; - }, context.leak_ptr()); + }, + context.leak_ptr()); ASSERT(rc == 0); return true; @@ -274,7 +276,7 @@ void WSCompositor::set_resolution(int width, int height) auto screen_rect = WSScreen::the().rect(); if (screen_rect.width() == width && screen_rect.height() == height) return; - m_wallpaper_path = { }; + m_wallpaper_path = {}; m_wallpaper = nullptr; WSScreen::the().set_resolution(width, height); m_front_bitmap = GraphicsBitmap::create_wrapper(GraphicsBitmap::Format::RGB32, { width, height }, WSScreen::the().scanline(0)); @@ -302,7 +304,7 @@ void WSCompositor::draw_geometry_label() auto& wm = WSWindowManager::the(); auto* window_being_moved_or_resized = wm.m_drag_window ? wm.m_drag_window.ptr() : (wm.m_resize_window ? wm.m_resize_window.ptr() : nullptr); if (!window_being_moved_or_resized) { - m_last_geometry_label_rect = { }; + m_last_geometry_label_rect = {}; return; } auto geometry_string = window_being_moved_or_resized->rect().to_string(); @@ -339,7 +341,7 @@ void WSCompositor::draw_menubar() m_back_painter->fill_rect(menubar_rect, Color::LightGray); m_back_painter->draw_line({ 0, menubar_rect.bottom() }, { menubar_rect.right(), menubar_rect.bottom() }, Color::MidGray); int index = 0; - wm.for_each_active_menubar_menu([&] (WSMenu& menu) { + wm.for_each_active_menubar_menu([&](WSMenu& menu) { Color text_color = Color::Black; if (&menu == wm.current_menu()) { m_back_painter->fill_rect(menu.rect_in_menubar(), wm.menu_selection_color()); @@ -350,8 +352,7 @@ void WSCompositor::draw_menubar() menu.name(), index == 1 ? wm.app_menu_font() : wm.menu_font(), TextAlignment::CenterLeft, - text_color - ); + text_color); ++index; return true; }); diff --git a/Servers/WindowServer/WSCompositor.h b/Servers/WindowServer/WSCompositor.h index eb217d88a8..8f9c15f6da 100644 --- a/Servers/WindowServer/WSCompositor.h +++ b/Servers/WindowServer/WSCompositor.h @@ -10,8 +10,7 @@ class Painter; class WSCursor; -enum class WallpaperMode -{ +enum class WallpaperMode { Simple, Tile, Center, diff --git a/Servers/WindowServer/WSCursor.h b/Servers/WindowServer/WSCursor.h index e16eada5c7..889fdcdef1 100644 --- a/Servers/WindowServer/WSCursor.h +++ b/Servers/WindowServer/WSCursor.h @@ -2,8 +2,7 @@ #include -enum class WSStandardCursor -{ +enum class WSStandardCursor { None = 0, Arrow, IBeam, diff --git a/Servers/WindowServer/WSEvent.h b/Servers/WindowServer/WSEvent.h index 95276d642a..d94693f54f 100644 --- a/Servers/WindowServer/WSEvent.h +++ b/Servers/WindowServer/WSEvent.h @@ -11,8 +11,7 @@ class WSEvent : public CEvent { public: - enum Type - { + enum Type { Invalid = 2000, WM_DeferredCompose, WM_ClientDisconnected, @@ -64,6 +63,7 @@ public: APIGetWallpaperRequest, APISetWindowOverrideCursorRequest, APISetWindowHasAlphaChannelRequest, + APIMoveWindowToFrontRequest, WMAPISetActiveWindowRequest, WMAPISetWindowMinimizedRequest, WMAPIStartWindowResizeRequest, @@ -460,6 +460,20 @@ private: int m_window_id { 0 }; }; +class WSAPIMoveWindowToFrontRequest final : public WSAPIClientRequest { +public: + explicit WSAPIMoveWindowToFrontRequest(int client_id, int window_id) + : WSAPIClientRequest(WSEvent::APIMoveWindowToFrontRequest, client_id) + , m_window_id(window_id) + { + } + + int window_id() const { return m_window_id; } + +private: + int m_window_id { 0 }; +}; + class WSAPISetClipboardContentsRequest final : public WSAPIClientRequest { public: explicit WSAPISetClipboardContentsRequest(int client_id, int shared_buffer_id, int size) @@ -691,8 +705,7 @@ private: Vector m_rects; }; -enum class MouseButton : byte -{ +enum class MouseButton : byte { None = 0, Left = 1, Right = 2, diff --git a/Servers/WindowServer/WSEventLoop.cpp b/Servers/WindowServer/WSEventLoop.cpp index 976068fdcf..479b7defac 100644 --- a/Servers/WindowServer/WSEventLoop.cpp +++ b/Servers/WindowServer/WSEventLoop.cpp @@ -1,21 +1,21 @@ -#include -#include -#include -#include -#include -#include -#include -#include #include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include #include #include #include -#include -#include -#include //#define WSMESSAGELOOP_DEBUG @@ -104,7 +104,7 @@ static Vector get_rects(const WSAPI_ClientMessage& message, const Byte { Vector rects; if (message.rect_count > (WSAPI_ClientMessage::max_inline_rect_count + extra_data.size() / sizeof(WSAPI_Rect))) { - return { }; + return {}; } for (int i = 0; i < min(WSAPI_ClientMessage::max_inline_rect_count, message.rect_count); ++i) rects.append(message.rects[i]); @@ -217,19 +217,19 @@ bool WSEventLoop::on_receive_from_client(int client_id, const WSAPI_ClientMessag } post_event(client, - make(client_id, - message.window.rect, - String(message.text, message.text_length), - message.window.has_alpha_channel, - message.window.modal, - message.window.resizable, - message.window.fullscreen, - message.window.show_titlebar, - message.window.opacity, - message.window.base_size, - message.window.size_increment, - ws_window_type, - Color::from_rgba(message.window.background_color))); + make(client_id, + message.window.rect, + String(message.text, message.text_length), + message.window.has_alpha_channel, + message.window.modal, + message.window.resizable, + message.window.fullscreen, + message.window.show_titlebar, + message.window.opacity, + message.window.base_size, + message.window.size_increment, + ws_window_type, + Color::from_rgba(message.window.background_color))); break; } case WSAPI_ClientMessage::Type::DestroyWindow: @@ -309,6 +309,9 @@ bool WSEventLoop::on_receive_from_client(int client_id, const WSAPI_ClientMessag case WSAPI_ClientMessage::Type::WM_StartWindowResize: post_event(client, make(client_id, message.wm.client_id, message.wm.window_id)); break; + case WSAPI_ClientMessage::Type::MoveWindowToFront: + post_event(client, make(client_id, message.window_id)); + break; default: break; } @@ -317,7 +320,7 @@ bool WSEventLoop::on_receive_from_client(int client_id, const WSAPI_ClientMessag void WSEventLoop::add_file_descriptors_for_select(fd_set& fds, int& max_fd_added) { - auto add_fd_to_set = [&max_fd_added] (int fd, auto& set) { + auto add_fd_to_set = [&max_fd_added](int fd, auto& set) { FD_SET(fd, &set); if (fd > max_fd_added) max_fd_added = fd; @@ -325,7 +328,7 @@ void WSEventLoop::add_file_descriptors_for_select(fd_set& fds, int& max_fd_added add_fd_to_set(m_keyboard_fd, fds); add_fd_to_set(m_mouse_fd, fds); add_fd_to_set(m_server_fd, fds); - WSClientConnection::for_each_client([&] (WSClientConnection& client) { + WSClientConnection::for_each_client([&](WSClientConnection& client) { add_fd_to_set(client.fd(), fds); }); } @@ -338,7 +341,7 @@ void WSEventLoop::process_file_descriptors_after_select(const fd_set& fds) drain_keyboard(); if (FD_ISSET(m_mouse_fd, &fds)) drain_mouse(); - WSClientConnection::for_each_client([&] (WSClientConnection& client) { + WSClientConnection::for_each_client([&](WSClientConnection& client) { if (FD_ISSET(client.fd(), &fds)) drain_client(client); }); diff --git a/Servers/WindowServer/WSMenu.cpp b/Servers/WindowServer/WSMenu.cpp index 3d36316f30..92a246418a 100644 --- a/Servers/WindowServer/WSMenu.cpp +++ b/Servers/WindowServer/WSMenu.cpp @@ -1,16 +1,16 @@ #include "WSMenu.h" -#include "WSMenuItem.h" -#include "WSWindow.h" #include "WSEvent.h" #include "WSEventLoop.h" -#include "WSWindowManager.h" +#include "WSMenuItem.h" #include "WSScreen.h" -#include -#include +#include "WSWindow.h" +#include "WSWindowManager.h" #include +#include #include #include -#include +#include +#include WSMenu::WSMenu(WSClientConnection* client, int menu_id, const String& name) : m_client(client) @@ -115,7 +115,7 @@ void WSMenu::draw() ASSERT(menu_window()->backing_store()); Painter painter(*menu_window()->backing_store()); - Rect rect { { }, menu_window()->size() }; + Rect rect { {}, menu_window()->size() }; painter.fill_rect(rect.shrunken(6, 6), Color::LightGray); StylePainter::paint_window_frame(painter, rect); int width = this->width(); diff --git a/Servers/WindowServer/WSMenuBar.cpp b/Servers/WindowServer/WSMenuBar.cpp index 6d642d160d..5893a6b83d 100644 --- a/Servers/WindowServer/WSMenuBar.cpp +++ b/Servers/WindowServer/WSMenuBar.cpp @@ -11,4 +11,3 @@ WSMenuBar::WSMenuBar(WSClientConnection& client, int menubar_id) WSMenuBar::~WSMenuBar() { } - diff --git a/Servers/WindowServer/WSMenuItem.h b/Servers/WindowServer/WSMenuItem.h index 7b381386e7..0b29d361ba 100644 --- a/Servers/WindowServer/WSMenuItem.h +++ b/Servers/WindowServer/WSMenuItem.h @@ -8,8 +8,7 @@ class WSMenu; class WSMenuItem { public: - enum Type - { + enum Type { None, Text, Separator, diff --git a/Servers/WindowServer/WSScreen.cpp b/Servers/WindowServer/WSScreen.cpp index bfb23e46fd..3582687881 100644 --- a/Servers/WindowServer/WSScreen.cpp +++ b/Servers/WindowServer/WSScreen.cpp @@ -1,7 +1,7 @@ +#include "WSScreen.h" #include "WSCompositor.h" #include "WSEvent.h" #include "WSEventLoop.h" -#include "WSScreen.h" #include "WSWindowManager.h" #include #include @@ -39,7 +39,7 @@ void WSScreen::set_resolution(int width, int height) int width; int height; }; - BXVGAResolution resolution { (int)width, (int)height}; + BXVGAResolution resolution { (int)width, (int)height }; int rc = ioctl(m_framebuffer_fd, 1985, (int)&resolution); ASSERT(rc == 0); @@ -67,7 +67,7 @@ void WSScreen::on_receive_mouse_data(int dx, int dy, int dz, unsigned buttons) unsigned prev_buttons = m_mouse_button_state; m_mouse_button_state = buttons; unsigned changed_buttons = prev_buttons ^ buttons; - auto post_mousedown_or_mouseup_if_needed = [&] (MouseButton button) { + auto post_mousedown_or_mouseup_if_needed = [&](MouseButton button) { if (!(changed_buttons & (unsigned)button)) return; auto message = make(buttons & (unsigned)button ? WSEvent::MouseDown : WSEvent::MouseUp, m_cursor_location, buttons, button, m_modifiers); diff --git a/Servers/WindowServer/WSWindow.cpp b/Servers/WindowServer/WSWindow.cpp index a6a85ff79b..d478331649 100644 --- a/Servers/WindowServer/WSWindow.cpp +++ b/Servers/WindowServer/WSWindow.cpp @@ -1,7 +1,7 @@ #include "WSWindow.h" -#include "WSWindowManager.h" #include "WSEvent.h" #include "WSEventLoop.h" +#include "WSWindowManager.h" #include #include @@ -77,10 +77,14 @@ void WSWindow::set_rect(const Rect& rect) static WSAPI_MouseButton to_api(MouseButton button) { switch (button) { - case MouseButton::None: return WSAPI_MouseButton::NoButton; - case MouseButton::Left: return WSAPI_MouseButton::Left; - case MouseButton::Right: return WSAPI_MouseButton::Right; - case MouseButton::Middle: return WSAPI_MouseButton::Middle; + case MouseButton::None: + return WSAPI_MouseButton::NoButton; + case MouseButton::Left: + return WSAPI_MouseButton::Left; + case MouseButton::Right: + return WSAPI_MouseButton::Right; + case MouseButton::Middle: + return WSAPI_MouseButton::Middle; } ASSERT_NOT_REACHED(); } @@ -93,12 +97,23 @@ void WSWindow::handle_mouse_event(const WSMouseEvent& event) server_message.window_id = window_id(); switch (event.type()) { - case WSEvent::MouseMove: server_message.type = WSAPI_ServerMessage::Type::MouseMove; break; - case WSEvent::MouseDown: server_message.type = WSAPI_ServerMessage::Type::MouseDown; break; - case WSEvent::MouseDoubleClick: server_message.type = WSAPI_ServerMessage::Type::MouseDoubleClick; break; - case WSEvent::MouseUp: server_message.type = WSAPI_ServerMessage::Type::MouseUp; break; - case WSEvent::MouseWheel: server_message.type = WSAPI_ServerMessage::Type::MouseWheel; break; - default: ASSERT_NOT_REACHED(); + case WSEvent::MouseMove: + server_message.type = WSAPI_ServerMessage::Type::MouseMove; + break; + case WSEvent::MouseDown: + server_message.type = WSAPI_ServerMessage::Type::MouseDown; + break; + case WSEvent::MouseDoubleClick: + server_message.type = WSAPI_ServerMessage::Type::MouseDoubleClick; + break; + case WSEvent::MouseUp: + server_message.type = WSAPI_ServerMessage::Type::MouseUp; + break; + case WSEvent::MouseWheel: + server_message.type = WSAPI_ServerMessage::Type::MouseWheel; + break; + default: + ASSERT_NOT_REACHED(); } server_message.mouse.position = event.position(); @@ -134,7 +149,7 @@ void WSWindow::set_minimized(bool minimized) return; m_minimized = minimized; if (!minimized) - request_update({ { }, size() }); + request_update({ {}, size() }); invalidate(); WSWindowManager::the().notify_minimization_state_changed(*this); } @@ -151,6 +166,7 @@ void WSWindow::set_maximized(bool maximized) } else { set_rect(m_unmaximized_rect); } + m_frame.did_set_maximized({}, maximized); WSEventLoop::the().post_event(*this, make(old_rect, m_rect)); } @@ -290,7 +306,7 @@ void WSWindow::set_default_icon() void WSWindow::request_update(const Rect& rect) { if (m_pending_paint_rects.is_empty()) { - deferred_invoke([this] (auto&) { + deferred_invoke([this](auto&) { client()->post_paint_message(*this); }); } diff --git a/Servers/WindowServer/WSWindowFrame.cpp b/Servers/WindowServer/WSWindowFrame.cpp index d73112bc5d..da3ea26715 100644 --- a/Servers/WindowServer/WSWindowFrame.cpp +++ b/Servers/WindowServer/WSWindowFrame.cpp @@ -90,19 +90,20 @@ WSWindowFrame::WSWindowFrame(WSWindow& window) if (!s_unmaximize_button_bitmap) s_unmaximize_button_bitmap = &CharacterBitmap::create_from_ascii(s_unmaximize_button_bitmap_data, s_unmaximize_button_bitmap_width, s_unmaximize_button_bitmap_height).leak_ref(); - m_buttons.append(make(*this, *s_close_button_bitmap, [this] (auto&) { + m_buttons.append(make(*this, *s_close_button_bitmap, [this](auto&) { WSEvent close_request(WSEvent::WindowCloseRequest); m_window.event(close_request); })); if (window.is_resizable()) { - m_buttons.append(make(*this, *s_maximize_button_bitmap, [this] (auto& button) { + auto button = make(*this, *s_maximize_button_bitmap, [this](auto&) { m_window.set_maximized(!m_window.is_maximized()); - button.set_bitmap(m_window.is_maximized() ? *s_unmaximize_button_bitmap : *s_maximize_button_bitmap); - })); + }); + m_maximize_button = button.ptr(); + m_buttons.append(move(button)); } - m_buttons.append(make(*this, *s_minimize_button_bitmap, [this] (auto&) { + m_buttons.append(make(*this, *s_minimize_button_bitmap, [this](auto&) { m_window.set_minimized(true); })); } @@ -111,6 +112,12 @@ WSWindowFrame::~WSWindowFrame() { } +void WSWindowFrame::did_set_maximized(Badge, bool maximized) +{ + ASSERT(m_maximize_button); + m_maximize_button->set_bitmap(maximized ? *s_unmaximize_button_bitmap : *s_maximize_button_bitmap); +} + Rect WSWindowFrame::title_bar_rect() const { return { 3, 3, m_window.width(), window_titlebar_height }; @@ -152,7 +159,7 @@ void WSWindowFrame::paint(Painter& painter) auto titlebar_rect = title_bar_rect(); auto titlebar_icon_rect = title_bar_icon_rect(); auto titlebar_inner_rect = title_bar_text_rect(); - Rect outer_rect = { { }, rect().size() }; + Rect outer_rect = { {}, rect().size() }; auto titlebar_title_rect = titlebar_inner_rect; titlebar_title_rect.set_width(Font::default_bold_font().width(window.title())); @@ -214,9 +221,9 @@ static Rect frame_rect_for_window(WSWindow& window, const Rect& rect) switch (type) { case WSWindowType::Normal: return { rect.x() - 3, - rect.y() - window_titlebar_height - 4 + offset, - rect.width() + 6, - rect.height() + 7 + window_titlebar_height - offset }; + rect.y() - window_titlebar_height - 4 + offset, + rect.width() + 6, + rect.height() + 7 + window_titlebar_height - offset }; default: return rect; } @@ -241,7 +248,8 @@ void WSWindowFrame::notify_window_rect_changed(const Rect& old_rect, const Rect& { int window_button_width = 15; int window_button_height = 15; - int x = title_bar_text_rect().right() + 1;; + int x = title_bar_text_rect().right() + 1; + ; for (auto& button : m_buttons) { x -= window_button_width; Rect rect { x, 0, window_button_width, window_button_height }; @@ -290,7 +298,7 @@ void WSWindowFrame::on_mouse_event(const WSMouseEvent& event) { ResizeDirection::Left, ResizeDirection::None, ResizeDirection::Right }, { ResizeDirection::DownLeft, ResizeDirection::Down, ResizeDirection::DownRight }, }; - Rect outer_rect = { { }, rect().size() }; + Rect outer_rect = { {}, rect().size() }; ASSERT(outer_rect.contains(event.position())); int window_relative_x = event.x() - outer_rect.x(); int window_relative_y = event.y() - outer_rect.y(); diff --git a/Servers/WindowServer/WSWindowFrame.h b/Servers/WindowServer/WSWindowFrame.h index c004446870..dde43deae9 100644 --- a/Servers/WindowServer/WSWindowFrame.h +++ b/Servers/WindowServer/WSWindowFrame.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -24,7 +25,10 @@ public: Rect title_bar_icon_rect() const; Rect title_bar_text_rect() const; + void did_set_maximized(Badge, bool); + private: WSWindow& m_window; Vector> m_buttons; + WSButton* m_maximize_button { nullptr }; }; diff --git a/Servers/WindowServer/WSWindowManager.cpp b/Servers/WindowServer/WSWindowManager.cpp index 1c8f594f13..aba405aeab 100644 --- a/Servers/WindowServer/WSWindowManager.cpp +++ b/Servers/WindowServer/WSWindowManager.cpp @@ -1,3 +1,4 @@ +#include "WSWindowManager.h" #include "WSCompositor.h" #include "WSEventLoop.h" #include "WSMenu.h" @@ -5,7 +6,6 @@ #include "WSMenuItem.h" #include "WSScreen.h" #include "WSWindow.h" -#include "WSWindowManager.h" #include #include #include @@ -43,8 +43,8 @@ WSWindowManager::WSWindowManager() reload_config(false); struct AppMenuItem { - const char *binary_name; - const char *description; + const char* binary_name; + const char* description; }; Vector apps; @@ -65,10 +65,10 @@ WSWindowManager::WSWindowManager() m_system_menu->add_item(make(*m_system_menu, 100, "Reload WM Config File")); m_system_menu->add_item(make(*m_system_menu, WSMenuItem::Separator)); m_system_menu->add_item(make(*m_system_menu, 200, "About...")); - m_system_menu->on_item_activation = [this, apps] (WSMenuItem& item) { + m_system_menu->on_item_activation = [this, apps](WSMenuItem& item) { if (item.identifier() >= 1 && item.identifier() <= 1 + apps.size() - 1) { if (fork() == 0) { - const auto& bin = apps[item.identifier() -1].binary_name; + const auto& bin = apps[item.identifier() - 1].binary_name; execl(bin, bin, nullptr); ASSERT_NOT_REACHED(); } @@ -139,7 +139,7 @@ void WSWindowManager::reload_config(bool set_screen) if (set_screen) set_resolution(m_wm_config->read_num_entry("Screen", "Width", 1920), - m_wm_config->read_num_entry("Screen", "Height", 1080)); + m_wm_config->read_num_entry("Screen", "Height", 1080)); m_arrow_cursor = get_cursor("Arrow", { 2, 2 }); m_resize_horizontally_cursor = get_cursor("ResizeH"); @@ -199,19 +199,18 @@ void WSWindowManager::tick_clock() void WSWindowManager::set_resolution(int width, int height) { WSCompositor::the().set_resolution(width, height); - WSClientConnection::for_each_client([&] (WSClientConnection& client) { + WSClientConnection::for_each_client([&](WSClientConnection& client) { client.notify_about_new_screen_rect(WSScreen::the().rect()); }); if (m_wm_config) { dbgprintf("Saving resolution: %dx%d to config file at %s.\n", width, height, - m_wm_config->file_name().characters()); + m_wm_config->file_name().characters()); m_wm_config->write_num_entry("Screen", "Width", width); m_wm_config->write_num_entry("Screen", "Height", height); m_wm_config->sync(); } } - int WSWindowManager::menubar_menu_margin() const { return 16; @@ -238,7 +237,7 @@ void WSWindowManager::set_current_menubar(WSMenuBar* menubar) #endif Point next_menu_location { menubar_menu_margin() / 2, 0 }; int index = 0; - for_each_active_menubar_menu([&] (WSMenu& menu) { + for_each_active_menubar_menu([&](WSMenu& menu) { int text_width = index == 1 ? Font::default_bold_font().width(menu.name()) : font().width(menu.name()); menu.set_rect_in_menubar({ next_menu_location.x() - menubar_menu_margin() / 2, 0, text_width + menubar_menu_margin(), menubar_rect().height() - 1 }); menu.set_text_rect_in_menubar({ next_menu_location, { text_width, menubar_rect().height() } }); @@ -263,7 +262,7 @@ void WSWindowManager::add_window(WSWindow& window) m_switcher.refresh(); if (window.listens_to_wm_events()) { - for_each_window([&] (WSWindow& other_window) { + for_each_window([&](WSWindow& other_window) { if (&window != &other_window) { tell_wm_listener_about_window(window, other_window); tell_wm_listener_about_window_icon(window, other_window); @@ -297,7 +296,7 @@ void WSWindowManager::remove_window(WSWindow& window) if (m_switcher.is_visible() && window.type() != WSWindowType::WindowSwitcher) m_switcher.refresh(); - for_each_window_listening_to_wm_events([&window] (WSWindow& listener) { + for_each_window_listening_to_wm_events([&window](WSWindow& listener) { if (!(listener.wm_event_mask() & WSAPI_WMEventMask::WindowRemovals)) return IterationDecision::Continue; if (window.client()) @@ -332,7 +331,7 @@ void WSWindowManager::tell_wm_listener_about_window_icon(WSWindow& listener, WSW void WSWindowManager::tell_wm_listeners_window_state_changed(WSWindow& window) { - for_each_window_listening_to_wm_events([&] (WSWindow& listener) { + for_each_window_listening_to_wm_events([&](WSWindow& listener) { tell_wm_listener_about_window(listener, window); return IterationDecision::Continue; }); @@ -340,7 +339,7 @@ void WSWindowManager::tell_wm_listeners_window_state_changed(WSWindow& window) void WSWindowManager::tell_wm_listeners_window_icon_changed(WSWindow& window) { - for_each_window_listening_to_wm_events([&] (WSWindow& listener) { + for_each_window_listening_to_wm_events([&](WSWindow& listener) { tell_wm_listener_about_window_icon(listener, window); return IterationDecision::Continue; }); @@ -348,7 +347,7 @@ void WSWindowManager::tell_wm_listeners_window_icon_changed(WSWindow& window) void WSWindowManager::tell_wm_listeners_window_rect_changed(WSWindow& window) { - for_each_window_listening_to_wm_events([&] (WSWindow& listener) { + for_each_window_listening_to_wm_events([&](WSWindow& listener) { tell_wm_listener_about_window_rect(listener, window); return IterationDecision::Continue; }); @@ -388,9 +387,9 @@ void WSWindowManager::notify_minimization_state_changed(WSWindow& window) void WSWindowManager::pick_new_active_window() { - for_each_visible_window_of_type_from_front_to_back(WSWindowType::Normal, [&] (WSWindow& candidate) { + for_each_visible_window_of_type_from_front_to_back(WSWindowType::Normal, [&](WSWindow& candidate) { set_active_window(&candidate); - return IterationDecision::Abort; + return IterationDecision::Break; }); } @@ -427,7 +426,7 @@ void WSWindowManager::close_current_menu() void WSWindowManager::handle_menubar_mouse_event(const WSMouseEvent& event) { - for_each_active_menubar_menu([&] (WSMenu& menu) { + for_each_active_menubar_menu([&](WSMenu& menu) { if (menu.rect_in_menubar().contains(event.position())) { handle_menu_mouse_event(menu, event); return false; @@ -442,7 +441,8 @@ void WSWindowManager::start_window_drag(WSWindow& window, const WSMouseEvent& ev printf("[WM] Begin dragging WSWindow{%p}\n", &window); #endif move_to_front_and_make_active(window); - m_drag_window = window.make_weak_ptr();; + m_drag_window = window.make_weak_ptr(); + ; m_drag_origin = event.position(); m_drag_window_origin = window.position(); invalidate(window); @@ -472,7 +472,8 @@ void WSWindowManager::start_window_resize(WSWindow& window, const Point& positio printf("[WM] Begin resizing WSWindow{%p}\n", &window); #endif m_resizing_mouse_button = button; - m_resize_window = window.make_weak_ptr();; + m_resize_window = window.make_weak_ptr(); + ; m_resize_origin = position; m_resize_window_original_rect = window.rect(); @@ -501,11 +502,7 @@ bool WSWindowManager::process_ongoing_window_drag(WSMouseEvent& event, WSWindow* #if defined(DOUBLECLICK_DEBUG) dbgprintf("[WM] Click up became doubleclick!\n"); #endif - if (m_drag_window->is_maximized()) { - m_drag_window->set_maximized(false); - } else { - m_drag_window->set_maximized(true); - } + m_drag_window->set_maximized(!m_drag_window->is_maximized()); } } m_drag_window = nullptr; @@ -616,8 +613,8 @@ bool WSWindowManager::process_ongoing_window_resize(const WSMouseEvent& event, W return true; #ifdef RESIZE_DEBUG dbgprintf("[WM] Resizing [original: %s] now: %s\n", - m_resize_window_original_rect.to_string().characters(), - new_rect.to_string().characters()); + m_resize_window_original_rect.to_string().characters(), + new_rect.to_string().characters()); #endif m_resize_window->set_rect(new_rect); WSEventLoop::the().post_event(*m_resize_window, make(old_rect, new_rect)); @@ -632,9 +629,12 @@ void WSWindowManager::set_cursor_tracking_button(WSButton* button) CElapsedTimer& WSWindowManager::DoubleClickInfo::click_clock(MouseButton button) { switch (button) { - case MouseButton::Left: return m_left_click_clock; - case MouseButton::Right: return m_right_click_clock; - case MouseButton::Middle: return m_middle_click_clock; + case MouseButton::Left: + return m_left_click_clock; + case MouseButton::Right: + return m_right_click_clock; + case MouseButton::Middle: + return m_middle_click_clock; default: ASSERT_NOT_REACHED(); } @@ -716,7 +716,7 @@ void WSWindowManager::process_mouse_event(WSMouseEvent& event, WSWindow*& hovere for (auto* window = m_windows_in_order.tail(); window; window = window->prev()) { if (!window->global_cursor_tracking()) continue; - ASSERT(window->is_visible()); // Maybe this should be supported? Idk. Let's catch it and think about it later. + ASSERT(window->is_visible()); // Maybe this should be supported? Idk. Let's catch it and think about it later. ASSERT(!window->is_minimized()); // Maybe this should also be supported? Idk. windows_who_received_mouse_event_due_to_cursor_tracking.set(window); auto translated_event = event.translated(-window->position()); @@ -746,7 +746,7 @@ void WSWindowManager::process_mouse_event(WSMouseEvent& event, WSWindow*& hovere WSWindow* event_window_with_frame = nullptr; - for_each_visible_window_from_front_to_back([&] (WSWindow& window) { + for_each_visible_window_from_front_to_back([&](WSWindow& window) { auto window_frame_rect = window.frame().rect(); if (!window_frame_rect.contains(event.position())) return IterationDecision::Continue; @@ -760,12 +760,12 @@ void WSWindowManager::process_mouse_event(WSMouseEvent& event, WSWindow*& hovere if (!window.is_fullscreen() && m_keyboard_modifiers == Mod_Logo && event.type() == WSEvent::MouseDown && event.button() == MouseButton::Left) { hovered_window = &window; start_window_drag(window, event); - return IterationDecision::Abort; + return IterationDecision::Break; } if (window.is_resizable() && m_keyboard_modifiers == Mod_Logo && event.type() == WSEvent::MouseDown && event.button() == MouseButton::Right && !window.is_blocked_by_modal_window()) { hovered_window = &window; start_window_resize(window, event); - return IterationDecision::Abort; + return IterationDecision::Break; } } // Well okay, let's see if we're hitting the frame or the window inside the frame. @@ -778,13 +778,13 @@ void WSWindowManager::process_mouse_event(WSMouseEvent& event, WSWindow*& hovere auto translated_event = event.translated(-window.position()); deliver_mouse_event(window, translated_event); } - return IterationDecision::Abort; + return IterationDecision::Break; } // We are hitting the frame, pass the event along to WSWindowFrame. window.frame().on_mouse_event(event.translated(-window_frame_rect.location())); event_window_with_frame = &window; - return IterationDecision::Abort; + return IterationDecision::Break; }); if (event_window_with_frame != m_resize_candidate.ptr()) @@ -801,7 +801,7 @@ void WSWindowManager::clear_resize_candidate() bool WSWindowManager::any_opaque_window_contains_rect(const Rect& rect) { bool found_containing_window = false; - for_each_window([&] (WSWindow& window) { + for_each_window([&](WSWindow& window) { if (!window.is_visible()) return IterationDecision::Continue; if (window.is_minimized()) @@ -815,7 +815,7 @@ bool WSWindowManager::any_opaque_window_contains_rect(const Rect& rect) } if (window.frame().rect().contains(rect)) { found_containing_window = true; - return IterationDecision::Abort; + return IterationDecision::Break; } return IterationDecision::Continue; }); @@ -826,7 +826,7 @@ bool WSWindowManager::any_opaque_window_above_this_one_contains_rect(const WSWin { bool found_containing_window = false; bool checking = false; - for_each_visible_window_from_back_to_front([&] (WSWindow& window) { + for_each_visible_window_from_back_to_front([&](WSWindow& window) { if (&window == &a_window) { checking = true; return IterationDecision::Continue; @@ -843,7 +843,7 @@ bool WSWindowManager::any_opaque_window_above_this_one_contains_rect(const WSWin return IterationDecision::Continue; if (window.frame().rect().contains(rect)) { found_containing_window = true; - return IterationDecision::Abort; + return IterationDecision::Break; } return IterationDecision::Continue; }); @@ -853,7 +853,7 @@ bool WSWindowManager::any_opaque_window_above_this_one_contains_rect(const WSWin Rect WSWindowManager::menubar_rect() const { if (active_fullscreen_window()) - return { }; + return {}; return { 0, 0, WSScreen::the().rect().width(), 18 }; } @@ -1054,9 +1054,9 @@ Rect WSWindowManager::maximized_window_rect(const WSWindow& window) const rect.set_height(rect.height() - menubar_rect().height()); // Subtract taskbar window height if present - const_cast(this)->for_each_visible_window_of_type_from_back_to_front(WSWindowType::Taskbar, [&rect] (WSWindow& taskbar_window) { + const_cast(this)->for_each_visible_window_of_type_from_back_to_front(WSWindowType::Taskbar, [&rect](WSWindow& taskbar_window) { rect.set_height(rect.height() - taskbar_window.height()); - return IterationDecision::Abort; + return IterationDecision::Break; }); return rect; diff --git a/Servers/WindowServer/WSWindowManager.h b/Servers/WindowServer/WSWindowManager.h index 6c2fde241f..4ed5fe4860 100644 --- a/Servers/WindowServer/WSWindowManager.h +++ b/Servers/WindowServer/WSWindowManager.h @@ -29,8 +29,7 @@ class WSWindowSwitcher; class GraphicsBitmap; class WSButton; -enum class ResizeDirection -{ +enum class ResizeDirection { None, Left, UpLeft, @@ -268,12 +267,12 @@ IterationDecision WSWindowManager::for_each_visible_window_of_type_from_back_to_ do_highlight_window_at_end = true; continue; } - if (callback(*window) == IterationDecision::Abort) - return IterationDecision::Abort; + if (callback(*window) == IterationDecision::Break) + return IterationDecision::Break; } if (do_highlight_window_at_end) { - if (callback(*m_highlight_window) == IterationDecision::Abort) - return IterationDecision::Abort; + if (callback(*m_highlight_window) == IterationDecision::Break) + return IterationDecision::Break; } return IterationDecision::Continue; } @@ -281,14 +280,14 @@ IterationDecision WSWindowManager::for_each_visible_window_of_type_from_back_to_ template IterationDecision WSWindowManager::for_each_visible_window_from_back_to_front(Callback callback) { - if (for_each_visible_window_of_type_from_back_to_front(WSWindowType::Normal, callback) == IterationDecision::Abort) - return IterationDecision::Abort; - if (for_each_visible_window_of_type_from_back_to_front(WSWindowType::Taskbar, callback) == IterationDecision::Abort) - return IterationDecision::Abort; - if (for_each_visible_window_of_type_from_back_to_front(WSWindowType::Tooltip, callback) == IterationDecision::Abort) - return IterationDecision::Abort; - if (for_each_visible_window_of_type_from_back_to_front(WSWindowType::Menu, callback) == IterationDecision::Abort) - return IterationDecision::Abort; + if (for_each_visible_window_of_type_from_back_to_front(WSWindowType::Normal, callback) == IterationDecision::Break) + return IterationDecision::Break; + if (for_each_visible_window_of_type_from_back_to_front(WSWindowType::Taskbar, callback) == IterationDecision::Break) + return IterationDecision::Break; + if (for_each_visible_window_of_type_from_back_to_front(WSWindowType::Tooltip, callback) == IterationDecision::Break) + return IterationDecision::Break; + if (for_each_visible_window_of_type_from_back_to_front(WSWindowType::Menu, callback) == IterationDecision::Break) + return IterationDecision::Break; return for_each_visible_window_of_type_from_back_to_front(WSWindowType::WindowSwitcher, callback); } @@ -296,8 +295,8 @@ template IterationDecision WSWindowManager::for_each_visible_window_of_type_from_front_to_back(WSWindowType type, Callback callback, bool ignore_highlight) { if (!ignore_highlight && m_highlight_window && m_highlight_window->type() == type && m_highlight_window->is_visible()) { - if (callback(*m_highlight_window) == IterationDecision::Abort) - return IterationDecision::Abort; + if (callback(*m_highlight_window) == IterationDecision::Break) + return IterationDecision::Break; } for (auto* window = m_windows_in_order.tail(); window; window = window->prev()) { @@ -309,8 +308,8 @@ IterationDecision WSWindowManager::for_each_visible_window_of_type_from_front_to continue; if (!ignore_highlight && window == m_highlight_window) continue; - if (callback(*window) == IterationDecision::Abort) - return IterationDecision::Abort; + if (callback(*window) == IterationDecision::Break) + return IterationDecision::Break; } return IterationDecision::Continue; } @@ -318,14 +317,14 @@ IterationDecision WSWindowManager::for_each_visible_window_of_type_from_front_to template IterationDecision WSWindowManager::for_each_visible_window_from_front_to_back(Callback callback) { - if (for_each_visible_window_of_type_from_front_to_back(WSWindowType::WindowSwitcher, callback) == IterationDecision::Abort) - return IterationDecision::Abort; - if (for_each_visible_window_of_type_from_front_to_back(WSWindowType::Menu, callback) == IterationDecision::Abort) - return IterationDecision::Abort; - if (for_each_visible_window_of_type_from_front_to_back(WSWindowType::Taskbar, callback) == IterationDecision::Abort) - return IterationDecision::Abort; - if (for_each_visible_window_of_type_from_front_to_back(WSWindowType::Tooltip, callback) == IterationDecision::Abort) - return IterationDecision::Abort; + if (for_each_visible_window_of_type_from_front_to_back(WSWindowType::WindowSwitcher, callback) == IterationDecision::Break) + return IterationDecision::Break; + if (for_each_visible_window_of_type_from_front_to_back(WSWindowType::Menu, callback) == IterationDecision::Break) + return IterationDecision::Break; + if (for_each_visible_window_of_type_from_front_to_back(WSWindowType::Taskbar, callback) == IterationDecision::Break) + return IterationDecision::Break; + if (for_each_visible_window_of_type_from_front_to_back(WSWindowType::Tooltip, callback) == IterationDecision::Break) + return IterationDecision::Break; return for_each_visible_window_of_type_from_front_to_back(WSWindowType::Normal, callback); } @@ -335,7 +334,7 @@ void WSWindowManager::for_each_window_listening_to_wm_events(Callback callback) for (auto* window = m_windows_in_order.tail(); window; window = window->prev()) { if (!window->listens_to_wm_events()) continue; - if (callback(*window) == IterationDecision::Abort) + if (callback(*window) == IterationDecision::Break) return; } } @@ -344,7 +343,7 @@ template void WSWindowManager::for_each_window(Callback callback) { for (auto* window = m_windows_in_order.tail(); window; window = window->prev()) { - if (callback(*window) == IterationDecision::Abort) + if (callback(*window) == IterationDecision::Break) return; } } diff --git a/Servers/WindowServer/WSWindowSwitcher.cpp b/Servers/WindowServer/WSWindowSwitcher.cpp index 69a84ec81a..42554265df 100644 --- a/Servers/WindowServer/WSWindowSwitcher.cpp +++ b/Servers/WindowServer/WSWindowSwitcher.cpp @@ -1,9 +1,9 @@ -#include -#include -#include -#include #include #include +#include +#include +#include +#include static WSWindowSwitcher* s_the; @@ -70,8 +70,8 @@ void WSWindowSwitcher::on_key_event(const WSKeyEvent& event) void WSWindowSwitcher::draw() { Painter painter(*m_switcher_window->backing_store()); - painter.fill_rect({ { }, m_rect.size() }, Color::LightGray); - painter.draw_rect({ { }, m_rect.size() }, Color::DarkGray); + painter.fill_rect({ {}, m_rect.size() }, Color::LightGray); + painter.draw_rect({ {}, m_rect.size() }, Color::DarkGray); for (int index = 0; index < m_windows.size(); ++index) { auto& window = *m_windows.at(index); Rect item_rect { @@ -116,14 +116,15 @@ void WSWindowSwitcher::refresh() m_selected_index = 0; int window_count = 0; int longest_title_width = 0; - wm.for_each_visible_window_of_type_from_front_to_back(WSWindowType::Normal, [&] (WSWindow& window) { + wm.for_each_visible_window_of_type_from_front_to_back(WSWindowType::Normal, [&](WSWindow& window) { ++window_count; longest_title_width = max(longest_title_width, wm.font().width(window.title())); if (selected_window == &window) m_selected_index = m_windows.size(); m_windows.append(window.make_weak_ptr()); return IterationDecision::Continue; - }, true); + }, + true); if (m_windows.is_empty()) { hide(); return; diff --git a/Servers/WindowServer/WSWindowType.h b/Servers/WindowServer/WSWindowType.h index 5197046f2c..897e81f74e 100644 --- a/Servers/WindowServer/WSWindowType.h +++ b/Servers/WindowServer/WSWindowType.h @@ -1,7 +1,6 @@ #pragma once -enum class WSWindowType -{ +enum class WSWindowType { Invalid = 0, Normal, Menu, diff --git a/Servers/WindowServer/main.cpp b/Servers/WindowServer/main.cpp index d4e889c1f5..3a8aff5c40 100644 --- a/Servers/WindowServer/main.cpp +++ b/Servers/WindowServer/main.cpp @@ -1,8 +1,8 @@ +#include +#include +#include #include #include -#include -#include -#include #include #include @@ -22,7 +22,7 @@ int main(int, char**) auto wm_config = CConfigFile::get_for_app("WindowManager"); WSScreen screen(wm_config->read_num_entry("Screen", "Width", 1024), - wm_config->read_num_entry("Screen", "Height", 768)); + wm_config->read_num_entry("Screen", "Height", 768)); WSCompositor::the(); WSWindowManager window_manager; diff --git a/SharedGraphics/CharacterBitmap.cpp b/SharedGraphics/CharacterBitmap.cpp index 62f1f26677..ecfc550d19 100644 --- a/SharedGraphics/CharacterBitmap.cpp +++ b/SharedGraphics/CharacterBitmap.cpp @@ -14,4 +14,3 @@ Retained CharacterBitmap::create_from_ascii(const char* asciiDa { return adopt(*new CharacterBitmap(asciiData, width, height)); } - diff --git a/SharedGraphics/CharacterBitmap.h b/SharedGraphics/CharacterBitmap.h index ef0b0d5c5a..e86f88fca8 100644 --- a/SharedGraphics/CharacterBitmap.h +++ b/SharedGraphics/CharacterBitmap.h @@ -1,8 +1,8 @@ #pragma once #include "Size.h" -#include #include +#include class CharacterBitmap : public Retainable { public: @@ -22,4 +22,3 @@ private: const char* m_bits { nullptr }; Size m_size; }; - diff --git a/SharedGraphics/Color.cpp b/SharedGraphics/Color.cpp index c982261c7e..2b86b20f99 100644 --- a/SharedGraphics/Color.cpp +++ b/SharedGraphics/Color.cpp @@ -10,25 +10,63 @@ Color::Color(NamedColor named) } rgb; switch (named) { - case Black: rgb = { 0, 0, 0 }; break; - case White: rgb = { 255, 255, 255 }; break; - case Red: rgb = { 255, 0, 0}; break; - case Green: rgb = { 0, 255, 0}; break; - case Cyan: rgb = { 0, 255, 255 }; break; - case Blue: rgb = { 0, 0, 255}; break; - case Yellow: rgb = { 255, 255, 0 }; break; - case Magenta: rgb = { 255, 0, 255 }; break; - case DarkGray: rgb = { 64, 64, 64 }; break; - case MidGray: rgb = { 127, 127, 127 }; break; - case LightGray: rgb = { 192, 192, 192 }; break; - case MidGreen: rgb = { 0, 192, 0 }; break; - case MidBlue: rgb = { 0, 0, 192 }; break; - case MidRed: rgb = { 192, 0, 0 }; break; - case MidMagenta: rgb = { 192, 0, 192 }; break; - case DarkGreen: rgb = { 0, 128, 0 }; break; - case DarkBlue: rgb = { 0, 0, 128 }; break; - case DarkRed: rgb = { 128, 0, 0 }; break; - default: ASSERT_NOT_REACHED(); break; + case Black: + rgb = { 0, 0, 0 }; + break; + case White: + rgb = { 255, 255, 255 }; + break; + case Red: + rgb = { 255, 0, 0 }; + break; + case Green: + rgb = { 0, 255, 0 }; + break; + case Cyan: + rgb = { 0, 255, 255 }; + break; + case Blue: + rgb = { 0, 0, 255 }; + break; + case Yellow: + rgb = { 255, 255, 0 }; + break; + case Magenta: + rgb = { 255, 0, 255 }; + break; + case DarkGray: + rgb = { 64, 64, 64 }; + break; + case MidGray: + rgb = { 127, 127, 127 }; + break; + case LightGray: + rgb = { 192, 192, 192 }; + break; + case MidGreen: + rgb = { 0, 192, 0 }; + break; + case MidBlue: + rgb = { 0, 0, 192 }; + break; + case MidRed: + rgb = { 192, 0, 0 }; + break; + case MidMagenta: + rgb = { 192, 0, 192 }; + break; + case DarkGreen: + rgb = { 0, 128, 0 }; + break; + case DarkBlue: + rgb = { 0, 0, 128 }; + break; + case DarkRed: + rgb = { 128, 0, 0 }; + break; + default: + ASSERT_NOT_REACHED(); + break; } m_value = 0xff000000 | (rgb.r << 16) | (rgb.g << 8) | rgb.b; diff --git a/SharedGraphics/Color.h b/SharedGraphics/Color.h index 29116790c6..630771087f 100644 --- a/SharedGraphics/Color.h +++ b/SharedGraphics/Color.h @@ -33,10 +33,16 @@ public: MidMagenta, }; - Color() { } + Color() {} Color(NamedColor); - Color(byte r, byte g, byte b) : m_value(0xff000000 | (r << 16) | (g << 8) | b) { } - Color(byte r, byte g, byte b, byte a) : m_value((a << 24) | (r << 16) | (g << 8) | b) { } + Color(byte r, byte g, byte b) + : m_value(0xff000000 | (r << 16) | (g << 8) | b) + { + } + Color(byte r, byte g, byte b, byte a) + : m_value((a << 24) | (r << 16) | (g << 8) | b) + { + } static Color from_rgb(unsigned rgb) { return Color(rgb | 0xff000000); } static Color from_rgba(unsigned rgba) { return Color(rgba); } @@ -89,12 +95,30 @@ public: return Color(min(255.0, red() * 1.2), min(255.0, green() * 1.2), min(255.0, blue() * 1.2), alpha()); } + Color inverted() const + { + return Color(~red(), ~green(), ~blue()); + } + RGBA32 value() const { return m_value; } + bool operator==(const Color& other) const + { + return m_value == other.m_value; + } + + bool operator!=(const Color& other) const + { + return m_value != other.m_value; + } + String to_string() const; private: - explicit Color(RGBA32 rgba) : m_value(rgba) { } + explicit Color(RGBA32 rgba) + : m_value(rgba) + { + } RGBA32 m_value { 0 }; }; diff --git a/SharedGraphics/DisjointRectSet.cpp b/SharedGraphics/DisjointRectSet.cpp index 38221fea66..c3eacf275a 100644 --- a/SharedGraphics/DisjointRectSet.cpp +++ b/SharedGraphics/DisjointRectSet.cpp @@ -39,7 +39,7 @@ void DisjointRectSet::shatter() } output.append(r1); } -next_pass: + next_pass: swap(output, m_rects); - } while(pass_had_intersections); + } while (pass_had_intersections); } diff --git a/SharedGraphics/DisjointRectSet.h b/SharedGraphics/DisjointRectSet.h index 1c15eadbd9..197cb4c81b 100644 --- a/SharedGraphics/DisjointRectSet.h +++ b/SharedGraphics/DisjointRectSet.h @@ -5,9 +5,12 @@ class DisjointRectSet { public: - DisjointRectSet() { } - ~DisjointRectSet() { } - DisjointRectSet(DisjointRectSet&& other) : m_rects(move(other.m_rects)) { } + DisjointRectSet() {} + ~DisjointRectSet() {} + DisjointRectSet(DisjointRectSet&& other) + : m_rects(move(other.m_rects)) + { + } void add(const Rect&); @@ -23,4 +26,3 @@ private: Vector m_rects; }; - diff --git a/SharedGraphics/Font.cpp b/SharedGraphics/Font.cpp index 615677aa13..47baaa7163 100644 --- a/SharedGraphics/Font.cpp +++ b/SharedGraphics/Font.cpp @@ -1,15 +1,16 @@ #include "Font.h" -#include #include -#include #include -#include -#include -#include +#include +#include #include +#include #include +#include +#include -struct [[gnu::packed]] FontFileHeader { +struct [[gnu::packed]] FontFileHeader +{ char magic[4]; byte glyph_width; byte glyph_height; @@ -66,7 +67,7 @@ RetainPtr Font::clone() const return adopt(*new Font(m_name, new_rows, new_widths, m_fixed_width, m_glyph_width, m_glyph_height)); } -Font::Font(const String& name, unsigned* rows, byte* widths, bool is_fixed_width, byte glyph_width, byte glyph_height) +Font::Font(const StringView& name, unsigned* rows, byte* widths, bool is_fixed_width, byte glyph_width, byte glyph_height) : m_name(name) , m_rows(rows) , m_glyph_widths(widths) @@ -113,7 +114,7 @@ RetainPtr Font::load_from_memory(const byte* data) return adopt(*new Font(String(header.name), rows, widths, !header.is_variable_width, header.glyph_width, header.glyph_height)); } -RetainPtr Font::load_from_file(const String& path) +RetainPtr Font::load_from_file(const StringView& path) { MappedFile mapped_file(path); if (!mapped_file.is_valid()) @@ -124,7 +125,7 @@ RetainPtr Font::load_from_file(const String& path) return font; } -bool Font::write_to_file(const String& path) +bool Font::write_to_file(const StringView& path) { int fd = creat(path.characters(), 0644); if (fd < 0) { @@ -158,22 +159,17 @@ bool Font::write_to_file(const String& path) return true; } -int Font::width(const String& string) const +int Font::width(const StringView& string) const { - return width(string.characters(), string.length()); -} - -int Font::width(const char* characters, int length) const -{ - if (!length) + if (!string.length()) return 0; if (m_fixed_width) - return length * m_glyph_width; + return string.length() * m_glyph_width; int width = 0; - for (int i = 0; i < length; ++i) - width += glyph_width(characters[i]) + 1; + for (int i = 0; i < string.length(); ++i) + width += glyph_width(string.characters()[i]) + 1; return width - 1; } diff --git a/SharedGraphics/Font.h b/SharedGraphics/Font.h index 60ecd32ba4..85d91e3bea 100644 --- a/SharedGraphics/Font.h +++ b/SharedGraphics/Font.h @@ -1,15 +1,16 @@ #pragma once -#include -#include -#include #include #include +#include +#include #include +#include // FIXME: Make a MutableGlyphBitmap buddy class for FontEditor instead? class GlyphBitmap { friend class Font; + public: const unsigned* rows() const { return m_rows; } unsigned row(unsigned index) const { return m_rows[index]; } @@ -48,8 +49,8 @@ public: RetainPtr clone() const; - static RetainPtr load_from_file(const String& path); - bool write_to_file(const String& path); + static RetainPtr load_from_file(const StringView& path); + bool write_to_file(const StringView& path); ~Font(); @@ -60,11 +61,10 @@ public: byte min_glyph_width() const { return m_min_glyph_width; } byte max_glyph_width() const { return m_max_glyph_width; } byte glyph_spacing() const { return m_fixed_width ? 0 : 1; } - int width(const String& string) const; - int width(const char*, int) const; + int width(const StringView& string) const; String name() const { return m_name; } - void set_name(const String& name) { m_name = name; } + void set_name(const StringView& name) { m_name = name; } bool is_fixed_width() const { return m_fixed_width; } void set_fixed_width(bool b) { m_fixed_width = b; } @@ -76,7 +76,7 @@ public: } private: - Font(const String& name, unsigned* rows, byte* widths, bool is_fixed_width, byte glyph_width, byte glyph_height); + Font(const StringView& name, unsigned* rows, byte* widths, bool is_fixed_width, byte glyph_width, byte glyph_height); static RetainPtr load_from_memory(const byte*); diff --git a/SharedGraphics/GraphicsBitmap.cpp b/SharedGraphics/GraphicsBitmap.cpp index 027dbbdaa8..5d9b85b382 100644 --- a/SharedGraphics/GraphicsBitmap.cpp +++ b/SharedGraphics/GraphicsBitmap.cpp @@ -1,11 +1,11 @@ +#include #include #include -#include +#include +#include +#include #include #include -#include -#include -#include Retained GraphicsBitmap::create(Format format, const Size& size) { @@ -29,12 +29,12 @@ Retained GraphicsBitmap::create_wrapper(Format format, const Siz return adopt(*new GraphicsBitmap(format, size, data)); } -RetainPtr GraphicsBitmap::load_from_file(const String& path) +RetainPtr GraphicsBitmap::load_from_file(const StringView& path) { return load_png(path); } -RetainPtr GraphicsBitmap::load_from_file(Format format, const String& path, const Size& size) +RetainPtr GraphicsBitmap::load_from_file(Format format, const StringView& path, const Size& size) { MappedFile mapped_file(path); if (!mapped_file.is_valid()) @@ -83,11 +83,20 @@ GraphicsBitmap::~GraphicsBitmap() ASSERT(rc == 0); } m_data = nullptr; - delete [] m_palette; + delete[] m_palette; } -void GraphicsBitmap::set_mmap_name(const String& name) +void GraphicsBitmap::set_mmap_name(const StringView& name) { ASSERT(m_needs_munmap); ::set_mmap_name(m_data, size_in_bytes(), name.characters()); } + +void GraphicsBitmap::fill(Color color) +{ + ASSERT(m_format == GraphicsBitmap::Format::RGB32 || m_format == GraphicsBitmap::Format::RGBA32); + for (int y = 0; y < height(); ++y) { + auto* scanline = this->scanline(y); + fast_dword_fill(scanline, color.value(), width()); + } +} diff --git a/SharedGraphics/GraphicsBitmap.h b/SharedGraphics/GraphicsBitmap.h index a51565e177..162517de2e 100644 --- a/SharedGraphics/GraphicsBitmap.h +++ b/SharedGraphics/GraphicsBitmap.h @@ -3,20 +3,26 @@ #include "Color.h" #include "Rect.h" #include "Size.h" -#include -#include #include #include +#include +#include +#include #include class GraphicsBitmap : public Retainable { public: - enum class Format { Invalid, RGB32, RGBA32, Indexed8 }; + enum class Format { + Invalid, + RGB32, + RGBA32, + Indexed8 + }; static Retained create(Format, const Size&); static Retained create_wrapper(Format, const Size&, RGBA32*); - static RetainPtr load_from_file(const String& path); - static RetainPtr load_from_file(Format, const String& path, const Size&); + static RetainPtr load_from_file(const StringView& path); + static RetainPtr load_from_file(Format, const StringView& path, const Size&); static Retained create_with_shared_buffer(Format, Retained&&, const Size&); ~GraphicsBitmap(); @@ -33,28 +39,42 @@ public: size_t pitch() const { return m_pitch; } int shared_buffer_id() const { return m_shared_buffer ? m_shared_buffer->shared_buffer_id() : -1; } + void fill(Color); + bool has_alpha_channel() const { return m_format == Format::RGBA32; } Format format() const { return m_format; } - void set_mmap_name(const String&); + void set_mmap_name(const StringView&); size_t size_in_bytes() const { return m_pitch * m_size.height(); } Color palette_color(byte index) const { return Color::from_rgba(m_palette[index]); } void set_palette_color(byte index, Color color) { m_palette[index] = color.value(); } + template Color get_pixel(int x, int y) const { - switch (m_format) { - case Format::RGB32: - return Color::from_rgb(scanline(y)[x]); - case Format::RGBA32: - return Color::from_rgba(scanline(y)[x]); - case Format::Indexed8: - return Color::from_rgba(m_palette[bits(y)[x]]); - default: - ASSERT_NOT_REACHED(); - } + ASSERT_NOT_REACHED(); + } + + Color get_pixel(int x, int y) const; + + Color get_pixel(const Point& position) const + { + return get_pixel(position.x(), position.y()); + } + + template + void set_pixel(int x, int y, Color) + { + ASSERT_NOT_REACHED(); + } + + void set_pixel(int x, int y, Color); + + void set_pixel(const Point& position, Color color) + { + set_pixel(position.x(), position.y(), color); } private: @@ -92,3 +112,63 @@ inline byte* GraphicsBitmap::bits(int y) { return reinterpret_cast(scanline(y)); } + +template<> +inline Color GraphicsBitmap::get_pixel(int x, int y) const +{ + return Color::from_rgb(scanline(y)[x]); +} + +template<> +inline Color GraphicsBitmap::get_pixel(int x, int y) const +{ + return Color::from_rgba(scanline(y)[x]); +} + +template<> +inline Color GraphicsBitmap::get_pixel(int x, int y) const +{ + return Color::from_rgba(m_palette[bits(y)[x]]); +} + +inline Color GraphicsBitmap::get_pixel(int x, int y) const +{ + switch (m_format) { + case Format::RGB32: + return get_pixel(x, y); + case Format::RGBA32: + return get_pixel(x, y); + case Format::Indexed8: + return get_pixel(x, y); + default: + ASSERT_NOT_REACHED(); + } +} + +template<> +inline void GraphicsBitmap::set_pixel(int x, int y, Color color) +{ + scanline(y)[x] = color.value(); +} + +template<> +inline void GraphicsBitmap::set_pixel(int x, int y, Color color) +{ + scanline(y)[x] = color.value(); +} + +inline void GraphicsBitmap::set_pixel(int x, int y, Color color) +{ + switch (m_format) { + case Format::RGB32: + set_pixel(x, y, color); + break; + case Format::RGBA32: + set_pixel(x, y, color); + break; + case Format::Indexed8: + ASSERT_NOT_REACHED(); + default: + ASSERT_NOT_REACHED(); + } +} diff --git a/SharedGraphics/PNGLoader.cpp b/SharedGraphics/PNGLoader.cpp index 3238269d08..5f67149906 100644 --- a/SharedGraphics/PNGLoader.cpp +++ b/SharedGraphics/PNGLoader.cpp @@ -1,15 +1,15 @@ -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include -#include -#include -#include -#include -#include //#define PNG_STOPWATCH_DEBUG @@ -101,7 +101,7 @@ private: static RetainPtr load_png_impl(const byte*, int); static bool process_chunk(Streamer&, PNGLoadingContext& context); -RetainPtr load_png(const String& path) +RetainPtr load_png(const StringView& path) { MappedFile mapped_file(path); if (!mapped_file.is_valid()) @@ -125,7 +125,8 @@ RetainPtr load_png(const String& path) return c; } -union [[gnu::packed]] Pixel { +union [[gnu::packed]] Pixel +{ RGBA32 rgba { 0 }; byte v[4]; struct { @@ -186,7 +187,8 @@ template auto& x = pixels[i]; swap(x.r, x.b); Pixel a; - if (i != 0) a = pixels[i - 1]; + if (i != 0) + a = pixels[i - 1]; const Pixel& b = pixels_y_minus_1[i]; x.v[0] = x.v[0] + ((a.v[0] + b.v[0]) / 2); x.v[1] = x.v[1] + ((a.v[1] + b.v[1]) / 2); @@ -222,32 +224,37 @@ template { { #ifdef PNG_STOPWATCH_DEBUG - Stopwatch sw("load_png_impl: unfilter: unpack"); + Stopwatch sw("load_png_impl: unfilter: unpack"); #endif - // First unpack the scanlines to RGBA: - switch (context.color_type) { - case 2: - for (int y = 0; y < context.height; ++y) { - struct [[gnu::packed]] Triplet { byte r; byte g; byte b; }; - auto* triplets = (Triplet*)context.scanlines[y].data.pointer(); - for (int i = 0; i < context.width; ++i) { - auto& pixel = (Pixel&)context.bitmap->scanline(y)[i]; - pixel.r = triplets[i].r; - pixel.g = triplets[i].g; - pixel.b = triplets[i].b; - pixel.a = 0xff; + // First unpack the scanlines to RGBA: + switch (context.color_type) { + case 2: + for (int y = 0; y < context.height; ++y) { + struct [[gnu::packed]] Triplet + { + byte r; + byte g; + byte b; + }; + auto* triplets = (Triplet*)context.scanlines[y].data.pointer(); + for (int i = 0; i < context.width; ++i) { + auto& pixel = (Pixel&)context.bitmap->scanline(y)[i]; + pixel.r = triplets[i].r; + pixel.g = triplets[i].g; + pixel.b = triplets[i].b; + pixel.a = 0xff; + } } + break; + case 6: + for (int y = 0; y < context.height; ++y) { + memcpy(context.bitmap->scanline(y), context.scanlines[y].data.pointer(), context.scanlines[y].data.size()); + } + break; + default: + ASSERT_NOT_REACHED(); + break; } - break; - case 6: - for (int y = 0; y < context.height; ++y) { - memcpy(context.bitmap->scanline(y), context.scanlines[y].data.pointer(), context.scanlines[y].data.size()); - } - break; - default: - ASSERT_NOT_REACHED(); - break; - } } auto dummy_scanline = ByteBuffer::create_zeroed(context.width * sizeof(RGBA32)); @@ -405,7 +412,7 @@ static bool process_IHDR(const ByteBuffer& data, PNGLoadingContext& context) #endif context.decompression_buffer_size = (context.width * context.height * context.bytes_per_pixel + context.height); - context.decompression_buffer = (byte*)mmap(nullptr, context.decompression_buffer_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); + context.decompression_buffer = (byte*)mmap_with_name(nullptr, context.decompression_buffer_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0, "PNG decompression buffer"); return true; } diff --git a/SharedGraphics/PNGLoader.h b/SharedGraphics/PNGLoader.h index d4e7c0ef7f..7365977ce7 100644 --- a/SharedGraphics/PNGLoader.h +++ b/SharedGraphics/PNGLoader.h @@ -2,4 +2,4 @@ #include -RetainPtr load_png(const String& path); +RetainPtr load_png(const StringView& path); diff --git a/SharedGraphics/Painter.cpp b/SharedGraphics/Painter.cpp index 748963de38..31d505fc9e 100644 --- a/SharedGraphics/Painter.cpp +++ b/SharedGraphics/Painter.cpp @@ -1,13 +1,13 @@ #include "Painter.h" #include "Font.h" #include "GraphicsBitmap.h" -#include #include #include #include -#include -#include +#include #include +#include +#include #pragma GCC optimize("O3") @@ -89,7 +89,7 @@ void Painter::fill_rect_with_gradient(const Rect& a_rect, Color gradient_start, RGBA32* dst = m_target->scanline(clipped_rect.top()) + clipped_rect.left(); const size_t dst_skip = m_target->pitch() / sizeof(RGBA32); - float increment = (1.0/((rect.width())/255.0)); + float increment = (1.0 / ((rect.width()) / 255.0)); int r2 = gradient_start.red(); int g2 = gradient_start.green(); @@ -104,8 +104,8 @@ void Painter::fill_rect_with_gradient(const Rect& a_rect, Color gradient_start, dst[j] = Color( r1 / 255.0 * c + r2 / 255.0 * (255 - c), g1 / 255.0 * c + g2 / 255.0 * (255 - c), - b1 / 255.0 * c + b2 / 255.0 * (255 - c) - ).value(); + b1 / 255.0 * c + b2 / 255.0 * (255 - c)) + .value(); c += increment; } dst += dst_skip; @@ -204,6 +204,36 @@ void Painter::draw_bitmap(const Point& p, const GlyphBitmap& bitmap, Color color } } +void Painter::blit_scaled(const Rect& dst_rect_raw, const GraphicsBitmap& source, const Rect& src_rect, float hscale, float vscale) +{ + auto dst_rect = Rect(dst_rect_raw.location(), dst_rect_raw.size()).translated(translation()); + auto clipped_rect = dst_rect.intersected(clip_rect()); + if (clipped_rect.is_empty()) + return; + const int first_row = (clipped_rect.top() - dst_rect.top()); + const int last_row = (clipped_rect.bottom() - dst_rect.top()); + const int first_column = (clipped_rect.left() - dst_rect.left()); + RGBA32* dst = m_target->scanline(clipped_rect.y()) + clipped_rect.x(); + const size_t dst_skip = m_target->pitch() / sizeof(RGBA32); + + int x_start = first_column + src_rect.left(); + for (int row = first_row; row <= last_row; ++row) { + int sr = (row + src_rect.top()) * vscale; + if (sr >= source.size().height() || sr < 0) { + dst += dst_skip; + continue; + } + const RGBA32* sl = source.scanline(sr); + for (int x = x_start; x < clipped_rect.width() + x_start; ++x) { + int sx = x * hscale; + if (sx < source.size().width() && sx >= 0) + dst[x - x_start] = sl[sx]; + } + dst += dst_skip; + } + return; +} + void Painter::blit_with_opacity(const Point& position, const GraphicsBitmap& source, const Rect& src_rect, float opacity) { ASSERT(!m_target->has_alpha_channel()); @@ -289,7 +319,7 @@ void Painter::blit_tiled(const Point& position, const GraphicsBitmap& source, co int x_start = first_column + src_rect.left(); for (int row = first_row; row <= last_row; ++row) { const RGBA32* sl = source.scanline((row + src_rect.top()) - % source.size().height()); + % source.size().height()); for (int x = x_start; x < clipped_rect.width() + x_start; ++x) { dst[x - x_start] = sl[x % source.size().width()]; } @@ -302,9 +332,9 @@ void Painter::blit_tiled(const Point& position, const GraphicsBitmap& source, co } void Painter::blit_offset(const Point& position, - const GraphicsBitmap& source, - const Rect& src_rect, - const Point& offset) + const GraphicsBitmap& source, + const Rect& src_rect, + const Point& offset) { auto dst_rect = Rect(position, src_rect.size()).translated(translation()); auto clipped_rect = dst_rect.intersected(clip_rect()); @@ -483,17 +513,33 @@ void Painter::draw_scaled_bitmap(const Rect& a_dst_rect, const GraphicsBitmap& s if (source.has_alpha_channel()) { switch (source.format()) { - case GraphicsBitmap::Format::RGB32: do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel); break; - case GraphicsBitmap::Format::RGBA32: do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel); break; - case GraphicsBitmap::Format::Indexed8: do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel); break; - default: do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel); break; + case GraphicsBitmap::Format::RGB32: + do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel); + break; + case GraphicsBitmap::Format::RGBA32: + do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel); + break; + case GraphicsBitmap::Format::Indexed8: + do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel); + break; + default: + do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel); + break; } } else { switch (source.format()) { - case GraphicsBitmap::Format::RGB32: do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel); break; - case GraphicsBitmap::Format::RGBA32: do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel); break; - case GraphicsBitmap::Format::Indexed8: do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel); break; - default: do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel); break; + case GraphicsBitmap::Format::RGB32: + do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel); + break; + case GraphicsBitmap::Format::RGBA32: + do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel); + break; + case GraphicsBitmap::Format::Indexed8: + do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel); + break; + default: + do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel); + break; } } } @@ -508,18 +554,24 @@ void Painter::draw_scaled_bitmap(const Rect& a_dst_rect, const GraphicsBitmap& s draw_bitmap(point, font.glyph_bitmap(ch), color); } -void Painter::draw_text(const Rect& rect, const char* text, int length, const Font& font, TextAlignment alignment, Color color, TextElision elision) +void Painter::draw_text(const Rect& rect, const StringView& text, TextAlignment alignment, Color color, TextElision elision) { + draw_text(rect, text, font(), alignment, color, elision); +} + +void Painter::draw_text(const Rect& rect, const StringView& text, const Font& font, TextAlignment alignment, Color color, TextElision elision) +{ + StringView final_text(text); String elided_text; if (elision == TextElision::Right) { - int text_width = font.width(text, length); - if (font.width(text, length) > rect.width()) { + int text_width = font.width(final_text); + if (font.width(final_text) > rect.width()) { int glyph_spacing = font.glyph_spacing(); int new_length = 0; int new_width = font.width("..."); if (new_width < text_width) { - for (int i = 0; i < length; ++i) { - int glyph_width = font.glyph_width(text[i]); + for (int i = 0; i < final_text.length(); ++i) { + int glyph_width = font.glyph_width(final_text.characters()[i]); // NOTE: Glyph spacing should not be added after the last glyph on the line, // but since we are here because the last glyph does not actually fit on the line, // we don't have to worry about spacing. @@ -530,11 +582,10 @@ void Painter::draw_text(const Rect& rect, const char* text, int length, const Fo new_width += glyph_width + glyph_spacing; } StringBuilder builder; - builder.append(text, new_length); + builder.append(StringView(final_text.characters(), new_length)); builder.append("..."); elided_text = builder.to_string(); - text = elided_text.characters(); - length = elided_text.length(); + final_text = elided_text; } } } @@ -546,10 +597,10 @@ void Painter::draw_text(const Rect& rect, const char* text, int length, const Fo } else if (alignment == TextAlignment::CenterLeft) { point = { rect.x(), rect.center().y() - (font.glyph_height() / 2) }; } else if (alignment == TextAlignment::CenterRight) { - int text_width = font.width(text); + int text_width = font.width(final_text); point = { rect.right() - text_width, rect.center().y() - (font.glyph_height() / 2) }; } else if (alignment == TextAlignment::Center) { - int text_width = font.width(text); + int text_width = font.width(final_text); point = rect.center(); point.move_by(-(text_width / 2), -(font.glyph_height() / 2)); } else { @@ -557,8 +608,8 @@ void Painter::draw_text(const Rect& rect, const char* text, int length, const Fo } int space_width = font.glyph_width(' ') + font.glyph_spacing(); - for (ssize_t i = 0; i < length; ++i) { - char ch = text[i]; + for (ssize_t i = 0; i < final_text.length(); ++i) { + char ch = final_text.characters()[i]; if (ch == ' ') { point.move_by(space_width, 0); continue; @@ -568,21 +619,6 @@ void Painter::draw_text(const Rect& rect, const char* text, int length, const Fo } } -void Painter::draw_text(const Rect& rect, const String& text, TextAlignment alignment, Color color, TextElision elision) -{ - draw_text(rect, text.characters(), text.length(), alignment, color, elision); -} - -void Painter::draw_text(const Rect& rect, const String& text, const Font& font, TextAlignment alignment, Color color, TextElision elision) -{ - draw_text(rect, text.characters(), text.length(), font, alignment, color, elision); -} - -void Painter::draw_text(const Rect& rect, const char* text, int length, TextAlignment alignment, Color color, TextElision elision) -{ - draw_text(rect, text, length, font(), alignment, color, elision); -} - void Painter::set_pixel(const Point& p, Color color) { auto point = p; diff --git a/SharedGraphics/Painter.h b/SharedGraphics/Painter.h index a9ca1750ac..ac92a2fe34 100644 --- a/SharedGraphics/Painter.h +++ b/SharedGraphics/Painter.h @@ -4,9 +4,9 @@ #include "Point.h" #include "Rect.h" #include "Size.h" +#include #include #include -#include class CharacterBitmap; class GlyphBitmap; @@ -29,18 +29,19 @@ public: void blit_dimmed(const Point&, const GraphicsBitmap&, const Rect& src_rect); void blit_tiled(const Point&, const GraphicsBitmap&, const Rect& src_rect); void blit_offset(const Point&, const GraphicsBitmap&, const Rect& src_rect, const Point&); - void blit_scaled(const Point&, const GraphicsBitmap&, const Rect& src_rect, const Size&); - void draw_text(const Rect&, const char* text, int length, const Font&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None); - void draw_text(const Rect&, const char* text, int length, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None); - void draw_text(const Rect&, const String&, const Font&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None); - void draw_text(const Rect&, const String&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None); + void blit_scaled(const Rect&, const GraphicsBitmap&, const Rect&, float, float); + void draw_text(const Rect&, const StringView&, const Font&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None); + void draw_text(const Rect&, const StringView&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None); void draw_glyph(const Point&, char, Color); void draw_glyph(const Point&, char, const Font&, Color); const Font& font() const { return *state().font; } void set_font(const Font& font) { state().font = &font; } - enum class DrawOp { Copy, Xor }; + enum class DrawOp { + Copy, + Xor + }; void set_draw_op(DrawOp op) { state().draw_op = op; } DrawOp draw_op() const { return state().draw_op; } @@ -56,7 +57,11 @@ public: GraphicsBitmap* target() { return m_target.ptr(); } void save() { m_state_stack.append(m_state_stack.last()); } - void restore() { ASSERT(m_state_stack.size() > 1); m_state_stack.take_last(); } + void restore() + { + ASSERT(m_state_stack.size() > 1); + m_state_stack.take_last(); + } protected: void set_pixel_with_draw_op(dword& pixel, const Color&); diff --git a/SharedGraphics/Point.h b/SharedGraphics/Point.h index b9fa85d994..0530da9adb 100644 --- a/SharedGraphics/Point.h +++ b/SharedGraphics/Point.h @@ -7,8 +7,12 @@ struct WSAPI_Point; class Point { public: - Point() { } - Point(int x, int y) : m_x(x) , m_y(y) { } + Point() {} + Point(int x, int y) + : m_x(x) + , m_y(y) + { + } Point(const WSAPI_Point&); int x() const { return m_x; } diff --git a/SharedGraphics/Rect.cpp b/SharedGraphics/Rect.cpp index 1f14918cd1..213d18ead9 100644 --- a/SharedGraphics/Rect.cpp +++ b/SharedGraphics/Rect.cpp @@ -9,8 +9,8 @@ void Rect::intersect(const Rect& other) int b = min(bottom(), other.bottom()); if (l > r || t > b) { - m_location = { }; - m_size = { }; + m_location = {}; + m_size = {}; return; } diff --git a/SharedGraphics/Rect.h b/SharedGraphics/Rect.h index de600a4e77..3fcc8649a1 100644 --- a/SharedGraphics/Rect.h +++ b/SharedGraphics/Rect.h @@ -9,7 +9,7 @@ struct WSAPI_Rect; class Rect { public: - Rect() { } + Rect() {} Rect(int x, int y, int width, int height) : m_location(x, y) , m_size(width, height) diff --git a/SharedGraphics/Size.h b/SharedGraphics/Size.h index 77638cca2f..e38c47e66d 100644 --- a/SharedGraphics/Size.h +++ b/SharedGraphics/Size.h @@ -6,8 +6,12 @@ struct WSAPI_Size; class Size { public: - Size() { } - Size(int w, int h) : m_width(w), m_height(h) { } + Size() {} + Size(int w, int h) + : m_width(w) + , m_height(h) + { + } Size(const WSAPI_Size&); bool is_null() const { return !m_width && !m_height; } @@ -23,8 +27,7 @@ public: bool operator==(const Size& other) const { - return m_width == other.m_width && - m_height == other.m_height; + return m_width == other.m_width && m_height == other.m_height; } bool operator!=(const Size& other) const @@ -54,4 +57,3 @@ private: int m_width { 0 }; int m_height { 0 }; }; - diff --git a/SharedGraphics/StylePainter.cpp b/SharedGraphics/StylePainter.cpp index bf08fbdb57..9b15282175 100644 --- a/SharedGraphics/StylePainter.cpp +++ b/SharedGraphics/StylePainter.cpp @@ -1,5 +1,5 @@ -#include #include +#include void StylePainter::paint_tab_button(Painter& painter, const Rect& rect, bool active, bool hovered, bool enabled) { @@ -25,9 +25,21 @@ void StylePainter::paint_tab_button(Painter& painter, const Rect& rect, bool act painter.set_pixel({ 1, 1 }, highlight_color2); // Right side - painter.draw_line({ rect.width() - 1, 2, }, { rect.width() - 1, rect.height() - 1 }, shadow_color2); - painter.draw_line({ rect.width() - 2, 2, }, { rect.width() - 2, rect.height() - 1 }, shadow_color1); - painter.set_pixel({ rect.width() - 2, 1, }, shadow_color2); + painter.draw_line({ + rect.width() - 1, + 2, + }, + { rect.width() - 1, rect.height() - 1 }, shadow_color2); + painter.draw_line({ + rect.width() - 2, + 2, + }, + { rect.width() - 2, rect.height() - 1 }, shadow_color1); + painter.set_pixel({ + rect.width() - 2, + 1, + }, + shadow_color2); } static void paint_button_new(Painter& painter, const Rect& rect, bool pressed, bool checked, bool hovered, bool enabled) @@ -52,11 +64,11 @@ static void paint_button_new(Painter& painter, const Rect& rect, bool pressed, b // Base painter.fill_rect({ 1, 1, rect.width() - 2, rect.height() - 2 }, button_color); - painter.draw_rect({ { }, rect.size() }, shadow_color2); + painter.draw_rect({ {}, rect.size() }, shadow_color2); // Sunken shadow painter.draw_line({ 1, 1 }, { rect.width() - 2, 1 }, shadow_color1); - painter.draw_line({ 1, 2 }, {1, rect.height() - 2 }, shadow_color1); + painter.draw_line({ 1, 2 }, { 1, rect.height() - 2 }, shadow_color1); } else { // Base painter.fill_rect({ 1, 1, rect.width() - 3, rect.height() - 3 }, button_color); @@ -96,7 +108,7 @@ void StylePainter::paint_button(Painter& painter, const Rect& rect, ButtonStyle // Sunken shadow painter.draw_line({ 1, 1 }, { rect.width() - 2, 1 }, shadow_color); - painter.draw_line({ 1, 2 }, {1, rect.height() - 2 }, shadow_color); + painter.draw_line({ 1, 2 }, { 1, rect.height() - 2 }, shadow_color); // Bottom highlight painter.draw_line({ rect.width() - 2, 1 }, { rect.width() - 2, rect.height() - 3 }, highlight_color); @@ -214,4 +226,3 @@ void StylePainter::paint_window_frame(Painter& painter, const Rect& rect) painter.draw_line(rect.bottom_left().translated(1, -1), rect.bottom_right().translated(-1, -1), mid_shade); painter.draw_line(rect.bottom_left().translated(2, -2), rect.bottom_right().translated(-2, -2), base_color); } - diff --git a/SharedGraphics/StylePainter.h b/SharedGraphics/StylePainter.h index 12aab47932..996c63c62f 100644 --- a/SharedGraphics/StylePainter.h +++ b/SharedGraphics/StylePainter.h @@ -3,9 +3,23 @@ class Painter; class Rect; -enum class ButtonStyle { Normal, CoolBar }; -enum class FrameShadow { Plain, Raised, Sunken }; -enum class FrameShape { NoFrame, Box, Container, Panel, VerticalLine, HorizontalLine }; +enum class ButtonStyle { + Normal, + CoolBar +}; +enum class FrameShadow { + Plain, + Raised, + Sunken +}; +enum class FrameShape { + NoFrame, + Box, + Container, + Panel, + VerticalLine, + HorizontalLine +}; class StylePainter { public: diff --git a/SharedGraphics/TextAlignment.h b/SharedGraphics/TextAlignment.h index 9f77c67179..bd9d61ac73 100644 --- a/SharedGraphics/TextAlignment.h +++ b/SharedGraphics/TextAlignment.h @@ -1,6 +1,11 @@ #pragma once -enum class TextAlignment { TopLeft, CenterLeft, Center, CenterRight }; +enum class TextAlignment { + TopLeft, + CenterLeft, + Center, + CenterRight +}; inline bool is_right_text_alignment(TextAlignment alignment) { diff --git a/SharedGraphics/TextElision.h b/SharedGraphics/TextElision.h index ecd97cd452..c5c8032b02 100644 --- a/SharedGraphics/TextElision.h +++ b/SharedGraphics/TextElision.h @@ -4,4 +4,3 @@ enum class TextElision { None, Right, }; - diff --git a/SharedGraphics/puff.h b/SharedGraphics/puff.h index e23a245431..50beef92a1 100644 --- a/SharedGraphics/puff.h +++ b/SharedGraphics/puff.h @@ -21,15 +21,14 @@ Mark Adler madler@alumni.caltech.edu */ - /* * See puff.c for purpose and usage. */ #ifndef NIL -# define NIL ((unsigned char *)0) /* for no output option */ +# define NIL ((unsigned char*)0) /* for no output option */ #endif -int puff(unsigned char *dest, /* pointer to destination pointer */ - unsigned long *destlen, /* amount of output space */ - const unsigned char *source, /* pointer to source data pointer */ - unsigned long *sourcelen); /* amount of input available */ +int puff(unsigned char* dest, /* pointer to destination pointer */ + unsigned long* destlen, /* amount of output space */ + const unsigned char* source, /* pointer to source data pointer */ + unsigned long* sourcelen); /* amount of input available */ diff --git a/Shell/LineEditor.cpp b/Shell/LineEditor.cpp index 547960858e..78b70794a4 100644 --- a/Shell/LineEditor.cpp +++ b/Shell/LineEditor.cpp @@ -1,8 +1,8 @@ #include "LineEditor.h" #include "GlobalState.h" +#include #include #include -#include LineEditor::LineEditor() { diff --git a/Shell/LineEditor.h b/Shell/LineEditor.h index 2de7d52e14..da01c435af 100644 --- a/Shell/LineEditor.h +++ b/Shell/LineEditor.h @@ -28,8 +28,7 @@ private: int m_history_cursor { 0 }; int m_history_capacity { 100 }; - enum class InputState - { + enum class InputState { Free, ExpectBracket, ExpectFinal, diff --git a/Shell/Parser.cpp b/Shell/Parser.cpp index d49027714b..dd85237fda 100644 --- a/Shell/Parser.cpp +++ b/Shell/Parser.cpp @@ -19,7 +19,7 @@ void Parser::commit_subcommand() { if (m_tokens.is_empty()) return; - m_subcommands.append({ move(m_tokens), move(m_redirections) }); + m_subcommands.append({ move(m_tokens), move(m_redirections), {} }); } void Parser::do_pipe() @@ -52,7 +52,7 @@ Vector Parser::parse() commit_token(); if (m_tokens.is_empty()) { fprintf(stderr, "Syntax error: Nothing before pipe (|)\n"); - return { }; + return {}; } do_pipe(); break; @@ -110,7 +110,7 @@ Vector Parser::parse() commit_token(); if (m_tokens.is_empty()) { fprintf(stderr, "Syntax error: Nothing before pipe (|)\n"); - return { }; + return {}; } do_pipe(); m_state = State::Free; @@ -145,7 +145,7 @@ Vector Parser::parse() for (auto& redirection : m_subcommands.last().redirections) { if (redirection.type == Redirection::Pipe) { fprintf(stderr, "Syntax error: Nothing after last pipe (|)\n"); - return { }; + return {}; } } } diff --git a/Shell/Parser.h b/Shell/Parser.h index 4f3bde4a7f..294a7ec63a 100644 --- a/Shell/Parser.h +++ b/Shell/Parser.h @@ -4,13 +4,11 @@ #include struct Redirection { - enum Type - { + enum Type { Pipe, FileWrite, FileWriteAppend, FileRead, - Rewire }; Type type; int fd { -1 }; @@ -18,9 +16,15 @@ struct Redirection { String path {}; }; +struct Rewiring { + int fd { -1 }; + int rewire_fd { -1 }; +}; + struct Subcommand { Vector args; Vector redirections; + Vector rewirings; }; class Parser { @@ -39,8 +43,7 @@ private: void begin_redirect_read(int fd); void begin_redirect_write(int fd); - enum State - { + enum State { Free, InSingleQuotes, InDoubleQuotes, diff --git a/Shell/main.cpp b/Shell/main.cpp index bd5e9858dd..a2f8080165 100644 --- a/Shell/main.cpp +++ b/Shell/main.cpp @@ -2,6 +2,7 @@ #include "LineEditor.h" #include "Parser.h" #include +#include #include #include #include @@ -189,10 +190,10 @@ static bool handle_builtin(int argc, char** argv, int& retval) return false; } -class FileDescriptorCollector { +class FileDescriptionCollector { public: - FileDescriptorCollector() { } - ~FileDescriptorCollector() { collect(); } + FileDescriptionCollector() {} + ~FileDescriptionCollector() { collect(); } void collect() { @@ -219,42 +220,108 @@ struct CommandTimer { CElapsedTimer timer; }; +static bool is_glob(const StringView& s) +{ + for (int i = 0; i < s.length(); i++) { + char c = s.characters()[i]; + if (c == '*' || c == '?') + return true; + } + return false; +} + +static Vector split_path(const StringView &path) +{ + Vector parts; + + ssize_t substart = 0; + for (ssize_t i = 0; i < path.length(); i++) { + char ch = path.characters()[i]; + if (ch != '/') + continue; + ssize_t sublen = i - substart; + if (sublen != 0) + parts.append(path.substring_view(substart, sublen)); + parts.append(path.substring_view(i, 1)); + substart = i + 1; + } + + ssize_t taillen = path.length() - substart; + if (taillen != 0) + parts.append(path.substring_view(substart, taillen)); + + return parts; +} + +static Vector expand_globs(const StringView& path, const StringView& base) +{ + auto parts = split_path(path); + + StringBuilder builder; + builder.append(base); + Vector res; + + for (int i = 0; i < parts.size(); ++i) { + auto& part = parts[i]; + if (!is_glob(part)) { + builder.append(part); + continue; + } + + // Found a glob. + String new_base = builder.to_string(); + StringView new_base_v = new_base; + if (new_base_v.is_empty()) + new_base_v = "."; + CDirIterator di(new_base_v, CDirIterator::NoFlags); + + if (di.has_error()) { + return res; + } + + while (di.has_next()) { + String name = di.next_path(); + + // Dotfiles have to be explicitly requested + if (name[0] == '.' && part[0] != '.') + continue; + + // And even if they are, skip . and .. + if (name == "." || name == "..") + continue; + + if (name.matches(part, String::CaseSensitivity::CaseSensitive)) { + + StringBuilder nested_base; + nested_base.append(new_base); + nested_base.append(name); + + StringView remaining_path = path.substring_view_starting_after_substring(part); + Vector nested_res = expand_globs(remaining_path, nested_base.to_string()); + for (auto& s : nested_res) + res.append(s); + } + } + return res; + } + + // Found no globs. + String new_path = builder.to_string(); + if (access(new_path.characters(), F_OK) == 0) + res.append(new_path); + return res; +} + static Vector process_arguments(const Vector& args) { Vector argv_string; for (auto& arg : args) { - bool is_glob = false; - for (int i = 0; i < arg.length(); i++) { - char c = arg.characters()[i]; - if (c == '*' || c == '?') { - is_glob = true; - } - } - - if (is_glob == false) { - argv_string.append(arg.characters()); - } else { - CDirIterator di(".", CDirIterator::NoFlags); - if (di.has_error()) { - fprintf(stderr, "CDirIterator: %s\n", di.error_string()); - continue; - } - - while (di.has_next()) { - String name = di.next_path(); - - // Dotfiles have to be explicitly requested - if (name[0] == '.' && arg[0] != '.') - continue; - - // And even if they are, skip . and .. - if (name == "." || name == "..") - continue; - - if (name.matches(arg, String::CaseSensitivity::CaseSensitive)) - argv_string.append(name); - } - } + auto expanded = expand_globs(arg, ""); + if (expanded.is_empty()) + argv_string.append(arg); + else + for (auto& path : expand_globs(arg, "")) + argv_string.append(path); } return argv_string; @@ -302,58 +369,56 @@ static int run_command(const String& cmd) if (subcommands.is_empty()) return 0; - FileDescriptorCollector fds; + FileDescriptionCollector fds; for (int i = 0; i < subcommands.size(); ++i) { auto& subcommand = subcommands[i]; for (auto& redirection : subcommand.redirections) { switch (redirection.type) { - case Redirection::Pipe: { - int pipefd[2]; - int rc = pipe(pipefd); - if (rc < 0) { - perror("pipe"); - return 1; - } - subcommand.redirections.append({ Redirection::Rewire, STDOUT_FILENO, pipefd[1] }); - auto& next_command = subcommands[i + 1]; - next_command.redirections.append({ Redirection::Rewire, STDIN_FILENO, pipefd[0] }); - fds.add(pipefd[0]); - fds.add(pipefd[1]); - break; + case Redirection::Pipe: { + int pipefd[2]; + int rc = pipe(pipefd); + if (rc < 0) { + perror("pipe"); + return 1; } - case Redirection::FileWriteAppend: { - int fd = open(redirection.path.characters(), O_WRONLY | O_CREAT | O_APPEND, 0666); - if (fd < 0) { - perror("open"); - return 1; - } - subcommand.redirections.append({ Redirection::Rewire, redirection.fd, fd }); - fds.add(fd); - break; + subcommand.rewirings.append({ STDOUT_FILENO, pipefd[1] }); + auto& next_command = subcommands[i + 1]; + next_command.rewirings.append({ STDIN_FILENO, pipefd[0] }); + fds.add(pipefd[0]); + fds.add(pipefd[1]); + break; + } + case Redirection::FileWriteAppend: { + int fd = open(redirection.path.characters(), O_WRONLY | O_CREAT | O_APPEND, 0666); + if (fd < 0) { + perror("open"); + return 1; } - case Redirection::FileWrite: { - int fd = open(redirection.path.characters(), O_WRONLY | O_CREAT | O_TRUNC, 0666); - if (fd < 0) { - perror("open"); - return 1; - } - subcommand.redirections.append({ Redirection::Rewire, redirection.fd, fd }); - fds.add(fd); - break; + subcommand.rewirings.append({ redirection.fd, fd }); + fds.add(fd); + break; + } + case Redirection::FileWrite: { + int fd = open(redirection.path.characters(), O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (fd < 0) { + perror("open"); + return 1; } - case Redirection::FileRead: { - int fd = open(redirection.path.characters(), O_RDONLY); - if (fd < 0) { - perror("open"); - return 1; - } - subcommand.redirections.append({ Redirection::Rewire, redirection.fd, fd }); - fds.add(fd); - break; + subcommand.rewirings.append({ redirection.fd, fd }); + fds.add(fd); + break; + } + case Redirection::FileRead: { + int fd = open(redirection.path.characters(), O_RDONLY); + if (fd < 0) { + perror("open"); + return 1; } - case Redirection::Rewire: - break; // ignore + subcommand.rewirings.append({ redirection.fd, fd }); + fds.add(fd); + break; + } } } } @@ -361,7 +426,12 @@ static int run_command(const String& cmd) struct termios trm; tcgetattr(0, &trm); - Vector children; + struct SpawnedProcess { + String name; + pid_t pid; + }; + + Vector children; CommandTimer timer; @@ -390,16 +460,14 @@ static int run_command(const String& cmd) if (!child) { setpgid(0, 0); tcsetpgrp(0, getpid()); - for (auto& redirection : subcommand.redirections) { - if (redirection.type == Redirection::Rewire) { -#ifdef SH_DEBUGsh - dbgprintf("in %s<%d>, dup2(%d, %d)\n", argv[0], getpid(), redirection.rewire_fd, redirection.fd); + for (auto& rewiring : subcommand.rewirings) { +#ifdef SH_DEBUG + dbgprintf("in %s<%d>, dup2(%d, %d)\n", argv[0], getpid(), redirection.rewire_fd, redirection.fd); #endif - int rc = dup2(redirection.rewire_fd, redirection.fd); - if (rc < 0) { - perror("dup2"); - return 1; - } + int rc = dup2(rewiring.rewire_fd, rewiring.fd); + if (rc < 0) { + perror("dup2"); + return 1; } } @@ -412,7 +480,7 @@ static int run_command(const String& cmd) } ASSERT_NOT_REACHED(); } - children.append(child); + children.append({ argv[0], child }); } #ifdef SH_DEBUG @@ -426,39 +494,38 @@ static int run_command(const String& cmd) dbgprintf(" %d\n", child); #endif - int wstatus = 0; - int rc; + int return_value = 0; - for (auto& child : children) { + for (int i = 0; i < children.size(); ++i) { + auto& child = children[i]; do { - rc = waitpid(child, &wstatus, 0); + int rc = waitpid(child.pid, &wstatus, 0); if (rc < 0 && errno != EINTR) { - perror("waitpid"); + if (errno != ECHILD) + perror("waitpid"); break; } - } while(errno == EINTR); + if (WIFEXITED(wstatus)) { + if (WEXITSTATUS(wstatus) != 0) + printf("Shell: %s(%d) exited with status %d\n", child.name.characters(), child.pid, WEXITSTATUS(wstatus)); + if (i == 0) + return_value = WEXITSTATUS(wstatus); + } else { + if (WIFSIGNALED(wstatus)) { + printf("Shell: %s(%d) exited due to signal '%s'\n", child.name.characters(), child.pid, strsignal(WTERMSIG(wstatus))); + } else { + printf("Shell: %s(%d) exited abnormally\n", child.name.characters(), child.pid); + } + } + } while (errno == EINTR); } // FIXME: Should I really have to tcsetpgrp() after my child has exited? // Is the terminal controlling pgrp really still the PGID of the dead process? tcsetpgrp(0, getpid()); - tcsetattr(0, TCSANOW, &trm); - - if (WIFEXITED(wstatus)) { - if (WEXITSTATUS(wstatus) != 0) - printf("Exited with status %d\n", WEXITSTATUS(wstatus)); - return WEXITSTATUS(wstatus); - } else { - if (WIFSIGNALED(wstatus)) { - puts(strsignal(WTERMSIG(wstatus))); - } else { - printf("Exited abnormally\n"); - return 1; - } - } - return 0; + return return_value; } int main(int argc, char** argv) diff --git a/Userland/.gitignore b/Userland/.gitignore index 781e185b0e..e38b03c53a 100644 --- a/Userland/.gitignore +++ b/Userland/.gitignore @@ -6,3 +6,4 @@ *.o *.d +compile_commands.json diff --git a/Userland/al.cpp b/Userland/al.cpp new file mode 100644 index 0000000000..96094d5d6c --- /dev/null +++ b/Userland/al.cpp @@ -0,0 +1,22 @@ +#include +#include +#include + +static volatile bool got_alarm = false; + +int main(int c, char** v) +{ + unsigned ret = alarm(5); + printf("alarm() with no alarm set: %u\n", ret); + ret = alarm(2); + printf("alarm() with an alarm(5) set: %u\n", ret); + + signal(SIGALRM, [](int) { + got_alarm = true; + }); + printf("Entering infinite loop.\n"); + while (!got_alarm) { + } + printf("Oh, we got the alarm. Exiting :)\n"); + return 0; +} diff --git a/Userland/allocate.cpp b/Userland/allocate.cpp new file mode 100644 index 0000000000..90f89248aa --- /dev/null +++ b/Userland/allocate.cpp @@ -0,0 +1,98 @@ +#include +#include +#include +#include + +void usage(void) +{ + printf("usage: allocate [number [unit (B/KB/MB)]]\n"); + exit(1); +} + +enum Unit { Bytes, KiloBytes, MegaBytes }; + +int main(int argc, char** argv) +{ + unsigned count = 50; + Unit unit = MegaBytes; + + if (argc >= 2) { + bool ok; + count = String(argv[1]).to_uint(ok); + if (!ok) { + usage(); + } + } + + if (argc >= 3) { + if (strcmp(argv[2], "B") == 0) + unit = Bytes; + else if (strcmp(argv[2], "KB") == 0) + unit = KiloBytes; + else if (strcmp(argv[2], "MB") == 0) + unit = MegaBytes; + else + usage(); + } + + switch (unit) { + case Bytes: + break; + case KiloBytes: + count *= 1024; + break; + case MegaBytes: + count *= 1024 * 1024; + break; + } + + CElapsedTimer timer; + + printf("allocating memory (%d bytes)...\n", count); + timer.start(); + char* ptr = (char*)malloc(count); + if (!ptr) { + printf("failed.\n"); + return 1; + } + printf("done in %dms\n", timer.elapsed()); + + auto pages = count / 4096; + auto step = pages / 10; + + CElapsedTimer timer2; + + printf("writing one byte to each page of allocated memory...\n"); + timer.start(); + timer2.start(); + for (int i = 0; i < pages; ++i) { + ptr[i * 4096] = 1; + + if (i != 0 && (i % step) == 0) { + auto ms = timer2.elapsed(); + if (ms == 0) + ms = 1; + + auto bps = double(step * 4096) / (double(ms) / 1000); + + printf("step took %dms (%fMB/s)\n", ms, bps / 1024 / 1024); + + timer2.start(); + } + } + printf("done in %dms\n", timer.elapsed()); + + printf("sleeping for ten seconds...\n"); + for (int i = 0; i < 10; i++) { + printf("%d\n", i); + sleep(1); + } + printf("done.\n"); + + printf("freeing memory...\n"); + timer.start(); + free(ptr); + printf("done in %dms\n", timer.elapsed()); + + return 0; +} diff --git a/Userland/cat.cpp b/Userland/cat.cpp index d084b532ed..e03801487d 100644 --- a/Userland/cat.cpp +++ b/Userland/cat.cpp @@ -1,16 +1,16 @@ -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include int main(int argc, char** argv) { int fd = argc > 1 ? open(argv[1], O_RDONLY) : 0; if (fd == -1) { - printf("failed to open %s: %s\n", argv[1], strerror(errno)); + fprintf(stderr, "Failed to open %s: %s\n", argv[1], strerror(errno)); return 1; } for (;;) { @@ -19,10 +19,15 @@ int main(int argc, char** argv) if (nread == 0) break; if (nread < 0) { - printf("read() error: %s\n", strerror(errno)); + perror("read"); return 2; } - write(1, buf, nread); + ssize_t nwritten = write(1, buf, nread); + if (nwritten < 0) { + perror("write"); + return 3; + } + ASSERT(nwritten == nread); } return 0; } diff --git a/Userland/chmod.cpp b/Userland/chmod.cpp index 496762226d..e4057af0c0 100644 --- a/Userland/chmod.cpp +++ b/Userland/chmod.cpp @@ -1,9 +1,9 @@ -#include -#include #include #include +#include +#include -int main(int argc, char **argv) +int main(int argc, char** argv) { if (argc != 3) { printf("usage: chmod \n"); diff --git a/Userland/chown.cpp b/Userland/chown.cpp index e5b2be2a36..256e82e81f 100644 --- a/Userland/chown.cpp +++ b/Userland/chown.cpp @@ -1,10 +1,10 @@ -#include -#include +#include #include #include -#include +#include +#include -int main(int argc, char **argv) +int main(int argc, char** argv) { if (argc < 2) { printf("usage: chown \n"); diff --git a/Userland/clear.cpp b/Userland/clear.cpp index e31f99328b..6cdedc3ec7 100644 --- a/Userland/clear.cpp +++ b/Userland/clear.cpp @@ -6,4 +6,3 @@ int main(int, char**) fflush(stdout); return 0; } - diff --git a/Userland/cp.cpp b/Userland/cp.cpp index bfc263e0aa..03e3e0411c 100644 --- a/Userland/cp.cpp +++ b/Userland/cp.cpp @@ -1,11 +1,11 @@ -#include -#include +#include +#include +#include #include +#include #include #include -#include -#include -#include +#include int main(int argc, char** argv) { diff --git a/Userland/crash.cpp b/Userland/crash.cpp index f19b714d6d..207d0f1c30 100644 --- a/Userland/crash.cpp +++ b/Userland/crash.cpp @@ -10,7 +10,12 @@ static void print_usage_and_exit() int main(int argc, char** argv) { - enum Mode { SegmentationViolation, DivisionByZero, IllegalInstruction, Abort }; + enum Mode { + SegmentationViolation, + DivisionByZero, + IllegalInstruction, + Abort + }; Mode mode = SegmentationViolation; if (argc != 2) diff --git a/Userland/date.cpp b/Userland/date.cpp index d280a7434f..90edd680c4 100644 --- a/Userland/date.cpp +++ b/Userland/date.cpp @@ -1,6 +1,6 @@ -#include #include #include +#include int main(int argc, char** argv) { @@ -21,4 +21,3 @@ int main(int argc, char** argv) tm->tm_sec); return 0; } - diff --git a/Userland/df.cpp b/Userland/df.cpp index 62572921aa..875aaa0d11 100644 --- a/Userland/df.cpp +++ b/Userland/df.cpp @@ -1,9 +1,9 @@ -#include -#include -#include -#include #include #include +#include +#include +#include +#include struct FileSystem { String fs; diff --git a/Userland/dmesg.cpp b/Userland/dmesg.cpp index 4f396a1b53..bc558815fc 100644 --- a/Userland/dmesg.cpp +++ b/Userland/dmesg.cpp @@ -1,31 +1,20 @@ +#include +#include +#include #include #include -#include -#include int main(int argc, char** argv) { - (void) argc; - (void) argv; - int fd = open("/proc/dmesg", O_RDONLY); - if (fd < 0) { - perror("open /proc/dmesg"); + (void)argc; + (void)argv; + CFile f("/proc/dmesg"); + if (!f.open(CIODevice::ReadOnly)) { + fprintf(stderr, "open: failed to open /proc/dmesg: %s", f.error_string()); return 1; } - for (;;) { - char buffer[BUFSIZ]; - ssize_t nread = read(fd, buffer, sizeof(buffer)); - if (nread < 0) { - perror("read"); - return 1; - } - if (nread == 0) { - break; - } - ssize_t nwritten = write(1, buffer, nread); - assert(nwritten == nread); - } - int rc = close(fd); - assert(rc == 0); + const auto& b = f.read_all(); + for (auto i = 0; i < b.size(); ++i) + putchar(b[i]); return 0; } diff --git a/Userland/env.cpp b/Userland/env.cpp index 0a2a0e39d5..dc1e8b26db 100644 --- a/Userland/env.cpp +++ b/Userland/env.cpp @@ -1,5 +1,5 @@ -#include #include +#include int main(int, char**) { diff --git a/Userland/fgrep.cpp b/Userland/fgrep.cpp index 8916d1131a..c24c3fa76a 100644 --- a/Userland/fgrep.cpp +++ b/Userland/fgrep.cpp @@ -1,7 +1,7 @@ +#include #include #include #include -#include int main(int argc, char** argv) { diff --git a/Userland/guitest2.cpp b/Userland/guitest2.cpp index 79c229c8f8..21ce0fd2a5 100644 --- a/Userland/guitest2.cpp +++ b/Userland/guitest2.cpp @@ -1,24 +1,24 @@ -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include static GWindow* make_launcher_window(); static GWindow* make_progress_window(); @@ -69,7 +69,7 @@ GWindow* make_launcher_window() terminal_button->set_relative_rect({ 5, 20, 90, 20 }); terminal_button->set_text("Terminal"); - terminal_button->on_click = [label] (GButton&) { + terminal_button->on_click = [label](GButton&) { pid_t child_pid = fork(); if (!child_pid) { execve("/bin/Terminal", nullptr, nullptr); @@ -85,7 +85,7 @@ GWindow* make_launcher_window() guitest_button->set_relative_rect({ 5, 50, 90, 20 }); guitest_button->set_text("guitest"); - guitest_button->on_click = [label] (GButton&) { + guitest_button->on_click = [label](GButton&) { pid_t child_pid = fork(); if (!child_pid) { execve("/bin/guitest", nullptr, nullptr); @@ -120,7 +120,7 @@ GWindow* make_launcher_window() auto* close_button = new GButton(widget); close_button->set_relative_rect({ 5, 200, 90, 20 }); close_button->set_text("Close"); - close_button->on_click = [window] (GButton&) { + close_button->on_click = [window](GButton&) { window->close(); }; @@ -169,7 +169,7 @@ static GWindow* make_frames_window() widget->layout()->set_margins({ 8, 8, 8, 8 }); widget->layout()->set_spacing(8); - auto add_label = [widget] (const String& text, FrameShape shape, FrameShadow shadow) { + auto add_label = [widget](const String& text, FrameShape shape, FrameShadow shadow) { auto* label = new GLabel(text, widget); label->set_size_policy(SizePolicy::Fill, SizePolicy::Fill); label->set_frame_thickness(1); diff --git a/Userland/head.cpp b/Userland/head.cpp index 85ec6faf1e..5a59603f48 100644 --- a/Userland/head.cpp +++ b/Userland/head.cpp @@ -1,25 +1,156 @@ +#include +#include + +#include #include #include +int head(const String& filename, bool print_filename, int line_count, int char_count); + int main(int argc, char** argv) { - // FIXME: Allow setting via command-line argument. - int line_count = 10; + CArgsParser args_parser("head"); - if (argc > 1) { - for (int i = 1; i < argc; ++i) { - if (argv[i][0] == '-') { - line_count = atoi(&argv[i][1]); + args_parser.add_arg("n", "lines", "Number of lines to print (default 10)"); + args_parser.add_arg("c", "characters", "Number of characters to print"); + args_parser.add_arg("q", "Never print filenames"); + args_parser.add_arg("v", "Always print filenames"); + + CArgsParserResult args = args_parser.parse(argc, (const char**)argv); + + int line_count = 0; + if (args.is_present("n")) { + line_count = strtol(args.get("n").characters(), NULL, 10); + if (errno) { + args_parser.print_usage(); + return -1; + } + + if (!line_count) { + args_parser.print_usage(); + return -1; + } + } + + int char_count = 0; + if (args.is_present("c")) { + char_count = strtol(args.get("c").characters(), NULL, 10); + if (errno) { + args_parser.print_usage(); + return -1; + } + + if (!char_count) { + args_parser.print_usage(); + return -1; + } + } + + if (line_count == 0 && char_count == 0) { + line_count = 10; + } + + Vector files = args.get_single_values(); + + bool print_filenames = files.size() > 1; + + if (args.is_present("v")) { + print_filenames = true; + } else if (args.is_present("q")) { + print_filenames = false; + } + + if (files.is_empty()) { + return head("", print_filenames, line_count, char_count); + } + + int rc = 0; + + for (auto& file : files) { + if (head(file, print_filenames, line_count, char_count) != 0) { + rc = 1; + } + } + + return rc; +} + +int head(const String& filename, bool print_filename, int line_count, int char_count) +{ + bool is_stdin = false; + FILE* fp = nullptr; + + if (filename == "" || filename == "-") { + fp = stdin; + is_stdin = true; + } else { + fp = fopen(filename.characters(), "r"); + if (!fp) { + fprintf(stderr, "can't open %s for reading: %s\n", filename.characters(), strerror(errno)); + return 1; + } + } + + if (print_filename) { + if (is_stdin) { + puts("==> standard input <=="); + } else { + printf("==> %s <==\n", filename.characters()); + } + } + + if (line_count) { + for (int line = 0; line < line_count; ++line) { + char buffer[BUFSIZ]; + auto* str = fgets(buffer, sizeof(buffer), fp); + if (!str) + break; + + // specifically use fputs rather than puts, because fputs doesn't add + // its own newline. + fputs(str, stdout); + } + } else if (char_count) { + char buffer[BUFSIZ]; + + while (char_count) { + int nread = fread(buffer, 1, min(BUFSIZ, char_count), fp); + if (nread > 0) { + int ncomplete = 0; + + while (ncomplete < nread) { + int nwrote = fwrite(&buffer[ncomplete], 1, nread - ncomplete, stdout); + if (nwrote > 0) + ncomplete += nwrote; + + if (feof(stdout)) { + fprintf(stderr, "unexpected eof writing to stdout\n"); + return 1; + } + + if (ferror(stdout)) { + fprintf(stderr, "error writing to stdout\n"); + return 1; + } + } + } + + char_count -= nread; + + if (feof(fp)) + break; + + if (ferror(fp)) { + fprintf(stderr, "error reading input\n"); + break; } } } - for (int line = 0; line < line_count; ++line) { - char buffer[BUFSIZ]; - auto* str = fgets(buffer, sizeof(buffer), stdin); - if (!str) - break; - fputs(str, stdout); + fclose(fp); + + if (print_filename) { + puts(""); } return 0; diff --git a/Userland/host.cpp b/Userland/host.cpp index 179e5a649e..74f1a0c822 100644 --- a/Userland/host.cpp +++ b/Userland/host.cpp @@ -1,7 +1,8 @@ -#include #include +#include #include #include +#include int main(int argc, char** argv) { @@ -10,9 +11,26 @@ int main(int argc, char** argv) return 0; } + // If input looks like an IPv4 address, we should do a reverse lookup. + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(53); + int rc = inet_pton(AF_INET, argv[1], &addr.sin_addr); + if (rc == 1) { + // Okay, let's do a reverse lookup. + auto* hostent = gethostbyaddr(&addr.sin_addr, sizeof(in_addr), AF_INET); + if (!hostent) { + fprintf(stderr, "Reverse lookup failed for '%s'\n", argv[1]); + return 1; + } + printf("%s is %s\n", argv[1], hostent->h_name); + return 0; + } + auto* hostent = gethostbyname(argv[1]); if (!hostent) { - printf("Lookup failed for '%s'\n", argv[1]); + fprintf(stderr, "Lookup failed for '%s'\n", argv[1]); return 1; } diff --git a/Userland/hostname.cpp b/Userland/hostname.cpp index 4589da8a5c..d343b5b55e 100644 --- a/Userland/hostname.cpp +++ b/Userland/hostname.cpp @@ -1,12 +1,12 @@ -#include -#include #include +#include #include +#include int main(int argc, char** argv) { - (void) argc; - (void) argv; + (void)argc; + (void)argv; char buffer[HOST_NAME_MAX]; int rc = gethostname(buffer, sizeof(buffer)); if (rc < 0) { @@ -16,4 +16,3 @@ int main(int argc, char** argv) printf("%s\n", buffer); return 0; } - diff --git a/Userland/id.cpp b/Userland/id.cpp index 9c4a0f24cb..b552f6a528 100644 --- a/Userland/id.cpp +++ b/Userland/id.cpp @@ -1,15 +1,15 @@ -#include -#include -#include -#include #include +#include +#include +#include +#include extern "C" int main(int, char**); int main(int argc, char** argv) { - (void) argc; - (void) argv; + (void)argc; + (void)argv; uid_t uid = getuid(); gid_t gid = getgid(); @@ -40,4 +40,3 @@ int main(int argc, char** argv) printf("\n"); return 0; } - diff --git a/Userland/kill.cpp b/Userland/kill.cpp index 7b1cb9a1d1..3a01d4f7eb 100644 --- a/Userland/kill.cpp +++ b/Userland/kill.cpp @@ -1,8 +1,8 @@ -#include -#include -#include -#include #include +#include +#include +#include +#include static void print_usage_and_exit() { @@ -38,4 +38,3 @@ int main(int argc, char** argv) perror("kill"); return 0; } - diff --git a/Userland/killall.cpp b/Userland/killall.cpp index 11413511a9..85594d8ea8 100644 --- a/Userland/killall.cpp +++ b/Userland/killall.cpp @@ -1,9 +1,9 @@ -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include static void print_usage_and_exit() { @@ -14,15 +14,15 @@ static void print_usage_and_exit() static int kill_all(const String& process_name, const unsigned signum) { HashMap processes = CProcessStatisticsReader().get_map(); - + for (auto& it : processes) { - if (it.value.name == process_name) { + if (it.value.name == process_name) { int ret = kill(it.value.pid, signum); if (ret < 0) perror("kill"); } } - + return 0; } @@ -31,16 +31,16 @@ int main(int argc, char** argv) bool ok; unsigned signum = SIGTERM; int name_argi = 1; - + if (argc != 2 && argc != 3) print_usage_and_exit(); - + if (argc == 3) { name_argi = 2; - + if (argv[1][0] != '-') print_usage_and_exit(); - + signum = String(&argv[1][1]).to_uint(ok); if (!ok) { printf("'%s' is not a valid signal number\n", &argv[1][1]); diff --git a/Userland/ln.cpp b/Userland/ln.cpp index 9e6a7c1021..54cf0d40d5 100644 --- a/Userland/ln.cpp +++ b/Userland/ln.cpp @@ -1,8 +1,8 @@ -#include -#include -#include -#include #include +#include +#include +#include +#include int main(int argc, char** argv) { @@ -35,4 +35,3 @@ int main(int argc, char** argv) } return 0; } - diff --git a/Userland/ls.cpp b/Userland/ls.cpp index 9dd54f0be2..f5655ac6a5 100644 --- a/Userland/ls.cpp +++ b/Userland/ls.cpp @@ -1,16 +1,18 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include static int do_file_system_object_long(const char* path); static int do_file_system_object_short(const char* path); @@ -19,10 +21,11 @@ static bool flag_colorize = true; static bool flag_long = false; static bool flag_show_dotfiles = false; static bool flag_show_inode = false; +static bool flag_print_numeric = false; int main(int argc, char** argv) { - static const char* valid_option_characters = "laiG"; + static const char* valid_option_characters = "laiGn"; int opt; while ((opt = getopt(argc, argv, valid_option_characters)) != -1) { switch (opt) { @@ -38,13 +41,17 @@ int main(int argc, char** argv) case 'i': flag_show_inode = true; break; + case 'n': + flag_print_numeric = true; + break; + default: fprintf(stderr, "usage: ls [-%s] [paths...]\n", valid_option_characters); return 1; } } - auto do_file_system_object = [&] (const char* path) { + auto do_file_system_object = [&](const char* path) { if (flag_long) return do_file_system_object_long(path); return do_file_system_object_short(path); @@ -53,7 +60,7 @@ int main(int argc, char** argv) int status; if (optind >= argc) { status = do_file_system_object("."); - } else if (optind+1 >= argc) { + } else if (optind + 1 >= argc) { status = do_file_system_object(argv[optind]); } else { for (; optind < argc; ++optind) { @@ -112,7 +119,8 @@ int print_name(struct stat& st, const char* name, const char* path_for_link_reso return nprinted; } -bool print_filesystem_object(const char* path, const char* name) { +bool print_filesystem_object(const char* path, const char* name) +{ struct stat st; int rc = lstat(path, &st); if (rc == -1) { @@ -148,18 +156,28 @@ bool print_filesystem_object(const char* path, const char* name) { st.st_mode & S_IWGRP ? 'w' : '-', st.st_mode & S_ISGID ? 's' : (st.st_mode & S_IXGRP ? 'x' : '-'), st.st_mode & S_IROTH ? 'r' : '-', - st.st_mode & S_IWOTH ? 'w' : '-' - ); + st.st_mode & S_IWOTH ? 'w' : '-'); if (st.st_mode & S_ISVTX) printf("t"); else printf("%c", st.st_mode & S_IXOTH ? 'x' : '-'); - printf(" %4u %4u", st.st_uid, st.st_gid); + passwd* pwd = getpwuid(st.st_uid); + group* grp = getgrgid(st.st_gid); + if (!flag_print_numeric && pwd) { + printf(" %5s", pwd->pw_name); + } else { + printf(" %5u", st.st_uid); + } + if (!flag_print_numeric && grp) { + printf(" %5s", grp->gr_name); + } else { + printf(" %5u", st.st_gid); + } if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) - printf(" %4u,%4u ", major(st.st_rdev), minor(st.st_rdev)); + printf(" %4u,%4u ", major(st.st_rdev), minor(st.st_rdev)); else printf(" %10u ", st.st_size); @@ -203,8 +221,8 @@ int do_file_system_object_long(const char* path) return 0; } - -bool print_filesystem_object_short(const char *path, const char *name, int *nprinted) { +bool print_filesystem_object_short(const char* path, const char* name, int* nprinted) +{ struct stat st; int rc = lstat(path, &st); if (rc == -1) { diff --git a/Userland/mkdir.cpp b/Userland/mkdir.cpp index c370a1486b..9bfe50b2bc 100644 --- a/Userland/mkdir.cpp +++ b/Userland/mkdir.cpp @@ -1,10 +1,10 @@ -#include -#include -#include -#include -#include #include +#include +#include +#include +#include #include +#include int main(int argc, char** argv) { diff --git a/Userland/mknod.cpp b/Userland/mknod.cpp index dc1221b51d..113aac1702 100644 --- a/Userland/mknod.cpp +++ b/Userland/mknod.cpp @@ -1,7 +1,7 @@ -#include #include #include #include +#include inline constexpr unsigned encoded_device(unsigned major, unsigned minor) { diff --git a/Userland/mm.cpp b/Userland/mm.cpp index 1e49f9a011..e9b734121c 100644 --- a/Userland/mm.cpp +++ b/Userland/mm.cpp @@ -1,28 +1,20 @@ +#include +#include #include #include -#include int main(int argc, char** argv) { - (void) argc; - (void) argv; - int fd = open("/proc/mm", O_RDONLY); - if (fd == -1) { - perror("failed to open /proc/mm"); + (void)argc; + (void)argv; + + CFile f("/proc/mm"); + if (!f.open(CIODevice::ReadOnly)) { + fprintf(stderr, "open: failed to open /proc/mm: %s", f.error_string()); return 1; } - for (;;) { - char buf[128]; - ssize_t nread = read(fd, buf, sizeof(buf)); - if (nread == 0) - break; - if (nread < 0) { - perror("failed to read"); - return 2; - } - for (ssize_t i = 0; i < nread; ++i) { - putchar(buf[i]); - } - } + const auto& b = f.read_all(); + for (auto i = 0; i < b.size(); ++i) + putchar(b[i]); return 0; } diff --git a/Userland/more.cpp b/Userland/more.cpp index d0050c6b9d..6371ef01f4 100644 --- a/Userland/more.cpp +++ b/Userland/more.cpp @@ -1,7 +1,7 @@ -#include -#include #include +#include #include +#include static int key_fd; @@ -16,8 +16,8 @@ void wait_for_key() int main(int argc, char** argv) { - (void) argc; - (void) argv; + (void)argc; + (void)argv; key_fd = open(ttyname(1), O_RDONLY); if (key_fd < 0) { @@ -36,10 +36,9 @@ int main(int argc, char** argv) break; printf(str); ++lines_printed; - if ((lines_printed % (ws.ws_row - 1)) == 0) { + if ((lines_printed % (ws.ws_row - 1)) == 0) { wait_for_key(); } - } close(key_fd); diff --git a/Userland/mv.cpp b/Userland/mv.cpp index 486761c00e..6edf589de3 100644 --- a/Userland/mv.cpp +++ b/Userland/mv.cpp @@ -1,8 +1,8 @@ -#include -#include -#include #include #include +#include +#include +#include int main(int argc, char** argv) { diff --git a/Userland/pape.cpp b/Userland/pape.cpp index 138b98642d..b77584165d 100644 --- a/Userland/pape.cpp +++ b/Userland/pape.cpp @@ -1,18 +1,18 @@ -#include -#include -#include -#include -#include -#include -#include #include +#include #include #include -#include #include #include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include static int handle_show_all() { @@ -73,4 +73,3 @@ int main(int argc, char** argv) return handle_set_pape(values[0]); } - diff --git a/Userland/pidof.cpp b/Userland/pidof.cpp index 09ce327ff1..ea2cb4c57a 100644 --- a/Userland/pidof.cpp +++ b/Userland/pidof.cpp @@ -1,21 +1,21 @@ -#include -#include -#include -#include -#include -#include #include -#include #include +#include +#include +#include +#include +#include +#include +#include static int pid_of(const String& process_name, bool single_shot, bool omit_pid, pid_t pid) { bool displayed_at_least_one = false; HashMap processes = CProcessStatisticsReader().get_map(); - + for (auto& it : processes) { - if (it.value.name == process_name) { + if (it.value.name == process_name) { if (!omit_pid || (omit_pid && it.value.pid != pid)) { printf("%d ", it.value.pid); displayed_at_least_one = true; @@ -40,11 +40,11 @@ int main(int argc, char** argv) args_parser.add_arg("o", "pid", "Tells pidof to omit processes with that pid. The special pid %PPID can be used to name the parent process of the pidof program."); CArgsParserResult args = args_parser.parse(argc, (const char**)argv); - + bool s_arg = args.is_present("s"); bool o_arg = args.is_present("o"); pid_t pid = 0; - + if (o_arg) { bool ok = false; String pid_str = args.get("o"); @@ -54,13 +54,13 @@ int main(int argc, char** argv) else pid = pid_str.to_uint(ok); } - + // We should have one single value : the process name Vector values = args.get_single_values(); if (values.size() == 0) { args_parser.print_usage(); return 0; } - + return pid_of(values[0], s_arg, o_arg, pid); } diff --git a/Userland/ping.cpp b/Userland/ping.cpp index 05a63d0b66..9151c0df72 100644 --- a/Userland/ping.cpp +++ b/Userland/ping.cpp @@ -1,17 +1,17 @@ -#include -#include #include -#include +#include #include +#include #include #include -#include -#include +#include +#include #include +#include uint16_t internet_checksum(const void* ptr, size_t count) { - uint32_t checksum = 0; + uint32_t checksum = 0; auto* w = (const uint16_t*)ptr; while (count > 1) { checksum += ntohs(*w++); @@ -47,7 +47,9 @@ int main(int argc, char** argv) return 1; } - struct timeval timeout { 1, 0 }; + struct timeval timeout { + 1, 0 + }; int rc = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); if (rc < 0) { perror("setsockopt"); @@ -131,8 +133,7 @@ int main(int argc, char** argv) ntohs(pong_packet.header.un.echo.id), ntohs(pong_packet.header.un.echo.sequence), pong_packet.header.un.echo.sequence != ping_packet.header.un.echo.sequence ? "(!)" : "", - ms - ); + ms); // If this was a response to an earlier packet, we still need to wait for the current one. if (pong_packet.header.un.echo.sequence != ping_packet.header.un.echo.sequence) diff --git a/Userland/ps.cpp b/Userland/ps.cpp index 6b18f3a0f1..2485b36057 100644 --- a/Userland/ps.cpp +++ b/Userland/ps.cpp @@ -1,28 +1,20 @@ +#include +#include #include #include -#include int main(int argc, char** argv) { - (void) argc; - (void) argv; - int fd = open("/proc/summary", O_RDONLY); - if (fd == -1) { - perror("failed to open /proc/summary"); + (void)argc; + (void)argv; + + CFile f("/proc/summary"); + if (!f.open(CIODevice::ReadOnly)) { + fprintf(stderr, "open: failed to open /proc/summary: %s", f.error_string()); return 1; } - for (;;) { - char buf[128]; - ssize_t nread = read(fd, buf, sizeof(buf)); - if (nread == 0) - break; - if (nread < 0) { - perror("failed to read"); - return 2; - } - for (ssize_t i = 0; i < nread; ++i) { - putchar(buf[i]); - } - } + const auto& b = f.read_all(); + for (auto i = 0; i < b.size(); ++i) + putchar(b[i]); return 0; } diff --git a/Userland/qs.cpp b/Userland/qs.cpp index e3b5c49cb9..f3ab074af9 100644 --- a/Userland/qs.cpp +++ b/Userland/qs.cpp @@ -1,11 +1,11 @@ -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include #include int main(int argc, char** argv) @@ -15,7 +15,7 @@ int main(int argc, char** argv) auto menubar = make(); auto app_menu = make("QuickShow"); - app_menu->add_action(GAction::create("Quit", { Mod_Alt, Key_F4 }, [] (const GAction&) { + app_menu->add_action(GAction::create("Quit", { Mod_Alt, Key_F4 }, [](const GAction&) { GApplication::the().quit(0); return; })); @@ -25,7 +25,7 @@ int main(int argc, char** argv) menubar->add_menu(move(file_menu)); auto help_menu = make("Help"); - help_menu->add_action(GAction::create("About", [] (const GAction&) { + help_menu->add_action(GAction::create("About", [](const GAction&) { dbgprintf("FIXME: Implement Help/About\n"); })); menubar->add_menu(move(help_menu)); diff --git a/Userland/rm.cpp b/Userland/rm.cpp index 606d92d7d9..2c62f4d628 100644 --- a/Userland/rm.cpp +++ b/Userland/rm.cpp @@ -1,18 +1,69 @@ +#include +#include +#include +#include +#include +#include #include -#include +#include +#include #include -int main(int argc, char** argv) +int remove(bool recursive, const char* path) { - if (argc != 2) { - fprintf(stderr, "usage: rm \n"); + struct stat path_stat; + int s = stat(path, &path_stat); + if (s < 0) { + perror("stat"); return 1; } - int rc = unlink(argv[1]); - if (rc < 0) { - perror("unlink"); - return 1; + + if (S_ISDIR(path_stat.st_mode) && recursive) { + DIR* derp = opendir(path); + if (!derp) { + return 1; + } + + while (auto* de = readdir(derp)) { + if (strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0) { + StringBuilder builder; + builder.append(path); + builder.append('/'); + builder.append(de->d_name); + int s = remove(true, builder.to_string().characters()); + if (s < 0) + return s; + } + } + printf("Removing directory: %s\n", path); + int s = rmdir(path); + if (s < 0) { + perror("rmdir"); + return 1; + } + } else { + int rc = unlink(path); + if (rc < 0) { + perror("unlink"); + return 1; + } + printf("Removing file: %s\n", path); } return 0; } +int main(int argc, char** argv) +{ + CArgsParser args_parser("rm"); + args_parser.add_arg("r", "Delete directory recursively."); + args_parser.add_required_single_value("path"); + + CArgsParserResult args = args_parser.parse(argc, (const char**)argv); + Vector values = args.get_single_values(); + if (values.size() == 0) { + args_parser.print_usage(); + return 1; + } + + return remove(args.is_present("r"), values[0].characters()); +} diff --git a/Userland/rmdir.cpp b/Userland/rmdir.cpp index 8d84f8cc67..8d802139b6 100644 --- a/Userland/rmdir.cpp +++ b/Userland/rmdir.cpp @@ -1,5 +1,5 @@ -#include #include +#include #include int main(int argc, char** argv) @@ -15,4 +15,3 @@ int main(int argc, char** argv) } return 0; } - diff --git a/Userland/sleep.cpp b/Userland/sleep.cpp index 25aa3732f8..a91001cc40 100644 --- a/Userland/sleep.cpp +++ b/Userland/sleep.cpp @@ -1,7 +1,7 @@ -#include -#include -#include #include +#include +#include +#include void handle_sigint(int) { @@ -29,4 +29,3 @@ int main(int argc, char** argv) } return 0; } - diff --git a/Userland/sort.cpp b/Userland/sort.cpp index 35d3933f9e..543a1185c3 100644 --- a/Userland/sort.cpp +++ b/Userland/sort.cpp @@ -1,6 +1,6 @@ +#include #include #include -#include #include #include @@ -16,7 +16,7 @@ int main(int argc, char** argv) lines.append(buffer); } - quick_sort(lines.begin(), lines.end(), [] (auto& a, auto& b) { + quick_sort(lines.begin(), lines.end(), [](auto& a, auto& b) { return strcmp(a.characters(), b.characters()) < 0; }); diff --git a/Userland/stat.cpp b/Userland/stat.cpp index fc6154f074..cab32139b9 100644 --- a/Userland/stat.cpp +++ b/Userland/stat.cpp @@ -1,9 +1,9 @@ -#include -#include -#include -#include #include +#include +#include #include +#include +#include int main(int argc, char** argv) { @@ -62,8 +62,7 @@ int main(int argc, char** argv) st.st_mode & S_IWGRP ? 'w' : '-', st.st_mode & S_ISGID ? 's' : (st.st_mode & S_IXGRP ? 'x' : '-'), st.st_mode & S_IROTH ? 'r' : '-', - st.st_mode & S_IWOTH ? 'w' : '-' - ); + st.st_mode & S_IWOTH ? 'w' : '-'); if (st.st_mode & S_ISVTX) printf("t"); @@ -72,7 +71,7 @@ int main(int argc, char** argv) printf(")\n"); - auto print_time = [] (time_t t) { + auto print_time = [](time_t t) { auto* tm = localtime(&t); printf("%4u-%02u-%02u %02u:%02u:%02u\n", tm->tm_year + 1900, diff --git a/Userland/strace.cpp b/Userland/strace.cpp index bd8b9cf61b..786479aade 100644 --- a/Userland/strace.cpp +++ b/Userland/strace.cpp @@ -1,11 +1,11 @@ -#include -#include -#include -#include -#include #include #include #include +#include +#include +#include +#include +#include static int usage() { diff --git a/Userland/su.cpp b/Userland/su.cpp index 354d97aa76..8f7a10aa82 100644 --- a/Userland/su.cpp +++ b/Userland/su.cpp @@ -1,8 +1,8 @@ -#include -#include -#include -#include #include +#include +#include +#include +#include extern "C" int main(int, char**); diff --git a/Userland/sysctl.cpp b/Userland/sysctl.cpp index 0b11a62a92..29e8c7f768 100644 --- a/Userland/sysctl.cpp +++ b/Userland/sysctl.cpp @@ -1,14 +1,15 @@ -#include -#include -#include -#include -#include -#include #include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include static String read_var(const String& name) { @@ -16,19 +17,17 @@ static String read_var(const String& name) builder.append("/proc/sys/"); builder.append(name); auto path = builder.to_string(); - int fd = open(path.characters(), O_RDONLY); - if (fd < 0) { - perror("open"); + CFile f(path); + if (!f.open(CIODevice::ReadOnly)) { + fprintf(stderr, "open: %s", f.error_string()); exit(1); } - char buffer[1024]; - int nread = read(fd, buffer, sizeof(buffer)); - close(fd); - if (nread < 0) { - perror("read"); + const auto& b = f.read_all(); + if (f.error() < 0) { + fprintf(stderr, "read: %s", f.error_string()); exit(1); } - return String(buffer, nread, Chomp); + return String((const char*)b.pointer(), b.size(), Chomp); } static void write_var(const String& name, const String& value) @@ -37,20 +36,18 @@ static void write_var(const String& name, const String& value) builder.append("/proc/sys/"); builder.append(name); auto path = builder.to_string(); - int fd = open(path.characters(), O_WRONLY); - if (fd < 0) { - perror("open"); + CFile f(path); + if (!f.open(CIODevice::WriteOnly)) { + fprintf(stderr, "open: %s", f.error_string()); exit(1); } - int nwritten = write(fd, value.characters(), value.length()); - if (nwritten < 0) { - perror("read"); + f.write(value); + if (f.error() < 0) { + fprintf(stderr, "write: %s", f.error_string()); exit(1); } - close(fd); } - static int handle_show_all() { CDirIterator di("/proc/sys", CDirIterator::SkipDots); @@ -61,24 +58,8 @@ static int handle_show_all() char pathbuf[PATH_MAX]; while (di.has_next()) { - String name = di.next_path(); - sprintf(pathbuf, "/proc/sys/%s", name.characters()); - int fd = open(pathbuf, O_RDONLY); - if (fd < 0) { - perror("open"); - continue; - } - char buffer[1024]; - int nread = read(fd, buffer, sizeof(buffer)); - close(fd); - if (nread < 0) { - perror("read"); - continue; - } - buffer[nread] = '\0'; - printf("%s = %s", name.characters(), buffer); - if (nread && buffer[nread - 1] != '\n') - printf("\n"); + String variable_name = di.next_path(); + printf("%s = %s\n", variable_name.characters(), read_var(variable_name).characters()); } return 0; } @@ -120,4 +101,3 @@ int main(int argc, char** argv) Vector values = args.get_single_values(); return handle_var(values[0]); } - diff --git a/Userland/tail.cpp b/Userland/tail.cpp index 4a0ef12317..0da99fa910 100644 --- a/Userland/tail.cpp +++ b/Userland/tail.cpp @@ -1,16 +1,18 @@ -#include -#include -#include -#include -#include #include -#include #include +#include +#include +#include +#include +#include +#include + +#define DEFAULT_LINE_COUNT 10 int tail_from_pos(CFile& file, off_t startline, bool want_follow) { if (!file.seek(startline + 1)) - return -1; + return 1; while (true) { const auto& b = file.read(4096); @@ -26,9 +28,8 @@ int tail_from_pos(CFile& file, off_t startline, bool want_follow) } } - if (write(STDOUT_FILENO, b.pointer(), b.size()) < 0) { - return -1; - } + if (write(STDOUT_FILENO, b.pointer(), b.size()) < 0) + return 1; } return 0; @@ -41,7 +42,7 @@ off_t find_seek_pos(CFile& file, int wanted_lines) off_t pos = 0; if (!file.seek(0, CIODevice::SeekMode::FromEndPosition, &pos)) { fprintf(stderr, "Failed to find end of file: %s\n", file.error_string()); - return -1; + return 1; } off_t end = pos; @@ -49,7 +50,7 @@ off_t find_seek_pos(CFile& file, int wanted_lines) // FIXME: Reading char-by-char is only OK if CIODevice's read buffer // is smart enough to not read char-by-char. Fix it there, or fix it here :) - for(; pos >= 0; pos--) { + for (; pos >= 0; pos--) { file.seek(pos); const auto& ch = file.read(1); if (ch.is_empty()) { @@ -70,10 +71,10 @@ off_t find_seek_pos(CFile& file, int wanted_lines) static void exit_because_we_wanted_lines() { fprintf(stderr, "Expected a line count after -n"); - exit(-1); + exit(1); } -int main(int argc, char *argv[]) +int main(int argc, char* argv[]) { CArgsParser args_parser("tail"); @@ -86,7 +87,7 @@ int main(int argc, char *argv[]) Vector values = args.get_single_values(); if (values.size() != 1) { args_parser.print_usage(); - return -1; + return 1; } int line_count = 0; @@ -94,14 +95,16 @@ int main(int argc, char *argv[]) line_count = strtol(args.get("n").characters(), NULL, 10); if (errno == EINVAL) { args_parser.print_usage(); - return -1; + return 1; } + } else { + line_count = DEFAULT_LINE_COUNT; } CFile f(values[0]); if (!f.open(CIODevice::ReadOnly)) { fprintf(stderr, "Error opening file %s: %s\n", f.filename().characters(), strerror(errno)); - exit(-1); + exit(1); } bool flag_follow = args.is_present("f"); diff --git a/Userland/tc.cpp b/Userland/tc.cpp index b19aa2a98e..7abf31c9af 100644 --- a/Userland/tc.cpp +++ b/Userland/tc.cpp @@ -18,9 +18,11 @@ int main(int argc, char** argv) if (fd < 0) { perror("socket"); return 1; - } + } - struct timeval timeout { 3, 0 }; + struct timeval timeout { + 3, 0 + }; int rc = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); if (rc < 0) { perror("setsockopt"); @@ -38,7 +40,7 @@ int main(int argc, char** argv) dst_addr.sin_family = AF_INET; dst_addr.sin_port = htons(80); rc = inet_pton(AF_INET, addr_str, &dst_addr.sin_addr); - if (rc < 0) { + if (rc <= 0) { perror("inet_pton"); return 1; } diff --git a/Userland/tee.cpp b/Userland/tee.cpp new file mode 100644 index 0000000000..d4bded2dd5 --- /dev/null +++ b/Userland/tee.cpp @@ -0,0 +1,122 @@ +#include +#include +#include +#include +#include +#include +#include + +static Vector collect_fds(int argc, char** argv, int start, bool aflag, bool* err) +{ + int oflag; + mode_t mode; + if (aflag) { + oflag = O_APPEND; + mode = 0; + } else { + oflag = O_CREAT | O_WRONLY | O_TRUNC; + mode = S_IROTH | S_IWOTH | S_IRGRP | S_IWGRP | S_IRUSR | S_IWUSR; + } + + Vector fds; + for (int i = start; i < argc; ++i) { + int fd = open(argv[i], oflag, mode); + if (fd < 0) { + perror("failed to open file for writing"); + *err = true; + } else { + fds.append(fd); + } + } + fds.append(STDOUT_FILENO); + return fds; +} + +static void copy_stdin(Vector& fds, bool* err) +{ + for (;;) { + char buf[4096]; + ssize_t nread = read(STDIN_FILENO, buf, sizeof(buf)); + if (nread == 0) + break; + if (nread < 0) { + perror("read() error"); + *err = true; + // a failure to read from stdin should lead to an early exit + return; + } + + Vector broken_fds; + for (int i = 0; i < fds.size(); ++i) { + auto fd = fds.at(i); + int twrite = 0; + while (twrite != nread) { + ssize_t nwrite = write(fd, buf + twrite, nread - twrite); + if (nwrite < 0) { + if (errno == EINTR) { + continue; + } else { + perror("write() failed"); + *err = true; + broken_fds.append(fd); + // write failures to a successfully opened fd shall + // prevent further writes, but shall not block writes + // to the other open fds + break; + } + } else { + twrite += nwrite; + } + } + } + + // remove any fds which we can no longer write to for subsequent copies + for (auto to_remove : broken_fds) + fds.remove_first_matching([&](int fd) { return to_remove == fd; }); + } +} + +static void close_fds(Vector& fds) +{ + for (int fd : fds) { + int closed = close(fd); + if (closed < 0) { + perror("failed to close output file"); + } + } +} + +static void int_handler(int) +{ + // pass +} + +int main(int argc, char** argv) +{ + bool aflag = false, iflag = false; + int c = 0; + while ((c = getopt(argc, argv, "ai")) != -1) { + switch (c) { + case 'a': + aflag = true; + break; + case 'i': + iflag = true; + break; + } + } + + if (iflag) { + if (signal(SIGINT, int_handler) == SIG_ERR) { + perror("failed to install SIGINT handler"); + } + } + + bool err_open = false; + bool err_write = false; + auto fds = collect_fds(argc, argv, optind, aflag, &err_open); + copy_stdin(fds, &err_write); + close_fds(fds); + + return (err_open || err_write) ? 1 : 0; +} diff --git a/Userland/top.cpp b/Userland/top.cpp index a0c3350049..4f5a07f60d 100644 --- a/Userland/top.cpp +++ b/Userland/top.cpp @@ -1,12 +1,12 @@ -#include -#include +#include +#include +#include +#include #include #include +#include #include -#include -#include -#include -#include +#include static HashMap* s_usernames; @@ -17,8 +17,8 @@ struct Process { String state; String user; String priority; - unsigned linear; - unsigned committed; + unsigned virtual_size; + unsigned physical_size; unsigned nsched_since_prev; unsigned cpu_percent; unsigned cpu_percent_decimal; @@ -61,9 +61,9 @@ static Snapshot get_snapshot() process.priority = parts[16]; process.state = parts[7]; process.name = parts[11]; - process.linear = parts[12].to_uint(ok); + process.virtual_size = parts[12].to_uint(ok); ASSERT(ok); - process.committed = parts[13].to_uint(ok); + process.physical_size = parts[13].to_uint(ok); ASSERT(ok); snapshot.map.set(pid, move(process)); } @@ -89,14 +89,14 @@ int main(int, char**) printf("\033[3J\033[H\033[2J"); printf("\033[47;30m%6s %3s % 8s % 8s %6s %6s %4s %s\033[K\033[0m\n", - "PID", - "PRI", - "USER", - "STATE", - "LINEAR", - "COMMIT", - "%CPU", - "NAME"); + "PID", + "PRI", + "USER", + "STATE", + "VIRT", + "PHYS", + "%CPU", + "NAME"); for (auto& it : current.map) { pid_t pid = it.key; if (pid == 0) @@ -108,13 +108,12 @@ int main(int, char**) dword nsched_before = (*jt).value.nsched; dword nsched_diff = nsched_now - nsched_before; it.value.nsched_since_prev = nsched_diff; - it.value.cpu_percent = ((nsched_diff * 100)/ sum_diff); - it.value.cpu_percent_decimal = (((nsched_diff * 1000)/ sum_diff) % 10); + it.value.cpu_percent = ((nsched_diff * 100) / sum_diff); + it.value.cpu_percent_decimal = (((nsched_diff * 1000) / sum_diff) % 10); processes.append(&it.value); } - - quick_sort(processes.begin(), processes.end(), [] (auto* p1, auto* p2) { + quick_sort(processes.begin(), processes.end(), [](auto* p1, auto* p2) { return p2->nsched_since_prev < p1->nsched_since_prev; }); @@ -124,12 +123,11 @@ int main(int, char**) process->priority[0], process->user.characters(), process->state.characters(), - process->linear / 1024, - process->committed / 1024, + process->virtual_size / 1024, + process->physical_size / 1024, process->cpu_percent, process->cpu_percent_decimal, - process->name.characters() - ); + process->name.characters()); } processes.clear_with_capacity(); prev = move(current); diff --git a/Userland/touch.cpp b/Userland/touch.cpp index 690e6d8671..8674a5b949 100644 --- a/Userland/touch.cpp +++ b/Userland/touch.cpp @@ -1,11 +1,11 @@ -#include #include -#include #include -#include +#include #include -#include #include +#include +#include +#include static bool file_exists(const char* path) { @@ -46,4 +46,3 @@ int main(int argc, char** argv) } return 0; } - diff --git a/Userland/tr.cpp b/Userland/tr.cpp index c9be4b0f3a..36b294318f 100644 --- a/Userland/tr.cpp +++ b/Userland/tr.cpp @@ -1,6 +1,6 @@ +#include #include #include -#include #include #include diff --git a/Userland/tst.cpp b/Userland/tst.cpp index bea9c63e61..b94ae2e486 100644 --- a/Userland/tst.cpp +++ b/Userland/tst.cpp @@ -1,11 +1,11 @@ #include -#include #include +#include int main(int argc, char** argv) { - (void) argc; - (void) argv; + (void)argc; + (void)argv; struct winsize ws; int rc = ioctl(0, TIOCGWINSZ, &ws); diff --git a/Userland/uc.cpp b/Userland/uc.cpp index c5aabda29d..5fe908ee54 100644 --- a/Userland/uc.cpp +++ b/Userland/uc.cpp @@ -18,9 +18,11 @@ int main(int argc, char** argv) if (fd < 0) { perror("socket"); return 1; - } + } - struct timeval timeout { 5, 0 }; + struct timeval timeout { + 5, 0 + }; int rc = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); if (rc < 0) { perror("setsockopt"); @@ -33,16 +35,20 @@ int main(int argc, char** argv) dst_addr.sin_family = AF_INET; dst_addr.sin_port = htons(8080); rc = inet_pton(AF_INET, addr_str, &dst_addr.sin_addr); + if (rc <= 0) { + perror("inet_pton"); + return 1; + } char buffer[BUFSIZ]; const char* msg = "Test message"; - sendto(fd, (const char *)msg, strlen(msg), 0,(const struct sockaddr *)&dst_addr, sizeof(dst_addr)); + sendto(fd, (const char*)msg, strlen(msg), 0, (const struct sockaddr*)&dst_addr, sizeof(dst_addr)); printf("Message sent.\n"); struct sockaddr_in src_addr; socklen_t src_addr_len = sizeof(src_addr); - ssize_t nrecv = recvfrom(fd, (char *)buffer, sizeof(buffer), 0, (struct sockaddr*)&src_addr, &src_addr_len); + ssize_t nrecv = recvfrom(fd, (char*)buffer, sizeof(buffer), 0, (struct sockaddr*)&src_addr, &src_addr_len); if (nrecv < 0) { perror("recvfrom"); return 1; diff --git a/Userland/uname.cpp b/Userland/uname.cpp index 64e43c3565..98987e0d40 100644 --- a/Userland/uname.cpp +++ b/Userland/uname.cpp @@ -20,11 +20,21 @@ int main(int argc, char** argv) if (argv[i][0] == '-') { for (const char* o = &argv[i][1]; *o; ++o) { switch (*o) { - case 's': flag_s = true; break; - case 'n': flag_n = true; break; - case 'r': flag_r = true; break; - case 'm': flag_m = true; break; - case 'a': flag_s = flag_n = flag_r = flag_m = true; break; + case 's': + flag_s = true; + break; + case 'n': + flag_n = true; + break; + case 'r': + flag_r = true; + break; + case 'm': + flag_m = true; + break; + case 'a': + flag_s = flag_n = flag_r = flag_m = true; + break; } } } @@ -43,4 +53,3 @@ int main(int argc, char** argv) printf("\n"); return 0; } - diff --git a/Userland/uptime.cpp b/Userland/uptime.cpp index 4ee6717f6a..4d430589dd 100644 --- a/Userland/uptime.cpp +++ b/Userland/uptime.cpp @@ -19,22 +19,22 @@ int main(int, char**) sscanf(buffer, "%u", &seconds); printf("Up "); - + if (seconds / 86400 > 0) { printf("%d day%s, ", seconds / 86400, (seconds / 86400) == 1 ? "" : "s"); seconds %= 86400; } - + if (seconds / 3600 > 0) { printf("%d hour%s, ", seconds / 3600, (seconds / 3600) == 1 ? "" : "s"); seconds %= 3600; } - + if (seconds / 60 > 0) { printf("%d minute%s, ", seconds / 60, (seconds / 60) == 1 ? "" : "s"); seconds %= 60; } - + printf("%d second%s\n", seconds, seconds == 1 ? "" : "s"); fclose(fp); diff --git a/Userland/yes.cpp b/Userland/yes.cpp new file mode 100644 index 0000000000..b9d3ed725b --- /dev/null +++ b/Userland/yes.cpp @@ -0,0 +1,15 @@ +#include + +int main(int argc, char** argv) +{ + if (argc > 1) { + for (;;) { + puts(argv[1]); + } + } else { + for (;;) { + puts("yes"); + } + } + return 0; +}