Integrate ext2 from VFS into Kernel.

This commit is contained in:
Andreas Kling 2018-10-17 10:55:43 +02:00
parent aec8ab0a60
commit 9171521752
Notes: sideshowbarker 2024-07-19 18:47:14 +09:00
45 changed files with 662 additions and 1085 deletions

View file

@ -3,8 +3,7 @@
#include "Assertions.h"
#include "Retainable.h"
#include "RetainPtr.h"
#include <cstdlib>
#include <cstring>
#include "StdLib.h"
#include "kmalloc.h"
namespace AK {

View file

@ -1,6 +1,6 @@
#pragma once
#include <utility>
#include "StdLib.h"
namespace AK {
@ -38,7 +38,7 @@ public:
void append(T&& value)
{
auto* node = new Node(std::move(value));
auto* node = new Node(move(value));
if (!m_head) {
ASSERT(!m_tail);
m_head = node;

111
AK/Function.h Normal file
View file

@ -0,0 +1,111 @@
/*
* Copyright (C) 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "OwnPtr.h"
#include "StdLib.h"
namespace AK {
template<typename> class Function;
template <typename Out, typename... In>
class Function<Out(In...)> {
public:
Function() = default;
Function(std::nullptr_t) { }
template<typename CallableType, class = typename EnableIf<!(IsPointer<CallableType>::value && IsFunction<typename RemovePointer<CallableType>::Type>::value) && IsRvalueReference<CallableType&&>::value>::Type>
Function(CallableType&& callable)
: m_callableWrapper(make<CallableWrapper<CallableType>>(move(callable)))
{
}
template<typename FunctionType, class = typename EnableIf<IsPointer<FunctionType>::value && IsFunction<typename RemovePointer<FunctionType>::Type>::value>::Type>
Function(FunctionType f)
: m_callableWrapper(make<CallableWrapper<FunctionType>>(move(f)))
{
}
Out operator()(In... in)
{
ASSERT(m_callableWrapper);
return m_callableWrapper->call(forward<In>(in)...);
}
explicit operator bool() const { return !!m_callableWrapper; }
template<typename CallableType, class = typename EnableIf<!(IsPointer<CallableType>::value && IsFunction<typename RemovePointer<CallableType>::Type>::value) && IsRvalueReference<CallableType&&>::value>::Type>
Function& operator=(CallableType&& callable)
{
m_callableWrapper = make<CallableWrapper<CallableType>>(move(callable));
return *this;
}
template<typename FunctionType, class = typename EnableIf<IsPointer<FunctionType>::value && IsFunction<typename RemovePointer<FunctionType>::Type>::value>::Type>
Function& operator=(FunctionType f)
{
m_callableWrapper = make<CallableWrapper<FunctionType>>(move(f));
return *this;
}
Function& operator=(std::nullptr_t)
{
m_callableWrapper = nullptr;
return *this;
}
private:
class CallableWrapperBase {
public:
virtual ~CallableWrapperBase() { }
virtual Out call(In...) = 0;
};
template<typename CallableType>
class CallableWrapper : public CallableWrapperBase {
public:
explicit CallableWrapper(CallableType&& callable)
: m_callable(move(callable))
{
}
CallableWrapper(const CallableWrapper&) = delete;
CallableWrapper& operator=(const CallableWrapper&) = delete;
Out call(In... in) final { return m_callable(forward<In>(in)...); }
private:
CallableType m_callable;
};
OwnPtr<CallableWrapperBase> m_callableWrapper;
};
}
using AK::Function;

View file

@ -1,7 +1,8 @@
#pragma once
#include "HashTable.h"
#include <utility>
#include "StdLib.h"
#include "kstdio.h"
namespace AK {
@ -22,9 +23,9 @@ private:
static unsigned hash(const Entry& entry) { return Traits<K>::hash(entry.key); }
static void dump(const Entry& entry)
{
printf("key=");
kprintf("key=");
Traits<K>::dump(entry.key);
printf(" value=");
kprintf(" value=");
Traits<V>::dump(entry.value);
}
};
@ -33,14 +34,14 @@ public:
HashMap() { }
HashMap(HashMap&& other)
: m_table(std::move(other.m_table))
: m_table(move(other.m_table))
{
}
HashMap& operator=(HashMap&& other)
{
if (this != &other) {
m_table = std::move(other.m_table);
m_table = move(other.m_table);
}
return *this;
}
@ -73,7 +74,7 @@ private:
template<typename K, typename V>
void HashMap<K, V>::set(const K& key, V&& value)
{
m_table.set(Entry{key, std::move(value)});
m_table.set(Entry{key, move(value)});
}
template<typename K, typename V>

View file

@ -3,8 +3,8 @@
#include "Assertions.h"
#include "DoublyLinkedList.h"
#include "Traits.h"
#include <cstdlib>
#include <utility>
#include "StdLib.h"
#include "kstdio.h"
//#define HASHTABLE_DEBUG
@ -68,7 +68,7 @@ public:
T& operator*()
{
#ifdef HASHTABLE_DEBUG
printf("retrieve { bucketIndex: %u, isEnd: %u }\n", m_bucketIndex, m_isEnd);
kprintf("retrieve { bucketIndex: %u, isEnd: %u }\n", m_bucketIndex, m_isEnd);
#endif
return *m_bucketIterator;
}
@ -86,7 +86,7 @@ public:
while (!m_isEnd) {
#ifdef HASHTABLE_DEBUG
++pass;
printf("skipToNext pass %u, m_bucketIndex=%u\n", pass, m_bucketIndex);
kprintf("skipToNext pass %u, m_bucketIndex=%u\n", pass, m_bucketIndex);
#endif
if (m_bucketIterator.isEnd()) {
++m_bucketIndex;
@ -112,7 +112,7 @@ public:
{
if (!isEnd && !m_table.isEmpty() && !(m_bucketIterator != DoublyLinkedList<T>::Iterator::universalEnd())) {
#ifdef HASHTABLE_DEBUG
printf("bucket iterator init!\n");
kprintf("bucket iterator init!\n");
#endif
m_bucketIterator = m_table.m_buckets[0].chain.begin();
if (m_bucketIterator.isEnd())
@ -143,7 +143,7 @@ public:
const T& operator*() const
{
#ifdef HASHTABLE_DEBUG
printf("retrieve { bucketIndex: %u, isEnd: %u }\n", m_bucketIndex, m_isEnd);
kprintf("retrieve { bucketIndex: %u, isEnd: %u }\n", m_bucketIndex, m_isEnd);
#endif
return *m_bucketIterator;
}
@ -161,7 +161,7 @@ public:
while (!m_isEnd) {
#ifdef HASHTABLE_DEBUG
++pass;
printf("skipToNext pass %u, m_bucketIndex=%u\n", pass, m_bucketIndex);
kprintf("skipToNext pass %u, m_bucketIndex=%u\n", pass, m_bucketIndex);
#endif
if (m_bucketIterator.isEnd()) {
++m_bucketIndex;
@ -188,7 +188,7 @@ public:
{
if (!isEnd && !m_table.isEmpty() && !(m_bucketIterator != DoublyLinkedList<T>::ConstIterator::universalEnd())) {
#ifdef HASHTABLE_DEBUG
printf("const bucket iterator init!\n");
kprintf("const bucket iterator init!\n");
#endif
const DoublyLinkedList<T>& chain = m_table.m_buckets[0].chain;
m_bucketIterator = chain.begin();
@ -242,9 +242,9 @@ void HashTable<T, TraitsForT>::set(T&& value)
}
if (size() >= capacity()) {
rehash(size() + 1);
insert(std::move(value));
insert(move(value));
} else {
bucket.chain.append(std::move(value));
bucket.chain.append(move(value));
}
m_size++;
}
@ -254,7 +254,7 @@ void HashTable<T, TraitsForT>::rehash(unsigned newCapacity)
{
newCapacity *= 2;
#ifdef HASHTABLE_DEBUG
printf("rehash to %u buckets\n", newCapacity);
kprintf("rehash to %u buckets\n", newCapacity);
#endif
auto* newBuckets = new Bucket[newCapacity];
auto* oldBuckets = m_buckets;
@ -263,11 +263,11 @@ void HashTable<T, TraitsForT>::rehash(unsigned newCapacity)
m_capacity = newCapacity;
#ifdef HASHTABLE_DEBUG
printf("reinsert %u buckets\n", oldCapacity);
kprintf("reinsert %u buckets\n", oldCapacity);
#endif
for (unsigned i = 0; i < oldCapacity; ++i) {
for (auto& value : oldBuckets[i].chain) {
insert(std::move(value));
insert(move(value));
}
}
@ -286,7 +286,7 @@ template<typename T, typename TraitsForT>
void HashTable<T, TraitsForT>::insert(T&& value)
{
auto& bucket = lookup(value);
bucket.chain.append(std::move(value));
bucket.chain.append(move(value));
}
template<typename T, typename TraitsForT>
@ -341,9 +341,9 @@ typename HashTable<T, TraitsForT>::Bucket& HashTable<T, TraitsForT>::lookup(cons
{
unsigned hash = TraitsForT::hash(value);
#ifdef HASHTABLE_DEBUG
printf("hash for ");
kprintf("hash for ");
TraitsForT::dump(value);
printf(" is %u\n", hash);
kprintf(" is %u\n", hash);
#endif
if (bucketIndex)
*bucketIndex = hash % m_capacity;
@ -355,9 +355,9 @@ const typename HashTable<T, TraitsForT>::Bucket& HashTable<T, TraitsForT>::looku
{
unsigned hash = TraitsForT::hash(value);
#ifdef HASHTABLE_DEBUG
printf("hash for ");
kprintf("hash for ");
TraitsForT::dump(value);
printf(" is %u\n", hash);
kprintf(" is %u\n", hash);
#endif
if (bucketIndex)
*bucketIndex = hash % m_capacity;
@ -367,14 +367,14 @@ const typename HashTable<T, TraitsForT>::Bucket& HashTable<T, TraitsForT>::looku
template<typename T, typename TraitsForT>
void HashTable<T, TraitsForT>::dump() const
{
printf("HashTable{%p} m_size=%u, m_capacity=%u, m_buckets=%p\n", this, m_size, m_capacity, m_buckets);
kprintf("HashTable{%p} m_size=%u, m_capacity=%u, m_buckets=%p\n", this, m_size, m_capacity, m_buckets);
for (unsigned i = 0; i < m_capacity; ++i) {
auto& bucket = m_buckets[i];
printf("Bucket %u\n", i);
kprintf("Bucket %u\n", i);
for (auto& e : bucket.chain) {
printf(" > ");
kprintf(" > ");
TraitsForT::dump(e);
printf("\n");
kprintf("\n");
}
}
}

View file

@ -4,6 +4,7 @@
#include <Kernel/StdLib.h>
#else
#include <cstring>
#include <cstdlib>
#include <utility>
#endif
@ -38,11 +39,12 @@ T&& move(T& arg)
}
template<typename T>
struct identity {
typedef T type;
struct Identity {
typedef T Type;
};
template<class T>
constexpr T&& forward(typename identity<T>::type& param)
constexpr T&& forward(typename Identity<T>::Type& param)
{
return static_cast<T&&>(param);
}
@ -63,6 +65,84 @@ void swap(T& a, U& b)
b = move(tmp);
}
template<bool B, class T = void>
struct EnableIf
{
};
template<class T>
struct EnableIf<true, T>
{
typedef T Type;
};
template<class T> struct RemoveConst { typedef T Type; };
template<class T> struct RemoveConst<const T> { typedef T Type; };
template<class T> struct RemoveVolatile { typedef T Type; };
template<class T> struct RemoveVolatile<const T> { typedef T Type; };
template<class T> struct RemoveCV {
typedef typename RemoveVolatile<typename RemoveConst<T>::Type>::Type Type;
};
template<class T, T v>
struct IntegralConstant {
static constexpr T value = v;
typedef T ValueType;
typedef IntegralConstant Type;
constexpr operator ValueType() const { return value; }
constexpr ValueType operator()() const { return value; }
};
typedef IntegralConstant<bool, false> FalseType;
typedef IntegralConstant<bool, true> TrueType;
template<class T>
struct __IsPointerHelper : FalseType { };
template<class T>
struct __IsPointerHelper<T*> : TrueType { };
template<class T>
struct IsPointer : __IsPointerHelper<typename RemoveCV<T>::Type> { };
template<class> struct IsFunction : FalseType { };
template<class Ret, class... Args> struct IsFunction<Ret(Args...)> : TrueType { };
template<class Ret, class... Args> struct IsFunction<Ret(Args......)> : TrueType { };
template<class Ret, class... Args> struct IsFunction<Ret(Args...) const> : TrueType { };
template<class Ret, class... Args> struct IsFunction<Ret(Args......) const> : TrueType { };
template<class Ret, class... Args> struct IsFunction<Ret(Args...) volatile> : TrueType { };
template<class Ret, class... Args> struct IsFunction<Ret(Args......) volatile> : TrueType { };
template<class Ret, class... Args> struct IsFunction<Ret(Args...) const volatile> : TrueType { };
template<class Ret, class... Args> struct IsFunction<Ret(Args......) const volatile> : TrueType { };
template<class Ret, class... Args> struct IsFunction<Ret(Args...) &> : TrueType { };
template<class Ret, class... Args> struct IsFunction<Ret(Args......) &> : TrueType { };
template<class Ret, class... Args> struct IsFunction<Ret(Args...) const &> : TrueType { };
template<class Ret, class... Args> struct IsFunction<Ret(Args......) const &> : TrueType { };
template<class Ret, class... Args> struct IsFunction<Ret(Args...) volatile &> : TrueType { };
template<class Ret, class... Args> struct IsFunction<Ret(Args......) volatile &> : TrueType { };
template<class Ret, class... Args> struct IsFunction<Ret(Args...) const volatile &> : TrueType { };
template<class Ret, class... Args> struct IsFunction<Ret(Args......) const volatile &> : TrueType { };
template<class Ret, class... Args> struct IsFunction<Ret(Args...) &&> : TrueType { };
template<class Ret, class... Args> struct IsFunction<Ret(Args......) &&> : TrueType { };
template<class Ret, class... Args> struct IsFunction<Ret(Args...) const &&> : TrueType { };
template<class Ret, class... Args> struct IsFunction<Ret(Args......) const &&> : TrueType { };
template<class Ret, class... Args> struct IsFunction<Ret(Args...) volatile &&> : TrueType { };
template<class Ret, class... Args> struct IsFunction<Ret(Args......) volatile &&> : TrueType { };
template<class Ret, class... Args> struct IsFunction<Ret(Args...) const volatile &&> : TrueType { };
template<class Ret, class... Args> struct IsFunction<Ret(Args......) const volatile &&> : TrueType { };
template<class T> struct IsRvalueReference : FalseType { };
template<class T> struct IsRvalueReference<T&&> : TrueType { };
template<class T> struct RemovePointer { typedef T Type; };
template<class T> struct RemovePointer<T*> { typedef T Type; };
template<class T> struct RemovePointer<T* const> { typedef T Type; };
template<class T> struct RemovePointer<T* volatile> { typedef T Type; };
template<class T> struct RemovePointer<T* const volatile> { typedef T Type; };
}
using AK::min;

View file

@ -1,5 +1,5 @@
#include "String.h"
#include <cstring>
#include "StdLib.h"
namespace AK {

View file

@ -5,7 +5,7 @@
#include "StringImpl.h"
#include "Traits.h"
#include "Vector.h"
#include <cstdio>
#include "kstdio.h"
namespace AK {
@ -20,7 +20,7 @@ public:
}
String(String&& other)
: m_impl(std::move(other.m_impl))
: m_impl(move(other.m_impl))
{
}
@ -40,7 +40,7 @@ public:
}
String(RetainPtr<StringImpl>&& impl)
: m_impl(std::move(impl))
: m_impl(move(impl))
{
}
@ -77,7 +77,7 @@ public:
String& operator=(String&& other)
{
if (this != &other) {
m_impl = std::move(other.m_impl);
m_impl = move(other.m_impl);
}
return *this;
}
@ -91,7 +91,7 @@ private:
template<>
struct Traits<String> {
static unsigned hash(const String& s) { return s.impl() ? s.impl()->hash() : 0; }
static void dump(const String& s) { printf("%s", s.characters()); }
static void dump(const String& s) { kprintf("%s", s.characters()); }
};
}

View file

@ -1,15 +1,14 @@
#include "StringImpl.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <new>
#include "StdLib.h"
#include "kmalloc.h"
namespace AK {
StringImpl& StringImpl::theEmptyStringImpl()
{
static StringImpl* s = new StringImpl(ConstructTheEmptyStringImpl);
static StringImpl* s = nullptr;
if (!s)
s = new StringImpl(ConstructTheEmptyStringImpl);
return *s;
}

View file

@ -1,6 +1,6 @@
#pragma once
#include <cstdio>
#include "kstdio.h"
namespace AK {
@ -12,19 +12,19 @@ struct Traits
template<>
struct Traits<int> {
static unsigned hash(int i) { return i; }
static void dump(int i) { printf("%d", i); }
static void dump(int i) { kprintf("%d", i); }
};
template<>
struct Traits<unsigned> {
static unsigned hash(unsigned u) { return u; }
static void dump(unsigned u) { printf("%u", u); }
static void dump(unsigned u) { kprintf("%u", u); }
};
template<typename T>
struct Traits<T*> {
static unsigned hash(const T* p) { return (unsigned)p; }
static void dump(const T* p) { printf("%p", p); }
static void dump(const T* p) { kprintf("%p", p); }
};
}

View file

@ -3,7 +3,6 @@
#include "Assertions.h"
#include "OwnPtr.h"
#include "kmalloc.h"
#include <new>
namespace AK {

View file

@ -1,6 +1,6 @@
#include <cstdio>
#include "SimpleMalloc.h"
#include <new>
#include "kmalloc.h"
#include <cstdlib>
#define USE_SYSTEM_MALLOC

View file

@ -1,13 +1,20 @@
#pragma once
#ifdef SERENITY_KERNEL
#include <Kernel/kmalloc.h>
#else
#include <new>
#include "Types.h"
extern "C" {
void* kcalloc(size_t nmemb, size_t size);
void* kmalloc(size_t size);
void* kmalloc(size_t size) __attribute__ ((malloc));
void kfree(void* ptr);
void* krealloc(void* ptr, size_t size);
}
#endif

15
AK/ktime.h Normal file
View file

@ -0,0 +1,15 @@
#pragma once
#ifdef SERENITY_KERNEL
inline time_t time(time_t* tloc)
{
if (tloc)
*tloc = 123;
return 123;
}
#else
#include <time.h>
#define ktime time
#define klocaltime localtime
#endif

54
Kernel/.bochsrc Normal file
View file

@ -0,0 +1,54 @@
# configuration file generated by Bochs
plugin_ctrl: unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true
config_interface: textconfig
display_library: x
memory: host=32, guest=32
romimage: file="/usr/local/share/bochs/BIOS-bochs-latest", address=0x00000000, options=none
vgaromimage: file="/usr/local/share/bochs/VGABIOS-lgpl-latest"
boot: floppy
floppy_bootsig_check: disabled=0
floppya: type=1_44, 1_44=".floppy-image", status=inserted, write_protected=0
# no floppyb
ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=disk, path="_fs_contents", mode=flat, cylinders=0, heads=0, spt=0, model="Generic 1234", biosdetect=auto, translation=auto
ata0-slave: type=none
ata1: enabled=true, ioaddr1=0x170, ioaddr2=0x370, irq=15
ata1-master: type=none
ata1-slave: type=none
ata2: enabled=false
ata3: enabled=false
optromimage1: file=none
optromimage2: file=none
optromimage3: file=none
optromimage4: file=none
optramimage1: file=none
optramimage2: file=none
optramimage3: file=none
optramimage4: file=none
pci: enabled=1, chipset=i440fx
vga: extension=vbe, update_freq=5, realtime=1
cpu: count=1, ips=4000000, model=bx_generic, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0
cpuid: level=6, stepping=3, model=3, family=6, vendor_string="GenuineIntel", brand_string=" Intel(R) Pentium(R) 4 CPU "
cpuid: mmx=true, apic=xapic, simd=sse2, sse4a=false, misaligned_sse=false, sep=true
cpuid: movbe=false, adx=false, aes=false, sha=false, xsave=false, xsaveopt=false, smep=false
cpuid: smap=false, mwait=true
print_timestamps: enabled=0
port_e9_hack: enabled=0
private_colormap: enabled=0
clock: sync=none, time0=local, rtc_sync=0
# no cmosimage
log: -
logprefix: %t%e%d
debug: action=ignore
info: action=report
error: action=report
panic: action=ask
keyboard: type=mf, serial_delay=250, paste_delay=100000, user_shortcut=none
mouse: type=ps2, enabled=false, toggle=ctrl+mbutton
speaker: enabled=true, mode=system
parport1: enabled=true, file=none
parport2: enabled=false
com1: enabled=true, mode=null
com2: enabled=false
com3: enabled=false
com4: enabled=false

View file

@ -4,42 +4,57 @@
[bits 16]
boot:
push cs
pop ds
xor bx, bx
mov ah, 0x0e
mov si, message
cli
mov ax, 0x8000
mov ss, ax
mov sp, 0xffff
push cs
pop ds
xor bx, bx
mov ah, 0x0e
mov si, message
lodsb
.lewp:
int 0x10
int 0x10
lodsb
cmp al, 0
jne .lewp
cmp al, 0
jne .lewp
mov bx, 0x1000
mov es, bx
xor bx, bx ; Load kernel @ 0x10000
mov bx, 0x1000
mov es, bx
xor bx, bx ; Load kernel @ 0x10000
mov cx, word [cur_lba]
.sector_loop:
call convert_lba_to_chs
mov ah, 0x02 ; cmd 0x02 - Read Disk Sectors
mov al, 72 ; 72 sectors (max allowed by bochs BIOS)
mov ch, 0 ; track 0
mov cl, 10 ; sector 10
mov dh, 0 ; head 0
mov al, 1 ; 1 sector at a time
mov dl, 0 ; drive 0 (fd0)
int 0x13
jc fug
mov ah, 0x02
mov al, 32
add bx, 0x9000
mov ch, 2
mov cl, 10
mov dh, 0
mov dl, 0
int 0x13
mov ah, 0x0e
mov al, '.'
int 0x10
jc fug
inc word [cur_lba]
mov cx, word [cur_lba]
cmp cx, 300
jz .sector_loop_end
mov bx, es
add bx, 0x20
mov es, bx
xor bx, bx
jmp .sector_loop
.sector_loop_end:
call durk
lgdt [cs:test_gdt_ptr]
@ -49,6 +64,20 @@ boot:
jmp 0x08:pmode
durk:
push cs
pop ds
xor bx, bx
mov ah, 0x0e
mov si, msg_sectors_loaded
lodsb
.lewp:
int 0x10
lodsb
cmp al, 0
jne .lewp
ret
pmode:
[bits 32]
mov ax, 0x10
@ -60,6 +89,14 @@ pmode:
mov ss, ax
mov esp, 0x2000
xor eax, eax
xor ebx, ebx
xor ecx, ecx
xor edx, edx
xor ebp, ebp
xor esi, esi
xor edi, edi
jmp 0x10000
hlt
@ -96,6 +133,55 @@ fug:
cli
hlt
; Input:
;
; AX = LBA
;
; Output:
;
; CX and DH = C/H/S address formatted for Int13,2
; CL = sector (LBA % sectors_per_track) + 1
;
; 1.44M floppy stats:
; (sectors_per_track: 18)
; (heads: 2)
; (sectors: 2880)
convert_lba_to_chs:
mov ax, cx
; AX = LBA/spt, DX = LBA%spt
xor dx, dx
div word [sectors_per_track]
; CL = sector (LBA % sectors_per_track) + 1
mov cl, dl
inc cl
; CH = track (LBA / sectors_per_track) / heads
mov ch, al
shr ch, 1
; AX = (LBA/spt)/heads, DX = (LBA/spt)%heads
xor dx, dx
div word [heads]
; DH = sector (LBA / sectors_per_track) % heads
mov dh, dl
ret
cur_lba:
dw 9
sectors_per_track:
dw 18
heads:
dw 2
msg_sectors_loaded:
db "sectors loaded", 0x0d, 0x0a, 0
message:
db "boot!", 0x0d, 0x0a, 0

View file

@ -1,74 +0,0 @@
#pragma once
#include "ext2fs.h"
#include "OwnPtr.h"
#include "DataBuffer.h"
#include "FileSystem.h"
static const size_t bytesPerSector = 512;
class Ext2VirtualNode;
class Ext2FileSystem {
public:
Ext2FileSystem() { }
~Ext2FileSystem();
void initialize();
RefPtr<DataBuffer> loadFile(ext2_dir_entry*);
ext2_inode* findInode(DWORD index);
ext2_inode* findPath(const String& path, DWORD& inodeIndex);
private:
friend class Ext2VirtualNode;
void readSuperBlock();
void readBlockGroup(DWORD);
void readInodeTable(DWORD);
void dumpDirectory(ext2_inode&);
void dumpFile(ext2_inode&);
template<typename F> void forEachBlockIn(ext2_inode&, F func);
template<typename F> void traverseDirectory(ext2_dir_entry&, DWORD blockCount, F);
template<typename F> void traverseDirectory(ext2_inode&, F);
RefPtr<DataBuffer> readFile(ext2_inode&);
RefPtr<DataBuffer> readBlocks(DWORD blockIndex, BYTE count);
void readDiskSector(DWORD sectorIndex, BYTE* buffer);
size_t blockSize() const { return 1024 << m_superBlock->s_log_frag_size; }
size_t sectorsPerBlock() const { return blockSize() / bytesPerSector; }
DWORD blockGroupForInode(DWORD inode) const;
DWORD toInodeTableIndex(DWORD inode) const;
ext2_super_block& superBlock() { ASSERT(m_superBlock); return *m_superBlock; }
OwnPtr<ext2_super_block> m_superBlock;
ext2_inode* m_root { nullptr }; // raw pointer into one of the m_inodeTables
size_t m_blockGroupCount { 0 };
ext2_group_descriptor* m_groupTable { nullptr };
ext2_inode** m_inodeTables { nullptr };
};
class Ext2VirtualNode final : public FileSystem::VirtualNode {
public:
static RefPtr<Ext2VirtualNode> create(DWORD index, String&& path, Ext2FileSystem&, DWORD inodeNumber);
virtual ~Ext2VirtualNode();
virtual size_t size() const override { return m_inode.i_size; }
virtual uid_t uid() const override { return m_inode.i_uid; }
virtual gid_t gid() const override { return m_inode.i_gid; }
virtual size_t mode() const override { return m_inode.i_mode; }
virtual size_t read(BYTE* outbuf, size_t start, size_t maxLength) override;
private:
Ext2VirtualNode(DWORD index, String&& path, Ext2FileSystem&, ext2_inode&, DWORD inodeNumber);
Ext2FileSystem& m_fileSystem;
ext2_inode& m_inode;
DWORD m_inodeNumber { 0 };
};

View file

@ -3,9 +3,9 @@
#include "Assertions.h"
#include "types.h"
template<typename T> class DoublyLinkedListNode {
template<typename T> class InlineLinkedListNode {
public:
DoublyLinkedListNode();
InlineLinkedListNode();
void setPrev(T*);
void setNext(T*);
@ -14,35 +14,35 @@ public:
T* next() const;
};
template<typename T> inline DoublyLinkedListNode<T>::DoublyLinkedListNode()
template<typename T> inline InlineLinkedListNode<T>::InlineLinkedListNode()
{
setPrev(0);
setNext(0);
}
template<typename T> inline void DoublyLinkedListNode<T>::setPrev(T* prev)
template<typename T> inline void InlineLinkedListNode<T>::setPrev(T* prev)
{
static_cast<T*>(this)->m_prev = prev;
}
template<typename T> inline void DoublyLinkedListNode<T>::setNext(T* next)
template<typename T> inline void InlineLinkedListNode<T>::setNext(T* next)
{
static_cast<T*>(this)->m_next = next;
}
template<typename T> inline T* DoublyLinkedListNode<T>::prev() const
template<typename T> inline T* InlineLinkedListNode<T>::prev() const
{
return static_cast<const T*>(this)->m_prev;
}
template<typename T> inline T* DoublyLinkedListNode<T>::next() const
template<typename T> inline T* InlineLinkedListNode<T>::next() const
{
return static_cast<const T*>(this)->m_next;
}
template<typename T> class DoublyLinkedList {
template<typename T> class InlineLinkedList {
public:
DoublyLinkedList() { }
InlineLinkedList() { }
bool isEmpty() const { return !m_head; }
size_t size() const;
@ -56,14 +56,14 @@ public:
void prepend(T*);
void append(T*);
void remove(T*);
void append(DoublyLinkedList<T>&);
void append(InlineLinkedList<T>&);
private:
T* m_head { nullptr };
T* m_tail { nullptr };
};
template<typename T> inline size_t DoublyLinkedList<T>::size() const
template<typename T> inline size_t InlineLinkedList<T>::size() const
{
size_t size = 0;
for (T* node = m_head; node; node = node->next())
@ -71,13 +71,13 @@ template<typename T> inline size_t DoublyLinkedList<T>::size() const
return size;
}
template<typename T> inline void DoublyLinkedList<T>::clear()
template<typename T> inline void InlineLinkedList<T>::clear()
{
m_head = 0;
m_tail = 0;
}
template<typename T> inline void DoublyLinkedList<T>::prepend(T* node)
template<typename T> inline void InlineLinkedList<T>::prepend(T* node)
{
if (!m_head) {
ASSERT(!m_tail);
@ -95,7 +95,7 @@ template<typename T> inline void DoublyLinkedList<T>::prepend(T* node)
m_head = node;
}
template<typename T> inline void DoublyLinkedList<T>::append(T* node)
template<typename T> inline void InlineLinkedList<T>::append(T* node)
{
if (!m_tail) {
ASSERT(!m_head);
@ -113,7 +113,7 @@ template<typename T> inline void DoublyLinkedList<T>::append(T* node)
m_tail = node;
}
template<typename T> inline void DoublyLinkedList<T>::remove(T* node)
template<typename T> inline void InlineLinkedList<T>::remove(T* node)
{
if (node->prev()) {
ASSERT(node != m_head);
@ -132,7 +132,7 @@ template<typename T> inline void DoublyLinkedList<T>::remove(T* node)
}
}
template<typename T> inline T* DoublyLinkedList<T>::removeHead()
template<typename T> inline T* InlineLinkedList<T>::removeHead()
{
T* node = head();
if (node)
@ -140,7 +140,7 @@ template<typename T> inline T* DoublyLinkedList<T>::removeHead()
return node;
}
template<typename T> inline void DoublyLinkedList<T>::append(DoublyLinkedList<T>& other)
template<typename T> inline void InlineLinkedList<T>::append(InlineLinkedList<T>& other)
{
if (!other.head())
return;

View file

@ -14,10 +14,8 @@ KERNEL_OBJS = \
PIC.o \
Syscall.o \
DataBuffer.o \
String.o \
panel.o \
Disk.o \
fs.o \
Userspace.o \
IDEDiskDevice.o
@ -27,9 +25,16 @@ VFS_OBJS = \
../VirtualFileSystem/NullDevice.o \
../VirtualFileSystem/FullDevice.o \
../VirtualFileSystem/ZeroDevice.o \
../VirtualFileSystem/RandomDevice.o
../VirtualFileSystem/RandomDevice.o \
../VirtualFileSystem/FileSystem.o \
../VirtualFileSystem/DiskBackedFileSystem.o \
../VirtualFileSystem/Ext2FileSystem.o
OBJS = $(KERNEL_OBJS) $(VFS_OBJS)
AK_OBJS = \
../AK/String.o \
../AK/StringImpl.o
OBJS = $(KERNEL_OBJS) $(VFS_OBJS) $(AK_OBJS)
NASM = nasm
KERNEL = kernel

View file

@ -1,78 +0,0 @@
#pragma once
#include "types.h"
template<typename T>
class OwnPtr {
public:
OwnPtr() { }
explicit OwnPtr(T* ptr) : m_ptr(ptr) { }
OwnPtr(OwnPtr&& other) : m_ptr(other.leakPtr()) { }
template<typename U> OwnPtr(OwnPtr<U>&& other) : m_ptr(static_cast<T*>(other.leakPtr())) { }
~OwnPtr() { clear(); }
OwnPtr& operator=(OwnPtr&& other)
{
if (this != &other) {
delete m_ptr;
m_ptr = other.leakPtr();
}
return *this;
}
template<typename U>
OwnPtr& operator=(OwnPtr<U>&& other)
{
if (this != static_cast<void*>(&other)) {
delete m_ptr;
m_ptr = other.leakPtr();
}
return *this;
}
OwnPtr& operator=(T* ptr)
{
if (m_ptr != ptr)
delete m_ptr;
m_ptr = ptr;
return *this;
}
void clear()
{
delete m_ptr;
m_ptr = nullptr;
}
bool operator!() const { return !m_ptr; }
typedef T* OwnPtr::*UnspecifiedBoolType;
operator UnspecifiedBoolType() const { return m_ptr ? &OwnPtr::m_ptr : nullptr; }
T* leakPtr()
{
T* leakedPtr = m_ptr;
m_ptr = nullptr;
return leakedPtr;
}
T* ptr() { return m_ptr; }
const T* ptr() const { return m_ptr; }
T* operator->() { return m_ptr; }
const T* operator->() const { return m_ptr; }
T& operator*() { return *m_ptr; }
const T& operator*() const { return *m_ptr; }
operator bool() { return !!m_ptr; }
private:
T* m_ptr = nullptr;
};
template<class T, class... Args> inline OwnPtr<T>
make(Args&&... args)
{
return OwnPtr<T>(new T(forward<Args>(args)...));
}

View file

@ -49,6 +49,15 @@ char* strdup(const char *str)
return s;
}
int memcmp(const void* v1, const void* v2, size_t n)
{
size_t m;
const char* s1 = (const char*)v1;
const char* s2 = (const char*)v2;
for (m = 0; m < n && *s1 == *s2; ++s1, ++s2);
return m == n ? 0 : -1;
}
extern "C" void __cxa_pure_virtual()
{
ASSERT_NOT_REACHED();

View file

@ -2,9 +2,10 @@
#include "types.h"
void memcpy(void *, const void *, DWORD);
void strcpy(char *, const char *);
int strcmp(char const *, const char *);
DWORD strlen(const char *) PURE;
void *memset(void *, BYTE, DWORD);
char *strdup(const char *);
void memcpy(void*, const void*, DWORD);
void strcpy(char*, const char*);
int strcmp(char const*, const char*);
DWORD strlen(const char*);
void *memset(void*, BYTE, DWORD);
char *strdup(const char*);
int memcmp(const void*, const void*, size_t);

View file

@ -1,86 +0,0 @@
#include "String.h"
#include <AK/StdLib.h>
String::String()
{
}
String::String(const char* characters)
: m_data(DataBuffer::copy((const BYTE*)characters, strlen(characters) + 1))
{
}
String::String(const char* characters, size_t length)
: m_data(DataBuffer::createUninitialized(length + 1))
{
memcpy(m_data->data(), characters, length);
m_data->data()[length] = '\0';
}
String::String(String&& other)
: m_data(move(other.m_data))
{
}
String::String(const String& other)
: m_data(other.m_data)
{
}
String& String::operator=(const String& other)
{
if (this == &other)
return *this;
m_data = other.m_data;
return *this;
}
String& String::operator=(const String&& other)
{
if (this == &other)
return *this;
m_data = move(other.m_data);
return *this;
}
String::~String()
{
}
bool String::operator==(const String& other) const
{
if (length() != other.length())
return false;
return strcmp(characters(), other.characters()) == 0;
}
String String::substring(size_t start, size_t length) const
{
ASSERT(start + length <= m_data->length());
// FIXME: This needs some input bounds checking.
auto buffer = DataBuffer::createUninitialized(length + 1);
memcpy(buffer->data(), characters() + start, length);
buffer->data()[length] = '\0';
String s;
s.m_data = move(buffer);
return s;
}
Vector<String> String::split(char separator) const
{
Vector<String> v;
size_t substart = 0;
for (size_t i = 0; i < length(); ++i) {
char ch = characters()[i];
if (ch == separator) {
size_t sublen = i - substart;
if (sublen != 0)
v.append(substring(substart, sublen));
substart = i + 1;
}
}
size_t taillen = length() - 1 - substart;
if (taillen != 0)
v.append(substring(substart, taillen));
return v;
}

View file

@ -1,31 +0,0 @@
#pragma once
#include "DataBuffer.h"
#include "Vector.h"
class String {
public:
String();
String(const char* characters);
String(const char* characters, size_t length);
String(String&&);
String(const String&);
String& operator=(const String&);
String& operator=(const String&&);
~String();
bool isEmpty() const { return m_data ? m_data->isEmpty() : true; }
size_t length() const { return m_data ? m_data->length() : 0; }
char operator[](size_t i) const { return (char)m_data->data()[i]; }
const char* characters() const { return m_data ? (const char*)m_data->data() : nullptr; }
bool operator==(const String&) const;
Vector<String> split(char separator) const;
String substring(size_t start, size_t length) const;
private:
RefPtr<DataBuffer> m_data;
};

View file

@ -11,7 +11,7 @@ Task* current;
Task* s_kernelTask;
static pid_t next_pid;
static DoublyLinkedList<Task>* s_tasks;
static InlineLinkedList<Task>* s_tasks;
static bool contextSwitch(Task*);
@ -46,7 +46,7 @@ void Task::initialize()
{
current = nullptr;
next_pid = 0;
s_tasks = new DoublyLinkedList<Task>;
s_tasks = new InlineLinkedList<Task>;
s_kernelTask = new Task(0, "idle", IPC::Handle::Any, Task::Ring0);
redoKernelTaskTSS();
loadTaskRegister(s_kernelTask->selector());
@ -415,12 +415,14 @@ int Task::sys$open(const char* path, size_t pathLength)
FileHandle* Task::openFile(String&& path)
{
#if 0
auto vnode = FileSystem::createVirtualNode(move(path));
if (!vnode) {
kprintf("createVirtualNode failed\n");
return nullptr;
}
#if 1
#endif
#if 0
FileHandle* fh = new FileHandle;
kprintf("made new FileHandle\n");
fh->m_fd = m_fileHandles.size();

View file

@ -2,18 +2,18 @@
#include "types.h"
#include "IPC.h"
#include "DoublyLinkedList.h"
#include "String.h"
#include "InlineLinkedList.h"
#include <AK/String.h>
#include "TSS.h"
#include "Vector.h"
#include <AK/Vector.h>
#include "i386.h"
//#define TASK_SANITY_CHECKS
class FileHandle;
class Task : public DoublyLinkedListNode<Task> {
friend class DoublyLinkedListNode<Task>;
class Task : public InlineLinkedListNode<Task> {
friend class InlineLinkedListNode<Task>;
public:
#ifdef TASK_SANITY_CHECKS
static void checkSanity(const char* msg = nullptr);

View file

@ -1,90 +0,0 @@
#pragma once
#include "Assertions.h"
#include "kmalloc.h"
#define SANITIZE_VECTOR
template<typename T>
class Vector {
public:
Vector() { }
~Vector();
Vector(const Vector&&);
Vector& operator=(const Vector&&);
bool isEmpty() const { return m_size == 0; }
size_t size() const { return m_size; }
size_t capacity() const { return m_capacity; }
void append(T&&);
void clear();
const T& operator[](size_t i) const { return m_elements[i]; }
T& operator[](size_t i) { return m_elements[i]; }
private:
Vector(const Vector&) = delete;
Vector& operator=(const Vector&) = delete;
void ensureCapacity(size_t);
T* m_elements { nullptr };
size_t m_size { 0 };
size_t m_capacity { 0 };
};
template<typename T>
Vector<T>::~Vector()
{
clear();
#ifdef SANITIZE_VECTOR
m_elements = (T*)0xdddddddd;
m_size = 0x8a8a8a8a;
m_capacity = 0xa8a8a8a8;
#endif
}
template<typename T>
void Vector<T>::clear()
{
if (!m_elements)
return;
for (size_t i = 0; i < m_size; ++i) {
m_elements[i].~T();
}
kfree(m_elements);
m_elements = nullptr;
m_size = 0;
m_capacity = 0;
}
template<typename T>
void Vector<T>::append(T&& element)
{
ensureCapacity(m_size + 1);
new (&m_elements[m_size]) T(move(element));
++m_size;
}
template<typename T>
void Vector<T>::ensureCapacity(size_t neededCapacity)
{
if (neededCapacity <= m_capacity)
return;
size_t newCapacity = (neededCapacity + 8) & ~7;
// FIXME: We need to support further growth here, jeez...
ASSERT(m_capacity == 0);
ASSERT(!m_elements);
m_capacity = newCapacity;
T* newElements = (T*)kmalloc(m_capacity * sizeof(T));
#ifdef SANITIZE_VECTOR
memset(newElements, 0x66, m_capacity * sizeof(T));
#endif
if (m_elements) {
memcpy(newElements, m_elements, m_size * sizeof(T));
kfree(m_elements);
}
m_elements = newElements;
}

View file

@ -1,451 +0,0 @@
#include "Disk.h"
#include "Task.h"
#include "VGA.h"
#include "kmalloc.h"
#include "Ext2FileSystem.h"
#include "i386.h"
#include "StdLib.h"
#include "OwnPtr.h"
#include "FileSystem.h"
#include "String.h"
//#define FS_DEBUG
Ext2FileSystem::~Ext2FileSystem()
{
kprintf("fs: kill Ext2FileSystem\n");
ASSERT(false);
kfree(m_groupTable);
m_groupTable = nullptr;
if (m_inodeTables) {
for (DWORD i = 0; i < m_blockGroupCount; ++i)
delete [] m_inodeTables[i];
}
delete [] m_inodeTables;
m_inodeTables = nullptr;
}
static Ext2FileSystem* fileSystem;
void Ext2FileSystem::readDiskSector(DWORD sectorIndex, BYTE* buffer)
{
Task::checkSanity("Ext2FileSystem::readDiskSector");
bool success = Disk::readSectors(sectorIndex, 1, buffer);
(void) success;
}
RefPtr<DataBuffer> Ext2FileSystem::readBlocks(DWORD blockIndex, BYTE count)
{
Task::checkSanity("readBlocks");
if (!m_superBlock) {
kprintf("fs: Attempt to read blocks without superblock!\n");
HANG;
}
#ifdef FS_DEBUG
kprintf("Read %u block(s) starting at %u\n", count, blockIndex);
#endif
// FIXME: This is broken up into 1-sector reads because the disk task can't handle multi-sector reads yet.
auto buffer = DataBuffer::createUninitialized(count * sectorsPerBlock() * bytesPerSector);
BYTE* bufptr = (BYTE*)buffer->data();
for (DWORD i = 0; i < count; ++i) {
readDiskSector(((blockIndex + i) * sectorsPerBlock()) + 0, bufptr);
readDiskSector(((blockIndex + i) * sectorsPerBlock()) + 1, bufptr + bytesPerSector);
bufptr += bytesPerSector * 2;
}
return buffer;
}
void Ext2FileSystem::readSuperBlock()
{
ASSERT(!m_superBlock);
ASSERT(!m_groupTable);
m_superBlock = make<ext2_super_block>();
readDiskSector(2, (BYTE*)m_superBlock.ptr());
if (m_superBlock->s_magic != EXT2_MAGIC) {
kprintf("fs: PANIC! No ext2 filesystem found\n");
HANG;
}
kprintf("fs: ext2 filesystem found -- %u inodes, %u blocks\n",
m_superBlock->s_inodes_count,
m_superBlock->s_blocks_count);
const BYTE* u = m_superBlock->s_uuid;
kprintf("fs: UUID: %b%b%b%b-%b%b-%b%b-%b%b-%b%b%b%b%b%b\n",
u[0], u[1], u[2], u[3], u[4], u[5], u[6], u[7], u[8],
u[9], u[10], u[11], u[12], u[13], u[14], u[15], u[16]);
#ifdef FS_DEBUG
kprintf("fs: Block size is %u bytes\n", 1024 << m_superBlock->s_log_frag_size);
kprintf("fs: Blocks per group: %u\n", m_superBlock->s_blocks_per_group);
#endif
m_blockGroupCount = m_superBlock->s_blocks_count / m_superBlock->s_blocks_per_group;
if ((m_superBlock->s_blocks_count % m_superBlock->s_blocks_per_group) != 0)
++m_blockGroupCount;
m_inodeTables = new ext2_inode*[m_blockGroupCount];
memset(m_inodeTables, 0, sizeof(ext2_inode*) * m_blockGroupCount);
}
void Ext2FileSystem::readBlockGroup(DWORD index)
{
Task::checkSanity("readBlockGroup");
DWORD superBlockBI = m_superBlock->s_first_data_block + (m_superBlock->s_blocks_per_group * index);
DWORD descriptorTableBI = superBlockBI + 1;
//DWORD blockBitmapBI = descriptorTableBI + 1;
//DWORD inodeBitmapBI = blockBitmapBI + 1;
//DWORD inodeTableBI = inodeBitmapBI + 1;
auto buffer = readBlocks(descriptorTableBI, 1);
#ifdef FS_DEBUG
kprintf("Inodes per group = %u\n", superBlock().s_inodes_per_group);
kprintf("First data block = %u\n", superBlock().s_first_data_block);
#endif
m_groupTable = (ext2_group_descriptor*)kmalloc(blockSize());
memcpy(m_groupTable, buffer->data(), buffer->length());
#ifdef FS_DEBUG
kprintf("[%u] block bitmap: %u\n", index, m_groupTable[index].bg_block_bitmap);
kprintf("[%u] inode bitmap: %u\n", index, m_groupTable[index].bg_inode_bitmap);
kprintf("[%u] inode table: %u\n", index, m_groupTable[index].bg_inode_table);
#endif
}
template<typename F>
void Ext2FileSystem::traverseDirectory(ext2_dir_entry& firstEntry, DWORD blockCount, F func)
{
Task::checkSanity("traverseDirectory1");
auto* entry = &firstEntry;
char* name = new char[EXT2_NAME_LEN + 1];
auto* end = (ext2_dir_entry*)((BYTE*)entry + blockCount * blockSize());
while (entry < end) {
if (entry->d_inode != 0) {
memcpy(name, entry->d_name, entry->d_name_len);
name[entry->d_name_len] = 0;
func(name, *entry);
}
entry = (ext2_dir_entry*)((BYTE *)entry + entry->d_rec_len);
}
delete [] name;
}
void Ext2FileSystem::readInodeTable(DWORD blockGroup)
{
Task::checkSanity("readInodeTable");
ext2_inode*& inodeTable = m_inodeTables[blockGroup];
if (!inodeTable)
inodeTable = new ext2_inode[m_superBlock->s_inodes_per_group];
DWORD inodeTableBlocks = (m_superBlock->s_inodes_per_group * sizeof(ext2_inode)) / blockSize();
// kprintf("inode table blocks: %u\n", inodeTableBlocks);
auto buffer = readBlocks(m_groupTable[blockGroup].bg_inode_table, inodeTableBlocks);
memcpy(inodeTable, buffer->data(), m_superBlock->s_inodes_per_group * sizeof(ext2_inode));
m_root = &inodeTable[1];
#ifdef FS_DEBUG
kprintf("Root directory inode:\n");
kprintf("sizeof(ext2_inode): %u\n", sizeof(ext2_inode));
kprintf("sizeof(ext2_dir_entry): %u\n", sizeof(ext2_dir_entry));
kprintf("Mode: %u, Owner: %u/%u, Size: %u\n", m_root->i_mode, m_root->i_uid, m_root->i_gid, m_root->i_size);
kprintf("Directory blocks: { ");
for (DWORD i = 0; i < 12; ++i) {
kprintf( "%u ", m_root->i_block[i] );
}
kprintf("}\n");
#endif
}
template<typename F>
void Ext2FileSystem::forEachBlockIn(ext2_inode& inode, F func)
{
Task::checkSanity("forEachBlockIn");
DWORD blockCount = inode.i_blocks / (2 << m_superBlock->s_log_block_size);
// FIXME: Support indirect blocks
for (DWORD i = 0; i < blockCount; ++i) {
//kprintf(" [blk %u]\n", inode.i_block[i]);
auto buffer = readBlocks(inode.i_block[i], 1);
func(move(buffer));
}
}
DWORD Ext2FileSystem::blockGroupForInode(DWORD inode) const
{
// FIXME: Implement
(void)inode;
return 0;
}
DWORD Ext2FileSystem::toInodeTableIndex(DWORD inode) const
{
// FIXME: Implement
return inode - 1;
}
ext2_inode* Ext2FileSystem::findInode(DWORD index)
{
if (index >= m_superBlock->s_inodes_count)
return nullptr;
return &m_inodeTables[blockGroupForInode(index)][toInodeTableIndex(index)];
}
ext2_inode* Ext2FileSystem::findPath(const String& path, DWORD& inodeIndex)
{
Task::checkSanity("findPath entry");
ASSERT(m_root);
Task::checkSanity("findPath entry2");
if (path.isEmpty())
return nullptr;
if (path[0] != '/')
return nullptr;
ext2_inode* dir = m_root;
Task::checkSanity("findPath pre-vector");
Vector<String> pathParts = path.split('/');
Task::checkSanity("findPath post-split");
for (size_t i = 0; i < pathParts.size(); ++i) {
//kprintf("[%u] %s\n", i, pathParts[i].characters());
auto& part = pathParts[i];
bool foundPart = false;
//kprintf("looking for part '%s' in inode{%p}\n", part.characters(), dir);
traverseDirectory(*dir, [&] (const char* name, ext2_dir_entry& entry) {
//kprintf(" ?= %s\n", name);
if (String(name) == part) {
foundPart = true;
//kprintf("found part ==> inode %u (type %b)\n", entry.d_inode, entry.d_file_type);
dir = findInode(entry.d_inode);
inodeIndex = entry.d_inode;
// FIXME: don't try to traverse files as if they're directories
// FIXME: need a way to skip the remaining traverseDirectory() callbacks
}
});
if (!foundPart)
return nullptr;
}
return dir;
}
template<typename F>
void Ext2FileSystem::traverseDirectory(ext2_inode& inode, F func)
{
Task::checkSanity("traverseDirectory2");
//kprintf("in traverseDir\n");
forEachBlockIn(inode, [this, &func] (RefPtr<DataBuffer>&& data) {
auto* directory = (ext2_dir_entry*)data->data();
traverseDirectory<F>(*directory, 1, func);
});
//kprintf("out traverseDir\n");
}
RefPtr<DataBuffer> Ext2FileSystem::readFile(ext2_inode& inode)
{
auto buffer = DataBuffer::createUninitialized(inode.i_size + 1);
BYTE* bufptr = buffer->data();
size_t dataRemaining = inode.i_size;
forEachBlockIn(inode, [this, &bufptr, &dataRemaining] (RefPtr<DataBuffer>&& data) {
memcpy(bufptr, data->data(), min(dataRemaining, data->length()));
dataRemaining -= blockSize();
bufptr += blockSize();
});
// HACK: This is silly, but let's just null terminate here for comfort.
buffer->data()[buffer->length() - 1] = '\0';
return buffer;
}
void Ext2FileSystem::dumpFile(ext2_inode& inode)
{
auto buffer = readFile(inode);
kprintf("%s", buffer->data());
}
void Ext2FileSystem::dumpDirectory(ext2_inode& inode)
{
traverseDirectory(inode, [this] (const char* name, ext2_dir_entry& entry) {
bool isDirectory = entry.d_file_type == EXT2_FT_DIR;
ext2_inode& inode = m_inodeTables[blockGroupForInode(entry.d_inode)][toInodeTableIndex(entry.d_inode)];
kprintf("i:%x %b %u:%u %x %s%s\n",
entry.d_inode,
entry.d_file_type,
inode.i_uid,
inode.i_gid,
inode.i_size,
name,
isDirectory ? "/" : "");
});
}
#if 0
void Ext2FileSystem::readRoot()
{
auto buffer = readBlocks(m_root->i_block[0], 1);
auto* dir_block = (ext2_dir_entry*)buffer.data();
traverseDirectory(dir_block, [this] (const char* name, ext2_dir_entry* entry) {
if (!strcmp(name, "test2")) {
auto test2_entry = loadFile(entry);
new Task((void (*)())test2_entry.data(), "test2", IPC::Handle::Any, Task::Ring3);
// HACK: Don't delete the code we just started running :)
test2_entry.leak();
} else if (!strcmp( name, "motd.txt")) {
auto motd_txt = loadFile(entry);
kprintf("===============================================\n\n");
vga_set_attr(0x03);
kprintf("%s\n", motd_txt.data());
vga_set_attr(0x07);
kprintf("===============================================\n");
}
});
}
#endif
void Ext2FileSystem::initialize()
{
readSuperBlock();
readBlockGroup(0);
readInodeTable(0);
#ifdef FS_DEBUG
dumpDirectory(*m_root);
#endif
DWORD inodeIndex;
auto* file = findPath("/motd.txt", inodeIndex);
dumpFile(*file);
}
RefPtr<DataBuffer> Ext2FileSystem::loadFile(ext2_dir_entry* dirent)
{
Task::checkSanity("loadFile");
DWORD inode_group = (dirent->d_inode - 1) / superBlock().s_inodes_per_group;
#ifdef FS_DEBUG
kprintf("inode: %u (group %u)\n", dirent->d_inode, inode_group);
kprintf("inode table at block %u\n", m_groupTable[inode_group].bg_inode_table);
#endif
// Calculate interesting offset into inode block.
DWORD inode_index = (dirent->d_inode - 1) % superBlock().s_inodes_per_group;
// Load the relevant inode block.
auto buffer = readBlocks(m_groupTable[inode_group].bg_inode_table, 4);
auto* inode_table = (ext2_inode*)buffer->data();
#ifdef FS_DEBUG
kprintf("inode index: %u\n", inode_index);
#endif
ext2_inode* inode = &inode_table[inode_index];
#ifdef FS_DEBUG
kprintf("Mode: %u UID: %u GID: %u Size: %u Block0: %u\n", inode->i_mode, inode->i_uid, inode->i_gid, inode->i_size, inode->i_block[0]);
#endif
auto fileContents = readBlocks(inode->i_block[0], 1);
#ifdef FS_DEBUG
kprintf("File @ %p\n", fileContents->data());
kprintf("File contents: %b %b %b %b %b\n",
(*fileContents)[0],
(*fileContents)[1],
(*fileContents)[2],
(*fileContents)[3],
(*fileContents)[4]);
#endif
return fileContents;
}
RefPtr<Ext2VirtualNode> Ext2VirtualNode::create(DWORD index, String&& path, Ext2FileSystem& fs, DWORD inodeNumber)
{
Task::checkSanity("enter E2VN::create");
ext2_inode* inode = fs.findInode(inodeNumber);
Task::checkSanity("post findInode");
if (!inode)
return nullptr;
auto* v = new Ext2VirtualNode(index, move(path), fs, *inode, inodeNumber);
kprintf("v=%p\n", v);
auto r = adoptRef(v);
kprintf("adopted(v)=%p\n", r.ptr());
return r;
}
Ext2VirtualNode::Ext2VirtualNode(DWORD index, String&& path, Ext2FileSystem& fs, ext2_inode& inode, DWORD inodeNumber)
: VirtualNode(index, move(path))
, m_fileSystem(fs)
, m_inode(inode)
, m_inodeNumber(inodeNumber)
{
Task::checkSanity("Ext2VirtualNode::Ext2VirtualNode");
}
Ext2VirtualNode::~Ext2VirtualNode()
{
Task::checkSanity("Ext2VirtualNode::~Ext2VirtualNode");
}
size_t Ext2VirtualNode::read(BYTE* outbuf, size_t start, size_t maxLength)
{
Task::checkSanity("Ext2VirtualNode::read");
kprintf("Ext2VirtualNode::read\n");
if (start >= size())
return 0;
auto fileContents = m_fileSystem.readFile(m_inode);
if (!fileContents)
return 0;
ASSERT(start < fileContents->length());
size_t nread = min(maxLength, fileContents->length() - start);
memcpy(outbuf, fileContents->data(), nread);
return nread;
}
namespace FileSystem {
static DWORD nextVNodeIndex;
void initialize()
{
nextVNodeIndex = 0;
fileSystem = new Ext2FileSystem;
fileSystem->initialize();
}
VirtualNode::VirtualNode(DWORD index, String&& path)
: m_index(index)
, m_path(move(path))
{
}
VirtualNode::~VirtualNode()
{
}
RefPtr<VirtualNode> createVirtualNode(String&& path)
{
Task::checkSanity("createVirtualNode");
DWORD inodeIndex = 0x12345678;
Task::checkSanity("pre-findPath");
kprintf("path: '%s'\n", path.characters());
auto* inode = fileSystem->findPath(path, inodeIndex);
Task::checkSanity("post-findPath");
if (!inode)
return nullptr;
kprintf("creating e2vn\n");
return Ext2VirtualNode::create(nextVNodeIndex++, move(path), *fileSystem, inodeIndex);
}
}

View file

@ -12,13 +12,13 @@
#include "StdLib.h"
#include "Syscall.h"
#include "CMOS.h"
#include "FileSystem.h"
#include "Userspace.h"
#include "IDEDiskDevice.h"
#include <VirtualFileSystem/NullDevice.h>
#include <VirtualFileSystem/ZeroDevice.h>
#include <VirtualFileSystem/FullDevice.h>
#include <VirtualFileSystem/RandomDevice.h>
#include <VirtualFileSystem/Ext2FileSystem.h>
#include <AK/OwnPtr.h>
#if 0
@ -127,7 +127,6 @@ void init()
banner();
Disk::initialize();
FileSystem::initialize();
auto dev_hd0 = IDEDiskDevice::create();
auto dev_null = make<NullDevice>();
@ -135,6 +134,9 @@ void init()
auto dev_zero = make<ZeroDevice>();
auto dev_random = make<RandomDevice>();
auto e2fs = Ext2FileSystem::create(dev_hd0.copyRef());
e2fs->initialize();
// new Task(motd_main, "motd", IPC::Handle::MotdTask, Task::Ring0);
new Task(user_main, "user", IPC::Handle::UserTask, Task::Ring3);

View file

@ -1,5 +1,5 @@
#!/bin/sh
#bochs -q -f .bochs.conf
bochs -q -f .bochsrc
qemu-system-i386 -drive format=raw,file=.floppy-image,if=floppy -drive format=raw,file=_fs_contents $@
#qemu-system-i386 -drive format=raw,file=.floppy-image,if=floppy -drive format=raw,file=_fs_contents $@

View file

@ -3,7 +3,7 @@
//#define DBFS_DEBUG
DiskBackedFileSystem::DiskBackedFileSystem(RetainPtr<DiskDevice>&& device)
: m_device(std::move(device))
: m_device(move(device))
{
ASSERT(m_device);
}
@ -18,7 +18,7 @@ bool DiskBackedFileSystem::writeBlock(unsigned index, const ByteBuffer& data)
#ifdef DBFS_DEBUG
printf("DiskBackedFileSystem::writeBlock %u\n", index);
#endif
qword baseOffset = static_cast<qword>(index) * static_cast<qword>(blockSize());
DiskOffset baseOffset = static_cast<DiskOffset>(index) * static_cast<DiskOffset>(blockSize());
return device().write(baseOffset, blockSize(), data.pointer());
}
@ -27,7 +27,7 @@ bool DiskBackedFileSystem::writeBlocks(unsigned index, unsigned count, const Byt
#ifdef DBFS_DEBUG
printf("DiskBackedFileSystem::writeBlocks %u x%u\n", index, count);
#endif
qword baseOffset = static_cast<qword>(index) * static_cast<qword>(blockSize());
DiskOffset baseOffset = static_cast<DiskOffset>(index) * static_cast<DiskOffset>(blockSize());
return device().write(baseOffset, count * blockSize(), data.pointer());
}
@ -37,7 +37,7 @@ ByteBuffer DiskBackedFileSystem::readBlock(unsigned index) const
printf("DiskBackedFileSystem::readBlock %u\n", index);
#endif
auto buffer = ByteBuffer::createUninitialized(blockSize());
qword baseOffset = static_cast<qword>(index) * static_cast<qword>(blockSize());
DiskOffset baseOffset = static_cast<DiskOffset>(index) * static_cast<DiskOffset>(blockSize());
auto* bufferPointer = buffer.pointer();
device().read(baseOffset, blockSize(), bufferPointer);
ASSERT(buffer.size() == blockSize());

View file

@ -8,14 +8,12 @@ DiskDevice::~DiskDevice()
{
}
bool DiskDevice::read(qword offset, unsigned length, byte* out) const
bool DiskDevice::read(DiskOffset offset, unsigned length, byte* out) const
{
ASSERT((offset % blockSize()) == 0);
ASSERT((length % blockSize()) == 0);
qword firstBlock = offset / blockSize();
qword endBlock = (offset + length) / blockSize();
ASSERT(firstBlock <= 0xffffffff);
ASSERT(endBlock <= 0xffffffff);
dword firstBlock = offset / blockSize();
dword endBlock = (offset + length) / blockSize();
byte* outptr = out;
unsigned remainingCount = length;
for (unsigned bi = firstBlock; bi < endBlock; ++bi) {
@ -26,12 +24,12 @@ bool DiskDevice::read(qword offset, unsigned length, byte* out) const
return true;
}
bool DiskDevice::write(qword offset, unsigned length, const byte* in)
bool DiskDevice::write(DiskOffset offset, unsigned length, const byte* in)
{
ASSERT((offset % blockSize()) == 0);
ASSERT((length % blockSize()) == 0);
qword firstBlock = offset / blockSize();
qword endBlock = (offset + length) / blockSize();
dword firstBlock = offset / blockSize();
dword endBlock = (offset + length) / blockSize();
ASSERT(firstBlock <= 0xffffffff);
ASSERT(endBlock <= 0xffffffff);
const byte* inptr = in;

View file

@ -3,6 +3,13 @@
#include <AK/Retainable.h>
#include <AK/Types.h>
#ifdef SERENITY_KERNEL
// FIXME: Support 64-bit DiskOffset
typedef dword DiskOffset;
#else
typedef qword DiskOffset;
#endif
class DiskDevice : public Retainable<DiskDevice> {
public:
virtual ~DiskDevice();
@ -11,8 +18,8 @@ public:
virtual bool readBlock(unsigned index, byte*) const = 0;
virtual bool writeBlock(unsigned index, const byte*) = 0;
virtual const char* className() const = 0;
bool read(qword offset, unsigned length, byte*) const;
bool write(qword offset, unsigned length, const byte*);
bool read(DiskOffset, unsigned length, byte*) const;
bool write(DiskOffset, unsigned length, const byte*);
protected:
DiskDevice();

View file

@ -3,20 +3,20 @@
#include "UnixTypes.h"
#include <AK/Bitmap.h>
#include <AK/StdLib.h>
#include <cstdio>
#include <cstring>
#include <AK/kmalloc.h>
#include <AK/ktime.h>
#include <AK/kstdio.h>
#include "sys-errno.h"
//#define EXT2_DEBUG
#define EXT2_DEBUG
RetainPtr<Ext2FileSystem> Ext2FileSystem::create(RetainPtr<DiskDevice>&& device)
{
return adopt(*new Ext2FileSystem(std::move(device)));
return adopt(*new Ext2FileSystem(move(device)));
}
Ext2FileSystem::Ext2FileSystem(RetainPtr<DiskDevice>&& device)
: DiskBackedFileSystem(std::move(device))
: DiskBackedFileSystem(move(device))
{
}
@ -64,9 +64,9 @@ const ext2_group_desc& Ext2FileSystem::blockGroupDescriptor(unsigned groupIndex)
if (!m_cachedBlockGroupDescriptorTable) {
unsigned blocksToRead = ceilDiv(m_blockGroupCount * (unsigned)sizeof(ext2_group_desc), blockSize());
printf("[ext2fs] block group count: %u, blocks-to-read: %u\n", m_blockGroupCount, blocksToRead);
kprintf("[ext2fs] block group count: %u, blocks-to-read: %u\n", m_blockGroupCount, blocksToRead);
unsigned firstBlockOfBGDT = blockSize() == 1024 ? 2 : 1;
printf("[ext2fs] first block of BGDT: %u\n", firstBlockOfBGDT);
kprintf("[ext2fs] first block of BGDT: %u\n", firstBlockOfBGDT);
m_cachedBlockGroupDescriptorTable = readBlocks(firstBlockOfBGDT, blocksToRead);
}
return reinterpret_cast<ext2_group_desc*>(m_cachedBlockGroupDescriptorTable.pointer())[groupIndex - 1];
@ -75,32 +75,32 @@ const ext2_group_desc& Ext2FileSystem::blockGroupDescriptor(unsigned groupIndex)
bool Ext2FileSystem::initialize()
{
auto& superBlock = this->superBlock();
printf("[ext2fs] super block magic: %04x (super block size: %u)\n", superBlock.s_magic, sizeof(ext2_super_block));
kprintf("[ext2fs] super block magic: %x (super block size: %u)\n", superBlock.s_magic, sizeof(ext2_super_block));
if (superBlock.s_magic != EXT2_SUPER_MAGIC)
return false;
printf("[ext2fs] %u inodes, %u blocks\n", superBlock.s_inodes_count, superBlock.s_blocks_count);
printf("[ext2fs] block size = %u\n", EXT2_BLOCK_SIZE(&superBlock));
printf("[ext2fs] first data block = %u\n", superBlock.s_first_data_block);
printf("[ext2fs] inodes per block = %u\n", inodesPerBlock());
printf("[ext2fs] inodes per group = %u\n", inodesPerGroup());
printf("[ext2fs] free inodes = %u\n", superBlock.s_free_inodes_count);
kprintf("[ext2fs] %u inodes, %u blocks\n", superBlock.s_inodes_count, superBlock.s_blocks_count);
kprintf("[ext2fs] block size = %u\n", EXT2_BLOCK_SIZE(&superBlock));
kprintf("[ext2fs] first data block = %u\n", superBlock.s_first_data_block);
kprintf("[ext2fs] inodes per block = %u\n", inodesPerBlock());
kprintf("[ext2fs] inodes per group = %u\n", inodesPerGroup());
kprintf("[ext2fs] free inodes = %u\n", superBlock.s_free_inodes_count);
printf("[ext2fs] desc per block = %u\n", EXT2_DESC_PER_BLOCK(&superBlock));
printf("[ext2fs] desc size = %u\n", EXT2_DESC_SIZE(&superBlock));
kprintf("[ext2fs] desc per block = %u\n", EXT2_DESC_PER_BLOCK(&superBlock));
kprintf("[ext2fs] desc size = %u\n", EXT2_DESC_SIZE(&superBlock));
setBlockSize(EXT2_BLOCK_SIZE(&superBlock));
m_blockGroupCount = ceilDiv(superBlock.s_blocks_count, superBlock.s_blocks_per_group);
if (m_blockGroupCount == 0) {
printf("[ext2fs] no block groups :(\n");
kprintf("[ext2fs] no block groups :(\n");
return false;
}
for (unsigned i = 1; i <= m_blockGroupCount; ++i) {
auto& group = blockGroupDescriptor(i);
printf("[ext2fs] group[%u] { block_bitmap: %u, inode_bitmap: %u, inode_table: %u }\n",
kprintf("[ext2fs] group[%u] { block_bitmap: %u, inode_bitmap: %u, inode_table: %u }\n",
i,
group.bg_block_bitmap,
group.bg_inode_bitmap,
@ -123,12 +123,12 @@ InodeIdentifier Ext2FileSystem::rootInode() const
#ifdef EXT2_DEBUG
static void dumpExt2Inode(const ext2_inode& inode)
{
printf("Dump of ext2_inode:\n");
printf(" i_size: %u\n", inode.i_size);
printf(" i_mode: %u\n", inode.i_mode);
printf(" i_blocks: %u\n", inode.i_blocks);
printf(" i_uid: %u\n", inode.i_uid);
printf(" i_gid: %u\n", inode.i_gid);
kprintf("Dump of ext2_inode:\n");
kprintf(" i_size: %u\n", inode.i_size);
kprintf(" i_mode: %u\n", inode.i_mode);
kprintf(" i_blocks: %u\n", inode.i_blocks);
kprintf(" i_uid: %u\n", inode.i_uid);
kprintf(" i_gid: %u\n", inode.i_gid);
}
#endif
@ -218,7 +218,7 @@ Vector<unsigned> Ext2FileSystem::blockListForInode(const ext2_inode& e2inode) co
if (!blocksRemaining)
return list;
auto processBlockArray = [&] (unsigned arrayBlockIndex, std::function<void(unsigned)> callback) {
auto processBlockArray = [&] (unsigned arrayBlockIndex, Function<void(unsigned)> callback) {
auto arrayBlock = readBlock(arrayBlockIndex);
ASSERT(arrayBlock);
auto* array = reinterpret_cast<const __u32*>(arrayBlock.pointer());
@ -267,7 +267,7 @@ Unix::ssize_t Ext2FileSystem::readInodeBytes(InodeIdentifier inode, Unix::off_t
auto e2inode = lookupExt2Inode(inode.index());
if (!e2inode) {
printf("[ext2fs] readInodeBytes: metadata lookup for inode %u failed\n", inode.index());
kprintf("[ext2fs] readInodeBytes: metadata lookup for inode %u failed\n", inode.index());
return -EIO;
}
@ -284,7 +284,7 @@ Unix::ssize_t Ext2FileSystem::readInodeBytes(InodeIdentifier inode, Unix::off_t
// This avoids wasting an entire block on short links. (Most links are short.)
static const unsigned maxInlineSymlinkLength = 60;
if (isSymbolicLink(e2inode->i_mode) && e2inode->i_size < maxInlineSymlinkLength) {
Unix::ssize_t nread = min(e2inode->i_size - offset, static_cast<Unix::off_t>(count));
Unix::ssize_t nread = min((Unix::off_t)e2inode->i_size - offset, static_cast<Unix::off_t>(count));
memcpy(buffer, e2inode->i_block + offset, nread);
return nread;
}
@ -293,7 +293,7 @@ Unix::ssize_t Ext2FileSystem::readInodeBytes(InodeIdentifier inode, Unix::off_t
// It needs to be cached!
auto list = blockListForInode(*e2inode);
if (list.isEmpty()) {
printf("[ext2fs] readInodeBytes: empty block list for inode %u\n", inode.index());
kprintf("[ext2fs] readInodeBytes: empty block list for inode %u\n", inode.index());
return -EIO;
}
@ -305,17 +305,17 @@ Unix::ssize_t Ext2FileSystem::readInodeBytes(InodeIdentifier inode, Unix::off_t
dword offsetIntoFirstBlock = offset % blockSize();
Unix::ssize_t nread = 0;
Unix::size_t remainingCount = min((Unix::off_t)count, e2inode->i_size - offset);
Unix::size_t remainingCount = min((Unix::off_t)count, (Unix::off_t)e2inode->i_size - offset);
byte* out = buffer;
#ifdef EXT2_DEBUG
printf("ok let's do it, read(%llu, %u) -> blocks %u thru %u, oifb: %u\n", offset, count, firstBlockLogicalIndex, lastBlockLogicalIndex, offsetIntoFirstBlock);
kprintf("ok let's do it, read(%llu, %u) -> blocks %u thru %u, oifb: %u\n", offset, count, firstBlockLogicalIndex, lastBlockLogicalIndex, offsetIntoFirstBlock);
#endif
for (dword bi = firstBlockLogicalIndex; bi <= lastBlockLogicalIndex; ++bi) {
auto block = readBlock(list[bi]);
if (!block) {
printf("[ext2fs] readInodeBytes: readBlock(%u) failed (lbi: %u)\n", list[bi], bi);
kprintf("[ext2fs] readInodeBytes: readBlock(%u) failed (lbi: %u)\n", list[bi], bi);
return -EIO;
}
@ -342,7 +342,7 @@ bool Ext2FileSystem::writeInode(InodeIdentifier inode, const ByteBuffer& data)
auto e2inode = lookupExt2Inode(inode.index());
if (!e2inode) {
printf("[ext2fs] writeInode: metadata lookup for inode %u failed\n", inode.index());
kprintf("[ext2fs] writeInode: metadata lookup for inode %u failed\n", inode.index());
return false;
}
@ -357,13 +357,13 @@ bool Ext2FileSystem::writeInode(InodeIdentifier inode, const ByteBuffer& data)
auto list = blockListForInode(*e2inode);
if (list.isEmpty()) {
printf("[ext2fs] writeInode: empty block list for inode %u\n", inode.index());
kprintf("[ext2fs] writeInode: empty block list for inode %u\n", inode.index());
return false;
}
for (unsigned i = 0; i < list.size(); ++i) {
auto section = data.slice(i * blockSize(), blockSize());
printf("section = %p (%u)\n", section.pointer(), section.size());
kprintf("section = %p (%u)\n", section.pointer(), section.size());
bool success = writeBlock(list[i], section);
ASSERT(success);
}
@ -371,13 +371,13 @@ bool Ext2FileSystem::writeInode(InodeIdentifier inode, const ByteBuffer& data)
return true;
}
bool Ext2FileSystem::enumerateDirectoryInode(InodeIdentifier inode, std::function<bool(const DirectoryEntry&)> callback) const
bool Ext2FileSystem::enumerateDirectoryInode(InodeIdentifier inode, Function<bool(const DirectoryEntry&)> callback) const
{
ASSERT(inode.fileSystemID() == id());
ASSERT(isDirectoryInode(inode.index()));
#ifdef EXT2_DEBUG
printf("[ext2fs] Enumerating directory contents of inode %u:\n", inode.index());
kprintf("[ext2fs] Enumerating directory contents of inode %u:\n", inode.index());
#endif
auto buffer = readEntireInode(inode);
@ -391,7 +391,7 @@ bool Ext2FileSystem::enumerateDirectoryInode(InodeIdentifier inode, std::functio
memcpy(namebuf, entry->name, entry->name_len);
namebuf[entry->name_len] = 0;
#ifdef EXT2_DEBUG
printf("inode: %u, name_len: %u, rec_len: %u, file_type: %u, name: %s\n", entry->inode, entry->name_len, entry->rec_len, entry->file_type, namebuf);
kprintf("inode: %u, name_len: %u, rec_len: %u, file_type: %u, name: %s\n", entry->inode, entry->name_len, entry->rec_len, entry->file_type, namebuf);
#endif
if (!callback({ namebuf, { id(), entry->inode }, entry->file_type }))
break;
@ -408,7 +408,7 @@ bool Ext2FileSystem::addInodeToDirectory(unsigned directoryInode, unsigned inode
ASSERT(isDirectory(e2inodeForDirectory->i_mode));
//#ifdef EXT2_DEBUG
printf("[ext2fs] Adding inode %u with name '%s' to directory %u\n", inode, name.characters(), directoryInode);
kprintf("[ext2fs] Adding inode %u with name '%s' to directory %u\n", inode, name.characters(), directoryInode);
//#endif
Vector<DirectoryEntry> entries;
@ -422,13 +422,13 @@ bool Ext2FileSystem::addInodeToDirectory(unsigned directoryInode, unsigned inode
return true;
});
if (nameAlreadyExists) {
printf("[ext2fs] Name '%s' already exists in directory inode %u\n", name.characters(), directoryInode);
kprintf("[ext2fs] Name '%s' already exists in directory inode %u\n", name.characters(), directoryInode);
return false;
}
entries.append({ name, { id(), inode }, fileType });
return writeDirectoryInode(directoryInode, std::move(entries));
return writeDirectoryInode(directoryInode, move(entries));
}
class BufferStream {
@ -476,18 +476,18 @@ private:
bool Ext2FileSystem::writeDirectoryInode(unsigned directoryInode, Vector<DirectoryEntry>&& entries)
{
printf("[ext2fs] New directory inode %u contents to write:\n", directoryInode);
kprintf("[ext2fs] New directory inode %u contents to write:\n", directoryInode);
unsigned directorySize = 0;
for (auto& entry : entries) {
printf(" - %08u %s\n", entry.inode.index(), entry.name.characters());
kprintf(" - %08u %s\n", entry.inode.index(), entry.name.characters());
directorySize += EXT2_DIR_REC_LEN(entry.name.length());
}
unsigned blocksNeeded = ceilDiv(directorySize, blockSize());
unsigned occupiedSize = blocksNeeded * blockSize();
printf("[ext2fs] directory size: %u (occupied: %u)\n", directorySize, occupiedSize);
kprintf("[ext2fs] directory size: %u (occupied: %u)\n", directorySize, occupiedSize);
auto directoryData = ByteBuffer::createUninitialized(occupiedSize);
@ -499,11 +499,11 @@ bool Ext2FileSystem::writeDirectoryInode(unsigned directoryInode, Vector<Directo
if (i == entries.size() - 1)
recordLength += occupiedSize - directorySize;
printf("* inode: %u", entry.inode.index());
printf(", name_len: %u", word(entry.name.length()));
printf(", rec_len: %u", word(recordLength));
printf(", file_type: %u", byte(entry.fileType));
printf(", name: %s\n", entry.name.characters());
kprintf("* inode: %u", entry.inode.index());
kprintf(", name_len: %u", word(entry.name.length()));
kprintf(", rec_len: %u", word(recordLength));
kprintf(", file_type: %u", byte(entry.fileType));
kprintf(", name: %s\n", entry.name.characters());
stream << dword(entry.inode.index());
stream << word(recordLength);
@ -512,7 +512,7 @@ bool Ext2FileSystem::writeDirectoryInode(unsigned directoryInode, Vector<Directo
stream << entry.name;
unsigned padding = recordLength - entry.name.length() - 8;
printf(" *** pad %u bytes\n", padding);
kprintf(" *** pad %u bytes\n", padding);
for (unsigned j = 0; j < padding; ++j) {
stream << byte(0);
}
@ -521,15 +521,15 @@ bool Ext2FileSystem::writeDirectoryInode(unsigned directoryInode, Vector<Directo
stream.fillToEnd(0);
#if 0
printf("data to write (%u):\n", directoryData.size());
kprintf("data to write (%u):\n", directoryData.size());
for (unsigned i = 0; i < directoryData.size(); ++i) {
printf("%02x ", directoryData[i]);
kprintf("%02x ", directoryData[i]);
if ((i + 1) % 8 == 0)
printf(" ");
kprintf(" ");
if ((i + 1) % 16 == 0)
printf("\n");
kprintf("\n");
}
printf("\n");
kprintf("\n");
#endif
writeInode({ id(), directoryInode }, directoryData);
@ -568,20 +568,20 @@ void Ext2FileSystem::dumpBlockBitmap(unsigned groupIndex) const
auto bitmapBlocks = readBlocks(bgd.bg_block_bitmap, blockCount);
ASSERT(bitmapBlocks);
printf("[ext2fs] group[%u] block bitmap (bitmap occupies %u blocks):\n", groupIndex, blockCount);
kprintf("[ext2fs] group[%u] block bitmap (bitmap occupies %u blocks):\n", groupIndex, blockCount);
auto bitmap = Bitmap::wrap(bitmapBlocks.pointer(), blocksInGroup);
for (unsigned i = 0; i < blocksInGroup; ++i) {
printf("%c", bitmap.get(i) ? '1' : '0');
kprintf("%c", bitmap.get(i) ? '1' : '0');
}
printf("\n");
kprintf("\n");
}
void Ext2FileSystem::dumpInodeBitmap(unsigned groupIndex) const
{
traverseInodeBitmap(groupIndex, [] (unsigned, const Bitmap& bitmap) {
for (unsigned i = 0; i < bitmap.size(); ++i)
printf("%c", bitmap.get(i) ? '1' : '0');
kprintf("%c", bitmap.get(i) ? '1' : '0');
return true;
});
}
@ -630,7 +630,7 @@ bool Ext2FileSystem::modifyLinkCount(InodeIndex inode, int delta)
return false;
auto newLinkCount = e2inode->i_links_count + delta;
printf("changing inode %u link count from %u to %u\n", inode, e2inode->i_links_count, newLinkCount);
kprintf("changing inode %u link count from %u to %u\n", inode, e2inode->i_links_count, newLinkCount);
e2inode->i_links_count = newLinkCount;
return writeExt2Inode(inode, *e2inode);
@ -644,7 +644,7 @@ bool Ext2FileSystem::setModificationTime(InodeIdentifier inode, dword timestamp)
if (!e2inode)
return false;
printf("changing inode %u mtime from %u to %u\n", inode.index(), e2inode->i_mtime, timestamp);
kprintf("changing inode %u mtime from %u to %u\n", inode.index(), e2inode->i_mtime, timestamp);
e2inode->i_mtime = timestamp;
return writeExt2Inode(inode.index(), *e2inode);
@ -671,11 +671,11 @@ bool Ext2FileSystem::isDirectoryInode(unsigned inode) const
Vector<Ext2FileSystem::BlockIndex> Ext2FileSystem::allocateBlocks(unsigned group, unsigned count)
{
printf("[ext2fs] allocateBlocks(group: %u, count: %u)\n", group, count);
kprintf("[ext2fs] allocateBlocks(group: %u, count: %u)\n", group, count);
auto& bgd = blockGroupDescriptor(group);
if (bgd.bg_free_blocks_count < count) {
printf("[ext2fs] allocateBlocks can't allocate out of group %u, wanted %u but only %u available\n", group, count, bgd.bg_free_blocks_count);
kprintf("[ext2fs] allocateBlocks can't allocate out of group %u, wanted %u but only %u available\n", group, count, bgd.bg_free_blocks_count);
return { };
}
@ -691,9 +691,9 @@ Vector<Ext2FileSystem::BlockIndex> Ext2FileSystem::allocateBlocks(unsigned group
}
return true;
});
printf("[ext2fs] allocateBlock found these blocks:\n");
kprintf("[ext2fs] allocateBlock found these blocks:\n");
for (auto& bi : blocks) {
printf(" > %u\n", bi);
kprintf(" > %u\n", bi);
}
return blocks;
@ -701,11 +701,11 @@ Vector<Ext2FileSystem::BlockIndex> Ext2FileSystem::allocateBlocks(unsigned group
unsigned Ext2FileSystem::allocateInode(unsigned preferredGroup, unsigned expectedSize)
{
printf("[ext2fs] allocateInode(preferredGroup: %u, expectedSize: %u)\n", preferredGroup, expectedSize);
kprintf("[ext2fs] allocateInode(preferredGroup: %u, expectedSize: %u)\n", preferredGroup, expectedSize);
unsigned neededBlocks = ceilDiv(expectedSize, blockSize());
printf("[ext2fs] minimum needed blocks: %u\n", neededBlocks);
kprintf("[ext2fs] minimum needed blocks: %u\n", neededBlocks);
unsigned groupIndex = 0;
@ -724,11 +724,11 @@ unsigned Ext2FileSystem::allocateInode(unsigned preferredGroup, unsigned expecte
}
if (!groupIndex) {
printf("[ext2fs] allocateInode: no suitable group found for new inode with %u blocks needed :(\n", neededBlocks);
kprintf("[ext2fs] allocateInode: no suitable group found for new inode with %u blocks needed :(\n", neededBlocks);
return 0;
}
printf("[ext2fs] allocateInode: found suitable group [%u] for new inode with %u blocks needed :^)\n", groupIndex, neededBlocks);
kprintf("[ext2fs] allocateInode: found suitable group [%u] for new inode with %u blocks needed :^)\n", groupIndex, neededBlocks);
unsigned firstFreeInodeInGroup = 0;
traverseInodeBitmap(groupIndex, [&firstFreeInodeInGroup] (unsigned firstInodeInBitmap, const Bitmap& bitmap) {
@ -742,12 +742,12 @@ unsigned Ext2FileSystem::allocateInode(unsigned preferredGroup, unsigned expecte
});
if (!firstFreeInodeInGroup) {
printf("[ext2fs] firstFreeInodeInGroup returned no inode, despite bgd claiming there are inodes :(\n");
kprintf("[ext2fs] firstFreeInodeInGroup returned no inode, despite bgd claiming there are inodes :(\n");
return 0;
}
unsigned inode = firstFreeInodeInGroup;
printf("[ext2fs] found suitable inode %u\n", inode);
kprintf("[ext2fs] found suitable inode %u\n", inode);
// FIXME: allocate blocks if needed!
@ -773,7 +773,7 @@ bool Ext2FileSystem::setInodeAllocationState(unsigned inode, bool newState)
ASSERT(block);
auto bitmap = Bitmap::wrap(block.pointer(), block.size());
bool currentState = bitmap.get(bitIndex);
printf("[ext2fs] setInodeAllocationState(%u) %u -> %u\n", inode, currentState, newState);
kprintf("[ext2fs] setInodeAllocationState(%u) %u -> %u\n", inode, currentState, newState);
if (currentState == newState)
return true;
@ -783,7 +783,7 @@ bool Ext2FileSystem::setInodeAllocationState(unsigned inode, bool newState)
// Update superblock
auto& sb = *reinterpret_cast<ext2_super_block*>(m_cachedSuperBlock.pointer());
printf("[ext2fs] superblock free inode count %u -> %u\n", sb.s_free_inodes_count, sb.s_free_inodes_count - 1);
kprintf("[ext2fs] superblock free inode count %u -> %u\n", sb.s_free_inodes_count, sb.s_free_inodes_count - 1);
if (newState)
--sb.s_free_inodes_count;
else
@ -796,7 +796,7 @@ bool Ext2FileSystem::setInodeAllocationState(unsigned inode, bool newState)
--mutableBGD.bg_free_inodes_count;
else
++mutableBGD.bg_free_inodes_count;
printf("[ext2fs] group free inode count %u -> %u\n", bgd.bg_free_inodes_count, bgd.bg_free_inodes_count - 1);
kprintf("[ext2fs] group free inode count %u -> %u\n", bgd.bg_free_inodes_count, bgd.bg_free_inodes_count - 1);
unsigned blocksToWrite = ceilDiv(m_blockGroupCount * (unsigned)sizeof(ext2_group_desc), blockSize());
unsigned firstBlockOfBGDT = blockSize() == 1024 ? 2 : 1;
@ -817,7 +817,7 @@ bool Ext2FileSystem::setBlockAllocationState(GroupIndex group, BlockIndex bi, bo
ASSERT(block);
auto bitmap = Bitmap::wrap(block.pointer(), block.size());
bool currentState = bitmap.get(bitIndex);
printf("[ext2fs] setBlockAllocationState(%u) %u -> %u\n", block, currentState, newState);
kprintf("[ext2fs] setBlockAllocationState(%u) %u -> %u\n", block, currentState, newState);
if (currentState == newState)
return true;
@ -827,7 +827,7 @@ bool Ext2FileSystem::setBlockAllocationState(GroupIndex group, BlockIndex bi, bo
// Update superblock
auto& sb = *reinterpret_cast<ext2_super_block*>(m_cachedSuperBlock.pointer());
printf("[ext2fs] superblock free block count %u -> %u\n", sb.s_free_blocks_count, sb.s_free_blocks_count - 1);
kprintf("[ext2fs] superblock free block count %u -> %u\n", sb.s_free_blocks_count, sb.s_free_blocks_count - 1);
if (newState)
--sb.s_free_blocks_count;
else
@ -840,7 +840,7 @@ bool Ext2FileSystem::setBlockAllocationState(GroupIndex group, BlockIndex bi, bo
--mutableBGD.bg_free_blocks_count;
else
++mutableBGD.bg_free_blocks_count;
printf("[ext2fs] group free block count %u -> %u\n", bgd.bg_free_blocks_count, bgd.bg_free_blocks_count - 1);
kprintf("[ext2fs] group free block count %u -> %u\n", bgd.bg_free_blocks_count, bgd.bg_free_blocks_count - 1);
unsigned blocksToWrite = ceilDiv(m_blockGroupCount * (unsigned)sizeof(ext2_group_desc), blockSize());
unsigned firstBlockOfBGDT = blockSize() == 1024 ? 2 : 1;
@ -865,13 +865,13 @@ InodeIdentifier Ext2FileSystem::makeDirectory(InodeIdentifier parentInode, const
if (!inode.isValid())
return { };
printf("[ext2fs] makeDirectory: created new directory named '%s' with inode %u\n", name.characters(), inode.index());
kprintf("[ext2fs] makeDirectory: created new directory named '%s' with inode %u\n", name.characters(), inode.index());
Vector<DirectoryEntry> entries;
entries.append({ ".", inode, EXT2_FT_DIR });
entries.append({ "..", parentInode, EXT2_FT_DIR });
bool success = writeDirectoryInode(inode.index(), std::move(entries));
bool success = writeDirectoryInode(inode.index(), move(entries));
ASSERT(success);
success = modifyLinkCount(parentInode.index(), 1);
@ -879,7 +879,7 @@ InodeIdentifier Ext2FileSystem::makeDirectory(InodeIdentifier parentInode, const
auto& bgd = const_cast<ext2_group_desc&>(blockGroupDescriptor(groupIndexFromInode(inode.index())));
++bgd.bg_used_dirs_count;
printf("[ext2fs] incremented bg_used_dirs_count %u -> %u\n", bgd.bg_used_dirs_count - 1, bgd.bg_used_dirs_count);
kprintf("[ext2fs] incremented bg_used_dirs_count %u -> %u\n", bgd.bg_used_dirs_count - 1, bgd.bg_used_dirs_count);
unsigned blocksToWrite = ceilDiv(m_blockGroupCount * (unsigned)sizeof(ext2_group_desc), blockSize());
unsigned firstBlockOfBGDT = blockSize() == 1024 ? 2 : 1;
@ -894,19 +894,19 @@ InodeIdentifier Ext2FileSystem::createInode(InodeIdentifier parentInode, const S
ASSERT(isDirectoryInode(parentInode.index()));
//#ifdef EXT2_DEBUG
printf("[ext2fs] Adding inode '%s' (mode %o) to parent directory %u:\n", name.characters(), mode, parentInode.index());
kprintf("[ext2fs] Adding inode '%s' (mode %o) to parent directory %u:\n", name.characters(), mode, parentInode.index());
//#endif
// NOTE: This doesn't commit the inode allocation just yet!
auto inode = allocateInode(0, 0);
if (!inode) {
printf("[ext2fs] createInode: allocateInode failed\n");
kprintf("[ext2fs] createInode: allocateInode failed\n");
return { };
}
auto blocks = allocateBlocks(groupIndexFromInode(inode), ceilDiv(size, blockSize()));
if (blocks.isEmpty()) {
printf("[ext2fs] createInode: allocateBlocks failed\n");
kprintf("[ext2fs] createInode: allocateBlocks failed\n");
return { };
}
@ -929,7 +929,7 @@ InodeIdentifier Ext2FileSystem::createInode(InodeIdentifier parentInode, const S
// Try adding it to the directory first, in case the name is already in use.
bool success = addInodeToDirectory(parentInode.index(), inode, name, fileType);
if (!success) {
printf("[ext2fs] failed to add inode to directory :(\n");
kprintf("[ext2fs] failed to add inode to directory :(\n");
return { };
}
@ -965,7 +965,7 @@ InodeIdentifier Ext2FileSystem::createInode(InodeIdentifier parentInode, const S
// FIXME: Implement writing out indirect blocks!
ASSERT(blocks.size() < EXT2_NDIR_BLOCKS);
printf("[XXX] writing %u blocks to i_block array\n", min((size_t)EXT2_NDIR_BLOCKS, blocks.size()));
kprintf("[XXX] writing %zu blocks to i_block array\n", min((size_t)EXT2_NDIR_BLOCKS, blocks.size()));
for (unsigned i = 0; i < min((size_t)EXT2_NDIR_BLOCKS, blocks.size()); ++i) {
e2inode->i_block[i] = blocks[i];
}

View file

@ -13,6 +13,7 @@ class Ext2FileSystem final : public DiskBackedFileSystem {
public:
static RetainPtr<Ext2FileSystem> create(RetainPtr<DiskDevice>&&);
virtual ~Ext2FileSystem() override;
virtual bool initialize() override;
private:
typedef unsigned BlockIndex;
@ -36,11 +37,10 @@ private:
ByteBuffer readSuperBlock() const;
bool writeSuperBlock(const ext2_super_block&);
virtual bool initialize() override;
virtual const char* className() const override;
virtual InodeIdentifier rootInode() const override;
virtual bool writeInode(InodeIdentifier, const ByteBuffer&) override;
virtual bool enumerateDirectoryInode(InodeIdentifier, std::function<bool(const DirectoryEntry&)>) const override;
virtual bool enumerateDirectoryInode(InodeIdentifier, Function<bool(const DirectoryEntry&)>) const override;
virtual InodeMetadata inodeMetadata(InodeIdentifier) const override;
virtual bool setModificationTime(InodeIdentifier, dword timestamp) override;
virtual InodeIdentifier createInode(InodeIdentifier parentInode, const String& name, Unix::mode_t, unsigned size) override;

View file

@ -34,17 +34,17 @@ unsigned FileBackedDiskDevice::blockSize() const
bool FileBackedDiskDevice::readBlock(unsigned index, byte* out) const
{
qword offset = index * m_blockSize;
DiskOffset offset = index * m_blockSize;
return readInternal(offset, blockSize(), out);
}
bool FileBackedDiskDevice::writeBlock(unsigned index, const byte* data)
{
qword offset = index * m_blockSize;
DiskOffset offset = index * m_blockSize;
return writeInternal(offset, blockSize(), data);
}
bool FileBackedDiskDevice::readInternal(qword offset, unsigned length, byte* out) const
bool FileBackedDiskDevice::readInternal(DiskOffset offset, unsigned length, byte* out) const
{
#ifndef IGNORE_FILE_LENGTH
if (offset + length >= m_fileLength)
@ -59,7 +59,7 @@ bool FileBackedDiskDevice::readInternal(qword offset, unsigned length, byte* out
return true;
}
bool FileBackedDiskDevice::writeInternal(qword offset, unsigned length, const byte* data)
bool FileBackedDiskDevice::writeInternal(DiskOffset offset, unsigned length, const byte* data)
{
#ifndef IGNORE_FILE_LENGTH
if (offset + length >= m_fileLength)

View file

@ -20,14 +20,14 @@ public:
private:
virtual const char* className() const override;
bool readInternal(qword offset, unsigned length, byte* out) const;
bool writeInternal(qword offset, unsigned length, const byte* data);
bool readInternal(DiskOffset, unsigned length, byte* out) const;
bool writeInternal(DiskOffset, unsigned length, const byte* data);
FileBackedDiskDevice(String&& imagePath, unsigned blockSize);
String m_imagePath;
FILE* m_file { nullptr };
qword m_fileLength { 0 };
DiskOffset m_fileLength { 0 };
unsigned m_blockSize { 0 };
};

View file

@ -6,7 +6,9 @@ static dword s_lastFileSystemID = 0;
static HashMap<dword, FileSystem*>& fileSystems()
{
static auto* map = new HashMap<dword, FileSystem*>();
static HashMap<dword, FileSystem*>* map;
if (!map)
map = new HashMap<dword, FileSystem*>();
return *map;
}
@ -48,7 +50,7 @@ ByteBuffer FileSystem::readEntireInode(InodeIdentifier inode) const
auto metadata = inodeMetadata(inode);
if (!metadata.isValid()) {
printf("[fs] readInode: metadata lookup for inode %u failed\n", inode.index());
kprintf("[fs] readInode: metadata lookup for inode %u failed\n", inode.index());
return nullptr;
}
@ -67,7 +69,7 @@ ByteBuffer FileSystem::readEntireInode(InodeIdentifier inode) const
offset += nread;
}
if (nread < 0) {
printf("[fs] readInode: ERROR: %d\n", nread);
kprintf("[fs] readInode: ERROR: %d\n", nread);
return nullptr;
}

View file

@ -11,7 +11,8 @@
#include <AK/Retainable.h>
#include <AK/RetainPtr.h>
#include <AK/String.h>
#include <functional>
#include <AK/Function.h>
#include <AK/kstdio.h>
static const dword mepoch = 476763780;
@ -35,7 +36,7 @@ public:
InodeIdentifier inode;
byte fileType { 0 };
};
virtual bool enumerateDirectoryInode(InodeIdentifier, std::function<bool(const DirectoryEntry&)>) const = 0;
virtual bool enumerateDirectoryInode(InodeIdentifier, Function<bool(const DirectoryEntry&)>) const = 0;
virtual bool setModificationTime(InodeIdentifier, dword timestamp) = 0;
virtual InodeIdentifier createInode(InodeIdentifier parentInode, const String& name, Unix::mode_t, unsigned size) = 0;
@ -79,7 +80,7 @@ template<>
struct Traits<InodeIdentifier> {
// FIXME: This is a shitty hash.
static unsigned hash(const InodeIdentifier& inode) { return Traits<unsigned>::hash(inode.fileSystemID()) + Traits<unsigned>::hash(inode.index()); }
static void dump(const InodeIdentifier& inode) { printf("%02u:%08u", inode.fileSystemID(), inode.index()); }
static void dump(const InodeIdentifier& inode) { kprintf("%02u:%08u", inode.fileSystemID(), inode.index()); }
};
}

View file

@ -3,7 +3,7 @@
#include "UnixTypes.h"
#ifdef SERENITY_KERNEL
inline static const Unix::off_t maxFileOffset = 9223372036854775807LL;
inline static const Unix::off_t maxFileOffset = 2147483647;
#else
#include <limits>
inline static const Unix::off_t maxFileOffset = std::numeric_limits<Unix::off_t>::max();

View file

@ -62,7 +62,7 @@ InodeIdentifier SyntheticFileSystem::rootInode() const
return { id(), 1 };
}
bool SyntheticFileSystem::enumerateDirectoryInode(InodeIdentifier inode, std::function<bool(const DirectoryEntry&)> callback) const
bool SyntheticFileSystem::enumerateDirectoryInode(InodeIdentifier inode, Function<bool(const DirectoryEntry&)> callback) const
{
ASSERT(inode.fileSystemID() == id());
#ifdef SYNTHFS_DEBUG

View file

@ -13,7 +13,7 @@ public:
virtual const char* className() const override;
virtual InodeIdentifier rootInode() const override;
virtual bool writeInode(InodeIdentifier, const ByteBuffer&) override;
virtual bool enumerateDirectoryInode(InodeIdentifier, std::function<bool(const DirectoryEntry&)>) const override;
virtual bool enumerateDirectoryInode(InodeIdentifier, Function<bool(const DirectoryEntry&)>) const override;
virtual InodeMetadata inodeMetadata(InodeIdentifier) const override;
virtual bool setModificationTime(InodeIdentifier, dword timestamp) override;
virtual InodeIdentifier createInode(InodeIdentifier parentInode, const String& name, Unix::mode_t, unsigned size) override;

View file

@ -14,7 +14,14 @@ typedef dword mode_t;
typedef dword nlink_t;
typedef dword uid_t;
typedef dword gid_t;
#ifdef SERENITY_KERNEL
// FIXME: Support 64-bit offsets!
typedef signed_dword off_t;
#else
typedef signed_qword off_t;
#endif
typedef dword blksize_t;
typedef dword blkcnt_t;
typedef long int time_t;

View file

@ -2,8 +2,8 @@
#include "FileHandle.h"
#include "FileSystem.h"
#include <AK/kmalloc.h>
#include <cstdio>
#include <cstdlib>
#include <AK/kstdio.h>
#include <AK/ktime.h>
//#define VFS_DEBUG
@ -24,7 +24,7 @@ VirtualFileSystem::VirtualFileSystem()
VirtualFileSystem::~VirtualFileSystem()
{
printf("[VFS] ~VirtualFileSystem with %u nodes allocated\n", allocatedNodeCount());
kprintf("[VFS] ~VirtualFileSystem with %u nodes allocated\n", allocatedNodeCount());
}
auto VirtualFileSystem::makeNode(InodeIdentifier inode) -> RetainPtr<Node>
@ -39,7 +39,7 @@ auto VirtualFileSystem::makeNode(InodeIdentifier inode) -> RetainPtr<Node>
if (it != m_characterDevices.end()) {
characterDevice = (*it).value;
} else {
printf("[VFS] makeNode() no such character device %u,%u\n", metadata.majorDevice, metadata.minorDevice);
kprintf("[VFS] makeNode() no such character device %u,%u\n", metadata.majorDevice, metadata.minorDevice);
return nullptr;
}
}
@ -53,7 +53,7 @@ auto VirtualFileSystem::makeNode(InodeIdentifier inode) -> RetainPtr<Node>
vnode->inode = inode;
#ifdef VFS_DEBUG
printf("makeNode: inode=%u, size=%u, mode=%o, uid=%u, gid=%u\n", inode.index(), metadata.size, metadata.mode, metadata.uid, metadata.gid);
kprintf("makeNode: inode=%u, size=%u, mode=%o, uid=%u, gid=%u\n", inode.index(), metadata.size, metadata.mode, metadata.uid, metadata.gid);
#endif
m_inode2vnode.set(inode, vnode.ptr());
@ -75,11 +75,11 @@ bool VirtualFileSystem::mount(RetainPtr<FileSystem>&& fileSystem, const String&
auto inode = resolvePath(path);
if (!inode.isValid()) {
printf("[VFS] mount can't resolve mount point '%s'\n", path.characters());
kprintf("[VFS] mount can't resolve mount point '%s'\n", path.characters());
return false;
}
printf("mounting %s{%p} at %s (inode: %u)\n", fileSystem->className(), fileSystem.ptr(), path.characters(), inode.index());
kprintf("mounting %s{%p} at %s (inode: %u)\n", fileSystem->className(), fileSystem.ptr(), path.characters(), inode.index());
// FIXME: check that this is not already a mount point
auto mount = make<Mount>(inode, std::move(fileSystem));
m_mounts.append(std::move(mount));
@ -89,7 +89,7 @@ bool VirtualFileSystem::mount(RetainPtr<FileSystem>&& fileSystem, const String&
bool VirtualFileSystem::mountRoot(RetainPtr<FileSystem>&& fileSystem)
{
if (m_rootNode) {
printf("[VFS] mountRoot can't mount another root\n");
kprintf("[VFS] mountRoot can't mount another root\n");
return false;
}
@ -97,17 +97,17 @@ bool VirtualFileSystem::mountRoot(RetainPtr<FileSystem>&& fileSystem)
auto node = makeNode(mount->guest());
if (!node->inUse()) {
printf("[VFS] root inode for / is not in use :(\n");
kprintf("[VFS] root inode for / is not in use :(\n");
return false;
}
if (!node->inode.metadata().isDirectory()) {
printf("[VFS] root inode for / is not in use :(\n");
kprintf("[VFS] root inode for / is not in use :(\n");
return false;
}
m_rootNode = std::move(node);
printf("[VFS] mountRoot mounted %s{%p}\n",
kprintf("[VFS] mountRoot mounted %s{%p}\n",
m_rootNode->fileSystem()->className(),
m_rootNode->fileSystem());
@ -118,7 +118,7 @@ bool VirtualFileSystem::mountRoot(RetainPtr<FileSystem>&& fileSystem)
auto VirtualFileSystem::allocateNode() -> RetainPtr<Node>
{
if (m_nodeFreeList.isEmpty()) {
printf("[VFS] allocateNode has no nodes left\n");
kprintf("[VFS] allocateNode has no nodes left\n");
return nullptr;
}
auto* node = m_nodeFreeList.takeLast();
@ -200,7 +200,7 @@ void VirtualFileSystem::listDirectory(const String& path)
if (!directoryInode.isValid())
return;
printf("[VFS] ls %s -> %s %02u:%08u\n", path.characters(), directoryInode.fileSystem()->className(), directoryInode.fileSystemID(), directoryInode.index());
kprintf("[VFS] ls %s -> %s %02u:%08u\n", path.characters(), directoryInode.fileSystem()->className(), directoryInode.fileSystemID(), directoryInode.index());
enumerateDirectoryInode(directoryInode, [&] (const FileSystem::DirectoryEntry& entry) {
const char* nameColorBegin = "";
const char* nameColorEnd = "";
@ -221,28 +221,28 @@ void VirtualFileSystem::listDirectory(const String& path)
nameColorBegin = "\033[33;1m";
nameColorEnd = "\033[0m";
}
printf("%02u:%08u ",
kprintf("%02u:%08u ",
metadata.inode.fileSystemID(),
metadata.inode.index());
if (metadata.isDirectory())
printf("d");
kprintf("d");
else if (metadata.isSymbolicLink())
printf("l");
kprintf("l");
else if (metadata.isBlockDevice())
printf("b");
kprintf("b");
else if (metadata.isCharacterDevice())
printf("c");
kprintf("c");
else if (metadata.isSocket())
printf("s");
kprintf("s");
else if (metadata.isFIFO())
printf("f");
kprintf("f");
else if (metadata.isRegularFile())
printf("-");
kprintf("-");
else
printf("?");
kprintf("?");
printf("%c%c%c%c%c%c%c%c",
kprintf("%c%c%c%c%c%c%c%c",
metadata.mode & 00400 ? 'r' : '-',
metadata.mode & 00200 ? 'w' : '-',
metadata.mode & 00100 ? 'x' : '-',
@ -254,41 +254,41 @@ void VirtualFileSystem::listDirectory(const String& path)
);
if (metadata.isSticky())
printf("t");
kprintf("t");
else
printf("%c", metadata.mode & 00001 ? 'x' : '-');
kprintf("%c", metadata.mode & 00001 ? 'x' : '-');
if (metadata.isCharacterDevice() || metadata.isBlockDevice()) {
char buf[16];
sprintf(buf, "%u, %u", metadata.majorDevice, metadata.minorDevice);
printf("%12s ", buf);
kprintf("%12s ", buf);
} else {
printf("%12lld ", metadata.size);
kprintf("%12lld ", metadata.size);
}
printf("\033[30;1m");
kprintf("\033[30;1m");
auto tm = *localtime(&metadata.mtime);
printf("%04u-%02u-%02u %02u:%02u:%02u ",
kprintf("%04u-%02u-%02u %02u:%02u:%02u ",
tm.tm_year + 1900,
tm.tm_mon + 1,
tm.tm_mday,
tm.tm_hour,
tm.tm_min,
tm.tm_sec);
printf("\033[0m");
kprintf("\033[0m");
printf("%s%s%s",
kprintf("%s%s%s",
nameColorBegin,
entry.name.characters(),
nameColorEnd);
if (metadata.isDirectory()) {
printf("/");
kprintf("/");
} else if (metadata.isSymbolicLink()) {
auto symlinkContents = directoryInode.fileSystem()->readEntireInode(metadata.inode);
printf(" -> %s", String((const char*)symlinkContents.pointer(), symlinkContents.size()).characters());
kprintf(" -> %s", String((const char*)symlinkContents.pointer(), symlinkContents.size()).characters());
}
printf("\n");
kprintf("\n");
return true;
});
}
@ -299,7 +299,7 @@ void VirtualFileSystem::listDirectoryRecursively(const String& path)
if (!directory.isValid())
return;
printf("%s\n", path.characters());
kprintf("%s\n", path.characters());
enumerateDirectoryInode(directory, [&] (const FileSystem::DirectoryEntry& entry) {
auto metadata = entry.inode.metadata();
@ -310,7 +310,7 @@ void VirtualFileSystem::listDirectoryRecursively(const String& path)
listDirectoryRecursively(buf);
}
} else {
printf("%s/%s\n", path.characters(), entry.name.characters());
kprintf("%s/%s\n", path.characters(), entry.name.characters());
}
});
}
@ -368,35 +368,35 @@ InodeIdentifier VirtualFileSystem::resolvePath(const String& path)
auto metadata = inode.metadata();
if (!metadata.isValid()) {
#ifdef VFS_DEBUG
printf("invalid metadata\n");
kprintf("invalid metadata\n");
#endif
return InodeIdentifier();
}
if (!metadata.isDirectory()) {
#ifdef VFS_DEBUG
printf("not directory\n");
kprintf("not directory\n");
#endif
return InodeIdentifier();
}
inode = inode.fileSystem()->childOfDirectoryInodeWithName(inode, part);
if (!inode.isValid()) {
#ifdef VFS_DEBUG
printf("bad child\n");
kprintf("bad child\n");
#endif
return InodeIdentifier();
}
#ifdef VFS_DEBUG
printf("<%s> %02u:%08u\n", part.characters(), inode.fileSystemID(), inode.index());
kprintf("<%s> %02u:%08u\n", part.characters(), inode.fileSystemID(), inode.index());
#endif
if (auto mount = findMountForHost(inode)) {
#ifdef VFS_DEBUG
printf(" -- is host\n");
kprintf(" -- is host\n");
#endif
inode = mount->guest();
}
if (inode.isRootInode() && !isRoot(inode) && part == "..") {
#ifdef VFS_DEBUG
printf(" -- is guest\n");
kprintf(" -- is guest\n");
#endif
auto mount = findMountForGuest(inode);
inode = mount->host();
@ -411,7 +411,7 @@ InodeIdentifier VirtualFileSystem::resolvePath(const String& path)
}
inode = resolveSymbolicLink(buf, inode);
if (!inode.isValid()) {
printf("Symbolic link resolution failed :(\n");
kprintf("Symbolic link resolution failed :(\n");
return { };
}
}

View file

@ -9,7 +9,9 @@
#include "RandomDevice.h"
#include <cstring>
#include <AK/SimpleMalloc.h>
#include <AK/StdLib.h>
#include <AK/kmalloc.h>
#include <AK/ktime.h>
static RetainPtr<FileSystem> makeFileSystem(const char* imagePath);