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 "ShortDirectory.h" 8 9 10 ShortDirectory::ShortDirectory(Inode* inode) 11 : 12 fInode(inode), 13 fTrack(0) 14 { 15 16 fHeader = (ShortFormHeader*)(DIR_DFORK_PTR(fInode->Buffer())); 17 } 18 19 20 ShortDirectory::~ShortDirectory() 21 { 22 } 23 24 25 bool 26 ShortDirectory::HasFileTypeField() 27 { 28 if (fInode->GetVolume()->SuperBlockFeatures2() & XFS_SB_VERSION2_FTYPE) 29 return true; 30 else 31 return false; 32 } 33 34 35 uint8 36 ShortDirectory::GetFileType(ShortFormEntry* entry) 37 { 38 ASSERT(HasFileTypeField() == true); 39 return entry->name[entry->namelen]; 40 } 41 42 43 ShortFormEntry* 44 ShortDirectory::FirstEntry() 45 { 46 return (ShortFormEntry*) ((char*) fHeader + HeaderSize()); 47 } 48 49 50 size_t 51 ShortDirectory::HeaderSize() 52 { 53 if (fHeader->i8count) 54 return sizeof(ShortFormHeader); 55 else 56 return sizeof(ShortFormHeader) - sizeof(uint32); 57 } 58 59 60 xfs_ino_t 61 ShortDirectory::GetIno(ShortFormInodeUnion* inum) 62 { 63 if (fHeader->i8count) 64 return B_BENDIAN_TO_HOST_INT64(inum->i8); 65 else 66 return B_BENDIAN_TO_HOST_INT32(inum->i4); 67 } 68 69 70 xfs_ino_t 71 ShortDirectory::GetEntryIno(ShortFormEntry* entry) 72 { 73 if (HasFileTypeField()) 74 return GetIno((ShortFormInodeUnion*)(entry->name 75 + entry->namelen + sizeof(uint8))); 76 else 77 return GetIno((ShortFormInodeUnion*)(entry->name + entry->namelen)); 78 } 79 80 81 size_t 82 ShortDirectory::EntrySize(int namelen) 83 { 84 return sizeof(ShortFormEntry) + namelen 85 + (HasFileTypeField()? sizeof(uint8) : 0) 86 + (fHeader->i8count? sizeof(uint64):sizeof(uint32)); 87 } 88 89 90 status_t 91 ShortDirectory::Lookup(const char* name, size_t length, xfs_ino_t* ino) 92 { 93 TRACE("ShortDirectory::Lookup\n"); 94 95 if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { 96 xfs_ino_t rootIno = fInode->GetVolume()->Root(); 97 if (strcmp(name, ".") == 0 || (rootIno == fInode->ID())) { 98 *ino = fInode->ID(); 99 TRACE("ShortDirectory:Lookup: name: \".\" ino: (%d)\n", *ino); 100 return B_OK; 101 } 102 *ino = GetIno(&fHeader->parent); 103 TRACE("Parent: (%d)\n", *ino); 104 return B_OK; 105 } 106 107 ShortFormEntry* entry = FirstEntry(); 108 TRACE("Length of first entry: (%d),offset of first entry:" 109 "(%d)\n", entry->namelen, B_BENDIAN_TO_HOST_INT16(entry->offset.i)); 110 111 int status; 112 for (int i = 0; i < fHeader->count; i++) { 113 status = strncmp(name, (char*)entry->name, entry->namelen); 114 if (status == 0) { 115 *ino = GetEntryIno(entry); 116 return B_OK; 117 } 118 entry = (ShortFormEntry*) 119 ((char*) entry + EntrySize(entry->namelen)); 120 } 121 122 return B_ENTRY_NOT_FOUND; 123 } 124 125 126 status_t 127 ShortDirectory::GetNext(char* name, size_t* length, xfs_ino_t* ino) 128 { 129 if (fTrack == 0) { 130 // Return '.' 131 if (*length < 2) 132 return B_BUFFER_OVERFLOW; 133 *length = 2; 134 strlcpy(name, ".", *length + 1); 135 *ino = fInode->ID(); 136 fTrack = 1; 137 TRACE("ShortDirectory:GetNext: name: \".\" ino: (%d)\n", *ino); 138 return B_OK; 139 } 140 if (fTrack == 1) { 141 // Return '..' 142 if (*length < 3) 143 return B_BUFFER_OVERFLOW; 144 *length = 3; 145 strlcpy(name, "..", *length + 1); 146 *ino = GetIno(&fHeader->parent); 147 fTrack = 2; 148 TRACE("ShortDirectory:GetNext: name: \"..\" ino: (%d)\n", *ino); 149 return B_OK; 150 } 151 152 ShortFormEntry* entry = FirstEntry(); 153 TRACE("Length of first entry: (%d), offset of first entry:" 154 "(%d)\n", entry->namelen, B_BENDIAN_TO_HOST_INT16(entry->offset.i)); 155 156 for (int i = 0; i < fHeader->count; i++) { 157 uint16 curOffset = B_BENDIAN_TO_HOST_INT16(entry->offset.i); 158 if (curOffset > fLastEntryOffset) { 159 160 if (entry->namelen > *length) 161 return B_BUFFER_OVERFLOW; 162 163 fLastEntryOffset = curOffset; 164 memcpy(name, entry->name, entry->namelen); 165 name[entry->namelen] = '\0'; 166 *length = entry->namelen + 1; 167 *ino = GetEntryIno(entry); 168 169 TRACE("Entry found. Name: (%s), Length: (%ld),ino: (%ld)\n", name, 170 *length, *ino); 171 return B_OK; 172 } 173 entry = (ShortFormEntry*)((char*)entry + EntrySize(entry->namelen)); 174 } 175 176 return B_ENTRY_NOT_FOUND; 177 } 178