* Copyright 2022, Raghav Sharma, raghavself28@gmail.com
* Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef _EXTENT_H_
#define _EXTENT_H_
#include "Directory.h"
#include "Inode.h"
#include "system_dependencies.h"
#define DIR2_BLOCK_HEADER_MAGIC 0x58443242
#define DIR3_BLOCK_HEADER_MAGIC 0x58444233
#define DIR2_FREE_TAG 0xffff
#define XFS_DIR2_DATA_FD_COUNT 3
#define EXTENT_SIZE 16
#define BLOCKNO_FROM_ADDRESS(n, volume) \
((n) >> (volume->BlockLog() + volume->DirBlockLog()))
#define BLOCKOFFSET_FROM_ADDRESS(n, inode) ((n) & (inode->DirBlockSize() - 1))
#define LEAF_STARTOFFSET(n) 1UL << (35 - (n))
enum DirectoryType {
XFS_BLOCK,
XFS_LEAF,
XFS_NODE,
XFS_BTREE,
};
struct FreeRegion {
uint16 offset;
uint16 length;
};
class ExtentDataHeader
{
public:
virtual ~ExtentDataHeader() = 0;
virtual uint32 Magic() = 0;
virtual uint64 Blockno() = 0;
virtual uint64 Lsn() = 0;
virtual uint64 Owner() = 0;
virtual const uuid_t& Uuid() = 0;
static uint32 ExpectedMagic(int8 WhichDirectory,
Inode* inode);
static uint32 CRCOffset();
static ExtentDataHeader* Create(Inode* inode, const char* buffer);
static uint32 Size(Inode* inode);
};
class ExtentDataHeaderV4 : public ExtentDataHeader
{
public :
struct OnDiskData {
public:
uint32 magic;
FreeRegion bestfree[XFS_DIR2_DATA_FD_COUNT];
};
ExtentDataHeaderV4(const char* buffer);
~ExtentDataHeaderV4();
uint32 Magic();
uint64 Blockno();
uint64 Lsn();
uint64 Owner();
const uuid_t& Uuid();
private:
void _SwapEndian();
private:
OnDiskData fData;
};
class ExtentDataHeaderV5 : public ExtentDataHeader
{
public:
struct OnDiskData {
public:
uint32 magic;
uint32 crc;
uint64 blkno;
uint64 lsn;
uuid_t uuid;
uint64 owner;
FreeRegion bestfree[XFS_DIR2_DATA_FD_COUNT];
uint32 pad;
};
ExtentDataHeaderV5(const char* buffer);
~ExtentDataHeaderV5();
uint32 Magic();
uint64 Blockno();
uint64 Lsn();
uint64 Owner();
const uuid_t& Uuid();
private:
void _SwapEndian();
private:
OnDiskData fData;
};
struct ExtentDataEntry {
xfs_ino_t inumber;
uint8 namelen;
uint8 name[];
};
struct ExtentUnusedEntry {
uint16 freetag;
uint16 length;
uint16 tag;
};
struct ExtentLeafEntry {
uint32 hashval;
uint32 address;
};
struct ExtentBlockTail {
uint32 count;
uint32 stale;
};
class Extent : public DirectoryIterator {
public:
Extent(Inode* inode);
~Extent();
status_t Init();
bool IsBlockType();
void FillMapEntry(void* pointerToMap);
status_t FillBlockBuffer();
ExtentBlockTail* BlockTail();
ExtentLeafEntry* BlockFirstLeaf(ExtentBlockTail* tail);
xfs_ino_t GetIno();
uint32 GetOffsetFromAddress(uint32 address);
int EntrySize(int len) const;
status_t GetNext(char* name, size_t* length,
xfs_ino_t* ino);
status_t Lookup(const char* name, size_t length,
xfs_ino_t* id);
private:
Inode* fInode;
ExtentMapEntry* fMap;
uint32 fOffset;
char* fBlockBuffer;
};
#endif