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