xref: /haiku/src/add-ons/kernel/file_systems/xfs/Directory.cpp (revision 4a55cc230cf7566cadcbb23b1928eefff8aea9a2)
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 		if (fLeafDir->IsLeafType())
58 			return fLeafDir->Init();
59 		delete fLeafDir;
60 		fLeafDir = NULL;
61 
62 		fNodeDir = new(std::nothrow) NodeDirectory(fInode);
63 		if (fNodeDir == NULL)
64 			return B_NO_MEMORY;
65 		if (fNodeDir->IsNodeType())
66 			return fNodeDir->Init();
67 		delete fNodeDir;
68 		fNodeDir = NULL;
69 	}
70 
71 	/* Return B_OK so even if the shortform directory has an extent directory
72 	 * we can atleast still list the shortform directory
73 	 */
74 	if (fInode->Format() == XFS_DINODE_FMT_BTREE) {
75 		TRACE("Iterator:Init(): B+TREE");
76 		fTreeDir = new(std::nothrow) TreeDirectory(fInode);
77 		if (fTreeDir == NULL)
78 			return B_NO_MEMORY;
79 		return fTreeDir->InitCheck();
80 	}
81 
82 	return B_BAD_VALUE;
83 }
84 
85 
86 status_t
87 DirectoryIterator::GetNext(char* name, size_t* length, xfs_ino_t* ino)
88 {
89 	status_t status;
90 	if (fInode->Format() == XFS_DINODE_FMT_LOCAL) {
91 		TRACE("Iterator:GetNext: LOCAL");
92 		status = fShortDir->GetNext(name, length, ino);
93 		return status;
94 	}
95 
96 	if (fInode->Format() == XFS_DINODE_FMT_EXTENTS) {
97 		TRACE("Iterator:GetNext: EXTENTS");
98 		if (fExtentDir != NULL)
99 			status = fExtentDir->GetNext(name, length, ino);
100 		else if (fLeafDir != NULL)
101 			status = fLeafDir->GetNext(name, length, ino);
102 		else
103 			status = fNodeDir->GetNext(name, length, ino);
104 		return status;
105 	}
106 
107 	if (fInode->Format() == XFS_DINODE_FMT_BTREE) {
108 		TRACE("Iterator:GetNext: B+TREE");
109 		if (fTreeDir != NULL)
110 			return status = fTreeDir->GetNext(name, length, ino);
111 		return B_NOT_SUPPORTED;
112 	}
113 
114 	// Only reaches here if Inode is a device or is corrupt.
115 	return B_BAD_VALUE;
116 }
117 
118 
119 status_t
120 DirectoryIterator::Lookup(const char* name, size_t length, xfs_ino_t* ino)
121 {
122 	status_t status;
123 	if (fInode->Format() == XFS_DINODE_FMT_LOCAL) {
124 		TRACE("Iterator:Lookup: LOCAL\n");
125 		status = fShortDir->Lookup(name, length, ino);
126 		return status;
127 	}
128 
129 	//TODO: Reading from extent based dirs
130 	if (fInode->Format() == XFS_DINODE_FMT_EXTENTS) {
131 		TRACE("Iterator:Lookup: EXTENTS\n");
132 		if (fExtentDir != NULL)
133 			status = fExtentDir->Lookup(name, length, ino);
134 		else if (fLeafDir != NULL)
135 			status = fLeafDir->Lookup(name, length, ino);
136 		else
137 			status = fNodeDir->Lookup(name, length, ino);
138 		return status;
139 	}
140 
141 	//TODO: Reading from B+Tree based dirs
142 	if (fInode->Format() == XFS_DINODE_FMT_BTREE) {
143 		TRACE("Iterator:Lookup: B+TREE\n");
144 		if (fTreeDir != NULL)
145 			return fTreeDir->Lookup(name, length, ino);
146 		return B_NOT_SUPPORTED;
147 	}
148 
149 	return B_BAD_VALUE;
150 }
151