2#include "pedigree/kernel/LockGuard.h"
3#include "pedigree/kernel/utilities/utility.h"
6#include "Ext2Filesystem.h"
8#include "modules/system/vfs/VFS.h"
11constexpr int32_t HandleType = 0x50444731;
12constexpr uint32_t HandleLength = 24;
16 for (
size_t i = 0; i < 16; ++i) {
17 value |=
static_cast<uint8_t
>(superblock->s_uuid[i]);
22uint32_t load32(
const uint8_t* bytes) {
24 MemoryCopy(&value, bytes,
sizeof(value));
25 return LITTLE_TO_HOST32(value);
28void store32(uint8_t* bytes, uint32_t value) {
29 value = HOST_TO_LITTLE32(value);
30 MemoryCopy(bytes, &value,
sizeof(value));
34FileHandleStatus Ext2Filesystem::fileHandleFsid(
FileSystemId& result) {
37 return FileHandleStatus::Unsupported;
39 const auto* uuid =
reinterpret_cast<const uint8_t*
>(
m_pSuperblock->s_uuid);
40 result.words[0] = load32(uuid) ^ load32(uuid + 8);
41 result.words[1] = load32(uuid + 4) ^ load32(uuid + 12);
42 if (!result.words[0] && !result.words[1]) {
45 return FileHandleStatus::Success;
48FileHandleStatus Ext2Filesystem::validateHandleInodeLocked(uint32_t number, uint32_t generation,
51 const uint32_t perGroup = LITTLE_TO_HOST32(
m_pSuperblock->s_inodes_per_group);
52 if (!number || number > LITTLE_TO_HOST32(
m_pSuperblock->s_inodes_count) || !perGroup ||
54 return FileHandleStatus::Stale;
56 const uint32_t group = (number - 1) / perGroup, index = (number - 1) % perGroup;
57 if (!ensureFreeInodeBitmapLoaded(group)) {
58 return FileHandleStatus::IoError;
63 if (!(*
byte & (1U << (index % 8)))) {
64 return FileHandleStatus::Stale;
66 inode = getInode(number);
68 return FileHandleStatus::IoError;
72 if (!LITTLE_TO_HOST16(inode->i_links_count) ||
73 LITTLE_TO_HOST32(inode->i_generation) != generation ||
74 (LITTLE_TO_HOST16(inode->i_mode) & 0xf000) != EXT2_S_IFREG) {
75 return FileHandleStatus::Stale;
77 return FileHandleStatus::Success;
84 return FileHandleStatus::Unsupported;
86 const uintptr_t number = file.getInode();
87 if (!number || number > LITTLE_TO_HOST32(
m_pSuperblock->s_inodes_count)) {
88 return FileHandleStatus::Stale;
92 if (!state || state->orphan) {
93 return FileHandleStatus::Stale;
96#if THREADS || defined(STANDALONE_MUTEXES)
99 Inode* inode = getInode(number);
101 return FileHandleStatus::IoError;
103 const uint32_t generation = LITTLE_TO_HOST32(inode->i_generation);
104 const auto status = validateHandleInodeLocked(number, generation, inode);
105 if (status != FileHandleStatus::Success) {
108 result.length = HandleLength;
109 result.type = HandleType;
111 store32(result.bytes + 16, number);
112 store32(result.bytes + 20, generation);
113 return FileHandleStatus::Success;
119 return FileHandleStatus::Unsupported;
121 if (handle.type != HandleType || handle.length != HandleLength ||
123 return FileHandleStatus::Stale;
125 const uint32_t number = load32(handle.bytes + 16), generation = load32(handle.bytes + 20);
126 Inode* inode =
nullptr;
131 LockGuard<Mutex> metadata(state ? state->writebackLock : m_InodeStateLock, state != nullptr);
132#if THREADS || defined(STANDALONE_MUTEXES)
135 const auto status = validateHandleInodeLocked(number, generation, inode);
136 if (status != FileHandleStatus::Success) {
139 if (state && state->orphan) {
140 return FileHandleStatus::Stale;
142 admitted = acquireInodeStateLocked(number, inode);
144 return FileHandleStatus::NoMemory;
150 Ext2Node admission(number, inode,
this, *admitted);
151 if (!admitted->allocationValid) {
152 return FileHandleStatus::IoError;
157 return FileHandleStatus::NoMemory;
160 return FileHandleStatus::Success;
size_t m_nGroupDescriptors
Vector< size_t > * m_pInodeBitmaps
virtual FileHandleStatus encodeFileHandle(File &, FileHandle &)
Superblock * m_pSuperblock
bool supportsRegularFileOperations()
E lookup(const K &key) const
bool tryTrackFile(File *pFile)