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