This source file includes following definitions.
- unixify_to_fs
- isofs_determine_filetype
- isofs_file_read
1
2
3
4
5
6
7
8
9
10
11 #include <linux/sched.h>
12 #include <linux/iso_fs.h>
13 #include <linux/fcntl.h>
14 #include <linux/kernel.h>
15 #include <linux/errno.h>
16 #include <linux/stat.h>
17 #include <linux/locks.h>
18
19 #include <asm/segment.h>
20 #include <asm/system.h>
21
22 #define NBUF 32
23
24 #define MIN(a,b) (((a)<(b))?(a):(b))
25 #define MAX(a,b) (((a)>(b))?(a):(b))
26
27 #include <linux/fs.h>
28 #include <linux/iso_fs.h>
29
30 static int isofs_file_read(struct inode *, struct file *, char *, int);
31
32
33
34
35
36 static struct file_operations isofs_file_operations = {
37 NULL,
38 isofs_file_read,
39 NULL,
40 NULL,
41 NULL,
42 NULL,
43 generic_mmap,
44 NULL,
45 NULL,
46 NULL
47 };
48
49 struct inode_operations isofs_file_inode_operations = {
50 &isofs_file_operations,
51 NULL,
52 NULL,
53 NULL,
54 NULL,
55 NULL,
56 NULL,
57 NULL,
58 NULL,
59 NULL,
60 NULL,
61 NULL,
62 isofs_bmap,
63 NULL,
64 NULL
65 };
66
67
68
69
70
71
72
73 static inline void unixify_to_fs(char * outbuf, char * buffer, int chars,
74 int mode)
75 {
76 char outchar;
77
78 while(chars--){
79 outchar = *buffer;
80 if(outchar == 0x1a) outchar = 0x0a;
81 if(outchar == 0x0d){
82 if(mode == ISOFS_FILE_TEXT_M) outchar = 0x0a;
83 if(mode == ISOFS_FILE_TEXT) outchar = ' ';
84 }
85 put_user(outchar, outbuf++);
86 buffer++;
87 }
88 }
89
90
91
92 static void isofs_determine_filetype(struct inode * inode)
93 {
94 int block;
95 int result, i;
96 struct buffer_head * bh;
97 unsigned char * pnt;
98
99 block = isofs_bmap(inode,0);
100 if (block && (bh = bread(inode->i_dev,block, ISOFS_BUFFER_SIZE(inode)))) {
101 pnt = (unsigned char *) bh->b_data;
102 result = ISOFS_FILE_TEXT_M;
103 for(i=0;i<(inode->i_size < ISOFS_BUFFER_SIZE(inode) ? inode->i_size : ISOFS_BUFFER_SIZE(inode));
104 i++,pnt++){
105 if(*pnt & 0x80) {result = ISOFS_FILE_BINARY; break;};
106 if(*pnt >= 0x20 || *pnt == 0x1a) continue;
107 if(*pnt == 0x0a) {result = ISOFS_FILE_TEXT; continue;};
108 if(*pnt >= 0x9 && *pnt <= 0x0d) continue;
109 result = ISOFS_FILE_BINARY;
110 break;
111 }
112 brelse(bh);
113 inode->u.isofs_i.i_file_format = result;
114 }
115 }
116
117 static int isofs_file_read(struct inode * inode, struct file * filp, char * buf, int count)
118 {
119 int read,left,chars;
120 int block, blocks, offset, total_blocks;
121 int bhrequest;
122 int ra_blocks, max_block, nextblock;
123 struct buffer_head ** bhb, ** bhe;
124 struct buffer_head * bhreq[NBUF];
125 struct buffer_head * buflist[NBUF];
126
127 if (!inode) {
128 printk("isofs_file_read: inode = NULL\n");
129 return -EINVAL;
130 }
131 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
132 printk("isofs_file_read: mode = %07o\n",inode->i_mode);
133 return -EINVAL;
134 }
135 if (inode->u.isofs_i.i_file_format == ISOFS_FILE_UNKNOWN)
136 isofs_determine_filetype(inode);
137 if (filp->f_pos > inode->i_size)
138 left = 0;
139 else
140 left = inode->i_size - filp->f_pos;
141 if (left > count)
142 left = count;
143 if (left <= 0)
144 return 0;
145 read = 0;
146 block = filp->f_pos >> ISOFS_BUFFER_BITS(inode);
147 offset = (inode->u.isofs_i.i_first_extent + filp->f_pos)
148 & (ISOFS_BUFFER_SIZE(inode)-1);
149 blocks = (left + offset + ISOFS_BUFFER_SIZE(inode) - 1) / ISOFS_BUFFER_SIZE(inode);
150 bhb = bhe = buflist;
151
152 ra_blocks = read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9);
153 if(ra_blocks > blocks) blocks = ra_blocks;
154
155
156
157
158
159
160
161
162 total_blocks = (inode->i_size + (1 << ISOFS_BUFFER_BITS(inode)) - 1)
163 >> ISOFS_BUFFER_BITS(inode);
164 if (block + blocks > total_blocks)
165 blocks = total_blocks - block;
166
167 max_block = (inode->i_size + BLOCK_SIZE - 1)/BLOCK_SIZE;
168 nextblock = -1;
169
170
171
172
173
174
175
176
177
178
179
180 do {
181 bhrequest = 0;
182 while (blocks) {
183 int uptodate;
184 --blocks;
185 *bhb = getblk(inode->i_dev,isofs_bmap(inode, block++), ISOFS_BUFFER_SIZE(inode));
186 uptodate = 1;
187 if (*bhb && !buffer_uptodate(*bhb)) {
188 uptodate = 0;
189 bhreq[bhrequest++] = *bhb;
190 };
191
192 if (++bhb == &buflist[NBUF])
193 bhb = buflist;
194
195
196
197 if(uptodate) break;
198
199 if (bhb == bhe)
200 break;
201 }
202
203
204 if (bhrequest)
205 ll_rw_block(READ, bhrequest, bhreq);
206
207 do{
208 if (*bhe) {
209 wait_on_buffer(*bhe);
210 if (!buffer_uptodate(*bhe)) {
211 brelse(*bhe);
212 if (++bhe == &buflist[NBUF])
213 bhe = buflist;
214 left = 0;
215 break;
216 }
217 }
218
219 if (left < ISOFS_BUFFER_SIZE(inode) - offset)
220 chars = left;
221 else
222 chars = ISOFS_BUFFER_SIZE(inode) - offset;
223 filp->f_pos += chars;
224 left -= chars;
225 read += chars;
226 if (*bhe) {
227 if (inode->u.isofs_i.i_file_format == ISOFS_FILE_TEXT ||
228 inode->u.isofs_i.i_file_format == ISOFS_FILE_TEXT_M)
229 unixify_to_fs(buf, offset+(*bhe)->b_data, chars,
230 inode->u.isofs_i.i_file_format);
231 else
232 memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
233 brelse(*bhe);
234 buf += chars;
235 } else {
236 while (chars-->0)
237 put_user(0,buf++);
238 }
239 offset = 0;
240 if (++bhe == &buflist[NBUF])
241 bhe = buflist;
242 } while( bhe != bhb && (*bhe == 0 || !buffer_locked(*bhe)) &&
243 (left > 0));
244 } while (left > 0);
245
246
247 while (bhe != bhb) {
248 if (*bhe) brelse(*bhe);
249 if (++bhe == &buflist[NBUF])
250 bhe = buflist;
251 };
252
253 filp->f_reada = 1;
254
255 if (!read)
256 return -EIO;
257 return read;
258 }