[haiku-commits] haiku: hrev54389 - src/add-ons/kernel/file_systems/ufs2

  • From: Adrien Destugues <pulkomandy@xxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Fri, 3 Jul 2020 15:21:40 -0400 (EDT)

hrev54389 adds 1 changeset to branch 'master'
old head: 4a230cfc6cbfb8413d9a02f81384fa4e201c23cd
new head: 239a1c3561edb27048be8730afb4f9d02d8c3cdc
overview: 
https://git.haiku-os.org/haiku/log/?qt=range&q=239a1c3561ed+%5E4a230cfc6cbf

----------------------------------------------------------------------------

239a1c3561ed: 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@xxxxxxxxx>

                                      [ Suhel Mehta <mehtasuhel@xxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev54389
Commit:      239a1c3561edb27048be8730afb4f9d02d8c3cdc
URL:         https://git.haiku-os.org/haiku/commit/?id=239a1c3561ed
Author:      Suhel Mehta <mehtasuhel@xxxxxxxxx>
Date:        Fri Jun 12 19:26:16 2020 UTC
Committer:   Adrien Destugues <pulkomandy@xxxxxxxxx>
Commit-Date: Fri Jul  3 19:21:06 2020 UTC

----------------------------------------------------------------------------

10 files changed, 282 insertions(+), 14 deletions(-)
.../file_systems/ufs2/DirectoryIterator.cpp      | 130 +++++++++++++++++++
.../kernel/file_systems/ufs2/DirectoryIterator.h |  66 ++++++++++
src/add-ons/kernel/file_systems/ufs2/Inode.cpp   |  11 ++
src/add-ons/kernel/file_systems/ufs2/Inode.h     |   4 +-
src/add-ons/kernel/file_systems/ufs2/Jamfile     |   1 +
src/add-ons/kernel/file_systems/ufs2/Volume.cpp  |   8 +-
src/add-ons/kernel/file_systems/ufs2/Volume.h    |   1 +
.../file_systems/ufs2/kernel_interface.cpp       |  71 +++++++++-
src/add-ons/kernel/file_systems/ufs2/ufs2.h      |   3 +
.../kernel/file_systems/ufs2/ufs2_shell/Jamfile  |   1 +

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/file_systems/ufs2/DirectoryIterator.cpp 
b/src/add-ons/kernel/file_systems/ufs2/DirectoryIterator.cpp
new file mode 100644
index 0000000000..36dd4d3d82
--- /dev/null
+++ b/src/add-ons/kernel/file_systems/ufs2/DirectoryIterator.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2020 Suhel Mehta, mehtasuhel@xxxxxxxxx
+ * 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;
+       }
+}
diff --git a/src/add-ons/kernel/file_systems/ufs2/DirectoryIterator.h 
b/src/add-ons/kernel/file_systems/ufs2/DirectoryIterator.h
new file mode 100644
index 0000000000..5da9f9fa0c
--- /dev/null
+++ b/src/add-ons/kernel/file_systems/ufs2/DirectoryIterator.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2020 Suhel Mehta, mehtasuhel@xxxxxxxxx
+ * 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
diff --git a/src/add-ons/kernel/file_systems/ufs2/Inode.cpp 
b/src/add-ons/kernel/file_systems/ufs2/Inode.cpp
index 7a73cbdc19..455e753d62 100644
--- a/src/add-ons/kernel/file_systems/ufs2/Inode.cpp
+++ b/src/add-ons/kernel/file_systems/ufs2/Inode.cpp
@@ -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");
+
+
 }
 
 
diff --git a/src/add-ons/kernel/file_systems/ufs2/Inode.h 
b/src/add-ons/kernel/file_systems/ufs2/Inode.h
index e1499f1f72..f76cd1a0f5 100644
--- a/src/add-ons/kernel/file_systems/ufs2/Inode.h
+++ b/src/add-ons/kernel/file_systems/ufs2/Inode.h
@@ -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;
diff --git a/src/add-ons/kernel/file_systems/ufs2/Jamfile 
b/src/add-ons/kernel/file_systems/ufs2/Jamfile
index b50e8ed08e..5b601de2bf 100644
--- a/src/add-ons/kernel/file_systems/ufs2/Jamfile
+++ b/src/add-ons/kernel/file_systems/ufs2/Jamfile
@@ -19,6 +19,7 @@ DEFINES += DEBUG_APP="\\\"ufs2\\\"" ;
 
 local ufs2Sources =
        DeviceOpener.cpp
+       DirectoryIterator.cpp
        Inode.cpp
        Volume.cpp
        kernel_interface.cpp
diff --git a/src/add-ons/kernel/file_systems/ufs2/Volume.cpp 
b/src/add-ons/kernel/file_systems/ufs2/Volume.cpp
index 1dae4b25b5..73971d4cb1 100644
--- a/src/add-ons/kernel/file_systems/ufs2/Volume.cpp
+++ b/src/add-ons/kernel/file_systems/ufs2/Volume.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;
 
diff --git a/src/add-ons/kernel/file_systems/ufs2/Volume.h 
b/src/add-ons/kernel/file_systems/ufs2/Volume.h
index 8bae234709..9defae27dd 100644
--- a/src/add-ons/kernel/file_systems/ufs2/Volume.h
+++ b/src/add-ons/kernel/file_systems/ufs2/Volume.h
@@ -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; }
diff --git a/src/add-ons/kernel/file_systems/ufs2/kernel_interface.cpp 
b/src/add-ons/kernel/file_systems/ufs2/kernel_interface.cpp
index b2f6b25331..c97855353f 100644
--- a/src/add-ons/kernel/file_systems/ufs2/kernel_interface.cpp
+++ b/src/add-ons/kernel/file_systems/ufs2/kernel_interface.cpp
@@ -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;
+
 }
 
 
diff --git a/src/add-ons/kernel/file_systems/ufs2/ufs2.h 
b/src/add-ons/kernel/file_systems/ufs2/ufs2.h
index 36f46411cf..00366f99b2 100644
--- a/src/add-ons/kernel/file_systems/ufs2/ufs2.h
+++ b/src/add-ons/kernel/file_systems/ufs2/ufs2.h
@@ -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
diff --git a/src/tests/add-ons/kernel/file_systems/ufs2/ufs2_shell/Jamfile 
b/src/tests/add-ons/kernel/file_systems/ufs2/ufs2_shell/Jamfile
index ebc59e0703..8bf460e4f5 100644
--- a/src/tests/add-ons/kernel/file_systems/ufs2/ufs2_shell/Jamfile
+++ b/src/tests/add-ons/kernel/file_systems/ufs2/ufs2_shell/Jamfile
@@ -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


Other related posts:

  • » [haiku-commits] haiku: hrev54389 - src/add-ons/kernel/file_systems/ufs2 - Adrien Destugues