embox

Форк
0
/
path.c 
227 строк · 4.3 Кб
1
/**
2
 * @brief
3
 *
4
 * @date 02.01.24
5
 * @author Aleksey Zhmulin
6
 */
7

8
#include <assert.h>
9
#include <errno.h>
10
#include <fcntl.h>
11
#include <limits.h>
12
#include <stdlib.h>
13
#include <string.h>
14
#include <sys/types.h>
15

16
#include <lib/cwalk.h>
17
#include <util/err.h>
18
#include <util/log.h>
19
#include <vfs/core.h>
20

21
struct idesc;
22

23
struct lookup {
24
	struct inode dir;
25
	struct inode file;
26
	char filename[NAME_MAX];
27
};
28

29
static int vfs_lookup_next(struct inode *dir_inode, struct cwk_segment *segment,
30
    struct lookup *lookup) {
31
	int err;
32

33
	if (!vfs_inode_is_directory(dir_inode)) {
34
		return -ENOTDIR;
35
	}
36

37
	vfs_mount_point_get_last(dir_inode, &lookup->dir);
38

39
	if (segment->size >= NAME_MAX) {
40
		return -ENAMETOOLONG;
41
	}
42

43
	memcpy(lookup->filename, segment->begin, segment->size);
44
	lookup->filename[segment->size] = '\0';
45

46
	do {
47
		if (!vfs_inode_is_available(&lookup->dir, O_RDONLY)) {
48
			err = -EACCES;
49
			continue;
50
		}
51
		err = lookup->dir.sb->drv->ops.lookup(&lookup->dir, lookup->filename,
52
		    &lookup->file);
53
	} while (err && vfs_mount_point_get_prev_bind(&lookup->dir, &lookup->dir));
54

55
	return err;
56
}
57

58
static int vfs_lookup(const char *path, struct lookup *lookup) {
59
	struct cwk_segment segment;
60
	const char *cwd;
61
	size_t len;
62
	int err;
63
	char normal_path[PATH_MAX];
64

65
	if (!path) {
66
		return -ENOENT;
67
	}
68

69
	if (cwk_path_is_absolute(path)) {
70
		len = cwk_path_normalize(path, normal_path, sizeof(normal_path));
71
	}
72
	else {
73
		cwd = getenv("PWD");
74
		if (!cwd) {
75
			cwd = "/";
76
		}
77
		if (cwk_path_is_relative(cwd)) {
78
			log_error("PWD is not an absolute path");
79
			return -ENOENT;
80
		}
81
		len = cwk_path_join(cwd, path, normal_path, sizeof(normal_path));
82
	}
83

84
	if (len >= PATH_MAX) {
85
		return -ENAMETOOLONG;
86
	}
87

88
	vfs_inode_get_root(&lookup->file);
89

90
	if (!cwk_path_get_first_segment(normal_path, &segment)) {
91
		lookup->dir.ino = VFS_BAD_INO;
92
		lookup->dir.sb = lookup->file.sb;
93
		return 0;
94
	}
95

96
	do {
97
		err = vfs_lookup_next(&lookup->file, &segment, lookup);
98
	} while (!err && cwk_path_get_next_segment(&segment));
99

100
	if ((err == -ENOENT) && !cwk_path_get_next_segment(&segment)) {
101
		lookup->file.ino = VFS_BAD_INO;
102
		lookup->file.sb = lookup->dir.sb;
103
		return 0;
104
	}
105

106
	return err;
107
}
108

109
int vfs_path_lookup(const char *path, struct inode *lookup) {
110
	struct lookup _lookup;
111
	int err;
112

113
	if ((err = vfs_lookup(path, &_lookup))) {
114
		return err;
115
	}
116

117
	if (vfs_inode_is_bad(&_lookup.file)) {
118
		return -ENOENT;
119
	}
120

121
	memcpy(lookup, &_lookup.file, sizeof(struct inode));
122

123
	return 0;
124
}
125

126
struct idesc *vfs_path_open(const char *path, int oflag, mode_t mode) {
127
	struct lookup lookup;
128
	int err;
129

130
	err = vfs_lookup(path, &lookup);
131
	if (err) {
132
		return err2ptr(-err);
133
	}
134

135
	if (!vfs_inode_is_bad(&lookup.file)) {
136
		if ((oflag & O_CREAT) && (oflag & O_EXCL)) {
137
			return err2ptr(EEXIST);
138
		}
139
		goto out;
140
	}
141

142
	if (!(oflag & O_CREAT)) {
143
		return err2ptr(ENOENT);
144
	}
145

146
	if (!vfs_inode_is_available(&lookup.dir, O_WRONLY)) {
147
		return err2ptr(EACCES);
148
	}
149

150
	if (!lookup.dir.sb->drv->ops.mkfile) {
151
		return err2ptr(ENOSUPP);
152
	}
153

154
	err = lookup.dir.sb->drv->ops.mkfile(&lookup.dir, lookup.filename,
155
	    &lookup.file);
156
	if (err) {
157
		return err2ptr(-err);
158
	}
159

160
	vfs_inode_update_mtime(&lookup.dir);
161
	vfs_inode_init(&lookup.file, (mode & S_IRWXA) | S_IFREG);
162

163
out:
164
	return lookup.file.sb->drv->ops.open(&lookup.file, oflag);
165
}
166

167
int vfs_path_mkdir(const char *path, mode_t mode) {
168
	struct lookup lookup;
169
	int err;
170

171
	err = vfs_lookup(path, &lookup);
172
	if (err) {
173
		return err;
174
	}
175

176
	if (!vfs_inode_is_bad(&lookup.file)) {
177
		return -EEXIST;
178
	}
179

180
	if (!vfs_inode_is_available(&lookup.dir, O_WRONLY)) {
181
		return -EACCES;
182
	}
183

184
	if (!lookup.dir.sb->drv->ops.mkdir) {
185
		return -ENOSUPP;
186
	}
187

188
	err = lookup.dir.sb->drv->ops.mkdir(&lookup.dir, lookup.filename,
189
	    &lookup.file);
190
	if (err) {
191
		return err;
192
	}
193

194
	vfs_inode_update_mtime(&lookup.dir);
195
	vfs_inode_init(&lookup.file, (mode & S_IRWXA) | S_IFDIR);
196

197
	return 0;
198
}
199

200
int vfs_path_remove(const char *path) {
201
	struct lookup lookup;
202
	int err;
203

204
	err = vfs_lookup(path, &lookup);
205
	if (err) {
206
		return err;
207
	}
208

209
	if (vfs_inode_is_bad(&lookup.file)) {
210
		return -ENOENT;
211
	}
212

213
	if (vfs_inode_is_mount_point(&lookup.file)
214
	    || vfs_mount_point_get_next(&lookup.file, &lookup.file)) {
215
		return -EBUSY;
216
	}
217

218
	if (!vfs_inode_is_available(&lookup.dir, O_WRONLY)) {
219
		return -EACCES;
220
	}
221

222
	if (!lookup.dir.sb->drv->ops.remove) {
223
		return -ENOSUPP;
224
	}
225

226
	return lookup.dir.sb->drv->ops.remove(&lookup.dir, &lookup.file);
227
}
228

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

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

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

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