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
18using std::nothrow;
19
20
21namespace FFS {
22
23
24Directory::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
37Directory::Directory(Volume &volume, RootBlock &root)
38	:
39	fVolume(volume)
40{
41	fNode.SetTo(root.BlockData(), root.BlockSize());
42}
43
44
45Directory::~Directory()
46{
47	free(fNode.BlockData());
48}
49
50
51status_t
52Directory::InitCheck()
53{
54	return fNode.ValidateCheckSum();
55}
56
57
58status_t
59Directory::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
77status_t
78Directory::Close(void *cookie)
79{
80	_inherited::Close(cookie);
81
82	delete (HashIterator *)cookie;
83	return B_OK;
84}
85
86
87Node*
88Directory::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
119status_t
120Directory::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
133status_t
134Directory::GetNextNode(void *cookie, Node **_node)
135{
136	return B_ERROR;
137}
138
139
140status_t
141Directory::Rewind(void *cookie)
142{
143	HashIterator *iterator = (HashIterator *)cookie;
144	iterator->Rewind();
145
146	return B_OK;
147}
148
149
150bool
151Directory::IsEmpty()
152{
153	int32 index;
154	return fNode.FirstHashValue(index) == -1;
155}
156
157
158status_t
159Directory::GetName(char *name, size_t size) const
160{
161	return fNode.GetName(name, size);
162}
163
164
165ino_t
166Directory::Inode() const
167{
168	return fNode.HeaderKey();
169}
170
171
172}	// namespace FFS
173