1 // VirtualDir.cpp
2
3 #include "VirtualDir.h"
4
5 #include <string.h>
6
7 #include <AutoDeleter.h>
8
9 // constructor
VirtualDirEntry()10 VirtualDirEntry::VirtualDirEntry()
11 : fName(),
12 fNode(NULL)
13 {
14 }
15
16 // destructor
~VirtualDirEntry()17 VirtualDirEntry::~VirtualDirEntry()
18 {
19 }
20
21 // SetTo
22 status_t
SetTo(const char * name,Node * node)23 VirtualDirEntry::SetTo(const char* name, Node* node)
24 {
25 if (!name || strlen(name) == 0 || !node)
26 return B_BAD_VALUE;
27
28 if (!fName.SetTo(name))
29 return B_NO_MEMORY;
30 fNode = node;
31
32 return B_OK;
33 }
34
35 // GetName
36 const char*
GetName() const37 VirtualDirEntry::GetName() const
38 {
39 return fName.GetString();
40 }
41
42 // GetNode
43 Node*
GetNode() const44 VirtualDirEntry::GetNode() const
45 {
46 return fNode;
47 }
48
49
50 // #pragma mark -
51
52 // constructor
VirtualDirIterator()53 VirtualDirIterator::VirtualDirIterator()
54 : fDirectory(NULL),
55 fCurrentEntry(NULL),
56 fState(STATE_DOT)
57 {
58 }
59
60 // destructor
~VirtualDirIterator()61 VirtualDirIterator::~VirtualDirIterator()
62 {
63 SetDirectory(NULL);
64 }
65
66 // SetDirectory
67 void
SetDirectory(VirtualDir * directory,bool onlyChildren)68 VirtualDirIterator::SetDirectory(VirtualDir* directory, bool onlyChildren)
69 {
70 // unset the old directory
71 if (fDirectory)
72 fDirectory->RemoveDirIterator(this);
73
74 // set the new directory
75 fDirectory = directory;
76 if (fDirectory) {
77 fDirectory->AddDirIterator(this);
78
79 if (onlyChildren) {
80 fCurrentEntry = fDirectory->GetFirstEntry();
81 fState = STATE_OTHERS;
82 } else {
83 fCurrentEntry = NULL;
84 fState = STATE_DOT;
85 }
86 }
87 }
88
89 // GetCurrentEntry
90 bool
GetCurrentEntry(const char ** name,Node ** node)91 VirtualDirIterator::GetCurrentEntry(const char** name, Node** node)
92 {
93 if (!fDirectory)
94 return false;
95 switch (fState) {
96 case STATE_DOT:
97 *name = ".";
98 *node = fDirectory;
99 return true;
100 case STATE_DOT_DOT:
101 *name = "..";
102 *node = fDirectory->GetParent();
103 if (!*node)
104 *node = fDirectory;
105 return true;
106 default:
107 if (!fCurrentEntry)
108 return false;
109 *name = fCurrentEntry->GetName();
110 *node = fCurrentEntry->GetNode();
111 return true;
112 }
113 }
114
115 // GetCurrentEntry
116 VirtualDirEntry*
GetCurrentEntry() const117 VirtualDirIterator::GetCurrentEntry() const
118 {
119 return fCurrentEntry;
120 }
121
122 // NextEntry
123 void
NextEntry()124 VirtualDirIterator::NextEntry()
125 {
126 if (!fDirectory)
127 return;
128 switch (fState) {
129 case STATE_DOT:
130 fState = STATE_DOT_DOT;
131 break;
132 case STATE_DOT_DOT:
133 fState = STATE_OTHERS;
134 fCurrentEntry = fDirectory->GetFirstEntry();
135 break;
136 default:
137 if (fCurrentEntry)
138 fCurrentEntry = fDirectory->GetNextEntry(fCurrentEntry);
139 break;
140 }
141 }
142
143 // Rewind
144 void
Rewind()145 VirtualDirIterator::Rewind()
146 {
147 fState = STATE_DOT;
148 fCurrentEntry = NULL;
149 }
150
151
152 // #pragma mark -
153
154 // constructor
VirtualDir(Volume * volume,vnode_id nodeID)155 VirtualDir::VirtualDir(Volume* volume, vnode_id nodeID)
156 : Node(volume, nodeID),
157 fParent(NULL),
158 fCreationTime(0),
159 fEntries(),
160 fEntryList(),
161 fIterators()
162 {
163 }
164
165 // destructor
~VirtualDir()166 VirtualDir::~VirtualDir()
167 {
168 while (VirtualDirEntry* entry = GetFirstEntry())
169 RemoveEntry(entry->GetName());
170 }
171
172 // InitCheck
173 status_t
InitCheck() const174 VirtualDir::InitCheck() const
175 {
176 return fEntries.InitCheck();
177 }
178
179 // SetParent
180 void
SetParent(VirtualDir * parent)181 VirtualDir::SetParent(VirtualDir* parent)
182 {
183 fParent = parent;
184 }
185
186 // GetParent
187 VirtualDir*
GetParent() const188 VirtualDir::GetParent() const
189 {
190 return fParent;
191 }
192
193 // GetCreationTime
194 time_t
GetCreationTime() const195 VirtualDir::GetCreationTime() const
196 {
197 return fCreationTime;
198 }
199
200 // AddEntry
201 status_t
AddEntry(const char * name,Node * child)202 VirtualDir::AddEntry(const char* name, Node* child)
203 {
204 if (!name || !child || fEntries.ContainsKey(name))
205 return B_BAD_VALUE;
206
207 // create an entry
208 VirtualDirEntry* entry = new(std::nothrow) VirtualDirEntry;
209 if (!entry)
210 return B_NO_MEMORY;
211 ObjectDeleter<VirtualDirEntry> entryDeleter(entry);
212 status_t error = entry->SetTo(name, child);
213 if (error != B_OK)
214 return error;
215
216 // add the entry
217 error = fEntries.Put(name, entry);
218 if (error != B_OK)
219 return error;
220 fEntryList.Insert(entry);
221 entryDeleter.Detach();
222
223 // TODO: That's not so nice. Check whether better to move the fParent
224 // property to Node.
225 if (VirtualDir* childDir = dynamic_cast<VirtualDir*>(child))
226 childDir->SetParent(this);
227
228 return error;
229 }
230
231 // RemoveEntry
232 Node*
RemoveEntry(const char * name)233 VirtualDir::RemoveEntry(const char* name)
234 {
235 if (!name)
236 return NULL;
237
238 Node* child = NULL;
239 VirtualDirEntry* entry = fEntries.Remove(name);
240 if (entry) {
241 child = entry->GetNode();
242 // update the directory iterators pointing to the removed entry
243 for (VirtualDirIterator* iterator = fIterators.First();
244 iterator;
245 iterator = fIterators.GetNext(iterator)) {
246 if (iterator->GetCurrentEntry() == entry)
247 iterator->NextEntry();
248 }
249
250 // remove the entry completely
251 fEntryList.Remove(entry);
252 delete entry;
253
254 // TODO: See AddEntry().
255 if (VirtualDir* childDir = dynamic_cast<VirtualDir*>(child))
256 childDir->SetParent(NULL);
257 }
258 return child;
259 }
260
261 // GetEntry
262 VirtualDirEntry*
GetEntry(const char * name) const263 VirtualDir::GetEntry(const char* name) const
264 {
265 if (!name)
266 return NULL;
267
268 return fEntries.Get(name);
269 }
270
271 // GetChildNode
272 Node*
GetChildNode(const char * name) const273 VirtualDir::GetChildNode(const char* name) const
274 {
275 if (VirtualDirEntry* entry = GetEntry(name))
276 return entry->GetNode();
277 return NULL;
278 }
279
280 // GetFirstEntry
281 VirtualDirEntry*
GetFirstEntry() const282 VirtualDir::GetFirstEntry() const
283 {
284 return fEntryList.First();
285 }
286
287 // GetNextEntry
288 VirtualDirEntry*
GetNextEntry(VirtualDirEntry * entry) const289 VirtualDir::GetNextEntry(VirtualDirEntry* entry) const
290 {
291 if (!entry)
292 return NULL;
293 return fEntryList.GetNext(entry);
294 }
295
296 // AddDirIterator
297 void
AddDirIterator(VirtualDirIterator * iterator)298 VirtualDir::AddDirIterator(VirtualDirIterator* iterator)
299 {
300 if (!iterator)
301 return;
302
303 fIterators.Insert(iterator);
304 }
305
306 // RemoveDirIterator
307 void
RemoveDirIterator(VirtualDirIterator * iterator)308 VirtualDir::RemoveDirIterator(VirtualDirIterator* iterator)
309 {
310 if (!iterator)
311 return;
312
313 fIterators.Remove(iterator);
314 }
315