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