ufs2: implementing open_dir and read_dir function

Root directory is read sucessfully.

Change-Id: I8bdc8c1a52edb679a6cb4b5f70e7f42eb2b2c8f1
Reviewed-on: https://review.haiku-os.org/c/haiku/+/2907
Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
This commit is contained in:
Suhel Mehta 2020-06-13 00:56:16 +05:30 committed by Adrien Destugues
parent 4a230cfc6c
commit 239a1c3561
10 changed files with 282 additions and 14 deletions

View File

@ -0,0 +1,130 @@
/*
* Copyright 2020 Suhel Mehta, mehtasuhel@gmail.com
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include "DirectoryIterator.h"
#include <stdlib.h>
#include "Inode.h"
#define TRACE_UFS2
#ifdef TRACE_UFS2
# define TRACE(x...) dprintf("\33[34mufs2:\33[0m " x)
#else
# define TRACE(x...) ;
#endif
#define ERROR(x...) dprintf("\33[34mufs2:\33[0m " x)
DirectoryIterator::DirectoryIterator(Inode* inode)
:
fInode(inode)
{
TRACE("DirectoryIterator::DirectoryIterator() \n");
}
int DirectoryIterator::countDir = 0;
DirectoryIterator::~DirectoryIterator()
{
}
status_t
DirectoryIterator::InitCheck()
{
return B_OK;
}
status_t
DirectoryIterator::Lookup(const char* name, size_t length, ino_t* _id)
{
int count = 0;
if (strcmp(name, ".") == 0) {
*_id = fInode->ID();
return B_OK;
} else if (strcmp(name, "..") == 0) {
if (fInode->ID() == 1)
*_id = fInode->ID();
/* else
*_id = fInode->Parent();*/
}
while(_GetNext(name, &length, _id, count) != B_OK) {
count++;
}
return B_OK;
}
status_t
DirectoryIterator::GetNext(char* name, size_t* _nameLength, ino_t* _id)
{
TRACE("In GetNext function\n");
int64_t offset = fInode->GetBlockPointer() * MINBSIZE;
dir direct;
dir_info direct_info;
int fd = fInode->GetVolume()->Device();
if (read_pos(fd, offset, &direct_info,
sizeof(dir_info)) != sizeof(dir_info)) {
return B_BAD_DATA;
}
offset = offset + sizeof(dir_info) + 16 * countDir;
if (read_pos(fd, offset, &direct, sizeof(dir)) != sizeof(dir)) {
return B_BAD_DATA;
}
if (direct.next_ino != 0) {
strlcpy(name, direct.name, sizeof(name));
*_id = direct.next_ino;
*_nameLength = direct.namlen;
countDir++;
return B_OK;
}
countDir = 0;
return B_ENTRY_NOT_FOUND;
}
status_t
DirectoryIterator::_GetNext(const char* name, size_t* _nameLength,
ino_t* _id, int count)
{
TRACE("In GetNext function\n");
int64_t offset = fInode->GetBlockPointer() * MINBSIZE;
dir direct;
dir_info direct_info;
int fd = fInode->GetVolume()->Device();
if (read_pos(fd, offset, &direct_info,
sizeof(dir_info)) != sizeof(dir_info)) {
return B_BAD_DATA;
}
if(strcmp(name, "..") == 0)
{
*_id = direct_info.dotdot_ino;
return B_OK;
}
offset = offset + sizeof(dir_info) + (16 * count);
if (read_pos(fd, offset, &direct, sizeof(dir)) != sizeof(dir)) {
return B_BAD_DATA;
}
char getname;
strlcpy(&getname, direct.name, sizeof(name));
if(strcmp(name, &getname) == 0) {
*_id = direct.next_ino;
return B_OK;
}
else {
return B_ENTRY_NOT_FOUND;
}
}

View File

@ -0,0 +1,66 @@
/*
* Copyright 2020 Suhel Mehta, mehtasuhel@gmail.com
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef DIRECTORYITERATOR_H
#define DIRECTORYITERATOR_H
#include "ufs2.h"
class Inode;
#define MAXNAMELEN 255
struct dir {
u_int32_t next_ino;
u_int16_t reclen;
u_int8_t type;
u_int8_t namlen;
char name[MAXNAMELEN + 1];
};
struct dir_info {
u_int32_t dot_ino;
int16_t dot_reclen;
u_int8_t dot_type;
u_int8_t dot_namelen;
char dot_name[4];
u_int32_t dotdot_ino;
int16_t dotdot_reclen;
u_int8_t dotdot_type;
u_int8_t dotdot_namelen;
char dotdot_name[4];
};
class DirectoryIterator {
public:
DirectoryIterator(Inode* inode);
~DirectoryIterator();
status_t InitCheck();
status_t Lookup(const char* name, size_t length,
ino_t* id);
status_t GetNext(char* name, size_t* _nameLength,
ino_t* _id);
status_t _GetNext(const char* name, size_t* _nameLength,
ino_t* _id, int count);
dir* DirectContent() { return direct; }
dir_info* DirectInfo() { return direct_info; }
static int countDir;
private:
int64 fOffset;
cluster_t fCluster;
Inode* fInode;
dir* direct;
dir_info* direct_info;
};
#endif // DIRECTORYITERATOR_H

View File

@ -13,6 +13,7 @@
#endif
#define ERROR(x...) dprintf("\33[34mufs2:\33[0m " x)
Inode::Inode(Volume* volume, ino_t id)
:
fVolume(volume),
@ -29,6 +30,16 @@ Inode::Inode(Volume* volume, ino_t id)
fMap = file_map_create(fVolume->ID(), ID(), Size());
}
}
int fd = fVolume->Device();
ufs2_super_block* superblock = (ufs2_super_block* )&fVolume->SuperBlock();
int64_t fs_block = ino_to_fsba(superblock, id);
int64_t offset_in_block = ino_to_fsbo(superblock, id);
int64_t offset = fs_block * MINBSIZE + offset_in_block * 256;
if (read_pos(fd, offset, (void*)&fNode, sizeof(fNode)) != sizeof(fNode))
ERROR("Inode::Inode(): IO Error\n");
}

View File

@ -118,6 +118,9 @@ class Inode {
Volume* GetVolume() const { return fVolume; }
int64_t GetBlockPointer() { return fNode.directBlkPtr1; }
ino_t Parent();
// status_t FindBlock(off_t logical, off_t& physical,
// off_t* _length = NULL);
// status_t ReadAt(off_t pos, uint8* buffer, size_t* length);
@ -140,7 +143,6 @@ private:
::Volume* fVolume;
ino_t fID;
void* fCache;
bool fHasNanoTime;
void* fMap;
status_t fInitStatus;
ufs2_inode fNode;

View File

@ -19,6 +19,7 @@ DEFINES += DEBUG_APP="\\\"ufs2\\\"" ;
local ufs2Sources =
DeviceOpener.cpp
DirectoryIterator.cpp
Inode.cpp
Volume.cpp
kernel_interface.cpp

View File

@ -111,14 +111,10 @@ Volume::Mount(const char *deviceName, uint32 flags)
TRACE("Valid super block\n");
status = get_vnode(fFSVolume, UFS2_ROOT, (void**) &fRootNode);
if (status != B_OK) {
ERROR("could not create root node: get_vnode() failed! %d\n",status);
return status;
}
fRootNode = new(std::nothrow) Inode(this, UFS2_ROOT);
status = publish_vnode(fFSVolume, UFS2_ROOT, (void*)fRootNode,
status = publish_vnode(this->FSVolume(), UFS2_ROOT, (void*)fRootNode,
&gufs2VnodeOps, fRootNode->Mode(), 0);
opener.Keep();
return B_OK;

View File

@ -32,6 +32,7 @@ class Volume {
{ return (fFlags & VOLUME_READ_ONLY) != 0; }
const char* Name() const;
fs_volume* FSVolume() const { return fFSVolume; }
int Device() const { return fDevice; }
dev_t ID() const
{ return fFSVolume ? fFSVolume->id : -1; }
ufs2_super_block& SuperBlock() { return fSuperBlock; }

View File

@ -4,11 +4,11 @@
*/
#include "DirectoryIterator.h"
#include "Inode.h"
#include "system_dependencies.h"
#include "ufs2.h"
#include "Volume.h"
#include "Inode.h"
#define TRACE_UFS2
#ifdef TRACE_UFS2
@ -196,7 +196,19 @@ static status_t
ufs2_lookup(fs_volume *_volume, fs_vnode *_directory, const char *name,
ino_t *_vnodeID)
{
return B_NOT_SUPPORTED;
TRACE("UFS2_LOOKUP: %p (%s)\n", name, name);
Volume* volume = (Volume*)_volume->private_volume;
Inode* directory = (Inode*)_directory->private_node;
status_t status = DirectoryIterator(directory).Lookup(name, strlen(name),
(ino_t*)_vnodeID);
if (status != B_OK)
return status;
status = get_vnode(volume->FSVolume(), *_vnodeID, NULL);
TRACE("get_vnode status: %s\n", strerror(status));
return status;
}
@ -215,6 +227,7 @@ ufs2_read_stat(fs_volume *_volume, fs_vnode *_node, struct stat *stat)
Inode* inode = (Inode*)_node->private_node;
stat->st_dev = inode->GetVolume()->ID();
stat->st_ino = inode->ID();
TRACE("stat->st_ino %ld\n",stat->st_ino);
// TODO handle hardlinks which will have nlink > 1. Maybe linkCount in inode
// structure may help?
stat->st_nlink = 1;
@ -226,7 +239,7 @@ ufs2_read_stat(fs_volume *_volume, fs_vnode *_node, struct stat *stat)
stat->st_type = 0;
inode->GetAccessTime(stat->st_atim);
/* inode->GetModificationTime(stat->st_mtim);*/
inode->GetModificationTime(stat->st_mtim);
inode->GetChangeTime(stat->st_ctim);
inode->GetCreationTime(stat->st_crtim);
@ -269,7 +282,8 @@ ufs2_free_cookie(fs_volume *_volume, fs_vnode *_node, void *_cookie)
static status_t
ufs2_access(fs_volume *_volume, fs_vnode *_node, int accessMode)
{
return B_NOT_SUPPORTED;
TRACE("In access\n");
return B_OK;
}
@ -308,7 +322,17 @@ ufs2_remove_dir(fs_volume *_volume, fs_vnode *_directory, const char *name)
static status_t
ufs2_open_dir(fs_volume * /*_volume*/, fs_vnode *_node, void **_cookie)
{
return B_NOT_SUPPORTED;
Inode* inode = (Inode*)_node->private_node;
if (!inode->IsDirectory())
return B_NOT_A_DIRECTORY;
DirectoryIterator* iterator = new(std::nothrow) DirectoryIterator(inode);
if (iterator == NULL)
return B_NO_MEMORY;
*_cookie = iterator;
return B_OK;
}
@ -316,7 +340,40 @@ static status_t
ufs2_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie,
struct dirent *dirent, size_t bufferSize, uint32 *_num)
{
return B_NOT_SUPPORTED;
TRACE("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;
ino_t iNodeNo;
status_t status = iterator->GetNext(dirent->d_name, &length, &iNodeNo);
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 = iNodeNo;
dirent->d_reclen = sizeof(dirent) + length;
bufferSize -= dirent->d_reclen;
dirent = (struct dirent*)((uint8*)dirent + dirent->d_reclen);
count++;
}
*_num = count;
TRACE("count is %d\n", count);
return B_OK;
}

View File

@ -37,6 +37,9 @@
#include "system_dependencies.h"
typedef uint32 cluster_t;
typedef uint64_t ufs2_daddr_t;
#define SBLOCK_FLOPPY 0
#define SBLOCK_UFS1 8192
#define SBLOCK_UFS2 65536

View File

@ -40,6 +40,7 @@ UseHeaders [ FDirName $(HAIKU_TOP) src tools fs_shell ] ;
local ufs2Source =
DeviceOpener.cpp
DirectoryIterator.cpp
Inode.cpp
Volume.cpp
kernel_interface.cpp