Two fixes
[tfsprogs.git] / file.c
blob4979e2b799fba29b77c1d87ed22f60ade593dea6
1 #include <stdio.h>
2 #include <string.h>
3 #include <malloc.h>
5 #include "tfs.h"
6 #include "cache.h"
7 #include "file.h"
10 struct file *tfs_open(struct tfs_sb_info *sbi, const char *filename, uint32_t flag)
12 struct inode *inode;
13 struct file *file;
15 inode = tfs_namei(sbi, filename, flag);
16 if (!inode) {
17 printf("ERROR: open file: %s falied!\n", filename);
18 return NULL;
21 file = malloc(sizeof(*file));
22 if (!file) {
23 printf("malloc file structure error!\n");
24 free_inode(inode);
25 return NULL;
28 file->sbi = sbi;
29 file->inode = inode;
30 file->offset = 0;
32 return file;
35 uint32_t fstk_lseek(struct file *file, uint32_t off, int mode)
37 if (mode == SEEK_CUR)
38 file->offset += off;
39 else if (mode == SEEK_END)
40 file->offset = file->inode->i_size + off;
41 else if (mode == SEEK_SET)
42 file->offset = off;
43 else
44 file->offset = -1;
45 return file->offset;
48 int tfs_read(struct file *file, void *buf, uint32_t count)
50 struct tfs_sb_info *sbi = file->sbi;
51 int blocks = roundup(count, sbi->s_block_size);
52 int index = file->offset >> sbi->s_block_shift;
53 int block = file->inode->i_data[index++];
54 int bufoff = file->offset & (sbi->s_block_size - 1);
55 int bytes_read = 0;
57 if (!blocks)
58 return -1;
59 if (!block)
60 return -1;
61 if (file->offset >= file->inode->i_size)
62 return -1;
63 tfs_bread(sbi, block, buf);
64 bytes_read = sbi->s_block_size - bufoff;
65 memcpy(buf, buf + bufoff, bytes_read);
66 buf += bytes_read;
67 file->offset += bytes_read;
68 blocks--;
70 while (blocks--) {
71 block = file->inode->i_data[index++];
72 if (!block)
73 break;
74 tfs_bread(sbi, block, buf);
75 bytes_read += sbi->s_block_size;
76 file->offset += sbi->s_block_size;
77 buf += sbi->s_block_size;
80 return bytes_read;
84 #define min(a, b) ((a) < (b) ? a : b)
85 int tfs_write(struct file *file, void *buf, uint32_t count)
87 struct tfs_sb_info *sbi = file->sbi;
88 struct cache_struct *cs;
89 int blocks = roundup(count, sbi->s_block_size);
90 int index = file->offset >> sbi->s_block_shift;
91 int block;
92 int bufoff = file->offset & (sbi->s_block_size - 1);
93 int bytes_written = 0;
96 if (!blocks)
97 return -1;
99 block = tfs_bmap(file->inode, index++);
100 if (!block) {
101 if (index - 1 < TFS_N_BLOCKS) {
102 block = tfs_alloc_block(sbi, sbi->s_data_area);
103 if (block == -1) {
104 printf("allocating block for new file faile! OUT OF SPACE!\n");
105 return -1;
107 file->inode->i_data[index - 1] = block;
108 } else {
109 /* file too big */
110 return -1;
113 cs = get_cache_block(sbi, block);
114 bytes_written = min(sbi->s_block_size, count) - bufoff;
115 memcpy(cs->data + bufoff, buf, bytes_written);
116 buf += bytes_written;
117 file->offset += bytes_written;
118 count -= bytes_written;
119 file->inode->i_size += bytes_written;
120 /* write back to disk */
121 if (tfs_bwrite(sbi, block, cs->data) == -1) {
122 printf("disk I/O error:failed to write file data back to disk!\n");
123 goto err;
125 blocks--;
127 while (blocks--) {
128 int bytes_need;
129 block = tfs_bmap(file->inode, index++);
130 if (!block) {
131 if (index - 1 < TFS_N_BLOCKS) {
132 block = tfs_alloc_block(sbi, sbi->s_data_area);
133 if (block == -1) {
134 printf("allocating block for new file faile: out of space!\n");
135 goto err;
137 file->inode->i_data[index - 1] = block;
138 } else {
139 /* fle too big */
140 goto err;
143 bytes_need = min(sbi->s_block_size, count);
144 cs = get_cache_block(sbi, block);
145 memcpy(cs->data, buf, bytes_need);
146 bytes_written += bytes_need;
147 file->offset += bytes_need;
148 buf += bytes_need;
149 file->inode->i_size += bytes_need;
150 if (tfs_bwrite(sbi, block, cs->data) == -1) {
151 printf("disk I/O error:failed to write file data back to disk!\n");
152 goto err;
156 done:
157 tfs_iwrite(sbi, file->inode);
159 return bytes_written;
161 err:
162 bytes_written = -1;
163 goto done;
166 void tfs_close(struct file *file)
168 if (file) {
169 free_inode(file->inode);
170 free(file);