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