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/fs.h>
14 #include <linux/msdos_fs.h>
15 #include <linux/errno.h>
16 #include <linux/fcntl.h>
17 #include <linux/stat.h>
18
19 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
20 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
21
22 static int msdos_file_read(struct inode *inode,struct file *filp,char *buf,
23 int count);
24 static int msdos_file_write(struct inode *inode,struct file *filp,char *buf,
25 int count);
26
27
28 static struct file_operations msdos_file_operations = {
29 NULL,
30 msdos_file_read,
31 msdos_file_write,
32 NULL,
33 NULL,
34 NULL,
35 NULL,
36 NULL,
37 NULL
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 };
57
58
59
60 struct inode_operations msdos_file_inode_operations_no_bmap = {
61 &msdos_file_operations,
62 NULL,
63 NULL,
64 NULL,
65 NULL,
66 NULL,
67 NULL,
68 NULL,
69 NULL,
70 NULL,
71 NULL,
72 NULL,
73 NULL,
74 msdos_truncate,
75 NULL
76 };
77
78
79 static int msdos_file_read(struct inode *inode,struct file *filp,char *buf,
80 int count)
81 {
82 char *start;
83 int left,offset,size,sector,cnt;
84 char ch;
85 struct buffer_head *bh;
86 void *data;
87
88
89 if (!inode) {
90 printk("msdos_file_read: inode = NULL\n");
91 return -EINVAL;
92 }
93 if (!S_ISREG(inode->i_mode)) {
94 printk("msdos_file_read: mode = %07o\n",inode->i_mode);
95 return -EINVAL;
96 }
97 if (filp->f_pos >= inode->i_size || count <= 0) return 0;
98 start = buf;
99 while ((left = MIN(inode->i_size-filp->f_pos,count-(buf-start))) > 0){
100 if (!(sector = msdos_smap(inode,filp->f_pos >> SECTOR_BITS)))
101 break;
102 offset = filp->f_pos & (SECTOR_SIZE-1);
103 if (!(bh = msdos_sread(inode->i_dev,sector,&data))) break;
104 filp->f_pos += (size = MIN(SECTOR_SIZE-offset,left));
105 if (MSDOS_I(inode)->i_binary) {
106 memcpy_tofs(buf,data+offset,size);
107 buf += size;
108 }
109 else for (cnt = size; cnt; cnt--) {
110 if ((ch = *((char *) data+offset++)) == '\r')
111 size--;
112 else {
113 if (ch != 26) put_fs_byte(ch,buf++);
114 else {
115 filp->f_pos = inode->i_size;
116 brelse(bh);
117 return buf-start;
118 }
119 }
120 }
121 brelse(bh);
122 }
123 if (start == buf) return -EIO;
124 return buf-start;
125 }
126
127
128 static int msdos_file_write(struct inode *inode,struct file *filp,char *buf,
129 int count)
130 {
131 int sector,offset,size,left,written;
132 int error,carry;
133 char *start,*to,ch;
134 struct buffer_head *bh;
135 void *data;
136
137 if (!inode) {
138 printk("msdos_file_write: inode = NULL\n");
139 return -EINVAL;
140 }
141 if (!S_ISREG(inode->i_mode)) {
142 printk("msdos_file_write: mode = %07o\n",inode->i_mode);
143 return -EINVAL;
144 }
145
146
147
148
149 if (filp->f_flags & O_APPEND) filp->f_pos = inode->i_size;
150 if (count <= 0) return 0;
151 error = carry = 0;
152 for (start = buf; count || carry; count -= size) {
153 while (!(sector = msdos_smap(inode,filp->f_pos >> SECTOR_BITS)))
154 if ((error = msdos_add_cluster(inode)) < 0) break;
155 if (error) {
156 msdos_truncate(inode);
157 break;
158 }
159 offset = filp->f_pos & (SECTOR_SIZE-1);
160 size = MIN(SECTOR_SIZE-offset,MAX(carry,count));
161 if (!(bh = msdos_sread(inode->i_dev,sector,&data))) {
162 error = -EIO;
163 break;
164 }
165 if (MSDOS_I(inode)->i_binary) {
166 memcpy_fromfs(data+(filp->f_pos & (SECTOR_SIZE-1)),
167 buf,written = size);
168 buf += size;
169 }
170 else {
171 written = left = SECTOR_SIZE-offset;
172 to = data+(filp->f_pos & (SECTOR_SIZE-1));
173 if (carry) {
174 *to++ = '\n';
175 left--;
176 carry = 0;
177 }
178 for (size = 0; size < count && left; size++) {
179 if ((ch = get_fs_byte(buf++)) == '\n') {
180 *to++ = '\r';
181 left--;
182 }
183 if (!left) carry = 1;
184 else {
185 *to++ = ch;
186 left--;
187 }
188 }
189 written -= left;
190 }
191 filp->f_pos += written;
192 if (filp->f_pos > inode->i_size) {
193 inode->i_size = filp->f_pos;
194 inode->i_dirt = 1;
195 }
196 bh->b_dirt = 1;
197 brelse(bh);
198 }
199 inode->i_mtime = inode->i_ctime = CURRENT_TIME;
200 MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
201 inode->i_dirt = 1;
202 return start == buf ? error : buf-start;
203 }
204
205
206 void msdos_truncate(struct inode *inode)
207 {
208 int cluster;
209
210 cluster = SECTOR_SIZE*MSDOS_SB(inode->i_sb)->cluster_size;
211 (void) fat_free(inode,(inode->i_size+(cluster-1))/cluster);
212 MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
213 inode->i_dirt = 1;
214 }