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