This source file includes following definitions.
- msdos_file_read
- msdos_file_write
- msdos_truncate
1
2
3
4
5
6
7
8
9 #include <asm/segment.h>
10 #include <asm/system.h>
11
12 #include <linux/sched.h>
13 #include <linux/locks.h>
14 #include <linux/fs.h>
15 #include <linux/msdos_fs.h>
16 #include <linux/errno.h>
17 #include <linux/fcntl.h>
18 #include <linux/stat.h>
19 #include <linux/string.h>
20
21 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
22 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
23
24 #define PRINTK(x)
25 #define Printk(x) printk x
26
27 static struct file_operations msdos_file_operations = {
28 NULL,
29 msdos_file_read,
30 msdos_file_write,
31 NULL,
32 NULL,
33 NULL,
34 generic_mmap,
35 NULL,
36 NULL,
37 file_fsync
38 };
39
40 struct inode_operations msdos_file_inode_operations = {
41 &msdos_file_operations,
42 NULL,
43 NULL,
44 NULL,
45 NULL,
46 NULL,
47 NULL,
48 NULL,
49 NULL,
50 NULL,
51 NULL,
52 NULL,
53 msdos_bmap,
54 msdos_truncate,
55 NULL,
56 NULL
57 };
58
59
60
61
62 int msdos_file_read(
63 struct inode *inode,
64 struct file *filp,
65 char *buf,
66 int count)
67 {
68 char *start;
69 int left,offset,size,cnt;
70 #define MSDOS_PREFETCH 48
71 struct {
72 int file_sector;
73
74 struct buffer_head *bhlist[MSDOS_PREFETCH];
75 int nblist;
76 int nolist;
77 int fetched_max;
78 }pre;
79 int i;
80
81
82 if (!inode) {
83 printk("msdos_file_read: inode = NULL\n");
84 return -EINVAL;
85 }
86
87 if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) {
88 printk("msdos_file_read: mode = %07o\n",inode->i_mode);
89 return -EINVAL;
90 }
91 if (filp->f_pos >= inode->i_size || count <= 0) return 0;
92
93
94
95
96
97
98
99
100
101 PRINTK (("#### ino %ld pos %ld size %ld count %d\n",inode->i_ino,filp->f_pos,inode->i_size,count));
102 {
103 struct buffer_head *bhreq[MSDOS_PREFETCH];
104
105 int nbreq;
106
107
108
109
110 int count_max = (filp->f_pos & (SECTOR_SIZE-1)) + count;
111 int to_reada;
112 pre.file_sector = filp->f_pos >> SECTOR_BITS;
113 to_reada = count_max / SECTOR_SIZE;
114 if (count_max & (SECTOR_SIZE-1)) to_reada++;
115 if (filp->f_reada){
116 int min_read = read_ahead[MAJOR(inode->i_dev)];
117 if (min_read > to_reada) to_reada = min_read;
118 }
119 if (to_reada > MSDOS_PREFETCH) to_reada = MSDOS_PREFETCH;
120 nbreq = pre.nblist = 0;
121 for (i=0; i<to_reada; i++){
122 int sector;
123 struct buffer_head *bh;
124 if (!(sector = msdos_smap(inode,pre.file_sector++))) break;
125 PRINTK (("fsector1 %d -> %d\n",pre.file_sector-1,sector));
126 bh = getblk(inode->i_dev,sector,SECTOR_SIZE);
127 if (bh == NULL) break;
128 pre.bhlist[pre.nblist++] = bh;
129 if (!bh->b_uptodate){
130 bhreq[nbreq++] = bh;
131 }
132 }
133 pre.fetched_max = pre.file_sector * SECTOR_SIZE;
134 if (nbreq > 0) ll_rw_block (READ,nbreq,bhreq);
135 }
136 start = buf;
137 pre.nolist = 0;
138 while ((left = MIN(inode->i_size-filp->f_pos,count-(buf-start))) > 0){
139 struct buffer_head *bh = pre.bhlist[pre.nolist];
140 char *data;
141 if (bh == NULL) break;
142 PRINTK (("file_read pos %ld nblist %d %d %d\n",filp->f_pos,pre.nblist,pre.fetched,count));
143 pre.bhlist[pre.nolist] = NULL;
144 if (left + filp->f_pos > pre.fetched_max){
145 int sector;
146 if ((sector = msdos_smap(inode,pre.file_sector++))){
147 struct buffer_head *bhreq[1];
148 PRINTK (("fsector2 %d -> %d\n",pre.file_sector-1,sector));
149 bhreq[0] = getblk(inode->i_dev,sector,SECTOR_SIZE);
150 if (bhreq[0] == NULL) break;
151 pre.bhlist[pre.nolist] = bhreq[0];
152 if (!bhreq[0]->b_uptodate)
153 ll_rw_block (READ,1,bhreq);
154 pre.fetched_max += SECTOR_SIZE;
155 }else{
156
157 pre.fetched_max = 2000000000l;
158 }
159 }
160 pre.nolist++;
161 if (pre.nolist >= pre.nblist) pre.nolist = 0;
162 wait_on_buffer(bh);
163 if (!bh->b_uptodate){
164
165 brelse (bh);
166 break;
167 }
168 offset = filp->f_pos & (SECTOR_SIZE-1);
169 filp->f_pos += (size = MIN(SECTOR_SIZE-offset,left));
170 data = bh->b_data;
171 if (MSDOS_I(inode)->i_binary) {
172 memcpy_tofs(buf,data+offset,size);
173 buf += size;
174 }
175 else for (cnt = size; cnt; cnt--) {
176 char ch;
177 if ((ch = *((char *) data+offset++)) == '\r')
178 size--;
179 else {
180 if (ch != 26) put_fs_byte(ch,buf++);
181 else {
182 filp->f_pos = inode->i_size;
183 brelse(bh);
184 break;
185 }
186 }
187 }
188 brelse(bh);
189 }
190 PRINTK (("--- %d -> %d\n",count,(int)(buf-start)));
191 for (i=0; i<pre.nblist; i++) brelse (pre.bhlist[i]);
192 if (start == buf) return -EIO;
193 if (!IS_RDONLY(inode))
194 inode->i_atime = CURRENT_TIME;
195 PRINTK (("file_read ret %d\n",(buf-start)));
196 filp->f_reada = 1;
197 return buf-start;
198 }
199
200
201
202
203 int msdos_file_write(
204 struct inode *inode,
205 struct file *filp,
206 char *buf,
207 int count)
208 {
209 int sector,offset,size,left,written;
210 int error,carry;
211 char *start,*to,ch;
212 struct buffer_head *bh;
213 int binary_mode = MSDOS_I(inode)->i_binary;
214
215 if (!inode) {
216 printk("msdos_file_write: inode = NULL\n");
217 return -EINVAL;
218 }
219
220 if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) {
221 printk("msdos_file_write: mode = %07o\n",inode->i_mode);
222 return -EINVAL;
223 }
224
225
226
227
228 if (filp->f_flags & O_APPEND) filp->f_pos = inode->i_size;
229 if (count <= 0) return 0;
230 error = carry = 0;
231 for (start = buf; count || carry; count -= size) {
232 while (!(sector = msdos_smap(inode,filp->f_pos >> SECTOR_BITS)))
233 if ((error = msdos_add_cluster(inode)) < 0) break;
234 if (error) {
235 msdos_truncate(inode);
236 break;
237 }
238 offset = filp->f_pos & (SECTOR_SIZE-1);
239 size = MIN(SECTOR_SIZE-offset,MAX(carry,count));
240 if (binary_mode
241 && offset == 0
242 && (size == SECTOR_SIZE
243 || filp->f_pos + size >= inode->i_size)){
244
245
246
247 if (!(bh = getblk(inode->i_dev,sector,SECTOR_SIZE))){
248 error = -EIO;
249 break;
250 }
251 }else if (!(bh = msdos_sread(inode->i_dev,sector))) {
252 error = -EIO;
253 break;
254 }
255 if (binary_mode) {
256 memcpy_fromfs(bh->b_data+offset,buf,written = size);
257 buf += size;
258 }
259 else {
260 written = left = SECTOR_SIZE-offset;
261 to = (char *) bh->b_data+(filp->f_pos & (SECTOR_SIZE-1));
262 if (carry) {
263 *to++ = '\n';
264 left--;
265 carry = 0;
266 }
267 for (size = 0; size < count && left; size++) {
268 if ((ch = get_fs_byte(buf++)) == '\n') {
269 *to++ = '\r';
270 left--;
271 }
272 if (!left) carry = 1;
273 else {
274 *to++ = ch;
275 left--;
276 }
277 }
278 written -= left;
279 }
280 filp->f_pos += written;
281 if (filp->f_pos > inode->i_size) {
282 inode->i_size = filp->f_pos;
283 inode->i_dirt = 1;
284 }
285 bh->b_uptodate = 1;
286 mark_buffer_dirty(bh, 0);
287 brelse(bh);
288 }
289 if (start == buf)
290 return error;
291 inode->i_mtime = inode->i_ctime = CURRENT_TIME;
292 MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
293 inode->i_dirt = 1;
294 return buf-start;
295 }
296
297 void msdos_truncate(struct inode *inode)
298 {
299 int cluster;
300
301 cluster = SECTOR_SIZE*MSDOS_SB(inode->i_sb)->cluster_size;
302 (void) fat_free(inode,(inode->i_size+(cluster-1))/cluster);
303 MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
304 inode->i_dirt = 1;
305 }