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