-
Notifications
You must be signed in to change notification settings - Fork 46
/
open_close.c
154 lines (130 loc) · 3.81 KB
/
open_close.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
#include <fs/fs.h>
#include <kernel/clock.h>
int filp_close(struct filp* filp){
return filp->filp_dev->fops->close(filp->filp_dev, filp);
}
int sys_close(struct proc *who, int fd)
{
filp_t *filp;
int ret;
if (!is_fd_opened_and_valid(who, fd))
return -EBADF;
filp = who->fp_filp[fd];
ret = filp_close(filp);
if (ret)
return ret;
who->fp_filp[fd] = NULL;
return 0;
}
int alloc_inode_under_dir(struct proc* who, struct device* dev, inode_t** _inode, inode_t* lastdir, char string[WINIX_NAME_LEN]){
inode_t* inode;
int ret;
dev = lastdir->i_dev;
inode = alloc_inode(dev, dev);
if (!inode)
return -ENOSPC;
// kprintf("creating %s with ino %d\n", string, inode->i_num);
if ((ret = add_inode_to_directory(who, lastdir, inode, string)))
{
release_inode(inode);
return ret;
}
*_inode = inode;
return 0;
}
int filp_open(struct proc* who, struct filp** _filp, const char *path, int flags, mode_t mode){
filp_t *filp;
int ret;
inode_t *inode = NULL, *lastdir = NULL;
char string[WINIX_NAME_LEN];
struct device *dev;
clock_t unix_time = get_unix_time();
bool is_new = false;
if ((ret = eat_path(who, path, &lastdir, &inode, string)))
return ret;
dev = lastdir->i_dev;
if (inode){
if ((flags & O_EXCL) && (flags & O_CREAT))
{
ret = -EEXIST;
goto final;
}
}else{
if (*string){ // if there still components left in path
if (!(flags & O_CREAT))
{
ret = -ENOENT;
goto final;
}
if ((ret = alloc_inode_under_dir(who, dev, &inode, lastdir, string)))
goto final;
init_inode_proc_field(inode, who, dev->device_type, mode);
is_new = true;
}else{ // if no components left, then path refers to the directory
// if opening a directory with write access, EISDIR is returned
if (flags & O_WRONLY)
{
ret = -EISDIR;
goto final;
}
inode = lastdir;
}
}
filp = get_free_filp();
if (!filp)
return -ENFILE;
if(flags & O_TRUNC)
truncate_inode(inode);
init_filp_by_inode(filp, inode);
if(flags & O_APPEND)
filp->filp_pos = inode->i_size;
filp->filp_mode = mode;
filp->filp_flags = flags;
inode->i_atime = unix_time;
if ((ret = inode->i_dev->fops->open(inode->i_dev, filp)))
goto final;
*_filp = filp;
// kdebug("Open: path %s Last dir %d, ret inode %d dev %u\n", path, lastdir->i_num, inode->i_num, inode->i_dev->dev_id);
final:
put_inode(lastdir, is_new);
return ret;
}
int sys_open(struct proc *who, const char *path, int flags, mode_t mode)
{
int open_slot, ret;
struct filp* filp;
ret = filp_open(who, &filp, path, flags, mode);
if(ret)
return ret;
if ((ret = get_fd(who, 0, &open_slot, filp)))
{
filp_close(filp);
return ret;
}
who->fp_filp[open_slot] = filp;
return open_slot;
}
int sys_creat(struct proc *who, const char* path, mode_t mode)
{
return sys_open(who, path, O_CREAT | O_EXCL, mode);
}
int do_open(struct proc *who, struct message *msg)
{
char *path;
if(!is_vaddr_accessible(msg->m1_p1, who))
return -EFAULT;
path = (char *)get_physical_addr(msg->m1_p1, who);
return sys_open(who, path, msg->m1_i1, msg->m1_i2);
}
int do_creat(struct proc *who, struct message *msg)
{
char *path;
if(!is_vaddr_accessible(msg->m1_p1, who))
return -EFAULT;
path = (char *)get_physical_addr(msg->m1_p1, who);
return sys_creat(who, path, msg->m1_i1);
}
int do_close(struct proc *who, struct message *msg)
{
return sys_close(who, msg->m1_i1);
}