summaryrefslogtreecommitdiff
path: root/Source/Kernel/VFS/DirectoryNode.class.cpp
blob: 55365f045fb4b28a379f9dc9649fc1564d911ac2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include "DirectoryNode.class.h"

call_t DirectoryNode::m_callTable[] = {
	CALL1(FNIF_GETIDXCHILD, &DirectoryNode::getIdxChildSC),
	CALL1(FNIF_GETNAMECHILD, &DirectoryNode::getNameChildSC),
	CALL0(0, 0)
};

DirectoryNode::~DirectoryNode() {
	if (m_contentLoaded) {
		for (u32int i = 0; i < m_children.size(); i++) {
			delete m_children[i];
		}
	}
	if (m_name == "/" && m_parent != NULL) ((DirectoryNode*)(m_parent))->unmount();
}

u32int DirectoryNode::getIdxChildSC(u32int idx) {
	if (!runnable()) return (u32int) - 1;
	FSNode* n = getChild(idx);
	if (n != NULL) return n->resId();
	return (u32int) - 1;
}

u32int DirectoryNode::getNameChildSC(u32int name) {
	if (!runnable()) return (u32int) - 1;
	String* w = (String*)name;
	FSNode* n = getChild(*w);
	if (n != NULL) return n->resId();
	return (u32int) - 1;
}

u64int DirectoryNode::getLength() {
	if (m_mounts != 0) return m_mounts->getLength();
	if (!m_contentLoaded)
		if (!loadContent())
			return 0;
	return m_length;
}

FSNode* DirectoryNode::getParent() {
	//if (m_name == "/" and m_parent != 0) return m_parent->getParent();
	return m_parent;
}

bool DirectoryNode::removable() {
	if (!m_contentLoaded)
		if (!loadContent())
			return false;
	return m_children.empty() && (m_mounts == 0);
}

bool DirectoryNode::unmountable() {
	if (!m_contentLoaded) return true;
	if (m_mounts != 0) return false;
	for (u32int i = 0; i < m_children.size(); i++) {
		if (m_children[i]->type() == NT_DIRECTORY) {
			if (!((DirectoryNode*)m_children[i])->unmountable()) return false;
		} else {
			if (!m_children[i]->removable()) return false;
		}
	}
	return true;
}

bool DirectoryNode::mountpointable() {
	if (!m_contentLoaded)
		if (!loadContent()) return false;
	return m_children.empty();
}

void DirectoryNode::mount(DirectoryNode* childRoot) {
	m_mounts = childRoot;
}

void DirectoryNode::unmount() {
	m_mounts = 0;
}

bool DirectoryNode::loadContent() {
	if (m_mounts != 0) return m_mounts->loadContent();
	if (m_contentLoaded) return true;
	bool b = m_fs->loadContents(this);
	if (!b) return false;
	m_length = m_children.size();
	m_contentLoaded = true;
	return b;
}

FSNode* DirectoryNode::getChild(u32int index) {
	if (m_mounts != 0) return m_mounts->getChild(index);
	if (!m_contentLoaded)
		if (!loadContent())
			return NULL;
	if (index >= m_children.size()) return NULL;
	return m_children[index];
}

FSNode* DirectoryNode::getChild(const String& name) {
	if (m_mounts != 0) return m_mounts->getChild(name);
	if (!m_contentLoaded)
		if (!loadContent())
			return NULL;
	for (u32int i = 0; i < m_children.size(); i++) {
		if (name == m_children[i]->getName())
			return m_children[i];
	}
	return NULL;
}

FileNode* DirectoryNode::createFile(const String& name) {
	if (m_mounts != 0) return m_mounts->createFile(name);
	FileNode* n = m_fs->createFile(this, name);
	m_length = m_children.size();
	return n;
}

DirectoryNode* DirectoryNode::createDirectory(const String& name) {
	if (m_mounts != 0) return m_mounts->createDirectory(name);
	DirectoryNode* n = m_fs->createDirectory(this, name);
	m_length = m_children.size();
	return n;
}

bool DirectoryNode::remove(FSNode* child) {
	if (m_mounts != 0) return m_mounts->remove(child);
	//Check node is indeed one of our childs
	if (!m_contentLoaded)
		if (!loadContent())
			return false;
	u32int idx = (u32int) - 1;
	for (u32int i = 0; i < m_children.size(); i++) {
		if (m_children[i] == child) {
			idx = i;
			break;
		}
	}
	if (idx == (u32int) - 1) return false;

	//Check if we can remove node
	if (!m_children[idx]->removable()) return false;
	if (m_fs != m_children[idx]->getFS()) return false;	//We could !be on the same FS

	//Ask FS to remove node
	if (!m_fs->remove(this, child)) return false;

	//Remove node from our children list
	m_children[idx] = m_children.back();
	m_children.pop();
	m_length--;

	delete child;

	return true;
}