This source file includes following definitions.
- isofs_put_super
- parse_options
- isofs_read_super
- isofs_statfs
- isofs_bmap
- isofs_read_inode
- isofs_lookup_grandparent
- leak_check_malloc
- leak_check_free_s
- leak_check_bread
- leak_check_brelse
1
2
3
4
5
6
7
8 #include <linux/config.h>
9 #include <linux/stat.h>
10 #include <linux/sched.h>
11 #include <linux/iso_fs.h>
12 #include <linux/kernel.h>
13 #include <linux/mm.h>
14 #include <linux/string.h>
15 #include <linux/locks.h>
16
17 #include <asm/system.h>
18 #include <asm/segment.h>
19 #include <linux/errno.h>
20
21 extern int check_cdrom_media_change(int, int);
22
23 #ifdef LEAK_CHECK
24 static int check_malloc = 0;
25 static int check_bread = 0;
26 #endif
27
28 void isofs_put_super(struct super_block *sb)
29 {
30 lock_super(sb);
31
32 #ifdef LEAK_CHECK
33 printk("Outstanding mallocs:%d, outstanding buffers: %d\n",
34 check_malloc, check_bread);
35 #endif
36 sb->s_dev = 0;
37 unlock_super(sb);
38 return;
39 }
40
41 static struct super_operations isofs_sops = {
42 isofs_read_inode,
43 NULL,
44 NULL,
45 NULL,
46 isofs_put_super,
47 NULL,
48 isofs_statfs
49 };
50
51
52
53 static int parse_options(char *options,char *map,char *conversion, char * rock, char * cruft)
54 {
55 char *this,*value;
56
57 *map = 'n';
58 *rock = 'y';
59 *cruft = 'n';
60 *conversion = 'a';
61 if (!options) return 1;
62 for (this = strtok(options,","); this; this = strtok(NULL,",")) {
63 if (strncmp(this,"norock",6) == 0) {
64 *rock = 'n';
65 continue;
66 };
67 if (strncmp(this,"cruft",5) == 0) {
68 *cruft = 'y';
69 continue;
70 };
71 if ((value = strchr(this,'=')) != NULL)
72 *value++ = 0;
73 if (!strcmp(this,"map") && value) {
74 if (value[0] && !value[1] && strchr("on",*value))
75 *map = *value;
76 else if (!strcmp(value,"off")) *map = 'o';
77 else if (!strcmp(value,"normal")) *map = 'n';
78 else return 0;
79 }
80 else if (!strcmp(this,"conv") && value) {
81 if (value[0] && !value[1] && strchr("bta",*value))
82 *conversion = *value;
83 else if (!strcmp(value,"binary")) *conversion = 'b';
84 else if (!strcmp(value,"text")) *conversion = 't';
85 else if (!strcmp(value,"mtext")) *conversion = 'm';
86 else if (!strcmp(value,"auto")) *conversion = 'a';
87 else return 0;
88 }
89 else return 0;
90 }
91 return 1;
92 }
93
94 struct super_block *isofs_read_super(struct super_block *s,void *data)
95 {
96 struct buffer_head *bh;
97 int iso_blknum;
98 int high_sierra;
99 int dev=s->s_dev;
100 struct iso_volume_descriptor *vdp;
101 struct hs_volume_descriptor *hdp;
102
103 struct iso_primary_descriptor *pri = NULL;
104 struct hs_primary_descriptor *h_pri = NULL;
105
106 struct iso_directory_record *rootp;
107
108 char map, conversion, rock, cruft;
109
110 if (!parse_options((char *) data,&map,&conversion, &rock, &cruft)) {
111 s->s_dev = 0;
112 return NULL;
113 }
114
115 lock_super(s);
116
117 s->u.isofs_sb.s_high_sierra = high_sierra = 0;
118
119 for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
120 if (!(bh = bread(dev, iso_blknum << (ISOFS_BLOCK_BITS-ISOFS_BUFFER_BITS), ISOFS_BUFFER_SIZE))) {
121 s->s_dev=0;
122 printk("isofs_read_super: bread failed, dev 0x%x iso_blknum %d\n",
123 dev, iso_blknum);
124 unlock_super(s);
125 return NULL;
126 }
127
128 vdp = (struct iso_volume_descriptor *)bh->b_data;
129 hdp = (struct hs_volume_descriptor *)bh->b_data;
130
131
132 if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) {
133 if (isonum_711 (hdp->type) != ISO_VD_PRIMARY)
134 goto out;
135 if (isonum_711 (hdp->type) == ISO_VD_END)
136 goto out;
137
138 s->u.isofs_sb.s_high_sierra = 1;
139 high_sierra = 1;
140 rock = 'n';
141 h_pri = (struct hs_primary_descriptor *)vdp;
142 break;
143 };
144
145 if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) {
146 if (isonum_711 (vdp->type) != ISO_VD_PRIMARY)
147 goto out;
148 if (isonum_711 (vdp->type) == ISO_VD_END)
149 goto out;
150
151 pri = (struct iso_primary_descriptor *)vdp;
152 break;
153 };
154
155 brelse(bh);
156 }
157 if(iso_blknum == 100) {
158 printk("Unable to identify CD-ROM format.\n");
159 s->s_dev = 0;
160 unlock_super(s);
161 return NULL;
162 };
163
164
165 if(high_sierra){
166 rootp = (struct iso_directory_record *) h_pri->root_directory_record;
167 if (isonum_723 (h_pri->volume_set_size) != 1) {
168 printk("Multi-volume disks not (yet) supported.\n");
169 goto out;
170 };
171 s->u.isofs_sb.s_nzones = isonum_733 (h_pri->volume_space_size);
172 s->u.isofs_sb.s_log_zone_size = isonum_723 (h_pri->logical_block_size);
173 s->u.isofs_sb.s_max_size = isonum_733(h_pri->volume_space_size);
174 } else {
175 rootp = (struct iso_directory_record *) pri->root_directory_record;
176 if (isonum_723 (pri->volume_set_size) != 1) {
177 printk("Multi-volume disks not (yet) supported.\n");
178 goto out;
179 };
180 s->u.isofs_sb.s_nzones = isonum_733 (pri->volume_space_size);
181 s->u.isofs_sb.s_log_zone_size = isonum_723 (pri->logical_block_size);
182 s->u.isofs_sb.s_max_size = isonum_733(pri->volume_space_size);
183 }
184
185 s->u.isofs_sb.s_ninodes = 0;
186
187 s->u.isofs_sb.s_firstdatazone = isonum_733( rootp->extent) <<
188 (ISOFS_BLOCK_BITS - ISOFS_BUFFER_BITS);
189 s->s_magic = ISOFS_SUPER_MAGIC;
190
191
192
193
194
195
196 s->s_flags = MS_RDONLY ;
197
198 if(s->u.isofs_sb.s_log_zone_size != (1 << ISOFS_BLOCK_BITS)) {
199 printk("1 <<Block bits != Block size\n");
200 goto out;
201 };
202
203 brelse(bh);
204
205 printk("Max size:%d Log zone size:%d\n",s->u.isofs_sb.s_max_size,
206 s->u.isofs_sb.s_log_zone_size);
207 printk("First datazone:%d Root inode number %d\n",s->u.isofs_sb.s_firstdatazone,
208 isonum_733 (rootp->extent) << ISOFS_BLOCK_BITS);
209 if(high_sierra) printk("Disc in High Sierra format.\n");
210 unlock_super(s);
211
212
213 s->s_dev = dev;
214 s->s_op = &isofs_sops;
215 s->u.isofs_sb.s_mapping = map;
216 s->u.isofs_sb.s_rock = (rock == 'y' ? 1 : 0);
217 s->u.isofs_sb.s_conversion = conversion;
218 s->u.isofs_sb.s_cruft = cruft;
219 s->s_blocksize = ISOFS_BUFFER_SIZE;
220 s->s_mounted = iget(s, isonum_733 (rootp->extent) << ISOFS_BLOCK_BITS);
221 unlock_super(s);
222
223 if (!(s->s_mounted)) {
224 s->s_dev=0;
225 printk("get root inode failed\n");
226 return NULL;
227 }
228 if(MAJOR(s->s_dev) == 11) {
229
230 if(check_cdrom_media_change(s->s_dev, 0))
231 goto out;
232 };
233 return s;
234 out:
235 brelse(bh);
236 s->s_dev = 0;
237 unlock_super(s);
238 return NULL;
239 }
240
241 void isofs_statfs (struct super_block *sb, struct statfs *buf)
242 {
243 put_fs_long(ISOFS_SUPER_MAGIC, &buf->f_type);
244 put_fs_long(1 << ISOFS_BLOCK_BITS, &buf->f_bsize);
245 put_fs_long(sb->u.isofs_sb.s_nzones, &buf->f_blocks);
246 put_fs_long(0, &buf->f_bfree);
247 put_fs_long(0, &buf->f_bavail);
248 put_fs_long(sb->u.isofs_sb.s_ninodes, &buf->f_files);
249 put_fs_long(0, &buf->f_ffree);
250
251 }
252
253 int isofs_bmap(struct inode * inode,int block)
254 {
255
256 if (block<0) {
257 printk("_isofs_bmap: block<0");
258 return 0;
259 }
260 return inode->u.isofs_i.i_first_extent + block;
261 }
262
263 void isofs_read_inode(struct inode * inode)
264 {
265 struct buffer_head * bh;
266 unsigned char * pnt, *cpnt = 0;
267 struct iso_directory_record * raw_inode;
268 int high_sierra;
269 int block;
270 int i;
271
272 block = inode->i_ino >> ISOFS_BUFFER_BITS;
273 if (!(bh=bread(inode->i_dev,block, ISOFS_BUFFER_SIZE)))
274 panic("unable to read i-node block");
275
276 pnt = ((char *) bh->b_data) + (inode->i_ino & (ISOFS_BUFFER_SIZE - 1));
277
278 raw_inode = ((struct iso_directory_record *) pnt);
279 high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
280
281 if ((inode->i_ino & (ISOFS_BUFFER_SIZE - 1)) + *pnt > ISOFS_BUFFER_SIZE){
282 cpnt = kmalloc(1 << ISOFS_BLOCK_BITS, GFP_KERNEL);
283 memcpy(cpnt, bh->b_data, ISOFS_BUFFER_SIZE);
284 brelse(bh);
285 if (!(bh = bread(inode->i_dev,++block, ISOFS_BUFFER_SIZE)))
286 panic("unable to read i-node block");
287 memcpy(cpnt+ISOFS_BUFFER_SIZE, bh->b_data, ISOFS_BUFFER_SIZE);
288 pnt = ((char *) cpnt) + (inode->i_ino & (ISOFS_BUFFER_SIZE - 1));
289 raw_inode = ((struct iso_directory_record *) pnt);
290 };
291
292
293 inode->i_mode = 0444;
294 inode->i_nlink = 1;
295
296 if (raw_inode->flags[-high_sierra] & 2) {
297 inode->i_mode = 0555 | S_IFDIR;
298 inode->i_nlink = 2;
299
300 } else {
301 inode->i_mode = 0444;
302 inode->i_nlink = 1;
303 inode->i_mode |= S_IFREG;
304
305 for(i=0; i< raw_inode->name_len[0]; i++)
306 if(raw_inode->name[i]=='.' || raw_inode->name[i]==';')
307 break;
308 if(i == raw_inode->name_len[0] || raw_inode->name[i] == ';')
309 inode->i_mode |= 0111;
310 };
311 inode->i_uid = 0;
312 inode->i_gid = 0;
313 inode->i_size = isonum_733 (raw_inode->size);
314
315
316
317 if(inode->i_size < 0 || inode->i_size > 700000000) {
318 printk("Warning: defective cdrom. Enabling \"cruft\" mount option.\n");
319 inode->i_sb->u.isofs_sb.s_cruft = 'y';
320 };
321
322
323
324
325
326 if(inode->i_sb->u.isofs_sb.s_cruft == 'y' &&
327 inode->i_size & 0xff000000){
328
329 inode->i_size &= 0x00ffffff;
330 };
331
332 if (isonum_723 (raw_inode->volume_sequence_number) != 1) {
333 panic("Multi volume CD somehow got mounted.\n");
334 };
335
336 if (raw_inode->interleave[0]) {
337 printk("Interleaved files not (yet) supported.\n");
338 inode->i_size = 0;
339 };
340
341 #ifdef DEBUG
342
343
344 if(raw_inode->ext_attr_length[0] != 0){
345 printk("Extended attributes present for ISO file (%d).\n",
346 inode->i_ino);
347 }
348 #endif
349
350
351
352 if(raw_inode->file_unit_size[0] != 0){
353 printk("File unit size != 0 for ISO file.(%d)\n",inode->i_ino);
354 }
355
356
357
358 if((raw_inode->flags[-high_sierra] & ~2)!= 0){
359 printk("Unusual flag settings for ISO file.(%d %x)\n",
360 inode->i_ino, raw_inode->flags[-high_sierra]);
361 }
362
363 #ifdef DEBUG
364 printk("Get inode %d: %d %d: %d\n",inode->i_ino, block,
365 ((int)pnt) & 0x3ff, inode->i_size);
366 #endif
367
368 inode->i_mtime = inode->i_atime = inode->i_ctime =
369 iso_date(raw_inode->date, high_sierra);
370
371 inode->u.isofs_i.i_first_extent = isonum_733 (raw_inode->extent) <<
372 (ISOFS_BLOCK_BITS - ISOFS_BUFFER_BITS);
373
374 inode->u.isofs_i.i_backlink = -1;
375 switch (inode->i_sb->u.isofs_sb.s_conversion){
376 case 'a':
377 inode->u.isofs_i.i_file_format = ISOFS_FILE_UNKNOWN;
378 break;
379 case 'b':
380 inode->u.isofs_i.i_file_format = ISOFS_FILE_BINARY;
381 break;
382 case 't':
383 inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT;
384 break;
385 case 'm':
386 inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT_M;
387 break;
388 };
389
390
391
392
393
394 if (!high_sierra)
395 parse_rock_ridge_inode(raw_inode, inode);
396
397 #ifdef DEBUG
398 printk("Inode: %x extent: %x\n",inode->i_ino, inode->u.isofs_i.i_first_extent);
399 #endif
400 brelse(bh);
401
402 if (cpnt) {
403 kfree_s (cpnt, 1 << ISOFS_BLOCK_BITS);
404 cpnt = 0;
405 };
406
407 inode->i_op = NULL;
408 if (S_ISREG(inode->i_mode))
409 inode->i_op = &isofs_file_inode_operations;
410 else if (S_ISDIR(inode->i_mode))
411 inode->i_op = &isofs_dir_inode_operations;
412 else if (S_ISLNK(inode->i_mode))
413 inode->i_op = &isofs_symlink_inode_operations;
414 else if (S_ISCHR(inode->i_mode))
415 inode->i_op = &isofs_chrdev_inode_operations;
416 else if (S_ISBLK(inode->i_mode))
417 inode->i_op = &isofs_blkdev_inode_operations;
418 else if (S_ISFIFO(inode->i_mode)) {
419 inode->i_op = &isofs_fifo_inode_operations;
420 inode->i_pipe = 1;
421 PIPE_BASE(*inode) = NULL;
422 PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
423 PIPE_READ_WAIT(*inode) = PIPE_WRITE_WAIT(*inode) = NULL;
424 PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
425 }
426 }
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447 int isofs_lookup_grandparent(struct inode * parent, int extent) {
448 unsigned int block,offset;
449 int parent_dir, inode_number;
450 int old_offset;
451 char * cpnt = 0;
452 int result;
453 struct buffer_head * bh;
454 struct iso_directory_record * de;
455
456 offset = 0;
457 block = extent << (ISOFS_BLOCK_BITS - ISOFS_BUFFER_BITS);
458 if (!(bh = bread(parent->i_dev, block, ISOFS_BUFFER_SIZE))) return 0;
459
460 while (1 == 1) {
461 de = (struct iso_directory_record *) (offset + bh->b_data);
462
463 if (*((char*) de) == 0)
464 {
465 brelse(bh);
466 return -1;
467 }
468
469 offset += *((unsigned char*) de);
470
471 if (offset >= ISOFS_BUFFER_SIZE)
472 {
473 printk(".. Directory not in first block of directory.\n");
474 brelse(bh);
475 return -1;
476 }
477
478 if (de->name_len[0] == 1 && de->name[0] == 1)
479 {
480 brelse(bh);
481 parent_dir = find_rock_ridge_relocation(de, parent);
482 break;
483 };
484 }
485 #ifdef DEBUG
486 printk("Parent dir:%x\n",parent_dir);
487 #endif
488
489
490
491
492 result = -1;
493
494 offset = 0;
495 block = parent_dir << (ISOFS_BLOCK_BITS - ISOFS_BUFFER_BITS);
496 if (!block || !(bh = bread(parent->i_dev,block, ISOFS_BUFFER_SIZE)))
497 return 0;
498
499 while (1==1) {
500 de = (struct iso_directory_record *) (offset + bh->b_data);
501 inode_number = (block << ISOFS_BUFFER_BITS)+(offset & (ISOFS_BUFFER_SIZE - 1));
502
503
504
505
506 if (*((char*) de) == 0)
507 {
508 brelse(bh);
509 offset = 0;
510 block++;
511 if(block & 1) return -1;
512 if (!block || !(bh = bread(parent->i_dev,block, ISOFS_BUFFER_SIZE)))
513 return -1;
514 continue;
515 }
516
517
518
519
520
521 old_offset = offset;
522 offset += *((unsigned char*) de);
523 if (offset >= ISOFS_BUFFER_SIZE)
524 {
525 cpnt = kmalloc(1<<ISOFS_BLOCK_BITS,GFP_KERNEL);
526 memcpy(cpnt, bh->b_data, ISOFS_BUFFER_SIZE);
527 de = (struct iso_directory_record *) (old_offset + cpnt);
528 brelse(bh);
529 offset -= ISOFS_BUFFER_SIZE;
530 block++;
531 if((block & 1) == 0) return -1;
532 if (!(bh = bread(parent->i_dev,block, ISOFS_BUFFER_SIZE)))
533 return -1;
534 memcpy(cpnt+ISOFS_BUFFER_SIZE, bh->b_data, ISOFS_BUFFER_SIZE);
535 }
536
537 if (find_rock_ridge_relocation(de, parent) == extent){
538 result = inode_number;
539 goto out;
540 };
541
542 if (cpnt) {
543 kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
544 cpnt = 0;
545 };
546 }
547
548
549
550 out:
551 if (cpnt) {
552 kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
553 cpnt = 0;
554 };
555 brelse(bh);
556 #ifdef DEBUG
557 printk("Resultant Inode %d\n",result);
558 #endif
559 return result;
560 }
561
562 #ifdef LEAK_CHECK
563 #undef malloc
564 #undef free_s
565 #undef bread
566 #undef brelse
567
568 void * leak_check_malloc(unsigned int size){
569 void * tmp;
570 check_malloc++;
571 tmp = kmalloc(size, GFP_KERNEL);
572 return tmp;
573 }
574
575 void leak_check_free_s(void * obj, int size){
576 check_malloc--;
577 return kfree_s(obj, size);
578 }
579
580 struct buffer_head * leak_check_bread(int dev, int block, int size){
581 check_bread++;
582 return bread(dev, block, size);
583 }
584
585 void leak_check_brelse(struct buffer_head * bh){
586 check_bread--;
587 return brelse(bh);
588 }
589
590 #endif