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 memcpy(cpnt, bh->b_data, bufsize);
357 brelse(bh);
358 if (!(bh = bread(inode->i_dev,++block, bufsize))) {
359 kfree_s (cpnt, 1 << ISOFS_BLOCK_BITS);
360 printk("unable to read i-node block");
361 goto fail;
362 };
363 memcpy((char *)cpnt + bufsize, bh->b_data, bufsize);
364 pnt = ((unsigned char *) cpnt
365 + (inode->i_ino & (bufsize - 1)));
366 raw_inode = ((struct iso_directory_record *) pnt);
367 };
368
369 inode->i_mode = S_IRUGO;
370 inode->i_nlink = 1;
371
372 if (raw_inode->flags[-high_sierra] & 2) {
373 inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
374 inode->i_nlink = 2;
375
376 } else {
377 inode->i_mode = S_IRUGO;
378 inode->i_nlink = 1;
379 inode->i_mode |= S_IFREG;
380
381 for(i=0; i< raw_inode->name_len[0]; i++)
382 if(raw_inode->name[i]=='.' || raw_inode->name[i]==';')
383 break;
384 if(i == raw_inode->name_len[0] || raw_inode->name[i] == ';')
385 inode->i_mode |= S_IXUGO;
386 };
387 inode->i_uid = 0;
388 inode->i_gid = 0;
389 inode->i_size = isonum_733 (raw_inode->size);
390
391
392
393 if((inode->i_size < 0 || inode->i_size > 700000000) &&
394 inode->i_sb->u.isofs_sb.s_cruft == 'n') {
395 printk("Warning: defective cdrom. Enabling \"cruft\" mount option.\n");
396 inode->i_sb->u.isofs_sb.s_cruft = 'y';
397 };
398
399
400
401
402
403 if(inode->i_sb->u.isofs_sb.s_cruft == 'y' &&
404 inode->i_size & 0xff000000){
405
406 inode->i_size &= 0x00ffffff;
407 };
408
409 if (raw_inode->interleave[0]) {
410 printk("Interleaved files not (yet) supported.\n");
411 inode->i_size = 0;
412 };
413
414 #ifdef DEBUG
415
416
417 if(raw_inode->ext_attr_length[0] != 0){
418 printk("Extended attributes present for ISO file (%ld).\n",
419 inode->i_ino);
420 }
421 #endif
422
423
424
425 if(raw_inode->file_unit_size[0] != 0){
426 printk("File unit size != 0 for ISO file (%ld).\n",inode->i_ino);
427 }
428
429
430
431 if((raw_inode->flags[-high_sierra] & ~2)!= 0){
432 printk("Unusual flag settings for ISO file (%ld %x).\n",
433 inode->i_ino, raw_inode->flags[-high_sierra]);
434 }
435
436 #ifdef DEBUG
437 printk("Get inode %d: %d %d: %d\n",inode->i_ino, block,
438 ((int)pnt) & 0x3ff, inode->i_size);
439 #endif
440
441 inode->i_mtime = inode->i_atime = inode->i_ctime =
442 iso_date(raw_inode->date, high_sierra);
443
444 inode->u.isofs_i.i_first_extent = isonum_733 (raw_inode->extent) <<
445 (ISOFS_BLOCK_BITS - ISOFS_BUFFER_BITS(inode));
446
447 inode->u.isofs_i.i_backlink = 0xffffffff;
448 switch (inode->i_sb->u.isofs_sb.s_conversion){
449 case 'a':
450 inode->u.isofs_i.i_file_format = ISOFS_FILE_UNKNOWN;
451 break;
452 case 'b':
453 inode->u.isofs_i.i_file_format = ISOFS_FILE_BINARY;
454 break;
455 case 't':
456 inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT;
457 break;
458 case 'm':
459 inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT_M;
460 break;
461 };
462
463
464
465
466
467 if (!high_sierra)
468 parse_rock_ridge_inode(raw_inode, inode);
469
470 #ifdef DEBUG
471 printk("Inode: %x extent: %x\n",inode->i_ino, inode->u.isofs_i.i_first_extent);
472 #endif
473 brelse(bh);
474
475 if (cpnt) {
476 kfree_s (cpnt, 1 << ISOFS_BLOCK_BITS);
477 cpnt = NULL;
478 };
479
480 inode->i_op = NULL;
481 if (inode->i_sb->u.isofs_sb.s_cruft != 'y' &&
482 isonum_723 (raw_inode->volume_sequence_number) != 1) {
483 printk("Multi volume CD somehow got mounted.\n");
484 } else {
485 if (S_ISREG(inode->i_mode))
486 inode->i_op = &isofs_file_inode_operations;
487 else if (S_ISDIR(inode->i_mode))
488 inode->i_op = &isofs_dir_inode_operations;
489 else if (S_ISLNK(inode->i_mode))
490 inode->i_op = &isofs_symlink_inode_operations;
491 else if (S_ISCHR(inode->i_mode))
492 inode->i_op = &chrdev_inode_operations;
493 else if (S_ISBLK(inode->i_mode))
494 inode->i_op = &blkdev_inode_operations;
495 else if (S_ISFIFO(inode->i_mode))
496 init_fifo(inode);
497 }
498 return;
499 fail:
500
501 inode->i_mtime = inode->i_atime = inode->i_ctime = 0;
502 inode->u.isofs_i.i_first_extent = 0;
503 inode->u.isofs_i.i_backlink = 0xffffffff;
504 inode->i_size = 0;
505 inode->i_nlink = 1;
506 inode->i_uid = inode->i_gid = 0;
507 inode->i_mode = S_IFREG;
508 inode->i_op = NULL;
509 return;
510 }
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531 int isofs_lookup_grandparent(struct inode * parent, int extent)
532 {
533 unsigned long bufsize = ISOFS_BUFFER_SIZE(parent);
534 unsigned char bufbits = ISOFS_BUFFER_BITS(parent);
535 unsigned int block,offset;
536 int parent_dir, inode_number;
537 int old_offset;
538 void * cpnt = NULL;
539 int result;
540 struct buffer_head * bh;
541 struct iso_directory_record * de;
542
543 offset = 0;
544 block = extent << (ISOFS_BLOCK_BITS - bufbits);
545 if (!(bh = bread(parent->i_dev, block, bufsize))) return -1;
546
547 while (1 == 1) {
548 de = (struct iso_directory_record *) (bh->b_data + offset);
549 if (*((unsigned char *) de) == 0)
550 {
551 brelse(bh);
552 return -1;
553 }
554
555 offset += *((unsigned char *) de);
556
557 if (offset >= bufsize)
558 {
559 printk(".. Directory not in first block"
560 " of directory.\n");
561 brelse(bh);
562 return -1;
563 }
564
565 if (de->name_len[0] == 1 && de->name[0] == 1)
566 {
567 parent_dir = find_rock_ridge_relocation(de, parent);
568 brelse(bh);
569 break;
570 }
571 }
572 #ifdef DEBUG
573 printk("Parent dir:%x\n",parent_dir);
574 #endif
575
576
577
578
579 result = -1;
580
581 offset = 0;
582 block = parent_dir << (ISOFS_BLOCK_BITS - bufbits);
583 if (!block || !(bh = bread(parent->i_dev,block, bufsize)))
584 return -1;
585
586 for(;;)
587 {
588 de = (struct iso_directory_record *) (bh->b_data + offset);
589 inode_number = (block << bufbits)+(offset & (bufsize - 1));
590
591
592
593
594
595 if (*((unsigned char *) de) == 0)
596 {
597 brelse(bh);
598 offset = 0;
599 block++;
600 if(block & 1) return -1;
601 if (!block
602 || !(bh = bread(parent->i_dev,block, bufsize)))
603 return -1;
604 continue;
605 }
606
607
608
609
610
611 old_offset = offset;
612 offset += *((unsigned char *) de);
613
614 if (offset >= bufsize)
615 {
616 if((block & 1) != 0) return -1;
617 cpnt = kmalloc(1<<ISOFS_BLOCK_BITS,GFP_KERNEL);
618 memcpy(cpnt, bh->b_data, bufsize);
619 de = (struct iso_directory_record *)
620 ((char *)cpnt + old_offset);
621 brelse(bh);
622 offset -= bufsize;
623 block++;
624 if (!(bh = bread(parent->i_dev,block,bufsize))) {
625 kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
626 return -1;
627 };
628 memcpy((char *)cpnt+bufsize, bh->b_data, bufsize);
629 }
630
631 if (find_rock_ridge_relocation(de, parent) == extent){
632 result = inode_number;
633 goto out;
634 }
635
636 if (cpnt) {
637 kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
638 cpnt = NULL;
639 }
640 }
641
642
643
644
645 out:
646 if (cpnt) {
647 kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
648 cpnt = NULL;
649 }
650 brelse(bh);
651 #ifdef DEBUG
652 printk("Resultant Inode %d\n",result);
653 #endif
654 return result;
655 }
656
657 #ifdef LEAK_CHECK
658 #undef malloc
659 #undef free_s
660 #undef bread
661 #undef brelse
662
663 void * leak_check_malloc(unsigned int size){
664 void * tmp;
665 check_malloc++;
666 tmp = kmalloc(size, GFP_KERNEL);
667 return tmp;
668 }
669
670 void leak_check_free_s(void * obj, int size){
671 check_malloc--;
672 return kfree_s(obj, size);
673 }
674
675 struct buffer_head * leak_check_bread(int dev, int block, int size){
676 check_bread++;
677 return bread(dev, block, size);
678 }
679
680 void leak_check_brelse(struct buffer_head * bh){
681 check_bread--;
682 return brelse(bh);
683 }
684
685 #endif