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:
parent
4a230cfc6c
commit
239a1c3561
130
src/add-ons/kernel/file_systems/ufs2/DirectoryIterator.cpp
Normal file
130
src/add-ons/kernel/file_systems/ufs2/DirectoryIterator.cpp
Normal 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;
|
||||
}
|
||||
}
|
66
src/add-ons/kernel/file_systems/ufs2/DirectoryIterator.h
Normal file
66
src/add-ons/kernel/file_systems/ufs2/DirectoryIterator.h
Normal 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
|
@ -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");
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -19,6 +19,7 @@ DEFINES += DEBUG_APP="\\\"ufs2\\\"" ;
|
||||
|
||||
local ufs2Sources =
|
||||
DeviceOpener.cpp
|
||||
DirectoryIterator.cpp
|
||||
Inode.cpp
|
||||
Volume.cpp
|
||||
kernel_interface.cpp
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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; }
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user