/
io.c
executable file
·143 lines (121 loc) · 3.44 KB
/
io.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
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "fs.h"
#include "dev.h"
#include "dir.h"
#include "fd.h"
#include "file.h"
#include "io.h"
#include "private.h"
#include "utils.h"
#include "alloc.h"
char *
kstrdup(const char *str) {
char *ret = kmalloc(strlen(str) + 1);
if (ret == NULL) return NULL;
strcpy(ret, str);
return ret;
}
void kprintf(int fd, const char *str) {
while(*str)
kwrite(fd, *str++);
}
int kwrite(int fd, char byte) {
char fbuf[256];
if (fd_table[fd] == NULL) {
sprintf(fbuf, "no such fd: %zu\r\n", fd);
kprintf(STDOUT, fbuf);
return -2;
}
int rv = fd_table[fd]->vn->ops->write(fd_table[fd]->vn, byte);
if (rv == 0 && fd_table[fd]->vn->fs->e_type == FS) fd_table[fd]->offset++;
return rv;
}
int kread(int fd, char *byte) {
char fbuf[256];
if (fd_table[fd] == NULL) {
sprintf(fbuf, "no such fd: %d\r\n", fd);
kprintf(STDOUT, fbuf);
return -2;
}
int rv = fd_table[fd]->vn->ops->read(fd_table[fd]->vn,
byte,
fd_table[fd]->offset);
if (rv == 0 && fd_table[fd]->vn->fs->e_type == FS) fd_table[fd]->offset++;
return rv;
}
int kremove(const char *path) {
if (is_dev(path)) return -1; /* devices can be only opened right now */
return file_remove(cwd, path);
}
int kcreate(const char *path) {
if (is_dev(path)) return -1; /* devices can be only opened right now */
char *fname = kstrdup(path);
if (fname == NULL) return -1; /* ENOMEM */
return file_create(cwd, REG, fname);
}
int mkdir (const char *path) {
if (is_dev(path)) return -1; /* devices can be only opened right now */
char *dirname = kstrdup(path);
if (dirname == NULL) return -1; /* ENOMEM */
return dir_create(cwd, REG, dirname);
}
int rmdir (const char *dirname) {
return 0;
}
int kopen(const char *path) {
struct vnode *vn = NULL;
int dev = is_dev(path);
int offset = dev ? NONSEEK : 0;
int next = get_fd();
if (next == -1) return -2; /* fd_table is full, can't open anything */
const char *name = (dev) ? path + 4 : path;
int err = (dev) ? dev_open(&vn, name) : file_open(&vn, name);
if (err) return -2; /* no such device or file */
fd_table[next] = fd_create(vn, offset);
if (fd_table[next] == NULL) return -2; /* ENOMEM */
/* logically this should be done in file_open, dev_open, dir_open, but
* complicates error handling */
vn->ref_count++;
return next;
}
int kclose(int fd) {
char fbuf[256];
if (fd_table[fd] == NULL) {
sprintf(fbuf, "fd #%d is not opened\r\n", fd);
kprintf(STDOUT, fbuf);
return -2;
}
fd_table[fd]->vn->ops->close(fd_table[fd]->vn);
fd_destroy(fd_table[fd]);
fd_table[fd] = NULL;
return 0;
}
int kls(void) {
return cwd->ops->stat(cwd);
}
int kpwd(void) {
if (cwd == NULL) return -1;
char fbuf[256];
sprintf(fbuf, "%s\r\n", cwd->fs->dir->name);
kprintf(STDOUT, fbuf);
return 0;
}
int kcd(const char *dir) {
if (!strcmp("..", dir)) {
if (!strcmp("/", cwd->fs->dir->name)) {
kprintf(STDOUT, "already at root\r\n");
} else {
cwd = cwd->fs->dir->parent;
}
return 0;
}
struct vnode *vn = dir_sub_lookup(cwd, dir);
if (vn == NULL) {
kprintf(STDOUT, "no such sub directory\r\n");
return -1;
}
cwd = vn;
return 0;
}