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.
7 #include "DirectoryIterator.h"
13 # define TRACE(x...) dprintf("\33[34mbtrfs:\33[0m " x)
15 # define TRACE(x...) ;
17 # define ERROR(x...) dprintf("\33[34mbtrfs:\33[0m " x)
20 DirectoryIterator::DirectoryIterator(Inode
* inode
)
27 key
.SetType(BTRFS_KEY_TYPE_DIR_INDEX
);
28 key
.SetObjectID(inode
->ID());
29 fIterator
= new(std::nothrow
) TreeIterator(inode
->GetVolume()->FSTree(),
34 DirectoryIterator::~DirectoryIterator()
36 if (fIterator
!= NULL
)
42 DirectoryIterator::InitCheck()
44 return fIterator
!= NULL
? B_OK
: B_NO_MEMORY
;
49 DirectoryIterator::GetNext(char* name
, size_t* _nameLength
, ino_t
* _id
)
53 return B_BUFFER_OVERFLOW
;
55 strlcpy(name
, "..", *_nameLength
+ 1);
59 } else if (fOffset
== 1) {
61 return B_BUFFER_OVERFLOW
;
63 strlcpy(name
, ".", *_nameLength
+ 1);
65 if (fInode
->ID() == BTRFS_FIRST_SUBVOLUME
) {
69 return fInode
->FindParent(_id
);
73 btrfs_dir_entry
* entries
;
74 uint32 entries_length
;
75 status_t status
= fIterator
->GetNextEntry(key
, (void**)&entries
,
80 btrfs_dir_entry
* entry
= entries
;
82 while (current
< entries_length
) {
83 current
+= entry
->Length();
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
) {
96 return B_BUFFER_OVERFLOW
;
99 memcpy(name
, entry
+ 1, length
);
101 *_nameLength
= length
;
102 *_id
= entry
->InodeID();
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
) {
118 return fInode
->FindParent(_id
);
121 uint32 hash
= calculate_crc((uint32
)~1, (uint8
*)name
, nameLength
);
123 key
.SetType(BTRFS_KEY_TYPE_DIR_ITEM
);
124 key
.SetObjectID(fInode
->ID());
127 btrfs_dir_entry
* entries
;
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
);
137 btrfs_dir_entry
* entry
= entries
;
139 while (current
< length
) {
140 current
+= entry
->Length();
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();
157 DirectoryIterator::Rewind()
160 fOffset
= BTREE_BEGIN
;