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