kbd: use a better get_key method
[thunix.git] / fs / file.c
blobb7c74c9df8e555597c80fef280147aa46bb5fbf6
1 #include <stdio.h>
2 #include <stdint.h>
3 #include <string.h>
4 #include <malloc.h>
5 #include <fs.h>
6 #include <err.h>
8 #define MAX_FD 32
9 uint8_t fds[MAX_FD] = {0,0,0};
10 struct file *files[MAX_FD] = {NULL, };
12 static int get_unused_fd(void)
14 int i;
16 for (i = 0; i < MAX_FD; i++) {
17 if (fds[i] == 0)
18 break;
21 if (i < MAX_FD)
22 fds[i] = 1;
24 return i;
27 int sys_open(const char *pathname, uint32_t flags)
29 struct inode *inode = namei(pathname, flags);
30 struct file *file;
31 int fd;
33 if (IS_ERR_OR_NULL(inode))
34 return inode ? PTR_ERR(inode) : -ENOENT;
36 FS_DEBUG("%s: namei returned successfully!\n", __FUNCTION__);
38 file = malloc(sizeof(*file));
39 if (!file)
40 return -ENOMEM;
41 file->inode = inode;
42 file->fs = inode->i_fs;
43 file->offset = 0;
44 file->f_op = inode->i_fop;
46 fd = get_unused_fd();
47 if (fd >= MAX_FD) {
48 printk("You opened two much files!\n");
49 free(file);
50 return -EINVAL;
52 files[fd] = file;
54 return fd;
57 static inline struct file *fget(int fd)
59 return files[fd];
62 int sys_read(int fd, void *buf, int size)
64 struct file *file;
65 struct inode *inode;
66 int blocks;
67 int bytes_need;
68 int bytes_read;
70 if (fd < 0 || fd > MAX_FD)
71 return -EBADF;
73 file = fget(fd);
74 if (!file)
75 return -EBADF;
77 inode = file->inode;
78 bytes_need = MIN(size, inode->i_size - file->offset);
79 blocks = (bytes_need + inode->i_blksize - 1) >> file->fs->block_shift;
81 bytes_read = file->f_op->read(file, buf, blocks);
82 bytes_read = MIN(bytes_need, bytes_read);
83 if (bytes_read > 0) {
84 memmove(buf, buf + (file->offset & (inode->i_blksize - 1)), bytes_read);
85 file->offset += bytes_read;
88 return bytes_read;
91 int sys_write(int fd, void *buf, int size)
93 struct file *file;
94 int blocks;
95 int bytes_written;
97 if (fd < 0 || fd > MAX_FD)
98 return -EBADF;
99 file = fget(fd);
100 if (!file)
101 return -EBADF;
103 blocks = (size + file->inode->i_blksize - 1) >> file->fs->block_shift;
105 bytes_written = file->f_op->write(file, buf, blocks);
106 bytes_written = MIN(size, bytes_written);
107 if (bytes_written > 0)
108 file->offset += bytes_written;
110 return bytes_written;
113 int sys_close(int fd)
115 struct file *file;
117 if (fd < 0 || fd > MAX_FD)
118 return -EBADF;
120 file = fget(fd);
121 if (!file)
122 return -EBADF;
124 free_inode(file->inode);
125 fds[fd] = 0;
126 files[fd] = NULL;
127 free(file);
128 return 0;
131 int sys_lseek(int fd, int off, int mode)
133 struct file *file;
135 if (fd < 0 || fd > MAX_FD)
136 return -EBADF;
138 file = fget(fd);
139 if (!file)
140 return -EBADF;
142 if (mode == SEEK_CUR)
143 file->offset += off;
144 else if (mode == SEEK_END)
145 file->offset = file->inode->i_size + off;
146 else if (mode == SEEK_SET)
147 file->offset = off;
148 else
149 return -EINVAL;
151 return file->offset;