#ifndef DIR_ITEM_H
#define DIR_ITEM_H
#include <string.h>
#include "Block.h"
#include "Debug.h"
#include "endianess.h"
#include "Item.h"
#include "String.h"
class DirEntry : private reiserfs_de_head {
public:
DirEntry() {}
uint32 GetOffset() const { return le2h(deh_offset); }
uint32 GetDirID() const { return le2h(deh_dir_id); }
uint32 GetObjectID() const { return le2h(deh_objectid); }
uint16 GetLocation() const { return le2h(deh_location); }
uint16 GetState() const { return le2h(deh_state); }
bool IsVisible() const { return (GetState() & (1 << DEH_Visible)); }
bool IsHidden() const { return !IsVisible(); }
void Dump()
{
PRINT((" dir entry\n"));
PRINT((" offset: %" B_PRIu32 "\n", GetOffset()));
PRINT((" dir ID: %" B_PRIu32 "\n", GetDirID()));
PRINT((" object ID: %" B_PRIu32 "\n", GetObjectID()));
PRINT((" location: %hu\n", GetLocation()));
PRINT((" state: %hx\n", GetState()));
}
} _PACKED;
class DirItem : public Item {
public:
DirItem() : Item() {}
DirItem(LeafNode *node, ItemHeader *header)
: Item(node, header) {}
DirEntry *EntryAt(int32 index) const
{
DirEntry *entry = NULL;
if (index >= 0 && index < GetEntryCount())
entry = (DirEntry*)GetData() + index;
return entry;
}
const char *EntryNameAt(int32 index, size_t *nameLen = NULL) const
{
const char *name = NULL;
if (DirEntry *entry = EntryAt(index)) {
uint32 location = entry->GetLocation();
if (location < GetEntryNameSpaceOffset() || location > GetLen()) {
FATAL(("WARNING: bad dir entry %" B_PRId32 " "
"in item %" B_PRId32 " on node %" B_PRIu64 ": "
"the entry's name location is %" B_PRIu32 ", "
"which is outside the entry name space "
"(%" B_PRIu32 " - %u)!\n",
index, GetIndex(), fNode->GetNumber(), location,
GetEntryNameSpaceOffset(), GetLen()));
} else {
name = (char*)((uint8*)GetData() + location);
}
if (name && nameLen) {
size_t maxLength = 0;
if (index == 0)
maxLength = fHeader->GetLen() - entry->GetLocation();
else {
maxLength = EntryAt(index -1)->GetLocation()
- entry->GetLocation();
}
*nameLen = strnlen(name, maxLength);
}
}
return name;
}
status_t GetEntryNameAt(int32 index, char *buffer, size_t bufferSize)
{
status_t error = (buffer && index >= 0 && index < GetEntryCount()
? B_OK : B_BAD_VALUE);
if (error == B_OK) {
size_t nameLen = 0;
const char *name = EntryNameAt(index, &nameLen);
if (name && nameLen > 0) {
if (nameLen + 1 <= bufferSize) {
strncpy(buffer, name, nameLen);
buffer[nameLen] = 0;
} else
error = B_BAD_VALUE;
} else
error = B_BAD_DATA;
}
return error;
}
int32 IndexOfName(const char *name) const
{
if (name == NULL)
return -1;
int32 count = GetEntryCount();
size_t len = strlen(name);
for (int32 i = 0; i < count; i++) {
size_t nameLen = 0;
const char *itemName = EntryNameAt(i, &nameLen);
if (nameLen == len && !strncmp(name, itemName, len)) {
return i;
}
}
return -1;
}
status_t Check() const
{
status_t error = Item::Check();
if (error == B_OK) {
if (GetEntryNameSpaceOffset() > GetLen()) {
FATAL(("WARNING: bad dir item %" B_PRId32 " "
"on node %" B_PRIu64 ": the item has "
"len %u and can thus impossibly contain %u entry "
"headers!\n", GetIndex(), fNode->GetNumber(), GetLen(),
GetEntryCount()));
return B_BAD_DATA;
}
}
return error;
}
private:
uint32 GetEntryNameSpaceOffset() const
{ return GetEntryCount() * sizeof(DirEntry); }
};
#endif