embox

Форк
0
/
dirent.c 
131 строка · 2.2 Кб
1
/**
2
 * @brief
3
 *
4
 * @date 12.02.24
5
 * @author Aleksey Zhmulin
6
 */
7

8
#include <dirent.h>
9
#include <errno.h>
10
#include <fcntl.h>
11
#include <stdbool.h>
12
#include <stddef.h>
13
#include <string.h>
14
#include <sys/cdefs.h>
15
#include <sys/stat.h>
16
#include <sys/types.h>
17
#include <time.h>
18
#include <unistd.h>
19

20
#include <framework/mod/options.h>
21
#include <mem/misc/pool.h>
22
#include <util/err.h>
23
#include <vfs/core.h>
24

25
#define DIR_POOL_SIZE OPTION_GET(NUMBER, dir_pool_size)
26

27
struct DIR_struct {
28
	struct inode inode;
29
	struct inode pos;
30
	struct dirent dirent;
31
	struct timespec mtime;
32
	bool end_of_dir;
33
};
34

35
POOL_DEF(dir_pool, DIR, DIR_POOL_SIZE);
36

37
static int __readdir(DIR *dir) {
38
	int err;
39

40
	do {
41
		if (vfs_inode_is_bad(&dir->pos)) {
42
			vfs_inode_get_mtime(&dir->inode, &dir->mtime);
43
		}
44
		else if (vfs_inode_is_modified(&dir->inode, &dir->mtime)) {
45
			return -ENOENT;
46
		}
47

48
		err = dir->inode.sb->drv->ops.readdir(&dir->inode, &dir->pos,
49
		    &dir->dirent);
50

51
		if (err) {
52
			dir->pos.ino = VFS_BAD_INO;
53
			dir->pos.sb = dir->inode.sb;
54
		}
55

56
	} while (err && vfs_mount_point_get_prev_bind(&dir->inode, &dir->inode));
57

58
	return err;
59
}
60

61
DIR *opendir(const char *path) {
62
	DIR *dir;
63
	int err;
64

65
	dir = pool_alloc(&dir_pool);
66
	if (!dir) {
67
		SET_ERRNO(ENFILE);
68
		return NULL;
69
	}
70

71
	vfs_inode_ops_lock();
72
	{
73
		err = vfs_path_lookup(path, &dir->inode);
74
		if (!err) {
75
			vfs_mount_point_get_last(&dir->inode, &dir->inode);
76
			vfs_inode_lock(&dir->inode);
77
		}
78
	}
79
	vfs_inode_ops_unlock();
80

81
	if (err) {
82
		pool_free(&dir_pool, dir);
83
		SET_ERRNO(-err);
84
		return NULL;
85
	}
86

87
	dir->pos.ino = VFS_BAD_INO;
88
	dir->pos.sb = dir->inode.sb;
89
	dir->end_of_dir = false;
90

91
	return dir;
92
}
93

94
int closedir(DIR *dir) {
95
	if (!dir->end_of_dir) {
96
		vfs_inode_unlock(&dir->inode);
97
	}
98
	pool_free(&dir_pool, dir);
99

100
	return 0;
101
}
102

103
struct dirent *readdir(DIR *dir) {
104
	struct inode old;
105
	int err;
106

107
	if (dir->end_of_dir) {
108
		SET_ERRNO(ENOENT);
109
		return NULL;
110
	}
111

112
	memcpy(&old, &dir->inode, sizeof(struct inode));
113

114
	vfs_inode_ops_lock();
115
	err = __readdir(dir);
116
	vfs_inode_ops_unlock();
117

118
	if (err) {
119
		dir->end_of_dir = true;
120
		vfs_inode_unlock(&dir->inode);
121
		SET_ERRNO(-err);
122
		return NULL;
123
	}
124

125
	if ((dir->inode.ino != old.ino) || (dir->inode.sb != old.sb)) {
126
		vfs_inode_lock(&dir->inode);
127
		vfs_inode_unlock(&old);
128
	}
129

130
	return &dir->dirent;
131
}
132

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

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

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

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