xref: /haiku/src/add-ons/kernel/file_systems/reiserfs/DirItem.h (revision 68ea01249e1e2088933cb12f9c28d4e5c5d1c9ef)
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