BTRFS: Node now holding Volume instead of cache to retrieve more values
[haiku.git] / src / add-ons / kernel / file_systems / btrfs / DirectoryIterator.cpp
blob4f9a1b793b60bea73ce093e436d1c76b6c7bb744
1 /*
2 * Copyright 2011-2013, Jérôme Duval, korli@users.berlios.de.
3 * This file may be used under the terms of the MIT License.
4 */
7 #include "DirectoryIterator.h"
8 #include "CRCTable.h"
11 //#define TRACE_BTRFS
12 #ifdef TRACE_BTRFS
13 # define TRACE(x...) dprintf("\33[34mbtrfs:\33[0m " x)
14 #else
15 # define TRACE(x...) ;
16 #endif
17 # define ERROR(x...) dprintf("\33[34mbtrfs:\33[0m " x)
20 DirectoryIterator::DirectoryIterator(Inode* inode)
22 fOffset(0),
23 fInode(inode),
24 fIterator(NULL)
26 btrfs_key key;
27 key.SetType(BTRFS_KEY_TYPE_DIR_INDEX);
28 key.SetObjectID(inode->ID());
29 fIterator = new(std::nothrow) TreeIterator(inode->GetVolume()->FSTree(),
30 key);
34 DirectoryIterator::~DirectoryIterator()
36 if (fIterator != NULL)
37 delete fIterator;
41 status_t
42 DirectoryIterator::InitCheck()
44 return fIterator != NULL ? B_OK : B_NO_MEMORY;
48 status_t
49 DirectoryIterator::GetNext(char* name, size_t* _nameLength, ino_t* _id)
51 if (fOffset == 0) {
52 if (*_nameLength < 3)
53 return B_BUFFER_OVERFLOW;
54 *_nameLength = 2;
55 strlcpy(name, "..", *_nameLength + 1);
56 *_id = fInode->ID();
57 fOffset = 1;
58 return B_OK;
59 } else if (fOffset == 1) {
60 if (*_nameLength < 2)
61 return B_BUFFER_OVERFLOW;
62 *_nameLength = 1;
63 strlcpy(name, ".", *_nameLength + 1);
64 fOffset = 2;
65 if (fInode->ID() == BTRFS_FIRST_SUBVOLUME) {
66 *_id = fInode->ID();
67 return B_OK;
69 return fInode->FindParent(_id);
72 btrfs_key key;
73 btrfs_dir_entry* entries;
74 uint32 entries_length;
75 status_t status = fIterator->GetNextEntry(key, (void**)&entries,
76 &entries_length);
77 if (status != B_OK)
78 return status;
80 btrfs_dir_entry* entry = entries;
81 uint16 current = 0;
82 while (current < entries_length) {
83 current += entry->Length();
84 break;
85 // TODO there could be several entries with the same name hash
86 entry = (btrfs_dir_entry*)((uint8*)entry + entry->Length());
89 size_t length = entry->NameLength();
91 TRACE("DirectoryIterator::GetNext() entries_length %ld name_length %d\n",
92 entries_length, entry->NameLength());
94 if (length + 1 > *_nameLength) {
95 free(entries);
96 return B_BUFFER_OVERFLOW;
99 memcpy(name, entry + 1, length);
100 name[length] = '\0';
101 *_nameLength = length;
102 *_id = entry->InodeID();
103 free(entries);
105 return B_OK;
109 status_t
110 DirectoryIterator::Lookup(const char* name, size_t nameLength, ino_t* _id)
112 if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
113 if (strcmp(name, ".") == 0
114 || fInode->ID() == BTRFS_FIRST_SUBVOLUME) {
115 *_id = fInode->ID();
116 return B_OK;
118 return fInode->FindParent(_id);
121 uint32 hash = calculate_crc((uint32)~1, (uint8*)name, nameLength);
122 btrfs_key key;
123 key.SetType(BTRFS_KEY_TYPE_DIR_ITEM);
124 key.SetObjectID(fInode->ID());
125 key.SetOffset(hash);
127 btrfs_dir_entry* entries;
128 uint32 length;
129 status_t status = fInode->GetVolume()->FSTree()->FindExact(key,
130 (void**)&entries, &length);
131 if (status != B_OK) {
132 TRACE("DirectoryIterator::Lookup(): Couldn't find entry with hash %" B_PRIu32
133 " \"%s\"\n", hash, name);
134 return status;
137 btrfs_dir_entry* entry = entries;
138 uint16 current = 0;
139 while (current < length) {
140 current += entry->Length();
141 break;
142 // TODO there could be several entries with the same name hash
143 entry = (btrfs_dir_entry*)((uint8*)entry + entry->Length());
146 TRACE("DirectoryIterator::Lookup() entries_length %ld name_length %d\n",
147 length, entry->NameLength());
149 *_id = entry->InodeID();
150 free(entries);
152 return B_OK;
156 status_t
157 DirectoryIterator::Rewind()
159 fIterator->Rewind();
160 fOffset = BTREE_BEGIN;
161 return B_OK;