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