embox

Форк
0
/
procfs.c 
187 строк · 4.0 Кб
1
#include <errno.h>
2
#include <string.h>
3
#include <sys/stat.h>
4
#include <fcntl.h>
5
#include <stdint.h>
6

7
#include <util/err.h>
8

9
#include <drivers/char_dev.h>
10
#include <drivers/block_dev.h>
11
#include <drivers/device.h>
12
#include <framework/mod/options.h>
13
#include <fs/dvfs.h>
14

15
#include <lib/libds/array.h>
16

17
#include <module/embox/driver/block_dev.h>
18

19
#include <fs/inode.h>
20
#include <limits.h>
21
#include <net/net_namespace.h>
22
#include <kernel/task.h>
23

24
extern net_namespace_p net_ns_lookup(const char *name);
25
extern net_namespace_p net_ns_lookup_by_inode(struct inode *inode);
26

27
unsigned long int strtoul(const char *nptr, char **endptr, int base);
28
static int is_number(const char *str) {
29
	char *invalid;
30
	strtoul(str, &invalid, 10);
31
	if (invalid == str)
32
		return 0;
33
	else
34
		return 1;
35
}
36

37
static struct inode *procfs_lookup(struct inode *node, char const *name, struct inode const *dir) {
38
	net_namespace_p net_ns_p;
39

40
	/* /proc/pid/ns/net case */
41
	if (is_number(name))
42
		node->i_mode = S_IFDIR;
43
	else if (strcmp(name, "ns") == 0)
44
		node->i_mode = S_IFDIR;
45
	else if (strcmp(name, "net") == 0) {
46
		node->length = NAME_MAX + 1;
47
		node->i_mode = S_IFLNK;
48
	}
49

50
	/* /proc/netns/name case */
51
	if (strcmp(name, "netns") == 0)
52
		node->i_mode = S_IFDIR;
53
	else if (strcmp(dir->i_dentry->name, "netns") == 0) {
54
		net_ns_p = net_ns_lookup(name);
55
		if (net_ns_p.p != NULL) {
56
			return net_ns_p.p->inode;
57
		} else {
58
			return NULL;
59
		}
60
	}
61

62
	return node;
63
}
64

65
static int procfs_iterate(struct inode *next, char *name, struct inode *parent,
66
			  struct dir_ctx *ctx) {
67
	struct task *tsk, *last;
68
	int show_this_task = 0;
69

70
	last = (struct task *)ctx->fs_ctx;
71

72
	task_foreach(tsk) {
73
		if (show_this_task || last == NULL) {
74
			ctx->fs_ctx = (void *)tsk;
75
			next->i_mode = S_IFDIR; 
76
			snprintf(name, NAME_MAX - 1, "%d", tsk->tsk_id);
77
			name[NAME_MAX - 1] = '\0';
78
			return 0;
79
		}
80

81
		if (tsk == last) {
82
			show_this_task = 1;
83
		}
84
	}
85

86
	return -1;
87
}
88

89
static size_t procfs_fill_read_buff(struct file_desc *desc, void *buf,
90
				    size_t size, const char *content) {
91
	off_t pos;
92
	size_t content_size;
93

94
	pos = file_get_pos(desc);
95
	content_size = strlen(content) + 1;
96

97
	if (pos + size > content_size) {
98
		size = content_size - pos;
99
	}
100

101
	memcpy(buf, content + pos, size);
102

103
	return size;
104
}
105

106
static size_t procfs_read(struct file_desc *desc, void *buf, size_t size) {
107
	char netns_name[NAME_MAX + 1];
108
	char netns_path[1024];
109
	unsigned long pid;
110
	struct task *tsk;
111

112
	if (S_ISLNK(desc->f_inode->i_mode)) { /* /proc/pid/ns/net case */
113
		pid = strtoul(desc->f_dentry->parent->parent->name, NULL, 10);
114
		task_foreach(tsk) {
115
			if (tsk->tsk_id != pid)
116
				continue;
117
			memcpy(netns_name, tsk->nsproxy.net_ns.p->name,
118
			       strlen(desc->f_inode->i_dentry->name) + 1);
119
			sprintf(netns_path, "/proc/netns/%s", netns_name);
120
			return procfs_fill_read_buff(desc, buf, size,
121
						     netns_path);
122
		}
123
		return 0;
124
	} else {
125
		return 0;
126
	}
127
}
128

129
struct idesc *procfs_open_idesc(struct lookup *lookup, int __oflag) {
130
	struct file_desc *desc;
131
	net_namespace_p net_ns_p;
132

133
	desc = (struct file_desc *)dvfs_file_open_idesc(lookup, __oflag);
134

135
	net_ns_p = net_ns_lookup_by_inode(desc->f_inode);
136

137
	if (net_ns_p.p != NULL)
138
		netns_increment_ref_cnt(net_ns_p);
139

140
	return &desc->f_idesc;
141
}
142

143
int procfs_close(struct file_desc *desc) {
144
	net_namespace_p net_ns_p;
145

146
	net_ns_p = net_ns_lookup_by_inode(desc->f_inode);
147

148
	if (net_ns_p.p != NULL)
149
		netns_decrement_ref_cnt(net_ns_p);
150

151
	return 0;
152
}
153

154
static struct super_block_operations procfs_sbops = {
155
	.open_idesc = procfs_open_idesc,
156
};
157

158
struct inode_operations procfs_iops = {
159
	.ino_lookup   = procfs_lookup,
160
	.ino_iterate  = procfs_iterate,
161
};
162

163
struct file_operations procfs_fops = {
164
	.read  = procfs_read,
165
	.close  = procfs_close
166
};
167

168
static int procfs_fill_sb(struct super_block *sb, const char *source) {
169
	if (source) {
170
		return -1;
171
	}
172

173
	sb->sb_iops = &procfs_iops;
174
	sb->sb_fops = &procfs_fops;
175
	sb->sb_ops  = &procfs_sbops;
176

177
	return 0; 
178
}
179

180
static const struct fs_driver procfs_dumb_driver = {
181
	.name      = "procfs",
182
	.fill_sb   = procfs_fill_sb,
183
};
184

185
DECLARE_FILE_SYSTEM_DRIVER(procfs_dumb_driver);
186

187
FILE_SYSTEM_AUTOMOUNT("/proc", procfs_dumb_driver);
188

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.