kbd: use a better get_key method
[thunix.git] / fs / tfs / file.c
blob286be706cfb04c49a43423077e811544f6c0449f
1 #include <stdio.h>
2 #include <string.h>
3 #include <malloc.h>
4 #include <err.h>
5 #include <fs.h>
6 #include <tfs.h>
7 #include <cache.h>
8 #include <dirent.h>
10 int tfs_read(struct file *file, void *buf, int blocks)
12 struct tfs_sb_info *sbi = TFS_SBI(file->fs);
13 struct cache_struct *cs;
14 uint32_t block;
15 int index = file->offset >> sbi->s_block_shift;
16 int bytes_read = 0;
18 TFS_DEBUG("rbuf: %p, blocks: %d, offset: %d\n", buf, blocks, file->offset);
20 if (!blocks)
21 return 0;
22 if (file->offset >= file->inode->i_size)
23 return -1;
25 while (blocks--) {
26 block = tfs_bmap(file->inode, index++);
27 if (!block)
28 break;
29 cs = get_cache_block(file->fs, block);
30 if (!cs)
31 return -EIO;
32 memcpy(buf, cs->data, sbi->s_block_size);
33 bytes_read += sbi->s_block_size;
34 buf += sbi->s_block_size;
37 return bytes_read;
41 #define min(a, b) ((a) < (b) ? a : b)
42 int tfs_write(struct file *file, void *buf, int blocks)
44 struct tfs_sb_info *sbi = TFS_SBI(file->fs);
45 struct cache_struct *cs;
46 int index = file->offset >> sbi->s_block_shift;
47 int block;
48 int bufoff = file->offset & (sbi->s_block_size - 1);
49 int bytes_written = 0;
51 TFS_DEBUG("wbuf: %p, blocks: %d, offset: %d\n", buf, blocks, file->offset);
53 if (!blocks)
54 return 0;
56 block = tfs_bmap(file->inode, index++);
57 if (!block) {
58 if (index - 1 < TFS_N_BLOCKS) {
59 block = tfs_alloc_block(sbi, sbi->s_data_area);
60 if (block < 0)
61 return -ENOSPC;
62 file->inode->i_data[index - 1] = block;
63 } else {
64 /* file too big */
65 return -EFBIG;
68 cs = get_cache_block(file->fs, block);
69 if (!cs)
70 return -EIO;
71 bytes_written = sbi->s_block_size - bufoff;
72 memmove(cs->data + bufoff, buf, bytes_written);
73 buf += bytes_written;
74 file->inode->i_size += MAX(0, file->offset + bytes_written - file->inode->i_size);
75 /* write back to disk */
76 if (tfs_bwrite(sbi, block, cs->data))
77 return -EIO;
79 blocks--;
80 while (blocks--) {
81 int bytes_need;
82 block = tfs_bmap(file->inode, index++);
83 if (!block) {
84 if (index - 1 < TFS_N_BLOCKS) {
85 block = tfs_alloc_block(sbi, sbi->s_data_area);
86 if (block < 0)
87 return -ENOSPC;
88 file->inode->i_data[index - 1] = block;
89 } else {
90 /* fle too big */
91 return -EFBIG;
94 bytes_need = sbi->s_block_size;
95 cs = get_cache_block(file->fs, block);
96 if (!cs)
97 return -EIO;
98 memcpy(cs->data, buf, bytes_need);
99 bytes_written += bytes_need;
100 buf += bytes_need;
101 file->inode->i_size += MAX(0, file->offset + bytes_written - file->inode->i_size);
102 if (tfs_bwrite(sbi, block, cs->data))
103 return -EIO;
106 if (tfs_iwrite(file->inode))
107 return -EIO;
109 return bytes_written;
112 void tfs_close(struct file *file)
114 if (file) {
115 free_inode(file->inode);
116 free(file);
120 struct file_operations tfs_file_ops = {
121 .read = tfs_read,
122 .write = tfs_write,
123 .close = tfs_close,
124 .readdir = tfs_readdir