xfs: An attempt at reading shortform dir
This patch gets read_dir, lookup and few others to work. Entries cannot be listed yet except the root. Change-Id: Ic4b7b61a794a1b75849e45777a383b3315b15aa8 Reviewed-on: https://review.haiku-os.org/c/haiku/+/2915 Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
committed by
Adrien Destugues
parent
66f0993a1b
commit
7e1b5cf809
@@ -1,7 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "BPlusTree.h"
|
#include "BPlusTree.h"
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +1,28 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _BPLUS_TREE_H_
|
#ifndef _BPLUS_TREE_H_
|
||||||
#define _BPLUS_TREE_H_
|
#define _BPLUS_TREE_H_
|
||||||
|
|
||||||
#include "system_dependencies.h"
|
#include "system_dependencies.h"
|
||||||
|
|
||||||
|
|
||||||
/* Allocation B+ Tree Format */
|
/* Allocation B+ Tree Format */
|
||||||
#define XFS_ABTB_MAGICNUM 0x41425442 // For block offset B+Tree
|
#define XFS_ABTB_MAGICNUM 0x41425442
|
||||||
#define XFS_ABTC_MAGICNUM 0x41425443 // For block count B+ Tree
|
// For block offset B+Tree
|
||||||
|
#define XFS_ABTC_MAGICNUM 0x41425443
|
||||||
|
// For block count B+ Tree
|
||||||
/* Header for Short Format btree */
|
|
||||||
#define XFS_BTREE_SBLOCK_SIZE 18
|
#define XFS_BTREE_SBLOCK_SIZE 18
|
||||||
|
// Header for Short Format btree
|
||||||
/* Header for Long Format btree */
|
|
||||||
#define XFS_BTREE_LBLOCK_SIZE 24
|
#define XFS_BTREE_LBLOCK_SIZE 24
|
||||||
|
// Header for Long Format btree
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Headers are the "nodes" really and are called "blocks". The records, keys and
|
* Headers are the "nodes" really and are called "blocks". The records, keys
|
||||||
* pts are calculated using helpers
|
* and ptrs are calculated using helpers
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct bplustree_short_block {
|
struct bplustree_short_block {
|
||||||
void SwapEndian();
|
void SwapEndian();
|
||||||
|
|
||||||
@@ -93,11 +91,11 @@ typedef struct xfs_alloc_rec {
|
|||||||
|
|
||||||
} xfs_alloc_rec_t, xfs_alloc_key_t;
|
} xfs_alloc_rec_t, xfs_alloc_key_t;
|
||||||
|
|
||||||
// Swap Endians while returning itself
|
|
||||||
typedef uint32 xfs_alloc_ptr_t; // Node pointers, AG relative block pointer
|
typedef uint32 xfs_alloc_ptr_t;
|
||||||
|
// Node pointers, AG relative block pointer
|
||||||
|
|
||||||
#define ALLOC_FLAG 0x1
|
#define ALLOC_FLAG 0x1
|
||||||
|
|
||||||
#define LONG_BLOCK_FLAG 0x1
|
#define LONG_BLOCK_FLAG 0x1
|
||||||
#define SHORT_BLOCK_FLAG 0x2
|
#define SHORT_BLOCK_FLAG 0x2
|
||||||
|
|
||||||
@@ -118,7 +116,7 @@ union btree_rec {
|
|||||||
|
|
||||||
|
|
||||||
class BPlusTree {
|
class BPlusTree {
|
||||||
public:
|
public:
|
||||||
uint32 BlockSize();
|
uint32 BlockSize();
|
||||||
int RecordSize();
|
int RecordSize();
|
||||||
int MaxRecords(bool leaf);
|
int MaxRecords(bool leaf);
|
||||||
@@ -129,7 +127,7 @@ class BPlusTree {
|
|||||||
int KeyOffset(int pos); // get the pos'th key
|
int KeyOffset(int pos); // get the pos'th key
|
||||||
int PtrOffset(int pos); // get the pos'th ptr
|
int PtrOffset(int pos); // get the pos'th ptr
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Volume* fVolume;
|
Volume* fVolume;
|
||||||
xfs_agnumber_t fAgnumber;
|
xfs_agnumber_t fAgnumber;
|
||||||
btree_ptr* fRoot;
|
btree_ptr* fRoot;
|
||||||
@@ -140,4 +138,3 @@ class BPlusTree {
|
|||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#ifndef _DEBUG_H_
|
#ifndef _DEBUG_H_
|
||||||
#define _DEBUG_H_
|
#define _DEBUG_H_
|
||||||
|
|
||||||
#define TRACE_XFS
|
// #define TRACE_XFS
|
||||||
#ifdef TRACE_XFS
|
#ifdef TRACE_XFS
|
||||||
#define TRACE(x...) dprintf("\n\33[34mxfs:\33[0m " x)
|
#define TRACE(x...) dprintf("\n\33[34mxfs:\33[0m " x)
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "Directory.h"
|
||||||
|
|
||||||
|
|
||||||
|
DirectoryIterator::DirectoryIterator(Inode* inode)
|
||||||
|
{
|
||||||
|
fInode = inode;
|
||||||
|
fShortDir = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DirectoryIterator::~DirectoryIterator()
|
||||||
|
{
|
||||||
|
delete fShortDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DirectoryIterator::Init()
|
||||||
|
{
|
||||||
|
if (fInode->Format() == XFS_DINODE_FMT_LOCAL)
|
||||||
|
{
|
||||||
|
fShortDir = new(std::nothrow) ShortDirectory(fInode);
|
||||||
|
if (fShortDir == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return B_OK so even if the shortform directory has an extent directory
|
||||||
|
* we can atleast still list the shortform directory
|
||||||
|
*/
|
||||||
|
|
||||||
|
//TODO: Reading from extent based directories
|
||||||
|
if (fInode->Format() == XFS_DINODE_FMT_EXTENTS) {
|
||||||
|
TRACE("Iterator:GetNext: EXTENTS");
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: Reading from B+Trees based directories
|
||||||
|
if (fInode->Format() == XFS_DINODE_FMT_BTREE) {
|
||||||
|
TRACE("Iterator:GetNext: B+TREE");
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DirectoryIterator::GetNext(char* name, size_t* length, xfs_ino_t* ino)
|
||||||
|
{
|
||||||
|
if (fInode->Format() == XFS_DINODE_FMT_LOCAL) {
|
||||||
|
status_t status = fShortDir->GetNext(name, length, ino);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: Reading from extent based directories
|
||||||
|
if (fInode->Format() == XFS_DINODE_FMT_EXTENTS) {
|
||||||
|
TRACE("Iterator:GetNext: EXTENTS");
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: Reading from B+Trees based directories
|
||||||
|
if (fInode->Format() == XFS_DINODE_FMT_BTREE) {
|
||||||
|
TRACE("Iterator:GetNext: B+TREE");
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only reaches here if Inode is a device or is corrupt.
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DirectoryIterator::Lookup(const char* name, size_t length, xfs_ino_t* ino)
|
||||||
|
{
|
||||||
|
if (fInode->Format() == XFS_DINODE_FMT_LOCAL) {
|
||||||
|
status_t status = fShortDir->Lookup(name, length, ino);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: Reading from extent based dirs
|
||||||
|
if (fInode->Format() == XFS_DINODE_FMT_EXTENTS) {
|
||||||
|
TRACE("Iterator:Lookup: EXTENTS");
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: Reading from B+Tree based dirs
|
||||||
|
if (fInode->Format() == XFS_DINODE_FMT_BTREE) {
|
||||||
|
TRACE("Iterator:Lookup: B+TREE");
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _DIRECTORY_H_
|
||||||
|
#define _DIRECTORY_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include "Inode.h"
|
||||||
|
#include "ShortDirectory.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This class should act as a layer between any kind of directory
|
||||||
|
* and the kernel interface
|
||||||
|
*/
|
||||||
|
class DirectoryIterator {
|
||||||
|
public:
|
||||||
|
DirectoryIterator(Inode* inode);
|
||||||
|
~DirectoryIterator();
|
||||||
|
status_t Init();
|
||||||
|
bool IsLocalDir() { return fInode->IsLocal(); }
|
||||||
|
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;
|
||||||
|
ShortDirectory* fShortDir;
|
||||||
|
// Short form Directory type
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "Inode.h"
|
#include "Inode.h"
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
xfs_inode::SwapEndian()
|
xfs_inode_t::SwapEndian()
|
||||||
{
|
{
|
||||||
di_magic = B_BENDIAN_TO_HOST_INT16(di_magic);
|
di_magic = B_BENDIAN_TO_HOST_INT16(di_magic);
|
||||||
di_mode = B_BENDIAN_TO_HOST_INT16(di_mode);
|
di_mode = B_BENDIAN_TO_HOST_INT16(di_mode);
|
||||||
@@ -37,42 +38,42 @@ xfs_inode::SwapEndian()
|
|||||||
|
|
||||||
|
|
||||||
xfs_rfsblock_t
|
xfs_rfsblock_t
|
||||||
xfs_inode::NoOfBlocks() const
|
xfs_inode_t::NoOfBlocks() const
|
||||||
{
|
{
|
||||||
return di_nblocks;
|
return di_nblocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
xfs_fsize_t
|
xfs_fsize_t
|
||||||
xfs_inode::Size() const
|
xfs_inode_t::Size() const
|
||||||
{
|
{
|
||||||
return di_size;
|
return di_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mode_t
|
mode_t
|
||||||
xfs_inode::Mode()
|
xfs_inode_t::Mode() const
|
||||||
{
|
{
|
||||||
return di_mode;
|
return di_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32
|
uint32
|
||||||
xfs_inode::UserId()
|
xfs_inode_t::UserId() const
|
||||||
{
|
{
|
||||||
return di_uid;
|
return di_uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32
|
uint32
|
||||||
xfs_inode::GroupId()
|
xfs_inode_t::GroupId() const
|
||||||
{
|
{
|
||||||
return di_gid;
|
return di_gid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
xfs_inode::GetModificationTime(struct timespec& stamp)
|
xfs_inode_t::GetModificationTime(struct timespec& stamp)
|
||||||
{
|
{
|
||||||
stamp.tv_sec = di_mtime.t_sec;
|
stamp.tv_sec = di_mtime.t_sec;
|
||||||
stamp.tv_nsec = di_mtime.t_nsec;
|
stamp.tv_nsec = di_mtime.t_nsec;
|
||||||
@@ -80,7 +81,7 @@ xfs_inode::GetModificationTime(struct timespec& stamp)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
xfs_inode::GetAccessTime(struct timespec& stamp)
|
xfs_inode_t::GetAccessTime(struct timespec& stamp)
|
||||||
{
|
{
|
||||||
stamp.tv_sec = di_atime.t_sec;
|
stamp.tv_sec = di_atime.t_sec;
|
||||||
stamp.tv_nsec = di_atime.t_nsec;
|
stamp.tv_nsec = di_atime.t_nsec;
|
||||||
@@ -88,7 +89,7 @@ xfs_inode::GetAccessTime(struct timespec& stamp)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
xfs_inode::GetChangeTime(struct timespec& stamp)
|
xfs_inode_t::GetChangeTime(struct timespec& stamp)
|
||||||
{
|
{
|
||||||
stamp.tv_sec = di_ctime.t_sec;
|
stamp.tv_sec = di_ctime.t_sec;
|
||||||
stamp.tv_nsec = di_ctime.t_nsec;
|
stamp.tv_nsec = di_ctime.t_nsec;
|
||||||
@@ -96,51 +97,66 @@ xfs_inode::GetChangeTime(struct timespec& stamp)
|
|||||||
|
|
||||||
|
|
||||||
uint32
|
uint32
|
||||||
xfs_inode::NLink()
|
xfs_inode_t::NLink() const
|
||||||
{
|
{
|
||||||
return di_nlink;
|
return di_nlink;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int8
|
int8
|
||||||
xfs_inode::Version()
|
xfs_inode_t::Version() const
|
||||||
{
|
{
|
||||||
return di_version;
|
return di_version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint16
|
uint16
|
||||||
xfs_inode::Flags()
|
xfs_inode_t::Flags() const
|
||||||
{
|
{
|
||||||
return di_flags;
|
return di_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int8
|
int8
|
||||||
xfs_inode::Format()
|
xfs_inode_t::Format() const
|
||||||
{
|
{
|
||||||
return di_format;
|
return di_format;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Inode::Inode(Volume* volume, xfs_ino_t id)
|
Inode::Inode(Volume* volume, xfs_ino_t id)
|
||||||
|
:
|
||||||
|
fVolume(volume),
|
||||||
|
fId(id)
|
||||||
{
|
{
|
||||||
fVolume = volume;
|
|
||||||
fId = id;
|
|
||||||
fNode = new(std::nothrow) xfs_inode_t;
|
|
||||||
|
|
||||||
uint16 inodeSize = volume->InodeSize();
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Inode::Init()
|
||||||
|
{
|
||||||
|
fNode = new(std::nothrow) xfs_inode_t;
|
||||||
|
if (fNode == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
uint16 inodeSize = fVolume->InodeSize();
|
||||||
fBuffer = new(std::nothrow) char[inodeSize];
|
fBuffer = new(std::nothrow) char[inodeSize];
|
||||||
|
if (fBuffer == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
status_t status = GetFromDisk();
|
status_t status = GetFromDisk();
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
status = InitCheck();
|
if (fNode->di_magic == INODE_MAGIC) {
|
||||||
if (status) {
|
TRACE("Init(): Inode successfully read.\n");
|
||||||
TRACE("Inode successfully read!");
|
status = B_OK;
|
||||||
} else {
|
} else {
|
||||||
TRACE("Inode wasn't read successfully!");
|
TRACE("Init(): Inode wasn't read successfully!\n");
|
||||||
|
status = B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -149,29 +165,28 @@ Inode::GetFromDisk()
|
|||||||
{
|
{
|
||||||
xfs_agnumber_t agNo = INO_TO_AGNO(fId, fVolume);
|
xfs_agnumber_t agNo = INO_TO_AGNO(fId, fVolume);
|
||||||
// Get the AG number from the inode
|
// Get the AG number from the inode
|
||||||
uint32 agInodeNo = INO_TO_AGINO(fId, fVolume->AgInodeBits());
|
uint32 agRelativeInodeNo = INO_TO_AGINO(fId, fVolume->AgInodeBits());
|
||||||
// AG relative ino #
|
// AG relative ino #
|
||||||
xfs_agblock_t agBlock = INO_TO_AGBLOCK(agInodeNo, fVolume);
|
xfs_agblock_t agBlock = INO_TO_AGBLOCK(agRelativeInodeNo, fVolume);
|
||||||
// AG relative block number
|
// AG relative block number
|
||||||
xfs_off_t offset = INO_TO_OFFSET(fId, fVolume);
|
xfs_off_t offset = INO_TO_BLOCKOFFSET(fId, fVolume);
|
||||||
// Offset into the block
|
// Offset into the block1
|
||||||
uint32 len = fVolume->InodeSize();
|
uint32 len = fVolume->InodeSize();
|
||||||
// Inode len to read (size of inode)
|
// Inode len to read (size of inode)
|
||||||
int fd = fVolume->Device();
|
|
||||||
|
|
||||||
if (agNo > fVolume->AgCount()) {
|
if (agNo > fVolume->AgCount()) {
|
||||||
ERROR("Inode::GetFromDisk : AG Number more than number of AGs");
|
ERROR("Inode::GetFromDisk : AG Number more than number of AGs");
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
xfs_agblock_t agBlocks = fVolume->AgBlocks();
|
xfs_agblock_t numberOfBlocksInAg = fVolume->AgBlocks();
|
||||||
|
|
||||||
xfs_fsblock_t blockToRead =
|
xfs_fsblock_t blockToRead = FSBLOCKS_TO_BASICBLOCKS(fVolume->BlockLog(),
|
||||||
FSB_TO_BB(fVolume->BlockLog(), ((uint64)(agNo * agBlocks) + agBlock));
|
((uint64)(agNo * numberOfBlocksInAg) + agBlock));
|
||||||
|
|
||||||
xfs_daddr_t readPos = blockToRead*(BBLOCKSIZE) + offset;
|
xfs_daddr_t readPos = blockToRead*(BASICBLOCKSIZE) + offset;
|
||||||
|
|
||||||
if (read_pos(fd, readPos, fBuffer, len) != len) {
|
if (read_pos(fVolume->Device(), readPos, fBuffer, len) != len) {
|
||||||
ERROR("Inode::Inode(): IO Error");
|
ERROR("Inode::Inode(): IO Error");
|
||||||
return B_IO_ERROR;
|
return B_IO_ERROR;
|
||||||
}
|
}
|
||||||
@@ -183,13 +198,6 @@ Inode::GetFromDisk()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
Inode::InitCheck()
|
|
||||||
{
|
|
||||||
return fNode->di_magic == INODE_MAGIC;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Inode::~Inode()
|
Inode::~Inode()
|
||||||
{
|
{
|
||||||
delete fBuffer;
|
delete fBuffer;
|
||||||
|
|||||||
@@ -1,22 +1,23 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _INODE_H_
|
#ifndef _INODE_H_
|
||||||
#define _INODE_H_
|
#define _INODE_H_
|
||||||
|
|
||||||
|
|
||||||
#include "system_dependencies.h"
|
#include "system_dependencies.h"
|
||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
#include "xfs_types.h"
|
#include "xfs_types.h"
|
||||||
|
|
||||||
|
|
||||||
#define INODE_MAGIC 0x494e
|
#define INODE_MAGIC 0x494e
|
||||||
#define INODE_CORE_SIZE 96 // For v4 FS
|
#define INODE_MINSIZE_LOG 8
|
||||||
#define INODE_CORE_UNLINKED_SIZE 100 //For v4 FS
|
#define INODE_MAXSIZE_LOG 11
|
||||||
|
#define INODE_CORE_SIZE 96
|
||||||
|
#define INODE_CORE_UNLINKED_SIZE 100
|
||||||
|
// Inode core but with unlinked pointer
|
||||||
#define DATA_FORK_OFFSET 0x64
|
#define DATA_FORK_OFFSET 0x64
|
||||||
|
// For v4 FS
|
||||||
#define INO_MASK(x) ((1ULL << (x)) - 1)
|
#define INO_MASK(x) ((1ULL << (x)) - 1)
|
||||||
// Gets 2^x - 1
|
// Gets 2^x - 1
|
||||||
#define INO_TO_AGNO(id, volume) (xfs_agnumber_t)id >> (volume->AgInodeBits())
|
#define INO_TO_AGNO(id, volume) (xfs_agnumber_t)id >> (volume->AgInodeBits())
|
||||||
@@ -27,132 +28,156 @@
|
|||||||
(id >> (volume->InodesPerBlkLog())) \
|
(id >> (volume->InodesPerBlkLog())) \
|
||||||
& (INO_MASK(volume->AgBlocksLog()))
|
& (INO_MASK(volume->AgBlocksLog()))
|
||||||
// Gets the AG relative block number that contains inode
|
// Gets the AG relative block number that contains inode
|
||||||
#define INO_TO_OFFSET(id, volume) (id & INO_MASK(volume->InodesPerBlkLog()))
|
#define INO_TO_BLOCKOFFSET(id, volume) (id & INO_MASK(volume->InodesPerBlkLog()))
|
||||||
// Gets the offset into the block from the inode number
|
// Gets the offset into the block from the inode number
|
||||||
|
#define DIR_DFORK_PTR(dir_ino_ptr) (char*) dir_ino_ptr + DATA_FORK_OFFSET
|
||||||
|
#define DIR_AFORK_PTR(dir_ino_ptr) \
|
||||||
|
(XFS_DFORK_PTR + \
|
||||||
|
((uint32)dir_ino_ptr->di_forkoff<<3))
|
||||||
|
#define DIR_AFORK_EXIST(dir_ino_ptr) dir_ino_ptr->di_forkoff!=0
|
||||||
|
|
||||||
|
|
||||||
typedef struct xfs_timestamp
|
struct xfs_timestamp_t {
|
||||||
{
|
|
||||||
int32 t_sec;
|
int32 t_sec;
|
||||||
int32 t_nsec;
|
int32 t_nsec;
|
||||||
} xfs_timestamp_t;
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef enum xfs_dinode_fmt
|
enum xfs_dinode_fmt_t {
|
||||||
{
|
XFS_DINODE_FMT_DEV,
|
||||||
XFS_DINODE_FMT_DEV, // For devices
|
// For devices
|
||||||
XFS_DINODE_FMT_LOCAL, // For Directories and links
|
XFS_DINODE_FMT_LOCAL,
|
||||||
XFS_DINODE_FMT_EXTENTS, // For large number of extents
|
// For Directories and links
|
||||||
XFS_DINODE_FMT_BTREE, // Extents and Directories
|
XFS_DINODE_FMT_EXTENTS,
|
||||||
XFS_DINODE_FMT_UUID, // Not used
|
// For large number of extents
|
||||||
} xfs_dinode_fmt_t;
|
XFS_DINODE_FMT_BTREE,
|
||||||
|
// Extents and Directories
|
||||||
|
XFS_DINODE_FMT_UUID,
|
||||||
|
// Not used
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The xfs_ino_t is the same for all types of inodes, the data and attribute
|
* The xfs_ino_t is the same for all types of inodes, the data and attribute
|
||||||
fork might be different and that is to be handled accordingly.
|
* fork might be different and that is to be handled accordingly.
|
||||||
*/
|
*/
|
||||||
typedef struct xfs_inode
|
struct xfs_inode_t {
|
||||||
{
|
void SwapEndian();
|
||||||
void SwapEndian();
|
int8 Version() const;
|
||||||
int8 Version(); //TODO
|
//TODO: Check
|
||||||
mode_t Mode();
|
mode_t Mode() const;
|
||||||
void GetModificationTime(struct timespec& timestamp);
|
void GetModificationTime(struct timespec&
|
||||||
void GetChangeTime(struct timespec& timestamp);
|
timestamp);
|
||||||
void GetAccessTime(struct timespec& timestamp);
|
void GetChangeTime(struct timespec& timestamp);
|
||||||
int8 Format(); // The format of the inode
|
void GetAccessTime(struct timespec& timestamp);
|
||||||
xfs_fsize_t Size() const; // TODO
|
int8 Format() const;
|
||||||
xfs_rfsblock_t NoOfBlocks() const;
|
// The format of the inode
|
||||||
uint32 NLink();
|
xfs_fsize_t Size() const;
|
||||||
uint16 Flags();
|
xfs_rfsblock_t NoOfBlocks() const;
|
||||||
uint32 UserId();
|
uint32 NLink() const;
|
||||||
uint32 GroupId();
|
uint16 Flags() const;
|
||||||
|
uint32 UserId() const;
|
||||||
|
uint32 GroupId() const;
|
||||||
|
|
||||||
uint16 di_magic;
|
uint16 di_magic;
|
||||||
uint16 di_mode; // uses standard S_Ixxx
|
uint16 di_mode;
|
||||||
int8 di_version; // 1 or 2
|
// uses standard S_Ixxx
|
||||||
int8 di_format;
|
int8 di_version;
|
||||||
uint16 di_onlink;
|
//This either would be 1 or 2
|
||||||
uint32 di_uid;
|
int8 di_format;
|
||||||
uint32 di_gid;
|
uint16 di_onlink;
|
||||||
uint32 di_nlink;
|
uint32 di_uid;
|
||||||
uint16 di_projid;
|
uint32 di_gid;
|
||||||
uint8 di_pad[8];
|
uint32 di_nlink;
|
||||||
uint16 di_flushiter;
|
uint16 di_projid;
|
||||||
xfs_timestamp_t di_atime;
|
uint8 di_pad[8];
|
||||||
xfs_timestamp_t di_mtime;
|
uint16 di_flushiter;
|
||||||
xfs_timestamp_t di_ctime;
|
xfs_timestamp_t di_atime;
|
||||||
xfs_fsize_t di_size; // size in bytes or length if link
|
xfs_timestamp_t di_mtime;
|
||||||
xfs_rfsblock_t di_nblocks; // blocks used including metadata
|
xfs_timestamp_t di_ctime;
|
||||||
// extended attributes not included
|
xfs_fsize_t di_size;
|
||||||
xfs_extlen_t di_extsize; // extent size
|
// size in bytes or length if link
|
||||||
xfs_extnum_t di_nextents; // number of data extents
|
xfs_rfsblock_t di_nblocks;
|
||||||
xfs_aextnum_t di_anextents; // number of EA extents
|
// blocks used including metadata
|
||||||
uint8 di_forkoff; // decides where di_a starts
|
// extended attributes not included
|
||||||
int8 di_aformat; // similar to di_format
|
xfs_extlen_t di_extsize;
|
||||||
uint32 di_dmevmask;
|
// extent size
|
||||||
uint16 di_dmstate;
|
xfs_extnum_t di_nextents;
|
||||||
uint16 di_flags;
|
// number of data extents
|
||||||
uint32 di_gen;
|
xfs_aextnum_t di_anextents;
|
||||||
|
// number of EA extents
|
||||||
|
uint8 di_forkoff;
|
||||||
|
// decides where di_a starts
|
||||||
|
int8 di_aformat;
|
||||||
|
// similar to di_format
|
||||||
|
uint32 di_dmevmask;
|
||||||
|
uint16 di_dmstate;
|
||||||
|
uint16 di_flags;
|
||||||
|
uint32 di_gen;
|
||||||
|
|
||||||
uint32 di_next_unlinked;
|
uint32 di_next_unlinked;
|
||||||
} xfs_inode_t;
|
};
|
||||||
|
|
||||||
|
|
||||||
class Inode
|
class Inode {
|
||||||
{
|
public:
|
||||||
public:
|
Inode(Volume* volume, xfs_ino_t id);
|
||||||
Inode(Volume* volume, xfs_ino_t id);
|
~Inode();
|
||||||
~Inode();
|
status_t Init();
|
||||||
bool InitCheck();
|
|
||||||
|
|
||||||
xfs_ino_t ID() const { return fId; }
|
xfs_ino_t ID() const { return fId; }
|
||||||
|
|
||||||
bool IsDirectory() const
|
bool IsDirectory() const
|
||||||
{ return S_ISDIR(Mode()); }
|
{ return S_ISDIR(Mode()); }
|
||||||
|
|
||||||
bool IsFile() const
|
bool IsFile() const
|
||||||
{ return S_ISREG(Mode()); }
|
{ return S_ISREG(Mode()); }
|
||||||
|
|
||||||
bool IsSymLink() const
|
bool IsSymLink() const
|
||||||
{ return S_ISLNK(Mode()); }
|
{ return S_ISLNK(Mode()); }
|
||||||
|
|
||||||
mode_t Mode() const { return fNode->Mode(); }
|
mode_t Mode() const { return fNode->Mode(); }
|
||||||
|
|
||||||
Volume* GetVolume() { return fVolume;}
|
Volume* GetVolume() { return fVolume;}
|
||||||
|
|
||||||
int8 Format() { return fNode->Format(); }
|
int8 Format() const { return fNode->Format(); }
|
||||||
|
|
||||||
bool IsLocal() { return Format() == XFS_DINODE_FMT_LOCAL; }
|
bool IsLocal() const
|
||||||
|
{ return
|
||||||
|
Format() == XFS_DINODE_FMT_LOCAL; }
|
||||||
|
|
||||||
uint32 NLink() { return fNode->NLink(); }
|
uint32 NLink() const { return fNode->NLink(); }
|
||||||
|
|
||||||
int8 Version() { return fNode->Version(); }
|
int8 Version() const { return fNode->Version(); }
|
||||||
|
|
||||||
xfs_fsize_t Size() const { return fNode->Size(); }
|
xfs_rfsblock_t NoOfBlocks() const
|
||||||
|
{ return fNode->NoOfBlocks(); }
|
||||||
|
|
||||||
xfs_rfsblock_t NoOfBlocks() const { return fNode->NoOfBlocks(); }
|
char* Buffer() { return fBuffer; }
|
||||||
|
|
||||||
int16 Flags() const { return fNode->Flags(); }
|
int16 Flags() const { return fNode->Flags(); }
|
||||||
|
|
||||||
void GetChangeTime(struct timespec& timestamp) const
|
xfs_fsize_t Size() const { return fNode->Size(); }
|
||||||
{ fNode->GetChangeTime(timestamp); }
|
|
||||||
|
|
||||||
void GetModificationTime(struct timespec& timestamp) const
|
void GetChangeTime(struct timespec& timestamp) const
|
||||||
{ fNode->GetModificationTime(timestamp); }
|
{ fNode->GetChangeTime(timestamp); }
|
||||||
|
|
||||||
void GetAccessTime(struct timespec& timestamp) const
|
void GetModificationTime(struct timespec& timestamp)
|
||||||
{ fNode->GetAccessTime(timestamp); }
|
const
|
||||||
|
{ fNode->GetModificationTime(timestamp); }
|
||||||
|
|
||||||
private:
|
void GetAccessTime(struct timespec& timestamp) const
|
||||||
uint32 UserId() { return fNode->UserId(); }
|
{ fNode->GetAccessTime(timestamp); }
|
||||||
uint32 GroupId() { return fNode->GroupId(); }
|
|
||||||
|
|
||||||
status_t GetFromDisk();
|
uint32 UserId() const { return fNode->UserId(); }
|
||||||
xfs_inode_t* fNode;
|
uint32 GroupId() const { return fNode->GroupId(); }
|
||||||
xfs_ino_t fId;
|
|
||||||
Volume* fVolume;
|
private:
|
||||||
char* fBuffer; // Contains the disk inode in BE format
|
status_t GetFromDisk();
|
||||||
|
xfs_inode_t* fNode;
|
||||||
|
xfs_ino_t fId;
|
||||||
|
Volume* fVolume;
|
||||||
|
char* fBuffer;
|
||||||
|
// Contains the disk inode in BE format
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -20,9 +20,12 @@ DEFINES += DEBUG_APP="\\\"xfs\\\"" ;
|
|||||||
UseHeaders [ FDirName $(HAIKU_TOP) src libs uuid ] : true ;
|
UseHeaders [ FDirName $(HAIKU_TOP) src libs uuid ] : true ;
|
||||||
|
|
||||||
local xfsSources =
|
local xfsSources =
|
||||||
|
DeviceOpener.cpp
|
||||||
|
Directory.cpp
|
||||||
Inode.cpp
|
Inode.cpp
|
||||||
kernel_cpp.cpp
|
kernel_cpp.cpp
|
||||||
kernel_interface.cpp
|
kernel_interface.cpp
|
||||||
|
ShortDirectory.cpp
|
||||||
Volume.cpp
|
Volume.cpp
|
||||||
xfs.cpp
|
xfs.cpp
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "ShortDirectory.h"
|
||||||
|
|
||||||
|
|
||||||
|
ShortDirectory::ShortDirectory(Inode* inode)
|
||||||
|
:
|
||||||
|
fInode(inode),
|
||||||
|
fTrack(0)
|
||||||
|
{
|
||||||
|
memcpy(&fHeader,
|
||||||
|
DIR_DFORK_PTR(fInode->Buffer()), sizeof(xfs_dir2_sf_hdr_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ShortDirectory::~ShortDirectory()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xfs_ino_t
|
||||||
|
ShortDirectory::GetParentIno()
|
||||||
|
{
|
||||||
|
TRACE("GetParentIno: \n");
|
||||||
|
if (fHeader.i8count > 0)
|
||||||
|
return B_BENDIAN_TO_HOST_INT64(fHeader.parent.i8);
|
||||||
|
else
|
||||||
|
return B_BENDIAN_TO_HOST_INT32(fHeader.parent.i4);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ShortDirectory::Lookup(const char* name, size_t length, xfs_ino_t* ino)
|
||||||
|
{
|
||||||
|
if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
|
||||||
|
xfs_ino_t rootIno = fInode->GetVolume()->Root();
|
||||||
|
if (strcmp(name, ".") == 0 || (rootIno == fInode->ID())) {
|
||||||
|
*ino = fInode->ID();
|
||||||
|
TRACE("ShortDirectory:Lookup: name: \".\" ino: (%d)\n", *ino);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
*ino = GetParentIno();
|
||||||
|
TRACE("Parent: (%d)\n", *ino);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: Other entries
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ShortDirectory::GetNext(char* name, size_t* length, xfs_ino_t* ino)
|
||||||
|
{
|
||||||
|
if (fTrack == 0) {
|
||||||
|
// Return '.'
|
||||||
|
if (*length < 2)
|
||||||
|
return B_BUFFER_OVERFLOW;
|
||||||
|
*length = 2;
|
||||||
|
strlcpy(name, ".", *length + 1);
|
||||||
|
*ino = fInode->ID();
|
||||||
|
fTrack = 1;
|
||||||
|
TRACE("ShortDirectory:GetNext: name: \".\" ino: (%d)\n", *ino);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
if (fTrack == 1) {
|
||||||
|
// Return '..'
|
||||||
|
if (*length < 3)
|
||||||
|
return B_BUFFER_OVERFLOW;
|
||||||
|
*length = 3;
|
||||||
|
strlcpy(name, "..", *length + 1);
|
||||||
|
*ino = GetParentIno();
|
||||||
|
fTrack = 2;
|
||||||
|
TRACE("ShortDirectory:GetNext: name: \"..\" ino: (%d)\n", *ino);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Now iterate through sf entries
|
||||||
|
return B_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef __SHORT_DIR_H__
|
||||||
|
#define __SHORT_DIR_H__
|
||||||
|
|
||||||
|
#include "Inode.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct xfs_dir2_sf_off_t { uint8 i[2]; };
|
||||||
|
//offset into the literal area
|
||||||
|
|
||||||
|
union xfs_dir2_inou_t {
|
||||||
|
uint64 i8;
|
||||||
|
uint32 i4;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Short form directory header
|
||||||
|
struct xfs_dir2_sf_hdr_t {
|
||||||
|
uint8 count;
|
||||||
|
// number of entries
|
||||||
|
uint8 i8count;
|
||||||
|
// # of 64bit inode entries
|
||||||
|
xfs_dir2_inou_t parent;
|
||||||
|
// absolute inode # of parent
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*The xfs_dir2_sf_entry is split into
|
||||||
|
* two parts because the entries size is variable
|
||||||
|
*/
|
||||||
|
struct xfs_dir2_sf_entry_t {
|
||||||
|
uint8 namelen;
|
||||||
|
// length of the name, in bytes
|
||||||
|
xfs_dir2_sf_off_t offset;
|
||||||
|
// offset tag, for directory iteration
|
||||||
|
uint8 name[];
|
||||||
|
// name of directory entry
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
union xfs_dir2_sf_entry_inum_t {
|
||||||
|
struct xfs_ftype_inum{
|
||||||
|
uint8 ftype;
|
||||||
|
xfs_dir2_inou_t inumber;
|
||||||
|
};
|
||||||
|
struct xfs_inum{
|
||||||
|
xfs_dir2_inou_t inumber;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ShortDirectory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ShortDirectory(Inode* inode);
|
||||||
|
~ShortDirectory();
|
||||||
|
status_t GetNext(char* name, size_t* length,
|
||||||
|
xfs_ino_t* ino);
|
||||||
|
xfs_ino_t GetParentIno();
|
||||||
|
status_t Lookup(const char* name, size_t length,
|
||||||
|
xfs_ino_t* id);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Inode* fInode;
|
||||||
|
xfs_dir2_sf_hdr_t fHeader;
|
||||||
|
xfs_dir2_sf_off_t fLastEntryOffset;
|
||||||
|
// offset into the literal area
|
||||||
|
uint8 fTrack;
|
||||||
|
// Takes the values 0, 1 or 2 only
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -3,12 +3,15 @@
|
|||||||
* Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com
|
* Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
#include "DeviceOpener.h"
|
|
||||||
|
#include "Inode.h"
|
||||||
|
|
||||||
|
|
||||||
Volume::Volume(fs_volume *volume)
|
Volume::Volume(fs_volume *volume)
|
||||||
: fFSVolume(volume)
|
: fFSVolume(volume)
|
||||||
{
|
{
|
||||||
fFlags = 0;
|
fFlags = 0;
|
||||||
mutex_init(&fLock, "xfs volume");
|
mutex_init(&fLock, "xfs volume");
|
||||||
@@ -24,7 +27,7 @@ Volume::~Volume()
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Volume::IsValidSuperBlock()
|
Volume::IsValidSuperBlock() const
|
||||||
{
|
{
|
||||||
return fSuperBlock.IsValid();
|
return fSuperBlock.IsValid();
|
||||||
}
|
}
|
||||||
@@ -65,7 +68,7 @@ Volume::Mount(const char *deviceName, uint32 flags)
|
|||||||
|
|
||||||
DeviceOpener opener(deviceName, (flags & B_MOUNT_READ_ONLY) != 0
|
DeviceOpener opener(deviceName, (flags & B_MOUNT_READ_ONLY) != 0
|
||||||
? O_RDONLY
|
? O_RDONLY
|
||||||
: O_RDWR);
|
: O_RDWR);
|
||||||
fDevice = opener.Device();
|
fDevice = opener.Device();
|
||||||
if (fDevice < B_OK) {
|
if (fDevice < B_OK) {
|
||||||
ERROR("Volume::Mount(): couldn't open device\n");
|
ERROR("Volume::Mount(): couldn't open device\n");
|
||||||
@@ -92,6 +95,21 @@ Volume::Mount(const char *deviceName, uint32 flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
opener.Keep();
|
opener.Keep();
|
||||||
|
|
||||||
|
//publish the root inode
|
||||||
|
Inode* rootInode = new(std::nothrow) Inode(this, Root());
|
||||||
|
if (rootInode == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
status = rootInode->Init();
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = publish_vnode(FSVolume(), Root(),
|
||||||
|
(void*)rootInode, &gxfsVnodeOps, rootInode->Mode(), 0);
|
||||||
|
if (status != B_OK)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,19 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com
|
* Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _VOLUME_H_
|
#ifndef _VOLUME_H_
|
||||||
#define _VOLUME_H_
|
#define _VOLUME_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include <DeviceOpener.h>
|
||||||
|
|
||||||
#include "xfs.h"
|
#include "xfs.h"
|
||||||
|
|
||||||
|
|
||||||
/* Converting the FS Blocks to Basic Blocks */
|
#define FSBLOCK_SHIFT(fsBlockLog) (fsBlockLog - BASICBLOCKLOG);
|
||||||
#define FSBSHIFT(fsBlockLog) (fsBlockLog - BBLOCKLOG);
|
#define FSBLOCKS_TO_BASICBLOCKS(fsBlockLog, x) x << FSBLOCK_SHIFT(fsBlockLog);
|
||||||
#define FSB_TO_BB(fsBlockLog, x) x << FSBSHIFT(fsBlockLog);
|
// Converting the FS Blocks to Basic Blocks
|
||||||
|
|
||||||
enum volume_flags {
|
enum volume_flags {
|
||||||
VOLUME_READ_ONLY = 0x0001
|
VOLUME_READ_ONLY = 0x0001
|
||||||
@@ -28,15 +30,16 @@ public:
|
|||||||
status_t Initialize(int fd, const char *label,
|
status_t Initialize(int fd, const char *label,
|
||||||
uint32 blockSize, uint32 sectorSize);
|
uint32 blockSize, uint32 sectorSize);
|
||||||
|
|
||||||
bool IsValidSuperBlock();
|
bool IsValidSuperBlock() const;
|
||||||
bool IsReadOnly() const
|
bool IsReadOnly() const
|
||||||
{ return (fFlags & VOLUME_READ_ONLY) != 0; }
|
{ return
|
||||||
|
(fFlags & VOLUME_READ_ONLY) != 0; }
|
||||||
|
|
||||||
dev_t ID() const
|
dev_t ID() const
|
||||||
{ return fFSVolume ? fFSVolume->id : -1; }
|
{ return fFSVolume ? fFSVolume->id : -1; }
|
||||||
fs_volume* FSVolume() const
|
fs_volume* FSVolume() const
|
||||||
{ return fFSVolume; }
|
{ return fFSVolume; }
|
||||||
char* Name()
|
const char* Name() const
|
||||||
{ return fSuperBlock.Name(); }
|
{ return fSuperBlock.Name(); }
|
||||||
|
|
||||||
XfsSuperBlock& SuperBlock() { return fSuperBlock; }
|
XfsSuperBlock& SuperBlock() { return fSuperBlock; }
|
||||||
@@ -44,29 +47,37 @@ public:
|
|||||||
|
|
||||||
static status_t Identify(int fd, XfsSuperBlock *superBlock);
|
static status_t Identify(int fd, XfsSuperBlock *superBlock);
|
||||||
|
|
||||||
uint32 BlockSize() { return fSuperBlock.BlockSize(); }
|
uint32 BlockSize() const
|
||||||
|
{ return fSuperBlock.BlockSize(); }
|
||||||
|
|
||||||
uint8 BlockLog() { return fSuperBlock.BlockLog(); }
|
uint8 BlockLog() const
|
||||||
|
{ return fSuperBlock.BlockLog(); }
|
||||||
|
|
||||||
uint32 DirBlockSize()
|
uint32 DirBlockSize() const
|
||||||
{ return fSuperBlock.DirBlockSize(); }
|
{ return fSuperBlock.DirBlockSize(); }
|
||||||
|
|
||||||
uint8 AgInodeBits()
|
uint8 AgInodeBits() const
|
||||||
{ return fSuperBlock.AgInodeBits(); }
|
{ return fSuperBlock.AgInodeBits(); }
|
||||||
|
|
||||||
uint8 AgBlocksLog()
|
uint8 AgBlocksLog() const
|
||||||
{ return fSuperBlock.AgBlocksLog(); }
|
{ return fSuperBlock.AgBlocksLog(); }
|
||||||
|
|
||||||
uint8 InodesPerBlkLog()
|
uint8 InodesPerBlkLog() const
|
||||||
{ return fSuperBlock.InodesPerBlkLog(); }
|
{ return fSuperBlock.InodesPerBlkLog(); }
|
||||||
|
|
||||||
off_t Root() const { return fSuperBlock.Root(); }
|
off_t Root() const { return fSuperBlock.Root(); }
|
||||||
|
|
||||||
uint16 InodeSize() { return fSuperBlock.InodeSize(); }
|
uint16 InodeSize() const
|
||||||
|
{ return fSuperBlock.InodeSize(); }
|
||||||
|
|
||||||
xfs_agnumber_t AgCount() { return fSuperBlock.AgCount(); }
|
xfs_agnumber_t AgCount() const
|
||||||
|
{ return fSuperBlock.AgCount(); }
|
||||||
|
|
||||||
xfs_agblock_t AgBlocks() { return fSuperBlock.AgBlocks(); }
|
xfs_agblock_t AgBlocks() const
|
||||||
|
{ return fSuperBlock.AgBlocks(); }
|
||||||
|
|
||||||
|
uint8 SuperBlockFlags() const
|
||||||
|
{ return fSuperBlock.Flags(); }
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
off_t NumBlocks() const
|
off_t NumBlocks() const
|
||||||
@@ -77,7 +88,8 @@ protected:
|
|||||||
fs_volume* fFSVolume;
|
fs_volume* fFSVolume;
|
||||||
int fDevice;
|
int fDevice;
|
||||||
XfsSuperBlock fSuperBlock;
|
XfsSuperBlock fSuperBlock;
|
||||||
char fName[32]; /* filesystem name */
|
char fName[32];
|
||||||
|
// Filesystem name
|
||||||
|
|
||||||
uint32 fDeviceBlockSize;
|
uint32 fDeviceBlockSize;
|
||||||
mutex fLock;
|
mutex fLock;
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2001-2017, Axel Dörfler, axeld@pinc-software.de.
|
* Copyright 2001-2017, Axel Dörfler, axeld@pinc-software.de.
|
||||||
* Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com
|
* Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "system_dependencies.h"
|
#include "system_dependencies.h"
|
||||||
|
#include "Directory.h"
|
||||||
#include "Inode.h"
|
#include "Inode.h"
|
||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
|
|
||||||
@@ -86,16 +89,6 @@ xfs_mount(fs_volume *_volume, const char *device, uint32 flags,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
//publish the root inode
|
|
||||||
Inode* rootInode = new(std::nothrow) Inode(volume, volume->Root());
|
|
||||||
if (rootInode != NULL) {
|
|
||||||
status = publish_vnode(volume->FSVolume(), volume->Root(),
|
|
||||||
(void*)rootInode, &gxfsVnodeOps, rootInode->Mode(), 0);
|
|
||||||
|
|
||||||
if (status!=B_OK)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
*_rootID = volume->Root();
|
*_rootID = volume->Root();
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -116,6 +109,7 @@ xfs_unmount(fs_volume *_volume)
|
|||||||
static status_t
|
static status_t
|
||||||
xfs_read_fs_info(fs_volume *_volume, struct fs_info *info)
|
xfs_read_fs_info(fs_volume *_volume, struct fs_info *info)
|
||||||
{
|
{
|
||||||
|
TRACE("XFS_READ_FS_INFO:\n");
|
||||||
Volume* volume = (Volume*)_volume->private_volume;
|
Volume* volume = (Volume*)_volume->private_volume;
|
||||||
|
|
||||||
info->flags = B_FS_IS_READONLY
|
info->flags = B_FS_IS_READONLY
|
||||||
@@ -140,15 +134,15 @@ static status_t
|
|||||||
xfs_get_vnode(fs_volume *_volume, ino_t id, fs_vnode *_node, int *_type,
|
xfs_get_vnode(fs_volume *_volume, ino_t id, fs_vnode *_node, int *_type,
|
||||||
uint32 *_flags, bool reenter)
|
uint32 *_flags, bool reenter)
|
||||||
{
|
{
|
||||||
|
TRACE("XFS_GET_VNODE:\n");
|
||||||
Volume* volume = (Volume*)_volume->private_volume;
|
Volume* volume = (Volume*)_volume->private_volume;
|
||||||
|
|
||||||
Inode* inode = new(std::nothrow) Inode(volume, id);
|
Inode* inode = new(std::nothrow) Inode(volume, id);
|
||||||
|
|
||||||
if (inode == NULL)
|
if (inode == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
status_t status = inode->InitCheck();
|
status_t status = inode->Init();
|
||||||
if (status == false) {
|
if (status != B_OK) {
|
||||||
delete inode;
|
delete inode;
|
||||||
ERROR("get_vnode: InitCheck() failed. Error: %s\n", strerror(status));
|
ERROR("get_vnode: InitCheck() failed. Error: %s\n", strerror(status));
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
@@ -158,7 +152,7 @@ xfs_get_vnode(fs_volume *_volume, ino_t id, fs_vnode *_node, int *_type,
|
|||||||
_node->ops = &gxfsVnodeOps;
|
_node->ops = &gxfsVnodeOps;
|
||||||
*_type = inode->Mode();
|
*_type = inode->Mode();
|
||||||
*_flags = 0;
|
*_flags = 0;
|
||||||
|
TRACE("(%d)\n", inode->ID());
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,7 +160,9 @@ xfs_get_vnode(fs_volume *_volume, ino_t id, fs_vnode *_node, int *_type,
|
|||||||
static status_t
|
static status_t
|
||||||
xfs_put_vnode(fs_volume *_volume, fs_vnode *_node, bool reenter)
|
xfs_put_vnode(fs_volume *_volume, fs_vnode *_node, bool reenter)
|
||||||
{
|
{
|
||||||
return B_NOT_SUPPORTED;
|
TRACE("XFS_PUT_VNODE:\n");
|
||||||
|
delete (Inode*)_node->private_node;
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -208,7 +204,36 @@ static status_t
|
|||||||
xfs_lookup(fs_volume *_volume, fs_vnode *_directory, const char *name,
|
xfs_lookup(fs_volume *_volume, fs_vnode *_directory, const char *name,
|
||||||
ino_t *_vnodeID)
|
ino_t *_vnodeID)
|
||||||
{
|
{
|
||||||
return B_NOT_SUPPORTED;
|
TRACE("XFS_LOOKUP: %p (%s)\n", name, name);
|
||||||
|
Volume* volume = (Volume*)_volume->private_volume;
|
||||||
|
Inode* directory = (Inode*)_directory->private_node;
|
||||||
|
|
||||||
|
if (!directory->IsDirectory())
|
||||||
|
return B_NOT_A_DIRECTORY;
|
||||||
|
|
||||||
|
//TODO: pretend everything is accessible. We should actually checking
|
||||||
|
//for permission here.
|
||||||
|
DirectoryIterator* iterator =
|
||||||
|
new(std::nothrow) DirectoryIterator(directory);
|
||||||
|
if (iterator == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
status_t status = iterator->Init();
|
||||||
|
if (status != B_OK) {
|
||||||
|
delete iterator;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = iterator->Lookup(name, strlen(name), (xfs_ino_t*)_vnodeID);
|
||||||
|
if (status != B_OK) {
|
||||||
|
delete iterator;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("XFS_LOOKUP: ID: (%d)\n", *_vnodeID);
|
||||||
|
status = get_vnode(volume->FSVolume(), *_vnodeID, NULL);
|
||||||
|
TRACE("get_vnode status: (%d)\n", status);
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -224,6 +249,7 @@ static status_t
|
|||||||
xfs_read_stat(fs_volume *_volume, fs_vnode *_node, struct stat *stat)
|
xfs_read_stat(fs_volume *_volume, fs_vnode *_node, struct stat *stat)
|
||||||
{
|
{
|
||||||
Inode* inode = (Inode*)_node->private_node;
|
Inode* inode = (Inode*)_node->private_node;
|
||||||
|
TRACE("XFS_READ_STAT: root_id: (%d)\n", inode->ID());
|
||||||
stat->st_dev = inode->GetVolume()->ID();
|
stat->st_dev = inode->GetVolume()->ID();
|
||||||
stat->st_ino = inode->ID();
|
stat->st_ino = inode->ID();
|
||||||
stat->st_nlink = 1;
|
stat->st_nlink = 1;
|
||||||
@@ -234,7 +260,7 @@ xfs_read_stat(fs_volume *_volume, fs_vnode *_node, struct stat *stat)
|
|||||||
stat->st_mode = inode->Mode();
|
stat->st_mode = inode->Mode();
|
||||||
stat->st_type = 0; // TODO
|
stat->st_type = 0; // TODO
|
||||||
|
|
||||||
stat->st_size = inode->GetVolume()->InodeSize();
|
stat->st_size = inode->Size();
|
||||||
stat->st_blocks = inode->NoOfBlocks();
|
stat->st_blocks = inode->NoOfBlocks();
|
||||||
|
|
||||||
inode->GetAccessTime(stat->st_atim);
|
inode->GetAccessTime(stat->st_atim);
|
||||||
@@ -282,7 +308,9 @@ xfs_free_cookie(fs_volume *_volume, fs_vnode *_node, void *_cookie)
|
|||||||
static status_t
|
static status_t
|
||||||
xfs_access(fs_volume *_volume, fs_vnode *_node, int accessMode)
|
xfs_access(fs_volume *_volume, fs_vnode *_node, int accessMode)
|
||||||
{
|
{
|
||||||
return B_NOT_SUPPORTED;
|
//TODO: pretend everything is accessible. We should actually checking
|
||||||
|
//for permission here.
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -322,7 +350,20 @@ xfs_remove_dir(fs_volume *_volume, fs_vnode *_directory, const char *name)
|
|||||||
static status_t
|
static status_t
|
||||||
xfs_open_dir(fs_volume * /*_volume*/, fs_vnode *_node, void **_cookie)
|
xfs_open_dir(fs_volume * /*_volume*/, fs_vnode *_node, void **_cookie)
|
||||||
{
|
{
|
||||||
return B_NOT_SUPPORTED;
|
Inode* inode = (Inode*)_node->private_node;
|
||||||
|
TRACE("XFS_OPEN_DIR: (%d)\n", inode->ID());
|
||||||
|
|
||||||
|
if (!inode->IsDirectory())
|
||||||
|
return B_NOT_A_DIRECTORY;
|
||||||
|
|
||||||
|
DirectoryIterator* iterator = new(std::nothrow) DirectoryIterator(inode);
|
||||||
|
if (iterator == NULL) {
|
||||||
|
delete iterator;
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
status_t status = iterator->Init();
|
||||||
|
*_cookie = iterator;
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -330,7 +371,39 @@ static status_t
|
|||||||
xfs_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie,
|
xfs_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie,
|
||||||
struct dirent *dirent, size_t bufferSize, uint32 *_num)
|
struct dirent *dirent, size_t bufferSize, uint32 *_num)
|
||||||
{
|
{
|
||||||
return B_NOT_SUPPORTED;
|
TRACE("XFS_READ_DIR\n");
|
||||||
|
DirectoryIterator* iterator = (DirectoryIterator*)_cookie;
|
||||||
|
Volume* volume = (Volume*)_volume->private_volume;
|
||||||
|
|
||||||
|
uint32 maxCount = *_num;
|
||||||
|
uint32 count = 0;
|
||||||
|
|
||||||
|
while (count < maxCount and (bufferSize > sizeof(struct dirent))) {
|
||||||
|
size_t length = bufferSize - sizeof(struct dirent) + 1;
|
||||||
|
xfs_ino_t ino;
|
||||||
|
|
||||||
|
status_t status = iterator->GetNext(dirent->d_name, &length, &ino);
|
||||||
|
if (status == B_ENTRY_NOT_FOUND)
|
||||||
|
break;
|
||||||
|
if (status == B_BUFFER_OVERFLOW) {
|
||||||
|
if (count == 0)
|
||||||
|
return status;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
dirent->d_dev = volume->ID();
|
||||||
|
dirent->d_ino = ino;
|
||||||
|
dirent->d_reclen = sizeof(dirent) + length;
|
||||||
|
bufferSize -= dirent->d_reclen;
|
||||||
|
dirent = (struct dirent*)((uint8*)dirent + dirent->d_reclen);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*_num = count;
|
||||||
|
TRACE("Count: (%d)\n", count);
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,13 +6,20 @@
|
|||||||
#include "xfs.h"
|
#include "xfs.h"
|
||||||
|
|
||||||
|
|
||||||
|
uint8
|
||||||
|
XfsSuperBlock::Flags() const
|
||||||
|
{
|
||||||
|
return sb_flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
XfsSuperBlock::IsValid()
|
XfsSuperBlock::IsValid() const
|
||||||
{
|
{
|
||||||
if (sb_magicnum != XFS_SB_MAGIC)
|
if (sb_magicnum != XFS_SB_MAGIC)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (BBLOCKSIZE > sb_blocksize) {
|
if (BASICBLOCKSIZE > sb_blocksize) {
|
||||||
ERROR("Basic block is less than 512 bytes!");
|
ERROR("Basic block is less than 512 bytes!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -22,91 +29,91 @@ XfsSuperBlock::IsValid()
|
|||||||
|
|
||||||
|
|
||||||
uint32
|
uint32
|
||||||
XfsSuperBlock::BlockSize()
|
XfsSuperBlock::BlockSize() const
|
||||||
{
|
{
|
||||||
return sb_blocksize;
|
return sb_blocksize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8
|
uint8
|
||||||
XfsSuperBlock::BlockLog()
|
XfsSuperBlock::BlockLog() const
|
||||||
{
|
{
|
||||||
return sb_blocklog;
|
return sb_blocklog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32
|
uint32
|
||||||
XfsSuperBlock::DirBlockSize()
|
XfsSuperBlock::DirBlockSize() const
|
||||||
{
|
{
|
||||||
return BlockSize() * (1 << sb_dirblklog);
|
return BlockSize() * (1 << sb_dirblklog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8
|
uint8
|
||||||
XfsSuperBlock::AgInodeBits()
|
XfsSuperBlock::AgInodeBits() const
|
||||||
{
|
{
|
||||||
return AgBlocksLog() + InodesPerBlkLog();
|
return AgBlocksLog() + InodesPerBlkLog();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8
|
uint8
|
||||||
XfsSuperBlock::InodesPerBlkLog()
|
XfsSuperBlock::InodesPerBlkLog() const
|
||||||
{
|
{
|
||||||
return sb_inopblog;
|
return sb_inopblog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8
|
uint8
|
||||||
XfsSuperBlock::AgBlocksLog()
|
XfsSuperBlock::AgBlocksLog() const
|
||||||
{
|
{
|
||||||
return sb_agblklog;
|
return sb_agblklog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32
|
uint32
|
||||||
XfsSuperBlock::Size()
|
XfsSuperBlock::Size() const
|
||||||
{
|
{
|
||||||
return XFS_SB_MAXSIZE;
|
return XFS_SB_MAXSIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint16
|
uint16
|
||||||
XfsSuperBlock::InodeSize()
|
XfsSuperBlock::InodeSize() const
|
||||||
{
|
{
|
||||||
return sb_inodesize;
|
return sb_inodesize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
xfs_rfsblock_t
|
xfs_rfsblock_t
|
||||||
XfsSuperBlock::TotalBlocks()
|
XfsSuperBlock::TotalBlocks() const
|
||||||
{
|
{
|
||||||
return sb_dblocks;
|
return sb_dblocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
xfs_rfsblock_t
|
xfs_rfsblock_t
|
||||||
XfsSuperBlock::TotalBlocksWithLog()
|
XfsSuperBlock::TotalBlocksWithLog() const
|
||||||
{
|
{
|
||||||
return TotalBlocks() + sb_logblocks;
|
return TotalBlocks() + sb_logblocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint64
|
uint64
|
||||||
XfsSuperBlock::FreeBlocks()
|
XfsSuperBlock::FreeBlocks() const
|
||||||
{
|
{
|
||||||
return sb_fdblocks;
|
return sb_fdblocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint64
|
uint64
|
||||||
XfsSuperBlock::UsedBlocks()
|
XfsSuperBlock::UsedBlocks() const
|
||||||
{
|
{
|
||||||
return TotalBlocks() - FreeBlocks();
|
return TotalBlocks() - FreeBlocks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char*
|
const char*
|
||||||
XfsSuperBlock::Name()
|
XfsSuperBlock::Name() const
|
||||||
{
|
{
|
||||||
return sb_fname;
|
return sb_fname;
|
||||||
}
|
}
|
||||||
@@ -120,14 +127,14 @@ XfsSuperBlock::Root() const
|
|||||||
|
|
||||||
|
|
||||||
xfs_agnumber_t
|
xfs_agnumber_t
|
||||||
XfsSuperBlock::AgCount()
|
XfsSuperBlock::AgCount() const
|
||||||
{
|
{
|
||||||
return sb_agcount;
|
return sb_agcount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
xfs_agblock_t
|
xfs_agblock_t
|
||||||
XfsSuperBlock::AgBlocks()
|
XfsSuperBlock::AgBlocks() const
|
||||||
{
|
{
|
||||||
return sb_agblocks;
|
return sb_agblocks;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com
|
* Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*Important:
|
*Important:
|
||||||
*All fields in XFS metadata structures are in big-endian byte order
|
*All fields in XFS metadata structures are in big-endian byte order
|
||||||
*except for log items which are formatted in host order.
|
*except for log items which are formatted in host order.
|
||||||
*
|
*
|
||||||
*This file contains all global structure definitions.
|
*This file contains all global structure definitions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _XFS_SB_H_
|
#ifndef _XFS_SB_H_
|
||||||
#define _XFS_SB_H_
|
#define _XFS_SB_H_
|
||||||
|
|
||||||
|
|
||||||
#include "system_dependencies.h"
|
#include "system_dependencies.h"
|
||||||
#include "xfs_types.h"
|
#include "xfs_types.h"
|
||||||
|
|
||||||
@@ -22,83 +22,86 @@ extern fs_vnode_ops gxfsVnodeOps;
|
|||||||
extern fs_volume_ops gxfsVolumeOps;
|
extern fs_volume_ops gxfsVolumeOps;
|
||||||
|
|
||||||
|
|
||||||
#define XFS_SB_MAGIC 0x58465342 /* Identifies XFS. "XFSB" */
|
#define XFS_SB_MAGIC 0x58465342
|
||||||
|
// Identifies XFS. "XFSB"
|
||||||
#define XFS_SB_MAXSIZE 512
|
#define XFS_SB_MAXSIZE 512
|
||||||
#define BBLOCKLOG 9 /* Log of block size should be 9 */
|
#define BASICBLOCKLOG 9
|
||||||
#define BBLOCKSIZE 1 << BBLOCKLOG /* The size of a basic block should be 512 */
|
// Log of block size should be 9
|
||||||
|
#define BASICBLOCKSIZE 1 << BASICBLOCKLOG
|
||||||
|
// The size of a basic block should be 512
|
||||||
|
|
||||||
|
|
||||||
/* Version 4 superblock definition */
|
/* Version 4 superblock definition */
|
||||||
class XfsSuperBlock
|
class XfsSuperBlock {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
bool IsValid();
|
bool IsValid() const;
|
||||||
char* Name();
|
const char* Name() const;
|
||||||
uint32 BlockSize();
|
uint32 BlockSize() const;
|
||||||
uint8 BlockLog();
|
uint8 BlockLog() const;
|
||||||
uint32 DirBlockSize(); // maximum 65536
|
uint32 DirBlockSize() const;
|
||||||
uint8 AgInodeBits();
|
// maximum 65536
|
||||||
uint8 InodesPerBlkLog();
|
uint8 AgInodeBits() const;
|
||||||
uint8 AgBlocksLog();
|
uint8 InodesPerBlkLog() const;
|
||||||
xfs_rfsblock_t TotalBlocks();
|
uint8 AgBlocksLog() const;
|
||||||
xfs_rfsblock_t TotalBlocksWithLog();
|
xfs_rfsblock_t TotalBlocks() const;
|
||||||
uint64 FreeBlocks();
|
xfs_rfsblock_t TotalBlocksWithLog() const;
|
||||||
uint64 UsedBlocks();
|
uint64 FreeBlocks() const;
|
||||||
uint32 Size();
|
uint64 UsedBlocks() const;
|
||||||
uint16 InodeSize();
|
uint32 Size() const;
|
||||||
void SwapEndian();
|
uint16 InodeSize() const;
|
||||||
xfs_ino_t Root() const;
|
void SwapEndian();
|
||||||
xfs_agnumber_t AgCount();
|
xfs_ino_t Root() const;
|
||||||
xfs_agblock_t AgBlocks();
|
xfs_agnumber_t AgCount() const;
|
||||||
|
xfs_agblock_t AgBlocks() const;
|
||||||
|
uint8 Flags() const;
|
||||||
private:
|
private:
|
||||||
|
|
||||||
uint32 sb_magicnum;
|
uint32 sb_magicnum;
|
||||||
uint32 sb_blocksize;
|
uint32 sb_blocksize;
|
||||||
xfs_rfsblock_t sb_dblocks;
|
xfs_rfsblock_t sb_dblocks;
|
||||||
xfs_rfsblock_t sb_rblocks;
|
xfs_rfsblock_t sb_rblocks;
|
||||||
xfs_rtblock_t sb_rextents;
|
xfs_rtblock_t sb_rextents;
|
||||||
uuid_t sb_uuid;
|
uuid_t sb_uuid;
|
||||||
xfs_fsblock_t sb_logstart;
|
xfs_fsblock_t sb_logstart;
|
||||||
xfs_ino_t sb_rootino;
|
xfs_ino_t sb_rootino;
|
||||||
xfs_ino_t sb_rbmino;
|
xfs_ino_t sb_rbmino;
|
||||||
xfs_ino_t sb_rsumino;
|
xfs_ino_t sb_rsumino;
|
||||||
xfs_agblock_t sb_rextsize;
|
xfs_agblock_t sb_rextsize;
|
||||||
xfs_agblock_t sb_agblocks;
|
xfs_agblock_t sb_agblocks;
|
||||||
xfs_agnumber_t sb_agcount;
|
xfs_agnumber_t sb_agcount;
|
||||||
xfs_extlen_t sb_rbmblocks;
|
xfs_extlen_t sb_rbmblocks;
|
||||||
xfs_extlen_t sb_logblocks;
|
xfs_extlen_t sb_logblocks;
|
||||||
uint16 sb_versionnum;
|
uint16 sb_versionnum;
|
||||||
uint16 sb_sectsize;
|
uint16 sb_sectsize;
|
||||||
uint16 sb_inodesize;
|
uint16 sb_inodesize;
|
||||||
uint16 sb_inopblock;
|
uint16 sb_inopblock;
|
||||||
char sb_fname[12];
|
char sb_fname[12];
|
||||||
uint8 sb_blocklog;
|
uint8 sb_blocklog;
|
||||||
uint8 sb_sectlog;
|
uint8 sb_sectlog;
|
||||||
uint8 sb_inodelog;
|
uint8 sb_inodelog;
|
||||||
uint8 sb_inopblog;
|
uint8 sb_inopblog;
|
||||||
uint8 sb_agblklog;
|
uint8 sb_agblklog;
|
||||||
uint8 sb_rextslog;
|
uint8 sb_rextslog;
|
||||||
uint8 sb_inprogress;
|
uint8 sb_inprogress;
|
||||||
uint8 sb_imax_pct;
|
uint8 sb_imax_pct;
|
||||||
uint64 sb_icount;
|
uint64 sb_icount;
|
||||||
uint64 sb_ifree;
|
uint64 sb_ifree;
|
||||||
uint64 sb_fdblocks;
|
uint64 sb_fdblocks;
|
||||||
uint64 sb_frextents;
|
uint64 sb_frextents;
|
||||||
xfs_ino_t sb_uquotino;
|
xfs_ino_t sb_uquotino;
|
||||||
xfs_ino_t sb_gquotino;
|
xfs_ino_t sb_gquotino;
|
||||||
uint16 sb_qflags;
|
uint16 sb_qflags;
|
||||||
uint8 sb_flags;
|
uint8 sb_flags;
|
||||||
uint8 sb_shared_vn;
|
uint8 sb_shared_vn;
|
||||||
xfs_extlen_t sb_inoalignmt;
|
xfs_extlen_t sb_inoalignmt;
|
||||||
uint32 sb_unit;
|
uint32 sb_unit;
|
||||||
uint32 sb_width;
|
uint32 sb_width;
|
||||||
uint8 sb_dirblklog;
|
uint8 sb_dirblklog;
|
||||||
uint8 sb_logsectlog;
|
uint8 sb_logsectlog;
|
||||||
uint16 sb_logsectsize;
|
uint16 sb_logsectsize;
|
||||||
uint32 sb_logsunit;
|
uint32 sb_logsunit;
|
||||||
uint32 sb_features2;
|
uint32 sb_features2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -39,8 +39,11 @@ UseHeaders [ FDirName $(HAIKU_TOP) headers private ] : true ;
|
|||||||
UseHeaders [ FDirName $(HAIKU_TOP) src tools fs_shell ] ;
|
UseHeaders [ FDirName $(HAIKU_TOP) src tools fs_shell ] ;
|
||||||
|
|
||||||
local xfsSource =
|
local xfsSource =
|
||||||
|
DeviceOpener.cpp
|
||||||
|
Directory.cpp
|
||||||
Inode.cpp
|
Inode.cpp
|
||||||
kernel_interface.cpp
|
kernel_interface.cpp
|
||||||
|
ShortDirectory.cpp
|
||||||
Volume.cpp
|
Volume.cpp
|
||||||
xfs.cpp
|
xfs.cpp
|
||||||
;
|
;
|
||||||
|
|||||||
Reference in New Issue
Block a user