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 "File.h"
9#include "Link.h"
10
11#include <StorageDefs.h>
12#include <KernelExport.h>
13
14#include <string.h>
15#include <unistd.h>
16
17
18// temp. private VFS API
19extern Node *get_node_from(int fd);
20
21
22using std::nothrow;
23
24
25namespace BFS {
26
27
28Directory::Directory(Volume &volume, block_run run)
29	:
30	fStream(volume, run),
31	fTree(&fStream)
32{
33}
34
35
36Directory::Directory(Volume &volume, off_t id)
37	:
38	fStream(volume, id),
39	fTree(&fStream)
40{
41}
42
43
44Directory::Directory(const Stream &stream)
45	:
46	fStream(stream),
47	fTree(&fStream)
48{
49}
50
51
52Directory::~Directory()
53{
54}
55
56
57status_t
58Directory::InitCheck()
59{
60	return fStream.InitCheck();
61}
62
63
64status_t
65Directory::Open(void **_cookie, int mode)
66{
67	_inherited::Open(_cookie, mode);
68
69	*_cookie = (void *)new(nothrow) TreeIterator(&fTree);
70	if (*_cookie == NULL)
71		return B_NO_MEMORY;
72
73	return B_OK;
74}
75
76
77status_t
78Directory::Close(void *cookie)
79{
80	_inherited::Close(cookie);
81
82	delete (TreeIterator *)cookie;
83	return B_OK;
84}
85
86
87Node*
88Directory::LookupDontTraverse(const char* name)
89{
90	off_t id;
91	if (fTree.Find((uint8 *)name, strlen(name), &id) < B_OK)
92		return NULL;
93
94	return Stream::NodeFactory(fStream.GetVolume(), id);
95}
96
97
98status_t
99Directory::GetNextEntry(void *cookie, char *name, size_t size)
100{
101	TreeIterator *iterator = (TreeIterator *)cookie;
102	uint16 length;
103	off_t id;
104
105	return iterator->GetNextEntry(name, &length, size, &id);
106}
107
108
109status_t
110Directory::GetNextNode(void *cookie, Node **_node)
111{
112	TreeIterator *iterator = (TreeIterator *)cookie;
113	char name[B_FILE_NAME_LENGTH];
114	uint16 length;
115	off_t id;
116
117	status_t status = iterator->GetNextEntry(name, &length, sizeof(name), &id);
118	if (status != B_OK)
119		return status;
120
121	*_node = Stream::NodeFactory(fStream.GetVolume(), id);
122	if (*_node == NULL)
123		return B_ERROR;
124
125	return B_OK;
126}
127
128
129status_t
130Directory::Rewind(void *cookie)
131{
132	TreeIterator *iterator = (TreeIterator *)cookie;
133
134	return iterator->Rewind();
135}
136
137
138bool
139Directory::IsEmpty()
140{
141	TreeIterator iterator(&fTree);
142
143	// index and attribute directories are really empty when they are
144	// empty - directories for standard files always contain ".", and
145	// "..", so we need to ignore those two
146
147	uint32 count = 0;
148	char name[BPLUSTREE_MAX_KEY_LENGTH];
149	uint16 length;
150	off_t id;
151	while (iterator.GetNextEntry(name, &length, B_FILE_NAME_LENGTH, &id)
152			== B_OK) {
153		if (fStream.Mode() & (S_ATTR_DIR | S_INDEX_DIR))
154			return false;
155
156		if (++count > 2 || (strcmp(".", name) && strcmp("..", name)))
157			return false;
158	}
159	return true;
160}
161
162
163status_t
164Directory::GetName(char *name, size_t size) const
165{
166	if (fStream.inode_num == fStream.GetVolume().Root()) {
167		strlcpy(name, fStream.GetVolume().SuperBlock().name, size);
168		return B_OK;
169	}
170
171	return fStream.GetName(name, size);
172}
173
174
175ino_t
176Directory::Inode() const
177{
178	return fStream.ID();
179}
180
181
182}	// namespace BFS
183