xref: /haiku/src/add-ons/kernel/file_systems/xfs/Directory.cpp (revision ae5abb58266fba43b3479995388d13e92013e08f)
1 /*
2  * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com
3  * All rights reserved. Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "Directory.h"
8 
9 
10 DirectoryIterator::DirectoryIterator(Inode* inode)
11 	:
12 	fInode(inode),
13 	fShortDir(NULL),
14 	fExtentDir(NULL),
15 	fLeafDir(NULL),
16 	fNodeDir(NULL),
17 	fTreeDir(NULL)
18 {
19 }
20 
21 
22 DirectoryIterator::~DirectoryIterator()
23 {
24 	delete fShortDir;
25 	delete fLeafDir;
26 	delete fExtentDir;
27 	delete fNodeDir;
28 	delete fTreeDir;
29 }
30 
31 
32 status_t
33 DirectoryIterator::Init()
34 {
35 	if (fInode->Format() == XFS_DINODE_FMT_LOCAL)
36 	{
37 		TRACE("Iterator:Init: LOCAL");
38 		fShortDir = new(std::nothrow) ShortDirectory(fInode);
39 		if (fShortDir == NULL)
40 			return B_NO_MEMORY;
41 		return B_OK;
42 	}
43 	if (fInode->Format() == XFS_DINODE_FMT_EXTENTS) {
44 		TRACE("Iterator:Init: EXTENTS");
45 		fExtentDir = new(std::nothrow) Extent(fInode);
46 		if (fExtentDir == NULL)
47 			return B_NO_MEMORY;
48 		if (fExtentDir->IsBlockType())
49 			return fExtentDir->Init();
50 
51 		delete fExtentDir;
52 		fExtentDir = NULL;
53 
54 		fLeafDir = new(std::nothrow) LeafDirectory(fInode);
55 		if (fLeafDir == NULL)
56 			return B_NO_MEMORY;
57 		status_t status = fLeafDir->Init();
58 		if (status != B_OK)
59 			return status;
60 		if (fLeafDir->IsLeafType())
61 			return B_OK;
62 		delete fLeafDir;
63 		fLeafDir = NULL;
64 
65 		fNodeDir = new(std::nothrow) NodeDirectory(fInode);
66 		if (fNodeDir == NULL)
67 			return B_NO_MEMORY;
68 		status = fNodeDir->Init();
69 		if (status != B_OK)
70 			return status;
71 		if (fNodeDir->IsNodeType())
72 			return B_OK;
73 		delete fNodeDir;
74 		fNodeDir = NULL;
75 	}
76 
77 	/* Return B_OK so even if the shortform directory has an extent directory
78 	 * we can atleast still list the shortform directory
79 	 */
80 	if (fInode->Format() == XFS_DINODE_FMT_BTREE) {
81 		TRACE("Iterator:Init(): B+TREE");
82 		fTreeDir = new(std::nothrow) TreeDirectory(fInode);
83 		if (fTreeDir == NULL)
84 			return B_NO_MEMORY;
85 		return fTreeDir->InitCheck();
86 	}
87 
88 	return B_BAD_VALUE;
89 }
90 
91 
92 status_t
93 DirectoryIterator::GetNext(char* name, size_t* length, xfs_ino_t* ino)
94 {
95 	status_t status;
96 	if (fInode->Format() == XFS_DINODE_FMT_LOCAL) {
97 		TRACE("Iterator:GetNext: LOCAL");
98 		status = fShortDir->GetNext(name, length, ino);
99 		return status;
100 	}
101 
102 	if (fInode->Format() == XFS_DINODE_FMT_EXTENTS) {
103 		TRACE("Iterator:GetNext: EXTENTS");
104 		if (fExtentDir != NULL)
105 			status = fExtentDir->GetNext(name, length, ino);
106 		else if (fLeafDir != NULL)
107 			status = fLeafDir->GetNext(name, length, ino);
108 		else
109 			status = fNodeDir->GetNext(name, length, ino);
110 		return status;
111 	}
112 
113 	if (fInode->Format() == XFS_DINODE_FMT_BTREE) {
114 		TRACE("Iterator:GetNext: B+TREE");
115 		if (fTreeDir != NULL)
116 			return status = fTreeDir->GetNext(name, length, ino);
117 		return B_NOT_SUPPORTED;
118 	}
119 
120 	// Only reaches here if Inode is a device or is corrupt.
121 	return B_BAD_VALUE;
122 }
123 
124 
125 status_t
126 DirectoryIterator::Lookup(const char* name, size_t length, xfs_ino_t* ino)
127 {
128 	status_t status;
129 	if (fInode->Format() == XFS_DINODE_FMT_LOCAL) {
130 		TRACE("Iterator:Lookup: LOCAL\n");
131 		status = fShortDir->Lookup(name, length, ino);
132 		return status;
133 	}
134 
135 	//TODO: Reading from extent based dirs
136 	if (fInode->Format() == XFS_DINODE_FMT_EXTENTS) {
137 		TRACE("Iterator:Lookup: EXTENTS\n");
138 		if (fExtentDir != NULL)
139 			status = fExtentDir->Lookup(name, length, ino);
140 		else if (fLeafDir != NULL)
141 			status = fLeafDir->Lookup(name, length, ino);
142 		else
143 			status = fNodeDir->Lookup(name, length, ino);
144 		return status;
145 	}
146 
147 	//TODO: Reading from B+Tree based dirs
148 	if (fInode->Format() == XFS_DINODE_FMT_BTREE) {
149 		TRACE("Iterator:Lookup: B+TREE\n");
150 		if (fTreeDir != NULL)
151 			return fTreeDir->Lookup(name, length, ino);
152 		return B_NOT_SUPPORTED;
153 	}
154 
155 	return B_BAD_VALUE;
156 }
157