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