xref: /haiku/src/system/boot/loader/file_systems/amiga_ffs/Directory.cpp (revision 9642f7705b27e5c270c15fa526d14e1848c2c27d)
1 /*
2  * Copyright 2003-2013, Axel Dörfler, axeld@pinc-software.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "Directory.h"
8 #include "Volume.h"
9 #include "File.h"
10 
11 #include <StorageDefs.h>
12 
13 #include <string.h>
14 #include <unistd.h>
15 #include <stdio.h>
16 
17 
18 using std::nothrow;
19 
20 
21 namespace FFS {
22 
23 
24 Directory::Directory(Volume &volume, int32 block)
25 	:
26 	fVolume(volume)
27 {
28 	void *data = malloc(volume.BlockSize());
29 	if (data == NULL)
30 		return;
31 
32 	if (read_pos(volume.Device(), block * volume.BlockSize(), data, volume.BlockSize()) == volume.BlockSize())
33 		fNode.SetTo(data, volume.BlockSize());
34 }
35 
36 
37 Directory::Directory(Volume &volume, RootBlock &root)
38 	:
39 	fVolume(volume)
40 {
41 	fNode.SetTo(root.BlockData(), root.BlockSize());
42 }
43 
44 
45 Directory::~Directory()
46 {
47 	free(fNode.BlockData());
48 }
49 
50 
51 status_t
52 Directory::InitCheck()
53 {
54 	return fNode.ValidateCheckSum();
55 }
56 
57 
58 status_t
59 Directory::Open(void **_cookie, int mode)
60 {
61 	_inherited::Open(_cookie, mode);
62 
63 	HashIterator *iterator = new(nothrow) HashIterator(fVolume.Device(), fNode);
64 	if (iterator == NULL)
65 		return B_NO_MEMORY;
66 
67 	if (iterator->InitCheck() != B_OK) {
68 		delete iterator;
69 		return B_NO_MEMORY;
70 	}
71 
72 	*_cookie = (void *)iterator;
73 	return B_OK;
74 }
75 
76 
77 status_t
78 Directory::Close(void *cookie)
79 {
80 	_inherited::Close(cookie);
81 
82 	delete (HashIterator *)cookie;
83 	return B_OK;
84 }
85 
86 
87 Node*
88 Directory::LookupDontTraverse(const char* name)
89 {
90 	if (!strcmp(name, ".")) {
91 		Acquire();
92 		return this;
93 	}
94 
95 	HashIterator iterator(fVolume.Device(), fNode);
96 	if (iterator.InitCheck() != B_OK)
97 		return NULL;
98 
99 	iterator.Goto(fNode.HashIndexFor(fVolume.Type(), name));
100 
101 	NodeBlock *node;
102 	int32 block;
103 	while ((node = iterator.GetNext(block)) != NULL) {
104 		char fileName[FFS_NAME_LENGTH];
105 		if (node->GetName(fileName, sizeof(fileName)) == B_OK
106 			&& !strcmp(name, fileName)) {
107 			if (node->IsFile())
108 				return new(nothrow) File(fVolume, block);
109 			if (node->IsDirectory())
110 				return new(nothrow) Directory(fVolume, block);
111 
112 			return NULL;
113 		}
114 	}
115 	return NULL;
116 }
117 
118 
119 status_t
120 Directory::GetNextEntry(void *cookie, char *name, size_t size)
121 {
122 	HashIterator *iterator = (HashIterator *)cookie;
123 	int32 block;
124 
125 	NodeBlock *node = iterator->GetNext(block);
126 	if (node == NULL)
127 		return B_ENTRY_NOT_FOUND;
128 
129 	return node->GetName(name, size);
130 }
131 
132 
133 status_t
134 Directory::GetNextNode(void *cookie, Node **_node)
135 {
136 	return B_ERROR;
137 }
138 
139 
140 status_t
141 Directory::Rewind(void *cookie)
142 {
143 	HashIterator *iterator = (HashIterator *)cookie;
144 	iterator->Rewind();
145 
146 	return B_OK;
147 }
148 
149 
150 bool
151 Directory::IsEmpty()
152 {
153 	int32 index;
154 	return fNode.FirstHashValue(index) == -1;
155 }
156 
157 
158 status_t
159 Directory::GetName(char *name, size_t size) const
160 {
161 	return fNode.GetName(name, size);
162 }
163 
164 
165 ino_t
166 Directory::Inode() const
167 {
168 	return fNode.HeaderKey();
169 }
170 
171 
172 }	// namespace FFS
173