1
2
3
4
5
6
7
8
9
10
11
12#include <linux/config.h>
13#include <linux/module.h>
14
15#include <linux/stat.h>
16#include <linux/sched.h>
17#include <linux/iso_fs.h>
18#include <linux/kernel.h>
19#include <linux/major.h>
20#include <linux/mm.h>
21#include <linux/string.h>
22#include <linux/locks.h>
23#include <linux/slab.h>
24#include <linux/errno.h>
25#include <linux/cdrom.h>
26#include <linux/init.h>
27#include <linux/nls.h>
28#include <linux/ctype.h>
29#include <linux/smp_lock.h>
30#include <linux/blkdev.h>
31
32#include <asm/system.h>
33#include <asm/uaccess.h>
34
35#include "zisofs.h"
36
37#define BEQUIET
38
39#ifdef LEAK_CHECK
40static int check_malloc = 0;
41static int check_bread = 0;
42#endif
43
44static int isofs_hashi(struct dentry *parent, struct qstr *qstr);
45static int isofs_hash(struct dentry *parent, struct qstr *qstr);
46static int isofs_dentry_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b);
47static int isofs_dentry_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b);
48
49#ifdef CONFIG_JOLIET
50static int isofs_hashi_ms(struct dentry *parent, struct qstr *qstr);
51static int isofs_hash_ms(struct dentry *parent, struct qstr *qstr);
52static int isofs_dentry_cmpi_ms(struct dentry *dentry, struct qstr *a, struct qstr *b);
53static int isofs_dentry_cmp_ms(struct dentry *dentry, struct qstr *a, struct qstr *b);
54#endif
55
56static void isofs_put_super(struct super_block *sb)
57{
58#ifdef CONFIG_JOLIET
59 if (sb->u.isofs_sb.s_nls_iocharset) {
60 unload_nls(sb->u.isofs_sb.s_nls_iocharset);
61 sb->u.isofs_sb.s_nls_iocharset = NULL;
62 }
63#endif
64
65#ifdef LEAK_CHECK
66 printk("Outstanding mallocs:%d, outstanding buffers: %d\n",
67 check_malloc, check_bread);
68#endif
69
70 return;
71}
72
73static void isofs_read_inode(struct inode *);
74static int isofs_statfs (struct super_block *, struct statfs *);
75
76static struct super_operations isofs_sops = {
77 read_inode: isofs_read_inode,
78 put_super: isofs_put_super,
79 statfs: isofs_statfs,
80};
81
82static struct dentry_operations isofs_dentry_ops[] = {
83 {
84 d_hash: isofs_hash,
85 d_compare: isofs_dentry_cmp,
86 },
87 {
88 d_hash: isofs_hashi,
89 d_compare: isofs_dentry_cmpi,
90 },
91#ifdef CONFIG_JOLIET
92 {
93 d_hash: isofs_hash_ms,
94 d_compare: isofs_dentry_cmp_ms,
95 },
96 {
97 d_hash: isofs_hashi_ms,
98 d_compare: isofs_dentry_cmpi_ms,
99 }
100#endif
101};
102
103struct iso9660_options{
104 char map;
105 char rock;
106 char joliet;
107 char cruft;
108 char unhide;
109 char nocompress;
110 unsigned char check;
111 unsigned int blocksize;
112 mode_t mode;
113 gid_t gid;
114 uid_t uid;
115 char *iocharset;
116 unsigned char utf8;
117
118 s32 session;
119 s32 sbsector;
120};
121
122
123
124
125static int
126isofs_hash_common(struct dentry *dentry, struct qstr *qstr, int ms)
127{
128 const char *name;
129 int len;
130
131 len = qstr->len;
132 name = qstr->name;
133 if (ms) {
134 while (len && name[len-1] == '.')
135 len--;
136 }
137
138 qstr->hash = full_name_hash(name, len);
139
140 return 0;
141}
142
143
144
145
146static int
147isofs_hashi_common(struct dentry *dentry, struct qstr *qstr, int ms)
148{
149 const char *name;
150 int len;
151 char c;
152 unsigned long hash;
153
154 len = qstr->len;
155 name = qstr->name;
156 if (ms) {
157 while (len && name[len-1] == '.')
158 len--;
159 }
160
161 hash = init_name_hash();
162 while (len--) {
163 c = tolower(*name++);
164 hash = partial_name_hash(tolower(c), hash);
165 }
166 qstr->hash = end_name_hash(hash);
167
168 return 0;
169}
170
171
172
173
174static int
175isofs_dentry_cmpi_common(struct dentry *dentry,struct qstr *a,struct qstr *b,int ms)
176{
177 int alen, blen;
178
179
180 alen = a->len;
181 blen = b->len;
182 if (ms) {
183 while (alen && a->name[alen-1] == '.')
184 alen--;
185 while (blen && b->name[blen-1] == '.')
186 blen--;
187 }
188 if (alen == blen) {
189 if (strnicmp(a->name, b->name, alen) == 0)
190 return 0;
191 }
192 return 1;
193}
194
195
196
197
198static int
199isofs_dentry_cmp_common(struct dentry *dentry,struct qstr *a,struct qstr *b,int ms)
200{
201 int alen, blen;
202
203
204 alen = a->len;
205 blen = b->len;
206 if (ms) {
207 while (alen && a->name[alen-1] == '.')
208 alen--;
209 while (blen && b->name[blen-1] == '.')
210 blen--;
211 }
212 if (alen == blen) {
213 if (strncmp(a->name, b->name, alen) == 0)
214 return 0;
215 }
216 return 1;
217}
218
219static int
220isofs_hash(struct dentry *dentry, struct qstr *qstr)
221{
222 return isofs_hash_common(dentry, qstr, 0);
223}
224
225static int
226isofs_hashi(struct dentry *dentry, struct qstr *qstr)
227{
228 return isofs_hashi_common(dentry, qstr, 0);
229}
230
231static int
232isofs_dentry_cmp(struct dentry *dentry,struct qstr *a,struct qstr *b)
233{
234 return isofs_dentry_cmp_common(dentry, a, b, 0);
235}
236
237static int
238isofs_dentry_cmpi(struct dentry *dentry,struct qstr *a,struct qstr *b)
239{
240 return isofs_dentry_cmpi_common(dentry, a, b, 0);
241}
242
243#ifdef CONFIG_JOLIET
244static int
245isofs_hash_ms(struct dentry *dentry, struct qstr *qstr)
246{
247 return isofs_hash_common(dentry, qstr, 1);
248}
249
250static int
251isofs_hashi_ms(struct dentry *dentry, struct qstr *qstr)
252{
253 return isofs_hashi_common(dentry, qstr, 1);
254}
255
256static int
257isofs_dentry_cmp_ms(struct dentry *dentry,struct qstr *a,struct qstr *b)
258{
259 return isofs_dentry_cmp_common(dentry, a, b, 1);
260}
261
262static int
263isofs_dentry_cmpi_ms(struct dentry *dentry,struct qstr *a,struct qstr *b)
264{
265 return isofs_dentry_cmpi_common(dentry, a, b, 1);
266}
267#endif
268
269static int parse_options(char *options, struct iso9660_options * popt)
270{
271 char *this_char,*value;
272
273 popt->map = 'n';
274 popt->rock = 'y';
275 popt->joliet = 'y';
276 popt->cruft = 'n';
277 popt->unhide = 'n';
278 popt->check = 'u';
279 popt->nocompress = 0;
280 popt->blocksize = 1024;
281 popt->mode = S_IRUGO | S_IXUGO;
282
283
284
285 popt->gid = 0;
286 popt->uid = 0;
287 popt->iocharset = NULL;
288 popt->utf8 = 0;
289 popt->session=-1;
290 popt->sbsector=-1;
291 if (!options) return 1;
292 for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
293 if (strncmp(this_char,"norock",6) == 0) {
294 popt->rock = 'n';
295 continue;
296 }
297 if (strncmp(this_char,"nojoliet",8) == 0) {
298 popt->joliet = 'n';
299 continue;
300 }
301 if (strncmp(this_char,"unhide",6) == 0) {
302 popt->unhide = 'y';
303 continue;
304 }
305 if (strncmp(this_char,"cruft",5) == 0) {
306 popt->cruft = 'y';
307 continue;
308 }
309 if (strncmp(this_char,"utf8",4) == 0) {
310 popt->utf8 = 1;
311 continue;
312 }
313 if (strncmp(this_char,"nocompress",10) == 0) {
314 popt->nocompress = 1;
315 continue;
316 }
317 if ((value = strchr(this_char,'=')) != NULL)
318 *value++ = 0;
319
320#ifdef CONFIG_JOLIET
321 if (!strcmp(this_char,"iocharset") && value) {
322 popt->iocharset = value;
323 while (*value && *value != ',')
324 value++;
325 if (value == popt->iocharset)
326 return 0;
327 *value = 0;
328 } else
329#endif
330 if (!strcmp(this_char,"map") && value) {
331 if (value[0] && !value[1] && strchr("ano",*value))
332 popt->map = *value;
333 else if (!strcmp(value,"off")) popt->map = 'o';
334 else if (!strcmp(value,"normal")) popt->map = 'n';
335 else if (!strcmp(value,"acorn")) popt->map = 'a';
336 else return 0;
337 }
338 if (!strcmp(this_char,"session") && value) {
339 char * vpnt = value;
340 unsigned int ivalue = simple_strtoul(vpnt, &vpnt, 0);
341 if(ivalue < 0 || ivalue >99) return 0;
342 popt->session=ivalue+1;
343 }
344 if (!strcmp(this_char,"sbsector") && value) {
345 char * vpnt = value;
346 unsigned int ivalue = simple_strtoul(vpnt, &vpnt, 0);
347 if(ivalue < 0 || ivalue >660*512) return 0;
348 popt->sbsector=ivalue;
349 }
350 else if (!strcmp(this_char,"check") && value) {
351 if (value[0] && !value[1] && strchr("rs",*value))
352 popt->check = *value;
353 else if (!strcmp(value,"relaxed")) popt->check = 'r';
354 else if (!strcmp(value,"strict")) popt->check = 's';
355 else return 0;
356 }
357 else if (!strcmp(this_char,"conv") && value) {
358
359
360
361 if (value[0] && !value[1] && strchr("btma",*value)) ;
362 else if (!strcmp(value,"binary")) ;
363 else if (!strcmp(value,"text")) ;
364 else if (!strcmp(value,"mtext")) ;
365 else if (!strcmp(value,"auto")) ;
366 else return 0;
367 }
368 else if (value &&
369 (!strcmp(this_char,"block") ||
370 !strcmp(this_char,"mode") ||
371 !strcmp(this_char,"uid") ||
372 !strcmp(this_char,"gid"))) {
373 char * vpnt = value;
374 unsigned int ivalue = simple_strtoul(vpnt, &vpnt, 0);
375 if (*vpnt) return 0;
376 switch(*this_char) {
377 case 'b':
378 if ( ivalue != 512
379 && ivalue != 1024
380 && ivalue != 2048) return 0;
381 popt->blocksize = ivalue;
382 break;
383 case 'u':
384 popt->uid = ivalue;
385 break;
386 case 'g':
387 popt->gid = ivalue;
388 break;
389 case 'm':
390 popt->mode = ivalue;
391 break;
392 }
393 }
394 else return 1;
395 }
396 return 1;
397}
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415#define WE_OBEY_THE_WRITTEN_STANDARDS 1
416
417static unsigned int isofs_get_last_session(struct super_block *sb,s32 session )
418{
419 struct cdrom_multisession ms_info;
420 unsigned int vol_desc_start;
421 struct block_device *bdev = sb->s_bdev;
422 int i;
423
424 vol_desc_start=0;
425 ms_info.addr_format=CDROM_LBA;
426 if(session >= 0 && session <= 99) {
427 struct cdrom_tocentry Te;
428 Te.cdte_track=session;
429 Te.cdte_format=CDROM_LBA;
430 i = ioctl_by_bdev(bdev, CDROMREADTOCENTRY, (unsigned long) &Te);
431 if (!i) {
432 printk(KERN_DEBUG "Session %d start %d type %d\n",
433 session, Te.cdte_addr.lba,
434 Te.cdte_ctrl&CDROM_DATA_TRACK);
435 if ((Te.cdte_ctrl&CDROM_DATA_TRACK) == 4)
436 return Te.cdte_addr.lba;
437 }
438
439 printk(KERN_ERR "Invalid session number or type of track\n");
440 }
441 i = ioctl_by_bdev(bdev, CDROMMULTISESSION, (unsigned long) &ms_info);
442 if(session > 0) printk(KERN_ERR "Invalid session number\n");
443#if 0
444 printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i);
445 if (i==0) {
446 printk("isofs.inode: XA disk: %s\n",ms_info.xa_flag?"yes":"no");
447 printk("isofs.inode: vol_desc_start = %d\n", ms_info.addr.lba);
448 }
449#endif
450 if (i==0)
451#if WE_OBEY_THE_WRITTEN_STANDARDS
452 if (ms_info.xa_flag)
453#endif
454 vol_desc_start=ms_info.addr.lba;
455 return vol_desc_start;
456}
457
458
459
460
461
462
463
464static struct super_block *isofs_read_super(struct super_block *s, void *data,
465 int silent)
466{
467 kdev_t dev = s->s_dev;
468 struct buffer_head * bh = NULL, *pri_bh = NULL;
469 struct hs_primary_descriptor * h_pri = NULL;
470 struct iso_primary_descriptor * pri = NULL;
471 struct iso_supplementary_descriptor *sec = NULL;
472 struct iso_directory_record * rootp;
473 int joliet_level = 0;
474 int high_sierra;
475 int iso_blknum, block;
476 int orig_zonesize;
477 int table;
478 unsigned int blocksize, blocksize_bits;
479 unsigned int vol_desc_start;
480 unsigned long first_data_zone;
481 struct inode * inode;
482 struct iso9660_options opt;
483
484 if (!parse_options((char *) data, &opt))
485 goto out_unlock;
486
487
488
489
490
491
492
493 blocksize = get_hardsect_size(dev);
494 if(blocksize > opt.blocksize) {
495
496
497
498
499 opt.blocksize = blocksize;
500 }
501
502 blocksize_bits = 0;
503 {
504 int i = opt.blocksize;
505 while (i != 1){
506 blocksize_bits++;
507 i >>=1;
508 }
509 }
510
511 set_blocksize(dev, opt.blocksize);
512 s->s_blocksize = opt.blocksize;
513
514 s->u.isofs_sb.s_high_sierra = high_sierra = 0;
515
516 vol_desc_start = (opt.sbsector != -1) ?
517 opt.sbsector : isofs_get_last_session(s,opt.session);
518
519 for (iso_blknum = vol_desc_start+16;
520 iso_blknum < vol_desc_start+100; iso_blknum++)
521 {
522 struct hs_volume_descriptor * hdp;
523 struct iso_volume_descriptor * vdp;
524
525 block = iso_blknum << (ISOFS_BLOCK_BITS-blocksize_bits);
526 if (!(bh = sb_bread(s, block)))
527 goto out_no_read;
528
529 vdp = (struct iso_volume_descriptor *)bh->b_data;
530 hdp = (struct hs_volume_descriptor *)bh->b_data;
531
532
533
534
535
536 if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) {
537 if (isonum_711 (vdp->type) == ISO_VD_END)
538 break;
539 if (isonum_711 (vdp->type) == ISO_VD_PRIMARY) {
540 if (pri == NULL) {
541 pri = (struct iso_primary_descriptor *)vdp;
542
543 pri_bh = bh;
544 bh = NULL;
545 }
546 }
547#ifdef CONFIG_JOLIET
548 else if (isonum_711 (vdp->type) == ISO_VD_SUPPLEMENTARY) {
549 sec = (struct iso_supplementary_descriptor *)vdp;
550 if (sec->escape[0] == 0x25 && sec->escape[1] == 0x2f) {
551 if (opt.joliet == 'y') {
552 if (sec->escape[2] == 0x40) {
553 joliet_level = 1;
554 } else if (sec->escape[2] == 0x43) {
555 joliet_level = 2;
556 } else if (sec->escape[2] == 0x45) {
557 joliet_level = 3;
558 }
559 printk(KERN_DEBUG"ISO 9660 Extensions: Microsoft Joliet Level %d\n",
560 joliet_level);
561 }
562 goto root_found;
563 } else {
564
565 sec = NULL;
566 }
567 }
568#endif
569 } else {
570 if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) {
571 if (isonum_711 (hdp->type) != ISO_VD_PRIMARY)
572 goto out_freebh;
573
574 s->u.isofs_sb.s_high_sierra = 1;
575 high_sierra = 1;
576 opt.rock = 'n';
577 h_pri = (struct hs_primary_descriptor *)vdp;
578 goto root_found;
579 }
580 }
581
582
583
584 brelse(bh);
585 bh = NULL;
586 }
587
588
589
590
591 if (!pri)
592 goto out_unknown_format;
593 brelse(bh);
594 bh = pri_bh;
595 pri_bh = NULL;
596
597root_found:
598
599 if (joliet_level && (pri == NULL || opt.rock == 'n')) {
600
601
602
603 pri = (struct iso_primary_descriptor *) sec;
604 }
605
606 if(high_sierra){
607 rootp = (struct iso_directory_record *) h_pri->root_directory_record;
608 s->u.isofs_sb.s_nzones = isonum_733 (h_pri->volume_space_size);
609 s->u.isofs_sb.s_log_zone_size = isonum_723 (h_pri->logical_block_size);
610 s->u.isofs_sb.s_max_size = isonum_733(h_pri->volume_space_size);
611 } else {
612 if (!pri)
613 goto out_freebh;
614 rootp = (struct iso_directory_record *) pri->root_directory_record;
615 s->u.isofs_sb.s_nzones = isonum_733 (pri->volume_space_size);
616 s->u.isofs_sb.s_log_zone_size = isonum_723 (pri->logical_block_size);
617 s->u.isofs_sb.s_max_size = isonum_733(pri->volume_space_size);
618 }
619
620 s->u.isofs_sb.s_ninodes = 0;
621
622 orig_zonesize = s -> u.isofs_sb.s_log_zone_size;
623
624
625
626
627
628
629
630 if(blocksize != 0 && orig_zonesize < blocksize)
631 goto out_bad_size;
632
633
634 switch (s -> u.isofs_sb.s_log_zone_size)
635 { case 512: s -> u.isofs_sb.s_log_zone_size = 9; break;
636 case 1024: s -> u.isofs_sb.s_log_zone_size = 10; break;
637 case 2048: s -> u.isofs_sb.s_log_zone_size = 11; break;
638
639 default:
640 goto out_bad_zone_size;
641 }
642
643 s->s_magic = ISOFS_SUPER_MAGIC;
644
645
646
647
648
649
650 s->s_flags |= MS_RDONLY ;
651
652
653
654
655
656
657 first_data_zone = ((isonum_733 (rootp->extent) +
658 isonum_711 (rootp->ext_attr_length))
659 << s -> u.isofs_sb.s_log_zone_size);
660 s->u.isofs_sb.s_firstdatazone = first_data_zone;
661#ifndef BEQUIET
662 printk(KERN_DEBUG "Max size:%ld Log zone size:%ld\n",
663 s->u.isofs_sb.s_max_size,
664 1UL << s->u.isofs_sb.s_log_zone_size);
665 printk(KERN_DEBUG "First datazone:%ld Root inode number:%ld\n",
666 s->u.isofs_sb.s_firstdatazone >> s -> u.isofs_sb.s_log_zone_size,
667 s->u.isofs_sb.s_firstdatazone);
668 if(high_sierra)
669 printk(KERN_DEBUG "Disc in High Sierra format.\n");
670#endif
671
672
673
674
675
676
677
678
679
680 if (joliet_level) {
681 pri = (struct iso_primary_descriptor *) sec;
682 rootp = (struct iso_directory_record *)
683 pri->root_directory_record;
684 first_data_zone = ((isonum_733 (rootp->extent) +
685 isonum_711 (rootp->ext_attr_length))
686 << s -> u.isofs_sb.s_log_zone_size);
687 }
688
689
690
691
692
693 brelse(pri_bh);
694 brelse(bh);
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713 if ( orig_zonesize != opt.blocksize ) {
714 set_blocksize(dev, orig_zonesize);
715#ifndef BEQUIET
716 printk(KERN_DEBUG
717 "ISOFS: Forcing new log zone size:%d\n", orig_zonesize);
718#endif
719 }
720 s->s_blocksize = orig_zonesize;
721 s->s_blocksize_bits = s -> u.isofs_sb.s_log_zone_size;
722
723 s->u.isofs_sb.s_nls_iocharset = NULL;
724
725#ifdef CONFIG_JOLIET
726 if (joliet_level && opt.utf8 == 0) {
727 char * p = opt.iocharset ? opt.iocharset : "iso8859-1";
728 s->u.isofs_sb.s_nls_iocharset = load_nls(p);
729 if (! s->u.isofs_sb.s_nls_iocharset) {
730
731 if (opt.iocharset)
732 goto out_unlock;
733 s->u.isofs_sb.s_nls_iocharset = load_nls_default();
734 }
735 }
736#endif
737 s->s_op = &isofs_sops;
738 s->u.isofs_sb.s_mapping = opt.map;
739 s->u.isofs_sb.s_rock = (opt.rock == 'y' ? 2 : 0);
740 s->u.isofs_sb.s_rock_offset = -1;
741 s->u.isofs_sb.s_cruft = opt.cruft;
742 s->u.isofs_sb.s_unhide = opt.unhide;
743 s->u.isofs_sb.s_uid = opt.uid;
744 s->u.isofs_sb.s_gid = opt.gid;
745 s->u.isofs_sb.s_utf8 = opt.utf8;
746 s->u.isofs_sb.s_nocompress = opt.nocompress;
747
748
749
750
751
752 s->u.isofs_sb.s_mode = opt.mode & 0777;
753
754
755
756
757
758
759 inode = iget(s, s->u.isofs_sb.s_firstdatazone);
760
761
762
763
764
765
766
767
768
769 if (s->u.isofs_sb.s_rock == 1) {
770 joliet_level = 0;
771 } else if (joliet_level) {
772 s->u.isofs_sb.s_rock = 0;
773 if (s->u.isofs_sb.s_firstdatazone != first_data_zone) {
774 s->u.isofs_sb.s_firstdatazone = first_data_zone;
775 printk(KERN_DEBUG
776 "ISOFS: changing to secondary root\n");
777 iput(inode);
778 inode = iget(s, s->u.isofs_sb.s_firstdatazone);
779 }
780 }
781
782 if (opt.check == 'u') {
783
784 if (joliet_level) opt.check = 'r';
785 else opt.check = 's';
786 }
787 s->u.isofs_sb.s_joliet_level = joliet_level;
788
789
790 if (!inode)
791 goto out_no_root;
792 if (!inode->i_op)
793 goto out_bad_root;
794
795 s->s_root = d_alloc_root(inode);
796 if (!(s->s_root))
797 goto out_no_root;
798
799 table = 0;
800 if (joliet_level) table += 2;
801 if (opt.check == 'r') table++;
802 s->s_root->d_op = &isofs_dentry_ops[table];
803
804 return s;
805
806
807
808
809out_bad_root:
810 printk(KERN_WARNING "isofs_read_super: root inode not initialized\n");
811 goto out_iput;
812out_no_root:
813 printk(KERN_WARNING "isofs_read_super: get root inode failed\n");
814out_iput:
815 iput(inode);
816#ifdef CONFIG_JOLIET
817 if (s->u.isofs_sb.s_nls_iocharset)
818 unload_nls(s->u.isofs_sb.s_nls_iocharset);
819#endif
820 goto out_unlock;
821out_no_read:
822 printk(KERN_WARNING "isofs_read_super: "
823 "bread failed, dev=%s, iso_blknum=%d, block=%d\n",
824 kdevname(dev), iso_blknum, block);
825 goto out_unlock;
826out_bad_zone_size:
827 printk(KERN_WARNING "Bad logical zone size %ld\n",
828 s->u.isofs_sb.s_log_zone_size);
829 goto out_freebh;
830out_bad_size:
831 printk(KERN_WARNING "Logical zone size(%d) < hardware blocksize(%u)\n",
832 orig_zonesize, blocksize);
833 goto out_freebh;
834out_unknown_format:
835 if (!silent)
836 printk(KERN_WARNING "Unable to identify CD-ROM format.\n");
837
838out_freebh:
839 brelse(bh);
840out_unlock:
841 return NULL;
842}
843
844static int isofs_statfs (struct super_block *sb, struct statfs *buf)
845{
846 buf->f_type = ISOFS_SUPER_MAGIC;
847 buf->f_bsize = sb->s_blocksize;
848 buf->f_blocks = (sb->u.isofs_sb.s_nzones
849 << (sb->u.isofs_sb.s_log_zone_size - sb->s_blocksize_bits));
850 buf->f_bfree = 0;
851 buf->f_bavail = 0;
852 buf->f_files = sb->u.isofs_sb.s_ninodes;
853 buf->f_ffree = 0;
854 buf->f_namelen = NAME_MAX;
855 return 0;
856}
857
858
859
860
861
862
863int isofs_get_blocks(struct inode *inode, long iblock,
864 struct buffer_head **bh_result, unsigned long nblocks)
865{
866 unsigned long b_off;
867 unsigned offset, sect_size;
868 unsigned int firstext;
869 unsigned long nextino;
870 int section, rv;
871
872 lock_kernel();
873
874 rv = 0;
875 if (iblock < 0) {
876 printk("isofs_get_blocks: block < 0\n");
877 goto abort;
878 }
879
880 b_off = iblock;
881
882 offset = 0;
883 firstext = inode->u.isofs_i.i_first_extent;
884 sect_size = inode->u.isofs_i.i_section_size >> ISOFS_BUFFER_BITS(inode);
885 nextino = inode->u.isofs_i.i_next_section_ino;
886 section = 0;
887
888 while ( nblocks ) {
889
890
891
892
893
894
895
896 if (b_off > ((inode->i_size + PAGE_CACHE_SIZE - 1) >> ISOFS_BUFFER_BITS(inode))) {
897 printk("isofs_get_blocks: block >= EOF (%ld, %ld)\n",
898 iblock, (unsigned long) inode->i_size);
899 goto abort;
900 }
901
902 if (nextino) {
903 while (b_off >= (offset + sect_size)) {
904 struct inode *ninode;
905
906 offset += sect_size;
907 if (nextino == 0)
908 goto abort;
909 ninode = iget(inode->i_sb, nextino);
910 if (!ninode)
911 goto abort;
912 firstext = ninode->u.isofs_i.i_first_extent;
913 sect_size = ninode->u.isofs_i.i_section_size;
914 nextino = ninode->u.isofs_i.i_next_section_ino;
915 iput(ninode);
916
917 if (++section > 100) {
918 printk("isofs_get_blocks: More than 100 file sections ?!?, aborting...\n");
919 printk("isofs_get_blocks: ino=%lu block=%ld firstext=%u sect_size=%u nextino=%lu\n",
920 inode->i_ino, iblock, firstext, (unsigned) sect_size, nextino);
921 goto abort;
922 }
923 }
924 }
925
926 if ( *bh_result ) {
927 (*bh_result)->b_dev = inode->i_dev;
928 (*bh_result)->b_blocknr = firstext + b_off - offset;
929 (*bh_result)->b_state |= (1UL << BH_Mapped);
930 } else {
931 *bh_result = sb_getblk(inode->i_sb, firstext+b_off-offset);
932 if ( !*bh_result )
933 goto abort;
934 }
935 bh_result++;
936 b_off++;
937 nblocks--;
938 rv++;
939 }
940
941
942abort:
943 unlock_kernel();
944 return rv;
945}
946
947
948
949
950static int isofs_get_block(struct inode *inode, long iblock,
951 struct buffer_head *bh_result, int create)
952{
953 if ( create ) {
954 printk("isofs_get_block: Kernel tries to allocate a block\n");
955 return -EROFS;
956 }
957
958 return isofs_get_blocks(inode, iblock, &bh_result, 1) ? 0 : -EIO;
959}
960
961static int isofs_bmap(struct inode *inode, int block)
962{
963 struct buffer_head dummy;
964 int error;
965
966 dummy.b_state = 0;
967 dummy.b_blocknr = -1000;
968 error = isofs_get_block(inode, block, &dummy, 0);
969 if (!error)
970 return dummy.b_blocknr;
971 return 0;
972}
973
974struct buffer_head *isofs_bread(struct inode *inode, unsigned int block)
975{
976 unsigned int blknr = isofs_bmap(inode, block);
977 if (!blknr)
978 return NULL;
979 return sb_bread(inode->i_sb, blknr);
980}
981
982static int isofs_readpage(struct file *file, struct page *page)
983{
984 return block_read_full_page(page,isofs_get_block);
985}
986
987static int _isofs_bmap(struct address_space *mapping, long block)
988{
989 return generic_block_bmap(mapping,block,isofs_get_block);
990}
991
992static struct address_space_operations isofs_aops = {
993 readpage: isofs_readpage,
994 sync_page: block_sync_page,
995 bmap: _isofs_bmap
996};
997
998static inline void test_and_set_uid(uid_t *p, uid_t value)
999{
1000 if(value) {
1001 *p = value;
1002 }
1003}
1004
1005static inline void test_and_set_gid(gid_t *p, gid_t value)
1006{
1007 if(value) {
1008 *p = value;
1009 }
1010}
1011
1012static int isofs_read_level3_size(struct inode * inode)
1013{
1014 unsigned long f_pos = inode->i_ino;
1015 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
1016 int high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
1017 struct buffer_head * bh = NULL;
1018 unsigned long block, offset;
1019 int i = 0;
1020 int more_entries = 0;
1021 struct iso_directory_record * tmpde = NULL;
1022
1023 inode->i_size = 0;
1024 inode->u.isofs_i.i_next_section_ino = 0;
1025
1026 block = f_pos >> ISOFS_BUFFER_BITS(inode);
1027 offset = f_pos & (bufsize-1);
1028
1029 do {
1030 struct iso_directory_record * de;
1031 unsigned int de_len;
1032
1033 if (!bh) {
1034 bh = sb_bread(inode->i_sb, block);
1035 if (!bh)
1036 goto out_noread;
1037 }
1038 de = (struct iso_directory_record *) (bh->b_data + offset);
1039 de_len = *(unsigned char *) de;
1040
1041 if (de_len == 0) {
1042 brelse(bh);
1043 bh = NULL;
1044 f_pos = (f_pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1);
1045 block = f_pos >> ISOFS_BUFFER_BITS(inode);
1046 offset = 0;
1047 continue;
1048 }
1049
1050 offset += de_len;
1051
1052
1053 if (offset >= bufsize) {
1054 int slop = bufsize - offset + de_len;
1055 if (!tmpde) {
1056 tmpde = kmalloc(256, GFP_KERNEL);
1057 if (!tmpde)
1058 goto out_nomem;
1059 }
1060 memcpy(tmpde, de, slop);
1061 offset &= bufsize - 1;
1062 block++;
1063 brelse(bh);
1064 bh = NULL;
1065 if (offset) {
1066 bh = sb_bread(inode->i_sb, block);
1067 if (!bh)
1068 goto out_noread;
1069 memcpy((void *) tmpde + slop, bh->b_data, offset);
1070 }
1071 de = tmpde;
1072 }
1073
1074 inode->i_size += isonum_733(de->size);
1075 if (i == 1)
1076 inode->u.isofs_i.i_next_section_ino = f_pos;
1077
1078 more_entries = de->flags[-high_sierra] & 0x80;
1079
1080 f_pos += de_len;
1081 i++;
1082 if(i > 100)
1083 goto out_toomany;
1084 } while(more_entries);
1085out:
1086 if (tmpde)
1087 kfree(tmpde);
1088 if (bh)
1089 brelse(bh);
1090 return 0;
1091
1092out_nomem:
1093 if (bh)
1094 brelse(bh);
1095 return -ENOMEM;
1096
1097out_noread:
1098 printk(KERN_INFO "ISOFS: unable to read i-node block %lu\n", block);
1099 if (tmpde)
1100 kfree(tmpde);
1101 return -EIO;
1102
1103out_toomany:
1104 printk(KERN_INFO "isofs_read_level3_size: "
1105 "More than 100 file sections ?!?, aborting...\n"
1106 "isofs_read_level3_size: inode=%lu ino=%lu\n",
1107 inode->i_ino, f_pos);
1108 goto out;
1109}
1110
1111static void isofs_read_inode(struct inode * inode)
1112{
1113 struct super_block *sb = inode->i_sb;
1114 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
1115 int block = inode->i_ino >> ISOFS_BUFFER_BITS(inode);
1116 int high_sierra = sb->u.isofs_sb.s_high_sierra;
1117 struct buffer_head * bh = NULL;
1118 struct iso_directory_record * de;
1119 struct iso_directory_record * tmpde = NULL;
1120 unsigned int de_len;
1121 unsigned long offset;
1122 int volume_seq_no, i;
1123
1124 bh = sb_bread(inode->i_sb, block);
1125 if (!bh)
1126 goto out_badread;
1127
1128 offset = (inode->i_ino & (bufsize - 1));
1129 de = (struct iso_directory_record *) (bh->b_data + offset);
1130 de_len = *(unsigned char *) de;
1131
1132 if (offset + de_len > bufsize) {
1133 int frag1 = bufsize - offset;
1134
1135 tmpde = kmalloc(de_len, GFP_KERNEL);
1136 if (tmpde == NULL) {
1137 printk(KERN_INFO "isofs_read_inode: out of memory\n");
1138 goto fail;
1139 }
1140 memcpy(tmpde, bh->b_data + offset, frag1);
1141 brelse(bh);
1142 bh = sb_bread(inode->i_sb, ++block);
1143 if (!bh)
1144 goto out_badread;
1145 memcpy((char *)tmpde+frag1, bh->b_data, de_len - frag1);
1146 de = tmpde;
1147 }
1148
1149
1150 inode->u.isofs_i.i_file_format = isofs_file_normal;
1151
1152 if (de->flags[-high_sierra] & 2) {
1153 inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
1154 inode->i_nlink = 1;
1155
1156
1157
1158
1159 } else {
1160
1161 inode->i_mode = inode->i_sb->u.isofs_sb.s_mode;
1162 inode->i_nlink = 1;
1163 inode->i_mode |= S_IFREG;
1164
1165
1166
1167 for(i=0; i< de->name_len[0]; i++)
1168 if(de->name[i]=='.' || de->name[i]==';')
1169 break;
1170 if(i == de->name_len[0] || de->name[i] == ';')
1171 inode->i_mode |= S_IXUGO;
1172 }
1173 inode->i_uid = inode->i_sb->u.isofs_sb.s_uid;
1174 inode->i_gid = inode->i_sb->u.isofs_sb.s_gid;
1175 inode->i_blocks = inode->i_blksize = 0;
1176
1177
1178 inode->u.isofs_i.i_section_size = isonum_733 (de->size);
1179 if(de->flags[-high_sierra] & 0x80) {
1180 if(isofs_read_level3_size(inode)) goto fail;
1181 } else {
1182 inode->i_size = isonum_733 (de->size);
1183 }
1184
1185
1186
1187
1188
1189
1190
1191 if (inode->i_sb->u.isofs_sb.s_cruft == 'y')
1192 inode->i_size &= 0x00ffffff;
1193
1194 if (de->interleave[0]) {
1195 printk("Interleaved files not (yet) supported.\n");
1196 inode->i_size = 0;
1197 }
1198
1199
1200
1201 if (de->file_unit_size[0] != 0) {
1202 printk("File unit size != 0 for ISO file (%ld).\n",
1203 inode->i_ino);
1204 }
1205
1206
1207
1208#ifdef DEBUG
1209 if((de->flags[-high_sierra] & ~2)!= 0){
1210 printk("Unusual flag settings for ISO file (%ld %x).\n",
1211 inode->i_ino, de->flags[-high_sierra]);
1212 }
1213#endif
1214
1215 inode->i_mtime = inode->i_atime = inode->i_ctime =
1216 iso_date(de->date, high_sierra);
1217
1218 inode->u.isofs_i.i_first_extent = (isonum_733 (de->extent) +
1219 isonum_711 (de->ext_attr_length));
1220
1221
1222 inode->i_blksize = PAGE_CACHE_SIZE;
1223 inode->i_blocks = (inode->i_size + 511) >> 9;
1224
1225
1226
1227
1228
1229
1230 if (!high_sierra) {
1231 parse_rock_ridge_inode(de, inode);
1232
1233 test_and_set_uid(&inode->i_uid, inode->i_sb->u.isofs_sb.s_uid);
1234 test_and_set_gid(&inode->i_gid, inode->i_sb->u.isofs_sb.s_gid);
1235 }
1236
1237
1238 volume_seq_no = isonum_723 (de->volume_sequence_number) ;
1239
1240
1241 if (S_ISREG(inode->i_mode)) {
1242 inode->i_fop = &generic_ro_fops;
1243 switch ( inode->u.isofs_i.i_file_format ) {
1244#ifdef CONFIG_ZISOFS
1245 case isofs_file_compressed:
1246 inode->i_data.a_ops = &zisofs_aops;
1247 break;
1248#endif
1249 default:
1250 inode->i_data.a_ops = &isofs_aops;
1251 break;
1252 }
1253 } else if (S_ISDIR(inode->i_mode)) {
1254 inode->i_op = &isofs_dir_inode_operations;
1255 inode->i_fop = &isofs_dir_operations;
1256 } else if (S_ISLNK(inode->i_mode)) {
1257 inode->i_op = &page_symlink_inode_operations;
1258 inode->i_data.a_ops = &isofs_symlink_aops;
1259 } else
1260
1261 init_special_inode(inode, inode->i_mode,
1262 kdev_t_to_nr(inode->i_rdev));
1263 out:
1264 if (tmpde)
1265 kfree(tmpde);
1266 if (bh)
1267 brelse(bh);
1268 return;
1269
1270 out_badread:
1271 printk(KERN_WARNING "ISOFS: unable to read i-node block\n");
1272 fail:
1273 make_bad_inode(inode);
1274 goto out;
1275}
1276
1277#ifdef LEAK_CHECK
1278#undef malloc
1279#undef free_s
1280#undef sb_bread
1281#undef brelse
1282
1283void * leak_check_malloc(unsigned int size){
1284 void * tmp;
1285 check_malloc++;
1286 tmp = kmalloc(size, GFP_KERNEL);
1287 return tmp;
1288}
1289
1290void leak_check_free_s(void * obj, int size){
1291 check_malloc--;
1292 return kfree(obj);
1293}
1294
1295struct buffer_head * leak_check_bread(struct super_block *sb, int block){
1296 check_bread++;
1297 return sb_bread(sb, block);
1298}
1299
1300void leak_check_brelse(struct buffer_head * bh){
1301 check_bread--;
1302 return brelse(bh);
1303}
1304
1305#endif
1306
1307static DECLARE_FSTYPE_DEV(iso9660_fs_type, "iso9660", isofs_read_super);
1308
1309static int __init init_iso9660_fs(void)
1310{
1311#ifdef CONFIG_ZISOFS
1312 int err;
1313
1314 err = zisofs_init();
1315 if ( err )
1316 return err;
1317#endif
1318 return register_filesystem(&iso9660_fs_type);
1319}
1320
1321static void __exit exit_iso9660_fs(void)
1322{
1323 unregister_filesystem(&iso9660_fs_type);
1324#ifdef CONFIG_ZISOFS
1325 zisofs_cleanup();
1326#endif
1327}
1328
1329EXPORT_NO_SYMBOLS;
1330
1331module_init(init_iso9660_fs)
1332module_exit(exit_iso9660_fs)
1333MODULE_LICENSE("GPL");
1334
1335