embox

Форк
0
/
fat_inode_ops.c 
189 строк · 3.7 Кб
1
/**
2
 * @file
3
 *
4
 * @date Dec 12, 2019
5
 * @author Anton Bondarev
6
 */
7
#include <stddef.h>
8
#include <fcntl.h>
9
#include <string.h>
10
#include <assert.h>
11
#include <errno.h>
12

13
#include <fs/inode.h>
14
#include <fs/super_block.h>
15
#include <fs/inode_operation.h>
16
#include <fs/dir_context.h>
17

18
#include "fat.h"
19

20
extern int fat_alloc_inode_priv(struct inode *inode, struct fat_dirent *de);
21
extern int fat_destroy_inode(struct inode *inode);
22

23
/* @brief Get next inode in directory
24
 * @param inode   Structure to be filled
25
 * @param parent  Inode of parent directory
26
 * @param dir_ctx Directory context
27
 *
28
 * @return Error code
29
 */
30
int fat_iterate(struct inode *next, char *name, struct inode *parent, struct dir_ctx *ctx) {
31
	struct dirinfo *dirinfo;
32
	struct fat_dirent de;
33
	int res;
34

35
	assert(parent->i_sb);
36

37
	dirinfo = inode_priv(parent);
38
	dirinfo->currententry = (uintptr_t) ctx->fs_ctx;
39

40
	if (dirinfo->currententry == 0) {
41
		/* Need to get directory data from drive */
42
		fat_reset_dir(dirinfo);
43
	}
44

45
	read_dir_buf(dirinfo);
46

47
	while (((res = fat_get_next_long(dirinfo, &de, NULL)) ==  DFS_OK) || res == DFS_ALLOCNEW) {
48
		if (de.attr & ATTR_VOLUME_ID) {
49
			continue;
50
		}
51

52
		if (!memcmp(de.name, MSDOS_DOT, strlen(MSDOS_DOT)) ||
53
			!memcmp(de.name, MSDOS_DOTDOT, strlen(MSDOS_DOT))) {
54
			continue;
55
		}
56

57
		break;
58
	}
59

60
	switch (res) {
61
	case DFS_OK: {
62
		char tmp_name[128];
63
		int res;
64

65
		res = fat_alloc_inode_priv(next, &de);
66
		if (res) {
67
			return res;
68
		}
69

70
		if (0 > fat_fill_inode(next, &de, dirinfo)) {
71
			fat_destroy_inode(next);
72
			return -1;
73
		}
74
		if (DFS_OK != fat_read_filename(inode_priv(next), fat_sector_buff, tmp_name)) {
75
			fat_destroy_inode(next);
76
			return -1;
77
		}
78
		strncpy(name, tmp_name, NAME_MAX-1);
79
		name[NAME_MAX - 1] = '\0';
80

81
		ctx->fs_ctx = (void *) ((uintptr_t) dirinfo->currententry);
82
		return 0;
83
	}
84
	case DFS_EOF:
85
		/* Fall through */
86
	default:
87
		return -1;
88
	}
89
}
90

91
int fat_truncate(struct inode *node, off_t length) {
92
	assert(node);
93

94
	inode_size_set(node, length);
95

96
	/* TODO realloc blocks*/
97

98
	return 0;
99
}
100

101
/* @brief Create new file or directory
102
 * @param i_new Inode to be filled
103
 * @param i_dir Inode realted to the parent
104
 * @param mode  Used to figure out file type
105
 *
106
 * @return Negative error code
107
 */
108
int fat_create(struct inode *i_new, struct inode *i_dir, int mode) {
109
	struct fat_file_info *fi;
110
	struct fat_fs_info *fsi;
111
	struct dirinfo *di;
112
	char *name;
113

114
	assert(i_dir && i_new);
115

116
	inode_size_set(i_new, 0);
117

118
	di = inode_priv(i_dir);
119

120
	name = inode_name(i_new);
121
	assert(name);
122

123
	/* TODO check file exists */
124
	assert(i_dir->i_sb);
125
	fsi = i_dir->i_sb->sb_data;
126

127
	fat_reset_dir(di);
128
	read_dir_buf(di);
129

130
	if (S_ISDIR(i_new->i_mode)) {
131
		struct dirinfo *new_di;
132
		new_di = fat_dirinfo_alloc();
133
		if (!new_di) {
134
			return -ENOMEM;
135
		}
136
		new_di->p_scratch = fat_sector_buff;
137
		fi = &new_di->fi;
138
	} else {
139
		fi = fat_file_alloc();
140
		if (!fi) {
141
			return -ENOMEM;
142
		}
143
	}
144

145
	inode_priv_set(i_new, fi);
146

147
	fi->volinfo = &fsi->vi;
148
	fi->fdi     = di;
149
	fi->fsi     = fsi;
150
	fi->mode   |= i_new->i_mode;
151

152
	if (0 != fat_create_file(fi, di, name, fi->mode)) {
153
		return -EIO;
154
	}
155

156
	return 0;
157
}
158
extern int fat_dir_empty(struct fat_file_info *fi);
159
int fat_delete(struct inode *dir, struct inode *node) {
160
	struct fat_file_info *fi;
161

162
	fi = inode_priv(node);
163

164
	if (S_ISDIR(node->i_mode) && !fat_dir_empty(fi)) {
165
		return -EPERM;
166
	}
167

168
	if (fat_unlike_file(fi, (uint8_t *) fat_sector_buff)) {
169
		return -1;
170
	}
171

172
	if (S_ISDIR(node->i_mode)) {
173
		fat_dirinfo_free((void *) fi);
174
	} else {
175
		fat_file_free(fi);
176
	}
177

178
	return 0;
179
}
180

181
extern struct inode *fat_ilookup(struct inode *node, char const *name, struct inode const *dir);
182

183
struct inode_operations fat_iops = {
184
	.ino_create   = fat_create,
185
	.ino_lookup   = fat_ilookup,
186
	.ino_remove   = fat_delete,
187
	.ino_iterate  = fat_iterate,
188
	.ino_truncate = fat_truncate,
189
};
190

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

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

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

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