xfs: Read Short Form Directories
We can now read short form directories. Change-Id: I23eb6ef52e8bb07643213e603ed0185f536c649f Reviewed-on: https://review.haiku-os.org/c/haiku/+/2952 Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
This commit is contained in:
parent
4639c4e898
commit
a060fa968e
@ -1,6 +1,10 @@
|
||||
/*
|
||||
* Copyright 2017, Chế Vũ Gia Hy, cvghy116@gmail.com.
|
||||
* Copyright 2011, Jérôme Duval, korli@users.berlios.de.
|
||||
* Copyright 2008-2014, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Copyright 2005-2007, Ingo Weinhold, bonefish@cs.tu-berlin.de.
|
||||
* Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
* This file may be used under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _DEBUG_H_
|
||||
#define _DEBUG_H_
|
||||
@ -8,8 +12,11 @@
|
||||
// #define TRACE_XFS
|
||||
#ifdef TRACE_XFS
|
||||
#define TRACE(x...) dprintf("\n\33[34mxfs:\33[0m " x)
|
||||
#define ASSERT(x) \
|
||||
{ if (!(x)) kernel_debugger("xfs: assert failed: " #x "\n"); }
|
||||
#else
|
||||
#define TRACE(x...) ;
|
||||
#define ASSERT(x) ;
|
||||
#endif
|
||||
#define ERROR(x...) dprintf("\n\33[34mxfs:\33[0m " x)
|
||||
|
||||
|
@ -50,6 +50,7 @@ DirectoryIterator::Init()
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
DirectoryIterator::GetNext(char* name, size_t* length, xfs_ino_t* ino)
|
||||
{
|
||||
|
@ -174,6 +174,9 @@ Inode::GetFromDisk()
|
||||
uint32 len = fVolume->InodeSize();
|
||||
// Inode len to read (size of inode)
|
||||
|
||||
TRACE("AgNumber: (%d), AgRelativeIno: (%d), AgRelativeBlockNum: (%d),"
|
||||
"Offset: (%d), len: (%d)\n", agNo, agInodeNo, agBlock, offset, len);
|
||||
|
||||
if (agNo > fVolume->AgCount()) {
|
||||
ERROR("Inode::GetFromDisk : AG Number more than number of AGs");
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
@ -184,7 +187,7 @@ Inode::GetFromDisk()
|
||||
xfs_fsblock_t blockToRead = FSBLOCKS_TO_BASICBLOCKS(fVolume->BlockLog(),
|
||||
((uint64)(agNo * numberOfBlocksInAg) + agBlock));
|
||||
|
||||
xfs_daddr_t readPos = blockToRead*(BASICBLOCKSIZE) + offset;
|
||||
xfs_daddr_t readPos = blockToRead * (BASICBLOCKSIZE) + offset * len;
|
||||
|
||||
if (read_pos(fVolume->Device(), readPos, fBuffer, len) != len) {
|
||||
ERROR("Inode::Inode(): IO Error");
|
||||
|
@ -30,9 +30,10 @@
|
||||
// Gets the AG relative block number that contains inode
|
||||
#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_DFORK_PTR(dir_ino_ptr) (void*) \
|
||||
((char*) dir_ino_ptr + DATA_FORK_OFFSET)
|
||||
#define DIR_AFORK_PTR(dir_ino_ptr) \
|
||||
(XFS_DFORK_PTR + \
|
||||
(void*)((char*)XFS_DFORK_PTR + \
|
||||
((uint32)dir_ino_ptr->di_forkoff<<3))
|
||||
#define DIR_AFORK_EXIST(dir_ino_ptr) dir_ino_ptr->di_forkoff!=0
|
||||
|
||||
|
@ -12,8 +12,8 @@ ShortDirectory::ShortDirectory(Inode* inode)
|
||||
fInode(inode),
|
||||
fTrack(0)
|
||||
{
|
||||
memcpy(&fHeader,
|
||||
DIR_DFORK_PTR(fInode->Buffer()), sizeof(xfs_dir2_sf_hdr_t));
|
||||
|
||||
fHeader = (ShortFormHeader*)(DIR_DFORK_PTR(fInode->Buffer()));
|
||||
}
|
||||
|
||||
|
||||
@ -22,20 +22,76 @@ ShortDirectory::~ShortDirectory()
|
||||
}
|
||||
|
||||
|
||||
xfs_ino_t
|
||||
ShortDirectory::GetParentIno()
|
||||
bool
|
||||
ShortDirectory::HasFileTypeField()
|
||||
{
|
||||
TRACE("GetParentIno: \n");
|
||||
if (fHeader.i8count > 0)
|
||||
return B_BENDIAN_TO_HOST_INT64(fHeader.parent.i8);
|
||||
if (fInode->GetVolume()->SuperBlockFeatures2() & XFS_SB_VERSION2_FTYPE)
|
||||
return true;
|
||||
else
|
||||
return B_BENDIAN_TO_HOST_INT32(fHeader.parent.i4);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
uint8
|
||||
ShortDirectory::GetFileType(ShortFormEntry* entry)
|
||||
{
|
||||
ASSERT(HasFileTypeField() == true);
|
||||
return entry->name[entry->namelen];
|
||||
}
|
||||
|
||||
|
||||
ShortFormEntry*
|
||||
ShortDirectory::FirstEntry()
|
||||
{
|
||||
return (ShortFormEntry*) ((char*) fHeader + HeaderSize());
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
ShortDirectory::HeaderSize()
|
||||
{
|
||||
if (fHeader->i8count)
|
||||
return sizeof(ShortFormHeader);
|
||||
else
|
||||
return sizeof(ShortFormHeader) - sizeof(uint32);
|
||||
}
|
||||
|
||||
|
||||
xfs_ino_t
|
||||
ShortDirectory::GetIno(ShortFormInodeUnion* inum)
|
||||
{
|
||||
if (fHeader->i8count)
|
||||
return B_BENDIAN_TO_HOST_INT64(inum->i8);
|
||||
else
|
||||
return B_BENDIAN_TO_HOST_INT32(inum->i4);
|
||||
}
|
||||
|
||||
|
||||
xfs_ino_t
|
||||
ShortDirectory::GetEntryIno(ShortFormEntry* entry)
|
||||
{
|
||||
if (HasFileTypeField())
|
||||
return GetIno((ShortFormInodeUnion*)(entry->name
|
||||
+ entry->namelen + sizeof(uint8)));
|
||||
else
|
||||
return GetIno((ShortFormInodeUnion*)(entry->name + entry->namelen));
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
ShortDirectory::EntrySize(int namelen)
|
||||
{
|
||||
return sizeof(ShortFormEntry) + namelen
|
||||
+ (HasFileTypeField()? sizeof(uint8) : 0)
|
||||
+ (fHeader->i8count? sizeof(uint64):sizeof(uint32));
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ShortDirectory::Lookup(const char* name, size_t length, xfs_ino_t* ino)
|
||||
{
|
||||
TRACE("ShortDirectory::Lookup\n");
|
||||
|
||||
if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
|
||||
xfs_ino_t rootIno = fInode->GetVolume()->Root();
|
||||
if (strcmp(name, ".") == 0 || (rootIno == fInode->ID())) {
|
||||
@ -43,13 +99,27 @@ ShortDirectory::Lookup(const char* name, size_t length, xfs_ino_t* ino)
|
||||
TRACE("ShortDirectory:Lookup: name: \".\" ino: (%d)\n", *ino);
|
||||
return B_OK;
|
||||
}
|
||||
*ino = GetParentIno();
|
||||
*ino = GetIno(&fHeader->parent);
|
||||
TRACE("Parent: (%d)\n", *ino);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
//TODO: Other entries
|
||||
return B_NOT_SUPPORTED;
|
||||
ShortFormEntry* entry = FirstEntry();
|
||||
TRACE("Length of first entry: (%d),offset of first entry:"
|
||||
"(%d)\n", entry->namelen, B_BENDIAN_TO_HOST_INT16(entry->offset.i));
|
||||
|
||||
int status;
|
||||
for (int i = 0; i < fHeader->count; i++) {
|
||||
status = strncmp(name, (char*)entry->name, entry->namelen);
|
||||
if (status == 0) {
|
||||
*ino = GetEntryIno(entry);
|
||||
return B_OK;
|
||||
}
|
||||
entry = (ShortFormEntry*)
|
||||
((char*) entry + EntrySize(entry->namelen));
|
||||
}
|
||||
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
@ -73,12 +143,35 @@ ShortDirectory::GetNext(char* name, size_t* length, xfs_ino_t* ino)
|
||||
return B_BUFFER_OVERFLOW;
|
||||
*length = 3;
|
||||
strlcpy(name, "..", *length + 1);
|
||||
*ino = GetParentIno();
|
||||
*ino = GetIno(&fHeader->parent);
|
||||
fTrack = 2;
|
||||
TRACE("ShortDirectory:GetNext: name: \"..\" ino: (%d)\n", *ino);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// TODO: Now iterate through sf entries
|
||||
return B_NOT_SUPPORTED;
|
||||
ShortFormEntry* entry = FirstEntry();
|
||||
TRACE("Length of first entry: (%d), offset of first entry:"
|
||||
"(%d)\n", entry->namelen, B_BENDIAN_TO_HOST_INT16(entry->offset.i));
|
||||
|
||||
for (int i = 0; i < fHeader->count; i++) {
|
||||
uint16 curOffset = B_BENDIAN_TO_HOST_INT16(entry->offset.i);
|
||||
if (curOffset > fLastEntryOffset) {
|
||||
|
||||
if (entry->namelen > *length)
|
||||
return B_BUFFER_OVERFLOW;
|
||||
|
||||
fLastEntryOffset = curOffset;
|
||||
memcpy(name, entry->name, entry->namelen);
|
||||
name[entry->namelen] = '\0';
|
||||
*length = entry->namelen + 1;
|
||||
*ino = GetEntryIno(entry);
|
||||
|
||||
TRACE("Entry found. Name: (%s), Length: (%ld),ino: (%ld)\n", name,
|
||||
*length, *ino);
|
||||
return B_OK;
|
||||
}
|
||||
entry = (ShortFormEntry*)((char*)entry + EntrySize(entry->namelen));
|
||||
}
|
||||
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
@ -5,52 +5,49 @@
|
||||
#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
|
||||
/*
|
||||
* offset into the literal area
|
||||
* xfs_dir2_sf_off_t
|
||||
*/
|
||||
struct ShortFormOffset {
|
||||
uint16 i;
|
||||
} __attribute__((packed));
|
||||
|
||||
union xfs_dir2_inou_t {
|
||||
//xfs_dir2_inou_t
|
||||
union ShortFormInodeUnion {
|
||||
uint64 i8;
|
||||
uint32 i4;
|
||||
};
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
// Short form directory header
|
||||
struct xfs_dir2_sf_hdr_t {
|
||||
// xfs_dir2_sf_hdr_t
|
||||
struct ShortFormHeader {
|
||||
uint8 count;
|
||||
// number of entries
|
||||
uint8 i8count;
|
||||
// # of 64bit inode entries
|
||||
xfs_dir2_inou_t parent;
|
||||
ShortFormInodeUnion parent;
|
||||
// absolute inode # of parent
|
||||
};
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
/*
|
||||
*The xfs_dir2_sf_entry is split into
|
||||
* two parts because the entries size is variable
|
||||
*/
|
||||
struct xfs_dir2_sf_entry_t {
|
||||
//xfs_dir2_sf_entry_t
|
||||
struct ShortFormEntry {
|
||||
uint8 namelen;
|
||||
// length of the name, in bytes
|
||||
xfs_dir2_sf_off_t offset;
|
||||
ShortFormOffset 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;
|
||||
};
|
||||
};
|
||||
/*
|
||||
* Following will be a single byte file type variable
|
||||
* and inode number (64bits or 32 bits)
|
||||
*/
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
class ShortDirectory
|
||||
@ -58,21 +55,24 @@ class ShortDirectory
|
||||
public:
|
||||
ShortDirectory(Inode* inode);
|
||||
~ShortDirectory();
|
||||
size_t HeaderSize();
|
||||
bool HasFileTypeField();
|
||||
uint8 GetFileType(ShortFormEntry* entry);
|
||||
ShortFormEntry* FirstEntry();
|
||||
xfs_ino_t GetIno(ShortFormInodeUnion* inum);
|
||||
xfs_ino_t GetEntryIno(ShortFormEntry* entry);
|
||||
size_t EntrySize(int namelen);
|
||||
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
|
||||
ShortFormHeader* fHeader;
|
||||
uint16 fLastEntryOffset;
|
||||
// offset into the literal area
|
||||
uint8 fTrack;
|
||||
// Takes the values 0, 1 or 2 only
|
||||
|
||||
// Takes the values 0, 1 or 2
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -79,6 +79,9 @@ public:
|
||||
uint8 SuperBlockFlags() const
|
||||
{ return fSuperBlock.Flags(); }
|
||||
|
||||
uint32 SuperBlockFeatures2() const
|
||||
{ return fSuperBlock.Features2(); }
|
||||
|
||||
#if 0
|
||||
off_t NumBlocks() const
|
||||
{ return fSuperBlock.NumBlocks(); }
|
||||
|
@ -249,7 +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());
|
||||
TRACE("XFS_READ_STAT: id: (%d)\n", inode->ID());
|
||||
stat->st_dev = inode->GetVolume()->ID();
|
||||
stat->st_ino = inode->ID();
|
||||
stat->st_nlink = 1;
|
||||
|
@ -24,10 +24,27 @@ XfsSuperBlock::IsValid() const
|
||||
return false;
|
||||
}
|
||||
|
||||
// Checking version 4 file system
|
||||
ASSERT((Version() & 0x000f) == 4)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint16
|
||||
XfsSuperBlock::Version() const
|
||||
{
|
||||
return sb_versionnum;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
XfsSuperBlock::Features2() const
|
||||
{
|
||||
return sb_features2;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
XfsSuperBlock::BlockSize() const
|
||||
{
|
||||
|
@ -55,6 +55,8 @@ public:
|
||||
xfs_agnumber_t AgCount() const;
|
||||
xfs_agblock_t AgBlocks() const;
|
||||
uint8 Flags() const;
|
||||
uint16 Version() const;
|
||||
uint32 Features2() const;
|
||||
private:
|
||||
|
||||
uint32 sb_magicnum;
|
||||
@ -151,13 +153,13 @@ Superblock quota flags - sb_qflags
|
||||
Extended v4 Superblock flags - sb_features2
|
||||
*/
|
||||
|
||||
#define XFS_SB_VERSION2_LAZYSBCOUNTBIT 0x0001
|
||||
#define XFS_SB_VERSION2_LAZYSBCOUNTBIT 0x00000001
|
||||
// update global free space and inode on clean unmount
|
||||
#define XFS_SB_VERSION2_ATTR2BIT 0x0002
|
||||
#define XFS_SB_VERSION2_ATTR2BIT 0x00000002
|
||||
// optimises the inode layout of ext-attr
|
||||
#define XFS_SB_VERSION2_PARENTBIT 0x0004 /* Parent pointers */
|
||||
#define XFS_SB_VERSION2_PROJID32BIT 0x0008 /* 32-bit project id */
|
||||
#define XFS_SB_VERSION2_CRCBIT 0x0010 /* Metadata checksumming */
|
||||
#define XFS_SB_VERSION2_FTYPE 0x0020
|
||||
#define XFS_SB_VERSION2_PARENTBIT 0x00000010 /* Parent pointers */
|
||||
#define XFS_SB_VERSION2_PROJID32BIT 0x00000080 /* 32-bit project id */
|
||||
#define XFS_SB_VERSION2_CRCBIT 0x00000100 /* Metadata checksumming */
|
||||
#define XFS_SB_VERSION2_FTYPE 0x00000200
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user