xref: /haiku/src/system/boot/loader/file_systems/bfs/Directory.cpp (revision 1e60bdeab63fa7a57bc9a55b032052e95a18bd2c)
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
19 extern Node *get_node_from(int fd);
20 
21 
22 using std::nothrow;
23 
24 
25 namespace BFS {
26 
27 
28 Directory::Directory(Volume &volume, block_run run)
29 	:
30 	fStream(volume, run),
31 	fTree(&fStream)
32 {
33 }
34 
35 
36 Directory::Directory(Volume &volume, off_t id)
37 	:
38 	fStream(volume, id),
39 	fTree(&fStream)
40 {
41 }
42 
43 
44 Directory::Directory(const Stream &stream)
45 	:
46 	fStream(stream),
47 	fTree(&fStream)
48 {
49 }
50 
51 
52 Directory::~Directory()
53 {
54 }
55 
56 
57 status_t
58 Directory::InitCheck()
59 {
60 	return fStream.InitCheck();
61 }
62 
63 
64 status_t
65 Directory::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 
77 status_t
78 Directory::Close(void *cookie)
79 {
80 	_inherited::Close(cookie);
81 
82 	delete (TreeIterator *)cookie;
83 	return B_OK;
84 }
85 
86 
87 Node*
88 Directory::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 
98 status_t
99 Directory::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 
109 status_t
110 Directory::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 
129 status_t
130 Directory::Rewind(void *cookie)
131 {
132 	TreeIterator *iterator = (TreeIterator *)cookie;
133 
134 	return iterator->Rewind();
135 }
136 
137 
138 bool
139 Directory::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 
163 status_t
164 Directory::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 
175 ino_t
176 Directory::Inode() const
177 {
178 	return fStream.ID();
179 }
180 
181 
182 }	// namespace BFS
183