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]
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "BPlusTree.h"
|
||||
|
||||
|
||||
@@ -1,30 +1,28 @@
|
||||
/*
|
||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _BPLUS_TREE_H_
|
||||
#define _BPLUS_TREE_H_
|
||||
|
||||
#include "system_dependencies.h"
|
||||
|
||||
|
||||
/* Allocation B+ Tree Format */
|
||||
#define XFS_ABTB_MAGICNUM 0x41425442 // For block offset B+Tree
|
||||
#define XFS_ABTC_MAGICNUM 0x41425443 // For block count B+ Tree
|
||||
|
||||
|
||||
/* Header for Short Format btree */
|
||||
#define XFS_ABTB_MAGICNUM 0x41425442
|
||||
// For block offset B+Tree
|
||||
#define XFS_ABTC_MAGICNUM 0x41425443
|
||||
// For block count B+ Tree
|
||||
#define XFS_BTREE_SBLOCK_SIZE 18
|
||||
|
||||
/* Header for Long Format btree */
|
||||
// Header for Short Format btree
|
||||
#define XFS_BTREE_LBLOCK_SIZE 24
|
||||
// Header for Long Format btree
|
||||
|
||||
|
||||
/*
|
||||
* Headers are the "nodes" really and are called "blocks". The records, keys and
|
||||
* pts are calculated using helpers
|
||||
*/
|
||||
|
||||
* Headers are the "nodes" really and are called "blocks". The records, keys
|
||||
* and ptrs are calculated using helpers
|
||||
*/
|
||||
struct bplustree_short_block {
|
||||
void SwapEndian();
|
||||
|
||||
@@ -93,11 +91,11 @@ typedef struct xfs_alloc_rec {
|
||||
|
||||
} 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 LONG_BLOCK_FLAG 0x1
|
||||
#define SHORT_BLOCK_FLAG 0x2
|
||||
|
||||
@@ -118,7 +116,7 @@ union btree_rec {
|
||||
|
||||
|
||||
class BPlusTree {
|
||||
public:
|
||||
public:
|
||||
uint32 BlockSize();
|
||||
int RecordSize();
|
||||
int MaxRecords(bool leaf);
|
||||
@@ -129,7 +127,7 @@ class BPlusTree {
|
||||
int KeyOffset(int pos); // get the pos'th key
|
||||
int PtrOffset(int pos); // get the pos'th ptr
|
||||
|
||||
private:
|
||||
private:
|
||||
Volume* fVolume;
|
||||
xfs_agnumber_t fAgnumber;
|
||||
btree_ptr* fRoot;
|
||||
@@ -140,4 +138,3 @@ class BPlusTree {
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#ifndef _DEBUG_H_
|
||||
#define _DEBUG_H_
|
||||
|
||||
#define TRACE_XFS
|
||||
// #define TRACE_XFS
|
||||
#ifdef TRACE_XFS
|
||||
#define TRACE(x...) dprintf("\n\33[34mxfs:\33[0m " x)
|
||||
#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]
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "Inode.h"
|
||||
|
||||
|
||||
void
|
||||
xfs_inode::SwapEndian()
|
||||
xfs_inode_t::SwapEndian()
|
||||
{
|
||||
di_magic = B_BENDIAN_TO_HOST_INT16(di_magic);
|
||||
di_mode = B_BENDIAN_TO_HOST_INT16(di_mode);
|
||||
@@ -37,42 +38,42 @@ xfs_inode::SwapEndian()
|
||||
|
||||
|
||||
xfs_rfsblock_t
|
||||
xfs_inode::NoOfBlocks() const
|
||||
xfs_inode_t::NoOfBlocks() const
|
||||
{
|
||||
return di_nblocks;
|
||||
}
|
||||
|
||||
|
||||
xfs_fsize_t
|
||||
xfs_inode::Size() const
|
||||
xfs_inode_t::Size() const
|
||||
{
|
||||
return di_size;
|
||||
}
|
||||
|
||||
|
||||
mode_t
|
||||
xfs_inode::Mode()
|
||||
xfs_inode_t::Mode() const
|
||||
{
|
||||
return di_mode;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
xfs_inode::UserId()
|
||||
xfs_inode_t::UserId() const
|
||||
{
|
||||
return di_uid;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
xfs_inode::GroupId()
|
||||
xfs_inode_t::GroupId() const
|
||||
{
|
||||
return di_gid;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
xfs_inode::GetModificationTime(struct timespec& stamp)
|
||||
xfs_inode_t::GetModificationTime(struct timespec& stamp)
|
||||
{
|
||||
stamp.tv_sec = di_mtime.t_sec;
|
||||
stamp.tv_nsec = di_mtime.t_nsec;
|
||||
@@ -80,7 +81,7 @@ xfs_inode::GetModificationTime(struct timespec& stamp)
|
||||
|
||||
|
||||
void
|
||||
xfs_inode::GetAccessTime(struct timespec& stamp)
|
||||
xfs_inode_t::GetAccessTime(struct timespec& stamp)
|
||||
{
|
||||
stamp.tv_sec = di_atime.t_sec;
|
||||
stamp.tv_nsec = di_atime.t_nsec;
|
||||
@@ -88,7 +89,7 @@ xfs_inode::GetAccessTime(struct timespec& stamp)
|
||||
|
||||
|
||||
void
|
||||
xfs_inode::GetChangeTime(struct timespec& stamp)
|
||||
xfs_inode_t::GetChangeTime(struct timespec& stamp)
|
||||
{
|
||||
stamp.tv_sec = di_ctime.t_sec;
|
||||
stamp.tv_nsec = di_ctime.t_nsec;
|
||||
@@ -96,51 +97,66 @@ xfs_inode::GetChangeTime(struct timespec& stamp)
|
||||
|
||||
|
||||
uint32
|
||||
xfs_inode::NLink()
|
||||
xfs_inode_t::NLink() const
|
||||
{
|
||||
return di_nlink;
|
||||
}
|
||||
|
||||
|
||||
int8
|
||||
xfs_inode::Version()
|
||||
xfs_inode_t::Version() const
|
||||
{
|
||||
return di_version;
|
||||
}
|
||||
|
||||
|
||||
uint16
|
||||
xfs_inode::Flags()
|
||||
xfs_inode_t::Flags() const
|
||||
{
|
||||
return di_flags;
|
||||
}
|
||||
|
||||
|
||||
int8
|
||||
xfs_inode::Format()
|
||||
xfs_inode_t::Format() const
|
||||
{
|
||||
return di_format;
|
||||
}
|
||||
|
||||
|
||||
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];
|
||||
if (fBuffer == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t status = GetFromDisk();
|
||||
if (status == B_OK) {
|
||||
status = InitCheck();
|
||||
if (status) {
|
||||
TRACE("Inode successfully read!");
|
||||
if (fNode->di_magic == INODE_MAGIC) {
|
||||
TRACE("Init(): Inode successfully read.\n");
|
||||
status = B_OK;
|
||||
} 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);
|
||||
// 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 #
|
||||
xfs_agblock_t agBlock = INO_TO_AGBLOCK(agInodeNo, fVolume);
|
||||
xfs_agblock_t agBlock = INO_TO_AGBLOCK(agRelativeInodeNo, fVolume);
|
||||
// AG relative block number
|
||||
xfs_off_t offset = INO_TO_OFFSET(fId, fVolume);
|
||||
// Offset into the block
|
||||
xfs_off_t offset = INO_TO_BLOCKOFFSET(fId, fVolume);
|
||||
// Offset into the block1
|
||||
uint32 len = fVolume->InodeSize();
|
||||
// Inode len to read (size of inode)
|
||||
int fd = fVolume->Device();
|
||||
|
||||
if (agNo > fVolume->AgCount()) {
|
||||
ERROR("Inode::GetFromDisk : AG Number more than number of AGs");
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
xfs_agblock_t agBlocks = fVolume->AgBlocks();
|
||||
xfs_agblock_t numberOfBlocksInAg = fVolume->AgBlocks();
|
||||
|
||||
xfs_fsblock_t blockToRead =
|
||||
FSB_TO_BB(fVolume->BlockLog(), ((uint64)(agNo * agBlocks) + agBlock));
|
||||
xfs_fsblock_t blockToRead = FSBLOCKS_TO_BASICBLOCKS(fVolume->BlockLog(),
|
||||
((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");
|
||||
return B_IO_ERROR;
|
||||
}
|
||||
@@ -183,13 +198,6 @@ Inode::GetFromDisk()
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Inode::InitCheck()
|
||||
{
|
||||
return fNode->di_magic == INODE_MAGIC;
|
||||
}
|
||||
|
||||
|
||||
Inode::~Inode()
|
||||
{
|
||||
delete fBuffer;
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
/*
|
||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _INODE_H_
|
||||
#define _INODE_H_
|
||||
|
||||
|
||||
#include "system_dependencies.h"
|
||||
#include "Volume.h"
|
||||
#include "xfs_types.h"
|
||||
|
||||
|
||||
#define INODE_MAGIC 0x494e
|
||||
#define INODE_CORE_SIZE 96 // For v4 FS
|
||||
#define INODE_CORE_UNLINKED_SIZE 100 //For v4 FS
|
||||
#define INODE_MINSIZE_LOG 8
|
||||
#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
|
||||
|
||||
// For v4 FS
|
||||
#define INO_MASK(x) ((1ULL << (x)) - 1)
|
||||
// Gets 2^x - 1
|
||||
#define INO_TO_AGNO(id, volume) (xfs_agnumber_t)id >> (volume->AgInodeBits())
|
||||
@@ -27,132 +28,156 @@
|
||||
(id >> (volume->InodesPerBlkLog())) \
|
||||
& (INO_MASK(volume->AgBlocksLog()))
|
||||
// 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
|
||||
#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_nsec;
|
||||
} xfs_timestamp_t;
|
||||
};
|
||||
|
||||
|
||||
typedef enum xfs_dinode_fmt
|
||||
{
|
||||
XFS_DINODE_FMT_DEV, // For devices
|
||||
XFS_DINODE_FMT_LOCAL, // For Directories and links
|
||||
XFS_DINODE_FMT_EXTENTS, // For large number of extents
|
||||
XFS_DINODE_FMT_BTREE, // Extents and Directories
|
||||
XFS_DINODE_FMT_UUID, // Not used
|
||||
} xfs_dinode_fmt_t;
|
||||
|
||||
enum xfs_dinode_fmt_t {
|
||||
XFS_DINODE_FMT_DEV,
|
||||
// For devices
|
||||
XFS_DINODE_FMT_LOCAL,
|
||||
// For Directories and links
|
||||
XFS_DINODE_FMT_EXTENTS,
|
||||
// For large number of extents
|
||||
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
|
||||
fork might be different and that is to be handled accordingly.
|
||||
*/
|
||||
typedef struct xfs_inode
|
||||
{
|
||||
void SwapEndian();
|
||||
int8 Version(); //TODO
|
||||
mode_t Mode();
|
||||
void GetModificationTime(struct timespec& timestamp);
|
||||
void GetChangeTime(struct timespec& timestamp);
|
||||
void GetAccessTime(struct timespec& timestamp);
|
||||
int8 Format(); // The format of the inode
|
||||
xfs_fsize_t Size() const; // TODO
|
||||
xfs_rfsblock_t NoOfBlocks() const;
|
||||
uint32 NLink();
|
||||
uint16 Flags();
|
||||
uint32 UserId();
|
||||
uint32 GroupId();
|
||||
* 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.
|
||||
*/
|
||||
struct xfs_inode_t {
|
||||
void SwapEndian();
|
||||
int8 Version() const;
|
||||
//TODO: Check
|
||||
mode_t Mode() const;
|
||||
void GetModificationTime(struct timespec&
|
||||
timestamp);
|
||||
void GetChangeTime(struct timespec& timestamp);
|
||||
void GetAccessTime(struct timespec& timestamp);
|
||||
int8 Format() const;
|
||||
// The format of the inode
|
||||
xfs_fsize_t Size() const;
|
||||
xfs_rfsblock_t NoOfBlocks() const;
|
||||
uint32 NLink() const;
|
||||
uint16 Flags() const;
|
||||
uint32 UserId() const;
|
||||
uint32 GroupId() const;
|
||||
|
||||
uint16 di_magic;
|
||||
uint16 di_mode; // uses standard S_Ixxx
|
||||
int8 di_version; // 1 or 2
|
||||
int8 di_format;
|
||||
uint16 di_onlink;
|
||||
uint32 di_uid;
|
||||
uint32 di_gid;
|
||||
uint32 di_nlink;
|
||||
uint16 di_projid;
|
||||
uint8 di_pad[8];
|
||||
uint16 di_flushiter;
|
||||
xfs_timestamp_t di_atime;
|
||||
xfs_timestamp_t di_mtime;
|
||||
xfs_timestamp_t di_ctime;
|
||||
xfs_fsize_t di_size; // size in bytes or length if link
|
||||
xfs_rfsblock_t di_nblocks; // blocks used including metadata
|
||||
// extended attributes not included
|
||||
xfs_extlen_t di_extsize; // extent size
|
||||
xfs_extnum_t di_nextents; // number of data extents
|
||||
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;
|
||||
uint16 di_magic;
|
||||
uint16 di_mode;
|
||||
// uses standard S_Ixxx
|
||||
int8 di_version;
|
||||
//This either would be 1 or 2
|
||||
int8 di_format;
|
||||
uint16 di_onlink;
|
||||
uint32 di_uid;
|
||||
uint32 di_gid;
|
||||
uint32 di_nlink;
|
||||
uint16 di_projid;
|
||||
uint8 di_pad[8];
|
||||
uint16 di_flushiter;
|
||||
xfs_timestamp_t di_atime;
|
||||
xfs_timestamp_t di_mtime;
|
||||
xfs_timestamp_t di_ctime;
|
||||
xfs_fsize_t di_size;
|
||||
// size in bytes or length if link
|
||||
xfs_rfsblock_t di_nblocks;
|
||||
// blocks used including metadata
|
||||
// extended attributes not included
|
||||
xfs_extlen_t di_extsize;
|
||||
// extent size
|
||||
xfs_extnum_t di_nextents;
|
||||
// number of data extents
|
||||
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;
|
||||
} xfs_inode_t;
|
||||
uint32 di_next_unlinked;
|
||||
};
|
||||
|
||||
|
||||
class Inode
|
||||
{
|
||||
public:
|
||||
Inode(Volume* volume, xfs_ino_t id);
|
||||
~Inode();
|
||||
bool InitCheck();
|
||||
class Inode {
|
||||
public:
|
||||
Inode(Volume* volume, xfs_ino_t id);
|
||||
~Inode();
|
||||
status_t Init();
|
||||
|
||||
xfs_ino_t ID() const { return fId; }
|
||||
xfs_ino_t ID() const { return fId; }
|
||||
|
||||
bool IsDirectory() const
|
||||
{ return S_ISDIR(Mode()); }
|
||||
bool IsDirectory() const
|
||||
{ return S_ISDIR(Mode()); }
|
||||
|
||||
bool IsFile() const
|
||||
{ return S_ISREG(Mode()); }
|
||||
bool IsFile() const
|
||||
{ return S_ISREG(Mode()); }
|
||||
|
||||
bool IsSymLink() const
|
||||
{ return S_ISLNK(Mode()); }
|
||||
bool IsSymLink() const
|
||||
{ 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
|
||||
{ fNode->GetChangeTime(timestamp); }
|
||||
xfs_fsize_t Size() const { return fNode->Size(); }
|
||||
|
||||
void GetModificationTime(struct timespec& timestamp) const
|
||||
{ fNode->GetModificationTime(timestamp); }
|
||||
void GetChangeTime(struct timespec& timestamp) const
|
||||
{ fNode->GetChangeTime(timestamp); }
|
||||
|
||||
void GetAccessTime(struct timespec& timestamp) const
|
||||
{ fNode->GetAccessTime(timestamp); }
|
||||
void GetModificationTime(struct timespec& timestamp)
|
||||
const
|
||||
{ fNode->GetModificationTime(timestamp); }
|
||||
|
||||
private:
|
||||
uint32 UserId() { return fNode->UserId(); }
|
||||
uint32 GroupId() { return fNode->GroupId(); }
|
||||
void GetAccessTime(struct timespec& timestamp) const
|
||||
{ fNode->GetAccessTime(timestamp); }
|
||||
|
||||
status_t GetFromDisk();
|
||||
xfs_inode_t* fNode;
|
||||
xfs_ino_t fId;
|
||||
Volume* fVolume;
|
||||
char* fBuffer; // Contains the disk inode in BE format
|
||||
uint32 UserId() const { return fNode->UserId(); }
|
||||
uint32 GroupId() const { return fNode->GroupId(); }
|
||||
|
||||
private:
|
||||
status_t GetFromDisk();
|
||||
xfs_inode_t* fNode;
|
||||
xfs_ino_t fId;
|
||||
Volume* fVolume;
|
||||
char* fBuffer;
|
||||
// Contains the disk inode in BE format
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -20,9 +20,12 @@ DEFINES += DEBUG_APP="\\\"xfs\\\"" ;
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src libs uuid ] : true ;
|
||||
|
||||
local xfsSources =
|
||||
DeviceOpener.cpp
|
||||
Directory.cpp
|
||||
Inode.cpp
|
||||
kernel_cpp.cpp
|
||||
kernel_interface.cpp
|
||||
ShortDirectory.cpp
|
||||
Volume.cpp
|
||||
xfs.cpp
|
||||
;
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||
* 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, [email protected]
|
||||
* 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, [email protected]
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "Volume.h"
|
||||
#include "DeviceOpener.h"
|
||||
|
||||
#include "Inode.h"
|
||||
|
||||
|
||||
Volume::Volume(fs_volume *volume)
|
||||
: fFSVolume(volume)
|
||||
: fFSVolume(volume)
|
||||
{
|
||||
fFlags = 0;
|
||||
mutex_init(&fLock, "xfs volume");
|
||||
@@ -24,7 +27,7 @@ Volume::~Volume()
|
||||
|
||||
|
||||
bool
|
||||
Volume::IsValidSuperBlock()
|
||||
Volume::IsValidSuperBlock() const
|
||||
{
|
||||
return fSuperBlock.IsValid();
|
||||
}
|
||||
@@ -65,7 +68,7 @@ Volume::Mount(const char *deviceName, uint32 flags)
|
||||
|
||||
DeviceOpener opener(deviceName, (flags & B_MOUNT_READ_ONLY) != 0
|
||||
? O_RDONLY
|
||||
: O_RDWR);
|
||||
: O_RDWR);
|
||||
fDevice = opener.Device();
|
||||
if (fDevice < B_OK) {
|
||||
ERROR("Volume::Mount(): couldn't open device\n");
|
||||
@@ -92,6 +95,21 @@ Volume::Mount(const char *deviceName, uint32 flags)
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
/*
|
||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _VOLUME_H_
|
||||
#define _VOLUME_H_
|
||||
|
||||
|
||||
#include <DeviceOpener.h>
|
||||
|
||||
#include "xfs.h"
|
||||
|
||||
|
||||
/* Converting the FS Blocks to Basic Blocks */
|
||||
#define FSBSHIFT(fsBlockLog) (fsBlockLog - BBLOCKLOG);
|
||||
#define FSB_TO_BB(fsBlockLog, x) x << FSBSHIFT(fsBlockLog);
|
||||
#define FSBLOCK_SHIFT(fsBlockLog) (fsBlockLog - BASICBLOCKLOG);
|
||||
#define FSBLOCKS_TO_BASICBLOCKS(fsBlockLog, x) x << FSBLOCK_SHIFT(fsBlockLog);
|
||||
// Converting the FS Blocks to Basic Blocks
|
||||
|
||||
enum volume_flags {
|
||||
VOLUME_READ_ONLY = 0x0001
|
||||
@@ -28,15 +30,16 @@ public:
|
||||
status_t Initialize(int fd, const char *label,
|
||||
uint32 blockSize, uint32 sectorSize);
|
||||
|
||||
bool IsValidSuperBlock();
|
||||
bool IsValidSuperBlock() const;
|
||||
bool IsReadOnly() const
|
||||
{ return (fFlags & VOLUME_READ_ONLY) != 0; }
|
||||
{ return
|
||||
(fFlags & VOLUME_READ_ONLY) != 0; }
|
||||
|
||||
dev_t ID() const
|
||||
{ return fFSVolume ? fFSVolume->id : -1; }
|
||||
fs_volume* FSVolume() const
|
||||
{ return fFSVolume; }
|
||||
char* Name()
|
||||
const char* Name() const
|
||||
{ return fSuperBlock.Name(); }
|
||||
|
||||
XfsSuperBlock& SuperBlock() { return fSuperBlock; }
|
||||
@@ -44,29 +47,37 @@ public:
|
||||
|
||||
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(); }
|
||||
|
||||
uint8 AgInodeBits()
|
||||
uint8 AgInodeBits() const
|
||||
{ return fSuperBlock.AgInodeBits(); }
|
||||
|
||||
uint8 AgBlocksLog()
|
||||
uint8 AgBlocksLog() const
|
||||
{ return fSuperBlock.AgBlocksLog(); }
|
||||
|
||||
uint8 InodesPerBlkLog()
|
||||
uint8 InodesPerBlkLog() const
|
||||
{ return fSuperBlock.InodesPerBlkLog(); }
|
||||
|
||||
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
|
||||
off_t NumBlocks() const
|
||||
@@ -77,7 +88,8 @@ protected:
|
||||
fs_volume* fFSVolume;
|
||||
int fDevice;
|
||||
XfsSuperBlock fSuperBlock;
|
||||
char fName[32]; /* filesystem name */
|
||||
char fName[32];
|
||||
// Filesystem name
|
||||
|
||||
uint32 fDeviceBlockSize;
|
||||
mutex fLock;
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
/*
|
||||
* Copyright 2001-2017, Axel Dörfler, [email protected].
|
||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
* Copyright 2001-2017, Axel Dörfler, [email protected].
|
||||
* Copyright 2020, Shubham Bhagat, [email protected]
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "system_dependencies.h"
|
||||
#include "Directory.h"
|
||||
#include "Inode.h"
|
||||
#include "Volume.h"
|
||||
|
||||
@@ -86,16 +89,6 @@ xfs_mount(fs_volume *_volume, const char *device, uint32 flags,
|
||||
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();
|
||||
return B_OK;
|
||||
}
|
||||
@@ -116,6 +109,7 @@ xfs_unmount(fs_volume *_volume)
|
||||
static status_t
|
||||
xfs_read_fs_info(fs_volume *_volume, struct fs_info *info)
|
||||
{
|
||||
TRACE("XFS_READ_FS_INFO:\n");
|
||||
Volume* volume = (Volume*)_volume->private_volume;
|
||||
|
||||
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,
|
||||
uint32 *_flags, bool reenter)
|
||||
{
|
||||
TRACE("XFS_GET_VNODE:\n");
|
||||
Volume* volume = (Volume*)_volume->private_volume;
|
||||
|
||||
Inode* inode = new(std::nothrow) Inode(volume, id);
|
||||
|
||||
if (inode == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t status = inode->InitCheck();
|
||||
if (status == false) {
|
||||
status_t status = inode->Init();
|
||||
if (status != B_OK) {
|
||||
delete inode;
|
||||
ERROR("get_vnode: InitCheck() failed. Error: %s\n", strerror(status));
|
||||
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;
|
||||
*_type = inode->Mode();
|
||||
*_flags = 0;
|
||||
|
||||
TRACE("(%d)\n", inode->ID());
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -166,7 +160,9 @@ xfs_get_vnode(fs_volume *_volume, ino_t id, fs_vnode *_node, int *_type,
|
||||
static status_t
|
||||
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,
|
||||
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)
|
||||
{
|
||||
Inode* inode = (Inode*)_node->private_node;
|
||||
TRACE("XFS_READ_STAT: root_id: (%d)\n", inode->ID());
|
||||
stat->st_dev = inode->GetVolume()->ID();
|
||||
stat->st_ino = inode->ID();
|
||||
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_type = 0; // TODO
|
||||
|
||||
stat->st_size = inode->GetVolume()->InodeSize();
|
||||
stat->st_size = inode->Size();
|
||||
stat->st_blocks = inode->NoOfBlocks();
|
||||
|
||||
inode->GetAccessTime(stat->st_atim);
|
||||
@@ -282,7 +308,9 @@ xfs_free_cookie(fs_volume *_volume, fs_vnode *_node, void *_cookie)
|
||||
static status_t
|
||||
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
|
||||
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,
|
||||
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"
|
||||
|
||||
|
||||
uint8
|
||||
XfsSuperBlock::Flags() const
|
||||
{
|
||||
return sb_flags;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
XfsSuperBlock::IsValid()
|
||||
XfsSuperBlock::IsValid() const
|
||||
{
|
||||
if (sb_magicnum != XFS_SB_MAGIC)
|
||||
return false;
|
||||
|
||||
if (BBLOCKSIZE > sb_blocksize) {
|
||||
if (BASICBLOCKSIZE > sb_blocksize) {
|
||||
ERROR("Basic block is less than 512 bytes!");
|
||||
return false;
|
||||
}
|
||||
@@ -22,91 +29,91 @@ XfsSuperBlock::IsValid()
|
||||
|
||||
|
||||
uint32
|
||||
XfsSuperBlock::BlockSize()
|
||||
XfsSuperBlock::BlockSize() const
|
||||
{
|
||||
return sb_blocksize;
|
||||
}
|
||||
|
||||
|
||||
uint8
|
||||
XfsSuperBlock::BlockLog()
|
||||
XfsSuperBlock::BlockLog() const
|
||||
{
|
||||
return sb_blocklog;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
XfsSuperBlock::DirBlockSize()
|
||||
XfsSuperBlock::DirBlockSize() const
|
||||
{
|
||||
return BlockSize() * (1 << sb_dirblklog);
|
||||
}
|
||||
|
||||
|
||||
uint8
|
||||
XfsSuperBlock::AgInodeBits()
|
||||
XfsSuperBlock::AgInodeBits() const
|
||||
{
|
||||
return AgBlocksLog() + InodesPerBlkLog();
|
||||
}
|
||||
|
||||
|
||||
uint8
|
||||
XfsSuperBlock::InodesPerBlkLog()
|
||||
XfsSuperBlock::InodesPerBlkLog() const
|
||||
{
|
||||
return sb_inopblog;
|
||||
}
|
||||
|
||||
|
||||
uint8
|
||||
XfsSuperBlock::AgBlocksLog()
|
||||
XfsSuperBlock::AgBlocksLog() const
|
||||
{
|
||||
return sb_agblklog;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
XfsSuperBlock::Size()
|
||||
XfsSuperBlock::Size() const
|
||||
{
|
||||
return XFS_SB_MAXSIZE;
|
||||
}
|
||||
|
||||
|
||||
uint16
|
||||
XfsSuperBlock::InodeSize()
|
||||
XfsSuperBlock::InodeSize() const
|
||||
{
|
||||
return sb_inodesize;
|
||||
}
|
||||
|
||||
|
||||
xfs_rfsblock_t
|
||||
XfsSuperBlock::TotalBlocks()
|
||||
XfsSuperBlock::TotalBlocks() const
|
||||
{
|
||||
return sb_dblocks;
|
||||
}
|
||||
|
||||
|
||||
xfs_rfsblock_t
|
||||
XfsSuperBlock::TotalBlocksWithLog()
|
||||
XfsSuperBlock::TotalBlocksWithLog() const
|
||||
{
|
||||
return TotalBlocks() + sb_logblocks;
|
||||
}
|
||||
|
||||
|
||||
uint64
|
||||
XfsSuperBlock::FreeBlocks()
|
||||
XfsSuperBlock::FreeBlocks() const
|
||||
{
|
||||
return sb_fdblocks;
|
||||
}
|
||||
|
||||
|
||||
uint64
|
||||
XfsSuperBlock::UsedBlocks()
|
||||
XfsSuperBlock::UsedBlocks() const
|
||||
{
|
||||
return TotalBlocks() - FreeBlocks();
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
XfsSuperBlock::Name()
|
||||
const char*
|
||||
XfsSuperBlock::Name() const
|
||||
{
|
||||
return sb_fname;
|
||||
}
|
||||
@@ -120,14 +127,14 @@ XfsSuperBlock::Root() const
|
||||
|
||||
|
||||
xfs_agnumber_t
|
||||
XfsSuperBlock::AgCount()
|
||||
XfsSuperBlock::AgCount() const
|
||||
{
|
||||
return sb_agcount;
|
||||
}
|
||||
|
||||
|
||||
xfs_agblock_t
|
||||
XfsSuperBlock::AgBlocks()
|
||||
XfsSuperBlock::AgBlocks() const
|
||||
{
|
||||
return sb_agblocks;
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
/*
|
||||
* Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
* Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
/*
|
||||
*Important:
|
||||
*All fields in XFS metadata structures are in big-endian byte order
|
||||
*except for log items which are formatted in host order.
|
||||
*
|
||||
*This file contains all global structure definitions.
|
||||
*/
|
||||
|
||||
*Important:
|
||||
*All fields in XFS metadata structures are in big-endian byte order
|
||||
*except for log items which are formatted in host order.
|
||||
*
|
||||
*This file contains all global structure definitions.
|
||||
*/
|
||||
#ifndef _XFS_SB_H_
|
||||
#define _XFS_SB_H_
|
||||
|
||||
|
||||
#include "system_dependencies.h"
|
||||
#include "xfs_types.h"
|
||||
|
||||
@@ -22,83 +22,86 @@ extern fs_vnode_ops gxfsVnodeOps;
|
||||
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 BBLOCKLOG 9 /* Log of block size should be 9 */
|
||||
#define BBLOCKSIZE 1 << BBLOCKLOG /* The size of a basic block should be 512 */
|
||||
#define BASICBLOCKLOG 9
|
||||
// Log of block size should be 9
|
||||
#define BASICBLOCKSIZE 1 << BASICBLOCKLOG
|
||||
// The size of a basic block should be 512
|
||||
|
||||
|
||||
/* Version 4 superblock definition */
|
||||
class XfsSuperBlock
|
||||
{
|
||||
class XfsSuperBlock {
|
||||
public:
|
||||
|
||||
bool IsValid();
|
||||
char* Name();
|
||||
uint32 BlockSize();
|
||||
uint8 BlockLog();
|
||||
uint32 DirBlockSize(); // maximum 65536
|
||||
uint8 AgInodeBits();
|
||||
uint8 InodesPerBlkLog();
|
||||
uint8 AgBlocksLog();
|
||||
xfs_rfsblock_t TotalBlocks();
|
||||
xfs_rfsblock_t TotalBlocksWithLog();
|
||||
uint64 FreeBlocks();
|
||||
uint64 UsedBlocks();
|
||||
uint32 Size();
|
||||
uint16 InodeSize();
|
||||
void SwapEndian();
|
||||
xfs_ino_t Root() const;
|
||||
xfs_agnumber_t AgCount();
|
||||
xfs_agblock_t AgBlocks();
|
||||
|
||||
bool IsValid() const;
|
||||
const char* Name() const;
|
||||
uint32 BlockSize() const;
|
||||
uint8 BlockLog() const;
|
||||
uint32 DirBlockSize() const;
|
||||
// maximum 65536
|
||||
uint8 AgInodeBits() const;
|
||||
uint8 InodesPerBlkLog() const;
|
||||
uint8 AgBlocksLog() const;
|
||||
xfs_rfsblock_t TotalBlocks() const;
|
||||
xfs_rfsblock_t TotalBlocksWithLog() const;
|
||||
uint64 FreeBlocks() const;
|
||||
uint64 UsedBlocks() const;
|
||||
uint32 Size() const;
|
||||
uint16 InodeSize() const;
|
||||
void SwapEndian();
|
||||
xfs_ino_t Root() const;
|
||||
xfs_agnumber_t AgCount() const;
|
||||
xfs_agblock_t AgBlocks() const;
|
||||
uint8 Flags() const;
|
||||
private:
|
||||
|
||||
uint32 sb_magicnum;
|
||||
uint32 sb_blocksize;
|
||||
xfs_rfsblock_t sb_dblocks;
|
||||
xfs_rfsblock_t sb_rblocks;
|
||||
xfs_rtblock_t sb_rextents;
|
||||
uuid_t sb_uuid;
|
||||
xfs_fsblock_t sb_logstart;
|
||||
xfs_ino_t sb_rootino;
|
||||
xfs_ino_t sb_rbmino;
|
||||
xfs_ino_t sb_rsumino;
|
||||
xfs_agblock_t sb_rextsize;
|
||||
xfs_agblock_t sb_agblocks;
|
||||
xfs_agnumber_t sb_agcount;
|
||||
xfs_extlen_t sb_rbmblocks;
|
||||
xfs_extlen_t sb_logblocks;
|
||||
uint16 sb_versionnum;
|
||||
uint16 sb_sectsize;
|
||||
uint16 sb_inodesize;
|
||||
uint16 sb_inopblock;
|
||||
char sb_fname[12];
|
||||
uint8 sb_blocklog;
|
||||
uint8 sb_sectlog;
|
||||
uint8 sb_inodelog;
|
||||
uint8 sb_inopblog;
|
||||
uint8 sb_agblklog;
|
||||
uint8 sb_rextslog;
|
||||
uint8 sb_inprogress;
|
||||
uint8 sb_imax_pct;
|
||||
uint64 sb_icount;
|
||||
uint64 sb_ifree;
|
||||
uint64 sb_fdblocks;
|
||||
uint64 sb_frextents;
|
||||
xfs_ino_t sb_uquotino;
|
||||
xfs_ino_t sb_gquotino;
|
||||
uint16 sb_qflags;
|
||||
uint8 sb_flags;
|
||||
uint8 sb_shared_vn;
|
||||
xfs_extlen_t sb_inoalignmt;
|
||||
uint32 sb_unit;
|
||||
uint32 sb_width;
|
||||
uint8 sb_dirblklog;
|
||||
uint8 sb_logsectlog;
|
||||
uint16 sb_logsectsize;
|
||||
uint32 sb_logsunit;
|
||||
uint32 sb_features2;
|
||||
uint32 sb_magicnum;
|
||||
uint32 sb_blocksize;
|
||||
xfs_rfsblock_t sb_dblocks;
|
||||
xfs_rfsblock_t sb_rblocks;
|
||||
xfs_rtblock_t sb_rextents;
|
||||
uuid_t sb_uuid;
|
||||
xfs_fsblock_t sb_logstart;
|
||||
xfs_ino_t sb_rootino;
|
||||
xfs_ino_t sb_rbmino;
|
||||
xfs_ino_t sb_rsumino;
|
||||
xfs_agblock_t sb_rextsize;
|
||||
xfs_agblock_t sb_agblocks;
|
||||
xfs_agnumber_t sb_agcount;
|
||||
xfs_extlen_t sb_rbmblocks;
|
||||
xfs_extlen_t sb_logblocks;
|
||||
uint16 sb_versionnum;
|
||||
uint16 sb_sectsize;
|
||||
uint16 sb_inodesize;
|
||||
uint16 sb_inopblock;
|
||||
char sb_fname[12];
|
||||
uint8 sb_blocklog;
|
||||
uint8 sb_sectlog;
|
||||
uint8 sb_inodelog;
|
||||
uint8 sb_inopblog;
|
||||
uint8 sb_agblklog;
|
||||
uint8 sb_rextslog;
|
||||
uint8 sb_inprogress;
|
||||
uint8 sb_imax_pct;
|
||||
uint64 sb_icount;
|
||||
uint64 sb_ifree;
|
||||
uint64 sb_fdblocks;
|
||||
uint64 sb_frextents;
|
||||
xfs_ino_t sb_uquotino;
|
||||
xfs_ino_t sb_gquotino;
|
||||
uint16 sb_qflags;
|
||||
uint8 sb_flags;
|
||||
uint8 sb_shared_vn;
|
||||
xfs_extlen_t sb_inoalignmt;
|
||||
uint32 sb_unit;
|
||||
uint32 sb_width;
|
||||
uint8 sb_dirblklog;
|
||||
uint8 sb_logsectlog;
|
||||
uint16 sb_logsectsize;
|
||||
uint32 sb_logsunit;
|
||||
uint32 sb_features2;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -39,8 +39,11 @@ UseHeaders [ FDirName $(HAIKU_TOP) headers private ] : true ;
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src tools fs_shell ] ;
|
||||
|
||||
local xfsSource =
|
||||
DeviceOpener.cpp
|
||||
Directory.cpp
|
||||
Inode.cpp
|
||||
kernel_interface.cpp
|
||||
ShortDirectory.cpp
|
||||
Volume.cpp
|
||||
xfs.cpp
|
||||
;
|
||||
|
||||
Reference in New Issue
Block a user