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