summaryrefslogtreecommitdiff
path: root/src/kernel/vfs/node.cpp
blob: 08c78170466696785ad1f683bff51d18174ab1f5 (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
#include "node.h"
#include "vdir.h"

int node::open(process *proc, int mode) {
	return 0;	// ok
}

int node::stat(file_info *info) {
	info->type = type;
	info->dev_type = dev_type;
	info->mode = mode;
	info->uid = uid;
	info->gid = gid;
	info->size = this->get_size();
	return 0;
}

node *root = 0, *dot_dev = 0, *dot_ui = 0;

void vfs_setup() {
	root = new vdir(0);
	dot_dev = new vdir(root);
	root->add_child(".dev", dot_dev);
	dot_ui = new vdir(root);
	root->add_child(".ui", dot_ui);
}

node* vfs_find(node* root, char* path) {
	node* el = root;
	char *member = path;
	
	while (*path != 0 && el != 0) {
		if (*path == '/') {
			if (member == path) {
				member++;
				path++;
			} else {
				*path = 0;
				el = el->get_child(member);
				path++;
				member = path;
			}
		} else {
			path++;
		}
	}
	if (el != 0 && member != path) {
		el = el->get_child(member);
	}

	return el;
}

node* vfs_read_fd(FILE d) {
	return current_process->fd.at(d);
}

// Syscalls

static FILE i_open(node* r, char* filename, int mode) {
	node* f = vfs_find(r, filename);
	if (f == 0) return E_NOT_FOUND;
	//TODO : different actions depending on open mode
	//TODO : permission checks
	int e = f->open(current_process, mode);
	if (e != 0) return e;
	return current_process->fd.add(f);
}

FILE open(char* filename, int mode) {
	return i_open(root, filename, mode);
}

FILE open_relative(FILE root, char* filename, int mode) {
	node* n = vfs_read_fd(root);
	if (n == 0) return E_INVALID_FD;
	return i_open(n, filename, mode);
}

int stat(char* filename, file_info *info) {
	node *f = vfs_find(root, filename);
	if (f == 0) return E_NOT_FOUND;
	return f->stat(info);
}

int stat_relative(FILE root, char* filename, file_info *info) {
	node *r = vfs_read_fd(root);
	if (r == 0) return E_INVALID_FD;
	node *f = vfs_find(r, filename);
	if (f == 0) return E_NOT_FOUND;
	return f->stat(info);
}

int statf(FILE file, file_info *info) {
	node *f = vfs_read_fd(file);
	if (f == 0) return E_INVALID_FD;
	return f->stat(info);
}

void close(FILE file) {
	node *f = vfs_read_fd(file);
	if (f != 0) {
		f->close(current_process);
		current_process->fd.set(file, 0);
	}
}

int read(FILE file, size_t offset, size_t len, char* buffer) {
	node *f = vfs_read_fd(file);
	if (f == 0) return E_INVALID_FD;
	return f->read(offset, len, buffer);
}

int write(FILE file, size_t offset, size_t len, char* buffer) {
	node *f = vfs_read_fd(file);
	if (f == 0) return E_INVALID_FD;
	return f->write(offset, len, buffer);
}

int link(char* from, char* to, int mode) {
	node *f1 = vfs_find(root, from);
	if (f1 == 0) return E_NOT_FOUND;
	node *f2 = (to == 0 ? 0 : vfs_find(root, to));
	return f1->link(f2, mode);
}