-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathnamei.c
288 lines (236 loc) · 7.66 KB
/
namei.c
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
#include <linux/fs.h>
#include <linux/version.h>
#include "fat.h"
#include "entry.h"
#include "file.h"
#include "namei.h"
extern struct inode_operations mfs_file_inode_ops;
extern struct inode_operations mfs_dir_inode_ops;
/**
@brief inode를 구조체 할당 함수
inode를 얻고 적당한 파라메터에 따라 값으로 초기화 해 주는 함수이다.
@param
struct super_block *sb MFS파일시스템의 superblock
int mode 파일 혹은 디렉토리 여부 등의 속성정보
dev_t dev 현재 미사용
@return 할당에 성공한 inode구조체 포인터
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
struct inode *mfs_get_inode(struct super_block *sb, umode_t mode, dev_t dev)
#else
struct inode *mfs_get_inode(struct super_block *sb, int mode, dev_t dev)
#endif
{
struct inode * inode = new_inode(sb);
if (inode) {
inode->i_mode = mode;
inode->i_size = 0;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
inode->i_uid.val = 0;//file의 소유uid는 root(0)
inode->i_gid.val = 0;//File의 소유gid는 root(0)
#else
inode->i_uid = 0;
inode->i_gid = 0;
#endif
inode->i_blocks = 0;//새로 만드는 inode이므로 사용 블럭은 0
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;//현재시간 기준으로
switch (mode & S_IFMT) {
default:
init_special_inode(inode, mode, dev);
break;
case S_IFREG:
printk("file inode\n");
inode->i_op = &mfs_file_inode_ops;
inode->i_fop = &mfs_file_operations;
break;
case S_IFDIR:
inode->i_op = &mfs_dir_inode_ops;
inode->i_fop = &mfs_dir_operations;
inc_nlink(inode);
break;
case S_IFLNK:
printk("no support symbolic link");
break;
}
}
return inode;
}
/**
@brief 디렉토리에 dentry에 해당하는 파일이 존재하는지 여부를 확인
@param
struct inode *dir 존재여부를 확인할 디렉토리의 inode
struct dentry *dentry 디렉토리에서 존재여부를 확인할 파일의 dentry
struct nameidata *nd 미사용
@return NULL
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
static struct dentry *mfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
#else
static struct dentry *mfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
#endif
{
printk("\t\t\t\t\t\t\t\t\t\tMFS LOOKUP\n");
struct inode* inode = NULL;
char path[512] = {0};
int res = 0;
void* volume = dir->i_sb->s_fs_info;
printk("mfs_lookup %s\n", dentry->d_name.name);
get_dir_path_from_dentry(dentry, path, 512);
if ((res = __mfs_lookup(volume, path, (ps16_t) dentry->d_name.name))) {
if(res == FILE_DENTRY){
printk("File : %s\n", res, dentry->d_name.name);
inode = mfs_get_inode(dir->i_sb, S_IFREG, 0);
}
else if(res == DIR_DENTRY){
printk("Dir : %s\n", res, dentry->d_name.name);
inode = mfs_get_inode(dir->i_sb, S_IFDIR, 0);
}
inode->i_ino = 2;
} else {
printk("not exist: %s\n",dentry->d_name.name);
}
d_add(dentry, inode);
return NULL;
}
/**
@brief 새로운 노드 생성
미사용
@param
struct inode *dir
struct dentry *dentry
int mode
dev_t dev
@return
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
static int mfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
#else
static int mfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
#endif
{
printk("\t\t\t\t\t\t\t\t\t\tMFS MKNOD\n");
struct inode * inode = mfs_get_inode(dir->i_sb, mode, dev);
int error = -ENOSPC;
printk("mfs_mknod\n");
if (inode) {
if (dir->i_mode & S_ISGID) {
inode->i_gid = dir->i_gid;
if (S_ISDIR(mode))
inode->i_mode |= S_ISGID;
}
d_instantiate(dentry, inode);
dget(dentry); /* Extra count - pin the dentry in core */
error = 0;
dir->i_mtime = dir->i_ctime = CURRENT_TIME;
/* real filesystems would normally use i_size_write function */
dir->i_size += 0x20; /* bogus small size for each dir entry */
}
return error;
}
/**
@brief 새로운 디렉토리 생성
inode로 들어오는 dir에 dentry->d_name.dname에 해당하는 디렉토리를 생성해준다.
@param
struct inode *dir 디렉토리를 생성할 디렉토리의 inode
struct dentry *dentry 생성할 디렉토리의 이름정보등이 담겨있는 dentry
int mode 현재 미사용
@return 0
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
static int mfs_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode)
#else
static int mfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
#endif
{
printk("\t\t\t\t\t\t\t\t\t\tMFS MKDIR\n");
char buf[512];
printk("mfs_mkdir %s\n", dentry->d_name.name);
get_dir_path_from_dentry(dentry, buf, 512);
__mfs_mkdir(dentry->d_sb->s_fs_info, buf, (ps16_t) dentry->d_name.name);
return 0;
}
/**
@brief 새로운 파일 생성
inode로 들어오는 dir에 dentry->d_name.dname에 해당하는 파일을 생성해준다.
@param
struct inode *dir 디렉토리를 생성할 디렉토리의 inode
struct dentry *dentry 생성할 파일의 이름정보등이 담겨있는 dentry
int mode 현재 미사용
struct nameidata *nd 현재 미사용
@return 0
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
static int mfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
static int mfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *nd)
#else
static int mfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
#endif
{
printk("\t\t\t\t\t\t\t\t\t\tMFS CREATE\n");
char path[512];
struct inode* inode = NULL;
printk("create \n");
get_dir_path_from_dentry(dentry, path, 512);
if (__mfs_create(dir->i_sb->s_fs_info, path, (ps16_t) dentry->d_name.name) == FALSE) {
printk("creation fail\n");
return 1;
}
inode = mfs_get_inode(dir->i_sb, S_IFREG, 0);
if (inode) {
inode->i_ino = 2;
dentry->d_inode = inode;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
d_instantiate(dentry, inode);
#endif
}
return 0;
}
/**
@brief 파일의 속성 조회
파일의 크기나 퍼미션등의 속성을 조회한다.
vfs에 기 구현되어있는 simple_getattr에 파일의 크기정보와 퍼미션을 설정
@param
struct vfsmount *mnt 마운트정보
struct dentry *dentry 속성을 조회할 파일의 이름정보등이 담겨있는 dentry
struct kstat *kstat 속성정보를 기록할 구조체
@return simple_getattr의 리턴값
*/
int mfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *kstat) {
printk("\t\t\t\t\t\t\t\t\t\tMFS GETATTR\n");
int ret;
s16_t full_path[512] = {0,};
s16_t route[128] = {0, };
s16_t file_name[64] = {0, };
int cluster_number;
void* volume = dentry->d_sb->s_fs_info;
struct mfs_dirent dentry_mfs;
get_file_path_from_dentry(dentry, full_path, 512);
printk("full_path: %s\n", full_path);
get_file_name(full_path, file_name);
get_dir_path(full_path, route);
cluster_number = get_cluster_number(volume, route);
printk("cluster number : %d\n", cluster_number);
get_dentry(volume, cluster_number, file_name, &dentry_mfs);
printk("mfs_getattr %s\n", dentry->d_name.name);
ret = simple_getattr(mnt, dentry, kstat);
printk("getattr ret : %d\n", ret);
kstat->size = dentry_mfs.size;
printk("mode - %d\n", kstat->mode);
kstat->mode|=0777;
return ret;
}
struct inode_operations mfs_file_inode_ops = {
.getattr = mfs_getattr,
};
struct inode_operations mfs_dir_inode_ops = {
.create = mfs_create,
.lookup = mfs_lookup,
.link = simple_link,
.unlink = simple_unlink,
.mkdir = mfs_mkdir,
.rmdir = simple_rmdir,
.mknod = mfs_mknod,
.rename = simple_rename,
.getattr = mfs_getattr,
};