1 // DirItem.h 2 // 3 // Copyright (c) 2003, Ingo Weinhold (bonefish@cs.tu-berlin.de) 4 // 5 // This program is free software; you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation; either version 2 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with this program; if not, write to the Free Software 17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 // 19 // You can alternatively use *this file* under the terms of the the MIT 20 // license included in this package. 21 22 #ifndef DIR_ITEM_H 23 #define DIR_ITEM_H 24 25 #include <string.h> 26 27 #include "Block.h" 28 #include "Debug.h" 29 #include "endianess.h" 30 #include "Item.h" 31 #include "String.h" 32 33 // DirEntry 34 /*! 35 \class DirEntry 36 \brief Represents the on-disk structure for a directory entry. 37 38 A DirEntry has an offset identifying it uniquely in the list of 39 entries, and it knows about the dir and object ID of the actual 40 entry. Note, that the dir ID is note necessarily the object ID of 41 the parent directory! The DirEntry also knows the relative 42 location of its name in the dir item. 43 */ 44 class DirEntry : private reiserfs_de_head { 45 public: 46 DirEntry() {} 47 48 uint32 GetOffset() const { return le2h(deh_offset); } 49 uint32 GetDirID() const { return le2h(deh_dir_id); } 50 uint32 GetObjectID() const { return le2h(deh_objectid); } 51 uint16 GetLocation() const { return le2h(deh_location); } 52 uint16 GetState() const { return le2h(deh_state); } 53 54 bool IsVisible() const { return (GetState() & (1 << DEH_Visible)); } 55 bool IsHidden() const { return !IsVisible(); } 56 57 void Dump() 58 { 59 PRINT((" dir entry\n")); 60 PRINT((" offset: %lu\n", GetOffset())); 61 PRINT((" dir ID: %lu\n", GetDirID())); 62 PRINT((" object ID: %lu\n", GetObjectID())); 63 PRINT((" location: %hu\n", GetLocation())); 64 PRINT((" state: %hx\n", GetState())); 65 } 66 } _PACKED; 67 68 // DirItem 69 /*! 70 \class DirItem 71 \brief Provides access to the on-disk dir item structure. 72 73 A dir item consists of an array of DirEntrys and the names of these 74 entries. Note, that in general the names are not null terminated. 75 EntryNameAt() returns the length of the name. 76 */ 77 class DirItem : public Item { 78 public: 79 DirItem() : Item() {} 80 DirItem(LeafNode *node, ItemHeader *header) 81 : Item(node, header) {} 82 83 DirEntry *EntryAt(int32 index) const 84 { 85 DirEntry *entry = NULL; 86 if (index >= 0 && index < GetEntryCount()) 87 entry = (DirEntry*)GetData() + index; 88 return entry; 89 } 90 91 const char *EntryNameAt(int32 index, size_t *nameLen = NULL) const 92 { 93 const char *name = NULL; 94 if (DirEntry *entry = EntryAt(index)) { 95 // check the name location 96 uint32 location = entry->GetLocation(); 97 if (location < GetEntryNameSpaceOffset() || location > GetLen()) { 98 // bad location 99 FATAL(("WARNING: bad dir entry %" B_PRId32 " " 100 "in item %" B_PRId32 " on node %" B_PRIu64 ": " 101 "the entry's name location is %" B_PRIu32 ", " 102 "which is outside the entry name space " 103 "(%" B_PRIu32 " - %u)!\n", 104 index, GetIndex(), fNode->GetNumber(), location, 105 GetEntryNameSpaceOffset(), GetLen())); 106 } else { 107 // get the name 108 name = (char*)((uint8*)GetData() + location); 109 } 110 if (name && nameLen) { 111 size_t maxLength = 0; 112 if (index == 0) 113 maxLength = fHeader->GetLen() - entry->GetLocation(); 114 else { 115 maxLength = EntryAt(index -1)->GetLocation() 116 - entry->GetLocation(); 117 } 118 *nameLen = strnlen(name, maxLength); 119 } 120 } 121 return name; 122 } 123 124 status_t GetEntryNameAt(int32 index, char *buffer, size_t bufferSize) 125 { 126 status_t error = (buffer && index >= 0 && index < GetEntryCount() 127 ? B_OK : B_BAD_VALUE); 128 if (error == B_OK) { 129 size_t nameLen = 0; 130 const char *name = EntryNameAt(index, &nameLen); 131 if (name && nameLen > 0) { 132 if (nameLen + 1 <= bufferSize) { 133 strncpy(buffer, name, nameLen); 134 buffer[nameLen] = 0; 135 } else // buffer too small 136 error = B_BAD_VALUE; 137 } else // bad name 138 error = B_BAD_DATA; 139 } 140 return error; 141 } 142 143 int32 IndexOfName(const char *name) const 144 { 145 if (name == NULL) 146 return -1; 147 148 int32 count = GetEntryCount(); 149 size_t len = strlen(name); 150 for (int32 i = 0; i < count; i++) { 151 size_t nameLen = 0; 152 const char *itemName = EntryNameAt(i, &nameLen); 153 if (nameLen == len && !strncmp(name, itemName, len)) { 154 return i; 155 } 156 } 157 return -1; 158 } 159 160 status_t Check() const 161 { 162 // the base class version checks the location of the item 163 status_t error = Item::Check(); 164 // check whether the entry headers can possibly fit into the item 165 if (error == B_OK) { 166 if (GetEntryNameSpaceOffset() > GetLen()) { 167 FATAL(("WARNING: bad dir item %" B_PRId32 " " 168 "on node %" B_PRIu64 ": the item has " 169 "len %u and can thus impossibly contain %u entry " 170 "headers!\n", GetIndex(), fNode->GetNumber(), GetLen(), 171 GetEntryCount())); 172 return B_BAD_DATA; 173 } 174 } 175 return error; 176 } 177 178 private: 179 uint32 GetEntryNameSpaceOffset() const 180 { return GetEntryCount() * sizeof(DirEntry); } 181 }; 182 183 #endif // DIR_ITEM_H 184